From 9b861ace46c4791150d23082016ec21bf944f86c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Mon, 5 Jan 2026 09:50:38 +0100 Subject: [PATCH] Generalize diag for missing assoc types to account for assoc consts --- .../src/hir_ty_lowering/dyn_trait.rs | 2 +- .../src/hir_ty_lowering/errors.rs | 230 ++++++++++-------- compiler/rustc_middle/src/ty/assoc.rs | 2 +- .../overlaping-bound-suggestion.stderr | 2 +- .../associated-types-incomplete-object.stderr | 6 +- .../ui/associated-types/issue-23595-1.stderr | 2 +- .../dyn-compat-unspecified-assoc-consts.rs | 6 +- ...dyn-compat-unspecified-assoc-consts.stderr | 12 +- .../assoc_type_bounds.stderr | 4 +- .../assoc_type_bounds2.stderr | 4 +- .../assoc_type_bounds_sized_others.stderr | 4 +- .../require-assoc-for-all-super-substs.stderr | 2 +- tests/ui/error-codes/E0191.stderr | 2 +- tests/ui/error-codes/E0220.stderr | 2 +- ...dynless-turbofish-e0191-issue-91997.stderr | 2 +- .../impl-trait/associated-type-cycle.stderr | 2 +- tests/ui/issues/issue-19482.stderr | 2 +- tests/ui/issues/issue-28344.stderr | 4 +- .../ui/suggestions/trait-hidden-method.stderr | 2 +- tests/ui/traits/alias/object-fail.stderr | 2 +- ...dyn-trait-wo-assoc-type-issue-21950.stderr | 2 +- .../with-self-in-projection-output-bad.stderr | 4 +- ...sociated-type-in-trait-object-22434.stderr | 2 +- 23 files changed, 170 insertions(+), 132 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs index 695a0793ccd1..d700bd544b0b 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs @@ -324,7 +324,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .collect(); // If there are any associated items whose value wasn't provided, bail out with an error. - if let Err(guar) = self.check_for_required_assoc_tys( + if let Err(guar) = self.check_for_required_assoc_items( principal_trait.as_ref().map_or(smallvec![], |(_, spans)| spans.clone()), missing_assoc_items, potential_assoc_items, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 92b77a2042b1..f467780143ef 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -909,43 +909,49 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { err.emit() } - /// When there are any missing associated types, emit an E0191 error and attempt to supply a - /// reasonable suggestion on how to write it. For the case of multiple associated types in the - /// same trait bound have the same name (as they come from different supertraits), we instead - /// emit a generic note suggesting using a `where` clause to constraint instead. - pub(crate) fn check_for_required_assoc_tys( + /// If there are any missing associated items, emit an error instructing the user to provide + /// them unless that's impossible due to shadowing. Moreover, if any corresponding trait refs + /// are dyn incompatible due to associated items we emit an dyn incompatibility error instead. + pub(crate) fn check_for_required_assoc_items( &self, spans: SmallVec<[Span; 1]>, - missing_assoc_types: FxIndexSet<(DefId, ty::PolyTraitRef<'tcx>)>, - potential_assoc_types: Vec, + missing_assoc_items: FxIndexSet<(DefId, ty::PolyTraitRef<'tcx>)>, + potential_assoc_items: Vec, trait_bounds: &[hir::PolyTraitRef<'_>], ) -> Result<(), ErrorGuaranteed> { - if missing_assoc_types.is_empty() { + if missing_assoc_items.is_empty() { return Ok(()); } + let tcx = self.tcx(); let principal_span = *spans.first().unwrap(); - let tcx = self.tcx(); // FIXME: This logic needs some more care w.r.t handling of conflicts - let missing_assoc_types: Vec<_> = missing_assoc_types + let missing_assoc_items: Vec<_> = missing_assoc_items .into_iter() .map(|(def_id, trait_ref)| (tcx.associated_item(def_id), trait_ref)) .collect(); - let mut names: FxIndexMap<_, Vec> = Default::default(); + let mut names: FxIndexMap<_, Vec<_>> = Default::default(); let mut names_len = 0; + let mut descr = None; - // Account for things like `dyn Foo + 'a`, like in tests `issue-22434.rs` and - // `issue-22560.rs`. - let mut dyn_compatibility_violations = Ok(()); - for (assoc_item, trait_ref) in &missing_assoc_types { - names.entry(trait_ref).or_default().push(assoc_item.name()); - names_len += 1; + enum Descr { + Item, + Tag(ty::AssocTag), + } + for &(assoc_item, trait_ref) in &missing_assoc_items { + // We don't want to suggest specifying associated items if there's something wrong with + // any of them that renders the trait dyn incompatible; providing them certainly won't + // fix the issue and we could also risk suggesting invalid code. + // + // Note that this check is only truly necessary in item ctxts where we merely perform + // *minimal* dyn compatibility checks. In fn ctxts we would've already bailed out with + // an error by this point if the trait was dyn incompatible. let violations = - dyn_compatibility_violations_for_assoc_item(tcx, trait_ref.def_id(), *assoc_item); + dyn_compatibility_violations_for_assoc_item(tcx, trait_ref.def_id(), assoc_item); if !violations.is_empty() { - dyn_compatibility_violations = Err(report_dyn_incompatibility( + return Err(report_dyn_incompatibility( tcx, principal_span, None, @@ -954,15 +960,20 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) .emit()); } - } - if let Err(guar) = dyn_compatibility_violations { - return Err(guar); + names.entry(trait_ref).or_default().push(assoc_item.name()); + names_len += 1; + + descr = match descr { + None => Some(Descr::Tag(assoc_item.as_tag())), + Some(Descr::Tag(tag)) if tag != assoc_item.as_tag() => Some(Descr::Item), + _ => continue, + }; } // related to issue #91997, turbofishes added only when in an expr or pat let mut in_expr_or_pat = false; - if let ([], [bound]) = (&potential_assoc_types[..], &trait_bounds) { + if let ([], [bound]) = (&potential_assoc_items[..], &trait_bounds) { let grandparent = tcx.parent_hir_node(tcx.parent_hir_id(bound.trait_ref.hir_ref_id)); in_expr_or_pat = match grandparent { hir::Node::Expr(_) | hir::Node::Pat(_) => true, @@ -970,37 +981,41 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }; } - // We get all the associated items that _are_ set, - // so that we can check if any of their names match one of the ones we are missing. - // This would mean that they are shadowing the associated type we are missing, - // and we can then use their span to indicate this to the user. - let bound_names = trait_bounds - .iter() - .filter_map(|poly_trait_ref| { - let path = poly_trait_ref.trait_ref.path.segments.last()?; - let args = path.args?; + // We get all the associated items that *are* set, so that we can check if any of + // their names match one of the ones we are missing. + // This would mean that they are shadowing the associated item we are missing, and + // we can then use their span to indicate this to the user. + // + // FIXME: This does not account for trait aliases. I think we should just make + // `lower_trait_object_ty` compute the list of all specified items or give us the + // necessary ingredients if it's too expensive to compute in the happy path. + let bound_names: UnordMap<_, _> = + trait_bounds + .iter() + .filter_map(|poly_trait_ref| { + let path = poly_trait_ref.trait_ref.path.segments.last()?; + let args = path.args?; + let Res::Def(DefKind::Trait, trait_def_id) = path.res else { return None }; - Some(args.constraints.iter().filter_map(|constraint| { - let ident = constraint.ident; + Some(args.constraints.iter().filter_map(move |constraint| { + let hir::AssocItemConstraintKind::Equality { term } = constraint.kind + else { + return None; + }; + let tag = match term { + hir::Term::Ty(_) => ty::AssocTag::Type, + hir::Term::Const(_) => ty::AssocTag::Const, + }; + let assoc_item = tcx + .associated_items(trait_def_id) + .find_by_ident_and_kind(tcx, constraint.ident, tag, trait_def_id)?; + Some(((constraint.ident.name, tag), assoc_item.def_id)) + })) + }) + .flatten() + .collect(); - let Res::Def(DefKind::Trait, trait_def) = path.res else { - return None; - }; - - let assoc_item = tcx.associated_items(trait_def).find_by_ident_and_kind( - tcx, - ident, - ty::AssocTag::Type, - trait_def, - ); - - Some((ident.name, assoc_item?)) - })) - }) - .flatten() - .collect::>(); - - let mut names = names + let mut names: Vec<_> = names .into_iter() .map(|(trait_, mut assocs)| { assocs.sort(); @@ -1010,66 +1025,71 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { listify(&assocs[..], |a| format!("`{a}`")).unwrap_or_default() ) }) - .collect::>(); + .collect(); names.sort(); let names = names.join(", "); + let descr = match descr.unwrap() { + // FIXME(fmease): Create `ty::AssocTag::descr`. + Descr::Tag(ty::AssocTag::Type) => "associated type", + Descr::Tag(ty::AssocTag::Const) => "associated constant", + _ => "associated item", + }; let mut err = struct_span_code_err!( self.dcx(), principal_span, E0191, - "the value of the associated type{} {} must be specified", - pluralize!(names_len), - names, + "the value of the {descr}{s} {names} must be specified", + s = pluralize!(names_len), ); let mut suggestions = vec![]; - let mut types_count = 0; + let mut items_count = 0; let mut where_constraints = vec![]; let mut already_has_generics_args_suggestion = false; let mut names: UnordMap<_, usize> = Default::default(); - for (item, _) in &missing_assoc_types { - types_count += 1; - *names.entry(item.name()).or_insert(0) += 1; + for (item, _) in &missing_assoc_items { + items_count += 1; + *names.entry((item.name(), item.as_tag())).or_insert(0) += 1; } let mut dupes = false; let mut shadows = false; - for (item, trait_ref) in &missing_assoc_types { + for (item, trait_ref) in &missing_assoc_items { let name = item.name(); - let prefix = if names[&name] > 1 { - let trait_def_id = trait_ref.def_id(); + let key = (name, item.as_tag()); + + if names[&key] > 1 { dupes = true; - format!("{}::", tcx.def_path_str(trait_def_id)) - } else if bound_names.get(&name).is_some_and(|x| *x != item) { - let trait_def_id = trait_ref.def_id(); + } else if bound_names.get(&key).is_some_and(|&def_id| def_id != item.def_id) { shadows = true; - format!("{}::", tcx.def_path_str(trait_def_id)) + } + + let prefix = if dupes || shadows { + format!("{}::", tcx.def_path_str(trait_ref.def_id())) } else { String::new() }; - let mut is_shadowed = false; - if let Some(assoc_item) = bound_names.get(&name) - && *assoc_item != item + if let Some(&def_id) = bound_names.get(&key) + && def_id != item.def_id { is_shadowed = true; - let rename_message = - if assoc_item.def_id.is_local() { ", consider renaming it" } else { "" }; + let rename_message = if def_id.is_local() { ", consider renaming it" } else { "" }; err.span_label( - tcx.def_span(assoc_item.def_id), - format!("`{}{}` shadowed here{}", prefix, name, rename_message), + tcx.def_span(def_id), + format!("`{prefix}{name}` shadowed here{rename_message}"), ); } let rename_message = if is_shadowed { ", consider renaming it" } else { "" }; if let Some(sp) = tcx.hir_span_if_local(item.def_id) { - err.span_label(sp, format!("`{}{}` defined here{}", prefix, name, rename_message)); + err.span_label(sp, format!("`{prefix}{name}` defined here{rename_message}")); } } - if potential_assoc_types.len() == missing_assoc_types.len() { + if potential_assoc_items.len() == missing_assoc_items.len() { // When the amount of missing associated types equals the number of // extra type arguments present. A suggesting to replace the generic args with // associated types is already emitted. @@ -1077,30 +1097,48 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } else if let (Ok(snippet), false, false) = (tcx.sess.source_map().span_to_snippet(principal_span), dupes, shadows) { - let types: Vec<_> = missing_assoc_types + let bindings: Vec<_> = missing_assoc_items .iter() - .map(|(item, _)| format!("{} = Type", item.name())) + .map(|(item, _)| { + format!( + "{} = /* {} */", + item.name(), + match item.kind { + ty::AssocKind::Const { .. } => "CONST", + ty::AssocKind::Type { .. } => "Type", + ty::AssocKind::Fn { .. } => unreachable!(), + } + ) + }) .collect(); + // FIXME(fmease): Does not account for `dyn Trait<>` (suggs `dyn Trait<, X = Y>`). let code = if let Some(snippet) = snippet.strip_suffix('>') { - // The user wrote `Trait<'a>` or similar and we don't have a type we can - // suggest, but at least we can clue them to the correct syntax - // `Trait<'a, Item = Type>` while accounting for the `<'a>` in the - // suggestion. - format!("{}, {}>", snippet, types.join(", ")) + // The user wrote `Trait<'a>` or similar and we don't have a term we can suggest, + // but at least we can clue them to the correct syntax `Trait<'a, Item = /* ... */>` + // while accounting for the `<'a>` in the suggestion. + format!("{}, {}>", snippet, bindings.join(", ")) } else if in_expr_or_pat { - // The user wrote `Iterator`, so we don't have a type we can suggest, but at - // least we can clue them to the correct syntax `Iterator::`. - format!("{}::<{}>", snippet, types.join(", ")) + // The user wrote `Trait`, so we don't have a term we can suggest, but at least we + // can clue them to the correct syntax `Trait::`. + format!("{}::<{}>", snippet, bindings.join(", ")) } else { - // The user wrote `Iterator`, so we don't have a type we can suggest, but at - // least we can clue them to the correct syntax `Iterator`. - format!("{}<{}>", snippet, types.join(", ")) + // The user wrote `Trait`, so we don't have a term we can suggest, but at least we + // can clue them to the correct syntax `Trait`. + format!("{}<{}>", snippet, bindings.join(", ")) }; suggestions.push((principal_span, code)); } else if dupes { where_constraints.push(principal_span); } + // FIXME: This note doesn't make sense, get rid of this outright. + // I don't see how adding a type param (to the trait?) would help. + // If the user can modify the trait, they should just rename one of the assoc tys. + // What does it mean with the rest of the message? + // Does it suggest adding equality predicates (unimplemented) to the trait object + // type? (pseudo) "dyn B + ::X = T + ::X = U"? + // Instead, maybe mention shadowing if applicable (yes, even when no "relevant" + // bindings were provided). let where_msg = "consider introducing a new type parameter, adding `where` constraints \ using the fully-qualified path to the associated types"; if !where_constraints.is_empty() && suggestions.is_empty() { @@ -1112,12 +1150,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { if suggestions.len() != 1 || already_has_generics_args_suggestion { // We don't need this label if there's an inline suggestion, show otherwise. let mut names: FxIndexMap<_, usize> = FxIndexMap::default(); - for (item, _) in &missing_assoc_types { - types_count += 1; + for (item, _) in &missing_assoc_items { + items_count += 1; *names.entry(item.name()).or_insert(0) += 1; } let mut label = vec![]; - for (item, trait_ref) in &missing_assoc_types { + for (item, trait_ref) in &missing_assoc_items { let name = item.name(); let postfix = if names[&name] > 1 { format!(" (from trait `{}`)", trait_ref.print_trait_sugared()) @@ -1130,9 +1168,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { err.span_label( principal_span, format!( - "associated type{} {} must be specified", - pluralize!(label.len()), - label.join(", "), + "{descr}{s} {names} must be specified", + s = pluralize!(label.len()), + names = label.join(", "), ), ); } @@ -1153,7 +1191,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let overlaps = suggestions.windows(2).any(|pair| pair[0].0.overlaps(pair[1].0)); if !suggestions.is_empty() && !overlaps { err.multipart_suggestion( - format!("specify the associated type{}", pluralize!(types_count)), + format!("specify the {descr}{s}", s = pluralize!(items_count)), suggestions, Applicability::HasPlaceholders, ); diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs index 0957d103d997..4a54a3109462 100644 --- a/compiler/rustc_middle/src/ty/assoc.rs +++ b/compiler/rustc_middle/src/ty/assoc.rs @@ -223,7 +223,7 @@ impl std::fmt::Display for AssocKind { } // Like `AssocKind`, but just the tag, no fields. Used in various kinds of matching. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum AssocTag { Const, Fn, diff --git a/tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr b/tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr index ad97df377b75..54bcef455746 100644 --- a/tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr +++ b/tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr @@ -2,7 +2,7 @@ error[E0191]: the value of the associated types `Item` and `IntoIter` in `IntoIt --> $DIR/overlaping-bound-suggestion.rs:7:13 | LL | inner: >::IntoIterator as Item>::Core, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: specify the associated types: `IntoIterator, Item = Type, IntoIter = Type>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: specify the associated types: `IntoIterator, Item = /* Type */, IntoIter = /* Type */>` error: aborting due to 1 previous error diff --git a/tests/ui/associated-types/associated-types-incomplete-object.stderr b/tests/ui/associated-types/associated-types-incomplete-object.stderr index 0c9761afeb51..52aa6adc4695 100644 --- a/tests/ui/associated-types/associated-types-incomplete-object.stderr +++ b/tests/ui/associated-types/associated-types-incomplete-object.stderr @@ -5,7 +5,7 @@ LL | type B; | ------ `B` defined here ... LL | let b = &42isize as &dyn Foo; - | ^^^^^^^^^^^^ help: specify the associated type: `Foo` + | ^^^^^^^^^^^^ help: specify the associated type: `Foo` error[E0191]: the value of the associated type `A` in `Foo` must be specified --> $DIR/associated-types-incomplete-object.rs:26:30 @@ -14,7 +14,7 @@ LL | type A; | ------ `A` defined here ... LL | let c = &42isize as &dyn Foo; - | ^^^^^^^^^^^ help: specify the associated type: `Foo` + | ^^^^^^^^^^^ help: specify the associated type: `Foo` error[E0191]: the value of the associated types `A` and `B` in `Foo` must be specified --> $DIR/associated-types-incomplete-object.rs:29:30 @@ -25,7 +25,7 @@ LL | type B; | ------ `B` defined here ... LL | let d = &42isize as &dyn Foo; - | ^^^ help: specify the associated types: `Foo` + | ^^^ help: specify the associated types: `Foo` error: aborting due to 3 previous errors diff --git a/tests/ui/associated-types/issue-23595-1.stderr b/tests/ui/associated-types/issue-23595-1.stderr index 694b68ef0901..8083355deb76 100644 --- a/tests/ui/associated-types/issue-23595-1.stderr +++ b/tests/ui/associated-types/issue-23595-1.stderr @@ -6,7 +6,7 @@ LL | type Value; LL | type ChildKey; | ------------- `ChildKey` defined here LL | type Children = dyn Index; - | ------------- `Children` defined here ^^^^^^^^^ help: specify the associated types: `Hierarchy` + | ------------- `Children` defined here ^^^^^^^^^ help: specify the associated types: `Hierarchy` error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-unspecified-assoc-consts.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-unspecified-assoc-consts.rs index 532c853c32b8..3525cbceb87b 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-unspecified-assoc-consts.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-unspecified-assoc-consts.rs @@ -13,13 +13,13 @@ trait Trait { // fn ctxt / body fn main() { let _: dyn Trait; - //~^ ERROR the value of the associated type `K` in `Trait` must be specified + //~^ ERROR the value of the associated constant `K` in `Trait` must be specified } // item ctxt / signature / non-body struct Store(dyn Trait); -//~^ ERROR the value of the associated type `K` in `Trait` must be specified +//~^ ERROR the value of the associated constant `K` in `Trait` must be specified // item ctxt & no wfcking (eager ty alias) type DynTrait = dyn Trait; -//~^ ERROR the value of the associated type `K` in `Trait` must be specified +//~^ ERROR the value of the associated constant `K` in `Trait` must be specified diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-unspecified-assoc-consts.stderr b/tests/ui/const-generics/associated-const-bindings/dyn-compat-unspecified-assoc-consts.stderr index 37a4fdd38d3b..68658a5711cb 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-unspecified-assoc-consts.stderr +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-unspecified-assoc-consts.stderr @@ -1,29 +1,29 @@ -error[E0191]: the value of the associated type `K` in `Trait` must be specified +error[E0191]: the value of the associated constant `K` in `Trait` must be specified --> $DIR/dyn-compat-unspecified-assoc-consts.rs:20:18 | LL | const K: usize; | -------------- `K` defined here ... LL | struct Store(dyn Trait); - | ^^^^^ help: specify the associated type: `Trait` + | ^^^^^ help: specify the associated constant: `Trait` -error[E0191]: the value of the associated type `K` in `Trait` must be specified +error[E0191]: the value of the associated constant `K` in `Trait` must be specified --> $DIR/dyn-compat-unspecified-assoc-consts.rs:24:21 | LL | const K: usize; | -------------- `K` defined here ... LL | type DynTrait = dyn Trait; - | ^^^^^ help: specify the associated type: `Trait` + | ^^^^^ help: specify the associated constant: `Trait` -error[E0191]: the value of the associated type `K` in `Trait` must be specified +error[E0191]: the value of the associated constant `K` in `Trait` must be specified --> $DIR/dyn-compat-unspecified-assoc-consts.rs:15:16 | LL | const K: usize; | -------------- `K` defined here ... LL | let _: dyn Trait; - | ^^^^^ help: specify the associated type: `Trait` + | ^^^^^ help: specify the associated constant: `Trait` error: aborting due to 3 previous errors diff --git a/tests/ui/dyn-compatibility/assoc_type_bounds.stderr b/tests/ui/dyn-compatibility/assoc_type_bounds.stderr index 21ba90301173..717d8949e2d8 100644 --- a/tests/ui/dyn-compatibility/assoc_type_bounds.stderr +++ b/tests/ui/dyn-compatibility/assoc_type_bounds.stderr @@ -5,7 +5,7 @@ LL | type Bar | -------- `Bar` defined here ... LL | fn foo(_: &dyn Foo<()>) {} - | ^^^^^^^ help: specify the associated type: `Foo<(), Bar = Type>` + | ^^^^^^^ help: specify the associated type: `Foo<(), Bar = /* Type */>` error[E0191]: the value of the associated type `Bar` in `Foo` must be specified --> $DIR/assoc_type_bounds.rs:11:16 @@ -14,7 +14,7 @@ LL | type Bar | -------- `Bar` defined here ... LL | fn bar(_: &dyn Foo) {} - | ^^^^^^^^ help: specify the associated type: `Foo` + | ^^^^^^^^ help: specify the associated type: `Foo` error: aborting due to 2 previous errors diff --git a/tests/ui/dyn-compatibility/assoc_type_bounds2.stderr b/tests/ui/dyn-compatibility/assoc_type_bounds2.stderr index 5c4163b19693..9ddded9addfa 100644 --- a/tests/ui/dyn-compatibility/assoc_type_bounds2.stderr +++ b/tests/ui/dyn-compatibility/assoc_type_bounds2.stderr @@ -5,7 +5,7 @@ LL | type Bar | -------- `Bar` defined here ... LL | fn foo(_: &dyn Foo<()>) {} - | ^^^^^^^ help: specify the associated type: `Foo<(), Bar = Type>` + | ^^^^^^^ help: specify the associated type: `Foo<(), Bar = /* Type */>` error[E0191]: the value of the associated type `Bar` in `Foo` must be specified --> $DIR/assoc_type_bounds2.rs:11:16 @@ -14,7 +14,7 @@ LL | type Bar | -------- `Bar` defined here ... LL | fn bar(_: &dyn Foo) {} - | ^^^^^^^^ help: specify the associated type: `Foo` + | ^^^^^^^^ help: specify the associated type: `Foo` error: aborting due to 2 previous errors diff --git a/tests/ui/dyn-compatibility/assoc_type_bounds_sized_others.stderr b/tests/ui/dyn-compatibility/assoc_type_bounds_sized_others.stderr index 5438faaaf054..8f75f19f571a 100644 --- a/tests/ui/dyn-compatibility/assoc_type_bounds_sized_others.stderr +++ b/tests/ui/dyn-compatibility/assoc_type_bounds_sized_others.stderr @@ -5,7 +5,7 @@ LL | type Bop; | -------- `Bop` defined here ... LL | fn foo(_: &dyn Foo) {} - | ^^^ help: specify the associated type: `Foo` + | ^^^ help: specify the associated type: `Foo` error[E0191]: the value of the associated type `Bop` in `Bar` must be specified --> $DIR/assoc_type_bounds_sized_others.rs:22:16 @@ -14,7 +14,7 @@ LL | type Bop; | -------- `Bop` defined here ... LL | fn bar(_: &dyn Bar) {} - | ^^^ help: specify the associated type: `Bar` + | ^^^ help: specify the associated type: `Bar` error: aborting due to 2 previous errors diff --git a/tests/ui/dyn-compatibility/require-assoc-for-all-super-substs.stderr b/tests/ui/dyn-compatibility/require-assoc-for-all-super-substs.stderr index 3d89b52d522d..f39be936f417 100644 --- a/tests/ui/dyn-compatibility/require-assoc-for-all-super-substs.stderr +++ b/tests/ui/dyn-compatibility/require-assoc-for-all-super-substs.stderr @@ -5,7 +5,7 @@ LL | type Assoc: Default; | ------------------- `Assoc` defined here ... LL | let q: as Sup>::Assoc = Default::default(); - | ^^^^^^^^^^^^^ help: specify the associated type: `Dyn` + | ^^^^^^^^^^^^^ help: specify the associated type: `Dyn` error: aborting due to 1 previous error diff --git a/tests/ui/error-codes/E0191.stderr b/tests/ui/error-codes/E0191.stderr index 63974fd6cbbb..6fbb20839777 100644 --- a/tests/ui/error-codes/E0191.stderr +++ b/tests/ui/error-codes/E0191.stderr @@ -5,7 +5,7 @@ LL | type Bar; | -------- `Bar` defined here ... LL | type Foo = dyn Trait; - | ^^^^^ help: specify the associated type: `Trait` + | ^^^^^ help: specify the associated type: `Trait` error: aborting due to 1 previous error diff --git a/tests/ui/error-codes/E0220.stderr b/tests/ui/error-codes/E0220.stderr index 0e0b5c7084cc..48197c9a8ccf 100644 --- a/tests/ui/error-codes/E0220.stderr +++ b/tests/ui/error-codes/E0220.stderr @@ -11,7 +11,7 @@ LL | type Bar; | -------- `Bar` defined here ... LL | type Foo = dyn Trait; - | ^^^^^^^^^^^^ help: specify the associated type: `Trait` + | ^^^^^^^^^^^^ help: specify the associated type: `Trait` error: aborting due to 2 previous errors diff --git a/tests/ui/errors/dynless-turbofish-e0191-issue-91997.stderr b/tests/ui/errors/dynless-turbofish-e0191-issue-91997.stderr index c1584e66e330..cae414bf1225 100644 --- a/tests/ui/errors/dynless-turbofish-e0191-issue-91997.stderr +++ b/tests/ui/errors/dynless-turbofish-e0191-issue-91997.stderr @@ -16,7 +16,7 @@ error[E0191]: the value of the associated type `Item` in `Iterator` must be spec --> $DIR/dynless-turbofish-e0191-issue-91997.rs:5:13 | LL | let _ = MyIterator::next; - | ^^^^^^^^^^ help: specify the associated type: `MyIterator::` + | ^^^^^^^^^^ help: specify the associated type: `MyIterator::` error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/impl-trait/associated-type-cycle.stderr b/tests/ui/impl-trait/associated-type-cycle.stderr index 7eef8d1e3389..438a5a92ffc2 100644 --- a/tests/ui/impl-trait/associated-type-cycle.stderr +++ b/tests/ui/impl-trait/associated-type-cycle.stderr @@ -5,7 +5,7 @@ LL | type Bar; | -------- `Bar` defined here ... LL | impl Foo for Box { - | ^^^ help: specify the associated type: `Foo` + | ^^^ help: specify the associated type: `Foo` error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-19482.stderr b/tests/ui/issues/issue-19482.stderr index 903a9f98c758..7683e16610e6 100644 --- a/tests/ui/issues/issue-19482.stderr +++ b/tests/ui/issues/issue-19482.stderr @@ -5,7 +5,7 @@ LL | type A; | ------ `A` defined here ... LL | fn bar(x: &dyn Foo) {} - | ^^^ help: specify the associated type: `Foo` + | ^^^ help: specify the associated type: `Foo` error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-28344.stderr b/tests/ui/issues/issue-28344.stderr index c85424e22794..9940f005b7f8 100644 --- a/tests/ui/issues/issue-28344.stderr +++ b/tests/ui/issues/issue-28344.stderr @@ -16,7 +16,7 @@ error[E0191]: the value of the associated type `Output` in `BitXor<_>` must be s --> $DIR/issue-28344.rs:5:17 | LL | let x: u8 = BitXor::bitor(0 as u8, 0 as u8); - | ^^^^^^ help: specify the associated type: `BitXor::` + | ^^^^^^ help: specify the associated type: `BitXor::` warning: trait objects without an explicit `dyn` are deprecated --> $DIR/issue-28344.rs:10:13 @@ -35,7 +35,7 @@ error[E0191]: the value of the associated type `Output` in `BitXor<_>` must be s --> $DIR/issue-28344.rs:10:13 | LL | let g = BitXor::bitor; - | ^^^^^^ help: specify the associated type: `BitXor::` + | ^^^^^^ help: specify the associated type: `BitXor::` error: aborting due to 2 previous errors; 2 warnings emitted diff --git a/tests/ui/suggestions/trait-hidden-method.stderr b/tests/ui/suggestions/trait-hidden-method.stderr index 87753e578462..c764034d8466 100644 --- a/tests/ui/suggestions/trait-hidden-method.stderr +++ b/tests/ui/suggestions/trait-hidden-method.stderr @@ -2,7 +2,7 @@ error[E0191]: the value of the associated type `Item` in `Iterator` must be spec --> $DIR/trait-hidden-method.rs:4:33 | LL | Box::new(1..=10) as Box - | ^^^^^^^^ help: specify the associated type: `Iterator` + | ^^^^^^^^ help: specify the associated type: `Iterator` error: aborting due to 1 previous error diff --git a/tests/ui/traits/alias/object-fail.stderr b/tests/ui/traits/alias/object-fail.stderr index d60d88434077..088af686258a 100644 --- a/tests/ui/traits/alias/object-fail.stderr +++ b/tests/ui/traits/alias/object-fail.stderr @@ -19,7 +19,7 @@ error[E0191]: the value of the associated type `Item` in `Iterator` must be spec --> $DIR/object-fail.rs:9:17 | LL | let _: &dyn IteratorAlias = &vec![123].into_iter(); - | ^^^^^^^^^^^^^ help: specify the associated type: `IteratorAlias` + | ^^^^^^^^^^^^^ help: specify the associated type: `IteratorAlias` error: aborting due to 2 previous errors diff --git a/tests/ui/traits/cast-as-dyn-trait-wo-assoc-type-issue-21950.stderr b/tests/ui/traits/cast-as-dyn-trait-wo-assoc-type-issue-21950.stderr index 5f4974e6f237..6a7d3c850c92 100644 --- a/tests/ui/traits/cast-as-dyn-trait-wo-assoc-type-issue-21950.stderr +++ b/tests/ui/traits/cast-as-dyn-trait-wo-assoc-type-issue-21950.stderr @@ -5,7 +5,7 @@ LL | type Output; | ----------- `Output` defined here ... LL | let x = &10 as &dyn Add; - | ^^^ help: specify the associated type: `Add` + | ^^^ help: specify the associated type: `Add` error: aborting due to 1 previous error diff --git a/tests/ui/traits/object/with-self-in-projection-output-bad.stderr b/tests/ui/traits/object/with-self-in-projection-output-bad.stderr index c9b36e8d29de..d0cc7f7fc924 100644 --- a/tests/ui/traits/object/with-self-in-projection-output-bad.stderr +++ b/tests/ui/traits/object/with-self-in-projection-output-bad.stderr @@ -5,7 +5,7 @@ LL | type Output; | ----------- `Output` defined here ... LL | let _x: Box> = Box::new(2u32); - | ^^^^^^^^^^^^^^^^^^ help: specify the associated type: `Helper` + | ^^^^^^^^^^^^^^^^^^ help: specify the associated type: `Helper` error[E0191]: the value of the associated type `Output` in `Base` must be specified --> $DIR/with-self-in-projection-output-bad.rs:48:21 @@ -14,7 +14,7 @@ LL | type Output; | ----------- `Output` defined here ... LL | let _y: Box> = Box::new(2u32); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: specify the associated type: `NormalizableHelper` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: specify the associated type: `NormalizableHelper` error: aborting due to 2 previous errors diff --git a/tests/ui/type-alias/missing-associated-type-in-trait-object-22434.stderr b/tests/ui/type-alias/missing-associated-type-in-trait-object-22434.stderr index 73afefa5a1fd..c198b83e9688 100644 --- a/tests/ui/type-alias/missing-associated-type-in-trait-object-22434.stderr +++ b/tests/ui/type-alias/missing-associated-type-in-trait-object-22434.stderr @@ -5,7 +5,7 @@ LL | type A; | ------ `A` defined here ... LL | type I<'a> = &'a (dyn Foo + 'a); - | ^^^ help: specify the associated type: `Foo` + | ^^^ help: specify the associated type: `Foo` error: aborting due to 1 previous error