diff options
| author | bors <bors@rust-lang.org> | 2020-05-04 06:32:49 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2020-05-04 06:32:49 +0000 |
| commit | d6823ba1666fa5f65e5fdd17cfc78ff227c092f2 (patch) | |
| tree | ff83906186e0ccc897fc117fd332296249a83e65 | |
| parent | ff4df04799c406c8149a041c3163321758aac924 (diff) | |
| parent | b368229d9bbaa840e777d33e36e649967e7ecb04 (diff) | |
| download | rust-d6823ba1666fa5f65e5fdd17cfc78ff227c092f2.tar.gz rust-d6823ba1666fa5f65e5fdd17cfc78ff227c092f2.zip | |
Auto merge of #71108 - estebank:suggest-proj-type-mismatch-constraint, r=oli-obk
On type mismatch involving associated type, suggest constraint
When an associated type is found when a specific type was expected, if
possible provide a structured suggestion constraining the associated
type in a bound.
```
error[E0271]: type mismatch resolving `<T as Foo>::Y == i32`
--> $DIR/associated-types-multiple-types-one-trait.rs:13:5
|
LL | want_y(t);
| ^^^^^^ expected `i32`, found associated type
...
LL | fn want_y<T:Foo<Y=i32>>(t: &T) { }
| ----- required by this bound in `want_y`
|
= note: expected type `i32`
found associated type `<T as Foo>::Y`
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[E0308]: mismatched types
--> $DIR/trait-with-missing-associated-type-restriction.rs:12:9
|
LL | qux(x.func())
| ^^^^^^^^ expected `usize`, found associated type
|
= note: expected type `usize`
found associated type `<impl Trait as Trait>::A`
help: consider constraining the associated type `<impl Trait as Trait>::A` to `usize`
|
LL | fn foo(x: impl Trait<A = usize>) {
| ^^^^^^^^^^
```
Fix #71035. Related to #70908.
35 files changed, 859 insertions, 136 deletions
diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs index 50e97c8fb7a..a8d6c01785f 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/traits/mod.rs b/src/librustc_middle/traits/mod.rs index d6989fd8e4e..3a05d577bfa 100644 --- a/src/librustc_middle/traits/mod.rs +++ b/src/librustc_middle/traits/mod.rs @@ -194,6 +194,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, impl_item_def_id: DefId, diff --git a/src/librustc_middle/traits/structural_impls.rs b/src/librustc_middle/traits/structural_impls.rs index 69a5213d3e4..668c84ad5e6 100644 --- a/src/librustc_middle/traits/structural_impls.rs +++ b/src/librustc_middle/traits/structural_impls.rs @@ -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, diff --git a/src/librustc_middle/ty/error.rs b/src/librustc_middle/ty/error.rs index 78a94b62d47..4e1a8b0e92f 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::Span; +use rustc_span::symbol::{sym, Symbol}; +use rustc_span::{BytePos, MultiSpan, Span}; use rustc_target::spec::abi; use std::borrow::Cow; @@ -332,11 +334,12 @@ impl<'tcx> TyCtxt<'tcx> { self, db: &mut DiagnosticBuilder<'_>, err: &TypeError<'tcx>, + cause: &ObligationCause<'tcx>, sp: Span, body_owner_def_id: DefId, ) { use self::TypeError::*; - + debug!("note_and_explain_type_err err={:?} cause={:?}", err, cause); match err { Sorts(values) => { let expected_str = values.expected.sort_string(self); @@ -370,7 +373,7 @@ impl<'tcx> TyCtxt<'tcx> { sp, "use a float literal", format!("{}.0", snippet), - Applicability::MachineApplicable, + MachineApplicable, ); } } @@ -401,7 +404,8 @@ impl<'tcx> TyCtxt<'tcx> { (ty::Param(_), ty::Projection(_)) | (ty::Projection(_), ty::Param(_)) => { db.note("you might be missing a type parameter or trait bound"); } - (ty::Param(p), _) | (_, ty::Param(p)) => { + (ty::Param(p), ty::Dynamic(..) | ty::Opaque(..)) + | (ty::Dynamic(..) | ty::Opaque(..), ty::Param(p)) => { let generics = self.generics_of(body_owner_def_id); let p_span = self.def_span(generics.type_param(p, self).def_id); if !sp.contains(p_span) { @@ -441,44 +445,40 @@ impl<T> Trait<T> for X { #traits-as-parameters", ); } - (ty::Projection(_), _) => { - db.note(&format!( - "consider constraining the associated type `{}` to `{}` or calling a \ - method that returns `{}`", - values.expected, values.found, values.expected, - )); - 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() } -} -```", - ); + (ty::Param(p), _) | (_, ty::Param(p)) => { + let generics = self.generics_of(body_owner_def_id); + let p_span = self.def_span(generics.type_param(p, self).def_id); + if !sp.contains(p_span) { + db.span_label(p_span, "this type parameter"); } - 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(_)) => { - db.note(&format!( + (_, ty::Projection(proj_ty)) => { + let msg = format!( "consider constraining the associated type `{}` to `{}`", values.found, values.expected, - )); - db.note( - "for more information, visit \ - https://doc.rust-lang.org/book/ch19-03-advanced-traits.html", ); + if !self.suggest_constraint( + db, + &msg, + body_owner_def_id, + proj_ty, + values.expected, + ) { + db.help(&msg); + db.note( + "for more information, visit \ + https://doc.rust-lang.org/book/ch19-03-advanced-traits.html", + ); + } } _ => {} } @@ -513,4 +513,357 @@ impl Trait for X { _ => {} } } + + fn suggest_constraint( + &self, + db: &mut DiagnosticBuilder<'_>, + msg: &str, + body_owner_def_id: DefId, + proj_ty: &ty::ProjectionTy<'tcx>, + ty: Ty<'tcx>, + ) -> bool { + let assoc = self.associated_item(proj_ty.item_def_id); + let trait_ref = proj_ty.trait_ref(*self); + if let Some(item) = self.hir().get_if_local(body_owner_def_id) { + if let Some(hir_generics) = item.generics() { + // Get the `DefId` for the type parameter corresponding to `A` in `<A as T>::Foo`. + // This will also work for `impl Trait`. + let def_id = if let ty::Param(param_ty) = proj_ty.self_ty().kind { + let generics = self.generics_of(body_owner_def_id); + generics.type_param(¶m_ty, *self).def_id + } else { + return false; + }; + + // First look in the `where` clause, as this might be + // `fn foo<T>(x: T) where T: Trait`. + for predicate in hir_generics.where_clause.predicates { + if let hir::WherePredicate::BoundPredicate(pred) = predicate { + if let hir::TyKind::Path(hir::QPath::Resolved(None, path)) = + pred.bounded_ty.kind + { + if path.res.opt_def_id() == Some(def_id) { + // This predicate is binding type param `A` in `<A as T>::Foo` to + // something, potentially `T`. + } else { + continue; + } + } else { + continue; + } + + if self.constrain_generic_bound_associated_type_structured_suggestion( + db, + &trait_ref, + pred.bounds, + &assoc, + ty, + msg, + ) { + return true; + } + } + } + for param in hir_generics.params { + if self.hir().opt_local_def_id(param.hir_id).map(|id| id.to_def_id()) + == Some(def_id) + { + // This is type param `A` in `<A as T>::Foo`. + return self.constrain_generic_bound_associated_type_structured_suggestion( + db, + &trait_ref, + param.bounds, + &assoc, + ty, + msg, + ); + } + } + } + } + false + } + + /// An associated type was expected and a different type was found. + /// + /// We perform a few different checks to see what we can suggest: + /// + /// - In the current item, look for associated functions that return the expected type and + /// suggest calling them. (Not a structured suggestion.) + /// - If any of the item's generic bounds can be constrained, we suggest constraining the + /// associated type to the found type. + /// - If the associated type has a default type and was expected inside of a `trait`, we + /// mention that this is disallowed. + /// - If all other things fail, and the error is not because of a mismatch between the `trait` + /// and the `impl`, we provide a generic `help` to constrain the assoc type or call an assoc + /// fn that returns the type. + 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 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); + + // We don't want to suggest calling an assoc fn in a scope where that isn't feasible. + let callable_scope = match body_owner { + Some( + hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(..), .. }) + | hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. }) + | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }), + ) => true, + _ => false, + }; + let impl_comparison = matches!( + cause_code, + ObligationCauseCode::CompareImplMethodObligation { .. } + | ObligationCauseCode::CompareImplTypeObligation { .. } + | ObligationCauseCode::CompareImplConstObligation + ); + let assoc = self.associated_item(proj_ty.item_def_id); + 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 { + // If we find a suitable associated function that returns the expected type, we don't + // want the more general suggestion later in this method about "consider constraining + // the associated type or calling a method that returns the associated type". + let point_at_assoc_fn = self.point_at_methods_that_satisfy_associated_type( + db, + assoc.container.id(), + current_method_ident, + proj_ty.item_def_id, + values.expected, + ); + // Possibly suggest constraining the associated type to conform to the + // found type. + if self.suggest_constraint(db, &msg, body_owner_def_id, proj_ty, values.found) + || point_at_assoc_fn + { + return; + } + } + + if let ty::Opaque(def_id, _) = proj_ty.self_ty().kind { + // When the expected `impl Trait` is not defined in the current item, it will come from + // a return type. This can occur when dealing with `TryStream` (#71035). + if self.constrain_associated_type_structured_suggestion( + db, + self.def_span(def_id), + &assoc, + values.found, + &msg, + ) { + return; + } + } + + if self.point_at_associated_type(db, body_owner_def_id, values.found) { + return; + } + + if !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 point_at_methods_that_satisfy_associated_type( + &self, + db: &mut DiagnosticBuilder<'_>, + assoc_container_id: DefId, + current_method_ident: Option<Symbol>, + proj_ty_item_def_id: DefId, + expected: Ty<'tcx>, + ) -> bool { + 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. + // FIXME: consider suggesting the use of associated `const`s. + let methods: Vec<(Span, String)> = items + .items + .iter() + .filter(|(name, item)| { + ty::AssocKind::Fn == 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 = expected + ); + for (sp, label) in methods.into_iter() { + span.push_span_label(sp, label); + } + db.span_help(span, &msg); + return true; + } + false + } + + fn point_at_associated_type( + &self, + db: &mut DiagnosticBuilder<'_>, + body_owner_def_id: DefId, + found: Ty<'tcx>, + ) -> bool { + let hir_id = match body_owner_def_id.as_local().map(|id| self.hir().as_local_hir_id(id)) { + Some(hir_id) => hir_id, + None => return false, + }; + // When `body_owner` is an `impl` or `trait` item, look in its associated types for + // `expected` and point at it. + let parent_id = self.hir().get_parent_item(hir_id); + let item = self.hir().find(parent_id); + debug!("expected_projection parent item {:?}", item); + match item { + Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Trait(.., items), .. })) => { + // FIXME: account for `#![feature(specialization)]` + for item in &items[..] { + match item.kind { + hir::AssocItemKind::Type | hir::AssocItemKind::OpaqueTy => { + if self.type_of(self.hir().local_def_id(item.id.hir_id)) == found { + if let hir::Defaultness::Default { has_value: true } = + item.defaultness + { + db.span_label( + item.span, + "associated type defaults can't be assumed inside the \ + trait defining them", + ); + } else { + db.span_label(item.span, "expected this associated type"); + } + return true; + } + } + _ => {} + } + } + } + Some(hir::Node::Item(hir::Item { + kind: hir::ItemKind::Impl { items, .. }, .. + })) => { + for item in &items[..] { + match item.kind { + hir::AssocItemKind::Type | hir::AssocItemKind::OpaqueTy => { + if self.type_of(self.hir().local_def_id(item.id.hir_id)) == found { + db.span_label(item.span, "expected this associated type"); + return true; + } + } + _ => {} + } + } + } + _ => {} + } + false + } + + /// Given a slice of `hir::GenericBound`s, if any of them corresponds to the `trait_ref` + /// requirement, provide a strucuted suggestion to constrain it to a given type `ty`. + fn constrain_generic_bound_associated_type_structured_suggestion( + &self, + db: &mut DiagnosticBuilder<'_>, + trait_ref: &ty::TraitRef<'tcx>, + bounds: hir::GenericBounds<'_>, + assoc: &ty::AssocItem, + ty: Ty<'tcx>, + msg: &str, + ) -> bool { + // FIXME: we would want to call `resolve_vars_if_possible` on `ty` before suggesting. + bounds.iter().any(|bound| match bound { + hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::None) => { + // Relate the type param against `T` in `<A as T>::Foo`. + ptr.trait_ref.trait_def_id() == Some(trait_ref.def_id) + && self.constrain_associated_type_structured_suggestion( + db, ptr.span, assoc, ty, msg, + ) + } + _ => false, + }) + } + + /// Given a span corresponding to a bound, provide a structured suggestion to set an + /// associated type to a given type `ty`. + fn constrain_associated_type_structured_suggestion( + &self, + db: &mut DiagnosticBuilder<'_>, + span: Span, + assoc: &ty::AssocItem, + ty: Ty<'tcx>, + msg: &str, + ) -> bool { + if let Ok(has_params) = + self.sess.source_map().span_to_snippet(span).map(|snippet| snippet.ends_with('>')) + { + let (span, sugg) = if has_params { + let pos = span.hi() - BytePos(1); + let span = Span::new(pos, pos, span.ctxt()); + (span, format!(", {} = {}", assoc.ident, ty)) + } else { + (span.shrink_to_hi(), format!("<{} = {}>", assoc.ident, ty)) + }; + db.span_suggestion_verbose(span, msg, sugg, MaybeIncorrect); + return true; + } + false + } } diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index 5ec2d68ab2a..ce7b1390d46 100644 --- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -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(_) => (), diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 6e4af6d769a..29cd9681295 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -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 = 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..d8bac07e058 100644 --- a/src/test/ui/associated-const/associated-const-generic-obligations.stderr +++ b/src/test/ui/associated-const/associated-const-generic-obligations.stderr @@ -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 diff --git a/src/test/ui/associated-types/associated-types-eq-3.stderr b/src/test/ui/associated-types/associated-types-eq-3.stderr index a8608abb4d9..dffa4780a09 100644 --- a/src/test/ui/associated-types/associated-types-eq-3.stderr +++ b/src/test/ui/associated-types/associated-types-eq-3.stderr @@ -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 diff --git a/src/test/ui/associated-types/associated-types-issue-20346.stderr b/src/test/ui/associated-types/associated-types-issue-20346.stderr index 8f2b760840c..db35c1af171 100644 --- a/src/test/ui/associated-types/associated-types-issue-20346.stderr +++ b/src/test/ui/associated-types/associated-types-issue-20346.stderr @@ -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 diff --git a/src/test/ui/associated-types/associated-types-multiple-types-one-trait.stderr b/src/test/ui/associated-types/associated-types-multiple-types-one-trait.stderr index 4e481411b4d..b8f20d00ff8 100644 --- a/src/test/ui/associated-types/associated-types-multiple-types-one-trait.stderr +++ b/src/test/ui/associated-types/associated-types-multiple-types-one-trait.stderr @@ -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 @@ -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 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..4014f46285d 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 @@ -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 } } @@ -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 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..493df30a64d 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 @@ -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 diff --git a/src/test/ui/associated-types/defaults-specialization.stderr b/src/test/ui/associated-types/defaults-specialization.stderr index 1dd536ec636..37a4d9b60fd 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 @@ -18,17 +16,21 @@ error[E0053]: method `make` has an incompatible type for trait 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 @@ -36,8 +38,6 @@ 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` - = 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 @@ -49,12 +49,15 @@ 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` | | @@ -62,8 +65,6 @@ 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` - = 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 @@ -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 @@ -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 @@ -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 @@ -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 diff --git a/src/test/ui/associated-types/impl-trait-return-missing-constraint.rs b/src/test/ui/associated-types/impl-trait-return-missing-constraint.rs new file mode 100644 index 00000000000..5f994f26534 --- /dev/null +++ b/src/test/ui/associated-types/impl-trait-return-missing-constraint.rs @@ -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(); +} diff --git a/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr b/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr new file mode 100644 index 00000000000..566e390a31e --- /dev/null +++ b/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr @@ -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`. 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 b1298163aab..6e754621225 100644 --- a/src/test/ui/generic-associated-types/iterable.stderr +++ b/src/test/ui/generic-associated-types/iterable.stderr @@ -6,7 +6,7 @@ LL | type Item<'a> where T: 'a = <std::slice::Iter<'a, T> as Iterator>::Item | = note: expected reference `&T` found associated type `<std::vec::Vec<T> as Iterable>::Item<'_>` - = note: consider constraining the associated type `<std::vec::Vec<T> as Iterable>::Item<'_>` to `&_` + = help: consider constraining the associated type `<std::vec::Vec<T> as Iterable>::Item<'_>` to `&_` = 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>` @@ -17,7 +17,7 @@ LL | type Item<'a> where T: 'a = <std::slice::Iter<'a, T> as Iterator>::Item | = note: expected reference `&T` found associated type `<[T] as Iterable>::Item<'_>` - = note: consider constraining the associated type `<[T] as Iterable>::Item<'_>` to `&_` + = help: consider constraining the associated type `<[T] as Iterable>::Item<'_>` to `&_` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0271]: type mismatch resolving `for<'a> <<std::vec::Vec<T> as Iterable>::Iter<'a> as std::iter::Iterator>::Item == <std::vec::Vec<T> as Iterable>::Item<'a>` @@ -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/hrtb/issue-62203-hrtb-ice.stderr b/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr index 759c7302d13..1c7bfa65d7c 100644 --- a/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr +++ b/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr @@ -6,7 +6,7 @@ LL | let v = Unit2.m( | = note: expected struct `Unit4` found associated type `<_ as Ty<'_>>::V` - = note: consider constraining the associated type `<_ as Ty<'_>>::V` to `Unit4` + = help: consider constraining the associated type `<_ as Ty<'_>>::V` to `Unit4` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0271]: type mismatch resolving `<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:39] as std::ops::FnOnce<((&u8,),)>>::Output == Unit3` diff --git a/src/test/ui/impl-trait/bound-normalization-fail.stderr b/src/test/ui/impl-trait/bound-normalization-fail.stderr index 314ed96fd5e..f5092044627 100644 --- a/src/test/ui/impl-trait/bound-normalization-fail.stderr +++ b/src/test/ui/impl-trait/bound-normalization-fail.stderr @@ -14,9 +14,11 @@ LL | fn foo_fail<T: Trait>() -> impl FooLike<Output=T::Assoc> { | = note: expected type `()` found associated type `<T as impl_trait::Trait>::Assoc` - = note: consider constraining the associated type `<T as impl_trait::Trait>::Assoc` to `()` - = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html = note: the return type of a function must have a statically known size +help: consider constraining the associated type `<T as impl_trait::Trait>::Assoc` to `()` + | +LL | fn foo_fail<T: Trait<Assoc = ()>>() -> impl FooLike<Output=T::Assoc> { + | ^^^^^^^^^^^^ error: `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope --> $DIR/bound-normalization-fail.rs:43:41 @@ -32,9 +34,11 @@ LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output=T::Assoc> { | = note: expected type `()` found associated type `<T as lifetimes::Trait<'static>>::Assoc` - = note: consider constraining the associated type `<T as lifetimes::Trait<'static>>::Assoc` to `()` - = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html = note: the return type of a function must have a statically known size +help: consider constraining the associated type `<T as lifetimes::Trait<'static>>::Assoc` to `()` + | +LL | fn foo2_fail<'a, T: Trait<'a, Assoc = ()>>() -> impl FooLike<Output=T::Assoc> { + | ^^^^^^^^^^^^ error: aborting due to 3 previous errors; 1 warning emitted diff --git a/src/test/ui/impl-trait/equality2.stderr b/src/test/ui/impl-trait/equality2.stderr index b882514f616..2454c218ffc 100644 --- a/src/test/ui/impl-trait/equality2.stderr +++ b/src/test/ui/impl-trait/equality2.stderr @@ -25,7 +25,7 @@ LL | let _: i32 = Leak::leak(hide(0_i32)); | = note: expected type `i32` found associated type `<impl Foo as Leak>::T` - = note: consider constraining the associated type `<impl Foo as Leak>::T` to `i32` + = help: consider constraining the associated type `<impl Foo as Leak>::T` to `i32` = 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/impl-trait/universal-mismatched-type.stderr b/src/test/ui/impl-trait/universal-mismatched-type.stderr index 3ffa2b55712..a12b01b4d2b 100644 --- a/src/test/ui/impl-trait/universal-mismatched-type.stderr +++ b/src/test/ui/impl-trait/universal-mismatched-type.stderr @@ -10,8 +10,6 @@ LL | x | = note: expected struct `std::string::String` found type parameter `impl Debug` - = 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 diff --git a/src/test/ui/issues/issue-13853.stderr b/src/test/ui/issues/issue-13853.stderr index 2f31636f8ad..3f1b955dddb 100644 --- a/src/test/ui/issues/issue-13853.stderr +++ b/src/test/ui/issues/issue-13853.stderr @@ -9,8 +9,6 @@ LL | self.iter() | = note: expected type parameter `I` found struct `std::slice::Iter<'_, N>` - = 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[E0599]: no method named `iter` found for reference `&G` in the current scope --> $DIR/issue-13853.rs:27:23 diff --git a/src/test/ui/issues/issue-20225.stderr b/src/test/ui/issues/issue-20225.stderr index 1c5911e05f7..3bcc50ded84 100644 --- a/src/test/ui/issues/issue-20225.stderr +++ b/src/test/ui/issues/issue-20225.stderr @@ -8,8 +8,6 @@ LL | extern "rust-call" fn call(&self, (_,): (T,)) {} | = note: expected fn pointer `extern "rust-call" fn(&Foo, (&'a T,))` found fn pointer `extern "rust-call" fn(&Foo, (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[E0053]: method `call_mut` has an incompatible type for trait --> $DIR/issue-20225.rs:11:3 @@ -21,8 +19,6 @@ LL | extern "rust-call" fn call_mut(&mut self, (_,): (T,)) {} | = note: expected fn pointer `extern "rust-call" fn(&mut Foo, (&'a T,))` found fn pointer `extern "rust-call" fn(&mut Foo, (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[E0053]: method `call_once` has an incompatible type for trait --> $DIR/issue-20225.rs:18:3 @@ -35,8 +31,6 @@ LL | extern "rust-call" fn call_once(self, (_,): (T,)) {} | = note: expected fn pointer `extern "rust-call" fn(Foo, (&'a T,))` found fn pointer `extern "rust-call" fn(Foo, (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 3 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/issues/issue-69306.stderr b/src/test/ui/issues/issue-69306.stderr index a2a42739ca8..58e85ec700d 100644 --- a/src/test/ui/issues/issue-69306.stderr +++ b/src/test/ui/issues/issue-69306.stderr @@ -8,8 +8,6 @@ LL | const C: S0<u8> = Self(0); | = note: expected type parameter `T` found type `{integer}` - = 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[E0308]: mismatched types --> $DIR/issue-69306.rs:5:23 @@ -21,8 +19,6 @@ LL | const C: S0<u8> = Self(0); | = note: expected struct `S0<u8>` found struct `S0<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[E0308]: mismatched types --> $DIR/issue-69306.rs:10:14 @@ -35,8 +31,6 @@ LL | Self(0); | = note: expected type parameter `T` found type `{integer}` - = 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[E0308]: mismatched types --> $DIR/issue-69306.rs:27:14 @@ -49,8 +43,6 @@ LL | Self(0); | = note: expected type parameter `T` found type `{integer}` - = 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[E0308]: mismatched types --> $DIR/issue-69306.rs:33:32 @@ -62,8 +54,6 @@ LL | const C: S1<u8, u8> = Self(0, 1); | = note: expected type parameter `T` found type `{integer}` - = 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[E0308]: mismatched types --> $DIR/issue-69306.rs:33:27 @@ -75,8 +65,6 @@ LL | const C: S1<u8, u8> = Self(0, 1); | = note: expected struct `S1<u8, _>` found struct `S1<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[E0308]: mismatched types --> $DIR/issue-69306.rs:41:14 diff --git a/src/test/ui/mismatched_types/issue-35030.stderr b/src/test/ui/mismatched_types/issue-35030.stderr index 6fb04ef5c99..9f4e4398984 100644 --- a/src/test/ui/mismatched_types/issue-35030.stderr +++ b/src/test/ui/mismatched_types/issue-35030.stderr @@ -9,8 +9,6 @@ LL | Some(true) | = note: expected type parameter `bool` (type parameter `bool`) found type `bool` (`bool`) - = 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 diff --git a/src/test/ui/specialization/specialization-default-projection.stderr b/src/test/ui/specialization/specialization-default-projection.stderr index d03aec7ab30..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 @@ -25,7 +25,7 @@ LL | generic::<()>() | = note: expected unit type `()` found associated type `<() as Foo>::Assoc` - = note: consider constraining the associated type `<() as Foo>::Assoc` to `()` + = help: consider constraining the associated type `<() as Foo>::Assoc` to `()` = 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/specialization/specialization-default-types.stderr b/src/test/ui/specialization/specialization-default-types.stderr index 257c114252c..7233387eba1 100644 --- a/src/test/ui/specialization/specialization-default-types.stderr +++ b/src/test/ui/specialization/specialization-default-types.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/specialization-default-types.rs:15:9 | +LL | default type Output = Box<T>; + | ----------------------------- expected this associated type LL | default fn generate(self) -> Self::Output { | ------------ expected `<T as Example>::Output` because of return type LL | Box::new(self) @@ -8,8 +10,6 @@ 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` - = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0308]: mismatched types --> $DIR/specialization-default-types.rs:25:5 @@ -21,7 +21,7 @@ LL | Example::generate(t) | = note: expected struct `std::boxed::Box<T>` found associated type `<T as Example>::Output` - = note: consider constraining the associated type `<T as Example>::Output` to `std::boxed::Box<T>` + = help: consider constraining the associated type `<T as Example>::Output` to `std::boxed::Box<T>` = 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/suggestions/expected-boxed-future-isnt-pinned.stderr b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr index ff256eb3094..52e13dbc2dd 100644 --- a/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr +++ b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr @@ -12,8 +12,6 @@ LL | x | = note: expected struct `std::pin::Pin<std::boxed::Box<(dyn std::future::Future<Output = i32> + std::marker::Send + 'static)>>` found type parameter `F` - = 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[E0308]: mismatched types --> $DIR/expected-boxed-future-isnt-pinned.rs:18:5 @@ -40,8 +38,6 @@ LL | Pin::new(x) | = note: expected struct `std::boxed::Box<dyn std::future::Future<Output = i32> + std::marker::Send>` found type parameter `F` - = 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 = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html error[E0277]: `dyn std::future::Future<Output = i32> + std::marker::Send` cannot be unpinned diff --git a/src/test/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.fixed b/src/test/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.fixed new file mode 100644 index 00000000000..8ef7e34ab30 --- /dev/null +++ b/src/test/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.fixed @@ -0,0 +1,43 @@ +// run-rustfix +#![allow(unused)] // for the fixed file + +trait Trait<T = Self> { + type A; + + fn func(&self) -> Self::A; +} + +struct S<T>(T); +impl<K> S<K> { + fn foo<'a, T: Trait + 'a>(&self, _: impl Trait, x: impl Trait<A = usize>, _: T) { + qux(x.func()) //~ ERROR mismatched types + } + + fn ban<T>(x: T) where T: Trait<A = usize> { + qux(x.func()) //~ ERROR mismatched types + } +} + +fn foo<'a, T: Trait + 'a>(_: impl Trait, x: impl Trait<A = usize>, _: T) { + qux(x.func()) //~ ERROR mismatched types +} + +fn bar<T: Trait<A = usize>>(x: T) { + qux(x.func()) //~ ERROR mismatched types +} + +fn foo2(x: impl Trait<i32, A = usize>) { + qux(x.func()) //~ ERROR mismatched types +} + +fn bar2<T: Trait<i32, A = usize>>(x: T) { + qux(x.func()) //~ ERROR mismatched types +} + +fn ban<T>(x: T) where T: Trait<A = usize> { + qux(x.func()) //~ ERROR mismatched types +} + +fn qux(_: usize) {} + +fn main() {} diff --git a/src/test/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.rs b/src/test/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.rs new file mode 100644 index 00000000000..7bd38d0d45d --- /dev/null +++ b/src/test/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.rs @@ -0,0 +1,43 @@ +// run-rustfix +#![allow(unused)] // for the fixed file + +trait Trait<T = Self> { + type A; + + fn func(&self) -> Self::A; +} + +struct S<T>(T); +impl<K> S<K> { + fn foo<'a, T: Trait + 'a>(&self, _: impl Trait, x: impl Trait, _: T) { + qux(x.func()) //~ ERROR mismatched types + } + + fn ban<T>(x: T) where T: Trait { + qux(x.func()) //~ ERROR mismatched types + } +} + +fn foo<'a, T: Trait + 'a>(_: impl Trait, x: impl Trait, _: T) { + qux(x.func()) //~ ERROR mismatched types +} + +fn bar<T: Trait>(x: T) { + qux(x.func()) //~ ERROR mismatched types +} + +fn foo2(x: impl Trait<i32>) { + qux(x.func()) //~ ERROR mismatched types +} + +fn bar2<T: Trait<i32>>(x: T) { + qux(x.func()) //~ ERROR mismatched types +} + +fn ban<T>(x: T) where T: Trait { + qux(x.func()) //~ ERROR mismatched types +} + +fn qux(_: usize) {} + +fn main() {} diff --git a/src/test/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.stderr b/src/test/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.stderr new file mode 100644 index 00000000000..f785f7b84a7 --- /dev/null +++ b/src/test/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.stderr @@ -0,0 +1,94 @@ +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:13:13 + | +LL | qux(x.func()) + | ^^^^^^^^ expected `usize`, found associated type + | + = note: expected type `usize` + found associated type `<impl Trait as Trait>::A` +help: consider constraining the associated type `<impl Trait as Trait>::A` to `usize` + | +LL | fn foo<'a, T: Trait + 'a>(&self, _: impl Trait, x: impl Trait<A = usize>, _: T) { + | ^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:17:13 + | +LL | qux(x.func()) + | ^^^^^^^^ expected `usize`, found associated type + | + = note: expected type `usize` + found associated type `<T as Trait>::A` +help: consider constraining the associated type `<T as Trait>::A` to `usize` + | +LL | fn ban<T>(x: T) where T: Trait<A = usize> { + | ^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:22:9 + | +LL | qux(x.func()) + | ^^^^^^^^ expected `usize`, found associated type + | + = note: expected type `usize` + found associated type `<impl Trait as Trait>::A` +help: consider constraining the associated type `<impl Trait as Trait>::A` to `usize` + | +LL | fn foo<'a, T: Trait + 'a>(_: impl Trait, x: impl Trait<A = usize>, _: T) { + | ^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:26:9 + | +LL | qux(x.func()) + | ^^^^^^^^ expected `usize`, found associated type + | + = note: expected type `usize` + found associated type `<T as Trait>::A` +help: consider constraining the associated type `<T as Trait>::A` to `usize` + | +LL | fn bar<T: Trait<A = usize>>(x: T) { + | ^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:30:9 + | +LL | qux(x.func()) + | ^^^^^^^^ expected `usize`, found associated type + | + = note: expected type `usize` + found associated type `<impl Trait<i32> as Trait<i32>>::A` +help: consider constraining the associated type `<impl Trait<i32> as Trait<i32>>::A` to `usize` + | +LL | fn foo2(x: impl Trait<i32, A = usize>) { + | ^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:34:9 + | +LL | qux(x.func()) + | ^^^^^^^^ expected `usize`, found associated type + | + = note: expected type `usize` + found associated type `<T as Trait<i32>>::A` +help: consider constraining the associated type `<T as Trait<i32>>::A` to `usize` + | +LL | fn bar2<T: Trait<i32, A = usize>>(x: T) { + | ^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:38:9 + | +LL | qux(x.func()) + | ^^^^^^^^ expected `usize`, found associated type + | + = note: expected type `usize` + found associated type `<T as Trait>::A` +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 + +For more information about this error, try `rustc --explain E0308`. 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 new file mode 100644 index 00000000000..7465049787f --- /dev/null +++ b/src/test/ui/suggestions/trait-with-missing-associated-type-restriction.rs @@ -0,0 +1,43 @@ +// These are all the possible variations of this error I could think of for. +// `trait-with-missing-associated-type-restriction-fixable.rs` contains the subset of these that +// can be fixed with `rustfix`. + +trait Trait<T = Self> { + type A; + + fn func(&self) -> Self::A; + fn funk(&self, _: Self::A); +} + +fn foo(_: impl Trait, x: impl Trait) { + qux(x.func()) //~ ERROR mismatched types +} + +fn bar<T: Trait>(x: T) { + qux(x.func()) //~ ERROR mismatched types +} + +fn foo2(x: impl Trait<i32>) { + qux(x.func()) //~ ERROR mismatched types +} + +fn bar2<T: Trait<i32>>(x: T) { + x.funk(3); //~ ERROR mismatched types + qux(x.func()) //~ ERROR mismatched types +} + +fn baz<D: std::fmt::Debug, T: Trait<A = D>>(x: T) { + qux(x.func()) //~ ERROR mismatched types +} + +fn bat(x: &mut dyn Trait<(), A = ()>) { + qux(x.func()) //~ ERROR mismatched types +} + +fn ban<T>(x: T) where T: Trait { + qux(x.func()) //~ ERROR mismatched types +} + +fn qux(_: usize) {} + +fn main() {} 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 new file mode 100644 index 00000000000..5ae1d45c6b7 --- /dev/null +++ b/src/test/ui/suggestions/trait-with-missing-associated-type-restriction.stderr @@ -0,0 +1,103 @@ +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction.rs:13:9 + | +LL | qux(x.func()) + | ^^^^^^^^ expected `usize`, found associated type + | + = note: expected type `usize` + found associated type `<impl Trait as Trait>::A` +help: consider constraining the associated type `<impl Trait as Trait>::A` to `usize` + | +LL | fn foo(_: impl Trait, x: impl Trait<A = usize>) { + | ^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction.rs:17:9 + | +LL | qux(x.func()) + | ^^^^^^^^ expected `usize`, found associated type + | + = note: expected type `usize` + found associated type `<T as Trait>::A` +help: consider constraining the associated type `<T as Trait>::A` to `usize` + | +LL | fn bar<T: Trait<A = usize>>(x: T) { + | ^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction.rs:21:9 + | +LL | qux(x.func()) + | ^^^^^^^^ expected `usize`, found associated type + | + = note: expected type `usize` + found associated type `<impl Trait<i32> as Trait<i32>>::A` +help: consider constraining the associated type `<impl Trait<i32> as Trait<i32>>::A` to `usize` + | +LL | fn foo2(x: impl Trait<i32, A = usize>) { + | ^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $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 + | + = note: expected type `usize` + found associated type `<T as Trait<i32>>::A` +help: consider constraining the associated type `<T as Trait<i32>>::A` to `usize` + | +LL | fn bar2<T: Trait<i32, A = usize>>(x: T) { + | ^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $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 +LL | qux(x.func()) + | ^^^^^^^^ expected `usize`, found type parameter `D` + | + = note: expected type `usize` + found type parameter `D` + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction.rs:34:9 + | +LL | qux(x.func()) + | ^^^^^^^^ expected `usize`, found `()` + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction.rs:38:9 + | +LL | qux(x.func()) + | ^^^^^^^^ expected `usize`, found associated type + | + = note: expected type `usize` + found associated type `<T as Trait>::A` +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 8 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.stderr b/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.stderr index 412b4dbda4f..caea791e653 100644 --- a/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.stderr +++ b/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.stderr @@ -9,8 +9,6 @@ LL | Self::TSVariant(()); | = note: expected type parameter `T` found unit type `()` - = 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[E0109]: type arguments are not allowed for this type --> $DIR/enum-variant-generic-args.rs:15:27 @@ -35,8 +33,6 @@ LL | Self::<()>::TSVariant(()); | = note: expected type parameter `T` found unit type `()` - = 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[E0109]: type arguments are not allowed for this type --> $DIR/enum-variant-generic-args.rs:20:16 @@ -61,8 +57,6 @@ LL | Self::SVariant { v: () }; | = note: expected type parameter `T` found unit type `()` - = 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[E0109]: type arguments are not allowed for this type --> $DIR/enum-variant-generic-args.rs:28:26 @@ -81,8 +75,6 @@ LL | Self::SVariant::<()> { v: () }; | = note: expected type parameter `T` found unit type `()` - = 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[E0109]: type arguments are not allowed for this type --> $DIR/enum-variant-generic-args.rs:31:16 @@ -101,8 +93,6 @@ LL | Self::<()>::SVariant { v: () }; | = note: expected type parameter `T` found unit type `()` - = 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[E0109]: type arguments are not allowed for this type --> $DIR/enum-variant-generic-args.rs:34:16 @@ -127,8 +117,6 @@ LL | Self::<()>::SVariant::<()> { v: () }; | = note: expected type parameter `T` found unit type `()` - = 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[E0109]: type arguments are not allowed for this type --> $DIR/enum-variant-generic-args.rs:41:26 |
