Soundness regression with for<'lt>
closure having an implied bound from return type #114936
Closed
Description
Bug originally found by @ast-ral, over Discord, which I've then reduced.
Code
I tried this code:
fn whoops(
s: String,
f: impl for<'s> FnOnce(&'s str) -> (&'static str, [&'static &'s (); 0]),
) -> &'static str
{
f(&s).0
}
I expected to see this happen:
error[E0597]: `s` does not live long enough
--> <source>:6:7
|
6 | f(&s).0
| --^^-
| | |
| | borrowed value does not live long enough
| argument requires that `s` is borrowed for `'static`
7 | }
| - `s` dropped here while still borrowed
error: aborting due to previous error
For more information about this error, try `rustc --explain E0597`.
Instead, this happened: code compiles successfully
Version it soundly rejected this code:
Version with soundness regression
1.65.0 and onwards
Proof of unsoundness:
fn static_str_identity()
-> impl for<'s> FnOnce(&'s str) -> (
[&'static &'s (); 0],
&'static str,
)
{
|s: &/* 's */ str| ( // <----------------+ inputs restricted to `'s`.
[], // `: [&'static &'s (); 0]`, |
// thus `'s : 'static` ->------+
// +-<----------------+
// |
// v
s, // `: &'s str <: &'static str`
)
}
fn main()
{
let f = static_str_identity();
let local = String::from("...");
let s: &'static str = f(&local).1; // <- should be rejected!
drop(local);
let _unrelated = String::from("UB!");
dbg!(s); // <- compiles and prints `"UB!"`
}
@rustbot modify labels: +I-unsound +regression-from-stable-to-stable -regression-untriaged
Observations
-
This does not occur if the implied-lifetime-bounds array is in closure parameter position; so it looks like a bug w.r.t. not properly checking the closure output type implied bounds?
-
-Ztrait-solver=next
does not help (as of2023-08-16
)
Activity