use rustc_ast::*;
use rustc_ast_pretty::pprust::{self, State};
use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::{error_code, pluralize, struct_span_err, Applicability, Diagnostic};
+use rustc_errors::{error_code, fluent, pluralize, struct_span_err, Applicability, Diagnostic};
use rustc_parse::validate_attr;
use rustc_session::lint::builtin::{
DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY,
use std::mem;
use std::ops::{Deref, DerefMut};
+use crate::errors::*;
+
const MORE_EXTERN: &str =
"for more information, visit https://doc.rust-lang.org/std/keyword.extern.html";
/// Emits an error banning the `let` expression provided in the given location.
fn ban_let_expr(&self, expr: &'a Expr, forbidden_let_reason: ForbiddenLetReason) {
- let err = "`let` expressions are not supported here";
- let mut diag = self.session.struct_span_err(expr.span, err);
- diag.note("only supported directly in conditions of `if` and `while` expressions");
- match forbidden_let_reason {
- ForbiddenLetReason::GenericForbidden => {}
- ForbiddenLetReason::NotSupportedOr(span) => {
- diag.span_note(span, "`||` operators are not supported in let chain expressions");
- }
- ForbiddenLetReason::NotSupportedParentheses(span) => {
- diag.span_note(
- span,
- "`let`s wrapped in parentheses are not supported in a context with let \
- chains",
- );
- }
- }
- diag.emit();
+ self.session.emit_err(ForbiddenLet { span: expr.span, reason: forbidden_let_reason });
}
fn check_gat_where(
DEPRECATED_WHERE_CLAUSE_LOCATION,
id,
where_clauses.0.1,
- "where clause not allowed here",
+ fluent::ast_passes::deprecated_where_clause_location,
BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(
where_clauses.1.1.shrink_to_hi(),
suggestion,
AssocConstraintKind::Equality { .. } => {}
AssocConstraintKind::Bound { .. } => {
if self.is_assoc_ty_bound_banned {
- self.err_handler().span_err(
- constraint.span,
- "associated type bounds are not allowed within structs, enums, or unions",
- );
+ self.session.emit_err(ForbiddenAssocConstraint { span: constraint.span });
}
}
}
fn check_lifetime(&self, ident: Ident) {
let valid_names = [kw::UnderscoreLifetime, kw::StaticLifetime, kw::Empty];
if !valid_names.contains(&ident.name) && ident.without_first_quote().is_reserved() {
- self.err_handler().span_err(ident.span, "lifetimes cannot use keyword names");
+ self.session.emit_err(KeywordLifetime { span: ident.span });
}
}
fn check_label(&self, ident: Ident) {
if ident.without_first_quote().is_reserved() {
- self.err_handler()
- .span_err(ident.span, &format!("invalid label name `{}`", ident.name));
+ self.session.emit_err(InvalidLabel { span: ident.span, name: ident.name });
}
}
- fn invalid_visibility(&self, vis: &Visibility, note: Option<&str>) {
+ fn invalid_visibility(&self, vis: &Visibility, note: Option<InvalidVisibilityNote>) {
if let VisibilityKind::Inherited = vis.kind {
return;
}
- let mut err =
- struct_span_err!(self.session, vis.span, E0449, "unnecessary visibility qualifier");
- if vis.kind.is_pub() {
- err.span_label(vis.span, "`pub` not permitted here because it's implied");
- }
- if let Some(note) = note {
- err.note(note);
- }
- err.emit();
+ self.session.emit_err(InvalidVisibility {
+ span: vis.span,
+ implied: if vis.kind.is_pub() { Some(vis.span) } else { None },
+ note,
+ });
}
fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option<Ident>, bool)) {
fn check_trait_fn_not_async(&self, fn_span: Span, asyncness: Async) {
if let Async::Yes { span, .. } = asyncness {
- struct_span_err!(
- self.session,
- fn_span,
- E0706,
- "functions in traits cannot be declared `async`"
- )
- .span_label(span, "`async` because of this")
- .note("`async` trait functions are not currently supported")
- .note("consider using the `async-trait` crate: https://crates.io/crates/async-trait")
- .emit();
+ self.session.emit_err(TraitFnAsync { fn_span, span });
}
}
fn check_trait_fn_not_const(&self, constness: Const) {
if let Const::Yes(span) = constness {
- struct_span_err!(
- self.session,
- span,
- E0379,
- "functions in traits cannot be declared const"
- )
- .span_label(span, "functions in traits cannot be const")
- .emit();
+ self.session.emit_err(TraitFnConst { span });
}
}
GenericParamKind::Lifetime { .. } => {
if !param.bounds.is_empty() {
let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
- self.err_handler()
- .span_err(spans, "lifetime bounds cannot be used in this context");
+ self.session.emit_err(ForbiddenLifetimeBound { spans });
}
None
}
})
.collect();
if !non_lt_param_spans.is_empty() {
- self.err_handler().span_err(
- non_lt_param_spans,
- "only lifetime parameters can be used in this context",
- );
+ self.session.emit_err(ForbiddenNonLifetimeParam { spans: non_lt_param_spans });
}
}
let max_num_args: usize = u16::MAX.into();
if fn_decl.inputs.len() > max_num_args {
let Param { span, .. } = fn_decl.inputs[0];
- self.err_handler().span_fatal(
- span,
- &format!("function can not have more than {} arguments", max_num_args),
- );
+ self.session.emit_fatal(FnParamTooMany { span, max_num_args });
}
}
match &*fn_decl.inputs {
[Param { ty, span, .. }] => {
if let TyKind::CVarArgs = ty.kind {
- self.err_handler().span_err(
- *span,
- "C-variadic function must be declared with at least one named argument",
- );
+ self.session.emit_err(FnParamCVarArgsOnly { span: *span });
}
}
[ps @ .., _] => {
for Param { ty, span, .. } in ps {
if let TyKind::CVarArgs = ty.kind {
- self.err_handler().span_err(
- *span,
- "`...` must be the last argument of a C-variadic function",
- );
+ self.session.emit_err(FnParamCVarArgsNotLast { span: *span });
}
}
}
})
.for_each(|attr| {
if attr.is_doc_comment() {
- self.err_handler()
- .struct_span_err(
- attr.span,
- "documentation comments cannot be applied to function parameters",
- )
- .span_label(attr.span, "doc comments are not allowed here")
- .emit();
+ self.session.emit_err(FnParamDocComment { span: attr.span });
} else {
- self.err_handler().span_err(
- attr.span,
- "allow, cfg, cfg_attr, deny, expect, \
- forbid, and warn are the only allowed built-in attributes in function parameters",
- );
+ self.session.emit_err(FnParamForbiddenAttr { span: attr.span });
}
});
}
fn check_decl_self_param(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) {
if let (SelfSemantic::No, [param, ..]) = (self_semantic, &*fn_decl.inputs) {
if param.is_self() {
- self.err_handler()
- .struct_span_err(
- param.span,
- "`self` parameter is only allowed in associated functions",
- )
- .span_label(param.span, "not semantically valid as function parameter")
- .note("associated functions are those in `impl` or `trait` definitions")
- .emit();
+ self.session.emit_err(FnParamForbiddenSelf { span: param.span });
}
}
}
self.invalid_visibility(
&item.vis,
- Some("place qualifiers on individual impl items instead"),
+ Some(InvalidVisibilityNote::IndividualImplItems),
);
if let Unsafe::Yes(span) = unsafety {
error(span, "unsafe").code(error_code!(E0197)).emit();
let old_item = mem::replace(&mut self.extern_mod, Some(item));
self.invalid_visibility(
&item.vis,
- Some("place qualifiers on individual foreign items instead"),
+ Some(InvalidVisibilityNote::IndividualForeignItems),
);
if let Unsafe::Yes(span) = unsafety {
self.err_handler().span_err(span, "extern block cannot be declared unsafe");
visit::walk_param_bound(self, bound)
}
- fn visit_poly_trait_ref(&mut self, t: &'a PolyTraitRef, m: &'a TraitBoundModifier) {
+ fn visit_poly_trait_ref(&mut self, t: &'a PolyTraitRef) {
self.check_late_bound_lifetime_defs(&t.bound_generic_params);
- visit::walk_poly_trait_ref(self, t, m);
+ visit::walk_poly_trait_ref(self, t);
}
fn visit_variant_data(&mut self, s: &'a VariantData) {
self.with_banned_assoc_ty_bound(|this| visit::walk_struct_def(this, s))
}
- fn visit_enum_def(
- &mut self,
- enum_definition: &'a EnumDef,
- generics: &'a Generics,
- item_id: NodeId,
- _: Span,
- ) {
- self.with_banned_assoc_ty_bound(|this| {
- visit::walk_enum_def(this, enum_definition, generics, item_id)
- })
+ fn visit_enum_def(&mut self, enum_definition: &'a EnumDef) {
+ self.with_banned_assoc_ty_bound(|this| visit::walk_enum_def(this, enum_definition))
}
fn visit_fn(&mut self, fk: FnKind<'a>, span: Span, id: NodeId) {
/// Used to forbid `let` expressions in certain syntactic locations.
#[derive(Clone, Copy)]
-enum ForbiddenLetReason {
+pub(crate) enum ForbiddenLetReason {
/// `let` is not valid and the source environment is not important
GenericForbidden,
/// A let chain with the `||` operator