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

Stop bailing out from compilation just because there were incoherent traits #120558

Merged
merged 3 commits into from
Feb 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
8 changes: 8 additions & 0 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1005,6 +1005,11 @@ 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.parent(item.trait_item_def_id.unwrap_or(item_id.into())))?;

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 @@ -1291,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
5 changes: 3 additions & 2 deletions compiler/rustc_hir_typeck/src/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pub fn check_legal_trait_for_method_call(
receiver: Option<Span>,
expr_span: Span,
trait_id: DefId,
) {
) -> Result<(), ErrorGuaranteed> {
if tcx.lang_items().drop_trait() == Some(trait_id) {
let sugg = if let Some(receiver) = receiver.filter(|s| !s.is_empty()) {
errors::ExplicitDestructorCallSugg::Snippet {
Expand All @@ -51,8 +51,9 @@ pub fn check_legal_trait_for_method_call(
} else {
errors::ExplicitDestructorCallSugg::Empty(span)
};
tcx.dcx().emit_err(errors::ExplicitDestructorCall { span, sugg });
return Err(tcx.dcx().emit_err(errors::ExplicitDestructorCall { span, sugg }));
}
tcx.coherent_trait(trait_id)
}

#[derive(Debug)]
Expand Down
18 changes: 11 additions & 7 deletions compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1105,13 +1105,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let container_id = assoc_item.container_id(tcx);
debug!(?def_id, ?container, ?container_id);
match container {
ty::TraitContainer => callee::check_legal_trait_for_method_call(
tcx,
path_span,
None,
span,
container_id,
),
ty::TraitContainer => {
if let Err(e) = callee::check_legal_trait_for_method_call(
tcx,
path_span,
None,
span,
container_id,
) {
self.set_tainted_by_errors(e);
}
}
ty::ImplContainer => {
if segments.len() == 1 {
// `<T>::assoc` will end up here, and so
Expand Down
6 changes: 4 additions & 2 deletions compiler/rustc_hir_typeck/src/method/confirm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -630,13 +630,15 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
fn enforce_illegal_method_limitations(&self, pick: &probe::Pick<'_>) {
// Disallow calls to the method `drop` defined in the `Drop` trait.
if let Some(trait_def_id) = pick.item.trait_container(self.tcx) {
callee::check_legal_trait_for_method_call(
if let Err(e) = callee::check_legal_trait_for_method_call(
self.tcx,
self.span,
Some(self.self_expr.span),
self.call_expr.span,
trait_def_id,
)
) {
self.set_tainted_by_errors(e);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2364,6 +2364,12 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
return e;
}

if let Err(guar) = self.tcx.ensure().coherent_trait(trait_ref.def_id()) {
// Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case
// other `Foo` impls are incoherent.
return guar;
}

// This is kind of a hack: it frequently happens that some earlier
// error prevents types from being fully inferred, and then we get
// a bunch of uninteresting errors saying something like "<generic
Expand Down Expand Up @@ -2659,6 +2665,14 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
if let Some(e) = self.tainted_by_errors() {
return e;
}

if let Err(guar) =
self.tcx.ensure().coherent_trait(self.tcx.parent(data.projection_ty.def_id))
{
// Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case
// other `Foo` impls are incoherent.
return guar;
}
let subst = data
.projection_ty
.args
Expand Down
36 changes: 0 additions & 36 deletions library/core/src/primitive_docs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -448,22 +448,6 @@ mod prim_unit {}
#[doc(hidden)]
impl () {}

// Fake impl that's only really used for docs.
#[cfg(doc)]
#[stable(feature = "rust1", since = "1.0.0")]
impl Clone for () {
fn clone(&self) -> Self {
loop {}
}
}

// Fake impl that's only really used for docs.
#[cfg(doc)]
#[stable(feature = "rust1", since = "1.0.0")]
impl Copy for () {
// empty
}

#[rustc_doc_primitive = "pointer"]
#[doc(alias = "ptr")]
#[doc(alias = "*")]
Expand Down Expand Up @@ -1690,23 +1674,3 @@ mod prim_fn {}
// See src/librustdoc/passes/collect_trait_impls.rs:collect_trait_impls
#[doc(hidden)]
impl<Ret, T> fn(T) -> Ret {}

// Fake impl that's only really used for docs.
#[cfg(doc)]
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(fake_variadic)]
/// This trait is implemented on function pointers with any number of arguments.
impl<Ret, T> Clone for fn(T) -> Ret {
fn clone(&self) -> Self {
loop {}
}
}

// Fake impl that's only really used for docs.
#[cfg(doc)]
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(fake_variadic)]
/// This trait is implemented on function pointers with any number of arguments.
impl<Ret, T> Copy for fn(T) -> Ret {
// empty
}
Comment on lines -1704 to -1712
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was added in #98180 by @notriddle but does not appear to affect any tests (anymore?). If this has a negative effect on docs, we should add tests for it and figure out how to get it back without having to add impls that don't typeck.

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`.
2 changes: 0 additions & 2 deletions tests/ui/async-await/in-trait/coherence-constrained.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,13 @@ impl Foo for Bar {
type T = ();

async fn foo(&self) {}
//~^ ERROR type annotations needed: cannot satisfy `<Bar as Foo>::T == ()`
}

impl Foo for Bar {
//~^ ERROR conflicting implementations of trait `Foo` for type `Bar`
type T = ();

async fn foo(&self) {}
//~^ ERROR type annotations needed: cannot satisfy `<Bar as Foo>::T == ()`
}

fn main() {}
19 changes: 3 additions & 16 deletions tests/ui/async-await/in-trait/coherence-constrained.stderr
Original file line number Diff line number Diff line change
@@ -1,25 +1,12 @@
error[E0284]: type annotations needed: cannot satisfy `<Bar as Foo>::T == ()`
--> $DIR/coherence-constrained.rs:14:5
|
LL | async fn foo(&self) {}
| ^^^^^^^^^^^^^^^^^^^ cannot satisfy `<Bar as Foo>::T == ()`

error[E0284]: type annotations needed: cannot satisfy `<Bar as Foo>::T == ()`
--> $DIR/coherence-constrained.rs:22:5
|
LL | async fn foo(&self) {}
| ^^^^^^^^^^^^^^^^^^^ cannot satisfy `<Bar as Foo>::T == ()`

error[E0119]: conflicting implementations of trait `Foo` for type `Bar`
--> $DIR/coherence-constrained.rs:18:1
--> $DIR/coherence-constrained.rs:17:1
|
LL | impl Foo for Bar {
| ---------------- first implementation here
...
LL | impl Foo for Bar {
| ^^^^^^^^^^^^^^^^ conflicting implementation for `Bar`

error: aborting due to 3 previous errors
error: aborting due to 1 previous error

Some errors have detailed explanations: E0119, E0284.
For more information about an error, try `rustc --explain E0119`.
For more information about this error, try `rustc --explain E0119`.
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`.
Loading
Loading