-
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
Trait with HRTB blanket impl is implemented when it shouldn't be #54302
Comments
Tagging P-high because this very much affects Serde. @rust-lang/compiler trait Deserialize<'de> {
fn from_str(s: &'de str) -> Self;
}
trait DeserializeOwned: for<'de> Deserialize<'de> {}
impl<T> DeserializeOwned for T where T: for<'de> Deserialize<'de> {}
impl<'de: 'a, 'a> Deserialize<'de> for &'a str {
fn from_str(s: &'de str) -> Self {
s
}
}
fn main() {
println!("{}", use_after_free::<&'static str>());
}
fn use_after_free<T: DeserializeOwned>() -> T {
let s = "oh my".to_owned();
T::from_str(&s)
} |
Same issue using Serde traits: extern crate serde;
extern crate serde_json;
fn use_after_free<T: serde::de::DeserializeOwned>() -> T {
let json = r#" "oh my" "#.to_owned();
serde_json::from_str(&json).unwrap()
}
fn main() {
println!("{}", use_after_free::<&'static str>());
} (One possible) output: ¢ÚU� |
Even better, enabling NLL causes an ICE:
|
Perhaps we can bisect this regression? (e.g., with https://github.com/rust-lang-nursery/cargo-bisect-rustc) |
Bisected to correct behavior in nightly-2017-07-07 -- rustc 1.20.0-nightly (696412d 2017-07-06), incorrect behavior in nightly-2017-07-08 -- rustc 1.20.0-nightly (9b85e1c 2017-07-07). That range is 696412d...9b85e1c. Looks like #42840. |
visited for triage. Assigning to @nikomatsakis |
@dtolnay thanks, very helpful! |
I think the bug is here: rust/src/librustc/traits/fulfill.rs Lines 296 to 304 in f7f4c50
In particular, I think the But I'm wondering if the whole concept is flawed. I'm a bit fearful of |
I have a fix. |
Of course, any approach that relies on any lifetimes in the affected trait-ref is fatally flawed - here's an example where the trait ref is the region-free trait Foo {
fn foo(self) -> &'static u32;
}
impl<'a> Foo for &'a u32 where 'a: 'static {
fn foo(self) -> &'static u32 { self }
}
trait RefFoo {
fn ref_foo(&self) -> &'static u32;
}
impl<T> RefFoo for T where for<'a> &'a T: Foo {
fn ref_foo(&self) -> &'static u32 {
self.foo()
}
}
fn coerce_lifetime(a: &u32) -> &'static u32
{
<u32 as RefFoo>::ref_foo(a)
}
fn main() {
} |
@arielb1 I'm not really sure what your example is meant to illustrate. That said, running that on my branch gives an error:
This seems like the error I would expect, more or less. We try to use the impl to prove that |
BTW, the |
visited for triage. bug seems to be being dealt with, assuming that PR #54401 is eventually deemed as passing muster... |
Yes, I think that the "no late-bound regions" check was basically a workaround for this same problem; I removed it in the PR since I think it has a "more correct" fix. |
…tsakis handle outlives predicates in trait evaluation This handles higher-ranked outlives predicates in trait evaluation the same way they are handled in projection. Fixes rust-lang#54302. I think this is a more correct fix than rust-lang#54401 because it fixes the root case in evaluation instead of making evaluation used in less cases. However, we might want to go to a direction closer to @nikomatsakis's solution with Chalk. r? @nikomatsakis
handle outlives predicates in trait evaluation This handles higher-ranked outlives predicates in trait evaluation the same way they are handled in projection. Fixes #54302. I think this is a more correct fix than #54401 because it fixes the root case in evaluation instead of making evaluation used in less cases. However, we might want to go to a direction closer to @nikomatsakis's solution with Chalk. r? @nikomatsakis
This is a regression between rustc 1.20.0 and 1.21.0.
1.20 correctly rejects this code with the following error.
The text was updated successfully, but these errors were encountered: