]> git.lizzy.rs Git - rust.git/commitdiff
rename "free region" to "universally quantified region"
authorNiko Matsakis <niko@alum.mit.edu>
Tue, 21 Nov 2017 18:12:24 +0000 (13:12 -0500)
committerNiko Matsakis <niko@alum.mit.edu>
Mon, 4 Dec 2017 14:14:38 +0000 (09:14 -0500)
This has been bugging me. All the regions appear free in the source;
the real difference is that some of them are universally quantified
(those in the function signature) and some are existentially
quantified (those for which we are inferring values).

src/librustc_mir/borrow_check/nll/free_regions.rs [deleted file]
src/librustc_mir/borrow_check/nll/mod.rs
src/librustc_mir/borrow_check/nll/region_infer/mod.rs
src/librustc_mir/borrow_check/nll/renumber.rs
src/librustc_mir/borrow_check/nll/subtype_constraint_generation.rs
src/librustc_mir/borrow_check/nll/universal_regions.rs [new file with mode: 0644]

diff --git a/src/librustc_mir/borrow_check/nll/free_regions.rs b/src/librustc_mir/borrow_check/nll/free_regions.rs
deleted file mode 100644 (file)
index 7f984c7..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Code to extract the free regions declared on a function and the
-//! relationships between them. For example:
-//!
-//! ```
-//! fn foo<'a, 'b, 'c: 'b>() { }
-//! ```
-//!
-//! here we would be returning a map assigning each of `{'a, 'b, 'c}`
-//! to an index, as well as the `FreeRegionMap` which can compute
-//! relationships between them.
-//!
-//! The code in this file doesn't *do anything* with those results; it
-//! just returns them for other code to use.
-
-use rustc::hir::def_id::DefId;
-use rustc::infer::InferCtxt;
-use rustc::infer::outlives::free_region_map::FreeRegionMap;
-use rustc::ty::{self, RegionVid};
-use rustc::ty::subst::Substs;
-use rustc::util::nodemap::FxHashMap;
-use rustc_data_structures::indexed_vec::Idx;
-
-#[derive(Debug)]
-pub struct FreeRegions<'tcx> {
-    /// Given a free region defined on this function (either early- or
-    /// late-bound), this maps it to its internal region index. When
-    /// the region context is created, the first N variables will be
-    /// created based on these indices.
-    pub indices: FxHashMap<ty::Region<'tcx>, RegionVid>,
-
-    /// The map from the typeck tables telling us how to relate free regions.
-    pub free_region_map: &'tcx FreeRegionMap<'tcx>,
-}
-
-pub fn free_regions<'a, 'gcx, 'tcx>(
-    infcx: &InferCtxt<'a, 'gcx, 'tcx>,
-    item_def_id: DefId,
-) -> FreeRegions<'tcx> {
-    debug!("free_regions(item_def_id={:?})", item_def_id);
-
-    let mut indices = FxHashMap();
-
-    // `'static` is always free.
-    insert_free_region(&mut indices, infcx.tcx.types.re_static);
-
-    // Extract the early regions.
-    let item_substs = Substs::identity_for_item(infcx.tcx, item_def_id);
-    for item_subst in item_substs {
-        if let Some(region) = item_subst.as_region() {
-            insert_free_region(&mut indices, region);
-        }
-    }
-
-    // Extract the late-bound regions. Use the liberated fn sigs,
-    // where the late-bound regions will have been converted into free
-    // regions, and add them to the map.
-    let item_id = infcx.tcx.hir.as_local_node_id(item_def_id).unwrap();
-    let fn_hir_id = infcx.tcx.hir.node_to_hir_id(item_id);
-    let tables = infcx.tcx.typeck_tables_of(item_def_id);
-    let fn_sig = tables.liberated_fn_sigs()[fn_hir_id].clone();
-    infcx
-        .tcx
-        .for_each_free_region(&fn_sig.inputs_and_output, |region| {
-            if let ty::ReFree(_) = *region {
-                insert_free_region(&mut indices, region);
-            }
-        });
-
-    debug!("free_regions: indices={:#?}", indices);
-
-    FreeRegions { indices, free_region_map: &tables.free_region_map }
-}
-
-fn insert_free_region<'tcx>(
-    free_regions: &mut FxHashMap<ty::Region<'tcx>, RegionVid>,
-    region: ty::Region<'tcx>,
-) {
-    let next = RegionVid::new(free_regions.len());
-    free_regions.entry(region).or_insert(next);
-}
index a04cc113e723d749ca28f9e853d518410bbc3945..804f5e2687597521cddac9ea77566c12ce8d4aae 100644 (file)
@@ -26,8 +26,8 @@
 
 mod constraint_generation;
 mod subtype_constraint_generation;
-mod free_regions;
-use self::free_regions::FreeRegions;
+mod universal_regions;
+use self::universal_regions::UniversalRegions;
 
 pub(crate) mod region_infer;
 use self::region_infer::RegionInferenceContext;
@@ -42,14 +42,14 @@ pub(in borrow_check) fn replace_regions_in_mir<'cx, 'gcx, 'tcx>(
     infcx: &InferCtxt<'cx, 'gcx, 'tcx>,
     def_id: DefId,
     mir: &mut Mir<'tcx>,
-) -> FreeRegions<'tcx> {
+) -> UniversalRegions<'tcx> {
     // Compute named region information.
-    let free_regions = free_regions::free_regions(infcx, def_id);
+    let universal_regions = universal_regions::universal_regions(infcx, def_id);
 
     // Replace all regions with fresh inference variables.
-    renumber::renumber_mir(infcx, &free_regions, mir);
+    renumber::renumber_mir(infcx, &universal_regions, mir);
 
-    free_regions
+    universal_regions
 }
 
 /// Computes the (non-lexical) regions from the input MIR.
@@ -58,7 +58,7 @@ pub(in borrow_check) fn replace_regions_in_mir<'cx, 'gcx, 'tcx>(
 pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
     infcx: &InferCtxt<'cx, 'gcx, 'tcx>,
     def_id: DefId,
-    free_regions: FreeRegions<'tcx>,
+    universal_regions: UniversalRegions<'tcx>,
     mir: &Mir<'tcx>,
     param_env: ty::ParamEnv<'gcx>,
     flow_inits: &mut FlowInProgress<MaybeInitializedLvals<'cx, 'gcx, 'tcx>>,
@@ -71,8 +71,13 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
     // Create the region inference context, taking ownership of the region inference
     // data that was contained in `infcx`.
     let var_origins = infcx.take_region_var_origins();
-    let mut regioncx = RegionInferenceContext::new(var_origins, &free_regions, mir);
-    subtype_constraint_generation::generate(&mut regioncx, &free_regions, mir, constraint_sets);
+    let mut regioncx = RegionInferenceContext::new(var_origins, &universal_regions, mir);
+    subtype_constraint_generation::generate(
+        &mut regioncx,
+        &universal_regions,
+        mir,
+        constraint_sets,
+    );
 
     // Compute what is live where.
     let liveness = &LivenessResults {
@@ -178,8 +183,7 @@ fn dump_mir_results<'a, 'gcx, 'tcx>(
                 writeln!(out, "            | Live variables at {:?}: {}", location, s)?;
             }
 
-            PassWhere::AfterLocation(_) |
-            PassWhere::AfterCFG => {}
+            PassWhere::AfterLocation(_) | PassWhere::AfterCFG => {}
         }
         Ok(())
     });
index b304ea4f7149a1074b0f3ac5f46f8d2f341b8607..26561329ae92420c7073938392620ff3994ad8b3 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use super::free_regions::FreeRegions;
+use super::universal_regions::UniversalRegions;
 use rustc::infer::InferCtxt;
 use rustc::infer::RegionVariableOrigin;
 use rustc::infer::NLLRegionVariableOrigin;
@@ -33,8 +33,8 @@ pub struct RegionInferenceContext<'tcx> {
 
     /// The liveness constraints added to each region. For most
     /// regions, these start out empty and steadily grow, though for
