From 5469673b02303d9f988366d1a74a42330f87ba05 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 23 Nov 2024 18:10:47 +0000 Subject: [PATCH 1/5] Dont use span as key when collecting missing associated types from dyn --- .../src/hir_ty_lowering/dyn_compatibility.rs | 41 ++- .../src/hir_ty_lowering/errors.rs | 242 +++++++++--------- 2 files changed, 134 insertions(+), 149 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs index 321a8aba7f727..470037d31e69f 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs @@ -1,9 +1,8 @@ -use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; +use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::struct_span_code_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::DefId; use rustc_lint_defs::builtin::UNUSED_ASSOCIATED_TYPE_BOUNDS; use rustc_middle::span_bug; use rustc_middle::ty::fold::BottomUpFolder; @@ -11,7 +10,7 @@ use rustc_middle::ty::{ self, DynKind, ExistentialPredicateStableCmpExt as _, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, Upcast, }; -use rustc_span::{ErrorGuaranteed, Span}; +use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span}; use rustc_trait_selection::error_reporting::traits::report_dyn_incompatibility; use rustc_trait_selection::traits::{self, hir_ty_lowering_dyn_compatibility_violations}; use rustc_type_ir::elaborate::ClauseWithSupertraitSpan; @@ -128,8 +127,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } - let mut associated_types: FxIndexMap> = FxIndexMap::default(); + let mut needed_associated_types = FxIndexSet::default(); + let principal_span = regular_traits.first().map_or(DUMMY_SP, |info| info.bottom().1); let regular_traits_refs_spans = trait_bounds .into_iter() .filter(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id())); @@ -146,11 +146,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { match bound_predicate.skip_binder() { ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => { let pred = bound_predicate.rebind(pred); - associated_types.entry(original_span).or_default().extend( + needed_associated_types.extend( tcx.associated_items(pred.def_id()) .in_definition_order() .filter(|item| item.kind == ty::AssocKind::Type) .filter(|item| !item.is_impl_trait_in_trait()) + // If the associated type has a `where Self: Sized` bound, + // we do not need to constrain the associated type. + .filter(|item| !tcx.generics_require_sized_self(item.def_id)) .map(|item| item.def_id), ); } @@ -201,26 +204,22 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // So every `Projection` clause is an `Assoc = Foo` bound. `associated_types` contains all associated // types's `DefId`, so the following loop removes all the `DefIds` of the associated types that have a // corresponding `Projection` clause - for def_ids in associated_types.values_mut() { - for (projection_bound, span) in &projection_bounds { - let def_id = projection_bound.projection_def_id(); - def_ids.swap_remove(&def_id); - if tcx.generics_require_sized_self(def_id) { - tcx.emit_node_span_lint( - UNUSED_ASSOCIATED_TYPE_BOUNDS, - hir_id, - *span, - crate::errors::UnusedAssociatedTypeBounds { span: *span }, - ); - } + for (projection_bound, span) in &projection_bounds { + let def_id = projection_bound.projection_def_id(); + needed_associated_types.swap_remove(&def_id); + if tcx.generics_require_sized_self(def_id) { + tcx.emit_node_span_lint( + UNUSED_ASSOCIATED_TYPE_BOUNDS, + hir_id, + *span, + crate::errors::UnusedAssociatedTypeBounds { span: *span }, + ); } - // If the associated type has a `where Self: Sized` bound, we do not need to constrain the associated - // type in the `dyn Trait`. - def_ids.retain(|def_id| !tcx.generics_require_sized_self(def_id)); } if let Err(guar) = self.check_for_required_assoc_tys( - associated_types, + principal_span, + needed_associated_types, potential_assoc_types, hir_trait_bounds, ) { 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 ff449a858d674..4e7747173701d 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -716,51 +716,40 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// emit a generic note suggesting using a `where` clause to constraint instead. pub(crate) fn check_for_required_assoc_tys( &self, - associated_types: FxIndexMap>, + principal_span: Span, + missing_assoc_types: FxIndexSet, potential_assoc_types: Vec, trait_bounds: &[hir::PolyTraitRef<'_>], ) -> Result<(), ErrorGuaranteed> { - if associated_types.values().all(|v| v.is_empty()) { + if missing_assoc_types.is_empty() { return Ok(()); } let tcx = self.tcx(); - // FIXME: Marked `mut` so that we can replace the spans further below with a more - // appropriate one, but this should be handled earlier in the span assignment. - let associated_types: FxIndexMap> = associated_types - .into_iter() - .map(|(span, def_ids)| { - (span, def_ids.into_iter().map(|did| tcx.associated_item(did)).collect()) - }) - .collect(); + let missing_assoc_types: Vec<_> = + missing_assoc_types.into_iter().map(|def_id| tcx.associated_item(def_id)).collect(); let mut names: FxIndexMap> = Default::default(); let mut names_len = 0; // Account for things like `dyn Foo + 'a`, like in tests `issue-22434.rs` and // `issue-22560.rs`. - let mut trait_bound_spans: Vec = vec![]; let mut dyn_compatibility_violations = Ok(()); - for (span, items) in &associated_types { - if !items.is_empty() { - trait_bound_spans.push(*span); - } - for assoc_item in items { - let trait_def_id = assoc_item.container_id(tcx); - names.entry(tcx.def_path_str(trait_def_id)).or_default().push(assoc_item.name); - names_len += 1; - - let violations = - dyn_compatibility_violations_for_assoc_item(tcx, trait_def_id, *assoc_item); - if !violations.is_empty() { - dyn_compatibility_violations = Err(report_dyn_incompatibility( - tcx, - *span, - None, - trait_def_id, - &violations, - ) - .emit()); - } + for assoc_item in &missing_assoc_types { + let trait_def_id = assoc_item.container_id(tcx); + names.entry(tcx.def_path_str(trait_def_id)).or_default().push(assoc_item.name); + names_len += 1; + + let violations = + dyn_compatibility_violations_for_assoc_item(tcx, trait_def_id, *assoc_item); + if !violations.is_empty() { + dyn_compatibility_violations = Err(report_dyn_incompatibility( + tcx, + principal_span, + None, + trait_def_id, + &violations, + ) + .emit()); } } @@ -821,10 +810,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { names.sort(); let names = names.join(", "); - trait_bound_spans.sort(); let mut err = struct_span_code_err!( self.dcx(), - trait_bound_spans, + principal_span, E0191, "the value of the associated type{} {} must be specified", pluralize!(names_len), @@ -834,81 +822,81 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let mut types_count = 0; let mut where_constraints = vec![]; let mut already_has_generics_args_suggestion = false; - for (span, assoc_items) in &associated_types { - let mut names: UnordMap<_, usize> = Default::default(); - for item in assoc_items { - types_count += 1; - *names.entry(item.name).or_insert(0) += 1; - } - let mut dupes = false; - let mut shadows = false; - for item in assoc_items { - let prefix = if names[&item.name] > 1 { - let trait_def_id = item.container_id(tcx); - dupes = true; - format!("{}::", tcx.def_path_str(trait_def_id)) - } else if bound_names.get(&item.name).is_some_and(|x| x != &item) { - let trait_def_id = item.container_id(tcx); - shadows = true; - format!("{}::", tcx.def_path_str(trait_def_id)) - } else { - String::new() - }; - let mut is_shadowed = false; - - if let Some(assoc_item) = bound_names.get(&item.name) - && assoc_item != &item - { - is_shadowed = true; + let mut names: UnordMap<_, usize> = Default::default(); + for item in &missing_assoc_types { + types_count += 1; + *names.entry(item.name).or_insert(0) += 1; + } + let mut dupes = false; + let mut shadows = false; + for item in &missing_assoc_types { + let prefix = if names[&item.name] > 1 { + let trait_def_id = item.container_id(tcx); + dupes = true; + format!("{}::", tcx.def_path_str(trait_def_id)) + } else if bound_names.get(&item.name).is_some_and(|x| *x != item) { + let trait_def_id = item.container_id(tcx); + shadows = true; + format!("{}::", tcx.def_path_str(trait_def_id)) + } else { + String::new() + }; - let rename_message = - if assoc_item.def_id.is_local() { ", consider renaming it" } else { "" }; - err.span_label( - tcx.def_span(assoc_item.def_id), - format!("`{}{}` shadowed here{}", prefix, item.name, rename_message), - ); - } + let mut is_shadowed = false; - let rename_message = if is_shadowed { ", consider renaming it" } else { "" }; + if let Some(assoc_item) = bound_names.get(&item.name) + && *assoc_item != item + { + is_shadowed = true; - if let Some(sp) = tcx.hir().span_if_local(item.def_id) { - err.span_label( - sp, - format!("`{}{}` defined here{}", prefix, item.name, rename_message), - ); - } + let rename_message = + if assoc_item.def_id.is_local() { ", consider renaming it" } else { "" }; + err.span_label( + tcx.def_span(assoc_item.def_id), + format!("`{}{}` shadowed here{}", prefix, item.name, rename_message), + ); } - if potential_assoc_types.len() == 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. - already_has_generics_args_suggestion = true; - } else if let (Ok(snippet), false, false) = - (tcx.sess.source_map().span_to_snippet(*span), dupes, shadows) - { - let types: Vec<_> = - assoc_items.iter().map(|item| format!("{} = Type", item.name)).collect(); - let code = if snippet.ends_with('>') { - // 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[..snippet.len() - 1], types.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(", ")) - } 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(", ")) - }; - suggestions.push((*span, code)); - } else if dupes { - where_constraints.push(*span); + + 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, item.name, rename_message), + ); } } + if potential_assoc_types.len() == missing_assoc_types.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. + already_has_generics_args_suggestion = true; + } else if let (Ok(snippet), false, false) = + (tcx.sess.source_map().span_to_snippet(principal_span), dupes, shadows) + { + let types: Vec<_> = + missing_assoc_types.iter().map(|item| format!("{} = Type", item.name)).collect(); + let code = if snippet.ends_with('>') { + // 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[..snippet.len() - 1], types.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(", ")) + } 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(", ")) + }; + suggestions.push((principal_span, code)); + } else if dupes { + where_constraints.push(principal_span); + } + 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() { @@ -919,32 +907,30 @@ 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. - for (span, assoc_items) in &associated_types { - let mut names: FxIndexMap<_, usize> = FxIndexMap::default(); - for item in assoc_items { - types_count += 1; - *names.entry(item.name).or_insert(0) += 1; - } - let mut label = vec![]; - for item in assoc_items { - let postfix = if names[&item.name] > 1 { - let trait_def_id = item.container_id(tcx); - format!(" (from trait `{}`)", tcx.def_path_str(trait_def_id)) - } else { - String::new() - }; - label.push(format!("`{}`{}", item.name, postfix)); - } - if !label.is_empty() { - err.span_label( - *span, - format!( - "associated type{} {} must be specified", - pluralize!(label.len()), - label.join(", "), - ), - ); - } + let mut names: FxIndexMap<_, usize> = FxIndexMap::default(); + for item in &missing_assoc_types { + types_count += 1; + *names.entry(item.name).or_insert(0) += 1; + } + let mut label = vec![]; + for item in &missing_assoc_types { + let postfix = if names[&item.name] > 1 { + let trait_def_id = item.container_id(tcx); + format!(" (from trait `{}`)", tcx.def_path_str(trait_def_id)) + } else { + String::new() + }; + label.push(format!("`{}`{}", item.name, postfix)); + } + if !label.is_empty() { + err.span_label( + principal_span, + format!( + "associated type{} {} must be specified", + pluralize!(label.len()), + label.join(", "), + ), + ); } } suggestions.sort_by_key(|&(span, _)| span); From 8e324b41459c2fbe6c29e43e3b37d3eab435e3fe Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 4 Dec 2024 02:04:26 +0000 Subject: [PATCH 2/5] Rework trait expansion to happen once explicitly --- .../src/hir_ty_lowering/dyn_compatibility.rs | 191 +++++----- .../src/hir_ty_lowering/errors.rs | 48 +-- compiler/rustc_hir_typeck/src/method/probe.rs | 11 +- .../src/error_reporting/traits/mod.rs | 3 +- .../rustc_trait_selection/src/traits/mod.rs | 6 +- .../rustc_trait_selection/src/traits/util.rs | 209 ++++------- compiler/rustc_type_ir/src/visit.rs | 8 + .../const_param_ty_dyn_compatibility.stderr | 8 +- .../mentions-Self-in-super-predicates.stderr | 12 +- .../supertrait-mentions-Self.stderr | 4 +- tests/ui/error-codes/E0225.stderr | 4 +- tests/ui/issues/issue-26056.stderr | 4 +- .../ui/traits/alias/generic-default-in-dyn.rs | 4 +- .../alias/generic-default-in-dyn.stderr | 30 +- tests/ui/traits/alias/no-duplicates.stderr | 234 ++++++------- tests/ui/traits/alias/no-extra-traits.stderr | 328 +++++++++--------- tests/ui/traits/alias/object-fail.rs | 2 +- tests/ui/traits/alias/object-fail.stderr | 13 +- .../alias/self-in-const-generics.stderr | 14 +- tests/ui/traits/alias/self-in-generics.stderr | 16 +- tests/ui/traits/bad-sized.stderr | 8 +- tests/ui/traits/issue-28576.stderr | 5 +- tests/ui/traits/issue-38404.stderr | 12 +- ...onicalize-fresh-infer-vars-issue-103626.rs | 1 - ...alize-fresh-infer-vars-issue-103626.stderr | 10 +- 25 files changed, 551 insertions(+), 634 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs index 470037d31e69f..2c642e1e5a869 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs @@ -4,13 +4,12 @@ use rustc_errors::struct_span_code_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_lint_defs::builtin::UNUSED_ASSOCIATED_TYPE_BOUNDS; -use rustc_middle::span_bug; use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::{ self, DynKind, ExistentialPredicateStableCmpExt as _, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, Upcast, }; -use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span}; +use rustc_span::{ErrorGuaranteed, Span}; use rustc_trait_selection::error_reporting::traits::report_dyn_incompatibility; use rustc_trait_selection::traits::{self, hir_ty_lowering_dyn_compatibility_violations}; use rustc_type_ir::elaborate::ClauseWithSupertraitSpan; @@ -30,16 +29,16 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { &self, span: Span, hir_id: hir::HirId, - hir_trait_bounds: &[hir::PolyTraitRef<'tcx>], + hir_bounds: &[hir::PolyTraitRef<'tcx>], lifetime: &hir::Lifetime, representation: DynKind, ) -> Ty<'tcx> { let tcx = self.tcx(); + let dummy_self = self.tcx().types.trait_object_dummy_self; - let mut bounds = Bounds::default(); + let mut user_written_bounds = Bounds::default(); let mut potential_assoc_types = Vec::new(); - let dummy_self = self.tcx().types.trait_object_dummy_self; - for trait_bound in hir_trait_bounds.iter().rev() { + for trait_bound in hir_bounds.iter() { if let hir::BoundPolarity::Maybe(_) = trait_bound.modifiers.polarity { continue; } @@ -53,92 +52,67 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { hir::BoundConstness::Never, hir::BoundPolarity::Positive, dummy_self, - &mut bounds, + &mut user_written_bounds, PredicateFilter::SelfOnly, ) { potential_assoc_types.extend(cur_potential_assoc_types); } } - let mut trait_bounds = vec![]; - let mut projection_bounds = vec![]; - for (pred, span) in bounds.clauses() { - let bound_pred = pred.kind(); - match bound_pred.skip_binder() { - ty::ClauseKind::Trait(trait_pred) => { - assert_eq!(trait_pred.polarity, ty::PredicatePolarity::Positive); - trait_bounds.push((bound_pred.rebind(trait_pred.trait_ref), span)); - } - ty::ClauseKind::Projection(proj) => { - projection_bounds.push((bound_pred.rebind(proj), span)); - } - ty::ClauseKind::TypeOutlives(_) => { - // Do nothing, we deal with regions separately - } - ty::ClauseKind::RegionOutlives(_) - | ty::ClauseKind::ConstArgHasType(..) - | ty::ClauseKind::WellFormed(_) - | ty::ClauseKind::ConstEvaluatable(_) - | ty::ClauseKind::HostEffect(..) => { - span_bug!(span, "did not expect {pred} clause in object bounds"); + // Check that there are no gross dyn-compatibility violations; + // most importantly, that the supertraits don't contain `Self`, + // to avoid ICEs. + for (clause, span) in user_written_bounds.clauses() { + if let Some(trait_pred) = clause.as_trait_clause() { + let violations = + hir_ty_lowering_dyn_compatibility_violations(tcx, trait_pred.def_id()); + if !violations.is_empty() { + let reported = report_dyn_incompatibility( + tcx, + span, + Some(hir_id), + trait_pred.def_id(), + &violations, + ) + .emit(); + return Ty::new_error(tcx, reported); } } } - // Expand trait aliases recursively and check that only one regular (non-auto) trait - // is used and no 'maybe' bounds are used. - let expanded_traits = - traits::expand_trait_aliases(tcx, trait_bounds.iter().map(|&(a, b)| (a, b))); - - let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = - expanded_traits.partition(|i| tcx.trait_is_auto(i.trait_ref().def_id())); + let (trait_bounds, mut projection_bounds) = + traits::expand_trait_aliases(tcx, user_written_bounds.clauses()); + let (regular_traits, mut auto_traits): (Vec<_>, Vec<_>) = trait_bounds + .into_iter() + .partition(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id())); + // We don't support empty trait objects. + if regular_traits.is_empty() && auto_traits.is_empty() { + let guar = + self.report_trait_object_with_no_traits_error(span, user_written_bounds.clauses()); + return Ty::new_error(tcx, guar); + } // We don't support >1 principal if regular_traits.len() > 1 { let guar = self.report_trait_object_addition_traits_error(®ular_traits); return Ty::new_error(tcx, guar); } - // We don't support empty trait objects. - if regular_traits.is_empty() && auto_traits.is_empty() { - let guar = self.report_trait_object_with_no_traits_error(span, &trait_bounds); - return Ty::new_error(tcx, guar); - } // Don't create a dyn trait if we have errors in the principal. - if let Err(guar) = trait_bounds.error_reported() { + if let Err(guar) = regular_traits.error_reported() { return Ty::new_error(tcx, guar); } - // Check that there are no gross dyn-compatibility violations; - // most importantly, that the supertraits don't contain `Self`, - // to avoid ICEs. - for item in ®ular_traits { - let violations = - hir_ty_lowering_dyn_compatibility_violations(tcx, item.trait_ref().def_id()); - if !violations.is_empty() { - let reported = report_dyn_incompatibility( - tcx, - span, - Some(hir_id), - item.trait_ref().def_id(), - &violations, - ) - .emit(); - return Ty::new_error(tcx, reported); - } - } + let principal_trait = regular_traits.into_iter().next(); let mut needed_associated_types = FxIndexSet::default(); - - let principal_span = regular_traits.first().map_or(DUMMY_SP, |info| info.bottom().1); - let regular_traits_refs_spans = trait_bounds - .into_iter() - .filter(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id())); - - for (base_trait_ref, original_span) in regular_traits_refs_spans { - let base_pred: ty::Predicate<'tcx> = base_trait_ref.upcast(tcx); + if let Some((principal_trait, spans)) = &principal_trait { + let pred: ty::Predicate<'tcx> = (*principal_trait).upcast(tcx); for ClauseWithSupertraitSpan { pred, supertrait_span } in - traits::elaborate(tcx, [ClauseWithSupertraitSpan::new(base_pred, original_span)]) - .filter_only_self() + traits::elaborate(tcx, [ClauseWithSupertraitSpan::new( + pred, + *spans.last().unwrap(), + )]) + .filter_only_self() { debug!("observing object predicate `{pred:?}`"); @@ -186,12 +160,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // the discussion in #56288 for alternatives. if !references_self { // Include projections defined on supertraits. - projection_bounds.push((pred, original_span)); + projection_bounds.push((pred, supertrait_span)); } self.check_elaborated_projection_mentions_input_lifetimes( pred, - original_span, + *spans.first().unwrap(), supertrait_span, ); } @@ -204,24 +178,24 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // So every `Projection` clause is an `Assoc = Foo` bound. `associated_types` contains all associated // types's `DefId`, so the following loop removes all the `DefIds` of the associated types that have a // corresponding `Projection` clause - for (projection_bound, span) in &projection_bounds { + for &(projection_bound, span) in &projection_bounds { let def_id = projection_bound.projection_def_id(); needed_associated_types.swap_remove(&def_id); if tcx.generics_require_sized_self(def_id) { tcx.emit_node_span_lint( UNUSED_ASSOCIATED_TYPE_BOUNDS, hir_id, - *span, - crate::errors::UnusedAssociatedTypeBounds { span: *span }, + span, + crate::errors::UnusedAssociatedTypeBounds { span }, ); } } if let Err(guar) = self.check_for_required_assoc_tys( - principal_span, + principal_trait.as_ref().map_or(smallvec![], |(_, spans)| spans.clone()), needed_associated_types, potential_assoc_types, - hir_trait_bounds, + hir_bounds, ) { return Ty::new_error(tcx, guar); } @@ -231,15 +205,20 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // We remove duplicates by inserting into a `FxHashSet` to avoid re-ordering // the bounds let mut duplicates = FxHashSet::default(); - auto_traits.retain(|i| duplicates.insert(i.trait_ref().def_id())); - debug!(?regular_traits); + auto_traits.retain(|(trait_pred, _)| duplicates.insert(trait_pred.def_id())); + + debug!(?principal_trait); debug!(?auto_traits); // Erase the `dummy_self` (`trait_object_dummy_self`) used above. - let existential_trait_refs = regular_traits.iter().map(|i| { - i.trait_ref().map_bound(|trait_ref: ty::TraitRef<'tcx>| { + let principal_trait_ref = principal_trait.map(|(trait_pred, spans)| { + trait_pred.map_bound(|trait_pred| { + let trait_ref = trait_pred.trait_ref; + assert_eq!(trait_pred.polarity, ty::PredicatePolarity::Positive); assert_eq!(trait_ref.self_ty(), dummy_self); + let span = *spans.first().unwrap(); + // Verify that `dummy_self` did not leak inside default type parameters. This // could not be done at path creation, since we need to see through trait aliases. let mut missing_type_params = vec![]; @@ -249,7 +228,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .args .iter() .enumerate() - .skip(1) // Remove `Self` for `ExistentialPredicate`. + // Skip `Self` + .skip(1) .map(|(index, arg)| { if arg == dummy_self.into() { let param = &generics.own_params[index]; @@ -268,8 +248,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }) .collect(); - let span = i.bottom().1; - let empty_generic_args = hir_trait_bounds.iter().any(|hir_bound| { + let empty_generic_args = hir_bounds.iter().any(|hir_bound| { hir_bound.trait_ref.path.res == Res::Def(DefKind::Trait, trait_ref.def_id) && hir_bound.span.contains(span) }); @@ -280,26 +259,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { empty_generic_args, ); - if references_self { - let def_id = i.bottom().0.def_id(); - struct_span_code_err!( - self.dcx(), - i.bottom().1, - E0038, - "the {} `{}` cannot be made into an object", - tcx.def_descr(def_id), - tcx.item_name(def_id), - ) - .with_note( - rustc_middle::traits::DynCompatibilityViolation::SupertraitSelf( - smallvec![], - ) - .error_msg(), - ) - .emit(); - } - - ty::ExistentialTraitRef::new(tcx, trait_ref.def_id, args) + ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef::new( + tcx, + trait_ref.def_id, + args, + )) }) }); @@ -322,21 +286,24 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { b.projection_term = replace_dummy_self_with_error(tcx, b.projection_term, guar); } - ty::ExistentialProjection::erase_self_ty(tcx, b) + ty::ExistentialPredicate::Projection(ty::ExistentialProjection::erase_self_ty( + tcx, b, + )) }) }); - let regular_trait_predicates = existential_trait_refs - .map(|trait_ref| trait_ref.map_bound(ty::ExistentialPredicate::Trait)); - let auto_trait_predicates = auto_traits.into_iter().map(|trait_ref| { - ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(trait_ref.trait_ref().def_id())) + let auto_trait_predicates = auto_traits.into_iter().map(|(trait_pred, _)| { + assert_eq!(trait_pred.polarity(), ty::PredicatePolarity::Positive); + assert_eq!(trait_pred.self_ty().skip_binder(), dummy_self); + + ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(trait_pred.def_id())) }); + // N.b. principal, projections, auto traits // FIXME: This is actually wrong with multiple principals in regards to symbol mangling - let mut v = regular_trait_predicates - .chain( - existential_projections.map(|x| x.map_bound(ty::ExistentialPredicate::Projection)), - ) + let mut v = principal_trait_ref + .into_iter() + .chain(existential_projections) .chain(auto_trait_predicates) .collect::>(); v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder())); 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 4e7747173701d..5b5beb31f1c5b 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -12,7 +12,7 @@ use rustc_middle::bug; use rustc_middle::query::Key; use rustc_middle::ty::print::{PrintPolyTraitRefExt as _, PrintTraitRefExt as _}; use rustc_middle::ty::{ - self, AdtDef, Binder, GenericParamDefKind, TraitRef, Ty, TyCtxt, TypeVisitableExt, + self, AdtDef, GenericParamDefKind, Ty, TyCtxt, TypeVisitableExt, suggest_constraining_type_param, }; use rustc_session::parse::feature_err; @@ -21,8 +21,9 @@ use rustc_span::symbol::{Ident, kw, sym}; use rustc_span::{BytePos, DUMMY_SP, Span, Symbol}; use rustc_trait_selection::error_reporting::traits::report_dyn_incompatibility; use rustc_trait_selection::traits::{ - FulfillmentError, TraitAliasExpansionInfo, dyn_compatibility_violations_for_assoc_item, + FulfillmentError, dyn_compatibility_violations_for_assoc_item, }; +use smallvec::SmallVec; use crate::errors::{ self, AssocItemConstraintsNotAllowedHere, ManualImplementation, MissingTypeParams, @@ -716,7 +717,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// emit a generic note suggesting using a `where` clause to constraint instead. pub(crate) fn check_for_required_assoc_tys( &self, - principal_span: Span, + spans: SmallVec<[Span; 1]>, missing_assoc_types: FxIndexSet, potential_assoc_types: Vec, trait_bounds: &[hir::PolyTraitRef<'_>], @@ -725,6 +726,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { return Ok(()); } + let principal_span = *spans.first().unwrap(); + let tcx = self.tcx(); let missing_assoc_types: Vec<_> = missing_assoc_types.into_iter().map(|def_id| tcx.associated_item(def_id)).collect(); @@ -1116,29 +1119,34 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { pub fn report_trait_object_addition_traits_error( &self, - regular_traits: &Vec>, + regular_traits: &Vec<(ty::PolyTraitPredicate<'tcx>, SmallVec<[Span; 1]>)>, ) -> ErrorGuaranteed { - let first_trait = ®ular_traits[0]; - let additional_trait = ®ular_traits[1]; + let (&first_span, first_alias_spans) = regular_traits[0].1.split_last().unwrap(); + let (&second_span, second_alias_spans) = regular_traits[1].1.split_last().unwrap(); let mut err = struct_span_code_err!( self.dcx(), - additional_trait.bottom().1, + *regular_traits[1].1.first().unwrap(), E0225, "only auto traits can be used as additional traits in a trait object" ); - additional_trait.label_with_exp_info( - &mut err, - "additional non-auto trait", - "additional use", - ); - first_trait.label_with_exp_info(&mut err, "first non-auto trait", "first use"); + err.span_label(first_span, "first non-auto trait"); + for &alias_span in first_alias_spans { + err.span_label(alias_span, "first non-auto trait comes from this alias"); + } + err.span_label(second_span, "additional non-auto trait"); + for &alias_span in second_alias_spans { + err.span_label(alias_span, "second non-auto trait comes from this alias"); + } err.help(format!( "consider creating a new trait with all of these as supertraits and using that \ trait here instead: `trait NewTrait: {} {{}}`", regular_traits .iter() // FIXME: This should `print_sugared`, but also needs to integrate projection bounds... - .map(|t| t.trait_ref().print_only_trait_path().to_string()) + .map(|(pred, _)| pred + .map_bound(|pred| pred.trait_ref) + .print_only_trait_path() + .to_string()) .collect::>() .join(" + "), )); @@ -1153,14 +1161,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { pub fn report_trait_object_with_no_traits_error( &self, span: Span, - trait_bounds: &Vec<(Binder<'tcx, TraitRef<'tcx>>, Span)>, + user_written_clauses: impl IntoIterator, Span)>, ) -> ErrorGuaranteed { let tcx = self.tcx(); - let trait_alias_span = trait_bounds - .iter() - .map(|&(trait_ref, _)| trait_ref.def_id()) - .find(|&trait_ref| tcx.is_trait_alias(trait_ref)) - .map(|trait_ref| tcx.def_span(trait_ref)); + let trait_alias_span = user_written_clauses + .into_iter() + .filter_map(|(clause, _)| clause.as_trait_clause()) + .find(|trait_ref| tcx.is_trait_alias(trait_ref.def_id())) + .map(|trait_ref| tcx.def_span(trait_ref.def_id())); self.dcx().emit_err(TraitObjectDeclaredWithNoTraits { span, trait_alias_span }) } diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 039c117c09995..bc51db1bdf4b2 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -1,6 +1,5 @@ use std::cell::{Cell, RefCell}; use std::cmp::max; -use std::iter; use std::ops::Deref; use rustc_data_structures::fx::FxHashSet; @@ -901,11 +900,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { if self.tcx.is_trait_alias(trait_def_id) { // For trait aliases, recursively assume all explicitly named traits are relevant - for expansion in traits::expand_trait_aliases( - self.tcx, - iter::once((ty::Binder::dummy(trait_ref), self.span)), - ) { - let bound_trait_ref = expansion.trait_ref(); + for (bound_trait_pred, _) in + traits::expand_trait_aliases(self.tcx, [(trait_ref.upcast(self.tcx), self.span)]).0 + { + assert_eq!(bound_trait_pred.polarity(), ty::PredicatePolarity::Positive); + let bound_trait_ref = bound_trait_pred.map_bound(|pred| pred.trait_ref); for item in self.impl_or_trait_item(bound_trait_ref.def_id()) { if !self.has_applicable_self(&item) { self.record_static_candidate(CandidateSource::Trait( diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs index b108a9352a53d..962e1747fe281 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs @@ -436,7 +436,8 @@ pub fn report_dyn_incompatibility<'tcx>( tcx.dcx(), span, E0038, - "the trait `{}` cannot be made into an object", + "the {} `{}` cannot be made into an object", + tcx.def_descr(trait_def_id), trait_str ); err.span_label(span, format!("`{trait_str}` cannot be made into an object")); diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 069fab6a6e6b9..2c22ecd7fe309 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -66,9 +66,9 @@ pub use self::specialize::{ }; pub use self::structural_normalize::StructurallyNormalizeExt; pub use self::util::{ - BoundVarReplacer, PlaceholderReplacer, TraitAliasExpander, TraitAliasExpansionInfo, elaborate, - expand_trait_aliases, impl_item_is_final, supertraits, - transitive_bounds_that_define_assoc_item, upcast_choices, with_replaced_escaping_bound_vars, + BoundVarReplacer, PlaceholderReplacer, elaborate, expand_trait_aliases, impl_item_is_final, + supertraits, transitive_bounds_that_define_assoc_item, upcast_choices, + with_replaced_escaping_bound_vars, }; use crate::error_reporting::InferCtxtErrorExt; use crate::infer::outlives::env::OutlivesEnvironment; diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index da1045b664afc..c9fb2a757e17d 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -1,162 +1,85 @@ -use std::collections::BTreeMap; +use std::collections::{BTreeMap, VecDeque}; -use rustc_data_structures::fx::FxIndexMap; -use rustc_errors::Diag; +use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_hir::def_id::DefId; use rustc_infer::infer::InferCtxt; pub use rustc_infer::traits::util::*; use rustc_middle::bug; use rustc_middle::ty::{ - self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, Upcast, + self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, }; use rustc_span::Span; use smallvec::{SmallVec, smallvec}; use tracing::debug; -/////////////////////////////////////////////////////////////////////////// -// `TraitAliasExpander` iterator -/////////////////////////////////////////////////////////////////////////// - -/// "Trait alias expansion" is the process of expanding a sequence of trait -/// references into another sequence by transitively following all trait -/// aliases. e.g. If you have bounds like `Foo + Send`, a trait alias -/// `trait Foo = Bar + Sync;`, and another trait alias -/// `trait Bar = Read + Write`, then the bounds would expand to -/// `Read + Write + Sync + Send`. -/// Expansion is done via a DFS (depth-first search), and the `visited` field -/// is used to avoid cycles. -pub struct TraitAliasExpander<'tcx> { - tcx: TyCtxt<'tcx>, - stack: Vec>, -} - -/// Stores information about the expansion of a trait via a path of zero or more trait aliases. -#[derive(Debug, Clone)] -pub struct TraitAliasExpansionInfo<'tcx> { - pub path: SmallVec<[(ty::PolyTraitRef<'tcx>, Span); 4]>, -} - -impl<'tcx> TraitAliasExpansionInfo<'tcx> { - fn new(trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self { - Self { path: smallvec![(trait_ref, span)] } - } - - /// Adds diagnostic labels to `diag` for the expansion path of a trait through all intermediate - /// trait aliases. - pub fn label_with_exp_info( - &self, - diag: &mut Diag<'_>, - top_label: &'static str, - use_desc: &str, - ) { - diag.span_label(self.top().1, top_label); - if self.path.len() > 1 { - for (_, sp) in self.path.iter().rev().skip(1).take(self.path.len() - 2) { - diag.span_label(*sp, format!("referenced here ({use_desc})")); - } - } - if self.top().1 != self.bottom().1 { - // When the trait object is in a return type these two spans match, we don't want - // redundant labels. - diag.span_label( - self.bottom().1, - format!("trait alias used in trait object type ({use_desc})"), - ); - } - } - - pub fn trait_ref(&self) -> ty::PolyTraitRef<'tcx> { - self.top().0 - } - - pub fn top(&self) -> &(ty::PolyTraitRef<'tcx>, Span) { - self.path.last().unwrap() - } - - pub fn bottom(&self) -> &(ty::PolyTraitRef<'tcx>, Span) { - self.path.first().unwrap() - } - - fn clone_and_push(&self, trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self { - let mut path = self.path.clone(); - path.push((trait_ref, span)); - - Self { path } - } -} - +/// Return the trait and projection predicates that come from eagerly expanding the +/// trait aliases in the list of clauses. For each trait predicate, record a stack +/// of spans that trace from the user-written trait alias bound. For projection predicates, +/// just record the span of the projection itself. +/// +/// For trait aliases, we don't deduplicte the predicates, since we currently do not +/// consider duplicated traits as a single trait for the purposes of our "one trait principal" +/// restriction; however, for projections we do deduplicate them. +/// +/// ```rust,ignore (fails) +/// trait Bar {} +/// trait Foo = Bar + Bar; +/// +/// let not_object_safe: dyn Foo; // bad, two `Bar` principals. +/// ``` pub fn expand_trait_aliases<'tcx>( tcx: TyCtxt<'tcx>, - trait_refs: impl Iterator, Span)>, -) -> TraitAliasExpander<'tcx> { - let items: Vec<_> = - trait_refs.map(|(trait_ref, span)| TraitAliasExpansionInfo::new(trait_ref, span)).collect(); - TraitAliasExpander { tcx, stack: items } -} - -impl<'tcx> TraitAliasExpander<'tcx> { - /// If `item` is a trait alias and its predicate has not yet been visited, then expands `item` - /// to the definition, pushes the resulting expansion onto `self.stack`, and returns `false`. - /// Otherwise, immediately returns `true` if `item` is a regular trait, or `false` if it is a - /// trait alias. - /// The return value indicates whether `item` should be yielded to the user. - fn expand(&mut self, item: &TraitAliasExpansionInfo<'tcx>) -> bool { - let tcx = self.tcx; - let trait_ref = item.trait_ref(); - let pred = trait_ref.upcast(tcx); - - debug!("expand_trait_aliases: trait_ref={:?}", trait_ref); - - // Don't recurse if this bound is not a trait alias. - let is_alias = tcx.is_trait_alias(trait_ref.def_id()); - if !is_alias { - return true; - } - - // Don't recurse if this trait alias is already on the stack for the DFS search. - let anon_pred = anonymize_predicate(tcx, pred); - if item - .path - .iter() - .rev() - .skip(1) - .any(|&(tr, _)| anonymize_predicate(tcx, tr.upcast(tcx)) == anon_pred) - { - return false; - } - - // Get components of trait alias. - let predicates = tcx.explicit_super_predicates_of(trait_ref.def_id()); - debug!(?predicates); - - let items = predicates.skip_binder().iter().rev().filter_map(|(pred, span)| { - pred.instantiate_supertrait(tcx, trait_ref) - .as_trait_clause() - .map(|trait_ref| item.clone_and_push(trait_ref.map_bound(|t| t.trait_ref), *span)) - }); - debug!("expand_trait_aliases: items={:?}", items.clone().collect::>()); - - self.stack.extend(items); - - false - } -} - -impl<'tcx> Iterator for TraitAliasExpander<'tcx> { - type Item = TraitAliasExpansionInfo<'tcx>; - - fn size_hint(&self) -> (usize, Option) { - (self.stack.len(), None) - } - - fn next(&mut self) -> Option> { - while let Some(item) = self.stack.pop() { - if self.expand(&item) { - return Some(item); + clauses: impl IntoIterator, Span)>, +) -> ( + Vec<(ty::PolyTraitPredicate<'tcx>, SmallVec<[Span; 1]>)>, + Vec<(ty::PolyProjectionPredicate<'tcx>, Span)>, +) { + let mut trait_preds = vec![]; + let mut projection_preds = vec![]; + let mut seen_projection_preds = FxHashSet::default(); + + let mut queue: VecDeque<_> = clauses.into_iter().map(|(p, s)| (p, smallvec![s])).collect(); + + while let Some((clause, spans)) = queue.pop_front() { + match clause.kind().skip_binder() { + ty::ClauseKind::Trait(trait_pred) => { + if tcx.is_trait_alias(trait_pred.def_id()) { + queue.extend( + tcx.explicit_super_predicates_of(trait_pred.def_id()) + .iter_identity_copied() + .map(|(clause, span)| { + let mut spans = spans.clone(); + spans.push(span); + ( + clause.instantiate_supertrait( + tcx, + clause.kind().rebind(trait_pred.trait_ref), + ), + spans, + ) + }), + ); + } else { + trait_preds.push((clause.kind().rebind(trait_pred), spans)); + } } + ty::ClauseKind::Projection(projection_pred) => { + let projection_pred = clause.kind().rebind(projection_pred); + if !seen_projection_preds.insert(tcx.anonymize_bound_vars(projection_pred)) { + continue; + } + projection_preds.push((projection_pred, *spans.last().unwrap())); + } + ty::ClauseKind::RegionOutlives(..) + | ty::ClauseKind::TypeOutlives(..) + | ty::ClauseKind::ConstArgHasType(_, _) + | ty::ClauseKind::WellFormed(_) + | ty::ClauseKind::ConstEvaluatable(_) + | ty::ClauseKind::HostEffect(..) => {} } - None } + + (trait_preds, projection_preds) } /////////////////////////////////////////////////////////////////////////// diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs index 71c3646498b9f..3213638afb258 100644 --- a/compiler/rustc_type_ir/src/visit.rs +++ b/compiler/rustc_type_ir/src/visit.rs @@ -47,6 +47,7 @@ use std::ops::ControlFlow; use rustc_ast_ir::visit::VisitorResult; use rustc_ast_ir::{try_visit, walk_visitable_list}; use rustc_index::{Idx, IndexVec}; +use smallvec::SmallVec; use thin_vec::ThinVec; use crate::data_structures::Lrc; @@ -192,6 +193,13 @@ impl> TypeVisitable for ThinVec { } } +impl, const N: usize> TypeVisitable for SmallVec<[T; N]> { + fn visit_with>(&self, visitor: &mut V) -> V::Result { + walk_visitable_list!(visitor, self.iter()); + V::Result::output() + } +} + // `TypeFoldable` isn't impl'd for `&[T]`. It doesn't make sense in the general // case, because we can't return a new slice. But note that there are a couple // of trivial impls of `TypeFoldable` for specific slice types elsewhere. diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_dyn_compatibility.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_dyn_compatibility.stderr index 84281eb53c946..7cd5754be8aae 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_dyn_compatibility.stderr +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_dyn_compatibility.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `ConstParamTy_` cannot be made into an object - --> $DIR/const_param_ty_dyn_compatibility.rs:6:12 + --> $DIR/const_param_ty_dyn_compatibility.rs:6:16 | LL | fn foo(a: &dyn ConstParamTy_) {} - | ^^^^^^^^^^^^^^^^^ `ConstParamTy_` cannot be made into an object + | ^^^^^^^^^^^^^ `ConstParamTy_` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $SRC_DIR/core/src/cmp.rs:LL:COL @@ -14,10 +14,10 @@ LL | fn foo(a: &impl ConstParamTy_) {} | ~~~~ error[E0038]: the trait `UnsizedConstParamTy` cannot be made into an object - --> $DIR/const_param_ty_dyn_compatibility.rs:9:12 + --> $DIR/const_param_ty_dyn_compatibility.rs:9:16 | LL | fn bar(a: &dyn UnsizedConstParamTy) {} - | ^^^^^^^^^^^^^^^^^^^^^^^ `UnsizedConstParamTy` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^ `UnsizedConstParamTy` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $SRC_DIR/core/src/cmp.rs:LL:COL diff --git a/tests/ui/dyn-compatibility/mentions-Self-in-super-predicates.stderr b/tests/ui/dyn-compatibility/mentions-Self-in-super-predicates.stderr index 7578edce7d19e..03e57841b1be4 100644 --- a/tests/ui/dyn-compatibility/mentions-Self-in-super-predicates.stderr +++ b/tests/ui/dyn-compatibility/mentions-Self-in-super-predicates.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Expr` cannot be made into an object - --> $DIR/mentions-Self-in-super-predicates.rs:12:23 + --> $DIR/mentions-Self-in-super-predicates.rs:12:27 | LL | elements: Vec>, - | ^^^^^^^^^^^^^ `Expr` cannot be made into an object + | ^^^^ `Expr` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/mentions-Self-in-super-predicates.rs:5:21 @@ -14,10 +14,10 @@ LL | trait Expr: Debug + PartialEq { = help: only type `SExpr<'x>` implements the trait, consider using it directly instead error[E0038]: the trait `Expr` cannot be made into an object - --> $DIR/mentions-Self-in-super-predicates.rs:38:16 + --> $DIR/mentions-Self-in-super-predicates.rs:38:20 | LL | let a: Box = Box::new(SExpr::new()); - | ^^^^^^^^ `Expr` cannot be made into an object + | ^^^^ `Expr` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/mentions-Self-in-super-predicates.rs:5:21 @@ -29,10 +29,10 @@ LL | trait Expr: Debug + PartialEq { = help: only type `SExpr<'x>` implements the trait, consider using it directly instead error[E0038]: the trait `Expr` cannot be made into an object - --> $DIR/mentions-Self-in-super-predicates.rs:40:16 + --> $DIR/mentions-Self-in-super-predicates.rs:40:20 | LL | let b: Box = Box::new(SExpr::new()); - | ^^^^^^^^ `Expr` cannot be made into an object + | ^^^^ `Expr` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/mentions-Self-in-super-predicates.rs:5:21 diff --git a/tests/ui/dyn-compatibility/supertrait-mentions-Self.stderr b/tests/ui/dyn-compatibility/supertrait-mentions-Self.stderr index 6474b115c4628..abeafa1967fba 100644 --- a/tests/ui/dyn-compatibility/supertrait-mentions-Self.stderr +++ b/tests/ui/dyn-compatibility/supertrait-mentions-Self.stderr @@ -19,10 +19,10 @@ LL | trait Bar { | ++++++++ error[E0038]: the trait `Baz` cannot be made into an object - --> $DIR/supertrait-mentions-Self.rs:16:31 + --> $DIR/supertrait-mentions-Self.rs:16:35 | LL | fn make_baz(t: &T) -> &dyn Baz { - | ^^^^^^^ `Baz` cannot be made into an object + | ^^^ `Baz` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/supertrait-mentions-Self.rs:8:13 diff --git a/tests/ui/error-codes/E0225.stderr b/tests/ui/error-codes/E0225.stderr index a4b33a0b7b408..e6781282c8f1b 100644 --- a/tests/ui/error-codes/E0225.stderr +++ b/tests/ui/error-codes/E0225.stderr @@ -20,8 +20,8 @@ LL | trait Foo = std::io::Read + std::io::Write; LL | let _: Box; | ^^^ | | - | trait alias used in trait object type (additional use) - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias + | second non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: std::io::Read + std::io::Write {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit diff --git a/tests/ui/issues/issue-26056.stderr b/tests/ui/issues/issue-26056.stderr index be5453ec19dfc..c5ae41200f6e0 100644 --- a/tests/ui/issues/issue-26056.stderr +++ b/tests/ui/issues/issue-26056.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Map` cannot be made into an object - --> $DIR/issue-26056.rs:20:13 + --> $DIR/issue-26056.rs:20:17 | LL | as &dyn Map; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Map` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^^^^^^ `Map` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/issue-26056.rs:9:12 diff --git a/tests/ui/traits/alias/generic-default-in-dyn.rs b/tests/ui/traits/alias/generic-default-in-dyn.rs index d44e1c2a97530..b180f0a68031e 100644 --- a/tests/ui/traits/alias/generic-default-in-dyn.rs +++ b/tests/ui/traits/alias/generic-default-in-dyn.rs @@ -2,9 +2,9 @@ trait SendEqAlias = PartialEq; //~^ ERROR trait aliases are experimental struct Foo(dyn SendEqAlias); -//~^ ERROR the type parameter `Rhs` must be explicitly specified [E0393] +//~^ ERROR the trait alias `SendEqAlias` cannot be made into an object struct Bar(dyn SendEqAlias, T); -//~^ ERROR the type parameter `Rhs` must be explicitly specified [E0393] +//~^ ERROR the trait alias `SendEqAlias` cannot be made into an object fn main() {} diff --git a/tests/ui/traits/alias/generic-default-in-dyn.stderr b/tests/ui/traits/alias/generic-default-in-dyn.stderr index 50031e184c106..902d18de9448b 100644 --- a/tests/ui/traits/alias/generic-default-in-dyn.stderr +++ b/tests/ui/traits/alias/generic-default-in-dyn.stderr @@ -8,29 +8,35 @@ LL | trait SendEqAlias = PartialEq; = help: add `#![feature(trait_alias)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0393]: the type parameter `Rhs` must be explicitly specified +error[E0038]: the trait alias `SendEqAlias` cannot be made into an object --> $DIR/generic-default-in-dyn.rs:4:19 | LL | struct Foo(dyn SendEqAlias); - | ^^^^^^^^^^^^^^ missing reference to `Rhs` - --> $SRC_DIR/core/src/cmp.rs:LL:COL + | ^^^^^^^^^^^^^^ `SendEqAlias` cannot be made into an object | - = note: type parameter `Rhs` must be specified for this +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/generic-default-in-dyn.rs:1:24 | - = note: because of the default `Self` reference, type parameters must be specified on object types +LL | trait SendEqAlias = PartialEq; + | ----------- ^^^^^^^^^ ...because it uses `Self` as a type parameter + | | + | this trait cannot be made into an object... -error[E0393]: the type parameter `Rhs` must be explicitly specified +error[E0038]: the trait alias `SendEqAlias` cannot be made into an object --> $DIR/generic-default-in-dyn.rs:7:19 | LL | struct Bar(dyn SendEqAlias, T); - | ^^^^^^^^^^^^^^ missing reference to `Rhs` - --> $SRC_DIR/core/src/cmp.rs:LL:COL + | ^^^^^^^^^^^^^^ `SendEqAlias` cannot be made into an object | - = note: type parameter `Rhs` must be specified for this +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/generic-default-in-dyn.rs:1:24 | - = note: because of the default `Self` reference, type parameters must be specified on object types +LL | trait SendEqAlias = PartialEq; + | ----------- ^^^^^^^^^ ...because it uses `Self` as a type parameter + | | + | this trait cannot be made into an object... error: aborting due to 3 previous errors -Some errors have detailed explanations: E0393, E0658. -For more information about an error, try `rustc --explain E0393`. +Some errors have detailed explanations: E0038, E0658. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/alias/no-duplicates.stderr b/tests/ui/traits/alias/no-duplicates.stderr index bf244b97e9b13..6a901a80554e9 100644 --- a/tests/ui/traits/alias/no-duplicates.stderr +++ b/tests/ui/traits/alias/no-duplicates.stderr @@ -4,32 +4,32 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _0 = Obj; | --- | | - | additional non-auto trait | first non-auto trait + | additional non-auto trait ... LL | type _T00 = dyn _0 + _0; - | -- ^^ trait alias used in trait object type (additional use) + | -- ^^ second non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/no-duplicates.rs:19:22 + --> $DIR/no-duplicates.rs:19:17 | LL | trait _0 = Obj; | --- | | - | additional non-auto trait | first non-auto trait + | additional non-auto trait LL | trait _1 = _0; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias ... LL | type _T01 = dyn _1 + _0; - | -- ^^ trait alias used in trait object type (additional use) + | ^^ -- first non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit @@ -40,18 +40,18 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _0 = Obj; | --- | | - | additional non-auto trait | first non-auto trait + | additional non-auto trait LL | trait _1 = _0; | -- | | - | referenced here (additional use) - | referenced here (first use) + | first non-auto trait comes from this alias + | second non-auto trait comes from this alias ... LL | type _T02 = dyn _1 + _1; - | -- ^^ trait alias used in trait object type (additional use) + | -- ^^ second non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit @@ -62,10 +62,10 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _0 = Obj; | --- additional non-auto trait LL | trait _1 = _0; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias ... LL | type _T03 = dyn Obj + _1; - | --- ^^ trait alias used in trait object type (additional use) + | --- ^^ second non-auto trait comes from this alias | | | first non-auto trait | @@ -73,17 +73,17 @@ LL | type _T03 = dyn Obj + _1; = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/no-duplicates.rs:28:22 + --> $DIR/no-duplicates.rs:28:17 | LL | trait _0 = Obj; - | --- first non-auto trait + | --- additional non-auto trait LL | trait _1 = _0; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias ... LL | type _T04 = dyn _1 + Obj; - | -- ^^^ additional non-auto trait + | ^^ --- first non-auto trait | | - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit @@ -92,23 +92,17 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec --> $DIR/no-duplicates.rs:37:17 | LL | trait _0 = Obj; - | --- - | | - | additional non-auto trait - | first non-auto trait -LL | trait _1 = _0; - | -- referenced here (additional use) + | --- additional non-auto trait ... LL | trait _2 = _0 + _1; - | -- -- referenced here (additional use) - | | - | referenced here (first use) + | -- second non-auto trait comes from this alias +LL | trait _3 = Obj; + | --- first non-auto trait ... LL | type _T10 = dyn _2 + _3; - | ^^ + | ^^ -- first non-auto trait comes from this alias | | - | trait alias used in trait object type (additional use) - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit @@ -120,14 +114,14 @@ LL | trait _0 = Obj; | --- additional non-auto trait ... LL | trait _2 = _0 + _1; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias LL | trait _3 = Obj; | --- first non-auto trait ... LL | type _T11 = dyn _3 + _2; - | -- ^^ trait alias used in trait object type (additional use) + | -- ^^ second non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit @@ -139,10 +133,10 @@ LL | trait _0 = Obj; | --- additional non-auto trait ... LL | trait _2 = _0 + _1; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias ... LL | type _T12 = dyn Obj + _2; - | --- ^^ trait alias used in trait object type (additional use) + | --- ^^ second non-auto trait comes from this alias | | | first non-auto trait | @@ -153,42 +147,34 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec --> $DIR/no-duplicates.rs:46:17 | LL | trait _0 = Obj; - | --- - | | - | additional non-auto trait - | first non-auto trait -LL | trait _1 = _0; - | -- referenced here (additional use) + | --- additional non-auto trait ... LL | trait _2 = _0 + _1; - | -- -- referenced here (additional use) - | | - | referenced here (first use) + | -- second non-auto trait comes from this alias ... LL | type _T13 = dyn _2 + Obj; - | ^^ + | ^^ --- first non-auto trait | | - | trait alias used in trait object type (additional use) - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/no-duplicates.rs:49:22 + --> $DIR/no-duplicates.rs:49:17 | LL | trait _0 = Obj; - | --- first non-auto trait + | --- additional non-auto trait LL | trait _1 = _0; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias ... LL | trait _3 = Obj; - | --- additional non-auto trait + | --- first non-auto trait ... LL | type _T14 = dyn _1 + _3; - | -- ^^ trait alias used in trait object type (additional use) + | ^^ -- first non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit @@ -199,15 +185,15 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _0 = Obj; | --- additional non-auto trait LL | trait _1 = _0; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias ... LL | trait _3 = Obj; | --- first non-auto trait ... LL | type _T15 = dyn _3 + _1; - | -- ^^ trait alias used in trait object type (additional use) + | -- ^^ second non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit @@ -218,17 +204,17 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _0 = Obj; | --- first non-auto trait LL | trait _1 = _0; - | -- referenced here (first use) + | -- first non-auto trait comes from this alias ... LL | trait _3 = Obj; | --- additional non-auto trait LL | trait _4 = _3; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias ... LL | type _T16 = dyn _1 + _4; - | -- ^^ trait alias used in trait object type (additional use) + | -- ^^ second non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit @@ -239,17 +225,17 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _0 = Obj; | --- additional non-auto trait LL | trait _1 = _0; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias ... LL | trait _3 = Obj; | --- first non-auto trait LL | trait _4 = _3; - | -- referenced here (first use) + | -- first non-auto trait comes from this alias ... LL | type _T17 = dyn _4 + _1; - | -- ^^ trait alias used in trait object type (additional use) + | -- ^^ second non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit @@ -260,13 +246,13 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _5 = Obj + Send; | --- | | - | additional non-auto trait | first non-auto trait + | additional non-auto trait LL | LL | type _T20 = dyn _5 + _5; - | -- ^^ trait alias used in trait object type (additional use) + | -- ^^ second non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit @@ -278,7 +264,7 @@ LL | trait _5 = Obj + Send; | --- additional non-auto trait ... LL | type _T21 = dyn Obj + _5; - | --- ^^ trait alias used in trait object type (additional use) + | --- ^^ second non-auto trait comes from this alias | | | first non-auto trait | @@ -286,29 +272,29 @@ LL | type _T21 = dyn Obj + _5; = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/no-duplicates.rs:71:22 + --> $DIR/no-duplicates.rs:71:17 | LL | trait _5 = Obj + Send; - | --- first non-auto trait + | --- additional non-auto trait ... LL | type _T22 = dyn _5 + Obj; - | -- ^^^ additional non-auto trait + | ^^ --- first non-auto trait | | - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/no-duplicates.rs:74:36 + --> $DIR/no-duplicates.rs:74:17 | LL | trait _5 = Obj + Send; - | --- first non-auto trait + | --- additional non-auto trait ... LL | type _T23 = dyn _5 + Send + Sync + Obj; - | -- ^^^ additional non-auto trait + | ^^ --- first non-auto trait | | - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit @@ -319,19 +305,19 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _5 = Obj + Send; | --- | | - | additional non-auto trait | first non-auto trait + | additional non-auto trait ... LL | trait _6 = _5 + _5; // ==> Obj + Send + Obj + Send - | -- -- referenced here (additional use) + | -- -- second non-auto trait comes from this alias | | - | referenced here (first use) + | first non-auto trait comes from this alias LL | LL | type _T30 = dyn _6; | ^^ | | - | trait alias used in trait object type (additional use) - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias + | second non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit @@ -342,19 +328,19 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _5 = Obj + Send; | --- | | - | additional non-auto trait | first non-auto trait + | additional non-auto trait ... LL | trait _6 = _5 + _5; // ==> Obj + Send + Obj + Send - | -- -- referenced here (additional use) + | -- -- second non-auto trait comes from this alias | | - | referenced here (first use) + | first non-auto trait comes from this alias ... LL | type _T31 = dyn _6 + Send; | ^^ | | - | trait alias used in trait object type (additional use) - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias + | second non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit @@ -365,38 +351,38 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _5 = Obj + Send; | --- | | - | additional non-auto trait | first non-auto trait + | additional non-auto trait ... LL | trait _6 = _5 + _5; // ==> Obj + Send + Obj + Send - | -- -- referenced here (additional use) + | -- -- second non-auto trait comes from this alias | | - | referenced here (first use) + | first non-auto trait comes from this alias ... LL | type _T32 = dyn Send + _6; | ^^ | | - | trait alias used in trait object type (additional use) - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias + | second non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/no-duplicates.rs:95:22 + --> $DIR/no-duplicates.rs:95:17 | LL | trait _5 = Obj + Send; - | --- first non-auto trait + | --- additional non-auto trait ... LL | trait _7 = _5 + Sync; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias LL | trait _8 = Unpin + _7; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias LL | LL | type _T40 = dyn _8 + Obj; - | -- ^^^ additional non-auto trait + | ^^ --- first non-auto trait | | - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit @@ -408,12 +394,12 @@ LL | trait _5 = Obj + Send; | --- additional non-auto trait ... LL | trait _7 = _5 + Sync; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias LL | trait _8 = Unpin + _7; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias ... LL | type _T41 = dyn Obj + _8; - | --- ^^ trait alias used in trait object type (additional use) + | --- ^^ second non-auto trait comes from this alias | | | first non-auto trait | @@ -421,25 +407,25 @@ LL | type _T41 = dyn Obj + _8; = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/no-duplicates.rs:101:22 + --> $DIR/no-duplicates.rs:101:17 | LL | trait _3 = Obj; - | --- additional non-auto trait + | --- first non-auto trait LL | trait _4 = _3; - | -- referenced here (additional use) + | -- first non-auto trait comes from this alias ... LL | trait _5 = Obj + Send; - | --- first non-auto trait + | --- additional non-auto trait ... LL | trait _7 = _5 + Sync; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias LL | trait _8 = Unpin + _7; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias ... LL | type _T42 = dyn _8 + _4; - | -- ^^ trait alias used in trait object type (additional use) + | ^^ -- first non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit @@ -450,20 +436,20 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _3 = Obj; | --- first non-auto trait LL | trait _4 = _3; - | -- referenced here (first use) + | -- first non-auto trait comes from this alias ... LL | trait _5 = Obj + Send; | --- additional non-auto trait ... LL | trait _7 = _5 + Sync; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias LL | trait _8 = Unpin + _7; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias ... LL | type _T43 = dyn _4 + _8; - | -- ^^ trait alias used in trait object type (additional use) + | -- ^^ second non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit @@ -474,20 +460,20 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _3 = Obj; | --- first non-auto trait LL | trait _4 = _3; - | -- referenced here (first use) + | -- first non-auto trait comes from this alias ... LL | trait _5 = Obj + Send; | --- additional non-auto trait ... LL | trait _7 = _5 + Sync; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias LL | trait _8 = Unpin + _7; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias ... LL | type _T44 = dyn _4 + Send + Sync + _8; - | -- ^^ trait alias used in trait object type (additional use) + | -- ^^ second non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit @@ -500,9 +486,9 @@ LL | trait _9 = for<'a> ObjL<'a>; LL | trait _10 = for<'b> ObjL<'b>; | ---------------- additional non-auto trait LL | type _T50 = dyn _9 + _10; - | -- ^^^ trait alias used in trait object type (additional use) + | -- ^^^ second non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: for<'a> ObjL<'a> + for<'b> ObjL<'b> {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit @@ -515,9 +501,9 @@ LL | trait _11 = ObjT fn(&'a u8)>; LL | trait _12 = ObjT fn(&'b u8)>; | ------------------------ additional non-auto trait LL | type _T60 = dyn _11 + _12; - | --- ^^^ trait alias used in trait object type (additional use) + | --- ^^^ second non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjT fn(&'a u8)> + ObjT fn(&'b u8)> {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit diff --git a/tests/ui/traits/alias/no-extra-traits.stderr b/tests/ui/traits/alias/no-extra-traits.stderr index 4b1ddf6843c3d..fcdb4937ff594 100644 --- a/tests/ui/traits/alias/no-extra-traits.stderr +++ b/tests/ui/traits/alias/no-extra-traits.stderr @@ -1,15 +1,15 @@ error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/no-extra-traits.rs:16:22 + --> $DIR/no-extra-traits.rs:16:17 | LL | trait _0 = ObjA; - | ---- first non-auto trait + | ---- additional non-auto trait ... LL | type _T00 = dyn _0 + ObjB; - | -- ^^^^ additional non-auto trait + | ^^ ---- first non-auto trait | | - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -19,7 +19,7 @@ LL | trait _0 = ObjA; | ---- additional non-auto trait ... LL | type _T01 = dyn ObjB + _0; - | ---- ^^ trait alias used in trait object type (additional use) + | ---- ^^ second non-auto trait comes from this alias | | | first non-auto trait | @@ -32,10 +32,10 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _0 = ObjA; | ---- additional non-auto trait LL | trait _1 = _0; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias ... LL | type _T02 = dyn ObjB + _1; - | ---- ^^ trait alias used in trait object type (additional use) + | ---- ^^ second non-auto trait comes from this alias | | | first non-auto trait | @@ -43,19 +43,19 @@ LL | type _T02 = dyn ObjB + _1; = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/no-extra-traits.rs:25:22 + --> $DIR/no-extra-traits.rs:25:17 | LL | trait _0 = ObjA; - | ---- first non-auto trait + | ---- additional non-auto trait LL | trait _1 = _0; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias ... LL | type _T03 = dyn _1 + ObjB; - | -- ^^^^ additional non-auto trait + | ^^ ---- first non-auto trait | | - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -64,34 +64,34 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _2 = ObjB; | ---- | | - | additional non-auto trait | first non-auto trait + | additional non-auto trait LL | trait _3 = _2; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias ... LL | type _T10 = dyn _2 + _3; - | -- ^^ trait alias used in trait object type (additional use) + | -- ^^ second non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjB {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/no-extra-traits.rs:37:22 + --> $DIR/no-extra-traits.rs:37:17 | LL | trait _2 = ObjB; | ---- | | - | additional non-auto trait | first non-auto trait + | additional non-auto trait LL | trait _3 = _2; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias ... LL | type _T11 = dyn _3 + _2; - | -- ^^ trait alias used in trait object type (additional use) + | ^^ -- first non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjB {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit @@ -102,38 +102,38 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _2 = ObjB; | ---- | | - | additional non-auto trait | first non-auto trait + | additional non-auto trait LL | trait _3 = _2; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias LL | trait _4 = _3; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias ... LL | type _T12 = dyn _2 + _4; - | -- ^^ trait alias used in trait object type (additional use) + | -- ^^ second non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjB {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/no-extra-traits.rs:43:22 + --> $DIR/no-extra-traits.rs:43:17 | LL | trait _2 = ObjB; | ---- | | - | additional non-auto trait | first non-auto trait + | additional non-auto trait LL | trait _3 = _2; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias LL | trait _4 = _3; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias ... LL | type _T13 = dyn _4 + _2; - | -- ^^ trait alias used in trait object type (additional use) + | ^^ -- first non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjB {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit @@ -144,50 +144,50 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _0 = ObjA; | ---- additional non-auto trait LL | trait _1 = _0; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias ... LL | trait _5 = Sync + ObjB + Send; | ---- first non-auto trait LL | LL | type _T20 = dyn _5 + _1; - | -- ^^ trait alias used in trait object type (additional use) + | -- ^^ second non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/no-extra-traits.rs:53:22 + --> $DIR/no-extra-traits.rs:53:17 | LL | trait _0 = ObjA; - | ---- first non-auto trait + | ---- additional non-auto trait LL | trait _1 = _0; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias ... LL | trait _5 = Sync + ObjB + Send; - | ---- additional non-auto trait + | ---- first non-auto trait ... LL | type _T21 = dyn _1 + _5; - | -- ^^ trait alias used in trait object type (additional use) + | ^^ -- first non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/no-extra-traits.rs:56:22 + --> $DIR/no-extra-traits.rs:56:17 | LL | trait _5 = Sync + ObjB + Send; - | ---- first non-auto trait + | ---- additional non-auto trait ... LL | type _T22 = dyn _5 + ObjA; - | -- ^^^^ additional non-auto trait + | ^^ ---- first non-auto trait | | - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -197,7 +197,7 @@ LL | trait _5 = Sync + ObjB + Send; | ---- additional non-auto trait ... LL | type _T23 = dyn ObjA + _5; - | ---- ^^ trait alias used in trait object type (additional use) + | ---- ^^ second non-auto trait comes from this alias | | | first non-auto trait | @@ -210,50 +210,50 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _0 = ObjA; | ---- additional non-auto trait LL | trait _1 = _0; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias ... LL | trait _5 = Sync + ObjB + Send; | ---- first non-auto trait ... LL | type _T24 = dyn Send + _5 + _1 + Sync; - | -- ^^ trait alias used in trait object type (additional use) + | -- ^^ second non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/no-extra-traits.rs:65:29 + --> $DIR/no-extra-traits.rs:65:17 | LL | trait _0 = ObjA; - | ---- first non-auto trait + | ---- additional non-auto trait LL | trait _1 = _0; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias ... LL | trait _5 = Sync + ObjB + Send; - | ---- additional non-auto trait + | ---- first non-auto trait ... LL | type _T25 = dyn _1 + Sync + _5 + Send; - | -- ^^ trait alias used in trait object type (additional use) + | ^^ -- first non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/no-extra-traits.rs:68:36 + --> $DIR/no-extra-traits.rs:68:31 | LL | trait _5 = Sync + ObjB + Send; - | ---- first non-auto trait + | ---- additional non-auto trait ... LL | type _T26 = dyn Sync + Send + _5 + ObjA; - | -- ^^^^ additional non-auto trait + | ^^ ---- first non-auto trait | | - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -263,7 +263,7 @@ LL | trait _5 = Sync + ObjB + Send; | ---- additional non-auto trait ... LL | type _T27 = dyn Send + Sync + ObjA + _5; - | ---- ^^ trait alias used in trait object type (additional use) + | ---- ^^ second non-auto trait comes from this alias | | | first non-auto trait | @@ -274,199 +274,199 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec --> $DIR/no-extra-traits.rs:80:17 | LL | trait _0 = ObjA; - | ---- first non-auto trait + | ---- additional non-auto trait LL | trait _1 = _0; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias ... LL | trait _5 = Sync + ObjB + Send; - | ---- additional non-auto trait + | ---- first non-auto trait ... LL | trait _6 = _1 + _5; - | -- -- referenced here (additional use) + | -- -- first non-auto trait comes from this alias | | - | referenced here (first use) + | second non-auto trait comes from this alias ... LL | type _T30 = dyn _6; | ^^ | | - | trait alias used in trait object type (additional use) - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias + | second non-auto trait comes from this alias | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/no-extra-traits.rs:83:17 | LL | trait _0 = ObjA; - | ---- first non-auto trait + | ---- additional non-auto trait LL | trait _1 = _0; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias ... LL | trait _5 = Sync + ObjB + Send; - | ---- additional non-auto trait + | ---- first non-auto trait ... LL | trait _6 = _1 + _5; - | -- -- referenced here (additional use) + | -- -- first non-auto trait comes from this alias | | - | referenced here (first use) + | second non-auto trait comes from this alias ... LL | type _T31 = dyn _6 + Send; | ^^ | | - | trait alias used in trait object type (additional use) - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias + | second non-auto trait comes from this alias | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/no-extra-traits.rs:86:24 | LL | trait _0 = ObjA; - | ---- first non-auto trait + | ---- additional non-auto trait LL | trait _1 = _0; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias ... LL | trait _5 = Sync + ObjB + Send; - | ---- additional non-auto trait + | ---- first non-auto trait ... LL | trait _6 = _1 + _5; - | -- -- referenced here (additional use) + | -- -- first non-auto trait comes from this alias | | - | referenced here (first use) + | second non-auto trait comes from this alias ... LL | type _T32 = dyn Send + _6; | ^^ | | - | trait alias used in trait object type (additional use) - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias + | second non-auto trait comes from this alias | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/no-extra-traits.rs:89:17 | LL | trait _0 = ObjA; - | ---- first non-auto trait + | ---- additional non-auto trait LL | trait _1 = _0; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias ... LL | trait _5 = Sync + ObjB + Send; - | ---- additional non-auto trait + | ---- first non-auto trait ... LL | trait _6 = _1 + _5; - | -- -- referenced here (additional use) + | -- -- first non-auto trait comes from this alias | | - | referenced here (first use) + | second non-auto trait comes from this alias LL | trait _7 = _6; | -- | | - | referenced here (additional use) - | referenced here (first use) + | first non-auto trait comes from this alias + | second non-auto trait comes from this alias LL | trait _8 = _7; | -- | | - | referenced here (additional use) - | referenced here (first use) + | first non-auto trait comes from this alias + | second non-auto trait comes from this alias ... LL | type _T33 = dyn _8; | ^^ | | - | trait alias used in trait object type (additional use) - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias + | second non-auto trait comes from this alias | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/no-extra-traits.rs:92:17 | LL | trait _0 = ObjA; - | ---- first non-auto trait + | ---- additional non-auto trait LL | trait _1 = _0; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias ... LL | trait _5 = Sync + ObjB + Send; - | ---- additional non-auto trait + | ---- first non-auto trait ... LL | trait _6 = _1 + _5; - | -- -- referenced here (additional use) + | -- -- first non-auto trait comes from this alias | | - | referenced here (first use) + | second non-auto trait comes from this alias LL | trait _7 = _6; | -- | | - | referenced here (additional use) - | referenced here (first use) + | first non-auto trait comes from this alias + | second non-auto trait comes from this alias LL | trait _8 = _7; | -- | | - | referenced here (additional use) - | referenced here (first use) + | first non-auto trait comes from this alias + | second non-auto trait comes from this alias ... LL | type _T34 = dyn _8 + Send; | ^^ | | - | trait alias used in trait object type (additional use) - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias + | second non-auto trait comes from this alias | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/no-extra-traits.rs:95:24 | LL | trait _0 = ObjA; - | ---- first non-auto trait + | ---- additional non-auto trait LL | trait _1 = _0; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias ... LL | trait _5 = Sync + ObjB + Send; - | ---- additional non-auto trait + | ---- first non-auto trait ... LL | trait _6 = _1 + _5; - | -- -- referenced here (additional use) + | -- -- first non-auto trait comes from this alias | | - | referenced here (first use) + | second non-auto trait comes from this alias LL | trait _7 = _6; | -- | | - | referenced here (additional use) - | referenced here (first use) + | first non-auto trait comes from this alias + | second non-auto trait comes from this alias LL | trait _8 = _7; | -- | | - | referenced here (additional use) - | referenced here (first use) + | first non-auto trait comes from this alias + | second non-auto trait comes from this alias ... LL | type _T35 = dyn Send + _8; | ^^ | | - | trait alias used in trait object type (additional use) - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias + | second non-auto trait comes from this alias | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/no-extra-traits.rs:103:23 + --> $DIR/no-extra-traits.rs:103:17 | LL | trait _5 = Sync + ObjB + Send; - | ---- first non-auto trait + | ---- additional non-auto trait ... LL | trait _9 = _5 + Sync; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias LL | trait _10 = Unpin + _9; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias LL | LL | type _T40 = dyn _10 + ObjA; - | --- ^^^^ additional non-auto trait + | ^^^ ---- first non-auto trait | | - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -476,12 +476,12 @@ LL | trait _5 = Sync + ObjB + Send; | ---- additional non-auto trait ... LL | trait _9 = _5 + Sync; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias LL | trait _10 = Unpin + _9; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias ... LL | type _T41 = dyn ObjA + _10; - | ---- ^^^ trait alias used in trait object type (additional use) + | ---- ^^^ second non-auto trait comes from this alias | | | first non-auto trait | @@ -489,46 +489,46 @@ LL | type _T41 = dyn ObjA + _10; = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/no-extra-traits.rs:109:23 + --> $DIR/no-extra-traits.rs:109:17 | LL | trait _0 = ObjA; - | ---- additional non-auto trait + | ---- first non-auto trait LL | trait _1 = _0; - | -- referenced here (additional use) + | -- first non-auto trait comes from this alias ... LL | trait _5 = Sync + ObjB + Send; - | ---- first non-auto trait + | ---- additional non-auto trait ... LL | trait _9 = _5 + Sync; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias LL | trait _10 = Unpin + _9; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias ... LL | type _T42 = dyn _10 + _1; - | --- ^^ trait alias used in trait object type (additional use) + | ^^^ -- first non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/no-extra-traits.rs:112:37 + --> $DIR/no-extra-traits.rs:112:24 | LL | trait _5 = Sync + ObjB + Send; - | ---- first non-auto trait + | ---- additional non-auto trait ... LL | trait _9 = _5 + Sync; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias LL | trait _10 = Unpin + _9; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias ... LL | type _T43 = dyn Send + _10 + Sync + ObjA; - | --- ^^^^ additional non-auto trait + | ^^^ ---- first non-auto trait | | - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -538,12 +538,12 @@ LL | trait _5 = Sync + ObjB + Send; | ---- additional non-auto trait ... LL | trait _9 = _5 + Sync; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias LL | trait _10 = Unpin + _9; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias ... LL | type _T44 = dyn ObjA + _10 + Send + Sync; - | ---- ^^^ trait alias used in trait object type (additional use) + | ---- ^^^ second non-auto trait comes from this alias | | | first non-auto trait | @@ -551,27 +551,27 @@ LL | type _T44 = dyn ObjA + _10 + Send + Sync; = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/no-extra-traits.rs:118:37 + --> $DIR/no-extra-traits.rs:118:31 | LL | trait _0 = ObjA; - | ---- additional non-auto trait + | ---- first non-auto trait LL | trait _1 = _0; - | -- referenced here (additional use) + | -- first non-auto trait comes from this alias ... LL | trait _5 = Sync + ObjB + Send; - | ---- first non-auto trait + | ---- additional non-auto trait ... LL | trait _9 = _5 + Sync; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias LL | trait _10 = Unpin + _9; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias ... LL | type _T45 = dyn Sync + Send + _10 + _1; - | --- ^^ trait alias used in trait object type (additional use) + | ^^^ -- first non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error: aborting due to 28 previous errors diff --git a/tests/ui/traits/alias/object-fail.rs b/tests/ui/traits/alias/object-fail.rs index 5c753ff207c1a..38da7b8eef400 100644 --- a/tests/ui/traits/alias/object-fail.rs +++ b/tests/ui/traits/alias/object-fail.rs @@ -5,7 +5,7 @@ trait IteratorAlias = Iterator; fn main() { let _: &dyn EqAlias = &123; - //~^ ERROR the trait `Eq` cannot be made into an object [E0038] + //~^ ERROR the trait alias `EqAlias` cannot be made into an object [E0038] let _: &dyn IteratorAlias = &vec![123].into_iter(); //~^ ERROR must be specified } diff --git a/tests/ui/traits/alias/object-fail.stderr b/tests/ui/traits/alias/object-fail.stderr index 1b89b87db9f8f..e4968ee2adc41 100644 --- a/tests/ui/traits/alias/object-fail.stderr +++ b/tests/ui/traits/alias/object-fail.stderr @@ -1,13 +1,18 @@ -error[E0038]: the trait `Eq` cannot be made into an object - --> $DIR/object-fail.rs:7:13 +error[E0038]: the trait alias `EqAlias` cannot be made into an object + --> $DIR/object-fail.rs:7:17 | LL | let _: &dyn EqAlias = &123; - | ^^^^^^^^^^^ `Eq` cannot be made into an object + | ^^^^^^^ `EqAlias` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $SRC_DIR/core/src/cmp.rs:LL:COL | - = note: the trait cannot be made into an object because it uses `Self` as a type parameter + = note: ...because it uses `Self` as a type parameter + | + ::: $DIR/object-fail.rs:3:7 + | +LL | trait EqAlias = Eq; + | ------- this trait cannot be made into an object... error[E0191]: the value of the associated type `Item` in `Iterator` must be specified --> $DIR/object-fail.rs:9:17 diff --git a/tests/ui/traits/alias/self-in-const-generics.stderr b/tests/ui/traits/alias/self-in-const-generics.stderr index 3de31b64c8bf9..6dd6fabe7b203 100644 --- a/tests/ui/traits/alias/self-in-const-generics.stderr +++ b/tests/ui/traits/alias/self-in-const-generics.stderr @@ -2,9 +2,19 @@ error[E0038]: the trait alias `BB` cannot be made into an object --> $DIR/self-in-const-generics.rs:9:16 | LL | fn foo(x: &dyn BB) {} - | ^^ + | ^^ `BB` cannot be made into an object | - = note: it cannot use `Self` as a type parameter in a supertrait or `where`-clause +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/self-in-const-generics.rs:7:12 + | +LL | trait BB = Bar<{ 2 + 1 }>; + | -- ^^^^^^^^^^^^^^ ...because it uses `Self` as a type parameter + | | + | this trait cannot be made into an object... +help: consider using an opaque type instead + | +LL | fn foo(x: &impl BB) {} + | ~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/traits/alias/self-in-generics.stderr b/tests/ui/traits/alias/self-in-generics.stderr index ffc0a00ad7d9b..4fbd979e5f53e 100644 --- a/tests/ui/traits/alias/self-in-generics.stderr +++ b/tests/ui/traits/alias/self-in-generics.stderr @@ -2,9 +2,21 @@ error[E0038]: the trait alias `SelfInput` cannot be made into an object --> $DIR/self-in-generics.rs:8:19 | LL | pub fn f(_f: &dyn SelfInput) {} - | ^^^^^^^^^ + | ^^^^^^^^^ `SelfInput` cannot be made into an object | - = note: it cannot use `Self` as a type parameter in a supertrait or `where`-clause +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/self-in-generics.rs:6:23 + | +LL | pub trait SelfInput = Fn(&mut Self); + | --------- ^^^^^^^^^^^^^ + | | | + | | ...because it uses `Self` as a type parameter + | | ...because it uses `Self` as a type parameter + | this trait cannot be made into an object... +help: consider using an opaque type instead + | +LL | pub fn f(_f: &impl SelfInput) {} + | ~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/traits/bad-sized.stderr b/tests/ui/traits/bad-sized.stderr index 0e82867ef03b0..21718cf0951ca 100644 --- a/tests/ui/traits/bad-sized.stderr +++ b/tests/ui/traits/bad-sized.stderr @@ -1,12 +1,12 @@ error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/bad-sized.rs:4:28 + --> $DIR/bad-sized.rs:4:20 | LL | let x: Vec = Vec::new(); - | ----- ^^^^^ additional non-auto trait + | ^^^^^ ----- first non-auto trait | | - | first non-auto trait + | additional non-auto trait | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Trait + Sized {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Sized + Trait {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error: aborting due to 1 previous error diff --git a/tests/ui/traits/issue-28576.stderr b/tests/ui/traits/issue-28576.stderr index 23581f2ee51aa..cb0d55dce5920 100644 --- a/tests/ui/traits/issue-28576.stderr +++ b/tests/ui/traits/issue-28576.stderr @@ -19,9 +19,10 @@ LL | pub trait Foo { | ++++++++ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/issue-28576.rs:9:12 + --> $DIR/issue-28576.rs:9:16 | -LL | / dyn Bar +LL | dyn Bar + | ________________^ LL | | | |________________________^ `Bar` cannot be made into an object | diff --git a/tests/ui/traits/issue-38404.stderr b/tests/ui/traits/issue-38404.stderr index 145eeb88dd5e7..98d49fa3cba75 100644 --- a/tests/ui/traits/issue-38404.stderr +++ b/tests/ui/traits/issue-38404.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `B` cannot be made into an object - --> $DIR/issue-38404.rs:3:15 + --> $DIR/issue-38404.rs:3:19 | LL | trait C: A> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ `B` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^ `B` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/issue-38404.rs:1:13 @@ -13,10 +13,10 @@ LL | trait B: A {} | - this trait cannot be made into an object... error[E0038]: the trait `B` cannot be made into an object - --> $DIR/issue-38404.rs:3:15 + --> $DIR/issue-38404.rs:3:19 | LL | trait C: A> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ `B` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^ `B` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/issue-38404.rs:1:13 @@ -28,10 +28,10 @@ LL | trait B: A {} = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0038]: the trait `B` cannot be made into an object - --> $DIR/issue-38404.rs:3:15 + --> $DIR/issue-38404.rs:3:19 | LL | trait C: A> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ `B` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^ `B` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/issue-38404.rs:1:13 diff --git a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.rs b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.rs index 4aadd45c49c1e..3af299e5b115a 100644 --- a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.rs +++ b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.rs @@ -10,7 +10,6 @@ fn w<'a, T: 'a, F: Fn(&'a T)>() { let b: &dyn FromResidual = &(); //~^ ERROR: the trait `FromResidual` cannot be made into an object //~| ERROR: the trait `FromResidual` cannot be made into an object - //~| ERROR: the trait `FromResidual` cannot be made into an object } fn main() {} diff --git a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr index c67a8c05379cd..a131227e78e34 100644 --- a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr +++ b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr @@ -1,11 +1,3 @@ -error[E0038]: the trait `FromResidual` cannot be made into an object - --> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:10:17 - | -LL | let b: &dyn FromResidual = &(); - | ^^^^^^^^^^^^ - | - = note: it cannot use `Self` as a type parameter in a supertrait or `where`-clause - error[E0038]: the trait `FromResidual` cannot be made into an object --> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:10:32 | @@ -51,6 +43,6 @@ help: alternatively, consider constraining `from_residual` so it does not apply LL | fn from_residual(residual: R) -> Self where Self: Sized; | +++++++++++++++++ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0038`. From c977f8e9db369a7528584b2466966f816501c42e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 23 Nov 2024 18:46:50 +0000 Subject: [PATCH 3/5] Fix ICE when multiple supertrait substitutions need assoc but only one is provided --- .../src/hir_ty_lowering/dyn_compatibility.rs | 13 ++++-- .../src/hir_ty_lowering/errors.rs | 42 ++++++++++--------- .../missing-associated-types.stderr | 4 +- .../ui/dyn-compatibility/assoc_type_bounds.rs | 4 +- .../assoc_type_bounds.stderr | 4 +- .../dyn-compatibility/assoc_type_bounds2.rs | 4 +- .../assoc_type_bounds2.stderr | 4 +- .../require-assoc-for-all-super-substs.rs | 15 +++++++ .../require-assoc-for-all-super-substs.stderr | 12 ++++++ tests/ui/issues/issue-28344.stderr | 4 +- 10 files changed, 71 insertions(+), 35 deletions(-) create mode 100644 tests/ui/dyn-compatibility/require-assoc-for-all-super-substs.rs create mode 100644 tests/ui/dyn-compatibility/require-assoc-for-all-super-substs.stderr diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs index 2c642e1e5a869..3715225f0370d 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs @@ -119,16 +119,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let bound_predicate = pred.kind(); match bound_predicate.skip_binder() { ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => { - let pred = bound_predicate.rebind(pred); + // FIXME(negative_bounds): Handle this correctly... + let trait_ref = + tcx.anonymize_bound_vars(bound_predicate.rebind(pred.trait_ref)); needed_associated_types.extend( - tcx.associated_items(pred.def_id()) + tcx.associated_items(trait_ref.def_id()) .in_definition_order() .filter(|item| item.kind == ty::AssocKind::Type) .filter(|item| !item.is_impl_trait_in_trait()) // If the associated type has a `where Self: Sized` bound, // we do not need to constrain the associated type. .filter(|item| !tcx.generics_require_sized_self(item.def_id)) - .map(|item| item.def_id), + .map(|item| (item.def_id, trait_ref)), ); } ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => { @@ -180,7 +182,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // corresponding `Projection` clause for &(projection_bound, span) in &projection_bounds { let def_id = projection_bound.projection_def_id(); - needed_associated_types.swap_remove(&def_id); + let trait_ref = tcx.anonymize_bound_vars( + projection_bound.map_bound(|p| p.projection_term.trait_ref(tcx)), + ); + needed_associated_types.swap_remove(&(def_id, trait_ref)); if tcx.generics_require_sized_self(def_id) { tcx.emit_node_span_lint( UNUSED_ASSOCIATED_TYPE_BOUNDS, 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 5b5beb31f1c5b..299d085aa0d92 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -718,7 +718,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { pub(crate) fn check_for_required_assoc_tys( &self, spans: SmallVec<[Span; 1]>, - missing_assoc_types: FxIndexSet, + missing_assoc_types: FxIndexSet<(DefId, ty::PolyTraitRef<'tcx>)>, potential_assoc_types: Vec, trait_bounds: &[hir::PolyTraitRef<'_>], ) -> Result<(), ErrorGuaranteed> { @@ -729,27 +729,29 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let principal_span = *spans.first().unwrap(); let tcx = self.tcx(); - let missing_assoc_types: Vec<_> = - missing_assoc_types.into_iter().map(|def_id| tcx.associated_item(def_id)).collect(); - let mut names: FxIndexMap> = Default::default(); + // FIXME: This logic needs some more care w.r.t handling of conflicts + let missing_assoc_types: Vec<_> = missing_assoc_types + .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_len = 0; // 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 in &missing_assoc_types { - let trait_def_id = assoc_item.container_id(tcx); - names.entry(tcx.def_path_str(trait_def_id)).or_default().push(assoc_item.name); + for (assoc_item, trait_ref) in &missing_assoc_types { + names.entry(trait_ref).or_default().push(assoc_item.name); names_len += 1; let violations = - dyn_compatibility_violations_for_assoc_item(tcx, trait_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( tcx, principal_span, None, - trait_def_id, + trait_ref.def_id(), &violations, ) .emit()); @@ -800,6 +802,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .into_iter() .map(|(trait_, mut assocs)| { assocs.sort(); + let trait_ = trait_.print_trait_sugared(); format!("{} in `{trait_}`", match &assocs[..] { [] => String::new(), [only] => format!("`{only}`"), @@ -827,19 +830,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let mut already_has_generics_args_suggestion = false; let mut names: UnordMap<_, usize> = Default::default(); - for item in &missing_assoc_types { + for (item, _) in &missing_assoc_types { types_count += 1; *names.entry(item.name).or_insert(0) += 1; } let mut dupes = false; let mut shadows = false; - for item in &missing_assoc_types { + for (item, trait_ref) in &missing_assoc_types { let prefix = if names[&item.name] > 1 { - let trait_def_id = item.container_id(tcx); + let trait_def_id = trait_ref.def_id(); dupes = true; format!("{}::", tcx.def_path_str(trait_def_id)) } else if bound_names.get(&item.name).is_some_and(|x| *x != item) { - let trait_def_id = item.container_id(tcx); + let trait_def_id = trait_ref.def_id(); shadows = true; format!("{}::", tcx.def_path_str(trait_def_id)) } else { @@ -878,8 +881,10 @@ 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.iter().map(|item| format!("{} = Type", item.name)).collect(); + let types: Vec<_> = missing_assoc_types + .iter() + .map(|(item, _)| format!("{} = Type", item.name)) + .collect(); let code = if snippet.ends_with('>') { // 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 @@ -911,15 +916,14 @@ 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 { + for (item, _) in &missing_assoc_types { types_count += 1; *names.entry(item.name).or_insert(0) += 1; } let mut label = vec![]; - for item in &missing_assoc_types { + for (item, trait_ref) in &missing_assoc_types { let postfix = if names[&item.name] > 1 { - let trait_def_id = item.container_id(tcx); - format!(" (from trait `{}`)", tcx.def_path_str(trait_def_id)) + format!(" (from trait `{}`)", trait_ref.print_trait_sugared()) } else { String::new() }; diff --git a/tests/ui/associated-types/missing-associated-types.stderr b/tests/ui/associated-types/missing-associated-types.stderr index ce4b57e8af813..3a56c55896ebf 100644 --- a/tests/ui/associated-types/missing-associated-types.stderr +++ b/tests/ui/associated-types/missing-associated-types.stderr @@ -42,11 +42,11 @@ LL | type Bat = dyn Add + Sub + Fine; = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Add + Sub + Fine {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit -error[E0191]: the value of the associated types `Output` in `Div`, `Output` in `Mul` must be specified +error[E0191]: the value of the associated types `Output` in `Div`, `Output` in `Mul` must be specified --> $DIR/missing-associated-types.rs:20:21 | LL | type Bal = dyn X; - | ^^^^^^ associated types `Output` (from trait `Div`), `Output` (from trait `Mul`) must be specified + | ^^^^^^ associated types `Output` (from trait `Div`), `Output` (from trait `Mul`) must be specified | = help: consider introducing a new type parameter, adding `where` constraints using the fully-qualified path to the associated types diff --git a/tests/ui/dyn-compatibility/assoc_type_bounds.rs b/tests/ui/dyn-compatibility/assoc_type_bounds.rs index 8634ba626a18a..6e2076a482247 100644 --- a/tests/ui/dyn-compatibility/assoc_type_bounds.rs +++ b/tests/ui/dyn-compatibility/assoc_type_bounds.rs @@ -7,7 +7,7 @@ trait Foo { trait Cake {} impl Cake for () {} -fn foo(_: &dyn Foo<()>) {} //~ ERROR: the value of the associated type `Bar` in `Foo` must be specified -fn bar(_: &dyn Foo) {} //~ ERROR: the value of the associated type `Bar` in `Foo` must be specified +fn foo(_: &dyn Foo<()>) {} //~ ERROR: the value of the associated type `Bar` in `Foo<()>` must be specified +fn bar(_: &dyn Foo) {} //~ ERROR: the value of the associated type `Bar` in `Foo` must be specified fn main() {} diff --git a/tests/ui/dyn-compatibility/assoc_type_bounds.stderr b/tests/ui/dyn-compatibility/assoc_type_bounds.stderr index 3d5482625af3e..21ba903011739 100644 --- a/tests/ui/dyn-compatibility/assoc_type_bounds.stderr +++ b/tests/ui/dyn-compatibility/assoc_type_bounds.stderr @@ -1,4 +1,4 @@ -error[E0191]: the value of the associated type `Bar` in `Foo` must be specified +error[E0191]: the value of the associated type `Bar` in `Foo<()>` must be specified --> $DIR/assoc_type_bounds.rs:10:16 | LL | type Bar @@ -7,7 +7,7 @@ LL | type Bar LL | fn foo(_: &dyn Foo<()>) {} | ^^^^^^^ help: specify the associated type: `Foo<(), Bar = Type>` -error[E0191]: the value of the associated type `Bar` in `Foo` must be specified +error[E0191]: the value of the associated type `Bar` in `Foo` must be specified --> $DIR/assoc_type_bounds.rs:11:16 | LL | type Bar diff --git a/tests/ui/dyn-compatibility/assoc_type_bounds2.rs b/tests/ui/dyn-compatibility/assoc_type_bounds2.rs index f7dc2fb88390f..2b35016d774ce 100644 --- a/tests/ui/dyn-compatibility/assoc_type_bounds2.rs +++ b/tests/ui/dyn-compatibility/assoc_type_bounds2.rs @@ -7,7 +7,7 @@ trait Foo { trait Cake {} impl Cake for () {} -fn foo(_: &dyn Foo<()>) {} //~ ERROR: the value of the associated type `Bar` in `Foo` must be specified -fn bar(_: &dyn Foo) {} //~ ERROR: the value of the associated type `Bar` in `Foo` must be specified +fn foo(_: &dyn Foo<()>) {} //~ ERROR: the value of the associated type `Bar` in `Foo<()>` must be specified +fn bar(_: &dyn Foo) {} //~ ERROR: the value of the associated type `Bar` in `Foo` must be specified fn main() {} diff --git a/tests/ui/dyn-compatibility/assoc_type_bounds2.stderr b/tests/ui/dyn-compatibility/assoc_type_bounds2.stderr index 815747436bf0d..5c4163b196936 100644 --- a/tests/ui/dyn-compatibility/assoc_type_bounds2.stderr +++ b/tests/ui/dyn-compatibility/assoc_type_bounds2.stderr @@ -1,4 +1,4 @@ -error[E0191]: the value of the associated type `Bar` in `Foo` must be specified +error[E0191]: the value of the associated type `Bar` in `Foo<()>` must be specified --> $DIR/assoc_type_bounds2.rs:10:16 | LL | type Bar @@ -7,7 +7,7 @@ LL | type Bar LL | fn foo(_: &dyn Foo<()>) {} | ^^^^^^^ help: specify the associated type: `Foo<(), Bar = Type>` -error[E0191]: the value of the associated type `Bar` in `Foo` must be specified +error[E0191]: the value of the associated type `Bar` in `Foo` must be specified --> $DIR/assoc_type_bounds2.rs:11:16 | LL | type Bar diff --git a/tests/ui/dyn-compatibility/require-assoc-for-all-super-substs.rs b/tests/ui/dyn-compatibility/require-assoc-for-all-super-substs.rs new file mode 100644 index 0000000000000..1f4e1bf653a3f --- /dev/null +++ b/tests/ui/dyn-compatibility/require-assoc-for-all-super-substs.rs @@ -0,0 +1,15 @@ +trait Sup { + type Assoc: Default; +} + +impl Sup for () { + type Assoc = T; +} +impl Dyn for () {} + +trait Dyn: Sup + Sup {} + +fn main() { + let q: as Sup>::Assoc = Default::default(); + //~^ ERROR the value of the associated type `Assoc` in `Sup` must be specified +} 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 new file mode 100644 index 0000000000000..3d89b52d522db --- /dev/null +++ b/tests/ui/dyn-compatibility/require-assoc-for-all-super-substs.stderr @@ -0,0 +1,12 @@ +error[E0191]: the value of the associated type `Assoc` in `Sup` must be specified + --> $DIR/require-assoc-for-all-super-substs.rs:13:17 + | +LL | type Assoc: Default; + | ------------------- `Assoc` defined here +... +LL | let q: as Sup>::Assoc = Default::default(); + | ^^^^^^^^^^^^^ help: specify the associated type: `Dyn` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0191`. diff --git a/tests/ui/issues/issue-28344.stderr b/tests/ui/issues/issue-28344.stderr index d8febe7165241..7bc965536e9a1 100644 --- a/tests/ui/issues/issue-28344.stderr +++ b/tests/ui/issues/issue-28344.stderr @@ -12,7 +12,7 @@ help: if this is a dyn-compatible trait, use `dyn` LL | let x: u8 = ::bitor(0 as u8, 0 as u8); | ++++ + -error[E0191]: the value of the associated type `Output` in `BitXor` must be specified +error[E0191]: the value of the associated type `Output` in `BitXor<_>` must be specified --> $DIR/issue-28344.rs:4:17 | LL | let x: u8 = BitXor::bitor(0 as u8, 0 as u8); @@ -31,7 +31,7 @@ help: if this is a dyn-compatible trait, use `dyn` LL | let g = ::bitor; | ++++ + -error[E0191]: the value of the associated type `Output` in `BitXor` must be specified +error[E0191]: the value of the associated type `Output` in `BitXor<_>` must be specified --> $DIR/issue-28344.rs:9:13 | LL | let g = BitXor::bitor; From dad2ecf1098ebef021b6f79824f6b698bc742a65 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 4 Dec 2024 18:14:04 +0000 Subject: [PATCH 4/5] Fix dyn incompleteness --- .../src/hir_ty_lowering/dyn_compatibility.rs | 163 +++++++++++++++--- compiler/rustc_hir_typeck/src/closure.rs | 24 +-- compiler/rustc_lint_defs/src/builtin.rs | 16 ++ compiler/rustc_middle/src/ty/relate.rs | 16 +- compiler/rustc_middle/src/ty/sty.rs | 4 + .../src/solve/assembly/mod.rs | 9 + .../src/solve/assembly/structural_traits.rs | 15 +- .../src/traits/project.rs | 26 ++- .../rustc_trait_selection/src/traits/wf.rs | 13 +- compiler/rustc_type_ir/src/elaborate.rs | 48 +++++- compiler/rustc_type_ir/src/inherent.rs | 2 + src/tools/tidy/src/ui_tests.rs | 2 +- tests/crashes/125957.rs | 20 --- tests/crashes/132330.rs | 28 --- .../associated-types-overridden-binding-2.rs | 2 +- ...sociated-types-overridden-binding-2.stderr | 14 +- .../associated-types-overridden-binding.rs | 1 + ...associated-types-overridden-binding.stderr | 13 +- tests/ui/associated-types/issue-59324.rs | 3 +- tests/ui/associated-types/issue-59324.stderr | 18 +- .../closures/deduce-from-object-supertrait.rs | 15 ++ .../multiple-supers-should-work.rs | 18 ++ tests/ui/issues/issue-57156.rs | 2 + tests/ui/issues/issue-57156.stderr | 21 +++ tests/ui/issues/issue-59326.rs | 3 +- tests/ui/issues/issue-59326.stderr | 25 +++ .../crash-due-to-projections-modulo-norm.rs} | 17 +- ...rash-due-to-projections-modulo-norm.stderr | 26 +++ .../incomplete-multiple-super-projection.rs | 30 ++++ ...ncomplete-multiple-super-projection.stderr | 12 ++ .../infer-shadows-implied-projection.rs} | 0 .../infer-shadows-implied-projection.stderr | 21 +++ tests/ui/traits/object/outlives-super-proj.rs | 24 +++ tests/ui/traits/object/pretty.rs | 2 + tests/ui/traits/object/pretty.stderr | 59 +++++-- tests/ui/traits/object/redundant.rs | 13 ++ tests/ui/traits/object/redundant.stderr | 13 ++ ...n-projection-output-repeated-supertrait.rs | 1 + ...ojection-output-repeated-supertrait.stderr | 13 ++ tests/ui/wf/hir-wf-canonicalized.rs | 4 +- tests/ui/wf/hir-wf-canonicalized.stderr | 8 +- 41 files changed, 607 insertions(+), 157 deletions(-) delete mode 100644 tests/crashes/125957.rs delete mode 100644 tests/crashes/132330.rs create mode 100644 tests/ui/closures/deduce-from-object-supertrait.rs create mode 100644 tests/ui/dyn-compatibility/multiple-supers-should-work.rs create mode 100644 tests/ui/issues/issue-57156.stderr create mode 100644 tests/ui/issues/issue-59326.stderr rename tests/{crashes/126944.rs => ui/traits/object/crash-due-to-projections-modulo-norm.rs} (64%) create mode 100644 tests/ui/traits/object/crash-due-to-projections-modulo-norm.stderr create mode 100644 tests/ui/traits/object/incomplete-multiple-super-projection.rs create mode 100644 tests/ui/traits/object/incomplete-multiple-super-projection.stderr rename tests/{crashes/79590.rs => ui/traits/object/infer-shadows-implied-projection.rs} (100%) create mode 100644 tests/ui/traits/object/infer-shadows-implied-projection.stderr create mode 100644 tests/ui/traits/object/outlives-super-proj.rs create mode 100644 tests/ui/traits/object/redundant.rs create mode 100644 tests/ui/traits/object/redundant.stderr create mode 100644 tests/ui/traits/object/with-self-in-projection-output-repeated-supertrait.stderr diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs index 3715225f0370d..f3117fb334145 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs @@ -1,9 +1,13 @@ -use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; +use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::struct_span_code_err; use rustc_hir as hir; +use rustc_hir::HirId; use rustc_hir::def::{DefKind, Res}; -use rustc_lint_defs::builtin::UNUSED_ASSOCIATED_TYPE_BOUNDS; +use rustc_hir::def_id::DefId; +use rustc_lint_defs::builtin::{ + DYN_ASSOC_REDUNDANT, DYN_ASSOC_SHADOWED, UNUSED_ASSOCIATED_TYPE_BOUNDS, +}; use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::{ self, DynKind, ExistentialPredicateStableCmpExt as _, Ty, TyCtxt, TypeFoldable, @@ -28,7 +32,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { pub(super) fn lower_trait_object_ty( &self, span: Span, - hir_id: hir::HirId, + hir_id: HirId, hir_bounds: &[hir::PolyTraitRef<'tcx>], lifetime: &hir::Lifetime, representation: DynKind, @@ -80,12 +84,42 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } - let (trait_bounds, mut projection_bounds) = + let (expanded_trait_bounds, expanded_projection_bounds) = traits::expand_trait_aliases(tcx, user_written_bounds.clauses()); - let (regular_traits, mut auto_traits): (Vec<_>, Vec<_>) = trait_bounds + let (regular_traits, mut auto_traits): (Vec<_>, Vec<_>) = expanded_trait_bounds .into_iter() .partition(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id())); + // Map the projection bounds onto a key that makes it easy to remove redundant + // bounds that are constrained by supertraits of the principal def id. + let mut projection_bounds = FxIndexMap::default(); + for (proj, proj_span) in expanded_projection_bounds { + if let Some((old_proj, old_proj_span)) = projection_bounds.insert( + tcx.anonymize_bound_vars(proj.map_bound(|proj| proj.projection_term)), + (proj, proj_span), + ) && tcx.anonymize_bound_vars(proj) != tcx.anonymize_bound_vars(old_proj) + { + let item = tcx.item_name(proj.projection_def_id()); + self.dcx() + .struct_span_err( + span, + format!( + "conflicting associated type bounds for `{item}` when \ + expanding trait alias" + ), + ) + .with_span_label( + old_proj_span, + format!("`{item}` is specified to be `{}` here", old_proj.term()), + ) + .with_span_label( + proj_span, + format!("`{item}` is specified to be `{}` here", proj.term()), + ) + .emit(); + } + } + // We don't support empty trait objects. if regular_traits.is_empty() && auto_traits.is_empty() { let guar = @@ -105,6 +139,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let principal_trait = regular_traits.into_iter().next(); let mut needed_associated_types = FxIndexSet::default(); + + // These are the projection bounds that we get from supertraits that + // don't mention the dyn trait recursively. See comment below. + let mut implied_projection_bounds = vec![]; + if let Some((principal_trait, spans)) = &principal_trait { let pred: ty::Predicate<'tcx> = (*principal_trait).upcast(tcx); for ClauseWithSupertraitSpan { pred, supertrait_span } in @@ -134,14 +173,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ); } ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => { - let pred = bound_predicate.rebind(pred); + let elaborated_projection = bound_predicate.rebind(pred); // A `Self` within the original bound will be instantiated with a // `trait_object_dummy_self`, so check for that. - let references_self = match pred.skip_binder().term.unpack() { - ty::TermKind::Ty(ty) => ty.walk().any(|arg| arg == dummy_self.into()), - // FIXME(associated_const_equality): We should walk the const instead of not doing anything - ty::TermKind::Const(_) => false, - }; + let references_self = + match elaborated_projection.skip_binder().term.unpack() { + ty::TermKind::Ty(ty) => { + ty.walk().any(|arg| arg == dummy_self.into()) + } + // FIXME(associated_const_equality): We should walk the const instead of not doing anything + ty::TermKind::Const(_) => false, + }; // If the projection output contains `Self`, force the user to // elaborate it explicitly to avoid a lot of complexity. @@ -162,11 +204,38 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // the discussion in #56288 for alternatives. if !references_self { // Include projections defined on supertraits. - projection_bounds.push((pred, supertrait_span)); + implied_projection_bounds.push(elaborated_projection); + + if let Some((user_written_projection, user_written_span)) = + projection_bounds.shift_remove(&tcx.anonymize_bound_vars( + elaborated_projection.map_bound(|pred| pred.projection_term), + )) + { + if tcx.anonymize_bound_vars(user_written_projection) + == tcx.anonymize_bound_vars(elaborated_projection) + { + self.lint_redundant_projection( + hir_id, + user_written_projection, + principal_trait.def_id(), + user_written_span, + supertrait_span, + ); + } else { + self.lint_shadowed_projection( + hir_id, + user_written_projection, + elaborated_projection, + principal_trait.def_id(), + user_written_span, + supertrait_span, + ); + } + } } self.check_elaborated_projection_mentions_input_lifetimes( - pred, + elaborated_projection, *spans.first().unwrap(), supertrait_span, ); @@ -176,16 +245,16 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } - // `dyn Trait` desugars to (not Rust syntax) `dyn Trait where ::Assoc = Foo`. - // So every `Projection` clause is an `Assoc = Foo` bound. `associated_types` contains all associated - // types's `DefId`, so the following loop removes all the `DefIds` of the associated types that have a - // corresponding `Projection` clause - for &(projection_bound, span) in &projection_bounds { + // `dyn Trait` desugars to something like `dyn Trait + (Trait::Assoc = Foo)`. + // So every `Projection` clause is an `Assoc = Foo` bound. `associated_types` + // contains all associated types's `DefId`, so the following loop removes all + // the `DefIds` of the associated types that have a corresponding `Projection`. + for &(projection_bound, span) in projection_bounds.values() { let def_id = projection_bound.projection_def_id(); let trait_ref = tcx.anonymize_bound_vars( projection_bound.map_bound(|p| p.projection_term.trait_ref(tcx)), ); - needed_associated_types.swap_remove(&(def_id, trait_ref)); + needed_associated_types.shift_remove(&(def_id, trait_ref)); if tcx.generics_require_sized_self(def_id) { tcx.emit_node_span_lint( UNUSED_ASSOCIATED_TYPE_BOUNDS, @@ -195,6 +264,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ); } } + for projection_bound in &implied_projection_bounds { + let def_id = projection_bound.projection_def_id(); + let trait_ref = tcx.anonymize_bound_vars( + projection_bound.map_bound(|p| p.projection_term.trait_ref(tcx)), + ); + needed_associated_types.swap_remove(&(def_id, trait_ref)); + } if let Err(guar) = self.check_for_required_assoc_tys( principal_trait.as_ref().map_or(smallvec![], |(_, spans)| spans.clone()), @@ -272,7 +348,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }) }); - let existential_projections = projection_bounds.iter().map(|(bound, _)| { + let existential_projections = projection_bounds.values().map(|(bound, _)| { bound.map_bound(|mut b| { assert_eq!(b.projection_term.self_ty(), dummy_self); @@ -349,6 +425,53 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { Ty::new_dynamic(tcx, existential_predicates, region_bound, representation) } + fn lint_shadowed_projection( + &self, + hir_id: HirId, + user_written_projection: ty::PolyProjectionPredicate<'tcx>, + elaborated_projection: ty::PolyProjectionPredicate<'tcx>, + principal_def_id: DefId, + user_written_span: Span, + supertrait_span: Span, + ) { + let tcx = self.tcx(); + let assoc = tcx.item_name(user_written_projection.projection_def_id()); + let principal = tcx.item_name(principal_def_id); + self.tcx().node_span_lint(DYN_ASSOC_SHADOWED, hir_id, user_written_span, |diag| { + diag.primary_message(format!( + "associated type bound for `{assoc}` in `dyn {principal}` differs from \ + associated type bound implied by supertrait", + )); + diag.span_label(user_written_span, "this bound has no effect and will be ignored"); + diag.note(format!( + "`{assoc} = {}` was implied by a supertrait and shadows any user-written bounds, \ + so `{assoc} = {}` will be ignored", + elaborated_projection.term(), + user_written_projection.term(), + )); + diag.span_label(supertrait_span, "shadowed due to this supertrait bound"); + }); + } + + fn lint_redundant_projection( + &self, + hir_id: HirId, + user_written_projection: ty::PolyProjectionPredicate<'tcx>, + principal_def_id: DefId, + user_written_span: Span, + supertrait_span: Span, + ) { + let tcx = self.tcx(); + let assoc = tcx.item_name(user_written_projection.projection_def_id()); + let principal = tcx.item_name(principal_def_id); + self.tcx().node_span_lint(DYN_ASSOC_REDUNDANT, hir_id, user_written_span, |diag| { + diag.primary_message(format!( + "associated type bound for `{assoc}` in `dyn {principal}` is redundant", + )); + diag.span_label(supertrait_span, "redundant due to this supertrait bound"); + }); + } + /// Check that elaborating the principal of a trait ref doesn't lead to projections /// that are unconstrained. This can happen because an otherwise unconstrained /// *type variable* can be substituted with a type that has late-bound regions. See diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index e715a7f7e1588..56d3a24560d88 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -18,7 +18,7 @@ use rustc_span::def_id::LocalDefId; use rustc_span::{DUMMY_SP, Span}; use rustc_trait_selection::error_reporting::traits::ArgKind; use rustc_trait_selection::traits; -use rustc_type_ir::ClosureKind; +use rustc_type_ir::{ClosureKind, Upcast as _}; use tracing::{debug, instrument, trace}; use super::{CoroutineTypes, Expectation, FnCtxt, check_fn}; @@ -312,16 +312,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .iter_instantiated_copied(self.tcx, args) .map(|(c, s)| (c.as_predicate(), s)), ), - ty::Dynamic(object_type, ..) => { - let sig = object_type.projection_bounds().find_map(|pb| { - let pb = pb.with_self_ty(self.tcx, self.tcx.types.trait_object_dummy_self); - self.deduce_sig_from_projection(None, closure_kind, pb) - }); - let kind = object_type - .principal_def_id() - .and_then(|did| self.tcx.fn_trait_kind_from_def_id(did)); - (sig, kind) - } + ty::Dynamic(data, ..) => self.deduce_closure_signature_from_predicates( + self.tcx.types.trait_object_dummy_self, + closure_kind, + data.iter().map(|bound| { + ( + bound + .with_self_ty(self.tcx, self.tcx.types.trait_object_dummy_self) + .upcast(self.tcx), + DUMMY_SP, + ) + }), + ), ty::Infer(ty::TyVar(vid)) => self.deduce_closure_signature_from_predicates( Ty::new_var(self.tcx, self.root_var(vid)), closure_kind, diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index d2b7ae620e2b4..58783df81cc59 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -39,6 +39,8 @@ declare_lint_pass! { DEPRECATED_SAFE_2024, DEPRECATED_WHERE_CLAUSE_LOCATION, DUPLICATE_MACRO_ATTRIBUTES, + DYN_ASSOC_REDUNDANT, + DYN_ASSOC_SHADOWED, ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT, ELIDED_LIFETIMES_IN_PATHS, ELIDED_NAMED_LIFETIMES, @@ -5112,6 +5114,20 @@ declare_lint! { crate_level_only } +declare_lint! { + /// Hi + pub DYN_ASSOC_REDUNDANT, + Warn, + "oops", +} + +declare_lint! { + /// Hi + pub DYN_ASSOC_SHADOWED, + Deny, + "oops", +} + declare_lint! { /// The `abi_unsupported_vector_types` lint detects function definitions and calls /// whose ABI depends on enabling certain target features, but those features are not enabled. diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index afdec7a86d445..5bc2a40016e17 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -80,19 +80,12 @@ impl<'tcx> Relate> for &'tcx ty::List RelateResult<'tcx, Self> { let tcx = relation.cx(); - // FIXME: this is wasteful, but want to do a perf run to see how slow it is. - // We need to perform this deduplication as we sometimes generate duplicate projections - // in `a`. - let mut a_v: Vec<_> = a.into_iter().collect(); - let mut b_v: Vec<_> = b.into_iter().collect(); - a_v.dedup(); - b_v.dedup(); - if a_v.len() != b_v.len() { + if a.len() != b.len() { return Err(TypeError::ExistentialMismatch(ExpectedFound::new(a, b))); } - let v = iter::zip(a_v, b_v).map(|(ep_a, ep_b)| { - match (ep_a.skip_binder(), ep_b.skip_binder()) { + let v = + iter::zip(a, b).map(|(ep_a, ep_b)| match (ep_a.skip_binder(), ep_b.skip_binder()) { (ty::ExistentialPredicate::Trait(a), ty::ExistentialPredicate::Trait(b)) => { Ok(ep_a.rebind(ty::ExistentialPredicate::Trait( relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(), @@ -109,8 +102,7 @@ impl<'tcx> Relate> for &'tcx ty::List Ok(ep_a.rebind(ty::ExistentialPredicate::AutoTrait(a))), _ => Err(TypeError::ExistentialMismatch(ExpectedFound::new(a, b))), - } - }); + }); tcx.mk_poly_existential_predicates_from_iter(v) } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 142db8a17f04f..64cc3ac39a8dd 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -978,6 +978,10 @@ impl<'tcx> rustc_type_ir::inherent::Ty> for Ty<'tcx> { fn async_destructor_ty(self, interner: TyCtxt<'tcx>) -> Ty<'tcx> { self.async_destructor_ty(interner) } + + fn is_self_param(self) -> bool { + self.is_param(0) + } } /// Type utilities diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index 198ccb000f345..12e08c990c344 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -696,6 +696,15 @@ where assumption.upcast(cx), )); } + + for assumption in elaborate::implied_supertrait_projections(cx, principal) { + candidates.extend(G::probe_and_consider_object_bound_candidate( + self, + CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), + goal, + assumption.with_self_ty(cx, self_ty).upcast(cx), + )); + } } } diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index 05ce61bc0678f..307a3558ffe7c 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -3,7 +3,7 @@ use derive_where::derive_where; use rustc_ast_ir::{Movability, Mutability}; -use rustc_type_ir::data_structures::HashMap; +use rustc_type_ir::data_structures::{HashMap, HashSet}; use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::TraitSolverLangItem; @@ -841,6 +841,14 @@ where .map(|(pred, _)| pred), )); + // It's sufficient to just keep track of the def ids of the explicitly specified + // associated types since when users write `dyn Trait`, that associated + // type must resolve to *one* bound from all of the supertraits. So the fact that + // there is a user-provided projection is enough proof that it's unique and we don't + // need to care about substitutions or anything like that. + let specified_associated_projections: HashSet<_> = + object_bounds.projection_bounds().into_iter().map(|proj| proj.item_def_id()).collect(); + // FIXME(associated_const_equality): Also add associated consts to // the requirements here. for associated_type_def_id in cx.associated_type_def_ids(trait_ref.def_id) { @@ -850,6 +858,11 @@ where continue; } + // We don't require these bounds to hold for supertrait implied projection bounds. + if !specified_associated_projections.contains(&associated_type_def_id) { + continue; + } + requirements .extend(cx.item_bounds(associated_type_def_id).iter_instantiated(cx, trait_ref.args)); } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 49c34550f8e03..a300b760ef047 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -18,6 +18,7 @@ use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{self, Term, Ty, TyCtxt, TypingMode, Upcast}; use rustc_middle::{bug, span_bug}; use rustc_span::symbol::sym; +use rustc_type_ir::elaborate; use tracing::{debug, instrument}; use super::{ @@ -59,7 +60,7 @@ enum ProjectionCandidate<'tcx> { TraitDef(ty::PolyProjectionPredicate<'tcx>), /// Bounds specified on an object type - Object(ty::PolyProjectionPredicate<'tcx>), + Object(ty::PolyProjectionPredicate<'tcx>, bool), /// From an "impl" (or a "pseudo-impl" returned by select) Select(Selection<'tcx>), @@ -658,7 +659,7 @@ fn project<'cx, 'tcx>( assemble_candidates_from_object_ty(selcx, obligation, &mut candidates); - if let ProjectionCandidateSet::Single(ProjectionCandidate::Object(_)) = candidates { + if let ProjectionCandidateSet::Single(ProjectionCandidate::Object(..)) = candidates { // Avoid normalization cycle from selection (see // `assemble_candidates_from_object_ty`). // FIXME(lazy_normalization): Lazy normalization should save us from @@ -814,6 +815,7 @@ fn assemble_candidates_from_object_ty<'cx, 'tcx>( } _ => return, }; + let env_predicates = data .projection_bounds() .filter(|bound| bound.item_def_id() == obligation.predicate.def_id) @@ -823,10 +825,22 @@ fn assemble_candidates_from_object_ty<'cx, 'tcx>( selcx, obligation, candidate_set, - ProjectionCandidate::Object, + |c| ProjectionCandidate::Object(c, false), env_predicates, false, ); + + if let Some(principal) = data.principal() { + assemble_candidates_from_predicates( + selcx, + obligation, + candidate_set, + |c| ProjectionCandidate::Object(c, true), + elaborate::implied_supertrait_projections(tcx, principal) + .map(|pred| pred.with_self_ty(tcx, object_ty).upcast(tcx)), + true, + ); + } } #[instrument( @@ -1235,10 +1249,12 @@ fn confirm_candidate<'cx, 'tcx>( ) -> Progress<'tcx> { debug!(?obligation, ?candidate, "confirm_candidate"); let mut progress = match candidate { - ProjectionCandidate::ParamEnv(poly_projection) - | ProjectionCandidate::Object(poly_projection) => { + ProjectionCandidate::ParamEnv(poly_projection) => { confirm_param_env_candidate(selcx, obligation, poly_projection, false) } + ProjectionCandidate::Object(poly_projection, from_super) => { + confirm_param_env_candidate(selcx, obligation, poly_projection, from_super) + } ProjectionCandidate::TraitDef(poly_projection) => { confirm_param_env_candidate(selcx, obligation, poly_projection, true) diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index c95b1641d1ffe..08a2170b928d9 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -10,6 +10,7 @@ use rustc_middle::ty::{ }; use rustc_span::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; use rustc_span::{DUMMY_SP, Span}; +use rustc_type_ir::elaborate; use tracing::{debug, instrument, trace}; use crate::infer::InferCtxt; @@ -632,7 +633,6 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { // am looking forward to the future here. if !data.has_escaping_bound_vars() && !region.has_escaping_bound_vars() { let implicit_bounds = object_region_bounds(self.tcx(), data); - let explicit_bound = region; self.out.reserve(implicit_bounds.len()); @@ -853,6 +853,17 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { )); } } + + // Finally, for backwards compatibility reasons, we imply the outlives bounds + // that come from supertrait projections since we used to elaborate them into + // the dyn trait itself. + // + // See when this was changed. + if let Some(principal) = data.principal() { + for projection in elaborate::implied_supertrait_projections(tcx, principal) { + projection.visit_with(self); + } + } } // Inference variables are the complicated case, since we don't diff --git a/compiler/rustc_type_ir/src/elaborate.rs b/compiler/rustc_type_ir/src/elaborate.rs index 0d574445df80d..38e2b9c338065 100644 --- a/compiler/rustc_type_ir/src/elaborate.rs +++ b/compiler/rustc_type_ir/src/elaborate.rs @@ -1,11 +1,13 @@ use std::marker::PhantomData; +use std::ops::ControlFlow; use smallvec::smallvec; use crate::data_structures::HashSet; use crate::inherent::*; use crate::outlives::{Component, push_outlives_components}; -use crate::{self as ty, Interner, Upcast as _}; +use crate::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; +use crate::{self as ty, Interner, TypeFlags, Upcast as _}; /// "Elaboration" is the process of identifying all the predicates that /// are implied by a source predicate. Currently, this basically means @@ -337,3 +339,47 @@ impl> Iterator for FilterToTraits( + cx: I, + principal: ty::Binder>, +) -> impl Iterator>> { + // We check that the predicates don't mention self, so we + // don't care about what self type we substitute here. + let principal = principal.with_self_ty(cx, Ty::new_unit(cx)); + + // Make sure we only elaborate one copy of every projection (modulo bound vars) + let mut seen = HashSet::default(); + + let clause: I::Clause = ty::TraitRef::identity(cx, principal.def_id()).upcast(cx); + elaborate(cx, [clause]) + .filter_only_self() + .filter(move |clause| { + clause.as_projection_clause().is_some_and(|proj_pred| { + proj_pred.term().visit_with(&mut MentionsSelf).is_continue() + }) + }) + .map(move |clause| clause.instantiate_supertrait(cx, principal)) + .map(move |clause| { + clause + .as_projection_clause() + .unwrap() + .map_bound(|proj| ty::ExistentialProjection::erase_self_ty(cx, proj)) + }) + .filter(move |proj_pred| seen.insert(cx.anonymize_bound_vars(*proj_pred))) +} + +struct MentionsSelf; +impl TypeVisitor for MentionsSelf { + type Result = ControlFlow<()>; + + fn visit_ty(&mut self, ty: I::Ty) -> Self::Result { + if ty.is_self_param() { + ControlFlow::Break(()) + } else if ty.has_type_flags(TypeFlags::HAS_TY_PARAM) { + ty.super_visit_with(self) + } else { + ControlFlow::Continue(()) + } + } +} diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index a201f2b1c11f1..b5b4d685671c5 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -136,6 +136,8 @@ pub trait Ty>: matches!(self.kind(), ty::FnPtr(..)) } + fn is_self_param(self) -> bool; + fn fn_sig(self, interner: I) -> ty::Binder> { match self.kind() { ty::FnPtr(sig_tys, hdr) => sig_tys.with(hdr), diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 11f9d5bb03df7..1daf01234a95c 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -17,7 +17,7 @@ use ignore::Walk; const ENTRY_LIMIT: u32 = 901; // FIXME: The following limits should be reduced eventually. -const ISSUES_ENTRY_LIMIT: u32 = 1672; +const ISSUES_ENTRY_LIMIT: u32 = 1674; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ "rs", // test source files diff --git a/tests/crashes/125957.rs b/tests/crashes/125957.rs deleted file mode 100644 index e3abe5262eb90..0000000000000 --- a/tests/crashes/125957.rs +++ /dev/null @@ -1,20 +0,0 @@ -//@ known-bug: rust-lang/rust#125957 -#![feature(generic_const_exprs)] -#![allow(incomplete_features)] -#![feature(associated_const_equality)] - -pub struct Equal(); - -pub enum ParseMode { - Raw, -} -pub trait Parse { - const PARSE_MODE: ParseMode; -} -pub trait RenderRaw: Parse {} - -trait GenericVec { - fn unwrap() -> dyn RenderRaw; -} - -fn main() {} diff --git a/tests/crashes/132330.rs b/tests/crashes/132330.rs deleted file mode 100644 index 3432685749d9d..0000000000000 --- a/tests/crashes/132330.rs +++ /dev/null @@ -1,28 +0,0 @@ -//@ known-bug: #132330 -//@compile-flags: -Znext-solver=globally - -trait Service { - type S; -} - -trait Framing { - type F; -} - -impl Framing for () { - type F = (); -} - -trait HttpService: Service {} - -type BoxService = Box>; - -fn build_server BoxService>(_: F) {} - -fn make_server() -> Box> { - unimplemented!() -} - -fn main() { - build_server(|| make_server()) -} diff --git a/tests/ui/associated-types/associated-types-overridden-binding-2.rs b/tests/ui/associated-types/associated-types-overridden-binding-2.rs index fed60ccf089d0..247724eaaf112 100644 --- a/tests/ui/associated-types/associated-types-overridden-binding-2.rs +++ b/tests/ui/associated-types/associated-types-overridden-binding-2.rs @@ -4,5 +4,5 @@ trait I32Iterator = Iterator; fn main() { let _: &dyn I32Iterator = &vec![42].into_iter(); - //~^ ERROR expected `IntoIter` to be an iterator that yields `i32`, but it yields `u32` + //~^ ERROR conflicting associated type bounds } diff --git a/tests/ui/associated-types/associated-types-overridden-binding-2.stderr b/tests/ui/associated-types/associated-types-overridden-binding-2.stderr index 4dfd275a19058..71a4a2610aac4 100644 --- a/tests/ui/associated-types/associated-types-overridden-binding-2.stderr +++ b/tests/ui/associated-types/associated-types-overridden-binding-2.stderr @@ -1,11 +1,13 @@ -error[E0271]: expected `IntoIter` to be an iterator that yields `i32`, but it yields `u32` - --> $DIR/associated-types-overridden-binding-2.rs:6:43 +error: conflicting associated type bounds for `Item` when expanding trait alias + --> $DIR/associated-types-overridden-binding-2.rs:6:13 | +LL | trait I32Iterator = Iterator; + | ---------- `Item` is specified to be `i32` here +... LL | let _: &dyn I32Iterator = &vec![42].into_iter(); - | ^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `u32` - | - = note: required for the cast from `&std::vec::IntoIter` to `&dyn Iterator` + | ^^^^^^^^^^^^^^^^----------^ + | | + | `Item` is specified to be `u32` here error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/associated-types/associated-types-overridden-binding.rs b/tests/ui/associated-types/associated-types-overridden-binding.rs index 9a64a06c31bad..333a3e30c7dcf 100644 --- a/tests/ui/associated-types/associated-types-overridden-binding.rs +++ b/tests/ui/associated-types/associated-types-overridden-binding.rs @@ -8,4 +8,5 @@ trait U32Iterator = I32Iterator; //~ ERROR type annotations needed fn main() { let _: &dyn I32Iterator; + //~^ ERROR conflicting associated type bounds } diff --git a/tests/ui/associated-types/associated-types-overridden-binding.stderr b/tests/ui/associated-types/associated-types-overridden-binding.stderr index dc087e4185fb6..3b20015dfcab3 100644 --- a/tests/ui/associated-types/associated-types-overridden-binding.stderr +++ b/tests/ui/associated-types/associated-types-overridden-binding.stderr @@ -22,6 +22,17 @@ note: required by a bound in `I32Iterator` LL | trait I32Iterator = Iterator; | ^^^^^^^^^^ required by this bound in `I32Iterator` -error: aborting due to 2 previous errors +error: conflicting associated type bounds for `Item` when expanding trait alias + --> $DIR/associated-types-overridden-binding.rs:10:13 + | +LL | trait I32Iterator = Iterator; + | ---------- `Item` is specified to be `i32` here +... +LL | let _: &dyn I32Iterator; + | ^^^^^^^^^^^^^^^^----------^ + | | + | `Item` is specified to be `u32` here + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/associated-types/issue-59324.rs b/tests/ui/associated-types/issue-59324.rs index 7421e08c89888..a05789c616cb3 100644 --- a/tests/ui/associated-types/issue-59324.rs +++ b/tests/ui/associated-types/issue-59324.rs @@ -21,8 +21,7 @@ pub trait ThriftService: } fn with_factory(factory: dyn ThriftService<()>) {} -//~^ ERROR the trait bound `(): Foo` is not satisfied +//~^ ERROR cannot be known at compilation time //~| ERROR the trait bound `(): Foo` is not satisfied -//~| ERROR cannot be known at compilation time fn main() {} diff --git a/tests/ui/associated-types/issue-59324.stderr b/tests/ui/associated-types/issue-59324.stderr index 6c77ee6044f16..a886c8ecef29e 100644 --- a/tests/ui/associated-types/issue-59324.stderr +++ b/tests/ui/associated-types/issue-59324.stderr @@ -66,25 +66,13 @@ help: consider further restricting this bound LL | pub trait ThriftService: | +++++ -error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/issue-59324.rs:23:52 - | -LL | fn with_factory(factory: dyn ThriftService<()>) {} - | ^^ the trait `Foo` is not implemented for `()` - | -help: this trait has no implementations, consider adding one - --> $DIR/issue-59324.rs:3:1 - | -LL | pub trait Foo: NotFoo { - | ^^^^^^^^^^^^^^^^^^^^^ - -error[E0277]: the size for values of type `(dyn ThriftService<(), AssocType = _> + 'static)` cannot be known at compilation time +error[E0277]: the size for values of type `(dyn ThriftService<()> + 'static)` cannot be known at compilation time --> $DIR/issue-59324.rs:23:29 | LL | fn with_factory(factory: dyn ThriftService<()>) {} | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: the trait `Sized` is not implemented for `(dyn ThriftService<(), AssocType = _> + 'static)` + = help: the trait `Sized` is not implemented for `(dyn ThriftService<()> + 'static)` = help: unsized fn params are gated as an unstable feature help: you can use `impl Trait` as the argument type | @@ -95,6 +83,6 @@ help: function arguments must have a statically known size, borrowed types alway LL | fn with_factory(factory: &dyn ThriftService<()>) {} | + -error: aborting due to 7 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/closures/deduce-from-object-supertrait.rs b/tests/ui/closures/deduce-from-object-supertrait.rs new file mode 100644 index 0000000000000..315d90c4c5086 --- /dev/null +++ b/tests/ui/closures/deduce-from-object-supertrait.rs @@ -0,0 +1,15 @@ +//@ check-pass + +trait Foo: Fn(Bar) {} +impl Foo for T where T: Fn(Bar) {} + +struct Bar; +impl Bar { + fn bar(&self) {} +} + +fn main() { + let x: &dyn Foo = &|x| { + x.bar(); + }; +} diff --git a/tests/ui/dyn-compatibility/multiple-supers-should-work.rs b/tests/ui/dyn-compatibility/multiple-supers-should-work.rs new file mode 100644 index 0000000000000..355089b9a9d89 --- /dev/null +++ b/tests/ui/dyn-compatibility/multiple-supers-should-work.rs @@ -0,0 +1,18 @@ +//@ check-pass + +trait Sup { + type Assoc; +} + +impl Sup for () { + type Assoc = T; +} + +trait Trait: Sup + Sup {} + +impl Trait for () {} + +fn main() { + let x: &dyn Trait<(), _> = &(); + let y: &dyn Trait<_, ()> = x; +} diff --git a/tests/ui/issues/issue-57156.rs b/tests/ui/issues/issue-57156.rs index 12251509abd2d..0a6023d70831b 100644 --- a/tests/ui/issues/issue-57156.rs +++ b/tests/ui/issues/issue-57156.rs @@ -6,6 +6,7 @@ trait Foo { trait Bar<'a, T>: for<'s> Foo<&'s T, Output=bool> { fn cb(&self) -> Box>; + //~^ WARN associated type bound for `Output` in `dyn Bar` is redundant } impl<'s> Foo<&'s ()> for () { @@ -14,6 +15,7 @@ impl<'s> Foo<&'s ()> for () { impl<'a> Bar<'a, ()> for () { fn cb(&self) -> Box> { + //~^ WARN associated type bound for `Output` in `dyn Bar` is redundant Box::new(*self) } } diff --git a/tests/ui/issues/issue-57156.stderr b/tests/ui/issues/issue-57156.stderr new file mode 100644 index 0000000000000..e9072e203fb7c --- /dev/null +++ b/tests/ui/issues/issue-57156.stderr @@ -0,0 +1,21 @@ +warning: associated type bound for `Output` in `dyn Bar` is redundant + --> $DIR/issue-57156.rs:8:40 + | +LL | trait Bar<'a, T>: for<'s> Foo<&'s T, Output=bool> { + | ----------- redundant due to this supertrait bound +LL | fn cb(&self) -> Box>; + | ^^^^^^^^^^^ + | + = note: `#[warn(dyn_assoc_redundant)]` on by default + +warning: associated type bound for `Output` in `dyn Bar` is redundant + --> $DIR/issue-57156.rs:17:41 + | +LL | trait Bar<'a, T>: for<'s> Foo<&'s T, Output=bool> { + | ----------- redundant due to this supertrait bound +... +LL | fn cb(&self) -> Box> { + | ^^^^^^^^^^^ + +warning: 2 warnings emitted + diff --git a/tests/ui/issues/issue-59326.rs b/tests/ui/issues/issue-59326.rs index e9634ad9fd8fe..6bfb875c5a73a 100644 --- a/tests/ui/issues/issue-59326.rs +++ b/tests/ui/issues/issue-59326.rs @@ -1,4 +1,3 @@ -//@ check-pass trait Service { type S; } @@ -14,10 +13,12 @@ impl Framing for () { trait HttpService: Service {} type BoxService = Box>; +//~^ ERROR associated type bound for `S` in `dyn HttpService` differs from bound implied by supertraits fn build_server BoxService>(_: F) {} fn make_server() -> Box> { + //~^ WARN associated type bound for `S` in `dyn HttpService` is redundant unimplemented!() } diff --git a/tests/ui/issues/issue-59326.stderr b/tests/ui/issues/issue-59326.stderr new file mode 100644 index 0000000000000..1a4d27ad8dca5 --- /dev/null +++ b/tests/ui/issues/issue-59326.stderr @@ -0,0 +1,25 @@ +error: associated type bound for `S` in `dyn HttpService` differs from associated type bound implied by supertrait + --> $DIR/issue-59326.rs:15:43 + | +LL | trait HttpService: Service {} + | -------- shadowed due to this supertrait bound +LL | +LL | type BoxService = Box>; + | ^^^^^^ this bound has no effect and will be ignored + | + = note: `S = <() as Framing>::F` was implied by a supertrait and shadows any user-written bounds, so `S = ()` will be ignored + = note: `#[deny(dyn_assoc_shadowed)]` on by default + +warning: associated type bound for `S` in `dyn HttpService` is redundant + --> $DIR/issue-59326.rs:20:56 + | +LL | trait HttpService: Service {} + | -------- redundant due to this supertrait bound +... +LL | fn make_server() -> Box> { + | ^^^^^^^^ + | + = note: `#[warn(dyn_assoc_redundant)]` on by default + +error: aborting due to 1 previous error; 1 warning emitted + diff --git a/tests/crashes/126944.rs b/tests/ui/traits/object/crash-due-to-projections-modulo-norm.rs similarity index 64% rename from tests/crashes/126944.rs rename to tests/ui/traits/object/crash-due-to-projections-modulo-norm.rs index c0c5622e26020..383000376e0dc 100644 --- a/tests/crashes/126944.rs +++ b/tests/ui/traits/object/crash-due-to-projections-modulo-norm.rs @@ -1,9 +1,8 @@ -//@ known-bug: rust-lang/rust#126944 // Step 1: Create two names for a single type: `Thing` and `AlsoThing` struct Thing; struct Dummy; -pub trait DummyTrait { +trait DummyTrait { type DummyType; } impl DummyTrait for Dummy { @@ -13,7 +12,7 @@ type AlsoThing = ::DummyType; // Step 2: Create names for a single trait object type: `TraitObject` and `AlsoTraitObject` -pub trait SomeTrait { +trait SomeTrait { type Item; } type TraitObject = dyn SomeTrait; @@ -21,18 +20,22 @@ type AlsoTraitObject = dyn SomeTrait; // Step 3: Force the compiler to check whether the two names are the same type -pub trait Supertrait { +trait Supertrait { type Foo; } -pub trait Subtrait: Supertrait {} +trait Subtrait: Supertrait {} -pub trait HasOutput { +trait HasOutput { type Output; } fn foo() -> F::Output where F: HasOutput>, -{ + //~^ ERROR associated type bound for `Foo` in `dyn Subtrait` differs from bound implied by supertraits + //~| ERROR associated type bound for `Foo` in `dyn Subtrait` differs from bound implied by supertraits + { todo!() } + +fn main() {} diff --git a/tests/ui/traits/object/crash-due-to-projections-modulo-norm.stderr b/tests/ui/traits/object/crash-due-to-projections-modulo-norm.stderr new file mode 100644 index 0000000000000..d72efc3fbc913 --- /dev/null +++ b/tests/ui/traits/object/crash-due-to-projections-modulo-norm.stderr @@ -0,0 +1,26 @@ +error: associated type bound for `Foo` in `dyn Subtrait` differs from associated type bound implied by supertrait + --> $DIR/crash-due-to-projections-modulo-norm.rs:34:31 + | +LL | trait Subtrait: Supertrait {} + | ----------------- shadowed due to this supertrait bound +... +LL | F: HasOutput>, + | ^^^^^^^^^^^^^^^^^^^^^ this bound has no effect and will be ignored + | + = note: `Foo = (dyn SomeTrait::DummyType> + 'static)` was implied by a supertrait and shadows any user-written bounds, so `Foo = (dyn SomeTrait + 'static)` will be ignored + = note: `#[deny(dyn_assoc_shadowed)]` on by default + +error: associated type bound for `Foo` in `dyn Subtrait` differs from associated type bound implied by supertrait + --> $DIR/crash-due-to-projections-modulo-norm.rs:34:31 + | +LL | trait Subtrait: Supertrait {} + | ----------------- shadowed due to this supertrait bound +... +LL | F: HasOutput>, + | ^^^^^^^^^^^^^^^^^^^^^ this bound has no effect and will be ignored + | + = note: `Foo = (dyn SomeTrait::DummyType> + 'static)` was implied by a supertrait and shadows any user-written bounds, so `Foo = (dyn SomeTrait + 'static)` will be ignored + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/traits/object/incomplete-multiple-super-projection.rs b/tests/ui/traits/object/incomplete-multiple-super-projection.rs new file mode 100644 index 0000000000000..c9f099b9a36de --- /dev/null +++ b/tests/ui/traits/object/incomplete-multiple-super-projection.rs @@ -0,0 +1,30 @@ +trait Sup { + type Assoc; +} + +impl Sup for () { + type Assoc = T; +} +impl Dyn for () {} + +trait Dyn: Sup + Sup {} + +trait Trait { + type Assoc; +} +impl Trait for dyn Dyn<(), ()> { + type Assoc = &'static str; +} +impl Trait for dyn Dyn { +//~^ ERROR conflicting implementations of trait `Trait` for type `(dyn Dyn<(), ()> + 'static)` + type Assoc = usize; +} + +fn call(x: usize) -> as Trait>::Assoc { + x +} + +fn main() { + let x: &'static str = call::<(), ()>(0xDEADBEEF); + println!("{x}"); +} diff --git a/tests/ui/traits/object/incomplete-multiple-super-projection.stderr b/tests/ui/traits/object/incomplete-multiple-super-projection.stderr new file mode 100644 index 0000000000000..90ad9e3272186 --- /dev/null +++ b/tests/ui/traits/object/incomplete-multiple-super-projection.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `Trait` for type `(dyn Dyn<(), ()> + 'static)` + --> $DIR/incomplete-multiple-super-projection.rs:18:1 + | +LL | impl Trait for dyn Dyn<(), ()> { + | ------------------------------ first implementation here +... +LL | impl Trait for dyn Dyn { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Dyn<(), ()> + 'static)` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/crashes/79590.rs b/tests/ui/traits/object/infer-shadows-implied-projection.rs similarity index 100% rename from tests/crashes/79590.rs rename to tests/ui/traits/object/infer-shadows-implied-projection.rs diff --git a/tests/ui/traits/object/infer-shadows-implied-projection.stderr b/tests/ui/traits/object/infer-shadows-implied-projection.stderr new file mode 100644 index 0000000000000..c4f93a6de56b0 --- /dev/null +++ b/tests/ui/traits/object/infer-shadows-implied-projection.stderr @@ -0,0 +1,21 @@ +error: associated type bound for `Inner` in `dyn Database` differs from associated type bound implied by supertrait + --> $DIR/infer-shadows-implied-projection.rs:18:26 + | +LL | trait Database: Restriction {} + | ----------- shadowed due to this supertrait bound +... +LL | let x: &dyn Database = &t; + | ^^^^^^^^^ this bound has no effect and will be ignored + | + = note: `Inner = u32` was implied by a supertrait and shadows any user-written bounds, so `Inner = _` will be ignored + = note: `#[deny(dyn_assoc_shadowed)]` on by default + +error[E0282]: type annotations needed + --> $DIR/infer-shadows-implied-projection.rs:18:34 + | +LL | let x: &dyn Database = &t; + | ^ cannot infer type + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/traits/object/outlives-super-proj.rs b/tests/ui/traits/object/outlives-super-proj.rs new file mode 100644 index 0000000000000..15b67d9ab68e7 --- /dev/null +++ b/tests/ui/traits/object/outlives-super-proj.rs @@ -0,0 +1,24 @@ +//@ check-pass + +// Make sure that we still deduce outlives bounds from supertrait projections +// and require them for well-formedness. + +trait Trait { + type Assoc; +} + +trait Bar { + type Assoc; +} + +trait Foo<'a, T: 'a>: Bar { + +} + +fn outlives<'a, T: 'a>() {} + +fn implied_outlives<'a, T: Trait>(x: &dyn Foo<'a, T::Assoc>) { + outlives::<'a, T::Assoc>(); +} + +fn main() {} diff --git a/tests/ui/traits/object/pretty.rs b/tests/ui/traits/object/pretty.rs index 603d7af526002..188aa8d9d6470 100644 --- a/tests/ui/traits/object/pretty.rs +++ b/tests/ui/traits/object/pretty.rs @@ -26,6 +26,7 @@ fn dyn_super(x: &dyn Super) { x } //~ERROR mismatched types fn dyn_any(x: &dyn Any) { x } //~ERROR mismatched types fn dyn_fixed(x: &dyn Fixed) { x } //~ERROR mismatched types fn dyn_fixed_multi(x: &dyn Fixed) { x } //~ERROR mismatched types +//~^ ERROR associated type bound for `Assoc` in `dyn Fixed` differs from bound implied by supertraits fn dyn_fixed_sub(x: &dyn FixedSub) { x } //~ERROR mismatched types fn dyn_fixed_static(x: &dyn FixedStatic) { x } //~ERROR mismatched types @@ -34,6 +35,7 @@ fn dyn_any_generic(x: &dyn for<'a> AnyGeneric<'a, Assoc2 = &'a u8>) { x } //~ERR fn dyn_fixed_generic1(x: &dyn for<'a> FixedGeneric1<'a>) { x } //~ERROR mismatched types // fn dyn_fixed_generic2(x: &dyn for<'a> FixedGeneric2<'a>) { x } // Unsound! fn dyn_fixed_generic_multi(x: &dyn for<'a> FixedGeneric1<'a, Assoc2 = &u8>) { x } //~ERROR mismatched types +//~^ ERROR associated type bound for `Assoc2` in `dyn FixedGeneric1` differs from bound implied by supertraits fn dyn_fixed_hrtb(x: &dyn FixedHrtb) { x } //~ERROR mismatched types fn dyn_any_different_binders(x: &dyn AnyDifferentBinders) { x } //~ERROR mismatched types fn dyn_fixed_different_binders(x: &dyn FixedDifferentBinders) { x } //~ERROR mismatched types diff --git a/tests/ui/traits/object/pretty.stderr b/tests/ui/traits/object/pretty.stderr index af941e69c5f84..2c8ea6f0423cb 100644 --- a/tests/ui/traits/object/pretty.stderr +++ b/tests/ui/traits/object/pretty.stderr @@ -1,5 +1,28 @@ +error: associated type bound for `Assoc` in `dyn Fixed` differs from associated type bound implied by supertrait + --> $DIR/pretty.rs:28:34 + | +LL | trait Fixed: Super {} + | ---------- shadowed due to this supertrait bound +... +LL | fn dyn_fixed_multi(x: &dyn Fixed) { x } + | ^^^^^^^^^^^ this bound has no effect and will be ignored + | + = note: `Assoc = u8` was implied by a supertrait and shadows any user-written bounds, so `Assoc = u16` will be ignored + = note: `#[deny(dyn_assoc_shadowed)]` on by default + +error: associated type bound for `Assoc2` in `dyn FixedGeneric1` differs from associated type bound implied by supertrait + --> $DIR/pretty.rs:37:62 + | +LL | trait FixedGeneric1<'a>: SuperGeneric<'a, Assoc2 = &'a u8> {} + | --------------- shadowed due to this supertrait bound +... +LL | fn dyn_fixed_generic_multi(x: &dyn for<'a> FixedGeneric1<'a, Assoc2 = &u8>) { x } + | ^^^^^^^^^^^^ this bound has no effect and will be ignored + | + = note: `Assoc2 = for<'a> &'a u8` was implied by a supertrait and shadows any user-written bounds, so `Assoc2 = &'a u8` will be ignored + warning: unnecessary associated type bound for dyn-incompatible associated type - --> $DIR/pretty.rs:41:35 + --> $DIR/pretty.rs:43:35 | LL | fn dyn_has_gat(x: &dyn HasGat = ()>) { x } | ^^^^^^^^^^^^^^^^ help: remove this bound @@ -44,15 +67,15 @@ error[E0308]: mismatched types --> $DIR/pretty.rs:28:50 | LL | fn dyn_fixed_multi(x: &dyn Fixed) { x } - | - ^ expected `()`, found `&dyn Fixed` + | - ^ expected `()`, found `&dyn Fixed` | | - | help: try adding a return type: `-> &dyn Fixed` + | help: try adding a return type: `-> &dyn Fixed` | = note: expected unit type `()` - found reference `&dyn Fixed` + found reference `&dyn Fixed` error[E0308]: mismatched types - --> $DIR/pretty.rs:29:38 + --> $DIR/pretty.rs:30:38 | LL | fn dyn_fixed_sub(x: &dyn FixedSub) { x } | - ^ expected `()`, found `&dyn FixedSub` @@ -63,7 +86,7 @@ LL | fn dyn_fixed_sub(x: &dyn FixedSub) { x } found reference `&dyn FixedSub` error[E0308]: mismatched types - --> $DIR/pretty.rs:30:44 + --> $DIR/pretty.rs:31:44 | LL | fn dyn_fixed_static(x: &dyn FixedStatic) { x } | - ^ expected `()`, found `&dyn FixedStatic` @@ -74,7 +97,7 @@ LL | fn dyn_fixed_static(x: &dyn FixedStatic) { x } found reference `&dyn FixedStatic` error[E0308]: mismatched types - --> $DIR/pretty.rs:32:75 + --> $DIR/pretty.rs:33:75 | LL | fn dyn_super_generic(x: &dyn for<'a> SuperGeneric<'a, Assoc2 = &'a u8>) { x } | - ^ expected `()`, found `&dyn SuperGeneric<'a, Assoc2 = &u8>` @@ -85,7 +108,7 @@ LL | fn dyn_super_generic(x: &dyn for<'a> SuperGeneric<'a, Assoc2 = &'a u8>) { x found reference `&dyn for<'a> SuperGeneric<'a, Assoc2 = &'a u8>` error[E0308]: mismatched types - --> $DIR/pretty.rs:33:71 + --> $DIR/pretty.rs:34:71 | LL | fn dyn_any_generic(x: &dyn for<'a> AnyGeneric<'a, Assoc2 = &'a u8>) { x } | - ^ expected `()`, found `&dyn AnyGeneric<'a, Assoc2 = &u8>` @@ -96,7 +119,7 @@ LL | fn dyn_any_generic(x: &dyn for<'a> AnyGeneric<'a, Assoc2 = &'a u8>) { x } found reference `&dyn for<'a> AnyGeneric<'a, Assoc2 = &'a u8>` error[E0308]: mismatched types - --> $DIR/pretty.rs:34:60 + --> $DIR/pretty.rs:35:60 | LL | fn dyn_fixed_generic1(x: &dyn for<'a> FixedGeneric1<'a>) { x } | - ^ expected `()`, found `&dyn FixedGeneric1<'a>` @@ -107,18 +130,18 @@ LL | fn dyn_fixed_generic1(x: &dyn for<'a> FixedGeneric1<'a>) { x } found reference `&dyn for<'a> FixedGeneric1<'a>` error[E0308]: mismatched types - --> $DIR/pretty.rs:36:79 + --> $DIR/pretty.rs:37:79 | LL | fn dyn_fixed_generic_multi(x: &dyn for<'a> FixedGeneric1<'a, Assoc2 = &u8>) { x } - | - ^ expected `()`, found `&dyn FixedGeneric1<'a, Assoc2 = ...>` + | - ^ expected `()`, found `&dyn FixedGeneric1<'a>` | | - | help: try adding a return type: `-> &dyn for<'a> FixedGeneric1<'a, Assoc2 = &u8>` + | help: try adding a return type: `-> &dyn for<'a> FixedGeneric1<'a>` | = note: expected unit type `()` - found reference `&dyn for<'a> FixedGeneric1<'a, Assoc2 = &u8>` + found reference `&dyn for<'a> FixedGeneric1<'a>` error[E0308]: mismatched types - --> $DIR/pretty.rs:37:40 + --> $DIR/pretty.rs:39:40 | LL | fn dyn_fixed_hrtb(x: &dyn FixedHrtb) { x } | - ^ expected `()`, found `&dyn FixedHrtb` @@ -129,7 +152,7 @@ LL | fn dyn_fixed_hrtb(x: &dyn FixedHrtb) { x } found reference `&dyn FixedHrtb` error[E0308]: mismatched types - --> $DIR/pretty.rs:38:73 + --> $DIR/pretty.rs:40:73 | LL | fn dyn_any_different_binders(x: &dyn AnyDifferentBinders) { x } | - ^ expected `()`, found `&dyn AnyDifferentBinders` @@ -140,7 +163,7 @@ LL | fn dyn_any_different_binders(x: &dyn AnyDifferentBinders) { x } found reference `&dyn AnyDifferentBinders` error[E0308]: mismatched types - --> $DIR/pretty.rs:39:65 + --> $DIR/pretty.rs:41:65 | LL | fn dyn_fixed_different_binders(x: &dyn FixedDifferentBinders) { x } | - ^ expected `()`, found `&dyn FixedDifferentBinders` @@ -151,7 +174,7 @@ LL | fn dyn_fixed_different_binders(x: &dyn FixedDifferentBinders) { x } found reference `&dyn FixedDifferentBinders` error[E0308]: mismatched types - --> $DIR/pretty.rs:41:56 + --> $DIR/pretty.rs:43:56 | LL | fn dyn_has_gat(x: &dyn HasGat = ()>) { x } | - ^ expected `()`, found `&dyn HasGat = ()>` @@ -161,6 +184,6 @@ LL | fn dyn_has_gat(x: &dyn HasGat = ()>) { x } = note: expected unit type `()` found reference `&dyn HasGat = ()>` -error: aborting due to 14 previous errors; 1 warning emitted +error: aborting due to 16 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/object/redundant.rs b/tests/ui/traits/object/redundant.rs new file mode 100644 index 0000000000000..0bbab092daca0 --- /dev/null +++ b/tests/ui/traits/object/redundant.rs @@ -0,0 +1,13 @@ +//@ check-pass + +trait Foo: Bar {} +trait Bar { + type Out; +} + +fn w(x: &dyn Foo) { + //~^ WARN associated type bound for `Out` in `dyn Foo` is redundant + let x: &dyn Foo = x; +} + +fn main() {} diff --git a/tests/ui/traits/object/redundant.stderr b/tests/ui/traits/object/redundant.stderr new file mode 100644 index 0000000000000..fe8d467a7ff78 --- /dev/null +++ b/tests/ui/traits/object/redundant.stderr @@ -0,0 +1,13 @@ +warning: associated type bound for `Out` in `dyn Foo` is redundant + --> $DIR/redundant.rs:8:18 + | +LL | trait Foo: Bar {} + | -------- redundant due to this supertrait bound +... +LL | fn w(x: &dyn Foo) { + | ^^^^^^^^ + | + = note: `#[warn(dyn_assoc_redundant)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/object/with-self-in-projection-output-repeated-supertrait.rs b/tests/ui/traits/object/with-self-in-projection-output-repeated-supertrait.rs index 2d8230973325d..61d6859878c41 100644 --- a/tests/ui/traits/object/with-self-in-projection-output-repeated-supertrait.rs +++ b/tests/ui/traits/object/with-self-in-projection-output-repeated-supertrait.rs @@ -48,4 +48,5 @@ fn main() { // being specified. let _x: Box> = Box::new(2u32); let _y: Box> = Box::new(2u32); + //~^ WARN associated type bound for `Output` in `dyn NormalizingHelper` is redundant } diff --git a/tests/ui/traits/object/with-self-in-projection-output-repeated-supertrait.stderr b/tests/ui/traits/object/with-self-in-projection-output-repeated-supertrait.stderr new file mode 100644 index 0000000000000..affdaa798037c --- /dev/null +++ b/tests/ui/traits/object/with-self-in-projection-output-repeated-supertrait.stderr @@ -0,0 +1,13 @@ +warning: associated type bound for `Output` in `dyn NormalizingHelper` is redundant + --> $DIR/with-self-in-projection-output-repeated-supertrait.rs:50:51 + | +LL | trait NormalizingHelper: Base::Out> + Base { + | ---------- redundant due to this supertrait bound +... +LL | let _y: Box> = Box::new(2u32); + | ^^^^^^^^^^ + | + = note: `#[warn(dyn_assoc_redundant)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/wf/hir-wf-canonicalized.rs b/tests/ui/wf/hir-wf-canonicalized.rs index abdcd1c04ab2a..dc80a7c795f71 100644 --- a/tests/ui/wf/hir-wf-canonicalized.rs +++ b/tests/ui/wf/hir-wf-canonicalized.rs @@ -9,8 +9,8 @@ trait Callback: Fn(&Bar<'_, T>, &T::V) {} struct Bar<'a, T> { callback: Box>>>, //~^ ERROR the trait bound `Bar<'a, T>: Foo` is not satisfied - //~| ERROR the trait bound `(dyn Callback, Output = ()> + 'static): Foo` is not satisfied - //~| ERROR the size for values of type `(dyn Callback, Output = ()> + 'static)` cannot be known at compilation time + //~| ERROR the trait bound `(dyn Callback> + 'static): Foo` is not satisfied + //~| ERROR the size for values of type `(dyn Callback> + 'static)` cannot be known at compilation time } impl Bar<'_, Bar<'_, T>> {} diff --git a/tests/ui/wf/hir-wf-canonicalized.stderr b/tests/ui/wf/hir-wf-canonicalized.stderr index 8938801ce3d97..434a1d6de238a 100644 --- a/tests/ui/wf/hir-wf-canonicalized.stderr +++ b/tests/ui/wf/hir-wf-canonicalized.stderr @@ -10,11 +10,11 @@ help: this trait has no implementations, consider adding one LL | trait Foo { | ^^^^^^^^^ -error[E0277]: the trait bound `(dyn Callback, Output = ()> + 'static): Foo` is not satisfied +error[E0277]: the trait bound `(dyn Callback> + 'static): Foo` is not satisfied --> $DIR/hir-wf-canonicalized.rs:10:15 | LL | callback: Box>>>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `(dyn Callback, Output = ()> + 'static)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `(dyn Callback> + 'static)` | help: this trait has no implementations, consider adding one --> $DIR/hir-wf-canonicalized.rs:3:1 @@ -22,13 +22,13 @@ help: this trait has no implementations, consider adding one LL | trait Foo { | ^^^^^^^^^ -error[E0277]: the size for values of type `(dyn Callback, Output = ()> + 'static)` cannot be known at compilation time +error[E0277]: the size for values of type `(dyn Callback> + 'static)` cannot be known at compilation time --> $DIR/hir-wf-canonicalized.rs:10:15 | LL | callback: Box>>>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: the trait `Sized` is not implemented for `(dyn Callback, Output = ()> + 'static)` + = help: the trait `Sized` is not implemented for `(dyn Callback> + 'static)` note: required by an implicit `Sized` bound in `Bar` --> $DIR/hir-wf-canonicalized.rs:9:16 | From e56f8d3e1ccac3db3dc9b6b2ad17b198d3746ab3 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 4 Dec 2024 18:50:14 +0000 Subject: [PATCH 5/5] Fix RA --- src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs | 4 ++-- src/tools/rust-analyzer/crates/hir-ty/src/lib.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs index 54aa18ce20766..4d0539c135ac3 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs @@ -666,7 +666,7 @@ impl<'a> InferenceTable<'a> { highest_known_var: InferenceVar, } impl TypeFolder for VarFudger<'_, '_> { - fn as_dyn(&mut self) -> &mut dyn TypeFolder { + fn as_dyn(&mut self) -> &mut dyn TypeFolder { self } @@ -1004,7 +1004,7 @@ mod resolve { where F: Fn(InferenceVar, VariableKind, GenericArg, DebruijnIndex) -> GenericArg, { - fn as_dyn(&mut self) -> &mut dyn TypeFolder { + fn as_dyn(&mut self) -> &mut dyn TypeFolder { self } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs index 22e7b1d920f60..975625fdfab7e 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs @@ -646,7 +646,7 @@ pub(crate) fn fold_free_vars + TypeFoldable< F2: FnMut(Ty, BoundVar, DebruijnIndex) -> Const, > TypeFolder for FreeVarFolder { - fn as_dyn(&mut self) -> &mut dyn TypeFolder { + fn as_dyn(&mut self) -> &mut dyn TypeFolder { self } @@ -697,7 +697,7 @@ pub(crate) fn fold_tys_and_consts + TypeFold impl, DebruijnIndex) -> Either> TypeFolder for TyFolder { - fn as_dyn(&mut self) -> &mut dyn TypeFolder { + fn as_dyn(&mut self) -> &mut dyn TypeFolder { self }