Closed
Description
I came across an interesting case today where the span for a diagnostic isn't quite leading to the best location. When compiling the example code below
struct A;
trait IntoWasmAbi {
type Abi;
fn into_abi(self) -> Self::Abi;
}
type T = <A as IntoWasmAbi>::Abi;
fn foo(a: T) {}
you get:
error[E0277]: the trait bound `A: IntoWasmAbi` is not satisfied
--> src/lib.rs:10:1
|
10 | fn foo(a: T) {}
| ^^^^^^^^^^^^^^^ the trait `IntoWasmAbi` is not implemented for `A`
but it's sort of misleading because neither A
nor IntoWasmAbi
is mentioned in the highlight. It'd be ideal if the error would point to the type
definition to indicat that's where the source of the error comes from.
Activity
estebank commentedon Oct 8, 2019
The following is where the obligation could be changed from
MiscObligation
to something more specific:rust/src/librustc/infer/mod.rs
Lines 1528 to 1550 in c20654e
And here is where we could peek at that new obligation and extend it with further information.
rust/src/librustc/traits/project.rs
Lines 417 to 455 in c20654e
Doing the naïve change
cause.span = tcx.def_span(tcx.associated_item(projection_ty.item_def_id).container.id())
would cause this error to output:The proper solution would require to track
type
s (which would probably need #21934 to be fixed), but would ideally look like this:estebank commentedon Mar 5, 2020
@rust-lang/lang: we could assert well-formedness of
hir::ItemKind::TyAlias
early incheck_item_well_formed
(we don't today, we just skip them 👀), which would turn this case into the following more understandable output:Is this something we would consider doing, even if it is as a warning? I believe this would be effectively a breaking change (code that compiles today would stop compiling) but not "in effect" because the previously compiling code could never be used. This seems to me like an accident to me.
For example, there's a test
type Y where i32: Foo = (); // OK - bound is ignored
which would fail with "the trait boundi32: Foo
is not satisfied" with my proposed change, which is the correct behavior of all other items.Edit: I see now that because we explicitily do not accept trait bounds on
type
s arguments, we cannot really perform the wf check always, otherwise we would need to allow trait bounds (and either propagate them or continue ignoring them but now without a warning) so thattype T<X: Trait> = <X as Trait>::Foo;
is allowed, or only do a wf check when there are no generic types involved (which feels like a hack, but a valid one that will expand to cover other invalid cases in the future). Thoughts?Edit: #69741 has the simplest change that should be safe to introduce based on my current understanding of the situation.
type
s with no type parameters #69741