Auto merge of #101064 - compiler-errors:rollup-fwm5m5f, r=compiler-errors

Rollup of 9 pull requests

Successful merges:

 - #100724 (Migrate ast lowering to session diagnostic)
 - #100735 (Migrate `rustc_ty_utils` to `SessionDiagnostic`)
 - #100738 (Diagnostics migr const eval)
 - #100744 (Migrate rustc_mir_dataflow to diagnostic structs)
 - #100776 (Migrate `rustc_lint` errors to `SessionDiagnostic`)
 - #100817 (sugg: suggest the usage of boolean value when there is a typo in the keyword)
 - #100836 (Migrate `rustc_attr` crate diagnostics)
 - #100890 (Migrate rustc_driver to SessionDiagnostic)
 - #100900 (on `region_errors.rs`)

Failed merges:

 - #100831 (Migrate `symbol_mangling` module to new diagnostics structs)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2022-08-27 00:38:06 +00:00
commit bb8a08f011
51 changed files with 2448 additions and 930 deletions

View File

@ -3574,6 +3574,7 @@ dependencies = [
"rustc_errors",
"rustc_hir",
"rustc_index",
"rustc_macros",
"rustc_middle",
"rustc_query_system",
"rustc_session",
@ -3819,6 +3820,7 @@ dependencies = [
"rustc_interface",
"rustc_lint",
"rustc_log",
"rustc_macros",
"rustc_metadata",
"rustc_middle",
"rustc_parse",
@ -4212,11 +4214,14 @@ dependencies = [
"regex",
"rustc_ast",
"rustc_data_structures",
"rustc_errors",
"rustc_graphviz",
"rustc_hir",
"rustc_index",
"rustc_macros",
"rustc_middle",
"rustc_serialize",
"rustc_session",
"rustc_span",
"rustc_target",
"smallvec",
@ -4600,6 +4605,7 @@ dependencies = [
"rustc_hir",
"rustc_index",
"rustc_infer",
"rustc_macros",
"rustc_middle",
"rustc_session",
"rustc_span",

View File

@ -15,6 +15,7 @@ rustc_target = { path = "../rustc_target" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_index = { path = "../rustc_index" }
rustc_middle = { path = "../rustc_middle" }
rustc_macros = { path = "../rustc_macros" }
rustc_query_system = { path = "../rustc_query_system" }
rustc_span = { path = "../rustc_span" }
rustc_errors = { path = "../rustc_errors" }

View File

@ -1,11 +1,17 @@
use crate::{ImplTraitContext, ImplTraitPosition, ParamMode, ResolverAstLoweringExt};
use super::errors::{
AbiSpecifiedMultipleTimes, AttSyntaxOnlyX86, ClobberAbiNotSupported,
InlineAsmUnsupportedTarget, InvalidAbiClobberAbi, InvalidAsmTemplateModifierConst,
InvalidAsmTemplateModifierRegClass, InvalidAsmTemplateModifierRegClassSub,
InvalidAsmTemplateModifierSym, InvalidRegister, InvalidRegisterClass, RegisterClassOnlyClobber,
RegisterConflict,
};
use super::LoweringContext;
use rustc_ast::ptr::P;
use rustc_ast::*;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::definitions::DefPathData;
@ -26,13 +32,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let asm_arch =
if self.tcx.sess.opts.actually_rustdoc { None } else { self.tcx.sess.asm_arch };
if asm_arch.is_none() && !self.tcx.sess.opts.actually_rustdoc {
struct_span_err!(
self.tcx.sess,
sp,
E0472,
"inline assembly is unsupported on this target"
)
.emit();
self.tcx.sess.emit_err(InlineAsmUnsupportedTarget { span: sp });
}
if let Some(asm_arch) = asm_arch {
// Inline assembly is currently only stable for these architectures.
@ -59,10 +59,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
&& !matches!(asm_arch, Some(asm::InlineAsmArch::X86 | asm::InlineAsmArch::X86_64))
&& !self.tcx.sess.opts.actually_rustdoc
{
self.tcx
.sess
.struct_span_err(sp, "the `att_syntax` option is only supported on x86")
.emit();
self.tcx.sess.emit_err(AttSyntaxOnlyX86 { span: sp });
}
if asm.options.contains(InlineAsmOptions::MAY_UNWIND) && !self.tcx.features().asm_unwind {
feature_err(
@ -82,51 +79,37 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// If the abi was already in the list, emit an error
match clobber_abis.get(&abi) {
Some((prev_name, prev_sp)) => {
let mut err = self.tcx.sess.struct_span_err(
*abi_span,
&format!("`{}` ABI specified multiple times", prev_name),
);
err.span_label(*prev_sp, "previously specified here");
// Multiple different abi names may actually be the same ABI
// If the specified ABIs are not the same name, alert the user that they resolve to the same ABI
let source_map = self.tcx.sess.source_map();
if source_map.span_to_snippet(*prev_sp)
!= source_map.span_to_snippet(*abi_span)
{
err.note("these ABIs are equivalent on the current target");
}
let equivalent = (source_map.span_to_snippet(*prev_sp)
!= source_map.span_to_snippet(*abi_span))
.then_some(());
err.emit();
self.tcx.sess.emit_err(AbiSpecifiedMultipleTimes {
abi_span: *abi_span,
prev_name: *prev_name,
prev_span: *prev_sp,
equivalent,
});
}
None => {
clobber_abis.insert(abi, (abi_name, *abi_span));
clobber_abis.insert(abi, (*abi_name, *abi_span));
}
}
}
Err(&[]) => {
self.tcx
.sess
.struct_span_err(
*abi_span,
"`clobber_abi` is not supported on this target",
)
.emit();
self.tcx.sess.emit_err(ClobberAbiNotSupported { abi_span: *abi_span });
}
Err(supported_abis) => {
let mut err = self
.tcx
.sess
.struct_span_err(*abi_span, "invalid ABI for `clobber_abi`");
let mut abis = format!("`{}`", supported_abis[0]);
for m in &supported_abis[1..] {
let _ = write!(abis, ", `{}`", m);
}
err.note(&format!(
"the following ABIs are supported on this target: {}",
abis
));
err.emit();
self.tcx.sess.emit_err(InvalidAbiClobberAbi {
abi_span: *abi_span,
supported_abis: abis,
});
}
}
}
@ -141,24 +124,28 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
.iter()
.map(|(op, op_sp)| {
let lower_reg = |reg| match reg {
InlineAsmRegOrRegClass::Reg(s) => {
InlineAsmRegOrRegClass::Reg(reg) => {
asm::InlineAsmRegOrRegClass::Reg(if let Some(asm_arch) = asm_arch {
asm::InlineAsmReg::parse(asm_arch, s).unwrap_or_else(|e| {
let msg = format!("invalid register `{}`: {}", s, e);
sess.struct_span_err(*op_sp, &msg).emit();
asm::InlineAsmReg::parse(asm_arch, reg).unwrap_or_else(|error| {
sess.emit_err(InvalidRegister { op_span: *op_sp, reg, error });
asm::InlineAsmReg::Err
})
} else {
asm::InlineAsmReg::Err
})
}
InlineAsmRegOrRegClass::RegClass(s) => {
InlineAsmRegOrRegClass::RegClass(reg_class) => {
asm::InlineAsmRegOrRegClass::RegClass(if let Some(asm_arch) = asm_arch {
asm::InlineAsmRegClass::parse(asm_arch, s).unwrap_or_else(|e| {
let msg = format!("invalid register class `{}`: {}", s, e);
sess.struct_span_err(*op_sp, &msg).emit();
asm::InlineAsmRegClass::Err
})
asm::InlineAsmRegClass::parse(asm_arch, reg_class).unwrap_or_else(
|error| {
sess.emit_err(InvalidRegisterClass {
op_span: *op_sp,
reg_class,
error,
});
asm::InlineAsmRegClass::Err
},
)
} else {
asm::InlineAsmRegClass::Err
})
@ -282,50 +269,39 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
let valid_modifiers = class.valid_modifiers(asm_arch.unwrap());
if !valid_modifiers.contains(&modifier) {
let mut err = sess.struct_span_err(
placeholder_span,
"invalid asm template modifier for this register class",
);
err.span_label(placeholder_span, "template modifier");
err.span_label(op_sp, "argument");
if !valid_modifiers.is_empty() {
let sub = if !valid_modifiers.is_empty() {
let mut mods = format!("`{}`", valid_modifiers[0]);
for m in &valid_modifiers[1..] {
let _ = write!(mods, ", `{}`", m);
}
err.note(&format!(
"the `{}` register class supports \
the following template modifiers: {}",
class.name(),
mods
));
InvalidAsmTemplateModifierRegClassSub::SupportModifier {
class_name: class.name(),
modifiers: mods,
}
} else {
err.note(&format!(
"the `{}` register class does not support template modifiers",
class.name()
));
}
err.emit();
InvalidAsmTemplateModifierRegClassSub::DoesNotSupportModifier {
class_name: class.name(),
}
};
sess.emit_err(InvalidAsmTemplateModifierRegClass {
placeholder_span,
op_span: op_sp,
sub,
});
}
}
hir::InlineAsmOperand::Const { .. } => {
let mut err = sess.struct_span_err(
sess.emit_err(InvalidAsmTemplateModifierConst {
placeholder_span,
"asm template modifiers are not allowed for `const` arguments",
);
err.span_label(placeholder_span, "template modifier");
err.span_label(op_sp, "argument");
err.emit();
op_span: op_sp,
});
}
hir::InlineAsmOperand::SymFn { .. }
| hir::InlineAsmOperand::SymStatic { .. } => {
let mut err = sess.struct_span_err(
sess.emit_err(InvalidAsmTemplateModifierSym {
placeholder_span,
"asm template modifiers are not allowed for `sym` arguments",
);
err.span_label(placeholder_span, "template modifier");
err.span_label(op_sp, "argument");
err.emit();
op_span: op_sp,
});
}
}
}
@ -346,12 +322,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// require that the operand name an explicit register, not a
// register class.
if reg_class.is_clobber_only(asm_arch.unwrap()) && !op.is_clobber() {
let msg = format!(
"register class `{}` can only be used as a clobber, \
not as an input or output",
reg_class.name()
);
sess.struct_span_err(op_sp, &msg).emit();
sess.emit_err(RegisterClassOnlyClobber {
op_span: op_sp,
reg_class_name: reg_class.name(),
});
continue;
}
@ -391,16 +365,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
unreachable!();
};
let msg = format!(
"register `{}` conflicts with register `{}`",
reg.name(),
reg2.name()
);
let mut err = sess.struct_span_err(op_sp, &msg);
err.span_label(op_sp, &format!("register `{}`", reg.name()));
err.span_label(op_sp2, &format!("register `{}`", reg2.name()));
match (op, op2) {
let in_out = match (op, op2) {
(
hir::InlineAsmOperand::In { .. },
hir::InlineAsmOperand::Out { late, .. },
@ -411,14 +376,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
) => {
assert!(!*late);
let out_op_sp = if input { op_sp2 } else { op_sp };
let msg = "use `lateout` instead of \
`out` to avoid conflict";
err.span_help(out_op_sp, msg);
}
_ => {}
}
Some(out_op_sp)
},
_ => None,
};
err.emit();
sess.emit_err(RegisterConflict {
op_span1: op_sp,
op_span2: op_sp2,
reg1_name: reg.name(),
reg2_name: reg2.name(),
in_out
});
}
Entry::Vacant(v) => {
if r == reg {

View File

@ -0,0 +1,329 @@
use rustc_errors::{fluent, AddSubdiagnostic, Applicability, Diagnostic, DiagnosticArgFromDisplay};
use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
use rustc_span::{symbol::Ident, Span, Symbol};
#[derive(SessionDiagnostic, Clone, Copy)]
#[diag(ast_lowering::generic_type_with_parentheses, code = "E0214")]
pub struct GenericTypeWithParentheses {
#[primary_span]
#[label]
pub span: Span,
#[subdiagnostic]
pub sub: Option<UseAngleBrackets>,
}
#[derive(Clone, Copy)]
pub struct UseAngleBrackets {
pub open_param: Span,
pub close_param: Span,
}
impl AddSubdiagnostic for UseAngleBrackets {
fn add_to_diagnostic(self, diag: &mut Diagnostic) {
diag.multipart_suggestion(
fluent::ast_lowering::use_angle_brackets,
vec![(self.open_param, String::from("<")), (self.close_param, String::from(">"))],
Applicability::MaybeIncorrect,
);
}
}
#[derive(SessionDiagnostic)]
#[help]
#[diag(ast_lowering::invalid_abi, code = "E0703")]
pub struct InvalidAbi {
#[primary_span]
#[label]
pub span: Span,
pub abi: Symbol,
pub valid_abis: String,
}
#[derive(SessionDiagnostic, Clone, Copy)]
#[diag(ast_lowering::assoc_ty_parentheses)]
pub struct AssocTyParentheses {
#[primary_span]
pub span: Span,
#[subdiagnostic]
pub sub: AssocTyParenthesesSub,
}
#[derive(Clone, Copy)]
pub enum AssocTyParenthesesSub {
Empty { parentheses_span: Span },
NotEmpty { open_param: Span, close_param: Span },
}
impl AddSubdiagnostic for AssocTyParenthesesSub {
fn add_to_diagnostic(self, diag: &mut Diagnostic) {
match self {
Self::Empty { parentheses_span } => diag.multipart_suggestion(
fluent::ast_lowering::remove_parentheses,
vec![(parentheses_span, String::new())],
Applicability::MaybeIncorrect,
),
Self::NotEmpty { open_param, close_param } => diag.multipart_suggestion(
fluent::ast_lowering::use_angle_brackets,
vec![(open_param, String::from("<")), (close_param, String::from(">"))],
Applicability::MaybeIncorrect,
),
};
}
}
#[derive(SessionDiagnostic)]
#[diag(ast_lowering::misplaced_impl_trait, code = "E0562")]
pub struct MisplacedImplTrait<'a> {
#[primary_span]
pub span: Span,
pub position: DiagnosticArgFromDisplay<'a>,
}
#[derive(SessionDiagnostic, Clone, Copy)]
#[diag(ast_lowering::rustc_box_attribute_error)]
pub struct RustcBoxAttributeError {
#[primary_span]
pub span: Span,
}
#[derive(SessionDiagnostic, Clone, Copy)]
#[diag(ast_lowering::underscore_expr_lhs_assign)]
pub struct UnderscoreExprLhsAssign {
#[primary_span]
#[label]
pub span: Span,
}
#[derive(SessionDiagnostic, Clone, Copy)]
#[diag(ast_lowering::base_expression_double_dot)]
pub struct BaseExpressionDoubleDot {
#[primary_span]
#[label]
pub span: Span,
}
#[derive(SessionDiagnostic, Clone, Copy)]
#[diag(ast_lowering::await_only_in_async_fn_and_blocks, code = "E0728")]
pub struct AwaitOnlyInAsyncFnAndBlocks {
#[primary_span]
#[label]
pub dot_await_span: Span,
#[label(ast_lowering::this_not_async)]
pub item_span: Option<Span>,
}
#[derive(SessionDiagnostic, Clone, Copy)]
#[diag(ast_lowering::generator_too_many_parameters, code = "E0628")]
pub struct GeneratorTooManyParameters {
#[primary_span]
pub fn_decl_span: Span,
}
#[derive(SessionDiagnostic, Clone, Copy)]
#[diag(ast_lowering::closure_cannot_be_static, code = "E0697")]
pub struct ClosureCannotBeStatic {
#[primary_span]
pub fn_decl_span: Span,
}
#[derive(SessionDiagnostic, Clone, Copy)]
#[help]
#[diag(ast_lowering::async_non_move_closure_not_supported, code = "E0708")]
pub struct AsyncNonMoveClosureNotSupported {
#[primary_span]
pub fn_decl_span: Span,
}
#[derive(SessionDiagnostic, Clone, Copy)]
#[diag(ast_lowering::functional_record_update_destructuring_assignment)]
pub struct FunctionalRecordUpdateDestructuringAssignemnt {
#[primary_span]
#[suggestion(code = "", applicability = "machine-applicable")]
pub span: Span,
}
#[derive(SessionDiagnostic, Clone, Copy)]
#[diag(ast_lowering::async_generators_not_supported, code = "E0727")]
pub struct AsyncGeneratorsNotSupported {
#[primary_span]
pub span: Span,
}
#[derive(SessionDiagnostic, Clone, Copy)]
#[diag(ast_lowering::inline_asm_unsupported_target, code = "E0472")]
pub struct InlineAsmUnsupportedTarget {
#[primary_span]
pub span: Span,
}
#[derive(SessionDiagnostic, Clone, Copy)]
#[diag(ast_lowering::att_syntax_only_x86)]
pub struct AttSyntaxOnlyX86 {
#[primary_span]
pub span: Span,
}
#[derive(SessionDiagnostic, Clone, Copy)]
#[diag(ast_lowering::abi_specified_multiple_times)]
pub struct AbiSpecifiedMultipleTimes {
#[primary_span]
pub abi_span: Span,
pub prev_name: Symbol,
#[label]
pub prev_span: Span,
#[note]
pub equivalent: Option<()>,
}
#[derive(SessionDiagnostic, Clone, Copy)]
#[diag(ast_lowering::clobber_abi_not_supported)]
pub struct ClobberAbiNotSupported {
#[primary_span]
pub abi_span: Span,
}
#[derive(SessionDiagnostic)]
#[note]
#[diag(ast_lowering::invalid_abi_clobber_abi)]
pub struct InvalidAbiClobberAbi {
#[primary_span]
pub abi_span: Span,
pub supported_abis: String,
}
#[derive(SessionDiagnostic, Clone, Copy)]
#[diag(ast_lowering::invalid_register)]
pub struct InvalidRegister<'a> {
#[primary_span]
pub op_span: Span,
pub reg: Symbol,
pub error: &'a str,
}
#[derive(SessionDiagnostic, Clone, Copy)]
#[diag(ast_lowering::invalid_register_class)]
pub struct InvalidRegisterClass<'a> {
#[primary_span]
pub op_span: Span,
pub reg_class: Symbol,
pub error: &'a str,
}
#[derive(SessionDiagnostic)]
#[diag(ast_lowering::invalid_asm_template_modifier_reg_class)]
pub struct InvalidAsmTemplateModifierRegClass {
#[primary_span]
#[label(ast_lowering::template_modifier)]
pub placeholder_span: Span,
#[label(ast_lowering::argument)]
pub op_span: Span,
#[subdiagnostic]
pub sub: InvalidAsmTemplateModifierRegClassSub,
}
#[derive(SessionSubdiagnostic)]
pub enum InvalidAsmTemplateModifierRegClassSub {
#[note(ast_lowering::support_modifiers)]
SupportModifier { class_name: Symbol, modifiers: String },
#[note(ast_lowering::does_not_support_modifiers)]
DoesNotSupportModifier { class_name: Symbol },
}
#[derive(SessionDiagnostic, Clone, Copy)]
#[diag(ast_lowering::invalid_asm_template_modifier_const)]
pub struct InvalidAsmTemplateModifierConst {
#[primary_span]
#[label(ast_lowering::template_modifier)]
pub placeholder_span: Span,
#[label(ast_lowering::argument)]
pub op_span: Span,
}
#[derive(SessionDiagnostic, Clone, Copy)]
#[diag(ast_lowering::invalid_asm_template_modifier_sym)]
pub struct InvalidAsmTemplateModifierSym {
#[primary_span]
#[label(ast_lowering::template_modifier)]
pub placeholder_span: Span,
#[label(ast_lowering::argument)]
pub op_span: Span,
}
#[derive(SessionDiagnostic, Clone, Copy)]
#[diag(ast_lowering::register_class_only_clobber)]
pub struct RegisterClassOnlyClobber {
#[primary_span]
pub op_span: Span,
pub reg_class_name: Symbol,
}
#[derive(SessionDiagnostic, Clone, Copy)]
#[diag(ast_lowering::register_conflict)]
pub struct RegisterConflict<'a> {
#[primary_span]
#[label(ast_lowering::register1)]
pub op_span1: Span,
#[label(ast_lowering::register2)]
pub op_span2: Span,
pub reg1_name: &'a str,
pub reg2_name: &'a str,
#[help]
pub in_out: Option<Span>,
}
#[derive(SessionDiagnostic, Clone, Copy)]
#[help]
#[diag(ast_lowering::sub_tuple_binding)]
pub struct SubTupleBinding<'a> {
#[primary_span]
#[label]
#[suggestion_verbose(
ast_lowering::sub_tuple_binding_suggestion,
code = "..",
applicability = "maybe-incorrect"
)]
pub span: Span,
pub ident: Ident,
pub ident_name: Symbol,
pub ctx: &'a str,
}
#[derive(SessionDiagnostic, Clone, Copy)]
#[diag(ast_lowering::extra_double_dot)]
pub struct ExtraDoubleDot<'a> {
#[primary_span]
#[label]
pub span: Span,
#[label(ast_lowering::previously_used_here)]
pub prev_span: Span,
pub ctx: &'a str,
}
#[derive(SessionDiagnostic, Clone, Copy)]
#[note]
#[diag(ast_lowering::misplaced_double_dot)]
pub struct MisplacedDoubleDot {
#[primary_span]
pub span: Span,
}
#[derive(SessionDiagnostic, Clone, Copy)]
#[diag(ast_lowering::misplaced_relax_trait_bound)]
pub struct MisplacedRelaxTraitBound {
#[primary_span]
pub span: Span,
}
#[derive(SessionDiagnostic, Clone, Copy)]
#[diag(ast_lowering::not_supported_for_lifetime_binder_async_closure)]
pub struct NotSupportedForLifetimeBinderAsyncClosure {
#[primary_span]
pub span: Span,
}
#[derive(SessionDiagnostic, Clone, Copy)]
#[diag(ast_lowering::arbitrary_expression_in_pattern)]
pub struct ArbitraryExpressionInPattern {
#[primary_span]
pub span: Span,
}

View File

@ -1,3 +1,9 @@
use super::errors::{
AsyncGeneratorsNotSupported, AsyncNonMoveClosureNotSupported, AwaitOnlyInAsyncFnAndBlocks,
BaseExpressionDoubleDot, ClosureCannotBeStatic, FunctionalRecordUpdateDestructuringAssignemnt,
GeneratorTooManyParameters, NotSupportedForLifetimeBinderAsyncClosure, RustcBoxAttributeError,
UnderscoreExprLhsAssign,
};
use super::ResolverAstLoweringExt;
use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs};
use crate::{FnDeclKind, ImplTraitPosition};
@ -6,7 +12,6 @@ use rustc_ast::attr;
use rustc_ast::ptr::P as AstP;
use rustc_ast::*;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_hir::def::Res;
use rustc_hir::definitions::DefPathData;
@ -45,13 +50,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let hir_id = self.lower_node_id(e.id);
return hir::Expr { hir_id, kind, span: self.lower_span(e.span) };
} else {
self.tcx.sess
.struct_span_err(
e.span,
"#[rustc_box] requires precisely one argument \
and no other attributes are allowed",
)
.emit();
self.tcx.sess.emit_err(RustcBoxAttributeError { span: e.span });
hir::ExprKind::Err
}
} else if let Some(legacy_args) = self.resolver.legacy_const_generic_args(f) {
@ -211,13 +210,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.lower_expr_range(e.span, e1.as_deref(), e2.as_deref(), lims)
}
ExprKind::Underscore => {
self.tcx
.sess.struct_span_err(
e.span,
"in expressions, `_` can only be used on the left-hand side of an assignment",
)
.span_label(e.span, "`_` not allowed here")
.emit();
self.tcx.sess.emit_err(UnderscoreExprLhsAssign { span: e.span });
hir::ExprKind::Err
}
ExprKind::Path(ref qself, ref path) => {
@ -249,11 +242,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let rest = match &se.rest {
StructRest::Base(e) => Some(self.lower_expr(e)),
StructRest::Rest(sp) => {
self.tcx
.sess
.struct_span_err(*sp, "base expression required after `..`")
.span_label(*sp, "add a base expression here")
.emit();
self.tcx.sess.emit_err(BaseExpressionDoubleDot { span: *sp });
Some(&*self.arena.alloc(self.expr_err(*sp)))
}
StructRest::None => None,
@ -662,17 +651,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
match self.generator_kind {
Some(hir::GeneratorKind::Async(_)) => {}
Some(hir::GeneratorKind::Gen) | None => {
let mut err = struct_span_err!(
self.tcx.sess,
self.tcx.sess.emit_err(AwaitOnlyInAsyncFnAndBlocks {
dot_await_span,
E0728,
"`await` is only allowed inside `async` functions and blocks"
);
err.span_label(dot_await_span, "only allowed inside `async` functions and blocks");
if let Some(item_sp) = self.current_item {
err.span_label(item_sp, "this is not `async`");
}
err.emit();
item_span: self.current_item,
});
}
}
let span = self.mark_span_with_reason(DesugaringKind::Await, dot_await_span, None);
@ -892,13 +874,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
match generator_kind {
Some(hir::GeneratorKind::Gen) => {
if decl.inputs.len() > 1 {
struct_span_err!(
self.tcx.sess,
fn_decl_span,
E0628,
"too many parameters for a generator (expected 0 or 1 parameters)"
)
.emit();
self.tcx.sess.emit_err(GeneratorTooManyParameters { fn_decl_span });
}
Some(movability)
}
@ -907,13 +883,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
None => {
if movability == Movability::Static {
struct_span_err!(
self.tcx.sess,
fn_decl_span,
E0697,
"closures cannot be static"
)
.emit();
self.tcx.sess.emit_err(ClosureCannotBeStatic { fn_decl_span });
}
None
}
@ -946,10 +916,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn_decl_span: Span,
) -> hir::ExprKind<'hir> {
if let &ClosureBinder::For { span, .. } = binder {
self.tcx.sess.span_err(
span,
"`for<...>` binders on `async` closures are not currently supported",
);
self.tcx.sess.emit_err(NotSupportedForLifetimeBinderAsyncClosure { span });
}
let (binder_clause, generic_params) = self.lower_closure_binder(binder);
@ -960,17 +927,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let body = self.with_new_scopes(|this| {
// FIXME(cramertj): allow `async` non-`move` closures with arguments.
if capture_clause == CaptureBy::Ref && !decl.inputs.is_empty() {
struct_span_err!(
this.tcx.sess,
fn_decl_span,
E0708,
"`async` non-`move` closures with parameters are not currently supported",
)
.help(
"consider using `let` statements to manually capture \
variables by reference before entering an `async move` closure",
)
.emit();
this.tcx.sess.emit_err(AsyncNonMoveClosureNotSupported { fn_decl_span });
}
// Transform `async |x: u8| -> X { ... }` into
@ -1210,20 +1167,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
);
let fields_omitted = match &se.rest {
StructRest::Base(e) => {
self.tcx
.sess
.struct_span_err(
e.span,
"functional record updates are not allowed in destructuring \
assignments",
)
.span_suggestion(
e.span,
"consider removing the trailing pattern",
"",
rustc_errors::Applicability::MachineApplicable,
)
.emit();
self.tcx.sess.emit_err(FunctionalRecordUpdateDestructuringAssignemnt {
span: e.span,
});
true
}
StructRest::Rest(_) => true,
@ -1420,13 +1366,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
match self.generator_kind {
Some(hir::GeneratorKind::Gen) => {}
Some(hir::GeneratorKind::Async(_)) => {
struct_span_err!(
self.tcx.sess,
span,
E0727,
"`async` generators are not yet supported"
)
.emit();
self.tcx.sess.emit_err(AsyncGeneratorsNotSupported { span });
}
None => self.generator_kind = Some(hir::GeneratorKind::Gen),
}

View File

@ -1,3 +1,4 @@
use super::errors::{InvalidAbi, MisplacedRelaxTraitBound};
use super::ResolverAstLoweringExt;
use super::{AstOwner, ImplTraitContext, ImplTraitPosition};
use super::{FnDeclKind, LoweringContext, ParamMode};
@ -7,7 +8,6 @@ use rustc_ast::visit::AssocCtxt;
use rustc_ast::*;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sorted_map::SortedMap;
use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
@ -1260,10 +1260,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
fn error_on_invalid_abi(&self, abi: StrLit) {
struct_span_err!(self.tcx.sess, abi.span, E0703, "invalid ABI: found `{}`", abi.symbol)
.span_label(abi.span, "invalid ABI")
.help(&format!("valid ABIs: {}", abi::all_names().join(", ")))
.emit();
self.tcx.sess.emit_err(InvalidAbi {
span: abi.span,
abi: abi.symbol,
valid_abis: abi::all_names().join(", "),
});
}
fn lower_asyncness(&mut self, a: Async) -> hir::IsAsync {
@ -1338,11 +1339,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
let is_param = *is_param.get_or_insert_with(compute_is_param);
if !is_param {
self.diagnostic().span_err(
bound.span(),
"`?Trait` bounds are only permitted at the \
point where a type parameter is declared",
);
self.tcx.sess.emit_err(MisplacedRelaxTraitBound { span: bound.span() });
}
}
}

View File

@ -39,6 +39,8 @@
#[macro_use]
extern crate tracing;
use crate::errors::{AssocTyParentheses, AssocTyParenthesesSub, MisplacedImplTrait};
use rustc_ast::ptr::P;
use rustc_ast::visit;
use rustc_ast::{self as ast, *};
@ -49,7 +51,7 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sorted_map::SortedMap;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::Lrc;
use rustc_errors::{struct_span_err, Applicability, Handler, StashKey};
use rustc_errors::{DiagnosticArgFromDisplay, Handler, StashKey};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
@ -75,6 +77,7 @@ macro_rules! arena_vec {
mod asm;
mod block;
mod errors;
mod expr;
mod index;
mod item;
@ -1070,19 +1073,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
fn emit_bad_parenthesized_trait_in_assoc_ty(&self, data: &ParenthesizedArgs) {
let mut err = self.tcx.sess.struct_span_err(
data.span,
"parenthesized generic arguments cannot be used in associated type constraints",
);
// Suggest removing empty parentheses: "Trait()" -> "Trait"
if data.inputs.is_empty() {
let sub = if data.inputs.is_empty() {
let parentheses_span =
data.inputs_span.shrink_to_lo().to(data.inputs_span.shrink_to_hi());
err.multipart_suggestion(
"remove these parentheses",
vec![(parentheses_span, String::new())],
Applicability::MaybeIncorrect,
);
AssocTyParenthesesSub::Empty { parentheses_span }
}
// Suggest replacing parentheses with angle brackets `Trait(params...)` to `Trait<params...>`
else {
@ -1096,13 +1091,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// End of last argument to end of parameters
let close_param =
data.inputs.last().unwrap().span.shrink_to_hi().to(data.inputs_span.shrink_to_hi());
err.multipart_suggestion(
&format!("use angle brackets instead",),
vec![(open_param, String::from("<")), (close_param, String::from(">"))],
Applicability::MaybeIncorrect,
);
}
err.emit();
AssocTyParenthesesSub::NotEmpty { open_param, close_param }
};
self.tcx.sess.emit_err(AssocTyParentheses { span: data.span, sub });
}
#[instrument(level = "debug", skip(self))]
@ -1341,14 +1332,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
path
}
ImplTraitContext::Disallowed(position) => {
let mut err = struct_span_err!(
self.tcx.sess,
t.span,
E0562,
"`impl Trait` only allowed in function and inherent method return types, not in {}",
position
);
err.emit();
self.tcx.sess.emit_err(MisplacedImplTrait {
span: t.span,
position: DiagnosticArgFromDisplay(&position),
});
hir::TyKind::Err
}
}

View File

@ -1,3 +1,6 @@
use super::errors::{
ArbitraryExpressionInPattern, ExtraDoubleDot, MisplacedDoubleDot, SubTupleBinding,
};
use super::ResolverAstLoweringExt;
use super::{ImplTraitContext, LoweringContext, ParamMode};
use crate::ImplTraitPosition;
@ -5,7 +8,6 @@ use crate::ImplTraitPosition;
use rustc_ast::ptr::P;
use rustc_ast::*;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::def::Res;
use rustc_span::symbol::Ident;
@ -134,20 +136,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// This is not allowed as a sub-tuple pattern
PatKind::Ident(ref _bm, ident, Some(ref sub)) if sub.is_rest() => {
let sp = pat.span;
self.diagnostic()
.struct_span_err(
sp,
&format!("`{} @` is not allowed in a {}", ident.name, ctx),
)
.span_label(sp, "this is only allowed in slice patterns")
.help("remove this and bind each tuple field independently")
.span_suggestion_verbose(
sp,
&format!("if you don't need to use the contents of {}, discard the tuple's remaining fields", ident),
"..",
Applicability::MaybeIncorrect,
)
.emit();
self.tcx.sess.emit_err(SubTupleBinding {
span: sp,
ident_name: ident.name,
ident,
ctx,
});
}
_ => {}
}
@ -296,19 +290,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
/// Emit a friendly error for extra `..` patterns in a tuple/tuple struct/slice pattern.
pub(crate) fn ban_extra_rest_pat(&self, sp: Span, prev_sp: Span, ctx: &str) {
self.diagnostic()
.struct_span_err(sp, &format!("`..` can only be used once per {} pattern", ctx))
.span_label(sp, &format!("can only be used once per {} pattern", ctx))
.span_label(prev_sp, "previously used here")
.emit();
self.tcx.sess.emit_err(ExtraDoubleDot { span: sp, prev_span: prev_sp, ctx });
}
/// Used to ban the `..` pattern in places it shouldn't be semantically.
fn ban_illegal_rest_pat(&self, sp: Span) -> hir::PatKind<'hir> {
self.diagnostic()
.struct_span_err(sp, "`..` patterns are not allowed here")
.note("only allowed in tuple, tuple struct, and slice patterns")
.emit();
self.tcx.sess.emit_err(MisplacedDoubleDot { span: sp });
// We're not in a list context so `..` can be reasonably treated
// as `_` because it should always be valid and roughly matches the
@ -345,8 +332,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
ExprKind::Path(..) if allow_paths => {}
ExprKind::Unary(UnOp::Neg, ref inner) if matches!(inner.kind, ExprKind::Lit(_)) => {}
_ => {
self.diagnostic()
.span_err(expr.span, "arbitrary expressions aren't allowed in patterns");
self.tcx.sess.emit_err(ArbitraryExpressionInPattern { span: expr.span });
return self.arena.alloc(self.expr_err(expr.span));
}
}

