mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-09 05:23:07 +00:00
Rollup merge of #108760 - clubby789:autolintstuff, r=wesleywiser
Add lint to deny diagnostics composed of static strings r? ghost I'm hoping to have a lint that semi-automatically converts simple diagnostics such as `struct_span_err(span, "msg").help("msg").span_note(span2, "msg").emit()` to typed session diagnostics. It's quite hacky and not entirely working because of problems with `x fix` but should hopefully help reduce some of the work. I'm going to start trying to apply what I can from this, but opening this as a draft in case anyone wants to develop on it. cc #100717
This commit is contained in:
commit
309496cf29
@ -149,6 +149,25 @@ builtin_macros_format_pos_mismatch = {$n} positional {$n ->
|
||||
[one] argument
|
||||
*[more] arguments
|
||||
} in format string, but {$desc}
|
||||
|
||||
builtin_macros_offset_of_expected_field = expected field
|
||||
|
||||
builtin_macros_offset_of_expected_two_args = expected 2 arguments
|
||||
|
||||
builtin_macros_test_case_non_item = `#[test_case]` attribute is only allowed on items
|
||||
|
||||
builtin_macros_test_bad_fn = {$kind} functions cannot be used for tests
|
||||
.label = `{$kind}` because of this
|
||||
|
||||
builtin_macros_asm_explicit_register_name = explicit register arguments cannot have names
|
||||
|
||||
builtin_macros_asm_mutually_exclusive = the `{$opt1}` and `{$opt2}` options are mutually exclusive
|
||||
|
||||
builtin_macros_asm_pure_combine = the `pure` option must be combined with either `nomem` or `readonly`
|
||||
|
||||
builtin_macros_asm_pure_no_output = asm with the `pure` option must have at least one output
|
||||
|
||||
builtin_macros_asm_modifier_invalid = asm template modifier must be a single character
|
||||
|
||||
builtin_macros_test_runner_invalid = `test_runner` argument must be a path
|
||||
builtin_macros_test_runner_nargs = `#![test_runner(..)]` accepts exactly 1 argument
|
||||
|
@ -15,6 +15,8 @@ use rustc_span::{InnerSpan, Span};
|
||||
use rustc_target::asm::InlineAsmArch;
|
||||
use smallvec::smallvec;
|
||||
|
||||
use crate::errors;
|
||||
|
||||
pub struct AsmArgs {
|
||||
pub templates: Vec<P<ast::Expr>>,
|
||||
pub operands: Vec<(ast::InlineAsmOperand, Span)>,
|
||||
@ -205,7 +207,7 @@ pub fn parse_asm_args<'a>(
|
||||
// of the argument available.
|
||||
if explicit_reg {
|
||||
if name.is_some() {
|
||||
diag.struct_span_err(span, "explicit register arguments cannot have names").emit();
|
||||
diag.emit_err(errors::AsmExplicitRegisterName { span });
|
||||
}
|
||||
args.reg_args.insert(slot);
|
||||
} else if let Some(name) = name {
|
||||
@ -240,25 +242,19 @@ pub fn parse_asm_args<'a>(
|
||||
&& args.options.contains(ast::InlineAsmOptions::READONLY)
|
||||
{
|
||||
let spans = args.options_spans.clone();
|
||||
diag.struct_span_err(spans, "the `nomem` and `readonly` options are mutually exclusive")
|
||||
.emit();
|
||||
diag.emit_err(errors::AsmMutuallyExclusive { spans, opt1: "nomem", opt2: "readonly" });
|
||||
}
|
||||
if args.options.contains(ast::InlineAsmOptions::PURE)
|
||||
&& args.options.contains(ast::InlineAsmOptions::NORETURN)
|
||||
{
|
||||
let spans = args.options_spans.clone();
|
||||
diag.struct_span_err(spans, "the `pure` and `noreturn` options are mutually exclusive")
|
||||
.emit();
|
||||
diag.emit_err(errors::AsmMutuallyExclusive { spans, opt1: "pure", opt2: "noreturn" });
|
||||
}
|
||||
if args.options.contains(ast::InlineAsmOptions::PURE)
|
||||
&& !args.options.intersects(ast::InlineAsmOptions::NOMEM | ast::InlineAsmOptions::READONLY)
|
||||
{
|
||||
let spans = args.options_spans.clone();
|
||||
diag.struct_span_err(
|
||||
spans,
|
||||
"the `pure` option must be combined with either `nomem` or `readonly`",
|
||||
)
|
||||
.emit();
|
||||
diag.emit_err(errors::AsmPureCombine { spans });
|
||||
}
|
||||
|
||||
let mut have_real_output = false;
|
||||
@ -285,11 +281,7 @@ pub fn parse_asm_args<'a>(
|
||||
}
|
||||
}
|
||||
if args.options.contains(ast::InlineAsmOptions::PURE) && !have_real_output {
|
||||
diag.struct_span_err(
|
||||
args.options_spans.clone(),
|
||||
"asm with the `pure` option must have at least one output",
|
||||
)
|
||||
.emit();
|
||||
diag.emit_err(errors::AsmPureNoOutput { spans: args.options_spans.clone() });
|
||||
}
|
||||
if args.options.contains(ast::InlineAsmOptions::NORETURN) && !outputs_sp.is_empty() {
|
||||
let err = diag
|
||||
@ -705,11 +697,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
|
||||
.ty_span
|
||||
.map(|sp| template_sp.from_inner(InnerSpan::new(sp.start, sp.end)))
|
||||
.unwrap_or(template_sp);
|
||||
ecx.struct_span_err(
|
||||
span,
|
||||
"asm template modifier must be a single character",
|
||||
)
|
||||
.emit();
|
||||
ecx.emit_err(errors::AsmModifierInvalid { span });
|
||||
modifier = None;
|
||||
}
|
||||
|
||||
|
@ -551,3 +551,71 @@ pub(crate) struct FormatPositionalMismatch {
|
||||
#[subdiagnostic]
|
||||
pub(crate) highlight: SingleLabelManySpans,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_test_case_non_item)]
|
||||
pub(crate) struct TestCaseNonItem {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_test_bad_fn)]
|
||||
pub(crate) struct TestBadFn {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
#[label]
|
||||
pub(crate) cause: Span,
|
||||
pub(crate) kind: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_asm_explicit_register_name)]
|
||||
pub(crate) struct AsmExplicitRegisterName {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_asm_mutually_exclusive)]
|
||||
pub(crate) struct AsmMutuallyExclusive {
|
||||
#[primary_span]
|
||||
pub(crate) spans: Vec<Span>,
|
||||
pub(crate) opt1: &'static str,
|
||||
pub(crate) opt2: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_asm_pure_combine)]
|
||||
pub(crate) struct AsmPureCombine {
|
||||
#[primary_span]
|
||||
pub(crate) spans: Vec<Span>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_asm_pure_no_output)]
|
||||
pub(crate) struct AsmPureNoOutput {
|
||||
#[primary_span]
|
||||
pub(crate) spans: Vec<Span>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_asm_modifier_invalid)]
|
||||
pub(crate) struct AsmModifierInvalid {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_test_runner_invalid)]
|
||||
pub(crate) struct TestRunnerInvalid {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_test_runner_nargs)]
|
||||
pub(crate) struct TestRunnerNargs {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::errors;
|
||||
/// The expansion from a test function to the appropriate test struct for libtest
|
||||
/// Ideally, this code would be in libtest but for efficiency and error messages it lives here.
|
||||
use crate::util::{check_builtin_macro_attribute, warn_on_duplicate_attribute};
|
||||
@ -40,12 +41,7 @@ pub fn expand_test_case(
|
||||
unreachable!()
|
||||
},
|
||||
_ => {
|
||||
ecx.struct_span_err(
|
||||
anno_item.span(),
|
||||
"`#[test_case]` attribute is only allowed on items",
|
||||
)
|
||||
.emit();
|
||||
|
||||
ecx.emit_err(errors::TestCaseNonItem { span: anno_item.span() });
|
||||
return vec![];
|
||||
}
|
||||
};
|
||||
@ -533,15 +529,11 @@ fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
|
||||
match &i.kind {
|
||||
ast::ItemKind::Fn(box ast::Fn { sig, generics, .. }) => {
|
||||
if let ast::Unsafe::Yes(span) = sig.header.unsafety {
|
||||
sd.struct_span_err(i.span, "unsafe functions cannot be used for tests")
|
||||
.span_label(span, "`unsafe` because of this")
|
||||
.emit();
|
||||
sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "unsafe" });
|
||||
return false;
|
||||
}
|
||||
if let ast::Async::Yes { span, .. } = sig.header.asyncness {
|
||||
sd.struct_span_err(i.span, "async functions cannot be used for tests")
|
||||
.span_label(span, "`async` because of this")
|
||||
.emit();
|
||||
sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "async" });
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,8 @@ use tracing::debug;
|
||||
|
||||
use std::{iter, mem};
|
||||
|
||||
use crate::errors;
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Test {
|
||||
span: Span,
|
||||
@ -385,11 +387,11 @@ fn get_test_runner(sd: &rustc_errors::Handler, krate: &ast::Crate) -> Option<ast
|
||||
[single] => match single.meta_item() {
|
||||
Some(meta_item) if meta_item.is_word() => return Some(meta_item.path.clone()),
|
||||
_ => {
|
||||
sd.struct_span_err(span, "`test_runner` argument must be a path").emit();
|
||||
sd.emit_err(errors::TestRunnerInvalid { span });
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
sd.struct_span_err(span, "`#![test_runner(..)]` accepts exactly 1 argument").emit();
|
||||
sd.emit_err(errors::TestRunnerNargs { span });
|
||||
}
|
||||
}
|
||||
None
|
||||
|
@ -291,3 +291,16 @@ codegen_ssa_invalid_monomorphization_unsupported_cast = invalid monomorphization
|
||||
codegen_ssa_invalid_monomorphization_unsupported_operation = invalid monomorphization of `{$name}` intrinsic: unsupported operation on `{$in_ty}` with element `{$in_elem}`
|
||||
|
||||
codegen_ssa_invalid_monomorphization_expected_vector_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of vector type `{$vector_type}` to be a signed or unsigned integer type
|
||||
|
||||
codegen_ssa_invalid_no_sanitize = invalid argument for `no_sanitize`
|
||||
.note = expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread`
|
||||
|
||||
codegen_ssa_invalid_link_ordinal_nargs = incorrect number of arguments to `#[link_ordinal]`
|
||||
.note = the attribute requires exactly one argument
|
||||
|
||||
codegen_ssa_illegal_link_ordinal_format = illegal ordinal format in `link_ordinal`
|
||||
.note = an unsuffixed integer value, e.g., `1`, is expected
|
||||
|
||||
codegen_ssa_target_feature_safe_trait = `#[target_feature(..)]` cannot be applied to safe trait method
|
||||
.label = cannot be applied to safe trait method
|
||||
.label_def = not an `unsafe` function
|
||||
|
@ -14,6 +14,7 @@ use rustc_span::symbol::Ident;
|
||||
use rustc_span::{sym, Span};
|
||||
use rustc_target::spec::{abi, SanitizerSet};
|
||||
|
||||
use crate::errors;
|
||||
use crate::target_features::from_target_feature;
|
||||
use crate::{errors::ExpectedUsedSymbol, target_features::check_target_feature_trait_unsafe};
|
||||
|
||||
@ -334,10 +335,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
||||
codegen_fn_attrs.no_sanitize |= SanitizerSet::HWADDRESS
|
||||
}
|
||||
_ => {
|
||||
tcx.sess
|
||||
.struct_span_err(item.span(), "invalid argument for `no_sanitize`")
|
||||
.note("expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread`")
|
||||
.emit();
|
||||
tcx.sess.emit_err(errors::InvalidNoSanitize { span: item.span() });
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -608,10 +606,7 @@ fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option<u16> {
|
||||
let sole_meta_list = match meta_item_list {
|
||||
Some([item]) => item.lit(),
|
||||
Some(_) => {
|
||||
tcx.sess
|
||||
.struct_span_err(attr.span, "incorrect number of arguments to `#[link_ordinal]`")
|
||||
.note("the attribute requires exactly one argument")
|
||||
.emit();
|
||||
tcx.sess.emit_err(errors::InvalidLinkOrdinalNargs { span: attr.span });
|
||||
return None;
|
||||
}
|
||||
_ => None,
|
||||
@ -642,10 +637,7 @@ fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option<u16> {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
tcx.sess
|
||||
.struct_span_err(attr.span, "illegal ordinal format in `link_ordinal`")
|
||||
.note("an unsuffixed integer value, e.g., `1`, is expected")
|
||||
.emit();
|
||||
tcx.sess.emit_err(errors::InvalidLinkOrdinalFormat { span: attr.span });
|
||||
None
|
||||
}
|
||||
}
|
||||
|
@ -981,3 +981,37 @@ impl IntoDiagnosticArg for ExpectedPointerMutability {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_invalid_no_sanitize)]
|
||||
#[note]
|
||||
pub struct InvalidNoSanitize {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_invalid_link_ordinal_nargs)]
|
||||
#[note]
|
||||
pub struct InvalidLinkOrdinalNargs {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_illegal_link_ordinal_format)]
|
||||
#[note]
|
||||
pub struct InvalidLinkOrdinalFormat {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_target_feature_safe_trait)]
|
||||
pub struct TargetFeatureSafeTrait {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[label(codegen_ssa_label_def)]
|
||||
pub def: Span,
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::errors;
|
||||
use rustc_ast::ast;
|
||||
use rustc_attr::InstructionSetAttr;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
@ -443,14 +444,10 @@ pub fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_s
|
||||
if let DefKind::AssocFn = tcx.def_kind(id) {
|
||||
let parent_id = tcx.local_parent(id);
|
||||
if let DefKind::Trait | DefKind::Impl { of_trait: true } = tcx.def_kind(parent_id) {
|
||||
tcx.sess
|
||||
.struct_span_err(
|
||||
attr_span,
|
||||
"`#[target_feature(..)]` cannot be applied to safe trait method",
|
||||
)
|
||||
.span_label(attr_span, "cannot be applied to safe trait method")
|
||||
.span_label(tcx.def_span(id), "not an `unsafe` function")
|
||||
.emit();
|
||||
tcx.sess.emit_err(errors::TargetFeatureSafeTrait {
|
||||
span: attr_span,
|
||||
def: tcx.def_span(id),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -136,3 +136,7 @@ expand_proc_macro_panicked =
|
||||
|
||||
expand_proc_macro_derive_tokens =
|
||||
proc-macro derive produced unparsable tokens
|
||||
|
||||
expand_duplicate_matcher_binding = duplicate matcher binding
|
||||
.label = duplicate binding
|
||||
.label2 = previous binding
|
||||
|
@ -397,3 +397,13 @@ pub struct ProcMacroDeriveTokens {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(expand_duplicate_matcher_binding)]
|
||||
pub struct DuplicateMatcherBinding {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[label(expand_label2)]
|
||||
pub prev: Span,
|
||||
}
|
||||
|
@ -104,6 +104,7 @@
|
||||
//! Kleene operators under which a meta-variable is repeating is the concatenation of the stacks
|
||||
//! stored when entering a macro definition starting from the state in which the meta-variable is
|
||||
//! bound.
|
||||
use crate::errors;
|
||||
use crate::mbe::{KleeneToken, TokenTree};
|
||||
|
||||
use rustc_ast::token::{Delimiter, Token, TokenKind};
|
||||
@ -281,10 +282,7 @@ fn check_binders(
|
||||
// Duplicate binders at the top-level macro definition are errors. The lint is only
|
||||
// for nested macro definitions.
|
||||
sess.span_diagnostic
|
||||
.struct_span_err(span, "duplicate matcher binding")
|
||||
.span_label(span, "duplicate binding")
|
||||
.span_label(prev_info.span, "previous binding")
|
||||
.emit();
|
||||
.emit_err(errors::DuplicateMatcherBinding { span, prev: prev_info.span });
|
||||
*valid = false;
|
||||
} else {
|
||||
binders.insert(name, BinderInfo { span, ops: ops.into() });
|
||||
|
@ -262,3 +262,17 @@ hir_analysis_transparent_non_zero_sized_enum = the variant of a transparent {$de
|
||||
hir_analysis_transparent_non_zero_sized = transparent {$desc} needs at most one non-zero-sized field, but has {$field_count}
|
||||
.label = needs at most one non-zero-sized field, but has {$field_count}
|
||||
.labels = this field is non-zero-sized
|
||||
|
||||
hir_analysis_too_large_static = extern static is too large for the current architecture
|
||||
|
||||
hir_analysis_specialization_trait = implementing `rustc_specialization_trait` traits is unstable
|
||||
.help = add `#![feature(min_specialization)]` to the crate attributes to enable
|
||||
|
||||
hir_analysis_closure_implicit_hrtb = implicit types in closure signatures are forbidden when `for<...>` is present
|
||||
.label = `for<...>` is here
|
||||
|
||||
hir_analysis_const_specialize = cannot specialize on const impl with non-const impl
|
||||
|
||||
hir_analysis_static_specialize = cannot specialize on `'static` lifetime
|
||||
|
||||
hir_analysis_missing_tilde_const = missing `~const` qualifier for specialization
|
||||
|
@ -170,9 +170,7 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||
if matches!(tcx.def_kind(def_id), DefKind::Static(_)
|
||||
if tcx.def_kind(tcx.local_parent(def_id)) == DefKind::ForeignMod) =>
|
||||
{
|
||||
tcx.sess
|
||||
.struct_span_err(span, "extern static is too large for the current architecture")
|
||||
.emit();
|
||||
tcx.sess.emit_err(errors::TooLargeStatic { span });
|
||||
return;
|
||||
}
|
||||
// Generic statics are rejected, but we still reach this case.
|
||||
|
@ -5,6 +5,7 @@
|
||||
// done by the orphan and overlap modules. Then we build up various
|
||||
// mappings. That mapping code resides here.
|
||||
|
||||
use crate::errors;
|
||||
use rustc_errors::{error_code, struct_span_err};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_middle::ty::query::Providers;
|
||||
@ -67,13 +68,7 @@ fn enforce_trait_manually_implementable(
|
||||
tcx.trait_def(trait_def_id).specialization_kind
|
||||
{
|
||||
if !tcx.features().specialization && !tcx.features().min_specialization {
|
||||
tcx.sess
|
||||
.struct_span_err(
|
||||
impl_header_span,
|
||||
"implementing `rustc_specialization_trait` traits is unstable",
|
||||
)
|
||||
.help("add `#![feature(min_specialization)]` to the crate attributes to enable")
|
||||
.emit();
|
||||
tcx.sess.emit_err(errors::SpecializationTrait { span: impl_header_span });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -455,13 +455,9 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if !infer_spans.is_empty() {
|
||||
self.tcx.sess
|
||||
.struct_span_err(
|
||||
infer_spans,
|
||||
"implicit types in closure signatures are forbidden when `for<...>` is present",
|
||||
)
|
||||
.span_label(for_sp, "`for<...>` is here")
|
||||
.emit();
|
||||
self.tcx
|
||||
.sess
|
||||
.emit_err(errors::ClosureImplicitHrtb { spans: infer_spans, for_sp });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -633,6 +633,7 @@ pub(crate) struct SIMDFFIHighlyExperimental {
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
||||
pub enum ImplNotMarkedDefault {
|
||||
#[diag(hir_analysis_impl_not_marked_default, code = "E0520")]
|
||||
#[note]
|
||||
@ -769,3 +770,48 @@ pub(crate) struct TransparentNonZeroSized<'a> {
|
||||
pub field_count: usize,
|
||||
pub desc: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_too_large_static)]
|
||||
pub(crate) struct TooLargeStatic {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_specialization_trait)]
|
||||
#[help]
|
||||
pub(crate) struct SpecializationTrait {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_closure_implicit_hrtb)]
|
||||
pub(crate) struct ClosureImplicitHrtb {
|
||||
#[primary_span]
|
||||
pub spans: Vec<Span>,
|
||||
#[label]
|
||||
pub for_sp: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_const_specialize)]
|
||||
pub(crate) struct ConstSpecialize {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_static_specialize)]
|
||||
pub(crate) struct StaticSpecialize {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_missing_tilde_const)]
|
||||
pub(crate) struct MissingTildeConst {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
@ -65,8 +65,8 @@
|
||||
//! cause use after frees with purely safe code in the same way as specializing
|
||||
//! on traits with methods can.
|
||||
|
||||
use crate::constrained_generic_params as cgp;
|
||||
use crate::errors::SubstsOnOverriddenImpl;
|
||||
use crate::{constrained_generic_params as cgp, errors};
|
||||
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_hir as hir;
|
||||
@ -137,9 +137,7 @@ fn check_constness(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node: Node,
|
||||
|
||||
if let hir::Constness::Const = impl2_constness {
|
||||
if let hir::Constness::NotConst = impl1_constness {
|
||||
tcx.sess
|
||||
.struct_span_err(span, "cannot specialize on const impl with non-const impl")
|
||||
.emit();
|
||||
tcx.sess.emit_err(errors::ConstSpecialize { span });
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -293,7 +291,7 @@ fn check_static_lifetimes<'tcx>(
|
||||
span: Span,
|
||||
) {
|
||||
if tcx.any_free_region_meets(parent_substs, |r| r.is_static()) {
|
||||
tcx.sess.struct_span_err(span, "cannot specialize on `'static` lifetime").emit();
|
||||
tcx.sess.emit_err(errors::StaticSpecialize { span });
|
||||
}
|
||||
}
|
||||
|
||||
@ -438,7 +436,7 @@ fn trait_predicates_eq<'tcx>(
|
||||
// the one on the base.
|
||||
match (trait_pred2.constness, trait_pred1.constness) {
|
||||
(ty::BoundConstness::ConstIfConst, ty::BoundConstness::NotConst) => {
|
||||
tcx.sess.struct_span_err(span, "missing `~const` qualifier for specialization").emit();
|
||||
tcx.sess.emit_err(errors::MissingTildeConst { span });
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -62,3 +62,16 @@ hir_typeck_fru_suggestion =
|
||||
[NONE]{""}
|
||||
*[other] {" "}from `{$expr}`
|
||||
}, separate the last named field with a comma
|
||||
|
||||
hir_typeck_const_select_must_be_const = this argument must be a `const fn`
|
||||
.help = consult the documentation on `const_eval_select` for more information
|
||||
|
||||
hir_typeck_const_select_must_be_fn = this argument must be a function item
|
||||
.note = expected a function item, found {$ty}
|
||||
.help = consult the documentation on `const_eval_select` for more information
|
||||
|
||||
hir_typeck_union_pat_multiple_fields = union patterns should have exactly one field
|
||||
hir_typeck_union_pat_dotdot = `..` cannot be used in union patterns
|
||||
|
||||
hir_typeck_arg_mismatch_indeterminate = argument type mismatch was detected, but rustc had trouble determining where
|
||||
.note = we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new
|
||||
|
@ -228,3 +228,42 @@ impl HelpUseLatestEdition {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_const_select_must_be_const)]
|
||||
#[help]
|
||||
pub struct ConstSelectMustBeConst {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_const_select_must_be_fn)]
|
||||
#[note]
|
||||
#[help]
|
||||
pub struct ConstSelectMustBeFn<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub ty: Ty<'a>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_union_pat_multiple_fields)]
|
||||
pub struct UnionPatMultipleFields {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_union_pat_dotdot)]
|
||||
pub struct UnionPatDotDot {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_arg_mismatch_indeterminate)]
|
||||
pub struct ArgMismatchIndeterminate {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
@ -2,8 +2,8 @@ use crate::coercion::CoerceMany;
|
||||
use crate::fn_ctxt::arg_matrix::{ArgMatrix, Compatibility, Error, ExpectedIdx, ProvidedIdx};
|
||||
use crate::gather_locals::Declaration;
|
||||
use crate::method::MethodCallee;
|
||||
use crate::Expectation::*;
|
||||
use crate::TupleArgumentsFlag::*;
|
||||
use crate::{errors, Expectation::*};
|
||||
use crate::{
|
||||
struct_span_err, BreakableCtxt, Diverges, Expectation, FnCtxt, LocalTy, Needs, RawTy,
|
||||
TupleArgumentsFlag,
|
||||
@ -283,19 +283,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
if idx == 1 && !self.tcx.is_const_fn_raw(*def_id) {
|
||||
self.tcx
|
||||
.sess
|
||||
.struct_span_err(provided_arg.span, "this argument must be a `const fn`")
|
||||
.help("consult the documentation on `const_eval_select` for more information")
|
||||
.emit();
|
||||
.emit_err(errors::ConstSelectMustBeConst { span: provided_arg.span });
|
||||
}
|
||||
} else {
|
||||
self.tcx
|
||||
.sess
|
||||
.struct_span_err(provided_arg.span, "this argument must be a function item")
|
||||
.note(format!("expected a function item, found {checked_ty}"))
|
||||
.help(
|
||||
"consult the documentation on `const_eval_select` for more information",
|
||||
)
|
||||
.emit();
|
||||
self.tcx.sess.emit_err(errors::ConstSelectMustBeFn {
|
||||
span: provided_arg.span,
|
||||
ty: checked_ty,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -744,17 +738,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
if cfg!(debug_assertions) {
|
||||
span_bug!(error_span, "expected errors from argument matrix");
|
||||
} else {
|
||||
tcx.sess
|
||||
.struct_span_err(
|
||||
error_span,
|
||||
"argument type mismatch was detected, \
|
||||
but rustc had trouble determining where",
|
||||
)
|
||||
.note(
|
||||
"we would appreciate a bug report: \
|
||||
https://github.com/rust-lang/rust/issues/new",
|
||||
)
|
||||
.emit();
|
||||
tcx.sess.emit_err(errors::ArgMismatchIndeterminate { span: error_span });
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::{FnCtxt, RawTy};
|
||||
use crate::{errors, FnCtxt, RawTy};
|
||||
use rustc_ast as ast;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::{
|
||||
@ -1410,12 +1410,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// Report an error if an incorrect number of fields was specified.
|
||||
if adt.is_union() {
|
||||
if fields.len() != 1 {
|
||||
tcx.sess
|
||||
.struct_span_err(pat.span, "union patterns should have exactly one field")
|
||||
.emit();
|
||||
tcx.sess.emit_err(errors::UnionPatMultipleFields { span: pat.span });
|
||||
}
|
||||
if has_rest_pat {
|
||||
tcx.sess.struct_span_err(pat.span, "`..` cannot be used in union patterns").emit();
|
||||
tcx.sess.emit_err(errors::UnionPatDotDot { span: pat.span });
|
||||
}
|
||||
} else if !unmentioned_fields.is_empty() {
|
||||
let accessible_unmentioned_fields: Vec<_> = unmentioned_fields
|
||||
|
@ -99,6 +99,8 @@ lint_diag_out_of_impl =
|
||||
|
||||
lint_untranslatable_diag = diagnostics should be created using translatable messages
|
||||
|
||||
lint_trivial_untranslatable_diag = diagnostic with static strings only
|
||||
|
||||
lint_bad_opt_access = {$msg}
|
||||
|
||||
lint_cstring_ptr = getting the inner pointer of a temporary `CString`
|
||||
|
@ -4,6 +4,7 @@
|
||||
use crate::lints::{
|
||||
BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonExistentDocKeyword,
|
||||
QueryInstability, TyQualified, TykindDiag, TykindKind, UntranslatableDiag,
|
||||
UntranslatableDiagnosticTrivial,
|
||||
};
|
||||
use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
|
||||
use rustc_ast as ast;
|
||||
@ -366,7 +367,15 @@ declare_tool_lint! {
|
||||
report_in_external_macro: true
|
||||
}
|
||||
|
||||
declare_lint_pass!(Diagnostics => [ UNTRANSLATABLE_DIAGNOSTIC, DIAGNOSTIC_OUTSIDE_OF_IMPL ]);
|
||||
declare_tool_lint! {
|
||||
/// The `untranslatable_diagnostic_trivial` lint detects diagnostics created using only static strings.
|
||||
pub rustc::UNTRANSLATABLE_DIAGNOSTIC_TRIVIAL,
|
||||
Deny,
|
||||
"prevent creation of diagnostics which cannot be translated, which use only static strings",
|
||||
report_in_external_macro: true
|
||||
}
|
||||
|
||||
declare_lint_pass!(Diagnostics => [ UNTRANSLATABLE_DIAGNOSTIC, DIAGNOSTIC_OUTSIDE_OF_IMPL, UNTRANSLATABLE_DIAGNOSTIC_TRIVIAL ]);
|
||||
|
||||
impl LateLintPass<'_> for Diagnostics {
|
||||
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
|
||||
@ -423,6 +432,75 @@ impl LateLintPass<'_> for Diagnostics {
|
||||
}
|
||||
}
|
||||
|
||||
impl EarlyLintPass for Diagnostics {
|
||||
#[allow(unused_must_use)]
|
||||
fn check_stmt(&mut self, cx: &EarlyContext<'_>, stmt: &ast::Stmt) {
|
||||
// Looking for a straight chain of method calls from 'struct_span_err' to 'emit'.
|
||||
let ast::StmtKind::Semi(expr) = &stmt.kind else {
|
||||
return;
|
||||
};
|
||||
let ast::ExprKind::MethodCall(meth) = &expr.kind else {
|
||||
return;
|
||||
};
|
||||
if meth.seg.ident.name != sym::emit || !meth.args.is_empty() {
|
||||
return;
|
||||
}
|
||||
let mut segments = vec![];
|
||||
let mut cur = &meth.receiver;
|
||||
let fake = &[].into();
|
||||
loop {
|
||||
match &cur.kind {
|
||||
ast::ExprKind::Call(func, args) => {
|
||||
if let ast::ExprKind::Path(_, path) = &func.kind {
|
||||
segments.push((path.segments.last().unwrap().ident.name, args))
|
||||
}
|
||||
break;
|
||||
}
|
||||
ast::ExprKind::MethodCall(method) => {
|
||||
segments.push((method.seg.ident.name, &method.args));
|
||||
cur = &method.receiver;
|
||||
}
|
||||
ast::ExprKind::MacCall(mac) => {
|
||||
segments.push((mac.path.segments.last().unwrap().ident.name, fake));
|
||||
break;
|
||||
}
|
||||
_ => {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
segments.reverse();
|
||||
if segments.is_empty() {
|
||||
return;
|
||||
}
|
||||
if segments[0].0.as_str() != "struct_span_err" {
|
||||
return;
|
||||
}
|
||||
if !segments.iter().all(|(name, args)| {
|
||||
let arg = match name.as_str() {
|
||||
"struct_span_err" | "span_note" | "span_label" | "span_help" => &args[1],
|
||||
"note" | "help" => &args[0],
|
||||
_ => {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
if let ast::ExprKind::Lit(lit) = arg.kind
|
||||
&& let ast::token::LitKind::Str = lit.kind {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}) {
|
||||
return;
|
||||
}
|
||||
cx.emit_spanned_lint(
|
||||
UNTRANSLATABLE_DIAGNOSTIC_TRIVIAL,
|
||||
stmt.span,
|
||||
UntranslatableDiagnosticTrivial,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
declare_tool_lint! {
|
||||
/// The `bad_opt_access` lint detects accessing options by field instead of
|
||||
/// the wrapper function.
|
||||
|
@ -518,6 +518,7 @@ fn register_internals(store: &mut LintStore) {
|
||||
store.register_lints(&TyTyKind::get_lints());
|
||||
store.register_late_pass(|_| Box::new(TyTyKind));
|
||||
store.register_lints(&Diagnostics::get_lints());
|
||||
store.register_early_pass(|| Box::new(Diagnostics));
|
||||
store.register_late_pass(|_| Box::new(Diagnostics));
|
||||
store.register_lints(&BadOptAccess::get_lints());
|
||||
store.register_late_pass(|_| Box::new(BadOptAccess));
|
||||
|
@ -820,6 +820,10 @@ pub struct DiagOutOfImpl;
|
||||
#[diag(lint_untranslatable_diag)]
|
||||
pub struct UntranslatableDiag;
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_trivial_untranslatable_diag)]
|
||||
pub struct UntranslatableDiagnosticTrivial;
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_bad_opt_access)]
|
||||
pub struct BadOptAccessDiag<'a> {
|
||||
|
@ -742,3 +742,33 @@ parse_bad_return_type_notation_output =
|
||||
parse_bad_return_type_notation_dotdot =
|
||||
return type notation uses `()` instead of `(..)` for elided arguments
|
||||
.suggestion = remove the `..`
|
||||
|
||||
parse_bad_assoc_type_bounds = bounds on associated types do not belong here
|
||||
.label = belongs in `where` clause
|
||||
|
||||
parse_attr_after_generic = trailing attribute after generic parameter
|
||||
.label = attributes must go before parameters
|
||||
|
||||
parse_attr_without_generics = attribute without generic parameters
|
||||
.label = attributes are only permitted when preceding parameters
|
||||
|
||||
parse_where_generics = generic parameters on `where` clauses are reserved for future use
|
||||
.label = currently unsupported
|
||||
|
||||
parse_generics_in_path = unexpected generic arguments in path
|
||||
|
||||
parse_assoc_lifetime = associated lifetimes are not supported
|
||||
.label = the lifetime is given here
|
||||
.help = if you meant to specify a trait object, write `dyn Trait + 'lifetime`
|
||||
|
||||
parse_tilde_const_lifetime = `~const` may only modify trait bounds, not lifetime bounds
|
||||
|
||||
parse_maybe_lifetime = `?` may only modify trait bounds, not lifetime bounds
|
||||
|
||||
parse_parenthesized_lifetime = parenthesized lifetime bounds are not supported
|
||||
.suggestion = remove the parentheses
|
||||
|
||||
parse_const_bounds_missing_tilde = const bounds must start with `~`
|
||||
.suggestion = add `~`
|
||||
|
||||
parse_underscore_literal_suffix = underscore literal suffix is not allowed
|
||||
|
@ -2332,3 +2332,92 @@ pub(crate) struct BadReturnTypeNotationDotDot {
|
||||
#[suggestion(code = "", applicability = "maybe-incorrect")]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parse_bad_assoc_type_bounds)]
|
||||
pub(crate) struct BadAssocTypeBounds {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parse_attr_after_generic)]
|
||||
pub(crate) struct AttrAfterGeneric {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parse_attr_without_generics)]
|
||||
pub(crate) struct AttrWithoutGenerics {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parse_where_generics)]
|
||||
pub(crate) struct WhereOnGenerics {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parse_generics_in_path)]
|
||||
pub(crate) struct GenericsInPath {
|
||||
#[primary_span]
|
||||
pub span: Vec<Span>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parse_assoc_lifetime)]
|
||||
#[help]
|
||||
pub(crate) struct AssocLifetime {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[label]
|
||||
pub lifetime: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parse_tilde_const_lifetime)]
|
||||
pub(crate) struct TildeConstLifetime {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parse_maybe_lifetime)]
|
||||
pub(crate) struct MaybeLifetime {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parse_parenthesized_lifetime)]
|
||||
pub(crate) struct ParenthesizedLifetime {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[suggestion(style = "short", applicability = "machine-applicable", code = "{snippet}")]
|
||||
pub sugg: Option<Span>,
|
||||
pub snippet: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parse_const_bounds_missing_tilde)]
|
||||
pub(crate) struct ConstMissingTilde {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[suggestion(code = "~", applicability = "machine-applicable")]
|
||||
pub start: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parse_underscore_literal_suffix)]
|
||||
pub(crate) struct UnderscoreLiteralSuffix {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
@ -209,11 +209,7 @@ impl<'a> StringReader<'a> {
|
||||
if string == "_" {
|
||||
self.sess
|
||||
.span_diagnostic
|
||||
.struct_span_err(
|
||||
self.mk_sp(suffix_start, self.pos),
|
||||
"underscore literal suffix is not allowed",
|
||||
)
|
||||
.emit();
|
||||
.emit_err(errors::UnderscoreLiteralSuffix { span: self.mk_sp(suffix_start, self.pos) });
|
||||
None
|
||||
} else {
|
||||
Some(Symbol::intern(string))
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::errors::{
|
||||
MultipleWhereClauses, UnexpectedDefaultValueForLifetimeInGenericParameters,
|
||||
self, MultipleWhereClauses, UnexpectedDefaultValueForLifetimeInGenericParameters,
|
||||
UnexpectedSelfInGenericParameters, WhereClauseBeforeTupleStructBody,
|
||||
WhereClauseBeforeTupleStructBodySugg,
|
||||
};
|
||||
@ -181,12 +181,9 @@ impl<'a> Parser<'a> {
|
||||
let snapshot = this.create_snapshot_for_diagnostic();
|
||||
match this.parse_ty_where_predicate() {
|
||||
Ok(where_predicate) => {
|
||||
this.struct_span_err(
|
||||
where_predicate.span(),
|
||||
"bounds on associated types do not belong here",
|
||||
)
|
||||
.span_label(where_predicate.span(), "belongs in `where` clause")
|
||||
.emit();
|
||||
this.sess.emit_err(errors::BadAssocTypeBounds {
|
||||
span: where_predicate.span(),
|
||||
});
|
||||
// FIXME - try to continue parsing other generics?
|
||||
return Ok((None, TrailingToken::None));
|
||||
}
|
||||
@ -201,22 +198,11 @@ impl<'a> Parser<'a> {
|
||||
// Check for trailing attributes and stop parsing.
|
||||
if !attrs.is_empty() {
|
||||
if !params.is_empty() {
|
||||
this.struct_span_err(
|
||||
attrs[0].span,
|
||||
"trailing attribute after generic parameter",
|
||||
)
|
||||
.span_label(attrs[0].span, "attributes must go before parameters")
|
||||
.emit();
|
||||
this.sess
|
||||
.emit_err(errors::AttrAfterGeneric { span: attrs[0].span });
|
||||
} else {
|
||||
this.struct_span_err(
|
||||
attrs[0].span,
|
||||
"attribute without generic parameters",
|
||||
)
|
||||
.span_label(
|
||||
attrs[0].span,
|
||||
"attributes are only permitted when preceding parameters",
|
||||
)
|
||||
.emit();
|
||||
this.sess
|
||||
.emit_err(errors::AttrWithoutGenerics { span: attrs[0].span });
|
||||
}
|
||||
}
|
||||
return Ok((None, TrailingToken::None));
|
||||
@ -304,12 +290,7 @@ impl<'a> Parser<'a> {
|
||||
// change we parse those generics now, but report an error.
|
||||
if self.choose_generics_over_qpath(0) {
|
||||
let generics = self.parse_generics()?;
|
||||
self.struct_span_err(
|
||||
generics.span,
|
||||
"generic parameters on `where` clauses are reserved for future use",
|
||||
)
|
||||
.span_label(generics.span, "currently unsupported")
|
||||
.emit();
|
||||
self.sess.emit_err(errors::WhereOnGenerics { span: generics.span });
|
||||
}
|
||||
|
||||
loop {
|
||||
|
@ -150,16 +150,13 @@ impl<'a> Parser<'a> {
|
||||
//
|
||||
if style == PathStyle::Mod && path.segments.iter().any(|segment| segment.args.is_some())
|
||||
{
|
||||
parser
|
||||
.struct_span_err(
|
||||
path.segments
|
||||
.iter()
|
||||
.filter_map(|segment| segment.args.as_ref())
|
||||
.map(|arg| arg.span())
|
||||
.collect::<Vec<_>>(),
|
||||
"unexpected generic arguments in path",
|
||||
)
|
||||
.emit();
|
||||
let span = path
|
||||
.segments
|
||||
.iter()
|
||||
.filter_map(|segment| segment.args.as_ref())
|
||||
.map(|arg| arg.span())
|
||||
.collect::<Vec<_>>();
|
||||
parser.sess.emit_err(errors::GenericsInPath { span });
|
||||
}
|
||||
};
|
||||
|
||||
@ -620,10 +617,7 @@ impl<'a> Parser<'a> {
|
||||
c.into()
|
||||
}
|
||||
Some(GenericArg::Lifetime(lt)) => {
|
||||
self.struct_span_err(span, "associated lifetimes are not supported")
|
||||
.span_label(lt.ident.span, "the lifetime is given here")
|
||||
.help("if you meant to specify a trait object, write `dyn Trait + 'lifetime`")
|
||||
.emit();
|
||||
self.sess.emit_err(errors::AssocLifetime { span, lifetime: lt.ident.span });
|
||||
self.mk_ty(span, ast::TyKind::Err).into()
|
||||
}
|
||||
None => {
|
||||
|
@ -1,7 +1,7 @@
|
||||
use super::{Parser, PathStyle, TokenType};
|
||||
|
||||
use crate::errors::{
|
||||
DynAfterMut, ExpectedFnPathFoundFnKeyword, ExpectedMutOrConstInRawPointerType,
|
||||
self, DynAfterMut, ExpectedFnPathFoundFnKeyword, ExpectedMutOrConstInRawPointerType,
|
||||
FnPointerCannotBeAsync, FnPointerCannotBeConst, FnPtrWithGenerics, FnPtrWithGenericsSugg,
|
||||
InvalidDynKeyword, LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime,
|
||||
NegativeBoundsNotSupported, NegativeBoundsNotSupportedSugg, NestedCVariadicType,
|
||||
@ -807,16 +807,11 @@ impl<'a> Parser<'a> {
|
||||
/// Emits an error if any trait bound modifiers were present.
|
||||
fn error_lt_bound_with_modifiers(&self, modifiers: BoundModifiers) {
|
||||
if let Some(span) = modifiers.maybe_const {
|
||||
self.struct_span_err(
|
||||
span,
|
||||
"`~const` may only modify trait bounds, not lifetime bounds",
|
||||
)
|
||||
.emit();
|
||||
self.sess.emit_err(errors::TildeConstLifetime { span });
|
||||
}
|
||||
|
||||
if let Some(span) = modifiers.maybe {
|
||||
self.struct_span_err(span, "`?` may only modify trait bounds, not lifetime bounds")
|
||||
.emit();
|
||||
self.sess.emit_err(errors::MaybeLifetime { span });
|
||||
}
|
||||
}
|
||||
|
||||
@ -824,19 +819,14 @@ impl<'a> Parser<'a> {
|
||||
fn recover_paren_lifetime(&mut self, lo: Span, inner_lo: Span) -> PResult<'a, ()> {
|
||||
let inner_span = inner_lo.to(self.prev_token.span);
|
||||
self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
|
||||
let mut err = self.struct_span_err(
|
||||
lo.to(self.prev_token.span),
|
||||
"parenthesized lifetime bounds are not supported",
|
||||
);
|
||||
if let Ok(snippet) = self.span_to_snippet(inner_span) {
|
||||
err.span_suggestion_short(
|
||||
lo.to(self.prev_token.span),
|
||||
"remove the parentheses",
|
||||
snippet,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
err.emit();
|
||||
let span = lo.to(self.prev_token.span);
|
||||
let (sugg, snippet) = if let Ok(snippet) = self.span_to_snippet(inner_span) {
|
||||
(Some(span), snippet)
|
||||
} else {
|
||||
(None, String::new())
|
||||
};
|
||||
|
||||
self.sess.emit_err(errors::ParenthesizedLifetime { span, sugg, snippet });
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -857,15 +847,7 @@ impl<'a> Parser<'a> {
|
||||
} else if self.eat_keyword(kw::Const) {
|
||||
let span = self.prev_token.span;
|
||||
self.sess.gated_spans.gate(sym::const_trait_impl, span);
|
||||
|
||||
self.struct_span_err(span, "const bounds must start with `~`")
|
||||
.span_suggestion(
|
||||
span.shrink_to_lo(),
|
||||
"add `~`",
|
||||
"~",
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
self.sess.emit_err(errors::ConstMissingTilde { span, start: span.shrink_to_lo() });
|
||||
|
||||
Some(span)
|
||||
} else {
|
||||
|
@ -226,3 +226,10 @@ resolve_add_as_non_derive =
|
||||
|
||||
resolve_proc_macro_same_crate = can't use a procedural macro from the same crate that defines it
|
||||
.help = you can define integration tests in a directory named `tests`
|
||||
|
||||
resolve_imported_crate = `$crate` may not be imported
|
||||
|
||||
resolve_macro_use_extern_crate_self = `#[macro_use]` is not supported on `extern crate self`
|
||||
|
||||
resolve_accessible_unsure = not sure whether the path is accessible or not
|
||||
.note = the type may have associated items, but we are currently not checking them
|
||||
|
@ -9,7 +9,9 @@ use crate::def_collector::collect_definitions;
|
||||
use crate::imports::{Import, ImportKind};
|
||||
use crate::macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef};
|
||||
use crate::Namespace::{self, MacroNS, TypeNS, ValueNS};
|
||||
use crate::{Determinacy, ExternPreludeEntry, Finalize, Module, ModuleKind, ModuleOrUniformRoot};
|
||||
use crate::{
|
||||
errors, Determinacy, ExternPreludeEntry, Finalize, Module, ModuleKind, ModuleOrUniformRoot,
|
||||
};
|
||||
use crate::{
|
||||
MacroData, NameBinding, NameBindingKind, ParentScope, PathResult, PerNS, ResolutionError,
|
||||
};
|
||||
@ -523,11 +525,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
|
||||
ident.name = crate_name;
|
||||
}
|
||||
|
||||
self.r
|
||||
.tcx
|
||||
.sess
|
||||
.struct_span_err(item.span, "`$crate` may not be imported")
|
||||
.emit();
|
||||
self.r.tcx.sess.emit_err(errors::CrateImported { span: item.span });
|
||||
}
|
||||
}
|
||||
|
||||
@ -1028,11 +1026,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
|
||||
self.r
|
||||
.tcx
|
||||
.sess
|
||||
.struct_span_err(
|
||||
attr.span,
|
||||
"`#[macro_use]` is not supported on `extern crate self`",
|
||||
)
|
||||
.emit();
|
||||
.emit_err(errors::MacroUseExternCrateSelf { span: attr.span });
|
||||
}
|
||||
}
|
||||
let ill_formed = |span| {
|
||||
|
@ -517,3 +517,25 @@ pub(crate) struct ProcMacroSameCrate {
|
||||
#[help]
|
||||
pub(crate) is_test: bool,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(resolve_imported_crate)]
|
||||
pub(crate) struct CrateImported {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(resolve_macro_use_extern_crate_self)]
|
||||
pub(crate) struct MacroUseExternCrateSelf {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(resolve_accessible_unsure)]
|
||||
#[note]
|
||||
pub(crate) struct CfgAccessibleUnsure {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
@ -436,9 +436,7 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> {
|
||||
// HACK(Urgau): This shouldn't be necessary
|
||||
PathResult::Failed { is_error_from_last_segment: false, .. } => {
|
||||
self.tcx.sess
|
||||
.struct_span_err(span, "not sure whether the path is accessible or not")
|
||||
.note("the type may have associated items, but we are currently not checking them")
|
||||
.emit();
|
||||
.emit_err(errors::CfgAccessibleUnsure { span });
|
||||
|
||||
// If we get a partially resolved NonModule in one namespace, we should get the
|
||||
// same result in any other namespaces, so we can return early.
|
||||
|
@ -651,6 +651,7 @@ symbols! {
|
||||
edition_panic,
|
||||
eh_catch_typeinfo,
|
||||
eh_personality,
|
||||
emit,
|
||||
emit_enum,
|
||||
emit_enum_variant,
|
||||
emit_enum_variant_arg,
|
||||
|
Loading…
Reference in New Issue
Block a user