@@ -27,7 +27,7 @@ use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
27
27
use rustc_hir:: def_id:: { DefId , LocalDefId } ;
28
28
use rustc_hir:: intravisit:: { walk_generics, Visitor as _} ;
29
29
use rustc_hir:: { GenericArg , GenericArgs , OpaqueTyOrigin } ;
30
- use rustc_infer:: infer:: TyCtxtInferExt ;
30
+ use rustc_infer:: infer:: { InferCtxt , TyCtxtInferExt } ;
31
31
use rustc_middle:: middle:: stability:: AllowUnstable ;
32
32
use rustc_middle:: ty:: subst:: { self , GenericArgKind , InternalSubsts , SubstsRef } ;
33
33
use rustc_middle:: ty:: GenericParamDefKind ;
@@ -37,7 +37,7 @@ use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECT
37
37
use rustc_span:: edition:: Edition ;
38
38
use rustc_span:: lev_distance:: find_best_match_for_name;
39
39
use rustc_span:: symbol:: { kw, Ident , Symbol } ;
40
- use rustc_span:: { sym, Span } ;
40
+ use rustc_span:: { sym, Span , DUMMY_SP } ;
41
41
use rustc_target:: spec:: abi;
42
42
use rustc_trait_selection:: traits;
43
43
use rustc_trait_selection:: traits:: astconv_object_safety_violations;
@@ -54,7 +54,7 @@ use std::slice;
54
54
pub struct PathSeg ( pub DefId , pub usize ) ;
55
55
56
56
pub trait AstConv < ' tcx > {
57
- fn tcx < ' a > ( & ' a self ) -> TyCtxt < ' tcx > ;
57
+ fn tcx ( & self ) -> TyCtxt < ' tcx > ;
58
58
59
59
fn item_def_id ( & self ) -> DefId ;
60
60
@@ -131,6 +131,8 @@ pub trait AstConv<'tcx> {
131
131
{
132
132
self
133
133
}
134
+
135
+ fn infcx ( & self ) -> Option < & InferCtxt < ' tcx > > ;
134
136
}
135
137
136
138
#[ derive( Debug ) ]
@@ -2132,48 +2134,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
2132
2134
)
2133
2135
. emit ( ) // Already reported in an earlier stage.
2134
2136
} 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) ;
2177
2139
2178
2140
// Don't print `TyErr` to the user.
2179
2141
self . report_ambiguous_associated_type (
@@ -2232,6 +2194,60 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
2232
2194
Ok ( ( ty, DefKind :: AssocTy , assoc_ty_did) )
2233
2195
}
2234
2196
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
+
2235
2251
fn lookup_assoc_ty (
2236
2252
& self ,
2237
2253
ident : Ident ,
0 commit comments