Auto merge of #117200 - rmehri01:repeated_help, r=WaffleLapkin
Don't add redundant help for object safety violations Fixes #117186 r? WaffleLapkin
This commit is contained in:
commit
6eb9524047
@ -101,12 +101,19 @@ pub fn report_object_safety_error<'tcx>(
|
|||||||
to be resolvable dynamically; for more information visit \
|
to be resolvable dynamically; for more information visit \
|
||||||
<https://doc.rust-lang.org/reference/items/traits.html#object-safety>",
|
<https://doc.rust-lang.org/reference/items/traits.html#object-safety>",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Only provide the help if its a local trait, otherwise it's not actionable.
|
||||||
if trait_span.is_some() {
|
if trait_span.is_some() {
|
||||||
let mut reported_violations: Vec<_> = reported_violations.into_iter().collect();
|
let mut reported_violations: Vec<_> = reported_violations.into_iter().collect();
|
||||||
reported_violations.sort();
|
reported_violations.sort();
|
||||||
for violation in reported_violations {
|
|
||||||
// Only provide the help if its a local trait, otherwise it's not actionable.
|
let mut potential_solutions: Vec<_> =
|
||||||
violation.solution(&mut err);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -832,50 +832,31 @@ impl ObjectSafetyViolation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn solution(&self, err: &mut Diagnostic) {
|
pub fn solution(&self) -> ObjectSafetyViolationSolution {
|
||||||
match self {
|
match self {
|
||||||
ObjectSafetyViolation::SizedSelf(_)
|
ObjectSafetyViolation::SizedSelf(_)
|
||||||
| ObjectSafetyViolation::SupertraitSelf(_)
|
| ObjectSafetyViolation::SupertraitSelf(_)
|
||||||
| ObjectSafetyViolation::SupertraitNonLifetimeBinder(..) => {}
|
| ObjectSafetyViolation::SupertraitNonLifetimeBinder(..) => {
|
||||||
|
ObjectSafetyViolationSolution::None
|
||||||
|
}
|
||||||
ObjectSafetyViolation::Method(
|
ObjectSafetyViolation::Method(
|
||||||
name,
|
name,
|
||||||
MethodViolationCode::StaticMethod(Some((add_self_sugg, make_sized_sugg))),
|
MethodViolationCode::StaticMethod(Some((add_self_sugg, make_sized_sugg))),
|
||||||
_,
|
_,
|
||||||
) => {
|
) => ObjectSafetyViolationSolution::AddSelfOrMakeSized {
|
||||||
err.span_suggestion(
|
name: *name,
|
||||||
add_self_sugg.1,
|
add_self_sugg: add_self_sugg.clone(),
|
||||||
format!(
|
make_sized_sugg: make_sized_sugg.clone(),
|
||||||
"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,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
ObjectSafetyViolation::Method(
|
ObjectSafetyViolation::Method(
|
||||||
name,
|
name,
|
||||||
MethodViolationCode::UndispatchableReceiver(Some(span)),
|
MethodViolationCode::UndispatchableReceiver(Some(span)),
|
||||||
_,
|
_,
|
||||||
) => {
|
) => ObjectSafetyViolationSolution::ChangeToRefSelf(*name, *span),
|
||||||
err.span_suggestion(
|
|
||||||
*span,
|
|
||||||
format!("consider changing method `{name}`'s `self` parameter to be `&self`"),
|
|
||||||
"&Self",
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
ObjectSafetyViolation::AssocConst(name, _)
|
ObjectSafetyViolation::AssocConst(name, _)
|
||||||
| ObjectSafetyViolation::GAT(name, _)
|
| ObjectSafetyViolation::GAT(name, _)
|
||||||
| ObjectSafetyViolation::Method(name, ..) => {
|
| ObjectSafetyViolation::Method(name, ..) => {
|
||||||
err.help(format!("consider moving `{name}` to another trait"));
|
ObjectSafetyViolationSolution::MoveToAnotherTrait(*name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -899,6 +880,60 @@ impl ObjectSafetyViolation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Reasons a method might not be object-safe.
|
/// Reasons a method might not be object-safe.
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable, PartialOrd, Ord)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable, PartialOrd, Ord)]
|
||||||
pub enum MethodViolationCode {
|
pub enum MethodViolationCode {
|
||||||
|
@ -192,7 +192,7 @@ fn lint_object_unsafe_trait(
|
|||||||
);
|
);
|
||||||
if node.is_some() {
|
if node.is_some() {
|
||||||
// Only provide the help if its a local trait, otherwise it's not
|
// Only provide the help if its a local trait, otherwise it's not
|
||||||
violation.solution(err);
|
violation.solution().add_to(err);
|
||||||
}
|
}
|
||||||
err
|
err
|
||||||
},
|
},
|
||||||
|
@ -14,7 +14,6 @@ LL | fn test(&self) -> [u8; bar::<Self>()];
|
|||||||
| |
|
| |
|
||||||
| ...because method `test` references the `Self` type in its `where` clause
|
| ...because method `test` references the `Self` type in its `where` clause
|
||||||
= help: consider moving `test` to another trait
|
= help: consider moving `test` to another trait
|
||||||
= help: consider moving `test` to another trait
|
|
||||||
= help: only type `()` implements the trait, consider using it directly instead
|
= help: only type `()` implements the trait, consider using it directly instead
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
Loading…
x
Reference in New Issue
Block a user