mir_node_id,
param_env,
mir,
+ &universal_regions.region_bound_pairs,
fr_fn_body,
universal_regions.input_tys,
universal_regions.output_ty,
use dataflow::MaybeInitializedLvals;
use dataflow::move_paths::MoveData;
use rustc::infer::{InferCtxt, InferOk, InferResult, LateBoundRegionConversionTime, UnitResult};
-use rustc::infer::region_constraints::RegionConstraintData;
+use rustc::infer::region_constraints::{GenericKind, RegionConstraintData};
use rustc::traits::{self, FulfillmentContext};
use rustc::ty::error::TypeError;
use rustc::ty::fold::TypeFoldable;
/// - `body_id` -- body-id of the MIR being checked
/// - `param_env` -- parameter environment to use for trait solving
/// - `mir` -- MIR to type-check
+/// - `region_bound_pairs` -- the implied outlives obligations between type parameters
+/// and lifetimes (e.g., `&'a T` implies `T: 'a`)
/// - `implicit_region_bound` -- a region which all generic parameters are assumed
/// to outlive; should represent the fn body
/// - `input_tys` -- fully liberated, but **not** normalized, expected types of the arguments;
body_id: ast::NodeId,
param_env: ty::ParamEnv<'gcx>,
mir: &Mir<'tcx>,
+ region_bound_pairs: &[(ty::Region<'tcx>, GenericKind<'tcx>)],
implicit_region_bound: ty::Region<'tcx>,
input_tys: &[Ty<'tcx>],
output_ty: Ty<'tcx>,
body_id,
param_env,
mir,
+ region_bound_pairs,
Some(implicit_region_bound),
&mut |cx| {
liveness::generate(cx, mir, liveness, flow_inits, move_data);
body_id: ast::NodeId,
param_env: ty::ParamEnv<'gcx>,
mir: &Mir<'tcx>,
+ region_bound_pairs: &[(ty::Region<'tcx>, GenericKind<'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, implicit_region_bound);
+ let mut checker = TypeChecker::new(
+ infcx,
+ body_id,
+ param_env,
+ region_bound_pairs,
+ 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,
+ region_bound_pairs: &'a [(ty::Region<'tcx>, GenericKind<'tcx>)],
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>,
+ region_bound_pairs: &'a [(ty::Region<'tcx>, GenericKind<'tcx>)],
implicit_region_bound: Option<ty::Region<'tcx>>,
) -> Self {
TypeChecker {
last_span: DUMMY_SP,
body_id,
param_env,
+ region_bound_pairs,
implicit_region_bound,
reported_errors: FxHashSet(),
constraints: MirTypeckRegionConstraints::default(),
}
self.infcx.process_registered_region_obligations(
- &[],
+ self.region_bound_pairs,
self.implicit_region_bound,
self.param_env,
self.body_id,
);
};
}
- StatementKind::StorageLive(_) |
- StatementKind::StorageDead(_) |
- StatementKind::InlineAsm { .. } |
- StatementKind::EndRegion(_) |
- StatementKind::Validate(..) |
- StatementKind::Nop => {}
+ StatementKind::StorageLive(_)
+ | StatementKind::StorageDead(_)
+ | StatementKind::InlineAsm { .. }
+ | StatementKind::EndRegion(_)
+ | StatementKind::Validate(..)
+ | StatementKind::Nop => {}
}
}
debug!("check_terminator: {:?}", term);
let tcx = self.tcx();
match term.kind {
- TerminatorKind::Goto { .. } |
- TerminatorKind::Resume |
- TerminatorKind::Return |
- TerminatorKind::GeneratorDrop |
- TerminatorKind::Unreachable |
- TerminatorKind::Drop { .. } |
- TerminatorKind::FalseEdges { .. } => {
+ TerminatorKind::Goto { .. }
+ | TerminatorKind::Resume
+ | TerminatorKind::Return
+ | TerminatorKind::GeneratorDrop
+ | TerminatorKind::Unreachable
+ | TerminatorKind::Drop { .. }
+ | TerminatorKind::FalseEdges { .. } => {
// no checks needed for these
}
// output) types in the signature must be live, since
// all the inputs that fed into it were live.
for &late_bound_region in map.values() {
- self.constraints
- .liveness_set
- .push((late_bound_region, term_location, Cause::LiveOther(term_location)));
+ self.constraints.liveness_set.push((
+ late_bound_region,
+ term_location,
+ Cause::LiveOther(term_location),
+ ));
}
if self.is_box_free(func) {
}
}
TerminatorKind::Unreachable => {}
- TerminatorKind::Drop { target, unwind, .. } |
- TerminatorKind::DropAndReplace { target, unwind, .. } |
- TerminatorKind::Assert {
+ TerminatorKind::Drop { target, unwind, .. }
+ | TerminatorKind::DropAndReplace { target, unwind, .. }
+ | TerminatorKind::Assert {
target,
cleanup: unwind,
..
},
// FIXME: These other cases have to be implemented in future PRs
- Rvalue::Use(..) |
- Rvalue::Ref(..) |
- Rvalue::Len(..) |
- Rvalue::BinaryOp(..) |
- Rvalue::CheckedBinaryOp(..) |
- Rvalue::UnaryOp(..) |
- Rvalue::Discriminant(..) => {}
+ Rvalue::Use(..)
+ | Rvalue::Ref(..)
+ | Rvalue::Len(..)
+ | Rvalue::BinaryOp(..)
+ | Rvalue::CheckedBinaryOp(..)
+ | Rvalue::UnaryOp(..)
+ | Rvalue::Discriminant(..) => {}
}
}
let cause = this.misc(this.last_span);
let obligations = predicates
.iter()
- .map(|&p| {
- traits::Obligation::new(cause.clone(), this.param_env, p)
- })
+ .map(|&p| traits::Obligation::new(cause.clone(), this.param_env, p))
.collect();
Ok(InferOk {
value: (),
}
let param_env = tcx.param_env(def_id);
tcx.infer_ctxt().enter(|infcx| {
- let _ = type_check_internal(&infcx, id, param_env, mir, None, &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. =)
--- /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 -Zverbose
+
+// Test that we can deduce when projections like `T::Item` outlive the
+// function body. Test that this does not imply that `T: 'a` holds.
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+fn twice<F, T>(mut value: T, mut f: F)
+where
+ F: FnMut(&T, Cell<&Option<T::Item>>),
+ T: Iterator,
+{
+ let mut n = value.next();
+ f(&value, Cell::new(&n));
+ f(&value, Cell::new(&n));
+}
+
+#[rustc_errors]
+fn generic1<T: Iterator>(value: T) {
+ // No error here:
+ twice(value, |value_ref, item| invoke1(item));
+}
+
+fn invoke1<'a, T>(x: Cell<&'a Option<T>>)
+where
+ T: 'a,
+{
+}
+
+#[rustc_errors]
+fn generic2<T: Iterator>(value: T) {
+ twice(value, |value_ref, item| invoke2(value_ref, item));
+ //~^ WARNING not reporting region error due to -Znll
+ //~| ERROR `T` does not outlive
+}
+
+fn invoke2<'a, T, U>(a: &T, b: Cell<&'a Option<U>>)
+where
+ T: 'a,
+{
+}
+
+fn main() {}
--- /dev/null
+warning: not reporting region error due to -Znll
+ --> $DIR/projection-implied-bounds.rs:45:36
+ |
+45 | twice(value, |value_ref, item| invoke2(value_ref, item));
+ | ^^^^^^^
+
+error: `T` does not outlive `'_#0r`
+ --> $DIR/projection-implied-bounds.rs:45:18
+ |
+45 | twice(value, |value_ref, item| invoke2(value_ref, item));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+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.
+
+// compile-flags:-Znll -Zborrowck=mir -Zverbose
+
+#![allow(warnings)]
+#![feature(dyn_trait)]
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+// Invoke in such a way that the callee knows:
+//
+// - 'a: 'x
+//
+// and it must prove that `T: 'x`. Callee passes along `T: 'a`.
+fn twice<'a, F, T>(v: Cell<&'a ()>, value: T, mut f: F)
+where
+ F: for<'x> FnMut(Option<Cell<&'a &'x ()>>, &T),
+{
+ f(None, &value);
+ f(None, &value);
+}
+
+#[rustc_regions]
+fn generic<T>(value: T) {
+ let cell = Cell::new(&());
+ twice(cell, value, |a, b| invoke(a, b));
+ //~^ WARNING not reporting region error
+ //
+ // This error from the old region solver looks bogus.
+}
+
+#[rustc_regions]
+fn generic_fail<'a, T>(cell: Cell<&'a ()>, value: T) {
+ twice(cell, value, |a, b| invoke(a, b));
+ //~^ WARNING not reporting region error
+ //~| WARNING not reporting region error
+ //~| ERROR `T` does not outlive
+}
+
+fn invoke<'a, 'x, T>(x: Option<Cell<&'x &'a ()>>, y: &T)
+where
+ T: 'x,
+{
+}
+
+fn main() {}
--- /dev/null
+warning: not reporting region error due to -Znll
+ --> $DIR/ty-param-closure-approximate-lower-bound.rs:35:31
+ |
+35 | twice(cell, value, |a, b| invoke(a, b));
+ | ^^^^^^^^^^^^
+
+warning: not reporting region error due to -Znll
+ --> $DIR/ty-param-closure-approximate-lower-bound.rs:43:31
+ |
+43 | twice(cell, value, |a, b| invoke(a, b));
+ | ^^^^^^
+
+warning: not reporting region error due to -Znll
+ --> $DIR/ty-param-closure-approximate-lower-bound.rs:43:31
+ |
+43 | twice(cell, value, |a, b| invoke(a, b));
+ | ^^^^^^^^^^^^
+
+note: External requirements
+ --> $DIR/ty-param-closure-approximate-lower-bound.rs:35:24
+ |
+35 | twice(cell, value, |a, b| invoke(a, b));
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+ = note: defining type: DefId(0/1:14 ~ ty_param_closure_approximate_lower_bound[317d]::generic[0]::{{closure}}[0]) with closure substs [
+ T,
+ i16,
+ for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) ()>>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) T))
+ ]
+ = note: number of external vids: 2
+ = note: where T: '_#1r
+
+note: External requirements
+ --> $DIR/ty-param-closure-approximate-lower-bound.rs:43:24
+ |
+43 | twice(cell, value, |a, b| invoke(a, b));
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+ = note: defining type: DefId(0/1:17 ~ ty_param_closure_approximate_lower_bound[317d]::generic_fail[0]::{{closure}}[0]) with closure substs [
+ T,
+ i16,
+ for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) ()>>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) T))
+ ]
+ = note: number of external vids: 2
+ = note: where T: '_#1r
+
+note: No external requirements
+ --> $DIR/ty-param-closure-approximate-lower-bound.rs:33:1
+ |
+33 | / fn generic<T>(value: T) {
+34 | | let cell = Cell::new(&());
+35 | | twice(cell, value, |a, b| invoke(a, b));
+36 | | //~^ WARNING not reporting region error
+37 | | //
+38 | | // This error from the old region solver looks bogus.
+39 | | }
+ | |_^
+ |
+ = note: defining type: DefId(0/0:5 ~ ty_param_closure_approximate_lower_bound[317d]::generic[0]) with substs [
+ T
+ ]
+
+error: `T` does not outlive `'_#3r`
+ --> $DIR/ty-param-closure-approximate-lower-bound.rs:43:24
+ |
+43 | twice(cell, value, |a, b| invoke(a, b));
+ | ^^^^^^^^^^^^^^^^^^^
+
+note: No external requirements
+ --> $DIR/ty-param-closure-approximate-lower-bound.rs:42:1
+ |
+42 | / fn generic_fail<'a, T>(cell: Cell<&'a ()>, value: T) {
+43 | | twice(cell, value, |a, b| invoke(a, b));
+44 | | //~^ WARNING not reporting region error
+45 | | //~| WARNING not reporting region error
+46 | | //~| ERROR `T` does not outlive
+47 | | }
+ | |_^
+ |
+ = note: defining type: DefId(0/0:6 ~ ty_param_closure_approximate_lower_bound[317d]::generic_fail[0]) with substs [
+ T
+ ]
+
+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.
+
+// compile-flags:-Znll -Zborrowck=mir -Zverbose
+// must-compile-successfully
+
+// Test that we assume that universal types like `T` outlive the
+// function body.
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+fn twice<F, T>(value: T, mut f: F)
+where
+ F: FnMut(Cell<&T>),
+{
+ f(Cell::new(&value));
+ f(Cell::new(&value));
+}
+
+#[rustc_errors]
+fn generic<T>(value: T) {
+ // No error here:
+ twice(value, |r| invoke(r));
+}
+
+fn invoke<'a, T>(x: Cell<&'a T>)
+where
+ T: 'a,
+{
+}
+
+fn main() {}