diff options
| author | Esteban Küber <esteban@kuber.com.ar> | 2020-04-13 19:46:34 -0700 |
|---|---|---|
| committer | Esteban Küber <esteban@kuber.com.ar> | 2020-05-02 18:24:07 -0700 |
| commit | 31b356619657928113902b975453a5e19371bb25 (patch) | |
| tree | 3091edeed3d01082c1e4e491a52ee36a5cffb363 | |
| parent | 3a795fba038bf64452abb8c2240fd1221185e274 (diff) | |
| download | rust-31b356619657928113902b975453a5e19371bb25.tar.gz rust-31b356619657928113902b975453a5e19371bb25.zip | |
When a projection is expected, suggest constraining or calling method
13 files changed, 228 insertions, 84 deletions
diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs index 9de7dcc845f..13c7989e5c8 100644 --- a/src/librustc_infer/infer/error_reporting/mod.rs +++ b/src/librustc_infer/infer/error_reporting/mod.rs @@ -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. @@ -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, diff --git a/src/librustc_middle/ty/error.rs b/src/librustc_middle/ty/error.rs index eb5a5702c45..99ea0068fed 100644 --- a/src/librustc_middle/ty/error.rs +++ b/src/librustc_middle/ty/error.rs @@ -1,10 +1,12 @@ +use crate::traits::{ObligationCause, ObligationCauseCode}; use crate::ty::{self, BoundRegion, Region, Ty, TyCtxt}; use rustc_ast::ast; -use rustc_errors::{pluralize, Applicability, DiagnosticBuilder}; +use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect}; +use rustc_errors::{pluralize, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_span::symbol::sym; -use rustc_span::{BytePos, Span}; +use rustc_span::{BytePos, MultiSpan, Span}; use rustc_target::spec::abi; use std::borrow::Cow; @@ -332,6 +334,7 @@ impl<'tcx> TyCtxt<'tcx> { self, db: &mut DiagnosticBuilder<'_>, err: &TypeError<'tcx>, + cause: &ObligationCause<'tcx>, sp: Span, body_owner_def_id: DefId, ) { @@ -370,7 +373,7 @@ impl<'tcx> TyCtxt<'tcx> { sp, "use a float literal", format!("{}.0", snippet), - Applicability::MachineApplicable, + MachineApplicable, ); } } @@ -451,33 +454,13 @@ impl<T> Trait<T> for X { db.span_label(p_span, "this type parameter"); } } - (ty::Projection(_), _) => { - db.note(&format!( - "consider constraining the associated type `{}` to `{}` or calling a \ - method that returns `{0}`", - values.expected, values.found, - )); - if self.sess.teach(&db.get_code().unwrap()) { - db.help( - "given an associated type `T` and a method `foo`: -``` -trait Trait { - type T; - fn foo(&self) -> Self::T; -} -``` -the only way of implementing method `foo` is to constrain `T` with an explicit associated type: -``` -impl Trait for X { - type T = String; - fn foo(&self) -> Self::T { String::new() } -} -```", - ); - } - db.note( - "for more information, visit \ - https://doc.rust-lang.org/book/ch19-03-advanced-traits.html", + (ty::Projection(proj_ty), _) => { + self.expected_projection( + db, + proj_ty, + values, + body_owner_def_id, + &cause.code, ); } (_, ty::Projection(proj_ty)) => { @@ -485,7 +468,13 @@ impl Trait for X { "consider constraining the associated type `{}` to `{}`", values.found, values.expected, ); - if !self.suggest_constraint(db, &msg, body_owner_def_id, proj_ty, values) { + if !self.suggest_constraint( + db, + &msg, + body_owner_def_id, + proj_ty, + values.expected, + ) { db.help(&msg); db.note( "for more information, visit \ @@ -533,7 +522,7 @@ impl Trait for X { msg: &str, body_owner_def_id: DefId, proj_ty: &ty::ProjectionTy<'tcx>, - values: &ExpectedFound<Ty<'tcx>>, + ty: Ty<'tcx>, ) -> bool { let assoc = self.associated_item(proj_ty.item_def_id); let trait_ref = proj_ty.trait_ref(*self); @@ -570,7 +559,7 @@ impl Trait for X { &trait_ref, pred.bounds, &assoc, - values, + ty, msg, ) { return true; @@ -587,7 +576,7 @@ impl Trait for X { &trait_ref, param.bounds, &assoc, - values, + ty, msg, ); } @@ -597,15 +586,145 @@ impl Trait for X { false } + fn expected_projection( + &self, + db: &mut DiagnosticBuilder<'_>, + proj_ty: &ty::ProjectionTy<'tcx>, + values: &ExpectedFound<Ty<'tcx>>, + body_owner_def_id: DefId, + cause_code: &ObligationCauseCode<'_>, + ) { + let msg = format!( + "consider constraining the associated type `{}` to `{}`", + values.expected, values.found + ); + let mut suggested = false; + let body_owner = self.hir().get_if_local(body_owner_def_id); + let current_method_ident = body_owner.and_then(|n| n.ident()).map(|i| i.name); + + let callable_scope = match body_owner { + Some( + hir::Node::Item(hir::Item { + kind: + hir::ItemKind::Trait(..) + | hir::ItemKind::Impl { .. } + | hir::ItemKind::Const(..) + | hir::ItemKind::Enum(..) + | hir::ItemKind::Struct(..) + | hir::ItemKind::Union(..), + .. + }) + | hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Const(..) | hir::TraitItemKind::Type(..), + .. + }) + | hir::Node::ImplItem(hir::ImplItem { + kind: hir::ImplItemKind::Const(..) | hir::ImplItemKind::TyAlias(..), + .. + }), + ) => false, + _ => true, + }; + let impl_comparison = + matches!(cause_code, ObligationCauseCode::CompareImplMethodObligation { .. }); + if !callable_scope || impl_comparison { + // We do not want to suggest calling functions when the reason of the + // type error is a comparison of an `impl` with its `trait` or when the + // scope is outside of a `Body`. + } else { + let assoc = self.associated_item(proj_ty.item_def_id); + let items = self.associated_items(assoc.container.id()); + // Find all the methods in the trait that could be called to construct the + // expected associated type. + let methods: Vec<(Span, String)> = items + .items + .iter() + .filter(|(name, item)| { + ty::AssocKind::Method == item.kind && Some(**name) != current_method_ident + }) + .filter_map(|(_, item)| { + let method = self.fn_sig(item.def_id); + match method.output().skip_binder().kind { + ty::Projection(ty::ProjectionTy { item_def_id, .. }) + if item_def_id == proj_ty.item_def_id => + { + Some(( + self.sess.source_map().guess_head_span(self.def_span(item.def_id)), + format!("consider calling `{}`", self.def_path_str(item.def_id)), + )) + } + _ => None, + } + }) + .collect(); + if !methods.is_empty() { + // Use a single `help:` to show all the methods in the trait that can + // be used to construct the expected associated type. + let mut span: MultiSpan = + methods.iter().map(|(sp, _)| *sp).collect::<Vec<Span>>().into(); + let msg = format!( + "{some} method{s} {are} available that return{r} `{ty}`", + some = if methods.len() == 1 { "a" } else { "some" }, + s = pluralize!(methods.len()), + are = if methods.len() == 1 { "is" } else { "are" }, + r = if methods.len() == 1 { "s" } else { "" }, + ty = values.expected + ); + for (sp, label) in methods.into_iter() { + span.push_span_label(sp, label); + } + db.span_help(span, &msg); + suggested = true; + } + // Possibly suggest constraining the associated type to conform to the + // found type. + suggested |= + self.suggest_constraint(db, &msg, body_owner_def_id, proj_ty, values.found); + } + if !suggested && !impl_comparison { + // Generic suggestion when we can't be more specific. + if callable_scope { + db.help( + &format!("{} or calling a method that returns `{}`", msg, values.expected,), + ); + } else { + db.help(&msg); + } + db.note( + "for more information, visit \ + https://doc.rust-lang.org/book/ch19-03-advanced-traits.html", + ); + } + if self.sess.teach(&db.get_code().unwrap()) { + db.help( + "given an associated type `T` and a method `foo`: +``` +trait Trait { +type T; +fn foo(&self) -> Self::T; +} +``` +the only way of implementing method `foo` is to constrain `T` with an explicit associated type: +``` +impl Trait for X { +type T = String; +fn foo(&self) -> Self::T { String::new() } +} +```", + ); + } + } + fn constrain_associated_type_structured_suggestion( &self, db: &mut DiagnosticBuilder<'_>, trait_ref: &ty::TraitRef<'tcx>, bounds: hir::GenericBounds<'_>, assoc: &ty::AssocItem, - values: &ExpectedFound<Ty<'tcx>>, + ty: Ty<'tcx>, msg: &str, ) -> bool { + // FIXME: we would want to call `resolve_vars_if_possible` on `ty` before suggesting. for bound in bounds { match bound { hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::None) => { @@ -620,14 +739,11 @@ impl Trait for X { let (span, sugg) = if has_params { let pos = ptr.span.hi() - BytePos(1); let span = Span::new(pos, pos, ptr.span.ctxt()); - (span, format!(", {} = {}", assoc.ident, values.expected)) + (span, format!(", {} = {}", assoc.ident, ty)) } else { - ( - ptr.span.shrink_to_hi(), - format!("<{} = {}>", assoc.ident, values.expected), - ) + (ptr.span.shrink_to_hi(), format!("<{} = {}>", assoc.ident, ty)) }; - db.span_suggestion(span, msg, sugg, Applicability::MaybeIncorrect); + db.span_suggestion_verbose(span, msg, sugg, MaybeIncorrect); return true; } } diff --git a/src/test/ui/associated-const/associated-const-generic-obligations.stderr b/src/test/ui/associated-const/associated-const-generic-obligations.stderr index d6cdcd4747f..6e3ec4ed155 100644 --- a/src/test/ui/associated-const/associated-const-generic-obligations.stderr +++ b/src/test/ui/associated-const/associated-const-generic-obligations.stderr @@ -9,7 +9,7 @@ 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` + = help: consider constraining the associated type `<T as Foo>::Out` to `&'static str` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error: aborting due to previous error diff --git a/src/test/ui/associated-types/defaults-in-other-trait-items.rs b/src/test/ui/associated-types/defaults-in-other-trait-items.rs index 9f2e8aca477..41dc67d6f47 100644 --- a/src/test/ui/associated-types/defaults-in-other-trait-items.rs +++ b/src/test/ui/associated-types/defaults-in-other-trait-items.rs @@ -10,7 +10,7 @@ trait Tr { //~^ ERROR mismatched types //~| NOTE expected associated type, found `()` //~| NOTE expected associated type `<Self as Tr>::A` - //~| NOTE consider constraining the associated type + //~| HELP consider constraining the associated type //~| NOTE for more information, visit } } @@ -38,7 +38,7 @@ trait AssocConst { //~^ ERROR mismatched types //~| NOTE expected associated type, found `u8` //~| NOTE expected associated type `<Self as AssocConst>::Ty` - //~| NOTE consider constraining the associated type + //~| HELP consider constraining the associated type //~| NOTE for more information, visit } diff --git a/src/test/ui/associated-types/defaults-in-other-trait-items.stderr b/src/test/ui/associated-types/defaults-in-other-trait-items.stderr index 9ecfe49c2b5..a5b170d05c4 100644 --- a/src/test/ui/associated-types/defaults-in-other-trait-items.stderr +++ b/src/test/ui/associated-types/defaults-in-other-trait-items.stderr @@ -6,7 +6,7 @@ LL | let () = p; | = 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` + = help: 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 @@ -17,7 +17,7 @@ LL | const C: Self::Ty = 0u8; | = 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` + = help: consider constraining the associated type `<Self as AssocConst>::Ty` to `u8` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error: aborting due to 2 previous errors diff --git a/src/test/ui/associated-types/defaults-specialization.stderr b/src/test/ui/associated-types/defaults-specialization.stderr index 1dd536ec636..2f3ce832725 100644 --- a/src/test/ui/associated-types/defaults-specialization.stderr +++ b/src/test/ui/associated-types/defaults-specialization.stderr @@ -9,8 +9,6 @@ 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 @@ -23,8 +21,6 @@ LL | fn make() -> bool { true } | = 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 @@ -36,7 +32,7 @@ LL | 0u8 | = 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` + = help: 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 @@ -49,7 +45,7 @@ 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 @@ -62,7 +58,7 @@ LL | fn make() -> Self::Ty { true } | = 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` + = help: 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 @@ -75,8 +71,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 @@ -88,8 +87,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 @@ -101,8 +103,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 @@ -114,8 +119,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 diff --git a/src/test/ui/associated-types/issue-26681.stderr b/src/test/ui/associated-types/issue-26681.stderr index da10933df92..74411008c9d 100644 --- a/src/test/ui/associated-types/issue-26681.stderr +++ b/src/test/ui/associated-types/issue-26681.stderr @@ -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 diff --git a/src/test/ui/generic-associated-types/iterable.stderr b/src/test/ui/generic-associated-types/iterable.stderr index 4a839ac4bcb..6e754621225 100644 --- a/src/test/ui/generic-associated-types/iterable.stderr +++ b/src/test/ui/generic-associated-types/iterable.stderr @@ -34,7 +34,7 @@ LL | fn iter<'a>(&'a self) -> Self::Iter<'a> { | = note: expected associated type `<std::vec::Vec<T> as Iterable>::Item<'_>` found reference `&T` - = note: consider constraining the associated type `<std::vec::Vec<T> as Iterable>::Item<'_>` to `&_` or calling a method that returns `<std::vec::Vec<T> as Iterable>::Item<'_>` + = help: consider constraining the associated type `<std::vec::Vec<T> as Iterable>::Item<'_>` to `&_` or calling a method that returns `<std::vec::Vec<T> as Iterable>::Item<'_>` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0271]: type mismatch resolving `for<'a> <<[T] as Iterable>::Iter<'a> as std::iter::Iterator>::Item == <[T] as Iterable>::Item<'a>` @@ -51,7 +51,7 @@ LL | fn iter<'a>(&'a self) -> Self::Iter<'a> { | = note: expected associated type `<[T] as Iterable>::Item<'_>` found reference `&T` - = note: consider constraining the associated type `<[T] as Iterable>::Item<'_>` to `&_` or calling a method that returns `<[T] as Iterable>::Item<'_>` + = help: consider constraining the associated type `<[T] as Iterable>::Item<'_>` to `&_` or calling a method that returns `<[T] as Iterable>::Item<'_>` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error: aborting due to 4 previous errors diff --git a/src/test/ui/issues/issue-32323.stderr b/src/test/ui/issues/issue-32323.stderr index 7c0928b1924..369f56b9869 100644 --- a/src/test/ui/issues/issue-32323.stderr +++ b/src/test/ui/issues/issue-32323.stderr @@ -8,8 +8,10 @@ LL | pub fn f<'a, T: Tr<'a>>() -> <T as Tr<'a>>::Out {} | = note: expected associated type `<T as Tr<'a>>::Out` found unit type `()` - = note: consider constraining the associated type `<T as Tr<'a>>::Out` to `()` or calling a method that returns `<T as Tr<'a>>::Out` - = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html +help: consider constraining the associated type `<T as Tr<'a>>::Out` to `()` + | +LL | pub fn f<'a, T: Tr<'a, Out = ()>>() -> <T as Tr<'a>>::Out {} + | ^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/specialization/specialization-default-projection.stderr b/src/test/ui/specialization/specialization-default-projection.stderr index 4344fe23bbc..ac15ab0681a 100644 --- a/src/test/ui/specialization/specialization-default-projection.stderr +++ b/src/test/ui/specialization/specialization-default-projection.stderr @@ -9,7 +9,7 @@ LL | () | = note: expected associated type `<T as Foo>::Assoc` found unit type `()` - = note: consider constraining the associated type `<T as Foo>::Assoc` to `()` or calling a method that returns `<T as Foo>::Assoc` + = help: consider constraining the associated type `<T as Foo>::Assoc` to `()` or calling a method that returns `<T as Foo>::Assoc` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0308]: mismatched types diff --git a/src/test/ui/specialization/specialization-default-types.stderr b/src/test/ui/specialization/specialization-default-types.stderr index d66aaa96274..4dccf9ad9ab 100644 --- a/src/test/ui/specialization/specialization-default-types.stderr +++ b/src/test/ui/specialization/specialization-default-types.stderr @@ -8,7 +8,7 @@ LL | Box::new(self) | = note: expected associated type `<T as Example>::Output` found struct `std::boxed::Box<T>` - = note: consider constraining the associated type `<T as Example>::Output` to `std::boxed::Box<T>` or calling a method that returns `<T as Example>::Output` + = help: consider constraining the associated type `<T as Example>::Output` to `std::boxed::Box<T>` or calling a method that returns `<T as Example>::Output` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0308]: mismatched types diff --git a/src/test/ui/suggestions/trait-with-missing-associated-type-restriction.rs b/src/test/ui/suggestions/trait-with-missing-associated-type-restriction.rs index 1166785d739..7465049787f 100644 --- a/src/test/ui/suggestions/trait-with-missing-associated-type-restriction.rs +++ b/src/test/ui/suggestions/trait-with-missing-associated-type-restriction.rs @@ -6,6 +6,7 @@ trait Trait<T = Self> { type A; fn func(&self) -> Self::A; + fn funk(&self, _: Self::A); } fn foo(_: impl Trait, x: impl Trait) { @@ -21,6 +22,7 @@ fn foo2(x: impl Trait<i32>) { } fn bar2<T: Trait<i32>>(x: T) { + x.funk(3); //~ ERROR mismatched types qux(x.func()) //~ ERROR mismatched types } @@ -29,7 +31,7 @@ fn baz<D: std::fmt::Debug, T: Trait<A = D>>(x: T) { } fn bat(x: &mut dyn Trait<(), A = ()>) { - qux(x) //~ ERROR mismatched types + qux(x.func()) //~ ERROR mismatched types } fn ban<T>(x: T) where T: Trait { diff --git a/src/test/ui/suggestions/trait-with-missing-associated-type-restriction.stderr b/src/test/ui/suggestions/trait-with-missing-associated-type-restriction.stderr index 08788db6ec9..5ae1d45c6b7 100644 --- a/src/test/ui/suggestions/trait-with-missing-associated-type-restriction.stderr +++ b/src/test/ui/suggestions/trait-with-missing-associated-type-restriction.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/trait-with-missing-associated-type-restriction.rs:12:9 + --> $DIR/trait-with-missing-associated-type-restriction.rs:13:9 | LL | qux(x.func()) | ^^^^^^^^ expected `usize`, found associated type @@ -12,7 +12,7 @@ LL | fn foo(_: impl Trait, x: impl Trait<A = usize>) { | ^^^^^^^^^^^ error[E0308]: mismatched types - --> $DIR/trait-with-missing-associated-type-restriction.rs:16:9 + --> $DIR/trait-with-missing-associated-type-restriction.rs:17:9 | LL | qux(x.func()) | ^^^^^^^^ expected `usize`, found associated type @@ -25,7 +25,7 @@ LL | fn bar<T: Trait<A = usize>>(x: T) { | ^^^^^^^^^^^ error[E0308]: mismatched types - --> $DIR/trait-with-missing-associated-type-restriction.rs:20:9 + --> $DIR/trait-with-missing-associated-type-restriction.rs:21:9 | LL | qux(x.func()) | ^^^^^^^^ expected `usize`, found associated type @@ -38,7 +38,25 @@ LL | fn foo2(x: impl Trait<i32, A = usize>) { | ^^^^^^^^^^^ error[E0308]: mismatched types - --> $DIR/trait-with-missing-associated-type-restriction.rs:24:9 + --> $DIR/trait-with-missing-associated-type-restriction.rs:25:12 + | +LL | x.funk(3); + | ^ expected associated type, found integer + | + = note: expected associated type `<T as Trait<i32>>::A` + found type `{integer}` +help: a method is available that returns `<T as Trait<i32>>::A` + --> $DIR/trait-with-missing-associated-type-restriction.rs:8:5 + | +LL | fn func(&self) -> Self::A; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ consider calling `Trait::func` +help: consider constraining the associated type `<T as Trait<i32>>::A` to `{integer}` + | +LL | fn bar2<T: Trait<i32, A = {integer}>>(x: T) { + | ^^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction.rs:26:9 | LL | qux(x.func()) | ^^^^^^^^ expected `usize`, found associated type @@ -51,7 +69,7 @@ LL | fn bar2<T: Trait<i32, A = usize>>(x: T) { | ^^^^^^^^^^^ error[E0308]: mismatched types - --> $DIR/trait-with-missing-associated-type-restriction.rs:28:9 + --> $DIR/trait-with-missing-associated-type-restriction.rs:30:9 | LL | fn baz<D: std::fmt::Debug, T: Trait<A = D>>(x: T) { | - this type parameter @@ -62,16 +80,13 @@ LL | qux(x.func()) found type parameter `D` error[E0308]: mismatched types - --> $DIR/trait-with-missing-associated-type-restriction.rs:32:9 + --> $DIR/trait-with-missing-associated-type-restriction.rs:34:9 | -LL | qux(x) - | ^ expected `usize`, found mutable reference - | - = note: expected type `usize` - found mutable reference `&mut dyn Trait<(), A = ()>` +LL | qux(x.func()) + | ^^^^^^^^ expected `usize`, found `()` error[E0308]: mismatched types - --> $DIR/trait-with-missing-associated-type-restriction.rs:36:9 + --> $DIR/trait-with-missing-associated-type-restriction.rs:38:9 | LL | qux(x.func()) | ^^^^^^^^ expected `usize`, found associated type @@ -83,6 +98,6 @@ help: consider constraining the associated type `<T as Trait>::A` to `usize` LL | fn ban<T>(x: T) where T: Trait<A = usize> { | ^^^^^^^^^^^ -error: aborting due to 7 previous errors +error: aborting due to 8 previous errors For more information about this error, try `rustc --explain E0308`. |
