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.rs163
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> {