]> git.lizzy.rs Git - rust.git/commitdiff
add closure requirement tests, improve debugging output
authorNiko Matsakis <niko@alum.mit.edu>
Wed, 22 Nov 2017 22:39:46 +0000 (17:39 -0500)
committerNiko Matsakis <niko@alum.mit.edu>
Thu, 7 Dec 2017 10:28:00 +0000 (05:28 -0500)
The overall format is now easier to read. Also, There is now graphviz
output, as well as a `#[rustc_regions]` annotation that dumps internal
state.

52 files changed:
src/librustc_mir/borrow_check/nll/mod.rs
src/librustc_mir/borrow_check/nll/region_infer/annotation.rs [new file with mode: 0644]
src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs [new file with mode: 0644]
src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs [new file with mode: 0644]
src/librustc_mir/borrow_check/nll/region_infer/mod.rs
src/libsyntax/feature_gate.rs
src/test/mir-opt/nll/liveness-call-subtlety.rs
src/test/mir-opt/nll/liveness-drop-intra-block.rs
src/test/mir-opt/nll/liveness-interblock.rs
src/test/mir-opt/nll/named-lifetimes-basic.rs
src/test/mir-opt/nll/reborrow-basic.rs
src/test/mir-opt/nll/region-liveness-basic.rs
src/test/mir-opt/nll/region-liveness-drop-may-dangle.rs
src/test/mir-opt/nll/region-liveness-drop-no-may-dangle.rs
src/test/mir-opt/nll/region-liveness-two-disjoint-uses.rs
src/test/mir-opt/nll/region-subtyping-basic.rs
src/test/ui/nll/capture-ref-in-struct.rs [new file with mode: 0644]
src/test/ui/nll/capture-ref-in-struct.stderr [new file with mode: 0644]
src/test/ui/nll/closure-requirements/escape-argument-callee.rs [new file with mode: 0644]
src/test/ui/nll/closure-requirements/escape-argument-callee.stderr [new file with mode: 0644]
src/test/ui/nll/closure-requirements/escape-argument.rs [new file with mode: 0644]
src/test/ui/nll/closure-requirements/escape-argument.stderr [new file with mode: 0644]
src/test/ui/nll/closure-requirements/escape-upvar-nested.rs [new file with mode: 0644]
src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr [new file with mode: 0644]
src/test/ui/nll/closure-requirements/escape-upvar-ref.rs [new file with mode: 0644]
src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr [new file with mode: 0644]
src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.rs [new file with mode: 0644]
src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr [new file with mode: 0644]
src/test/ui/nll/closure-requirements/propagate-approximated-ref.rs [new file with mode: 0644]
src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr [new file with mode: 0644]
src/test/ui/nll/closure-requirements/propagate-approximated-to-empty.rs [new file with mode: 0644]
src/test/ui/nll/closure-requirements/propagate-approximated-to-empty.stderr [new file with mode: 0644]
src/test/ui/nll/closure-requirements/propagate-approximated-to-static.rs [new file with mode: 0644]
src/test/ui/nll/closure-requirements/propagate-approximated-to-static.stderr [new file with mode: 0644]
src/test/ui/nll/closure-requirements/propagate-approximated-val.rs [new file with mode: 0644]
src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr [new file with mode: 0644]
src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.rs [new file with mode: 0644]
src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr [new file with mode: 0644]
src/test/ui/nll/closure-requirements/region-ebr-does-not-outlive-static.rs [new file with mode: 0644]
src/test/ui/nll/closure-requirements/region-ebr-does-not-outlive-static.stderr [new file with mode: 0644]
src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs [new file with mode: 0644]
src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr [new file with mode: 0644]
src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.rs [new file with mode: 0644]
src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr [new file with mode: 0644]
src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.rs [new file with mode: 0644]
src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr [new file with mode: 0644]
src/test/ui/nll/closure-requirements/region-lbr1-does-outlive-lbr2-because-implied-bound.rs [new file with mode: 0644]
src/test/ui/nll/closure-requirements/return-wrong-bound-region.rs [new file with mode: 0644]
src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr [new file with mode: 0644]
src/test/ui/nll/closure-requirements/via-upvar-nested.stderr [new file with mode: 0644]
src/test/ui/nll/named-region-basic.rs [deleted file]
src/test/ui/nll/named-region-basic.stderr [deleted file]

index 3d698abc83f4349ab8fb4bed3f83acb76317bf04..4ff299efb95558f26dc24f86e7eebf0710be94ab 100644 (file)
@@ -14,6 +14,7 @@
 use rustc::ty::{self, RegionKind, RegionVid};
 use rustc::util::nodemap::FxHashMap;
 use std::collections::BTreeSet;
+use std::io;
 use transform::MirSource;
 use transform::type_check;
 use util::liveness::{self, LivenessMode, LivenessResult, LocalSet};
@@ -22,6 +23,7 @@
 use dataflow::move_paths::MoveData;
 
 use util as mir_util;
+use util::pretty::{self, ALIGN};
 use self::mir_util::PassWhere;
 
 mod constraint_generation;
@@ -117,8 +119,19 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
     let closure_region_requirements = regioncx.solve(infcx, &mir, def_id);
 
     // Dump MIR results into a file, if that is enabled. This let us
-    // write unit-tests.
-    dump_mir_results(infcx, liveness, MirSource::item(def_id), &mir, &regioncx);
+    // write unit-tests, as well as helping with debugging.
+    dump_mir_results(
+        infcx,
+        liveness,
+        MirSource::item(def_id),
+        &mir,
+        &regioncx,
+        &closure_region_requirements,
+    );
+
+    // We also have a `#[rustc_nll]` annotation that causes us to dump
+    // information
+    dump_annotation(infcx, &mir, def_id, &regioncx, &closure_region_requirements);
 
     (regioncx, closure_region_requirements)
 }
@@ -134,6 +147,7 @@ fn dump_mir_results<'a, 'gcx, 'tcx>(
     source: MirSource,
     mir: &Mir<'tcx>,
     regioncx: &RegionInferenceContext,
+    closure_region_requirements: &Option<ClosureRegionRequirements>,
 ) {
     if !mir_util::dump_enabled(infcx.tcx, "nll", source) {
         return;
@@ -168,9 +182,17 @@ fn dump_mir_results<'a, 'gcx, 'tcx>(
     mir_util::dump_mir(infcx.tcx, None, "nll", &0, source, mir, |pass_where, out| {
         match pass_where {
             // Before the CFG, dump out the values for each region variable.
-            PassWhere::BeforeCFG => for region in regioncx.regions() {
-                writeln!(out, "| {:?}: {}", region, regioncx.region_value_str(region))?;
-            },
+            PassWhere::BeforeCFG => {
+                regioncx.dump_mir(out)?;
+
+                if let Some(closure_region_requirements) = closure_region_requirements {
+                    writeln!(out, "|")?;
+                    writeln!(out, "| Free Region Constraints")?;
+                    for_each_region_constraint(closure_region_requirements, &mut |msg| {
+                        writeln!(out, "| {}", msg)
+                    })?;
+                }
+            }
 
             // Before each basic block, dump out the values
             // that are live on entry to the basic block.
@@ -184,13 +206,90 @@ fn dump_mir_results<'a, 'gcx, 'tcx>(
                     &regular_liveness_per_location[&location],
                     &drop_liveness_per_location[&location],
                 );
-                writeln!(out, "            | Live variables at {:?}: {}", location, s)?;
+                writeln!(
+                    out,
+                    "{:ALIGN$} | Live variables on entry to {:?}: {}",
+                    "",
+                    location,
+                    s,
+                    ALIGN = ALIGN
+                )?;
             }
 
             PassWhere::AfterLocation(_) | PassWhere::AfterCFG => {}
         }
         Ok(())
     });