-    /// each free region R they start out containing the entire CFG
-    /// and `end(R)`.
+    /// each universally quantified region R they start out containing
+    /// the entire CFG and `end(R)`.
     ///
     /// In this `BitMatrix` representation, the rows are the region
     /// variables and the columns are the free regions and MIR locations.
@@ -52,7 +52,10 @@ pub struct RegionInferenceContext<'tcx> {
     /// the free regions.)
     point_indices: BTreeMap<Location, usize>,
 
-    num_free_regions: usize,
+    /// Number of universally quantified regions. This is used to
+    /// determine the meaning of the bits in `inferred_values` and
+    /// friends.
+    num_universal_regions: usize,
 
     free_region_map: &'tcx FreeRegionMap<'tcx>,
 }
@@ -92,10 +95,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// Creates a new region inference context with a total of
     /// `num_region_variables` valid inference variables; the first N
     /// of those will be constant regions representing the free
-    /// regions defined in `free_regions`.
-    pub fn new(var_origins: VarOrigins, free_regions: &FreeRegions<'tcx>, mir: &Mir<'tcx>) -> Self {
+    /// regions defined in `universal_regions`.
+    pub fn new(
+        var_origins: VarOrigins,
+        universal_regions: &UniversalRegions<'tcx>,
+        mir: &Mir<'tcx>,
+    ) -> Self {
         let num_region_variables = var_origins.len();
-        let num_free_regions = free_regions.indices.len();
+        let num_universal_regions = universal_regions.indices.len();
 
         let mut num_points = 0;
         let mut point_indices = BTreeMap::new();
@@ -106,7 +113,7 @@ pub fn new(var_origins: VarOrigins, free_regions: &FreeRegions<'tcx>, mir: &Mir<
                     block,
                     statement_index,
                 };
-                point_indices.insert(location, num_free_regions + num_points);
+                point_indices.insert(location, num_universal_regions + num_points);
                 num_points += 1;
             }
         }
@@ -121,25 +128,26 @@ pub fn new(var_origins: VarOrigins, free_regions: &FreeRegions<'tcx>, mir: &Mir<
             definitions,
             liveness_constraints: BitMatrix::new(
                 num_region_variables,
-                num_free_regions + num_points,
+                num_universal_regions + num_points,
             ),
             inferred_values: None,
             constraints: Vec::new(),
             point_indices,
-            num_free_regions,
-            free_region_map: free_regions.free_region_map,
+            num_universal_regions,
+            free_region_map: universal_regions.free_region_map,
         };
 
-        result.init_free_regions(free_regions);
+        result.init_universal_regions(universal_regions);
 
         result
     }
 
-    /// Initializes the region variables for each free region
-    /// (lifetime parameter). The first N variables always correspond
-    /// to the free regions appearing in the function signature (both
-    /// named and anonymous) and where clauses. This function iterates
-    /// over those regions and initializes them with minimum values.
+    /// Initializes the region variables for each universally
+    /// quantified region (lifetime parameter). The first N variables
+    /// always correspond to the regions appearing in the function
+    /// signature (both named and anonymous) and where clauses. This
+    /// function iterates over those regions and initializes them with
+    /// minimum values.
     ///
     /// For example:
     ///
