Skip to content

Commit

Permalink
Auto merge of #120558 - oli-obk:missing_impl_item_ice, r=estebank
Browse files Browse the repository at this point in the history
Stop bailing out from compilation just because there were incoherent traits

fixes #120343

but also has a lot of "type annotations needed" fallout. Some are fixed in the second commit.
  • Loading branch information
bors committed Feb 8, 2024
2 parents 384b02c + a59a1e7 commit 870a01a
Show file tree
Hide file tree
Showing 50 changed files with 490 additions and 146 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
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 @@ -2371,6 +2371,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 @@ -2666,6 +2672,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
}
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

0 comments on commit 870a01a

Please sign in to comment.