From 4a2eaddc77744a8a791c8eec5a6b47137db980ae Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 24 Apr 2025 08:21:57 +0200 Subject: [PATCH 1/2] refactor: Remove `WherePredicateTypeTarget` --- crates/hir-def/src/expr_store/lower.rs | 144 ++++--- crates/hir-def/src/expr_store/lower/asm.rs | 11 +- .../hir-def/src/expr_store/lower/generics.rs | 400 +++++++++--------- crates/hir-def/src/expr_store/lower/path.rs | 10 +- .../src/expr_store/lower/path/tests.rs | 3 +- crates/hir-def/src/expr_store/pretty.rs | 40 +- crates/hir-def/src/hir/generics.rs | 25 +- crates/hir-def/src/signatures.rs | 5 +- crates/hir-ty/src/display.rs | 20 +- crates/hir-ty/src/lower.rs | 52 +-- crates/hir-ty/src/utils.rs | 15 +- crates/hir/src/display.rs | 48 +-- crates/hir/src/source_analyzer.rs | 10 +- 13 files changed, 387 insertions(+), 396 deletions(-) diff --git a/crates/hir-def/src/expr_store/lower.rs b/crates/hir-def/src/expr_store/lower.rs index d49c283bee..ddcdb321e2 100644 --- a/crates/hir-def/src/expr_store/lower.rs +++ b/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>, ) -> (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, ) -> (Arc, Arc, 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) { 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) { 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(), ¶m); @@ -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) -> 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, - impl_trait_lower_fn: &mut impl FnMut(ThinVec) -> 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, ) -> 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) -> TypeRef, + impl_trait_lower_fn: ImplTraitLowerFn<'_>, ) -> Option { 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, + ) -> TypeRefId { + ec.alloc_type_ref(TypeRef::Error, ptr) + } + + fn impl_trait_allocator( + ec: &mut ExprCollector<'_>, + ptr: TypePtr, + bounds: ThinVec, + ) -> 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, ret_type: Option, - impl_trait_lower_fn: &mut impl FnMut(ThinVec) -> TypeRef, + impl_trait_lower_fn: ImplTraitLowerFn<'_>, ) -> Option { 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) -> TypeRef, + impl_trait_lower_fn: ImplTraitLowerFn<'_>, ) -> Option { // 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, - impl_trait_lower_fn: &mut impl FnMut(ThinVec) -> TypeRef, + impl_trait_lower_fn: ImplTraitLowerFn<'_>, ) -> ThinVec { 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) -> TypeRef, + impl_trait_lower_fn: ImplTraitLowerFn<'_>, ) -> Option { 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) -> 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/crates/hir-def/src/expr_store/lower/asm.rs b/crates/hir-def/src/expr_store/lower/asm.rs index ca331e84d3..9ef0306565 100644 --- a/crates/hir-def/src/expr_store/lower/asm.rs +++ b/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/crates/hir-def/src/expr_store/lower/generics.rs b/crates/hir-def/src/expr_store/lower/generics.rs index 4f14a7f2d9..004bbe949f 100644 --- a/crates/hir-def/src/expr_store/lower/generics.rs +++ b/crates/hir-def/src/expr_store/lower/generics.rs @@ -15,205 +15,67 @@ 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, +) -> TypeRefId; + +pub(crate) struct GenericParamsCollector { type_or_consts: Arena, lifetimes: Arena, where_predicates: Vec, 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) { - 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, + ) -> 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, where_clause: Option, ) { 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) { - 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, - ); - if !enabled { - continue; - } - - 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 param = TypeParamData { - name: Some(name.clone()), - default, - provenance: TypeParamProvenance::TypeParamList, - }; - let idx = self.type_or_consts.alloc(param.into()); - let type_ref = - TypeRef::TypeParam(TypeParamId::from_unchecked(TypeOrConstParamId { - 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)); - } - 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 param = ConstParamData { - name, - ty, - default: const_param - .default_val() - .map(|it| self.expr_collector.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()); - if let LifetimeRef::Named(name) = &lifetime_ref { - let param = LifetimeParamData { name: name.clone() }; - let _idx = self.lifetimes.alloc(param); - self.lower_bounds( - lifetime_param.type_bound_list(), - Either::Right(lifetime_ref), - ); - } - } - } - } - } - - fn lower_where_predicates(&mut self, 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)) - } else if let Some(lifetime) = pred.lifetime() { - Either::Right(self.expr_collector.lower_lifetime_ref(lifetime)) - } else { - continue; - }; - - let lifetimes: Option> = pred.generic_param_list().map(|param_list| { - // Higher-Ranked Trait Bounds - param_list - .lifetime_params() - .map(|lifetime_param| { - lifetime_param - .lifetime() - .map_or_else(Name::missing, |lt| Name::new_lifetime(<.text())) - }) - .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()); - } - } - } - - fn lower_bounds( - &mut self, - type_bounds: Option, - target: Either, - ) { - 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()); - } - } - - fn lower_type_bound_as_predicate( - &mut self, - bound: ast::TypeBound, - hrtb_lifetimes: Option<&[Name]>, - target: Either, - ) { - let bound = self.expr_collector.lower_type_bound( - bound, - &mut Self::lower_argument_impl_trait( - &mut self.type_or_consts, - &mut self.where_predicates, - self.parent, - ), - ); - let predicate = match (target, bound) { - (_, TypeBound::Error | TypeBound::Use(_)) => return, - (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), - bound, - }, - }, - (Either::Right(lifetime), TypeBound::Lifetime(bound)) => { - WherePredicate::Lifetime { target: lifetime, bound } - } - (Either::Right(_), TypeBound::ForLifetime(..) | TypeBound::Path(..)) => return, - }; - self.where_predicates.push(predicate); - } - pub(crate) fn collect_impl_trait( &mut self, - cb: impl FnOnce(&mut ExprCollector<'_>, &mut dyn FnMut(ThinVec) -> TypeRef) -> R, + ec: &mut ExprCollector<'_>, + cb: impl FnOnce(&mut ExprCollector<'_>, ImplTraitLowerFn<'_>) -> R, ) -> R { cb( - self.expr_collector, + ec, &mut Self::lower_argument_impl_trait( &mut self.type_or_consts, &mut self.where_predicates, @@ -222,39 +84,8 @@ impl<'db, 'c> GenericParamsCollector<'db, 'c> { ) } - fn lower_argument_impl_trait( - type_or_consts: &mut Arena, - where_predicates: &mut Vec, - parent: GenericDefId, - ) -> impl FnMut(ThinVec) -> TypeRef { - move |impl_trait_bounds| { - let param = TypeParamData { - name: None, - default: None, - provenance: TypeParamProvenance::ArgumentImplTrait, - }; - let param_id = type_or_consts.alloc(param.into()); - for bound in impl_trait_bounds { - where_predicates.push(WherePredicate::TypeBound { - target: WherePredicateTypeTarget::TypeOrConstParam(param_id), - bound: bound.clone(), - }); - } - TypeRef::TypeParam(TypeParamId::from_unchecked(TypeOrConstParamId { - parent, - local_id: param_id, - })) - } - } - pub(crate) fn finish(self) -> Arc { - let Self { - mut lifetimes, - mut type_or_consts, - mut where_predicates, - expr_collector: _, - parent: _, - } = self; + 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> = LazyLock::new(|| { @@ -276,4 +107,183 @@ impl<'db, 'c> GenericParamsCollector<'db, 'c> { 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 = ec.expander.is_cfg_enabled(ec.db, ec.module.krate(), &generic_param); + if !enabled { + continue; + } + + 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| { + ec.lower_type_ref(it, &mut ExprCollector::impl_trait_error_allocator) + }); + let param = TypeParamData { + name: Some(name.clone()), + default, + provenance: TypeParamProvenance::TypeParamList, + }; + let idx = self.type_or_consts.alloc(param.into()); + let type_ref = + TypeRef::TypeParam(TypeParamId::from_unchecked(TypeOrConstParamId { + parent: self.parent, + local_id: idx, + })); + 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 = 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| ec.lower_const_arg(it)), + }; + let _idx = self.type_or_consts.alloc(param.into()); + } + ast::GenericParam::LifetimeParam(lifetime_param) => { + 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), + ); + } + } + } + } + } + + 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( + ec.lower_type_ref(type_ref, &mut ExprCollector::impl_trait_error_allocator), + ) + } else if let Some(lifetime) = pred.lifetime() { + Either::Right(ec.lower_lifetime_ref(lifetime)) + } else { + continue; + }; + + let lifetimes: Option> = pred.generic_param_list().map(|param_list| { + // Higher-Ranked Trait Bounds + param_list + .lifetime_params() + .map(|lifetime_param| { + lifetime_param + .lifetime() + .map_or_else(Name::missing, |lt| Name::new_lifetime(<.text())) + }) + .collect() + }); + for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) { + self.lower_type_bound_as_predicate(ec, bound, lifetimes.as_deref(), target.clone()); + } + } + } + + fn lower_bounds( + &mut self, + ec: &mut ExprCollector<'_>, + type_bounds: Option, + target: Either, + ) { + for bound in type_bounds.iter().flat_map(|type_bound_list| type_bound_list.bounds()) { + 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, + ) { + let bound = ec.lower_type_bound( + bound, + &mut Self::lower_argument_impl_trait( + &mut self.type_or_consts, + &mut self.where_predicates, + self.parent, + ), + ); + let predicate = match (target, bound) { + (_, TypeBound::Error | TypeBound::Use(_)) => return, + (Either::Left(type_ref), bound) => match hrtb_lifetimes { + Some(hrtb_lifetimes) => WherePredicate::ForLifetime { + lifetimes: hrtb_lifetimes.to_vec().into_boxed_slice(), + target: type_ref, + bound, + }, + None => WherePredicate::TypeBound { target: type_ref, bound }, + }, + (Either::Right(lifetime), TypeBound::Lifetime(bound)) => { + WherePredicate::Lifetime { target: lifetime, bound } + } + (Either::Right(_), TypeBound::ForLifetime(..) | TypeBound::Path(..)) => return, + }; + self.where_predicates.push(predicate); + } + + fn lower_argument_impl_trait( + type_or_consts: &mut Arena, + where_predicates: &mut Vec, + parent: GenericDefId, + ) -> impl for<'ec, 'db> FnMut(&'ec mut ExprCollector<'db>, TypePtr, ThinVec) -> TypeRefId + { + move |ec, ptr, impl_trait_bounds| { + let param = TypeParamData { + name: None, + default: None, + provenance: TypeParamProvenance::ArgumentImplTrait, + }; + 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: type_ref, bound: bound.clone() }); + } + type_ref + } + } + + fn fill_self_param(&mut self, ec: &mut ExprCollector<'_>, bounds: Option) { + 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_)); + } + } } diff --git a/crates/hir-def/src/expr_store/lower/path.rs b/crates/hir-def/src/expr_store/lower/path.rs index 14b0d3abd4..629d1f2ada 100644 --- a/crates/hir-def/src/expr_store/lower/path.rs +++ b/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) -> TypeRef, + impl_trait_lower_fn: ImplTraitLowerFn<'_>, ) -> Option { let mut kind = PathKind::Plain; let mut type_anchor = None; diff --git a/crates/hir-def/src/expr_store/lower/path/tests.rs b/crates/hir-def/src/expr_store/lower/path/tests.rs index 44043fd056..337cb103bd 100644 --- a/crates/hir-def/src/expr_store/lower/path/tests.rs +++ b/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) { 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/crates/hir-def/src/expr_store/pretty.rs b/crates/hir-def/src/expr_store/pretty.rs index 5e3580e590..5adf462062 100644 --- a/crates/hir-def/src/expr_store/pretty.rs +++ b/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/crates/hir-def/src/hir/generics.rs b/crates/hir-def/src/hir/generics.rs index 52c0c669ea..685847c9fd 100644 --- a/crates/hir-def/src/hir/generics.rs +++ b/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 = - LocalTypeOrConstParamId::from_raw(RawIdx::from_u32(0)); - pub type LocalTypeOrConstParamId = Idx; pub type LocalLifetimeParamId = Idx; @@ -173,17 +169,9 @@ impl ops::Index for GenericParams { /// associated type bindings like `Iterator`. #[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> = LazyLock::new(|| { @@ -193,7 +181,12 @@ static EMPTY: LazyLock> = 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 = + LocalTypeOrConstParamId::from_raw(RawIdx::from_u32(0)); + pub fn new(db: &dyn DefDatabase, def: GenericDefId) -> Arc { 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/crates/hir-def/src/signatures.rs b/crates/hir-def/src/signatures.rs index 4c5cae129a..44cfd72c48 100644 --- a/crates/hir-def/src/signatures.rs +++ b/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/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index 39d6083b35..128dd42f73 100644 --- a/crates/hir-ty/src/display.rs +++ b/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/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index eecca32240..e65f6a2c5d 100644 --- a/crates/hir-ty/src/lower.rs +++ b/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 + 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/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs index ba98bbe3ed..198f715a6d 100644 --- a/crates/hir-ty/src/utils.rs +++ b/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/crates/hir/src/display.rs b/crates/hir/src/display.rs index 83d1668220..53817f37aa 100644 --- a/crates/hir/src/display.rs +++ b/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(¶ms).then_some((params, params_store)) + has_disaplayable_predicates(f.db, ¶ms, ¶ms_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(¶ms).then_some((params, params_store)) + has_disaplayable_predicates(f.db, ¶ms, ¶ms_store) + .then_some((params, params_store)) } else { None } @@ -619,7 +619,7 @@ fn write_where_clause( f: &mut HirFormatter<'_>, ) -> Result { let (params, store) = f.db.generic_params_and_store(def); - if !has_disaplayable_predicates(¶ms) { + if !has_disaplayable_predicates(f.db, ¶ms, &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/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index 00e67fbd74..666efe8ec6 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/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 From 99a7e423e2660f587eacb47d7c7a11e14ca24638 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 24 Apr 2025 09:22:41 +0200 Subject: [PATCH 2/2] Shrink `WherePredicate` by 8 bytes --- crates/hir-def/src/expr_store/lower/generics.rs | 2 +- crates/hir-def/src/hir/generics.rs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/hir-def/src/expr_store/lower/generics.rs b/crates/hir-def/src/expr_store/lower/generics.rs index 004bbe949f..5cea8a2435 100644 --- a/crates/hir-def/src/expr_store/lower/generics.rs +++ b/crates/hir-def/src/expr_store/lower/generics.rs @@ -227,7 +227,7 @@ impl GenericParamsCollector { (_, TypeBound::Error | TypeBound::Use(_)) => return, (Either::Left(type_ref), bound) => match hrtb_lifetimes { Some(hrtb_lifetimes) => WherePredicate::ForLifetime { - lifetimes: hrtb_lifetimes.to_vec().into_boxed_slice(), + lifetimes: ThinVec::from_iter(hrtb_lifetimes.iter().cloned()), target: type_ref, bound, }, diff --git a/crates/hir-def/src/hir/generics.rs b/crates/hir-def/src/hir/generics.rs index 685847c9fd..1bb9e48d55 100644 --- a/crates/hir-def/src/hir/generics.rs +++ b/crates/hir-def/src/hir/generics.rs @@ -4,6 +4,7 @@ use std::{ops, sync::LazyLock}; use hir_expand::name::Name; use la_arena::{Arena, Idx, RawIdx}; use stdx::impl_from; +use thin_vec::ThinVec; use triomphe::Arc; use crate::{ @@ -171,7 +172,7 @@ impl ops::Index for GenericParams { pub enum WherePredicate { TypeBound { target: TypeRefId, bound: TypeBound }, Lifetime { target: LifetimeRef, bound: LifetimeRef }, - ForLifetime { lifetimes: Box<[Name]>, target: TypeRefId, bound: TypeBound }, + ForLifetime { lifetimes: ThinVec, target: TypeRefId, bound: TypeBound }, } static EMPTY: LazyLock> = LazyLock::new(|| {