-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
'static closures/FnDefs/futures with non-'static return type are unsound #84366
Comments
This also works with functions fn make_static_displayable<'a>(s: &'a str) -> Box<dyn fmt::Display> {
//let f = || -> &'a str { "" };
fn f<'a>() -> &'a str { "" }
// problem is: the type of `f::<'a>` is 'static
static_transfers_to_associated(&f::<'a>, s)
} but only since Rust
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> <source>:24:36
|
24 | static_transfers_to_associated(&f::<'a>, s)
| ^^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 20:1...
--> <source>:20:1
|
20 | / fn make_static_displayable<'a>(s: &'a str) -> Box<fmt::Display> {
21 | | //let f = || -> &'a str { "" };
22 | | fn f<'a>() -> &'a str { "" }
23 | | // problem is: the type of `f::<'a>` is 'static
24 | | static_transfers_to_associated(&f::<'a>, s)
25 | | }
| |_^
note: ...so that reference does not outlive borrowed content
--> <source>:24:46
|
24 | static_transfers_to_associated(&f::<'a>, s)
| ^
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type `fn() -> &str {make_static_displayable::f::<'a>}` will meet its required lifetime bounds
--> <source>:24:5
|
24 | static_transfers_to_associated(&f::<'a>, s)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error(s)
Compiler returned: 101 |
The version with functions regressed (started compiling without error) at
This includes
Looking at those, almost certainly #42417 is the relevant PR. |
Assigning priority as discussed as part of the Prioritization Working Group procedure and removing @rustbot label -I-prioritize +P-high |
Finally figured out how to make a generic lifetime extension function out of this. Also not requiring use std::marker::PhantomData;
trait FancyTrait<'b, T: ?Sized> {
type Associated;
fn convert(self, x: Self::Associated, proof: PhantomData<&'b Self::Associated>) -> &'b T;
}
impl<'a, 'b, T: ?Sized + 'a, F> FancyTrait<'b, T> for F
where
F: Fn() -> &'a str,
{
type Associated = &'a T;
fn convert(self, x: &'a T, _: PhantomData<&'b &'a T>) -> &'b T {
x
}
}
fn extend_lifetime<'a, 'b, T: ?Sized>(x: &'a T) -> &'b T {
// closure has inferred return type `&'a str`
static_transfers_to_associated(|| "", x)
}
fn static_transfers_to_associated<'a, 'b, F, T: ?Sized>(f: F, x: F::Associated) -> &'b T
where
F: FancyTrait<'b, T> + 'b,
{
// `F: 'b` implies `F::Assocaited: 'b`
f.convert(x, PhantomData) // callable since `&'b F::Associated` is a valid type
}
fn main() {
let r;
{
let x = String::from("Hello World?");
r = extend_lifetime(&x);
}
println!("{}", r);
} |
For the record, fn foo<'a, F: Future<Output = &'a str> + 'static>(f: F) {}
fn bar<'a>() {
let fut = async { "" };
foo::<'a>(fut);
} @rustbot label A-async-await |
OK, I'm thinking about this issue. So, in a top-level function, it is considered "ok" for a lifetime to appear in the return type that does not also appear in the arguments, but that is only because it is forced to be early bound and hence it is part of the generics of the fn foo<'a>() -> &'a str { "" }
// 'desugars' to the rough equivalent of `struct foo<'a>; impl<'a> Fn<()> for foo<'a> { .. }` For closures, the return type (as #84385 points out) has not been considered part of the "outlives" relation, which means that it is effectively not part of the "self type" of the closure. However, that means that you wind up with an impl like struct ClosureType;
impl<'a> Fn<()> for ClosureType {
type Output = &'a str;
} This impl would not normally be permitted and it violates RFC 1214, leading to this unsoundness. The fix in #84385 is effectively to make the return type part of the self type: struct ClosureType<R>;
impl<'a> Fn<()> for ClosureType<&'a str> {
type Output = &'a str;
} At first I was unsure if this was the fix I wanted, but now I think it's exactly right, as it preserves a fairly analogous relationship between the |
I believe the problem with async generators is the same, but for yield types. That fix should be included in #84385 as well. |
that “desugaring” however breaks down with the fact that
|
@steffahn to be honest, I had forgotten about that, but I do remember now =) similar flaw. I want to think over the best fix a bit more in any case. Another option would be to impose smarter limits at the point where we are inferring the return types for closures. |
Visiting for P-high review. This is very much a T-types matter. Officially assigning to @Aaron1011 based on their ongoing efforts in PR #84385. |
…unsound-issues, r=jackh726 Add `known-bug` tests for 11 unsound issues r? `@jackh726` Should tests for other issues be in separate PRs? Thanks. Edit: Partially addresses rust-lang#105107. This PR adds `known-bug` tests for 11 unsound issues: - rust-lang#25860 - rust-lang#49206 - rust-lang#57893 - rust-lang#84366 - rust-lang#84533 - rust-lang#84591 - rust-lang#85099 - rust-lang#98117 - rust-lang#100041 - rust-lang#100051 - rust-lang#104005
…unsound-issues, r=jackh726 Add `known-bug` tests for 11 unsound issues r? ``@jackh726`` Should tests for other issues be in separate PRs? Thanks. Edit: Partially addresses rust-lang#105107. This PR adds `known-bug` tests for 11 unsound issues: - rust-lang#25860 - rust-lang#49206 - rust-lang#57893 - rust-lang#84366 - rust-lang#84533 - rust-lang#84591 - rust-lang#85099 - rust-lang#98117 - rust-lang#100041 - rust-lang#100051 - rust-lang#104005
…unsound-issues, r=jackh726 Add `known-bug` tests for 11 unsound issues r? `@jackh726` Should tests for other issues be in separate PRs? Thanks. Edit: Partially addresses rust-lang#105107. This PR adds `known-bug` tests for 11 unsound issues: - rust-lang#25860 - rust-lang#49206 - rust-lang#57893 - rust-lang#84366 - rust-lang#84533 - rust-lang#84591 - rust-lang#85099 - rust-lang#98117 - rust-lang#100041 - rust-lang#100051 - rust-lang#104005
…unsound-issues, r=jackh726 Add `known-bug` tests for 11 unsound issues r? ``@jackh726`` Should tests for other issues be in separate PRs? Thanks. Edit: Partially addresses rust-lang#105107. This PR adds `known-bug` tests for 11 unsound issues: - rust-lang#25860 - rust-lang#49206 - rust-lang#57893 - rust-lang#84366 - rust-lang#84533 - rust-lang#84591 - rust-lang#85099 - rust-lang#98117 - rust-lang#100041 - rust-lang#100051 - rust-lang#104005
…unsound-issues, r=jackh726 Add `known-bug` tests for 11 unsound issues r? `@jackh726` Should tests for other issues be in separate PRs? Thanks. Edit: Partially addresses rust-lang#105107. This PR adds `known-bug` tests for 11 unsound issues: - rust-lang#25860 - rust-lang#49206 - rust-lang#57893 - rust-lang#84366 - rust-lang#84533 - rust-lang#84591 - rust-lang#85099 - rust-lang#98117 - rust-lang#100041 - rust-lang#100051 - rust-lang#104005
…unsound-issues, r=jackh726 Add `known-bug` tests for 11 unsound issues r? ``@jackh726`` Should tests for other issues be in separate PRs? Thanks. Edit: Partially addresses rust-lang#105107. This PR adds `known-bug` tests for 11 unsound issues: - rust-lang#25860 - rust-lang#49206 - rust-lang#57893 - rust-lang#84366 - rust-lang#84533 - rust-lang#84591 - rust-lang#85099 - rust-lang#98117 - rust-lang#100041 - rust-lang#100051 - rust-lang#104005
Protect against rust-lang/rust#84366
Protect against rust-lang/rust#84366
Argument-free closures can return non-
'static
types but be'static
themselves:However, associated types of
'static
types must be'static
, too. So the fact that the above compiles results in unsoundness, as demonstrated below:(playground)
@rustbot modify labels: T-compiler, T-lang, A-closures, A-lifetimes, A-traits, A-typesystem, A-associated-items
and someone please add “I-unsound 💥”.
Found this bug while experimenting with variations of #84305.
Without the
dyn
keyword, this seems to compile “successfully” since Rust1.4.0
. Godbolt link.The text was updated successfully, but these errors were encountered: