diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 9f6175eac1350..df8fb5f7a3cad 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -1058,7 +1058,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let coerce = Coerce::new(self, cause, AllowTwoPhase::No); coerce .autoderef(rustc_span::DUMMY_SP, expr_ty) - .find_map(|(ty, steps)| self.probe(|_| coerce.unify(ty, target)).ok().map(|_| steps)) + .find_map(|(ty, steps)| self.probe(|_| coerce.unify(ty, target).ok().map(|_| steps))) } /// Given a type, this function will calculate and return the type given diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index ad4546c09b546..13e4c8380efde 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -163,7 +163,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if fn_sig.has_escaping_bound_vars() { return fn_sig; } - self.probe(|_| { + // We only return the normalized `fn_sig` if it does not contain infer vars. + self.probe_unchecked(|_| { let ocx = ObligationCtxt::new(self); let normalized_fn_sig = ocx.normalize(&ObligationCause::dummy(), self.param_env, fn_sig); diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index f8d0911a2eb69..2f8ce89eea51d 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -15,7 +15,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder, SubdiagnosticMessage}; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Namespace}; use rustc_hir::def_id::DefId; -use rustc_infer::infer::{self, InferOk}; +use rustc_infer::infer::{self, InferCtxt, InferOk, PlugSnapshotLeaks}; use rustc_middle::query::Providers; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{self, GenericParamDefKind, Ty, TypeVisitableExt}; @@ -67,6 +67,13 @@ pub enum MethodError<'tcx> { BadReturnType, } +impl<'tcx> PlugSnapshotLeaks<'tcx> for MethodError<'tcx> { + fn plug_leaks(self, infcx: &InferCtxt<'tcx>) -> Self { + // TODO + self + } +} + // Contains a list of static methods that may apply, a list of unsatisfied trait predicates which // could lead to matches if satisfied, and a list of not-in-scope traits which may work. #[derive(Debug)] @@ -86,6 +93,11 @@ pub enum CandidateSource { Impl(DefId), Trait(DefId /* trait id */), } +impl<'tcx> PlugSnapshotLeaks<'tcx> for CandidateSource { + fn plug_leaks(self, _: &InferCtxt<'tcx>) -> Self { + self + } +} impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Determines whether the type `self_ty` supports a visible method named `method_name` or not. diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index d7edc70bce82e..12c7ee5ea8c3b 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -14,12 +14,15 @@ use rustc_infer::infer::canonical::OriginalQueryValues; use rustc_infer::infer::canonical::{Canonical, QueryResponse}; use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282; use rustc_infer::infer::DefineOpaqueTypes; +use rustc_infer::infer::InferCtxt; +use rustc_infer::infer::PlugSnapshotLeaks; use rustc_infer::infer::{self, InferOk, TyCtxtInferExt}; use rustc_middle::middle::stability; use rustc_middle::query::Providers; use rustc_middle::ty::fast_reject::{simplify_type, TreatParams}; use rustc_middle::ty::AssocItem; use rustc_middle::ty::GenericParamDefKind; +use rustc_middle::ty::PolySubtypePredicate; use rustc_middle::ty::ToPredicate; use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_middle::ty::{GenericArgs, GenericArgsRef}; @@ -136,6 +139,12 @@ pub(crate) struct Candidate<'tcx> { pub(crate) kind: CandidateKind<'tcx>, pub(crate) import_ids: SmallVec<[LocalDefId; 1]>, } +impl<'tcx> PlugSnapshotLeaks<'tcx> for Candidate<'tcx> { + fn plug_leaks(self, _: &InferCtxt<'tcx>) -> Self { + // TODO + self + } +} #[derive(Debug, Clone)] pub(crate) enum CandidateKind<'tcx> { @@ -158,6 +167,11 @@ enum ProbeResult { BadReturnType, Match, } +impl<'tcx> PlugSnapshotLeaks<'tcx> for ProbeResult { + fn plug_leaks(self, _: &infer::InferCtxt<'tcx>) -> Self { + self + } +} /// When adjusting a receiver we often want to do one of /// @@ -216,6 +230,13 @@ pub struct Pick<'tcx> { unstable_candidates: Vec<(Candidate<'tcx>, Symbol)>, } +impl<'tcx> PlugSnapshotLeaks<'tcx> for Pick<'tcx> { + fn plug_leaks(self, _: &infer::InferCtxt<'tcx>) -> Self { + // TODO + self + } +} + #[derive(Clone, Debug, PartialEq, Eq)] pub enum PickKind<'tcx> { InherentImplPick, @@ -355,7 +376,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .unwrap() } - fn probe_op( + fn probe_op>( &'a self, span: Span, mode: Mode, diff --git a/compiler/rustc_infer/src/infer/fudge.rs b/compiler/rustc_infer/src/infer/fudge.rs index 99033922bdf76..5c7379816ade4 100644 --- a/compiler/rustc_infer/src/infer/fudge.rs +++ b/compiler/rustc_infer/src/infer/fudge.rs @@ -109,7 +109,7 @@ impl<'tcx> InferCtxt<'tcx> { T: TypeFoldable>, { let variable_lengths = self.variable_lengths(); - let (mut fudger, value) = self.probe(|_| { + let (mut fudger, value) = self.probe_unchecked(|_| { match f() { Ok(value) => { let value = self.resolve_vars_if_possible(value); diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 243558b11a863..53213acc3727c 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1,6 +1,8 @@ pub use self::at::DefineOpaqueTypes; pub use self::freshen::TypeFreshener; pub use self::lexical_region_resolve::RegionResolutionError; +use self::opaque_types::OpaqueTypeStorage; +pub(crate) use self::undo_log::{InferCtxtUndoLogs, Snapshot, UndoLog}; pub use self::BoundRegionConversionTime::*; pub use self::RegionVariableOrigin::*; pub use self::SubregionOrigin::*; @@ -10,9 +12,7 @@ use rustc_data_structures::captures::Captures; use rustc_data_structures::undo_log::UndoLogs; use rustc_middle::infer::unify_key::EffectVarValue; use rustc_middle::infer::unify_key::{ConstVidKey, EffectVidKey}; - -use self::opaque_types::OpaqueTypeStorage; -pub(crate) use self::undo_log::{InferCtxtUndoLogs, Snapshot, UndoLog}; +use rustc_middle::ty::TypeVisitable; use crate::traits::{ self, ObligationCause, ObligationInspector, PredicateObligations, TraitEngine, TraitEngineExt, @@ -45,6 +45,7 @@ use rustc_span::Span; use std::cell::{Cell, RefCell}; use std::fmt; +use std::ops::ControlFlow; use self::error_reporting::TypeErrCtxt; use self::free_regions::RegionRelations; @@ -890,24 +891,34 @@ impl<'tcx> InferCtxt<'tcx> { pub fn commit_if_ok(&self, f: F) -> Result where F: FnOnce(&CombinedSnapshot<'tcx>) -> Result, + E: PlugSnapshotLeaks<'tcx>, { let snapshot = self.start_snapshot(); let r = f(&snapshot); debug!("commit_if_ok() -- r.is_ok() = {}", r.is_ok()); match r { - Ok(_) => { + Ok(value) => { self.commit_from(snapshot); + Some(value) } - Err(_) => { + Err(e) => { self.rollback_to(snapshot); + Err(e.plug_leaks(self)) } } - r } /// Execute `f` then unroll any bindings it creates. #[instrument(skip(self, f), level = "debug")] - pub fn probe(&self, f: F) -> R + pub fn probe, F>(&self, f: F) -> R + where + F: FnOnce(&CombinedSnapshot<'tcx>) -> R, + { + let r = self.probe_unchecked(f); + r.plug_leaks(self) + } + + pub fn probe_unchecked(&self, f: F) -> R where F: FnOnce(&CombinedSnapshot<'tcx>) -> R, { @@ -2134,3 +2145,129 @@ fn replace_param_and_infer_args_with_placeholder<'tcx>( args.fold_with(&mut ReplaceParamAndInferWithPlaceholder { tcx, idx: 0 }) } + +pub trait PlugSnapshotLeaks<'tcx> { + fn plug_leaks(self, infcx: &InferCtxt<'tcx>) -> Self; +} + +macro_rules! noop_plug_leaks { + (<$tcx:lifetime> $($ty:ty),*$(,)?) => { + $( + impl<$tcx> PlugSnapshotLeaks<$tcx> for $ty { + fn plug_leaks(self, _: &InferCtxt<$tcx>) -> Self { + self + } + } + )* + }; +} + +noop_plug_leaks!(<'tcx> + !, + (), + bool, + usize, + DefId, + rustc_middle::ty::AssocItem, + rustc_middle::traits::query::NoSolution, + rustc_middle::traits::solve::Certainty, + rustc_middle::traits::EvaluationResult, + rustc_middle::traits::BuiltinImplSource, + rustc_middle::traits::query::MethodAutoderefStepsResult<'tcx>, + rustc_span::symbol::Ident, + ErrorGuaranteed, + rustc_middle::traits::OverflowError, +); + +impl<'tcx, T: PlugSnapshotLeaks<'tcx>> PlugSnapshotLeaks<'tcx> for Option { + fn plug_leaks(self, infcx: &InferCtxt<'tcx>) -> Self { + self.map(|v| v.plug_leaks(infcx)) + } +} + +impl<'tcx, T0, T1> PlugSnapshotLeaks<'tcx> for (T0, T1) +where + T0: PlugSnapshotLeaks<'tcx>, + T1: PlugSnapshotLeaks<'tcx>, +{ + fn plug_leaks(self, infcx: &InferCtxt<'tcx>) -> Self { + (self.0.plug_leaks(infcx), self.1.plug_leaks(infcx)) + } +} + +impl<'tcx, V: TypeVisitable>> PlugSnapshotLeaks<'tcx> for Canonical<'tcx, V> { + fn plug_leaks(self, _: &InferCtxt<'tcx>) -> Self { + debug_assert!(!self.has_infer() && !self.has_placeholders()); + self + } +} + +impl<'tcx, T, E> PlugSnapshotLeaks<'tcx> for Result +where + T: PlugSnapshotLeaks<'tcx>, + E: PlugSnapshotLeaks<'tcx>, +{ + fn plug_leaks(self, infcx: &InferCtxt<'tcx>) -> Self { + match self { + Ok(v) => Ok(v.plug_leaks(infcx)), + Err(e) => Err(e.plug_leaks(infcx)), + } + } +} + +impl<'tcx, T, E> PlugSnapshotLeaks<'tcx> for ControlFlow +where + T: PlugSnapshotLeaks<'tcx>, + E: PlugSnapshotLeaks<'tcx>, +{ + fn plug_leaks(self, infcx: &InferCtxt<'tcx>) -> Self { + match self { + ControlFlow::Continue(c) => ControlFlow::Continue(c.plug_leaks(infcx)), + ControlFlow::Break(b) => ControlFlow::Break(b.plug_leaks(infcx)), + } + } +} + +impl<'tcx, T: PlugSnapshotLeaks<'tcx>> PlugSnapshotLeaks<'tcx> for Vec { + fn plug_leaks(self, infcx: &InferCtxt<'tcx>) -> Self { + self.into_iter().map(|e| e.plug_leaks(infcx)).collect() + } +} + +impl<'tcx> PlugSnapshotLeaks<'tcx> for TypeError<'tcx> { + fn plug_leaks(self, _: &InferCtxt<'tcx>) -> Self { + match self { + TypeError::Mismatch + | TypeError::ConstnessMismatch(_) + | TypeError::PolarityMismatch(_) + | TypeError::UnsafetyMismatch(_) + | TypeError::AbiMismatch(_) + | TypeError::Mutability + | TypeError::ArgumentMutability(_) + | TypeError::TupleSize(_) + | TypeError::FixedArraySize(_) + | TypeError::ArgCount + | TypeError::FieldMisMatch(_, _) + | TypeError::RegionsPlaceholderMismatch + | TypeError::IntMismatch(_) + | TypeError::FloatMismatch(_) + | TypeError::Traits(_) + | TypeError::VariadicMismatch(_) + | TypeError::ProjectionMismatched(_) + | TypeError::IntrinsicCast + | TypeError::TargetFeatureCast(_) => { + debug_assert!(!self.has_infer() && !self.has_placeholders()); + self + } + + TypeError::RegionsDoesNotOutlive(_, _) + | TypeError::RegionsInsufficientlyPolymorphic(_, _) + | TypeError::Sorts(_) + | TypeError::ArgumentSorts(_, _) + | TypeError::CyclicTy(_) + | TypeError::CyclicConst(_) + | TypeError::ExistentialMismatch(_) + | TypeError::ConstMismatch(_) => TypeError::Mismatch, + } + } +} diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index 97f9a4b291d09..8d4ede966c696 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -23,6 +23,7 @@ #![feature(extend_one)] #![feature(let_chains)] #![feature(if_let_guard)] +#![feature(never_type)] #![feature(iterator_try_collect)] #![cfg_attr(bootstrap, feature(min_specialization))] #![feature(try_blocks)] diff --git a/compiler/rustc_infer/src/traits/project.rs b/compiler/rustc_infer/src/traits/project.rs index afba2e50a23c5..8fd729ce67f14 100644 --- a/compiler/rustc_infer/src/traits/project.rs +++ b/compiler/rustc_infer/src/traits/project.rs @@ -2,7 +2,7 @@ use super::PredicateObligation; -use crate::infer::InferCtxtUndoLogs; +use crate::infer::{InferCtxt, InferCtxtUndoLogs, PlugSnapshotLeaks}; use rustc_data_structures::{ snapshot_map::{self, SnapshotMapRef, SnapshotMapStorage}, @@ -19,6 +19,11 @@ pub(crate) type UndoLog<'tcx> = pub struct MismatchedProjectionTypes<'tcx> { pub err: ty::error::TypeError<'tcx>, } +impl<'tcx> PlugSnapshotLeaks<'tcx> for MismatchedProjectionTypes<'tcx> { + fn plug_leaks(self, infcx: &InferCtxt<'tcx>) -> Self { + MismatchedProjectionTypes { err: self.err.plug_leaks(infcx) } + } +} #[derive(Clone)] pub struct Normalized<'tcx, T> { diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index f694dd0070363..d9884f3084ef3 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -86,22 +86,20 @@ impl<'tcx> InferCtxt<'tcx> { ty: Ty<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> Option>> { - self.probe(|_snapshot| { - let mut selcx = SelectionContext::new(self); - match selcx.select(&Obligation::new( - self.tcx, - ObligationCause::dummy(), - param_env, - ty::TraitRef::new(self.tcx, trait_def_id, [ty]), - )) { - Ok(Some(selection)) => { - let mut fulfill_cx = >::new(self); - fulfill_cx.register_predicate_obligations(self, selection.nested_obligations()); - Some(fulfill_cx.select_all_or_error(self)) - } - Ok(None) | Err(_) => None, + let mut selcx = SelectionContext::new(self); + match selcx.select(&Obligation::new( + self.tcx, + ObligationCause::dummy(), + param_env, + ty::TraitRef::new(self.tcx, trait_def_id, [ty]), + )) { + Ok(Some(selection)) => { + let mut fulfill_cx = >::new(self); + fulfill_cx.register_predicate_obligations(self, selection.nested_obligations()); + Some(fulfill_cx.select_all_or_error(self)) } - }) + Ok(None) | Err(_) => None, + } } } diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs index 91fd48807a4d8..70c025b18878f 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs @@ -1,6 +1,7 @@ use crate::solve::assembly::Candidate; use super::EvalCtxt; +use rustc_infer::infer::PlugSnapshotLeaks; use rustc_middle::traits::{ query::NoSolution, solve::{inspect, CandidateSource, QueryResult}, @@ -17,7 +18,10 @@ impl<'tcx, F, T> ProbeCtxt<'_, '_, 'tcx, F, T> where F: FnOnce(&T) -> inspect::ProbeKind<'tcx>, { - pub(in crate::solve) fn enter(self, f: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> T) -> T { + pub(in crate::solve) fn enter(self, f: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> T) -> T + where + T: PlugSnapshotLeaks<'tcx>, + { let ProbeCtxt { ecx: outer_ecx, probe_kind, _result } = self; let mut nested_ecx = EvalCtxt { diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 63555a305d855..f28033fc8808b 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -75,25 +75,25 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { self.obligations .drain(..) .map(|obligation| { - let code = infcx.probe(|_| { - match infcx + let code = match infcx.probe(|_| { + infcx .evaluate_root_goal(obligation.clone().into(), GenerateProofTree::IfEnabled) .0 - { - Ok((_, Certainty::Maybe(MaybeCause::Ambiguity), _)) => { - FulfillmentErrorCode::Ambiguity { overflow: false } - } - Ok((_, Certainty::Maybe(MaybeCause::Overflow), _)) => { - FulfillmentErrorCode::Ambiguity { overflow: true } - } - Ok((_, Certainty::Yes, _)) => { - bug!("did not expect successful goal when collecting ambiguity errors") - } - Err(_) => { - bug!("did not expect selection error when collecting ambiguity errors") - } + .map(|(_, cert, _)| cert) + }) { + Ok(Certainty::Maybe(MaybeCause::Ambiguity)) => { + FulfillmentErrorCode::Ambiguity { overflow: false } } - }); + Ok(Certainty::Maybe(MaybeCause::Overflow)) => { + FulfillmentErrorCode::Ambiguity { overflow: true } + } + Ok(Certainty::Yes) => { + bug!("did not expect successful goal when collecting ambiguity errors") + } + Err(_) => { + bug!("did not expect selection error when collecting ambiguity errors") + } + }; FulfillmentError { obligation: obligation.clone(), diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index c5d4ce33d8617..ae59a8bcaac76 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -10,7 +10,7 @@ /// as is until we start using it for something else. use std::ops::ControlFlow; -use rustc_infer::infer::InferCtxt; +use rustc_infer::infer::{InferCtxt, PlugSnapshotLeaks}; use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::solve::{inspect, QueryResult}; use rustc_middle::traits::solve::{Certainty, Goal}; @@ -211,7 +211,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { /// The public API to interact with proof trees. pub trait ProofTreeVisitor<'tcx> { - type BreakTy; + type BreakTy: PlugSnapshotLeaks<'tcx>; fn visit_goal(&mut self, goal: &InspectGoal<'_, 'tcx>) -> ControlFlow; } diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 39f4ceda9f17a..d8aea988604c0 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -893,7 +893,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty: Ty<'tcx>, param_env: ty::ParamEnv<'tcx>, cause: &ObligationCause<'tcx>, - ) -> Option> { + ) -> Option { let tcx = self.tcx(); if tcx.features().trait_upcasting { return None; @@ -922,7 +922,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .ty() .unwrap(); - if let ty::Dynamic(data, ..) = ty.kind() { data.principal() } else { None } + if let ty::Dynamic(data, ..) = ty.kind() { data.principal_def_id() } else { None } }) } @@ -993,12 +993,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let principal_a = a_data.principal().unwrap(); let target_trait_did = principal_def_id_b.unwrap(); let source_trait_ref = principal_a.with_self_ty(self.tcx(), source); - if let Some(deref_trait_ref) = self.need_migrate_deref_output_trait_object( + if let Some(principal_def_id) = self.need_migrate_deref_output_trait_object( source, obligation.param_env, &obligation.cause, ) { - if deref_trait_ref.def_id() == target_trait_did { + if principal_def_id == target_trait_did { return; } } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 1146f869fc16d..2a81dac2c1a7b 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -34,6 +34,7 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_infer::infer::BoundRegionConversionTime; use rustc_infer::infer::DefineOpaqueTypes; +use rustc_infer::infer::PlugSnapshotLeaks; use rustc_infer::traits::TraitObligation; use rustc_middle::dep_graph::dep_kinds; use rustc_middle::dep_graph::DepNodeIndex; @@ -3084,6 +3085,11 @@ pub enum ProjectionMatchesProjection { Ambiguous, No, } +impl PlugSnapshotLeaks<'_> for ProjectionMatchesProjection { + fn plug_leaks(self, _: &InferCtxt<'_>) -> Self { + self + } +} /// Replace all regions inside the coroutine interior with late bound regions. /// Note that each region slot in the types gets a new fresh late bound region, which means that