// Run the MIR type-checker.
let mir_node_id = infcx.tcx.hir.as_local_node_id(def_id).unwrap();
let liveness = &LivenessResults::compute(mir);
+ let fr_fn_body = infcx.tcx.mk_region(ty::ReVar(universal_regions.fr_fn_body));
let constraint_sets = &type_check::type_check(
infcx,
mir_node_id,
param_env,
mir,
+ fr_fn_body,
&liveness,
flow_inits,
move_data,
/// have no evidence that `'b` outlives `'a`, so we want to report
/// an error.
fn check_type_tests(&self, infcx: &InferCtxt<'_, '_, 'tcx>, mir: &Mir<'tcx>) {
+ let tcx = infcx.tcx;
+
for type_test in &self.type_tests {
debug!("check_type_test: {:?}", type_test);
}
// Oh the humanity. Obviously we will do better than this error eventually.
- infcx.tcx.sess.span_err(
+ tcx.sess.span_err(
type_test.span,
&format!("failed type test: {:?}", type_test),
);
body_id: ast::NodeId,
param_env: ty::ParamEnv<'gcx>,
mir: &Mir<'tcx>,
+ implicit_region_bound: ty::Region<'tcx>,
liveness: &LivenessResults,
flow_inits: &mut FlowAtLocation<MaybeInitializedLvals<'_, 'gcx, 'tcx>>,
move_data: &MoveData<'tcx>,
) -> MirTypeckRegionConstraints<'tcx> {
- type_check_internal(infcx, body_id, param_env, mir, &mut |cx| {
- liveness::generate(cx, mir, liveness, flow_inits, move_data)
- })
+ type_check_internal(
+ infcx,
+ body_id,
+ param_env,
+ mir,
+ Some(implicit_region_bound),
+ &mut |cx| liveness::generate(cx, mir, liveness, flow_inits, move_data),
+ )
}
fn type_check_internal<'gcx, 'tcx>(
body_id: ast::NodeId,
param_env: ty::ParamEnv<'gcx>,
mir: &Mir<'tcx>,
+ implicit_region_bound: Option<ty::Region<'tcx>>,
extra: &mut FnMut(&mut TypeChecker<'_, 'gcx, 'tcx>),
) -> MirTypeckRegionConstraints<'tcx> {
- let mut checker = TypeChecker::new(infcx, body_id, param_env);
+ let mut checker = TypeChecker::new(infcx, body_id, param_env, implicit_region_bound);
let errors_reported = {
let mut verifier = TypeVerifier::new(&mut checker, mir);
verifier.visit_mir(mir);
param_env: ty::ParamEnv<'gcx>,
last_span: Span,
body_id: ast::NodeId,
+ implicit_region_bound: Option<ty::Region<'tcx>>,
reported_errors: FxHashSet<(Ty<'tcx>, Span)>,
constraints: MirTypeckRegionConstraints<'tcx>,
}
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
body_id: ast::NodeId,
param_env: ty::ParamEnv<'gcx>,
+ implicit_region_bound: Option<ty::Region<'tcx>>,
) -> Self {
TypeChecker {
infcx,
last_span: DUMMY_SP,
body_id,
param_env,
+ implicit_region_bound,
reported_errors: FxHashSet(),
constraints: MirTypeckRegionConstraints::default(),
}
span_mirbug!(self, "", "errors selecting obligation: {:?}", e);
}
- self.infcx
- .process_registered_region_obligations(&[], None, self.param_env, self.body_id);
+ self.infcx.process_registered_region_obligations(
+ &[],
+ self.implicit_region_bound,
+ self.param_env,
+ self.body_id,
+ );
let data = self.infcx.take_and_reset_region_constraints();
if !data.is_empty() {
}
let param_env = tcx.param_env(def_id);
tcx.infer_ctxt().enter(|infcx| {
- let _ = type_check_internal(&infcx, id, param_env, mir, &mut |_| ());
+ let _ = type_check_internal(&infcx, id, param_env, mir, None, &mut |_| ());
// For verification purposes, we just ignore the resulting
// region constraint sets. Not our problem. =)
/// The vid assigned to `'static`
pub fr_static: RegionVid,
+ /// A special region vid created to represent the current MIR fn
+ /// body. It will outlive the entire CFG but it will not outlive
+ /// any other universal regions.
+ pub fr_fn_body: RegionVid,
+
/// We create region variables such that they are ordered by their
/// `RegionClassification`. The first block are globals, then
/// externals, then locals. So things from:
let first_local_index = self.infcx.num_region_vars();
let inputs_and_output = self.infcx
.replace_bound_regions_with_nll_infer_vars(FR, &bound_inputs_and_output);
+ let fr_fn_body = self.infcx.next_nll_region_var(FR).to_region_vid();
let num_universals = self.infcx.num_region_vars();
// Insert the facts we know from the predicates. Why? Why not.
self.add_implied_bounds(&indices, ty);
}
- // Finally, outlives is reflexive, and static outlives every
- // other free region.
+ // Finally:
+ // - outlives is reflexive, so `'r: 'r` for every region `'r`
+ // - `'static: 'r` for every region `'r`
+ // - `'r: 'fn_body` for every (other) universally quantified
+ // region `'r`, all of which are provided by our caller
for fr in (FIRST_GLOBAL_INDEX..num_universals).map(RegionVid::new) {
debug!("build: relating free region {:?} to itself and to 'static", fr);
self.relations.relate_universal_regions(fr, fr);
self.relations.relate_universal_regions(fr_static, fr);
+ self.relations.relate_universal_regions(fr, fr_fn_body);
}
let (output_ty, input_tys) = inputs_and_output.split_last().unwrap();
UniversalRegions {
indices,
fr_static,
+ fr_fn_body,
first_extern_index,
first_local_index,
num_universals,
// END RUST SOURCE
// START rustc.use_x.nll.0.mir
// | Free Region Mapping
-// | '_#0r | Global | ['_#2r, '_#1r, '_#0r, '_#3r]
-// | '_#1r | External | ['_#1r]
-// | '_#2r | External | ['_#2r, '_#1r]
-// | '_#3r | Local | ['_#3r]
+// | '_#0r | Global | ['_#2r, '_#1r, '_#0r, '_#4r, '_#3r]
+// | '_#1r | External | ['_#1r, '_#4r]
+// | '_#2r | External | ['_#2r, '_#1r, '_#4r]
+// | '_#3r | Local | ['_#4r, '_#3r]
+// | '_#4r | Local | ['_#4r]
// |
// | Inferred Region Values
// | '_#0r | {'_#0r, bb0[0], bb0[1]}
// | '_#1r | {'_#1r, bb0[0], bb0[1]}
// | '_#2r | {'_#2r, bb0[0], bb0[1]}
// | '_#3r | {'_#3r, bb0[0], bb0[1]}
+// | '_#4r | {'_#4r, bb0[0], bb0[1]}
// |
// ...
// fn use_x(_1: &'_#1r mut i32, _2: &'_#2r u32, _3: &'_#1r u32, _4: &'_#3r u32) -> bool {
// 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]}
+// | '_#7r | {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]}
+// | '_#9r | {bb0[11], bb0[12], bb0[13], bb0[14]}
// ...
-// let _2: &'_#6r mut i32;
+// let _2: &'_#7r mut i32;
// ...
-// let _4: &'_#8r mut i32;
+// let _4: &'_#9r mut i32;
// END rustc.main.nll.0.mir
// 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]}
+// | '_#2r | {bb2[0], bb2[1], bb3[0], bb3[1]}
+// | '_#3r | {bb2[1], bb3[0], bb3[1]}
// ...
-// let _2: &'_#2r usize;
+// let _2: &'_#3r usize;
// END rustc.main.nll.0.mir
// START rustc.main.nll.0.mir
// bb2: {
// | Live variables on entry to bb2[0]: [_1, _3]
-// _2 = &'_#1r _1[_3];
+// _2 = &'_#2r _1[_3];
// | Live variables on entry to bb2[1]: [_2]
// switchInt(const true) -> [0u8: bb4, otherwise: bb3];
// }
// END RUST SOURCE
// START rustc.main.nll.0.mir
-// | '_#5r | {bb2[3], bb2[4], bb2[5], bb3[0], bb3[1]}
+// | '_#6r | {bb2[3], bb2[4], bb2[5], bb3[0], bb3[1]}
+// ...
+// let _2: Wrap<&'_#6r usize>;
// 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]}
+// | '_#6r | {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]}
+// ...
+// let _2: Wrap<&'_#6r usize>;
// END rustc.main.nll.0.mir
// END RUST SOURCE
// START rustc.main.nll.0.mir
-// | '_#1r | {bb2[0], bb2[1], bb3[0], bb3[1]}
+// | '_#2r | {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]}
+// | '_#4r | {bb8[1], bb8[2], bb8[3], bb8[4]}
+// | '_#5r | {bb2[1], bb3[0], bb3[1], bb8[2], bb8[3], bb8[4]}
// ...
-// let mut _2: &'_#4r usize;
+// let mut _2: &'_#5r usize;
// ...
-// _2 = &'_#1r _1[_3];
+// _2 = &'_#2r _1[_3];
// ...
-// _2 = &'_#3r (*_10);
+// _2 = &'_#4r (*_10);
// END rustc.main.nll.0.mir
// 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]}
+// | '_#2r | {bb2[0], bb2[1], bb2[2], bb2[3], bb2[4], bb2[5], bb2[6], bb3[0], bb3[1]}
+// | '_#3r | {bb2[1], bb2[2], bb2[3], bb2[4], bb2[5], bb2[6], bb3[0], bb3[1]}
+// | '_#4r | {bb2[5], bb2[6], bb3[0], bb3[1]}
// END rustc.main.nll.0.mir
// START rustc.main.nll.0.mir
-// let _2: &'_#2r usize;
+// let _2: &'_#3r usize;
// ...
-// let _6: &'_#3r usize;
+// let _6: &'_#4r usize;
// ...
-// _2 = &'_#1r _1[_3];
+// _2 = &'_#2r _1[_3];
// ...
// _7 = _2;
// ...
37 | }
| - borrowed value only lives until here
|
- = note: borrowed value must be valid for lifetime '_#4r...
+ = note: borrowed value must be valid for lifetime '_#5r...
error: aborting due to previous error
39 | }
| - borrowed value only lives until here
|
- = note: borrowed value must be valid for lifetime '_#5r...
+ = note: borrowed value must be valid for lifetime '_#6r...
error: aborting due to previous error
36 | }
| - borrowed value only lives until here
|
- = note: borrowed value must be valid for lifetime '_#3r...
+ = note: borrowed value must be valid for lifetime '_#4r...
error: aborting due to previous error
36 | }
| - borrowed value only lives until here
|
- = note: borrowed value must be valid for lifetime '_#3r...
+ = note: borrowed value must be valid for lifetime '_#4r...
error: aborting due to previous error
49 | }
| - borrowed value only lives until here
|
- = note: borrowed value must be valid for lifetime '_#1r...
+ = note: borrowed value must be valid for lifetime '_#2r...
error: aborting due to 2 previous errors
40 | Box::new(x.next())
| ^^^^^^^^^^^^^^^^^^
-error: failed type test: TypeTest { generic_kind: ProjectionTy { substs: Slice([T]), item_def_id: DefId(2/0:1695 ~ core[2633]::iter[0]::iterator[0]::Iterator[0]::Item[0]) }, lower_bound: '_#3r, point: bb5[0], span: $DIR/projection-fn.rs:24:5: 24:23, test: IsOutlivedByAnyRegionIn([]) }
+error: failed type test: TypeTest { generic_kind: ProjectionTy { substs: Slice([T]), item_def_id: DefId(2/0:1695 ~ core[2633]::iter[0]::iterator[0]::Iterator[0]::Item[0]) }, lower_bound: '_#4r, point: bb5[0], span: $DIR/projection-fn.rs:24:5: 24:23, test: IsOutlivedByAnyRegionIn(['_#2r]) }
--> $DIR/projection-fn.rs:24:5
|
24 | Box::new(x.next())
| ^^^^^^^^^^^^^^^^^^
-error: failed type test: TypeTest { generic_kind: ProjectionTy { substs: Slice([T]), item_def_id: DefId(2/0:1695 ~ core[2633]::iter[0]::iterator[0]::Iterator[0]::Item[0]) }, lower_bound: '_#4r, point: bb5[0], span: $DIR/projection-fn.rs:40:5: 40:23, test: IsOutlivedByAnyRegionIn(['_#2r]) }
+error: failed type test: TypeTest { generic_kind: ProjectionTy { substs: Slice([T]), item_def_id: DefId(2/0:1695 ~ core[2633]::iter[0]::iterator[0]::Iterator[0]::Item[0]) }, lower_bound: '_#5r, point: bb5[0], span: $DIR/projection-fn.rs:40:5: 40:23, test: IsOutlivedByAnyRegionIn(['_#2r, '_#3r]) }
--> $DIR/projection-fn.rs:40:5
|
40 | Box::new(x.next())
--- /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 we assume that universal types like `T` outlive the
+// function body.
+
+#![allow(warnings)]
+#![feature(dyn_trait)]
+
+use std::cell::Cell;
+
+// No errors here, because `'a` is local to the body.
+fn region_within_body<T>(t: T) {
+ let some_int = 22;
+ let cell = Cell::new(&some_int);
+ outlives(cell, t)
+}
+
+// Error here, because T: 'a is not satisfied.
+fn region_static<'a, T>(cell: Cell<&'a usize>, t: T) {
+ outlives(cell, t)
+ //~^ WARNING not reporting region error due to -Znll
+ //~| ERROR failed type test
+}
+
+fn outlives<'a, T>(x: Cell<&'a usize>, y: T)
+where
+ T: 'a,
+{
+}
+
+fn main() {}
--- /dev/null
+warning: not reporting region error due to -Znll
+ --> $DIR/ty-param-fn-body.rs:30:5
+ |
+30 | outlives(cell, t)
+ | ^^^^^^^^
+
+error: failed type test: TypeTest { generic_kind: T/#0, lower_bound: '_#4r, point: bb0[4], span: $DIR/ty-param-fn-body.rs:30:5: 30:22, test: IsOutlivedByAnyRegionIn(['_#2r]) }
+ --> $DIR/ty-param-fn-body.rs:30:5
+ |
+30 | outlives(cell, t)
+ | ^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
38 | x
| ^
-error: failed type test: TypeTest { generic_kind: T/#1, lower_bound: '_#2r, point: bb0[3], span: $DIR/ty-param-fn.rs:22:5: 22:6, test: IsOutlivedByAnyRegionIn([]) }
+error: failed type test: TypeTest { generic_kind: T/#1, lower_bound: '_#3r, point: bb0[3], span: $DIR/ty-param-fn.rs:22:5: 22:6, test: IsOutlivedByAnyRegionIn(['_#2r]) }
--> $DIR/ty-param-fn.rs:22:5
|
22 | x
| ^
-error: failed type test: TypeTest { generic_kind: T/#2, lower_bound: '_#3r, point: bb0[3], span: $DIR/ty-param-fn.rs:38:5: 38:6, test: IsOutlivedByAnyRegionIn(['_#2r]) }
+error: failed type test: TypeTest { generic_kind: T/#2, lower_bound: '_#4r, point: bb0[3], span: $DIR/ty-param-fn.rs:38:5: 38:6, test: IsOutlivedByAnyRegionIn(['_#2r, '_#3r]) }
--> $DIR/ty-param-fn.rs:38:5
|
38 | x