@@ -13,7 +13,7 @@ use rustc_hir::def::DefKind;
1313use rustc_hir_analysis:: autoderef:: { self , Autoderef } ;
1414use rustc_infer:: infer:: canonical:: { Canonical , OriginalQueryValues , QueryResponse } ;
1515use rustc_infer:: infer:: { BoundRegionConversionTime , DefineOpaqueTypes , InferOk , TyCtxtInferExt } ;
16- use rustc_infer:: traits:: ObligationCauseCode ;
16+ use rustc_infer:: traits:: { ObligationCauseCode , query } ;
1717use rustc_middle:: middle:: stability;
1818use rustc_middle:: ty:: elaborate:: supertrait_def_ids;
1919use rustc_middle:: ty:: fast_reject:: { DeepRejectCtxt , TreatParams , simplify_type} ;
@@ -30,7 +30,7 @@ use rustc_span::edit_distance::{
3030use rustc_span:: { DUMMY_SP , Ident , Span , Symbol , sym} ;
3131use rustc_trait_selection:: error_reporting:: infer:: need_type_info:: TypeAnnotationNeeded ;
3232use rustc_trait_selection:: infer:: InferCtxtExt as _;
33- use rustc_trait_selection:: traits:: query:: CanonicalTyGoal ;
33+ use rustc_trait_selection:: traits:: query:: CanonicalMethodAutoderefStepsGoal ;
3434use rustc_trait_selection:: traits:: query:: evaluate_obligation:: InferCtxtExt ;
3535use rustc_trait_selection:: traits:: query:: method_autoderef:: {
3636 CandidateStep , MethodAutoderefBadTy , MethodAutoderefStepsResult ,
@@ -389,10 +389,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
389389 OP : FnOnce ( ProbeContext < ' _ , ' tcx > ) -> Result < R , MethodError < ' tcx > > ,
390390 {
391391 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) ;
396402
397403 let steps = match mode {
398404 Mode :: MethodCall => self . tcx . method_autoderef_steps ( query_input) ,
@@ -403,8 +409,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
403409 // special handling for this "trivial case" is a good idea.
404410
405411 let infcx = & self . infcx ;
406- let ( ParamEnvAnd { param_env : _, value : self_ty } , var_values) =
412+ let ( ParamEnvAnd { param_env : _, value } , var_values) =
407413 infcx. instantiate_canonical ( span, & query_input. canonical ) ;
414+ let query:: MethodAutoderefSteps { predefined_opaques_in_body : _, self_ty } = value;
408415 debug ! ( ?self_ty, ?query_input, "probe_op: Mode::Path" ) ;
409416 MethodAutoderefStepsResult {
410417 steps : infcx. tcx . arena . alloc_from_iter ( [ CandidateStep {
@@ -553,12 +560,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
553560
554561pub ( crate ) fn method_autoderef_steps < ' tcx > (
555562 tcx : TyCtxt < ' tcx > ,
556- goal : CanonicalTyGoal < ' tcx > ,
563+ goal : CanonicalMethodAutoderefStepsGoal < ' tcx > ,
557564) -> MethodAutoderefStepsResult < ' tcx > {
558565 debug ! ( "method_autoderef_steps({:?})" , goal) ;
559566
560567 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+ }
562590
563591 // If arbitrary self types is not enabled, we follow the chain of
564592 // `Deref<Target=T>`. If arbitrary self types is enabled, we instead
@@ -655,7 +683,8 @@ pub(crate) fn method_autoderef_steps<'tcx>(
655683 } ;
656684
657685 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 ( ) ;
659688 MethodAutoderefStepsResult {
660689 steps : tcx. arena . alloc_from_iter ( steps) ,
661690 opt_bad_ty : opt_bad_ty. map ( |ty| & * tcx. arena . alloc ( ty) ) ,
0 commit comments