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};
use dataflow::move_paths::MoveData;
use util as mir_util;
+use util::pretty::{self, ALIGN};
use self::mir_util::PassWhere;
mod constraint_generation;
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, ®ioncx);
+ // write unit-tests, as well as helping with debugging.
+ dump_mir_results(
+ infcx,
+ liveness,
+ MirSource::item(def_id),
+ &mir,
+ ®ioncx,
+ &closure_region_requirements,
+ );
+
+ // We also have a `#[rustc_nll]` annotation that causes us to dump
+ // information
+ dump_annotation(infcx, &mir, def_id, ®ioncx, &closure_region_requirements);
(regioncx, closure_region_requirements)
}
source: MirSource,
mir: &Mir<'tcx>,
regioncx: &RegionInferenceContext,
+ closure_region_requirements: &Option<ClosureRegionRequirements>,
) {
if !mir_util::dump_enabled(infcx.tcx, "nll", source) {
return;
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.
®ular_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
--- /dev/null
+// 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
+ ));
+ }
+ }
+ }
+}
--- /dev/null
+// 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(())
+ }
+}
+
--- /dev/null
+// 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
+ }
+}
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
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 \
// 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
// 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
// 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
// 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
// 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;
// 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
// 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
// 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
// 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;
// ...
// 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;
--- /dev/null
+// 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() { }
--- /dev/null
+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
+
--- /dev/null
+// 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() { }
--- /dev/null
+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
+
--- /dev/null
+// 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() { }
--- /dev/null
+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
+
--- /dev/null
+// 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() { }
--- /dev/null
+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
+
--- /dev/null
+// 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() { }
--- /dev/null
+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
+
--- /dev/null
+// 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() {}
--- /dev/null
+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
+
--- /dev/null
+// 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() {}
--- /dev/null
+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 []
+
--- /dev/null
+// 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() {}
--- /dev/null
+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
+
--- /dev/null
+// 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() {}
--- /dev/null
+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 []
+
--- /dev/null
+// 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() {}
--- /dev/null
+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 []
+
--- /dev/null
+// 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() {}
--- /dev/null
+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 []
+
--- /dev/null
+// 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() { }
--- /dev/null
+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
+
--- /dev/null
+// 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() { }
--- /dev/null
+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
+
--- /dev/null
+// 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() { }
--- /dev/null
+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
+
--- /dev/null
+// 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() { }
--- /dev/null
+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
+
--- /dev/null
+// 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() { }
--- /dev/null
+// 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() { }
--- /dev/null
+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
+
--- /dev/null
+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
+
+++ /dev/null
-// 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() { }
+++ /dev/null
-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
-