diff --git a/compiler/rustc_data_structures/src/snapshot_map/mod.rs b/compiler/rustc_data_structures/src/snapshot_map/mod.rs index b4cc85293f7..8a50179cd3b 100644 --- a/compiler/rustc_data_structures/src/snapshot_map/mod.rs +++ b/compiler/rustc_data_structures/src/snapshot_map/mod.rs @@ -13,6 +13,7 @@ mod tests; pub type SnapshotMapStorage = SnapshotMap, ()>; pub type SnapshotMapRef<'a, K, V, L> = SnapshotMap, &'a mut L>; +#[derive(Clone)] pub struct SnapshotMap, L = VecLog>> { map: M, undo_log: L, @@ -30,6 +31,7 @@ where } } +#[derive(Clone)] pub enum UndoLog { Inserted(K), Overwrite(K, V), diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index c26ea4c9669..63871d428e1 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -51,6 +51,29 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ) -> At<'a, 'tcx> { At { infcx: self, cause, param_env } } + + /// Forks the inference context, creating a new inference context with the same inference + /// variables in the same state. This can be used to "branch off" many tests from the same + /// common state. Used in coherence. + pub fn fork(&self) -> Self { + Self { + tcx: self.tcx.clone(), + defining_use_anchor: self.defining_use_anchor.clone(), + reveal_defining_opaque_types: self.reveal_defining_opaque_types, + in_progress_typeck_results: self.in_progress_typeck_results.clone(), + inner: self.inner.clone(), + skip_leak_check: self.skip_leak_check.clone(), + lexical_region_resolutions: self.lexical_region_resolutions.clone(), + selection_cache: self.selection_cache.clone(), + evaluation_cache: self.evaluation_cache.clone(), + reported_trait_errors: self.reported_trait_errors.clone(), + reported_closure_mismatch: self.reported_closure_mismatch.clone(), + tainted_by_errors_flag: self.tainted_by_errors_flag.clone(), + err_count_on_creation: self.err_count_on_creation, + in_snapshot: self.in_snapshot.clone(), + universe: self.universe.clone(), + } + } } pub trait ToTrace<'tcx>: Relate<'tcx> + Copy { diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs index a5ec84a4f14..f5e61d28ac5 100644 --- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs +++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs @@ -61,6 +61,7 @@ pub(crate) fn resolve<'tcx>( /// Contains the result of lexical region resolution. Offers methods /// to lookup up the final value of a region variable. +#[derive(Clone)] pub struct LexicalRegionResolutions<'tcx> { values: IndexVec>, error_region: ty::Region<'tcx>, diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index c18d36d1f74..be38ace3bd2 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -130,6 +130,7 @@ impl RegionckMode { /// `RefCell` and are involved with taking/rolling back snapshots. Snapshot /// operations are hot enough that we want only one call to `borrow_mut` per /// call to `start_snapshot` and `rollback_to`. +#[derive(Clone)] pub struct InferCtxtInner<'tcx> { /// Cache for projections. This cache is snapshotted along with the infcx. /// diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index 29775a96685..078575b5377 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -28,7 +28,7 @@ mod leak_check; pub use rustc_middle::infer::MemberConstraint; -#[derive(Default)] +#[derive(Clone, Default)] pub struct RegionConstraintStorage<'tcx> { /// For each `RegionVid`, the corresponding `RegionVariableOrigin`. var_infos: IndexVec, diff --git a/compiler/rustc_infer/src/infer/type_variable.rs b/compiler/rustc_infer/src/infer/type_variable.rs index 82970f214fa..d320728a43f 100644 --- a/compiler/rustc_infer/src/infer/type_variable.rs +++ b/compiler/rustc_infer/src/infer/type_variable.rs @@ -14,6 +14,7 @@ use std::ops::Range; use rustc_data_structures::undo_log::{Rollback, UndoLogs}; /// Represents a single undo-able action that affects a type inference variable. +#[derive(Clone)] pub(crate) enum UndoLog<'tcx> { EqRelation(sv::UndoLog>>), SubRelation(sv::UndoLog>), @@ -58,6 +59,7 @@ impl<'tcx> Rollback> for TypeVariableStorage<'tcx> { } } +#[derive(Clone)] pub struct TypeVariableStorage<'tcx> { values: sv::SnapshotVecStorage, @@ -137,6 +139,7 @@ pub enum TypeVariableOriginKind { LatticeVariable, } +#[derive(Clone)] pub(crate) struct TypeVariableData { origin: TypeVariableOrigin, } @@ -165,6 +168,7 @@ impl<'tcx> TypeVariableValue<'tcx> { } } +#[derive(Clone)] pub(crate) struct Instantiate; pub(crate) struct Delegate; diff --git a/compiler/rustc_infer/src/infer/undo_log.rs b/compiler/rustc_infer/src/infer/undo_log.rs index 89db8f464b4..ecd886b5478 100644 --- a/compiler/rustc_infer/src/infer/undo_log.rs +++ b/compiler/rustc_infer/src/infer/undo_log.rs @@ -17,6 +17,7 @@ pub struct Snapshot<'tcx> { } /// Records the "undo" data for a single operation that affects some form of inference variable. +#[derive(Clone)] pub(crate) enum UndoLog<'tcx> { TypeVariables(type_variable::UndoLog<'tcx>), ConstUnificationTable(sv::UndoLog>>), @@ -84,6 +85,7 @@ impl<'tcx> Rollback> for InferCtxtInner<'tcx> { /// The combined undo log for all the various unification tables. For each change to the storage /// for any kind of inference variable, we record an UndoLog entry in the vector here. +#[derive(Clone)] pub(crate) struct InferCtxtUndoLogs<'tcx> { logs: Vec>, num_open_snapshots: usize, diff --git a/compiler/rustc_infer/src/traits/project.rs b/compiler/rustc_infer/src/traits/project.rs index a1a1168a21d..b84ed3dc689 100644 --- a/compiler/rustc_infer/src/traits/project.rs +++ b/compiler/rustc_infer/src/traits/project.rs @@ -70,7 +70,7 @@ pub struct ProjectionCache<'a, 'tcx> { undo_log: &'a mut InferCtxtUndoLogs<'tcx>, } -#[derive(Default)] +#[derive(Clone, Default)] pub struct ProjectionCacheStorage<'tcx> { map: SnapshotMapStorage, ProjectionCacheEntry<'tcx>>, } diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 8ee578b77dc..7dd01f5b0b0 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -379,7 +379,7 @@ fn negative_impl_exists<'cx, 'tcx>( region_context: DefId, o: &PredicateObligation<'tcx>, ) -> bool { - let infcx = selcx.infcx().clone(); + let infcx = &selcx.infcx().fork(); let tcx = infcx.tcx; o.flip_polarity(tcx) .map(|o| {