View File

@ -1,11 +1,11 @@
use crate::ImplTraitPosition;
use super::errors::{GenericTypeWithParentheses, UseAngleBrackets};
use super::ResolverAstLoweringExt;
use super::{GenericArgsCtor, LifetimeRes, ParenthesizedGenericArgs};
use super::{ImplTraitContext, LoweringContext, ParamMode};
use rustc_ast::{self as ast, *};
use rustc_errors::{struct_span_err, Applicability};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, PartialRes, Res};
use rustc_hir::GenericArg;
@ -185,7 +185,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
) -> hir::PathSegment<'hir> {
debug!("path_span: {:?}, lower_path_segment(segment: {:?})", path_span, segment,);
let (mut generic_args, infer_args) = if let Some(ref generic_args) = segment.args {
let msg = "parenthesized type parameters may only be used with a `Fn` trait";
match **generic_args {
GenericArgs::AngleBracketed(ref data) => {
self.lower_angle_bracketed_parameter_data(data, param_mode, itctx)
@ -193,10 +192,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
GenericArgs::Parenthesized(ref data) => match parenthesized_generic_args {
ParenthesizedGenericArgs::Ok => self.lower_parenthesized_parameter_data(data),
ParenthesizedGenericArgs::Err => {
let mut err = struct_span_err!(self.tcx.sess, data.span, E0214, "{}", msg);
err.span_label(data.span, "only `Fn` traits may use parentheses");
// Suggest replacing parentheses with angle brackets `Trait(params...)` to `Trait<params...>`
if !data.inputs.is_empty() {
let sub = if !data.inputs.is_empty() {
// Start of the span to the 1st character of 1st argument
let open_param = data.inputs_span.shrink_to_lo().to(data
.inputs
@ -212,16 +209,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
.span
.shrink_to_hi()
.to(data.inputs_span.shrink_to_hi());
err.multipart_suggestion(
&format!("use angle brackets instead",),
vec![
(open_param, String::from("<")),
(close_param, String::from(">")),
],
Applicability::MaybeIncorrect,
);
}
err.emit();
Some(UseAngleBrackets { open_param, close_param })
} else {
None
};
self.tcx.sess.emit_err(GenericTypeWithParentheses { span: data.span, sub });
(
self.lower_angle_bracketed_parameter_data(
&data.as_angle_bracketed_args(),

View File

@ -3,7 +3,6 @@
use rustc_ast as ast;
use rustc_ast::{Attribute, Lit, LitKind, MetaItem, MetaItemKind, NestedMetaItem, NodeId};
use rustc_ast_pretty::pprust;
use rustc_errors::{struct_span_err, Applicability};
use rustc_feature::{find_gated_cfg, is_builtin_attr_name, Features, GatedCfg};
use rustc_macros::HashStable_Generic;
use rustc_session::lint::builtin::UNEXPECTED_CFGS;
@ -14,6 +13,8 @@ use rustc_span::hygiene::Transparency;
use rustc_span::{symbol::sym, symbol::Symbol, Span};
use std::num::NonZeroU32;
use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause};
pub fn is_builtin_attr(attr: &Attribute) -> bool {
attr.is_doc_comment() || attr.ident().filter(|ident| is_builtin_attr_name(ident.name)).is_some()
}
@ -25,46 +26,38 @@ enum AttrError {
NonIdentFeature,
MissingFeature,
MultipleStabilityLevels,
UnsupportedLiteral(&'static str, /* is_bytestr */ bool),
UnsupportedLiteral(UnsupportedLiteralReason, /* is_bytestr */ bool),
}
pub(crate) enum UnsupportedLiteralReason {
Generic,
CfgString,
DeprecatedString,
DeprecatedKvPair,
}
fn handle_errors(sess: &ParseSess, span: Span, error: AttrError) {
let diag = &sess.span_diagnostic;
match error {
AttrError::MultipleItem(item) => {
struct_span_err!(diag, span, E0538, "multiple '{}' items", item).emit();
sess.emit_err(session_diagnostics::MultipleItem { span, item });
}
AttrError::UnknownMetaItem(item, expected) => {
let expected = expected.iter().map(|name| format!("`{}`", name)).collect::<Vec<_>>();
struct_span_err!(diag, span, E0541, "unknown meta item '{}'", item)
.span_label(span, format!("expected one of {}", expected.join(", ")))
.emit();
sess.emit_err(session_diagnostics::UnknownMetaItem { span, item, expected });
}
AttrError::MissingSince => {
struct_span_err!(diag, span, E0542, "missing 'since'").emit();
sess.emit_err(session_diagnostics::MissingSince { span });
}
AttrError::NonIdentFeature => {
struct_span_err!(diag, span, E0546, "'feature' is not an identifier").emit();
sess.emit_err(session_diagnostics::NonIdentFeature { span });
}
AttrError::MissingFeature => {
struct_span_err!(diag, span, E0546, "missing 'feature'").emit();
sess.emit_err(session_diagnostics::MissingFeature { span });
}
AttrError::MultipleStabilityLevels => {
struct_span_err!(diag, span, E0544, "multiple stability levels").emit();
sess.emit_err(session_diagnostics::MultipleStabilityLevels { span });
}
AttrError::UnsupportedLiteral(msg, is_bytestr) => {
let mut err = struct_span_err!(diag, span, E0565, "{}", msg);
if is_bytestr {
if let Ok(lint_str) = sess.source_map().span_to_snippet(span) {
err.span_suggestion(
span,
"consider removing the prefix",
&lint_str[1..],
Applicability::MaybeIncorrect,
);
}
}
err.emit();
AttrError::UnsupportedLiteral(reason, is_bytestr) => {
sess.emit_err(session_diagnostics::UnsupportedLiteral { span, reason, is_bytestr });
}
}
}
@ -243,8 +236,6 @@ where
let mut promotable = false;
let mut allowed_through_unstable_modules = false;
let diagnostic = &sess.parse_sess.span_diagnostic;
'outer: for attr in attrs_iter {
if ![
sym::rustc_const_unstable,
@ -284,7 +275,7 @@ where
*item = Some(v);
true
} else {
struct_span_err!(diagnostic, meta.span, E0539, "incorrect meta item").emit();
sess.emit_err(session_diagnostics::IncorrectMetaItem { span: meta.span });
false
}
};
@ -326,7 +317,7 @@ where
handle_errors(
&sess.parse_sess,
meta.span(),
AttrError::UnsupportedLiteral("unsupported literal", false),
AttrError::UnsupportedLiteral(UnsupportedLiteralReason::Generic, false),
);
continue 'outer;
};
@ -350,39 +341,28 @@ where
// is a name/value pair string literal.
issue_num = match issue.unwrap().as_str() {
"none" => None,
issue => {
let emit_diag = |msg: &str| {
struct_span_err!(
diagnostic,
mi.span,
E0545,
"`issue` must be a non-zero numeric string \
or \"none\"",
)
.span_label(mi.name_value_literal_span().unwrap(), msg)
.emit();
};
match issue.parse() {
Ok(0) => {
emit_diag(
"`issue` must not be \"0\", \
use \"none\" instead",
);
continue 'outer;
}
Ok(num) => NonZeroU32::new(num),
Err(err) => {
emit_diag(&err.to_string());
continue 'outer;
}
issue => match issue.parse::<NonZeroU32>() {
Ok(num) => Some(num),
Err(err) => {
sess.emit_err(
session_diagnostics::InvalidIssueString {
span: mi.span,
cause: session_diagnostics::InvalidIssueStringCause::from_int_error_kind(
mi.name_value_literal_span().unwrap(),
err.kind(),
),
},
);
continue 'outer;
}
}
},
};
}
sym::soft => {
if !mi.is_word() {
let msg = "`soft` should not have any arguments";
sess.parse_sess.span_diagnostic.span_err(mi.span, msg);
sess.emit_err(session_diagnostics::SoftNoArgs {
span: mi.span,
});
}
is_soft = true;
}
@ -440,8 +420,7 @@ where
continue;
}
_ => {
struct_span_err!(diagnostic, attr.span, E0547, "missing 'issue'")
.emit();
sess.emit_err(session_diagnostics::MissingIssue { span: attr.span });
continue;
}
}
@ -494,7 +473,10 @@ where
handle_errors(
&sess.parse_sess,
lit.span,
AttrError::UnsupportedLiteral("unsupported literal", false),
AttrError::UnsupportedLiteral(
UnsupportedLiteralReason::Generic,
false,
),
);
continue 'outer;
}
@ -533,14 +515,7 @@ where
if let Some((ref mut stab, _)) = const_stab {
stab.promotable = promotable;
} else {
struct_span_err!(
diagnostic,
item_sp,
E0717,
"`rustc_promotable` attribute must be paired with either a `rustc_const_unstable` \
or a `rustc_const_stable` attribute"
)
.emit();
sess.emit_err(session_diagnostics::RustcPromotablePairing { span: item_sp });
}
}
@ -555,13 +530,7 @@ where
{
*allowed_through_unstable_modules = true;
} else {
struct_span_err!(
diagnostic,
item_sp,
E0789,
"`rustc_allowed_through_unstable_modules` attribute must be paired with a `stable` attribute"
)
.emit();
sess.emit_err(session_diagnostics::RustcAllowedUnstablePairing { span: item_sp });
}
}
@ -675,25 +644,18 @@ pub fn eval_condition(
NestedMetaItem::Literal(Lit { span, .. })
| NestedMetaItem::MetaItem(MetaItem { span, .. }),
] => {
sess.span_diagnostic
.struct_span_err(*span, "expected a version literal")
.emit();
sess.emit_err(session_diagnostics::ExpectedVersionLiteral { span: *span });
return false;
}
[..] => {
sess.span_diagnostic
.struct_span_err(cfg.span, "expected single version literal")
.emit();
sess.emit_err(session_diagnostics::ExpectedSingleVersionLiteral {
span: cfg.span,
});
return false;
}
};
let Some(min_version) = parse_version(min_version.as_str(), false) else {
sess.span_diagnostic
.struct_span_warn(
*span,
"unknown version literal format, assuming it refers to a future version",
)
.emit();
sess.emit_warning(session_diagnostics::UnknownVersionLiteral { span: *span });
return false;
};
let rustc_version = parse_version(env!("CFG_RELEASE"), true).unwrap();
@ -711,7 +673,7 @@ pub fn eval_condition(
handle_errors(
sess,
mi.span(),
AttrError::UnsupportedLiteral("unsupported literal", false),
AttrError::UnsupportedLiteral(UnsupportedLiteralReason::Generic, false),
);
return false;
}
@ -736,13 +698,9 @@ pub fn eval_condition(
}),
sym::not => {
if mis.len() != 1 {
struct_span_err!(
sess.span_diagnostic,
cfg.span,
E0536,
"expected 1 cfg-pattern"
)
.emit();
sess.emit_err(session_diagnostics::ExpectedOneCfgPattern {
span: cfg.span,
});
return false;
}
@ -768,21 +726,16 @@ pub fn eval_condition(
})
}
_ => {
struct_span_err!(
sess.span_diagnostic,
cfg.span,
E0537,
"invalid predicate `{}`",
pprust::path_to_string(&cfg.path)
)
.emit();
sess.emit_err(session_diagnostics::InvalidPredicate {
span: cfg.span,
predicate: pprust::path_to_string(&cfg.path),
});
false
}
}
}
ast::MetaItemKind::Word | MetaItemKind::NameValue(..) if cfg.path.segments.len() != 1 => {
sess.span_diagnostic
.span_err(cfg.path.span, "`cfg` predicate key must be an identifier");
sess.emit_err(session_diagnostics::CfgPredicateIdentifier { span: cfg.path.span });
true
}
MetaItemKind::NameValue(ref lit) if !lit.kind.is_str() => {
@ -790,7 +743,7 @@ pub fn eval_condition(
sess,
lit.span,
AttrError::UnsupportedLiteral(
"literal in `cfg` predicate value must be a string",
UnsupportedLiteralReason::CfgString,
lit.kind.is_bytestr(),
),
);
@ -834,7 +787,6 @@ where
I: Iterator<Item = &'a Attribute>,
{
let mut depr: Option<(Deprecation, Span)> = None;
let diagnostic = &sess.parse_sess.span_diagnostic;
let is_rustc = sess.features_untracked().staged_api;
'outer: for attr in attrs_iter {
@ -870,14 +822,14 @@ where
&sess.parse_sess,
lit.span,
AttrError::UnsupportedLiteral(
"literal in `deprecated` \
value must be a string",
UnsupportedLiteralReason::DeprecatedString,
lit.kind.is_bytestr(),
),
);
} else {
struct_span_err!(diagnostic, meta.span, E0551, "incorrect meta item")
.emit();
sess.emit_err(session_diagnostics::IncorrectMetaItem2 {
span: meta.span,
});
}
false
@ -899,14 +851,11 @@ where
}
sym::suggestion => {
if !sess.features_untracked().deprecated_suggestion {
let mut diag = sess.struct_span_err(
mi.span,
"suggestions on deprecated items are unstable",
);
if sess.is_nightly_build() {
diag.help("add `#![feature(deprecated_suggestion)]` to the crate root");
}
diag.note("see #94785 for more details").emit();
sess.emit_err(session_diagnostics::DeprecatedItemSuggestion {
span: mi.span,
is_nightly: sess.is_nightly_build().then_some(()),
details: (),
});
}
if !get(mi, &mut suggestion) {
@ -934,7 +883,7 @@ where
&sess.parse_sess,
lit.span,
AttrError::UnsupportedLiteral(
"item in `deprecated` must be a key/value pair",
UnsupportedLiteralReason::DeprecatedKvPair,
false,
),
);
@ -952,7 +901,7 @@ where
}
if note.is_none() {
struct_span_err!(diagnostic, attr.span, E0543, "missing 'note'").emit();
sess.emit_err(session_diagnostics::MissingNote { span: attr.span });
continue;
}
}
@ -1022,19 +971,9 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
sym::simd => Some(ReprSimd),
sym::transparent => Some(ReprTransparent),
sym::align => {
let mut err = struct_span_err!(
diagnostic,
item.span(),
E0589,
"invalid `repr(align)` attribute: `align` needs an argument"
);
err.span_suggestion(
item.span(),
"supply an argument here",
"align(...)",
Applicability::HasPlaceholders,
);
err.emit();
sess.emit_err(session_diagnostics::InvalidReprAlignNeedArg {
span: item.span(),
});
recognised = true;
None
}
@ -1063,57 +1002,32 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
|| int_type_of_word(name).is_some()
{
recognised = true;
struct_span_err!(
diagnostic,
item.span(),
E0552,
"invalid representation hint: `{}` does not take a parenthesized argument list",
name.to_ident_string(),
).emit();
sess.emit_err(session_diagnostics::InvalidReprHintNoParen {
span: item.span(),
name: name.to_ident_string(),
});
}
if let Some(literal_error) = literal_error {
struct_span_err!(
diagnostic,
item.span(),
E0589,
"invalid `repr({})` attribute: {}",
name.to_ident_string(),
literal_error
)
.emit();
sess.emit_err(session_diagnostics::InvalidReprGeneric {
span: item.span(),
repr_arg: name.to_ident_string(),
error_part: literal_error,
});
}
} else if let Some(meta_item) = item.meta_item() {
if let MetaItemKind::NameValue(ref value) = meta_item.kind {
if meta_item.has_name(sym::align) || meta_item.has_name(sym::packed) {
let name = meta_item.name_or_empty().to_ident_string();
recognised = true;
let mut err = struct_span_err!(
diagnostic,
item.span(),
E0693,
"incorrect `repr({})` attribute format",
name,
);
match value.kind {
ast::LitKind::Int(int, ast::LitIntType::Unsuffixed) => {
err.span_suggestion(
item.span(),
"use parentheses instead",
format!("{}({})", name, int),
Applicability::MachineApplicable,
);
}
ast::LitKind::Str(s, _) => {
err.span_suggestion(
item.span(),
"use parentheses instead",
format!("{}({})", name, s),
Applicability::MachineApplicable,
);
}
_ => {}
}
err.emit();
sess.emit_err(session_diagnostics::IncorrectReprFormatGeneric {
span: item.span(),
repr_arg: &name,
cause: IncorrectReprFormatGenericCause::from_lit_kind(
item.span(),
&value.kind,
&name,
),
});
} else {
if matches!(
meta_item.name_or_empty(),
@ -1121,51 +1035,33 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
) || int_type_of_word(meta_item.name_or_empty()).is_some()
{
recognised = true;
struct_span_err!(
diagnostic,
meta_item.span,
E0552,
"invalid representation hint: `{}` does not take a value",
meta_item.name_or_empty().to_ident_string(),
)
.emit();
sess.emit_err(session_diagnostics::InvalidReprHintNoValue {
span: meta_item.span,
name: meta_item.name_or_empty().to_ident_string(),
});
}
}
} else if let MetaItemKind::List(_) = meta_item.kind {
if meta_item.has_name(sym::align) {
recognised = true;
struct_span_err!(
diagnostic,
meta_item.span,
E0693,
"incorrect `repr(align)` attribute format: \
`align` takes exactly one argument in parentheses"
)
.emit();
sess.emit_err(session_diagnostics::IncorrectReprFormatAlignOneArg {
span: meta_item.span,
});
} else if meta_item.has_name(sym::packed) {
recognised = true;
struct_span_err!(
diagnostic,
meta_item.span,
E0552,
"incorrect `repr(packed)` attribute format: \
`packed` takes exactly one parenthesized argument, \
or no parentheses at all"
)
.emit();
sess.emit_err(session_diagnostics::IncorrectReprFormatPackedOneOrZeroArg {
span: meta_item.span,
});
} else if matches!(
meta_item.name_or_empty(),
sym::C | sym::simd | sym::transparent
) || int_type_of_word(meta_item.name_or_empty()).is_some()
{
recognised = true;
struct_span_err!(
diagnostic,
meta_item.span,
E0552,
"invalid representation hint: `{}` does not take a parenthesized argument list",
meta_item.name_or_empty().to_ident_string(),
).emit();
sess.emit_err(session_diagnostics::InvalidReprHintNoParen {
span: meta_item.span,
name: meta_item.name_or_empty().to_ident_string(),
});
}
}
}
@ -1262,10 +1158,10 @@ fn allow_unstable<'a>(
let list = attrs
.filter_map(move |attr| {
attr.meta_item_list().or_else(|| {
sess.diagnostic().span_err(
attr.span,
&format!("`{}` expects a list of feature names", symbol.to_ident_string()),
);
sess.emit_err(session_diagnostics::ExpectsFeatureList {
span: attr.span,
name: symbol.to_ident_string(),
});
None
})
})
@ -1274,10 +1170,10 @@ fn allow_unstable<'a>(
list.into_iter().filter_map(move |it| {
let name = it.ident().map(|ident| ident.name);
if name.is_none() {
sess.diagnostic().span_err(
it.span(),
&format!("`{}` expects feature names", symbol.to_ident_string()),
);
sess.emit_err(session_diagnostics::ExpectsFeatures {
span: it.span(),
name: symbol.to_ident_string(),
});
}
name
})

