Skip to content
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

auto trait candidate selection is unsound #84857

Closed
lcnr opened this issue May 3, 2021 · 11 comments
Closed

auto trait candidate selection is unsound #84857

lcnr opened this issue May 3, 2021 · 11 comments
Assignees
Labels
A-trait-system Area: Trait system A-type-system Area: Type system C-bug Category: This is a bug. E-medium Call for participation: Medium difficulty. Experience needed to fix: Intermediate. E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. I-unsound Issue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness P-high High priority T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-types Relevant to the types team, which will review and decide on the PR/issue.

Comments

@lcnr
Copy link
Contributor

lcnr commented May 3, 2021

struct Always<T, U>(T, U);
unsafe impl<T, U> Send for Always<T, U> {}
struct Foo<T, U>(Always<T, U>);

trait False {}
unsafe impl<U: False> Send for Foo<u32, U> {}

trait WithAssoc {
    type Output;
}
impl<T: Send> WithAssoc for T {
    type Output = Self;
}
impl WithAssoc for Foo<u32, ()> {
    type Output = Box<i32>;
}

fn generic<T, U>(v: Foo<T, U>, f: fn(<Foo<T, U> as WithAssoc>::Output) -> i32) {
    f(foo(v));
}

fn foo<T: Send>(x: T) -> <T as WithAssoc>::Output {
    x
}

fn main() {
    generic(Foo(Always(0, ())), |b| *b);
}

Segmentation fault (core dumped)


There are two impls of Send for Foo, the explicit impl<U: False> Send for Foo<u32, U> and the implicit one if all fields are Send. The implicit one always holds in this example.

Candidate selection only acknowledges the existence of the implicit impl if the explicit one is known to not apply even when ignoring where bounds.

For Foo<T, U>: Send candidate selection can't use impl<U: False> Send for Foo<u32, U>, because Foo<T, U> is more generic than Foo<u32, U>. So we use the implicit impl which always applies.

For Foo<u32, ()> the explicit impl does apply, ignoring where bounds. This impl gets rejected however, as (): False does not hold. As we don't consider the implicit impl in this case we therefore accept impl WithAssoc for Foo<u32, ()> during coherence.

We now have two arbitrary overlapping impls which is unsound.

@lcnr lcnr added A-type-system Area: Type system I-unsound Issue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness C-bug Category: This is a bug. labels May 3, 2021
@rustbot rustbot added the I-prioritize Issue: Indicates that prioritization has been requested for this issue. label May 3, 2021
@lcnr
Copy link
Contributor Author

lcnr commented May 3, 2021

modifying main to the following this unsoundness exists since version 1.0

fn main() {
    fn deref(b: Box<i32>) -> i32 {
        *b
    }
    generic(Foo(Always(0, ())), deref);
}

@steffahn
Copy link
Member

steffahn commented May 3, 2021

Using e.g. Unpin or UnwindSafe instead of Send allows you to remove the unsafe. (Of course it won’t work with Rust 1.0 anymore with those.)


@rustbot label A-traits, T-compiler

@rustbot rustbot added A-trait-system Area: Trait system T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels May 3, 2021
@jackh726
Copy link
Member

jackh726 commented May 3, 2021

I think there was some discussion previously in wg-traits that an implicit impl should never be considered if there is an explicit impl. And I think that makes sense and would fix this. It isn't fully backwards compatible though, but I'm unsure how often that would get run into in practice.

@apiraino
Copy link
Contributor

apiraino commented May 3, 2021

Assigning priority as discussed as part of the Prioritization Working Group procedure and removing I-prioritize.

@rustbot label -I-prioritize +P-high

@rustbot rustbot added P-high High priority and removed I-prioritize Issue: Indicates that prioritization has been requested for this issue. labels May 3, 2021
@lcnr
Copy link
Contributor Author

lcnr commented Jan 27, 2022

a more beautiful example ✨ https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=7dcd002a139a2c2d18b2651aeca8a7c0

@lcnr lcnr added E-easy Call for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue. E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. E-medium Call for participation: Medium difficulty. Experience needed to fix: Intermediate. and removed E-easy Call for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue. E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. E-medium Call for participation: Medium difficulty. Experience needed to fix: Intermediate. labels Jul 15, 2022
@oli-obk oli-obk added the T-types Relevant to the types team, which will review and decide on the PR/issue. label Oct 21, 2022
@pnkfelix
Copy link
Member

Visited for P-high review

Work seems to be ongoing in #93367, including a lint that fires today, so at least people are aware of the issue, I hope.

@pnkfelix
Copy link
Member

pnkfelix commented Mar 3, 2023

visiting for 2023 Q1 P-high review

@lcnr am I correct in thinking that resolving this is blocked on #107374 ?

@pnkfelix
Copy link
Member

pnkfelix commented Mar 3, 2023

also, assigning this to @lcnr based on an assumption that #107374 will resolve this

@lcnr lcnr added E-hard Call for participation: Hard difficulty. Experience needed to fix: A lot. E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. labels Mar 6, 2023
@lcnr
Copy link
Contributor Author

lcnr commented Mar 6, 2023

The current status here is that there's a lint (#93367) which warns on impls which will change behavior due to the fix. Actually landing the fix breaks some crates and keeping the behavior of imagequant would require the stabilization of marker_trait_attrs (which is blocked on the new trait solver). See #85048 (comment)

I just saw that @kornelski actually rewrote imagequant to silence the lint in ImageOptim/libimagequant@d69cbfd in a way which does not rely on marker_traits 🤔 ❤️

So maybe we don't actually have to land the new solver for this.

Going to mentor someone to:

Please open a thread in #t-types on zulip if you get stuck

@lcnr lcnr added E-medium Call for participation: Medium difficulty. Experience needed to fix: Intermediate. and removed E-hard Call for participation: Hard difficulty. Experience needed to fix: A lot. labels Mar 6, 2023
@Ddystopia
Copy link
Contributor

Hello, can I give it a try?

@lcnr
Copy link
Contributor Author

lcnr commented Jul 28, 2023

fixed by #113312

@lcnr lcnr closed this as completed Jul 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-trait-system Area: Trait system A-type-system Area: Type system C-bug Category: This is a bug. E-medium Call for participation: Medium difficulty. Experience needed to fix: Intermediate. E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. I-unsound Issue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness P-high High priority T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-types Relevant to the types team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants