-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
NLL: unsound verification of higher ranked outlives bounds #98095
Comments
Here’s a way to exploit this behavior for unsoundness: use std::any::Any;
trait Lt<'a>: 'a {}
impl<'a, T: ?Sized + 'a> Lt<'a> for T {}
trait Tr {}
impl<T: ?Sized> Tr for T {}
fn test<T, R: Any>(x: T) -> R {
// works despite non-'static
step1::<T, R>(x)
}
// remark: starting in `test` with `step2` directly works, too.
fn step1<T, R: Any>(x: T) -> R
where
for<'a> T: 'a,
{
step2::<T, R>(x)
}
fn step2<T, R: Any>(x: T) -> R
where
for<'a> T: Lt<'a>,
{
step3::<T, R>(x)
}
fn step3<T, R: Any>(x: T) -> R
where
T: Lt<'static>,
{
step4::<T, R>(x)
}
fn step4<T, R: Any>(x: T) -> R
where
T: 'static,
{
*(Box::new(x) as Box<dyn Any>).downcast::<R>().unwrap()
}
fn main() {
let x = String::from("Hello World");
let r: &'static str = test(&x[..]);
drop(x);
println!("{r}");
}
@rustbot label I-unsound Interestingly, not only calling |
This comment was marked as resolved.
This comment was marked as resolved.
Yea |
This is confirmed to be directly because of NLL and not something else. I'm going to nominate for compiler team, since this is pretty significant. We'll continue to discuss within types team if there is a reasonable fix here, but I want this to be on people's radar since this might end up being a NLL stabilization revert in the short-term. |
This is used to be rejected by NLLs, and started being accepted in List of merged PRs for that nightly
Out of those, #73503 looks like the most likely candidate, cc PR author @lcnr and reviewer @nikomatsakis. |
WG-prioritization assigning priority (Zulip discussion). @rustbot label -I-prioritize +P-critical |
Discussed with @oli-obk and @lcnr -- we believe the problem is that the outlives code isn't handling placeholder regions correctly... they are in this fallthrough
but they should be handled more like parameters, except that (at least at present) we can only bound them by I might be able to make this fix today else could mentor someone potentially (ping me on Zulip). |
I have a somewhat clear understanding for why this happens. Specifically, consider the two cases:
On stable, both Why does
|
So @compiler-errors and I did a deep dive here. What we found is that:
|
Fix is in #98109, this includes the fix for both this bug and the bug that the fix revealed :) |
This code now passes under under NLL after #95565: (playground)
assert_static
should be able to infer thatT: 'static
because, in the language of Chalk, I believe the boundfor<'a> T: 'a
should be lowered toforall<'a> { Outlives(T: 'a) :- WellFormed(T). }
and because the well-formedness of T is assumed to be true, we can instantiate'a
to any lifetime including'static
.@rustbot label T-compiler T-types regression-from-stable-to-nightly C-bug
The text was updated successfully, but these errors were encountered: