-
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
Rust 1.84 sometimes allows overlapping impls in incremental re-builds #135514
Comments
For context, I ran into this accidentally. (Without prior knowledge of #133828.) Granted I was trying to explore the behavior of overlap checks; my first reaction this was “wait, why does this compile despite the overlap?” Only a while later (after making a bunch of changes, e.g. crafting the whole exploitation into I.e: when they don’t ICE, incr-comp issues can be very confusing to the user, especially if they result in illegal code being accepted rather than legal code erroring. My main concern wouldn’t be the “tricky safe code could be unsound” aspect of the issue as much as the “normal users might accidentally create overlapping trait impls and be really confused when it creates compilation errors potentially only much much later”, [assuming that such an overlap can realistically happen for normal users accidentally, that aren’t deliberately exploring the behavior of overlap checks]. |
Yep, let's backport it at least to 1.85. |
The fix should already be on track for 1.85 naturally (and beta doesn’t reproduce, confirming the milestones labelling). |
oh, lemme un-beta-nominate it then |
Also would be cool if this test was written with cfg's rather than commenting. Then we could probably add it to the suite. |
Yes, that'd definitely be cleaner. TBH, I simply didn't know before that |
Here's a main.rstrait Trait {}
struct S0<T>(T);
struct S<T>(T);
impl<T> Trait for S<T> where S0<T>: Trait {}
struct W;
trait Other {
type Choose<L, R>;
}
struct A;
struct B;
// first impl
impl<T: Trait> Other for T {
type Choose<L, R> = L;
}
// second impl
impl<T> Other for S<T> {
type Choose<L, R> = R;
}
#[cfg(before)]
impl Trait for W {}
#[cfg(before)]
pub fn transmute<L, R>(l: L) -> R {
todo!();
}
#[cfg(after)]
impl Trait for S<W> {}
#[cfg(after)]
fn use_first_impl<T: Trait, L, R>(l: L) -> <<T as TyEq>::To as Other>::Choose<L, R> {
l
}
#[cfg(after)]
fn use_second_impl<T, L, R>(l: <S<T> as Other>::Choose<L, R>) -> R {
l
}
#[cfg(after)]
trait TyEq {
type To;
}
#[cfg(after)]
impl<T> TyEq for T {
type To = T;
}
#[cfg(after)]
fn transmute_inner<W, T, L, R>(l: L) -> R
where
T: Trait + TyEq<To = S<W>>,
{
use_second_impl::<W, L, R>(use_first_impl::<T, L, R>(l))
}
#[cfg(after)]
pub fn transmute<L, R>(l: L) -> R {
transmute_inner::<W, S<W>, L, R>(l)
}
fn main() {
let v = vec![65_u8, 66, 67];
let s: String = transmute(v);
println!("{}", s);
} $ RUSTFLAGS="--cfg before" cargo run
// cargo output
thread 'main' panicked at main.rs:34:5:
not yet implemented
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
$ RUSTFLAGS="--cfg after" cargo run
// cargo output
ABC or, without cargo (edition doesn't appear to matter, as long as it's consistent) $ rustc -Cincremental=incremental --cfg before main.rs && ./main
// rustc output
thread 'main' panicked at main.rs:34:5:
not yet implemented
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
$ rustc -Cincremental=incremental --cfg after main.rs && ./main
// rustc output
ABC (all on 1.84.0 stable) I couldn't get a version using |
Incremental tests require special cfgs to model fail/pass etc as well. I had already done this locally so I've opened PR #135522 for it. (I didn't end up including the actual safe transmute exploit into the test, just that the overlapping impl is rejected) |
add incremental test for issue 135514 r? `@compiler-errors` as requested in rust-lang#135514 (comment) This adds parts of `@steffahn's` repro as an incremental test for rust-lang#135514. I had initially added the actual exploitation of the issue into the safe transmute, but removed it because it's not exactly needed for such a test. I can add it back if you'd like. I've verified that the test fails with rust-lang#133828 reverted.
Rollup merge of rust-lang#135522 - lqd:issue-135514, r=compiler-errors add incremental test for issue 135514 r? `@compiler-errors` as requested in rust-lang#135514 (comment) This adds parts of `@steffahn's` repro as an incremental test for rust-lang#135514. I had initially added the actual exploitation of the issue into the safe transmute, but removed it because it's not exactly needed for such a test. I can add it back if you'd like. I've verified that the test fails with rust-lang#133828 reverted.
This repro uses a bit of lexical comments trickery, but only for convenience. (Quite useful while manually testing multiple rust versions), so the whole change you need to do between incremental compilations is turning
// /* // <- uncomment this line
into
/* // <- uncomment this line
The main relevant change that this entails is
turning into
which makes the
Other
-impls overlapping. As an additional effect, the code turning the overlap into UB is also uncommented. (Theconst _ …
stuff only “fixes” the*
symbols left behind by the*/*
in the middle.)Reproduce
Is safe code that compiles to UB, but only in incremental re-builds (compilation error otherwise), considered a soundness issue to be labelled
I-unsound
?This was already fixed with #133828 (which also explains what was the underlying issue). That PR seems like a fairly small & straightforward fix to me… should it perhaps be considered for backporting to stable? cc @compiler-errors
@rustbot label regression-from-stable-to-stable, T-compiler, A-incr-comp, A-coherence
The text was updated successfully, but these errors were encountered: