Rust 1.84 sometimes allows overlapping impls in incremental re-builds #135514
Description
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
impl Trait for W {}
turning into
impl Trait for S<W> {}
which makes the Other
-impls overlapping. As an additional effect, the code turning the overlap into UB is also uncommented. (The const _ …
stuff only “fixes” the *
symbols left behind by the */*
in the middle.)
trait 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;
}
const _: u8 = 0
// /* // <- uncomment this line
*0;
impl Trait for W {}
pub fn transmute<L, R>(l: L) -> R {
todo!();
}
const _: u8 = 0
*/*
0;
impl Trait for S<W> {}
fn use_first_impl<T: Trait, L, R>(l: L) -> <<T as TyEq>::To as Other>::Choose<L, R> {
l
}
fn use_second_impl<T, L, R>(l: <S<T> as Other>::Choose<L, R>) -> R {
l
}
trait TyEq {
type To;
}
impl<T> TyEq for T {
type To = T;
}
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))
}
pub fn transmute<L, R>(l: L) -> R {
transmute_inner::<W, S<W>, L, R>(l)
}
const _: u8 =
// */
0;
fn main() {
let v = vec![65_u8, 66, 67];
let s: String = transmute(v);
println!("{}", s);
}
Reproduce
cargo new repro
cd repro
…write above to src/main…
cargo run
…uncomment the line in question as described…
cargo run
Compiling repro v0.1.0 (/home/frank/repro)
warning: struct `A` is never constructed
--> src/main.rs:14:8
|
14 | struct A;
| ^
|
= note: `#[warn(dead_code)]` on by default
warning: struct `B` is never constructed
--> src/main.rs:15:8
|
15 | struct B;
| ^
warning: `repro` (bin "repro") generated 2 warnings
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.12s
Running `target/debug/repro`
ABC
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