Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/lower_nextsolver/path.rs')
| -rw-r--r-- | crates/hir-ty/src/lower_nextsolver/path.rs | 163 |
1 files changed, 35 insertions, 128 deletions
diff --git a/crates/hir-ty/src/lower_nextsolver/path.rs b/crates/hir-ty/src/lower_nextsolver/path.rs index df67b2c59b..e3efb38306 100644 --- a/crates/hir-ty/src/lower_nextsolver/path.rs +++ b/crates/hir-ty/src/lower_nextsolver/path.rs @@ -4,7 +4,7 @@ use std::ops::Deref; use either::Either; use hir_def::{ - AssocItemId, GenericDefId, GenericParamId, Lookup, TraitId, + AssocItemId, GenericDefId, GenericParamId, Lookup, TraitId, TypeAliasId, builtin_type::BuiltinType, expr_store::{ ExpressionStore, HygieneId, @@ -17,6 +17,7 @@ use hir_def::{ signatures::TraitFlags, type_ref::{TypeRef, TypeRefId}, }; +use hir_expand::name::Name; use intern::sym; use rustc_hash::FxHashSet; use rustc_type_ir::{ @@ -33,7 +34,10 @@ use crate::{ db::HirDatabase, generics::{Generics, generics}, lower::PathDiagnosticCallbackData, - lower_nextsolver::{LifetimeElisionKind, PredicateFilter, generic_predicates_filtered_by}, + lower_nextsolver::{ + LifetimeElisionKind, PredicateFilter, generic_predicates_filtered_by, + named_associated_type_shorthand_candidates, + }, next_solver::{ AdtDef, Binder, Clause, Const, DbInterner, ErrorGuaranteed, Predicate, ProjectionPredicate, Region, SolverDefId, TraitRef, Ty, @@ -501,137 +505,40 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { let Some(res) = res else { return Ty::new_error(self.ctx.interner, ErrorGuaranteed); }; - let segment = self.current_or_prev_segment; - let assoc_name = segment.name; let db = self.ctx.db; let def = self.ctx.def; - let mut search = |t: TraitRef<'db>| { - let trait_id = match t.def_id { - SolverDefId::TraitId(id) => id, - _ => unreachable!(), - }; - let mut checked_traits = FxHashSet::default(); - let mut check_trait = |trait_id: TraitId| { - let name = &db.trait_signature(trait_id).name; - tracing::debug!(?trait_id, ?name); - if !checked_traits.insert(trait_id) { - return None; - } - let data = trait_id.trait_items(db); - - tracing::debug!(?data.items); - for (name, assoc_id) in &data.items { - if let &AssocItemId::TypeAliasId(alias) = assoc_id { - if name != assoc_name { - continue; - } - - // FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent - // generic params. It's inefficient to splice the `Substitution`s, so we may want - // that method to optionally take parent `Substitution` as we already know them at - // this point (`t.substitution`). - let substs = self.substs_from_path_segment(alias.into(), false, None, true); - - let substs = crate::next_solver::GenericArgs::new_from_iter( - interner, - t.args.iter().chain(substs.iter().skip(t.args.len())), - ); - - return Some(Ty::new_alias( - interner, - AliasTyKind::Projection, - AliasTy::new(interner, alias.into(), substs), - )); - } - } - None - }; - let mut stack: SmallVec<[_; 4]> = smallvec![trait_id]; - while let Some(trait_def_id) = stack.pop() { - if let Some(alias) = check_trait(trait_def_id) { - return alias; - } - for pred in generic_predicates_filtered_by( - db, - GenericDefId::TraitId(trait_def_id), - PredicateFilter::SelfTrait, - |pred| pred == GenericDefId::TraitId(trait_def_id), - ) - .0 - .deref() - { - tracing::debug!(?pred); - let trait_id = match pred.kind().skip_binder() { - rustc_type_ir::ClauseKind::Trait(pred) => pred.def_id(), - _ => continue, - }; - let trait_id = match trait_id { - SolverDefId::TraitId(trait_id) => trait_id, - _ => continue, - }; - stack.push(trait_id); - } - tracing::debug!(?stack); + let segment = self.current_or_prev_segment; + let assoc_name = segment.name; + let mut check_alias = |name: &Name, t: TraitRef<'db>, associated_ty: TypeAliasId| { + if name != assoc_name { + return None; } - Ty::new_error(interner, ErrorGuaranteed) + // FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent + // generic params. It's inefficient to splice the `Substitution`s, so we may want + // that method to optionally take parent `Substitution` as we already know them at + // this point (`t.substitution`). + let substs = self.substs_from_path_segment(associated_ty.into(), false, None, true); + + let substs = crate::next_solver::GenericArgs::new_from_iter( + interner, + t.args.iter().chain(substs.iter().skip(t.args.len())), + ); + + Some(Ty::new_alias( + interner, + AliasTyKind::Projection, + AliasTy::new(interner, associated_ty.into(), substs), + )) }; - - match res { - TypeNs::SelfType(impl_id) => { - let trait_ref = db.impl_trait_ns(impl_id); - let Some(trait_ref) = trait_ref else { - return Ty::new_error(interner, ErrorGuaranteed); - }; - - // we're _in_ the impl -- the binders get added back later. Correct, - // but it would be nice to make this more explicit - search(trait_ref.skip_binder()) - } - TypeNs::GenericParam(param_id) => { - // Handle `Self::Type` referring to own associated type in trait definitions - // This *must* be done first to avoid cycles with - // `generic_predicates_for_param`, but not sure that it's sufficient, - // see FIXME in `search`. - if let GenericDefId::TraitId(trait_id) = param_id.parent() { - let trait_name = &db.trait_signature(trait_id).name; - tracing::debug!(?trait_name); - let trait_generics = generics(db, trait_id.into()); - tracing::debug!(?trait_generics); - if trait_generics[param_id.local_id()].is_trait_self() { - let args = crate::next_solver::GenericArgs::identity_for_item( - interner, - trait_id.into(), - ); - let trait_ref = TraitRef::new_from_args(interner, trait_id.into(), args); - tracing::debug!(?args, ?trait_ref); - return search(trait_ref); - } - } - - let predicates = db.generic_predicates_for_param_ns( - def, - param_id.into(), - Some(segment.name.clone()), - ); - predicates - .iter() - .find_map(|pred| match (*pred).kind().skip_binder() { - rustc_type_ir::ClauseKind::Trait(trait_predicate) => Some(trait_predicate), - _ => None, - }) - .map(|trait_predicate| { - let trait_ref = trait_predicate.trait_ref; - assert!( - !trait_ref.has_escaping_bound_vars(), - "FIXME unexpected higher-ranked trait bound" - ); - search(trait_ref) - }) - .unwrap_or_else(|| Ty::new_error(interner, ErrorGuaranteed)) - } - _ => Ty::new_error(interner, ErrorGuaranteed), - } + named_associated_type_shorthand_candidates( + interner, + def, + res, + Some(assoc_name.clone()), + check_alias, + ) + .unwrap_or_else(|| Ty::new_error(interner, ErrorGuaranteed)) } fn lower_path_inner(&mut self, typeable: TyDefId, infer_args: bool) -> Ty<'db> { |