about summary refs log tree commit diff
path: root/compiler/rustc_borrowck
diff options
context:
space:
mode:
authorAaron Hill <aa1ronham@gmail.com>2021-12-31 16:55:34 -0500
committerAaron Hill <aa1ronham@gmail.com>2021-12-31 18:42:54 -0500
commite3a048c3c9da3ad6faa2b576de044cc52dee2c62 (patch)
tree4023e3ee26c8f6dc70da77d8d37a440c18b7561a /compiler/rustc_borrowck
parent984a6bf9c11b7356f696c685a145d7136fff051c (diff)
downloadrust-e3a048c3c9da3ad6faa2b576de044cc52dee2c62.tar.gz
rust-e3a048c3c9da3ad6faa2b576de044cc52dee2c62.zip
Ensure that early-bound function lifetimes are always 'local'
During borrowchecking, we treat any free (early-bound) regions on
the 'defining type' as `RegionClassification::External`. According
to the doc comments, we should only have 'external' regions when
checking a closure/generator.

However, a plain function can also have some if its regions
be considered 'early bound' - this occurs when the region is
constrained by an argument, appears in a `where` clause, or
in an opaque type. This was causing us to incorrectly mark these
regions as 'external', which caused some diagnostic code
to act as if we were referring to a 'parent' region from inside
a closure.

This PR marks all instantiated region variables as 'local'
when we're borrow-checking something other than a
closure/generator/inline-const.
Diffstat (limited to 'compiler/rustc_borrowck')
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs41
1 files changed, 25 insertions, 16 deletions
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index b986df403f9..16a903d5e59 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -180,8 +180,9 @@ pub enum RegionClassification {
     /// anywhere. There is only one, `'static`.
     Global,
 
-    /// An **external** region is only relevant for closures. In that
-    /// case, it refers to regions that are free in the closure type
+    /// An **external** region is only relevant for
+    /// closures, generators, and inline consts. In that
+    /// case, it refers to regions that are free in the type
     /// -- basically, something bound in the surrounding context.
     ///
     /// Consider this example:
@@ -198,8 +199,8 @@ pub enum RegionClassification {
     /// Here, the lifetimes `'a` and `'b` would be **external** to the
     /// closure.
     ///
-    /// If we are not analyzing a closure, there are no external
-    /// lifetimes.
+    /// If we are not analyzing a closure/generator/inline-const,
+    /// there are no external lifetimes.
     External,
 
     /// A **local** lifetime is one about which we know the full set
@@ -424,22 +425,30 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
 
         let typeck_root_def_id = self.infcx.tcx.typeck_root_def_id(self.mir_def.did.to_def_id());
 
-        // If this is a closure or generator, then the late-bound regions from the enclosing
-        // function are actually external regions to us. For example, here, 'a is not local
-        // to the closure c (although it is local to the fn foo):
-        // fn foo<'a>() {
-        //     let c = || { let x: &'a u32 = ...; }
-        // }
-        if self.mir_def.did.to_def_id() != typeck_root_def_id {
+        // If this is is a 'root' body (not a closure/generator/inline const), then
+        // there are no extern regions, so the local regions start at the same
+        // position as the (empty) sub-list of extern regions
+        let first_local_index = if self.mir_def.did.to_def_id() == typeck_root_def_id {
+            first_extern_index
+        } else {
+            // If this is a closure, generator, or inline-const, then the late-bound regions from the enclosing
+            // function are actually external regions to us. For example, here, 'a is not local
+            // to the closure c (although it is local to the fn foo):
+            // fn foo<'a>() {
+            //     let c = || { let x: &'a u32 = ...; }
+            // }
             self.infcx
-                .replace_late_bound_regions_with_nll_infer_vars(self.mir_def.did, &mut indices)
-        }
-
-        let bound_inputs_and_output = self.compute_inputs_and_output(&indices, defining_ty);
+                .replace_late_bound_regions_with_nll_infer_vars(self.mir_def.did, &mut indices);
+            // Any regions created during the execution of `defining_ty` or during the above
+            // late-bound region replacement are all considered 'extern' regions
+            self.infcx.num_region_vars()
+        };
 
         // "Liberate" the late-bound regions. These correspond to
         // "local" free regions.
-        let first_local_index = self.infcx.num_region_vars();
+
+        let bound_inputs_and_output = self.compute_inputs_and_output(&indices, defining_ty);
+
         let inputs_and_output = self.infcx.replace_bound_regions_with_nll_infer_vars(
             FR,
             self.mir_def.did,