+
+    // Also dump the inference graph constraints as a graphviz file.
+    let _: io::Result<()> = do catch {
+        let mut file =
+            pretty::create_dump_file(infcx.tcx, "regioncx.dot", None, "nll", &0, source)?;
+        regioncx.dump_graphviz(&mut file)
+    };
+}
+
+fn dump_annotation<'a, 'gcx, 'tcx>(
+    infcx: &InferCtxt<'a, 'gcx, 'tcx>,
+    mir: &Mir<'tcx>,
+    mir_def_id: DefId,
+    regioncx: &RegionInferenceContext,
+    closure_region_requirements: &Option<ClosureRegionRequirements>,
+) {
+    let tcx = infcx.tcx;
+    let base_def_id = tcx.closure_base_def_id(mir_def_id);
+    if !tcx.has_attr(base_def_id, "rustc_regions") {
+        return;
+    }
+
+    // When the enclosing function is tagged with `#[rustc_regions]`,
+    // we dump out various bits of state as warnings. This is useful
+    // for verifying that the compiler is behaving as expected.  These
+    // warnings focus on the closure region requirements -- for
+    // viewing the intraprocedural state, the -Zdump-mir output is
+    // better.
+
+    if let Some(closure_region_requirements) = closure_region_requirements {
+        let mut err = tcx.sess
+            .diagnostic()
+            .span_note_diag(mir.span, "External requirements");
+
+        regioncx.annotate(&mut err);
+
+        err.note(&format!(
+            "number of external vids: {}",
+            closure_region_requirements.num_external_vids
+        ));
+
+        // Dump the region constraints we are imposing *between* those
+        // newly created variables.
+        for_each_region_constraint(closure_region_requirements, &mut |msg| {
+            err.note(msg);
+            Ok(())
+        }).unwrap();
+
+        err.emit();
+    } else {
+        let mut err = tcx.sess
+            .diagnostic()
+            .span_note_diag(mir.span, "No external requirements");
+        regioncx.annotate(&mut err);
+        err.emit();
+    }
+}
+
+fn for_each_region_constraint(
+    closure_region_requirements: &ClosureRegionRequirements,
+    with_msg: &mut FnMut(&str) -> io::Result<()>,
+) -> io::Result<()> {
+    for req in &closure_region_requirements.outlives_requirements {
+        with_msg(&format!(
+            "where {:?}: {:?}",
+            req.free_region,
+            req.outlived_free_region,
+        ))?;
+    }
+    Ok(())
 }
 
 /// Right now, we piggy back on the `ReVar` to store our NLL inference
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/annotation.rs b/src/librustc_mir/borrow_check/nll/region_infer/annotation.rs
new file mode 100644 (file)
index 0000000..906efae
--- /dev/null
@@ -0,0 +1,48 @@
+// 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.
+
+//! As part of the NLL unit tests, you can annotate a function with
+//! `#[rustc_regions]`, and we will emit information about the region
+//! inference context and -- in particular -- the external constraints
+//! that this region imposes on others. The methods in this file
+//! handle the part about dumping the inference context internal
+//! state.
+
+use rustc::ty;
+use rustc_errors::DiagnosticBuilder;
+use super::RegionInferenceContext;
+
+impl<'gcx, 'tcx> RegionInferenceContext<'tcx> {
+    /// Write out our state into the `.mir` files.
+    pub(crate) fn annotate(&self, err: &mut DiagnosticBuilder<'_>) {
+        match self.universal_regions.defining_ty.sty {
+            ty::TyClosure(def_id, substs) => {
+                err.note(&format!(
+                    "defining type: {:?} with closure substs {:#?}",
+                    def_id,
+                    &substs.substs[..]
+                ));
+            }
+            ty::TyFnDef(def_id, substs) => {
+                err.note(&format!(
+                    "defining type: {:?} with substs {:#?}",
+                    def_id,
+                    &substs[..]
+                ));
+            }
+            _ => {
+                err.note(&format!(
+                    "defining type: {:?}",
+                    self.universal_regions.defining_ty
+                ));
+            }
+        }
+    }
+}
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs b/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs
new file mode 100644 (file)
index 0000000..5477308
--- /dev/null
@@ -0,0 +1,100 @@
+// 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.
+
+//! As part of generating the regions, if you enable `-Zdump-mir=nll`,
+//! we will generate an annotated copy of the MIR that includes the
+//! state of region inference. This code handles emitting the region
+//! context internal state.
+
+use std::io::{self, Write};
+use super::{Constraint, RegionInferenceContext};
+
+// Room for "'_#NNNNr" before things get misaligned.
+// Easy enough to fix if this ever doesn't seem like
+// enough.
+const REGION_WIDTH: usize = 8;
+
+impl<'tcx> RegionInferenceContext<'tcx> {
+    /// Write out our state into the `.mir` files.
+    pub(crate) fn dump_mir(&self, out: &mut Write) -> io::Result<()> {
+        writeln!(out, "| Free Region Mapping")?;
+
+        for region in self.regions() {
+            if self.definitions[region].is_universal {
+                let classification = self.universal_regions.region_classification(region).unwrap();
+                let outlived_by = self.universal_regions.regions_outlived_by(region);
+                writeln!(
+                    out,
+                    "| {r:rw$} | {c:cw$} | {ob}",
+                    r = format!("{:?}", region),
+                    rw = REGION_WIDTH,
+                    c = format!("{:?}", classification),
+                    cw = 8, // "External" at most
+                    ob = format!("{:?}", outlived_by)
+                )?;
+            }
+        }
+
+        writeln!(out, "|")?;
+        writeln!(out, "| Inferred Region Values")?;
+        for region in self.regions() {
+            writeln!(
+                out,
+                "| {r:rw$} | {v}",
+                r = format!("{:?}", region),
+                rw = REGION_WIDTH,
+                v = self.region_value_str(region),
+            )?;
+        }
+
+        writeln!(out, "|")?;
+        writeln!(out, "| Inference Constraints")?;
+        self.for_each_constraint(&mut |msg| writeln!(out, "| {}", msg))?;
+
+        Ok(())
+    }
+
+    /// Debugging aid: Invokes the `with_msg` callback repeatedly with
+    /// our internal region constraints.  These are dumped into the
+    /// -Zdump-mir file so that we can figure out why the region
+    /// inference resulted in the values that it did when debugging.
+    fn for_each_constraint(
+        &self,
+        with_msg: &mut FnMut(&str) -> io::Result<()>,
+    ) -> io::Result<()> {
+        for region in self.definitions.indices() {
+            let value = self.region_value_str_from_matrix(&self.liveness_constraints, region);
+            if value != "{}" {
+                with_msg(&format!("{:?} live at {}", region, value))?;
+            }
+        }
+
+        let mut constraints: Vec<_> = self.constraints.iter().collect();
+        constraints.sort();
+        for constraint in &constraints {
+            let Constraint {
+                sup,
+                sub,
+                point,
+                span,
+            } = constraint;
+            with_msg(&format!(
+                "{:?}: {:?} @ {:?} due to {:?}",
+                sup,
+                sub,
+                point,
+                span
+            ))?;
+        }
+
+        Ok(())
+    }
+}
+
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs b/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs
new file mode 100644 (file)
index 0000000..7923b15
--- /dev/null
@@ -0,0 +1,71 @@
+// Copyright 2014 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.
+
+//! This module provides linkage between RegionInferenceContext and
+//! libgraphviz traits, specialized to attaching borrowck analysis
+//! data to rendered labels.
+
+use dot::{self, IntoCow};
+use rustc_data_structures::indexed_vec::Idx;
+use std::borrow::Cow;
+use std::io::{self, Write};
+use super::*;
+
+impl<'tcx> RegionInferenceContext<'tcx> {
+    /// Write out the region constraint graph.
+    pub(crate) fn dump_graphviz(&self, mut w: &mut Write) -> io::Result<()> {
+        dot::render(self, &mut w)
+    }
+}
+
+impl<'this, 'tcx> dot::Labeller<'this> for RegionInferenceContext<'tcx> {
+    type Node = RegionVid;
+    type Edge = Constraint;
+
+    fn graph_id(&'this self) -> dot::Id<'this> {
+        dot::Id::new(format!("RegionInferenceContext")).unwrap()
+    }
+    fn node_id(&'this self, n: &RegionVid) -> dot::Id<'this> {
+        dot::Id::new(format!("r{}", n.index())).unwrap()
+    }
+    fn node_shape(&'this self, _node: &RegionVid) -> Option<dot::LabelText<'this>> {
+        Some(dot::LabelText::LabelStr(Cow::Borrowed("box")))
+    }
+    fn node_label(&'this self, n: &RegionVid) -> dot::LabelText<'this> {
+        dot::LabelText::LabelStr(format!("{:?}", n).into_cow())
+    }
+    fn edge_label(&'this self, e: &Constraint) -> dot::LabelText<'this> {
+        dot::LabelText::LabelStr(format!("{:?}", e.point).into_cow())
+    }
+}
+
+impl<'this, 'tcx> dot::GraphWalk<'this> for RegionInferenceContext<'tcx> {
+    type Node = RegionVid;
+    type Edge = Constraint;
+
+    fn nodes(&'this self) -> dot::Nodes<'this, RegionVid> {
+        let vids: Vec<RegionVid> = self.definitions.indices().collect();
+        vids.into_cow()
+    }
+    fn edges(&'this self) -> dot::Edges<'this, Constraint> {
+        (&self.constraints[..]).into_cow()
+    }
+
+    // Render `a: b` as `a <- b`, indicating the flow
+    // of data during inference.
+
+    fn source(&'this self, edge: &Constraint) -> RegionVid {
+        edge.sub
+    }
+
+    fn target(&'this self, edge: &Constraint) -> RegionVid {
+        edge.sup
+    }
+}
index 171deb3e1d753797b7a67cc8b58383438770662e..b2e2ccc5d0b720d889fa3598b02d87627d8e66b3 100644 (file)
 use std::fmt;
 use syntax_pos::Span;
 
+mod annotation;
+mod dump_mir;
+mod graphviz;
+
 pub struct RegionInferenceContext<'tcx> {
     /// Contains the definition for every region variable.  Region
     /// variables are identified by their index (`RegionVid`). The
index e5296e7d88cd6f457e253bce291f50ec054058a5..22cef25320ed30317b824dbc592bc9c07c8ef8c2 100644 (file)
@@ -717,6 +717,12 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
                                       is just used for rustc unit tests \
                                       and will never be stable",
                                      cfg_fn!(rustc_attrs))),
+    ("rustc_regions", Normal, Gated(Stability::Unstable,
+                                    "rustc_attrs",
+                                    "the `#[rustc_regions]` attribute \
+                                     is just used for rustc unit tests \
+                                     and will never be stable",
+                                    cfg_fn!(rustc_attrs))),
     ("rustc_error", Whitelisted, Gated(Stability::Unstable,
                                        "rustc_attrs",
                                        "the `#[rustc_error]` attribute \
index e4dd99f5a1e75e8874e39f9fc064ac68ae1f30be..09288cf69ff586064efc7116894ccf6d5257dc89 100644 (file)
@@ -28,18 +28,18 @@ fn main() {
 // START rustc.main.nll.0.mir
 //    | Live variables on entry to bb0: []
 //    bb0: {
-//            | Live variables at bb0[0]: []
+//            | Live variables on entry to bb0[0]: []
 //        StorageLive(_1);
-//            | Live variables at bb0[1]: []
+//            | Live variables on entry to bb0[1]: []
 //        _1 = const <std::boxed::Box<T>>::new(const 22usize) -> [return: bb2, unwind: bb1];
 //    }
 // END rustc.main.nll.0.mir
 // START rustc.main.nll.0.mir
 //    | Live variables on entry to bb2: [_1 (drop)]
 //    bb2: {
-//            | Live variables at bb2[0]: [_1 (drop)]
+//            | Live variables on entry to bb2[0]: [_1 (drop)]
 //        StorageLive(_2);
-//            | Live variables at bb2[1]: [_1 (drop)]
+//            | Live variables on entry to bb2[1]: [_1 (drop)]
 //        _2 = const can_panic() -> [return: bb3, unwind: bb4];
 //    }
 // END rustc.main.nll.0.mir
index 8dae773806718094a85ac1e378c72fd8af1ed210..b060222a95f1701ea42b1c9a5c7ec44b91db1556 100644 (file)
@@ -27,15 +27,15 @@ fn main() {
 // START rustc.main.nll.0.mir
 //    | Live variables on entry to bb2: []
 //    bb2: {
-//            | Live variables at bb2[0]: []
+//            | Live variables on entry to bb2[0]: []
 //        _1 = const 55usize;
-//            | Live variables at bb2[1]: [_1]
+//            | Live variables on entry to bb2[1]: [_1]
 //        StorageLive(_3);
-//            | Live variables at bb2[2]: [_1]
+//            | Live variables on entry to bb2[2]: [_1]
 //        StorageLive(_4);
-//            | Live variables at bb2[3]: [_1]
+//            | Live variables on entry to bb2[3]: [_1]
 //        _4 = _1;
-//            | Live variables at bb2[4]: [_4]
+//            | Live variables on entry to bb2[4]: [_4]
 //        _3 = const use_x(move _4) -> [return: bb3, unwind: bb1];
 //    }
 // END rustc.main.nll.0.mir
index 5d799d3d90b414c87c6aea71393b9eeb96b7be6f..671f5e5292aa439029b6e98221ed7e51bb9da502 100644 (file)
@@ -31,18 +31,18 @@ fn main() {
 // START rustc.main.nll.0.mir
 //     | Live variables on entry to bb3: [_1]
 //     bb3: {
-//             | Live variables at bb3[0]: [_1]
+//             | Live variables on entry to bb3[0]: [_1]
 //         StorageLive(_4);
-//             | Live variables at bb3[1]: [_1]
+//             | Live variables on entry to bb3[1]: [_1]
 //         _4 = _1;
-//             | Live variables at bb3[2]: [_4]
+//             | Live variables on entry to bb3[2]: [_4]
 //         _3 = const make_live(move _4) -> [return: bb5, unwind: bb1];
 //     }
 // END rustc.main.nll.0.mir
 // START rustc.main.nll.0.mir
 //     | Live variables on entry to bb4: []
 //     bb4: {
-//             | Live variables at bb4[0]: []
+//             | Live variables on entry to bb4[0]: []
 //         _5 = const make_dead() -> [return: bb6, unwind: bb1];
 //     }
 // END rustc.main.nll.0.mir
index 7039de727faa98b7b6b319bb12145e85ce9d3f65..0c42585a528e0c3d4c4f927109af14aeb9c2e5f4 100644 (file)
@@ -26,9 +26,18 @@ fn main() {
 
 // END RUST SOURCE
 // START rustc.use_x.nll.0.mir
-// | '_#0r: {bb0[0], bb0[1], '_#0r}
-// | '_#1r: {bb0[0], bb0[1], '_#1r}
-// | '_#2r: {bb0[0], bb0[1], '_#2r}
-// | '_#3r: {bb0[0], bb0[1], '_#3r}
+// | Free Region Mapping
+// | '_#0r    | Global   | ['_#2r, '_#1r, '_#0r, '_#3r]
+// | '_#1r    | External | ['_#1r]
+// | '_#2r    | External | ['_#2r, '_#1r]
+// | '_#3r    | Local    | ['_#3r]
+// |
+// | Inferred Region Values
+// | '_#0r    | {bb0[0], bb0[1], '_#0r}
+// | '_#1r    | {bb0[0], bb0[1], '_#1r}
+// | '_#2r    | {bb0[0], bb0[1], '_#2r}
+// | '_#3r    | {bb0[0], bb0[1], '_#3r}
+// |
+// ...
 // fn use_x(_1: &'_#1r mut i32, _2: &'_#2r u32, _3: &'_#1r u32, _4: &'_#3r u32) -> bool {
 // END rustc.use_x.nll.0.mir
index f51e839e4fc350ce11e942e17afe910bf6de5b86..d203472f20c737d5bb29a556a32abf17c7b3b41b 100644 (file)
@@ -28,11 +28,10 @@ fn main() {
 
 // END RUST SOURCE
 // START rustc.main.nll.0.mir
-// | '_#6r: {bb0[6], bb0[7], bb0[8], bb0[9], bb0[10], bb0[11], bb0[12], bb0[13], bb0[14]}
+// | '_#6r    | {bb0[6], bb0[7], bb0[8], bb0[9], bb0[10], bb0[11], bb0[12], bb0[13], bb0[14]}
+// ...
+// | '_#8r    | {bb0[11], bb0[12], bb0[13], bb0[14]}
 // ...
-// | '_#8r: {bb0[11], bb0[12], bb0[13], bb0[14]}
-// END rustc.main.nll.0.mir
-// START rustc.main.nll.0.mir
 // let _2: &'_#6r mut i32;
 // ...
 // let _4: &'_#8r mut i32;
index cfbc51f9e18613ee5430548235daa6846612ebee..c04cedbc04b4d95e1de5163bb4e1138c0489ee8e 100644 (file)
@@ -31,26 +31,26 @@ fn main() {
 
 // END RUST SOURCE
 // START rustc.main.nll.0.mir
-// | '_#1r: {bb2[0], bb2[1], bb3[0], bb3[1]}
-// | '_#2r: {bb2[1], bb3[0], bb3[1]}
+// | '_#1r    | {bb2[0], bb2[1], bb3[0], bb3[1]}
+// | '_#2r    | {bb2[1], bb3[0], bb3[1]}
 // ...
 //             let _2: &'_#2r usize;
 // END rustc.main.nll.0.mir
 // START rustc.main.nll.0.mir
 //    bb2: {
-//            | Live variables at bb2[0]: [_1, _3]
+//            | Live variables on entry to bb2[0]: [_1, _3]
 //        _2 = &'_#1r _1[_3];
-//            | Live variables at bb2[1]: [_2]
+//            | Live variables on entry to bb2[1]: [_2]
 //        switchInt(const true) -> [0u8: bb4, otherwise: bb3];
 //    }
 // END rustc.main.nll.0.mir
 // START rustc.main.nll.0.mir
 //    bb3: {
-//            | Live variables at bb3[0]: [_2]
+//            | Live variables on entry to bb3[0]: [_2]
 //        StorageLive(_7);
-//            | Live variables at bb3[1]: [_2]
+//            | Live variables on entry to bb3[1]: [_2]
 //        _7 = (*_2);
-//            | Live variables at bb3[2]: [_7]
+//            | Live variables on entry to bb3[2]: [_7]
 //        _6 = const use_x(move _7) -> [return: bb5, unwind: bb1];
 //    }
 // END rustc.main.nll.0.mir
index 04a30dc284d7727f997970d6019fa4b691d394e0..e2ad49a443625f57c6b88e7c77622b1c7040bdf6 100644 (file)
@@ -44,5 +44,5 @@ fn drop(&mut self) { }
 
 // END RUST SOURCE
 // START rustc.main.nll.0.mir
-// | '_#5r: {bb2[3], bb2[4], bb2[5], bb3[0], bb3[1]}
+// | '_#5r    | {bb2[3], bb2[4], bb2[5], bb3[0], bb3[1]}
 // END rustc.main.nll.0.mir
index 5569fe7f5748c44b7b6ef4b6bf3439421f5dbc49..e0272a51d03d996459411d05db1d4ece24598c81 100644 (file)
@@ -46,5 +46,5 @@ fn drop(&mut self) { }
 
 // END RUST SOURCE
 // START rustc.main.nll.0.mir
-// | '_#5r: {bb2[3], bb2[4], bb2[5], bb3[0], bb3[1], bb3[2], bb4[0], bb5[0], bb5[1], bb5[2], bb6[0], bb7[0], bb7[1], bb8[0]}
+// | '_#5r    | {bb2[3], bb2[4], bb2[5], bb3[0], bb3[1], bb3[2], bb4[0], bb5[0], bb5[1], bb5[2], bb6[0], bb7[0], bb7[1], bb8[0]}
 // END rustc.main.nll.0.mir
index 679f31fdab9035161302651afba534ba69044b31..8aa0eb1a3a90eb0f15e403a8f9233f26e01728c5 100644 (file)
@@ -36,10 +36,10 @@ fn main() {
 
 // END RUST SOURCE
 // START rustc.main.nll.0.mir
-// | '_#1r: {bb2[0], bb2[1], bb3[0], bb3[1]}
+// | '_#1r    | {bb2[0], bb2[1], bb3[0], bb3[1]}
 // ...
-// | '_#3r: {bb8[1], bb8[2], bb8[3], bb8[4]}
-// | '_#4r: {bb2[1], bb3[0], bb3[1], bb8[2], bb8[3], bb8[4]}
+// | '_#3r    | {bb8[1], bb8[2], bb8[3], bb8[4]}
+// | '_#4r    | {bb2[1], bb3[0], bb3[1], bb8[2], bb8[3], bb8[4]}
 // ...
 // let mut _2: &'_#4r usize;
 // ...
index 471d77aefac622bc0e5a2286e6de587a4dd25c4f..2bc165bd3c4a3a6d6d47d602538fd2b507602c21 100644 (file)
@@ -32,9 +32,9 @@ fn main() {
 
 // END RUST SOURCE
 // START rustc.main.nll.0.mir
-// | '_#1r: {bb2[0], bb2[1], bb2[2], bb2[3], bb2[4], bb2[5], bb2[6], bb3[0], bb3[1]}
-// | '_#2r: {bb2[1], bb2[2], bb2[3], bb2[4], bb2[5], bb2[6], bb3[0], bb3[1]}
-// | '_#3r: {bb2[5], bb2[6], bb3[0], bb3[1]}
+// | '_#1r    | {bb2[0], bb2[1], bb2[2], bb2[3], bb2[4], bb2[5], bb2[6], bb3[0], bb3[1]}
+// | '_#2r    | {bb2[1], bb2[2], bb2[3], bb2[4], bb2[5], bb2[6], bb3[0], bb3[1]}
+// | '_#3r    | {bb2[5], bb2[6], bb3[0], bb3[1]}
 // END rustc.main.nll.0.mir
 // START rustc.main.nll.0.mir
 // let _2: &'_#2r usize;
diff --git a/src/test/ui/nll/capture-ref-in-struct.rs b/src/test/ui/nll/capture-ref-in-struct.rs
new file mode 100644 (file)
index 0000000..00a0c94
--- /dev/null
@@ -0,0 +1,50 @@
+// Copyright 2016 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.
+
+// compile-flags:-Znll -Zborrowck=mir
+
+// Test that a structure which tries to store a pointer to `y` into
+// `p` (indirectly) fails to compile.
+
+#![feature(rustc_attrs)]
+
+struct SomeStruct<'a, 'b: 'a> {
+    p: &'a mut &'b i32,
+    y: &'b i32,
+}
+
+fn test() {
+    let x = 44;
+    let mut p = &x;
+
+    {
+        let y = 22;
+
+        let closure = SomeStruct {
+            p: &mut p,
+            y: &y,
+        };
+
+        closure.invoke();
+    }
+    //~^ ERROR borrowed value does not live long enough [E0597]
+
+    deref(p);
+}
+
+impl<'a, 'b> SomeStruct<'a, 'b> {
+    fn invoke(self) {
+        *self.p = self.y;
+    }
+}
+
+fn deref(_: &i32) { }
+
+fn main() { }
diff --git a/src/test/ui/nll/capture-ref-in-struct.stderr b/src/test/ui/nll/capture-ref-in-struct.stderr
new file mode 100644 (file)
index 0000000..f10e52e
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/capture-ref-in-struct.rs:36:6
+   |
+28 |         let y = 22;
+   |             - temporary value created here
+...
+36 |     }
+   |      ^ temporary value dropped here while still borrowed
+   |
+   = note: consider using a `let` binding to increase its lifetime
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/closure-requirements/escape-argument-callee.rs b/src/test/ui/nll/closure-requirements/escape-argument-callee.rs
new file mode 100644 (file)
index 0000000..dae8c84
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright 2016 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.
+
+// Test closure that:
+//
+// - takes an argument `y`
+// - stores `y` into another, longer-lived spot
+//
+// *but* the signature of the closure doesn't indicate that `y` lives
+// long enough for that. The closure reports the error (and hence we
+// see it before the closure's "external requirements" report).
+
+// compile-flags:-Znll -Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+
+#[rustc_regions]
+fn test() {
+    let x = 44;
+    let mut p = &x;
+
+    {
+        let y = 22;
+        let mut closure = expect_sig(|p, y| *p = y);
+        //~^ ERROR free region `'_#4r` does not outlive free region `'_#3r`
+        //~| WARNING not reporting region error due to -Znll
+        closure(&mut p, &y);
+    }
+
+    deref(p);
+}
+
+fn expect_sig<F>(f: F) -> F
+    where F: FnMut(&mut &i32, &i32)
+{
+    f
+}
+
+fn deref(_p: &i32) { }
+
+fn main() { }
diff --git a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
new file mode 100644 (file)
index 0000000..a0587c7
--- /dev/null
@@ -0,0 +1,40 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/escape-argument-callee.rs:31:50
+   |
+31 |         let mut closure = expect_sig(|p, y| *p = y);
+   |                                                  ^
+
+error: free region `'_#4r` does not outlive free region `'_#3r`
+  --> $DIR/escape-argument-callee.rs:31:45
+   |
+31 |         let mut closure = expect_sig(|p, y| *p = y);
+   |                                             ^^^^^^
+
+note: External requirements
+  --> $DIR/escape-argument-callee.rs:31:38
+   |
+31 |         let mut closure = expect_sig(|p, y| *p = y);
+   |                                      ^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:9 ~ escape_argument_callee[317d]::test[0]::{{closure}}[0]) with closure substs [
+               i16,
+               for<'r, 's, 't0> extern "rust-call" fn((&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r(7666))) mut &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's(7667))) i32, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't0(7668))) i32))
+           ]
+   = note: number of external vids: 1
+
+note: No external requirements
+  --> $DIR/escape-argument-callee.rs:25:1
+   |
+25 | / fn test() {
+26 | |     let x = 44;
+27 | |     let mut p = &x;
+28 | |
+...  |
+37 | |     deref(p);
+38 | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:3 ~ escape_argument_callee[317d]::test[0]) with substs []
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/closure-requirements/escape-argument.rs b/src/test/ui/nll/closure-requirements/escape-argument.rs
new file mode 100644 (file)
index 0000000..da6d60e
--- /dev/null
@@ -0,0 +1,50 @@
+// Copyright 2016 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.
+
+// Test closure that:
+//
+// - takes an argument `y`
+// - stores `y` into another, longer-lived spot
+//
+// but is invoked with a spot that doesn't live long
+// enough to store `y`.
+//
+// The error is reported in the caller: invoking the closure links the
+// lifetime of the borrow that is given as `y` and forces it to live
+// too long.
+
+// compile-flags:-Znll -Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+
+#[rustc_regions]
+fn test() {
+    let x = 44;
+    let mut p = &x;
+
+    {
+        let y = 22;
+        let mut closure = expect_sig(|p, y| *p = y);
+        closure(&mut p, &y);
+    }
+    //~^ ERROR borrowed value does not live long enough [E0597]
+
+    deref(p);
+}
+
+fn expect_sig<F>(f: F) -> F
+    where F: for<'a, 'b> FnMut(&'a mut &'b i32, &'b i32)
+{
+    f
+}
+
+fn deref(_p: &i32) { }
+
+fn main() { }
diff --git a/src/test/ui/nll/closure-requirements/escape-argument.stderr b/src/test/ui/nll/closure-requirements/escape-argument.stderr
new file mode 100644 (file)
index 0000000..653c461
--- /dev/null
@@ -0,0 +1,39 @@
+note: External requirements
+  --> $DIR/escape-argument.rs:34:38
+   |
+34 |         let mut closure = expect_sig(|p, y| *p = y);
+   |                                      ^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:9 ~ escape_argument[317d]::test[0]::{{closure}}[0]) with closure substs [
+               i16,
+               for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r(8634))) mut &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's(8635))) i32, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's(8635))) i32))
+           ]
+   = note: number of external vids: 1
+
+note: No external requirements
+  --> $DIR/escape-argument.rs:28:1
+   |
+28 | / fn test() {
+29 | |     let x = 44;
+30 | |     let mut p = &x;
+31 | |
+...  |
+39 | |     deref(p);
+40 | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:3 ~ escape_argument[317d]::test[0]) with substs []
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/escape-argument.rs:36:6
+   |
+33 |         let y = 22;
+   |             - temporary value created here
+...
+36 |     }
+   |      ^ temporary value dropped here while still borrowed
+   |
+   = note: consider using a `let` binding to increase its lifetime
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-nested.rs b/src/test/ui/nll/closure-requirements/escape-upvar-nested.rs
new file mode 100644 (file)
index 0000000..6a94f24
--- /dev/null
@@ -0,0 +1,43 @@
+// Copyright 2016 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.
+
+// As in via-upvar, test closure that:
+//
+// - captures a variable `y`
+// - stores reference to `y` into another, longer-lived spot
+//
+// except that the closure does so via a second closure.
+
+// compile-flags:-Znll -Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+
+#[rustc_regions]
+fn test() {
+    let x = 44;
+    let mut p = &x;
+
+    {
+        let y = 22;
+
+        let mut closure = || {
+            let mut closure1 = || p = &y;
+            closure1();
+        };
+
+        closure();
+    } //~ ERROR borrowed value does not live long enough
+
+    deref(p);
+}
+
+fn deref(_p: &i32) { }
+
+fn main() { }
diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr b/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr
new file mode 100644 (file)
index 0000000..201590f
--- /dev/null
@@ -0,0 +1,61 @@
+note: External requirements
+  --> $DIR/escape-upvar-nested.rs:31:32
+   |
+31 |             let mut closure1 = || p = &y;
+   |                                ^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:10 ~ escape_upvar_nested[317d]::test[0]::{{closure}}[0]::{{closure}}[0]) with closure substs [
+               i16,
+               extern "rust-call" fn(()),
+               &'_#1r mut &'_#2r i32,
+               &'_#3r i32
+           ]
+   = note: number of external vids: 4
+   = note: where '_#3r: '_#2r
+
+note: External requirements
+  --> $DIR/escape-upvar-nested.rs:30:27
+   |
+30 |           let mut closure = || {
+   |  ___________________________^
+31 | |             let mut closure1 = || p = &y;
+32 | |             closure1();
+33 | |         };
+   | |_________^
+   |
+   = note: defining type: DefId(0/1:9 ~ escape_upvar_nested[317d]::test[0]::{{closure}}[0]) with closure substs [
+               i16,
+               extern "rust-call" fn(()),
+               &'_#1r mut &'_#2r i32,
+               &'_#3r i32
+           ]
+   = note: number of external vids: 4
+   = note: where '_#3r: '_#2r
+
+note: No external requirements
+  --> $DIR/escape-upvar-nested.rs:23:1
+   |
+23 | / fn test() {
+24 | |     let x = 44;
+25 | |     let mut p = &x;
+26 | |
+...  |
+38 | |     deref(p);
+39 | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:3 ~ escape_upvar_nested[317d]::test[0]) with substs []
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/escape-upvar-nested.rs:36:6
+   |
+28 |         let y = 22;
+   |             - temporary value created here
+...
+36 |     } //~ ERROR borrowed value does not live long enough
+   |      ^ temporary value dropped here while still borrowed
+   |
+   = note: consider using a `let` binding to increase its lifetime
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-ref.rs b/src/test/ui/nll/closure-requirements/escape-upvar-ref.rs
new file mode 100644 (file)
index 0000000..5d14501
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright 2016 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.
+
+// Test closure that:
+// - captures a variable `y`
+// - stores reference to `y` into another, longer-lived spot
+
+// compile-flags:-Znll -Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+
+#[rustc_regions]
+fn test() {
+    let x = 44;
+    let mut p = &x;
+
+    {
+        let y = 22;
+        let mut closure = || p = &y;
+        closure();
+    } //~ ERROR borrowed value does not live long enough
+
+    deref(p);
+}
+
+fn deref(_p: &i32) { }
+
+fn main() { }
diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr b/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr
new file mode 100644 (file)
index 0000000..0a182fb
--- /dev/null
@@ -0,0 +1,42 @@
+note: External requirements
+  --> $DIR/escape-upvar-ref.rs:26:27
+   |
+26 |         let mut closure = || p = &y;
+   |                           ^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:9 ~ escape_upvar_ref[317d]::test[0]::{{closure}}[0]) with closure substs [
+               i16,
+               extern "rust-call" fn(()),
+               &'_#1r mut &'_#2r i32,
+               &'_#3r i32
+           ]
+   = note: number of external vids: 4
+   = note: where '_#3r: '_#2r
+
+note: No external requirements
+  --> $DIR/escape-upvar-ref.rs:20:1
+   |
+20 | / fn test() {
+21 | |     let x = 44;
+22 | |     let mut p = &x;
+23 | |
+...  |
+30 | |     deref(p);
+31 | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:3 ~ escape_upvar_ref[317d]::test[0]) with substs []
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/escape-upvar-ref.rs:28:6
+   |
+25 |         let y = 22;
+   |             - temporary value created here
+...
+28 |     } //~ ERROR borrowed value does not live long enough
+   |      ^ temporary value dropped here while still borrowed
+   |
+   = note: consider using a `let` binding to increase its lifetime
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.rs
new file mode 100644 (file)
index 0000000..c2f071c
--- /dev/null
@@ -0,0 +1,63 @@
+// Copyright 2016 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.
+
+// Test where we fail to approximate due to demanding a postdom
+// relationship between our upper bounds.
+
+// compile-flags:-Znll -Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+// Callee knows that:
+//
+// 'x: 'a
+// 'x: 'b
+// 'c: 'y
+//
+// we have to prove that `'x: 'y`. We currently can only approximate
+// via a postdominator -- hence we fail to choose between `'a` and
+// `'b` here and report the error in the closure.
+fn establish_relationships<'a, 'b, 'c, F>(
+    _cell_a: Cell<&'a u32>,
+    _cell_b: Cell<&'b u32>,
+    _cell_c: Cell<&'c u32>,
+    _closure: F,
+) where
+    F: for<'x, 'y> FnMut(
+        Cell<&'a &'x u32>, // shows that 'x: 'a
+        Cell<&'b &'x u32>, // shows that 'x: 'b
+        Cell<&'y &'c u32>, // shows that 'c: 'y
+        Cell<&'x u32>,
+        Cell<&'y u32>,
+    ),
+{
+}
+
+fn demand_y<'x, 'y>(_cell_x: Cell<&'x u32>, _cell_y: Cell<&'y u32>, _y: &'y u32) {}
+
+#[rustc_regions]
+fn supply<'a, 'b, 'c>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>, cell_c: Cell<&'c u32>) {
+    establish_relationships(
+        cell_a,
+        cell_b,
+        cell_c,
+        |_outlives1, _outlives2, _outlives3, x, y| {
+            // Only works if 'x: 'y:
+            let p = x.get();
+            //~^ WARN not reporting region error due to -Znll
+            demand_y(x, y, p)
+            //~^ ERROR free region `'_#5r` does not outlive free region `'_#6r`
+        },
+    );
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
new file mode 100644 (file)
index 0000000..c52701d
--- /dev/null
@@ -0,0 +1,46 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/propagate-approximated-fail-no-postdom.rs:55:21
+   |
+55 |             let p = x.get();
+   |                     ^^^^^^^
+
+error: free region `'_#5r` does not outlive free region `'_#6r`
+  --> $DIR/propagate-approximated-fail-no-postdom.rs:57:25
+   |
+57 |             demand_y(x, y, p)
+   |                         ^
+
+note: External requirements
+  --> $DIR/propagate-approximated-fail-no-postdom.rs:53:9
+   |
+53 | /         |_outlives1, _outlives2, _outlives3, x, y| {
+54 | |             // Only works if 'x: 'y:
+55 | |             let p = x.get();
+56 | |             //~^ WARN not reporting region error due to -Znll
+57 | |             demand_y(x, y, p)
+58 | |             //~^ ERROR free region `'_#5r` does not outlive free region `'_#6r`
+59 | |         },
+   | |_________^
+   |
+   = note: defining type: DefId(0/1:20 ~ propagate_approximated_fail_no_postdom[317d]::supply[0]::{{closure}}[0]) with closure substs [
+               i16,
+               for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r(9523))) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r(9523))) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's(9524))) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r(9523))) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's(9524))) u32>))
+           ]
+   = note: number of external vids: 4
+
+note: No external requirements
+  --> $DIR/propagate-approximated-fail-no-postdom.rs:48:1
+   |
+48 | / fn supply<'a, 'b, 'c>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>, cell_c: Cell<&'c u32>) {
+49 | |     establish_relationships(
+50 | |         cell_a,
+51 | |         cell_b,
+...  |
+60 | |     );
+61 | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:6 ~ propagate_approximated_fail_no_postdom[317d]::supply[0]) with substs []
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.rs
new file mode 100644 (file)
index 0000000..a18b618
--- /dev/null
@@ -0,0 +1,64 @@
+// Copyright 2016 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.
+
+// Rather convoluted setup where we infer a relationship between two
+// free regions in the closure signature (`'a` and `'b`) on the basis
+// of a relationship between two bound regions (`'x` and `'y`).
+//
+// The idea is that, thanks to invoking `demand_y`, `'x: 'y` must
+// hold, where `'x` and `'y` are bound regions. The closure can't
+// prove that directly, and because `'x` and `'y` are bound it cannot
+// ask the caller to prove it either. But it has bounds on `'x` and
+// `'y` in terms of `'a` and `'b`, and it can propagate a relationship
+// between `'a` and `'b` to the caller.
+//
+// Note: the use of `Cell` here is to introduce invariance. One less
+// variable.
+//
+// FIXME: The `supply` function *ought* to generate an error, but it
+// currently does not. This is I believe a shortcoming of the MIR type
+// checker: the closure inference is expressing the correct
+// requirement, as you can see from the `#[rustc_regions]` output.
+
+// compile-flags:-Znll -Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+// Callee knows that:
+//
+// 'x: 'a
+// 'b: 'y
+//
+// so if we are going to ensure that `'x: 'y`, then `'a: 'b` must
+// hold.
+fn establish_relationships<'a, 'b, F>(_cell_a: &Cell<&'a u32>, _cell_b: &Cell<&'b u32>, _closure: F)
+where
+    F: for<'x, 'y> FnMut(
+        &Cell<&'a &'x u32>, // shows that 'x: 'a
+        &Cell<&'y &'b u32>, // shows that 'b: 'y
+        &Cell<&'x u32>,
+        &Cell<&'y u32>,
+    ),
+{
+}
+
+fn demand_y<'x, 'y>(_cell_x: &Cell<&'x u32>, _cell_y: &Cell<&'y u32>, _y: &'y u32) {}
+
+#[rustc_regions]
+fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+    establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
+        // Only works if 'x: 'y:
+        demand_y(x, y, x.get())
+    });
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
new file mode 100644 (file)
index 0000000..6cdbd87
--- /dev/null
@@ -0,0 +1,36 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/propagate-approximated-ref.rs:60:9
+   |
+60 |         demand_y(x, y, x.get())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+note: External requirements
+  --> $DIR/propagate-approximated-ref.rs:58:47
+   |
+58 |       establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
+   |  _______________________________________________^
+59 | |         // Only works if 'x: 'y:
+60 | |         demand_y(x, y, x.get())
+61 | |     });
+   | |_____^
+   |
+   = note: defining type: DefId(0/1:18 ~ propagate_approximated_ref[317d]::supply[0]::{{closure}}[0]) with closure substs [
+               i16,
+               for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r(7696))) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's(7697))) u32>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't0(7698))) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't1(7699))) &'_#2r u32>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't2(9524))) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's(7697))) u32>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't3(9525))) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't1(7699))) u32>))
+           ]
+   = note: number of external vids: 3
+   = note: where '_#1r: '_#2r
+
+note: No external requirements
+  --> $DIR/propagate-approximated-ref.rs:57:1
+   |
+57 | / fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+58 | |     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
+59 | |         // Only works if 'x: 'y:
+60 | |         demand_y(x, y, x.get())
+61 | |     });
+62 | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:6 ~ propagate_approximated_ref[317d]::supply[0]) with substs []
+
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-to-empty.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-to-empty.rs
new file mode 100644 (file)
index 0000000..8a6384d
--- /dev/null
@@ -0,0 +1,47 @@
+// Copyright 2016 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.
+
+// Test a case where we fail to approximate one of the regions and
+// hence report an error while checking the closure.
+
+// compile-flags:-Znll -Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+// Callee knows that:
+//
+// 'b: 'y
+//
+// but this doesn't really help us in proving that `'x: 'y`, so closure gets an error.
+fn establish_relationships<'a, 'b, F>(_cell_a: &Cell<&'a u32>, _cell_b: &Cell<&'b u32>, _closure: F)
+where
+    F: for<'x, 'y> FnMut(
+        &Cell<&'y &'b u32>, // shows that 'b: 'y
+        &Cell<&'x u32>,
+        &Cell<&'y u32>,
+    ),
+{
+}
+
+fn demand_y<'x, 'y>(_cell_x: &Cell<&'x u32>, _cell_y: &Cell<&'y u32>, _y: &'y u32) {}
+
+#[rustc_regions]
+fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+    establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
+        // Only works if 'x: 'y:
+        demand_y(x, y, x.get())
+        //~^ WARN not reporting region error due to -Znll
+        //~| ERROR free region `'_#6r` does not outlive free region `'_#4r`
+    });
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-to-empty.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-to-empty.stderr
new file mode 100644 (file)
index 0000000..8d62e49
--- /dev/null
@@ -0,0 +1,46 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/propagate-approximated-to-empty.rs:41:9
+   |
+41 |         demand_y(x, y, x.get())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: free region `'_#6r` does not outlive free region `'_#4r`
+  --> $DIR/propagate-approximated-to-empty.rs:41:21
+   |
+41 |         demand_y(x, y, x.get())
+   |                     ^
+
+note: External requirements
+  --> $DIR/propagate-approximated-to-empty.rs:39:47
+   |
+39 |       establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
+   |  _______________________________________________^
+40 | |         // Only works if 'x: 'y:
+41 | |         demand_y(x, y, x.get())
+42 | |         //~^ WARN not reporting region error due to -Znll
+43 | |         //~| ERROR free region `'_#6r` does not outlive free region `'_#4r`
+44 | |     });
+   | |_____^
+   |
+   = note: defining type: DefId(0/1:18 ~ propagate_approximated_to_empty[317d]::supply[0]::{{closure}}[0]) with closure substs [
+               i16,
+               for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r(7695))) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's(7696))) &'_#1r u32>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't0(7697))) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't1(9522))) u32>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't2(9523))) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's(7696))) u32>))
+           ]
+   = note: number of external vids: 2
+
+note: No external requirements
+  --> $DIR/propagate-approximated-to-empty.rs:38:1
+   |
+38 | / fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+39 | |     establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
+40 | |         // Only works if 'x: 'y:
+41 | |         demand_y(x, y, x.get())
+...  |
+44 | |     });
+45 | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:6 ~ propagate_approximated_to_empty[317d]::supply[0]) with substs []
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-to-static.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-to-static.rs
new file mode 100644 (file)
index 0000000..5e669b3
--- /dev/null
@@ -0,0 +1,46 @@
+// Copyright 2016 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.
+
+// Test a case where we are forced to approximate one end-point with
+// `'static`. Note that `'static` shows up in the stderr output as `'0`.
+
+// compile-flags:-Znll -Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+// Callee knows that:
+//
+// 'x: 'a
+//
+// so the only way we can ensure that `'x: 'y` is to show that
+// `'a: 'static`.
+fn establish_relationships<'a, 'b, F>(_cell_a: &Cell<&'a u32>, _cell_b: &Cell<&'b u32>, _closure: F)
+where
+    F: for<'x, 'y> FnMut(
+        &Cell<&'a &'x u32>, // shows that 'x: 'a
+        &Cell<&'x u32>,
+        &Cell<&'y u32>,
+    ),
+{
+}
+
+fn demand_y<'x, 'y>(_cell_x: &Cell<&'x u32>, _cell_y: &Cell<&'y u32>, _y: &'y u32) {}
+
+#[rustc_regions]
+fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+    establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
+        // Only works if 'x: 'y:
+        demand_y(x, y, x.get())
+    });
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-to-static.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-to-static.stderr
new file mode 100644 (file)
index 0000000..d406433
--- /dev/null
@@ -0,0 +1,36 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/propagate-approximated-to-static.rs:42:9
+   |
+42 |         demand_y(x, y, x.get())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+note: External requirements
+  --> $DIR/propagate-approximated-to-static.rs:40:47
+   |
+40 |       establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
+   |  _______________________________________________^
+41 | |         // Only works if 'x: 'y:
+42 | |         demand_y(x, y, x.get())
+43 | |     });
+   | |_____^
+   |
+   = note: defining type: DefId(0/1:18 ~ propagate_approximated_to_static[317d]::supply[0]::{{closure}}[0]) with closure substs [
+               i16,
+               for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r(7695))) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's(7696))) u32>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't0(7697))) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's(7696))) u32>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't1(9522))) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't2(9523))) u32>))
+           ]
+   = note: number of external vids: 2
+   = note: where '_#1r: '_#0r
+
+note: No external requirements
+  --> $DIR/propagate-approximated-to-static.rs:39:1
+   |
+39 | / fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+40 | |     establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
+41 | |         // Only works if 'x: 'y:
+42 | |         demand_y(x, y, x.get())
+43 | |     });
+44 | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:6 ~ propagate_approximated_to_static[317d]::supply[0]) with substs []
+
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-val.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-val.rs
new file mode 100644 (file)
index 0000000..48d446b
--- /dev/null
@@ -0,0 +1,52 @@
+// Copyright 2016 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.
+
+// A simpler variant of `outlives-from-argument` where cells are
+// passed by value.
+//
+// This is simpler because there are no "extraneous" region
+// relationships. In the 'main' variant, there are a number of
+// anonymous regions as well.
+
+// compile-flags:-Znll -Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+// Callee knows that:
+//
+// 'x: 'a
+// 'b: 'y
+//
+// so if we are going to ensure that `'x: 'y`, then `'a: 'b` must
+// hold.
+fn establish_relationships<'a, 'b, F>(_cell_a: Cell<&'a u32>, _cell_b: Cell<&'b u32>, _closure: F)
+where
+    F: for<'x, 'y> FnMut(
+        Cell<&'a &'x u32>, // shows that 'x: 'a
+        Cell<&'y &'b u32>, // shows that 'b: 'y
+        Cell<&'x u32>,
+        Cell<&'y u32>,
+    ),
+{
+}
+
+fn demand_y<'x, 'y>(_outlives1: Cell<&&'x u32>, _outlives2: Cell<&'y &u32>, _y: &'y u32) {}
+
+#[rustc_regions]
+fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+    establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| {
+        // Only works if 'x: 'y:
+        demand_y(outlives1, outlives2, x.get())
+    });
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
new file mode 100644 (file)
index 0000000..7751454
--- /dev/null
@@ -0,0 +1,36 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/propagate-approximated-val.rs:48:9
+   |
+48 |         demand_y(outlives1, outlives2, x.get())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+note: External requirements
+  --> $DIR/propagate-approximated-val.rs:46:45
+   |
+46 |       establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| {
+   |  _____________________________________________^
+47 | |         // Only works if 'x: 'y:
+48 | |         demand_y(outlives1, outlives2, x.get())
+49 | |     });
+   | |_____^
+   |
+   = note: defining type: DefId(0/1:18 ~ propagate_approximated_val[317d]::test[0]::{{closure}}[0]) with closure substs [
+               i16,
+               for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r(9519))) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's(9520))) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r(9519))) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's(9520))) u32>))
+           ]
+   = note: number of external vids: 3
+   = note: where '_#1r: '_#2r
+
+note: No external requirements
+  --> $DIR/propagate-approximated-val.rs:45:1
+   |
+45 | / fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+46 | |     establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| {
+47 | |         // Only works if 'x: 'y:
+48 | |         demand_y(outlives1, outlives2, x.get())
+49 | |     });
+50 | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:6 ~ propagate_approximated_val[317d]::test[0]) with substs []
+
diff --git a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.rs b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.rs
new file mode 100644 (file)
index 0000000..a28b5f4
--- /dev/null
@@ -0,0 +1,59 @@
+// Copyright 2016 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.
+
+// Test where we might in theory be able to see that the relationship
+// between two bound regions is true within closure and hence have no
+// need to propagate; but in fact we do because identity of free
+// regions is erased.
+
+// compile-flags:-Znll -Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+// In theory, callee knows that:
+//
+// 'x: 'a
+// 'a: 'y
+//
+// and hence could satisfy that `'x: 'y` locally. However, in our
+// checking, we ignore the precise free regions that come into the
+// region and just assign each position a distinct universally bound
+// region. Hence, we propagate a constraint to our caller that will
+// wind up being solvable.
+fn establish_relationships<'a, F>(
+    _cell_a: Cell<&'a u32>,
+    _closure: F,
+) where
+    F: for<'x, 'y> FnMut(
+        Cell<&'a &'x u32>, // shows that 'x: 'a
+        Cell<&'y &'a u32>, // shows that 'a: 'y
+        Cell<&'x u32>,
+        Cell<&'y u32>,
+    ),
+{
+}
+
+fn demand_y<'x, 'y>(_cell_x: Cell<&'x u32>, _cell_y: Cell<&'y u32>, _y: &'y u32) {}
+
+#[rustc_regions]
+fn supply<'a>(cell_a: Cell<&'a u32>) {
+    establish_relationships(
+        cell_a,
+        |_outlives1, _outlives2, x, y| {
+            // Only works if 'x: 'y:
+            let p = x.get();
+            demand_y(x, y, p)
+        },
+    );
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr
new file mode 100644 (file)
index 0000000..87fda8c
--- /dev/null
@@ -0,0 +1,37 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/propagate-despite-same-free-region.rs:53:21
+   |
+53 |             let p = x.get();
+   |                     ^^^^^^^
+
+note: External requirements
+  --> $DIR/propagate-despite-same-free-region.rs:51:9
+   |
+51 | /         |_outlives1, _outlives2, x, y| {
+52 | |             // Only works if 'x: 'y:
+53 | |             let p = x.get();
+54 | |             demand_y(x, y, p)
+55 | |         },
+   | |_________^
+   |
+   = note: defining type: DefId(0/1:16 ~ propagate_despite_same_free_region[317d]::supply[0]::{{closure}}[0]) with closure substs [
+               i16,
+               for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r(9518))) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's(9519))) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r(9518))) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's(9519))) u32>))
+           ]
+   = note: number of external vids: 3
+   = note: where '_#1r: '_#2r
+
+note: No external requirements
+  --> $DIR/propagate-despite-same-free-region.rs:48:1
+   |
+48 | / fn supply<'a>(cell_a: Cell<&'a u32>) {
+49 | |     establish_relationships(
+50 | |         cell_a,
+51 | |         |_outlives1, _outlives2, x, y| {
+...  |
+56 | |     );
+57 | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:6 ~ propagate_despite_same_free_region[317d]::supply[0]) with substs []
+
diff --git a/src/test/ui/nll/closure-requirements/region-ebr-does-not-outlive-static.rs b/src/test/ui/nll/closure-requirements/region-ebr-does-not-outlive-static.rs
new file mode 100644 (file)
index 0000000..fc8b48b
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2016 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.
+
+// Basic test for free regions in the NLL code. This test ought to
+// report an error due to a reborrowing constraint. Right now, we get
+// a variety of errors from the older, AST-based machinery (notably
+// borrowck), and then we get the NLL error at the end.
+
+// compile-flags:-Znll -Zborrowck=mir
+
+fn foo<'a>(x: &'a u32) -> &'static u32
+    where 'static: 'a
+{
+    &*x
+        //~^ WARN not reporting region error due to -Znll
+        //~| ERROR free region `'a` does not outlive free region `'static`
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/closure-requirements/region-ebr-does-not-outlive-static.stderr b/src/test/ui/nll/closure-requirements/region-ebr-does-not-outlive-static.stderr
new file mode 100644 (file)
index 0000000..d3fbbb8
--- /dev/null
@@ -0,0 +1,14 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/region-ebr-does-not-outlive-static.rs:21:5
+   |
+21 |     &*x
+   |     ^^^
+
+error: free region `'a` does not outlive free region `'static`
+  --> $DIR/region-ebr-does-not-outlive-static.rs:21:5
+   |
+21 |     &*x
+   |     ^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs b/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs
new file mode 100644 (file)
index 0000000..ec661bf
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2016 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.
+
+// Basic test for free regions in the NLL code. This test ought to
+// report an error due to a reborrowing constraint. Right now, we get
+// a variety of errors from the older, AST-based machinery (notably
+// borrowck), and then we get the NLL error at the end.
+
+// compile-flags:-Znll
+
+fn foo(x: &u32) -> &'static u32 {
+    &*x
+        //~^ WARN not reporting region error due to -Znll
+        //~| ERROR `*x` does not live long enough
+        //~| ERROR free region `'_#1r` does not outlive free region `'static`
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr b/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr
new file mode 100644 (file)
index 0000000..d5d4a56
--- /dev/null
@@ -0,0 +1,32 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/region-lbr-anon-does-not-outlive-static.rs:19:5
+   |
+19 |     &*x
+   |     ^^^
+
+error[E0597]: `*x` does not live long enough
+  --> $DIR/region-lbr-anon-does-not-outlive-static.rs:19:6
+   |
+19 |     &*x
+   |      ^^ does not live long enough
+   |
+   = note: borrowed value must be valid for the static lifetime...
+note: ...but borrowed value is only valid for the anonymous lifetime #1 defined on the function body at 18:1
+  --> $DIR/region-lbr-anon-does-not-outlive-static.rs:18:1
+   |
+18 | / fn foo(x: &u32) -> &'static u32 {
+19 | |     &*x
+20 | |         //~^ WARN not reporting region error due to -Znll
+21 | |         //~| ERROR `*x` does not live long enough
+22 | |         //~| ERROR free region `'_#1r` does not outlive free region `'static`
+23 | | }
+   | |_^
+
+error: free region `'_#1r` does not outlive free region `'static`
+  --> $DIR/region-lbr-anon-does-not-outlive-static.rs:19:5
+   |
+19 |     &*x
+   |     ^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.rs b/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.rs
new file mode 100644 (file)
index 0000000..f70441c
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2016 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.
+
+// Basic test for free regions in the NLL code. This test ought to
+// report an error due to a reborrowing constraint. Right now, we get
+// a variety of errors from the older, AST-based machinery (notably
+// borrowck), and then we get the NLL error at the end.
+
+// compile-flags:-Znll -Zborrowck=mir
+
+fn foo<'a>(x: &'a u32) -> &'static u32 {
+    &*x
+        //~^ WARN not reporting region error due to -Znll
+        //~| ERROR free region `'_#1r` does not outlive free region `'static`
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr b/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr
new file mode 100644 (file)
index 0000000..a54e7b6
--- /dev/null
@@ -0,0 +1,14 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/region-lbr-named-does-not-outlive-static.rs:19:5
+   |
+19 |     &*x
+   |     ^^^
+
+error: free region `'_#1r` does not outlive free region `'static`
+  --> $DIR/region-lbr-named-does-not-outlive-static.rs:19:5
+   |
+19 |     &*x
+   |     ^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.rs b/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.rs
new file mode 100644 (file)
index 0000000..94a234b
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2016 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.
+
+// Basic test for free regions in the NLL code. This test ought to
+// report an error due to a reborrowing constraint. Right now, we get
+// a variety of errors from the older, AST-based machinery (notably
+// borrowck), and then we get the NLL error at the end.
+
+// compile-flags:-Znll -Zborrowck=mir
+
+fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> &'b u32 {
+    &*x
+        //~^ WARN not reporting region error due to -Znll
+        //~| ERROR free region `'_#1r` does not outlive free region `'_#2r`
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr b/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr
new file mode 100644 (file)
index 0000000..c1b2f44
--- /dev/null
@@ -0,0 +1,14 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/region-lbr1-does-not-outlive-ebr2.rs:19:5
+   |
+19 |     &*x
+   |     ^^^
+
+error: free region `'_#1r` does not outlive free region `'_#2r`
+  --> $DIR/region-lbr1-does-not-outlive-ebr2.rs:19:5
+   |
+19 |     &*x
+   |     ^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/closure-requirements/region-lbr1-does-outlive-lbr2-because-implied-bound.rs b/src/test/ui/nll/closure-requirements/region-lbr1-does-outlive-lbr2-because-implied-bound.rs
new file mode 100644 (file)
index 0000000..d63fd04
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2016 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.
+
+// Basic test for free regions in the NLL code. This test does not
+// report an error because of the (implied) bound that `'b: 'a`.
+
+// compile-flags:-Znll
+// must-compile-successfully
+
+#![allow(warnings)]
+
+fn foo<'a, 'b>(x: &'a &'b u32) -> &'a u32 {
+    &**x
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.rs b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.rs
new file mode 100644 (file)
index 0000000..9314bbf
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright 2016 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.
+
+// Test closure that takes two references and is supposed to return
+// the first, but actually returns the second. This should fail within
+// the closure.
+
+// compile-flags:-Znll -Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+
+#[rustc_regions]
+fn test() {
+    expect_sig(|a, b| b); // ought to return `a`
+    //~^ WARN not reporting region error due to -Znll
+    //~| ERROR free region `'_#3r` does not outlive free region `'_#2r`
+}
+
+fn expect_sig<F>(f: F) -> F
+    where F: for<'a> FnMut(&'a i32, &i32) -> &'a i32
+{
+    f
+}
+
+fn deref(_p: &i32) { }
+
+fn main() { }
diff --git a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr
new file mode 100644 (file)
index 0000000..ba0c6cd
--- /dev/null
@@ -0,0 +1,38 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/return-wrong-bound-region.rs:21:23
+   |
+21 |     expect_sig(|a, b| b); // ought to return `a`
+   |                       ^
+
+error: free region `'_#3r` does not outlive free region `'_#2r`
+  --> $DIR/return-wrong-bound-region.rs:21:23
+   |
+21 |     expect_sig(|a, b| b); // ought to return `a`
+   |                       ^
+
+note: External requirements
+  --> $DIR/return-wrong-bound-region.rs:21:16
+   |
+21 |     expect_sig(|a, b| b); // ought to return `a`
+   |                ^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:9 ~ return_wrong_bound_region[317d]::test[0]::{{closure}}[0]) with closure substs [
+               i16,
+               for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r(7661))) i32, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's(8630))) i32)) -> &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r(7661))) i32
+           ]
+   = note: number of external vids: 1
+
+note: No external requirements
+  --> $DIR/return-wrong-bound-region.rs:20:1
+   |
+20 | / fn test() {
+21 | |     expect_sig(|a, b| b); // ought to return `a`
+22 | |     //~^ WARN not reporting region error due to -Znll
+23 | |     //~| ERROR free region `'_#3r` does not outlive free region `'_#2r`
+24 | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:3 ~ return_wrong_bound_region[317d]::test[0]) with substs []
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/closure-requirements/via-upvar-nested.stderr b/src/test/ui/nll/closure-requirements/via-upvar-nested.stderr
new file mode 100644 (file)
index 0000000..ba06888
--- /dev/null
@@ -0,0 +1,87 @@
+note: External requirements
+  --> $DIR/via-upvar-nested.rs:24:28
+   |
+24 |             let closure1 = || p = &y;
+   |                            ^^^^^^^^^
+   |
+   = note: _0: ()
+   = note: _1: &mut [closure@$DIR/via-upvar-nested.rs:24:28: 24:37 p:&mut &i32, y:&i32]
+
+note: External requirements
+  --> $DIR/via-upvar-nested.rs:23:27
+   |
+23 |           let mut closure = || {
+   |  ___________________________^
+24 | |             let closure1 = || p = &y;
+25 | |             closure1();
+26 | |         };
+   | |_________^
+   |
+   = note: _0: ()
+   = note: _1: &mut [closure@$DIR/via-upvar-nested.rs:23:27: 26:10 p:&mut &i32, y:&i32]
+   = note: where '_#1r: '_#2r
+
+error[E0596]: cannot borrow immutable item `closure1` as mutable (Mir)
+  --> $DIR/via-upvar-nested.rs:25:13
+   |
+25 |             closure1();
+   |             ^^^^^^^^ cannot borrow as mutable
+
+error[E0597]: `**y` does not live long enough (Ast)
+  --> $DIR/via-upvar-nested.rs:24:36
+   |
+24 |             let closure1 = || p = &y;
+   |                            --      ^ does not live long enough
+   |                            |
+   |                            capture occurs here
+...
+29 |     }
+   |     - borrowed value only lives until here
+...
+32 | }
+   | - borrowed value needs to live until here
+
+error[E0596]: cannot borrow immutable local variable `closure1` as mutable (Ast)
+  --> $DIR/via-upvar-nested.rs:25:13
+   |
+24 |             let closure1 = || p = &y;
+   |                 -------- consider changing this to `mut closure1`
+25 |             closure1();
+   |             ^^^^^^^^ cannot borrow mutably
+
+note: No external requirements
+  --> $DIR/via-upvar-nested.rs:16:1
+   |
+16 | / fn test() {
+17 | |     let x = 44;
+18 | |     let mut p = &x;
+19 | |
+...  |
+31 | |     deref(p);
+32 | | }
+   | |_^
+
+error[E0597]: borrowed value does not live long enough (Mir)
+  --> $DIR/via-upvar-nested.rs:29:6
+   |
+21 |         let y = 22;
+   |             - temporary value created here
+...
+29 |     }
+   |      ^ temporary value dropped here while still borrowed
+   |
+   = note: consider using a `let` binding to increase its lifetime
+
+error[E0502]: cannot borrow `(*p)` as immutable because it is also borrowed as mutable (Mir)
+  --> $DIR/via-upvar-nested.rs:31:11
+   |
+23 |         let mut closure = || {
+   |                           -- mutable borrow occurs here
+24 |             let closure1 = || p = &y;
+   |                               - previous borrow occurs due to use of `(*p)` in closure
+...
+31 |     deref(p);
+   |           ^ immutable borrow occurs here
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/nll/named-region-basic.rs b/src/test/ui/nll/named-region-basic.rs
deleted file mode 100644 (file)
index 001ce41..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2016 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.
-
-// Basic test for free regions in the NLL code. This test ought to
-// report an error due to a reborrowing constraint. Right now, we get
-// a variety of errors from the older, AST-based machinery (notably
-// borrowck), and then we get the NLL error at the end.
-
-// compile-flags:-Znll
-
-fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> &'b u32 {
-    &*x //~ ERROR free region `'a` does not outlive `'b`
-    //~^ ERROR `*x` does not live long enough
-    //~| WARN not reporting region error due to -Znll
-}
-
-fn main() { }
diff --git a/src/test/ui/nll/named-region-basic.stderr b/src/test/ui/nll/named-region-basic.stderr
deleted file mode 100644 (file)
index 9c1de6c..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-warning: not reporting region error due to -Znll
-  --> $DIR/named-region-basic.rs:19:5
-   |
-19 |     &*x //~ ERROR free region `'a` does not outlive `'b`
-   |     ^^^
-
-error[E0597]: `*x` does not live long enough
-  --> $DIR/named-region-basic.rs:19:6
-   |
-19 |     &*x //~ ERROR free region `'a` does not outlive `'b`
-   |      ^^ does not live long enough
-   |
-   = note: borrowed value must be valid for the static lifetime...
-note: ...but borrowed value is only valid for the lifetime 'a as defined on the function body at 18:1
-  --> $DIR/named-region-basic.rs:18:1
-   |
-18 | / fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> &'b u32 {
-19 | |     &*x //~ ERROR free region `'a` does not outlive `'b`
-20 | |     //~^ ERROR `*x` does not live long enough
-21 | |     //~| WARN not reporting region error due to -Znll
-22 | | }
-   | |_^
-
-error: free region `'a` does not outlive `'b`
-  --> $DIR/named-region-basic.rs:19:5
-   |
-19 |     &*x //~ ERROR free region `'a` does not outlive `'b`
-   |     ^^^
-
-error: aborting due to 2 previous errors
-