@@ -13,7 +13,7 @@ use rustc_hir::def::DefKind;
13
13
use rustc_hir_analysis:: autoderef:: { self , Autoderef } ;
14
14
use rustc_infer:: infer:: canonical:: { Canonical , OriginalQueryValues , QueryResponse } ;
15
15
use rustc_infer:: infer:: { BoundRegionConversionTime , DefineOpaqueTypes , InferOk , TyCtxtInferExt } ;
16
- use rustc_infer:: traits:: ObligationCauseCode ;
16
+ use rustc_infer:: traits:: { ObligationCauseCode , query } ;
17
17
use rustc_middle:: middle:: stability;
18
18
use rustc_middle:: ty:: elaborate:: supertrait_def_ids;
19
19
use rustc_middle:: ty:: fast_reject:: { DeepRejectCtxt , TreatParams , simplify_type} ;
@@ -30,7 +30,7 @@ use rustc_span::edit_distance::{
30
30
use rustc_span:: { DUMMY_SP , Ident , Span , Symbol , sym} ;
31
31
use rustc_trait_selection:: error_reporting:: infer:: need_type_info:: TypeAnnotationNeeded ;
32
32
use rustc_trait_selection:: infer:: InferCtxtExt as _;
33
- use rustc_trait_selection:: traits:: query:: CanonicalTyGoal ;
33
+ use rustc_trait_selection:: traits:: query:: CanonicalMethodAutoderefStepsGoal ;
34
34
use rustc_trait_selection:: traits:: query:: evaluate_obligation:: InferCtxtExt ;
35
35
use rustc_trait_selection:: traits:: query:: method_autoderef:: {
36
36
CandidateStep , MethodAutoderefBadTy , MethodAutoderefStepsResult ,
@@ -389,10 +389,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
389
389
OP : FnOnce ( ProbeContext < ' _ , ' tcx > ) -> Result < R , MethodError < ' tcx > > ,
390
390
{
391
391
let mut orig_values = OriginalQueryValues :: default ( ) ;
392
- let query_input = self . canonicalize_query (
393
- ParamEnvAnd { param_env : self . param_env , value : self_ty } ,
394
- & mut orig_values,
395
- ) ;
392
+ let predefined_opaques_in_body = if self . next_trait_solver ( ) {
393
+ self . tcx . mk_predefined_opaques_in_body_from_iter (
394
+ self . inner . borrow_mut ( ) . opaque_types ( ) . iter_opaque_types ( ) . map ( |( k, v) | ( k, v. ty ) ) ,
395
+ )
396
+ } else {
397
+ ty:: List :: empty ( )
398
+ } ;
399
+ let value = query:: MethodAutoderefSteps { predefined_opaques_in_body, self_ty } ;
400
+ let query_input = self
401
+ . canonicalize_query ( ParamEnvAnd { param_env : self . param_env , value } , & mut orig_values) ;
396
402
397
403
let steps = match mode {
398
404
Mode :: MethodCall => self . tcx . method_autoderef_steps ( query_input) ,
@@ -403,8 +409,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
403
409
// special handling for this "trivial case" is a good idea.
404
410
405
411
let infcx = & self . infcx ;
406
- let ( ParamEnvAnd { param_env : _, value : self_ty } , var_values) =
412
+ let ( ParamEnvAnd { param_env : _, value } , var_values) =
407
413
infcx. instantiate_canonical ( span, & query_input. canonical ) ;
414
+ let query:: MethodAutoderefSteps { predefined_opaques_in_body : _, self_ty } = value;
408
415
debug ! ( ?self_ty, ?query_input, "probe_op: Mode::Path" ) ;
409
416
MethodAutoderefStepsResult {
410
417
steps : infcx. tcx . arena . alloc_from_iter ( [ CandidateStep {
@@ -553,12 +560,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
553
560
554
561
pub ( crate ) fn method_autoderef_steps < ' tcx > (
555
562
tcx : TyCtxt < ' tcx > ,
556
- goal : CanonicalTyGoal < ' tcx > ,
563
+ goal : CanonicalMethodAutoderefStepsGoal < ' tcx > ,
557
564
) -> MethodAutoderefStepsResult < ' tcx > {
558
565
debug ! ( "method_autoderef_steps({:?})" , goal) ;
559
566
560
567
let ( ref infcx, goal, inference_vars) = tcx. infer_ctxt ( ) . build_with_canonical ( DUMMY_SP , & goal) ;
561
- let ParamEnvAnd { param_env, value : self_ty } = goal;
568
+ let ParamEnvAnd {
569
+ param_env,
570
+ value : query:: MethodAutoderefSteps { predefined_opaques_in_body, self_ty } ,
571
+ } = goal;
572
+ for ( key, ty) in predefined_opaques_in_body {
573
+ let prev =
574
+ infcx. register_hidden_type_in_storage ( key, ty:: OpaqueHiddenType { span : DUMMY_SP , ty } ) ;
575
+ // It may be possible that two entries in the opaque type storage end up
576
+ // with the same key after resolving contained inference variables.
577
+ //
578
+ // We could put them in the duplicate list but don't have to. The opaques we
579
+ // encounter here are already tracked in the caller, so there's no need to
580
+ // also store them here. We'd take them out when computing the query response
581
+ // and then discard them, as they're already present in the input.
582
+ //
583
+ // Ideally we'd drop duplicate opaque type definitions when computing
584
+ // the canonical input. This is more annoying to implement and may cause a
585
+ // perf regression, so we do it inside of the query for now.
586
+ if let Some ( prev) = prev {
587
+ debug ! ( ?key, ?ty, ?prev, "ignore duplicate in `opaque_types_storage`" ) ;
588
+ }
589
+ }
562
590
563
591
// If arbitrary self types is not enabled, we follow the chain of
564
592
// `Deref<Target=T>`. If arbitrary self types is enabled, we instead
@@ -655,7 +683,8 @@ pub(crate) fn method_autoderef_steps<'tcx>(
655
683
} ;
656
684
657
685
debug ! ( "method_autoderef_steps: steps={:?} opt_bad_ty={:?}" , steps, opt_bad_ty) ;
658
-
686
+ // Need to empty the opaque types storage before it gets dropped.
687
+ let _ = infcx. take_opaque_types ( ) ;
659
688
MethodAutoderefStepsResult {
660
689
steps : tcx. arena . alloc_from_iter ( steps) ,
661
690
opt_bad_ty : opt_bad_ty. map ( |ty| & * tcx. arena . alloc ( ty) ) ,
0 commit comments