Skip to content

Commit

Permalink
Stop bailing out from compilation just because there were incoherent …
Browse files Browse the repository at this point in the history
…traits
  • Loading branch information
oli-obk committed Feb 2, 2024
1 parent fe8c4ed commit 965da3a
Show file tree
Hide file tree
Showing 44 changed files with 480 additions and 83 deletions.
4 changes: 4 additions & 0 deletions compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1990,6 +1990,10 @@ pub(super) fn check_type_bounds<'tcx>(
impl_ty: ty::AssocItem,
impl_trait_ref: ty::TraitRef<'tcx>,
) -> Result<(), ErrorGuaranteed> {
// Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case
// other `Foo` impls are incoherent.
tcx.ensure().coherent_trait(impl_trait_ref.def_id)?;

let param_env = tcx.param_env(impl_ty.def_id);
debug!(?param_env);

Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1006,6 +1006,10 @@ fn check_associated_item(
enter_wf_checking_ctxt(tcx, span, item_id, |wfcx| {
let item = tcx.associated_item(item_id);

// Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case
// other `Foo` impls are incoherent.
tcx.ensure().coherent_trait(tcx.local_parent(item_id))?;

let self_ty = match item.container {
ty::TraitContainer => tcx.types.self_param,
ty::ImplContainer => tcx.type_of(item.container_id(tcx)).instantiate_identity(),
Expand Down Expand Up @@ -1292,6 +1296,9 @@ fn check_impl<'tcx>(
// therefore don't need to be WF (the trait's `Self: Trait` predicate
// won't hold).
let trait_ref = tcx.impl_trait_ref(item.owner_id).unwrap().instantiate_identity();
// Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case
// other `Foo` impls are incoherent.
tcx.ensure().coherent_trait(trait_ref.def_id)?;
let trait_ref = wfcx.normalize(
ast_trait_ref.path.span,
Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_analysis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,11 +169,11 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {

tcx.sess.time("coherence_checking", || {
// Check impls constrain their parameters
let mut res =
let res =
tcx.hir().try_par_for_each_module(|module| tcx.ensure().check_mod_impl_wf(module));

for &trait_def_id in tcx.all_local_trait_impls(()).keys() {
res = res.and(tcx.ensure().coherent_trait(trait_def_id));
let _ = tcx.ensure().coherent_trait(trait_def_id);
}
// these queries are executed for side-effects (error reporting):
res.and(tcx.ensure().crate_inherent_impls(()))
Expand Down
1 change: 1 addition & 0 deletions tests/ui/associated-consts/issue-105330.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ fn foo<A: TraitWAssocConst<A=32>>() { //~ ERROR E0658

fn main<A: TraitWAssocConst<A=32>>() {
//~^ ERROR E0658
//~| ERROR E0131
foo::<Demo>();
}
12 changes: 9 additions & 3 deletions tests/ui/associated-consts/issue-105330.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,13 @@ LL | impl TraitWAssocConst for impl Demo {
|
= note: `impl Trait` is only allowed in arguments and return types of functions and methods

error: aborting due to 5 previous errors
error[E0131]: `main` function is not allowed to have generic parameters
--> $DIR/issue-105330.rs:15:8
|
LL | fn main<A: TraitWAssocConst<A=32>>() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `main` cannot have generic parameters

error: aborting due to 6 previous errors

Some errors have detailed explanations: E0404, E0562, E0658.
For more information about an error, try `rustc --explain E0404`.
Some errors have detailed explanations: E0131, E0404, E0562, E0658.
For more information about an error, try `rustc --explain E0131`.
20 changes: 20 additions & 0 deletions tests/ui/coherence/associated-type2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//! A regression test for #120343. The overlap error was previously
//! silenced in coherence because projecting `<() as ToUnit>::Unit`
//! failed. Then then silenced the missing items error in the `ToUnit`
//! impl, causing us to not emit any errors and ICEing due to a
//! `span_delay_bug`.

trait ToUnit {
type Unit;
}

impl<T> ToUnit for *const T {}
//~^ ERROR: not all trait items implemented

trait Overlap<T> {}

impl<T> Overlap<T> for T {}

impl<T> Overlap<<*const T as ToUnit>::Unit> for T {}

fn main() {}
12 changes: 12 additions & 0 deletions tests/ui/coherence/associated-type2.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
error[E0046]: not all trait items implemented, missing: `Unit`
--> $DIR/associated-type2.rs:11:1
|
LL | type Unit;
| --------- `Unit` from trait
...
LL | impl<T> ToUnit for *const T {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `Unit` in implementation

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0046`.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ struct MyType {
impl MyTrait<MyType> for MyType {
//~^ ERROR E0119
fn get(&self) -> usize { (*self).clone() }
//~^ ERROR incompatible type
}

fn main() { }
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,24 @@ LL | impl<T> MyTrait<T> for T {
LL | impl MyTrait<MyType> for MyType {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyType`

error: aborting due to 1 previous error
error[E0053]: method `get` has an incompatible type for trait
--> $DIR/coherence-blanket-conflicts-with-specific-multidispatch.rs:24:22
|
LL | fn get(&self) -> usize { (*self).clone() }
| ^^^^^
| |
| expected `MyType`, found `usize`
| help: change the output type to match the trait: `MyType`
|
note: type in trait
--> $DIR/coherence-blanket-conflicts-with-specific-multidispatch.rs:8:22
|
LL | fn get(&self) -> T;
| ^
= note: expected signature `fn(&MyType) -> MyType`
found signature `fn(&MyType) -> usize`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0119`.
Some errors have detailed explanations: E0053, E0119.
For more information about an error, try `rustc --explain E0053`.
3 changes: 3 additions & 0 deletions tests/ui/coherence/coherence-orphan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@ struct TheType;

impl TheTrait<usize> for isize { }
//~^ ERROR E0117
//~| ERROR not all trait items implemented

impl TheTrait<TheType> for isize { }
//~^ ERROR not all trait items implemented

impl TheTrait<isize> for TheType { }
//~^ ERROR not all trait items implemented

impl !Send for Vec<isize> { } //~ ERROR E0117
//~^ WARNING
Expand Down
33 changes: 29 additions & 4 deletions tests/ui/coherence/coherence-orphan.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ LL | impl TheTrait<usize> for isize { }
= note: define and implement a trait or new type instead

error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
--> $DIR/coherence-orphan.rs:17:1
--> $DIR/coherence-orphan.rs:20:1
|
LL | impl !Send for Vec<isize> { }
| ^^^^^^^^^^^^^^^----------
Expand All @@ -22,7 +22,7 @@ LL | impl !Send for Vec<isize> { }
= note: define and implement a trait or new type instead

warning: cross-crate traits with a default impl, like `Send`, should not be specialized
--> $DIR/coherence-orphan.rs:17:1
--> $DIR/coherence-orphan.rs:20:1
|
LL | impl !Send for Vec<isize> { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -34,6 +34,31 @@ note: try using the same sequence of generic parameters as the struct definition
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
= note: `#[warn(suspicious_auto_trait_impls)]` on by default

error: aborting due to 2 previous errors; 1 warning emitted
error[E0046]: not all trait items implemented, missing: `the_fn`
--> $DIR/coherence-orphan.rs:10:1
|
LL | impl TheTrait<usize> for isize { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `the_fn` in implementation
|
= help: implement the missing item: `fn the_fn(&self) { todo!() }`

error[E0046]: not all trait items implemented, missing: `the_fn`
--> $DIR/coherence-orphan.rs:14:1
|
LL | impl TheTrait<TheType> for isize { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `the_fn` in implementation
|
= help: implement the missing item: `fn the_fn(&self) { todo!() }`

error[E0046]: not all trait items implemented, missing: `the_fn`
--> $DIR/coherence-orphan.rs:17:1
|
LL | impl TheTrait<isize> for TheType { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `the_fn` in implementation
|
= help: implement the missing item: `fn the_fn(&self) { todo!() }`

error: aborting due to 5 previous errors; 1 warning emitted

For more information about this error, try `rustc --explain E0117`.
Some errors have detailed explanations: E0046, E0117.
For more information about an error, try `rustc --explain E0046`.
5 changes: 5 additions & 0 deletions tests/ui/coherence/deep-bad-copy-reason.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@ extern "Rust" {
}

pub struct ListS<T> {
//~^ NOTE: required because it appears within the type
len: usize,
data: [T; 0],
opaque: OpaqueListContents,
}

pub struct Interned<'a, T>(&'a T);
//~^ NOTE: required by this bound
//~| NOTE: required by a bound

impl<'a, T> Clone for Interned<'a, T> {
fn clone(&self) -> Self {
Expand All @@ -23,6 +26,8 @@ impl<'a, T> Copy for Interned<'a, T> {}
pub struct List<'tcx, T>(Interned<'tcx, ListS<T>>);
//~^ NOTE this field does not implement `Copy`
//~| NOTE the `Copy` impl for `Interned<'tcx, ListS<T>>` requires that `OpaqueListContents: Sized`
//~| NOTE: doesn't have a size known at compile-time
//~| ERROR: cannot be known at compilation time

impl<'tcx, T> Clone for List<'tcx, T> {
fn clone(&self) -> Self {
Expand Down
31 changes: 27 additions & 4 deletions tests/ui/coherence/deep-bad-copy-reason.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0204]: the trait `Copy` cannot be implemented for this type
--> $DIR/deep-bad-copy-reason.rs:33:24
--> $DIR/deep-bad-copy-reason.rs:38:24
|
LL | pub struct List<'tcx, T>(Interned<'tcx, ListS<T>>);
| ------------------------ this field does not implement `Copy`
Expand All @@ -8,11 +8,34 @@ LL | impl<'tcx, T> Copy for List<'tcx, T> {}
| ^^^^^^^^^^^^^
|
note: the `Copy` impl for `Interned<'tcx, ListS<T>>` requires that `OpaqueListContents: Sized`
--> $DIR/deep-bad-copy-reason.rs:23:26
--> $DIR/deep-bad-copy-reason.rs:26:26
|
LL | pub struct List<'tcx, T>(Interned<'tcx, ListS<T>>);
| ^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 1 previous error
error[E0277]: the size for values of type `OpaqueListContents` cannot be known at compilation time
--> $DIR/deep-bad-copy-reason.rs:26:26
|
LL | pub struct List<'tcx, T>(Interned<'tcx, ListS<T>>);
| ^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: within `ListS<T>`, the trait `Sized` is not implemented for `OpaqueListContents`, which is required by `ListS<T>: Sized`
note: required because it appears within the type `ListS<T>`
--> $DIR/deep-bad-copy-reason.rs:7:12
|
LL | pub struct ListS<T> {
| ^^^^^
note: required by a bound in `Interned`
--> $DIR/deep-bad-copy-reason.rs:14:25
|
LL | pub struct Interned<'a, T>(&'a T);
| ^ required by this bound in `Interned`
help: consider relaxing the implicit `Sized` restriction
|
LL | pub struct Interned<'a, T: ?Sized>(&'a T);
| ++++++++

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0204`.
Some errors have detailed explanations: E0204, E0277.
For more information about an error, try `rustc --explain E0204`.
13 changes: 10 additions & 3 deletions tests/ui/coherence/occurs-check/opaques.next.stderr
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
error[E0119]: conflicting implementations of trait `Trait<Alias<_>>` for type `Alias<_>`
--> $DIR/opaques.rs:29:1
--> $DIR/opaques.rs:30:1
|
LL | impl<T> Trait<T> for T {
| ---------------------- first implementation here
...
LL | impl<T> Trait<T> for defining_scope::Alias<T> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Alias<_>`

error: aborting due to 1 previous error
error[E0282]: type annotations needed
--> $DIR/opaques.rs:13:20
|
LL | pub fn cast<T>(x: Container<Alias<T>, T>) -> Container<T, T> {
| ^ cannot infer type for struct `Container<Alias<T>, T>`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0119`.
Some errors have detailed explanations: E0119, E0282.
For more information about an error, try `rustc --explain E0119`.
1 change: 1 addition & 0 deletions tests/ui/coherence/occurs-check/opaques.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ mod defining_scope {
pub type Alias<T> = impl Sized;

pub fn cast<T>(x: Container<Alias<T>, T>) -> Container<T, T> {
//[next]~^ ERROR type annotations needed
x
}
}
Expand Down
1 change: 1 addition & 0 deletions tests/ui/error-codes/E0117.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
impl Drop for u32 {} //~ ERROR E0117
//~| ERROR the `Drop` trait may only be implemented for local structs, enums, and unions
//~| ERROR not all trait items implemented

fn main() {}
14 changes: 11 additions & 3 deletions tests/ui/error-codes/E0117.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,15 @@ error[E0120]: the `Drop` trait may only be implemented for local structs, enums,
LL | impl Drop for u32 {}
| ^^^ must be a struct, enum, or union in the current crate

error: aborting due to 2 previous errors
error[E0046]: not all trait items implemented, missing: `drop`
--> $DIR/E0117.rs:1:1
|
LL | impl Drop for u32 {}
| ^^^^^^^^^^^^^^^^^ missing `drop` in implementation
|
= help: implement the missing item: `fn drop(&mut self) { todo!() }`

error: aborting due to 3 previous errors

Some errors have detailed explanations: E0117, E0120.
For more information about an error, try `rustc --explain E0117`.
Some errors have detailed explanations: E0046, E0117, E0120.
For more information about an error, try `rustc --explain E0046`.
2 changes: 2 additions & 0 deletions tests/ui/error-codes/E0120.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ trait MyTrait { fn foo() {} }
impl Drop for dyn MyTrait {
//~^ ERROR E0120
fn drop(&mut self) {}
//~^ ERROR E0038

}

fn main() {}
27 changes: 25 additions & 2 deletions tests/ui/error-codes/E0120.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,29 @@ error[E0120]: the `Drop` trait may only be implemented for local structs, enums,
LL | impl Drop for dyn MyTrait {
| ^^^^^^^^^^^ must be a struct, enum, or union in the current crate

error: aborting due to 1 previous error
error[E0038]: the trait `MyTrait` cannot be made into an object
--> $DIR/E0120.rs:5:18
|
LL | fn drop(&mut self) {}
| ^^^^ `MyTrait` cannot be made into an object
|
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/E0120.rs:1:20
|
LL | trait MyTrait { fn foo() {} }
| ------- ^^^ ...because associated function `foo` has no `self` parameter
| |
| this trait cannot be made into an object...
help: consider turning `foo` into a method by giving it a `&self` argument
|
LL | trait MyTrait { fn foo(&self) {} }
| +++++
help: alternatively, consider constraining `foo` so it does not apply to trait objects
|
LL | trait MyTrait { fn foo() where Self: Sized {} }
| +++++++++++++++++

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0120`.
Some errors have detailed explanations: E0038, E0120.
For more information about an error, try `rustc --explain E0038`.
2 changes: 1 addition & 1 deletion tests/ui/error-codes/E0374.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#![feature(coerce_unsized)]
use std::ops::CoerceUnsized;

struct Foo<T: ?Sized> {
struct Foo<T: ?Sized> { //~ ERROR `T` is never used
a: i32,
}

Expand Down
13 changes: 11 additions & 2 deletions tests/ui/error-codes/E0374.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@ LL | | where T: CoerceUnsized<U> {}
|
= note: expected a single field to be coerced, none found

error: aborting due to 1 previous error
error[E0392]: parameter `T` is never used
--> $DIR/E0374.rs:4:12
|
LL | struct Foo<T: ?Sized> {
| ^ unused parameter
|
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0374`.
Some errors have detailed explanations: E0374, E0392.
For more information about an error, try `rustc --explain E0374`.
Loading

0 comments on commit 965da3a

Please sign in to comment.