Auto merge of #31210 - Manishearth:rollup, r=Manishearth
- Successful merges: #31152, #31184, #31189, #31192, #31197, #31199, #31201 - Failed merges:
This commit is contained in:
commit
acf4aeeda0
@ -1512,7 +1512,7 @@ and [`rustc-serialize`](https://crates.io/crates/rustc-serialize) crates.
|
||||
|
||||
We're not going to spend a lot of time on setting up a project with
|
||||
Cargo because it is already covered well in [the Cargo
|
||||
section](../book/hello-cargo.html) and [Cargo's documentation][14].
|
||||
section](getting-started.html#hello-cargo) and [Cargo's documentation][14].
|
||||
|
||||
To get started from scratch, run `cargo new --bin city-pop` and make sure your
|
||||
`Cargo.toml` looks something like this:
|
||||
|
@ -167,6 +167,10 @@ variable. If it isn't, run the installer again, select "Change" on the "Change,
|
||||
repair, or remove installation" page and ensure "Add to PATH" is installed on
|
||||
the local hard drive.
|
||||
|
||||
Rust does not do its own linking, and so you’ll need to have a linker
|
||||
installed. Doing so will depend on your specific system, consult its
|
||||
documentation for more details.
|
||||
|
||||
If not, there are a number of places where we can get help. The easiest is
|
||||
[the #rust IRC channel on irc.mozilla.org][irc], which we can access through
|
||||
[Mibbit][mibbit]. Click that link, and we'll be chatting with other Rustaceans
|
||||
@ -604,11 +608,11 @@ This chapter covered the basics that will serve you well through the rest of
|
||||
this book, and the rest of your time with Rust. Now that you’ve got the tools
|
||||
down, we'll cover more about the Rust language itself.
|
||||
|
||||
You have two options: Dive into a project with ‘[Learn Rust][learnrust]’, or
|
||||
You have two options: Dive into a project with ‘[Tutorial: Guessing Game][guessinggame]’, or
|
||||
start from the bottom and work your way up with ‘[Syntax and
|
||||
Semantics][syntax]’. More experienced systems programmers will probably prefer
|
||||
‘Learn Rust’, while those from dynamic backgrounds may enjoy either. Different
|
||||
‘Tutorial: Guessing Game’, while those from dynamic backgrounds may enjoy either. Different
|
||||
people learn differently! Choose whatever’s right for you.
|
||||
|
||||
[learnrust]: learn-rust.html
|
||||
[guessinggame]: guessing-game.html
|
||||
[syntax]: syntax-and-semantics.html
|
||||
|
@ -1,9 +0,0 @@
|
||||
% Learn Rust
|
||||
|
||||
Welcome! This chapter has a few tutorials that teach you Rust through building
|
||||
projects. You’ll get a high-level overview, but we’ll skim over the details.
|
||||
|
||||
If you’d prefer a more ‘from the ground up’-style experience, check
|
||||
out [Syntax and Semantics][ss].
|
||||
|
||||
[ss]: syntax-and-semantics.html
|
@ -195,7 +195,7 @@ for x in 0..10 {
|
||||
You may also encounter situations where you have nested loops and need to
|
||||
specify which one your `break` or `continue` statement is for. Like most
|
||||
other languages, by default a `break` or `continue` will apply to innermost
|
||||
loop. In a situation where you would like to a `break` or `continue` for one
|
||||
loop. In a situation where you would like to `break` or `continue` for one
|
||||
of the outer loops, you can use labels to specify which loop the `break` or
|
||||
`continue` statement applies to. This will only print when both `x` and `y` are
|
||||
odd:
|
||||
|
@ -414,7 +414,9 @@ impl<T: ?Sized> RefCell<T> {
|
||||
///
|
||||
/// let c = RefCell::new(5);
|
||||
///
|
||||
/// let borrowed_five = c.borrow_mut();
|
||||
/// *c.borrow_mut() = 7;
|
||||
///
|
||||
/// assert_eq!(*c.borrow(), 7);
|
||||
/// ```
|
||||
///
|
||||
/// An example of panic:
|
||||
|
@ -2740,7 +2740,13 @@ pub trait Extend<A> {
|
||||
/// It is important to note that both back and forth work on the same range,
|
||||
/// and do not cross: iteration is over when they meet in the middle.
|
||||
///
|
||||
/// In a similar fashion to the [`Iterator`] protocol, once a
|
||||
/// `DoubleEndedIterator` returns `None` from a `next_back()`, calling it again
|
||||
/// may or may not ever return `Some` again. `next()` and `next_back()` are
|
||||
/// interchangable for this purpose.
|
||||
///
|
||||
/// [`Iterator`]: trait.Iterator.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
|
@ -108,7 +108,6 @@ pub mod middle {
|
||||
pub mod free_region;
|
||||
pub mod intrinsicck;
|
||||
pub mod infer;
|
||||
pub mod implicator;
|
||||
pub mod lang_items;
|
||||
pub mod liveness;
|
||||
pub mod mem_categorization;
|
||||
|
@ -1,454 +0,0 @@
|
||||
// Copyright 2012 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.
|
||||
|
||||
// #![warn(deprecated_mode)]
|
||||
|
||||
use middle::def_id::DefId;
|
||||
use middle::infer::{InferCtxt, GenericKind};
|
||||
use middle::subst::Substs;
|
||||
use middle::traits;
|
||||
use middle::ty::{self, ToPredicate, Ty};
|
||||
use middle::ty::fold::{TypeFoldable, TypeFolder};
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::codemap::Span;
|
||||
|
||||
use util::common::ErrorReported;
|
||||
use util::nodemap::FnvHashSet;
|
||||
|
||||
// Helper functions related to manipulating region types.
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Implication<'tcx> {
|
||||
RegionSubRegion(Option<Ty<'tcx>>, ty::Region, ty::Region),
|
||||
RegionSubGeneric(Option<Ty<'tcx>>, ty::Region, GenericKind<'tcx>),
|
||||
Predicate(DefId, ty::Predicate<'tcx>),
|
||||
}
|
||||
|
||||
struct Implicator<'a, 'tcx: 'a> {
|
||||
infcx: &'a InferCtxt<'a,'tcx>,
|
||||
body_id: ast::NodeId,
|
||||
stack: Vec<(ty::Region, Option<Ty<'tcx>>)>,
|
||||
span: Span,
|
||||
out: Vec<Implication<'tcx>>,
|
||||
visited: FnvHashSet<Ty<'tcx>>,
|
||||
}
|
||||
|
||||
/// This routine computes the well-formedness constraints that must hold for the type `ty` to
|
||||
/// appear in a context with lifetime `outer_region`
|
||||
pub fn implications<'a,'tcx>(
|
||||
infcx: &'a InferCtxt<'a,'tcx>,
|
||||
body_id: ast::NodeId,
|
||||
ty: Ty<'tcx>,
|
||||
outer_region: ty::Region,
|
||||
span: Span)
|
||||
-> Vec<Implication<'tcx>>
|
||||
{
|
||||
debug!("implications(body_id={}, ty={:?}, outer_region={:?})",
|
||||
body_id,
|
||||
ty,
|
||||
outer_region);
|
||||
|
||||
let mut stack = Vec::new();
|
||||
stack.push((outer_region, None));
|
||||
let mut wf = Implicator { infcx: infcx,
|
||||
body_id: body_id,
|
||||
span: span,
|
||||
stack: stack,
|
||||
out: Vec::new(),
|
||||
visited: FnvHashSet() };
|
||||
wf.accumulate_from_ty(ty);
|
||||
debug!("implications: out={:?}", wf.out);
|
||||
wf.out
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Implicator<'a, 'tcx> {
|
||||
fn tcx(&self) -> &'a ty::ctxt<'tcx> {
|
||||
self.infcx.tcx
|
||||
}
|
||||
|
||||
fn accumulate_from_ty(&mut self, ty: Ty<'tcx>) {
|
||||
debug!("accumulate_from_ty(ty={:?})",
|
||||
ty);
|
||||
|
||||
// When expanding out associated types, we can visit a cyclic
|
||||
// set of types. Issue #23003.
|
||||
if !self.visited.insert(ty) {
|
||||
return;
|
||||
}
|
||||
|
||||
match ty.sty {
|
||||
ty::TyBool |
|
||||
ty::TyChar |
|
||||
ty::TyInt(..) |
|
||||
ty::TyUint(..) |
|
||||
ty::TyFloat(..) |
|
||||
ty::TyBareFn(..) |
|
||||
ty::TyError |
|
||||
ty::TyStr => {
|
||||
// No borrowed content reachable here.
|
||||
}
|
||||
|
||||
ty::TyClosure(_, ref substs) => {
|
||||
// FIXME(#27086). We do not accumulate from substs, since they
|
||||
// don't represent reachable data. This means that, in
|
||||
// practice, some of the lifetime parameters might not
|
||||
// be in scope when the body runs, so long as there is
|
||||
// no reachable data with that lifetime. For better or
|
||||
// worse, this is consistent with fn types, however,
|
||||
// which can also encapsulate data in this fashion
|
||||
// (though it's somewhat harder, and typically
|
||||
// requires virtual dispatch).
|
||||
//
|
||||
// Note that changing this (in a naive way, at least)
|
||||
// causes regressions for what appears to be perfectly
|
||||
// reasonable code like this:
|
||||
//
|
||||
// ```
|
||||
// fn foo<'a>(p: &Data<'a>) {
|
||||
// bar(|q: &mut Parser| q.read_addr())
|
||||
// }
|
||||
// fn bar(p: Box<FnMut(&mut Parser)+'static>) {
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// Note that `p` (and `'a`) are not used in the
|
||||
// closure at all, but to meet the requirement that
|
||||
// the closure type `C: 'static` (so it can be coerced
|
||||
// to the object type), we get the requirement that
|
||||
// `'a: 'static` since `'a` appears in the closure
|
||||
// type `C`.
|
||||
//
|
||||
// A smarter fix might "prune" unused `func_substs` --
|
||||
// this would avoid breaking simple examples like
|
||||
// this, but would still break others (which might
|
||||
// indeed be invalid, depending on your POV). Pruning
|
||||
// would be a subtle process, since we have to see
|
||||
// what func/type parameters are used and unused,
|
||||
// taking into consideration UFCS and so forth.
|
||||
|
||||
for &upvar_ty in &substs.upvar_tys {
|
||||
self.accumulate_from_ty(upvar_ty);
|
||||
}
|
||||
}
|
||||
|
||||
ty::TyTrait(ref t) => {
|
||||
let required_region_bounds =
|
||||
object_region_bounds(self.tcx(), &t.principal, t.bounds.builtin_bounds);
|
||||
self.accumulate_from_object_ty(ty, t.bounds.region_bound, required_region_bounds)
|
||||
}
|
||||
|
||||
ty::TyEnum(def, substs) |
|
||||
ty::TyStruct(def, substs) => {
|
||||
let item_scheme = def.type_scheme(self.tcx());
|
||||
self.accumulate_from_adt(ty, def.did, &item_scheme.generics, substs)
|
||||
}
|
||||
|
||||
ty::TyArray(t, _) |
|
||||
ty::TySlice(t) |
|
||||
ty::TyRawPtr(ty::TypeAndMut { ty: t, .. }) |
|
||||
ty::TyBox(t) => {
|
||||
self.accumulate_from_ty(t)
|
||||
}
|
||||
|
||||
ty::TyRef(r_b, mt) => {
|
||||
self.accumulate_from_rptr(ty, *r_b, mt.ty);
|
||||
}
|
||||
|
||||
ty::TyParam(p) => {
|
||||
self.push_param_constraint_from_top(p);
|
||||
}
|
||||
|
||||
ty::TyProjection(ref data) => {
|
||||
// `<T as TraitRef<..>>::Name`
|
||||
|
||||
self.push_projection_constraint_from_top(data);
|
||||
}
|
||||
|
||||
ty::TyTuple(ref tuptys) => {
|
||||
for &tupty in tuptys {
|
||||
self.accumulate_from_ty(tupty);
|
||||
}
|
||||
}
|
||||
|
||||
ty::TyInfer(_) => {
|
||||
// This should not happen, BUT:
|
||||
//
|
||||
// Currently we uncover region relationships on
|
||||
// entering the fn check. We should do this after
|
||||
// the fn check, then we can call this case a bug().
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn accumulate_from_rptr(&mut self,
|
||||
ty: Ty<'tcx>,
|
||||
r_b: ty::Region,
|
||||
ty_b: Ty<'tcx>) {
|
||||
// We are walking down a type like this, and current
|
||||
// position is indicated by caret:
|
||||
//
|
||||
// &'a &'b ty_b
|
||||
// ^
|
||||
//
|
||||
// At this point, top of stack will be `'a`. We must
|
||||
// require that `'a <= 'b`.
|
||||
|
||||
self.push_region_constraint_from_top(r_b);
|
||||
|
||||
// Now we push `'b` onto the stack, because it must
|
||||
// constrain any borrowed content we find within `T`.
|
||||
|
||||
self.stack.push((r_b, Some(ty)));
|
||||
self.accumulate_from_ty(ty_b);
|
||||
self.stack.pop().unwrap();
|
||||
}
|
||||
|
||||
/// Pushes a constraint that `r_b` must outlive the top region on the stack.
|
||||
fn push_region_constraint_from_top(&mut self,
|
||||
r_b: ty::Region) {
|
||||
|
||||
// Indicates that we have found borrowed content with a lifetime
|
||||
// of at least `r_b`. This adds a constraint that `r_b` must
|
||||
// outlive the region `r_a` on top of the stack.
|
||||
//
|
||||
// As an example, imagine walking a type like:
|
||||
//
|
||||
// &'a &'b T
|
||||
// ^
|
||||
//
|
||||
// when we hit the inner pointer (indicated by caret), `'a` will
|
||||
// be on top of stack and `'b` will be the lifetime of the content
|
||||
// we just found. So we add constraint that `'a <= 'b`.
|
||||
|
||||
let &(r_a, opt_ty) = self.stack.last().unwrap();
|
||||
self.push_sub_region_constraint(opt_ty, r_a, r_b);
|
||||
}
|
||||
|
||||
/// Pushes a constraint that `r_a <= r_b`, due to `opt_ty`
|
||||
fn push_sub_region_constraint(&mut self,
|
||||
opt_ty: Option<Ty<'tcx>>,
|
||||
r_a: ty::Region,
|
||||
r_b: ty::Region) {
|
||||
self.out.push(Implication::RegionSubRegion(opt_ty, r_a, r_b));
|
||||
}
|
||||
|
||||
/// Pushes a constraint that `param_ty` must outlive the top region on the stack.
|
||||
fn push_param_constraint_from_top(&mut self,
|
||||
param_ty: ty::ParamTy) {
|
||||
let &(region, opt_ty) = self.stack.last().unwrap();
|
||||
self.push_param_constraint(region, opt_ty, param_ty);
|
||||
}
|
||||
|
||||
/// Pushes a constraint that `projection_ty` must outlive the top region on the stack.
|
||||
fn push_projection_constraint_from_top(&mut self,
|
||||
projection_ty: &ty::ProjectionTy<'tcx>) {
|
||||
let &(region, opt_ty) = self.stack.last().unwrap();
|
||||
self.out.push(Implication::RegionSubGeneric(
|
||||
opt_ty, region, GenericKind::Projection(projection_ty.clone())));
|
||||
}
|
||||
|
||||
/// Pushes a constraint that `region <= param_ty`, due to `opt_ty`
|
||||
fn push_param_constraint(&mut self,
|
||||
region: ty::Region,
|
||||
opt_ty: Option<Ty<'tcx>>,
|
||||
param_ty: ty::ParamTy) {
|
||||
self.out.push(Implication::RegionSubGeneric(
|
||||
opt_ty, region, GenericKind::Param(param_ty)));
|
||||
}
|
||||
|
||||
fn accumulate_from_adt(&mut self,
|
||||
ty: Ty<'tcx>,
|
||||
def_id: DefId,
|
||||
_generics: &ty::Generics<'tcx>,
|
||||
substs: &Substs<'tcx>)
|
||||
{
|
||||
let predicates =
|
||||
self.tcx().lookup_predicates(def_id).instantiate(self.tcx(), substs);
|
||||
let predicates = match self.fully_normalize(&predicates) {
|
||||
Ok(predicates) => predicates,
|
||||
Err(ErrorReported) => { return; }
|
||||
};
|
||||
|
||||
for predicate in predicates.predicates.as_slice() {
|
||||
match *predicate {
|
||||
ty::Predicate::Trait(..) => { }
|
||||
ty::Predicate::Equate(..) => { }
|
||||
ty::Predicate::Projection(..) => { }
|
||||
ty::Predicate::RegionOutlives(ref data) => {
|
||||
match self.tcx().no_late_bound_regions(data) {
|
||||
None => { }
|
||||
Some(ty::OutlivesPredicate(r_a, r_b)) => {
|
||||
self.push_sub_region_constraint(Some(ty), r_b, r_a);
|
||||
}
|
||||
}
|
||||
}
|
||||
ty::Predicate::TypeOutlives(ref data) => {
|
||||
match self.tcx().no_late_bound_regions(data) {
|
||||
None => { }
|
||||
Some(ty::OutlivesPredicate(ty_a, r_b)) => {
|
||||
self.stack.push((r_b, Some(ty)));
|
||||
self.accumulate_from_ty(ty_a);
|
||||
self.stack.pop().unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
ty::Predicate::ObjectSafe(_) |
|
||||
ty::Predicate::WellFormed(_) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let obligations = predicates.predicates
|
||||
.into_iter()
|
||||
.map(|pred| Implication::Predicate(def_id, pred));
|
||||
self.out.extend(obligations);
|
||||
|
||||
let variances = self.tcx().item_variances(def_id);
|
||||
self.accumulate_from_substs(substs, Some(&variances));
|
||||
}
|
||||
|
||||
fn accumulate_from_substs(&mut self,
|
||||
substs: &Substs<'tcx>,
|
||||
variances: Option<&ty::ItemVariances>)
|
||||
{
|
||||
let mut tmp_variances = None;
|
||||
let variances = variances.unwrap_or_else(|| {
|
||||
tmp_variances = Some(ty::ItemVariances {
|
||||
types: substs.types.map(|_| ty::Variance::Invariant),
|
||||
regions: substs.regions().map(|_| ty::Variance::Invariant),
|
||||
});
|
||||
tmp_variances.as_ref().unwrap()
|
||||
});
|
||||
|
||||
for (®ion, &variance) in substs.regions().iter().zip(&variances.regions) {
|
||||
match variance {
|
||||
ty::Contravariant | ty::Invariant => {
|
||||
// If any data with this lifetime is reachable
|
||||
// within, it must be at least contravariant.
|
||||
self.push_region_constraint_from_top(region)
|
||||
}
|
||||
ty::Covariant | ty::Bivariant => { }
|
||||
}
|
||||
}
|
||||
|
||||
for (&ty, &variance) in substs.types.iter().zip(&variances.types) {
|
||||
match variance {
|
||||
ty::Covariant | ty::Invariant => {
|
||||
// If any data of this type is reachable within,
|
||||
// it must be at least covariant.
|
||||
self.accumulate_from_ty(ty);
|
||||
}
|
||||
ty::Contravariant | ty::Bivariant => { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn accumulate_from_object_ty(&mut self,
|
||||
ty: Ty<'tcx>,
|
||||
region_bound: ty::Region,
|
||||
required_region_bounds: Vec<ty::Region>)
|
||||
{
|
||||
// Imagine a type like this:
|
||||
//
|
||||
// trait Foo { }
|
||||
// trait Bar<'c> : 'c { }
|
||||
//
|
||||
// &'b (Foo+'c+Bar<'d>)
|
||||
// ^
|
||||
//
|
||||
// In this case, the following relationships must hold:
|
||||
//
|
||||
// 'b <= 'c
|
||||
// 'd <= 'c
|
||||
//
|
||||
// The first conditions is due to the normal region pointer
|
||||
// rules, which say that a reference cannot outlive its
|
||||
// referent.
|
||||
//
|
||||
// The final condition may be a bit surprising. In particular,
|
||||
// you may expect that it would have been `'c <= 'd`, since
|
||||
// usually lifetimes of outer things are conservative
|
||||
// approximations for inner things. However, it works somewhat
|
||||
// differently with trait objects: here the idea is that if the
|
||||
// user specifies a region bound (`'c`, in this case) it is the
|
||||
// "master bound" that *implies* that bounds from other traits are
|
||||
// all met. (Remember that *all bounds* in a type like
|
||||
// `Foo+Bar+Zed` must be met, not just one, hence if we write
|
||||
// `Foo<'x>+Bar<'y>`, we know that the type outlives *both* 'x and
|
||||
// 'y.)
|
||||
//
|
||||
// Note: in fact we only permit builtin traits, not `Bar<'d>`, I
|
||||
// am looking forward to the future here.
|
||||
|
||||
// The content of this object type must outlive
|
||||
// `bounds.region_bound`:
|
||||
let r_c = region_bound;
|
||||
self.push_region_constraint_from_top(r_c);
|
||||
|
||||
// And then, in turn, to be well-formed, the
|
||||
// `region_bound` that user specified must imply the
|
||||
// region bounds required from all of the trait types:
|
||||
for &r_d in &required_region_bounds {
|
||||
// Each of these is an instance of the `'c <= 'b`
|
||||
// constraint above
|
||||
self.out.push(Implication::RegionSubRegion(Some(ty), r_d, r_c));
|
||||
}
|
||||
}
|
||||
|
||||
fn fully_normalize<T>(&self, value: &T) -> Result<T,ErrorReported>
|
||||
where T : TypeFoldable<'tcx>
|
||||
{
|
||||
let value =
|
||||
traits::fully_normalize(self.infcx,
|
||||
traits::ObligationCause::misc(self.span, self.body_id),
|
||||
value);
|
||||
match value {
|
||||
Ok(value) => Ok(value),
|
||||
Err(errors) => {
|
||||
// I don't like reporting these errors here, but I
|
||||
// don't know where else to report them just now. And
|
||||
// I don't really expect errors to arise here
|
||||
// frequently. I guess the best option would be to
|
||||
// propagate them out.
|
||||
traits::report_fulfillment_errors(self.infcx, &errors);
|
||||
Err(ErrorReported)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Given an object type like `SomeTrait+Send`, computes the lifetime
|
||||
/// bounds that must hold on the elided self type. These are derived
|
||||
/// from the declarations of `SomeTrait`, `Send`, and friends -- if
|
||||
/// they declare `trait SomeTrait : 'static`, for example, then
|
||||
/// `'static` would appear in the list. The hard work is done by
|
||||
/// `ty::required_region_bounds`, see that for more information.
|
||||
pub fn object_region_bounds<'tcx>(
|
||||
tcx: &ty::ctxt<'tcx>,
|
||||
principal: &ty::PolyTraitRef<'tcx>,
|
||||
others: ty::BuiltinBounds)
|
||||
-> Vec<ty::Region>
|
||||
{
|
||||
// Since we don't actually *know* the self type for an object,
|
||||
// this "open(err)" serves as a kind of dummy standin -- basically
|
||||
// a skolemized type.
|
||||
let open_ty = tcx.mk_infer(ty::FreshTy(0));
|
||||
|
||||
// Note that we preserve the overall binding levels here.
|
||||
assert!(!open_ty.has_escaping_regions());
|
||||
let substs = tcx.mk_substs(principal.0.substs.with_self_ty(open_ty));
|
||||
let trait_refs = vec!(ty::Binder(ty::TraitRef::new(principal.0.def_id, substs)));
|
||||
|
||||
let mut predicates = others.to_predicates(tcx, open_ty);
|
||||
predicates.extend(trait_refs.iter().map(|t| t.to_predicate()));
|
||||
|
||||
tcx.required_region_bounds(open_ty, predicates)
|
||||
}
|
@ -86,7 +86,6 @@ use astconv::AstConv;
|
||||
use check::dropck;
|
||||
use check::FnCtxt;
|
||||
use middle::free_region::FreeRegionMap;
|
||||
use middle::implicator::{self, Implication};
|
||||
use middle::mem_categorization as mc;
|
||||
use middle::mem_categorization::Categorization;
|
||||
use middle::region::{self, CodeExtent};
|
||||
@ -365,12 +364,7 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> {
|
||||
r_o, r_o.cause);
|
||||
let sup_type = self.resolve_type(r_o.sup_type);
|
||||
let origin = self.code_to_origin(r_o.cause.span, sup_type, &r_o.cause.code);
|
||||
|
||||
if r_o.sub_region != ty::ReEmpty {
|
||||
type_must_outlive(self, origin, sup_type, r_o.sub_region);
|
||||
} else {
|
||||
self.visit_old_school_wf(node_id, sup_type, origin);
|
||||
}
|
||||
type_must_outlive(self, origin, sup_type, r_o.sub_region);
|
||||
}
|
||||
|
||||
// Processing the region obligations should not cause the list to grow further:
|
||||
@ -378,47 +372,6 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> {
|
||||
self.fcx.inh.infcx.fulfillment_cx.borrow().region_obligations(node_id).len());
|
||||
}
|
||||
|
||||
fn visit_old_school_wf(&mut self,
|
||||
body_id: ast::NodeId,
|
||||
ty: Ty<'tcx>,
|
||||
origin: infer::SubregionOrigin<'tcx>) {
|
||||
// As a weird kind of hack, we use a region of empty as a signal
|
||||
// to mean "old-school WF rules". The only reason the old-school
|
||||
// WF rules are not encoded using WF is that this leads to errors,
|
||||
// and we want to phase those in gradually.
|
||||
|
||||
// FIXME(#27579) remove this weird special case once we phase in new WF rules completely
|
||||
let implications = implicator::implications(self.infcx(),
|
||||
body_id,
|
||||
ty,
|
||||
ty::ReEmpty,
|
||||
origin.span());
|
||||
let origin_for_ty = |ty: Option<Ty<'tcx>>| match ty {
|
||||
None => origin.clone(),
|
||||
Some(ty) => infer::ReferenceOutlivesReferent(ty, origin.span()),
|
||||
};
|
||||
for implication in implications {
|
||||
match implication {
|
||||
Implication::RegionSubRegion(ty, r1, r2) => {
|
||||
self.fcx.mk_subr(origin_for_ty(ty), r1, r2);
|
||||
}
|
||||
Implication::RegionSubGeneric(ty, r1, GenericKind::Param(param_ty)) => {
|
||||
param_ty_must_outlive(self, origin_for_ty(ty), r1, param_ty);
|
||||
}
|
||||
Implication::RegionSubGeneric(ty, r1, GenericKind::Projection(proj_ty)) => {
|
||||
projection_must_outlive(self, origin_for_ty(ty), r1, proj_ty);
|
||||
}
|
||||
Implication::Predicate(def_id, predicate) => {
|
||||
let cause = traits::ObligationCause::new(origin.span(),
|
||||
body_id,
|
||||
traits::ItemObligation(def_id));
|
||||
let obligation = traits::Obligation::new(cause, predicate);
|
||||
self.fcx.register_predicate(obligation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn code_to_origin(&self,
|
||||
span: Span,
|
||||
sup_type: Ty<'tcx>,
|
||||
|
@ -1005,7 +1005,7 @@ fn is_in_follow(_: &ExtCtxt, tok: &Token, frag: &str) -> Result<bool, String> {
|
||||
},
|
||||
"path" | "ty" => {
|
||||
match *tok {
|
||||
OpenDelim(token::DelimToken::Brace) |
|
||||
OpenDelim(token::DelimToken::Brace) | OpenDelim(token::DelimToken::Bracket) |
|
||||
Comma | FatArrow | Colon | Eq | Gt | Semi | BinOp(token::Or) => Ok(true),
|
||||
Ident(i, _) if (i.name.as_str() == "as" ||
|
||||
i.name.as_str() == "where") => Ok(true),
|
||||
|
122
src/test/compile-fail/macro-follow.rs
Normal file
122
src/test/compile-fail/macro-follow.rs
Normal file
@ -0,0 +1,122 @@
|
||||
// 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.
|
||||
//
|
||||
// Check the macro follow sets (see corresponding rpass test).
|
||||
|
||||
// FOLLOW(pat) = {FatArrow, Comma, Eq, Or, Ident(if), Ident(in)}
|
||||
macro_rules! follow_pat {
|
||||
($p:pat ()) => {}; //~WARN `$p:pat` is followed by `(`
|
||||
($p:pat []) => {}; //~WARN `$p:pat` is followed by `[`
|
||||
($p:pat {}) => {}; //~WARN `$p:pat` is followed by `{`
|
||||
($p:pat :) => {}; //~ERROR `$p:pat` is followed by `:`
|
||||
($p:pat >) => {}; //~ERROR `$p:pat` is followed by `>`
|
||||
($p:pat +) => {}; //~ERROR `$p:pat` is followed by `+`
|
||||
($p:pat ident) => {}; //~ERROR `$p:pat` is followed by `ident`
|
||||
($p:pat $p:pat) => {}; //~ERROR `$p:pat` is followed by `$p:pat`
|
||||
($p:pat $e:expr) => {}; //~ERROR `$p:pat` is followed by `$e:expr`
|
||||
($p:pat $t:ty) => {}; //~ERROR `$p:pat` is followed by `$t:ty`
|
||||
($p:pat $s:stmt) => {}; //~ERROR `$p:pat` is followed by `$s:stmt`
|
||||
($p:pat $p:path) => {}; //~ERROR `$p:pat` is followed by `$p:path`
|
||||
($p:pat $b:block) => {}; //~ERROR `$p:pat` is followed by `$b:block`
|
||||
($p:pat $i:ident) => {}; //~ERROR `$p:pat` is followed by `$i:ident`
|
||||
($p:pat $t:tt) => {}; //~ERROR `$p:pat` is followed by `$t:tt`
|
||||
($p:pat $i:item) => {}; //~ERROR `$p:pat` is followed by `$i:item`
|
||||
($p:pat $m:meta) => {}; //~ERROR `$p:pat` is followed by `$m:meta`
|
||||
}
|
||||
// FOLLOW(expr) = {FatArrow, Comma, Semicolon}
|
||||
macro_rules! follow_expr {
|
||||
($e:expr ()) => {}; //~WARN `$e:expr` is followed by `(`
|
||||
($e:expr []) => {}; //~WARN `$e:expr` is followed by `[`
|
||||
($e:expr {}) => {}; //~WARN `$e:expr` is followed by `{`
|
||||
($e:expr =) => {}; //~ERROR `$e:expr` is followed by `=`
|
||||
($e:expr |) => {}; //~ERROR `$e:expr` is followed by `|`
|
||||
($e:expr :) => {}; //~ERROR `$e:expr` is followed by `:`
|
||||
($e:expr >) => {}; //~ERROR `$e:expr` is followed by `>`
|
||||
($e:expr +) => {}; //~ERROR `$e:expr` is followed by `+`
|
||||
($e:expr ident) => {}; //~ERROR `$e:expr` is followed by `ident`
|
||||
($e:expr if) => {}; //~ERROR `$e:expr` is followed by `if`
|
||||
($e:expr in) => {}; //~ERROR `$e:expr` is followed by `in`
|
||||
($e:expr $p:pat) => {}; //~ERROR `$e:expr` is followed by `$p:pat`
|
||||
($e:expr $e:expr) => {}; //~ERROR `$e:expr` is followed by `$e:expr`
|
||||
($e:expr $t:ty) => {}; //~ERROR `$e:expr` is followed by `$t:ty`
|
||||
($e:expr $s:stmt) => {}; //~ERROR `$e:expr` is followed by `$s:stmt`
|
||||
($e:expr $p:path) => {}; //~ERROR `$e:expr` is followed by `$p:path`
|
||||
($e:expr $b:block) => {}; //~ERROR `$e:expr` is followed by `$b:block`
|
||||
($e:expr $i:ident) => {}; //~ERROR `$e:expr` is followed by `$i:ident`
|
||||
($e:expr $t:tt) => {}; //~ERROR `$e:expr` is followed by `$t:tt`
|
||||
($e:expr $i:item) => {}; //~ERROR `$e:expr` is followed by `$i:item`
|
||||
($e:expr $m:meta) => {}; //~ERROR `$e:expr` is followed by `$m:meta`
|
||||
}
|
||||
// FOLLOW(ty) = {OpenDelim(Brace), Comma, FatArrow, Colon, Eq, Gt, Semi, Or,
|
||||
// Ident(as), Ident(where), OpenDelim(Bracket)}
|
||||
macro_rules! follow_ty {
|
||||
($t:ty ()) => {}; //~WARN `$t:ty` is followed by `(`
|
||||
($t:ty []) => {}; // ok (RFC 1462)
|
||||
($t:ty +) => {}; //~ERROR `$t:ty` is followed by `+`
|
||||
($t:ty ident) => {}; //~ERROR `$t:ty` is followed by `ident`
|
||||
($t:ty if) => {}; //~ERROR `$t:ty` is followed by `if`
|
||||
($t:ty $p:pat) => {}; //~ERROR `$t:ty` is followed by `$p:pat`
|
||||
($t:ty $e:expr) => {}; //~ERROR `$t:ty` is followed by `$e:expr`
|
||||
($t:ty $t:ty) => {}; //~ERROR `$t:ty` is followed by `$t:ty`
|
||||
($t:ty $s:stmt) => {}; //~ERROR `$t:ty` is followed by `$s:stmt`
|
||||
($t:ty $p:path) => {}; //~ERROR `$t:ty` is followed by `$p:path`
|
||||
($t:ty $b:block) => {}; //~ERROR `$t:ty` is followed by `$b:block`
|
||||
($t:ty $i:ident) => {}; //~ERROR `$t:ty` is followed by `$i:ident`
|
||||
($t:ty $t:tt) => {}; //~ERROR `$t:ty` is followed by `$t:tt`
|
||||
($t:ty $i:item) => {}; //~ERROR `$t:ty` is followed by `$i:item`
|
||||
($t:ty $m:meta) => {}; //~ERROR `$t:ty` is followed by `$m:meta`
|
||||
}
|
||||
// FOLLOW(stmt) = FOLLOW(expr)
|
||||
macro_rules! follow_stmt {
|
||||
($s:stmt ()) => {}; //~WARN `$s:stmt` is followed by `(`
|
||||
($s:stmt []) => {}; //~WARN `$s:stmt` is followed by `[`
|
||||
($s:stmt {}) => {}; //~WARN `$s:stmt` is followed by `{`
|
||||
($s:stmt =) => {}; //~ERROR `$s:stmt` is followed by `=`
|
||||
($s:stmt |) => {}; //~ERROR `$s:stmt` is followed by `|`
|
||||
($s:stmt :) => {}; //~ERROR `$s:stmt` is followed by `:`
|
||||
($s:stmt >) => {}; //~ERROR `$s:stmt` is followed by `>`
|
||||
($s:stmt +) => {}; //~ERROR `$s:stmt` is followed by `+`
|
||||
($s:stmt ident) => {}; //~ERROR `$s:stmt` is followed by `ident`
|
||||
($s:stmt if) => {}; //~ERROR `$s:stmt` is followed by `if`
|
||||
($s:stmt in) => {}; //~ERROR `$s:stmt` is followed by `in`
|
||||
($s:stmt $p:pat) => {}; //~ERROR `$s:stmt` is followed by `$p:pat`
|
||||
($s:stmt $e:expr) => {}; //~ERROR `$s:stmt` is followed by `$e:expr`
|
||||
($s:stmt $t:ty) => {}; //~ERROR `$s:stmt` is followed by `$t:ty`
|
||||
($s:stmt $s:stmt) => {}; //~ERROR `$s:stmt` is followed by `$s:stmt`
|
||||
($s:stmt $p:path) => {}; //~ERROR `$s:stmt` is followed by `$p:path`
|
||||
($s:stmt $b:block) => {}; //~ERROR `$s:stmt` is followed by `$b:block`
|
||||
($s:stmt $i:ident) => {}; //~ERROR `$s:stmt` is followed by `$i:ident`
|
||||
($s:stmt $t:tt) => {}; //~ERROR `$s:stmt` is followed by `$t:tt`
|
||||
($s:stmt $i:item) => {}; //~ERROR `$s:stmt` is followed by `$i:item`
|
||||
($s:stmt $m:meta) => {}; //~ERROR `$s:stmt` is followed by `$m:meta`
|
||||
}
|
||||
// FOLLOW(path) = FOLLOW(ty)
|
||||
macro_rules! follow_path {
|
||||
($p:path ()) => {}; //~WARN `$p:path` is followed by `(`
|
||||
($p:path []) => {}; // ok (RFC 1462)
|
||||
($p:path +) => {}; //~ERROR `$p:path` is followed by `+`
|
||||
($p:path ident) => {}; //~ERROR `$p:path` is followed by `ident`
|
||||
($p:path if) => {}; //~ERROR `$p:path` is followed by `if`
|
||||
($p:path $p:pat) => {}; //~ERROR `$p:path` is followed by `$p:pat`
|
||||
($p:path $e:expr) => {}; //~ERROR `$p:path` is followed by `$e:expr`
|
||||
($p:path $t:ty) => {}; //~ERROR `$p:path` is followed by `$t:ty`
|
||||
($p:path $s:stmt) => {}; //~ERROR `$p:path` is followed by `$s:stmt`
|
||||
($p:path $p:path) => {}; //~ERROR `$p:path` is followed by `$p:path`
|
||||
($p:path $b:block) => {}; //~ERROR `$p:path` is followed by `$b:block`
|
||||
($p:path $i:ident) => {}; //~ERROR `$p:path` is followed by `$i:ident`
|
||||
($p:path $t:tt) => {}; //~ERROR `$p:path` is followed by `$t:tt`
|
||||
($p:path $i:item) => {}; //~ERROR `$p:path` is followed by `$i:item`
|
||||
($p:path $m:meta) => {}; //~ERROR `$p:path` is followed by `$m:meta`
|
||||
}
|
||||
// FOLLOW(block) = any token
|
||||
// FOLLOW(ident) = any token
|
||||
|
||||
fn main() {}
|
||||
|
190
src/test/run-pass/macro-follow.rs
Normal file
190
src/test/run-pass/macro-follow.rs
Normal file
@ -0,0 +1,190 @@
|
||||
// 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.
|
||||
|
||||
// Check the macro follow sets (see corresponding cfail test).
|
||||
|
||||
// FOLLOW(pat) = {FatArrow, Comma, Eq, Or, Ident(if), Ident(in)}
|
||||
macro_rules! follow_pat {
|
||||
($p:pat =>) => {};
|
||||
($p:pat ,) => {};
|
||||
($p:pat =) => {};
|
||||
($p:pat |) => {};
|
||||
($p:pat if) => {};
|
||||
($p:pat in) => {};
|
||||
}
|
||||
// FOLLOW(expr) = {FatArrow, Comma, Semicolon}
|
||||
macro_rules! follow_expr {
|
||||
($e:expr =>) => {};
|
||||
($e:expr ,) => {};
|
||||
($e:expr ;) => {};
|
||||
}
|
||||
// FOLLOW(ty) = {OpenDelim(Brace), Comma, FatArrow, Colon, Eq, Gt, Semi, Or,
|
||||
// Ident(as), Ident(where), OpenDelim(Bracket)}
|
||||
macro_rules! follow_ty {
|
||||
($t:ty {}) => {};
|
||||
($t:ty ,) => {};
|
||||
($t:ty =>) => {};
|
||||
($t:ty :) => {};
|
||||
($t:ty =) => {};
|
||||
($t:ty >) => {};
|
||||
($t:ty ;) => {};
|
||||
($t:ty |) => {};
|
||||
($t:ty as) => {};
|
||||
($t:ty where) => {};
|
||||
($t:ty []) => {};
|
||||
}
|
||||
// FOLLOW(stmt) = FOLLOW(expr)
|
||||
macro_rules! follow_stmt {
|
||||
($s:stmt =>) => {};
|
||||
($s:stmt ,) => {};
|
||||
($s:stmt ;) => {};
|
||||
}
|
||||
// FOLLOW(path) = FOLLOW(ty)
|
||||
macro_rules! follow_path {
|
||||
($p:path {}) => {};
|
||||
($p:path ,) => {};
|
||||
($p:path =>) => {};
|
||||
($p:path :) => {};
|
||||
($p:path =) => {};
|
||||
($p:path >) => {};
|
||||
($p:path ;) => {};
|
||||
($p:path |) => {};
|
||||
($p:path as) => {};
|
||||
($p:path where) => {};
|
||||
($p:path []) => {};
|
||||
}
|
||||
// FOLLOW(block) = any token
|
||||
macro_rules! follow_block {
|
||||
($b:block ()) => {};
|
||||
($b:block []) => {};
|
||||
($b:block {}) => {};
|
||||
($b:block ,) => {};
|
||||
($b:block =>) => {};
|
||||
($b:block :) => {};
|
||||
($b:block =) => {};
|
||||
($b:block >) => {};
|
||||
($b:block ;) => {};
|
||||
($b:block |) => {};
|
||||
($b:block +) => {};
|
||||
($b:block ident) => {};
|
||||
($b:block $p:pat) => {};
|
||||
($b:block $e:expr) => {};
|
||||
($b:block $t:ty) => {};
|
||||
($b:block $s:stmt) => {};
|
||||
($b:block $p:path) => {};
|
||||
($b:block $b:block) => {};
|
||||
($b:block $i:ident) => {};
|
||||
($b:block $t:tt) => {};
|
||||
($b:block $i:item) => {};
|
||||
($b:block $m:meta) => {};
|
||||
}
|
||||
// FOLLOW(ident) = any token
|
||||
macro_rules! follow_ident {
|
||||
($i:ident ()) => {};
|
||||
($i:ident []) => {};
|
||||
($i:ident {}) => {};
|
||||
($i:ident ,) => {};
|
||||
($i:ident =>) => {};
|
||||
($i:ident :) => {};
|
||||
($i:ident =) => {};
|
||||
($i:ident >) => {};
|
||||
($i:ident ;) => {};
|
||||
($i:ident |) => {};
|
||||
($i:ident +) => {};
|
||||
($i:ident ident) => {};
|
||||
($i:ident $p:pat) => {};
|
||||
($i:ident $e:expr) => {};
|
||||
($i:ident $t:ty) => {};
|
||||
($i:ident $s:stmt) => {};
|
||||
($i:ident $p:path) => {};
|
||||
($i:ident $b:block) => {};
|
||||
($i:ident $i:ident) => {};
|
||||
($i:ident $t:tt) => {};
|
||||
($i:ident $i:item) => {};
|
||||
($i:ident $m:meta) => {};
|
||||
}
|
||||
// FOLLOW(tt) = any token
|
||||
macro_rules! follow_tt {
|
||||
($t:tt ()) => {};
|
||||
($t:tt []) => {};
|
||||
($t:tt {}) => {};
|
||||
($t:tt ,) => {};
|
||||
($t:tt =>) => {};
|
||||
($t:tt :) => {};
|
||||
($t:tt =) => {};
|
||||
($t:tt >) => {};
|
||||
($t:tt ;) => {};
|
||||
($t:tt |) => {};
|
||||
($t:tt +) => {};
|
||||
($t:tt ident) => {};
|
||||
($t:tt $p:pat) => {};
|
||||
($t:tt $e:expr) => {};
|
||||
($t:tt $t:ty) => {};
|
||||
($t:tt $s:stmt) => {};
|
||||
($t:tt $p:path) => {};
|
||||
($t:tt $b:block) => {};
|
||||
($t:tt $i:ident) => {};
|
||||
($t:tt $t:tt) => {};
|
||||
($t:tt $i:item) => {};
|
||||
($t:tt $m:meta) => {};
|
||||
}
|
||||
// FOLLOW(item) = any token
|
||||
macro_rules! follow_item {
|
||||
($i:item ()) => {};
|
||||
($i:item []) => {};
|
||||
($i:item {}) => {};
|
||||
($i:item ,) => {};
|
||||
($i:item =>) => {};
|
||||
($i:item :) => {};
|
||||
($i:item =) => {};
|
||||
($i:item >) => {};
|
||||
($i:item ;) => {};
|
||||
($i:item |) => {};
|
||||
($i:item +) => {};
|
||||
($i:item ident) => {};
|
||||
($i:item $p:pat) => {};
|
||||
($i:item $e:expr) => {};
|
||||
($i:item $t:ty) => {};
|
||||
($i:item $s:stmt) => {};
|
||||
($i:item $p:path) => {};
|
||||
($i:item $b:block) => {};
|
||||
($i:item $i:ident) => {};
|
||||
($i:item $t:tt) => {};
|
||||
($i:item $i:item) => {};
|
||||
($i:item $m:meta) => {};
|
||||
}
|
||||
// FOLLOW(meta) = any token
|
||||
macro_rules! follow_meta {
|
||||
($m:meta ()) => {};
|
||||
($m:meta []) => {};
|
||||
($m:meta {}) => {};
|
||||
($m:meta ,) => {};
|
||||
($m:meta =>) => {};
|
||||
($m:meta :) => {};
|
||||
($m:meta =) => {};
|
||||
($m:meta >) => {};
|
||||
($m:meta ;) => {};
|
||||
($m:meta |) => {};
|
||||
($m:meta +) => {};
|
||||
($m:meta ident) => {};
|
||||
($m:meta $p:pat) => {};
|
||||
($m:meta $e:expr) => {};
|
||||
($m:meta $t:ty) => {};
|
||||
($m:meta $s:stmt) => {};
|
||||
($m:meta $p:path) => {};
|
||||
($m:meta $b:block) => {};
|
||||
($m:meta $i:ident) => {};
|
||||
($m:meta $t:tt) => {};
|
||||
($m:meta $i:item) => {};
|
||||
($m:meta $m:meta) => {};
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
Loading…
x
Reference in New Issue
Block a user