View File

@ -5,11 +5,14 @@
//! to this crate.
#![feature(let_else)]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
#[macro_use]
extern crate rustc_macros;
mod builtin;
mod session_diagnostics;
pub use builtin::*;
pub use IntType::*;

View File

@ -0,0 +1,397 @@
use std::num::IntErrorKind;
use rustc_ast as ast;
use rustc_errors::{error_code, fluent, Applicability, DiagnosticBuilder, ErrorGuaranteed};
use rustc_macros::SessionDiagnostic;
use rustc_session::{parse::ParseSess, SessionDiagnostic};
use rustc_span::{Span, Symbol};
use crate::UnsupportedLiteralReason;
#[derive(SessionDiagnostic)]
#[diag(attr::expected_one_cfg_pattern, code = "E0536")]
pub(crate) struct ExpectedOneCfgPattern {
#[primary_span]
pub span: Span,
}
#[derive(SessionDiagnostic)]
#[diag(attr::invalid_predicate, code = "E0537")]
pub(crate) struct InvalidPredicate {
#[primary_span]
pub span: Span,
pub predicate: String,
}
#[derive(SessionDiagnostic)]
#[diag(attr::multiple_item, code = "E0538")]
pub(crate) struct MultipleItem {
#[primary_span]
pub span: Span,
pub item: String,
}
#[derive(SessionDiagnostic)]
#[diag(attr::incorrect_meta_item, code = "E0539")]
pub(crate) struct IncorrectMetaItem {
#[primary_span]
pub span: Span,
}
// Error code: E0541
pub(crate) struct UnknownMetaItem<'a> {
pub span: Span,
pub item: String,
pub expected: &'a [&'a str],
}
// Manual implementation to be able to format `expected` items correctly.
impl<'a> SessionDiagnostic<'a> for UnknownMetaItem<'_> {
fn into_diagnostic(self, sess: &'a ParseSess) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
let expected = self.expected.iter().map(|name| format!("`{}`", name)).collect::<Vec<_>>();
let mut diag = sess.span_diagnostic.struct_span_err_with_code(
self.span,
fluent::attr::unknown_meta_item,
error_code!(E0541),
);
diag.set_arg("item", self.item);
diag.set_arg("expected", expected.join(", "));
diag.span_label(self.span, fluent::attr::label);
diag
}
}
#[derive(SessionDiagnostic)]
#[diag(attr::missing_since, code = "E0542")]
pub(crate) struct MissingSince {
#[primary_span]
pub span: Span,
}
#[derive(SessionDiagnostic)]
#[diag(attr::missing_note, code = "E0543")]
pub(crate) struct MissingNote {
#[primary_span]
pub span: Span,
}
#[derive(SessionDiagnostic)]
#[diag(attr::multiple_stability_levels, code = "E0544")]
pub(crate) struct MultipleStabilityLevels {
#[primary_span]
pub span: Span,
}
#[derive(SessionDiagnostic)]
#[diag(attr::invalid_issue_string, code = "E0545")]
pub(crate) struct InvalidIssueString {
#[primary_span]
pub span: Span,
#[subdiagnostic]
pub cause: Option<InvalidIssueStringCause>,
}
// The error kinds of `IntErrorKind` are duplicated here in order to allow the messages to be
// translatable.
#[derive(SessionSubdiagnostic)]
pub(crate) enum InvalidIssueStringCause {
#[label(attr::must_not_be_zero)]
MustNotBeZero {
#[primary_span]
span: Span,
},
#[label(attr::empty)]
Empty {
#[primary_span]
span: Span,
},
#[label(attr::invalid_digit)]
InvalidDigit {
#[primary_span]
span: Span,
},
#[label(attr::pos_overflow)]
PosOverflow {
#[primary_span]
span: Span,
},
#[label(attr::neg_overflow)]
NegOverflow {
#[primary_span]
span: Span,
},
}
impl InvalidIssueStringCause {
pub fn from_int_error_kind(span: Span, kind: &IntErrorKind) -> Option<Self> {
match kind {
IntErrorKind::Empty => Some(Self::Empty { span }),
IntErrorKind::InvalidDigit => Some(Self::InvalidDigit { span }),
IntErrorKind::PosOverflow => Some(Self::PosOverflow { span }),
IntErrorKind::NegOverflow => Some(Self::NegOverflow { span }),
IntErrorKind::Zero => Some(Self::MustNotBeZero { span }),
_ => None,
}
}
}
#[derive(SessionDiagnostic)]
#[diag(attr::missing_feature, code = "E0546")]
pub(crate) struct MissingFeature {
#[primary_span]
pub span: Span,
}
#[derive(SessionDiagnostic)]
#[diag(attr::non_ident_feature, code = "E0546")]
pub(crate) struct NonIdentFeature {
#[primary_span]
pub span: Span,
}
#[derive(SessionDiagnostic)]
#[diag(attr::missing_issue, code = "E0547")]
pub(crate) struct MissingIssue {
#[primary_span]
pub span: Span,
}
// FIXME: This diagnostic is identical to `IncorrectMetaItem`, barring the error code. Consider
// changing this to `IncorrectMetaItem`. See #51489.
#[derive(SessionDiagnostic)]
#[diag(attr::incorrect_meta_item, code = "E0551")]
pub(crate) struct IncorrectMetaItem2 {
#[primary_span]
pub span: Span,
}
// FIXME: Why is this the same error code as `InvalidReprHintNoParen` and `InvalidReprHintNoValue`?
// It is more similar to `IncorrectReprFormatGeneric`.
#[derive(SessionDiagnostic)]
#[diag(attr::incorrect_repr_format_packed_one_or_zero_arg, code = "E0552")]
pub(crate) struct IncorrectReprFormatPackedOneOrZeroArg {
#[primary_span]
pub span: Span,
}
#[derive(SessionDiagnostic)]
#[diag(attr::invalid_repr_hint_no_paren, code = "E0552")]
pub(crate) struct InvalidReprHintNoParen {
#[primary_span]
pub span: Span,
pub name: String,
}
#[derive(SessionDiagnostic)]
#[diag(attr::invalid_repr_hint_no_value, code = "E0552")]
pub(crate) struct InvalidReprHintNoValue {
#[primary_span]
pub span: Span,
pub name: String,
}
// Error code: E0565
pub(crate) struct UnsupportedLiteral {
pub span: Span,
pub reason: UnsupportedLiteralReason,
pub is_bytestr: bool,
}
impl<'a> SessionDiagnostic<'a> for UnsupportedLiteral {
fn into_diagnostic(self, sess: &'a ParseSess) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
let mut diag = sess.span_diagnostic.struct_span_err_with_code(
self.span,
match self.reason {
UnsupportedLiteralReason::Generic => fluent::attr::unsupported_literal_generic,
UnsupportedLiteralReason::CfgString => fluent::attr::unsupported_literal_cfg_string,
UnsupportedLiteralReason::DeprecatedString => {
fluent::attr::unsupported_literal_deprecated_string
}
UnsupportedLiteralReason::DeprecatedKvPair => {
fluent::attr::unsupported_literal_deprecated_kv_pair
}
},
error_code!(E0565),
);
if self.is_bytestr {
if let Ok(lint_str) = sess.source_map().span_to_snippet(self.span) {
diag.span_suggestion(
self.span,
fluent::attr::unsupported_literal_suggestion,
&lint_str[1..],
Applicability::MaybeIncorrect,
);
}
}
diag
}
}
#[derive(SessionDiagnostic)]
#[diag(attr::invalid_repr_align_need_arg, code = "E0589")]
pub(crate) struct InvalidReprAlignNeedArg {
#[primary_span]
#[suggestion(code = "align(...)", applicability = "has-placeholders")]
pub span: Span,
}
#[derive(SessionDiagnostic)]
#[diag(attr::invalid_repr_generic, code = "E0589")]
pub(crate) struct InvalidReprGeneric<'a> {
#[primary_span]
pub span: Span,
pub repr_arg: String,
pub error_part: &'a str,
}
#[derive(SessionDiagnostic)]
#[diag(attr::incorrect_repr_format_align_one_arg, code = "E0693")]
pub(crate) struct IncorrectReprFormatAlignOneArg {
#[primary_span]
pub span: Span,
}
#[derive(SessionDiagnostic)]
#[diag(attr::incorrect_repr_format_generic, code = "E0693")]
pub(crate) struct IncorrectReprFormatGeneric<'a> {
#[primary_span]
pub span: Span,
pub repr_arg: &'a str,
#[subdiagnostic]
pub cause: Option<IncorrectReprFormatGenericCause<'a>>,
}
#[derive(SessionSubdiagnostic)]
pub(crate) enum IncorrectReprFormatGenericCause<'a> {
#[suggestion(attr::suggestion, code = "{name}({int})", applicability = "machine-applicable")]
Int {
#[primary_span]
span: Span,
#[skip_arg]
name: &'a str,
#[skip_arg]
int: u128,
},
#[suggestion(
attr::suggestion,
code = "{name}({symbol})",
applicability = "machine-applicable"
)]
Symbol {
#[primary_span]
span: Span,
#[skip_arg]
name: &'a str,
#[skip_arg]
symbol: Symbol,
},
}
impl<'a> IncorrectReprFormatGenericCause<'a> {
pub fn from_lit_kind(span: Span, kind: &ast::LitKind, name: &'a str) -> Option<Self> {
match kind {
ast::LitKind::Int(int, ast::LitIntType::Unsuffixed) => {
Some(Self::Int { span, name, int: *int })
}
ast::LitKind::Str(symbol, _) => Some(Self::Symbol { span, name, symbol: *symbol }),
_ => None,
}
}
}
#[derive(SessionDiagnostic)]
#[diag(attr::rustc_promotable_pairing, code = "E0717")]
pub(crate) struct RustcPromotablePairing {
#[primary_span]
pub span: Span,
}
#[derive(SessionDiagnostic)]
#[diag(attr::rustc_allowed_unstable_pairing, code = "E0789")]
pub(crate) struct RustcAllowedUnstablePairing {
#[primary_span]
pub span: Span,
}
#[derive(SessionDiagnostic)]
#[diag(attr::cfg_predicate_identifier)]
pub(crate) struct CfgPredicateIdentifier {
#[primary_span]
pub span: Span,
}
#[derive(SessionDiagnostic)]
#[diag(attr::deprecated_item_suggestion)]
pub(crate) struct DeprecatedItemSuggestion {
#[primary_span]
pub span: Span,
#[help]
pub is_nightly: Option<()>,
#[note]
pub details: (),
}
#[derive(SessionDiagnostic)]
#[diag(attr::expected_single_version_literal)]
pub(crate) struct ExpectedSingleVersionLiteral {
#[primary_span]
pub span: Span,
}
#[derive(SessionDiagnostic)]
#[diag(attr::expected_version_literal)]
pub(crate) struct ExpectedVersionLiteral {
#[primary_span]
pub span: Span,
}
#[derive(SessionDiagnostic)]
#[diag(attr::expects_feature_list)]
pub(crate) struct ExpectsFeatureList {
#[primary_span]
pub span: Span,
pub name: String,
}
#[derive(SessionDiagnostic)]
#[diag(attr::expects_features)]
pub(crate) struct ExpectsFeatures {
#[primary_span]
pub span: Span,
pub name: String,
}
#[derive(SessionDiagnostic)]
#[diag(attr::soft_no_args)]
pub(crate) struct SoftNoArgs {
#[primary_span]
pub span: Span,
}
#[derive(SessionDiagnostic)]
#[diag(attr::unknown_version_literal)]
pub(crate) struct UnknownVersionLiteral {
#[primary_span]
pub span: Span,
}

View File

@ -1,3 +1,5 @@
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
//! Error reporting machinery for lifetime errors.
use rustc_data_structures::fx::FxHashSet;
@ -23,7 +25,10 @@ use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::Span;
use crate::borrowck_errors;
use crate::session_diagnostics::GenericDoesNotLiveLongEnough;
use crate::session_diagnostics::{
FnMutError, FnMutReturnTypeErr, GenericDoesNotLiveLongEnough, LifetimeOutliveErr,
LifetimeReturnCategoryErr, RequireStaticErr, VarHereDenote,
};
use super::{OutlivesSuggestionBuilder, RegionName};
use crate::region_infer::BlameConstraint;
@ -488,12 +493,6 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
let ErrorConstraintInfo { outlived_fr, span, .. } = errci;
let mut diag = self
.infcx
.tcx
.sess
.struct_span_err(*span, "captured variable cannot escape `FnMut` closure body");
let mut output_ty = self.regioncx.universal_regions().unnormalized_output_ty;
if let ty::Opaque(def_id, _) = *output_ty.kind() {
output_ty = self.infcx.tcx.type_of(def_id)
@ -501,19 +500,20 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
debug!("report_fnmut_error: output_ty={:?}", output_ty);
let message = match output_ty.kind() {
ty::Closure(_, _) => {
"returns a closure that contains a reference to a captured variable, which then \
escapes the closure body"
}
ty::Adt(def, _) if self.infcx.tcx.is_diagnostic_item(sym::gen_future, def.did()) => {
"returns an `async` block that contains a reference to a captured variable, which then \
escapes the closure body"
}
_ => "returns a reference to a captured variable which escapes the closure body",
let err = FnMutError {
span: *span,
ty_err: match output_ty.kind() {
ty::Closure(_, _) => FnMutReturnTypeErr::ReturnClosure { span: *span },
ty::Adt(def, _)
if self.infcx.tcx.is_diagnostic_item(sym::gen_future, def.did()) =>
{
FnMutReturnTypeErr::ReturnAsyncBlock { span: *span }
}
_ => FnMutReturnTypeErr::ReturnRef { span: *span },
},
};
diag.span_label(*span, message);
let mut diag = self.infcx.tcx.sess.create_err(err);
if let ReturnConstraint::ClosureUpvar(upvar_field) = kind {
let def_id = match self.regioncx.universal_regions().defining_ty {
@ -532,20 +532,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
let upvars_map = self.infcx.tcx.upvars_mentioned(def_id).unwrap();
let upvar_def_span = self.infcx.tcx.hir().span(def_hir);
let upvar_span = upvars_map.get(&def_hir).unwrap().span;
diag.span_label(upvar_def_span, "variable defined here");
diag.span_label(upvar_span, "variable captured here");
diag.subdiagnostic(VarHereDenote::Defined { span: upvar_def_span });
diag.subdiagnostic(VarHereDenote::Captured { span: upvar_span });
}
}
if let Some(fr_span) = self.give_region_a_name(*outlived_fr).unwrap().span() {
diag.span_label(fr_span, "inferred to be a `FnMut` closure");
diag.subdiagnostic(VarHereDenote::FnMutInferred { span: fr_span });
}
diag.note(
"`FnMut` closures only have access to their captured variables while they are \
executing...",
);
diag.note("...therefore, they cannot allow references to captured variables to escape");
self.suggest_move_on_borrowing_closure(&mut diag);
diag
@ -681,39 +676,33 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
..
} = errci;
let mut diag =
self.infcx.tcx.sess.struct_span_err(*span, "lifetime may not live long enough");
let (_, mir_def_name) =
self.infcx.tcx.article_and_description(self.mir_def_id().to_def_id());
let err = LifetimeOutliveErr { span: *span };
let mut diag = self.infcx.tcx.sess.create_err(err);
let fr_name = self.give_region_a_name(*fr).unwrap();
fr_name.highlight_region_name(&mut diag);
let outlived_fr_name = self.give_region_a_name(*outlived_fr).unwrap();
outlived_fr_name.highlight_region_name(&mut diag);
match (category, outlived_fr_is_local, fr_is_local) {
(ConstraintCategory::Return(_), true, _) => {
diag.span_label(
*span,
format!(
"{mir_def_name} was supposed to return data with lifetime `{outlived_fr_name}` but it is returning \
data with lifetime `{fr_name}`",
),
);
}
_ => {
diag.span_label(
*span,
format!(
"{}requires that `{}` must outlive `{}`",
category.description(),
fr_name,
outlived_fr_name,
),
);
}
}
let err_category = match (category, outlived_fr_is_local, fr_is_local) {
(ConstraintCategory::Return(_), true, _) => LifetimeReturnCategoryErr::WrongReturn {
span: *span,
mir_def_name,
outlived_fr_name,
fr_name: &fr_name,
},
_ => LifetimeReturnCategoryErr::ShortReturn {
span: *span,
category_desc: category.description(),
free_region_name: &fr_name,
outlived_fr_name,
},
};
diag.subdiagnostic(err_category);
self.add_static_impl_trait_suggestion(&mut diag, *fr, fr_name, *outlived_fr);
self.suggest_adding_lifetime_params(&mut diag, *fr, *outlived_fr);
@ -862,7 +851,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
ident.span,
"calling this method introduces the `impl`'s 'static` requirement",
);
err.span_note(multi_span, "the used `impl` has a `'static` requirement");
err.subdiagnostic(RequireStaticErr::UsedImpl { multi_span });
err.span_suggestion_verbose(
span.shrink_to_hi(),
"consider relaxing the implicit `'static` requirement",

View File

@ -18,7 +18,7 @@ extern crate tracing;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::graph::dominators::Dominators;
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
use rustc_errors::{Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_index::bit_set::ChunkedBitSet;
@ -50,6 +50,8 @@ use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult, MoveData, MoveE
use rustc_mir_dataflow::Analysis;
use rustc_mir_dataflow::MoveDataParamEnv;
use crate::session_diagnostics::VarNeedNotMut;
use self::diagnostics::{AccessKind, RegionName};
use self::location::LocationTable;
use self::prefixes::PrefixSet;
@ -424,17 +426,9 @@ fn do_mir_borrowck<'a, 'tcx>(
continue;
}
tcx.struct_span_lint_hir(UNUSED_MUT, lint_root, span, |lint| {
let mut_span = tcx.sess.source_map().span_until_non_whitespace(span);
lint.build("variable does not need to be mutable")
.span_suggestion_short(
mut_span,
"remove this `mut`",
"",
Applicability::MachineApplicable,
)
.emit();
})
let mut_span = tcx.sess.source_map().span_until_non_whitespace(span);
tcx.emit_spanned_lint(UNUSED_MUT, lint_root, span, VarNeedNotMut { span: mut_span })
}
let tainted_by_errors = mbcx.emit_errors();

View File

@ -16,6 +16,8 @@ use rustc_span::Span;
use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
use rustc_trait_selection::traits::TraitEngineExt as _;
use crate::session_diagnostics::ConstNotUsedTraitAlias;
use super::RegionInferenceContext;
impl<'tcx> RegionInferenceContext<'tcx> {
@ -639,17 +641,10 @@ impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
Some(GenericArgKind::Const(c1)) => c1,
Some(u) => panic!("const mapped to unexpected kind: {:?}", u),
None => {
self.tcx
.sess
.struct_span_err(
self.span,
&format!(
"const parameter `{}` is part of concrete type but not \
used in parameter list for the `impl Trait` type alias",
ct
),
)
.emit();
self.tcx.sess.emit_err(ConstNotUsedTraitAlias {
ct: ct.to_string(),
span: self.span,
});
self.tcx().const_error(ct.ty())
}

View File

@ -1,7 +1,10 @@
use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
use rustc_errors::{IntoDiagnosticArg, MultiSpan};
use rustc_macros::{LintDiagnostic, SessionDiagnostic, SessionSubdiagnostic};
use rustc_middle::ty::Ty;
use rustc_span::Span;
use crate::diagnostics::RegionName;
#[derive(SessionDiagnostic)]
#[diag(borrowck::move_unsized, code = "E0161")]
pub(crate) struct MoveUnsized<'tcx> {
@ -42,3 +45,115 @@ pub(crate) struct GenericDoesNotLiveLongEnough {
#[primary_span]
pub span: Span,
}
#[derive(LintDiagnostic)]
#[diag(borrowck::var_does_not_need_mut)]
pub(crate) struct VarNeedNotMut {
#[suggestion_short(applicability = "machine-applicable", code = "")]
pub span: Span,
}
#[derive(SessionDiagnostic)]
#[diag(borrowck::const_not_used_in_type_alias)]
pub(crate) struct ConstNotUsedTraitAlias {
pub ct: String,
#[primary_span]
pub span: Span,
}
#[derive(SessionDiagnostic)]
#[diag(borrowck::var_cannot_escape_closure)]
#[note]
#[note(borrowck::cannot_escape)]
pub(crate) struct FnMutError {
#[primary_span]
pub span: Span,
#[subdiagnostic]
pub ty_err: FnMutReturnTypeErr,
}
#[derive(SessionSubdiagnostic)]
pub(crate) enum VarHereDenote {
#[label(borrowck::var_here_captured)]
Captured {
#[primary_span]
span: Span,
},
#[label(borrowck::var_here_defined)]
Defined {
#[primary_span]
span: Span,
},
#[label(borrowck::closure_inferred_mut)]
FnMutInferred {
#[primary_span]
span: Span,
},
}
#[derive(SessionSubdiagnostic)]
pub(crate) enum FnMutReturnTypeErr {
#[label(borrowck::returned_closure_escaped)]
ReturnClosure {
#[primary_span]
span: Span,
},
#[label(borrowck::returned_async_block_escaped)]
ReturnAsyncBlock {
#[primary_span]
span: Span,
},
#[label(borrowck::returned_ref_escaped)]
ReturnRef {
#[primary_span]
span: Span,
},
}
#[derive(SessionDiagnostic)]
#[diag(borrowck::lifetime_constraints_error)]
pub(crate) struct LifetimeOutliveErr {
#[primary_span]
pub span: Span,
}
#[derive(SessionSubdiagnostic)]
pub(crate) enum LifetimeReturnCategoryErr<'a> {
#[label(borrowck::returned_lifetime_wrong)]
WrongReturn {
#[primary_span]
span: Span,
mir_def_name: &'a str,
outlived_fr_name: RegionName,
fr_name: &'a RegionName,
},
#[label(borrowck::returned_lifetime_short)]
ShortReturn {
#[primary_span]
span: Span,
category_desc: &'static str,
free_region_name: &'a RegionName,
outlived_fr_name: RegionName,
},
}
impl IntoDiagnosticArg for &RegionName {
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
format!("{}", self).into_diagnostic_arg()
}
}
impl IntoDiagnosticArg for RegionName {
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
format!("{}", self).into_diagnostic_arg()
}
}
#[derive(SessionSubdiagnostic)]
pub(crate) enum RequireStaticErr {
#[note(borrowck::used_impl_require_static)]
UsedImpl {
#[primary_span]
multi_span: MultiSpan,
},
}

View File

