diff --git a/crates/hir-def/src/find_path.rs b/crates/hir-def/src/find_path.rs index 0cd4a5db8c345..d06fc4df7681e 100644 --- a/crates/hir-def/src/find_path.rs +++ b/crates/hir-def/src/find_path.rs @@ -30,6 +30,8 @@ pub fn find_path( find_path_inner(FindPathCtx { db, prefixed: None, prefer_no_std, prefer_prelude }, item, from) } +/// Find a path that can be used to refer to a certain item. This can depend on +/// *from where* you're referring to the item, hence the `from` parameter. pub fn find_path_prefixed( db: &dyn DefDatabase, item: ItemInNs, @@ -255,7 +257,7 @@ fn find_in_scope( item: ItemInNs, ) -> Option { def_map.with_ancestor_maps(db, from.local_id, &mut |def_map, local_id| { - def_map[local_id].scope.name_of(item).map(|(name, _, _)| name.clone()) + def_map[local_id].scope.names_of(item, |name, _, _| Some(name.clone())) }) } diff --git a/crates/hir-def/src/generics.rs b/crates/hir-def/src/generics.rs index 4638b3771973c..118055b605eca 100644 --- a/crates/hir-def/src/generics.rs +++ b/crates/hir-def/src/generics.rs @@ -29,6 +29,8 @@ use crate::{ /// Data about a generic type parameter (to a function, struct, impl, ...). #[derive(Clone, PartialEq, Eq, Debug, Hash)] pub struct TypeParamData { + /// [`None`] only if the type ref is an [`TypeRef::ImplTrait`]. FIXME: Might be better to just + /// make it always be a value, giving impl trait a special name. pub name: Option, pub default: Option>, pub provenance: TypeParamProvenance, diff --git a/crates/hir-def/src/item_scope.rs b/crates/hir-def/src/item_scope.rs index 2b059d1f8dcd4..a60b9f9f3ab75 100644 --- a/crates/hir-def/src/item_scope.rs +++ b/crates/hir-def/src/item_scope.rs @@ -277,13 +277,43 @@ impl ItemScope { ItemInNs::Types(def) => self.types.iter().find_map(|(name, &(other_def, vis, i))| { (other_def == def).then_some((name, vis, i.is_none())) }), - ItemInNs::Values(def) => self.values.iter().find_map(|(name, &(other_def, vis, i))| { (other_def == def).then_some((name, vis, i.is_none())) }), } } + /// XXX: this is O(N) rather than O(1), try to not introduce new usages. + pub(crate) fn names_of( + &self, + item: ItemInNs, + mut cb: impl FnMut(&Name, Visibility, bool) -> Option, + ) -> Option { + match item { + ItemInNs::Macros(def) => self + .macros + .iter() + .filter_map(|(name, &(other_def, vis, i))| { + (other_def == def).then_some((name, vis, i.is_none())) + }) + .find_map(|(a, b, c)| cb(a, b, c)), + ItemInNs::Types(def) => self + .types + .iter() + .filter_map(|(name, &(other_def, vis, i))| { + (other_def == def).then_some((name, vis, i.is_none())) + }) + .find_map(|(a, b, c)| cb(a, b, c)), + ItemInNs::Values(def) => self + .values + .iter() + .filter_map(|(name, &(other_def, vis, i))| { + (other_def == def).then_some((name, vis, i.is_none())) + }) + .find_map(|(a, b, c)| cb(a, b, c)), + } + } + pub(crate) fn traits(&self) -> impl Iterator + '_ { self.types .values() diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs index 46898ce542d6d..88d4572196cde 100644 --- a/crates/hir-def/src/lib.rs +++ b/crates/hir-def/src/lib.rs @@ -422,6 +422,10 @@ impl ModuleId { } } + pub fn crate_def_map(self, db: &dyn DefDatabase) -> Arc { + db.crate_def_map(self.krate) + } + pub fn krate(self) -> CrateId { self.krate } @@ -438,6 +442,8 @@ impl ModuleId { }) } + /// Returns the module containing `self`, either the parent `mod`, or the module (or block) containing + /// the block, if `self` corresponds to a block expression. pub fn containing_module(self, db: &dyn DefDatabase) -> Option { self.def_map(db).containing_module(self.local_id) } @@ -929,6 +935,18 @@ impl GenericDefId { GenericDefId::EnumVariantId(_) => (FileId::BOGUS.into(), None), } } + + pub fn assoc_trait_container(self, db: &dyn DefDatabase) -> Option { + match match self { + GenericDefId::FunctionId(f) => f.lookup(db).container, + GenericDefId::TypeAliasId(t) => t.lookup(db).container, + GenericDefId::ConstId(c) => c.lookup(db).container, + _ => return None, + } { + ItemContainerId::TraitId(trait_) => Some(trait_), + _ => None, + } + } } impl From for GenericDefId { diff --git a/crates/hir-ty/src/chalk_ext.rs b/crates/hir-ty/src/chalk_ext.rs index d1aebeff261c5..0bf01b0bc6ae2 100644 --- a/crates/hir-ty/src/chalk_ext.rs +++ b/crates/hir-ty/src/chalk_ext.rs @@ -1,6 +1,8 @@ //! Various extensions traits for Chalk types. -use chalk_ir::{cast::Cast, FloatTy, IntTy, Mutability, Scalar, TyVariableKind, UintTy}; +use chalk_ir::{ + cast::Cast, FloatTy, IntTy, Mutability, Scalar, TyVariableKind, TypeOutlives, UintTy, +}; use hir_def::{ builtin_type::{BuiltinFloat, BuiltinInt, BuiltinType, BuiltinUint}, generics::TypeOrConstParamData, @@ -312,7 +314,7 @@ impl TyExt for Ty { .generic_predicates(id.parent) .iter() .map(|pred| pred.clone().substitute(Interner, &substs)) - .filter(|wc| match &wc.skip_binders() { + .filter(|wc| match wc.skip_binders() { WhereClause::Implemented(tr) => { &tr.self_type_parameter(Interner) == self } @@ -320,6 +322,9 @@ impl TyExt for Ty { alias: AliasTy::Projection(proj), ty: _, }) => &proj.self_type_parameter(db) == self, + WhereClause::TypeOutlives(TypeOutlives { ty, lifetime: _ }) => { + ty == self + } _ => false, }) .collect::>(); diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index 8740ae6797cb1..eb7f106cdfaa1 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -9,6 +9,7 @@ use std::{ use base_db::CrateId; use chalk_ir::{BoundVar, Safety, TyKind}; +use either::Either; use hir_def::{ data::adt::VariantData, db::DefDatabase, @@ -1072,6 +1073,7 @@ impl HirDisplay for Ty { write_bounds_like_dyn_trait_with_prefix( f, "impl", + Either::Left(self), bounds.skip_binders(), SizedByDefault::Sized { anchor: krate }, )?; @@ -1087,6 +1089,7 @@ impl HirDisplay for Ty { write_bounds_like_dyn_trait_with_prefix( f, "impl", + Either::Left(self), bounds.skip_binders(), SizedByDefault::Sized { anchor: krate }, )?; @@ -1189,21 +1192,24 @@ impl HirDisplay for Ty { .generic_predicates(id.parent) .iter() .map(|pred| pred.clone().substitute(Interner, &substs)) - .filter(|wc| match &wc.skip_binders() { + .filter(|wc| match wc.skip_binders() { WhereClause::Implemented(tr) => { - &tr.self_type_parameter(Interner) == self + tr.self_type_parameter(Interner) == *self } WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(proj), ty: _, - }) => &proj.self_type_parameter(db) == self, - _ => false, + }) => proj.self_type_parameter(db) == *self, + WhereClause::AliasEq(_) => false, + WhereClause::TypeOutlives(to) => to.ty == *self, + WhereClause::LifetimeOutlives(_) => false, }) .collect::>(); let krate = id.parent.module(db.upcast()).krate(); write_bounds_like_dyn_trait_with_prefix( f, "impl", + Either::Left(self), &bounds, SizedByDefault::Sized { anchor: krate }, )?; @@ -1229,6 +1235,7 @@ impl HirDisplay for Ty { write_bounds_like_dyn_trait_with_prefix( f, "dyn", + Either::Left(self), &bounds, SizedByDefault::NotSized, )?; @@ -1252,6 +1259,7 @@ impl HirDisplay for Ty { write_bounds_like_dyn_trait_with_prefix( f, "impl", + Either::Left(self), bounds.skip_binders(), SizedByDefault::Sized { anchor: krate }, )?; @@ -1266,6 +1274,7 @@ impl HirDisplay for Ty { write_bounds_like_dyn_trait_with_prefix( f, "impl", + Either::Left(self), bounds.skip_binders(), SizedByDefault::Sized { anchor: krate }, )?; @@ -1468,6 +1477,7 @@ impl SizedByDefault { pub fn write_bounds_like_dyn_trait_with_prefix( f: &mut HirFormatter<'_>, prefix: &str, + this: Either<&Ty, &Lifetime>, predicates: &[QuantifiedWhereClause], default_sized: SizedByDefault, ) -> Result<(), HirDisplayError> { @@ -1476,7 +1486,7 @@ pub fn write_bounds_like_dyn_trait_with_prefix( || predicates.is_empty() && matches!(default_sized, SizedByDefault::Sized { .. }) { write!(f, " ")?; - write_bounds_like_dyn_trait(f, predicates, default_sized) + write_bounds_like_dyn_trait(f, this, predicates, default_sized) } else { Ok(()) } @@ -1484,6 +1494,7 @@ pub fn write_bounds_like_dyn_trait_with_prefix( fn write_bounds_like_dyn_trait( f: &mut HirFormatter<'_>, + this: Either<&Ty, &Lifetime>, predicates: &[QuantifiedWhereClause], default_sized: SizedByDefault, ) -> Result<(), HirDisplayError> { @@ -1541,6 +1552,28 @@ fn write_bounds_like_dyn_trait( } } } + WhereClause::TypeOutlives(to) if Either::Left(&to.ty) == this => { + if !is_fn_trait && angle_open { + write!(f, ">")?; + angle_open = false; + } + if !first { + write!(f, " + ")?; + } + to.lifetime.hir_fmt(f)?; + } + WhereClause::TypeOutlives(_) => {} + WhereClause::LifetimeOutlives(lo) if Either::Right(&lo.a) == this => { + if !is_fn_trait && angle_open { + write!(f, ">")?; + angle_open = false; + } + if !first { + write!(f, " + ")?; + } + lo.b.hir_fmt(f)?; + } + WhereClause::LifetimeOutlives(_) => {} WhereClause::AliasEq(alias_eq) if is_fn_trait => { is_fn_trait = false; if !alias_eq.ty.is_unit() { @@ -1577,10 +1610,6 @@ fn write_bounds_like_dyn_trait( } ty.hir_fmt(f)?; } - - // FIXME implement these - WhereClause::LifetimeOutlives(_) => {} - WhereClause::TypeOutlives(_) => {} } first = false; } diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs index bb558e533c4e3..3b644379fa6e6 100644 --- a/crates/hir-ty/src/infer.rs +++ b/crates/hir-ty/src/infer.rs @@ -55,10 +55,10 @@ use triomphe::Arc; use crate::{ db::HirDatabase, - fold_tys, + error_lifetime, fold_tys, infer::{coerce::CoerceMany, unify::InferenceTable}, lower::ImplTraitLoweringMode, - static_lifetime, to_assoc_type_id, + to_assoc_type_id, traits::FnTrait, utils::{InTypeConstIdMetadata, UnevaluatedConstEvaluatorFolder}, AliasEq, AliasTy, Binders, ClosureId, Const, DomainGoal, GenericArg, Goal, ImplTraitId, @@ -326,7 +326,7 @@ pub struct Adjustment { impl Adjustment { pub fn borrow(m: Mutability, ty: Ty) -> Self { - let ty = TyKind::Ref(m, static_lifetime(), ty).intern(Interner); + let ty = TyKind::Ref(m, error_lifetime(), ty).intern(Interner); Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(m)), target: ty } } } diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs index 32845ac2e36aa..20d24e6fe2ee6 100644 --- a/crates/hir-ty/src/infer/closure.rs +++ b/crates/hir-ty/src/infer/closure.rs @@ -22,9 +22,9 @@ use stdx::never; use crate::{ db::{HirDatabase, InternedClosure}, - from_chalk_trait_id, from_placeholder_idx, make_binders, + error_lifetime, from_chalk_trait_id, from_placeholder_idx, make_binders, mir::{BorrowKind, MirSpan, MutBorrowKind, ProjectionElem}, - static_lifetime, to_chalk_trait_id, + to_chalk_trait_id, traits::FnTrait, utils::{self, elaborate_clause_supertraits, generics, Generics}, Adjust, Adjustment, AliasEq, AliasTy, Binders, BindingMode, ChalkTraitId, ClosureId, DynTy, @@ -324,7 +324,7 @@ impl CapturedItemWithoutTy { BorrowKind::Mut { .. } => Mutability::Mut, _ => Mutability::Not, }; - TyKind::Ref(m, static_lifetime(), ty).intern(Interner) + TyKind::Ref(m, error_lifetime(), ty).intern(Interner) } }; return CapturedItem { diff --git a/crates/hir-ty/src/infer/coerce.rs b/crates/hir-ty/src/infer/coerce.rs index cfbbc9dd6c04f..72928851f123c 100644 --- a/crates/hir-ty/src/infer/coerce.rs +++ b/crates/hir-ty/src/infer/coerce.rs @@ -18,11 +18,11 @@ use triomphe::Arc; use crate::{ autoderef::{Autoderef, AutoderefKind}, db::HirDatabase, + error_lifetime, infer::{ Adjust, Adjustment, AutoBorrow, InferOk, InferenceContext, OverloadedDeref, PointerCast, TypeError, TypeMismatch, }, - static_lifetime, utils::ClosureSubst, Canonical, DomainGoal, FnAbi, FnPointer, FnSig, Guidance, InEnvironment, Interner, Solution, Substitution, TraitEnvironment, Ty, TyBuilder, TyExt, @@ -427,7 +427,7 @@ impl InferenceTable<'_> { // compare those. Note that this means we use the target // mutability [1], since it may be that we are coercing // from `&mut T` to `&U`. - let lt = static_lifetime(); // FIXME: handle lifetimes correctly, see rustc + let lt = error_lifetime(); // FIXME: handle lifetimes correctly, see rustc let derefd_from_ty = TyKind::Ref(to_mt, lt, referent_ty).intern(Interner); match autoderef.table.try_unify(&derefd_from_ty, to_ty) { Ok(result) => { @@ -621,7 +621,7 @@ impl InferenceTable<'_> { (TyKind::Ref(from_mt, _, from_inner), &TyKind::Ref(to_mt, _, _)) => { coerce_mutabilities(*from_mt, to_mt)?; - let lt = static_lifetime(); + let lt = error_lifetime(); Some(( Adjustment { kind: Adjust::Deref(None), target: from_inner.clone() }, Adjustment { diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index 35d59679355a6..4d3d7376c4dec 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/crates/hir-ty/src/infer/expr.rs @@ -23,6 +23,7 @@ use crate::{ autoderef::{builtin_deref, deref_by_trait, Autoderef}, consteval, db::{InternedClosure, InternedCoroutine}, + error_lifetime, infer::{ coerce::{CoerceMany, CoercionCause}, find_continuable, @@ -630,7 +631,7 @@ impl InferenceContext<'_> { let inner_ty = self.infer_expr_inner(*expr, &expectation); match rawness { Rawness::RawPtr => TyKind::Raw(mutability, inner_ty), - Rawness::Ref => TyKind::Ref(mutability, static_lifetime(), inner_ty), + Rawness::Ref => TyKind::Ref(mutability, error_lifetime(), inner_ty), } .intern(Interner) } diff --git a/crates/hir-ty/src/infer/pat.rs b/crates/hir-ty/src/infer/pat.rs index 30005a25512e7..440ffa335728a 100644 --- a/crates/hir-ty/src/infer/pat.rs +++ b/crates/hir-ty/src/infer/pat.rs @@ -12,6 +12,7 @@ use hir_expand::name::Name; use crate::{ consteval::{try_const_usize, usize_const}, + error_lifetime, infer::{BindingMode, Expectation, InferenceContext, TypeMismatch}, lower::lower_to_chalk_mutability, primitive::UintTy, @@ -396,14 +397,14 @@ impl InferenceContext<'_> { None => { let inner_ty = self.table.new_type_var(); let ref_ty = - TyKind::Ref(mutability, static_lifetime(), inner_ty.clone()).intern(Interner); + TyKind::Ref(mutability, error_lifetime(), inner_ty.clone()).intern(Interner); // Unification failure will be reported by the caller. self.unify(&ref_ty, expected); inner_ty } }; let subty = self.infer_pat(inner_pat, &expectation, default_bm); - TyKind::Ref(mutability, static_lifetime(), subty).intern(Interner) + TyKind::Ref(mutability, error_lifetime(), subty).intern(Interner) } fn infer_bind_pat( @@ -430,7 +431,7 @@ impl InferenceContext<'_> { let bound_ty = match mode { BindingMode::Ref(mutability) => { - TyKind::Ref(mutability, static_lifetime(), inner_ty.clone()).intern(Interner) + TyKind::Ref(mutability, error_lifetime(), inner_ty.clone()).intern(Interner) } BindingMode::Move => inner_ty.clone(), }; diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs index afb89fe1e5b1c..b68fefc5150b1 100644 --- a/crates/hir-ty/src/infer/unify.rs +++ b/crates/hir-ty/src/infer/unify.rs @@ -16,8 +16,8 @@ use triomphe::Arc; use super::{InferOk, InferResult, InferenceContext, TypeError}; use crate::{ - consteval::unknown_const, db::HirDatabase, fold_generic_args, fold_tys_and_consts, - static_lifetime, to_chalk_trait_id, traits::FnTrait, AliasEq, AliasTy, BoundVar, Canonical, + consteval::unknown_const, db::HirDatabase, error_lifetime, fold_generic_args, + fold_tys_and_consts, to_chalk_trait_id, traits::FnTrait, AliasEq, AliasTy, BoundVar, Canonical, Const, ConstValue, DebruijnIndex, DomainGoal, GenericArg, GenericArgData, Goal, GoalData, Guidance, InEnvironment, InferenceVar, Interner, Lifetime, OpaqueTyId, ParamKind, ProjectionTy, ProjectionTyExt, Scalar, Solution, Substitution, TraitEnvironment, Ty, TyBuilder, TyExt, @@ -43,40 +43,21 @@ impl InferenceContext<'_> { let obligations = pending_obligations .iter() .filter_map(|obligation| match obligation.value.value.goal.data(Interner) { - GoalData::DomainGoal(DomainGoal::Holds( - clause @ WhereClause::AliasEq(AliasEq { - alias: AliasTy::Projection(projection), - .. - }), - )) => { - let projection_self = projection.self_type_parameter(self.db); - let uncanonical = chalk_ir::Substitute::apply( - &obligation.free_vars, - projection_self, - Interner, - ); - if matches!( - self.resolve_ty_shallow(&uncanonical).kind(Interner), - TyKind::InferenceVar(iv, TyVariableKind::General) if *iv == root, - ) { - Some(chalk_ir::Substitute::apply( - &obligation.free_vars, - clause.clone(), - Interner, - )) - } else { - None - } - } - GoalData::DomainGoal(DomainGoal::Holds( - clause @ WhereClause::Implemented(trait_ref), - )) => { - let trait_ref_self = trait_ref.self_type_parameter(Interner); - let uncanonical = chalk_ir::Substitute::apply( - &obligation.free_vars, - trait_ref_self, - Interner, - ); + GoalData::DomainGoal(DomainGoal::Holds(clause)) => { + let ty = match clause { + WhereClause::AliasEq(AliasEq { + alias: AliasTy::Projection(projection), + .. + }) => projection.self_type_parameter(self.db), + WhereClause::Implemented(trait_ref) => { + trait_ref.self_type_parameter(Interner) + } + WhereClause::TypeOutlives(to) => to.ty.clone(), + _ => return None, + }; + + let uncanonical = + chalk_ir::Substitute::apply(&obligation.free_vars, ty, Interner); if matches!( self.resolve_ty_shallow(&uncanonical).kind(Interner), TyKind::InferenceVar(iv, TyVariableKind::General) if *iv == root, @@ -121,8 +102,9 @@ impl> Canonicalized { VariableKind::Ty(TyVariableKind::General) => ctx.new_type_var().cast(Interner), VariableKind::Ty(TyVariableKind::Integer) => ctx.new_integer_var().cast(Interner), VariableKind::Ty(TyVariableKind::Float) => ctx.new_float_var().cast(Interner), - // Chalk can sometimes return new lifetime variables. We just use the static lifetime everywhere - VariableKind::Lifetime => static_lifetime().cast(Interner), + // Chalk can sometimes return new lifetime variables. We just replace them by errors + // for now. + VariableKind::Lifetime => error_lifetime().cast(Interner), VariableKind::Const(ty) => ctx.new_const_var(ty.clone()).cast(Interner), }), ); @@ -1020,11 +1002,11 @@ mod resolve { _var: InferenceVar, _outer_binder: DebruijnIndex, ) -> Lifetime { - // fall back all lifetimes to 'static -- currently we don't deal + // fall back all lifetimes to 'error -- currently we don't deal // with any lifetimes, but we can sometimes get some lifetime // variables through Chalk's unification, and this at least makes // sure we don't leak them outside of inference - crate::static_lifetime() + crate::error_lifetime() } } } diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs index ba64f5c8d7ea8..ad8202d4d2332 100644 --- a/crates/hir-ty/src/lib.rs +++ b/crates/hir-ty/src/lib.rs @@ -622,7 +622,7 @@ pub fn static_lifetime() -> Lifetime { } pub fn error_lifetime() -> Lifetime { - static_lifetime() + LifetimeData::Static.intern(Interner) } pub(crate) fn fold_free_vars + TypeFoldable>( @@ -861,7 +861,7 @@ where if cfg!(debug_assertions) { Err(NoSolution) } else { - Ok(static_lifetime()) + Ok(error_lifetime()) } } @@ -873,7 +873,7 @@ where if cfg!(debug_assertions) { Err(NoSolution) } else { - Ok(static_lifetime()) + Ok(error_lifetime()) } } } diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 25ccc84c13c85..9a468e2a23355 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -15,7 +15,10 @@ use base_db::{ CrateId, }; use chalk_ir::{ - cast::Cast, fold::Shift, fold::TypeFoldable, interner::HasInterner, Mutability, Safety, + cast::Cast, + fold::{Shift, TypeFoldable}, + interner::HasInterner, + Mutability, Safety, TypeOutlives, }; use either::Either; @@ -64,7 +67,7 @@ use crate::{ }, AliasEq, AliasTy, Binders, BoundVar, CallableSig, Const, ConstScalar, DebruijnIndex, DynTy, FnAbi, FnPointer, FnSig, FnSubst, ImplTrait, ImplTraitId, ImplTraits, Interner, Lifetime, - LifetimeData, ParamKind, PolyFnSig, ProjectionTy, QuantifiedWhereClause, + LifetimeData, LifetimeOutlives, ParamKind, PolyFnSig, ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyKind, WhereClause, }; @@ -282,7 +285,7 @@ impl<'a> TyLoweringContext<'a> { let inner_ty = self.lower_ty(inner); // FIXME: It should infer the eldided lifetimes instead of stubbing with static let lifetime = - lifetime.as_ref().map_or_else(static_lifetime, |lr| self.lower_lifetime(lr)); + lifetime.as_ref().map_or_else(error_lifetime, |lr| self.lower_lifetime(lr)); TyKind::Ref(lower_to_chalk_mutability(*mutability), lifetime, inner_ty) .intern(Interner) } @@ -1048,7 +1051,13 @@ impl<'a> TyLoweringContext<'a> { .collect::>() .into_iter() } - WherePredicate::Lifetime { .. } => vec![].into_iter(), + WherePredicate::Lifetime { bound, target } => { + vec![crate::wrap_empty_binders(WhereClause::LifetimeOutlives(LifetimeOutlives { + a: self.lower_lifetime(bound), + b: self.lower_lifetime(target), + }))] + .into_iter() + } } } @@ -1101,7 +1110,13 @@ impl<'a> TyLoweringContext<'a> { bindings = self.lower_trait_ref_from_path(path, Some(self_ty)); bindings.clone().map(WhereClause::Implemented).map(crate::wrap_empty_binders) } - TypeBound::Lifetime(_) => None, + TypeBound::Lifetime(l) => { + let lifetime = self.lower_lifetime(l); + Some(crate::wrap_empty_binders(WhereClause::TypeOutlives(TypeOutlives { + ty: self_ty, + lifetime, + }))) + } TypeBound::Error => None, }; trait_ref.into_iter().chain( @@ -1264,10 +1279,19 @@ impl<'a> TyLoweringContext<'a> { // bounds in the input. // INVARIANT: If this function returns `DynTy`, there should be at least one trait bound. // These invariants are utilized by `TyExt::dyn_trait()` and chalk. + let mut lifetime = None; let bounds = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { let mut bounds: Vec<_> = bounds .iter() .flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false)) + .filter(|b| match b.skip_binders() { + WhereClause::Implemented(_) | WhereClause::AliasEq(_) => true, + WhereClause::LifetimeOutlives(_) => false, + WhereClause::TypeOutlives(t) => { + lifetime = Some(t.lifetime.clone()); + false + } + }) .collect(); let mut multiple_regular_traits = false; @@ -1305,7 +1329,7 @@ impl<'a> TyLoweringContext<'a> { _ => unreachable!(), } } - // We don't produce `WhereClause::{TypeOutlives, LifetimeOutlives}` yet. + // `WhereClause::{TypeOutlives, LifetimeOutlives}` have been filtered out _ => unreachable!(), } }); @@ -1325,7 +1349,21 @@ impl<'a> TyLoweringContext<'a> { if let Some(bounds) = bounds { let bounds = crate::make_single_type_binders(bounds); - TyKind::Dyn(DynTy { bounds, lifetime: static_lifetime() }).intern(Interner) + TyKind::Dyn(DynTy { + bounds, + lifetime: match lifetime { + Some(it) => match it.bound_var(Interner) { + Some(bound_var) => LifetimeData::BoundVar(BoundVar::new( + DebruijnIndex::INNERMOST, + bound_var.index, + )) + .intern(Interner), + None => it, + }, + None => static_lifetime(), + }, + }) + .intern(Interner) } else { // FIXME: report error // (additional non-auto traits, associated type rebound, or no resolved trait) @@ -1657,18 +1695,7 @@ pub(crate) fn trait_environment_query( } } - let container: Option = match def { - // FIXME: is there a function for this? - GenericDefId::FunctionId(f) => Some(f.lookup(db.upcast()).container), - GenericDefId::AdtId(_) => None, - GenericDefId::TraitId(_) => None, - GenericDefId::TraitAliasId(_) => None, - GenericDefId::TypeAliasId(t) => Some(t.lookup(db.upcast()).container), - GenericDefId::ImplId(_) => None, - GenericDefId::EnumVariantId(_) => None, - GenericDefId::ConstId(c) => Some(c.lookup(db.upcast()).container), - }; - if let Some(ItemContainerId::TraitId(trait_id)) = container { + if let Some(trait_id) = def.assoc_trait_container(db.upcast()) { // add `Self: Trait` to the environment in trait // function default implementations (and speculative code // inside consts or type aliases) @@ -1796,8 +1823,7 @@ pub(crate) fn generic_defaults_query( make_binders(db, &generic_params, val) } GenericParamDataRef::LifetimeParamData(_) => { - // using static because it requires defaults - make_binders(db, &generic_params, static_lifetime().cast(Interner)) + make_binders(db, &generic_params, error_lifetime().cast(Interner)) } } })); @@ -1817,7 +1843,7 @@ pub(crate) fn generic_defaults_recover( let val = match id { GenericParamId::TypeParamId(_) => TyKind::Error.intern(Interner).cast(Interner), GenericParamId::ConstParamId(id) => unknown_const_as_generic(db.const_param_ty(id)), - GenericParamId::LifetimeParamId(_) => static_lifetime().cast(Interner), + GenericParamId::LifetimeParamId(_) => error_lifetime().cast(Interner), }; crate::make_binders(db, &generic_params, val) })); diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs index 73b07df56f7ea..cd723494713b3 100644 --- a/crates/hir-ty/src/method_resolution.rs +++ b/crates/hir-ty/src/method_resolution.rs @@ -22,10 +22,10 @@ use triomphe::Arc; use crate::{ autoderef::{self, AutoderefKind}, db::HirDatabase, - from_chalk_trait_id, from_foreign_def_id, + error_lifetime, from_chalk_trait_id, from_foreign_def_id, infer::{unify::InferenceTable, Adjust, Adjustment, OverloadedDeref, PointerCast}, primitive::{FloatTy, IntTy, UintTy}, - static_lifetime, to_chalk_trait_id, + to_chalk_trait_id, utils::all_super_traits, AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, DynTyExt, ForeignDefId, Goal, Guidance, InEnvironment, Interner, Scalar, Solution, Substitution, TraitEnvironment, TraitRef, @@ -1035,7 +1035,7 @@ fn iterate_method_candidates_with_autoref( iterate_method_candidates_by_receiver(receiver_ty.clone(), maybe_reborrowed)?; let refed = Canonical { - value: TyKind::Ref(Mutability::Not, static_lifetime(), receiver_ty.value.clone()) + value: TyKind::Ref(Mutability::Not, error_lifetime(), receiver_ty.value.clone()) .intern(Interner), binders: receiver_ty.binders.clone(), }; @@ -1043,7 +1043,7 @@ fn iterate_method_candidates_with_autoref( iterate_method_candidates_by_receiver(refed, first_adjustment.with_autoref(Mutability::Not))?; let ref_muted = Canonical { - value: TyKind::Ref(Mutability::Mut, static_lifetime(), receiver_ty.value.clone()) + value: TyKind::Ref(Mutability::Mut, error_lifetime(), receiver_ty.value.clone()) .intern(Interner), binders: receiver_ty.binders, }; @@ -1369,6 +1369,7 @@ pub(crate) fn resolve_indexing_op( None } +// FIXME: Replace this with a `Try` impl once stable macro_rules! check_that { ($cond:expr) => { if !$cond { @@ -1377,6 +1378,7 @@ macro_rules! check_that { }; } +#[derive(Debug)] enum IsValidCandidate { Yes, No, diff --git a/crates/hir-ty/src/mir/eval/shim.rs b/crates/hir-ty/src/mir/eval/shim.rs index d4d669182f2e3..fee3dd3ada852 100644 --- a/crates/hir-ty/src/mir/eval/shim.rs +++ b/crates/hir-ty/src/mir/eval/shim.rs @@ -9,11 +9,14 @@ use hir_def::{ resolver::HasResolver, }; -use crate::mir::eval::{ - name, pad16, static_lifetime, Address, AdtId, Arc, BuiltinType, Evaluator, FunctionId, - HasModule, HirDisplay, Interned, InternedClosure, Interner, Interval, IntervalAndTy, - IntervalOrOwned, ItemContainerId, LangItem, Layout, Locals, Lookup, MirEvalError, MirSpan, - Mutability, Result, Substitution, Ty, TyBuilder, TyExt, +use crate::{ + error_lifetime, + mir::eval::{ + name, pad16, Address, AdtId, Arc, BuiltinType, Evaluator, FunctionId, HasModule, + HirDisplay, Interned, InternedClosure, Interner, Interval, IntervalAndTy, IntervalOrOwned, + ItemContainerId, LangItem, Layout, Locals, Lookup, MirEvalError, MirSpan, Mutability, + Result, Substitution, Ty, TyBuilder, TyExt, + }, }; mod simd; @@ -247,7 +250,7 @@ impl Evaluator<'_> { let tmp = self.heap_allocate(self.ptr_size(), self.ptr_size())?; let arg = IntervalAndTy { interval: Interval { addr: tmp, size: self.ptr_size() }, - ty: TyKind::Ref(Mutability::Not, static_lifetime(), ty.clone()).intern(Interner), + ty: TyKind::Ref(Mutability::Not, error_lifetime(), ty.clone()).intern(Interner), }; let offset = layout.fields.offset(i).bytes_usize(); self.write_memory(tmp, &addr.offset(offset).to_bytes())?; diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs index f2505c1937774..ea311cadb727d 100644 --- a/crates/hir-ty/src/mir/lower.rs +++ b/crates/hir-ty/src/mir/lower.rs @@ -27,6 +27,7 @@ use crate::{ consteval::ConstEvalError, db::{HirDatabase, InternedClosure}, display::HirDisplay, + error_lifetime, infer::{CaptureKind, CapturedItem, TypeMismatch}, inhabitedness::is_ty_uninhabited_from, layout::LayoutError, @@ -2033,10 +2034,12 @@ pub fn mir_body_for_closure_query( let closure_local = ctx.result.locals.alloc(Local { ty: match kind { FnTrait::FnOnce => infer[expr].clone(), - FnTrait::FnMut => TyKind::Ref(Mutability::Mut, static_lifetime(), infer[expr].clone()) - .intern(Interner), - FnTrait::Fn => TyKind::Ref(Mutability::Not, static_lifetime(), infer[expr].clone()) - .intern(Interner), + FnTrait::FnMut => { + TyKind::Ref(Mutability::Mut, error_lifetime(), infer[expr].clone()).intern(Interner) + } + FnTrait::Fn => { + TyKind::Ref(Mutability::Not, error_lifetime(), infer[expr].clone()).intern(Interner) + } }, }); ctx.result.param_locals.push(closure_local); diff --git a/crates/hir-ty/src/mir/lower/as_place.rs b/crates/hir-ty/src/mir/lower/as_place.rs index be81915bb407f..4ad00909e4127 100644 --- a/crates/hir-ty/src/mir/lower/as_place.rs +++ b/crates/hir-ty/src/mir/lower/as_place.rs @@ -290,7 +290,7 @@ impl MirLowerCtx<'_> { Some((_, _, mutability)) => mutability, None => Mutability::Not, }; - let result_ref = TyKind::Ref(mutability, static_lifetime(), result_ty).intern(Interner); + let result_ref = TyKind::Ref(mutability, error_lifetime(), result_ty).intern(Interner); let mut result: Place = self.temp(result_ref, current, span)?.into(); let index_fn_op = Operand::const_zst( TyKind::FnDef( @@ -333,8 +333,8 @@ impl MirLowerCtx<'_> { BorrowKind::Mut { kind: MutBorrowKind::Default }, ) }; - let ty_ref = TyKind::Ref(chalk_mut, static_lifetime(), source_ty.clone()).intern(Interner); - let target_ty_ref = TyKind::Ref(chalk_mut, static_lifetime(), target_ty).intern(Interner); + let ty_ref = TyKind::Ref(chalk_mut, error_lifetime(), source_ty.clone()).intern(Interner); + let target_ty_ref = TyKind::Ref(chalk_mut, error_lifetime(), target_ty).intern(Interner); let ref_place: Place = self.temp(ty_ref, current, span)?.into(); self.push_assignment(current, ref_place, Rvalue::Ref(borrow_kind, place), span); let deref_trait = self diff --git a/crates/hir-ty/src/tests/traits.rs b/crates/hir-ty/src/tests/traits.rs index 759af18c98bf5..fac850eeaf3cc 100644 --- a/crates/hir-ty/src/tests/traits.rs +++ b/crates/hir-ty/src/tests/traits.rs @@ -1612,10 +1612,10 @@ fn test( ) {} "#, expect![[r#" - 28..29 'a': impl Trait - 59..60 'b': impl Sized + 28..29 'a': impl Trait + 'static + 59..60 'b': impl 'static 82..83 'c': impl Trait - 103..104 'd': impl Sized + 103..104 'd': impl 'static 128..129 'e': impl ?Sized 148..149 'f': impl Trait + ?Sized 173..175 '{}': () diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 23c6b078b9696..84f03d111f275 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -1,4 +1,5 @@ //! HirDisplay implementations for various hir types. +use either::Either; use hir_def::{ data::adt::{StructKind, VariantData}, generics::{ @@ -13,7 +14,7 @@ use hir_ty::{ write_bounds_like_dyn_trait_with_prefix, write_visibility, HirDisplay, HirDisplayError, HirFormatter, SizedByDefault, }, - Interner, TraitRefExt, WhereClause, + AliasEq, AliasTy, Interner, ProjectionTyExt, TraitRefExt, TyKind, WhereClause, }; use crate::{ @@ -363,16 +364,52 @@ impl HirDisplay for TypeOrConstParam { impl HirDisplay for TypeParam { fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> { - write!(f, "{}", self.name(f.db).display(f.db.upcast()))?; + let params = f.db.generic_params(self.id.parent()); + let param_data = ¶ms.type_or_consts[self.id.local_id()]; + let substs = TyBuilder::placeholder_subst(f.db, self.id.parent()); + let krate = self.id.parent().krate(f.db).id; + let ty = + TyKind::Placeholder(hir_ty::to_placeholder_idx(f.db, self.id.into())).intern(Interner); + let predicates = f.db.generic_predicates(self.id.parent()); + let predicates = predicates + .iter() + .cloned() + .map(|pred| pred.substitute(Interner, &substs)) + .filter(|wc| match wc.skip_binders() { + WhereClause::Implemented(tr) => tr.self_type_parameter(Interner) == ty, + WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(proj), ty: _ }) => { + proj.self_type_parameter(f.db) == ty + } + WhereClause::AliasEq(_) => false, + WhereClause::TypeOutlives(to) => to.ty == ty, + WhereClause::LifetimeOutlives(_) => false, + }) + .collect::>(); + + match param_data { + TypeOrConstParamData::TypeParamData(p) => match p.provenance { + TypeParamProvenance::TypeParamList | TypeParamProvenance::TraitSelf => { + write!(f, "{}", p.name.clone().unwrap().display(f.db.upcast()))? + } + TypeParamProvenance::ArgumentImplTrait => { + return write_bounds_like_dyn_trait_with_prefix( + f, + "impl", + Either::Left(&ty), + &predicates, + SizedByDefault::Sized { anchor: krate }, + ); + } + }, + TypeOrConstParamData::ConstParamData(p) => { + write!(f, "{}", p.name.display(f.db.upcast()))?; + } + } + if f.omit_verbose_types() { return Ok(()); } - let bounds = f.db.generic_predicates_for_param(self.id.parent(), self.id.into(), None); - let substs = TyBuilder::placeholder_subst(f.db, self.id.parent()); - let predicates: Vec<_> = - bounds.iter().cloned().map(|b| b.substitute(Interner, &substs)).collect(); - let krate = self.id.parent().krate(f.db).id; let sized_trait = f.db.lang_item(krate, LangItem::Sized).and_then(|lang_item| lang_item.as_trait()); let has_only_sized_bound = predicates.iter().all(move |pred| match pred.skip_binders() { @@ -382,7 +419,16 @@ impl HirDisplay for TypeParam { let has_only_not_sized_bound = predicates.is_empty(); if !has_only_sized_bound || has_only_not_sized_bound { let default_sized = SizedByDefault::Sized { anchor: krate }; - write_bounds_like_dyn_trait_with_prefix(f, ":", &predicates, default_sized)?; + write_bounds_like_dyn_trait_with_prefix( + f, + ":", + Either::Left( + &hir_ty::TyKind::Placeholder(hir_ty::to_placeholder_idx(f.db, self.id.into())) + .intern(Interner), + ), + &predicates, + default_sized, + )?; } Ok(()) } diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 3165adcd3a5cb..d1735e9f1d3c6 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -3910,7 +3910,7 @@ impl Type { inner.derived( TyKind::Ref( if m.is_mut() { hir_ty::Mutability::Mut } else { hir_ty::Mutability::Not }, - hir_ty::static_lifetime(), + hir_ty::error_lifetime(), inner.ty.clone(), ) .intern(Interner), diff --git a/crates/ide-assists/src/handlers/auto_import.rs b/crates/ide-assists/src/handlers/auto_import.rs index 62696d1a9a808..5545e41f53074 100644 --- a/crates/ide-assists/src/handlers/auto_import.rs +++ b/crates/ide-assists/src/handlers/auto_import.rs @@ -1585,6 +1585,38 @@ mod bar { Foo; } } +"#, + ); + } + + #[test] + fn local_inline_import_has_alias() { + // FIXME + check_assist_not_applicable( + auto_import, + r#" +struct S(T); +use S as IoResult; + +mod foo { + pub fn bar() -> S$0<()> {} +} +"#, + ); + } + + #[test] + fn alias_local() { + // FIXME + check_assist_not_applicable( + auto_import, + r#" +struct S(T); +use S as IoResult; + +mod foo { + pub fn bar() -> IoResult$0<()> {} +} "#, ); } diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index 08925fcdff580..d1721f1191a02 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -4040,7 +4040,6 @@ impl Foo {} ``` "#]], ); - // lifetimes bounds arent being tracked yet check( r#" //- minicore: sized @@ -4051,7 +4050,7 @@ impl Foo {} *T* ```rust - T + T: 'static ``` "#]], );