Skip to content

Commit 6eb9524

Browse files
committed
Auto merge of #117200 - rmehri01:repeated_help, r=WaffleLapkin
Don't add redundant help for object safety violations Fixes #117186 r? WaffleLapkin
2 parents b4c4664 + ee96a7a commit 6eb9524

File tree

4 files changed

+76
-35
lines changed

4 files changed

+76
-35
lines changed

compiler/rustc_infer/src/traits/error_reporting/mod.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,19 @@ pub fn report_object_safety_error<'tcx>(
101101
to be resolvable dynamically; for more information visit \
102102
<https://doc.rust-lang.org/reference/items/traits.html#object-safety>",
103103
);
104+
105+
// Only provide the help if its a local trait, otherwise it's not actionable.
104106
if trait_span.is_some() {
105107
let mut reported_violations: Vec<_> = reported_violations.into_iter().collect();
106108
reported_violations.sort();
107-
for violation in reported_violations {
108-
// Only provide the help if its a local trait, otherwise it's not actionable.
109-
violation.solution(&mut err);
109+
110+
let mut potential_solutions: Vec<_> =
111+
reported_violations.into_iter().map(|violation| violation.solution()).collect();
112+
potential_solutions.sort();
113+
// Allows us to skip suggesting that the same item should be moved to another trait multiple times.
114+
potential_solutions.dedup();
115+
for solution in potential_solutions {
116+
solution.add_to(&mut err);
110117
}
111118
}
112119

compiler/rustc_middle/src/traits/mod.rs

+65-30
Original file line numberDiff line numberDiff line change
@@ -832,50 +832,31 @@ impl ObjectSafetyViolation {
832832
}
833833
}
834834

835-
pub fn solution(&self, err: &mut Diagnostic) {
835+
pub fn solution(&self) -> ObjectSafetyViolationSolution {
836836
match self {
837837
ObjectSafetyViolation::SizedSelf(_)
838838
| ObjectSafetyViolation::SupertraitSelf(_)
839-
| ObjectSafetyViolation::SupertraitNonLifetimeBinder(..) => {}
839+
| ObjectSafetyViolation::SupertraitNonLifetimeBinder(..) => {
840+
ObjectSafetyViolationSolution::None
841+
}
840842
ObjectSafetyViolation::Method(
841843
name,
842844
MethodViolationCode::StaticMethod(Some((add_self_sugg, make_sized_sugg))),
843845
_,
844-
) => {
845-
err.span_suggestion(
846-
add_self_sugg.1,
847-
format!(
848-
"consider turning `{name}` into a method by giving it a `&self` argument"
849-
),
850-
add_self_sugg.0.to_string(),
851-
Applicability::MaybeIncorrect,
852-
);
853-
err.span_suggestion(
854-
make_sized_sugg.1,
855-
format!(
856-
"alternatively, consider constraining `{name}` so it does not apply to \
857-
trait objects"
858-
),
859-
make_sized_sugg.0.to_string(),
860-
Applicability::MaybeIncorrect,
861-
);
862-
}
846+
) => ObjectSafetyViolationSolution::AddSelfOrMakeSized {
847+
name: *name,
848+
add_self_sugg: add_self_sugg.clone(),
849+
make_sized_sugg: make_sized_sugg.clone(),
850+
},
863851
ObjectSafetyViolation::Method(
864852
name,
865853
MethodViolationCode::UndispatchableReceiver(Some(span)),
866854
_,
867-
) => {
868-
err.span_suggestion(
869-
*span,
870-
format!("consider changing method `{name}`'s `self` parameter to be `&self`"),
871-
"&Self",
872-
Applicability::MachineApplicable,
873-
);
874-
}
855+
) => ObjectSafetyViolationSolution::ChangeToRefSelf(*name, *span),
875856
ObjectSafetyViolation::AssocConst(name, _)
876857
| ObjectSafetyViolation::GAT(name, _)
877858
| ObjectSafetyViolation::Method(name, ..) => {
878-
err.help(format!("consider moving `{name}` to another trait"));
859+
ObjectSafetyViolationSolution::MoveToAnotherTrait(*name)
879860
}
880861
}
881862
}
@@ -899,6 +880,60 @@ impl ObjectSafetyViolation {
899880
}
900881
}
901882

883+
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
884+
pub enum ObjectSafetyViolationSolution {
885+
None,
886+
AddSelfOrMakeSized {
887+
name: Symbol,
888+
add_self_sugg: (String, Span),
889+
make_sized_sugg: (String, Span),
890+
},
891+
ChangeToRefSelf(Symbol, Span),
892+
MoveToAnotherTrait(Symbol),
893+
}
894+
895+
impl ObjectSafetyViolationSolution {
896+
pub fn add_to(self, err: &mut Diagnostic) {
897+
match self {
898+
ObjectSafetyViolationSolution::None => {}
899+
ObjectSafetyViolationSolution::AddSelfOrMakeSized {
900+
name,
901+
add_self_sugg,
902+
make_sized_sugg,
903+
} => {
904+
err.span_suggestion(
905+
add_self_sugg.1,
906+
format!(
907+
"consider turning `{name}` into a method by giving it a `&self` argument"
908+
),
909+
add_self_sugg.0,
910+
Applicability::MaybeIncorrect,
911+
);
912+
err.span_suggestion(
913+
make_sized_sugg.1,
914+
format!(
915+
"alternatively, consider constraining `{name}` so it does not apply to \
916+
trait objects"
917+
),
918+
make_sized_sugg.0,
919+
Applicability::MaybeIncorrect,
920+
);
921+
}
922+
ObjectSafetyViolationSolution::ChangeToRefSelf(name, span) => {
923+
err.span_suggestion(
924+
span,
925+
format!("consider changing method `{name}`'s `self` parameter to be `&self`"),
926+
"&Self",
927+
Applicability::MachineApplicable,
928+
);
929+
}
930+
ObjectSafetyViolationSolution::MoveToAnotherTrait(name) => {
931+
err.help(format!("consider moving `{name}` to another trait"));
932+
}
933+
}
934+
}
935+
}
936+
902937
/// Reasons a method might not be object-safe.
903938
#[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable, PartialOrd, Ord)]
904939
pub enum MethodViolationCode {

compiler/rustc_trait_selection/src/traits/object_safety.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ fn lint_object_unsafe_trait(
192192
);
193193
if node.is_some() {
194194
// Only provide the help if its a local trait, otherwise it's not
195-
violation.solution(err);
195+
violation.solution().add_to(err);
196196
}
197197
err
198198
},

tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr

-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ LL | fn test(&self) -> [u8; bar::<Self>()];
1414
| |
1515
| ...because method `test` references the `Self` type in its `where` clause
1616
= help: consider moving `test` to another trait
17-
= help: consider moving `test` to another trait
1817
= help: only type `()` implements the trait, consider using it directly instead
1918

2019
error: aborting due to 1 previous error

0 commit comments

Comments
 (0)