about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-04-02 14:13:22 +0000
committerbors <bors@rust-lang.org>2024-04-02 14:13:22 +0000
commitc3b8c2a25413e2aa58295d18c12902a624471b74 (patch)
treec040390114aab42ddef26f28e0a4f98e8552c4f7
parent54faa0312156c79b0af9e9f4fef8f3bada41e69f (diff)
parent707be6b99c660d3919da0b5c1d60933ff4654247 (diff)
downloadrust-c3b8c2a25413e2aa58295d18c12902a624471b74.tar.gz
rust-c3b8c2a25413e2aa58295d18c12902a624471b74.zip
Auto merge of #16996 - Veykril:lt-err, r=Veykril
internal: Lower outlive goals, respect them in display impls
-rw-r--r--crates/hir-def/src/find_path.rs4
-rw-r--r--crates/hir-def/src/generics.rs2
-rw-r--r--crates/hir-def/src/item_scope.rs32
-rw-r--r--crates/hir-def/src/lib.rs18
-rw-r--r--crates/hir-ty/src/chalk_ext.rs9
-rw-r--r--crates/hir-ty/src/display.rs47
-rw-r--r--crates/hir-ty/src/infer.rs6
-rw-r--r--crates/hir-ty/src/infer/closure.rs6
-rw-r--r--crates/hir-ty/src/infer/coerce.rs6
-rw-r--r--crates/hir-ty/src/infer/expr.rs3
-rw-r--r--crates/hir-ty/src/infer/pat.rs7
-rw-r--r--crates/hir-ty/src/infer/unify.rs62
-rw-r--r--crates/hir-ty/src/lib.rs6
-rw-r--r--crates/hir-ty/src/lower.rs70
-rw-r--r--crates/hir-ty/src/method_resolution.rs10
-rw-r--r--crates/hir-ty/src/mir/eval/shim.rs15
-rw-r--r--crates/hir-ty/src/mir/lower.rs11
-rw-r--r--crates/hir-ty/src/mir/lower/as_place.rs6
-rw-r--r--crates/hir-ty/src/tests/traits.rs6
-rw-r--r--crates/hir/src/display.rs62
-rw-r--r--crates/hir/src/lib.rs2
-rw-r--r--crates/ide-assists/src/handlers/auto_import.rs32
-rw-r--r--crates/ide/src/hover/tests.rs3
23 files changed, 303 insertions, 122 deletions
diff --git a/crates/hir-def/src/find_path.rs b/crates/hir-def/src/find_path.rs
index 0cd4a5db8c3..d06fc4df768 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<Name> {
     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 4638b377197..118055b605e 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<Name>,
     pub default: Option<Interned<TypeRef>>,
     pub provenance: TypeParamProvenance,
diff --git a/crates/hir-def/src/item_scope.rs b/crates/hir-def/src/item_scope.rs
index 2b059d1f8dc..a60b9f9f3ab 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<T>(
+        &self,
+        item: ItemInNs,
+        mut cb: impl FnMut(&Name, Visibility, bool) -> Option<T>,
+    ) -> Option<T> {
+        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<Item = TraitId> + '_ {
         self.types
             .values()
diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs
index 46898ce542d..88d4572196c 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<DefMap> {
+        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<ModuleId> {
         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<TraitId> {
+        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<AssocItemId> for GenericDefId {
diff --git a/crates/hir-ty/src/chalk_ext.rs b/crates/hir-ty/src/chalk_ext.rs
index d1aebeff261..0bf01b0bc6a 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::<Vec<_>>();
diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs
index 8740ae6797c..eb7f106cdfa 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::<Vec<_>>();
                             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 bb558e533c4..3b644379fa6 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 32845ac2e36..20d24e6fe2e 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 cfbbc9dd6c0..72928851f12 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 35d59679355..4d3d7376c4d 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 30005a25512..440ffa33572 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 afb89fe1e5b..b68fefc5150 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<T: HasInterner<Interner = Interner>> Canonicalized<T> {
                 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 ba64f5c8d7e..ad8202d4d23 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<T: HasInterner<Interner = Interner> + TypeFoldable<Interner>>(
@@ -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 25ccc84c13c..9a468e2a233 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::<Vec<_>>()
                     .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<ItemContainerId> = 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<T1, T2, ...>` 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 73b07df56f7..cd723494713 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 d4d669182f2..fee3dd3ada8 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 f2505c19377..ea311cadb72 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 be81915bb40..4ad00909e41 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 759af18c98b..fac850eeaf3 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 23c6b078b96..84f03d111f2 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 = &params.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::<Vec<_>>();
+
+        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 3165adcd3a5..d1735e9f1d3 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 62696d1a9a8..5545e41f530 100644
--- a/crates/ide-assists/src/handlers/auto_import.rs
+++ b/crates/ide-assists/src/handlers/auto_import.rs
@@ -1588,4 +1588,36 @@ mod bar {
 "#,
         );
     }
+
+    #[test]
+    fn local_inline_import_has_alias() {
+        // FIXME
+        check_assist_not_applicable(
+            auto_import,
+            r#"
+struct S<T>(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>(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 08925fcdff5..d1721f1191a 100644
--- a/crates/ide/src/hover/tests.rs
+++ b/crates/ide/src/hover/tests.rs
@@ -4040,7 +4040,6 @@ impl<T> Foo<T$0> {}
             ```
         "#]],
     );
-    // lifetimes bounds arent being tracked yet
     check(
         r#"
 //- minicore: sized
@@ -4051,7 +4050,7 @@ impl<T: 'static> Foo<T$0> {}
             *T*
 
             ```rust
-            T
+            T: 'static
             ```
         "#]],
     );