about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorDylan DPC <dylan.dpc@gmail.com>2020-03-15 02:44:18 +0100
committerGitHub <noreply@github.com>2020-03-15 02:44:18 +0100
commitbf6e715fa00d63f366cd8d587000aa6185cea041 (patch)
treee48f494b5b52f6770b04c474625601775d682565 /src
parentf40272ca6f9cba29632406efde371dc5c9751fe9 (diff)
parenta58b17f2b5e57baa45ffb5b8c979faa3191bc05a (diff)
downloadrust-bf6e715fa00d63f366cd8d587000aa6185cea041.tar.gz
rust-bf6e715fa00d63f366cd8d587000aa6185cea041.zip
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
Diffstat (limited to 'src')
-rw-r--r--src/librustc_data_structures/frozen.rs63
-rw-r--r--src/librustc_data_structures/lib.rs1
-rw-r--r--src/librustc_mir/borrow_check/region_infer/mod.rs15
-rw-r--r--src/librustc_mir/borrow_check/type_check/free_region_relations.rs5
-rw-r--r--src/librustc_mir/borrow_check/type_check/mod.rs3
5 files changed, 77 insertions, 10 deletions
diff --git a/src/librustc_data_structures/frozen.rs b/src/librustc_data_structures/frozen.rs
new file mode 100644
index 00000000000..2daf5b04141
--- /dev/null
+++ b/src/librustc_data_structures/frozen.rs
@@ -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
+    }
+}
diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs
index 13792a0c890..f9f8ff5303e 100644
--- a/src/librustc_data_structures/lib.rs
+++ b/src/librustc_data_structures/lib.rs
@@ -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);
 
diff --git a/src/librustc_mir/borrow_check/region_infer/mod.rs b/src/librustc_mir/borrow_check/region_infer/mod.rs
index 144f655420b..fe96b3e34a2 100644
--- a/src/librustc_mir/borrow_check/region_infer/mod.rs
+++ b/src/librustc_mir/borrow_check/region_infer/mod.rs
@@ -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));
 
diff --git a/src/librustc_mir/borrow_check/type_check/free_region_relations.rs b/src/librustc_mir/borrow_check/type_check/free_region_relations.rs
index c17db926946..86951f93f0e 100644
--- a/src/librustc_mir/borrow_check/type_check/free_region_relations.rs
+++ b/src/librustc_mir/borrow_check/type_check/free_region_relations.rs
@@ -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,
         }
diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs
index 351b30bab61..d98abc57bfd 100644
--- a/src/librustc_mir/borrow_check/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/type_check/mod.rs
@@ -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>>,
 }