Transition to the new object lifetime defaults, replacing the old
defaults completely.
This commit is contained in:
parent
5708b1a18a
commit
de6b3c282e
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
@ -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"
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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),
|
||||
@ -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,
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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,
|
||||
@ -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)
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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)]
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
@ -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)
|
||||
@ -384,12 +377,9 @@ 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)));
|
||||
@ -397,8 +387,7 @@ impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::ExistentialBounds<'tcx> {
|
||||
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 })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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(())
|
||||
}
|
||||
}
|
||||
|
@ -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>
|
||||
{
|
||||
|
@ -2040,23 +2040,22 @@ 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);
|
||||
|
||||
@ -2064,7 +2063,6 @@ pub fn conv_existential_bounds_from_partitioned_bounds<'tcx>(
|
||||
region_bound: region_bound,
|
||||
builtin_bounds: builtin_bounds,
|
||||
projection_bounds: projection_bounds,
|
||||
region_bound_will_change: will_change,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,19 +51,6 @@ pub trait RegionScope {
|
||||
/// computing `object_lifetime_default` (in particular, in legacy
|
||||
/// modes, it may not be relevant).
|
||||
fn base_object_lifetime_default(&self, span: Span) -> ty::Region;
|
||||
|
||||
/// Used to issue warnings in Rust 1.2, not needed after that.
|
||||
/// True if the result of `object_lifetime_default` will change in 1.3.
|
||||
fn object_lifetime_default_will_change_in_1_3(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
/// Used to issue warnings in Rust 1.2, not needed after that.
|
||||
/// True if the result of `base_object_lifetime_default` differs
|
||||
/// from the result of `object_lifetime_default`.
|
||||
fn base_object_lifetime_default_differs(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
// A scope in which all regions must be explicitly named. This is used
|
||||
@ -216,11 +203,8 @@ impl<'r> RegionScope for ObjectLifetimeDefaultRscope<'r> {
|
||||
None,
|
||||
|
||||
ty::ObjectLifetimeDefault::BaseDefault =>
|
||||
if false { // this will become the behavior in Rust 1.3
|
||||
Some(self.base_object_lifetime_default(span))
|
||||
} else {
|
||||
self.base_scope.object_lifetime_default(span)
|
||||
},
|
||||
// NB: This behavior changed in Rust 1.3.
|
||||
Some(self.base_object_lifetime_default(span)),
|
||||
|
||||
ty::ObjectLifetimeDefault::Specific(r) =>
|
||||
Some(r),
|
||||
@ -228,36 +212,9 @@ impl<'r> RegionScope for ObjectLifetimeDefaultRscope<'r> {
|
||||
}
|
||||
|
||||
fn base_object_lifetime_default(&self, span: Span) -> ty::Region {
|
||||
assert!(false, "this code should not execute until Rust 1.3");
|
||||
self.base_scope.base_object_lifetime_default(span)
|
||||
}
|
||||
|
||||
fn object_lifetime_default_will_change_in_1_3(&self) -> bool {
|
||||
debug!("object_lifetime_default_will_change_in_1_3: {:?}", self.default);
|
||||
|
||||
match self.default {
|
||||
ty::ObjectLifetimeDefault::Ambiguous |
|
||||
ty::ObjectLifetimeDefault::Specific(_) =>
|
||||
false,
|
||||
|
||||
ty::ObjectLifetimeDefault::BaseDefault =>
|
||||
self.base_scope.base_object_lifetime_default_differs()
|
||||
}
|
||||
}
|
||||
|
||||
fn base_object_lifetime_default_differs(&self) -> bool {
|
||||
debug!("base_object_lifetime_default_differs: {:?}", self.default);
|
||||
|
||||
match self.default {
|
||||
ty::ObjectLifetimeDefault::Ambiguous |
|
||||
ty::ObjectLifetimeDefault::Specific(_) =>
|
||||
true,
|
||||
|
||||
ty::ObjectLifetimeDefault::BaseDefault =>
|
||||
self.base_scope.base_object_lifetime_default_differs(),
|
||||
}
|
||||
}
|
||||
|
||||
fn anon_regions(&self,
|
||||
span: Span,
|
||||
count: usize)
|
||||
|
@ -10,8 +10,8 @@
|
||||
|
||||
// aux-build:lifetime_bound_will_change_warning_lib.rs
|
||||
|
||||
// Test that we get suitable warnings when lifetime bound change will
|
||||
// cause breakage.
|
||||
// Test that various corner cases cause an error. These are tests
|
||||
// that used to pass before we tweaked object defaults.
|
||||
|
||||
#![allow(dead_code)]
|
||||
#![allow(unused_variables)]
|
||||
@ -41,12 +41,12 @@ fn test1cc<'a>(x: &'a Box<Fn()+'a>) {
|
||||
|
||||
fn test2<'a>(x: &'a Box<Fn()+'a>) {
|
||||
// but ref_obj will not, so warn.
|
||||
ref_obj(x) //~ WARNING this code may fail to compile in Rust 1.3
|
||||
ref_obj(x) //~ ERROR mismatched types
|
||||
}
|
||||
|
||||
fn test2cc<'a>(x: &'a Box<Fn()+'a>) {
|
||||
// same as test2, but cross crate
|
||||
lib::ref_obj(x) //~ WARNING this code may fail to compile in Rust 1.3
|
||||
lib::ref_obj(x) //~ ERROR mismatched types
|
||||
}
|
||||
|
||||
fn test3<'a>(x: &'a Box<Fn()+'static>) {
|
||||
@ -60,5 +60,5 @@ fn test3cc<'a>(x: &'a Box<Fn()+'static>) {
|
||||
}
|
||||
|
||||
#[rustc_error]
|
||||
fn main() { //~ ERROR compilation successful
|
||||
fn main() {
|
||||
}
|
||||
|
@ -47,10 +47,7 @@ fn d(t: Ref2<Ref1<Test>>) {
|
||||
}
|
||||
|
||||
fn e(t: Ref2<Ref0<Test>>) {
|
||||
//~^ ERROR lifetime bound for this object type cannot be deduced from context
|
||||
//
|
||||
// In this case, Ref2 is ambiguous, and Ref0 inherits the
|
||||
// ambiguity.
|
||||
// In this case, Ref2 is ambiguous, but Ref0 overrides with 'static.
|
||||
}
|
||||
|
||||
fn f(t: &Ref2<Test>) {
|
||||
|
@ -34,13 +34,11 @@ fn load0<'a>(ss: &'a Box<SomeTrait>) -> Box<SomeTrait> {
|
||||
//
|
||||
// Under new rules the result is:
|
||||
//
|
||||
// for<'a> fn(&'a Box<SomeTrait+'a>) -> Box<SomeTrait+'static>
|
||||
// for<'a> fn(&'a Box<SomeTrait+'static>) -> Box<SomeTrait+'static>
|
||||
//
|
||||
// Therefore, we get a type error attempting to return `deref(ss)`
|
||||
// since `SomeTrait+'a <: SomeTrait+'static` does not hold.
|
||||
// Therefore, no type error.
|
||||
|
||||
deref(ss)
|
||||
//~^ ERROR cannot infer
|
||||
}
|
||||
|
||||
fn load1(ss: &SomeTrait) -> &SomeTrait {
|
||||
|
@ -0,0 +1,31 @@
|
||||
// Copyright 2015 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.
|
||||
|
||||
// Test that the lifetime from the enclosing `&` is "inherited"
|
||||
// through the `Box` struct.
|
||||
|
||||
// pretty-expanded FIXME #23616
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
trait Test {
|
||||
fn foo(&self) { }
|
||||
}
|
||||
|
||||
struct SomeStruct<'a> {
|
||||
t: &'a Box<Test>,
|
||||
}
|
||||
|
||||
fn c<'a>(t: &'a Box<Test+'a>, mut ss: SomeStruct<'a>) {
|
||||
ss.t = t; //~ ERROR mismatched types
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
// Copyright 2015 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.
|
||||
|
||||
// Test that the lifetime from the enclosing `&` is "inherited"
|
||||
// through the `MyBox` struct.
|
||||
|
||||
// pretty-expanded FIXME #23616
|
||||
|
||||
#![allow(dead_code)]
|
||||
#![feature(rustc_error)]
|
||||
|
||||
trait Test {
|
||||
fn foo(&self) { }
|
||||
}
|
||||
|
||||
struct SomeStruct<'a> {
|
||||
t: &'a MyBox<Test>,
|
||||
u: &'a MyBox<Test+'a>,
|
||||
}
|
||||
|
||||
struct MyBox<T:?Sized> {
|
||||
b: Box<T>
|
||||
}
|
||||
|
||||
fn c<'a>(t: &'a MyBox<Test+'a>, mut ss: SomeStruct<'a>) {
|
||||
ss.t = t; //~ ERROR mismatched types
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
@ -27,7 +27,7 @@ fn deref<T>(ss: &T) -> T {
|
||||
}
|
||||
|
||||
fn load0(ss: &MyBox<SomeTrait>) -> MyBox<SomeTrait> {
|
||||
deref(ss) //~ ERROR cannot infer
|
||||
deref(ss)
|
||||
}
|
||||
|
||||
fn load1<'a,'b>(a: &'a MyBox<SomeTrait>,
|
||||
@ -36,11 +36,10 @@ fn load1<'a,'b>(a: &'a MyBox<SomeTrait>,
|
||||
{
|
||||
a
|
||||
//~^ ERROR cannot infer
|
||||
//~| ERROR mismatched types
|
||||
}
|
||||
|
||||
fn load2<'a>(ss: &MyBox<SomeTrait+'a>) -> MyBox<SomeTrait+'a> {
|
||||
load0(ss) //~ WARNING E0398
|
||||
load0(ss) //~ ERROR mismatched types
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
@ -1,22 +0,0 @@
|
||||
// Copyright 2014-2015 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.
|
||||
|
||||
// aux-build:lang-item-public.rs
|
||||
// ignore-android
|
||||
|
||||
#![feature(start, no_std)]
|
||||
#![no_std]
|
||||
|
||||
extern crate lang_item_public as lang_lib;
|
||||
|
||||
#[start]
|
||||
fn main(_: isize, _: *const *const u8) -> isize {
|
||||
1_isize % 1_isize
|
||||
}
|
@ -32,9 +32,7 @@ fn b<'a>(t: &'a Box<Test>, mut ss: SomeStruct<'a>) {
|
||||
ss.u = t;
|
||||
}
|
||||
|
||||
fn c<'a>(t: &'a Box<Test+'a>, mut ss: SomeStruct<'a>) {
|
||||
ss.t = t;
|
||||
}
|
||||
// see also compile-fail/object-lifetime-default-from-rptr-box-error.rs
|
||||
|
||||
fn d<'a>(t: &'a Box<Test+'a>, mut ss: SomeStruct<'a>) {
|
||||
ss.u = t;
|
||||
|
@ -36,9 +36,7 @@ fn b<'a>(t: &'a MyBox<Test>, mut ss: SomeStruct<'a>) {
|
||||
ss.u = t;
|
||||
}
|
||||
|
||||
fn c<'a>(t: &'a MyBox<Test+'a>, mut ss: SomeStruct<'a>) {
|
||||
ss.t = t;
|
||||
}
|
||||
// see also compile-fail/object-lifetime-default-from-rptr-box-error.rs
|
||||
|
||||
fn d<'a>(t: &'a MyBox<Test+'a>, mut ss: SomeStruct<'a>) {
|
||||
ss.u = t;
|
||||
|
Loading…
x
Reference in New Issue
Block a user