@@ -10,7 +10,7 @@ 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 } ;
13
+ use rustc_infer:: infer:: { self , DefineOpaqueTypes , InferCtxt , InferOk , TyCtxtInferExt } ;
14
14
use rustc_infer:: traits:: ObligationCauseCode ;
15
15
use rustc_middle:: middle:: stability;
16
16
use rustc_middle:: query:: Providers ;
@@ -442,7 +442,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
442
442
// If we encountered an `_` type or an error type during autoderef, this is
443
443
// ambiguous.
444
444
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 {
446
456
// Ambiguity was encountered during a suggestion. There's really
447
457
// not much use in suggesting methods in this case.
448
458
return Err ( MethodError :: NoMatch ( NoMatchData {
@@ -468,13 +478,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
468
478
} ,
469
479
) ;
470
480
} 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
481
let ty = self . resolve_vars_if_possible ( ty. value ) ;
479
482
let guar = match * ty. kind ( ) {
480
483
ty:: Infer ( ty:: TyVar ( _) ) => {
@@ -582,60 +585,75 @@ fn method_autoderef_steps<'tcx>(
582
585
let mut reached_raw_pointer = false ;
583
586
let arbitrary_self_types_enabled =
584
587
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
+ } ;
636
648
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 {
638
655
reached_raw_pointer,
656
+ is_opaque_type : false ,
639
657
ty : infcx. make_query_response_ignoring_pending_obligations ( inference_vars, final_ty) ,
640
658
} ) ,
641
659
ty:: Array ( elem_ty, _) => {
@@ -668,6 +686,20 @@ fn method_autoderef_steps<'tcx>(
668
686
}
669
687
}
670
688
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
+
671
703
impl < ' a , ' tcx > ProbeContext < ' a , ' tcx > {
672
704
fn new (
673
705
fcx : & ' a FnCtxt < ' a , ' tcx > ,
@@ -1881,31 +1913,39 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1881
1913
( xform_self_ty, xform_ret_ty) =
1882
1914
self . xform_self_ty ( probe. item , trait_ref. self_ty ( ) , trait_ref. args ) ;
1883
1915
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( ) ) ;
1905
1934
return ProbeResult :: NoMatch ;
1906
1935
}
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
+ }
1908
1947
}
1948
+
1909
1949
let obligation = traits:: Obligation :: new (
1910
1950
self . tcx ,
1911
1951
cause. clone ( ) ,
0 commit comments