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:
commit
bb8a08f011
@ -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",
|
||||
|
@ -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" }
|
||||
|
@ -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 {
|
||||
|
329
compiler/rustc_ast_lowering/src/errors.rs
Normal file
329
compiler/rustc_ast_lowering/src/errors.rs
Normal 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,
|
||||
}
|
@ -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),
|
||||
}
|
||||
|
@ -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() });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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(),
|
||||
|
@ -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
|
||||
})
|
||||
|
@ -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::*;
|
||||
|
397
compiler/rustc_attr/src/session_diagnostics.rs
Normal file
397
compiler/rustc_attr/src/session_diagnostics.rs
Normal 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,
|
||||
}
|
@ -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",
|
||||
|
@ -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();
|
||||
|
@ -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())
|
||||
}
|
||||
|
@ -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,
|
||||
},
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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" }
|
||||
|
@ -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 {
|
||||
|
33
compiler/rustc_driver/src/session_diagnostics.rs
Normal file
33
compiler/rustc_driver/src/session_diagnostics.rs
Normal 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;
|
131
compiler/rustc_error_messages/locales/en-US/ast_lowering.ftl
Normal file
131
compiler/rustc_error_messages/locales/en-US/ast_lowering.ftl
Normal 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
|
107
compiler/rustc_error_messages/locales/en-US/attr.ftl
Normal file
107
compiler/rustc_error_messages/locales/en-US/attr.ftl
Normal 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
|
@ -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
|
||||
|
@ -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
|
||||
|
11
compiler/rustc_error_messages/locales/en-US/driver.ftl
Normal file
11
compiler/rustc_error_messages/locales/en-US/driver.ftl
Normal 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
|
@ -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}
|
||||
|
29
compiler/rustc_error_messages/locales/en-US/mir_dataflow.ftl
Normal file
29
compiler/rustc_error_messages/locales/en-US/mir_dataflow.ftl
Normal 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
|
47
compiler/rustc_error_messages/locales/en-US/ty_utils.ftl
Normal file
47
compiler/rustc_error_messages/locales/en-US/ty_utils.ftl
Normal 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
|
@ -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};
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
|
162
compiler/rustc_lint/src/errors.rs
Normal file
162
compiler/rustc_lint/src/errors.rs
Normal 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,
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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" }
|
||||
|
71
compiler/rustc_mir_dataflow/src/errors.rs
Normal file
71
compiler/rustc_mir_dataflow/src/errors.rs
Normal 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,
|
||||
}
|
@ -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(())
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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" }
|
||||
|
@ -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))?
|
||||
}
|
||||
})
|
||||
}
|
||||
|
69
compiler/rustc_ty_utils/src/errors.rs
Normal file
69
compiler/rustc_ty_utils/src/errors.rs
Normal 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),
|
||||
}
|
@ -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;
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
12
src/test/ui/suggestions/bool_typo_err_suggest.rs
Normal file
12
src/test/ui/suggestions/bool_typo_err_suggest.rs
Normal 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
|
||||
}
|
25
src/test/ui/suggestions/bool_typo_err_suggest.stderr
Normal file
25
src/test/ui/suggestions/bool_typo_err_suggest.stderr
Normal 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`.
|
Loading…
x
Reference in New Issue
Block a user