-
Notifications
You must be signed in to change notification settings - Fork 13k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
impl Trait + 'static
is not 'static
if returned from a generic function
#76882
Comments
You need to add a trait Trait {}
impl Trait for () {}
fn get_trait<I: 'static>() -> impl Trait + 'static {
()
}
fn assert_static<A: 'static>(_: A) {}
fn test<T: 'static>(_: T) {
assert_static(get_trait::<T>());
} The core reason for this behaviour is the variance behaviour of impl Trait in return position: the returned impl Trait is always variant over all generic input parameters, even if not technically used. This is done so that if you change the internal implementation of a public API returning |
That makes some sense, but in my opinion, this should be only 'behaviour by default'. If the lifetime is explicitly set ( Also, note that with fn erase<I: Trait>(x: I) -> impl Trait + 'static {
x
}
|
Note that this behaviour is also inconsistent with lifetimes which are not captured by default: trait Trait {}
impl Trait for &() {}
fn get_trait<I>(a: &()) -> impl Trait {
a
}
|
It seems that the current behaviour of capturing lifetimes from generic arguments as lifetimes in the Here's an example of some very strange behaviour caused by this sort of capture: #![feature(type_alias_impl_trait)]
#![feature(unsize)]
use core::marker::Unsize;
use core::fmt::Debug;
pub fn returns_unrelated_impl<T>() -> impl Debug + 'static { () }
// doesn't compile: the compiler thinks the `impl Debug` should capture `'a`
pub fn test_1<'a>() -> impl Debug {
returns_unrelated_impl::<&'a ()>()
}
// doesn't compile: the compiler thinks `ImplUnsizeStatic` should capture `'a`
pub fn test_2a<'a>() -> impl Debug {
type ImplUnsizeStatic = impl Unsize<dyn Debug> + 'static;
let rv1: ImplUnsizeStatic = returns_unrelated_impl::<&'a ()>();
let rv2: Box<dyn Debug> = Box::new(rv1);
rv2
}
// does compile, because we aren't assigning an `impl` to another `impl`
pub fn test_2b<'a>() -> impl Debug {
fn verify_impl_unsize_static<T: Unsize<dyn Debug> + 'static>(x: &T) {}
let rv1 = returns_unrelated_impl::<&'a ()>();
verify_impl_unsize_static(&rv1);
let rv2: Box<dyn Debug> = Box::new(rv1);
rv2
} The check that the return value of This makes me concerned that if "an |
Another example, when that behavior is inappropriate #![feature(return_position_impl_trait_in_trait)]
trait Foo: 'static { }
trait Trait {
fn foo(&mut self) -> impl Foo + 'static;
fn bar(&mut self, foo: impl Foo + 'static) {
std::hint::black_box((self, foo));
}
}
struct FooImpl;
impl Foo for FooImpl { }
struct TraitImpl;
impl Trait for TraitImpl {
fn foo(&mut self) -> impl Foo + 'static {
FooImpl
}
}
fn main() {
let mut t = TraitImpl;
let foo = t.foo();
t.bar(foo);
} (here Here default behavior stands in the way of me creating an API, that would be possible without rpitit - you could change return type of |
impl Trait + 'static
is not 'static
if returned from a generic function
Fixed by #95474. |
nice |
I tried this code:
(playground)
I expected that
rustc
will compile this code. But it doesn't. Instead, I've got this error:The error seems weird because the return type of
get_trait
is explicitly marked as'static
andT
/I
is not used anywhere at all.This may be related to #49431 though I'm not entirely sure.
Meta
Checked on
1.46.0
stable and1.48.0-nightly
(2020-09-17 f3c923a)The text was updated successfully, but these errors were encountered: