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:
Dylan DPC 2020-03-15 02:44:18 +01:00 committed by GitHub
commit bf6e715fa0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 77 additions and 10 deletions

View 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
}
}

View File

@ -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);

View File

@ -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));

View File

@ -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,
}

View File

@ -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>>,
}