Change:
made it so that we report all object safety violations at the same time. However, it also results in a redundant note: We should not add the same note multiple times.
Can we add a debug assertion for duplicate identical help messages? (sorta like we do for "Span must not be empty and have no suggestion" or "Suggestion may not have overlapping parts" ?
I guess we could, but I think there are multiple diagnostics that currently do this, so we'll have to fix them first.
Did not find tooo much... inside :

Discussion:
to be resolvable dynamically; for more information visit  <https://doc.rust-lang.org/reference/items/traits.html#object-safety>", ); <ins> // Only provide the help if its a local trait, otherwise it's not actionable. </ins> if trait_span.is_some() { let mut reported_violations: Vec<_> = reported_violations.into_iter().collect(); reported_violations.sort(); <del> for violation in reported_violations { // Only provide the help if its a local trait, otherwise it's not actionable. violation.solution(&mut err); </del> <ins> let mut potential_solutions: Vec<_> = reported_violations.into_iter().map(|violation| violation.solution()).collect(); potential_solutions.sort(); // Allows us to skip suggesting that the same item should be moved to another trait multiple times. potential_solutions.dedup(); for solution in potential_solutions { solution.add_to(&mut err); </ins> } }

} } <del> pub fn solution(&self, err: &mut Diagnostic) { </del> <ins> pub fn solution(&self) -> ObjectSafetyViolationSolution { </ins> match self { ObjectSafetyViolation::SizedSelf(_) | ObjectSafetyViolation::SupertraitSelf(_) <del> | ObjectSafetyViolation::SupertraitNonLifetimeBinder(..) => {} </del> <ins> | ObjectSafetyViolation::SupertraitNonLifetimeBinder(..) => { ObjectSafetyViolationSolution::None } </ins> ObjectSafetyViolation::Method( name, MethodViolationCode::StaticMethod(Some((add_self_sugg, make_sized_sugg))), _, <del> ) => { err.span_suggestion( add_self_sugg.1, format!( "consider turning `{name}` into a method by giving it a `&self` argument" ), add_self_sugg.0.to_string(), Applicability::MaybeIncorrect, ); err.span_suggestion( make_sized_sugg.1, format!( "alternatively, consider constraining `{name}` so it does not apply to  trait objects" ), make_sized_sugg.0.to_string(), Applicability::MaybeIncorrect, ); } </del> <ins> ) => ObjectSafetyViolationSolution::AddSelfOrMakeSized { name: *name, add_self_sugg: add_self_sugg.clone(), make_sized_sugg: make_sized_sugg.clone(), }, </ins> ObjectSafetyViolation::Method( name, MethodViolationCode::UndispatchableReceiver(Some(span)), _, <del> ) => { err.span_suggestion( *span, format!("consider changing method `{name}`'s `self` parameter to be `&self`"), "&Self", Applicability::MachineApplicable, ); } </del> <ins> ) => ObjectSafetyViolationSolution::ChangeToRefSelf(*name, *span), </ins> ObjectSafetyViolation::AssocConst(name, _) | ObjectSafetyViolation::GAT(name, _) | ObjectSafetyViolation::Method(name, ..) => { <del> err.help(format!("consider moving `{name}` to another trait")); </del> <ins> ObjectSafetyViolationSolution::MoveToAnotherTrait(*name) </ins> } } }

} } <ins> #[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] pub enum ObjectSafetyViolationSolution { None, AddSelfOrMakeSized { name: Symbol, add_self_sugg: (String, Span), make_sized_sugg: (String, Span), }, ChangeToRefSelf(Symbol, Span), MoveToAnotherTrait(Symbol), } impl ObjectSafetyViolationSolution { pub fn add_to(self, err: &mut Diagnostic) { match self { ObjectSafetyViolationSolution::None => {} ObjectSafetyViolationSolution::AddSelfOrMakeSized { name, add_self_sugg, make_sized_sugg, } => { err.span_suggestion( add_self_sugg.1, format!( "consider turning `{name}` into a method by giving it a `&self` argument" ), add_self_sugg.0, Applicability::MaybeIncorrect, ); err.span_suggestion( make_sized_sugg.1, format!( "alternatively, consider constraining `{name}` so it does not apply to  trait objects" ), make_sized_sugg.0, Applicability::MaybeIncorrect, ); } ObjectSafetyViolationSolution::ChangeToRefSelf(name, span) => { err.span_suggestion( span, format!("consider changing method `{name}`'s `self` parameter to be `&self`"), "&Self", Applicability::MachineApplicable, ); } ObjectSafetyViolationSolution::MoveToAnotherTrait(name) => { err.help(format!("consider moving `{name}` to another trait")); } } } } </ins> /// Reasons a method might not be object-safe. #[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable, PartialOrd, Ord)] pub enum MethodViolationCode {

); if node.is_some() { // Only provide the help if its a local trait, otherwise it's not <del> violation.solution(err); </del> <ins> violation.solution().add_to(err); </ins> } err },

|        | |        ...because method `test` references the `Self` type in its `where` clause = help: consider moving `test` to another trait <del> = help: consider moving `test` to another trait </del> = help: only type `()` implements the trait, consider using it directly instead error: aborting due to previous error