Skip to content

Commit

Permalink
Auto merge of #27045 - nikomatsakis:better-object-defaults-error, r=p…
Browse files Browse the repository at this point in the history
…nkfelix

Transition to the new object lifetime defaults, replacing the old defaults completely.

r? @pnkfelix 

This is a [breaking-change] as specified by [RFC 1156][1156] (though all cases that would break should have been receiving warnings starting in Rust 1.2). Types like `&'a Box<Trait>` (or `&'a Rc<Trait>`, etc) will change from being interpreted as `&'a Box<Trait+'a>` to `&'a Box<Trait+'static>`. To restore the old behavior, write the `+'a` explicitly. For example, the function:


```rust
trait Trait { }
fn foo(x: &Box<Trait>) { ... }
```

would be rewritten as:

```rust
trait Trait { }
fn foo(x: &'a Box<Trait+'a>) { ... }
```

if one wanted to preserve the current typing.

[1156]: https://github.com/rust-lang/rfcs/blob/master/text/1156-adjust-default-object-bounds.md
  • Loading branch information
bors committed Jul 17, 2015
2 parents d4432b3 + de6b3c2 commit e05ac39
Show file tree
Hide file tree
Showing 28 changed files with 97 additions and 240 deletions.
9 changes: 1 addition & 8 deletions src/librustc/metadata/tydecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -887,16 +887,9 @@ fn parse_existential_bounds_<'a,'tcx, F>(st: &mut PState<'a,'tcx>,
}
}

let region_bound_will_change = match next(st) {
'y' => true,
'n' => false,
c => panic!("parse_ty: expected y/n not '{}'", c)
};

return ty::ExistentialBounds { region_bound: region_bound,
builtin_bounds: builtin_bounds,
projection_bounds: projection_bounds,
region_bound_will_change: region_bound_will_change };
projection_bounds: projection_bounds };
}

fn parse_builtin_bounds<F>(st: &mut PState, mut _conv: F) -> ty::BuiltinBounds where
Expand Down
2 changes: 0 additions & 2 deletions src/librustc/metadata/tyencode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,8 +390,6 @@ pub fn enc_existential_bounds<'a,'tcx>(w: &mut Encoder,
}

mywrite!(w, ".");

mywrite!(w, "{}", if bs.region_bound_will_change {'y'} else {'n'});
}

