-
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
Methods in impls allowed more restrictive lifetime bounds than in the trait. #18937
Comments
tl;dr: this bug still reproduces but no longer causes an ICE Hopefully I updated @eddyb's code properly. This compiles and executes fine. #![feature(core, hash)]
use std::hash::{hash, SipHasher};
trait Foo {
fn foo<T>(self) -> u64;
}
impl Foo for () {
fn foo<T: 'static>(self) -> u64 {
// ^^^^^^^ this should cause an error, the bound is missing from the
// method definition in the trait, and calls are checked against that.
hash::<_, SipHasher>(unsafe{ &std::intrinsics::type_id::<&'static T>() })
}
}
fn main() {
println!("{}", ().foo::<&()>());
}
|
@JustAPerson Thanks! Marking as |
triage: P-backcompat-lang (1.0) I'm removing the E-needstest label because there is still a bug here -- actually ICEing is better than accepting an illegal program. That said, this may be a dup of #22779 -- although I suspect it is somewhat different. I'm going to triage it as 1.0 and try to fix it. |
Still broken after the fix of #22779 (http://is.gd/rZ0MgK) |
So I know what the problem is here, but fixing it is a bit annoying due to the way our contexts are structured (we're not processing the fulfillment context's "region obligations" list). I've been wanting to do some restructuring here that would help, I'll look into that. (The very existence of the "region obligations" list is actually a demonstration of the problem.) |
cc me |
Ran into an example that creates unsoundness and doesn't use unsafe. I think it's ultimately the same issue: https://play.rust-lang.org/?gist=25b7461083e5ee9b3415&version=nightly |
Is it planned to be fixed in stable? PS just another example with use after free in safe code from dup issue: |
@nikomatsakis said he will look at this when he comes back from vacation. |
@rust-lang/compiler Can you reaffirm this is P-high and somebody is on it? Maybe this can be mentored? |
@sanxiyn Says they may be able to do this with some mentoring! |
I've just closed #35730 as a dupe of this which has another example of a segfault related to this we believe. Renominating as this came up again, unfortunately... |
triage: P-high |
OK, so @jroesch and I implemented an initial fix for this (finally). I did a crater run with the following results:
https://gist.github.com/nikomatsakis/cba00297c8659f71740b8e45dad07137 That's not too bad. I want to dig into those results some more, but I'm hoping we can get away w/o a warning period on this one -- it would be a real pain to support! |
(It may also be worth investing a bit of energy in the error messages, which do not currently hint at the fact that the impl is imposing more requirements than the trait.) |
This appears to be broken by the fix: pub trait Leak<T : ?Sized> {
fn leak<'a>(self) -> &'a T where T: 'a;
}
impl<T> Leak<[T]> for Vec<T> {
fn leak<'a>(mut self) -> &'a [T] where [T]: 'a {
let r: *mut [T] = &mut self[..];
std::mem::forget(self);
unsafe { &mut *r }
}
}
fn main() {
println!("Hello, world!");
} error[E0309]: the parameter type `T` may not live long enough
--> src/lib.rs:45:5
|
45 | fn leak<'a>(mut self) -> &'a [T] where [T]: 'a {
| ^
|
= help: consider adding an explicit lifetime bound `T: 'a`...
note: ...so that the type `[T]` will meet its required lifetime bounds
--> src/lib.rs:45:5
|
45 | fn leak<'a>(mut self) -> &'a [T] where [T]: 'a {
| ^ |
@arielb1 I feel that is an orthogonal issue. It is true that this code no longer compiles, and that it would be nice and safe if it did compile, but it is not true that it should compile with the current state of rustc's reasoning. That is, I think we should indeed deduce that if Now, one could argue -- and I might agree -- that we should try to fix that oversight at the same time as applying this path. I think it'd be fairly straightforward to do, really, though it probably wants an RFC. I think @alexcrichton ran into this limitation in futures in some other setting. |
@nikomatsakis do you think you two are still making fwd progress here, or should we delegate? |
Got distracted but I now have a local branch that I think both rejects the original case but accepts this case. I have to press on a bit more. The key change though is to expand on things like |
Argh. This is frustrating. So I put in some work into the error messages, which now look like this: lunch-box. rustc --stage1 region-unrelated.rs
error[E0276]: impl has stricter requirements than trait
--> region-unrelated.rs:21:5
|
16 | fn foo() where T: 'a;
| --------------------- definition of `foo` from trait
...
21 | fn foo() where V: 'a { }
| ^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `V: 'a`
error: aborting due to previous error I am trying to turn these into future-compatibility lints, but the current infrastructure (e.g., |
Update: I now have the lints mostly working, though I'm still refactoring the changes I made to that end. |
Pr enqueud #37167 |
detect extra region requirements in impls The current "compare method" check fails to check for the "region obligations" that accrue in the fulfillment context. This branch switches that code to create a `FnCtxt` so that it can invoke the regionck code. Previous crater runs (I haven't done one with the latest tip) have found some small number of affected crates, so I went ahead and introduced a warning cycle. I will kick off a crater run with this branch shortly. This is a [breaking-change] because previously unsound code was accepted. The crater runs also revealed some cases where legitimate code was no longer type-checking, so the branch contains one additional (but orthogonal) change. It improves the elaborator so that we elaborate region requirements more thoroughly. In particular, if we know that `&'a T: 'b`, we now deduce that `T: 'b` and `'a: 'b`. I invested a certain amount of effort in getting a good error message. The error message looks like this: ``` error[E0276]: impl has stricter requirements than trait --> traits-elaborate-projection-region.rs:33:5 | 21 | fn foo() where T: 'a; | --------------------- definition of `foo` from trait ... 33 | fn foo() where U: 'a { } | ^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `U: 'a` | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #18937 <#18937> note: lint level defined here --> traits-elaborate-projection-region.rs:12:9 | 12 | #![deny(extra_requirement_in_impl)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ ``` Obviously the warning only prints if this is a _new_ error (that resulted from the bugfix). But all existing errors that fit this description are updated to follow the general template. In order to get the lint to preserve the span-labels and the error code, I separate out the core `Diagnostic` type (which encapsulates the error code, message, span, and children) from the `DiagnosticBuilder` (which layers on a `Handler` that can be used to report errors). I also extended `add_lint` with an alternative `add_lint_diagnostic` that takes in a full diagnostic (cc @jonathandturner for those changes). This doesn't feel ideal but feels like it's moving in the right direction =). r? @pnkfelix cc @arielb1 Fixes #18937
See rust-lang/rust#18937 and related issues for upstream discussion. Compiling the previous code on modern rust results in: error[E0276]: impl has stricter requirements than trait This is the most trivial way to fix this issue. A better fix might be possible. If the event loop were to migrate to tokio and be external to the library (as hyper does these days), that would allow expressing a more stringent lifetime on the handler. For now, getting it back to a compiling state seems like a good step.
cc @nikomatsakis
The text was updated successfully, but these errors were encountered: