Skip to content
5 changes: 3 additions & 2 deletions src/librustc_infer/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1388,6 +1388,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
terr: &TypeError<'tcx>,
) {
let span = cause.span(self.tcx);
debug!("note_type_err cause={:?} values={:?}, terr={:?}", cause, values, terr);

// For some types of errors, expected-found does not make
// sense, so just ignore the values we were given.
Expand Down Expand Up @@ -1599,11 +1600,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
self.tcx.hir().body_owner_def_id(hir::BodyId { hir_id: cause.body_id })
});
self.check_and_note_conflicting_crates(diag, terr);
self.tcx.note_and_explain_type_err(diag, terr, span, body_owner_def_id.to_def_id());
self.tcx.note_and_explain_type_err(diag, terr, cause, span, body_owner_def_id.to_def_id());

// It reads better to have the error origin as the final
// thing.
self.note_error_origin(diag, &cause, exp_found);
self.note_error_origin(diag, cause, exp_found);
}

/// When encountering a case where `.as_ref()` on a `Result` or `Option` would be appropriate,
Expand Down
3 changes: 3 additions & 0 deletions src/librustc_middle/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,9 @@ pub enum ObligationCauseCode<'tcx> {

DerivedObligation(DerivedObligationCause<'tcx>),

/// Error derived when matching traits/impls; see ObligationCause for more details
CompareImplConstObligation,

/// Error derived when matching traits/impls; see ObligationCause for more details
CompareImplMethodObligation {
item_name: ast::Name,
Expand Down
1 change: 1 addition & 0 deletions src/librustc_middle/traits/structural_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
tcx.lift(cause).map(super::ImplDerivedObligation)
}
super::DerivedObligation(ref cause) => tcx.lift(cause).map(super::DerivedObligation),
super::CompareImplConstObligation => Some(super::CompareImplConstObligation),
super::CompareImplMethodObligation {
item_name,
impl_item_def_id,
Expand Down
414 changes: 377 additions & 37 deletions src/librustc_middle/ty/error.rs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -1738,6 +1738,13 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
predicate
));
}
ObligationCauseCode::CompareImplConstObligation => {
err.note(&format!(
"the requirement `{}` appears on the associated impl constant \
but not on the corresponding associated trait constant",
predicate
));
}
ObligationCauseCode::ReturnType
| ObligationCauseCode::ReturnValue(_)
| ObligationCauseCode::BlockTailExpression(_) => (),
Expand Down
1 change: 1 addition & 0 deletions src/librustc_typeck/check/compare_method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -966,6 +966,7 @@ crate fn compare_const_impl<'tcx>(
let impl_ty = tcx.type_of(impl_c.def_id);
let trait_ty = tcx.type_of(trait_c.def_id).subst(tcx, trait_to_impl_substs);
let mut cause = ObligationCause::misc(impl_c_span, impl_c_hir_id);
cause.code = ObligationCauseCode::CompareImplConstObligation;

// There is no "body" here, so just pass dummy id.
let impl_ty =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ LL | const FROM: &'static str = "foo";
|
= note: expected associated type `<T as Foo>::Out`
found reference `&'static str`
= note: consider constraining the associated type `<T as Foo>::Out` to `&'static str` or calling a method that returns `<T as Foo>::Out`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html

error: aborting due to previous error

