@@ -10,15 +10,16 @@ use rustc_hir::HirId;
1010use rustc_hir:: def:: DefKind ;
1111use rustc_hir_analysis:: autoderef:: { self , Autoderef } ;
1212use rustc_infer:: infer:: canonical:: { Canonical , OriginalQueryValues , QueryResponse } ;
13- use rustc_infer:: infer:: { self , DefineOpaqueTypes , InferOk , TyCtxtInferExt } ;
14- use rustc_infer:: traits:: ObligationCauseCode ;
13+ use rustc_infer:: infer:: { self , DefineOpaqueTypes , InferCtxt , InferOk , TyCtxtInferExt } ;
14+ use rustc_infer:: traits:: solve:: Goal ;
15+ use rustc_infer:: traits:: { ObligationCauseCode , PredicateObligation } ;
1516use rustc_middle:: middle:: stability;
1617use rustc_middle:: query:: Providers ;
1718use rustc_middle:: ty:: elaborate:: supertrait_def_ids;
1819use rustc_middle:: ty:: fast_reject:: { TreatParams , simplify_type} ;
1920use rustc_middle:: ty:: {
2021 self , AssocItem , AssocItemContainer , GenericArgs , GenericArgsRef , GenericParamDefKind ,
21- ParamEnvAnd , Ty , TyCtxt , TypeVisitableExt , Upcast ,
22+ ParamEnvAnd , PredicateKind , Ty , TyCtxt , TypeVisitableExt , Upcast ,
2223} ;
2324use rustc_middle:: { bug, span_bug} ;
2425use rustc_session:: lint;
@@ -29,6 +30,9 @@ use rustc_span::edit_distance::{
2930use rustc_span:: { DUMMY_SP , Ident , Span , Symbol , sym} ;
3031use rustc_trait_selection:: error_reporting:: infer:: need_type_info:: TypeAnnotationNeeded ;
3132use rustc_trait_selection:: infer:: InferCtxtExt as _;
33+ use rustc_trait_selection:: solve:: inspect:: {
34+ InspectConfig , InspectGoal , ProofTreeInferCtxtExt , ProofTreeVisitor ,
35+ } ;
3236use rustc_trait_selection:: traits:: query:: CanonicalTyGoal ;
3337use rustc_trait_selection:: traits:: query:: evaluate_obligation:: InferCtxtExt ;
3438use rustc_trait_selection:: traits:: query:: method_autoderef:: {
@@ -442,7 +446,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
442446 // If we encountered an `_` type or an error type during autoderef, this is
443447 // ambiguous.
444448 if let Some ( bad_ty) = & steps. opt_bad_ty {
445- if is_suggestion. 0 {
449+ // Ended up encountering a type variable when doing autoderef,
450+ // but it may not be a type variable after processing obligations
451+ // in our local `FnCtxt`, so don't call `structurally_resolve_type`.
452+ let ty = & bad_ty. ty ;
453+ let ty = self
454+ . probe_instantiate_query_response ( span, & orig_values, ty)
455+ . unwrap_or_else ( |_| span_bug ! ( span, "instantiating {:?} failed?" , ty) ) ;
456+ if bad_ty. is_opaque_type
457+ || final_ty_is_opaque (
458+ & self . infcx ,
459+ & self . fulfillment_cx . borrow ( ) . pending_obligations ( ) ,
460+ ty. value ,
461+ )
462+ {
463+ // FIXME(-Znext-solver): This isn't really what we want :<
464+ assert ! ( self . tcx. next_trait_solver_globally( ) ) ;
465+ } else if is_suggestion. 0 {
446466 // Ambiguity was encountered during a suggestion. There's really
447467 // not much use in suggesting methods in this case.
448468 return Err ( MethodError :: NoMatch ( NoMatchData {
@@ -468,13 +488,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
468488 } ,
469489 ) ;
470490 } else {
471- // Ended up encountering a type variable when doing autoderef,
472- // but it may not be a type variable after processing obligations
473- // in our local `FnCtxt`, so don't call `structurally_resolve_type`.
474- let ty = & bad_ty. ty ;
475- let ty = self
476- . probe_instantiate_query_response ( span, & orig_values, ty)
477- . unwrap_or_else ( |_| span_bug ! ( span, "instantiating {:?} failed?" , ty) ) ;
478491 let ty = self . resolve_vars_if_possible ( ty. value ) ;
479492 let guar = match * ty. kind ( ) {
480493 ty:: Infer ( ty:: TyVar ( _) ) => {
@@ -582,60 +595,77 @@ fn method_autoderef_steps<'tcx>(
582595 let mut reached_raw_pointer = false ;
583596 let arbitrary_self_types_enabled =
584597 tcx. features ( ) . arbitrary_self_types ( ) || tcx. features ( ) . arbitrary_self_types_pointers ( ) ;
585- let ( mut steps, reached_recursion_limit) : ( Vec < _ > , bool ) = if arbitrary_self_types_enabled {
586- let reachable_via_deref =
587- autoderef_via_deref. by_ref ( ) . map ( |_| true ) . chain ( std:: iter:: repeat ( false ) ) ;
588-
589- let mut autoderef_via_receiver =
590- Autoderef :: new ( infcx, param_env, hir:: def_id:: CRATE_DEF_ID , DUMMY_SP , self_ty)
591- . include_raw_pointers ( )
592- . use_receiver_trait ( )
593- . silence_errors ( ) ;
594- let steps = autoderef_via_receiver
595- . by_ref ( )
596- . zip ( reachable_via_deref)
597- . map ( |( ( ty, d) , reachable_via_deref) | {
598- let step = CandidateStep {
599- self_ty : infcx
600- . make_query_response_ignoring_pending_obligations ( inference_vars, ty) ,
601- autoderefs : d,
602- from_unsafe_deref : reached_raw_pointer,
603- unsize : false ,
604- reachable_via_deref,
605- } ;
606- if ty. is_raw_ptr ( ) {
607- // all the subsequent steps will be from_unsafe_deref
608- reached_raw_pointer = true ;
609- }
610- step
611- } )
612- . collect ( ) ;
613- ( steps, autoderef_via_receiver. reached_recursion_limit ( ) )
614- } else {
615- let steps = autoderef_via_deref
616- . by_ref ( )
617- . map ( |( ty, d) | {
618- let step = CandidateStep {
619- self_ty : infcx
620- . make_query_response_ignoring_pending_obligations ( inference_vars, ty) ,
621- autoderefs : d,
622- from_unsafe_deref : reached_raw_pointer,
623- unsize : false ,
624- reachable_via_deref : true ,
625- } ;
626- if ty. is_raw_ptr ( ) {
627- // all the subsequent steps will be from_unsafe_deref
628- reached_raw_pointer = true ;
629- }
630- step
631- } )
632- . collect ( ) ;
633- ( steps, autoderef_via_deref. reached_recursion_limit ( ) )
634- } ;
635- let final_ty = autoderef_via_deref. final_ty ( true ) ;
598+ let ( mut steps, final_ty, reached_recursion_limit, obligations) : ( Vec < _ > , _ , _ , _ ) =
599+ if arbitrary_self_types_enabled {
600+ let reachable_via_deref =
601+ autoderef_via_deref. by_ref ( ) . map ( |_| true ) . chain ( std:: iter:: repeat ( false ) ) ;
602+
603+ let mut autoderef_via_receiver =
604+ Autoderef :: new ( infcx, param_env, hir:: def_id:: CRATE_DEF_ID , DUMMY_SP , self_ty)
605+ . include_raw_pointers ( )
606+ . use_receiver_trait ( )
607+ . silence_errors ( ) ;
608+ let steps = autoderef_via_receiver
609+ . by_ref ( )
610+ . zip ( reachable_via_deref)
611+ . map ( |( ( ty, d) , reachable_via_deref) | {
612+ let step = CandidateStep {
613+ self_ty : infcx
614+ . make_query_response_ignoring_pending_obligations ( inference_vars, ty) ,
615+ autoderefs : d,
616+ from_unsafe_deref : reached_raw_pointer,
617+ unsize : false ,
618+ reachable_via_deref,
619+ } ;
620+ if ty. is_raw_ptr ( ) {
621+ // all the subsequent steps will be from_unsafe_deref
622+ reached_raw_pointer = true ;
623+ }
624+ step
625+ } )
626+ . collect ( ) ;
627+ (
628+ steps,
629+ // FIXME(arbitrary_self_types): This is sus.
630+ autoderef_via_deref. final_ty ( true ) ,
631+ autoderef_via_receiver. reached_recursion_limit ( ) ,
632+ autoderef_via_receiver. into_obligations ( ) ,
633+ )
634+ } else {
635+ let steps = autoderef_via_deref
636+ . by_ref ( )
637+ . map ( |( ty, d) | {
638+ let step = CandidateStep {
639+ self_ty : infcx
640+ . make_query_response_ignoring_pending_obligations ( inference_vars, ty) ,
641+ autoderefs : d,
642+ from_unsafe_deref : reached_raw_pointer,
643+ unsize : false ,
644+ reachable_via_deref : true ,
645+ } ;
646+ if ty. is_raw_ptr ( ) {
647+ // all the subsequent steps will be from_unsafe_deref
648+ reached_raw_pointer = true ;
649+ }
650+ step
651+ } )
652+ . collect ( ) ;
653+ (
654+ steps,
655+ autoderef_via_deref. final_ty ( true ) ,
656+ autoderef_via_deref. reached_recursion_limit ( ) ,
657+ autoderef_via_deref. into_obligations ( ) ,
658+ )
659+ } ;
636660 let opt_bad_ty = match final_ty. kind ( ) {
637- ty:: Infer ( ty:: TyVar ( _) ) | ty :: Error ( _ ) => Some ( MethodAutoderefBadTy {
661+ ty:: Infer ( ty:: TyVar ( _) ) => Some ( MethodAutoderefBadTy {
638662 reached_raw_pointer,
663+ is_opaque_type : final_ty_is_opaque ( infcx, & obligations, final_ty) ,
664+ ty : infcx. make_query_response_ignoring_pending_obligations ( inference_vars, final_ty) ,
665+ } ) ,
666+ ty:: Error ( _) => Some ( MethodAutoderefBadTy {
667+ reached_raw_pointer,
668+ is_opaque_type : false ,
639669 ty : infcx. make_query_response_ignoring_pending_obligations ( inference_vars, final_ty) ,
640670 } ) ,
641671 ty:: Array ( elem_ty, _) => {
@@ -668,6 +698,71 @@ fn method_autoderef_steps<'tcx>(
668698 }
669699}
670700
701+ /// Returns `true` in case the final type is the hidden type of an opaque.
702+ #[ instrument( level = "debug" , skip( infcx) , ret) ]
703+ fn final_ty_is_opaque < ' tcx > (
704+ infcx : & InferCtxt < ' tcx > ,
705+ obligations : & [ PredicateObligation < ' tcx > ] ,
706+ final_ty : Ty < ' tcx > ,
707+ ) -> bool {
708+ // nyaaaa~
709+ if infcx. next_trait_solver ( ) {
710+ for obligation in obligations {
711+ let mut visitor = FinalTyIsOpaque { final_ty, is_opaque_ty : false } ;
712+ let goal = Goal :: new ( infcx. tcx , obligation. param_env , obligation. predicate ) ;
713+ infcx. visit_proof_tree ( goal, & mut visitor) ;
714+ if visitor. is_opaque_ty {
715+ return true ;
716+ }
717+ }
718+
719+ let opaque_types = infcx. clone_opaque_types ( ) ;
720+ for ( _, hidden_ty) in & opaque_types {
721+ if infcx. shallow_resolve ( hidden_ty. ty ) == final_ty {
722+ return true ;
723+ }
724+ }
725+ }
726+
727+ false
728+ }
729+
730+ struct FinalTyIsOpaque < ' tcx > {
731+ final_ty : Ty < ' tcx > ,
732+ is_opaque_ty : bool ,
733+ }
734+
735+ impl < ' tcx > ProofTreeVisitor < ' tcx > for FinalTyIsOpaque < ' tcx > {
736+ fn span ( & self ) -> Span {
737+ DUMMY_SP
738+ }
739+
740+ fn config ( & self ) -> InspectConfig {
741+ // Using an intentionally low depth to avoid potential hangs
742+ // due to exponentially growing proof trees.
743+ InspectConfig { max_depth : 5 }
744+ }
745+
746+ fn visit_goal ( & mut self , inspect_goal : & InspectGoal < ' _ , ' tcx > ) {
747+ let infcx = inspect_goal. infcx ( ) ;
748+ let goal = inspect_goal. goal ( ) ;
749+ if let PredicateKind :: NormalizesTo ( ty:: NormalizesTo { alias, term } ) =
750+ goal. predicate . kind ( ) . skip_binder ( )
751+ {
752+ debug ! ( ?alias, ?term, "visiting normalizes-to goal" ) ;
753+ if term. as_type ( ) . is_some_and ( |ty| ty == self . final_ty )
754+ && alias. kind ( infcx. tcx ) == ty:: AliasTermKind :: OpaqueTy
755+ {
756+ self . is_opaque_ty = true ;
757+ }
758+ }
759+
760+ if let Some ( candidate) = inspect_goal. unique_applicable_candidate ( ) {
761+ candidate. visit_nested_in_probe ( self )
762+ }
763+ }
764+ }
765+
671766impl < ' a , ' tcx > ProbeContext < ' a , ' tcx > {
672767 fn new (
673768 fcx : & ' a FnCtxt < ' a , ' tcx > ,
@@ -1881,31 +1976,39 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
18811976 ( xform_self_ty, xform_ret_ty) =
18821977 self . xform_self_ty ( probe. item , trait_ref. self_ty ( ) , trait_ref. args ) ;
18831978 xform_self_ty = ocx. normalize ( cause, self . param_env , xform_self_ty) ;
1884- match self_ty. kind ( ) {
1885- // HACK: opaque types will match anything for which their bounds hold.
1886- // Thus we need to prevent them from trying to match the `&_` autoref
1887- // candidates that get created for `&self` trait methods.
1888- ty:: Alias ( ty:: Opaque , alias_ty)
1889- if !self . next_trait_solver ( )
1890- && self . infcx . can_define_opaque_ty ( alias_ty. def_id )
1891- && !xform_self_ty. is_ty_var ( ) =>
1892- {
1893- return ProbeResult :: NoMatch ;
1894- }
1895- _ => match ocx. relate (
1896- cause,
1897- self . param_env ,
1898- self . variance ( ) ,
1899- self_ty,
1900- xform_self_ty,
1901- ) {
1902- Ok ( ( ) ) => { }
1903- Err ( err) => {
1904- debug ! ( "--> cannot relate self-types {:?}" , err) ;
1979+
1980+ // HACK: opaque types will match anything for which their bounds hold.
1981+ // Thus we need to prevent them from trying to match the `&_` autoref
1982+ // candidates that get created for `&self` trait methods.
1983+ if self . mode == Mode :: MethodCall {
1984+ match self_ty. kind ( ) {
1985+ ty:: Infer ( ty:: TyVar ( _) ) => {
1986+ assert ! ( self . infcx. next_trait_solver( ) ) ;
1987+ if !xform_self_ty. is_ty_var ( ) {
1988+ return ProbeResult :: NoMatch ;
1989+ }
1990+ }
1991+ ty:: Alias ( ty:: Opaque , alias_ty)
1992+ if !self . infcx . next_trait_solver ( )
1993+ && self . infcx . can_define_opaque_ty ( alias_ty. def_id )
1994+ && !xform_self_ty. is_ty_var ( ) =>
1995+ {
1996+ assert ! ( !self . infcx. next_trait_solver( ) ) ;
19051997 return ProbeResult :: NoMatch ;
19061998 }
1907- } ,
1999+ _ => { }
2000+ }
2001+ }
2002+
2003+ match ocx. relate ( cause, self . param_env , self . variance ( ) , self_ty, xform_self_ty)
2004+ {
2005+ Ok ( ( ) ) => { }
2006+ Err ( err) => {
2007+ debug ! ( "--> cannot relate self-types {:?}" , err) ;
2008+ return ProbeResult :: NoMatch ;
2009+ }
19082010 }
2011+
19092012 let obligation = traits:: Obligation :: new (
19102013 self . tcx ,
19112014 cause. clone ( ) ,
0 commit comments