@@ -10,7 +10,7 @@ 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 } ;
13+ use rustc_infer:: infer:: { self , DefineOpaqueTypes , InferCtxt , InferOk , TyCtxtInferExt } ;
1414use rustc_infer:: traits:: ObligationCauseCode ;
1515use rustc_middle:: middle:: stability;
1616use rustc_middle:: query:: Providers ;
@@ -442,7 +442,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
442442 // If we encountered an `_` type or an error type during autoderef, this is
443443 // ambiguous.
444444 if let Some ( bad_ty) = & steps. opt_bad_ty {
445- if is_suggestion. 0 {
445+ // Ended up encountering a type variable when doing autoderef,
446+ // but it may not be a type variable after processing obligations
447+ // in our local `FnCtxt`, so don't call `structurally_resolve_type`.
448+ let ty = & bad_ty. ty ;
449+ let ty = self
450+ . probe_instantiate_query_response ( span, & orig_values, ty)
451+ . unwrap_or_else ( |_| span_bug ! ( span, "instantiating {:?} failed?" , ty) ) ;
452+ if bad_ty. is_opaque_type || final_ty_is_opaque ( & self . infcx , ty. value ) {
453+ // FIXME(-Znext-solver): This isn't really what we want :<
454+ assert ! ( self . tcx. next_trait_solver_globally( ) ) ;
455+ } else if is_suggestion. 0 {
446456 // Ambiguity was encountered during a suggestion. There's really
447457 // not much use in suggesting methods in this case.
448458 return Err ( MethodError :: NoMatch ( NoMatchData {
@@ -468,13 +478,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
468478 } ,
469479 ) ;
470480 } 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) ) ;
478481 let ty = self . resolve_vars_if_possible ( ty. value ) ;
479482 let guar = match * ty. kind ( ) {
480483 ty:: Infer ( ty:: TyVar ( _) ) => {
@@ -582,60 +585,75 @@ fn method_autoderef_steps<'tcx>(
582585 let mut reached_raw_pointer = false ;
583586 let arbitrary_self_types_enabled =
584587 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 ) ;
588+ let ( mut steps, final_ty, reached_recursion_limit) : ( Vec < _ > , _ , _ ) =
589+ if arbitrary_self_types_enabled {
590+ let reachable_via_deref =
591+ autoderef_via_deref. by_ref ( ) . map ( |_| true ) . chain ( std:: iter:: repeat ( false ) ) ;
592+
593+ let mut autoderef_via_receiver =
594+ Autoderef :: new ( infcx, param_env, hir:: def_id:: CRATE_DEF_ID , DUMMY_SP , self_ty)
595+ . include_raw_pointers ( )
596+ . use_receiver_trait ( )
597+ . silence_errors ( ) ;
598+ let steps = autoderef_via_receiver
599+ . by_ref ( )
600+ . zip ( reachable_via_deref)
601+ . map ( |( ( ty, d) , reachable_via_deref) | {
602+ let step = CandidateStep {
603+ self_ty : infcx
604+ . make_query_response_ignoring_pending_obligations ( inference_vars, ty) ,
605+ autoderefs : d,
606+ from_unsafe_deref : reached_raw_pointer,
607+ unsize : false ,
608+ reachable_via_deref,
609+ } ;
610+ if ty. is_raw_ptr ( ) {
611+ // all the subsequent steps will be from_unsafe_deref
612+ reached_raw_pointer = true ;
613+ }
614+ step
615+ } )
616+ . collect ( ) ;
617+ (
618+ steps,
619+ // FIXME(arbitrary_self_types): This is sus.
620+ autoderef_via_deref. final_ty ( true ) ,
621+ autoderef_via_receiver. reached_recursion_limit ( ) ,
622+ )
623+ } else {
624+ let steps = autoderef_via_deref
625+ . by_ref ( )
626+ . map ( |( ty, d) | {
627+ let step = CandidateStep {
628+ self_ty : infcx
629+ . make_query_response_ignoring_pending_obligations ( inference_vars, ty) ,
630+ autoderefs : d,
631+ from_unsafe_deref : reached_raw_pointer,
632+ unsize : false ,
633+ reachable_via_deref : true ,
634+ } ;
635+ if ty. is_raw_ptr ( ) {
636+ // all the subsequent steps will be from_unsafe_deref
637+ reached_raw_pointer = true ;
638+ }
639+ step
640+ } )
641+ . collect ( ) ;
642+ (
643+ steps,
644+ autoderef_via_deref. final_ty ( true ) ,
645+ autoderef_via_deref. reached_recursion_limit ( ) ,
646+ )
647+ } ;
636648 let opt_bad_ty = match final_ty. kind ( ) {
637- ty:: Infer ( ty:: TyVar ( _) ) | ty:: Error ( _) => Some ( MethodAutoderefBadTy {
649+ ty:: Infer ( ty:: TyVar ( _) ) => Some ( MethodAutoderefBadTy {
650+ reached_raw_pointer,
651+ is_opaque_type : final_ty_is_opaque ( infcx, final_ty) ,
652+ ty : infcx. make_query_response_ignoring_pending_obligations ( inference_vars, final_ty) ,
653+ } ) ,
654+ ty:: Error ( _) => Some ( MethodAutoderefBadTy {
638655 reached_raw_pointer,
656+ is_opaque_type : false ,
639657 ty : infcx. make_query_response_ignoring_pending_obligations ( inference_vars, final_ty) ,
640658 } ) ,
641659 ty:: Array ( elem_ty, _) => {
@@ -668,6 +686,20 @@ fn method_autoderef_steps<'tcx>(
668686 }
669687}
670688
689+ /// Returns `true` in case the final type is the hidden type of an opaque.
690+ #[ instrument( level = "debug" , skip( infcx) , ret) ]
691+ fn final_ty_is_opaque < ' tcx > ( infcx : & InferCtxt < ' tcx > , final_ty : Ty < ' tcx > ) -> bool {
692+ // nyaaaa~
693+ if infcx. next_trait_solver ( ) {
694+ let & ty:: Infer ( ty:: TyVar ( vid) ) = final_ty. kind ( ) else {
695+ return false ;
696+ } ;
697+ infcx. find_sup_as_registered_opaque ( vid) . is_some ( )
698+ } else {
699+ false
700+ }
701+ }
702+
671703impl < ' a , ' tcx > ProbeContext < ' a , ' tcx > {
672704 fn new (
673705 fcx : & ' a FnCtxt < ' a , ' tcx > ,
@@ -1881,31 +1913,39 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
18811913 ( xform_self_ty, xform_ret_ty) =
18821914 self . xform_self_ty ( probe. item , trait_ref. self_ty ( ) , trait_ref. args ) ;
18831915 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) ;
1916+
1917+ // HACK: opaque types will match anything for which their bounds hold.
1918+ // Thus we need to prevent them from trying to match the `&_` autoref
1919+ // candidates that get created for `&self` trait methods.
1920+ if self . mode == Mode :: MethodCall {
1921+ match self_ty. kind ( ) {
1922+ ty:: Infer ( ty:: TyVar ( _) ) => {
1923+ assert ! ( self . infcx. next_trait_solver( ) ) ;
1924+ if !xform_self_ty. is_ty_var ( ) {
1925+ return ProbeResult :: NoMatch ;
1926+ }
1927+ }
1928+ ty:: Alias ( ty:: Opaque , alias_ty)
1929+ if !self . infcx . next_trait_solver ( )
1930+ && self . infcx . can_define_opaque_ty ( alias_ty. def_id )
1931+ && !xform_self_ty. is_ty_var ( ) =>
1932+ {
1933+ assert ! ( !self . infcx. next_trait_solver( ) ) ;
19051934 return ProbeResult :: NoMatch ;
19061935 }
1907- } ,
1936+ _ => { }
1937+ }
1938+ }
1939+
1940+ match ocx. relate ( cause, self . param_env , self . variance ( ) , self_ty, xform_self_ty)
1941+ {
1942+ Ok ( ( ) ) => { }
1943+ Err ( err) => {
1944+ debug ! ( "--> cannot relate self-types {:?}" , err) ;
1945+ return ProbeResult :: NoMatch ;
1946+ }
19081947 }
1948+
19091949 let obligation = traits:: Obligation :: new (
19101950 self . tcx ,
19111951 cause. clone ( ) ,
0 commit comments