pub fn enc_region_bounds<'a, 'tcx>(w: &mut Encoder,
Expand Down
5 changes: 0 additions & 5 deletions src/librustc/middle/infer/bivariate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,6 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Bivariate<'a, 'tcx> {

fn a_is_expected(&self) -> bool { self.fields.a_is_expected }

fn will_change(&mut self, _: bool, _: bool) -> bool {
// since we are not comparing regions, we don't care
false
}

fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self,
variance: ty::Variance,
a: &T,
Expand Down
5 changes: 0 additions & 5 deletions src/librustc/middle/infer/equate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,6 @@ impl<'a, 'tcx> TypeRelation<'a,'tcx> for Equate<'a, 'tcx> {

fn a_is_expected(&self) -> bool { self.fields.a_is_expected }

fn will_change(&mut self, a: bool, b: bool) -> bool {
// if either side changed from what it was, that could cause equality to fail
a || b
}

fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self,
_: ty::Variance,
a: &T,
Expand Down
6 changes: 2 additions & 4 deletions src/librustc/middle/infer/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -593,8 +593,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
sub: Region,
sup: Region) {
match origin {
infer::Subtype(trace) |
infer::DefaultExistentialBound(trace) => {
infer::Subtype(trace) => {
let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
self.report_and_explain_type_error(trace, &terr);
}
Expand Down Expand Up @@ -1570,8 +1569,7 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {

fn note_region_origin(&self, origin: &SubregionOrigin<'tcx>) {
match *origin {
infer::Subtype(ref trace) |
infer::DefaultExistentialBound(ref trace) => {
infer::Subtype(ref trace) => {
let desc = match trace.origin {
infer::Misc(_) => {
"types are compatible"
Expand Down
10 changes: 0 additions & 10 deletions src/librustc/middle/infer/glb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,6 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Glb<'a, 'tcx> {

fn a_is_expected(&self) -> bool { self.fields.a_is_expected }

fn will_change(&mut self, a: bool, b: bool) -> bool {
// Hmm, so the result of GLB will still be a LB if one or both
// sides change to 'static, but it may no longer be the GLB.
// I'm going to go with `a || b` here to be conservative,
// since the result of this operation may be affected, though
// I think it would mostly be more accepting than before (since the result
// would be a bigger region).
a || b
}

fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self,
variance: ty::Variance,
a: &T,
Expand Down
5 changes: 0 additions & 5 deletions src/librustc/middle/infer/lub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,6 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Lub<'a, 'tcx> {

fn a_is_expected(&self) -> bool { self.fields.a_is_expected }

fn will_change(&mut self, a: bool, b: bool) -> bool {
// result will be 'static if a || b
a || b
}

fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self,
variance: ty::Variance,
a: &T,
Expand Down
4 changes: 0 additions & 4 deletions src/librustc/middle/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,9 +191,6 @@ pub enum SubregionOrigin<'tcx> {
// Arose from a subtyping relation
Subtype(TypeTrace<'tcx>),

// Arose from a subtyping relation
DefaultExistentialBound(TypeTrace<'tcx>),

// Stack-allocated closures cannot outlive innermost loop
// or function so as to ensure we only require finite stack
InfStackClosure(Span),
Expand Down Expand Up @@ -1466,7 +1463,6 @@ impl<'tcx> SubregionOrigin<'tcx> {
pub fn span(&self) -> Span {
match *self {
Subtype(ref a) => a.span(),
DefaultExistentialBound(ref a) => a.span(),
InfStackClosure(a) => a,
InvokeClosure(a) => a,
DerefPointer(a) => a,
Expand Down
47 changes: 0 additions & 47 deletions src/librustc/middle/infer/region_inference/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1357,56 +1357,9 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
}
}

// Check for future hostile edges tied to a bad default
self.report_future_hostility(&graph);

(0..self.num_vars() as usize).map(|idx| var_data[idx].value).collect()
}

fn report_future_hostility(&self, graph: &RegionGraph) {
let constraints = self.constraints.borrow();
for edge in graph.all_edges() {
match constraints[&edge.data] {
SubregionOrigin::DefaultExistentialBound(_) => {
// this will become 'static in the future
}
_ => { continue; }
}

// this constraint will become a 'static constraint in the
// future, so walk outward and see if we have any hard
// bounds that could not be inferred to 'static
for nid in graph.depth_traverse(edge.target()) {
for (_, succ) in graph.outgoing_edges(nid) {
match succ.data {
ConstrainVarSubReg(_, r) => {
match r {
ty::ReStatic | ty::ReInfer(_) => {
/* OK */
}
ty::ReFree(_) | ty::ReScope(_) | ty::ReEmpty => {
span_warn!(
self.tcx.sess,
constraints[&edge.data].span(),
E0398,
"this code may fail to compile in Rust 1.3 due to \
the proposed change in object lifetime bound defaults");
return; // only issue the warning once per fn
}
ty::ReEarlyBound(..) | ty::ReLateBound(..) => {
self.tcx.sess.span_bug(
constraints[&succ.data].span(),
"relation to bound region");
}
}
}
_ => { }
}
}
}
}
}

fn construct_graph(&self) -> RegionGraph {
let num_vars = self.num_vars();

Expand Down
18 changes: 4 additions & 14 deletions src/librustc/middle/infer/sub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,6 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Sub<'a, 'tcx> {
r
}

fn will_change(&mut self, a: bool, b: bool) -> bool {
// if we have (Foo+'a) <: (Foo+'b), this requires that 'a:'b.
// So if 'a becomes 'static, no additional errors can occur.
// OTOH, if 'a stays the same, but 'b becomes 'static, we
// could have a problem.
!a && b
}

fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self,
variance: ty::Variance,
a: &T,
Expand Down Expand Up @@ -106,12 +98,10 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Sub<'a, 'tcx> {
fn regions(&mut self, a: ty::Region, b: ty::Region) -> RelateResult<'tcx, ty::Region> {
debug!("{}.regions({:?}, {:?}) self.cause={:?}",
self.tag(), a, b, self.fields.cause);
let origin = match self.fields.cause {
Some(Cause::ExistentialRegionBound(true)) =>
SubregionOrigin::DefaultExistentialBound(self.fields.trace.clone()),
_ =>
SubregionOrigin::Subtype(self.fields.trace.clone()),
};
// FIXME -- we have more fine-grained information available
// from the "cause" field, we could perhaps give more tailored
// error messages.
let origin = SubregionOrigin::Subtype(self.fields.trace.clone());
self.fields.infcx.region_vars.make_subregion(origin, a, b);
Ok(a)
}
Expand Down
1 change: 0 additions & 1 deletion src/librustc/middle/traits/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2462,7 +2462,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
region_bound: data_b.bounds.region_bound,
builtin_bounds: data_b.bounds.builtin_bounds,
projection_bounds: data_a.bounds.projection_bounds.clone(),
region_bound_will_change: data_b.bounds.region_bound_will_change,
};

let new_trait = tcx.mk_trait(data_a.principal.clone(), bounds);
Expand Down
5 changes: 0 additions & 5 deletions src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1989,11 +1989,6 @@ pub struct ExistentialBounds<'tcx> {
pub region_bound: ty::Region,
pub builtin_bounds: BuiltinBounds,
pub projection_bounds: Vec<PolyProjectionPredicate<'tcx>>,

// If true, this TyTrait used a "default bound" in the surface
// syntax. This makes no difference to the type system but is
// handy for error reporting.
pub region_bound_will_change: bool,
}

#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
Expand Down
1 change: 0 additions & 1 deletion src/librustc/middle/ty_fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -700,7 +700,6 @@ pub fn super_fold_existential_bounds<'tcx, T: TypeFolder<'tcx>>(
region_bound: bounds.region_bound.fold_with(this),
builtin_bounds: bounds.builtin_bounds,
projection_bounds: bounds.projection_bounds.fold_with(this),
region_bound_will_change: bounds.region_bound_will_change,
}
}

Expand Down
5 changes: 0 additions & 5 deletions src/librustc/middle/ty_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,6 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Match<'a, 'tcx> {
fn tcx(&self) -> &'a ty::ctxt<'tcx> { self.tcx }
fn a_is_expected(&self) -> bool { true } // irrelevant

fn will_change(&mut self, _: bool, _: bool) -> bool {
// we're ignoring regions in this code
false
}

fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self,
_: ty::Variance,
a: &T,
Expand Down
17 changes: 3 additions & 14 deletions src/librustc/middle/ty_relate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub type RelateResult<'tcx, T> = Result<T, ty::TypeError<'tcx>>;

#[derive(Clone, Debug)]
pub enum Cause {
ExistentialRegionBound(bool), // if true, this is a default, else explicit
ExistentialRegionBound, // relating an existential region bound
}

pub trait TypeRelation<'a,'tcx> : Sized {
Expand All @@ -43,13 +43,6 @@ pub trait TypeRelation<'a,'tcx> : Sized {
f(self)
}

/// Hack for deciding whether the lifetime bound defaults change
/// will be a breaking change or not. The bools indicate whether
/// `a`/`b` have a default that will change to `'static`; the
/// result is true if this will potentially affect the affect of
/// relating `a` and `b`.
fn will_change(&mut self, a: bool, b: bool) -> bool;

/// Generic relation routine suitable for most anything.
fn relate<T:Relate<'a,'tcx>>(&mut self, a: &T, b: &T) -> RelateResult<'tcx, T> {
Relate::relate(self, a, b)
Expand Down Expand Up @@ -384,21 +377,17 @@ impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::ExistentialBounds<'tcx> {
-> RelateResult<'tcx, ty::ExistentialBounds<'tcx>>
where R: TypeRelation<'a,'tcx>
{
let will_change = relation.will_change(a.region_bound_will_change,
b.region_bound_will_change);

let r =
try!(relation.with_cause(
Cause::ExistentialRegionBound(will_change),
Cause::ExistentialRegionBound,
|relation| relation.relate_with_variance(ty::Contravariant,
&a.region_bound,
&b.region_bound)));
let nb = try!(relation.relate(&a.builtin_bounds, &b.builtin_bounds));
let pb = try!(relation.relate(&a.projection_bounds, &b.projection_bounds));
Ok(ty::ExistentialBounds { region_bound: r,
builtin_bounds: nb,
projection_bounds: pb,
region_bound_will_change: will_change })
projection_bounds: pb })
}
}

Expand Down
4 changes: 0 additions & 4 deletions src/librustc/util/ppaux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -300,10 +300,6 @@ impl<'tcx> fmt::Display for ty::TraitTy<'tcx> {
try!(write!(f, " + {}", bound));
}

if bounds.region_bound_will_change && verbose() {
try!(write!(f, " [WILL-CHANGE]"));
}

Ok(())
}
}
Expand Down
10 changes: 0 additions & 10 deletions src/librustc_trans/trans/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,16 +82,6 @@ pub fn erase_regions<'tcx,T>(cx: &ty::ctxt<'tcx>, value: &T) -> T
return t_norm;
}

fn fold_existential_bounds(&mut self, s: &ty::ExistentialBounds<'tcx>)
-> ty::ExistentialBounds<'tcx> {
let mut s = ty_fold::super_fold_existential_bounds(self, s);

// this annoying flag messes up trans normalization
s.region_bound_will_change = false;

s
}

fn fold_binder<T>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T>
where T : TypeFoldable<'tcx>
{
Expand Down
12 changes: 5 additions & 7 deletions src/librustc_typeck/astconv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2040,31 +2040,29 @@ pub fn conv_existential_bounds_from_partitioned_bounds<'tcx>(
principal_trait_ref,
builtin_bounds);

let (region_bound, will_change) = match region_bound {
Some(r) => (r, false),
let region_bound = match region_bound {
Some(r) => r,
None => {
match rscope.object_lifetime_default(span) {
Some(r) => (r, rscope.object_lifetime_default_will_change_in_1_3()),
Some(r) => r,
None => {
span_err!(this.tcx().sess, span, E0228,
"the lifetime bound for this object type cannot be deduced \
from context; please supply an explicit bound");
(ty::ReStatic, false)
ty::ReStatic
}
}
}
};

debug!("region_bound: {:?} will_change: {:?}",
region_bound, will_change);
debug!("region_bound: {:?}", region_bound);

ty::sort_bounds_list(&mut projection_bounds);

ty::ExistentialBounds {
region_bound: region_bound,
builtin_bounds: builtin_bounds,
projection_bounds: projection_bounds,
region_bound_will_change: will_change,
}
}

Expand Down
Loading

0 comments on commit e05ac39

Please sign in to comment.