@ -168,6 +168,13 @@ pub struct CodegenResults {
pub crate_info: CrateInfo,
}
pub enum CodegenErrors<'a> {
WrongFileType,
EmptyVersionNumber,
EncodingVersionMismatch { version_array: String, rlink_version: u32 },
RustcVersionMismatch { rustc_version: String, current_version: &'a str },
}
pub fn provide(providers: &mut Providers) {
crate::back::symbol_export::provide(providers);
crate::base::provide(providers);
@ -212,30 +219,34 @@ impl CodegenResults {
encoder.finish()
}
pub fn deserialize_rlink(data: Vec<u8>) -> Result<Self, String> {
pub fn deserialize_rlink<'a>(data: Vec<u8>) -> Result<Self, CodegenErrors<'a>> {
// The Decodable machinery is not used here because it panics if the input data is invalid
// and because its internal representation may change.
if !data.starts_with(RLINK_MAGIC) {
return Err("The input does not look like a .rlink file".to_string());
return Err(CodegenErrors::WrongFileType);
}
let data = &data[RLINK_MAGIC.len()..];
if data.len() < 4 {
return Err("The input does not contain version number".to_string());
return Err(CodegenErrors::EmptyVersionNumber);
}
let mut version_array: [u8; 4] = Default::default();
version_array.copy_from_slice(&data[..4]);
if u32::from_be_bytes(version_array) != RLINK_VERSION {
return Err(".rlink file was produced with encoding version {version_array}, but the current version is {RLINK_VERSION}".to_string());
return Err(CodegenErrors::EncodingVersionMismatch {
version_array: String::from_utf8_lossy(&version_array).to_string(),
rlink_version: RLINK_VERSION,
});
}
let mut decoder = MemDecoder::new(&data[4..], 0);
let rustc_version = decoder.read_str();
let current_version = RUSTC_VERSION.unwrap();
if rustc_version != current_version {
return Err(format!(
".rlink file was produced by rustc version {rustc_version}, but the current version is {current_version}."
));
return Err(CodegenErrors::RustcVersionMismatch {
rustc_version: rustc_version.to_string(),
current_version,
});
}
let codegen_results = CodegenResults::decode(&mut decoder);

View File

@ -1,16 +1,16 @@
// Not in interpret to make sure we do not use private implementation details
use crate::errors::MaxNumNodesInConstErr;
use crate::interpret::{
intern_const_alloc_recursive, ConstValue, InternKind, InterpCx, InterpResult, MemPlaceMeta,
Scalar,
};
use rustc_hir::Mutability;
use rustc_middle::mir;
use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId};
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::{source_map::DUMMY_SP, symbol::Symbol};
use crate::interpret::{
intern_const_alloc_recursive, ConstValue, InternKind, InterpCx, InterpResult, MemPlaceMeta,
Scalar,
};
mod error;
mod eval_queries;
mod fn_queries;
@ -72,12 +72,17 @@ pub(crate) fn eval_to_valtree<'tcx>(
Ok(valtree) => Ok(Some(valtree)),
Err(err) => {
let did = cid.instance.def_id();
let s = cid.display(tcx);
let global_const_id = cid.display(tcx);
match err {
ValTreeCreationError::NodesOverflow => {
let msg = format!("maximum number of nodes exceeded in constant {}", &s);
let msg = format!(
"maximum number of nodes exceeded in constant {}",
&global_const_id
);
let mut diag = match tcx.hir().span_if_local(did) {
Some(span) => tcx.sess.struct_span_err(span, &msg),
Some(span) => {
tcx.sess.create_err(MaxNumNodesInConstErr { span, global_const_id })
}
None => tcx.sess.struct_err(&msg),
};
diag.emit();

View File

@ -87,3 +87,110 @@ pub(crate) struct TransientMutBorrowErrRaw {
pub span: Span,
pub kind: ConstContext,
}
#[derive(SessionDiagnostic)]
#[diag(const_eval::max_num_nodes_in_const)]
pub(crate) struct MaxNumNodesInConstErr {
#[primary_span]
pub span: Span,
pub global_const_id: String,
}
#[derive(SessionDiagnostic)]
#[diag(const_eval::unallowed_fn_pointer_call)]
pub(crate) struct UnallowedFnPointerCall {
#[primary_span]
pub span: Span,
pub kind: ConstContext,
}
#[derive(SessionDiagnostic)]
#[diag(const_eval::unstable_const_fn)]
pub(crate) struct UnstableConstFn {
#[primary_span]
pub span: Span,
pub def_path: String,
}
#[derive(SessionDiagnostic)]
#[diag(const_eval::unallowed_mutable_refs, code = "E0764")]
pub(crate) struct UnallowedMutableRefs {
#[primary_span]
pub span: Span,
pub kind: ConstContext,
#[note(const_eval::teach_note)]
pub teach: Option<()>,
}
#[derive(SessionDiagnostic)]
#[diag(const_eval::unallowed_mutable_refs_raw, code = "E0764")]
pub(crate) struct UnallowedMutableRefsRaw {
#[primary_span]
pub span: Span,
pub kind: ConstContext,
#[note(const_eval::teach_note)]
pub teach: Option<()>,
}
#[derive(SessionDiagnostic)]
#[diag(const_eval::non_const_fmt_macro_call, code = "E0015")]
pub(crate) struct NonConstFmtMacroCall {
#[primary_span]
pub span: Span,
pub kind: ConstContext,
}
#[derive(SessionDiagnostic)]
#[diag(const_eval::non_const_fn_call, code = "E0015")]
pub(crate) struct NonConstFnCall {
#[primary_span]
pub span: Span,
pub def_path_str: String,
pub kind: ConstContext,
}
#[derive(SessionDiagnostic)]
#[diag(const_eval::unallowed_op_in_const_context)]
pub(crate) struct UnallowedOpInConstContext {
#[primary_span]
pub span: Span,
pub msg: String,
}
#[derive(SessionDiagnostic)]
#[diag(const_eval::unallowed_heap_allocations, code = "E0010")]
pub(crate) struct UnallowedHeapAllocations {
#[primary_span]
#[label]
pub span: Span,
pub kind: ConstContext,
#[note(const_eval::teach_note)]
pub teach: Option<()>,
}
#[derive(SessionDiagnostic)]
#[diag(const_eval::unallowed_inline_asm, code = "E0015")]
pub(crate) struct UnallowedInlineAsm {
#[primary_span]
pub span: Span,
pub kind: ConstContext,
}
#[derive(SessionDiagnostic)]
#[diag(const_eval::interior_mutable_data_refer, code = "E0492")]
pub(crate) struct InteriorMutableDataRefer {
#[primary_span]
#[label]
pub span: Span,
#[help]
pub opt_help: Option<()>,
pub kind: ConstContext,
#[note(const_eval::teach_note)]
pub teach: Option<()>,
}
#[derive(SessionDiagnostic)]
#[diag(const_eval::interior_mutability_borrow)]
pub(crate) struct InteriorMutabilityBorrow {
#[primary_span]
pub span: Span,
}

View File

@ -24,8 +24,11 @@ use rustc_trait_selection::traits::SelectionContext;
use super::ConstCx;
use crate::errors::{
MutDerefErr, NonConstOpErr, PanicNonStrErr, RawPtrToIntErr, StaticAccessErr,
TransientMutBorrowErr, TransientMutBorrowErrRaw,
InteriorMutabilityBorrow, InteriorMutableDataRefer, MutDerefErr, NonConstFmtMacroCall,
NonConstFnCall, NonConstOpErr, PanicNonStrErr, RawPtrToIntErr, StaticAccessErr,
TransientMutBorrowErr, TransientMutBorrowErrRaw, UnallowedFnPointerCall,
UnallowedHeapAllocations, UnallowedInlineAsm, UnallowedMutableRefs, UnallowedMutableRefsRaw,
UnallowedOpInConstContext, UnstableConstFn,
};
use crate::util::{call_kind, CallDesugaringKind, CallKind};
@ -97,10 +100,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallIndirect {
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
ccx.tcx.sess.struct_span_err(
span,
&format!("function pointer calls are not allowed in {}s", ccx.const_kind()),
)
ccx.tcx.sess.create_err(UnallowedFnPointerCall { span, kind: ccx.const_kind() })
}
}
@ -308,22 +308,13 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
err
}
_ if tcx.opt_parent(callee) == tcx.get_diagnostic_item(sym::ArgumentV1Methods) => {
struct_span_err!(
ccx.tcx.sess,
span,
E0015,
"cannot call non-const formatting macro in {}s",
ccx.const_kind(),
)
ccx.tcx.sess.create_err(NonConstFmtMacroCall { span, kind: ccx.const_kind() })
}
_ => struct_span_err!(
ccx.tcx.sess,
_ => ccx.tcx.sess.create_err(NonConstFnCall {
span,
E0015,
"cannot call non-const fn `{}` in {}s",
ccx.tcx.def_path_str_with_substs(callee, substs),
ccx.const_kind(),
),
def_path_str: ccx.tcx.def_path_str_with_substs(callee, substs),
kind: ccx.const_kind(),
}),
};
err.note(&format!(
@ -354,10 +345,10 @@ impl<'tcx> NonConstOp<'tcx> for FnCallUnstable {
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
let FnCallUnstable(def_id, feature) = *self;
let mut err = ccx.tcx.sess.struct_span_err(
span,
&format!("`{}` is not yet stable as a const fn", ccx.tcx.def_path_str(def_id)),
);
let mut err = ccx
.tcx
.sess
.create_err(UnstableConstFn { span, def_path: ccx.tcx.def_path_str(def_id) });
if ccx.is_const_stable_const_fn() {
err.help("const-stable functions can only call other const-stable functions");
@ -392,9 +383,12 @@ impl<'tcx> NonConstOp<'tcx> for Generator {
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
let msg = format!("{}s are not allowed in {}s", self.0, ccx.const_kind());
if let hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) = self.0 {
feature_err(&ccx.tcx.sess.parse_sess, sym::const_async_blocks, span, &msg)
ccx.tcx.sess.create_feature_err(
UnallowedOpInConstContext { span, msg },
sym::const_async_blocks,
)
} else {
ccx.tcx.sess.struct_span_err(span, &msg)
ccx.tcx.sess.create_err(UnallowedOpInConstContext { span, msg })
}
}
}
@ -407,23 +401,11 @@ impl<'tcx> NonConstOp<'tcx> for HeapAllocation {
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
let mut err = struct_span_err!(
ccx.tcx.sess,
ccx.tcx.sess.create_err(UnallowedHeapAllocations {
span,
E0010,
"allocations are not allowed in {}s",
ccx.const_kind()
);
err.span_label(span, format!("allocation not allowed in {}s", ccx.const_kind()));
if ccx.tcx.sess.teach(&err.get_code().unwrap()) {
err.note(
"The value of statics and constants must be known at compile time, \
and they live for the entire lifetime of a program. Creating a boxed \
value allocates memory on the heap at runtime, and therefore cannot \
be done at compile time.",
);
}
err
kind: ccx.const_kind(),
teach: ccx.tcx.sess.teach(&error_code!(E0010)).then_some(()),
})
}
}
@ -435,13 +417,7 @@ impl<'tcx> NonConstOp<'tcx> for InlineAsm {
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
struct_span_err!(
ccx.tcx.sess,
span,
E0015,
"inline assembly is not allowed in {}s",
ccx.const_kind()
)
ccx.tcx.sess.create_err(UnallowedInlineAsm { span, kind: ccx.const_kind() })
}
}
@ -487,12 +463,7 @@ impl<'tcx> NonConstOp<'tcx> for TransientCellBorrow {
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
feature_err(
&ccx.tcx.sess.parse_sess,
sym::const_refs_to_cell,
span,
"cannot borrow here, since the borrowed element may contain interior mutability",
)
ccx.tcx.sess.create_feature_err(InteriorMutabilityBorrow { span }, sym::const_refs_to_cell)
}
}
@ -507,32 +478,22 @@ impl<'tcx> NonConstOp<'tcx> for CellBorrow {
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
let mut err = struct_span_err!(
ccx.tcx.sess,
span,
E0492,
"{}s cannot refer to interior mutable data",
ccx.const_kind(),
);
err.span_label(
span,
"this borrow of an interior mutable value may end up in the final value",
);
// FIXME: Maybe a more elegant solution to this if else case
if let hir::ConstContext::Static(_) = ccx.const_kind() {
err.help(
"to fix this, the value can be extracted to a separate \
`static` item and then referenced",
);
ccx.tcx.sess.create_err(InteriorMutableDataRefer {
span,
opt_help: Some(()),
kind: ccx.const_kind(),
teach: ccx.tcx.sess.teach(&error_code!(E0492)).then_some(()),
})
} else {
ccx.tcx.sess.create_err(InteriorMutableDataRefer {
span,
opt_help: None,
kind: ccx.const_kind(),
teach: ccx.tcx.sess.teach(&error_code!(E0492)).then_some(()),
})
}
if ccx.tcx.sess.teach(&err.get_code().unwrap()) {
err.note(
"A constant containing interior mutable data behind a reference can allow you
to modify that data. This would make multiple uses of a constant to be able to
see different values and allow circumventing the `Send` and `Sync` requirements
for shared mutable data, which is unsound.",
);
}
err
}
}
@ -558,33 +519,18 @@ impl<'tcx> NonConstOp<'tcx> for MutBorrow {
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
let raw = match self.0 {
hir::BorrowKind::Raw => "raw ",
hir::BorrowKind::Ref => "",
};
let mut err = struct_span_err!(
ccx.tcx.sess,
span,
E0764,
"{}mutable references are not allowed in the final value of {}s",
raw,
ccx.const_kind(),
);
if ccx.tcx.sess.teach(&err.get_code().unwrap()) {
err.note(
"References in statics and constants may only refer \
to immutable values.\n\n\
Statics are shared everywhere, and if they refer to \
mutable data one might violate memory safety since \
holding multiple mutable references to shared data \
is not allowed.\n\n\
If you really want global mutable state, try using \
static mut or a global UnsafeCell.",
);
match self.0 {
hir::BorrowKind::Raw => ccx.tcx.sess.create_err(UnallowedMutableRefsRaw {
span,
kind: ccx.const_kind(),
teach: ccx.tcx.sess.teach(&error_code!(E0764)).then_some(()),
}),
hir::BorrowKind::Ref => ccx.tcx.sess.create_err(UnallowedMutableRefs {
span,
kind: ccx.const_kind(),
teach: ccx.tcx.sess.teach(&error_code!(E0764)).then_some(()),
}),
}
err
}
}

View File

@ -19,6 +19,7 @@ rustc_errors = { path = "../rustc_errors" }
rustc_feature = { path = "../rustc_feature" }
rustc_hir = { path = "../rustc_hir" }
rustc_hir_pretty = { path = "../rustc_hir_pretty" }
rustc_macros = { path = "../rustc_macros" }
rustc_metadata = { path = "../rustc_metadata" }
rustc_parse = { path = "../rustc_parse" }
rustc_plugin_impl = { path = "../rustc_plugin_impl" }

View File

@ -9,6 +9,8 @@
#![feature(once_cell)]
#![recursion_limit = "256"]
#![allow(rustc::potential_query_instability)]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
#[macro_use]
extern crate tracing;
@ -16,7 +18,7 @@ extern crate tracing;
pub extern crate rustc_plugin_impl as plugin;
use rustc_ast as ast;
use rustc_codegen_ssa::{traits::CodegenBackend, CodegenResults};
use rustc_codegen_ssa::{traits::CodegenBackend, CodegenErrors, CodegenResults};
use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
use rustc_data_structures::sync::SeqCst;
use rustc_errors::registry::{InvalidErrorCode, Registry};
@ -56,6 +58,12 @@ use std::time::Instant;
pub mod args;
pub mod pretty;
mod session_diagnostics;
use crate::session_diagnostics::{
RLinkEmptyVersionNumber, RLinkEncodingVersionMismatch, RLinkRustcVersionMismatch,
RLinkWrongFileType, RlinkNotAFile, RlinkUnableToRead,
};
/// Exit status code used for successful compilation and help output.
pub const EXIT_SUCCESS: i32 = 0;
@ -581,18 +589,35 @@ pub fn try_process_rlink(sess: &Session, compiler: &interface::Compiler) -> Comp
sess.init_crate_types(collect_crate_types(sess, &[]));
let outputs = compiler.build_output_filenames(sess, &[]);
let rlink_data = fs::read(file).unwrap_or_else(|err| {
sess.fatal(&format!("failed to read rlink file: {}", err));
sess.emit_fatal(RlinkUnableToRead { err });
});
let codegen_results = match CodegenResults::deserialize_rlink(rlink_data) {
Ok(codegen) => codegen,
Err(error) => {
sess.fatal(&format!("Could not deserialize .rlink file: {error}"));
Err(err) => {
match err {
CodegenErrors::WrongFileType => sess.emit_fatal(RLinkWrongFileType),
CodegenErrors::EmptyVersionNumber => {
sess.emit_fatal(RLinkEmptyVersionNumber)
}
CodegenErrors::EncodingVersionMismatch { version_array, rlink_version } => {
sess.emit_fatal(RLinkEncodingVersionMismatch {
version_array,
rlink_version,
})
}
CodegenErrors::RustcVersionMismatch { rustc_version, current_version } => {
sess.emit_fatal(RLinkRustcVersionMismatch {
rustc_version,
current_version,
})
}
};
}
};
let result = compiler.codegen_backend().link(sess, codegen_results, &outputs);
abort_on_err(result, sess);
} else {
sess.fatal("rlink must be a file")
sess.emit_fatal(RlinkNotAFile {})
}
Compilation::Stop
} else {

View File

@ -0,0 +1,33 @@
use rustc_macros::SessionDiagnostic;
#[derive(SessionDiagnostic)]
#[diag(driver::rlink_unable_to_read)]
pub(crate) struct RlinkUnableToRead {
pub err: std::io::Error,
}
#[derive(SessionDiagnostic)]
#[diag(driver::rlink_wrong_file_type)]
pub(crate) struct RLinkWrongFileType;
#[derive(SessionDiagnostic)]
#[diag(driver::rlink_empty_version_number)]
pub(crate) struct RLinkEmptyVersionNumber;
#[derive(SessionDiagnostic)]
#[diag(driver::rlink_encoding_version_mismatch)]
pub(crate) struct RLinkEncodingVersionMismatch {
pub version_array: String,
pub rlink_version: u32,
}
#[derive(SessionDiagnostic)]
#[diag(driver::rlink_rustc_version_mismatch)]
pub(crate) struct RLinkRustcVersionMismatch<'a> {
pub rustc_version: String,
pub current_version: &'a str,
}
#[derive(SessionDiagnostic)]
#[diag(driver::rlink_no_a_file)]
pub(crate) struct RlinkNotAFile;

View File

@ -0,0 +1,131 @@
ast_lowering_generic_type_with_parentheses =
parenthesized type parameters may only be used with a `Fn` trait
.label = only `Fn` traits may use parentheses
ast_lowering_use_angle_brackets = use angle brackets instead
ast_lowering_invalid_abi =
invalid ABI: found `{$abi}`
.label = invalid ABI
.help = valid ABIs: {$valid_abis}
ast_lowering_assoc_ty_parentheses =
parenthesized generic arguments cannot be used in associated type constraints
ast_lowering_remove_parentheses = remove these parentheses
ast_lowering_misplaced_impl_trait =
`impl Trait` only allowed in function and inherent method return types, not in {$position}
ast_lowering_rustc_box_attribute_error =
#[rustc_box] requires precisely one argument and no other attributes are allowed
ast_lowering_underscore_expr_lhs_assign =
in expressions, `_` can only be used on the left-hand side of an assignment
.label = `_` not allowed here
ast_lowering_base_expression_double_dot =
base expression required after `..`
.label = add a base expression here
ast_lowering_await_only_in_async_fn_and_blocks =
`await` is only allowed inside `async` functions and blocks
.label = only allowed inside `async` functions and blocks
ast_lowering_this_not_async = this is not `async`
ast_lowering_generator_too_many_parameters =
too many parameters for a generator (expected 0 or 1 parameters)
ast_lowering_closure_cannot_be_static = closures cannot be static
ast_lowering_async_non_move_closure_not_supported =
`async` non-`move` closures with parameters are not currently supported
.help = consider using `let` statements to manually capture variables by reference before entering an `async move` closure
ast_lowering_functional_record_update_destructuring_assignment =
functional record updates are not allowed in destructuring assignments
.suggestion = consider removing the trailing pattern
ast_lowering_async_generators_not_supported =
`async` generators are not yet supported
ast_lowering_inline_asm_unsupported_target =
inline assembly is unsupported on this target
ast_lowering_att_syntax_only_x86 =
the `att_syntax` option is only supported on x86
ast_lowering_abi_specified_multiple_times =
`{$prev_name}` ABI specified multiple times
.label = previously specified here
.note = these ABIs are equivalent on the current target
ast_lowering_clobber_abi_not_supported =
`clobber_abi` is not supported on this target
ast_lowering_invalid_abi_clobber_abi =
invalid ABI for `clobber_abi`
.note = the following ABIs are supported on this target: {$supported_abis}
ast_lowering_invalid_register =
invalid register `{$reg}`: {$error}
ast_lowering_invalid_register_class =
invalid register class `{$reg_class}`: {$error}
ast_lowering_invalid_asm_template_modifier_reg_class =
invalid asm template modifier for this register class
ast_lowering_argument = argument
ast_lowering_template_modifier = template modifier
ast_lowering_support_modifiers =
the `{$class_name}` register class supports the following template modifiers: {$modifiers}
ast_lowering_does_not_support_modifiers =
the `{$class_name}` register class does not support template modifiers
ast_lowering_invalid_asm_template_modifier_const =
asm template modifiers are not allowed for `const` arguments
ast_lowering_invalid_asm_template_modifier_sym =
asm template modifiers are not allowed for `sym` arguments
ast_lowering_register_class_only_clobber =
register class `{$reg_class_name}` can only be used as a clobber, not as an input or output
ast_lowering_register_conflict =
register `{$reg1_name}` conflicts with register `{$reg2_name}`
.help = use `lateout` instead of `out` to avoid conflict
ast_lowering_register1 = register `{$reg1_name}`
ast_lowering_register2 = register `{$reg2_name}`
ast_lowering_sub_tuple_binding =
`{$ident_name} @` is not allowed in a {$ctx}
.label = this is only allowed in slice patterns
.help = remove this and bind each tuple field independently
ast_lowering_sub_tuple_binding_suggestion = if you don't need to use the contents of {$ident}, discard the tuple's remaining fields
ast_lowering_extra_double_dot =
`..` can only be used once per {$ctx} pattern
.label = can only be used once per {$ctx} pattern
ast_lowering_previously_used_here = previously used here
ast_lowering_misplaced_double_dot =
`..` patterns are not allowed here
.note = only allowed in tuple, tuple struct, and slice patterns
ast_lowering_misplaced_relax_trait_bound =
`?Trait` bounds are only permitted at the point where a type parameter is declared
ast_lowering_not_supported_for_lifetime_binder_async_closure =
`for<...>` binders on `async` closures are not currently supported
ast_lowering_arbitrary_expression_in_pattern =
arbitrary expressions aren't allowed in patterns

View File

@ -0,0 +1,107 @@
attr_expected_one_cfg_pattern =
expected 1 cfg-pattern
attr_invalid_predicate =
invalid predicate `{$predicate}`
attr_multiple_item =
multiple '{$item}' items
attr_incorrect_meta_item =
incorrect meta item
attr_unknown_meta_item =
unknown meta item '{$item}'
.label = expected one of {$expected}
attr_missing_since =
missing 'since'
attr_missing_note =
missing 'note'
attr_multiple_stability_levels =
multiple stability levels
attr_invalid_issue_string =
`issue` must be a non-zero numeric string or "none"
.must_not_be_zero = `issue` must not be "0", use "none" instead
.empty = cannot parse integer from empty string
.invalid_digit = invalid digit found in string
.pos_overflow = number too large to fit in target type
.neg_overflow = number too small to fit in target type
attr_missing_feature =
missing 'feature'
attr_non_ident_feature =
'feature' is not an identifier
attr_missing_issue =
missing 'issue'
attr_incorrect_repr_format_packed_one_or_zero_arg =
incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all
attr_invalid_repr_hint_no_paren =
invalid representation hint: `{$name}` does not take a parenthesized argument list
attr_invalid_repr_hint_no_value =
invalid representation hint: `{$name}` does not take a value
attr_unsupported_literal_generic =
unsupported literal
attr_unsupported_literal_cfg_string =
literal in `cfg` predicate value must be a string
attr_unsupported_literal_deprecated_string =
literal in `deprecated` value must be a string
attr_unsupported_literal_deprecated_kv_pair =
item in `deprecated` must be a key/value pair
attr_unsupported_literal_suggestion =
consider removing the prefix
attr_invalid_repr_align_need_arg =
invalid `repr(align)` attribute: `align` needs an argument
.suggestion = supply an argument here
attr_invalid_repr_generic =
invalid `repr({$repr_arg})` attribute: {$error_part}
attr_incorrect_repr_format_align_one_arg =
incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses
attr_incorrect_repr_format_generic =
incorrect `repr({$repr_arg})` attribute format
.suggestion = use parentheses instead
attr_rustc_promotable_pairing =
`rustc_promotable` attribute must be paired with either a `rustc_const_unstable` or a `rustc_const_stable` attribute
attr_rustc_allowed_unstable_pairing =
`rustc_allowed_through_unstable_modules` attribute must be paired with a `stable` attribute
attr_cfg_predicate_identifier =
`cfg` predicate key must be an identifier
attr_deprecated_item_suggestion =
suggestions on deprecated items are unstable
.help = add `#![feature(deprecated_suggestion)]` to the crate root
.note = see #94785 for more details
attr_expected_single_version_literal =
expected single version literal
attr_expected_version_literal =
expected a version literal
attr_expects_feature_list =
`{$name}` expects a list of feature names
attr_expects_features =
`{$name}` expects feature names
attr_soft_no_args =
`soft` should not have any arguments
attr_unknown_version_literal =
unknown version literal format, assuming it refers to a future version

View File

@ -16,3 +16,45 @@ borrowck_higher_ranked_subtype_error =
borrowck_generic_does_not_live_long_enough =
`{$kind}` does not live long enough
borrowck_move_borrowed =
cannot move out of `{$desc}` beacause it is borrowed
borrowck_var_does_not_need_mut =
variable does not need to be mutable
.suggestion = remove this `mut`
borrowck_const_not_used_in_type_alias =
const parameter `{$ct}` is part of concrete type but not used in parameter list for the `impl Trait` type alias
borrowck_var_cannot_escape_closure =
captured variable cannot escape `FnMut` closure body
.note = `FnMut` closures only have access to their captured variables while they are executing...
.cannot_escape = ...therefore, they cannot allow references to captured variables to escape
borrowck_var_here_defined = variable defined here
borrowck_var_here_captured = variable captured here
borrowck_closure_inferred_mut = inferred to be a `FnMut` closure
borrowck_returned_closure_escaped =
returns a closure that contains a reference to a captured variable, which then escapes the closure body
borrowck_returned_async_block_escaped =
returns an `async` block that contains a reference to a captured variable, which then escapes the closure body
borrowck_returned_ref_escaped =
returns a reference to a captured variable which escapes the closure body
borrowck_lifetime_constraints_error =
lifetime may not live long enough
borrowck_returned_lifetime_wrong =
{$mir_def_name} was supposed to return data with lifetime `{$outlived_fr_name}` but it is returning data with lifetime `{$fr_name}`
borrowck_returned_lifetime_short =
{$category_desc}requires that `{$free_region_name}` must outlive `{$outlived_fr_name}`
borrowck_used_impl_require_static =
the used `impl` has a `'static` requirement

View File

@ -29,3 +29,55 @@ const_eval_mut_deref =
const_eval_transient_mut_borrow = mutable references are not allowed in {$kind}s
const_eval_transient_mut_borrow_raw = raw mutable references are not allowed in {$kind}s
const_eval_max_num_nodes_in_const = maximum number of nodes exceeded in constant {$global_const_id}
const_eval_unallowed_fn_pointer_call = function pointer calls are not allowed in {$kind}s
const_eval_unstable_const_fn = `{$def_path}` is not yet stable as a const fn
const_eval_unallowed_mutable_refs =
mutable references are not allowed in the final value of {$kind}s
.teach_note =
References in statics and constants may only refer to immutable values.\n\n
Statics are shared everywhere, and if they refer to mutable data one might violate memory
safety since holding multiple mutable references to shared data is not allowed.\n\n
If you really want global mutable state, try using static mut or a global UnsafeCell.
const_eval_unallowed_mutable_refs_raw =
raw mutable references are not allowed in the final value of {$kind}s
.teach_note =
References in statics and constants may only refer to immutable values.\n\n
Statics are shared everywhere, and if they refer to mutable data one might violate memory
safety since holding multiple mutable references to shared data is not allowed.\n\n
If you really want global mutable state, try using static mut or a global UnsafeCell.
const_eval_non_const_fmt_macro_call =
cannot call non-const formatting macro in {$kind}s
const_eval_non_const_fn_call =
cannot call non-const fn `{$def_path_str}` in {$kind}s
const_eval_unallowed_op_in_const_context =
{$msg}
const_eval_unallowed_heap_allocations =
allocations are not allowed in {$kind}s
.label = allocation not allowed in {$kind}s
.teach_note =
The value of statics and constants must be known at compile time, and they live for the entire lifetime of a program. Creating a boxed value allocates memory on the heap at runtime, and therefore cannot be done at compile time.
const_eval_unallowed_inline_asm =
inline assembly is not allowed in {$kind}s
const_eval_interior_mutable_data_refer =
{$kind}s cannot refer to interior mutable data
.label = this borrow of an interior mutable value may end up in the final value
.help = to fix this, the value can be extracted to a separate `static` item and then referenced
.teach_note =
A constant containing interior mutable data behind a reference can allow you to modify that data.
This would make multiple uses of a constant to be able to see different values and allow circumventing
the `Send` and `Sync` requirements for shared mutable data, which is unsound.
const_eval_interior_mutability_borrow =
cannot borrow here, since the borrowed element may contain interior mutability

View File

@ -0,0 +1,11 @@
driver_rlink_unable_to_read = failed to read rlink file: `{$err}`
driver_rlink_wrong_file_type = The input does not look like a .rlink file
driver_rlink_empty_version_number = The input does not contain version number
driver_rlink_encoding_version_mismatch = .rlink file was produced with encoding version `{$version_array}`, but the current version is `{$rlink_version}`
driver_rlink_rustc_version_mismatch = .rlink file was produced by rustc version `{$rustc_version}`, but the current version is `{$current_version}`
driver_rlink_no_a_file = rlink must be a file

View File

@ -393,3 +393,37 @@ lint_builtin_deref_nullptr = dereferencing a null pointer
.label = this code causes undefined behavior when executed
lint_builtin_asm_labels = avoid using named labels in inline assembly
lint_overruled_attribute = {$lint_level}({$lint_source}) incompatible with previous forbid
.label = overruled by previous forbid
lint_default_source = `forbid` lint level is the default for {$id}
lint_node_source = `forbid` level set here
.note = {$reason}
lint_command_line_source = `forbid` lint level was set on command line
lint_malformed_attribute = malformed lint attribute input
lint_bad_attribute_argument = bad attribute argument
lint_reason_must_be_string_literal = reason must be a string literal
lint_reason_must_come_last = reason in lint attribute must come last
lint_unknown_tool_in_scoped_lint = unknown tool name `{$tool_name}` found in scoped lint: `{$tool_name}::{$lint_name}`
.help = add `#![register_tool({$tool_name})]` to the crate root
lint_unsupported_group = `{$lint_group}` lint group is not supported with ´--force-warn´
lint_requested_level = requested on the command line with `{$level} {$lint_name}`
lint_check_name_unknown = unknown lint: `{$lint_name}`
.help = did you mean: `{$suggestion}`
lint_check_name_unknown_tool = unknown lint tool: `{$tool_name}`
lint_check_name_warning = {$msg}
lint_check_name_deprecated = lint name `{$lint_name}` is deprecated and does not have an effect anymore. Use: {$new_name}

View File

@ -0,0 +1,29 @@
mir_dataflow_path_must_end_in_filename =
path must end in a filename
mir_dataflow_unknown_formatter =
unknown formatter
mir_dataflow_duplicate_values_for =
duplicate values for `{$name}`
mir_dataflow_requires_an_argument =
`{$name}` requires an argument
mir_dataflow_stop_after_dataflow_ended_compilation =
stop_after_dataflow ended compilation
mir_dataflow_peek_must_be_place_or_ref_place =
rustc_peek: argument expression must be either `place` or `&place`
mir_dataflow_peek_must_be_not_temporary =
dataflow::sanity_check cannot feed a non-temp to rustc_peek
mir_dataflow_peek_bit_not_set =
rustc_peek: bit not set
mir_dataflow_peek_argument_not_a_local =
rustc_peek: argument was not a local
mir_dataflow_peek_argument_untracked =
rustc_peek: argument untracked

View File

@ -0,0 +1,47 @@
ty_utils_needs_drop_overflow = overflow while checking whether `{$query_ty}` requires drop
ty_utils_generic_constant_too_complex = overly complex generic constant
.help = consider moving this anonymous constant into a `const` function
.maybe_supported = this operation may be supported in the future
ty_utils_borrow_not_supported = borrowing is not supported in generic constants
ty_utils_address_and_deref_not_supported = dereferencing or taking the address is not supported in generic constants
ty_utils_array_not_supported = array construction is not supported in generic constants
ty_utils_block_not_supported = blocks are not supported in generic constant
ty_utils_never_to_any_not_supported = converting nevers to any is not supported in generic constant
ty_utils_tuple_not_supported = tuple construction is not supported in generic constants
ty_utils_index_not_supported = indexing is not supported in generic constant
ty_utils_field_not_supported = field access is not supported in generic constant
ty_utils_const_block_not_supported = const blocks are not supported in generic constant
ty_utils_adt_not_supported = struct/enum construction is not supported in generic constants
ty_utils_pointer_not_supported = pointer casts are not allowed in generic constants
ty_utils_yield_not_supported = generator control flow is not allowed in generic constants
ty_utils_loop_not_supported = loops and loop control flow are not supported in generic constants
ty_utils_box_not_supported = allocations are not allowed in generic constants
ty_utils_binary_not_supported = unsupported binary operation in generic constants
ty_utils_logical_op_not_supported = unsupported operation in generic constants, short-circuiting operations would imply control flow
ty_utils_assign_not_supported = assignment is not supported in generic constants
ty_utils_closure_and_return_not_supported = closures and function keywords are not supported in generic constants
ty_utils_control_flow_not_supported = control flow is not supported in generic constants
ty_utils_inline_asm_not_supported = assembly is not supported in generic constants
ty_utils_operation_not_supported = unsupported operation in generic constant

View File

