mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-27 09:14:20 +00:00
add fut/back compat tests for implied trait bounds
This commit is contained in:
parent
926e7843ea
commit
c965d0eaf2
@ -0,0 +1,51 @@
|
||||
// A test exploiting the bug behind #25860 except with
|
||||
// implied trait bounds which currently don't exist,
|
||||
//
|
||||
// please ping @lcnr if your changes end up causing `badboi` to compile.
|
||||
use std::marker::PhantomData;
|
||||
struct Foo<'a, 'b, T>(PhantomData<(&'a (), &'b (), T)>)
|
||||
where
|
||||
T: Convert<'a, 'b>;
|
||||
|
||||
trait Convert<'a, 'b>: Sized {
|
||||
fn cast(&'a self) -> &'b Self;
|
||||
}
|
||||
impl<'long: 'short, 'short, T> Convert<'long, 'short> for T {
|
||||
fn cast(&'long self) -> &'short T {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
// This function will compile once we add implied trait bounds.
|
||||
//
|
||||
// If we're not careful with our impl, the transformations
|
||||
// in `bad` would succeed, which is unsound ✨
|
||||
//
|
||||
// FIXME: the error is pretty bad, this should say
|
||||
//
|
||||
// `T: Convert<'in_, 'out>` is not implemented
|
||||
//
|
||||
// help: needed by `Foo<'in_, 'out, T>`
|
||||
fn badboi<'in_, 'out, T>(x: Foo<'in_, 'out, T>, sadness: &'in_ T) -> &'out T {
|
||||
//~^ ERROR lifetime mismatch
|
||||
sadness.cast()
|
||||
}
|
||||
|
||||
fn bad<'short, T>(value: &'short T) -> &'static T {
|
||||
let x: for<'in_, 'out> fn(Foo<'in_, 'out, T>, &'in_ T) -> &'out T = badboi;
|
||||
let x: for<'out> fn(Foo<'short, 'out, T>, &'short T) -> &'out T = x;
|
||||
let x: for<'out> fn(Foo<'static, 'out, T>, &'short T) -> &'out T = x;
|
||||
let x: fn(Foo<'static, 'static, T>, &'short T) -> &'static T = x;
|
||||
x(Foo(PhantomData), value)
|
||||
}
|
||||
|
||||
// Use `bad` to cause a segfault.
|
||||
fn main() {
|
||||
let mut outer: Option<&'static u32> = Some(&3);
|
||||
let static_ref: &'static &'static u32 = match outer {
|
||||
Some(ref reference) => bad(reference),
|
||||
None => unreachable!(),
|
||||
};
|
||||
outer = None;
|
||||
println!("{}", static_ref);
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
error[E0623]: lifetime mismatch
|
||||
--> $DIR/hrlt-implied-trait-bounds-guard.rs:29:29
|
||||
|
|
||||
LL | fn badboi<'in_, 'out, T>(x: Foo<'in_, 'out, T>, sadness: &'in_ T) -> &'out T {
|
||||
| ^^^^^^^^^^^^^^^^^^ -------
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
| ...but data from `x` is returned here
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0623`.
|
@ -0,0 +1,35 @@
|
||||
// check-pass
|
||||
struct Foo<'a>(&'a ())
|
||||
where
|
||||
(): Trait<'a>;
|
||||
|
||||
trait Trait<'a> {
|
||||
fn id<T>(value: &'a T) -> &'static T;
|
||||
}
|
||||
|
||||
impl Trait<'static> for () {
|
||||
fn id<T>(value: &'static T) -> &'static T {
|
||||
value
|
||||
}
|
||||
}
|
||||
|
||||
fn could_use_implied_bounds<'a, T>(_: Foo<'a>, x: &'a T) -> &'static T
|
||||
where
|
||||
(): Trait<'a>, // This could be an implied bound
|
||||
{
|
||||
<()>::id(x)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let bar: for<'a, 'b> fn(Foo<'a>, &'b ()) = |_, _| {};
|
||||
|
||||
// If `could_use_implied_bounds` were to use implied bounds,
|
||||
// keeping 'a late-bound, then we could assign that function
|
||||
// to this variable.
|
||||
let bar: for<'a> fn(Foo<'a>, &'a ()) = bar;
|
||||
|
||||
// In this case, the subtyping relation here would be unsound,
|
||||
// allowing us to transmute lifetimes. This currently compiles
|
||||
// because we incorrectly deal with implied bounds inside of binders.
|
||||
let _bar: for<'a, 'b> fn(Foo<'a>, &'b ()) = bar;
|
||||
}
|
Loading…
Reference in New Issue
Block a user