@@ -27,7 +27,7 @@ use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
2727use rustc_hir:: def_id:: { DefId , LocalDefId } ;
2828use rustc_hir:: intravisit:: { walk_generics, Visitor as _} ;
2929use rustc_hir:: { GenericArg , GenericArgs , OpaqueTyOrigin } ;
30- use rustc_infer:: infer:: TyCtxtInferExt ;
30+ use rustc_infer:: infer:: { InferCtxt , TyCtxtInferExt } ;
3131use rustc_middle:: middle:: stability:: AllowUnstable ;
3232use rustc_middle:: ty:: subst:: { self , GenericArgKind , InternalSubsts , SubstsRef } ;
3333use rustc_middle:: ty:: GenericParamDefKind ;
@@ -37,7 +37,7 @@ use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECT
3737use rustc_span:: edition:: Edition ;
3838use rustc_span:: lev_distance:: find_best_match_for_name;
3939use rustc_span:: symbol:: { kw, Ident , Symbol } ;
40- use rustc_span:: { sym, Span } ;
40+ use rustc_span:: { sym, Span , DUMMY_SP } ;
4141use rustc_target:: spec:: abi;
4242use rustc_trait_selection:: traits;
4343use rustc_trait_selection:: traits:: astconv_object_safety_violations;
@@ -54,7 +54,7 @@ use std::slice;
5454pub struct PathSeg ( pub DefId , pub usize ) ;
5555
5656pub trait AstConv < ' tcx > {
57- fn tcx < ' a > ( & ' a self ) -> TyCtxt < ' tcx > ;
57+ fn tcx ( & self ) -> TyCtxt < ' tcx > ;
5858
5959 fn item_def_id ( & self ) -> DefId ;
6060
@@ -131,6 +131,8 @@ pub trait AstConv<'tcx> {
131131 {
132132 self
133133 }
134+
135+ fn infcx ( & self ) -> Option < & InferCtxt < ' tcx > > ;
134136}
135137
136138#[ derive( Debug ) ]
@@ -2132,48 +2134,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
21322134 )
21332135 . emit ( ) // Already reported in an earlier stage.
21342136 } else {
2135- // Find all the `impl`s that `qself_ty` has for any trait that has the
2136- // associated type, so that we suggest the right one.
2137- let infcx = tcx. infer_ctxt ( ) . build ( ) ;
2138- // We create a fresh `ty::ParamEnv` instead of the one for `self.item_def_id()`
2139- // to avoid a cycle error in `src/test/ui/resolve/issue-102946.rs`.
2140- let param_env = ty:: ParamEnv :: empty ( ) ;
2141- let traits: Vec < _ > = self
2142- . tcx ( )
2143- . all_traits ( )
2144- . filter ( |trait_def_id| {
2145- // Consider only traits with the associated type
2146- tcx. associated_items ( * trait_def_id)
2147- . in_definition_order ( )
2148- . any ( |i| {
2149- i. kind . namespace ( ) == Namespace :: TypeNS
2150- && i. ident ( tcx) . normalize_to_macros_2_0 ( ) == assoc_ident
2151- && matches ! ( i. kind, ty:: AssocKind :: Type )
2152- } )
2153- // Consider only accessible traits
2154- && tcx. visibility ( * trait_def_id)
2155- . is_accessible_from ( self . item_def_id ( ) , tcx)
2156- && tcx. all_impls ( * trait_def_id)
2157- . any ( |impl_def_id| {
2158- let trait_ref = tcx. impl_trait_ref ( impl_def_id) ;
2159- trait_ref. map_or ( false , |trait_ref| {
2160- let impl_ = trait_ref. subst (
2161- tcx,
2162- infcx. fresh_substs_for_item ( span, impl_def_id) ,
2163- ) ;
2164- infcx
2165- . can_eq (
2166- param_env,
2167- tcx. erase_regions ( impl_. self_ty ( ) ) ,
2168- tcx. erase_regions ( qself_ty) ,
2169- )
2170- . is_ok ( )
2171- } )
2172- && tcx. impl_polarity ( impl_def_id) != ty:: ImplPolarity :: Negative
2173- } )
2174- } )
2175- . map ( |trait_def_id| tcx. def_path_str ( trait_def_id) )
2176- . collect ( ) ;
2137+ let traits: Vec < _ > =
2138+ self . probe_traits_that_match_assoc_ty ( qself_ty, assoc_ident) ;
21772139
21782140 // Don't print `TyErr` to the user.
21792141 self . report_ambiguous_associated_type (
@@ -2232,6 +2194,60 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
22322194 Ok ( ( ty, DefKind :: AssocTy , assoc_ty_did) )
22332195 }
22342196
2197+ fn probe_traits_that_match_assoc_ty (
2198+ & self ,
2199+ qself_ty : Ty < ' tcx > ,
2200+ assoc_ident : Ident ,
2201+ ) -> Vec < String > {
2202+ let tcx = self . tcx ( ) ;
2203+
2204+ // In contexts that have no inference context, just make a new one.
2205+ // We do need a local variable to store it, though.
2206+ let infcx_;
2207+ let infcx = if let Some ( infcx) = self . infcx ( ) {
2208+ infcx
2209+ } else {
2210+ assert ! ( !qself_ty. needs_infer( ) ) ;
2211+ infcx_ = tcx. infer_ctxt ( ) . build ( ) ;
2212+ & infcx_
2213+ } ;
2214+
2215+ tcx. all_traits ( )
2216+ . filter ( |trait_def_id| {
2217+ // Consider only traits with the associated type
2218+ tcx. associated_items ( * trait_def_id)
2219+ . in_definition_order ( )
2220+ . any ( |i| {
2221+ i. kind . namespace ( ) == Namespace :: TypeNS
2222+ && i. ident ( tcx) . normalize_to_macros_2_0 ( ) == assoc_ident
2223+ && matches ! ( i. kind, ty:: AssocKind :: Type )
2224+ } )
2225+ // Consider only accessible traits
2226+ && tcx. visibility ( * trait_def_id)
2227+ . is_accessible_from ( self . item_def_id ( ) , tcx)
2228+ && tcx. all_impls ( * trait_def_id)
2229+ . any ( |impl_def_id| {
2230+ let trait_ref = tcx. impl_trait_ref ( impl_def_id) ;
2231+ trait_ref. map_or ( false , |trait_ref| {
2232+ let impl_ = trait_ref. subst (
2233+ tcx,
2234+ infcx. fresh_substs_for_item ( DUMMY_SP , impl_def_id) ,
2235+ ) ;
2236+ infcx
2237+ . can_eq (
2238+ ty:: ParamEnv :: empty ( ) ,
2239+ tcx. erase_regions ( impl_. self_ty ( ) ) ,
2240+ tcx. erase_regions ( qself_ty) ,
2241+ )
2242+ . is_ok ( )
2243+ } )
2244+ && tcx. impl_polarity ( impl_def_id) != ty:: ImplPolarity :: Negative
2245+ } )
2246+ } )
2247+ . map ( |trait_def_id| tcx. def_path_str ( trait_def_id) )
2248+ . collect ( )
2249+ }
2250+
22352251 fn lookup_assoc_ty (
22362252 & self ,
22372253 ident : Ident ,
0 commit comments