@@ -12,7 +12,9 @@ use rustc_hir::HirId;
1212use rustc_hir:: def:: DefKind ;
1313use rustc_hir_analysis:: autoderef:: { self , Autoderef } ;
1414use rustc_infer:: infer:: canonical:: { Canonical , OriginalQueryValues , QueryResponse } ;
15- use rustc_infer:: infer:: { BoundRegionConversionTime , DefineOpaqueTypes , InferOk , TyCtxtInferExt } ;
15+ use rustc_infer:: infer:: {
16+ BoundRegionConversionTime , DefineOpaqueTypes , InferCtxt , InferOk , TyCtxtInferExt ,
17+ } ;
1618use rustc_infer:: traits:: ObligationCauseCode ;
1719use rustc_middle:: middle:: stability;
1820use rustc_middle:: ty:: elaborate:: supertrait_def_ids;
@@ -441,7 +443,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
441443 // If we encountered an `_` type or an error type during autoderef, this is
442444 // ambiguous.
443445 if let Some ( bad_ty) = & steps. opt_bad_ty {
444- if is_suggestion. 0 {
446+ // Ended up encountering a type variable when doing autoderef,
447+ // but it may not be a type variable after processing obligations
448+ // in our local `FnCtxt`, so don't call `structurally_resolve_type`.
449+ let ty = & bad_ty. ty ;
450+ let ty = self
451+ . probe_instantiate_query_response ( span, & orig_values, ty)
452+ . unwrap_or_else ( |_| span_bug ! ( span, "instantiating {:?} failed?" , ty) ) ;
453+ if bad_ty. is_opaque_type || final_ty_is_opaque ( & self . infcx , ty. value ) {
454+ // FIXME(-Znext-solver): This isn't really what we want :<
455+ assert ! ( self . tcx. next_trait_solver_globally( ) ) ;
456+ } else if is_suggestion. 0 {
445457 // Ambiguity was encountered during a suggestion. There's really
446458 // not much use in suggesting methods in this case.
447459 return Err ( MethodError :: NoMatch ( NoMatchData {
@@ -467,13 +479,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
467479 } ,
468480 ) ;
469481 } else {
470- // Ended up encountering a type variable when doing autoderef,
471- // but it may not be a type variable after processing obligations
472- // in our local `FnCtxt`, so don't call `structurally_resolve_type`.
473- let ty = & bad_ty. ty ;
474- let ty = self
475- . probe_instantiate_query_response ( span, & orig_values, ty)
476- . unwrap_or_else ( |_| span_bug ! ( span, "instantiating {:?} failed?" , ty) ) ;
477482 let ty = self . resolve_vars_if_possible ( ty. value ) ;
478483 let guar = match * ty. kind ( ) {
479484 ty:: Infer ( ty:: TyVar ( _) ) => {
@@ -629,8 +634,14 @@ pub(crate) fn method_autoderef_steps<'tcx>(
629634 } ;
630635 let final_ty = autoderef_via_deref. final_ty ( ) ;
631636 let opt_bad_ty = match final_ty. kind ( ) {
632- ty:: Infer ( ty:: TyVar ( _) ) | ty :: Error ( _ ) => Some ( MethodAutoderefBadTy {
637+ ty:: Infer ( ty:: TyVar ( _) ) => Some ( MethodAutoderefBadTy {
633638 reached_raw_pointer,
639+ is_opaque_type : final_ty_is_opaque ( infcx, final_ty) ,
640+ ty : infcx. make_query_response_ignoring_pending_obligations ( inference_vars, final_ty) ,
641+ } ) ,
642+ ty:: Error ( _) => Some ( MethodAutoderefBadTy {
643+ reached_raw_pointer,
644+ is_opaque_type : false ,
634645 ty : infcx. make_query_response_ignoring_pending_obligations ( inference_vars, final_ty) ,
635646 } ) ,
636647 ty:: Array ( elem_ty, _) => {
@@ -663,6 +674,15 @@ pub(crate) fn method_autoderef_steps<'tcx>(
663674 }
664675}
665676
677+ /// Returns `true` in case the final type is the hidden type of an opaque.
678+ #[ instrument( level = "debug" , skip( infcx) , ret) ]
679+ fn final_ty_is_opaque < ' tcx > ( infcx : & InferCtxt < ' tcx > , final_ty : Ty < ' tcx > ) -> bool {
680+ let & ty:: Infer ( ty:: TyVar ( vid) ) = final_ty. kind ( ) else {
681+ return false ;
682+ } ;
683+ infcx. has_opaques_with_sub_unified_hidden_type ( vid)
684+ }
685+
666686impl < ' a , ' tcx > ProbeContext < ' a , ' tcx > {
667687 fn new (
668688 fcx : & ' a FnCtxt < ' a , ' tcx > ,
@@ -1871,31 +1891,39 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
18711891 ( xform_self_ty, xform_ret_ty) =
18721892 self . xform_self_ty ( probe. item , trait_ref. self_ty ( ) , trait_ref. args ) ;
18731893 xform_self_ty = ocx. normalize ( cause, self . param_env , xform_self_ty) ;
1874- match self_ty. kind ( ) {
1875- // HACK: opaque types will match anything for which their bounds hold.
1876- // Thus we need to prevent them from trying to match the `&_` autoref
1877- // candidates that get created for `&self` trait methods.
1878- ty:: Alias ( ty:: Opaque , alias_ty)
1879- if !self . next_trait_solver ( )
1880- && self . infcx . can_define_opaque_ty ( alias_ty. def_id )
1881- && !xform_self_ty. is_ty_var ( ) =>
1882- {
1883- return ProbeResult :: NoMatch ;
1884- }
1885- _ => match ocx. relate (
1886- cause,
1887- self . param_env ,
1888- self . variance ( ) ,
1889- self_ty,
1890- xform_self_ty,
1891- ) {
1892- Ok ( ( ) ) => { }
1893- Err ( err) => {
1894- debug ! ( "--> cannot relate self-types {:?}" , err) ;
1894+
1895+ // HACK: opaque types will match anything for which their bounds hold.
1896+ // Thus we need to prevent them from trying to match the `&_` autoref
1897+ // candidates that get created for `&self` trait methods.
1898+ if self . mode == Mode :: MethodCall {
1899+ match self_ty. kind ( ) {
1900+ ty:: Infer ( ty:: TyVar ( _) ) => {
1901+ assert ! ( self . infcx. next_trait_solver( ) ) ;
1902+ if !xform_self_ty. is_ty_var ( ) {
1903+ return ProbeResult :: NoMatch ;
1904+ }
1905+ }
1906+ ty:: Alias ( ty:: Opaque , alias_ty)
1907+ if !self . infcx . next_trait_solver ( )
1908+ && self . infcx . can_define_opaque_ty ( alias_ty. def_id )
1909+ && !xform_self_ty. is_ty_var ( ) =>
1910+ {
1911+ assert ! ( !self . infcx. next_trait_solver( ) ) ;
18951912 return ProbeResult :: NoMatch ;
18961913 }
1897- } ,
1914+ _ => { }
1915+ }
1916+ }
1917+
1918+ match ocx. relate ( cause, self . param_env , self . variance ( ) , self_ty, xform_self_ty)
1919+ {
1920+ Ok ( ( ) ) => { }
1921+ Err ( err) => {
1922+ debug ! ( "--> cannot relate self-types {:?}" , err) ;
1923+ return ProbeResult :: NoMatch ;
1924+ }
18981925 }
1926+
18991927 let obligation = traits:: Obligation :: new (
19001928 self . tcx ,
19011929 cause. clone ( ) ,
0 commit comments