-
Notifications
You must be signed in to change notification settings - Fork 13.1k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # 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: