@@ -4,7 +4,7 @@ use std::ops::Deref;
44
55use either:: Either ;
66use hir_def:: {
7- AssocItemId , GenericDefId , GenericParamId , Lookup , TraitId ,
7+ AssocItemId , GenericDefId , GenericParamId , Lookup , TraitId , TypeAliasId ,
88 builtin_type:: BuiltinType ,
99 expr_store:: {
1010 ExpressionStore , HygieneId ,
@@ -17,6 +17,7 @@ use hir_def::{
1717 signatures:: TraitFlags ,
1818 type_ref:: { TypeRef , TypeRefId } ,
1919} ;
20+ use hir_expand:: name:: Name ;
2021use intern:: sym;
2122use rustc_hash:: FxHashSet ;
2223use rustc_type_ir:: {
@@ -33,7 +34,10 @@ use crate::{
3334 db:: HirDatabase ,
3435 generics:: { Generics , generics} ,
3536 lower:: PathDiagnosticCallbackData ,
36- lower_nextsolver:: { LifetimeElisionKind , PredicateFilter , generic_predicates_filtered_by} ,
37+ lower_nextsolver:: {
38+ LifetimeElisionKind , PredicateFilter , generic_predicates_filtered_by,
39+ named_associated_type_shorthand_candidates,
40+ } ,
3741 next_solver:: {
3842 AdtDef , Binder , Clause , Const , DbInterner , ErrorGuaranteed , Predicate , ProjectionPredicate ,
3943 Region , SolverDefId , TraitRef , Ty ,
@@ -501,137 +505,40 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
501505 let Some ( res) = res else {
502506 return Ty :: new_error ( self . ctx . interner , ErrorGuaranteed ) ;
503507 } ;
504- let segment = self . current_or_prev_segment ;
505- let assoc_name = segment. name ;
506508 let db = self . ctx . db ;
507509 let def = self . ctx . def ;
508- let mut search = |t : TraitRef < ' db > | {
509- let trait_id = match t. def_id {
510- SolverDefId :: TraitId ( id) => id,
511- _ => unreachable ! ( ) ,
512- } ;
513- let mut checked_traits = FxHashSet :: default ( ) ;
514- let mut check_trait = |trait_id : TraitId | {
515- let name = & db. trait_signature ( trait_id) . name ;
516- tracing:: debug!( ?trait_id, ?name) ;
517- if !checked_traits. insert ( trait_id) {
518- return None ;
519- }
520- let data = trait_id. trait_items ( db) ;
521-
522- tracing:: debug!( ?data. items) ;
523- for ( name, assoc_id) in & data. items {
524- if let & AssocItemId :: TypeAliasId ( alias) = assoc_id {
525- if name != assoc_name {
526- continue ;
527- }
528-
529- // FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent
530- // generic params. It's inefficient to splice the `Substitution`s, so we may want
531- // that method to optionally take parent `Substitution` as we already know them at
532- // this point (`t.substitution`).
533- let substs = self . substs_from_path_segment ( alias. into ( ) , false , None , true ) ;
534-
535- let substs = crate :: next_solver:: GenericArgs :: new_from_iter (
536- interner,
537- t. args . iter ( ) . chain ( substs. iter ( ) . skip ( t. args . len ( ) ) ) ,
538- ) ;
539-
540- return Some ( Ty :: new_alias (
541- interner,
542- AliasTyKind :: Projection ,
543- AliasTy :: new ( interner, alias. into ( ) , substs) ,
544- ) ) ;
545- }
546- }
547- None
548- } ;
549- let mut stack: SmallVec < [ _ ; 4 ] > = smallvec ! [ trait_id] ;
550- while let Some ( trait_def_id) = stack. pop ( ) {
551- if let Some ( alias) = check_trait ( trait_def_id) {
552- return alias;
553- }
554- for pred in generic_predicates_filtered_by (
555- db,
556- GenericDefId :: TraitId ( trait_def_id) ,
557- PredicateFilter :: SelfTrait ,
558- |pred| pred == GenericDefId :: TraitId ( trait_def_id) ,
559- )
560- . 0
561- . deref ( )
562- {
563- tracing:: debug!( ?pred) ;
564- let trait_id = match pred. kind ( ) . skip_binder ( ) {
565- rustc_type_ir:: ClauseKind :: Trait ( pred) => pred. def_id ( ) ,
566- _ => continue ,
567- } ;
568- let trait_id = match trait_id {
569- SolverDefId :: TraitId ( trait_id) => trait_id,
570- _ => continue ,
571- } ;
572- stack. push ( trait_id) ;
573- }
574- tracing:: debug!( ?stack) ;
510+ let segment = self . current_or_prev_segment ;
511+ let assoc_name = segment. name ;
512+ let mut check_alias = |name : & Name , t : TraitRef < ' db > , associated_ty : TypeAliasId | {
513+ if name != assoc_name {
514+ return None ;
575515 }
576516
577- Ty :: new_error ( interner, ErrorGuaranteed )
517+ // FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent
518+ // generic params. It's inefficient to splice the `Substitution`s, so we may want
519+ // that method to optionally take parent `Substitution` as we already know them at
520+ // this point (`t.substitution`).
521+ let substs = self . substs_from_path_segment ( associated_ty. into ( ) , false , None , true ) ;
522+
523+ let substs = crate :: next_solver:: GenericArgs :: new_from_iter (
524+ interner,
525+ t. args . iter ( ) . chain ( substs. iter ( ) . skip ( t. args . len ( ) ) ) ,
526+ ) ;
527+
528+ Some ( Ty :: new_alias (
529+ interner,
530+ AliasTyKind :: Projection ,
531+ AliasTy :: new ( interner, associated_ty. into ( ) , substs) ,
532+ ) )
578533 } ;
579-
580- match res {
581- TypeNs :: SelfType ( impl_id) => {
582- let trait_ref = db. impl_trait_ns ( impl_id) ;
583- let Some ( trait_ref) = trait_ref else {
584- return Ty :: new_error ( interner, ErrorGuaranteed ) ;
585- } ;
586-
587- // we're _in_ the impl -- the binders get added back later. Correct,
588- // but it would be nice to make this more explicit
589- search ( trait_ref. skip_binder ( ) )
590- }
591- TypeNs :: GenericParam ( param_id) => {
592- // Handle `Self::Type` referring to own associated type in trait definitions
593- // This *must* be done first to avoid cycles with
594- // `generic_predicates_for_param`, but not sure that it's sufficient,
595- // see FIXME in `search`.
596- if let GenericDefId :: TraitId ( trait_id) = param_id. parent ( ) {
597- let trait_name = & db. trait_signature ( trait_id) . name ;
598- tracing:: debug!( ?trait_name) ;
599- let trait_generics = generics ( db, trait_id. into ( ) ) ;
600- tracing:: debug!( ?trait_generics) ;
601- if trait_generics[ param_id. local_id ( ) ] . is_trait_self ( ) {
602- let args = crate :: next_solver:: GenericArgs :: identity_for_item (
603- interner,
604- trait_id. into ( ) ,
605- ) ;
606- let trait_ref = TraitRef :: new_from_args ( interner, trait_id. into ( ) , args) ;
607- tracing:: debug!( ?args, ?trait_ref) ;
608- return search ( trait_ref) ;
609- }
610- }
611-
612- let predicates = db. generic_predicates_for_param_ns (
613- def,
614- param_id. into ( ) ,
615- Some ( segment. name . clone ( ) ) ,
616- ) ;
617- predicates
618- . iter ( )
619- . find_map ( |pred| match ( * pred) . kind ( ) . skip_binder ( ) {
620- rustc_type_ir:: ClauseKind :: Trait ( trait_predicate) => Some ( trait_predicate) ,
621- _ => None ,
622- } )
623- . map ( |trait_predicate| {
624- let trait_ref = trait_predicate. trait_ref ;
625- assert ! (
626- !trait_ref. has_escaping_bound_vars( ) ,
627- "FIXME unexpected higher-ranked trait bound"
628- ) ;
629- search ( trait_ref)
630- } )
631- . unwrap_or_else ( || Ty :: new_error ( interner, ErrorGuaranteed ) )
632- }
633- _ => Ty :: new_error ( interner, ErrorGuaranteed ) ,
634- }
534+ named_associated_type_shorthand_candidates (
535+ interner,
536+ def,
537+ res,
538+ Some ( assoc_name. clone ( ) ) ,
539+ check_alias,
540+ )
541+ . unwrap_or_else ( || Ty :: new_error ( interner, ErrorGuaranteed ) )
635542 }
636543
637544 fn lower_path_inner ( & mut self , typeable : TyDefId , infer_args : bool ) -> Ty < ' db > {
0 commit comments