Expand Down
6 changes: 4 additions & 2 deletions src/test/ui/associated-types/associated-types-eq-3.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ LL | let _: Bar = x.boo();
|
= note: expected struct `Bar`
found associated type `<I as Foo>::A`
= note: consider constraining the associated type `<I as Foo>::A` to `Bar`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
help: consider constraining the associated type `<I as Foo>::A` to `Bar`
|
LL | fn foo2<I: Foo<A = Bar>>(x: I) {
| ^^^^^^^^^

error[E0271]: type mismatch resolving `<isize as Foo>::A == Bar`
--> $DIR/associated-types-eq-3.rs:38:5
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ LL | is_iterator_of::<Option<T>, _>(&adapter);
|
= note: expected enum `std::option::Option<T>`
found type `T`
= help: type parameters must be constrained to match other types
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters

error: aborting due to previous error

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ LL | fn want_y<T:Foo<Y=i32>>(t: &T) { }
|
= note: expected type `i32`
found associated type `<T as Foo>::Y`
= note: consider constraining the associated type `<T as Foo>::Y` to `i32`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
help: consider constraining the associated type `<T as Foo>::Y` to `i32`
|
LL | fn have_x_want_y<T:Foo<X=u32, Y = i32>>(t: &T)
| ^^^^^^^^^

error[E0271]: type mismatch resolving `<T as Foo>::X == u32`
--> $DIR/associated-types-multiple-types-one-trait.rs:18:5
Expand All @@ -23,8 +25,10 @@ LL | fn want_x<T:Foo<X=u32>>(t: &T) { }
|
= note: expected type `u32`
found associated type `<T as Foo>::X`
= note: consider constraining the associated type `<T as Foo>::X` to `u32`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
help: consider constraining the associated type `<T as Foo>::X` to `u32`
|
LL | fn have_y_want_x<T:Foo<Y=i32, X = u32>>(t: &T)
| ^^^^^^^^^

error: aborting due to 2 previous errors

Expand Down
8 changes: 2 additions & 6 deletions src/test/ui/associated-types/defaults-in-other-trait-items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,13 @@
// Associated type defaults may not be assumed inside the trait defining them.
// ie. they only resolve to `<Self as Tr>::A`, not the actual type `()`
trait Tr {
type A = ();
type A = (); //~ NOTE associated type defaults can't be assumed inside the trait defining them

fn f(p: Self::A) {
let () = p;
//~^ ERROR mismatched types
//~| NOTE expected associated type, found `()`
//~| NOTE expected associated type `<Self as Tr>::A`
//~| NOTE consider constraining the associated type
//~| NOTE for more information, visit
}
}

Expand All @@ -31,15 +29,13 @@ impl Tr for u8 {
}

trait AssocConst {
type Ty = u8;
type Ty = u8; //~ NOTE associated type defaults can't be assumed inside the trait defining them

// Assoc. consts also cannot assume that default types hold
const C: Self::Ty = 0u8;
//~^ ERROR mismatched types
//~| NOTE expected associated type, found `u8`
//~| NOTE expected associated type `<Self as AssocConst>::Ty`
//~| NOTE consider constraining the associated type
//~| NOTE for more information, visit
}

// An impl can, however
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
error[E0308]: mismatched types
--> $DIR/defaults-in-other-trait-items.rs:9:13
|
LL | type A = ();
| ------------ associated type defaults can't be assumed inside the trait defining them
...
LL | let () = p;
| ^^ expected associated type, found `()`
|
= note: expected associated type `<Self as Tr>::A`
found unit type `()`
= note: consider constraining the associated type `<Self as Tr>::A` to `()` or calling a method that returns `<Self as Tr>::A`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html

error[E0308]: mismatched types
--> $DIR/defaults-in-other-trait-items.rs:37:25
--> $DIR/defaults-in-other-trait-items.rs:35:25
|
LL | type Ty = u8;
| ------------- associated type defaults can't be assumed inside the trait defining them
...
LL | const C: Self::Ty = 0u8;
| ^^^ expected associated type, found `u8`
|
= note: expected associated type `<Self as AssocConst>::Ty`
found type `u8`
= note: consider constraining the associated type `<Self as AssocConst>::Ty` to `u8` or calling a method that returns `<Self as AssocConst>::Ty`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html

error: aborting due to 2 previous errors

Expand Down
47 changes: 30 additions & 17 deletions src/test/ui/associated-types/defaults-specialization.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -9,35 +9,35 @@ LL | fn make() -> u8 { 0 }
|
= note: expected fn pointer `fn() -> <A<T> as Tr>::Ty`
found fn pointer `fn() -> u8`
= note: consider constraining the associated type `<A<T> as Tr>::Ty` to `u8` or calling a method that returns `<A<T> as Tr>::Ty`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html

error[E0053]: method `make` has an incompatible type for trait
--> $DIR/defaults-specialization.rs:34:18
|
LL | fn make() -> Self::Ty {
| -------- type in trait
...
LL | default type Ty = bool;
| ----------------------- expected this associated type
LL |
LL | fn make() -> bool { true }
| ^^^^ expected associated type, found `bool`
|
= note: expected fn pointer `fn() -> <B<T> as Tr>::Ty`
found fn pointer `fn() -> bool`
= note: consider constraining the associated type `<B<T> as Tr>::Ty` to `bool` or calling a method that returns `<B<T> as Tr>::Ty`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html

error[E0308]: mismatched types
--> $DIR/defaults-specialization.rs:9:9
|
LL | type Ty = u8;
| ------------- associated type defaults can't be assumed inside the trait defining them
LL |
LL | fn make() -> Self::Ty {
| -------- expected `<Self as Tr>::Ty` because of return type
LL | 0u8
| ^^^ expected associated type, found `u8`
|
= note: expected associated type `<Self as Tr>::Ty`
found type `u8`
= note: consider constraining the associated type `<Self as Tr>::Ty` to `u8` or calling a method that returns `<Self as Tr>::Ty`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html

error[E0308]: mismatched types
--> $DIR/defaults-specialization.rs:25:29
Expand All @@ -49,21 +49,22 @@ LL | fn make() -> Self::Ty { 0u8 }
|
= note: expected associated type `<A2<T> as Tr>::Ty`
found type `u8`
= note: consider constraining the associated type `<A2<T> as Tr>::Ty` to `u8` or calling a method that returns `<A2<T> as Tr>::Ty`
= help: consider constraining the associated type `<A2<T> as Tr>::Ty` to `u8` or calling a method that returns `<A2<T> as Tr>::Ty`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html

error[E0308]: mismatched types
--> $DIR/defaults-specialization.rs:43:29
|
LL | default type Ty = bool;
| ----------------------- expected this associated type
LL |
LL | fn make() -> Self::Ty { true }
| -------- ^^^^ expected associated type, found `bool`
| |
| expected `<B2<T> as Tr>::Ty` because of return type
|
= note: expected associated type `<B2<T> as Tr>::Ty`
found type `bool`
= note: consider constraining the associated type `<B2<T> as Tr>::Ty` to `bool` or calling a method that returns `<B2<T> as Tr>::Ty`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html

error[E0308]: mismatched types
--> $DIR/defaults-specialization.rs:86:32
Expand All @@ -75,8 +76,11 @@ LL | let _: <B<()> as Tr>::Ty = 0u8;
|
= note: expected associated type `<B<()> as Tr>::Ty`
found type `u8`
= note: consider constraining the associated type `<B<()> as Tr>::Ty` to `u8` or calling a method that returns `<B<()> as Tr>::Ty`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
help: a method is available that returns `<B<()> as Tr>::Ty`
--> $DIR/defaults-specialization.rs:8:5
|
LL | fn make() -> Self::Ty {
| ^^^^^^^^^^^^^^^^^^^^^ consider calling `Tr::make`

error[E0308]: mismatched types
--> $DIR/defaults-specialization.rs:87:32
Expand All @@ -88,8 +92,11 @@ LL | let _: <B<()> as Tr>::Ty = true;
|
= note: expected associated type `<B<()> as Tr>::Ty`
found type `bool`
= note: consider constraining the associated type `<B<()> as Tr>::Ty` to `bool` or calling a method that returns `<B<()> as Tr>::Ty`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
help: a method is available that returns `<B<()> as Tr>::Ty`
--> $DIR/defaults-specialization.rs:8:5
|
LL | fn make() -> Self::Ty {
| ^^^^^^^^^^^^^^^^^^^^^ consider calling `Tr::make`

error[E0308]: mismatched types
--> $DIR/defaults-specialization.rs:88:33
Expand All @@ -101,8 +108,11 @@ LL | let _: <B2<()> as Tr>::Ty = 0u8;
|
= note: expected associated type `<B2<()> as Tr>::Ty`
found type `u8`
= note: consider constraining the associated type `<B2<()> as Tr>::Ty` to `u8` or calling a method that returns `<B2<()> as Tr>::Ty`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
help: a method is available that returns `<B2<()> as Tr>::Ty`
--> $DIR/defaults-specialization.rs:8:5
|
LL | fn make() -> Self::Ty {
| ^^^^^^^^^^^^^^^^^^^^^ consider calling `Tr::make`

error[E0308]: mismatched types
--> $DIR/defaults-specialization.rs:89:33
Expand All @@ -114,8 +124,11 @@ LL | let _: <B2<()> as Tr>::Ty = true;
|
= note: expected associated type `<B2<()> as Tr>::Ty`
found type `bool`
= note: consider constraining the associated type `<B2<()> as Tr>::Ty` to `bool` or calling a method that returns `<B2<()> as Tr>::Ty`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
help: a method is available that returns `<B2<()> as Tr>::Ty`
--> $DIR/defaults-specialization.rs:8:5
|
LL | fn make() -> Self::Ty {
| ^^^^^^^^^^^^^^^^^^^^^ consider calling `Tr::make`

error: aborting due to 9 previous errors

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
trait Foo {
type Item;
}

trait Bar: Foo {}

struct S;

impl Foo for S {
type Item = i32;
}
impl Bar for S {}

struct T;

impl Foo for T {
type Item = u32;
}
impl Bar for T {}

fn bar() -> impl Bar {
T
}

fn baz() -> impl Bar<Item = i32> {
//~^ ERROR type mismatch resolving `<impl Bar as Foo>::Item == i32`
bar()
}

fn main() {
let _ = baz();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
error[E0271]: type mismatch resolving `<impl Bar as Foo>::Item == i32`
--> $DIR/impl-trait-return-missing-constraint.rs:25:13
|
LL | fn bar() -> impl Bar {
| -------- the expected opaque type
...
LL | fn baz() -> impl Bar<Item = i32> {
| ^^^^^^^^^^^^^^^^^^^^ expected associated type, found `i32`
|
= note: expected associated type `<impl Bar as Foo>::Item`
found type `i32`
= note: the return type of a function must have a statically known size
help: consider constraining the associated type `<impl Bar as Foo>::Item` to `i32`
|
LL | fn bar() -> impl Bar<Item = i32> {
| ^^^^^^^^^^^^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0271`.
2 changes: 1 addition & 1 deletion src/test/ui/associated-types/issue-26681.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ LL | const C: <Self::Fv as Foo>::Bar = 6665;
|
= note: expected associated type `<<Self as Baz>::Fv as Foo>::Bar`
found type `{integer}`
= note: consider constraining the associated type `<<Self as Baz>::Fv as Foo>::Bar` to `{integer}` or calling a method that returns `<<Self as Baz>::Fv as Foo>::Bar`
= help: consider constraining the associated type `<<Self as Baz>::Fv as Foo>::Bar` to `{integer}`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html

error: aborting due to previous error
Expand Down
Loading