@@ -10,15 +10,16 @@ use rustc_hir::HirId;
10
10
use rustc_hir:: def:: DefKind ;
11
11
use rustc_hir_analysis:: autoderef:: { self , Autoderef } ;
12
12
use 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 } ;
15
16
use rustc_middle:: middle:: stability;
16
17
use rustc_middle:: query:: Providers ;
17
18
use rustc_middle:: ty:: elaborate:: supertrait_def_ids;
18
19
use rustc_middle:: ty:: fast_reject:: { TreatParams , simplify_type} ;
19
20
use rustc_middle:: ty:: {
20
21
self , AssocItem , AssocItemContainer , GenericArgs , GenericArgsRef , GenericParamDefKind ,
21
- ParamEnvAnd , Ty , TyCtxt , TypeVisitableExt , Upcast ,
22
+ ParamEnvAnd , PredicateKind , Ty , TyCtxt , TypeVisitableExt , Upcast ,
22
23
} ;
23
24
use rustc_middle:: { bug, span_bug} ;
24
25
use rustc_session:: lint;
@@ -29,6 +30,9 @@ use rustc_span::edit_distance::{
29
30
use rustc_span:: { DUMMY_SP , Ident , Span , Symbol , sym} ;
30
31
use rustc_trait_selection:: error_reporting:: infer:: need_type_info:: TypeAnnotationNeeded ;
31
32
use rustc_trait_selection:: infer:: InferCtxtExt as _;
33
+ use rustc_trait_selection:: solve:: inspect:: {
34
+ InspectConfig , InspectGoal , ProofTreeInferCtxtExt , ProofTreeVisitor ,
35
+ } ;
32
36
use rustc_trait_selection:: traits:: query:: CanonicalTyGoal ;
33
37
use rustc_trait_selection:: traits:: query:: evaluate_obligation:: InferCtxtExt ;
34
38
use rustc_trait_selection:: traits:: query:: method_autoderef:: {
@@ -442,7 +446,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
442
446
// If we encountered an `_` type or an error type during autoderef, this is
443
447
// ambiguous.
444
448
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 {
446
466
// Ambiguity was encountered during a suggestion. There's really
447
467
// not much use in suggesting methods in this case.
448
468
return Err ( MethodError :: NoMatch ( NoMatchData {
@@ -468,13 +488,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
468
488
} ,
469
489
) ;
470
490
} 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) ) ;
478
491
let ty = self . resolve_vars_if_possible ( ty. value ) ;
479
492
let guar = match * ty. kind ( ) {
480
493
ty:: Infer ( ty:: TyVar ( _) ) => {
@@ -582,60 +595,77 @@ fn method_autoderef_steps<'tcx>(
582
595
let mut reached_raw_pointer = false ;
583
596
let arbitrary_self_types_enabled =
584
597
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
+ } ;
636
660
let opt_bad_ty = match final_ty. kind ( ) {
637
- ty:: Infer ( ty:: TyVar ( _) ) | ty :: Error ( _ ) => Some ( MethodAutoderefBadTy {
661
+ ty:: Infer ( ty:: TyVar ( _) ) => Some ( MethodAutoderefBadTy {
638
662
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 ,
639
669
ty : infcx. make_query_response_ignoring_pending_obligations ( inference_vars, final_ty) ,
640
670
} ) ,
641
671
ty:: Array ( elem_ty, _) => {
@@ -668,6 +698,71 @@ fn method_autoderef_steps<'tcx>(
668
698
}
669
699
}
670
700
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
+
671
766
impl < ' a , ' tcx > ProbeContext < ' a , ' tcx > {
672
767
fn new (
673
768
fcx : & ' a FnCtxt < ' a , ' tcx > ,
@@ -1881,31 +1976,39 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1881
1976
( xform_self_ty, xform_ret_ty) =
1882
1977
self . xform_self_ty ( probe. item , trait_ref. self_ty ( ) , trait_ref. args ) ;
1883
1978
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( ) ) ;
1905
1997
return ProbeResult :: NoMatch ;
1906
1998
}
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
+ }
1908
2010
}
2011
+
1909
2012
let obligation = traits:: Obligation :: new (
1910
2013
self . tcx ,
1911
2014
cause. clone ( ) ,
0 commit comments