about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs144
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/asm.rs11
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/generics.rs230
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/path.rs10
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/path/tests.rs3
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs40
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/hir/generics.rs25
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/signatures.rs5
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/display.rs20
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lower.rs52
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/utils.rs15
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/display.rs48
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs10
13 files changed, 302 insertions, 311 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs
index d49c283bee6..ddcdb321e22 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs
@@ -37,6 +37,7 @@ use crate::{
         Body, BodySourceMap, ExprPtr, ExpressionStore, ExpressionStoreBuilder,
         ExpressionStoreDiagnostics, ExpressionStoreSourceMap, HygieneId, LabelPtr, PatPtr, TypePtr,
         expander::Expander,
+        lower::generics::ImplTraitLowerFn,
         path::{AssociatedTypeBinding, GenericArg, GenericArgs, GenericArgsParentheses, Path},
     },
     hir::{
@@ -193,7 +194,8 @@ pub(crate) fn lower_type_ref(
     type_ref: InFile<Option<ast::Type>>,
 ) -> (ExpressionStore, ExpressionStoreSourceMap, TypeRefId) {
     let mut expr_collector = ExprCollector::new(db, module, type_ref.file_id);
-    let type_ref = expr_collector.lower_type_ref_opt(type_ref.value, &mut TypeRef::ImplTrait);
+    let type_ref =
+        expr_collector.lower_type_ref_opt(type_ref.value, &mut ExprCollector::impl_trait_allocator);
     (expr_collector.store.finish(), expr_collector.source_map, type_ref)
 }
 
@@ -206,8 +208,8 @@ pub(crate) fn lower_generic_params(
     where_clause: Option<ast::WhereClause>,
 ) -> (Arc<ExpressionStore>, Arc<GenericParams>, ExpressionStoreSourceMap) {
     let mut expr_collector = ExprCollector::new(db, module, file_id);
-    let mut collector = generics::GenericParamsCollector::new(&mut expr_collector, def);
-    collector.lower(param_list, where_clause);
+    let mut collector = generics::GenericParamsCollector::new(def);
+    collector.lower(&mut expr_collector, param_list, where_clause);
     let params = collector.finish();
     (Arc::new(expr_collector.store.finish()), params, expr_collector.source_map)
 }
@@ -223,13 +225,18 @@ pub(crate) fn lower_impl(
         expr_collector.lower_type_ref_opt_disallow_impl_trait(impl_syntax.value.self_ty());
     let trait_ = impl_syntax.value.trait_().and_then(|it| match &it {
         ast::Type::PathType(path_type) => {
-            let path = expr_collector.lower_path_type(path_type, &mut |_| TypeRef::Error)?;
+            let path = expr_collector
+                .lower_path_type(path_type, &mut ExprCollector::impl_trait_allocator)?;
             Some(TraitRef { path: expr_collector.alloc_path(path, AstPtr::new(&it)) })
         }
         _ => None,
     });
-    let mut collector = generics::GenericParamsCollector::new(&mut expr_collector, impl_id.into());
-    collector.lower(impl_syntax.value.generic_param_list(), impl_syntax.value.where_clause());
+    let mut collector = generics::GenericParamsCollector::new(impl_id.into());
+    collector.lower(
+        &mut expr_collector,
+        impl_syntax.value.generic_param_list(),
+        impl_syntax.value.where_clause(),
+    );
     let params = collector.finish();
     (expr_collector.store.finish(), expr_collector.source_map, self_ty, trait_, params)
 }
@@ -241,9 +248,16 @@ pub(crate) fn lower_trait(
     trait_id: TraitId,
 ) -> (ExpressionStore, ExpressionStoreSourceMap, Arc<GenericParams>) {
     let mut expr_collector = ExprCollector::new(db, module, trait_syntax.file_id);
-    let mut collector = generics::GenericParamsCollector::new(&mut expr_collector, trait_id.into());
-    collector.fill_self_param(trait_syntax.value.type_bound_list());
-    collector.lower(trait_syntax.value.generic_param_list(), trait_syntax.value.where_clause());
+    let mut collector = generics::GenericParamsCollector::with_self_param(
+        &mut expr_collector,
+        trait_id.into(),
+        trait_syntax.value.type_bound_list(),
+    );
+    collector.lower(
+        &mut expr_collector,
+        trait_syntax.value.generic_param_list(),
+        trait_syntax.value.where_clause(),
+    );
     let params = collector.finish();
     (expr_collector.store.finish(), expr_collector.source_map, params)
 }
@@ -255,9 +269,16 @@ pub(crate) fn lower_trait_alias(
     trait_id: TraitAliasId,
 ) -> (ExpressionStore, ExpressionStoreSourceMap, Arc<GenericParams>) {
     let mut expr_collector = ExprCollector::new(db, module, trait_syntax.file_id);
-    let mut collector = generics::GenericParamsCollector::new(&mut expr_collector, trait_id.into());
-    collector.fill_self_param(trait_syntax.value.type_bound_list());
-    collector.lower(trait_syntax.value.generic_param_list(), trait_syntax.value.where_clause());
+    let mut collector = generics::GenericParamsCollector::with_self_param(
+        &mut expr_collector,
+        trait_id.into(),
+        trait_syntax.value.type_bound_list(),
+    );
+    collector.lower(
+        &mut expr_collector,
+        trait_syntax.value.generic_param_list(),
+        trait_syntax.value.where_clause(),
+    );
     let params = collector.finish();
     (expr_collector.store.finish(), expr_collector.source_map, params)
 }
@@ -281,16 +302,23 @@ pub(crate) fn lower_type_alias(
         .map(|bounds| {
             bounds
                 .bounds()
-                .map(|bound| expr_collector.lower_type_bound(bound, &mut TypeRef::ImplTrait))
+                .map(|bound| {
+                    expr_collector.lower_type_bound(bound, &mut ExprCollector::impl_trait_allocator)
+                })
                 .collect()
         })
         .unwrap_or_default();
-    let mut collector =
-        generics::GenericParamsCollector::new(&mut expr_collector, type_alias_id.into());
-    collector.lower(alias.value.generic_param_list(), alias.value.where_clause());
+    let mut collector = generics::GenericParamsCollector::new(type_alias_id.into());
+    collector.lower(
+        &mut expr_collector,
+        alias.value.generic_param_list(),
+        alias.value.where_clause(),
+    );
     let params = collector.finish();
-    let type_ref =
-        alias.value.ty().map(|ty| expr_collector.lower_type_ref(ty, &mut TypeRef::ImplTrait));
+    let type_ref = alias
+        .value
+        .ty()
+        .map(|ty| expr_collector.lower_type_ref(ty, &mut ExprCollector::impl_trait_allocator));
     (expr_collector.store.finish(), expr_collector.source_map, params, bounds, type_ref)
 }
 
@@ -309,13 +337,12 @@ pub(crate) fn lower_function(
     bool,
 ) {
     let mut expr_collector = ExprCollector::new(db, module, fn_.file_id);
-    let mut collector =
-        generics::GenericParamsCollector::new(&mut expr_collector, function_id.into());
-    collector.lower(fn_.value.generic_param_list(), fn_.value.where_clause());
+    let mut collector = generics::GenericParamsCollector::new(function_id.into());
+    collector.lower(&mut expr_collector, fn_.value.generic_param_list(), fn_.value.where_clause());
     let mut params = vec![];
     let mut has_self_param = false;
     let mut has_variadic = false;
-    collector.collect_impl_trait(|collector, mut impl_trait_lower_fn| {
+    collector.collect_impl_trait(&mut expr_collector, |collector, mut impl_trait_lower_fn| {
         if let Some(param_list) = fn_.value.param_list() {
             if let Some(param) = param_list.self_param() {
                 let enabled = collector.expander.is_cfg_enabled(db, module.krate(), &param);
@@ -368,10 +395,9 @@ pub(crate) fn lower_function(
         }
     });
     let generics = collector.finish();
-    let return_type = fn_
-        .value
-        .ret_type()
-        .map(|ret_type| expr_collector.lower_type_ref_opt(ret_type.ty(), &mut TypeRef::ImplTrait));
+    let return_type = fn_.value.ret_type().map(|ret_type| {
+        expr_collector.lower_type_ref_opt(ret_type.ty(), &mut ExprCollector::impl_trait_allocator)
+    });
 
     let return_type = if fn_.value.async_token().is_some() {
         let path = hir_expand::mod_path::path![core::future::Future];
@@ -563,7 +589,7 @@ impl ExprCollector<'_> {
     pub fn lower_type_ref(
         &mut self,
         node: ast::Type,
-        impl_trait_lower_fn: &mut impl FnMut(ThinVec<TypeBound>) -> TypeRef,
+        impl_trait_lower_fn: ImplTraitLowerFn<'_>,
     ) -> TypeRefId {
         let ty = match &node {
             ast::Type::ParenType(inner) => {
@@ -653,11 +679,11 @@ impl ExprCollector<'_> {
                     // Disallow nested impl traits
                     TypeRef::Error
                 } else {
-                    self.with_outer_impl_trait_scope(true, |this| {
+                    return self.with_outer_impl_trait_scope(true, |this| {
                         let type_bounds =
                             this.type_bounds_from_ast(inner.type_bound_list(), impl_trait_lower_fn);
-                        impl_trait_lower_fn(type_bounds)
-                    })
+                        impl_trait_lower_fn(this, AstPtr::new(&node), type_bounds)
+                    });
                 }
             }
             ast::Type::DynTraitType(inner) => TypeRef::DynTrait(
@@ -680,13 +706,13 @@ impl ExprCollector<'_> {
     }
 
     pub(crate) fn lower_type_ref_disallow_impl_trait(&mut self, node: ast::Type) -> TypeRefId {
-        self.lower_type_ref(node, &mut |_| TypeRef::Error)
+        self.lower_type_ref(node, &mut Self::impl_trait_error_allocator)
     }
 
     pub(crate) fn lower_type_ref_opt(
         &mut self,
         node: Option<ast::Type>,
-        impl_trait_lower_fn: &mut impl FnMut(ThinVec<TypeBound>) -> TypeRef,
+        impl_trait_lower_fn: ImplTraitLowerFn<'_>,
     ) -> TypeRefId {
         match node {
             Some(node) => self.lower_type_ref(node, impl_trait_lower_fn),
@@ -698,7 +724,7 @@ impl ExprCollector<'_> {
         &mut self,
         node: Option<ast::Type>,
     ) -> TypeRefId {
-        self.lower_type_ref_opt(node, &mut |_| TypeRef::Error)
+        self.lower_type_ref_opt(node, &mut Self::impl_trait_error_allocator)
     }
 
     fn alloc_type_ref(&mut self, type_ref: TypeRef, node: TypePtr) -> TypeRefId {
@@ -712,7 +738,7 @@ impl ExprCollector<'_> {
     pub fn lower_path(
         &mut self,
         ast: ast::Path,
-        impl_trait_lower_fn: &mut impl FnMut(ThinVec<TypeBound>) -> TypeRef,
+        impl_trait_lower_fn: ImplTraitLowerFn<'_>,
     ) -> Option<Path> {
         super::lower::path::lower_path(self, ast, impl_trait_lower_fn)
     }
@@ -736,6 +762,22 @@ impl ExprCollector<'_> {
         self.store.types.alloc(TypeRef::Error)
     }
 
+    pub fn impl_trait_error_allocator(
+        ec: &mut ExprCollector<'_>,
+        ptr: TypePtr,
+        _: ThinVec<TypeBound>,
+    ) -> TypeRefId {
+        ec.alloc_type_ref(TypeRef::Error, ptr)
+    }
+
+    fn impl_trait_allocator(
+        ec: &mut ExprCollector<'_>,
+        ptr: TypePtr,
+        bounds: ThinVec<TypeBound>,
+    ) -> TypeRefId {
+        ec.alloc_type_ref(TypeRef::ImplTrait(bounds), ptr)
+    }
+
     fn alloc_path(&mut self, path: Path, node: TypePtr) -> PathId {
         PathId::from_type_ref_unchecked(self.alloc_type_ref(TypeRef::Path(path), node))
     }
@@ -746,7 +788,7 @@ impl ExprCollector<'_> {
         &mut self,
         args: Option<ast::ParenthesizedArgList>,
         ret_type: Option<ast::RetType>,
-        impl_trait_lower_fn: &mut impl FnMut(ThinVec<TypeBound>) -> TypeRef,
+        impl_trait_lower_fn: ImplTraitLowerFn<'_>,
     ) -> Option<GenericArgs> {
         let params = args?;
         let mut param_types = Vec::new();
@@ -786,7 +828,7 @@ impl ExprCollector<'_> {
     pub(super) fn lower_generic_args(
         &mut self,
         node: ast::GenericArgList,
-        impl_trait_lower_fn: &mut impl FnMut(ThinVec<TypeBound>) -> TypeRef,
+        impl_trait_lower_fn: ImplTraitLowerFn<'_>,
     ) -> Option<GenericArgs> {
         // This needs to be kept in sync with `hir_generic_arg_to_ast()`.
         let mut args = Vec::new();
@@ -877,7 +919,7 @@ impl ExprCollector<'_> {
     fn type_bounds_from_ast(
         &mut self,
         type_bounds_opt: Option<ast::TypeBoundList>,
-        impl_trait_lower_fn: &mut impl FnMut(ThinVec<TypeBound>) -> TypeRef,
+        impl_trait_lower_fn: ImplTraitLowerFn<'_>,
     ) -> ThinVec<TypeBound> {
         if let Some(type_bounds) = type_bounds_opt {
             ThinVec::from_iter(Vec::from_iter(
@@ -891,7 +933,7 @@ impl ExprCollector<'_> {
     fn lower_path_type(
         &mut self,
         path_type: &ast::PathType,
-        impl_trait_lower_fn: &mut impl FnMut(ThinVec<TypeBound>) -> TypeRef,
+        impl_trait_lower_fn: ImplTraitLowerFn<'_>,
     ) -> Option<Path> {
         let path = self.lower_path(path_type.path()?, impl_trait_lower_fn)?;
         Some(path)
@@ -900,7 +942,7 @@ impl ExprCollector<'_> {
     fn lower_type_bound(
         &mut self,
         node: ast::TypeBound,
-        impl_trait_lower_fn: &mut impl FnMut(ThinVec<TypeBound>) -> TypeRef,
+        impl_trait_lower_fn: ImplTraitLowerFn<'_>,
     ) -> TypeBound {
         match node.kind() {
             ast::TypeBoundKind::PathType(path_type) => {
@@ -1081,7 +1123,9 @@ impl ExprCollector<'_> {
                 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
                 let generic_args = e
                     .generic_arg_list()
-                    .and_then(|it| self.lower_generic_args(it, &mut |_| TypeRef::Error))
+                    .and_then(|it| {
+                        self.lower_generic_args(it, &mut Self::impl_trait_error_allocator)
+                    })
                     .map(Box::new);
                 self.alloc_expr(
                     Expr::MethodCall { receiver, method_name, args, generic_args },
@@ -1162,7 +1206,7 @@ impl ExprCollector<'_> {
             ast::Expr::RecordExpr(e) => {
                 let path = e
                     .path()
-                    .and_then(|path| self.lower_path(path, &mut |_| TypeRef::Error))
+                    .and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator))
                     .map(Box::new);
                 let record_lit = if let Some(nfl) = e.record_expr_field_list() {
                     let fields = nfl
@@ -1390,7 +1434,7 @@ impl ExprCollector<'_> {
 
     fn collect_expr_path(&mut self, e: ast::PathExpr) -> Option<(Path, HygieneId)> {
         e.path().and_then(|path| {
-            let path = self.lower_path(path, &mut |_| TypeRef::Error)?;
+            let path = self.lower_path(path, &mut Self::impl_trait_error_allocator)?;
             // Need to enable `mod_path.len() < 1` for `self`.
             let may_be_variable = matches!(&path, Path::BarePath(mod_path) if mod_path.len() <= 1);
             let hygiene = if may_be_variable {
@@ -1459,7 +1503,7 @@ impl ExprCollector<'_> {
                 let path = collect_path(self, e.expr()?)?;
                 let path = path
                     .path()
-                    .and_then(|path| self.lower_path(path, &mut |_| TypeRef::Error))
+                    .and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator))
                     .map(Box::new);
                 let (ellipsis, args) = collect_tuple(self, e.arg_list()?.args());
                 self.alloc_pat_from_expr(Pat::TupleStruct { path, args, ellipsis }, syntax_ptr)
@@ -1488,7 +1532,7 @@ impl ExprCollector<'_> {
             ast::Expr::RecordExpr(e) => {
                 let path = e
                     .path()
-                    .and_then(|path| self.lower_path(path, &mut |_| TypeRef::Error))
+                    .and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator))
                     .map(Box::new);
                 let record_field_list = e.record_expr_field_list()?;
                 let ellipsis = record_field_list.dotdot_token().is_some();
@@ -2225,7 +2269,7 @@ impl ExprCollector<'_> {
             ast::Pat::TupleStructPat(p) => {
                 let path = p
                     .path()
-                    .and_then(|path| self.lower_path(path, &mut |_| TypeRef::Error))
+                    .and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator))
                     .map(Box::new);
                 let (args, ellipsis) = self.collect_tuple_pat(
                     p.fields(),
@@ -2240,7 +2284,9 @@ impl ExprCollector<'_> {
                 Pat::Ref { pat, mutability }
             }
             ast::Pat::PathPat(p) => {
-                let path = p.path().and_then(|path| self.lower_path(path, &mut |_| TypeRef::Error));
+                let path = p
+                    .path()
+                    .and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator));
                 path.map(Pat::Path).unwrap_or(Pat::Missing)
             }
             ast::Pat::OrPat(p) => 'b: {
@@ -2289,7 +2335,7 @@ impl ExprCollector<'_> {
             ast::Pat::RecordPat(p) => {
                 let path = p
                     .path()
-                    .and_then(|path| self.lower_path(path, &mut |_| TypeRef::Error))
+                    .and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator))
                     .map(Box::new);
                 let record_pat_field_list =
                     &p.record_pat_field_list().expect("every struct should have a field list");
@@ -2385,7 +2431,9 @@ impl ExprCollector<'_> {
                                 .map(|path| self.alloc_expr_from_pat(Expr::Path(path), ptr)),
                             ast::Pat::PathPat(p) => p
                                 .path()
-                                .and_then(|path| self.lower_path(path, &mut |_| TypeRef::Error))
+                                .and_then(|path| {
+                                    self.lower_path(path, &mut Self::impl_trait_error_allocator)
+                                })
                                 .map(|parsed| self.alloc_expr_from_pat(Expr::Path(parsed), ptr)),
                             // We only need to handle literal, ident (if bare) and path patterns here,
                             // as any other pattern as a range pattern operand is semantically invalid.
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/asm.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/asm.rs
index ca331e84d30..9ef03065651 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/asm.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/asm.rs
@@ -11,7 +11,6 @@ use tt::TextRange;
 use crate::{
     expr_store::lower::{ExprCollector, FxIndexSet},
     hir::{AsmOperand, AsmOptions, Expr, ExprId, InlineAsm, InlineAsmRegOrRegClass},
-    type_ref::TypeRef,
 };
 
 impl ExprCollector<'_> {
@@ -159,10 +158,12 @@ impl ExprCollector<'_> {
                                 AsmOperand::Const(self.collect_expr_opt(c.expr()))
                             }
                             ast::AsmOperand::AsmSym(s) => {
-                                let Some(path) = s
-                                    .path()
-                                    .and_then(|p| self.lower_path(p, &mut |_| TypeRef::Error))
-                                else {
+                                let Some(path) = s.path().and_then(|p| {
+                                    self.lower_path(
+                                        p,
+                                        &mut ExprCollector::impl_trait_error_allocator,
+                                    )
+                                }) else {
                                     continue;
                                 };
                                 AsmOperand::Sym(path)
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/generics.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/generics.rs
index 4f14a7f2d9c..004bbe949f2 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/generics.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/generics.rs
@@ -15,73 +15,102 @@ use triomphe::Arc;
 
 use crate::{
     GenericDefId, TypeOrConstParamId, TypeParamId,
-    expr_store::lower::ExprCollector,
+    expr_store::{TypePtr, lower::ExprCollector},
     hir::generics::{
         ConstParamData, GenericParams, LifetimeParamData, TypeOrConstParamData, TypeParamData,
-        TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
+        TypeParamProvenance, WherePredicate,
     },
     type_ref::{LifetimeRef, TypeBound, TypeRef, TypeRefId},
 };
 
-pub(crate) struct GenericParamsCollector<'db, 'c> {
-    expr_collector: &'c mut ExprCollector<'db>,
+pub(crate) type ImplTraitLowerFn<'l> = &'l mut dyn for<'ec, 'db> FnMut(
+    &'ec mut ExprCollector<'db>,
+    TypePtr,
+    ThinVec<TypeBound>,
+) -> TypeRefId;
+
+pub(crate) struct GenericParamsCollector {
     type_or_consts: Arena<TypeOrConstParamData>,
     lifetimes: Arena<LifetimeParamData>,
     where_predicates: Vec<WherePredicate>,
     parent: GenericDefId,
 }
 
-impl<'db, 'c> GenericParamsCollector<'db, 'c> {
-    pub(crate) fn new(expr_collector: &'c mut ExprCollector<'db>, parent: GenericDefId) -> Self {
+impl GenericParamsCollector {
+    pub(crate) fn new(parent: GenericDefId) -> Self {
         Self {
-            expr_collector,
             type_or_consts: Default::default(),
             lifetimes: Default::default(),
             where_predicates: Default::default(),
             parent,
         }
     }
-
-    pub(crate) fn fill_self_param(&mut self, bounds: Option<ast::TypeBoundList>) {
-        let self_ = Name::new_symbol_root(sym::Self_);
-        let idx = self.type_or_consts.alloc(
-            TypeParamData {
-                name: Some(self_.clone()),
-                default: None,
-                provenance: TypeParamProvenance::TraitSelf,
-            }
-            .into(),
-        );
-        let type_ref = TypeRef::TypeParam(TypeParamId::from_unchecked(TypeOrConstParamId {
-            parent: self.parent,
-            local_id: idx,
-        }));
-        let self_ = self.expr_collector.alloc_type_ref_desugared(type_ref);
-        if let Some(bounds) = bounds {
-            self.lower_bounds(Some(bounds), Either::Left(self_));
-        }
+    pub(crate) fn with_self_param(
+        ec: &mut ExprCollector<'_>,
+        parent: GenericDefId,
+        bounds: Option<ast::TypeBoundList>,
+    ) -> Self {
+        let mut this = Self::new(parent);
+        this.fill_self_param(ec, bounds);
+        this
     }
 
     pub(crate) fn lower(
         &mut self,
+        ec: &mut ExprCollector<'_>,
         generic_param_list: Option<ast::GenericParamList>,
         where_clause: Option<ast::WhereClause>,
     ) {
         if let Some(params) = generic_param_list {
-            self.lower_param_list(params)
+            self.lower_param_list(ec, params)
         }
         if let Some(where_clause) = where_clause {
-            self.lower_where_predicates(where_clause);
+            self.lower_where_predicates(ec, where_clause);
         }
     }
 
-    fn lower_param_list(&mut self, params: ast::GenericParamList) {
+    pub(crate) fn collect_impl_trait<R>(
+        &mut self,
+        ec: &mut ExprCollector<'_>,
+        cb: impl FnOnce(&mut ExprCollector<'_>, ImplTraitLowerFn<'_>) -> R,
+    ) -> R {
+        cb(
+            ec,
+            &mut Self::lower_argument_impl_trait(
+                &mut self.type_or_consts,
+                &mut self.where_predicates,
+                self.parent,
+            ),
+        )
+    }
+
+    pub(crate) fn finish(self) -> Arc<GenericParams> {
+        let Self { mut lifetimes, mut type_or_consts, mut where_predicates, parent: _ } = self;
+
+        if lifetimes.is_empty() && type_or_consts.is_empty() && where_predicates.is_empty() {
+            static EMPTY: LazyLock<Arc<GenericParams>> = LazyLock::new(|| {
+                Arc::new(GenericParams {
+                    lifetimes: Arena::new(),
+                    type_or_consts: Arena::new(),
+                    where_predicates: Box::default(),
+                })
+            });
+            return Arc::clone(&EMPTY);
+        }
+
+        lifetimes.shrink_to_fit();
+        type_or_consts.shrink_to_fit();
+        where_predicates.shrink_to_fit();
+        Arc::new(GenericParams {
+            type_or_consts,
+            lifetimes,
+            where_predicates: where_predicates.into_boxed_slice(),
+        })
+    }
+
+    fn lower_param_list(&mut self, ec: &mut ExprCollector<'_>, params: ast::GenericParamList) {
         for generic_param in params.generic_params() {
-            let enabled = self.expr_collector.expander.is_cfg_enabled(
-                self.expr_collector.db,
-                self.expr_collector.module.krate(),
-                &generic_param,
-            );
+            let enabled = ec.expander.is_cfg_enabled(ec.db, ec.module.krate(), &generic_param);
             if !enabled {
                 continue;
             }
@@ -89,9 +118,9 @@ impl<'db, 'c> GenericParamsCollector<'db, 'c> {
             match generic_param {
                 ast::GenericParam::TypeParam(type_param) => {
                     let name = type_param.name().map_or_else(Name::missing, |it| it.as_name());
-                    let default = type_param
-                        .default_type()
-                        .map(|it| self.expr_collector.lower_type_ref(it, &mut |_| TypeRef::Error));
+                    let default = type_param.default_type().map(|it| {
+                        ec.lower_type_ref(it, &mut ExprCollector::impl_trait_error_allocator)
+                    });
                     let param = TypeParamData {
                         name: Some(name.clone()),
                         default,
@@ -103,30 +132,29 @@ impl<'db, 'c> GenericParamsCollector<'db, 'c> {
                             parent: self.parent,
                             local_id: idx,
                         }));
-                    let type_ref = self.expr_collector.alloc_type_ref_desugared(type_ref);
-                    self.lower_bounds(type_param.type_bound_list(), Either::Left(type_ref));
+                    let type_ref = ec.alloc_type_ref_desugared(type_ref);
+                    self.lower_bounds(ec, type_param.type_bound_list(), Either::Left(type_ref));
                 }
                 ast::GenericParam::ConstParam(const_param) => {
                     let name = const_param.name().map_or_else(Name::missing, |it| it.as_name());
-                    let ty = self
-                        .expr_collector
-                        .lower_type_ref_opt(const_param.ty(), &mut |_| TypeRef::Error);
+                    let ty = ec.lower_type_ref_opt(
+                        const_param.ty(),
+                        &mut ExprCollector::impl_trait_error_allocator,
+                    );
                     let param = ConstParamData {
                         name,
                         ty,
-                        default: const_param
-                            .default_val()
-                            .map(|it| self.expr_collector.lower_const_arg(it)),
+                        default: const_param.default_val().map(|it| ec.lower_const_arg(it)),
                     };
                     let _idx = self.type_or_consts.alloc(param.into());
                 }
                 ast::GenericParam::LifetimeParam(lifetime_param) => {
-                    let lifetime_ref =
-                        self.expr_collector.lower_lifetime_ref_opt(lifetime_param.lifetime());
+                    let lifetime_ref = ec.lower_lifetime_ref_opt(lifetime_param.lifetime());
                     if let LifetimeRef::Named(name) = &lifetime_ref {
                         let param = LifetimeParamData { name: name.clone() };
                         let _idx = self.lifetimes.alloc(param);
                         self.lower_bounds(
+                            ec,
                             lifetime_param.type_bound_list(),
                             Either::Right(lifetime_ref),
                         );
@@ -136,12 +164,18 @@ impl<'db, 'c> GenericParamsCollector<'db, 'c> {
         }
     }
 
-    fn lower_where_predicates(&mut self, where_clause: ast::WhereClause) {
+    fn lower_where_predicates(
+        &mut self,
+        ec: &mut ExprCollector<'_>,
+        where_clause: ast::WhereClause,
+    ) {
         for pred in where_clause.predicates() {
             let target = if let Some(type_ref) = pred.ty() {
-                Either::Left(self.expr_collector.lower_type_ref(type_ref, &mut |_| TypeRef::Error))
+                Either::Left(
+                    ec.lower_type_ref(type_ref, &mut ExprCollector::impl_trait_error_allocator),
+                )
             } else if let Some(lifetime) = pred.lifetime() {
-                Either::Right(self.expr_collector.lower_lifetime_ref(lifetime))
+                Either::Right(ec.lower_lifetime_ref(lifetime))
             } else {
                 continue;
             };
@@ -158,28 +192,30 @@ impl<'db, 'c> GenericParamsCollector<'db, 'c> {
                     .collect()
             });
             for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) {
-                self.lower_type_bound_as_predicate(bound, lifetimes.as_deref(), target.clone());
+                self.lower_type_bound_as_predicate(ec, bound, lifetimes.as_deref(), target.clone());
             }
         }
     }
 
     fn lower_bounds(
         &mut self,
+        ec: &mut ExprCollector<'_>,
         type_bounds: Option<ast::TypeBoundList>,
         target: Either<TypeRefId, LifetimeRef>,
     ) {
         for bound in type_bounds.iter().flat_map(|type_bound_list| type_bound_list.bounds()) {
-            self.lower_type_bound_as_predicate(bound, None, target.clone());
+            self.lower_type_bound_as_predicate(ec, bound, None, target.clone());
         }
     }
 
     fn lower_type_bound_as_predicate(
         &mut self,
+        ec: &mut ExprCollector<'_>,
         bound: ast::TypeBound,
         hrtb_lifetimes: Option<&[Name]>,
         target: Either<TypeRefId, LifetimeRef>,
     ) {
-        let bound = self.expr_collector.lower_type_bound(
+        let bound = ec.lower_type_bound(
             bound,
             &mut Self::lower_argument_impl_trait(
                 &mut self.type_or_consts,
@@ -192,13 +228,10 @@ impl<'db, 'c> GenericParamsCollector<'db, 'c> {
             (Either::Left(type_ref), bound) => match hrtb_lifetimes {
                 Some(hrtb_lifetimes) => WherePredicate::ForLifetime {
                     lifetimes: hrtb_lifetimes.to_vec().into_boxed_slice(),
-                    target: WherePredicateTypeTarget::TypeRef(type_ref),
-                    bound,
-                },
-                None => WherePredicate::TypeBound {
-                    target: WherePredicateTypeTarget::TypeRef(type_ref),
+                    target: type_ref,
                     bound,
                 },
+                None => WherePredicate::TypeBound { target: type_ref, bound },
             },
             (Either::Right(lifetime), TypeBound::Lifetime(bound)) => {
                 WherePredicate::Lifetime { target: lifetime, bound }
@@ -208,72 +241,49 @@ impl<'db, 'c> GenericParamsCollector<'db, 'c> {
         self.where_predicates.push(predicate);
     }
 
-    pub(crate) fn collect_impl_trait<R>(
-        &mut self,
-        cb: impl FnOnce(&mut ExprCollector<'_>, &mut dyn FnMut(ThinVec<TypeBound>) -> TypeRef) -> R,
-    ) -> R {
-        cb(
-            self.expr_collector,
-            &mut Self::lower_argument_impl_trait(
-                &mut self.type_or_consts,
-                &mut self.where_predicates,
-                self.parent,
-            ),
-        )
-    }
-
     fn lower_argument_impl_trait(
         type_or_consts: &mut Arena<TypeOrConstParamData>,
         where_predicates: &mut Vec<WherePredicate>,
         parent: GenericDefId,
-    ) -> impl FnMut(ThinVec<TypeBound>) -> TypeRef {
-        move |impl_trait_bounds| {
+    ) -> impl for<'ec, 'db> FnMut(&'ec mut ExprCollector<'db>, TypePtr, ThinVec<TypeBound>) -> TypeRefId
+    {
+        move |ec, ptr, impl_trait_bounds| {
             let param = TypeParamData {
                 name: None,
                 default: None,
                 provenance: TypeParamProvenance::ArgumentImplTrait,
             };
-            let param_id = type_or_consts.alloc(param.into());
+            let param_id = TypeRef::TypeParam(TypeParamId::from_unchecked(TypeOrConstParamId {
+                parent,
+                local_id: type_or_consts.alloc(param.into()),
+            }));
+            let type_ref = ec.alloc_type_ref(param_id, ptr);
             for bound in impl_trait_bounds {
-                where_predicates.push(WherePredicate::TypeBound {
-                    target: WherePredicateTypeTarget::TypeOrConstParam(param_id),
-                    bound: bound.clone(),
-                });
+                where_predicates
+                    .push(WherePredicate::TypeBound { target: type_ref, bound: bound.clone() });
             }
-            TypeRef::TypeParam(TypeParamId::from_unchecked(TypeOrConstParamId {
-                parent,
-                local_id: param_id,
-            }))
+            type_ref
         }
     }
 
-    pub(crate) fn finish(self) -> Arc<GenericParams> {
-        let Self {
-            mut lifetimes,
-            mut type_or_consts,
-            mut where_predicates,
-            expr_collector: _,
-            parent: _,
-        } = self;
-
-        if lifetimes.is_empty() && type_or_consts.is_empty() && where_predicates.is_empty() {
-            static EMPTY: LazyLock<Arc<GenericParams>> = LazyLock::new(|| {
-                Arc::new(GenericParams {
-                    lifetimes: Arena::new(),
-                    type_or_consts: Arena::new(),
-                    where_predicates: Box::default(),
-                })
-            });
-            return Arc::clone(&EMPTY);
+    fn fill_self_param(&mut self, ec: &mut ExprCollector<'_>, bounds: Option<ast::TypeBoundList>) {
+        let self_ = Name::new_symbol_root(sym::Self_);
+        let idx = self.type_or_consts.alloc(
+            TypeParamData {
+                name: Some(self_.clone()),
+                default: None,
+                provenance: TypeParamProvenance::TraitSelf,
+            }
+            .into(),
+        );
+        debug_assert_eq!(idx, GenericParams::SELF_PARAM_ID_IN_SELF);
+        let type_ref = TypeRef::TypeParam(TypeParamId::from_unchecked(TypeOrConstParamId {
+            parent: self.parent,
+            local_id: idx,
+        }));
+        let self_ = ec.alloc_type_ref_desugared(type_ref);
+        if let Some(bounds) = bounds {
+            self.lower_bounds(ec, Some(bounds), Either::Left(self_));
         }
-
-        lifetimes.shrink_to_fit();
-        type_or_consts.shrink_to_fit();
-        where_predicates.shrink_to_fit();
-        Arc::new(GenericParams {
-            type_or_consts,
-            lifetimes,
-            where_predicates: where_predicates.into_boxed_slice(),
-        })
     }
 }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/path.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/path.rs
index 14b0d3abd41..629d1f2ada7 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/path.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/path.rs
@@ -5,7 +5,10 @@ mod tests;
 
 use std::iter;
 
-use crate::expr_store::{lower::ExprCollector, path::NormalPath};
+use crate::expr_store::{
+    lower::{ExprCollector, generics::ImplTraitLowerFn},
+    path::NormalPath,
+};
 
 use hir_expand::{
     mod_path::{ModPath, PathKind, resolve_crate_root},
@@ -16,11 +19,10 @@ use syntax::{
     AstPtr,
     ast::{self, AstNode, HasGenericArgs},
 };
-use thin_vec::ThinVec;
 
 use crate::{
     expr_store::path::{GenericArg, GenericArgs, Path},
-    type_ref::{TypeBound, TypeRef},
+    type_ref::TypeRef,
 };
 
 #[cfg(test)]
@@ -36,7 +38,7 @@ thread_local! {
 pub(super) fn lower_path(
     collector: &mut ExprCollector<'_>,
     mut path: ast::Path,
-    impl_trait_lower_fn: &mut impl FnMut(ThinVec<TypeBound>) -> TypeRef,
+    impl_trait_lower_fn: ImplTraitLowerFn<'_>,
 ) -> Option<Path> {
     let mut kind = PathKind::Plain;
     let mut type_anchor = None;
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/path/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/path/tests.rs
index 44043fd0560..337cb103bde 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/path/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/path/tests.rs
@@ -15,14 +15,13 @@ use crate::{
         pretty,
     },
     test_db::TestDB,
-    type_ref::TypeRef,
 };
 
 fn lower_path(path: ast::Path) -> (TestDB, ExpressionStore, Option<Path>) {
     let (db, file_id) = TestDB::with_single_file("");
     let krate = db.fetch_test_crate();
     let mut ctx = ExprCollector::new(&db, db.crate_def_map(krate).root_module_id(), file_id.into());
-    let lowered_path = ctx.lower_path(path, &mut TypeRef::ImplTrait);
+    let lowered_path = ctx.lower_path(path, &mut ExprCollector::impl_trait_allocator);
     let store = ctx.store.finish();
     (db, store, lowered_path)
 }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs
index 5e3580e590e..5adf462062b 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs
@@ -16,7 +16,7 @@ use crate::{
     expr_store::path::{GenericArg, GenericArgs},
     hir::{
         Array, BindingAnnotation, CaptureBy, ClosureKind, Literal, Movability, Statement,
-        generics::{GenericParams, WherePredicate, WherePredicateTypeTarget},
+        generics::{GenericParams, WherePredicate},
     },
     lang_item::LangItemTarget,
     signatures::{FnFlags, FunctionSignature, StructSignature},
@@ -336,21 +336,11 @@ fn print_where_clauses(db: &dyn DefDatabase, generic_params: &GenericParams, p:
                     w!(p, ",\n");
                 }
                 match pred {
-                    WherePredicate::TypeBound { target, bound } => match target {
-                        &WherePredicateTypeTarget::TypeRef(idx) => {
-                            p.print_type_ref(idx);
-                            w!(p, ": ");
-                            p.print_type_bounds(std::slice::from_ref(bound));
-                        }
-                        WherePredicateTypeTarget::TypeOrConstParam(idx) => {
-                            match generic_params[*idx].name() {
-                                Some(name) => w!(p, "{}", name.display(db, p.edition)),
-                                None => w!(p, "Param[{}]", idx.into_raw()),
-                            }
-                            w!(p, ": ");
-                            p.print_type_bounds(std::slice::from_ref(bound));
-                        }
-                    },
+                    WherePredicate::TypeBound { target, bound } => {
+                        p.print_type_ref(*target);
+                        w!(p, ": ");
+                        p.print_type_bounds(std::slice::from_ref(bound));
+                    }
                     WherePredicate::Lifetime { target, bound } => {
                         p.print_lifetime_ref(target);
                         w!(p, ": ");
@@ -365,21 +355,9 @@ fn print_where_clauses(db: &dyn DefDatabase, generic_params: &GenericParams, p:
                             w!(p, "{}", lifetime.display(db, p.edition));
                         }
                         w!(p, "> ");
-                        match target {
-                            WherePredicateTypeTarget::TypeRef(idx) => {
-                                p.print_type_ref(*idx);
-                                w!(p, ": ");
-                                p.print_type_bounds(std::slice::from_ref(bound));
-                            }
-                            WherePredicateTypeTarget::TypeOrConstParam(idx) => {
-                                match generic_params[*idx].name() {
-                                    Some(name) => w!(p, "{}", name.display(db, p.edition)),
-                                    None => w!(p, "Param[{}]", idx.into_raw()),
-                                }
-                                w!(p, ": ");
-                                p.print_type_bounds(std::slice::from_ref(bound));
-                            }
-                        }
+                        p.print_type_ref(*target);
+                        w!(p, ": ");
+                        p.print_type_bounds(std::slice::from_ref(bound));
                     }
                 }
             }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir/generics.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir/generics.rs
index 52c0c669ea4..685847c9fdd 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/hir/generics.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/hir/generics.rs
@@ -13,10 +13,6 @@ use crate::{
     type_ref::{ConstRef, LifetimeRef, TypeBound, TypeRefId},
 };
 
-/// The index of the self param in the generic of the non-parent definition.
-const SELF_PARAM_ID_IN_SELF: la_arena::Idx<TypeOrConstParamData> =
-    LocalTypeOrConstParamId::from_raw(RawIdx::from_u32(0));
-
 pub type LocalTypeOrConstParamId = Idx<TypeOrConstParamData>;
 pub type LocalLifetimeParamId = Idx<LifetimeParamData>;
 
@@ -173,17 +169,9 @@ impl ops::Index<LocalLifetimeParamId> for GenericParams {
 /// associated type bindings like `Iterator<Item = u32>`.
 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
 pub enum WherePredicate {
-    TypeBound { target: WherePredicateTypeTarget, bound: TypeBound },
+    TypeBound { target: TypeRefId, bound: TypeBound },
     Lifetime { target: LifetimeRef, bound: LifetimeRef },
-    ForLifetime { lifetimes: Box<[Name]>, target: WherePredicateTypeTarget, bound: TypeBound },
-}
-
-#[derive(Clone, PartialEq, Eq, Debug, Hash)]
-pub enum WherePredicateTypeTarget {
-    TypeRef(TypeRefId),
-    // FIXME: This can be folded into the above now that `TypeRef` can refer to `TypeParam`?
-    /// For desugared where predicates that can directly refer to a type param.
-    TypeOrConstParam(LocalTypeOrConstParamId),
+    ForLifetime { lifetimes: Box<[Name]>, target: TypeRefId, bound: TypeBound },
 }
 
 static EMPTY: LazyLock<Arc<GenericParams>> = LazyLock::new(|| {
@@ -193,7 +181,12 @@ static EMPTY: LazyLock<Arc<GenericParams>> = LazyLock::new(|| {
         where_predicates: Box::default(),
     })
 });
+
 impl GenericParams {
+    /// The index of the self param in the generic of the non-parent definition.
+    pub(crate) const SELF_PARAM_ID_IN_SELF: la_arena::Idx<TypeOrConstParamData> =
+        LocalTypeOrConstParamId::from_raw(RawIdx::from_u32(0));
+
     pub fn new(db: &dyn DefDatabase, def: GenericDefId) -> Arc<GenericParams> {
         match def {
             GenericDefId::AdtId(AdtId::EnumId(it)) => db.enum_signature(it).generic_params.clone(),
@@ -388,13 +381,13 @@ impl GenericParams {
             return None;
         }
         matches!(
-            self.type_or_consts[SELF_PARAM_ID_IN_SELF],
+            self.type_or_consts[Self::SELF_PARAM_ID_IN_SELF],
             TypeOrConstParamData::TypeParamData(TypeParamData {
                 provenance: TypeParamProvenance::TraitSelf,
                 ..
             })
         )
-        .then(|| SELF_PARAM_ID_IN_SELF)
+        .then(|| Self::SELF_PARAM_ID_IN_SELF)
     }
 
     pub fn find_lifetime_by_name(
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/signatures.rs b/src/tools/rust-analyzer/crates/hir-def/src/signatures.rs
index 4c5cae129a3..44cfd72c48f 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/signatures.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/signatures.rs
@@ -34,7 +34,7 @@ use crate::{
     },
     lang_item::LangItem,
     src::HasSource,
-    type_ref::{TraitRef, TypeBound, TypeRef, TypeRefId},
+    type_ref::{TraitRef, TypeBound, TypeRefId},
 };
 
 #[derive(Debug, PartialEq, Eq)]
@@ -877,7 +877,8 @@ fn lower_fields<'a>(
         if attrs.is_cfg_enabled(cfg_options) {
             arena.alloc(FieldData {
                 name: field.name.clone(),
-                type_ref: col.lower_type_ref_opt(ty, &mut |_| TypeRef::Error),
+                type_ref: col
+                    .lower_type_ref_opt(ty, &mut ExprCollector::impl_trait_error_allocator),
                 visibility: item_tree[override_visibility.unwrap_or(field.visibility)].clone(),
                 is_unsafe: field.is_unsafe,
             });
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
index 39d6083b35c..128dd42f739 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
@@ -16,9 +16,7 @@ use hir_def::{
     db::DefDatabase,
     expr_store::{ExpressionStore, path::Path},
     find_path::{self, PrefixKind},
-    hir::generics::{
-        TypeOrConstParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
-    },
+    hir::generics::{TypeOrConstParamData, TypeParamProvenance, WherePredicate},
     item_scope::ItemInNs,
     item_tree::FieldsShape,
     lang_item::{LangItem, LangItemTarget},
@@ -2119,15 +2117,15 @@ impl HirDisplayWithExpressionStore for TypeRefId {
                             generic_params
                                 .where_predicates()
                                 .filter_map(|it| match it {
-                                    WherePredicate::TypeBound {
-                                        target: WherePredicateTypeTarget::TypeOrConstParam(p),
-                                        bound,
+                                    WherePredicate::TypeBound { target, bound }
+                                    | WherePredicate::ForLifetime { lifetimes: _, target, bound }
+                                        if matches!(
+                                            store[*target],
+                                            TypeRef::TypeParam(t) if t == *param
+                                        ) =>
+                                    {
+                                        Some(bound)
                                     }
-                                    | WherePredicate::ForLifetime {
-                                        lifetimes: _,
-                                        target: WherePredicateTypeTarget::TypeOrConstParam(p),
-                                        bound,
-                                    } if *p == param.local_id() => Some(bound),
                                     _ => None,
                                 })
                                 .map(ExpressionStoreAdapter::wrap(store)),
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
index eecca322405..e65f6a2c5de 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
@@ -29,9 +29,7 @@ use hir_def::{
     Lookup, StaticId, StructId, TypeAliasId, TypeOrConstParamId, UnionId, VariantId,
     builtin_type::BuiltinType,
     expr_store::{ExpressionStore, path::Path},
-    hir::generics::{
-        GenericParamDataRef, TypeOrConstParamData, WherePredicate, WherePredicateTypeTarget,
-    },
+    hir::generics::{GenericParamDataRef, TypeOrConstParamData, WherePredicate},
     item_tree::FieldsShape,
     lang_item::LangItem,
     resolver::{HasResolver, LifetimeNs, Resolver, TypeNs},
@@ -555,32 +553,12 @@ impl<'a> TyLoweringContext<'a> {
     pub(crate) fn lower_where_predicate<'b>(
         &'b mut self,
         where_predicate: &'b WherePredicate,
-        generics: &'b Generics,
-        predicate_owner: GenericDefId,
         ignore_bindings: bool,
     ) -> impl Iterator<Item = QuantifiedWhereClause> + use<'a, 'b> {
         match where_predicate {
             WherePredicate::ForLifetime { target, bound, .. }
             | WherePredicate::TypeBound { target, bound } => {
-                let self_ty = match target {
-                    WherePredicateTypeTarget::TypeRef(type_ref) => self.lower_ty(*type_ref),
-                    &WherePredicateTypeTarget::TypeOrConstParam(local_id) => {
-                        let param_id =
-                            hir_def::TypeOrConstParamId { parent: predicate_owner, local_id };
-                        match self.type_param_mode {
-                            ParamLoweringMode::Placeholder => {
-                                TyKind::Placeholder(to_placeholder_idx(self.db, param_id))
-                            }
-                            ParamLoweringMode::Variable => {
-                                let idx = generics
-                                    .type_or_const_param_idx(param_id)
-                                    .expect("matching generics");
-                                TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, idx))
-                            }
-                        }
-                        .intern(Interner)
-                    }
-                };
+                let self_ty = self.lower_ty(*target);
                 Either::Left(self.lower_type_bound(bound, self_ty, ignore_bindings))
             }
             WherePredicate::Lifetime { bound, target } => Either::Right(iter::once(
@@ -959,22 +937,14 @@ pub(crate) fn generic_predicates_for_param_query(
     .with_type_param_mode(ParamLoweringMode::Variable);
 
     // we have to filter out all other predicates *first*, before attempting to lower them
-    let predicate = |pred: &_, generics: &Generics, ctx: &mut TyLoweringContext<'_>| match pred {
+    let predicate = |pred: &_, ctx: &mut TyLoweringContext<'_>| match pred {
         WherePredicate::ForLifetime { target, bound, .. }
         | WherePredicate::TypeBound { target, bound, .. } => {
-            let invalid_target = match target {
-                WherePredicateTypeTarget::TypeRef(type_ref) => {
-                    ctx.lower_ty_only_param(*type_ref) != Some(param_id)
-                }
-                &WherePredicateTypeTarget::TypeOrConstParam(local_id) => {
-                    let target_id = TypeOrConstParamId { parent: generics.def(), local_id };
-                    target_id != param_id
-                }
-            };
+            let invalid_target = { ctx.lower_ty_only_param(*target) != Some(param_id) };
             if invalid_target {
                 // If this is filtered out without lowering, `?Sized` is not gathered into `ctx.unsized_types`
                 if let TypeBound::Path(_, TraitBoundModifier::Maybe) = bound {
-                    ctx.lower_where_predicate(pred, generics, generics.def(), true).for_each(drop);
+                    ctx.lower_where_predicate(pred, true).for_each(drop);
                 }
                 return false;
             }
@@ -1009,10 +979,9 @@ pub(crate) fn generic_predicates_for_param_query(
     {
         ctx.store = maybe_parent_generics.store();
         for pred in maybe_parent_generics.where_predicates() {
-            if predicate(pred, maybe_parent_generics, &mut ctx) {
+            if predicate(pred, &mut ctx) {
                 predicates.extend(
-                    ctx.lower_where_predicate(pred, &generics, maybe_parent_generics.def(), true)
-                        .map(|p| make_binders(db, &generics, p)),
+                    ctx.lower_where_predicate(pred, true).map(|p| make_binders(db, &generics, p)),
                 );
             }
         }
@@ -1078,9 +1047,7 @@ pub(crate) fn trait_environment_query(
     {
         ctx.store = maybe_parent_generics.store();
         for pred in maybe_parent_generics.where_predicates() {
-            for pred in
-                ctx.lower_where_predicate(pred, &generics, maybe_parent_generics.def(), false)
-            {
+            for pred in ctx.lower_where_predicate(pred, false) {
                 if let WhereClause::Implemented(tr) = pred.skip_binders() {
                     traits_in_scope
                         .push((tr.self_type_parameter(Interner).clone(), tr.hir_trait_id()));
@@ -1187,8 +1154,7 @@ where
                 // We deliberately use `generics` and not `maybe_parent_generics` here. This is not a mistake!
                 // If we use the parent generics
                 predicates.extend(
-                    ctx.lower_where_predicate(pred, &generics, maybe_parent_generics.def(), false)
-                        .map(|p| make_binders(db, &generics, p)),
+                    ctx.lower_where_predicate(pred, false).map(|p| make_binders(db, &generics, p)),
                 );
             }
         }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
index ba98bbe3ede..198f715a6db 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
@@ -11,7 +11,7 @@ use chalk_ir::{
 use hir_def::{
     EnumId, EnumVariantId, FunctionId, Lookup, TraitId, TypeAliasId, TypeOrConstParamId,
     db::DefDatabase,
-    hir::generics::{WherePredicate, WherePredicateTypeTarget},
+    hir::generics::WherePredicate,
     lang_item::LangItem,
     resolver::{HasResolver, TypeNs},
     type_ref::{TraitBoundModifier, TypeRef},
@@ -170,15 +170,10 @@ fn direct_super_traits_cb(db: &dyn DefDatabase, trait_: TraitId, cb: impl FnMut(
         .filter_map(|pred| match pred {
             WherePredicate::ForLifetime { target, bound, .. }
             | WherePredicate::TypeBound { target, bound } => {
-                let is_trait = match *target {
-                    WherePredicateTypeTarget::TypeRef(type_ref) => match &store[type_ref] {
-                        TypeRef::Path(p) => p.is_self_type(),
-                        TypeRef::TypeParam(p) => Some(p.local_id()) == trait_self,
-                        _ => false,
-                    },
-                    WherePredicateTypeTarget::TypeOrConstParam(local_id) => {
-                        Some(local_id) == trait_self
-                    }
+                let is_trait = match &store[*target] {
+                    TypeRef::Path(p) => p.is_self_type(),
+                    TypeRef::TypeParam(p) => Some(p.local_id()) == trait_self,
+                    _ => false,
                 };
                 match is_trait {
                     true => bound.as_path(&store),
diff --git a/src/tools/rust-analyzer/crates/hir/src/display.rs b/src/tools/rust-analyzer/crates/hir/src/display.rs
index 83d16682206..53817f37aa6 100644
--- a/src/tools/rust-analyzer/crates/hir/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/display.rs
@@ -4,17 +4,15 @@ use either::Either;
 use hir_def::{
     AdtId, GenericDefId,
     expr_store::ExpressionStore,
-    hir::generics::{
-        GenericParams, TypeOrConstParamData, TypeParamProvenance, WherePredicate,
-        WherePredicateTypeTarget,
-    },
+    hir::generics::{GenericParams, TypeOrConstParamData, TypeParamProvenance, WherePredicate},
     item_tree::FieldsShape,
     lang_item::LangItem,
     signatures::{StaticFlags, TraitFlags},
-    type_ref::{TypeBound, TypeRef},
+    type_ref::{TypeBound, TypeRef, TypeRefId},
 };
 use hir_ty::{
     AliasEq, AliasTy, Interner, ProjectionTyExt, TraitRefExt, TyKind, WhereClause,
+    db::HirDatabase,
     display::{
         HirDisplay, HirDisplayError, HirDisplayWithExpressionStore, HirFormatter, SizedByDefault,
         hir_display_with_store, write_bounds_like_dyn_trait_with_prefix, write_visibility,
@@ -43,7 +41,8 @@ impl HirDisplay for Function {
                 if f.show_container_bounds() && !params.is_empty() {
                     write_trait_header(&trait_, f)?;
                     f.write_char('\n')?;
-                    has_disaplayable_predicates(&params).then_some((params, params_store))
+                    has_disaplayable_predicates(f.db, &params, &params_store)
+                        .then_some((params, params_store))
                 } else {
                     None
                 }
@@ -53,7 +52,8 @@ impl HirDisplay for Function {
                 if f.show_container_bounds() && !params.is_empty() {
                     write_impl_header(&impl_, f)?;
                     f.write_char('\n')?;
-                    has_disaplayable_predicates(&params).then_some((params, params_store))
+                    has_disaplayable_predicates(f.db, &params, &params_store)
+                        .then_some((params, params_store))
                 } else {
                     None
                 }
@@ -619,7 +619,7 @@ fn write_where_clause(
     f: &mut HirFormatter<'_>,
 ) -> Result<bool, HirDisplayError> {
     let (params, store) = f.db.generic_params_and_store(def);
-    if !has_disaplayable_predicates(&params) {
+    if !has_disaplayable_predicates(f.db, &params, &store) {
         return Ok(false);
     }
 
@@ -629,12 +629,18 @@ fn write_where_clause(
     Ok(true)
 }
 
-fn has_disaplayable_predicates(params: &GenericParams) -> bool {
+fn has_disaplayable_predicates(
+    db: &dyn HirDatabase,
+    params: &GenericParams,
+    store: &ExpressionStore,
+) -> bool {
     params.where_predicates().any(|pred| {
         !matches!(
             pred,
-            WherePredicate::TypeBound { target: WherePredicateTypeTarget::TypeOrConstParam(id), .. }
-            if params[*id].name().is_none()
+            WherePredicate::TypeBound { target, .. }
+            if  matches!(store[*target],
+                TypeRef::TypeParam(id) if db.generic_params(id.parent())[id.local_id()].name().is_none()
+            )
         )
     })
 }
@@ -647,20 +653,12 @@ fn write_where_predicates(
     use WherePredicate::*;
 
     // unnamed type targets are displayed inline with the argument itself, e.g. `f: impl Y`.
-    let is_unnamed_type_target = |params: &GenericParams, target: &WherePredicateTypeTarget| {
-        matches!(target,
-            WherePredicateTypeTarget::TypeOrConstParam(id) if params[*id].name().is_none()
+    let is_unnamed_type_target = |target: TypeRefId| {
+        matches!(store[target],
+            TypeRef::TypeParam(id) if f.db.generic_params(id.parent())[id.local_id()].name().is_none()
         )
     };
 
-    let write_target = |target: &WherePredicateTypeTarget, f: &mut HirFormatter<'_>| match target {
-        WherePredicateTypeTarget::TypeRef(ty) => ty.hir_fmt(f, store),
-        WherePredicateTypeTarget::TypeOrConstParam(id) => match params[*id].name() {
-            Some(name) => write!(f, "{}", name.display(f.db, f.edition())),
-            None => f.write_str("{unnamed}"),
-        },
-    };
-
     let check_same_target = |pred1: &WherePredicate, pred2: &WherePredicate| match (pred1, pred2) {
         (TypeBound { target: t1, .. }, TypeBound { target: t2, .. }) => t1 == t2,
         (Lifetime { target: t1, .. }, Lifetime { target: t2, .. }) => t1 == t2,
@@ -673,14 +671,14 @@ fn write_where_predicates(
 
     let mut iter = params.where_predicates().peekable();
     while let Some(pred) = iter.next() {
-        if matches!(pred, TypeBound { target, .. } if is_unnamed_type_target(params, target)) {
+        if matches!(pred, TypeBound { target, .. } if is_unnamed_type_target(*target)) {
             continue;
         }
 
         f.write_str("\n    ")?;
         match pred {
             TypeBound { target, bound } => {
-                write_target(target, f)?;
+                target.hir_fmt(f, store)?;
                 f.write_str(": ")?;
                 bound.hir_fmt(f, store)?;
             }
@@ -692,7 +690,7 @@ fn write_where_predicates(
             ForLifetime { lifetimes, target, bound } => {
                 let lifetimes = lifetimes.iter().map(|it| it.display(f.db, f.edition())).join(", ");
                 write!(f, "for<{lifetimes}> ")?;
-                write_target(target, f)?;
+                target.hir_fmt(f, store)?;
                 f.write_str(": ")?;
                 bound.hir_fmt(f, store)?;
             }
diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
index 00e67fbd744..666efe8ec64 100644
--- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
@@ -26,7 +26,7 @@ use hir_def::{
     lang_item::LangItem,
     nameres::MacroSubNs,
     resolver::{HasResolver, Resolver, TypeNs, ValueNs, resolver_for_scope},
-    type_ref::{Mutability, TypeRef, TypeRefId},
+    type_ref::{Mutability, TypeRefId},
 };
 use hir_expand::{
     HirFileId, InFile, MacroCallId,
@@ -1004,9 +1004,11 @@ impl SourceAnalyzer {
 
         // FIXME: collectiong here shouldnt be necessary?
         let mut collector = ExprCollector::new(db, self.resolver.module(), self.file_id);
-        let hir_path = collector.lower_path(path.clone(), &mut |_| TypeRef::Error)?;
-        let parent_hir_path =
-            path.parent_path().and_then(|p| collector.lower_path(p, &mut |_| TypeRef::Error));
+        let hir_path =
+            collector.lower_path(path.clone(), &mut ExprCollector::impl_trait_error_allocator)?;
+        let parent_hir_path = path
+            .parent_path()
+            .and_then(|p| collector.lower_path(p, &mut ExprCollector::impl_trait_error_allocator));
         let store = collector.store.finish();
 
         // Case where path is a qualifier of a use tree, e.g. foo::bar::{Baz, Qux} where we are