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

Inconsistent behavior of auto_traits+negative_impls across crates. #108995

Open
booti386 opened this issue Mar 10, 2023 · 3 comments
Open

Inconsistent behavior of auto_traits+negative_impls across crates. #108995

booti386 opened this issue Mar 10, 2023 · 3 comments
Labels
A-auto-traits Area: auto traits (e.g., `auto trait Send {}`) A-trait-system Area: Trait system C-bug Category: This is a bug. F-auto_traits `#![feature(auto_traits)]` F-negative_impls #![feature(negative_impls)] T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@booti386
Copy link

I tried this code:

// Crate a

#![feature(auto_traits)]
#![feature(negative_impls)]

pub auto trait NotVoid {}
impl !NotVoid for () {}

pub trait A<I, O> {}

impl<T, I: NotVoid> A<I, ()> for T {}
impl<T, O: NotVoid> A<(), O> for T {} // OK

use b::ExternNotVoid;

pub trait B<I, O> {}

impl<T, I: ExternNotVoid> B<I, ()> for T {}
impl<T, O: ExternNotVoid> B<(), O> for T {} // Error
// Crate b

#![feature(auto_traits)]
#![feature(negative_impls)]

pub auto trait ExternNotVoid {}
impl !ExternNotVoid for () {}

I expected to see this happen:
Identical behavior when NotVoid is declared in an external crate.

Instead, this happened:

error[E0119]: conflicting implementations of trait `B<(), ()>`
  --> a.rs:19:1
   |
18 | impl<T, I: ExternNotVoid> B<I, ()> for T {} // Error
   | ---------------------------------------- first implementation here
19 | impl<T, O: ExternNotVoid> B<(), O> for T {} // Error
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation

error: aborting due to previous error

For more information about this error, try `rustc --explain E0119`.

An error is produced when NotVoid is declared in an external crate (ExternNotVoid).

Meta

rustc --version --verbose:

rustc 1.70.0-nightly (e3dfeeaa4 2023-03-07)
binary: rustc
commit-hash: e3dfeeaa45f117281b19773d67f3f253de65cee1
commit-date: 2023-03-07
host: x86_64-unknown-linux-gnu
release: 1.70.0-nightly
LLVM version: 15.0.7
@booti386 booti386 added the C-bug Category: This is a bug. label Mar 10, 2023
@booti386 booti386 changed the title Inconsistent behavior of auto_traits+negative_impl across crates. Inconsistent behavior of auto_traits+negative_impls across crates. Mar 10, 2023
@workingjubilee workingjubilee added A-trait-system Area: Trait system F-negative_impls #![feature(negative_impls)] F-auto_traits `#![feature(auto_traits)]` A-auto-traits Area: auto traits (e.g., `auto trait Send {}`) labels Mar 11, 2023
@workingjubilee
Copy link
Member

I believe this problem looks like

pub trait B<I, O> {}
impl<T, I: ExternNotVoid> B<I, ()> for T {} // Generic over B<I, ()>
impl<T, O: ExternNotVoid> B<(), O> for T {} // I is generic,
// and () is !ExternNotVoid, so it can't be in I
// but that isn't factored into checking the validity of the implementation

I'm not sure which is the "intended" behavior. But I believe this is a known issue? There are several issues regarding negative impls, coherence-checking, their interaction with auto-traits, and their soundness:

At a glance, none seem like an exact match, but it could just be my inability to perceive a pattern where one exists.

@booti386
Copy link
Author

What particularly surprises me is that it works when everything is in the same crate, but stops working when NotVoid is declared in another crate.

@workingjubilee
Copy link
Member

workingjubilee commented Mar 11, 2023

A crate is allowed to bend the rules slightly for its own trait-and-type implementations (due to not being subject as directly to the "orphan rule"). I'm not sure this case of such a weakening is sound (or due to the orphan rule and related coherence checks, for that matter).

@Noratrieb Noratrieb added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Apr 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-auto-traits Area: auto traits (e.g., `auto trait Send {}`) A-trait-system Area: Trait system C-bug Category: This is a bug. F-auto_traits `#![feature(auto_traits)]` F-negative_impls #![feature(negative_impls)] T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

3 participants