Rollup merge of #69967 - mark-i-m:rinfctx, r=matthewjasper
Remove a few `Rc`s from RegionInferenceCtxt fixes https://github.com/rust-lang/rust/issues/55853 r? @matthewjasper
This commit is contained in:
commit
bf6e715fa0
63
src/librustc_data_structures/frozen.rs
Normal file
63
src/librustc_data_structures/frozen.rs
Normal file
@ -0,0 +1,63 @@
|
||||
//! An immutable, owned value (except for interior mutability).
|
||||
//!
|
||||
//! The purpose of `Frozen` is to make a value immutable for the sake of defensive programming. For example,
|
||||
//! suppose we have the following:
|
||||
//!
|
||||
//! ```rust
|
||||
//! struct Bar { /* some data */ }
|
||||
//!
|
||||
//! struct Foo {
|
||||
//! /// Some computed data that should never change after construction.
|
||||
//! pub computed: Bar,
|
||||
//!
|
||||
//! /* some other fields */
|
||||
//! }
|
||||
//!
|
||||
//! impl Bar {
|
||||
//! /// Mutate the `Bar`.
|
||||
//! pub fn mutate(&mut self) { }
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! Now suppose we want to pass around a mutable `Foo` instance but, we want to make sure that
|
||||
//! `computed` does not change accidentally (e.g. somebody might accidentally call
|
||||
//! `foo.computed.mutate()`). This is what `Frozen` is for. We can do the following:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use rustc_data_structures::frozen::Frozen;
|
||||
//!
|
||||
//! struct Foo {
|
||||
//! /// Some computed data that should never change after construction.
|
||||
//! pub computed: Frozen<Bar>,
|
||||
//!
|
||||
//! /* some other fields */
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! `Frozen` impls `Deref`, so we can ergonomically call methods on `Bar`, but it doesn't `impl
|
||||
//! DerefMut`. Now calling `foo.compute.mutate()` will result in a compile-time error stating that
|
||||
//! `mutate` requires a mutable reference but we don't have one.
|
||||
//!
|
||||
//! # Caveats
|
||||
//!
|
||||
//! - `Frozen` doesn't try to defend against interior mutability (e.g. `Frozen<RefCell<Bar>>`).
|
||||
//! - `Frozen` doesn't pin it's contents (e.g. one could still do `foo.computed =
|
||||
//! Frozen::freeze(new_bar)`).
|
||||
|
||||
/// An owned immutable value.
|
||||
#[derive(Debug)]
|
||||
pub struct Frozen<T>(T);
|
||||
|
||||
impl<T> Frozen<T> {
|
||||
pub fn freeze(val: T) -> Self {
|
||||
Frozen(val)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> std::ops::Deref for Frozen<T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &T {
|
||||
&self.0
|
||||
}
|
||||
}
|
@ -94,6 +94,7 @@ pub mod profiling;
|
||||
pub mod vec_linked_list;
|
||||
pub mod work_queue;
|
||||
pub use atomic_ref::AtomicRef;
|
||||
pub mod frozen;
|
||||
|
||||
pub struct OnDrop<F: Fn()>(pub F);
|
||||
|
||||
|
@ -7,6 +7,7 @@ use rustc::mir::{
|
||||
};
|
||||
use rustc::ty::{self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc_data_structures::binary_search_util;
|
||||
use rustc_data_structures::frozen::Frozen;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::graph::scc::Sccs;
|
||||
use rustc_hir::def_id::DefId;
|
||||
@ -54,12 +55,12 @@ pub struct RegionInferenceContext<'tcx> {
|
||||
liveness_constraints: LivenessValues<RegionVid>,
|
||||
|
||||
/// The outlives constraints computed by the type-check.
|
||||
constraints: Rc<OutlivesConstraintSet>,
|
||||
constraints: Frozen<OutlivesConstraintSet>,
|
||||
|
||||
/// The constraint-set, but in graph form, making it easy to traverse
|
||||
/// the constraints adjacent to a particular region. Used to construct
|
||||
/// the SCC (see `constraint_sccs`) and for error reporting.
|
||||
constraint_graph: Rc<NormalConstraintGraph>,
|
||||
constraint_graph: Frozen<NormalConstraintGraph>,
|
||||
|
||||
/// The SCC computed from `constraints` and the constraint
|
||||
/// graph. We have an edge from SCC A to SCC B if `A: B`. Used to
|
||||
@ -112,7 +113,7 @@ pub struct RegionInferenceContext<'tcx> {
|
||||
|
||||
/// Information about how the universally quantified regions in
|
||||
/// scope on this function relate to one another.
|
||||
universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
|
||||
universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
|
||||
}
|
||||
|
||||
/// Each time that `apply_member_constraint` is successful, it appends
|
||||
@ -242,11 +243,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
///
|
||||
/// The `outlives_constraints` and `type_tests` are an initial set
|
||||
/// of constraints produced by the MIR type check.
|
||||
pub(crate) fn new(
|
||||
pub(in crate::borrow_check) fn new(
|
||||
var_infos: VarInfos,
|
||||
universal_regions: Rc<UniversalRegions<'tcx>>,
|
||||
placeholder_indices: Rc<PlaceholderIndices>,
|
||||
universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
|
||||
universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
|
||||
outlives_constraints: OutlivesConstraintSet,
|
||||
member_constraints_in: MemberConstraintSet<'tcx, RegionVid>,
|
||||
closure_bounds_mapping: FxHashMap<
|
||||
@ -263,8 +264,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
.map(|info| RegionDefinition::new(info.universe, info.origin))
|
||||
.collect();
|
||||
|
||||
let constraints = Rc::new(outlives_constraints); // freeze constraints
|
||||
let constraint_graph = Rc::new(constraints.graph(definitions.len()));
|
||||
let constraints = Frozen::freeze(outlives_constraints);
|
||||
let constraint_graph = Frozen::freeze(constraints.graph(definitions.len()));
|
||||
let fr_static = universal_regions.fr_static;
|
||||
let constraint_sccs = Rc::new(constraints.compute_sccs(&constraint_graph, fr_static));
|
||||
|
||||
|
@ -2,6 +2,7 @@ use rustc::mir::ConstraintCategory;
|
||||
use rustc::traits::query::OutlivesBound;
|
||||
use rustc::ty::free_region_map::FreeRegionRelations;
|
||||
use rustc::ty::{self, RegionVid, Ty, TyCtxt};
|
||||
use rustc_data_structures::frozen::Frozen;
|
||||
use rustc_data_structures::transitive_relation::TransitiveRelation;
|
||||
use rustc_infer::infer::canonical::QueryRegionConstraints;
|
||||
use rustc_infer::infer::outlives;
|
||||
@ -53,7 +54,7 @@ type RegionBoundPairs<'tcx> = Vec<(ty::Region<'tcx>, GenericKind<'tcx>)>;
|
||||
type NormalizedInputsAndOutput<'tcx> = Vec<Ty<'tcx>>;
|
||||
|
||||
crate struct CreateResult<'tcx> {
|
||||
crate universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
|
||||
pub(in crate::borrow_check) universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
|
||||
crate region_bound_pairs: RegionBoundPairs<'tcx>,
|
||||
crate normalized_inputs_and_output: NormalizedInputsAndOutput<'tcx>,
|
||||
}
|
||||
@ -298,7 +299,7 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> {
|
||||
}
|
||||
|
||||
CreateResult {
|
||||
universal_region_relations: Rc::new(self.relations),
|
||||
universal_region_relations: Frozen::freeze(self.relations),
|
||||
region_bound_pairs: self.region_bound_pairs,
|
||||
normalized_inputs_and_output,
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ use rustc::ty::{
|
||||
self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, RegionVid, ToPolyTraitRef, Ty,
|
||||
TyCtxt, UserType, UserTypeAnnotationIndex,
|
||||
};
|
||||
use rustc_data_structures::frozen::Frozen;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_errors::struct_span_err;
|
||||
use rustc_hir as hir;
|
||||
@ -830,7 +831,7 @@ struct BorrowCheckContext<'a, 'tcx> {
|
||||
|
||||
crate struct MirTypeckResults<'tcx> {
|
||||
crate constraints: MirTypeckRegionConstraints<'tcx>,
|
||||
crate universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
|
||||
pub(in crate::borrow_check) universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
|
||||
crate opaque_type_values: FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>>,
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user