Skip to content

Commit 9099577

Browse files
committed
Add a boolean flag to ExistentialBounds tracking whether the
region-bound is expected to change in Rust 1.3, but don't use it for anything in this commit. Note that this is not a "significant" part of the type (it's not part of the formal model) so we have to normalize this away or trans starts to get confused because two equal types wind up with distinct LLVM types.
1 parent ef85338 commit 9099577

File tree

19 files changed

+202
-39
lines changed

19 files changed

+202
-39
lines changed

src/librustc/metadata/tydecode.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -887,9 +887,16 @@ fn parse_existential_bounds_<'a,'tcx, F>(st: &mut PState<'a,'tcx>,
887887
}
888888
}
889889

890+
let region_bound_will_change = match next(st) {
891+
'y' => true,
892+
'n' => false,
893+
c => panic!("parse_ty: expected y/n not '{}'", c)
894+
};
895+
890896
return ty::ExistentialBounds { region_bound: region_bound,
891897
builtin_bounds: builtin_bounds,
892-
projection_bounds: projection_bounds };
898+
projection_bounds: projection_bounds,
899+
region_bound_will_change: region_bound_will_change };
893900
}
894901

895902
fn parse_builtin_bounds<F>(st: &mut PState, mut _conv: F) -> ty::BuiltinBounds where

src/librustc/metadata/tyencode.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,8 @@ pub fn enc_existential_bounds<'a,'tcx>(w: &mut Encoder,
390390
}
391391

392392
mywrite!(w, ".");
393+
394+
mywrite!(w, "{}", if bs.region_bound_will_change {'y'} else {'n'});
393395
}
394396

