@@ -4,7 +4,7 @@ use super::{
44} ;
55
66use crate :: autoderef:: Autoderef ;
7- use crate :: infer:: { InferCtxt , InferOk } ;
7+ use crate :: infer:: InferCtxt ;
88use crate :: traits:: { self , normalize_projection_type} ;
99
1010use rustc_data_structures:: fx:: FxHashSet ;
@@ -16,12 +16,11 @@ use rustc_hir::def_id::DefId;
1616use rustc_hir:: intravisit:: Visitor ;
1717use rustc_hir:: lang_items:: LangItem ;
1818use rustc_hir:: { AsyncGeneratorKind , GeneratorKind , Node } ;
19- use rustc_middle:: ty:: subst:: { GenericArgKind , Subst } ;
19+ use rustc_middle:: ty:: subst:: InternalSubsts ;
2020use rustc_middle:: ty:: {
2121 self , suggest_constraining_type_param, AdtKind , DefIdTree , Infer , InferTy , ToPredicate , Ty ,
22- TyCtxt , TypeFoldable , WithConstness ,
22+ TyCtxt , TypeAndMut , TypeFoldable , TypeckResults , WithConstness ,
2323} ;
24- use rustc_middle:: ty:: { TypeAndMut , TypeckResults } ;
2524use rustc_span:: symbol:: { kw, sym, Ident , Symbol } ;
2625use rustc_span:: { MultiSpan , Span , DUMMY_SP } ;
2726use rustc_target:: spec:: abi;
@@ -338,67 +337,45 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
338337 let mut turbofish_suggestions = FxHashSet :: default ( ) ;
339338 self . tcx . for_each_relevant_impl ( data. trait_ref . def_id , self_ty, |impl_def_id| {
340339 self . probe ( |_| {
341- let impl_substs = self . fresh_substs_for_item ( DUMMY_SP , impl_def_id) ;
340+ let trait_args = InternalSubsts :: identity_for_item ( self . tcx , data. trait_ref . def_id ) ;
341+ let impl_args = traits:: specialize:: fulfill_implication (
342+ self ,
343+ obligation. param_env ,
344+ data. trait_ref ,
345+ impl_def_id,
346+ ) ;
347+ let substs = match impl_args {
348+ Ok ( impl_args) => trait_args. rebase_onto ( self . tcx , impl_def_id, impl_args) ,
349+ _ => return ,
350+ } ;
342351 let trait_ref = self . tcx . impl_trait_ref ( impl_def_id) . unwrap ( ) ;
343- let trait_ref = trait_ref. subst ( self . tcx , impl_substs) ;
344352
345- // Require the type the impl is implemented on to match
346- // our type, and ignore the impl if there was a mismatch.
347353 let cause = traits:: ObligationCause :: dummy ( ) ;
348- let eq_result =
349- self . at ( & cause, obligation. param_env ) . eq ( trait_ref. self_ty ( ) , self_ty) ;
350- if let Ok ( InferOk { value : ( ) , obligations : _ } ) = eq_result {
351- if let Ok ( eval_result) = self . evaluate_obligation ( & Obligation :: new (
354+ let mut selcx = SelectionContext :: new ( & self ) ;
355+ let param_env = obligation. param_env . clone ( ) ;
356+ let ( target_trait_ref, obligations) = traits:: util:: impl_trait_ref_and_oblig (
357+ & mut selcx,
358+ param_env,
359+ impl_def_id,
360+ substs,
361+ ) ;
362+ self . resolve_vars_if_possible ( & target_trait_ref) ;
363+ if let Ok ( eval_result) = selcx. evaluate_predicates (
364+ Some ( Obligation :: new (
352365 cause. clone ( ) ,
353- obligation. param_env ,
354- trait_ref. without_const ( ) . to_predicate ( self . tcx ) ,
355- ) ) {
356- // FIXME: We will also suggest cases where `eval_result` is
357- // `EvaluatedToAmbig`, we just put them at the end of the sugg list.
358- // Ideally we would only suggest types that would always apply cleanly.
359- // This means that for `collect` we will suggest `PathBuf` as a valid type
360- // whereas that `impl` has an extra requirement `T: AsRef<Path>` which we
361- // don't evaluate.
362- if eval_result. may_apply ( )
363- && data. trait_ref . substs . iter ( ) . zip ( trait_ref. substs . iter ( ) ) . all (
364- // Here we'll have something like `[_, i32]` coming from our code
365- // and `[Vec<_>, _]` from the probe. For cases with
366- // inference variables we are left with ambiguous cases due to
367- // trait bounds we couldn't evaluate, but we *can* filter out cases
368- // like `[std::string::String, char]`, where we can `collect` a
369- // `String` only if we have an `IntoIterator<Item = char>`, which
370- // won't match the `i32` we have.
371- |( l, r) | {
372- // FIXME: ideally we would use `can_coerce` here instead, but `typeck`
373- // comes *after* in the dependency graph.
374- match ( l. unpack ( ) , r. unpack ( ) ) {
375- (
376- GenericArgKind :: Type ( left_ty) ,
377- GenericArgKind :: Type ( right_ty) ,
378- ) => match (
379- & left_ty. peel_refs ( ) . kind ( ) ,
380- & right_ty. peel_refs ( ) . kind ( ) ,
381- ) {
382- ( Infer ( _) , _) | ( _, Infer ( _) ) => true ,
383- ( left_kind, right_kind) => left_kind == right_kind,
384- } ,
385- (
386- GenericArgKind :: Lifetime ( _) ,
387- GenericArgKind :: Lifetime ( _) ,
388- )
389- | ( GenericArgKind :: Const ( _) , GenericArgKind :: Const ( _) ) => {
390- true
391- }
392- _ => false ,
393- }
394- } ,
395- )
396- && !matches ! ( trait_ref. self_ty( ) . kind( ) , ty:: Infer ( _) )
397- {
398- turbofish_suggestions. insert ( trait_ref. self_ty ( ) ) ;
399- }
400- } ;
401- }
366+ param_env,
367+ target_trait_ref. without_const ( ) . to_predicate ( self . tcx ) ,
368+ ) )
369+ . into_iter ( )
370+ . chain ( obligations) ,
371+ ) {
372+ debug ! ( "get_turbofish_suggestions result {:?}" , eval_result) ;
373+ if eval_result. must_apply_modulo_regions ( )
374+ && !matches ! ( trait_ref. self_ty( ) . kind( ) , ty:: Infer ( _) )
375+ {
376+ turbofish_suggestions. insert ( trait_ref. self_ty ( ) ) ;
377+ }
378+ } ;
402379 } )
403380 } ) ;
404381 // Sort types by always suggesting `Vec<_>` and `String` first, as they are the
0 commit comments