@@ -10,14 +10,15 @@ 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:: fast_reject:: { TreatParams , simplify_type} ;
1819use rustc_middle:: ty:: {
1920 self , AssocItem , AssocItemContainer , GenericArgs , GenericArgsRef , GenericParamDefKind ,
20- ParamEnvAnd , Ty , TyCtxt , TypeVisitableExt , Upcast ,
21+ ParamEnvAnd , PredicateKind , Ty , TyCtxt , TypeVisitableExt , Upcast ,
2122} ;
2223use rustc_middle:: { bug, span_bug} ;
2324use rustc_session:: lint;
@@ -28,6 +29,9 @@ use rustc_span::edit_distance::{
2829use rustc_span:: { DUMMY_SP , Ident , Span , Symbol , sym} ;
2930use rustc_trait_selection:: error_reporting:: infer:: need_type_info:: TypeAnnotationNeeded ;
3031use rustc_trait_selection:: infer:: InferCtxtExt as _;
32+ use rustc_trait_selection:: solve:: inspect:: {
33+ InspectConfig , InspectGoal , ProofTreeInferCtxtExt , ProofTreeVisitor ,
34+ } ;
3135use rustc_trait_selection:: traits:: query:: CanonicalTyGoal ;
3236use rustc_trait_selection:: traits:: query:: evaluate_obligation:: InferCtxtExt ;
3337use rustc_trait_selection:: traits:: query:: method_autoderef:: {
@@ -438,7 +442,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
438442 // If we encountered an `_` type or an error type during autoderef, this is
439443 // ambiguous.
440444 if let Some ( bad_ty) = & steps. opt_bad_ty {
441- 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
453+ || final_ty_is_opaque (
454+ & self . infcx ,
455+ & self . fulfillment_cx . borrow ( ) . pending_obligations ( ) ,
456+ ty. value ,
457+ )
458+ {
459+ // FIXME(-Znext-solver): This isn't really what we want :<
460+ assert ! ( self . tcx. next_trait_solver_globally( ) ) ;
461+ } else if is_suggestion. 0 {
442462 // Ambiguity was encountered during a suggestion. There's really
443463 // not much use in suggesting methods in this case.
444464 return Err ( MethodError :: NoMatch ( NoMatchData {
@@ -464,13 +484,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
464484 } ,
465485 ) ;
466486 } else {
467- // Ended up encountering a type variable when doing autoderef,
468- // but it may not be a type variable after processing obligations
469- // in our local `FnCtxt`, so don't call `structurally_resolve_type`.
470- let ty = & bad_ty. ty ;
471- let ty = self
472- . probe_instantiate_query_response ( span, & orig_values, ty)
473- . unwrap_or_else ( |_| span_bug ! ( span, "instantiating {:?} failed?" , ty) ) ;
474487 let ty = self . resolve_vars_if_possible ( ty. value ) ;
475488 let guar = match * ty. kind ( ) {
476489 ty:: Infer ( ty:: TyVar ( _) ) => {
@@ -578,60 +591,78 @@ fn method_autoderef_steps<'tcx>(
578591 let mut reached_raw_pointer = false ;
579592 let arbitrary_self_types_enabled =
580593 tcx. features ( ) . arbitrary_self_types ( ) || tcx. features ( ) . arbitrary_self_types_pointers ( ) ;
581- let ( mut steps, reached_recursion_limit) : ( Vec < _ > , bool ) = if arbitrary_self_types_enabled {
582- let reachable_via_deref =
583- autoderef_via_deref. by_ref ( ) . map ( |_| true ) . chain ( std:: iter:: repeat ( false ) ) ;
584-
585- let mut autoderef_via_receiver =
586- Autoderef :: new ( infcx, param_env, hir:: def_id:: CRATE_DEF_ID , DUMMY_SP , self_ty)
587- . include_raw_pointers ( )
588- . use_receiver_trait ( )
589- . silence_errors ( ) ;
590- let steps = autoderef_via_receiver
591- . by_ref ( )
592- . zip ( reachable_via_deref)
593- . map ( |( ( ty, d) , reachable_via_deref) | {
594- let step = CandidateStep {
595- self_ty : infcx
596- . make_query_response_ignoring_pending_obligations ( inference_vars, ty) ,
597- autoderefs : d,
598- from_unsafe_deref : reached_raw_pointer,
599- unsize : false ,
600- reachable_via_deref,
601- } ;
602- if ty. is_unsafe_ptr ( ) {
603- // all the subsequent steps will be from_unsafe_deref
604- reached_raw_pointer = true ;
605- }
606- step
607- } )
608- . collect ( ) ;
609- ( steps, autoderef_via_receiver. reached_recursion_limit ( ) )
610- } else {
611- let steps = autoderef_via_deref
612- . by_ref ( )
613- . map ( |( ty, d) | {
614- let step = CandidateStep {
615- self_ty : infcx
616- . make_query_response_ignoring_pending_obligations ( inference_vars, ty) ,
617- autoderefs : d,
618- from_unsafe_deref : reached_raw_pointer,
619- unsize : false ,
620- reachable_via_deref : true ,
621- } ;
622- if ty. is_unsafe_ptr ( ) {
623- // all the subsequent steps will be from_unsafe_deref
624- reached_raw_pointer = true ;
625- }
626- step
627- } )
628- . collect ( ) ;
629- ( steps, autoderef_via_deref. reached_recursion_limit ( ) )
630- } ;
631- let final_ty = autoderef_via_deref. final_ty ( true ) ;
594+ let ( mut steps, final_ty, reached_recursion_limit, obligations) =
595+ if arbitrary_self_types_enabled {
596+ let reachable_via_deref =
597+ autoderef_via_deref. by_ref ( ) . map ( |_| true ) . chain ( std:: iter:: repeat ( false ) ) ;
598+
599+ let mut autoderef_via_receiver =
600+ Autoderef :: new ( infcx, param_env, hir:: def_id:: CRATE_DEF_ID , DUMMY_SP , self_ty)
601+ . include_raw_pointers ( )
602+ . use_receiver_trait ( )
603+ . silence_errors ( ) ;
604+ let steps: Vec < _ > = autoderef_via_receiver
605+ . by_ref ( )
606+ . zip ( reachable_via_deref)
607+ . map ( |( ( ty, d) , reachable_via_deref) | {
608+ let step = CandidateStep {
609+ self_ty : infcx
610+ . make_query_response_ignoring_pending_obligations ( inference_vars, ty) ,
611+ autoderefs : d,
612+ from_unsafe_deref : reached_raw_pointer,
613+ unsize : false ,
614+ reachable_via_deref,
615+ } ;
616+ if ty. is_unsafe_ptr ( ) {
617+ // all the subsequent steps will be from_unsafe_deref
618+ reached_raw_pointer = true ;
619+ }
620+ step
621+ } )
622+ . collect ( ) ;
623+ (
624+ steps,
625+ // FIXME(arbitrary_self_types): Why do we look at the final type of
626+ // the `deref` chain here?
627+ autoderef_via_deref. final_ty ( true ) ,
628+ autoderef_via_receiver. reached_recursion_limit ( ) ,
629+ autoderef_via_receiver. into_obligations ( ) ,
630+ )
631+ } else {
632+ let steps = autoderef_via_deref
633+ . by_ref ( )
634+ . map ( |( ty, d) | {
635+ let step = CandidateStep {
636+ self_ty : infcx
637+ . make_query_response_ignoring_pending_obligations ( inference_vars, ty) ,
638+ autoderefs : d,
639+ from_unsafe_deref : reached_raw_pointer,
640+ unsize : false ,
641+ reachable_via_deref : true ,
642+ } ;
643+ if ty. is_unsafe_ptr ( ) {
644+ // all the subsequent steps will be from_unsafe_deref
645+ reached_raw_pointer = true ;
646+ }
647+ step
648+ } )
649+ . collect ( ) ;
650+ (
651+ steps,
652+ autoderef_via_deref. final_ty ( true ) ,
653+ autoderef_via_deref. reached_recursion_limit ( ) ,
654+ autoderef_via_deref. into_obligations ( ) ,
655+ )
656+ } ;
632657 let opt_bad_ty = match final_ty. kind ( ) {
633- ty:: Infer ( ty:: TyVar ( _) ) | ty :: Error ( _ ) => Some ( MethodAutoderefBadTy {
658+ ty:: Infer ( ty:: TyVar ( _) ) => Some ( MethodAutoderefBadTy {
634659 reached_raw_pointer,
660+ is_opaque_type : final_ty_is_opaque ( infcx, & obligations, final_ty) ,
661+ ty : infcx. make_query_response_ignoring_pending_obligations ( inference_vars, final_ty) ,
662+ } ) ,
663+ ty:: Error ( _) => Some ( MethodAutoderefBadTy {
664+ reached_raw_pointer,
665+ is_opaque_type : false ,
635666 ty : infcx. make_query_response_ignoring_pending_obligations ( inference_vars, final_ty) ,
636667 } ) ,
637668 ty:: Array ( elem_ty, _) => {
@@ -664,6 +695,71 @@ fn method_autoderef_steps<'tcx>(
664695 }
665696}
666697
698+ /// Returns `true` in case the final type is the hidden type of an opaque.
699+ #[ instrument( level = "debug" , skip( infcx) , ret) ]
700+ fn final_ty_is_opaque < ' tcx > (
701+ infcx : & InferCtxt < ' tcx > ,
702+ obligations : & [ PredicateObligation < ' tcx > ] ,
703+ final_ty : Ty < ' tcx > ,
704+ ) -> bool {
705+ // nyaaaa~
706+ if infcx. next_trait_solver ( ) {
707+ for obligation in obligations {
708+ let mut visitor = FinalTyIsOpaque { final_ty, is_opaque_ty : false } ;
709+ let goal = Goal :: new ( infcx. tcx , obligation. param_env , obligation. predicate ) ;
710+ infcx. visit_proof_tree ( goal, & mut visitor) ;
711+ if visitor. is_opaque_ty {
712+ return true ;
713+ }
714+ }
715+
716+ let opaque_types = infcx. clone_opaque_types ( ) ;
717+ for ( key, hidden_ty) in & opaque_types {
718+ if infcx. shallow_resolve ( hidden_ty. ty ) == final_ty {
719+ return true ;
720+ }
721+ }
722+ }
723+
724+ false
725+ }
726+
727+ struct FinalTyIsOpaque < ' tcx > {
728+ final_ty : Ty < ' tcx > ,
729+ is_opaque_ty : bool ,
730+ }
731+
732+ impl < ' tcx > ProofTreeVisitor < ' tcx > for FinalTyIsOpaque < ' tcx > {
733+ fn span ( & self ) -> Span {
734+ DUMMY_SP
735+ }
736+
737+ fn config ( & self ) -> InspectConfig {
738+ // Using an intentionally low depth to avoid potential hangs
739+ // due to exponentially growing proof trees.
740+ InspectConfig { max_depth : 5 }
741+ }
742+
743+ fn visit_goal ( & mut self , inspect_goal : & InspectGoal < ' _ , ' tcx > ) {
744+ let infcx = inspect_goal. infcx ( ) ;
745+ let goal = inspect_goal. goal ( ) ;
746+ if let PredicateKind :: NormalizesTo ( ty:: NormalizesTo { alias, term } ) =
747+ goal. predicate . kind ( ) . skip_binder ( )
748+ {
749+ debug ! ( ?alias, ?term, "visiting normalizes-to goal" ) ;
750+ if term. as_type ( ) . is_some_and ( |ty| ty == self . final_ty )
751+ && alias. kind ( infcx. tcx ) == ty:: AliasTermKind :: OpaqueTy
752+ {
753+ self . is_opaque_ty = true ;
754+ }
755+ }
756+
757+ if let Some ( candidate) = inspect_goal. unique_applicable_candidate ( ) {
758+ candidate. visit_nested_in_probe ( self )
759+ }
760+ }
761+ }
762+
667763impl < ' a , ' tcx > ProbeContext < ' a , ' tcx > {
668764 fn new (
669765 fcx : & ' a FnCtxt < ' a , ' tcx > ,
@@ -1879,31 +1975,39 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
18791975 ( xform_self_ty, xform_ret_ty) =
18801976 self . xform_self_ty ( probe. item , trait_ref. self_ty ( ) , trait_ref. args ) ;
18811977 xform_self_ty = ocx. normalize ( cause, self . param_env , xform_self_ty) ;
1882- match self_ty. kind ( ) {
1883- // HACK: opaque types will match anything for which their bounds hold.
1884- // Thus we need to prevent them from trying to match the `&_` autoref
1885- // candidates that get created for `&self` trait methods.
1886- ty:: Alias ( ty:: Opaque , alias_ty)
1887- if !self . next_trait_solver ( )
1888- && self . infcx . can_define_opaque_ty ( alias_ty. def_id )
1889- && !xform_self_ty. is_ty_var ( ) =>
1890- {
1891- return ProbeResult :: NoMatch ;
1892- }
1893- _ => match ocx. relate (
1894- cause,
1895- self . param_env ,
1896- self . variance ( ) ,
1897- self_ty,
1898- xform_self_ty,
1899- ) {
1900- Ok ( ( ) ) => { }
1901- Err ( err) => {
1902- debug ! ( "--> cannot relate self-types {:?}" , err) ;
1978+
1979+ // HACK: opaque types will match anything for which their bounds hold.
1980+ // Thus we need to prevent them from trying to match the `&_` autoref
1981+ // candidates that get created for `&self` trait methods.
1982+ if self . mode == Mode :: MethodCall {
1983+ match self_ty. kind ( ) {
1984+ ty:: Infer ( ty:: TyVar ( _) ) => {
1985+ assert ! ( self . infcx. next_trait_solver( ) ) ;
1986+ if !xform_self_ty. is_ty_var ( ) {
1987+ return ProbeResult :: NoMatch ;
1988+ }
1989+ }
1990+ ty:: Alias ( ty:: Opaque , alias_ty)
1991+ if !self . infcx . next_trait_solver ( )
1992+ && self . infcx . can_define_opaque_ty ( alias_ty. def_id )
1993+ && !xform_self_ty. is_ty_var ( ) =>
1994+ {
1995+ assert ! ( !self . infcx. next_trait_solver( ) ) ;
19031996 return ProbeResult :: NoMatch ;
19041997 }
1905- } ,
1998+ _ => { }
1999+ }
2000+ }
2001+
2002+ match ocx. relate ( cause, self . param_env , self . variance ( ) , self_ty, xform_self_ty)
2003+ {
2004+ Ok ( ( ) ) => { }
2005+ Err ( err) => {
2006+ debug ! ( "--> cannot relate self-types {:?}" , err) ;
2007+ return ProbeResult :: NoMatch ;
2008+ }
19062009 }
2010+
19072011 let obligation = traits:: Obligation :: new (
19082012 self . tcx ,
19092013 cause. clone ( ) ,
0 commit comments