395397
pub fn enc_region_bounds<'a, 'tcx>(w: &mut Encoder,

src/librustc/middle/infer/bivariate.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Bivariate<'a, 'tcx> {
4949

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

52+
fn will_change(&mut self, _: bool, _: bool) -> bool {
53+
// since we are not comparing regions, we don't care
54+
false
55+
}
56+
5257
fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self,
5358
variance: ty::Variance,
5459
a: &T,

src/librustc/middle/infer/combine.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ pub struct CombineFields<'a, 'tcx: 'a> {
5656
pub infcx: &'a InferCtxt<'a, 'tcx>,
5757
pub a_is_expected: bool,
5858
pub trace: TypeTrace<'tcx>,
59+
pub cause: Option<ty_relate::Cause>,
5960
}
6061

6162
pub fn super_combine_tys<'a,'tcx:'a,R>(infcx: &InferCtxt<'a, 'tcx>,

src/librustc/middle/infer/equate.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ impl<'a, 'tcx> TypeRelation<'a,'tcx> for Equate<'a, 'tcx> {
3434

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

37+
fn will_change(&mut self, a: bool, b: bool) -> bool {
38+
// if either side changed from what it was, that could cause equality to fail
39+
a || b
40+
}
41+
3742
fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self,
3843
_: ty::Variance,
3944
a: &T,

src/librustc/middle/infer/error_reporting.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -593,7 +593,8 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
593593
sub: Region,
594594
sup: Region) {
595595
match origin {
596-
infer::Subtype(trace) => {
596+
infer::Subtype(trace) |
597+
infer::DefaultExistentialBound(trace) => {
597598
let terr = ty::terr_regions_does_not_outlive(sup, sub);
598599
self.report_and_explain_type_error(trace, &terr);
599600
}
@@ -1569,7 +1570,8 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
15691570

15701571
fn note_region_origin(&self, origin: &SubregionOrigin<'tcx>) {
15711572
match *origin {
1572-
infer::Subtype(ref trace) => {
1573+
infer::Subtype(ref trace) |
1574+
infer::DefaultExistentialBound(ref trace) => {
15731575
let desc = match trace.origin {
15741576
infer::Misc(_) => {
15751577
"types are compatible"

src/librustc/middle/infer/glb.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,16 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Glb<'a, 'tcx> {
3535

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

38+
fn will_change(&mut self, a: bool, b: bool) -> bool {
39+
// Hmm, so the result of GLB will still be a LB if one or both
40+
// sides change to 'static, but it may no longer be the GLB.
41+
// I'm going to go with `a || b` here to be conservative,
42+
// since the result of this operation may be affected, though
43+
// I think it would mostly be more accepting than before (since the result
44+
// would be a bigger region).
45+
a || b
46+
}
47+
3848
fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self,
3949
variance: ty::Variance,
4050
a: &T,

src/librustc/middle/infer/lub.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Lub<'a, 'tcx> {
3535

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

38+
fn will_change(&mut self, a: bool, b: bool) -> bool {
39+
// result will be 'static if a || b
40+
a || b
41+
}
42+
3843
fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self,
3944
variance: ty::Variance,
4045
a: &T,

src/librustc/middle/infer/mod.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,9 @@ pub enum SubregionOrigin<'tcx> {
194194
// Arose from a subtyping relation
195195
Subtype(TypeTrace<'tcx>),
196196

197+
// Arose from a subtyping relation
198+
DefaultExistentialBound(TypeTrace<'tcx>),
199+
197200
// Stack-allocated closures cannot outlive innermost loop
198201
// or function so as to ensure we only require finite stack
199202
InfStackClosure(Span),
@@ -658,7 +661,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
658661
-> CombineFields<'a, 'tcx> {
659662
CombineFields {infcx: self,
660663
a_is_expected: a_is_expected,
661-
trace: trace}
664+
trace: trace,
665+
cause: None}
662666
}
663667

664668
// public so that it can be used from the rustc_driver unit tests
@@ -1464,6 +1468,7 @@ impl<'tcx> SubregionOrigin<'tcx> {
14641468
pub fn span(&self) -> Span {
14651469
match *self {
14661470
Subtype(ref a) => a.span(),
1471+
DefaultExistentialBound(ref a) => a.span(),
14671472
InfStackClosure(a) => a,
14681473
InvokeClosure(a) => a,
14691474
DerefPointer(a) => a,

src/librustc/middle/infer/sub.rs

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,17 @@
1010

1111
use super::combine::{self, CombineFields};
1212
use super::higher_ranked::HigherRankedRelations;
13-
use super::Subtype;
13+
use super::SubregionOrigin;
1414
use super::type_variable::{SubtypeOf, SupertypeOf};
1515

1616
use middle::ty::{self, Ty};
1717
use middle::ty::TyVar;
18-
use middle::ty_relate::{Relate, RelateResult, TypeRelation};
18+
use middle::ty_relate::{Cause, Relate, RelateResult, TypeRelation};
19+
use std::mem;
1920

2021
/// "Greatest lower bound" (common subtype)
2122
pub struct Sub<'a, 'tcx: 'a> {
22-
fields: CombineFields<'a, 'tcx>
23+
fields: CombineFields<'a, 'tcx>,
2324
}
2425

2526
impl<'a, 'tcx> Sub<'a, 'tcx> {
@@ -33,6 +34,25 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Sub<'a, 'tcx> {
3334
fn tcx(&self) -> &'a ty::ctxt<'tcx> { self.fields.infcx.tcx }
3435
fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
3536

37+
fn with_cause<F,R>(&mut self, cause: Cause, f: F) -> R
38+
where F: FnOnce(&mut Self) -> R
39+
{
40+
debug!("sub with_cause={:?}", cause);
41+
let old_cause = mem::replace(&mut self.fields.cause, Some(cause));
42+
let r = f(self);
43+
debug!("sub old_cause={:?}", old_cause);
44+
self.fields.cause = old_cause;
45+
r
46+
}
47+
48+
fn will_change(&mut self, a: bool, b: bool) -> bool {
49+
// if we have (Foo+'a) <: (Foo+'b), this requires that 'a:'b.
50+
// So if 'a becomes 'static, no additional errors can occur.
51+
// OTOH, if 'a stays the same, but 'b becomes 'static, we
52+
// could have a problem.
53+
!a && b
54+
}
55+
3656
fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self,
3757
variance: ty::Variance,
3858
a: &T,
@@ -84,11 +104,14 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Sub<'a, 'tcx> {
84104
}
85105

86106
fn regions(&mut self, a: ty::Region, b: ty::Region) -> RelateResult<'tcx, ty::Region> {
87-
debug!("{}.regions({:?}, {:?})",
88-
self.tag(),
89-
a,
90-
b);
91-
let origin = Subtype(self.fields.trace.clone());
107+
debug!("{}.regions({:?}, {:?}) self.cause={:?}",
108+
self.tag(), a, b, self.fields.cause);
109+
let origin = match self.fields.cause {
110+
Some(Cause::ExistentialRegionBound(true)) =>
111+
SubregionOrigin::DefaultExistentialBound(self.fields.trace.clone()),
112+
_ =>
113+
SubregionOrigin::Subtype(self.fields.trace.clone()),
114+
};
92115
self.fields.infcx.region_vars.make_subregion(origin, a, b);
93116
Ok(a)
94117
}

src/librustc/middle/traits/select.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2445,6 +2445,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
24452445
region_bound: data_b.bounds.region_bound,
24462446
builtin_bounds: data_b.bounds.builtin_bounds,
24472447
projection_bounds: data_a.bounds.projection_bounds.clone(),
2448+
region_bound_will_change: data_b.bounds.region_bound_will_change,
24482449
};
24492450

24502451
let new_trait = tcx.mk_trait(data_a.principal.clone(), bounds);

src/librustc/middle/ty.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2055,6 +2055,11 @@ pub struct ExistentialBounds<'tcx> {
20552055
pub region_bound: ty::Region,
20562056
pub builtin_bounds: BuiltinBounds,
20572057
pub projection_bounds: Vec<PolyProjectionPredicate<'tcx>>,
2058+
2059+
// If true, this TyTrait used a "default bound" in the surface
2060+
// syntax. This makes no difference to the type system but is
2061+
// handy for error reporting.
2062+
pub region_bound_will_change: bool,
20582063
}
20592064

20602065
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]

src/librustc/middle/ty_fold.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -728,6 +728,7 @@ pub fn super_fold_existential_bounds<'tcx, T: TypeFolder<'tcx>>(
728728
region_bound: bounds.region_bound.fold_with(this),
729729
builtin_bounds: bounds.builtin_bounds,
730730
projection_bounds: bounds.projection_bounds.fold_with(this),
731+
region_bound_will_change: bounds.region_bound_will_change,
731732
}
732733
}
733734

src/librustc/middle/ty_match.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Match<'a, 'tcx> {
4242
fn tcx(&self) -> &'a ty::ctxt<'tcx> { self.tcx }
4343
fn a_is_expected(&self) -> bool { true } // irrelevant
4444

45+
fn will_change(&mut self, _: bool, _: bool) -> bool {
46+
// we're ignoring regions in this code
47+
false
48+
}
49+
4550
fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self,
4651
_: ty::Variance,
4752
a: &T,

src/librustc/middle/ty_relate/mod.rs

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ use syntax::ast;
2222

2323
pub type RelateResult<'tcx, T> = Result<T, ty::type_err<'tcx>>;
2424

25+
#[derive(Clone, Debug)]
26+
pub enum Cause {
27+
ExistentialRegionBound(bool), // if true, this is a default, else explicit
28+
}
29+
2530
pub trait TypeRelation<'a,'tcx> : Sized {
2631
fn tcx(&self) -> &'a ty::ctxt<'tcx>;
2732

@@ -32,6 +37,19 @@ pub trait TypeRelation<'a,'tcx> : Sized {
3237
/// relation. Just affects error messages.
3338
fn a_is_expected(&self) -> bool;
3439

40+
fn with_cause<F,R>(&mut self, _cause: Cause, f: F) -> R
41+
where F: FnOnce(&mut Self) -> R
42+
{
43+
f(self)
44+
}
45+
46+
/// Hack for deciding whether the lifetime bound defaults change
47+
/// will be a breaking change or not. The bools indicate whether
48+
/// `a`/`b` have a default that will change to `'static`; the
49+
/// result is true if this will potentially affect the affect of
50+
/// relating `a` and `b`.
51+
fn will_change(&mut self, a: bool, b: bool) -> bool;
52+
3553
/// Generic relation routine suitable for most anything.
3654
fn relate<T:Relate<'a,'tcx>>(&mut self, a: &T, b: &T) -> RelateResult<'tcx, T> {
3755
Relate::relate(self, a, b)
@@ -366,14 +384,21 @@ impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::ExistentialBounds<'tcx> {
366384
-> RelateResult<'tcx, ty::ExistentialBounds<'tcx>>
367385
where R: TypeRelation<'a,'tcx>
368386
{
369-
let r = try!(relation.relate_with_variance(ty::Contravariant,
370-
&a.region_bound,
371-
&b.region_bound));
387+
let will_change = relation.will_change(a.region_bound_will_change,
388+
b.region_bound_will_change);
389+
390+
let r =
391+
try!(relation.with_cause(
392+
Cause::ExistentialRegionBound(will_change),
393+
|relation| relation.relate_with_variance(ty::Contravariant,
394+
&a.region_bound,
395+
&b.region_bound)));
372396
let nb = try!(relation.relate(&a.builtin_bounds, &b.builtin_bounds));
373397
let pb = try!(relation.relate(&a.projection_bounds, &b.projection_bounds));
374398
Ok(ty::ExistentialBounds { region_bound: r,
375399
builtin_bounds: nb,
376-
projection_bounds: pb })
400+
projection_bounds: pb,
401+
region_bound_will_change: will_change })
377402
}
378403
}
379404

src/librustc/util/ppaux.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,10 @@ impl<'tcx> fmt::Display for ty::TraitTy<'tcx> {
299299
}
300300
}
301301

302+
if bounds.region_bound_will_change && tcx.sess.verbose() {
303+
components.push(format!("WILL-CHANGE"));
304+
}
305+
302306
Ok(())
303307
}
304308
}

src/librustc_trans/trans/common.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,16 @@ pub fn erase_regions<'tcx,T>(cx: &ty::ctxt<'tcx>, value: &T) -> T
8282
return t_norm;
8383
}
8484

85+
fn fold_existential_bounds(&mut self, s: &ty::ExistentialBounds<'tcx>)
86+
-> ty::ExistentialBounds<'tcx> {
87+
let mut s = ty_fold::super_fold_existential_bounds(self, s);
88+
89+
// this annoying flag messes up trans normalization
90+
s.region_bound_will_change = false;
91+
92+
s
93+
}
94+
8595
fn fold_binder<T>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T>
8696
where T : TypeFoldable<'tcx>
8797
{

0 commit comments

Comments
 (0)