}
_ => (source, None),
};
- let source = source.adjust_for_autoref(self.tcx, reborrow);
+ let coerce_source = source.adjust_for_autoref(self.tcx, reborrow);
+
+ let adjust = Adjust::DerefRef {
+ autoderefs: if reborrow.is_some() { 1 } else { 0 },
+ autoref: reborrow,
+ unsize: true,
+ };
+
+ // Setup either a subtyping or a LUB relationship between
+ // the `CoerceUnsized` target type and the expected type.
+ // We only have the latter, so we use an inference variable
+ // for the former and let type inference do the rest.
+ let origin = TypeVariableOrigin::MiscVariable(self.cause.span);
+ let coerce_target = self.next_ty_var(origin);
+ let mut coercion = self.unify_and(coerce_target, target, adjust)?;
let mut selcx = traits::SelectionContext::new(self);
// Use a FIFO queue for this custom fulfillment procedure.
let mut queue = VecDeque::new();
- let mut obligations = vec![];
// Create an obligation for `Source: CoerceUnsized<Target>`.
let cause = ObligationCause::misc(self.cause.span, self.body_id);
queue.push_back(self.tcx
- .predicate_for_trait_def(cause, coerce_unsized_did, 0, source, &[target]));
+ .predicate_for_trait_def(cause, coerce_unsized_did, 0,
+ coerce_source, &[coerce_target]));
// Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
// emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where
let trait_ref = match obligation.predicate {
ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => tr.clone(),
_ => {
- obligations.push(obligation);
+ coercion.obligations.push(obligation);
continue;
}
};
}
}
- success(Adjust::DerefRef {
- autoderefs: if reborrow.is_some() { 1 } else { 0 },
- autoref: reborrow,
- unsize: true,
- }, target, obligations)
+ Ok(coercion)
}
fn coerce_from_safe_fn(&self,
// which fails to type check.
ss
- //~^ ERROR lifetime bound not satisfied
+ //~^ ERROR cannot infer
//~| ERROR cannot infer
}
// `Box<SomeTrait>` defaults to a `'static` bound, so this return
// is illegal.
- ss.r //~ ERROR lifetime bound not satisfied
+ ss.r //~ ERROR cannot infer an appropriate lifetime
}
fn store(ss: &mut SomeStruct, b: Box<SomeTrait>) {
fn store1<'b>(ss: &mut SomeStruct, b: Box<SomeTrait+'b>) {
// Here we override the lifetimes explicitly, and so naturally we get an error.
- ss.r = b; //~ ERROR lifetime bound not satisfied
+ ss.r = b; //~ ERROR cannot infer an appropriate lifetime
}
fn main() {
fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box<SomeTrait+'c> {
// A outlives 'a AND 'b...but not 'c.
- box v as Box<SomeTrait+'a> //~ ERROR lifetime bound not satisfied
+ box v as Box<SomeTrait+'a> //~ ERROR cannot infer an appropriate lifetime
}
fn main() {
fn static_proc(x: &isize) -> Box<FnMut()->(isize) + 'static> {
// This is illegal, because the region bound on `proc` is 'static.
- Box::new(move|| { *x }) //~ ERROR does not fulfill the required lifetime
+ Box::new(move|| { *x }) //~ ERROR cannot infer an appropriate lifetime
}
fn main() { }
fn foo3<'a,'b>(x: &'a mut Dummy) -> &'b mut Dummy {
// Without knowing 'a:'b, we can't coerce
- x //~ ERROR lifetime bound not satisfied
- //~^ ERROR cannot infer
+ x //~ ERROR cannot infer an appropriate lifetime
+ //~^ ERROR cannot infer an appropriate lifetime
}
struct Wrapper<T>(T);
-> Box<Get<&'min i32>>
where 'max : 'min
{
- v //~ ERROR mismatched types
+ v //~ ERROR cannot infer an appropriate lifetime
}
fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
where 'max : 'min
{
// Previously OK:
- v //~ ERROR mismatched types
+ v //~ ERROR cannot infer an appropriate lifetime
}
fn main() { }
where 'max : 'min
{
// Previously OK, now an error as traits are invariant.
- v //~ ERROR mismatched types
+ v //~ ERROR cannot infer an appropriate lifetime
}
fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
-> Box<Get<&'max i32>>
where 'max : 'min
{
- v //~ ERROR mismatched types
+ v //~ ERROR cannot infer an appropriate lifetime
}
fn main() { }
-> Box<Get<&'min i32>>
where 'max : 'min
{
- v //~ ERROR mismatched types
+ v //~ ERROR cannot infer an appropriate lifetime
}
fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
-> Box<Get<&'max i32>>
where 'max : 'min
{
- v //~ ERROR mismatched types
+ v //~ ERROR cannot infer an appropriate lifetime
}
fn main() { }
--- /dev/null
+// Copyright 2017 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.
+
+// pretty-expanded FIXME #23616
+
+use std::rc::Rc;
+
+fn lub_short<'a, T>(_: &[&'a T], _: &[&'a T]) {}
+
+// The two arguments are a subtype of their LUB, after coercion.
+fn long_and_short<'a, T>(xs: &[&'static T; 1], ys: &[&'a T; 1]) {
+ lub_short(xs, ys);
+}
+
+// The argument coerces to a subtype of the return type.
+fn long_to_short<'a, 'b, T>(xs: &'b [&'static T; 1]) -> &'b [&'a T] {
+ xs
+}
+
+// Rc<T> is covariant over T just like &T.
+fn long_to_short_rc<'a, T>(xs: Rc<[&'static T; 1]>) -> Rc<[&'a T]> {
+ xs
+}
+
+// LUB-coercion (if-else/match/array) coerces `xs: &'b [&'static T: N]`
+// to a subtype of the LUB of `xs` and `ys` (i.e. `&'b [&'a T]`),
+// regardless of the order they appear (in if-else/match/array).
+fn long_and_short_lub1<'a, 'b, T>(xs: &'b [&'static T; 1], ys: &'b [&'a T]) {
+ let _order1 = [xs, ys];
+ let _order2 = [ys, xs];
+}
+
+// LUB-coercion should also have the exact same effect when `&'b [&'a T; N]`
+// needs to be coerced, i.e. the resulting type is not &'b [&'static T], but
+// rather the `&'b [&'a T]` LUB.
+fn long_and_short_lub2<'a, 'b, T>(xs: &'b [&'static T], ys: &'b [&'a T; 1]) {
+ let _order1 = [xs, ys];
+ let _order2 = [ys, xs];
+}
+
+fn main() {}