@ -32,10 +32,13 @@ pub use unic_langid::{langid, LanguageIdentifier};
// Generates `DEFAULT_LOCALE_RESOURCES` static and `fluent_generated` module.
fluent_messages! {
ast_lowering => "../locales/en-US/ast_lowering.ftl",
ast_passes => "../locales/en-US/ast_passes.ftl",
attr => "../locales/en-US/attr.ftl",
borrowck => "../locales/en-US/borrowck.ftl",
builtin_macros => "../locales/en-US/builtin_macros.ftl",
const_eval => "../locales/en-US/const_eval.ftl",
driver => "../locales/en-US/driver.ftl",
expand => "../locales/en-US/expand.ftl",
interface => "../locales/en-US/interface.ftl",
lint => "../locales/en-US/lint.ftl",
@ -44,7 +47,9 @@ fluent_messages! {
plugin_impl => "../locales/en-US/plugin_impl.ftl",
privacy => "../locales/en-US/privacy.ftl",
save_analysis => "../locales/en-US/save_analysis.ftl",
ty_utils => "../locales/en-US/ty_utils.ftl",
typeck => "../locales/en-US/typeck.ftl",
mir_dataflow => "../locales/en-US/mir_dataflow.ftl",
}
pub use fluent_generated::{self as fluent, DEFAULT_LOCALE_RESOURCES};

View File

@ -21,6 +21,7 @@
//! `late_lint_methods!` invocation in `lib.rs`.
use crate::{
errors::BuiltinEllpisisInclusiveRangePatterns,
types::{transparent_newtype_field, CItemKind},
EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext,
};
@ -1760,18 +1761,11 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns {
None => format!("&(..={})", end),
};
if join.edition() >= Edition::Edition2021 {
let mut err = cx.sess().struct_span_err_with_code(
pat.span,
msg,
rustc_errors::error_code!(E0783),
);
err.span_suggestion(
pat.span,
suggestion,
cx.sess().emit_err(BuiltinEllpisisInclusiveRangePatterns {
span: pat.span,
suggestion: pat.span,
replace,
Applicability::MachineApplicable,
)
.emit();
});
} else {
cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, pat.span, |lint| {
lint.build(msg)
@ -1787,18 +1781,11 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns {
} else {
let replace = "..=";
if join.edition() >= Edition::Edition2021 {
let mut err = cx.sess().struct_span_err_with_code(
pat.span,
msg,
rustc_errors::error_code!(E0783),
);
err.span_suggestion_short(
join,
suggestion,
replace,
Applicability::MachineApplicable,
)
.emit();
cx.sess().emit_err(BuiltinEllpisisInclusiveRangePatterns {
span: pat.span,
suggestion: join,
replace: replace.to_string(),
});
} else {
cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, join, |lint| {
lint.build(msg)

View File

@ -16,12 +16,16 @@
use self::TargetLint::*;
use crate::errors::{
CheckNameDeprecated, CheckNameUnknown, CheckNameUnknownTool, CheckNameWarning, RequestedLevel,
UnsupportedGroup,
};
use crate::levels::LintLevelsBuilder;
use crate::passes::{EarlyLintPassObject, LateLintPassObject};
use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync;
use rustc_errors::{add_elided_lifetime_in_path_suggestion, struct_span_err};
use rustc_errors::add_elided_lifetime_in_path_suggestion;
use rustc_errors::{
Applicability, DecorateLint, LintDiagnosticBuilder, MultiSpan, SuggestionStyle,
};
@ -39,7 +43,7 @@ use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintBuffer, LintI
use rustc_session::Session;
use rustc_span::lev_distance::find_best_match_for_name;
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::{BytePos, Span, DUMMY_SP};
use rustc_span::{BytePos, Span};
use rustc_target::abi;
use tracing::debug;
@ -326,68 +330,41 @@ impl LintStore {
) {
let (tool_name, lint_name_only) = parse_lint_and_tool_name(lint_name);
if lint_name_only == crate::WARNINGS.name_lower() && matches!(level, Level::ForceWarn(_)) {
struct_span_err!(
sess,
DUMMY_SP,
E0602,
"`{}` lint group is not supported with ´--force-warn´",
crate::WARNINGS.name_lower()
)
.emit();
sess.emit_err(UnsupportedGroup { lint_group: crate::WARNINGS.name_lower() });
return;
}
let db = match self.check_lint_name(lint_name_only, tool_name, registered_tools) {
CheckLintNameResult::Ok(_) => None,
CheckLintNameResult::Warning(ref msg, _) => Some(sess.struct_warn(msg)),
CheckLintNameResult::NoLint(suggestion) => {
let mut err =
struct_span_err!(sess, DUMMY_SP, E0602, "unknown lint: `{}`", lint_name);
if let Some(suggestion) = suggestion {
err.help(&format!("did you mean: `{}`", suggestion));
}
Some(err.forget_guarantee())
let lint_name = lint_name.to_string();
match self.check_lint_name(lint_name_only, tool_name, registered_tools) {
CheckLintNameResult::Warning(msg, _) => {
sess.emit_warning(CheckNameWarning {
msg,
sub: RequestedLevel { level, lint_name },
});
}
CheckLintNameResult::Tool(result) => match result {
Err((Some(_), new_name)) => Some(sess.struct_warn(&format!(
"lint name `{}` is deprecated \
and does not have an effect anymore. \
Use: {}",
lint_name, new_name
))),
_ => None,
},
CheckLintNameResult::NoTool => Some(
struct_span_err!(
sess,
DUMMY_SP,
E0602,
"unknown lint tool: `{}`",
tool_name.unwrap()
)
.forget_guarantee(),
),
CheckLintNameResult::NoLint(suggestion) => {
sess.emit_err(CheckNameUnknown {
lint_name: lint_name.clone(),
suggestion,
sub: RequestedLevel { level, lint_name },
});
}
CheckLintNameResult::Tool(result) => {
if let Err((Some(_), new_name)) = result {
sess.emit_warning(CheckNameDeprecated {
lint_name: lint_name.clone(),
new_name,
sub: RequestedLevel { level, lint_name },
});
}
}
CheckLintNameResult::NoTool => {
sess.emit_err(CheckNameUnknownTool {
tool_name: tool_name.unwrap(),
sub: RequestedLevel { level, lint_name },
});
}
_ => {}
};
if let Some(mut db) = db {
let msg = format!(
"requested on the command line with `{} {}`",
match level {
Level::Allow => "-A",
Level::Warn => "-W",
Level::ForceWarn(_) => "--force-warn",
Level::Deny => "-D",
Level::Forbid => "-F",
Level::Expect(_) => {
unreachable!("lints with the level of `expect` should not run this code");
}
},
lint_name
);
db.note(&msg);
db.emit();
}
}
/// True if this symbol represents a lint group name.

View File

@ -0,0 +1,162 @@
use rustc_errors::{fluent, AddSubdiagnostic, ErrorGuaranteed};
use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
use rustc_session::{lint::Level, parse::ParseSess, SessionDiagnostic};
use rustc_span::{Span, Symbol};
#[derive(SessionDiagnostic)]
#[diag(lint::overruled_attribute, code = "E0453")]
pub struct OverruledAttribute {
#[primary_span]
pub span: Span,
#[label]
pub overruled: Span,
pub lint_level: String,
pub lint_source: Symbol,
#[subdiagnostic]
pub sub: OverruledAttributeSub,
}
//
pub enum OverruledAttributeSub {
DefaultSource { id: String },
NodeSource { span: Span, reason: Option<Symbol> },
CommandLineSource,
}
impl AddSubdiagnostic for OverruledAttributeSub {
fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) {
match self {
OverruledAttributeSub::DefaultSource { id } => {
diag.note(fluent::lint::default_source);
diag.set_arg("id", id);
}
OverruledAttributeSub::NodeSource { span, reason } => {
diag.span_label(span, fluent::lint::node_source);
if let Some(rationale) = reason {
diag.note(rationale.as_str());
}
}
OverruledAttributeSub::CommandLineSource => {
diag.note(fluent::lint::command_line_source);
}
}
}
}
#[derive(SessionDiagnostic)]
#[diag(lint::malformed_attribute, code = "E0452")]
pub struct MalformedAttribute {
#[primary_span]
pub span: Span,
#[subdiagnostic]
pub sub: MalformedAttributeSub,
}
#[derive(SessionSubdiagnostic)]
pub enum MalformedAttributeSub {
#[label(lint::bad_attribute_argument)]
BadAttributeArgument(#[primary_span] Span),
#[label(lint::reason_must_be_string_literal)]
ReasonMustBeStringLiteral(#[primary_span] Span),
#[label(lint::reason_must_come_last)]
ReasonMustComeLast(#[primary_span] Span),
}
#[derive(SessionDiagnostic)]
#[diag(lint::unknown_tool_in_scoped_lint, code = "E0710")]
pub struct UnknownToolInScopedLint {
#[primary_span]
pub span: Option<Span>,
pub tool_name: Symbol,
pub lint_name: String,
#[help]
pub is_nightly_build: Option<()>,
}
#[derive(SessionDiagnostic)]
#[diag(lint::builtin_ellipsis_inclusive_range_patterns, code = "E0783")]
pub struct BuiltinEllpisisInclusiveRangePatterns {
#[primary_span]
pub span: Span,
#[suggestion_short(code = "{replace}", applicability = "machine-applicable")]
pub suggestion: Span,
pub replace: String,
}
pub struct RequestedLevel {
pub level: Level,
pub lint_name: String,
}
impl AddSubdiagnostic for RequestedLevel {
fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) {
diag.note(fluent::lint::requested_level);
diag.set_arg(
"level",
match self.level {
Level::Allow => "-A",
Level::Warn => "-W",
Level::ForceWarn(_) => "--force-warn",
Level::Deny => "-D",
Level::Forbid => "-F",
Level::Expect(_) => {
unreachable!("lints with the level of `expect` should not run this code");
}
},
);
diag.set_arg("lint_name", self.lint_name);
}
}
#[derive(SessionDiagnostic)]
#[diag(lint::unsupported_group, code = "E0602")]
pub struct UnsupportedGroup {
pub lint_group: String,
}
pub struct CheckNameUnknown {
pub lint_name: String,
pub suggestion: Option<Symbol>,
pub sub: RequestedLevel,
}
impl SessionDiagnostic<'_> for CheckNameUnknown {
fn into_diagnostic(
self,
sess: &ParseSess,
) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
let mut diag = sess.struct_err(fluent::lint::check_name_unknown);
diag.code(rustc_errors::error_code!(E0602));
if let Some(suggestion) = self.suggestion {
diag.help(fluent::lint::help);
diag.set_arg("suggestion", suggestion);
}
diag.set_arg("lint_name", self.lint_name);
diag.subdiagnostic(self.sub);
diag
}
}
#[derive(SessionDiagnostic)]
#[diag(lint::check_name_unknown_tool, code = "E0602")]
pub struct CheckNameUnknownTool {
pub tool_name: Symbol,
#[subdiagnostic]
pub sub: RequestedLevel,
}
#[derive(SessionDiagnostic)]
#[diag(lint::check_name_warning)]
pub struct CheckNameWarning {
pub msg: String,
#[subdiagnostic]
pub sub: RequestedLevel,
}
#[derive(SessionDiagnostic)]
#[diag(lint::check_name_deprecated)]
pub struct CheckNameDeprecated {
pub lint_name: String,
pub new_name: String,
#[subdiagnostic]
pub sub: RequestedLevel,
}

View File

@ -3,7 +3,7 @@ use crate::late::unerased_lint_store;
use rustc_ast as ast;
use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{struct_span_err, Applicability, Diagnostic, LintDiagnosticBuilder, MultiSpan};
use rustc_errors::{Applicability, Diagnostic, LintDiagnosticBuilder, MultiSpan};
use rustc_hir as hir;
use rustc_hir::{intravisit, HirId};
use rustc_middle::hir::nested_filter;
@ -23,6 +23,11 @@ use rustc_span::symbol::{sym, Symbol};
use rustc_span::{Span, DUMMY_SP};
use tracing::debug;
use crate::errors::{
MalformedAttribute, MalformedAttributeSub, OverruledAttribute, OverruledAttributeSub,
UnknownToolInScopedLint,
};
fn lint_levels(tcx: TyCtxt<'_>, (): ()) -> LintLevelMap {
let store = unerased_lint_store(tcx);
let levels =
@ -186,16 +191,26 @@ impl<'s> LintLevelsBuilder<'s> {
}
};
if !fcw_warning {
let mut diag_builder = struct_span_err!(
self.sess,
src.span(),
E0453,
"{}({}) incompatible with previous forbid",
level.as_str(),
src.name(),
);
decorate_diag(&mut diag_builder);
diag_builder.emit();
self.sess.emit_err(OverruledAttribute {
span: src.span(),
overruled: src.span(),
lint_level: level.as_str().to_string(),
lint_source: src.name(),
sub: match old_src {
LintLevelSource::Default => {
OverruledAttributeSub::DefaultSource { id: id.to_string() }
}
LintLevelSource::Node(_, forbid_source_span, reason) => {
OverruledAttributeSub::NodeSource {
span: forbid_source_span,
reason,
}
}
LintLevelSource::CommandLine(_, _) => {
OverruledAttributeSub::CommandLineSource
}
},
});
} else {
self.struct_lint(
FORBIDDEN_LINT_GROUPS,
@ -266,7 +281,6 @@ impl<'s> LintLevelsBuilder<'s> {
self.cur = self.sets.list.push(LintSet { specs: FxHashMap::default(), parent: prev });
let sess = self.sess;
let bad_attr = |span| struct_span_err!(sess, span, E0452, "malformed lint attribute input");
for (attr_index, attr) in attrs.iter().enumerate() {
if attr.has_name(sym::automatically_derived) {
self.current_specs_mut().insert(
@ -317,20 +331,27 @@ impl<'s> LintLevelsBuilder<'s> {
}
reason = Some(rationale);
} else {
bad_attr(name_value.span)
.span_label(name_value.span, "reason must be a string literal")
.emit();
sess.emit_err(MalformedAttribute {
span: name_value.span,
sub: MalformedAttributeSub::ReasonMustBeStringLiteral(
name_value.span,
),
});
}
// found reason, reslice meta list to exclude it
metas.pop().unwrap();
} else {
bad_attr(item.span)
.span_label(item.span, "bad attribute argument")
.emit();
sess.emit_err(MalformedAttribute {
span: item.span,
sub: MalformedAttributeSub::BadAttributeArgument(item.span),
});
}
}
ast::MetaItemKind::List(_) => {
bad_attr(item.span).span_label(item.span, "bad attribute argument").emit();
sess.emit_err(MalformedAttribute {
span: item.span,
sub: MalformedAttributeSub::BadAttributeArgument(item.span),
});
}
}
}
@ -348,20 +369,21 @@ impl<'s> LintLevelsBuilder<'s> {
let meta_item = match li {
ast::NestedMetaItem::MetaItem(meta_item) if meta_item.is_word() => meta_item,
_ => {
let mut err = bad_attr(sp);
let mut add_label = true;
if let Some(item) = li.meta_item() {
if let ast::MetaItemKind::NameValue(_) = item.kind {
if item.path == sym::reason {
err.span_label(sp, "reason in lint attribute must come last");
add_label = false;
sess.emit_err(MalformedAttribute {
span: sp,
sub: MalformedAttributeSub::ReasonMustComeLast(sp),
});
continue;
}
}
}
if add_label {
err.span_label(sp, "bad attribute argument");
}
err.emit();
sess.emit_err(MalformedAttribute {
span: sp,
sub: MalformedAttributeSub::BadAttributeArgument(sp),
});
continue;
}
};
@ -485,22 +507,12 @@ impl<'s> LintLevelsBuilder<'s> {
}
&CheckLintNameResult::NoTool => {
let mut err = struct_span_err!(
sess,
tool_ident.map_or(DUMMY_SP, |ident| ident.span),
E0710,
"unknown tool name `{}` found in scoped lint: `{}::{}`",
tool_name.unwrap(),
tool_name.unwrap(),
pprust::path_to_string(&meta_item.path),
);
if sess.is_nightly_build() {
err.help(&format!(
"add `#![register_tool({})]` to the crate root",
tool_name.unwrap()
));
}
err.emit();
sess.emit_err(UnknownToolInScopedLint {
span: tool_ident.map(|ident| ident.span),
tool_name: tool_name.unwrap(),
lint_name: pprust::path_to_string(&meta_item.path),
is_nightly_build: sess.is_nightly_build().then_some(()),
});
continue;
}

View File

@ -47,6 +47,7 @@ pub mod builtin;
mod context;
mod early;
mod enum_intrinsics_non_enums;
mod errors;
mod expect;
pub mod hidden_unicode_codepoints;
mod internal;

View File

@ -13,10 +13,13 @@ smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
tracing = "0.1"
rustc_ast = { path = "../rustc_ast" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_graphviz = { path = "../rustc_graphviz" }
rustc_hir = { path = "../rustc_hir" }
rustc_index = { path = "../rustc_index" }
rustc_macros = { path = "../rustc_macros" }
rustc_middle = { path = "../rustc_middle" }
rustc_serialize = { path = "../rustc_serialize" }
rustc_session = { path = "../rustc_session" }
rustc_target = { path = "../rustc_target" }
rustc_span = { path = "../rustc_span" }

View File

@ -0,0 +1,71 @@
use rustc_macros::SessionDiagnostic;
use rustc_span::{Span, Symbol};
#[derive(SessionDiagnostic)]
#[diag(mir_dataflow::path_must_end_in_filename)]
pub(crate) struct PathMustEndInFilename {
#[primary_span]
pub span: Span,
}
#[derive(SessionDiagnostic)]
#[diag(mir_dataflow::unknown_formatter)]
pub(crate) struct UnknownFormatter {
#[primary_span]
pub span: Span,
}
#[derive(SessionDiagnostic)]
#[diag(mir_dataflow::duplicate_values_for)]
pub(crate) struct DuplicateValuesFor {
#[primary_span]
pub span: Span,
pub name: Symbol,
}
#[derive(SessionDiagnostic)]
#[diag(mir_dataflow::requires_an_argument)]
pub(crate) struct RequiresAnArgument {
#[primary_span]
pub span: Span,
pub name: Symbol,
}
#[derive(SessionDiagnostic)]
#[diag(mir_dataflow::stop_after_dataflow_ended_compilation)]
pub(crate) struct StopAfterDataFlowEndedCompilation;
#[derive(SessionDiagnostic)]
#[diag(mir_dataflow::peek_must_be_place_or_ref_place)]
pub(crate) struct PeekMustBePlaceOrRefPlace {
#[primary_span]
pub span: Span,
}
#[derive(SessionDiagnostic)]
#[diag(mir_dataflow::peek_must_be_not_temporary)]
pub(crate) struct PeekMustBeNotTemporary {
#[primary_span]
pub span: Span,
}
#[derive(SessionDiagnostic)]
#[diag(mir_dataflow::peek_bit_not_set)]
pub(crate) struct PeekBitNotSet {
#[primary_span]
pub span: Span,
}
#[derive(SessionDiagnostic)]
#[diag(mir_dataflow::peek_argument_not_a_local)]
pub(crate) struct PeekArgumentNotALocal {
#[primary_span]
pub span: Span,
}
#[derive(SessionDiagnostic)]
#[diag(mir_dataflow::peek_argument_untracked)]
pub(crate) struct PeekArgumentUntracked {
#[primary_span]
pub span: Span,
}

View File

@ -1,5 +1,8 @@
//! A solver for dataflow problems.
use crate::errors::{
DuplicateValuesFor, PathMustEndInFilename, RequiresAnArgument, UnknownFormatter,
};
use crate::framework::BitSetExt;
use std::ffi::OsString;
@ -347,7 +350,7 @@ impl RustcMirAttrs {
match path.file_name() {
Some(_) => Ok(path),
None => {
tcx.sess.span_err(attr.span(), "path must end in a filename");
tcx.sess.emit_err(PathMustEndInFilename { span: attr.span() });
Err(())
}
}
@ -356,7 +359,7 @@ impl RustcMirAttrs {
Self::set_field(&mut ret.formatter, tcx, &attr, |s| match s {
sym::gen_kill | sym::two_phase => Ok(s),
_ => {
tcx.sess.span_err(attr.span(), "unknown formatter");
tcx.sess.emit_err(UnknownFormatter { span: attr.span() });
Err(())
}
})
@ -377,8 +380,7 @@ impl RustcMirAttrs {
mapper: impl FnOnce(Symbol) -> Result<T, ()>,
) -> Result<(), ()> {
if field.is_some() {
tcx.sess
.span_err(attr.span(), &format!("duplicate values for `{}`", attr.name_or_empty()));
tcx.sess.emit_err(DuplicateValuesFor { span: attr.span(), name: attr.name_or_empty() });
return Err(());
}
@ -387,8 +389,7 @@ impl RustcMirAttrs {
*field = Some(mapper(s)?);
Ok(())
} else {
tcx.sess
.span_err(attr.span(), &format!("`{}` requires an argument", attr.name_or_empty()));
tcx.sess.emit_err(RequiresAnArgument { span: attr.span(), name: attr.name_or_empty() });
Err(())
}
}

View File

@ -7,6 +7,8 @@
#![feature(stmt_expr_attributes)]
#![feature(trusted_step)]
#![recursion_limit = "256"]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
#[macro_use]
extern crate tracing;
@ -33,6 +35,7 @@ use self::move_paths::MoveData;
pub mod drop_flag_effects;
pub mod elaborate_drops;
mod errors;
mod framework;
pub mod impls;
pub mod move_paths;

View File

@ -6,6 +6,10 @@ use rustc_middle::mir::MirPass;
use rustc_middle::mir::{self, Body, Local, Location};
use rustc_middle::ty::{self, Ty, TyCtxt};
use crate::errors::{
PeekArgumentNotALocal, PeekArgumentUntracked, PeekBitNotSet, PeekMustBeNotTemporary,
PeekMustBePlaceOrRefPlace, StopAfterDataFlowEndedCompilation,
};
use crate::framework::BitSetExt;
use crate::impls::{
DefinitelyInitializedPlaces, MaybeInitializedPlaces, MaybeLiveLocals, MaybeUninitializedPlaces,
@ -64,7 +68,7 @@ impl<'tcx> MirPass<'tcx> for SanityCheck {
}
if has_rustc_mir_with(tcx, def_id, sym::stop_after_dataflow).is_some() {
tcx.sess.fatal("stop_after_dataflow ended compilation");
tcx.sess.emit_fatal(StopAfterDataFlowEndedCompilation);
}
}
}
@ -133,9 +137,7 @@ pub fn sanity_check_via_rustc_peek<'tcx, A>(
}
_ => {
let msg = "rustc_peek: argument expression \
must be either `place` or `&place`";
tcx.sess.span_err(call.span, msg);
tcx.sess.emit_err(PeekMustBePlaceOrRefPlace { span: call.span });
}
}
}
@ -204,18 +206,12 @@ impl PeekCall {
if let Some(local) = place.as_local() {
local
} else {
tcx.sess.diagnostic().span_err(
span,
"dataflow::sanity_check cannot feed a non-temp to rustc_peek.",
);
tcx.sess.emit_err(PeekMustBeNotTemporary { span });
return None;
}
}
_ => {
tcx.sess.diagnostic().span_err(
span,
"dataflow::sanity_check cannot feed a non-temp to rustc_peek.",
);
tcx.sess.emit_err(PeekMustBeNotTemporary { span });
return None;
}
};
@ -255,12 +251,12 @@ where
let bit_state = flow_state.contains(peek_mpi);
debug!("rustc_peek({:?} = &{:?}) bit_state: {}", call.arg, place, bit_state);
if !bit_state {
tcx.sess.span_err(call.span, "rustc_peek: bit not set");
tcx.sess.emit_err(PeekBitNotSet { span: call.span });
}
}
LookupResult::Parent(..) => {
tcx.sess.span_err(call.span, "rustc_peek: argument untracked");
tcx.sess.emit_err(PeekArgumentUntracked { span: call.span });
}
}
}
@ -276,12 +272,12 @@ impl<'tcx> RustcPeekAt<'tcx> for MaybeLiveLocals {
) {
info!(?place, "peek_at");
let Some(local) = place.as_local() else {
tcx.sess.span_err(call.span, "rustc_peek: argument was not a local");
tcx.sess.emit_err(PeekArgumentNotALocal { span: call.span });
return;
};
if !flow_state.contains(local) {
tcx.sess.span_err(call.span, "rustc_peek: bit not set");
tcx.sess.emit_err(PeekBitNotSet { span: call.span });
}
}
}

View File

@ -250,13 +250,30 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
.map_or_else(String::new, |res| format!("{} ", res.descr()));
(mod_prefix, format!("`{}`", Segment::names_to_string(mod_path)), None)
};
let (fallback_label, suggestion) = if path_str == "async"
&& expected.starts_with("struct")
{
("`async` blocks are only allowed in Rust 2018 or later".to_string(), suggestion)
} else {
// check if we are in situation of typo like `True` instead of `true`.
let override_suggestion =
if ["true", "false"].contains(&item_str.to_string().to_lowercase().as_str()) {
let item_typo = item_str.to_string().to_lowercase();
Some((
item_span,
"you may want to use a bool value instead",
format!("{}", item_typo),
))
} else {
suggestion
};
(format!("not found in {mod_str}"), override_suggestion)
};
BaseError {
msg: format!("cannot find {expected} `{item_str}` in {mod_prefix}{mod_str}"),
fallback_label: if path_str == "async" && expected.starts_with("struct") {
"`async` blocks are only allowed in Rust 2018 or later".to_string()
} else {
format!("not found in {mod_str}")
},
fallback_label,
span: item_span,
span_label: None,
could_be_expr: false,

View File

@ -20,8 +20,8 @@ use rustc_errors::emitter::{Emitter, EmitterWriter, HumanReadableErrorType};
use rustc_errors::json::JsonEmitter;
use rustc_errors::registry::Registry;
use rustc_errors::{
fallback_fluent_bundle, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, EmissionGuarantee,
ErrorGuaranteed, FluentBundle, LazyFallbackBundle, MultiSpan,
error_code, fallback_fluent_bundle, DiagnosticBuilder, DiagnosticId, DiagnosticMessage,
EmissionGuarantee, ErrorGuaranteed, FluentBundle, LazyFallbackBundle, MultiSpan,
};
use rustc_macros::HashStable_Generic;
pub use rustc_span::def_id::StableCrateId;
@ -467,6 +467,9 @@ impl Session {
feature: Symbol,
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
let mut err = self.parse_sess.create_err(err);
if err.code.is_none() {
err.code = std::option::Option::Some(error_code!(E0658));
}
add_feature_diagnostics(&mut err, &self.parse_sess, feature);
err
}

View File

@ -10,6 +10,7 @@ rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_hir = { path = "../rustc_hir" }
rustc_infer = { path = "../rustc_infer" }
rustc_macros = { path = "../rustc_macros" }
rustc_span = { path = "../rustc_span" }
rustc_session = { path = "../rustc_session" }
rustc_target = { path = "../rustc_target" }

View File

@ -11,6 +11,8 @@ use rustc_target::abi::VariantIdx;
use std::iter;
use crate::errors::{GenericConstantTooComplex, GenericConstantTooComplexSub};
/// Destructures array, ADT or tuple constants into the constants
/// of their fields.
pub(crate) fn destructure_const<'tcx>(
@ -93,26 +95,25 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
self.body.exprs[self.body_id].span
}
fn error(&mut self, span: Span, msg: &str) -> Result<!, ErrorGuaranteed> {
let reported = self
.tcx
.sess
.struct_span_err(self.root_span(), "overly complex generic constant")
.span_label(span, msg)
.help("consider moving this anonymous constant into a `const` function")
.emit();
fn error(&mut self, sub: GenericConstantTooComplexSub) -> Result<!, ErrorGuaranteed> {
let reported = self.tcx.sess.emit_err(GenericConstantTooComplex {
span: self.root_span(),
maybe_supported: None,
sub,
});
Err(reported)
}
fn maybe_supported_error(&mut self, span: Span, msg: &str) -> Result<!, ErrorGuaranteed> {
let reported = self
.tcx
.sess
.struct_span_err(self.root_span(), "overly complex generic constant")
.span_label(span, msg)
.help("consider moving this anonymous constant into a `const` function")
.note("this operation may be supported in the future")
.emit();
fn maybe_supported_error(
&mut self,
sub: GenericConstantTooComplexSub,
) -> Result<!, ErrorGuaranteed> {
let reported = self.tcx.sess.emit_err(GenericConstantTooComplex {
span: self.root_span(),
maybe_supported: Some(()),
sub,
});
Err(reported)
}
@ -243,22 +244,23 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
&ExprKind::Scope { value, .. } => self.recurse_build(value)?,
&ExprKind::PlaceTypeAscription { source, .. }
| &ExprKind::ValueTypeAscription { source, .. } => self.recurse_build(source)?,
&ExprKind::Literal { lit, neg} => {
&ExprKind::Literal { lit, neg } => {
let sp = node.span;
let constant =
match self.tcx.at(sp).lit_to_const(LitToConstInput { lit: &lit.node, ty: node.ty, neg }) {
Ok(c) => c,
Err(LitToConstError::Reported) => {
self.tcx.const_error(node.ty)
}
Err(LitToConstError::TypeError) => {
bug!("encountered type error in lit_to_const")
}
};
let constant = match self.tcx.at(sp).lit_to_const(LitToConstInput {
lit: &lit.node,
ty: node.ty,
neg,
}) {
Ok(c) => c,
Err(LitToConstError::Reported) => self.tcx.const_error(node.ty),
Err(LitToConstError::TypeError) => {
bug!("encountered type error in lit_to_const")
}
};
self.nodes.push(Node::Leaf(constant))
}
&ExprKind::NonHirLiteral { lit , user_ty: _} => {
&ExprKind::NonHirLiteral { lit, user_ty: _ } => {
let val = ty::ValTree::from_scalar_int(lit);
self.nodes.push(Node::Leaf(ty::Const::from_value(self.tcx, val, node.ty)))
}
@ -269,19 +271,17 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
&ExprKind::NamedConst { def_id, substs, user_ty: _ } => {
let uneval = ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs);
let constant = self.tcx.mk_const(ty::ConstS {
kind: ty::ConstKind::Unevaluated(uneval),
ty: node.ty,
});
let constant = self
.tcx
.mk_const(ty::ConstS { kind: ty::ConstKind::Unevaluated(uneval), ty: node.ty });
self.nodes.push(Node::Leaf(constant))
}
ExprKind::ConstParam {param, ..} => {
let const_param = self.tcx.mk_const(ty::ConstS {
kind: ty::ConstKind::Param(*param),
ty: node.ty,
});
ExprKind::ConstParam { param, .. } => {
let const_param = self
.tcx
.mk_const(ty::ConstS { kind: ty::ConstKind::Param(*param), ty: node.ty });
self.nodes.push(Node::Leaf(const_param))
}
@ -312,13 +312,13 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
// }
// ```
ExprKind::Block { block } => {
if let thir::Block { stmts: box [], expr: Some(e), .. } = &self.body.blocks[*block] {
if let thir::Block { stmts: box [], expr: Some(e), .. } = &self.body.blocks[*block]
{
self.recurse_build(*e)?
} else {
self.maybe_supported_error(
self.maybe_supported_error(GenericConstantTooComplexSub::BlockNotSupported(
node.span,
"blocks are not supported in generic constant",
)?
))?
}
}
// `ExprKind::Use` happens when a `hir::ExprKind::Cast` is a
@ -332,7 +332,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
let arg = self.recurse_build(source)?;
self.nodes.push(Node::Cast(CastKind::As, arg, node.ty))
}
ExprKind::Borrow{ arg, ..} => {
ExprKind::Borrow { arg, .. } => {
let arg_node = &self.body.exprs[*arg];
// Skip reborrows for now until we allow Deref/Borrow/AddressOf
@ -341,76 +341,69 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
if let ExprKind::Deref { arg } = arg_node.kind {
self.recurse_build(arg)?
} else {
self.maybe_supported_error(
self.maybe_supported_error(GenericConstantTooComplexSub::BorrowNotSupported(
node.span,
"borrowing is not supported in generic constants",
)?
))?
}
}
// FIXME(generic_const_exprs): We may want to support these.
ExprKind::AddressOf { .. } | ExprKind::Deref {..}=> self.maybe_supported_error(
node.span,
"dereferencing or taking the address is not supported in generic constants",
ExprKind::AddressOf { .. } | ExprKind::Deref { .. } => self.maybe_supported_error(
GenericConstantTooComplexSub::AddressAndDerefNotSupported(node.span),
)?,
ExprKind::Repeat { .. } | ExprKind::Array { .. } => self.maybe_supported_error(
node.span,
"array construction is not supported in generic constants",
ExprKind::Repeat { .. } | ExprKind::Array { .. } => self.maybe_supported_error(
GenericConstantTooComplexSub::ArrayNotSupported(node.span),
)?,
ExprKind::NeverToAny { .. } => self.maybe_supported_error(
node.span,
"converting nevers to any is not supported in generic constant",
GenericConstantTooComplexSub::NeverToAnyNotSupported(node.span),
)?,
ExprKind::Tuple { .. } => self.maybe_supported_error(
node.span,
"tuple construction is not supported in generic constants",
GenericConstantTooComplexSub::TupleNotSupported(node.span),
)?,
ExprKind::Index { .. } => self.maybe_supported_error(
node.span,
"indexing is not supported in generic constant",
GenericConstantTooComplexSub::IndexNotSupported(node.span),
)?,
ExprKind::Field { .. } => self.maybe_supported_error(
node.span,
"field access is not supported in generic constant",
GenericConstantTooComplexSub::FieldNotSupported(node.span),
)?,
ExprKind::ConstBlock { .. } => self.maybe_supported_error(
node.span,
"const blocks are not supported in generic constant",
)?,
ExprKind::Adt(_) => self.maybe_supported_error(
node.span,
"struct/enum construction is not supported in generic constants",
GenericConstantTooComplexSub::ConstBlockNotSupported(node.span),
)?,
ExprKind::Adt(_) => self
.maybe_supported_error(GenericConstantTooComplexSub::AdtNotSupported(node.span))?,
// dont know if this is correct
ExprKind::Pointer { .. } =>
self.error(node.span, "pointer casts are not allowed in generic constants")?,
ExprKind::Yield { .. } =>
self.error(node.span, "generator control flow is not allowed in generic constants")?,
ExprKind::Continue { .. } | ExprKind::Break { .. } | ExprKind::Loop { .. } => self
.error(
node.span,
"loops and loop control flow are not supported in generic constants",
)?,
ExprKind::Box { .. } =>
self.error(node.span, "allocations are not allowed in generic constants")?,
ExprKind::Pointer { .. } => {
self.error(GenericConstantTooComplexSub::PointerNotSupported(node.span))?
}
ExprKind::Yield { .. } => {
self.error(GenericConstantTooComplexSub::YieldNotSupported(node.span))?
}
ExprKind::Continue { .. } | ExprKind::Break { .. } | ExprKind::Loop { .. } => {
self.error(GenericConstantTooComplexSub::LoopNotSupported(node.span))?
}
ExprKind::Box { .. } => {
self.error(GenericConstantTooComplexSub::BoxNotSupported(node.span))?
}
ExprKind::Unary { .. } => unreachable!(),
// we handle valid unary/binary ops above
ExprKind::Binary { .. } =>
self.error(node.span, "unsupported binary operation in generic constants")?,
ExprKind::LogicalOp { .. } =>
self.error(node.span, "unsupported operation in generic constants, short-circuiting operations would imply control flow")?,
ExprKind::Assign { .. } | ExprKind::AssignOp { .. } => {
self.error(node.span, "assignment is not supported in generic constants")?
ExprKind::Binary { .. } => {
self.error(GenericConstantTooComplexSub::BinaryNotSupported(node.span))?
}
ExprKind::LogicalOp { .. } => {
self.error(GenericConstantTooComplexSub::LogicalOpNotSupported(node.span))?
}
ExprKind::Assign { .. } | ExprKind::AssignOp { .. } => {
self.error(GenericConstantTooComplexSub::AssignNotSupported(node.span))?
}
ExprKind::Closure { .. } | ExprKind::Return { .. } => {
self.error(GenericConstantTooComplexSub::ClosureAndReturnNotSupported(node.span))?
}
ExprKind::Closure { .. } | ExprKind::Return { .. } => self.error(
node.span,
"closures and function keywords are not supported in generic constants",
)?,
// let expressions imply control flow
ExprKind::Match { .. } | ExprKind::If { .. } | ExprKind::Let { .. } =>
self.error(node.span, "control flow is not supported in generic constants")?,
ExprKind::Match { .. } | ExprKind::If { .. } | ExprKind::Let { .. } => {
self.error(GenericConstantTooComplexSub::ControlFlowNotSupported(node.span))?
}
ExprKind::InlineAsm { .. } => {
self.error(node.span, "assembly is not supported in generic constants")?
self.error(GenericConstantTooComplexSub::InlineAsmNotSupported(node.span))?
}
// we dont permit let stmts so `VarRef` and `UpvarRef` cant happen
@ -418,7 +411,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
| ExprKind::UpvarRef { .. }
| ExprKind::StaticRef { .. }
| ExprKind::ThreadLocalRef(_) => {
self.error(node.span, "unsupported operation in generic constant")?
self.error(GenericConstantTooComplexSub::OperationNotSupported(node.span))?
}
})
}

View File

@ -0,0 +1,69 @@
//! Errors emitted by ty_utils
use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
use rustc_middle::ty::Ty;
use rustc_span::Span;
#[derive(SessionDiagnostic)]
#[diag(ty_utils::needs_drop_overflow)]
pub struct NeedsDropOverflow<'tcx> {
pub query_ty: Ty<'tcx>,
}
#[derive(SessionDiagnostic)]
#[diag(ty_utils::generic_constant_too_complex)]
#[help]
pub struct GenericConstantTooComplex {
#[primary_span]
pub span: Span,
#[note(ty_utils::maybe_supported)]
pub maybe_supported: Option<()>,
#[subdiagnostic]
pub sub: GenericConstantTooComplexSub,
}
#[derive(SessionSubdiagnostic)]
pub enum GenericConstantTooComplexSub {
#[label(ty_utils::borrow_not_supported)]
BorrowNotSupported(#[primary_span] Span),
#[label(ty_utils::address_and_deref_not_supported)]
AddressAndDerefNotSupported(#[primary_span] Span),
#[label(ty_utils::array_not_supported)]
ArrayNotSupported(#[primary_span] Span),
#[label(ty_utils::block_not_supported)]
BlockNotSupported(#[primary_span] Span),
#[label(ty_utils::never_to_any_not_supported)]
NeverToAnyNotSupported(#[primary_span] Span),
#[label(ty_utils::tuple_not_supported)]
TupleNotSupported(#[primary_span] Span),
#[label(ty_utils::index_not_supported)]
IndexNotSupported(#[primary_span] Span),
#[label(ty_utils::field_not_supported)]
FieldNotSupported(#[primary_span] Span),
#[label(ty_utils::const_block_not_supported)]
ConstBlockNotSupported(#[primary_span] Span),
#[label(ty_utils::adt_not_supported)]
AdtNotSupported(#[primary_span] Span),
#[label(ty_utils::pointer_not_supported)]
PointerNotSupported(#[primary_span] Span),
#[label(ty_utils::yield_not_supported)]
YieldNotSupported(#[primary_span] Span),
#[label(ty_utils::loop_not_supported)]
LoopNotSupported(#[primary_span] Span),
#[label(ty_utils::box_not_supported)]
BoxNotSupported(#[primary_span] Span),
#[label(ty_utils::binary_not_supported)]
BinaryNotSupported(#[primary_span] Span),
#[label(ty_utils::logical_op_not_supported)]
LogicalOpNotSupported(#[primary_span] Span),
#[label(ty_utils::assign_not_supported)]
AssignNotSupported(#[primary_span] Span),
#[label(ty_utils::closure_and_return_not_supported)]
ClosureAndReturnNotSupported(#[primary_span] Span),
#[label(ty_utils::control_flow_not_supported)]
ControlFlowNotSupported(#[primary_span] Span),
#[label(ty_utils::inline_asm_not_supported)]
InlineAsmNotSupported(#[primary_span] Span),
#[label(ty_utils::operation_not_supported)]
OperationNotSupported(#[primary_span] Span),
}

View File

@ -10,6 +10,8 @@
#![feature(never_type)]
#![feature(box_patterns)]
#![recursion_limit = "256"]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
#[macro_use]
extern crate rustc_middle;
@ -21,6 +23,7 @@ use rustc_middle::ty::query::Providers;
mod assoc;
mod common_traits;
mod consts;
mod errors;
mod implied_bounds;
pub mod instance;
mod needs_drop;

View File

@ -9,6 +9,8 @@ use rustc_middle::ty::{self, EarlyBinder, Ty, TyCtxt};
use rustc_session::Limit;
use rustc_span::{sym, DUMMY_SP};
use crate::errors::NeedsDropOverflow;
type NeedsDropResult<T> = Result<T, AlwaysRequiresDrop>;
fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
@ -90,10 +92,7 @@ where
if !self.recursion_limit.value_within_limit(level) {
// Not having a `Span` isn't great. But there's hopefully some other
// recursion limit error as well.
tcx.sess.span_err(
DUMMY_SP,
&format!("overflow while checking whether `{}` requires drop", self.query_ty),
);
tcx.sess.emit_err(NeedsDropOverflow { query_ty: self.query_ty });
return Some(Err(AlwaysRequiresDrop));
}

View File

@ -0,0 +1,12 @@
// Suggest the boolean value instead of emit a generic error that the value
// True is not in the scope.
fn main() {
let x = True;
//~^ ERROR cannot find value `True` in this scope
//~| HELP you may want to use a bool value instead
let y = False;
//~^ ERROR cannot find value `False` in this scope
//~| HELP you may want to use a bool value instead
}

View File

@ -0,0 +1,25 @@
error[E0425]: cannot find value `True` in this scope
--> $DIR/bool_typo_err_suggest.rs:5:13
|
LL | let x = True;
| ^^^^ not found in this scope
|
help: you may want to use a bool value instead
|
LL | let x = true;
| ~~~~
error[E0425]: cannot find value `False` in this scope
--> $DIR/bool_typo_err_suggest.rs:9:13
|
LL | let y = False;
| ^^^^^ not found in this scope
|
help: you may want to use a bool value instead
|
LL | let y = false;
| ~~~~~
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0425`.