@@ -154,13 +162,13 @@ pub fn new(var_origins: VarOrigins, free_regions: &FreeRegions<'tcx>, mir: &Mir<
     /// and (b) any free regions that it outlives, which in this case
     /// is just itself. R1 (`'b`) in contrast also outlives `'a` and
     /// hence contains R0 and R1.
-    fn init_free_regions(&mut self, free_regions: &FreeRegions<'tcx>) {
-        let FreeRegions {
+    fn init_universal_regions(&mut self, universal_regions: &UniversalRegions<'tcx>) {
+        let UniversalRegions {
             indices,
             free_region_map: _,
-        } = free_regions;
+        } = universal_regions;
 
-        // For each free region X:
+        // For each universally quantified region X:
         for (free_region, &variable) in indices {
             // These should be free-region variables.
             assert!(match self.definitions[variable].origin {
@@ -218,7 +226,7 @@ fn region_contains_region_in_matrix(
         &self,
         matrix: &BitMatrix,
         r: RegionVid,
-        s: RegionVid
+        s: RegionVid,
     ) -> bool {
         matrix.contains(r.index(), s.index())
     }
@@ -240,7 +248,7 @@ pub(super) fn region_value_str(&self, r: RegionVid) -> String {
             }
         }
 
-        for fr in (0 .. self.num_free_regions).map(RegionVid::new) {
+        for fr in (0..self.num_universal_regions).map(RegionVid::new) {
             if self.region_contains_region_in_matrix(inferred_values, r, fr) {
                 result.push_str(&format!("{}{:?}", sep, fr));
                 sep = ", ";
@@ -287,9 +295,9 @@ pub(super) fn solve(&mut self, infcx: &InferCtxt<'_, '_, 'tcx>, mir: &Mir<'tcx>)
         // Find the minimal regions that can solve the constraints. This is infallible.
         self.propagate_constraints(mir);
 
-        // Now, see whether any of the constraints were too strong. In particular,
-        // we want to check for a case where a free region exceeded its bounds.
-        // Consider:
+        // Now, see whether any of the constraints were too strong. In
+        // particular, we want to check for a case where a universally
+        // quantified region exceeded its bounds.  Consider:
         //
         //     fn foo<'a, 'b>(x: &'a u32) -> &'b u32 { x }
         //
@@ -300,7 +308,8 @@ pub(super) fn solve(&mut self, infcx: &InferCtxt<'_, '_, 'tcx>, mir: &Mir<'tcx>)
         // have no evidence that `'b` outlives `'a`, so we want to report
         // an error.
 
-        // The free regions are always found in a prefix of the full list.
+        // The universal regions are always found in a prefix of the
+        // full list.
         let free_region_definitions = self.definitions
             .iter_enumerated()
             .take_while(|(_, fr_definition)| fr_definition.name.is_some());
@@ -322,7 +331,7 @@ fn check_free_region(
 
         // Find every region `o` such that `fr: o`
         // (because `fr` includes `end(o)`).
-        for outlived_fr in fr_value.take_while(|&i| i < self.num_free_regions) {
+        for outlived_fr in fr_value.take_while(|&i| i < self.num_universal_regions) {
             // `fr` includes `end(fr)`, that's not especially
             // interesting.
             if fr.index() == outlived_fr {
@@ -451,11 +460,11 @@ fn copy(
                 // If we reach the END point in the graph, then copy
                 // over any skolemized end points in the `from_region`
                 // and make sure they are included in the `to_region`.
-                let free_region_indices = inferred_values
+                let universal_region_indices = inferred_values
                     .iter(from_region.index())
-                    .take_while(|&i| i < self.num_free_regions)
+                    .take_while(|&i| i < self.num_universal_regions)
                     .collect::<Vec<_>>();
-                for fr in &free_region_indices {
+                for fr in &universal_region_indices {
                     changed |= inferred_values.add(to_region.index(), *fr);
                 }
             } else {
@@ -523,7 +532,7 @@ impl<'tcx> RegionDefinition<'tcx> {
     fn new(origin: RegionVariableOrigin) -> Self {
         // Create a new region definition. Note that, for free
         // regions, these fields get updated later in
-        // `init_free_regions`.
+        // `init_universal_regions`.
         Self { origin, name: None }
     }
 }
index 1076b774de6578851392bdf8c386d19d30c1f65a..371419da0244871fd4d6114ca53296eda0024180 100644 (file)
 use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
 
 use super::ToRegionVid;
-use super::free_regions::FreeRegions;
+use super::universal_regions::UniversalRegions;
 
 /// Replaces all free regions appearing in the MIR with fresh
 /// inference variables, returning the number of variables created.
 pub fn renumber_mir<'a, 'gcx, 'tcx>(
     infcx: &InferCtxt<'a, 'gcx, 'tcx>,
-    free_regions: &FreeRegions<'tcx>,
+    universal_regions: &UniversalRegions<'tcx>,
     mir: &mut Mir<'tcx>,
 ) {
     // Create inference variables for each of the free regions
     // declared on the function signature.
-    let free_region_inference_vars = (0..free_regions.indices.len())
+    let free_region_inference_vars = (0..universal_regions.indices.len())
         .map(RegionVid::new)
         .map(|vid_expected| {
             let r = infcx.next_nll_region_var(NLLRegionVariableOrigin::FreeRegion);
@@ -37,12 +37,12 @@ pub fn renumber_mir<'a, 'gcx, 'tcx>(
         .collect();
 
     debug!("renumber_mir()");
-    debug!("renumber_mir: free_regions={:#?}", free_regions);
+    debug!("renumber_mir: universal_regions={:#?}", universal_regions);
     debug!("renumber_mir: mir.arg_count={:?}", mir.arg_count);
 
     let mut visitor = NLLVisitor {
         infcx,
-        free_regions,
+        universal_regions,
         free_region_inference_vars,
         arg_count: mir.arg_count,
     };
@@ -51,7 +51,7 @@ pub fn renumber_mir<'a, 'gcx, 'tcx>(
 
 struct NLLVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
     infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
-    free_regions: &'a FreeRegions<'tcx>,
+    universal_regions: &'a UniversalRegions<'tcx>,
     free_region_inference_vars: IndexVec<RegionVid, ty::Region<'tcx>>,
     arg_count: usize,
 }
@@ -76,16 +76,16 @@ fn renumber_regions<T>(&mut self, ty_context: TyContext, value: &T) -> T
 
     /// Renumbers the regions appearing in `value`, but those regions
     /// are expected to be free regions from the function signature.
-    fn renumber_free_regions<T>(&mut self, value: &T) -> T
+    fn renumber_universal_regions<T>(&mut self, value: &T) -> T
     where
         T: TypeFoldable<'tcx>,
     {
-        debug!("renumber_free_regions(value={:?})", value);
+        debug!("renumber_universal_regions(value={:?})", value);
 
         self.infcx
             .tcx
             .fold_regions(value, &mut false, |region, _depth| {
-                let index = self.free_regions.indices[&region];
+                let index = self.universal_regions.indices[&region];
                 self.free_region_inference_vars[index]
             })
     }
@@ -112,7 +112,7 @@ fn visit_ty(&mut self, ty: &mut Ty<'tcx>, ty_context: TyContext) {
 
         let old_ty = *ty;
         *ty = if is_arg {
-            self.renumber_free_regions(&old_ty)
+            self.renumber_universal_regions(&old_ty)
         } else {
             self.renumber_regions(ty_context, &old_ty)
         };
index c1850c76541d78f75d4c1f6e06cf50ab6ab459f6..dbae40be6fe1da1a15a9a5a1a5801b96b5cbc0f5 100644 (file)
@@ -15,7 +15,7 @@
 use transform::type_check::MirTypeckRegionConstraints;
 use transform::type_check::OutlivesSet;
 
-use super::free_regions::FreeRegions;
+use super::universal_regions::UniversalRegions;
 use super::region_infer::RegionInferenceContext;
 
 /// When the MIR type-checker executes, it validates all the types in
 /// them into the NLL `RegionInferenceContext`.
 pub(super) fn generate<'tcx>(
     regioncx: &mut RegionInferenceContext<'tcx>,
-    free_regions: &FreeRegions<'tcx>,
+    universal_regions: &UniversalRegions<'tcx>,
     mir: &Mir<'tcx>,
     constraints: &MirTypeckRegionConstraints<'tcx>,
 ) {
     SubtypeConstraintGenerator {
         regioncx,
-        free_regions,
+        universal_regions,
         mir,
     }.generate(constraints);
 }
 
 struct SubtypeConstraintGenerator<'cx, 'tcx: 'cx> {
     regioncx: &'cx mut RegionInferenceContext<'tcx>,
-    free_regions: &'cx FreeRegions<'tcx>,
+    universal_regions: &'cx UniversalRegions<'tcx>,
     mir: &'cx Mir<'tcx>,
 }
 
@@ -102,11 +102,11 @@ fn to_region_vid(&self, r: ty::Region<'tcx>) -> ty::RegionVid {
         // Every region that we see in the constraints came from the
         // MIR or from the parameter environment. If the former, it
         // will be a region variable.  If the latter, it will be in
-        // the set of free regions *somewhere*.
+        // the set of universal regions *somewhere*.
         if let ty::ReVar(vid) = r {
             *vid
         } else {
-            self.free_regions.indices[&r]
+            self.universal_regions.indices[&r]
         }
     }
 }
diff --git a/src/librustc_mir/borrow_check/nll/universal_regions.rs b/src/librustc_mir/borrow_check/nll/universal_regions.rs
new file mode 100644 (file)
index 0000000..3be95a1
--- /dev/null
@@ -0,0 +1,90 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Code to extract the universally quantified regions declared on a
+//! function and the relationships between them. For example:
+//!
+//! ```
+//! fn foo<'a, 'b, 'c: 'b>() { }
+//! ```
+//!
+//! here we would be returning a map assigning each of `{'a, 'b, 'c}`
+//! to an index, as well as the `FreeRegionMap` which can compute
+//! relationships between them.
+//!
+//! The code in this file doesn't *do anything* with those results; it
+//! just returns them for other code to use.
+
+use rustc::hir::def_id::DefId;
+use rustc::infer::InferCtxt;
+use rustc::infer::outlives::free_region_map::FreeRegionMap;
+use rustc::ty::{self, RegionVid};
+use rustc::ty::subst::Substs;
+use rustc::util::nodemap::FxHashMap;
+use rustc_data_structures::indexed_vec::Idx;
+
+#[derive(Debug)]
+pub struct UniversalRegions<'tcx> {
+    /// Given a universally quantified region defined on this function
+    /// (either early- or late-bound), this maps it to its internal
+    /// region index. When the region context is created, the first N
+    /// variables will be created based on these indices.
+    pub indices: FxHashMap<ty::Region<'tcx>, RegionVid>,
+
+    /// The map from the typeck tables telling us how to relate universal regions.
+    pub free_region_map: &'tcx FreeRegionMap<'tcx>,
+}
+
+pub fn universal_regions<'a, 'gcx, 'tcx>(
+    infcx: &InferCtxt<'a, 'gcx, 'tcx>,
+    item_def_id: DefId,
+) -> UniversalRegions<'tcx> {
+    debug!("universal_regions(item_def_id={:?})", item_def_id);
+
+    let mut indices = FxHashMap();
+
+    // `'static` is always free.
+    insert_free_region(&mut indices, infcx.tcx.types.re_static);
+
+    // Extract the early regions.
+    let item_substs = Substs::identity_for_item(infcx.tcx, item_def_id);
+    for item_subst in item_substs {
+        if let Some(region) = item_subst.as_region() {
+            insert_free_region(&mut indices, region);
+        }
+    }
+
+    // Extract the late-bound regions. Use the liberated fn sigs,
+    // where the late-bound regions will have been converted into free
+    // regions, and add them to the map.
+    let item_id = infcx.tcx.hir.as_local_node_id(item_def_id).unwrap();
+    let fn_hir_id = infcx.tcx.hir.node_to_hir_id(item_id);
+    let tables = infcx.tcx.typeck_tables_of(item_def_id);
+    let fn_sig = tables.liberated_fn_sigs()[fn_hir_id].clone();
+    infcx
+        .tcx
+        .for_each_free_region(&fn_sig.inputs_and_output, |region| {
+            if let ty::ReFree(_) = *region {
+                insert_free_region(&mut indices, region);
+            }
+        });
+
+    debug!("universal_regions: indices={:#?}", indices);
+
+    UniversalRegions { indices, free_region_map: &tables.free_region_map }
+}
+
+fn insert_free_region<'tcx>(
+    universal_regions: &mut FxHashMap<ty::Region<'tcx>, RegionVid>,
+    region: ty::Region<'tcx>,
+) {
+    let next = RegionVid::new(universal_regions.len());
+    universal_regions.entry(region).or_insert(next);
+}