@@ -11,7 +11,7 @@ use rustc_hir::HirId;
11
11
use rustc_hir:: def:: DefKind ;
12
12
use rustc_hir_analysis:: autoderef:: { self , Autoderef } ;
13
13
use rustc_infer:: infer:: canonical:: { Canonical , OriginalQueryValues , QueryResponse } ;
14
- use rustc_infer:: infer:: { self , DefineOpaqueTypes , InferOk , TyCtxtInferExt } ;
14
+ use rustc_infer:: infer:: { self , DefineOpaqueTypes , InferCtxt , InferOk , TyCtxtInferExt } ;
15
15
use rustc_infer:: traits:: ObligationCauseCode ;
16
16
use rustc_middle:: middle:: stability;
17
17
use rustc_middle:: query:: Providers ;
@@ -443,7 +443,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
443
443
// If we encountered an `_` type or an error type during autoderef, this is
444
444
// ambiguous.
445
445
if let Some ( bad_ty) = & steps. opt_bad_ty {
446
- 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 {
447
457
// Ambiguity was encountered during a suggestion. There's really
448
458
// not much use in suggesting methods in this case.
449
459
return Err ( MethodError :: NoMatch ( NoMatchData {
@@ -469,13 +479,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
469
479
} ,
470
480
) ;
471
481
} else {
472
- // Ended up encountering a type variable when doing autoderef,
473
- // but it may not be a type variable after processing obligations
474
- // in our local `FnCtxt`, so don't call `structurally_resolve_type`.
475
- let ty = & bad_ty. ty ;
476
- let ty = self
477
- . probe_instantiate_query_response ( span, & orig_values, ty)
478
- . unwrap_or_else ( |_| span_bug ! ( span, "instantiating {:?} failed?" , ty) ) ;
479
482
let ty = self . resolve_vars_if_possible ( ty. value ) ;
480
483
let guar = match * ty. kind ( ) {
481
484
ty:: Infer ( ty:: TyVar ( _) ) => {
@@ -583,60 +586,75 @@ fn method_autoderef_steps<'tcx>(
583
586
let mut reached_raw_pointer = false ;
584
587
let arbitrary_self_types_enabled =
585
588
tcx. features ( ) . arbitrary_self_types ( ) || tcx. features ( ) . arbitrary_self_types_pointers ( ) ;
586
- let ( mut steps, reached_recursion_limit) : ( Vec < _ > , bool ) = if arbitrary_self_types_enabled {
587
- let reachable_via_deref =
588
- autoderef_via_deref. by_ref ( ) . map ( |_| true ) . chain ( std:: iter:: repeat ( false ) ) ;
589
-
590
- let mut autoderef_via_receiver =
591
- Autoderef :: new ( infcx, param_env, hir:: def_id:: CRATE_DEF_ID , DUMMY_SP , self_ty)
592
- . include_raw_pointers ( )
593
- . use_receiver_trait ( )
594
- . silence_errors ( ) ;
595
- let steps = autoderef_via_receiver
596
- . by_ref ( )
597
- . zip ( reachable_via_deref)
598
- . map ( |( ( ty, d) , reachable_via_deref) | {
599
- let step = CandidateStep {
600
- self_ty : infcx
601
- . make_query_response_ignoring_pending_obligations ( inference_vars, ty) ,
602
- autoderefs : d,
603
- from_unsafe_deref : reached_raw_pointer,
604
- unsize : false ,
605
- reachable_via_deref,
606
- } ;
607
- if ty. is_raw_ptr ( ) {
608
- // all the subsequent steps will be from_unsafe_deref
609
- reached_raw_pointer = true ;
610
- }
611
- step
612
- } )
613
- . collect ( ) ;
614
- ( steps, autoderef_via_receiver. reached_recursion_limit ( ) )
615
- } else {
616
- let steps = autoderef_via_deref
617
- . by_ref ( )
618
- . map ( |( ty, d) | {
619
- let step = CandidateStep {
620
- self_ty : infcx
621
- . make_query_response_ignoring_pending_obligations ( inference_vars, ty) ,
622
- autoderefs : d,
623
- from_unsafe_deref : reached_raw_pointer,
624
- unsize : false ,
625
- reachable_via_deref : true ,
626
- } ;
627
- if ty. is_raw_ptr ( ) {
628
- // all the subsequent steps will be from_unsafe_deref
629
- reached_raw_pointer = true ;
630
- }
631
- step
632
- } )
633
- . collect ( ) ;
634
- ( steps, autoderef_via_deref. reached_recursion_limit ( ) )
635
- } ;
636
- let final_ty = autoderef_via_deref. final_ty ( true ) ;
589
+ let ( mut steps, final_ty, reached_recursion_limit) : ( Vec < _ > , _ , _ ) =
590
+ if arbitrary_self_types_enabled {
591
+ let reachable_via_deref =
592
+ autoderef_via_deref. by_ref ( ) . map ( |_| true ) . chain ( std:: iter:: repeat ( false ) ) ;
593
+
594
+ let mut autoderef_via_receiver =
595
+ Autoderef :: new ( infcx, param_env, hir:: def_id:: CRATE_DEF_ID , DUMMY_SP , self_ty)
596
+ . include_raw_pointers ( )
597
+ . use_receiver_trait ( )
598
+ . silence_errors ( ) ;
599
+ let steps = autoderef_via_receiver
600
+ . by_ref ( )
601
+ . zip ( reachable_via_deref)
602
+ . map ( |( ( ty, d) , reachable_via_deref) | {
603
+ let step = CandidateStep {
604
+ self_ty : infcx
605
+ . make_query_response_ignoring_pending_obligations ( inference_vars, ty) ,
606
+ autoderefs : d,
607
+ from_unsafe_deref : reached_raw_pointer,
608
+ unsize : false ,
609
+ reachable_via_deref,
610
+ } ;
611
+ if ty. is_raw_ptr ( ) {
612
+ // all the subsequent steps will be from_unsafe_deref
613
+ reached_raw_pointer = true ;
614
+ }
615
+ step
616
+ } )
617
+ . collect ( ) ;
618
+ (
619
+ steps,
620
+ // FIXME(arbitrary_self_types): This is sus.
621
+ autoderef_via_deref. final_ty ( true ) ,
622
+ autoderef_via_receiver. reached_recursion_limit ( ) ,
623
+ )
624
+ } else {
625
+ let steps = autoderef_via_deref
626
+ . by_ref ( )
627
+ . map ( |( ty, d) | {
628
+ let step = CandidateStep {
629
+ self_ty : infcx
630
+ . make_query_response_ignoring_pending_obligations ( inference_vars, ty) ,
631
+ autoderefs : d,
632
+ from_unsafe_deref : reached_raw_pointer,
633
+ unsize : false ,
634
+ reachable_via_deref : true ,
635
+ } ;
636
+ if ty. is_raw_ptr ( ) {
637
+ // all the subsequent steps will be from_unsafe_deref
638
+ reached_raw_pointer = true ;
639
+ }
640
+ step
641
+ } )
642
+ . collect ( ) ;
643
+ (
644
+ steps,
645
+ autoderef_via_deref. final_ty ( true ) ,
646
+ autoderef_via_deref. reached_recursion_limit ( ) ,
647
+ )
648
+ } ;
637
649
let opt_bad_ty = match final_ty. kind ( ) {
638
- ty:: Infer ( ty:: TyVar ( _) ) | ty:: Error ( _) => Some ( MethodAutoderefBadTy {
650
+ ty:: Infer ( ty:: TyVar ( _) ) => Some ( MethodAutoderefBadTy {
651
+ reached_raw_pointer,
652
+ is_opaque_type : final_ty_is_opaque ( infcx, final_ty) ,
653
+ ty : infcx. make_query_response_ignoring_pending_obligations ( inference_vars, final_ty) ,
654
+ } ) ,
655
+ ty:: Error ( _) => Some ( MethodAutoderefBadTy {
639
656
reached_raw_pointer,
657
+ is_opaque_type : false ,
640
658
ty : infcx. make_query_response_ignoring_pending_obligations ( inference_vars, final_ty) ,
641
659
} ) ,
642
660
ty:: Array ( elem_ty, _) => {
@@ -669,6 +687,20 @@ fn method_autoderef_steps<'tcx>(
669
687
}
670
688
}
671
689
690
+ /// Returns `true` in case the final type is the hidden type of an opaque.
691
+ #[ instrument( level = "debug" , skip( infcx) , ret) ]
692
+ fn final_ty_is_opaque < ' tcx > ( infcx : & InferCtxt < ' tcx > , final_ty : Ty < ' tcx > ) -> bool {
693
+ // nyaaaa~
694
+ if infcx. next_trait_solver ( ) {
695
+ let & ty:: Infer ( ty:: TyVar ( vid) ) = final_ty. kind ( ) else {
696
+ return false ;
697
+ } ;
698
+ infcx. find_sup_as_registered_opaque ( vid) . is_some ( )
699
+ } else {
700
+ false
701
+ }
702
+ }
703
+
672
704
impl < ' a , ' tcx > ProbeContext < ' a , ' tcx > {
673
705
fn new (
674
706
fcx : & ' a FnCtxt < ' a , ' tcx > ,
@@ -1882,31 +1914,39 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1882
1914
( xform_self_ty, xform_ret_ty) =
1883
1915
self . xform_self_ty ( probe. item , trait_ref. self_ty ( ) , trait_ref. args ) ;
1884
1916
xform_self_ty = ocx. normalize ( cause, self . param_env , xform_self_ty) ;
1885
- match self_ty. kind ( ) {
1886
- // HACK: opaque types will match anything for which their bounds hold.
1887
- // Thus we need to prevent them from trying to match the `&_` autoref
1888
- // candidates that get created for `&self` trait methods.
1889
- ty:: Alias ( ty:: Opaque , alias_ty)
1890
- if !self . next_trait_solver ( )
1891
- && self . infcx . can_define_opaque_ty ( alias_ty. def_id )
1892
- && !xform_self_ty. is_ty_var ( ) =>
1893
- {
1894
- return ProbeResult :: NoMatch ;
1895
- }
1896
- _ => match ocx. relate (
1897
- cause,
1898
- self . param_env ,
1899
- self . variance ( ) ,
1900
- self_ty,
1901
- xform_self_ty,
1902
- ) {
1903
- Ok ( ( ) ) => { }
1904
- Err ( err) => {
1905
- debug ! ( "--> cannot relate self-types {:?}" , err) ;
1917
+
1918
+ // HACK: opaque types will match anything for which their bounds hold.
1919
+ // Thus we need to prevent them from trying to match the `&_` autoref
1920
+ // candidates that get created for `&self` trait methods.
1921
+ if self . mode == Mode :: MethodCall {
1922
+ match self_ty. kind ( ) {
1923
+ ty:: Infer ( ty:: TyVar ( _) ) => {
1924
+ assert ! ( self . infcx. next_trait_solver( ) ) ;
1925
+ if !xform_self_ty. is_ty_var ( ) {
1926
+ return ProbeResult :: NoMatch ;
1927
+ }
1928
+ }
1929
+ ty:: Alias ( ty:: Opaque , alias_ty)
1930
+ if !self . infcx . next_trait_solver ( )
1931
+ && self . infcx . can_define_opaque_ty ( alias_ty. def_id )
1932
+ && !xform_self_ty. is_ty_var ( ) =>
1933
+ {
1934
+ assert ! ( !self . infcx. next_trait_solver( ) ) ;
1906
1935
return ProbeResult :: NoMatch ;
1907
1936
}
1908
- } ,
1937
+ _ => { }
1938
+ }
1939
+ }
1940
+
1941
+ match ocx. relate ( cause, self . param_env , self . variance ( ) , self_ty, xform_self_ty)
1942
+ {
1943
+ Ok ( ( ) ) => { }
1944
+ Err ( err) => {
1945
+ debug ! ( "--> cannot relate self-types {:?}" , err) ;
1946
+ return ProbeResult :: NoMatch ;
1947
+ }
1909
1948
}
1949
+
1910
1950
let obligation = traits:: Obligation :: new (
1911
1951
self . tcx ,
1912
1952
cause. clone ( ) ,
0 commit comments