Add infrastructure #[rustc_confusables]
attribute to allow targeted
"no method" errors on standard library types The standard library developer can annotate methods on e.g. `BTreeSet::push` with `#[rustc_confusables("insert")]`. When the user mistypes `btreeset.push()`, `BTreeSet::insert` will be suggested if there are no other candidates to suggest.
This commit is contained in:
parent
00a39cc785
commit
08c77a6eb4
12 changed files with 259 additions and 4 deletions
|
@ -98,6 +98,9 @@ passes_collapse_debuginfo =
|
|||
`collapse_debuginfo` attribute should be applied to macro definitions
|
||||
.label = not a macro definition
|
||||
|
||||
passes_confusables = attribute should be applied to an inherent method
|
||||
.label = not an inherent method
|
||||
|
||||
passes_const_impl_const_trait =
|
||||
const `impl`s must be for traits marked with `#[const_trait]`
|
||||
.note = this trait must be annotated with `#[const_trait]`
|
||||
|
@ -266,6 +269,9 @@ passes_duplicate_lang_item_crate_depends =
|
|||
.first_definition_path = first definition in `{$orig_crate_name}` loaded from {$orig_path}
|
||||
.second_definition_path = second definition in `{$crate_name}` loaded from {$path}
|
||||
|
||||
passes_empty_confusables =
|
||||
expected at least one confusable name
|
||||
|
||||
passes_export_name =
|
||||
attribute should be applied to a free function, impl method or static
|
||||
.label = not a free function, impl method or static
|
||||
|
@ -326,6 +332,9 @@ passes_implied_feature_not_exist =
|
|||
passes_incorrect_do_not_recommend_location =
|
||||
`#[do_not_recommend]` can only be placed on trait implementations
|
||||
|
||||
passes_incorrect_meta_item = expected a quoted string literal
|
||||
passes_incorrect_meta_item_suggestion = consider surrounding this with quotes
|
||||
|
||||
passes_incorrect_target =
|
||||
`{$name}` language item must be applied to a {$kind} with {$at_least ->
|
||||
[true] at least {$num}
|
||||
|
|
|
@ -183,6 +183,7 @@ impl CheckAttrVisitor<'_> {
|
|||
| sym::rustc_allowed_through_unstable_modules
|
||||
| sym::rustc_promotable => self.check_stability_promotable(&attr, span, target),
|
||||
sym::link_ordinal => self.check_link_ordinal(&attr, span, target),
|
||||
sym::rustc_confusables => self.check_confusables(&attr, target),
|
||||
_ => true,
|
||||
};
|
||||
|
||||
|
@ -1985,6 +1986,46 @@ impl CheckAttrVisitor<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_confusables(&self, attr: &Attribute, target: Target) -> bool {
|
||||
match target {
|
||||
Target::Method(MethodKind::Inherent) => {
|
||||
let Some(meta) = attr.meta() else {
|
||||
return false;
|
||||
};
|
||||
let ast::MetaItem { kind: MetaItemKind::List(ref metas), .. } = meta else {
|
||||
return false;
|
||||
};
|
||||
|
||||
let mut candidates = Vec::new();
|
||||
|
||||
for meta in metas {
|
||||
let NestedMetaItem::Lit(meta_lit) = meta else {
|
||||
self.tcx.sess.emit_err(errors::IncorrectMetaItem {
|
||||
span: meta.span(),
|
||||
suggestion: errors::IncorrectMetaItemSuggestion {
|
||||
lo: meta.span().shrink_to_lo(),
|
||||
hi: meta.span().shrink_to_hi(),
|
||||
},
|
||||
});
|
||||
return false;
|
||||
};
|
||||
candidates.push(meta_lit.symbol);
|
||||
}
|
||||
|
||||
if candidates.is_empty() {
|
||||
self.tcx.sess.emit_err(errors::EmptyConfusables { span: attr.span });
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
_ => {
|
||||
self.tcx.sess.emit_err(errors::Confusables { attr_span: attr.span });
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_deprecated(&self, hir_id: HirId, attr: &Attribute, _span: Span, target: Target) {
|
||||
match target {
|
||||
Target::Closure | Target::Expression | Target::Statement | Target::Arm => {
|
||||
|
|
|
@ -617,6 +617,38 @@ pub struct LinkOrdinal {
|
|||
pub attr_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_confusables)]
|
||||
pub struct Confusables {
|
||||
#[primary_span]
|
||||
pub attr_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_empty_confusables)]
|
||||
pub(crate) struct EmptyConfusables {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_incorrect_meta_item, code = "E0539")]
|
||||
pub(crate) struct IncorrectMetaItem {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[subdiagnostic]
|
||||
pub suggestion: IncorrectMetaItemSuggestion,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[multipart_suggestion(passes_incorrect_meta_item_suggestion, applicability = "maybe-incorrect")]
|
||||
pub(crate) struct IncorrectMetaItemSuggestion {
|
||||
#[suggestion_part(code = "\"")]
|
||||
pub lo: Span,
|
||||
#[suggestion_part(code = "\"")]
|
||||
pub hi: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_stability_promotable)]
|
||||
pub struct StabilityPromotable {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue