mirror of https://github.com/rust-lang/rust.git
Auto merge of #119621 - compiler-errors:rollup-5mxtvuk, r=compiler-errors
Rollup of 10 pull requests Successful merges: - #119034 (Allow coverage tests to ignore test modes, and to enable color in coverage reports) - #119148 (Tweak suggestions for bare trait used as a type) - #119538 (Cleanup error handlers: round 5) - #119566 (Remove `-Zdump-mir-spanview`) - #119567 (Remove `-Zreport-delayed-bugs`.) - #119577 (Migrate memory overlap check from validator to lint) - #119583 (Make `intrinsics::assume` const stable) - #119586 ([rustdoc] Fix invalid handling for static method calls in jump to definition feature) - #119588 (Move `i586-unknown-netbsd` from tier 2 to tier 3 platform support table) - #119601 (`Emitter` cleanups) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
11035f9f52
|
@ -725,8 +725,8 @@ impl AddToDiagnostic for StableFeature {
|
|||
rustc_errors::SubdiagnosticMessage,
|
||||
) -> rustc_errors::SubdiagnosticMessage,
|
||||
{
|
||||
diag.set_arg("name", self.name);
|
||||
diag.set_arg("since", self.since);
|
||||
diag.arg("name", self.name);
|
||||
diag.arg("since", self.since);
|
||||
diag.help(fluent::ast_passes_stable_since);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,10 +55,10 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for UnknownMetaItem<'_> {
|
|||
fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> {
|
||||
let expected = self.expected.iter().map(|name| format!("`{name}`")).collect::<Vec<_>>();
|
||||
let mut diag = DiagnosticBuilder::new(dcx, level, fluent::attr_unknown_meta_item);
|
||||
diag.set_span(self.span);
|
||||
diag.span(self.span);
|
||||
diag.code(error_code!(E0541));
|
||||
diag.set_arg("item", self.item);
|
||||
diag.set_arg("expected", expected.join(", "));
|
||||
diag.arg("item", self.item);
|
||||
diag.arg("expected", expected.join(", "));
|
||||
diag.span_label(self.span, fluent::attr_label);
|
||||
diag
|
||||
}
|
||||
|
@ -215,7 +215,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for UnsupportedLiteral {
|
|||
}
|
||||
},
|
||||
);
|
||||
diag.set_span(self.span);
|
||||
diag.span(self.span);
|
||||
diag.code(error_code!(E0565));
|
||||
if self.is_bytestr {
|
||||
diag.span_suggestion(
|
||||
|
|
|
@ -454,7 +454,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for EnvNotDefinedWithUserMe
|
|||
reason = "cannot translate user-provided messages"
|
||||
)]
|
||||
let mut diag = DiagnosticBuilder::new(dcx, level, self.msg_from_user.to_string());
|
||||
diag.set_span(self.span);
|
||||
diag.span(self.span);
|
||||
diag
|
||||
}
|
||||
}
|
||||
|
@ -618,7 +618,7 @@ impl AddToDiagnostic for FormatUnusedArg {
|
|||
rustc_errors::SubdiagnosticMessage,
|
||||
) -> rustc_errors::SubdiagnosticMessage,
|
||||
{
|
||||
diag.set_arg("named", self.named);
|
||||
diag.arg("named", self.named);
|
||||
let msg = f(diag, crate::fluent_generated::builtin_macros_format_unused_arg.into());
|
||||
diag.span_label(self.span, msg);
|
||||
}
|
||||
|
@ -808,7 +808,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for AsmClobberNoReg {
|
|||
level,
|
||||
crate::fluent_generated::builtin_macros_asm_clobber_no_reg,
|
||||
);
|
||||
diag.set_span(self.spans.clone());
|
||||
diag.span(self.spans.clone());
|
||||
// eager translation as `span_labels` takes `AsRef<str>`
|
||||
let lbl1 = dcx.eagerly_translate_to_string(
|
||||
crate::fluent_generated::builtin_macros_asm_clobber_abi,
|
||||
|
|
|
@ -395,10 +395,10 @@ fn not_testable_error(cx: &ExtCtxt<'_>, attr_sp: Span, item: Option<&ast::Item>)
|
|||
// These were a warning before #92959 and need to continue being that to avoid breaking
|
||||
// stable user code (#94508).
|
||||
Some(ast::ItemKind::MacCall(_)) => Level::Warning(None),
|
||||
_ => Level::Error { lint: false },
|
||||
_ => Level::Error,
|
||||
};
|
||||
let mut err = DiagnosticBuilder::<()>::new(dcx, level, msg);
|
||||
err.set_span(attr_sp);
|
||||
err.span(attr_sp);
|
||||
if let Some(item) = item {
|
||||
err.span_label(
|
||||
item.span,
|
||||
|
|
|
@ -119,12 +119,12 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for TargetFeatureDisableOrEnabl
|
|||
fluent::codegen_gcc_target_feature_disable_or_enable
|
||||
);
|
||||
if let Some(span) = self.span {
|
||||
diag.set_span(span);
|
||||
diag.span(span);
|
||||
};
|
||||
if let Some(missing_features) = self.missing_features {
|
||||
diag.subdiagnostic(missing_features);
|
||||
}
|
||||
diag.set_arg("features", self.features.join(", "));
|
||||
diag.arg("features", self.features.join(", "));
|
||||
diag
|
||||
}
|
||||
}
|
||||
|
|
|
@ -416,7 +416,7 @@ fn report_inline_asm(
|
|||
cookie = 0;
|
||||
}
|
||||
let level = match level {
|
||||
llvm::DiagnosticLevel::Error => Level::Error { lint: false },
|
||||
llvm::DiagnosticLevel::Error => Level::Error,
|
||||
llvm::DiagnosticLevel::Warning => Level::Warning(None),
|
||||
llvm::DiagnosticLevel::Note | llvm::DiagnosticLevel::Remark => Level::Note,
|
||||
};
|
||||
|
|
|
@ -107,7 +107,7 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for ParseTargetMachineConfig<'_
|
|||
|
||||
let mut diag =
|
||||
DiagnosticBuilder::new(dcx, level, fluent::codegen_llvm_parse_target_machine_config);
|
||||
diag.set_arg("error", message);
|
||||
diag.arg("error", message);
|
||||
diag
|
||||
}
|
||||
}
|
||||
|
@ -130,12 +130,12 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for TargetFeatureDisableOrEnabl
|
|||
fluent::codegen_llvm_target_feature_disable_or_enable,
|
||||
);
|
||||
if let Some(span) = self.span {
|
||||
diag.set_span(span);
|
||||
diag.span(span);
|
||||
};
|
||||
if let Some(missing_features) = self.missing_features {
|
||||
diag.subdiagnostic(missing_features);
|
||||
}
|
||||
diag.set_arg("features", self.features.join(", "));
|
||||
diag.arg("features", self.features.join(", "));
|
||||
diag
|
||||
}
|
||||
}
|
||||
|
@ -205,8 +205,8 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for WithLlvmError<'_> {
|
|||
ParseBitcode => fluent::codegen_llvm_parse_bitcode_with_llvm_err,
|
||||
};
|
||||
let mut diag = self.0.into_diagnostic(dcx, level);
|
||||
diag.set_primary_message(msg_with_llvm_err);
|
||||
diag.set_arg("llvm_err", self.1);
|
||||
diag.primary_message(msg_with_llvm_err);
|
||||
diag.arg("llvm_err", self.1);
|
||||
diag
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1848,9 +1848,9 @@ impl SharedEmitterMain {
|
|||
}
|
||||
Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)) => {
|
||||
let err_level = match level {
|
||||
Level::Error { lint: false } => rustc_errors::Level::Error { lint: false },
|
||||
Level::Warning(_) => rustc_errors::Level::Warning(None),
|
||||
Level::Note => rustc_errors::Level::Note,
|
||||
Level::Error => Level::Error,
|
||||
Level::Warning(_) => Level::Warning(None),
|
||||
Level::Note => Level::Note,
|
||||
_ => bug!("Invalid inline asm diagnostic level"),
|
||||
};
|
||||
let msg = msg.strip_prefix("error: ").unwrap_or(&msg).to_string();
|
||||
|
@ -1860,7 +1860,7 @@ impl SharedEmitterMain {
|
|||
if cookie != 0 {
|
||||
let pos = BytePos::from_u32(cookie);
|
||||
let span = Span::with_root_ctxt(pos, pos);
|
||||
err.set_span(span);
|
||||
err.span(span);
|
||||
};
|
||||
|
||||
// Point to the generated assembly if it is available.
|
||||
|
|
|
@ -244,30 +244,30 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for ThorinErrorWrapper {
|
|||
}
|
||||
thorin::Error::NamelessSection(_, offset) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_section_without_name);
|
||||
diag.set_arg("offset", format!("0x{offset:08x}"));
|
||||
diag.arg("offset", format!("0x{offset:08x}"));
|
||||
diag
|
||||
}
|
||||
thorin::Error::RelocationWithInvalidSymbol(section, offset) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_relocation_with_invalid_symbol);
|
||||
diag.set_arg("section", section);
|
||||
diag.set_arg("offset", format!("0x{offset:08x}"));
|
||||
diag.arg("section", section);
|
||||
diag.arg("offset", format!("0x{offset:08x}"));
|
||||
diag
|
||||
}
|
||||
thorin::Error::MultipleRelocations(section, offset) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_multiple_relocations);
|
||||
diag.set_arg("section", section);
|
||||
diag.set_arg("offset", format!("0x{offset:08x}"));
|
||||
diag.arg("section", section);
|
||||
diag.arg("offset", format!("0x{offset:08x}"));
|
||||
diag
|
||||
}
|
||||
thorin::Error::UnsupportedRelocation(section, offset) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_unsupported_relocation);
|
||||
diag.set_arg("section", section);
|
||||
diag.set_arg("offset", format!("0x{offset:08x}"));
|
||||
diag.arg("section", section);
|
||||
diag.arg("offset", format!("0x{offset:08x}"));
|
||||
diag
|
||||
}
|
||||
thorin::Error::MissingDwoName(id) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_missing_dwo_name);
|
||||
diag.set_arg("id", format!("0x{id:08x}"));
|
||||
diag.arg("id", format!("0x{id:08x}"));
|
||||
diag
|
||||
}
|
||||
thorin::Error::NoCompilationUnits => {
|
||||
|
@ -284,7 +284,7 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for ThorinErrorWrapper {
|
|||
}
|
||||
thorin::Error::MissingRequiredSection(section) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_missing_required_section);
|
||||
diag.set_arg("section", section);
|
||||
diag.arg("section", section);
|
||||
diag
|
||||
}
|
||||
thorin::Error::ParseUnitAbbreviations(_) => {
|
||||
|
@ -305,34 +305,34 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for ThorinErrorWrapper {
|
|||
}
|
||||
thorin::Error::IncompatibleIndexVersion(section, format, actual) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_incompatible_index_version);
|
||||
diag.set_arg("section", section);
|
||||
diag.set_arg("actual", actual);
|
||||
diag.set_arg("format", format);
|
||||
diag.arg("section", section);
|
||||
diag.arg("actual", actual);
|
||||
diag.arg("format", format);
|
||||
diag
|
||||
}
|
||||
thorin::Error::OffsetAtIndex(_, index) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_offset_at_index);
|
||||
diag.set_arg("index", index);
|
||||
diag.arg("index", index);
|
||||
diag
|
||||
}
|
||||
thorin::Error::StrAtOffset(_, offset) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_str_at_offset);
|
||||
diag.set_arg("offset", format!("0x{offset:08x}"));
|
||||
diag.arg("offset", format!("0x{offset:08x}"));
|
||||
diag
|
||||
}
|
||||
thorin::Error::ParseIndex(_, section) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_parse_index);
|
||||
diag.set_arg("section", section);
|
||||
diag.arg("section", section);
|
||||
diag
|
||||
}
|
||||
thorin::Error::UnitNotInIndex(unit) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_unit_not_in_index);
|
||||
diag.set_arg("unit", format!("0x{unit:08x}"));
|
||||
diag.arg("unit", format!("0x{unit:08x}"));
|
||||
diag
|
||||
}
|
||||
thorin::Error::RowNotInIndex(_, row) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_row_not_in_index);
|
||||
diag.set_arg("row", row);
|
||||
diag.arg("row", row);
|
||||
diag
|
||||
}
|
||||
thorin::Error::SectionNotInRow => {
|
||||
|
@ -341,7 +341,7 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for ThorinErrorWrapper {
|
|||
}
|
||||
thorin::Error::EmptyUnit(unit) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_empty_unit);
|
||||
diag.set_arg("unit", format!("0x{unit:08x}"));
|
||||
diag.arg("unit", format!("0x{unit:08x}"));
|
||||
diag
|
||||
}
|
||||
thorin::Error::MultipleDebugInfoSection => {
|
||||
|
@ -358,12 +358,12 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for ThorinErrorWrapper {
|
|||
}
|
||||
thorin::Error::DuplicateUnit(unit) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_duplicate_unit);
|
||||
diag.set_arg("unit", format!("0x{unit:08x}"));
|
||||
diag.arg("unit", format!("0x{unit:08x}"));
|
||||
diag
|
||||
}
|
||||
thorin::Error::MissingReferencedUnit(unit) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_missing_referenced_unit);
|
||||
diag.set_arg("unit", format!("0x{unit:08x}"));
|
||||
diag.arg("unit", format!("0x{unit:08x}"));
|
||||
diag
|
||||
}
|
||||
thorin::Error::NoOutputObjectCreated => {
|
||||
|
@ -376,27 +376,27 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for ThorinErrorWrapper {
|
|||
}
|
||||
thorin::Error::Io(e) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_io);
|
||||
diag.set_arg("error", format!("{e}"));
|
||||
diag.arg("error", format!("{e}"));
|
||||
diag
|
||||
}
|
||||
thorin::Error::ObjectRead(e) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_object_read);
|
||||
diag.set_arg("error", format!("{e}"));
|
||||
diag.arg("error", format!("{e}"));
|
||||
diag
|
||||
}
|
||||
thorin::Error::ObjectWrite(e) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_object_write);
|
||||
diag.set_arg("error", format!("{e}"));
|
||||
diag.arg("error", format!("{e}"));
|
||||
diag
|
||||
}
|
||||
thorin::Error::GimliRead(e) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_gimli_read);
|
||||
diag.set_arg("error", format!("{e}"));
|
||||
diag.arg("error", format!("{e}"));
|
||||
diag
|
||||
}
|
||||
thorin::Error::GimliWrite(e) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_gimli_write);
|
||||
diag.set_arg("error", format!("{e}"));
|
||||
diag.arg("error", format!("{e}"));
|
||||
diag
|
||||
}
|
||||
_ => unimplemented!("Untranslated thorin error"),
|
||||
|
@ -414,8 +414,8 @@ pub struct LinkingFailed<'a> {
|
|||
impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for LinkingFailed<'_> {
|
||||
fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> {
|
||||
let mut diag = DiagnosticBuilder::new(dcx, level, fluent::codegen_ssa_linking_failed);
|
||||
diag.set_arg("linker_path", format!("{}", self.linker_path.display()));
|
||||
diag.set_arg("exit_status", format!("{}", self.exit_status));
|
||||
diag.arg("linker_path", format!("{}", self.linker_path.display()));
|
||||
diag.arg("exit_status", format!("{}", self.exit_status));
|
||||
|
||||
let contains_undefined_ref = self.escaped_output.contains("undefined reference to");
|
||||
|
||||
|
|
|
@ -518,7 +518,7 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
|
|||
Ub(_) => {}
|
||||
Custom(custom) => {
|
||||
(custom.add_args)(&mut |name, value| {
|
||||
builder.set_arg(name, value);
|
||||
builder.arg(name, value);
|
||||
});
|
||||
}
|
||||
ValidationError(e) => e.add_args(dcx, builder),
|
||||
|
@ -536,65 +536,65 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
|
|||
| UninhabitedEnumVariantWritten(_)
|
||||
| UninhabitedEnumVariantRead(_) => {}
|
||||
BoundsCheckFailed { len, index } => {
|
||||
builder.set_arg("len", len);
|
||||
builder.set_arg("index", index);
|
||||
builder.arg("len", len);
|
||||
builder.arg("index", index);
|
||||
}
|
||||
UnterminatedCString(ptr) | InvalidFunctionPointer(ptr) | InvalidVTablePointer(ptr) => {
|
||||
builder.set_arg("pointer", ptr);
|
||||
builder.arg("pointer", ptr);
|
||||
}
|
||||
PointerUseAfterFree(alloc_id, msg) => {
|
||||
builder
|
||||
.set_arg("alloc_id", alloc_id)
|
||||
.set_arg("bad_pointer_message", bad_pointer_message(msg, dcx));
|
||||
.arg("alloc_id", alloc_id)
|
||||
.arg("bad_pointer_message", bad_pointer_message(msg, dcx));
|
||||
}
|
||||
PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, ptr_size, msg } => {
|
||||
builder
|
||||
.set_arg("alloc_id", alloc_id)
|
||||
.set_arg("alloc_size", alloc_size.bytes())
|
||||
.set_arg("ptr_offset", ptr_offset)
|
||||
.set_arg("ptr_size", ptr_size.bytes())
|
||||
.set_arg("bad_pointer_message", bad_pointer_message(msg, dcx));
|
||||
.arg("alloc_id", alloc_id)
|
||||
.arg("alloc_size", alloc_size.bytes())
|
||||
.arg("ptr_offset", ptr_offset)
|
||||
.arg("ptr_size", ptr_size.bytes())
|
||||
.arg("bad_pointer_message", bad_pointer_message(msg, dcx));
|
||||
}
|
||||
DanglingIntPointer(ptr, msg) => {
|
||||
if ptr != 0 {
|
||||
builder.set_arg("pointer", format!("{ptr:#x}[noalloc]"));
|
||||
builder.arg("pointer", format!("{ptr:#x}[noalloc]"));
|
||||
}
|
||||
|
||||
builder.set_arg("bad_pointer_message", bad_pointer_message(msg, dcx));
|
||||
builder.arg("bad_pointer_message", bad_pointer_message(msg, dcx));
|
||||
}
|
||||
AlignmentCheckFailed(Misalignment { required, has }, msg) => {
|
||||
builder.set_arg("required", required.bytes());
|
||||
builder.set_arg("has", has.bytes());
|
||||
builder.set_arg("msg", format!("{msg:?}"));
|
||||
builder.arg("required", required.bytes());
|
||||
builder.arg("has", has.bytes());
|
||||
builder.arg("msg", format!("{msg:?}"));
|
||||
}
|
||||
WriteToReadOnly(alloc) | DerefFunctionPointer(alloc) | DerefVTablePointer(alloc) => {
|
||||
builder.set_arg("allocation", alloc);
|
||||
builder.arg("allocation", alloc);
|
||||
}
|
||||
InvalidBool(b) => {
|
||||
builder.set_arg("value", format!("{b:02x}"));
|
||||
builder.arg("value", format!("{b:02x}"));
|
||||
}
|
||||
InvalidChar(c) => {
|
||||
builder.set_arg("value", format!("{c:08x}"));
|
||||
builder.arg("value", format!("{c:08x}"));
|
||||
}
|
||||
InvalidTag(tag) => {
|
||||
builder.set_arg("tag", format!("{tag:x}"));
|
||||
builder.arg("tag", format!("{tag:x}"));
|
||||
}
|
||||
InvalidStr(err) => {
|
||||
builder.set_arg("err", format!("{err}"));
|
||||
builder.arg("err", format!("{err}"));
|
||||
}
|
||||
InvalidUninitBytes(Some((alloc, info))) => {
|
||||
builder.set_arg("alloc", alloc);
|
||||
builder.set_arg("access", info.access);
|
||||
builder.set_arg("uninit", info.bad);
|
||||
builder.arg("alloc", alloc);
|
||||
builder.arg("access", info.access);
|
||||
builder.arg("uninit", info.bad);
|
||||
}
|
||||
ScalarSizeMismatch(info) => {
|
||||
builder.set_arg("target_size", info.target_size);
|
||||
builder.set_arg("data_size", info.data_size);
|
||||
builder.arg("target_size", info.target_size);
|
||||
builder.arg("data_size", info.data_size);
|
||||
}
|
||||
AbiMismatchArgument { caller_ty, callee_ty }
|
||||
| AbiMismatchReturn { caller_ty, callee_ty } => {
|
||||
builder.set_arg("caller_ty", caller_ty.to_string());
|
||||
builder.set_arg("callee_ty", callee_ty.to_string());
|
||||
builder.arg("caller_ty", caller_ty.to_string());
|
||||
builder.arg("callee_ty", callee_ty.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -695,7 +695,7 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
|
|||
)
|
||||
};
|
||||
|
||||
err.set_arg("front_matter", message);
|
||||
err.arg("front_matter", message);
|
||||
|
||||
fn add_range_arg<G: EmissionGuarantee>(
|
||||
r: WrappingRange,
|
||||
|
@ -725,12 +725,12 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
|
|||
];
|
||||
let args = args.iter().map(|(a, b)| (a, b));
|
||||
let message = dcx.eagerly_translate_to_string(msg, args);
|
||||
err.set_arg("in_range", message);
|
||||
err.arg("in_range", message);
|
||||
}
|
||||
|
||||
match self.kind {
|
||||
PtrToUninhabited { ty, .. } | UninhabitedVal { ty } => {
|
||||
err.set_arg("ty", ty);
|
||||
err.arg("ty", ty);
|
||||
}
|
||||
PointerAsInt { expected } | Uninit { expected } => {
|
||||
let msg = match expected {
|
||||
|
@ -747,28 +747,28 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
|
|||
ExpectedKind::Str => fluent::const_eval_validation_expected_str,
|
||||
};
|
||||
let msg = dcx.eagerly_translate_to_string(msg, [].into_iter());
|
||||
err.set_arg("expected", msg);
|
||||
err.arg("expected", msg);
|
||||
}
|
||||
InvalidEnumTag { value }
|
||||
| InvalidVTablePtr { value }
|
||||
| InvalidBool { value }
|
||||
| InvalidChar { value }
|
||||
| InvalidFnPtr { value } => {
|
||||
err.set_arg("value", value);
|
||||
err.arg("value", value);
|
||||
}
|
||||
NullablePtrOutOfRange { range, max_value } | PtrOutOfRange { range, max_value } => {
|
||||
add_range_arg(range, max_value, dcx, err)
|
||||
}
|
||||
OutOfRange { range, max_value, value } => {
|
||||
err.set_arg("value", value);
|
||||
err.arg("value", value);
|
||||
add_range_arg(range, max_value, dcx, err);
|
||||
}
|
||||
UnalignedPtr { required_bytes, found_bytes, .. } => {
|
||||
err.set_arg("required_bytes", required_bytes);
|
||||
err.set_arg("found_bytes", found_bytes);
|
||||
err.arg("required_bytes", required_bytes);
|
||||
err.arg("found_bytes", found_bytes);
|
||||
}
|
||||
DanglingPtrNoProvenance { pointer, .. } => {
|
||||
err.set_arg("pointer", pointer);
|
||||
err.arg("pointer", pointer);
|
||||
}
|
||||
NullPtr { .. }
|
||||
| PtrToStatic { .. }
|
||||
|
@ -814,10 +814,10 @@ impl ReportErrorExt for UnsupportedOpInfo {
|
|||
// print. So it's not worth the effort of having diagnostics that can print the `info`.
|
||||
UnsizedLocal | Unsupported(_) | ReadPointerAsInt(_) => {}
|
||||
OverwritePartialPointer(ptr) | ReadPartialPointer(ptr) => {
|
||||
builder.set_arg("ptr", ptr);
|
||||
builder.arg("ptr", ptr);
|
||||
}
|
||||
ThreadLocalStatic(did) | ReadExternStatic(did) => {
|
||||
builder.set_arg("did", format!("{did:?}"));
|
||||
builder.arg("did", format!("{did:?}"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -844,7 +844,7 @@ impl<'tcx> ReportErrorExt for InterpError<'tcx> {
|
|||
InterpError::InvalidProgram(e) => e.add_args(dcx, builder),
|
||||
InterpError::ResourceExhaustion(e) => e.add_args(dcx, builder),
|
||||
InterpError::MachineStop(e) => e.add_args(&mut |name, value| {
|
||||
builder.set_arg(name, value);
|
||||
builder.arg(name, value);
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
@ -880,15 +880,15 @@ impl<'tcx> ReportErrorExt for InvalidProgramInfo<'tcx> {
|
|||
let diag: DiagnosticBuilder<'_, ()> =
|
||||
e.into_diagnostic().into_diagnostic(dcx, dummy_level);
|
||||
for (name, val) in diag.args() {
|
||||
builder.set_arg(name.clone(), val.clone());
|
||||
builder.arg(name.clone(), val.clone());
|
||||
}
|
||||
diag.cancel();
|
||||
}
|
||||
InvalidProgramInfo::FnAbiAdjustForForeignAbi(
|
||||
AdjustForForeignAbiError::Unsupported { arch, abi },
|
||||
) => {
|
||||
builder.set_arg("arch", arch);
|
||||
builder.set_arg("abi", abi.name());
|
||||
builder.arg("arch", arch);
|
||||
builder.arg("abi", abi.name());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,7 +74,6 @@ impl<'tcx> MirPass<'tcx> for Validator {
|
|||
mir_phase,
|
||||
unwind_edge_count: 0,
|
||||
reachable_blocks: traversal::reachable_as_bitset(body),
|
||||
place_cache: FxHashSet::default(),
|
||||
value_cache: FxHashSet::default(),
|
||||
can_unwind,
|
||||
};
|
||||
|
@ -106,7 +105,6 @@ struct CfgChecker<'a, 'tcx> {
|
|||
mir_phase: MirPhase,
|
||||
unwind_edge_count: usize,
|
||||
reachable_blocks: BitSet<BasicBlock>,
|
||||
place_cache: FxHashSet<PlaceRef<'tcx>>,
|
||||
value_cache: FxHashSet<u128>,
|
||||
// If `false`, then the MIR must not contain `UnwindAction::Continue` or
|
||||
// `TerminatorKind::Resume`.
|
||||
|
@ -294,19 +292,6 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
|
|||
|
||||
fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
|
||||
match &statement.kind {
|
||||
StatementKind::Assign(box (dest, rvalue)) => {
|
||||
// FIXME(JakobDegen): Check this for all rvalues, not just this one.
|
||||
if let Rvalue::Use(Operand::Copy(src) | Operand::Move(src)) = rvalue {
|
||||
// The sides of an assignment must not alias. Currently this just checks whether
|
||||
// the places are identical.
|
||||
if dest == src {
|
||||
self.fail(
|
||||
location,
|
||||
"encountered `Assign` statement with overlapping memory",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
StatementKind::AscribeUserType(..) => {
|
||||
if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {
|
||||
self.fail(
|
||||
|
@ -341,7 +326,8 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
|
|||
self.fail(location, format!("explicit `{kind:?}` is forbidden"));
|
||||
}
|
||||
}
|
||||
StatementKind::StorageLive(_)
|
||||
StatementKind::Assign(..)
|
||||
| StatementKind::StorageLive(_)
|
||||
| StatementKind::StorageDead(_)
|
||||
| StatementKind::Intrinsic(_)
|
||||
| StatementKind::Coverage(_)
|
||||
|
@ -404,10 +390,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
|
|||
}
|
||||
|
||||
// The call destination place and Operand::Move place used as an argument might be
|
||||
// passed by a reference to the callee. Consequently they must be non-overlapping
|
||||
// and cannot be packed. Currently this simply checks for duplicate places.
|
||||
self.place_cache.clear();
|
||||
self.place_cache.insert(destination.as_ref());
|
||||
// passed by a reference to the callee. Consequently they cannot be packed.
|
||||
if is_within_packed(self.tcx, &self.body.local_decls, *destination).is_some() {
|
||||
// This is bad! The callee will expect the memory to be aligned.
|
||||
self.fail(
|
||||
|
@ -418,10 +401,8 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
|
|||
),
|
||||
);
|
||||
}
|
||||
let mut has_duplicates = false;
|
||||
for arg in args {
|
||||
if let Operand::Move(place) = arg {
|
||||
has_duplicates |= !self.place_cache.insert(place.as_ref());
|
||||
if is_within_packed(self.tcx, &self.body.local_decls, *place).is_some() {
|
||||
// This is bad! The callee will expect the memory to be aligned.
|
||||
self.fail(
|
||||
|
@ -434,16 +415,6 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if has_duplicates {
|
||||
self.fail(
|
||||
location,
|
||||
format!(
|
||||
"encountered overlapping memory in `Move` arguments to `Call` terminator: {:?}",
|
||||
terminator.kind,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
TerminatorKind::Assert { target, unwind, .. } => {
|
||||
self.check_edge(location, *target, EdgeKind::Normal);
|
||||
|
@ -1112,17 +1083,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
)
|
||||
}
|
||||
}
|
||||
// FIXME(JakobDegen): Check this for all rvalues, not just this one.
|
||||
if let Rvalue::Use(Operand::Copy(src) | Operand::Move(src)) = rvalue {
|
||||
// The sides of an assignment must not alias. Currently this just checks whether
|
||||
// the places are identical.
|
||||
if dest == src {
|
||||
self.fail(
|
||||
location,
|
||||
"encountered `Assign` statement with overlapping memory",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
StatementKind::AscribeUserType(..) => {
|
||||
if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {
|
||||
|
|
|
@ -1393,7 +1393,7 @@ fn report_ice(
|
|||
) {
|
||||
let fallback_bundle =
|
||||
rustc_errors::fallback_fluent_bundle(crate::DEFAULT_LOCALE_RESOURCES.to_vec(), false);
|
||||
let emitter = Box::new(rustc_errors::emitter::EmitterWriter::stderr(
|
||||
let emitter = Box::new(rustc_errors::emitter::HumanEmitter::stderr(
|
||||
rustc_errors::ColorConfig::Auto,
|
||||
fallback_bundle,
|
||||
));
|
||||
|
|
|
@ -20,7 +20,7 @@ use rustc_span::source_map::SourceMap;
|
|||
use rustc_span::SourceFile;
|
||||
|
||||
/// Generates diagnostics using annotate-snippet
|
||||
pub struct AnnotateSnippetEmitterWriter {
|
||||
pub struct AnnotateSnippetEmitter {
|
||||
source_map: Option<Lrc<SourceMap>>,
|
||||
fluent_bundle: Option<Lrc<FluentBundle>>,
|
||||
fallback_bundle: LazyFallbackBundle,
|
||||
|
@ -33,7 +33,7 @@ pub struct AnnotateSnippetEmitterWriter {
|
|||
macro_backtrace: bool,
|
||||
}
|
||||
|
||||
impl Translate for AnnotateSnippetEmitterWriter {
|
||||
impl Translate for AnnotateSnippetEmitter {
|
||||
fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> {
|
||||
self.fluent_bundle.as_ref()
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ impl Translate for AnnotateSnippetEmitterWriter {
|
|||
}
|
||||
}
|
||||
|
||||
impl Emitter for AnnotateSnippetEmitterWriter {
|
||||
impl Emitter for AnnotateSnippetEmitter {
|
||||
/// The entry point for the diagnostics generation
|
||||
fn emit_diagnostic(&mut self, diag: &Diagnostic) {
|
||||
let fluent_args = to_fluent_args(diag.args());
|
||||
|
@ -86,9 +86,7 @@ fn source_string(file: Lrc<SourceFile>, line: &Line) -> String {
|
|||
/// Maps `Diagnostic::Level` to `snippet::AnnotationType`
|
||||
fn annotation_type_for_level(level: Level) -> AnnotationType {
|
||||
match level {
|
||||
Level::Bug | Level::DelayedBug | Level::Fatal | Level::Error { .. } => {
|
||||
AnnotationType::Error
|
||||
}
|
||||
Level::Bug | Level::DelayedBug | Level::Fatal | Level::Error => AnnotationType::Error,
|
||||
Level::Warning(_) => AnnotationType::Warning,
|
||||
Level::Note | Level::OnceNote => AnnotationType::Note,
|
||||
Level::Help | Level::OnceHelp => AnnotationType::Help,
|
||||
|
@ -99,7 +97,7 @@ fn annotation_type_for_level(level: Level) -> AnnotationType {
|
|||
}
|
||||
}
|
||||
|
||||
impl AnnotateSnippetEmitterWriter {
|
||||
impl AnnotateSnippetEmitter {
|
||||
pub fn new(
|
||||
source_map: Option<Lrc<SourceMap>>,
|
||||
fluent_bundle: Option<Lrc<FluentBundle>>,
|
||||
|
|
|
@ -212,6 +212,9 @@ impl StringPart {
|
|||
}
|
||||
}
|
||||
|
||||
// Note: most of these methods are setters that return `&mut Self`. The small
|
||||
// number of simple getter functions all have `get_` prefixes to distinguish
|
||||
// them from the setters.
|
||||
impl Diagnostic {
|
||||
#[track_caller]
|
||||
pub fn new<M: Into<DiagnosticMessage>>(level: Level, message: M) -> Self {
|
||||
|
@ -241,11 +244,9 @@ impl Diagnostic {
|
|||
|
||||
pub fn is_error(&self) -> bool {
|
||||
match self.level {
|
||||
Level::Bug
|
||||
| Level::DelayedBug
|
||||
| Level::Fatal
|
||||
| Level::Error { .. }
|
||||
| Level::FailureNote => true,
|
||||
Level::Bug | Level::DelayedBug | Level::Fatal | Level::Error | Level::FailureNote => {
|
||||
true
|
||||
}
|
||||
|
||||
Level::Warning(_)
|
||||
| Level::Note
|
||||
|
@ -308,25 +309,27 @@ impl Diagnostic {
|
|||
/// In the meantime, though, callsites are required to deal with the "bug"
|
||||
/// locally in whichever way makes the most sense.
|
||||
#[track_caller]
|
||||
pub fn downgrade_to_delayed_bug(&mut self) -> &mut Self {
|
||||
pub fn downgrade_to_delayed_bug(&mut self) {
|
||||
assert!(
|
||||
self.is_error(),
|
||||
"downgrade_to_delayed_bug: cannot downgrade {:?} to DelayedBug: not an error",
|
||||
self.level
|
||||
);
|
||||
self.level = Level::DelayedBug;
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Adds a span/label to be included in the resulting snippet.
|
||||
/// Appends a labeled span to the diagnostic.
|
||||
///
|
||||
/// This is pushed onto the [`MultiSpan`] that was created when the diagnostic
|
||||
/// was first built. That means it will be shown together with the original
|
||||
/// span/label, *not* a span added by one of the `span_{note,warn,help,suggestions}` methods.
|
||||
/// Labels are used to convey additional context for the diagnostic's primary span. They will
|
||||
/// be shown together with the original diagnostic's span, *not* with spans added by
|
||||
/// `span_note`, `span_help`, etc. Therefore, if the primary span is not displayable (because
|
||||
/// the span is `DUMMY_SP` or the source code isn't found), labels will not be displayed
|
||||
/// either.
|
||||
///
|
||||
/// This span is *not* considered a ["primary span"][`MultiSpan`]; only
|
||||
/// the `Span` supplied when creating the diagnostic is primary.
|
||||
/// Implementation-wise, the label span is pushed onto the [`MultiSpan`] that was created when
|
||||
/// the diagnostic was constructed. However, the label span is *not* considered a
|
||||
/// ["primary span"][`MultiSpan`]; only the `Span` supplied when creating the diagnostic is
|
||||
/// primary.
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn span_label(&mut self, span: Span, label: impl Into<SubdiagnosticMessage>) -> &mut Self {
|
||||
self.span.push_span_label(span, self.subdiagnostic_message_to_diagnostic_message(label));
|
||||
|
@ -344,7 +347,7 @@ impl Diagnostic {
|
|||
|
||||
pub fn replace_span_with(&mut self, after: Span, keep_label: bool) -> &mut Self {
|
||||
let before = self.span.clone();
|
||||
self.set_span(after);
|
||||
self.span(after);
|
||||
for span_label in before.span_labels() {
|
||||
if let Some(label) = span_label.label {
|
||||
if span_label.is_primary && keep_label {
|
||||
|
@ -876,7 +879,7 @@ impl Diagnostic {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn set_span<S: Into<MultiSpan>>(&mut self, sp: S) -> &mut Self {
|
||||
pub fn span<S: Into<MultiSpan>>(&mut self, sp: S) -> &mut Self {
|
||||
self.span = sp.into();
|
||||
if let Some(span) = self.span.primary_span() {
|
||||
self.sort_span = span;
|
||||
|
@ -884,7 +887,7 @@ impl Diagnostic {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn set_is_lint(&mut self) -> &mut Self {
|
||||
pub fn is_lint(&mut self) -> &mut Self {
|
||||
self.is_lint = true;
|
||||
self
|
||||
}
|
||||
|
@ -903,7 +906,7 @@ impl Diagnostic {
|
|||
self.code.clone()
|
||||
}
|
||||
|
||||
pub fn set_primary_message(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self {
|
||||
pub fn primary_message(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self {
|
||||
self.messages[0] = (msg.into(), Style::NoStyle);
|
||||
self
|
||||
}
|
||||
|
@ -915,7 +918,7 @@ impl Diagnostic {
|
|||
self.args.iter()
|
||||
}
|
||||
|
||||
pub fn set_arg(
|
||||
pub fn arg(
|
||||
&mut self,
|
||||
name: impl Into<Cow<'static, str>>,
|
||||
arg: impl IntoDiagnosticArg,
|
||||
|
|
|
@ -31,7 +31,7 @@ where
|
|||
{
|
||||
fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> {
|
||||
let mut diag = self.node.into_diagnostic(dcx, level);
|
||||
diag.set_span(self.span);
|
||||
diag.span(self.span);
|
||||
diag
|
||||
}
|
||||
}
|
||||
|
@ -207,11 +207,11 @@ macro_rules! forward {
|
|||
// Forward pattern for &mut self -> &mut Self
|
||||
(
|
||||
$(#[$attrs:meta])*
|
||||
pub fn $n:ident(&mut self, $($name:ident: $ty:ty),* $(,)?) -> &mut Self
|
||||
pub fn $n:ident(&mut self $(, $name:ident: $ty:ty)* $(,)?) -> &mut Self
|
||||
) => {
|
||||
$(#[$attrs])*
|
||||
#[doc = concat!("See [`Diagnostic::", stringify!($n), "()`].")]
|
||||
pub fn $n(&mut self, $($name: $ty),*) -> &mut Self {
|
||||
pub fn $n(&mut self $(, $name: $ty)*) -> &mut Self {
|
||||
self.diagnostic.$n($($name),*);
|
||||
self
|
||||
}
|
||||
|
@ -356,35 +356,16 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
|
|||
self.emit()
|
||||
}
|
||||
|
||||
forward!(
|
||||
#[track_caller]
|
||||
pub fn downgrade_to_delayed_bug(&mut self,) -> &mut Self
|
||||
);
|
||||
|
||||
forward!(
|
||||
/// Appends a labeled span to the diagnostic.
|
||||
///
|
||||
/// Labels are used to convey additional context for the diagnostic's primary span. They will
|
||||
/// be shown together with the original diagnostic's span, *not* with spans added by
|
||||
/// `span_note`, `span_help`, etc. Therefore, if the primary span is not displayable (because
|
||||
/// the span is `DUMMY_SP` or the source code isn't found), labels will not be displayed
|
||||
/// either.
|
||||
///
|
||||
/// Implementation-wise, the label span is pushed onto the [`MultiSpan`] that was created when
|
||||
/// the diagnostic was constructed. However, the label span is *not* considered a
|
||||
/// ["primary span"][`MultiSpan`]; only the `Span` supplied when creating the diagnostic is
|
||||
/// primary.
|
||||
pub fn span_label(&mut self, span: Span, label: impl Into<SubdiagnosticMessage>) -> &mut Self);
|
||||
|
||||
forward!(
|
||||
/// Labels all the given spans with the provided label.
|
||||
/// See [`Diagnostic::span_label()`] for more information.
|
||||
pub fn span_labels(
|
||||
forward!(pub fn span_label(
|
||||
&mut self,
|
||||
span: Span,
|
||||
label: impl Into<SubdiagnosticMessage>
|
||||
) -> &mut Self);
|
||||
forward!(pub fn span_labels(
|
||||
&mut self,
|
||||
spans: impl IntoIterator<Item = Span>,
|
||||
label: &str,
|
||||
) -> &mut Self);
|
||||
|
||||
forward!(pub fn note_expected_found(
|
||||
&mut self,
|
||||
expected_label: &dyn fmt::Display,
|
||||
|
@ -392,7 +373,6 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
|
|||
found_label: &dyn fmt::Display,
|
||||
found: DiagnosticStyledString,
|
||||
) -> &mut Self);
|
||||
|
||||
forward!(pub fn note_expected_found_extra(
|
||||
&mut self,
|
||||
expected_label: &dyn fmt::Display,
|
||||
|
@ -402,7 +382,6 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
|
|||
expected_extra: &dyn fmt::Display,
|
||||
found_extra: &dyn fmt::Display,
|
||||
) -> &mut Self);
|
||||
|
||||
forward!(pub fn note(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self);
|
||||
forward!(pub fn note_once(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self);
|
||||
forward!(pub fn span_note(
|
||||
|
@ -428,10 +407,8 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
|
|||
sp: impl Into<MultiSpan>,
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
) -> &mut Self);
|
||||
forward!(pub fn set_is_lint(&mut self,) -> &mut Self);
|
||||
|
||||
forward!(pub fn disable_suggestions(&mut self,) -> &mut Self);
|
||||
|
||||
forward!(pub fn is_lint(&mut self) -> &mut Self);
|
||||
forward!(pub fn disable_suggestions(&mut self) -> &mut Self);
|
||||
forward!(pub fn multipart_suggestion(
|
||||
&mut self,
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
|
@ -498,16 +475,14 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
|
|||
suggestion: impl ToString,
|
||||
applicability: Applicability,
|
||||
) -> &mut Self);
|
||||
|
||||
forward!(pub fn set_primary_message(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self);
|
||||
forward!(pub fn set_span(&mut self, sp: impl Into<MultiSpan>) -> &mut Self);
|
||||
forward!(pub fn primary_message(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self);
|
||||
forward!(pub fn span(&mut self, sp: impl Into<MultiSpan>) -> &mut Self);
|
||||
forward!(pub fn code(&mut self, s: DiagnosticId) -> &mut Self);
|
||||
forward!(pub fn set_arg(
|
||||
forward!(pub fn arg(
|
||||
&mut self,
|
||||
name: impl Into<Cow<'static, str>>,
|
||||
arg: impl IntoDiagnosticArg,
|
||||
) -> &mut Self);
|
||||
|
||||
forward!(pub fn subdiagnostic(
|
||||
&mut self,
|
||||
subdiagnostic: impl crate::AddToDiagnostic
|
||||
|
|
|
@ -254,29 +254,29 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for TargetDataLayoutErrors<'_>
|
|||
TargetDataLayoutErrors::InvalidAddressSpace { addr_space, err, cause } => {
|
||||
diag =
|
||||
DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_address_space);
|
||||
diag.set_arg("addr_space", addr_space);
|
||||
diag.set_arg("cause", cause);
|
||||
diag.set_arg("err", err);
|
||||
diag.arg("addr_space", addr_space);
|
||||
diag.arg("cause", cause);
|
||||
diag.arg("err", err);
|
||||
diag
|
||||
}
|
||||
TargetDataLayoutErrors::InvalidBits { kind, bit, cause, err } => {
|
||||
diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_bits);
|
||||
diag.set_arg("kind", kind);
|
||||
diag.set_arg("bit", bit);
|
||||
diag.set_arg("cause", cause);
|
||||
diag.set_arg("err", err);
|
||||
diag.arg("kind", kind);
|
||||
diag.arg("bit", bit);
|
||||
diag.arg("cause", cause);
|
||||
diag.arg("err", err);
|
||||
diag
|
||||
}
|
||||
TargetDataLayoutErrors::MissingAlignment { cause } => {
|
||||
diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_missing_alignment);
|
||||
diag.set_arg("cause", cause);
|
||||
diag.arg("cause", cause);
|
||||
diag
|
||||
}
|
||||
TargetDataLayoutErrors::InvalidAlignment { cause, err } => {
|
||||
diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_alignment);
|
||||
diag.set_arg("cause", cause);
|
||||
diag.set_arg("err_kind", err.diag_ident());
|
||||
diag.set_arg("align", err.align());
|
||||
diag.arg("cause", cause);
|
||||
diag.arg("err_kind", err.diag_ident());
|
||||
diag.arg("align", err.align());
|
||||
diag
|
||||
}
|
||||
TargetDataLayoutErrors::InconsistentTargetArchitecture { dl, target } => {
|
||||
|
@ -285,8 +285,8 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for TargetDataLayoutErrors<'_>
|
|||
level,
|
||||
fluent::errors_target_inconsistent_architecture,
|
||||
);
|
||||
diag.set_arg("dl", dl);
|
||||
diag.set_arg("target", target);
|
||||
diag.arg("dl", dl);
|
||||
diag.arg("target", target);
|
||||
diag
|
||||
}
|
||||
TargetDataLayoutErrors::InconsistentTargetPointerWidth { pointer_size, target } => {
|
||||
|
@ -295,13 +295,13 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for TargetDataLayoutErrors<'_>
|
|||
level,
|
||||
fluent::errors_target_inconsistent_pointer_width,
|
||||
);
|
||||
diag.set_arg("pointer_size", pointer_size);
|
||||
diag.set_arg("target", target);
|
||||
diag.arg("pointer_size", pointer_size);
|
||||
diag.arg("target", target);
|
||||
diag
|
||||
}
|
||||
TargetDataLayoutErrors::InvalidBitsSize { err } => {
|
||||
diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_bits_size);
|
||||
diag.set_arg("err", err);
|
||||
diag.arg("err", err);
|
||||
diag
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,13 +61,13 @@ impl HumanReadableErrorType {
|
|||
self,
|
||||
mut dst: Box<dyn WriteColor + Send>,
|
||||
fallback_bundle: LazyFallbackBundle,
|
||||
) -> EmitterWriter {
|
||||
) -> HumanEmitter {
|
||||
let (short, color_config) = self.unzip();
|
||||
let color = color_config.suggests_using_colors();
|
||||
if !dst.supports_color() && color {
|
||||
dst = Box::new(Ansi::new(dst));
|
||||
}
|
||||
EmitterWriter::new(dst, fallback_bundle).short_message(short)
|
||||
HumanEmitter::new(dst, fallback_bundle).short_message(short)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -196,13 +196,15 @@ pub trait Emitter: Translate {
|
|||
fn emit_diagnostic(&mut self, diag: &Diagnostic);
|
||||
|
||||
/// Emit a notification that an artifact has been output.
|
||||
/// This is currently only supported for the JSON format,
|
||||
/// other formats can, and will, simply ignore it.
|
||||
/// Currently only supported for the JSON format.
|
||||
fn emit_artifact_notification(&mut self, _path: &Path, _artifact_type: &str) {}
|
||||
|
||||
/// Emit a report about future breakage.
|
||||
/// Currently only supported for the JSON format.
|
||||
fn emit_future_breakage_report(&mut self, _diags: Vec<Diagnostic>) {}
|
||||
|
||||
/// Emit list of unused externs
|
||||
/// Emit list of unused externs.
|
||||
/// Currently only supported for the JSON format.
|
||||
fn emit_unused_externs(
|
||||
&mut self,
|
||||
_lint_level: rustc_lint_defs::Level,
|
||||
|
@ -501,7 +503,7 @@ pub trait Emitter: Translate {
|
|||
}
|
||||
}
|
||||
|
||||
impl Translate for EmitterWriter {
|
||||
impl Translate for HumanEmitter {
|
||||
fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> {
|
||||
self.fluent_bundle.as_ref()
|
||||
}
|
||||
|
@ -511,7 +513,7 @@ impl Translate for EmitterWriter {
|
|||
}
|
||||
}
|
||||
|
||||
impl Emitter for EmitterWriter {
|
||||
impl Emitter for HumanEmitter {
|
||||
fn source_map(&self) -> Option<&Lrc<SourceMap>> {
|
||||
self.sm.as_ref()
|
||||
}
|
||||
|
@ -622,7 +624,7 @@ impl ColorConfig {
|
|||
|
||||
/// Handles the writing of `HumanReadableErrorType::Default` and `HumanReadableErrorType::Short`
|
||||
#[derive(Setters)]
|
||||
pub struct EmitterWriter {
|
||||
pub struct HumanEmitter {
|
||||
#[setters(skip)]
|
||||
dst: IntoDynSyncSend<Destination>,
|
||||
sm: Option<Lrc<SourceMap>>,
|
||||
|
@ -647,14 +649,14 @@ pub struct FileWithAnnotatedLines {
|
|||
multiline_depth: usize,
|
||||
}
|
||||
|
||||
impl EmitterWriter {
|
||||
pub fn stderr(color_config: ColorConfig, fallback_bundle: LazyFallbackBundle) -> EmitterWriter {
|
||||
impl HumanEmitter {
|
||||
pub fn stderr(color_config: ColorConfig, fallback_bundle: LazyFallbackBundle) -> HumanEmitter {
|
||||
let dst = from_stderr(color_config);
|
||||
Self::create(dst, fallback_bundle)
|
||||
}
|
||||
|
||||
fn create(dst: Destination, fallback_bundle: LazyFallbackBundle) -> EmitterWriter {
|
||||
EmitterWriter {
|
||||
fn create(dst: Destination, fallback_bundle: LazyFallbackBundle) -> HumanEmitter {
|
||||
HumanEmitter {
|
||||
dst: IntoDynSyncSend(dst),
|
||||
sm: None,
|
||||
fluent_bundle: None,
|
||||
|
@ -673,7 +675,7 @@ impl EmitterWriter {
|
|||
pub fn new(
|
||||
dst: Box<dyn WriteColor + Send>,
|
||||
fallback_bundle: LazyFallbackBundle,
|
||||
) -> EmitterWriter {
|
||||
) -> HumanEmitter {
|
||||
Self::create(dst, fallback_bundle)
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ pub use snippet::Style;
|
|||
pub use termcolor::{Color, ColorSpec, WriteColor};
|
||||
|
||||
use crate::diagnostic_impls::{DelayedAtWithNewline, DelayedAtWithoutNewline};
|
||||
use emitter::{is_case_difference, DynEmitter, Emitter, EmitterWriter};
|
||||
use emitter::{is_case_difference, DynEmitter, Emitter, HumanEmitter};
|
||||
use registry::Registry;
|
||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
||||
use rustc_data_structures::stable_hasher::{Hash128, StableHasher};
|
||||
|
@ -525,9 +525,6 @@ pub struct DiagCtxtFlags {
|
|||
/// If true, immediately emit diagnostics that would otherwise be buffered.
|
||||
/// (rustc: see `-Z dont-buffer-diagnostics` and `-Z treat-err-as-bug`)
|
||||
pub dont_buffer_diagnostics: bool,
|
||||
/// If true, immediately print bugs registered with `span_delayed_bug`.
|
||||
/// (rustc: see `-Z report-delayed-bugs`)
|
||||
pub report_delayed_bugs: bool,
|
||||
/// Show macro backtraces.
|
||||
/// (rustc: see `-Z macro-backtrace`)
|
||||
pub macro_backtrace: bool,
|
||||
|
@ -574,7 +571,7 @@ impl DiagCtxt {
|
|||
sm: Option<Lrc<SourceMap>>,
|
||||
fallback_bundle: LazyFallbackBundle,
|
||||
) -> Self {
|
||||
let emitter = Box::new(EmitterWriter::stderr(ColorConfig::Auto, fallback_bundle).sm(sm));
|
||||
let emitter = Box::new(HumanEmitter::stderr(ColorConfig::Auto, fallback_bundle).sm(sm));
|
||||
Self::with_emitter(emitter)
|
||||
}
|
||||
pub fn disable_warnings(mut self) -> Self {
|
||||
|
@ -673,7 +670,7 @@ impl DiagCtxt {
|
|||
let key = (span.with_parent(None), key);
|
||||
|
||||
if diag.is_error() {
|
||||
if matches!(diag.level, Error { lint: true }) {
|
||||
if diag.level == Error && diag.is_lint {
|
||||
inner.lint_err_count += 1;
|
||||
} else {
|
||||
inner.err_count += 1;
|
||||
|
@ -697,7 +694,7 @@ impl DiagCtxt {
|
|||
let key = (span.with_parent(None), key);
|
||||
let diag = inner.stashed_diagnostics.remove(&key)?;
|
||||
if diag.is_error() {
|
||||
if matches!(diag.level, Error { lint: true }) {
|
||||
if diag.level == Error && diag.is_lint {
|
||||
inner.lint_err_count -= 1;
|
||||
} else {
|
||||
inner.err_count -= 1;
|
||||
|
@ -732,7 +729,7 @@ impl DiagCtxt {
|
|||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> DiagnosticBuilder<'_, ()> {
|
||||
let mut result = self.struct_warn(msg);
|
||||
result.set_span(span);
|
||||
result.span(span);
|
||||
result
|
||||
}
|
||||
|
||||
|
@ -789,7 +786,7 @@ impl DiagCtxt {
|
|||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> DiagnosticBuilder<'_> {
|
||||
let mut result = self.struct_err(msg);
|
||||
result.set_span(span);
|
||||
result.span(span);
|
||||
result
|
||||
}
|
||||
|
||||
|
@ -812,7 +809,7 @@ impl DiagCtxt {
|
|||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_err(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_> {
|
||||
DiagnosticBuilder::new(self, Error { lint: false }, msg)
|
||||
DiagnosticBuilder::new(self, Error, msg)
|
||||
}
|
||||
|
||||
/// Construct a builder at the `Error` level with the `msg` and the `code`.
|
||||
|
@ -850,7 +847,7 @@ impl DiagCtxt {
|
|||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> DiagnosticBuilder<'_, FatalAbort> {
|
||||
let mut result = self.struct_fatal(msg);
|
||||
result.set_span(span);
|
||||
result.span(span);
|
||||
result
|
||||
}
|
||||
|
||||
|
@ -878,16 +875,6 @@ impl DiagCtxt {
|
|||
DiagnosticBuilder::new(self, Fatal, msg)
|
||||
}
|
||||
|
||||
/// Construct a builder at the `Fatal` level with the `msg`, that doesn't abort.
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_almost_fatal(
|
||||
&self,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> DiagnosticBuilder<'_, FatalError> {
|
||||
DiagnosticBuilder::new(self, Fatal, msg)
|
||||
}
|
||||
|
||||
/// Construct a builder at the `Help` level with the `msg`.
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn struct_help(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
|
||||
|
@ -917,7 +904,7 @@ impl DiagCtxt {
|
|||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> DiagnosticBuilder<'_, BugAbort> {
|
||||
let mut result = self.struct_bug(msg);
|
||||
result.set_span(span);
|
||||
result.span(span);
|
||||
result
|
||||
}
|
||||
|
||||
|
@ -1004,11 +991,10 @@ impl DiagCtxt {
|
|||
) -> ErrorGuaranteed {
|
||||
let treat_next_err_as_bug = self.inner.borrow().treat_next_err_as_bug();
|
||||
if treat_next_err_as_bug {
|
||||
// FIXME: don't abort here if report_delayed_bugs is off
|
||||
self.span_bug(sp, msg);
|
||||
}
|
||||
let mut diagnostic = Diagnostic::new(DelayedBug, msg);
|
||||
diagnostic.set_span(sp);
|
||||
diagnostic.span(sp);
|
||||
self.emit_diagnostic(diagnostic).unwrap()
|
||||
}
|
||||
|
||||
|
@ -1016,11 +1002,7 @@ impl DiagCtxt {
|
|||
// where the explanation of what "good path" is (also, it should be renamed).
|
||||
pub fn good_path_delayed_bug(&self, msg: impl Into<DiagnosticMessage>) {
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
|
||||
let mut diagnostic = Diagnostic::new(DelayedBug, msg);
|
||||
if inner.flags.report_delayed_bugs {
|
||||
inner.emit_diagnostic_without_consuming(&mut diagnostic);
|
||||
}
|
||||
let diagnostic = Diagnostic::new(DelayedBug, msg);
|
||||
let backtrace = std::backtrace::Backtrace::capture();
|
||||
inner.good_path_delayed_bugs.push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace));
|
||||
}
|
||||
|
@ -1039,7 +1021,7 @@ impl DiagCtxt {
|
|||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> DiagnosticBuilder<'_, ()> {
|
||||
let mut db = DiagnosticBuilder::new(self, Note, msg);
|
||||
db.set_span(span);
|
||||
db.span(span);
|
||||
db
|
||||
}
|
||||
|
||||
|
@ -1222,7 +1204,7 @@ impl DiagCtxt {
|
|||
|
||||
#[track_caller]
|
||||
pub fn create_err<'a>(&'a self, err: impl IntoDiagnostic<'a>) -> DiagnosticBuilder<'a> {
|
||||
err.into_diagnostic(self, Error { lint: false })
|
||||
err.into_diagnostic(self, Error)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
|
@ -1377,7 +1359,7 @@ impl DiagCtxtInner {
|
|||
for diag in diags {
|
||||
// Decrement the count tracking the stash; emitting will increment it.
|
||||
if diag.is_error() {
|
||||
if matches!(diag.level, Error { lint: true }) {
|
||||
if diag.level == Error && diag.is_lint {
|
||||
self.lint_err_count -= 1;
|
||||
} else {
|
||||
self.err_count -= 1;
|
||||
|
@ -1408,7 +1390,7 @@ impl DiagCtxtInner {
|
|||
&mut self,
|
||||
diagnostic: &mut Diagnostic,
|
||||
) -> Option<ErrorGuaranteed> {
|
||||
if matches!(diagnostic.level, Error { .. } | Fatal) && self.treat_err_as_bug() {
|
||||
if matches!(diagnostic.level, Error | Fatal) && self.treat_err_as_bug() {
|
||||
diagnostic.level = Bug;
|
||||
}
|
||||
|
||||
|
@ -1430,10 +1412,8 @@ impl DiagCtxtInner {
|
|||
self.span_delayed_bugs
|
||||
.push(DelayedDiagnostic::with_backtrace(diagnostic.clone(), backtrace));
|
||||
|
||||
if !self.flags.report_delayed_bugs {
|
||||
#[allow(deprecated)]
|
||||
return Some(ErrorGuaranteed::unchecked_claim_error_was_emitted());
|
||||
}
|
||||
#[allow(deprecated)]
|
||||
return Some(ErrorGuaranteed::unchecked_claim_error_was_emitted());
|
||||
}
|
||||
|
||||
if diagnostic.has_future_breakage() {
|
||||
|
@ -1509,7 +1489,7 @@ impl DiagCtxtInner {
|
|||
}
|
||||
}
|
||||
if diagnostic.is_error() {
|
||||
if matches!(diagnostic.level, Error { lint: true }) {
|
||||
if diagnostic.level == Error && diagnostic.is_lint {
|
||||
self.bump_lint_err_count();
|
||||
} else {
|
||||
self.bump_err_count();
|
||||
|
@ -1705,11 +1685,7 @@ pub enum Level {
|
|||
/// most common case.
|
||||
///
|
||||
/// Its `EmissionGuarantee` is `ErrorGuaranteed`.
|
||||
Error {
|
||||
/// If this error comes from a lint, don't abort compilation even when abort_if_errors() is
|
||||
/// called.
|
||||
lint: bool,
|
||||
},
|
||||
Error,
|
||||
|
||||
/// A warning about the code being compiled. Does not prevent compilation from finishing.
|
||||
///
|
||||
|
@ -1768,7 +1744,7 @@ impl Level {
|
|||
fn color(self) -> ColorSpec {
|
||||
let mut spec = ColorSpec::new();
|
||||
match self {
|
||||
Bug | DelayedBug | Fatal | Error { .. } => {
|
||||
Bug | DelayedBug | Fatal | Error => {
|
||||
spec.set_fg(Some(Color::Red)).set_intense(true);
|
||||
}
|
||||
Warning(_) => {
|
||||
|
@ -1789,7 +1765,7 @@ impl Level {
|
|||
pub fn to_str(self) -> &'static str {
|
||||
match self {
|
||||
Bug | DelayedBug => "error: internal compiler error",
|
||||
Fatal | Error { .. } => "error",
|
||||
Fatal | Error => "error",
|
||||
Warning(_) => "warning",
|
||||
Note | OnceNote => "note",
|
||||
Help | OnceHelp => "help",
|
||||
|
|
|
@ -855,7 +855,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
}
|
||||
Err(mut err) => {
|
||||
if err.span.is_dummy() {
|
||||
err.set_span(span);
|
||||
err.span(span);
|
||||
}
|
||||
annotate_err_with_kind(&mut err, kind, span);
|
||||
err.emit();
|
||||
|
|
|
@ -379,7 +379,7 @@ impl ToInternal<SmallVec<[tokenstream::TokenTree; 2]>>
|
|||
impl ToInternal<rustc_errors::Level> for Level {
|
||||
fn to_internal(self) -> rustc_errors::Level {
|
||||
match self {
|
||||
Level::Error => rustc_errors::Level::Error { lint: false },
|
||||
Level::Error => rustc_errors::Level::Error,
|
||||
Level::Warning => rustc_errors::Level::Warning(None),
|
||||
Level::Note => rustc_errors::Level::Note,
|
||||
Level::Help => rustc_errors::Level::Help,
|
||||
|
@ -497,7 +497,7 @@ impl server::FreeFunctions for Rustc<'_, '_> {
|
|||
fn emit_diagnostic(&mut self, diagnostic: Diagnostic<Self::Span>) {
|
||||
let mut diag =
|
||||
rustc_errors::Diagnostic::new(diagnostic.level.to_internal(), diagnostic.message);
|
||||
diag.set_span(MultiSpan::from_spans(diagnostic.spans));
|
||||
diag.span(MultiSpan::from_spans(diagnostic.spans));
|
||||
for child in diagnostic.children {
|
||||
diag.sub(child.level.to_internal(), child.message, MultiSpan::from_spans(child.spans));
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ use rustc_span::source_map::{FilePathMapping, SourceMap};
|
|||
use rustc_span::{BytePos, Span};
|
||||
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::emitter::EmitterWriter;
|
||||
use rustc_errors::emitter::HumanEmitter;
|
||||
use rustc_errors::{DiagCtxt, MultiSpan, PResult};
|
||||
use termcolor::WriteColor;
|
||||
|
||||
|
@ -30,7 +30,7 @@ fn create_test_handler() -> (DiagCtxt, Lrc<SourceMap>, Arc<Mutex<Vec<u8>>>) {
|
|||
vec![crate::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE],
|
||||
false,
|
||||
);
|
||||
let emitter = EmitterWriter::new(Box::new(Shared { data: output.clone() }), fallback_bundle)
|
||||
let emitter = HumanEmitter::new(Box::new(Shared { data: output.clone() }), fallback_bundle)
|
||||
.sm(Some(source_map.clone()))
|
||||
.diagnostic_width(Some(140));
|
||||
let dcx = DiagCtxt::with_emitter(Box::new(emitter));
|
||||
|
|
|
@ -605,7 +605,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
let violations =
|
||||
object_safety_violations_for_assoc_item(tcx, trait_def_id, *assoc_item);
|
||||
if !violations.is_empty() {
|
||||
report_object_safety_error(tcx, *span, trait_def_id, &violations).emit();
|
||||
report_object_safety_error(tcx, *span, None, trait_def_id, &violations).emit();
|
||||
object_safety_violations = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ fn generic_arg_mismatch_err(
|
|||
Res::Err => {
|
||||
add_braces_suggestion(arg, &mut err);
|
||||
return err
|
||||
.set_primary_message("unresolved item provided when a constant was expected")
|
||||
.primary_message("unresolved item provided when a constant was expected")
|
||||
.emit();
|
||||
}
|
||||
Res::Def(DefKind::TyParam, src_def_id) => {
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
use rustc_ast::TraitObjectSyntax;
|
||||
use rustc_errors::{Diagnostic, StashKey};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_lint_defs::{builtin::BARE_TRAIT_OBJECTS, Applicability};
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName;
|
||||
|
||||
use super::AstConv;
|
||||
|
@ -32,32 +34,146 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
}
|
||||
let of_trait_span = of_trait_ref.path.span;
|
||||
// make sure that we are not calling unwrap to abort during the compilation
|
||||
let Ok(impl_trait_name) = tcx.sess.source_map().span_to_snippet(self_ty.span) else {
|
||||
return;
|
||||
};
|
||||
let Ok(of_trait_name) = tcx.sess.source_map().span_to_snippet(of_trait_span) else {
|
||||
return;
|
||||
};
|
||||
// check if the trait has generics, to make a correct suggestion
|
||||
let param_name = generics.params.next_type_param_name(None);
|
||||
|
||||
let add_generic_sugg = if let Some(span) = generics.span_for_param_suggestion() {
|
||||
(span, format!(", {param_name}: {impl_trait_name}"))
|
||||
} else {
|
||||
(generics.span, format!("<{param_name}: {impl_trait_name}>"))
|
||||
let Ok(impl_trait_name) = self.tcx().sess.source_map().span_to_snippet(self_ty.span)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let sugg = self.add_generic_param_suggestion(generics, self_ty.span, &impl_trait_name);
|
||||
if sugg.is_empty() {
|
||||
return;
|
||||
};
|
||||
diag.multipart_suggestion(
|
||||
format!(
|
||||
"alternatively use a blanket \
|
||||
implementation to implement `{of_trait_name}` for \
|
||||
"alternatively use a blanket implementation to implement `{of_trait_name}` for \
|
||||
all types that also implement `{impl_trait_name}`"
|
||||
),
|
||||
vec![(self_ty.span, param_name), add_generic_sugg],
|
||||
sugg,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn add_generic_param_suggestion(
|
||||
&self,
|
||||
generics: &hir::Generics<'_>,
|
||||
self_ty_span: Span,
|
||||
impl_trait_name: &str,
|
||||
) -> Vec<(Span, String)> {
|
||||
// check if the trait has generics, to make a correct suggestion
|
||||
let param_name = generics.params.next_type_param_name(None);
|
||||
|
||||
let add_generic_sugg = if let Some(span) = generics.span_for_param_suggestion() {
|
||||
(span, format!(", {param_name}: {impl_trait_name}"))
|
||||
} else {
|
||||
(generics.span, format!("<{param_name}: {impl_trait_name}>"))
|
||||
};
|
||||
vec![(self_ty_span, param_name), add_generic_sugg]
|
||||
}
|
||||
|
||||
/// Make sure that we are in the condition to suggest `impl Trait`.
|
||||
fn maybe_lint_impl_trait(&self, self_ty: &hir::Ty<'_>, diag: &mut Diagnostic) -> bool {
|
||||
let tcx = self.tcx();
|
||||
let parent_id = tcx.hir().get_parent_item(self_ty.hir_id).def_id;
|
||||
let (hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, generics, _), .. })
|
||||
| hir::Node::TraitItem(hir::TraitItem {
|
||||
kind: hir::TraitItemKind::Fn(sig, _),
|
||||
generics,
|
||||
..
|
||||
})) = tcx.hir_node_by_def_id(parent_id)
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
let Ok(trait_name) = tcx.sess.source_map().span_to_snippet(self_ty.span) else {
|
||||
return false;
|
||||
};
|
||||
let impl_sugg = vec![(self_ty.span.shrink_to_lo(), "impl ".to_string())];
|
||||
let is_object_safe = match self_ty.kind {
|
||||
hir::TyKind::TraitObject(objects, ..) => {
|
||||
objects.iter().all(|o| match o.trait_ref.path.res {
|
||||
Res::Def(DefKind::Trait, id) => tcx.check_is_object_safe(id),
|
||||
_ => false,
|
||||
})
|
||||
}
|
||||
_ => false,
|
||||
};
|
||||
if let hir::FnRetTy::Return(ty) = sig.decl.output
|
||||
&& ty.hir_id == self_ty.hir_id
|
||||
{
|
||||
let pre = if !is_object_safe {
|
||||
format!("`{trait_name}` is not object safe, ")
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
let msg = format!(
|
||||
"{pre}use `impl {trait_name}` to return an opaque type, as long as you return a \
|
||||
single underlying type",
|
||||
);
|
||||
diag.multipart_suggestion_verbose(msg, impl_sugg, Applicability::MachineApplicable);
|
||||
if is_object_safe {
|
||||
diag.multipart_suggestion_verbose(
|
||||
"alternatively, you can return an owned trait object",
|
||||
vec![
|
||||
(ty.span.shrink_to_lo(), "Box<dyn ".to_string()),
|
||||
(ty.span.shrink_to_hi(), ">".to_string()),
|
||||
],
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else {
|
||||
// We'll emit the object safety error already, with a structured suggestion.
|
||||
diag.downgrade_to_delayed_bug();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
for ty in sig.decl.inputs {
|
||||
if ty.hir_id != self_ty.hir_id {
|
||||
continue;
|
||||
}
|
||||
let sugg = self.add_generic_param_suggestion(generics, self_ty.span, &trait_name);
|
||||
if !sugg.is_empty() {
|
||||
diag.multipart_suggestion_verbose(
|
||||
format!("use a new generic type parameter, constrained by `{trait_name}`"),
|
||||
sugg,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
diag.multipart_suggestion_verbose(
|
||||
"you can also use an opaque type, but users won't be able to specify the type \
|
||||
parameter when calling the `fn`, having to rely exclusively on type inference",
|
||||
impl_sugg,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
if !is_object_safe {
|
||||
diag.note(format!("`{trait_name}` it is not object safe, so it can't be `dyn`"));
|
||||
// We'll emit the object safety error already, with a structured suggestion.
|
||||
diag.downgrade_to_delayed_bug();
|
||||
} else {
|
||||
let sugg = if let hir::TyKind::TraitObject([_, _, ..], _, _) = self_ty.kind {
|
||||
// There are more than one trait bound, we need surrounding parentheses.
|
||||
vec![
|
||||
(self_ty.span.shrink_to_lo(), "&(dyn ".to_string()),
|
||||
(self_ty.span.shrink_to_hi(), ")".to_string()),
|
||||
]
|
||||
} else {
|
||||
vec![(self_ty.span.shrink_to_lo(), "&dyn ".to_string())]
|
||||
};
|
||||
diag.multipart_suggestion_verbose(
|
||||
format!(
|
||||
"alternatively, use a trait object to accept any type that implements \
|
||||
`{trait_name}`, accessing its methods at runtime using dynamic dispatch",
|
||||
),
|
||||
sugg,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub(super) fn maybe_lint_bare_trait(&self, self_ty: &hir::Ty<'_>, in_path: bool) {
|
||||
let tcx = self.tcx();
|
||||
if let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) =
|
||||
|
@ -98,7 +214,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
let label = "add `dyn` keyword before this trait";
|
||||
let mut diag =
|
||||
rustc_errors::struct_span_err!(tcx.dcx(), self_ty.span, E0782, "{}", msg);
|
||||
if self_ty.span.can_be_used_for_suggestions() {
|
||||
if self_ty.span.can_be_used_for_suggestions()
|
||||
&& !self.maybe_lint_impl_trait(self_ty, &mut diag)
|
||||
{
|
||||
diag.multipart_suggestion_verbose(
|
||||
label,
|
||||
sugg,
|
||||
|
@ -116,11 +234,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
self_ty.span,
|
||||
msg,
|
||||
|lint| {
|
||||
lint.multipart_suggestion_verbose(
|
||||
"use `dyn`",
|
||||
sugg,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
if self_ty.span.can_be_used_for_suggestions()
|
||||
&& !self.maybe_lint_impl_trait(self_ty, lint)
|
||||
{
|
||||
lint.multipart_suggestion_verbose(
|
||||
"use `dyn`",
|
||||
sugg,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
self.maybe_lint_blanket_trait_impl(self_ty, lint);
|
||||
},
|
||||
);
|
||||
|
|
|
@ -140,6 +140,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
let reported = report_object_safety_error(
|
||||
tcx,
|
||||
span,
|
||||
Some(hir_id),
|
||||
item.trait_ref().def_id(),
|
||||
&object_safety_violations,
|
||||
)
|
||||
|
|
|
@ -319,10 +319,10 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for MissingTypeParams {
|
|||
#[track_caller]
|
||||
fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> {
|
||||
let mut err = DiagnosticBuilder::new(dcx, level, fluent::hir_analysis_missing_type_params);
|
||||
err.set_span(self.span);
|
||||
err.span(self.span);
|
||||
err.code(error_code!(E0393));
|
||||
err.set_arg("parameterCount", self.missing_type_params.len());
|
||||
err.set_arg(
|
||||
err.arg("parameterCount", self.missing_type_params.len());
|
||||
err.arg(
|
||||
"parameters",
|
||||
self.missing_type_params
|
||||
.iter()
|
||||
|
|
|
@ -73,7 +73,8 @@ pub(super) fn check_fn<'a, 'tcx>(
|
|||
let inputs_fn = fn_sig.inputs().iter().copied();
|
||||
for (idx, (param_ty, param)) in inputs_fn.chain(maybe_va_list).zip(body.params).enumerate() {
|
||||
// Check the pattern.
|
||||
let ty_span = try { inputs_hir?.get(idx)?.span };
|
||||
let ty: Option<&hir::Ty<'_>> = try { inputs_hir?.get(idx)? };
|
||||
let ty_span = ty.map(|ty| ty.span);
|
||||
fcx.check_pat_top(param.pat, param_ty, ty_span, None, None);
|
||||
|
||||
// Check that argument is Sized.
|
||||
|
@ -81,14 +82,14 @@ pub(super) fn check_fn<'a, 'tcx>(
|
|||
fcx.require_type_is_sized(
|
||||
param_ty,
|
||||
param.pat.span,
|
||||
// ty_span == binding_span iff this is a closure parameter with no type ascription,
|
||||
// ty.span == binding_span iff this is a closure parameter with no type ascription,
|
||||
// or if it's an implicit `self` parameter
|
||||
traits::SizedArgumentType(
|
||||
if ty_span == Some(param.span) && tcx.is_closure_or_coroutine(fn_def_id.into())
|
||||
{
|
||||
None
|
||||
} else {
|
||||
ty_span
|
||||
ty.map(|ty| ty.hir_id)
|
||||
},
|
||||
),
|
||||
);
|
||||
|
|
|
@ -215,7 +215,7 @@ impl AddToDiagnostic for TypeMismatchFruTypo {
|
|||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
diag.set_arg("expr", self.expr.as_deref().unwrap_or("NONE"));
|
||||
diag.arg("expr", self.expr.as_deref().unwrap_or("NONE"));
|
||||
|
||||
// Only explain that `a ..b` is a range if it's split up
|
||||
if self.expr_span.between(self.fru_span).is_empty() {
|
||||
|
|
|
@ -60,7 +60,7 @@ pub(super) struct GatherLocalsVisitor<'a, 'tcx> {
|
|||
// parameters are special cases of patterns, but we want to handle them as
|
||||
// *distinct* cases. so track when we are hitting a pattern *within* an fn
|
||||
// parameter.
|
||||
outermost_fn_param_pat: Option<Span>,
|
||||
outermost_fn_param_pat: Option<(Span, hir::HirId)>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
|
||||
|
@ -131,7 +131,8 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
|
||||
let old_outermost_fn_param_pat = self.outermost_fn_param_pat.replace(param.ty_span);
|
||||
let old_outermost_fn_param_pat =
|
||||
self.outermost_fn_param_pat.replace((param.ty_span, param.hir_id));
|
||||
intravisit::walk_param(self, param);
|
||||
self.outermost_fn_param_pat = old_outermost_fn_param_pat;
|
||||
}
|
||||
|
@ -141,7 +142,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
|
|||
if let PatKind::Binding(_, _, ident, _) = p.kind {
|
||||
let var_ty = self.assign(p.span, p.hir_id, None);
|
||||
|
||||
if let Some(ty_span) = self.outermost_fn_param_pat {
|
||||
if let Some((ty_span, hir_id)) = self.outermost_fn_param_pat {
|
||||
if !self.fcx.tcx.features().unsized_fn_params {
|
||||
self.fcx.require_type_is_sized(
|
||||
var_ty,
|
||||
|
@ -154,7 +155,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
|
|||
{
|
||||
None
|
||||
} else {
|
||||
Some(ty_span)
|
||||
Some(hir_id)
|
||||
},
|
||||
),
|
||||
);
|
||||
|
|
|
@ -961,7 +961,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
but its trait bounds were not satisfied"
|
||||
)
|
||||
});
|
||||
err.set_primary_message(primary_message);
|
||||
err.primary_message(primary_message);
|
||||
if let Some(label) = label {
|
||||
custom_span_label = true;
|
||||
err.span_label(span, label);
|
||||
|
|
|
@ -247,8 +247,8 @@ impl AddToDiagnostic for RegionOriginNote<'_> {
|
|||
}
|
||||
RegionOriginNote::WithName { span, msg, name, continues } => {
|
||||
label_or_note(span, msg);
|
||||
diag.set_arg("name", name);
|
||||
diag.set_arg("continues", continues);
|
||||
diag.arg("name", name);
|
||||
diag.arg("continues", continues);
|
||||
}
|
||||
RegionOriginNote::WithRequirement {
|
||||
span,
|
||||
|
@ -256,7 +256,7 @@ impl AddToDiagnostic for RegionOriginNote<'_> {
|
|||
expected_found: Some((expected, found)),
|
||||
} => {
|
||||
label_or_note(span, fluent::infer_subtype);
|
||||
diag.set_arg("requirement", requirement);
|
||||
diag.arg("requirement", requirement);
|
||||
|
||||
diag.note_expected_found(&"", expected, &"", found);
|
||||
}
|
||||
|
@ -265,7 +265,7 @@ impl AddToDiagnostic for RegionOriginNote<'_> {
|
|||
// handling of region checking when type errors are present is
|
||||
// *terrible*.
|
||||
label_or_note(span, fluent::infer_subtype_2);
|
||||
diag.set_arg("requirement", requirement);
|
||||
diag.arg("requirement", requirement);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -298,8 +298,8 @@ impl AddToDiagnostic for LifetimeMismatchLabels {
|
|||
diag.span_label(param_span, fluent::infer_declared_different);
|
||||
diag.span_label(ret_span, fluent::infer_nothing);
|
||||
diag.span_label(span, fluent::infer_data_returned);
|
||||
diag.set_arg("label_var1_exists", label_var1.is_some());
|
||||
diag.set_arg("label_var1", label_var1.map(|x| x.to_string()).unwrap_or_default());
|
||||
diag.arg("label_var1_exists", label_var1.is_some());
|
||||
diag.arg("label_var1", label_var1.map(|x| x.to_string()).unwrap_or_default());
|
||||
}
|
||||
LifetimeMismatchLabels::Normal {
|
||||
hir_equal,
|
||||
|
@ -317,16 +317,10 @@ impl AddToDiagnostic for LifetimeMismatchLabels {
|
|||
diag.span_label(ty_sup, fluent::infer_types_declared_different);
|
||||
diag.span_label(ty_sub, fluent::infer_nothing);
|
||||
diag.span_label(span, fluent::infer_data_flows);
|
||||
diag.set_arg("label_var1_exists", label_var1.is_some());
|
||||
diag.set_arg(
|
||||
"label_var1",
|
||||
label_var1.map(|x| x.to_string()).unwrap_or_default(),
|
||||
);
|
||||
diag.set_arg("label_var2_exists", label_var2.is_some());
|
||||
diag.set_arg(
|
||||
"label_var2",
|
||||
label_var2.map(|x| x.to_string()).unwrap_or_default(),
|
||||
);
|
||||
diag.arg("label_var1_exists", label_var1.is_some());
|
||||
diag.arg("label_var1", label_var1.map(|x| x.to_string()).unwrap_or_default());
|
||||
diag.arg("label_var2_exists", label_var2.is_some());
|
||||
diag.arg("label_var2", label_var2.map(|x| x.to_string()).unwrap_or_default());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -417,7 +411,7 @@ impl AddToDiagnostic for AddLifetimeParamsSuggestion<'_> {
|
|||
suggestions,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
diag.set_arg("is_impl", is_impl);
|
||||
diag.arg("is_impl", is_impl);
|
||||
true
|
||||
};
|
||||
if mk_suggestion() && self.add_note {
|
||||
|
@ -878,8 +872,8 @@ impl AddToDiagnostic for MoreTargeted {
|
|||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
diag.code(rustc_errors::error_code!(E0772));
|
||||
diag.set_primary_message(fluent::infer_more_targeted);
|
||||
diag.set_arg("ident", self.ident);
|
||||
diag.primary_message(fluent::infer_more_targeted);
|
||||
diag.arg("ident", self.ident);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1299,7 +1293,7 @@ impl AddToDiagnostic for SuggestTuplePatternMany {
|
|||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
diag.set_arg("path", self.path);
|
||||
diag.arg("path", self.path);
|
||||
let message = f(diag, crate::fluent_generated::infer_stp_wrap_many.into());
|
||||
diag.multipart_suggestions(
|
||||
message,
|
||||
|
|
|
@ -164,10 +164,10 @@ impl AddToDiagnostic for RegionExplanation<'_> {
|
|||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
diag.set_arg("pref_kind", self.prefix);
|
||||
diag.set_arg("suff_kind", self.suffix);
|
||||
diag.set_arg("desc_kind", self.desc.kind);
|
||||
diag.set_arg("desc_arg", self.desc.arg);
|
||||
diag.arg("pref_kind", self.prefix);
|
||||
diag.arg("suff_kind", self.suffix);
|
||||
diag.arg("desc_kind", self.desc.kind);
|
||||
diag.arg("desc_arg", self.desc.arg);
|
||||
|
||||
let msg = f(diag, fluent::infer_region_explanation.into());
|
||||
if let Some(span) = self.desc.span {
|
||||
|
|
|
@ -2,9 +2,10 @@ use super::ObjectSafetyViolation;
|
|||
|
||||
use crate::infer::InferCtxt;
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_errors::{struct_span_err, DiagnosticBuilder, MultiSpan};
|
||||
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, MultiSpan};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::intravisit::Map;
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_span::Span;
|
||||
|
@ -42,6 +43,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
pub fn report_object_safety_error<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
span: Span,
|
||||
hir_id: Option<hir::HirId>,
|
||||
trait_def_id: DefId,
|
||||
violations: &[ObjectSafetyViolation],
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
|
@ -59,6 +61,24 @@ pub fn report_object_safety_error<'tcx>(
|
|||
);
|
||||
err.span_label(span, format!("`{trait_str}` cannot be made into an object"));
|
||||
|
||||
if let Some(hir_id) = hir_id
|
||||
&& let Some(hir::Node::Ty(ty)) = tcx.hir().find(hir_id)
|
||||
&& let hir::TyKind::TraitObject([trait_ref, ..], ..) = ty.kind
|
||||
{
|
||||
let mut hir_id = hir_id;
|
||||
while let hir::Node::Ty(ty) = tcx.hir().get_parent(hir_id) {
|
||||
hir_id = ty.hir_id;
|
||||
}
|
||||
if tcx.hir().get_parent(hir_id).fn_sig().is_some() {
|
||||
// Do not suggest `impl Trait` when dealing with things like super-traits.
|
||||
err.span_suggestion_verbose(
|
||||
ty.span.until(trait_ref.span),
|
||||
"consider using an opaque type instead",
|
||||
"impl ",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
let mut reported_violations = FxIndexSet::default();
|
||||
let mut multi_span = vec![];
|
||||
let mut messages = vec![];
|
||||
|
|
|
@ -6,8 +6,8 @@ use rustc_session::config::{
|
|||
build_configuration, build_session_options, rustc_optgroups, BranchProtection, CFGuard, Cfg,
|
||||
DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, ExternLocation, Externs,
|
||||
FunctionReturn, InliningThreshold, Input, InstrumentCoverage, InstrumentXRay,
|
||||
LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli, MirSpanview, NextSolverConfig,
|
||||
OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet, Passes, Polonius,
|
||||
LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli, NextSolverConfig, OomStrategy,
|
||||
Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet, Passes, Polonius,
|
||||
ProcMacroExecutionStrategy, Strip, SwitchWithOptPath, SymbolManglingVersion, WasiExecModel,
|
||||
};
|
||||
use rustc_session::lint::Level;
|
||||
|
@ -666,7 +666,6 @@ fn test_unstable_options_tracking_hash() {
|
|||
untracked!(dump_mir_dir, String::from("abc"));
|
||||
untracked!(dump_mir_exclude_pass_number, true);
|
||||
untracked!(dump_mir_graphviz, true);
|
||||
untracked!(dump_mir_spanview, Some(MirSpanview::Statement));
|
||||
untracked!(dump_mono_stats, SwitchWithOptPath::Enabled(Some("mono-items-dir/".into())));
|
||||
untracked!(dump_mono_stats_format, DumpMonoStatsFormat::Json);
|
||||
untracked!(dylib_lto, true);
|
||||
|
@ -806,7 +805,6 @@ fn test_unstable_options_tracking_hash() {
|
|||
tracked!(relax_elf_relocations, Some(true));
|
||||
tracked!(relro_level, Some(RelroLevel::Full));
|
||||
tracked!(remap_cwd_prefix, Some(PathBuf::from("abc")));
|
||||
tracked!(report_delayed_bugs, true);
|
||||
tracked!(sanitizer, SanitizerSet::ADDRESS);
|
||||
tracked!(sanitizer_cfi_canonical_jump_tables, None);
|
||||
tracked!(sanitizer_cfi_generalize_pointers, Some(true));
|
||||
|
|
|
@ -31,7 +31,7 @@ impl AddToDiagnostic for OverruledAttributeSub {
|
|||
match self {
|
||||
OverruledAttributeSub::DefaultSource { id } => {
|
||||
diag.note(fluent::lint_default_source);
|
||||
diag.set_arg("id", id);
|
||||
diag.arg("id", id);
|
||||
}
|
||||
OverruledAttributeSub::NodeSource { span, reason } => {
|
||||
diag.span_label(span, fluent::lint_node_source);
|
||||
|
|
|
@ -1069,7 +1069,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
|
|||
Some(span.into()),
|
||||
fluent::lint_unknown_gated_lint,
|
||||
|lint| {
|
||||
lint.set_arg("name", lint_id.lint.name_lower());
|
||||
lint.arg("name", lint_id.lint.name_lower());
|
||||
lint.note(fluent::lint_note);
|
||||
rustc_session::parse::add_feature_diagnostics_for_issue(
|
||||
lint,
|
||||
|
|
|
@ -5,8 +5,8 @@ use std::num::NonZeroU32;
|
|||
use crate::errors::RequestedLevel;
|
||||
use crate::fluent_generated as fluent;
|
||||
use rustc_errors::{
|
||||
AddToDiagnostic, Applicability, DecorateLint, DiagnosticMessage, DiagnosticStyledString,
|
||||
SuggestionStyle,
|
||||
AddToDiagnostic, Applicability, DecorateLint, Diagnostic, DiagnosticBuilder, DiagnosticMessage,
|
||||
DiagnosticStyledString, SubdiagnosticMessage, SuggestionStyle,
|
||||
};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_macros::{LintDiagnostic, Subdiagnostic};
|
||||
|
@ -135,7 +135,7 @@ pub struct BuiltinMissingDebugImpl<'a> {
|
|||
// Needed for def_path_str
|
||||
impl<'a> DecorateLint<'a, ()> for BuiltinMissingDebugImpl<'_> {
|
||||
fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) {
|
||||
diag.set_arg("debug", self.tcx.def_path_str(self.def_id));
|
||||
diag.arg("debug", self.tcx.def_path_str(self.def_id));
|
||||
}
|
||||
|
||||
fn msg(&self) -> DiagnosticMessage {
|
||||
|
@ -239,7 +239,7 @@ pub struct BuiltinUngatedAsyncFnTrackCaller<'a> {
|
|||
}
|
||||
|
||||
impl<'a> DecorateLint<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> {
|
||||
fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) {
|
||||
fn decorate_lint<'b>(self, diag: &'b mut DiagnosticBuilder<'a, ()>) {
|
||||
diag.span_label(self.label, fluent::lint_label);
|
||||
rustc_session::parse::add_feature_diagnostics(
|
||||
diag,
|
||||
|
@ -268,12 +268,9 @@ pub struct SuggestChangingAssocTypes<'a, 'b> {
|
|||
}
|
||||
|
||||
impl AddToDiagnostic for SuggestChangingAssocTypes<'_, '_> {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(
|
||||
&mut rustc_errors::Diagnostic,
|
||||
rustc_errors::SubdiagnosticMessage,
|
||||
) -> rustc_errors::SubdiagnosticMessage,
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
// Access to associates types should use `<T as Bound>::Assoc`, which does not need a
|
||||
// bound. Let's see if this type does that.
|
||||
|
@ -281,7 +278,7 @@ impl AddToDiagnostic for SuggestChangingAssocTypes<'_, '_> {
|
|||
// We use a HIR visitor to walk the type.
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
struct WalkAssocTypes<'a> {
|
||||
err: &'a mut rustc_errors::Diagnostic,
|
||||
err: &'a mut Diagnostic,
|
||||
}
|
||||
impl Visitor<'_> for WalkAssocTypes<'_> {
|
||||
fn visit_qpath(
|
||||
|
@ -326,12 +323,9 @@ pub struct BuiltinTypeAliasGenericBoundsSuggestion {
|
|||
}
|
||||
|
||||
impl AddToDiagnostic for BuiltinTypeAliasGenericBoundsSuggestion {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(
|
||||
&mut rustc_errors::Diagnostic,
|
||||
rustc_errors::SubdiagnosticMessage,
|
||||
) -> rustc_errors::SubdiagnosticMessage,
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
diag.multipart_suggestion(
|
||||
fluent::lint_suggestion,
|
||||
|
@ -425,8 +419,8 @@ pub struct BuiltinUnpermittedTypeInit<'a> {
|
|||
}
|
||||
|
||||
impl<'a> DecorateLint<'a, ()> for BuiltinUnpermittedTypeInit<'_> {
|
||||
fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) {
|
||||
diag.set_arg("ty", self.ty);
|
||||
fn decorate_lint<'b>(self, diag: &'b mut DiagnosticBuilder<'a, ()>) {
|
||||
diag.arg("ty", self.ty);
|
||||
diag.span_label(self.label, fluent::lint_builtin_unpermitted_type_init_label);
|
||||
if let InhabitedPredicate::True = self.ty.inhabited_predicate(self.tcx) {
|
||||
// Only suggest late `MaybeUninit::assume_init` initialization if the type is inhabited.
|
||||
|
@ -438,7 +432,7 @@ impl<'a> DecorateLint<'a, ()> for BuiltinUnpermittedTypeInit<'_> {
|
|||
self.sub.add_to_diagnostic(diag);
|
||||
}
|
||||
|
||||
fn msg(&self) -> rustc_errors::DiagnosticMessage {
|
||||
fn msg(&self) -> DiagnosticMessage {
|
||||
self.msg.clone()
|
||||
}
|
||||
}
|
||||
|
@ -449,12 +443,9 @@ pub struct BuiltinUnpermittedTypeInitSub {
|
|||
}
|
||||
|
||||
impl AddToDiagnostic for BuiltinUnpermittedTypeInitSub {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(
|
||||
&mut rustc_errors::Diagnostic,
|
||||
rustc_errors::SubdiagnosticMessage,
|
||||
) -> rustc_errors::SubdiagnosticMessage,
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
let mut err = self.err;
|
||||
loop {
|
||||
|
@ -506,12 +497,9 @@ pub struct BuiltinClashingExternSub<'a> {
|
|||
}
|
||||
|
||||
impl AddToDiagnostic for BuiltinClashingExternSub<'_> {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(
|
||||
&mut rustc_errors::Diagnostic,
|
||||
rustc_errors::SubdiagnosticMessage,
|
||||
) -> rustc_errors::SubdiagnosticMessage,
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
let mut expected_str = DiagnosticStyledString::new();
|
||||
expected_str.push(self.expected.fn_sig(self.tcx).to_string(), false);
|
||||
|
@ -779,12 +767,9 @@ pub struct HiddenUnicodeCodepointsDiagLabels {
|
|||
}
|
||||
|
||||
impl AddToDiagnostic for HiddenUnicodeCodepointsDiagLabels {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(
|
||||
&mut rustc_errors::Diagnostic,
|
||||
rustc_errors::SubdiagnosticMessage,
|
||||
) -> rustc_errors::SubdiagnosticMessage,
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
for (c, span) in self.spans {
|
||||
diag.span_label(span, format!("{c:?}"));
|
||||
|
@ -799,12 +784,9 @@ pub enum HiddenUnicodeCodepointsDiagSub {
|
|||
|
||||
// Used because of multiple multipart_suggestion and note
|
||||
impl AddToDiagnostic for HiddenUnicodeCodepointsDiagSub {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(
|
||||
&mut rustc_errors::Diagnostic,
|
||||
rustc_errors::SubdiagnosticMessage,
|
||||
) -> rustc_errors::SubdiagnosticMessage,
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
match self {
|
||||
HiddenUnicodeCodepointsDiagSub::Escape { spans } => {
|
||||
|
@ -830,7 +812,7 @@ impl AddToDiagnostic for HiddenUnicodeCodepointsDiagSub {
|
|||
// FIXME: in other suggestions we've reversed the inner spans of doc comments. We
|
||||
// should do the same here to provide the same good suggestions as we do for
|
||||
// literals above.
|
||||
diag.set_arg(
|
||||
diag.arg(
|
||||
"escaped",
|
||||
spans
|
||||
.into_iter()
|
||||
|
@ -953,12 +935,9 @@ pub struct NonBindingLetSub {
|
|||
}
|
||||
|
||||
impl AddToDiagnostic for NonBindingLetSub {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(
|
||||
&mut rustc_errors::Diagnostic,
|
||||
rustc_errors::SubdiagnosticMessage,
|
||||
) -> rustc_errors::SubdiagnosticMessage,
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
diag.span_suggestion_verbose(
|
||||
self.suggestion,
|
||||
|
@ -1147,8 +1126,8 @@ pub struct NonFmtPanicUnused {
|
|||
|
||||
// Used because of two suggestions based on one Option<Span>
|
||||
impl<'a> DecorateLint<'a, ()> for NonFmtPanicUnused {
|
||||
fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) {
|
||||
diag.set_arg("count", self.count);
|
||||
fn decorate_lint<'b>(self, diag: &'b mut DiagnosticBuilder<'a, ()>) {
|
||||
diag.arg("count", self.count);
|
||||
diag.note(fluent::lint_note);
|
||||
if let Some(span) = self.suggestion {
|
||||
diag.span_suggestion(
|
||||
|
@ -1166,7 +1145,7 @@ impl<'a> DecorateLint<'a, ()> for NonFmtPanicUnused {
|
|||
}
|
||||
}
|
||||
|
||||
fn msg(&self) -> rustc_errors::DiagnosticMessage {
|
||||
fn msg(&self) -> DiagnosticMessage {
|
||||
fluent::lint_non_fmt_panic_unused
|
||||
}
|
||||
}
|
||||
|
@ -1224,12 +1203,9 @@ pub enum NonSnakeCaseDiagSub {
|
|||
}
|
||||
|
||||
impl AddToDiagnostic for NonSnakeCaseDiagSub {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(
|
||||
&mut rustc_errors::Diagnostic,
|
||||
rustc_errors::SubdiagnosticMessage,
|
||||
) -> rustc_errors::SubdiagnosticMessage,
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
match self {
|
||||
NonSnakeCaseDiagSub::Label { span } => {
|
||||
|
@ -1342,12 +1318,12 @@ pub struct DropTraitConstraintsDiag<'a> {
|
|||
|
||||
// Needed for def_path_str
|
||||
impl<'a> DecorateLint<'a, ()> for DropTraitConstraintsDiag<'_> {
|
||||
fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) {
|
||||
diag.set_arg("predicate", self.predicate);
|
||||
diag.set_arg("needs_drop", self.tcx.def_path_str(self.def_id));
|
||||
fn decorate_lint<'b>(self, diag: &'b mut DiagnosticBuilder<'a, ()>) {
|
||||
diag.arg("predicate", self.predicate);
|
||||
diag.arg("needs_drop", self.tcx.def_path_str(self.def_id));
|
||||
}
|
||||
|
||||
fn msg(&self) -> rustc_errors::DiagnosticMessage {
|
||||
fn msg(&self) -> DiagnosticMessage {
|
||||
fluent::lint_drop_trait_constraints
|
||||
}
|
||||
}
|
||||
|
@ -1359,11 +1335,11 @@ pub struct DropGlue<'a> {
|
|||
|
||||
// Needed for def_path_str
|
||||
impl<'a> DecorateLint<'a, ()> for DropGlue<'_> {
|
||||
fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) {
|
||||
diag.set_arg("needs_drop", self.tcx.def_path_str(self.def_id));
|
||||
fn decorate_lint<'b>(self, diag: &'b mut DiagnosticBuilder<'a, ()>) {
|
||||
diag.arg("needs_drop", self.tcx.def_path_str(self.def_id));
|
||||
}
|
||||
|
||||
fn msg(&self) -> rustc_errors::DiagnosticMessage {
|
||||
fn msg(&self) -> DiagnosticMessage {
|
||||
fluent::lint_drop_glue
|
||||
}
|
||||
}
|
||||
|
@ -1423,12 +1399,9 @@ pub enum OverflowingBinHexSign {
|
|||
}
|
||||
|
||||
impl AddToDiagnostic for OverflowingBinHexSign {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(
|
||||
&mut rustc_errors::Diagnostic,
|
||||
rustc_errors::SubdiagnosticMessage,
|
||||
) -> rustc_errors::SubdiagnosticMessage,
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
match self {
|
||||
OverflowingBinHexSign::Positive => {
|
||||
|
@ -1633,9 +1606,9 @@ pub struct ImproperCTypes<'a> {
|
|||
|
||||
// Used because of the complexity of Option<DiagnosticMessage>, DiagnosticMessage, and Option<Span>
|
||||
impl<'a> DecorateLint<'a, ()> for ImproperCTypes<'_> {
|
||||
fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) {
|
||||
diag.set_arg("ty", self.ty);
|
||||
diag.set_arg("desc", self.desc);
|
||||
fn decorate_lint<'b>(self, diag: &'b mut DiagnosticBuilder<'a, ()>) {
|
||||
diag.arg("ty", self.ty);
|
||||
diag.arg("desc", self.desc);
|
||||
diag.span_label(self.label, fluent::lint_label);
|
||||
if let Some(help) = self.help {
|
||||
diag.help(help);
|
||||
|
@ -1646,7 +1619,7 @@ impl<'a> DecorateLint<'a, ()> for ImproperCTypes<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
fn msg(&self) -> rustc_errors::DiagnosticMessage {
|
||||
fn msg(&self) -> DiagnosticMessage {
|
||||
fluent::lint_improper_ctypes
|
||||
}
|
||||
}
|
||||
|
@ -1776,10 +1749,10 @@ pub enum UnusedDefSuggestion {
|
|||
|
||||
// Needed because of def_path_str
|
||||
impl<'a> DecorateLint<'a, ()> for UnusedDef<'_, '_> {
|
||||
fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) {
|
||||
diag.set_arg("pre", self.pre);
|
||||
diag.set_arg("post", self.post);
|
||||
diag.set_arg("def", self.cx.tcx.def_path_str(self.def_id));
|
||||
fn decorate_lint<'b>(self, diag: &'b mut DiagnosticBuilder<'a, ()>) {
|
||||
diag.arg("pre", self.pre);
|
||||
diag.arg("post", self.post);
|
||||
diag.arg("def", self.cx.tcx.def_path_str(self.def_id));
|
||||
// check for #[must_use = "..."]
|
||||
if let Some(note) = self.note {
|
||||
diag.note(note.to_string());
|
||||
|
@ -1789,7 +1762,7 @@ impl<'a> DecorateLint<'a, ()> for UnusedDef<'_, '_> {
|
|||
}
|
||||
}
|
||||
|
||||
fn msg(&self) -> rustc_errors::DiagnosticMessage {
|
||||
fn msg(&self) -> DiagnosticMessage {
|
||||
fluent::lint_unused_def
|
||||
}
|
||||
}
|
||||
|
@ -1859,14 +1832,14 @@ pub struct AsyncFnInTraitDiag {
|
|||
}
|
||||
|
||||
impl<'a> DecorateLint<'a, ()> for AsyncFnInTraitDiag {
|
||||
fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) {
|
||||
fn decorate_lint<'b>(self, diag: &'b mut DiagnosticBuilder<'a, ()>) {
|
||||
diag.note(fluent::lint_note);
|
||||
if let Some(sugg) = self.sugg {
|
||||
diag.multipart_suggestion(fluent::lint_suggestion, sugg, Applicability::MaybeIncorrect);
|
||||
}
|
||||
}
|
||||
|
||||
fn msg(&self) -> rustc_errors::DiagnosticMessage {
|
||||
fn msg(&self) -> DiagnosticMessage {
|
||||
fluent::lint_async_fn_in_trait
|
||||
}
|
||||
}
|
||||
|
|
|
@ -121,7 +121,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
|
|||
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
cx.struct_span_lint(NON_FMT_PANICS, arg_span, fluent::lint_non_fmt_panic, |lint| {
|
||||
lint.set_arg("name", symbol);
|
||||
lint.arg("name", symbol);
|
||||
lint.note(fluent::lint_note);
|
||||
lint.note(fluent::lint_more_info_note);
|
||||
if !is_arg_inside_call(arg_span, span) {
|
||||
|
@ -180,7 +180,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
|
|||
fmt_applicability,
|
||||
);
|
||||
} else if suggest_debug {
|
||||
lint.set_arg("ty", ty);
|
||||
lint.arg("ty", ty);
|
||||
lint.span_suggestion_verbose(
|
||||
arg_span.shrink_to_lo(),
|
||||
fluent::lint_debug_suggestion,
|
||||
|
@ -191,7 +191,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
|
|||
|
||||
if suggest_panic_any {
|
||||
if let Some((open, close, del)) = find_delimiters(cx, span) {
|
||||
lint.set_arg("already_suggested", suggest_display || suggest_debug);
|
||||
lint.arg("already_suggested", suggest_display || suggest_debug);
|
||||
lint.multipart_suggestion(
|
||||
fluent::lint_panic_suggestion,
|
||||
if del == '(' {
|
||||
|
|
|
@ -5,8 +5,8 @@ use crate::diagnostics::error::{
|
|||
};
|
||||
use crate::diagnostics::utils::{
|
||||
build_field_mapping, is_doc_comment, report_error_if_not_applied_to_span, report_type_error,
|
||||
should_generate_set_arg, type_is_bool, type_is_unit, type_matches_path, FieldInfo,
|
||||
FieldInnerTy, FieldMap, HasFieldMap, SetOnce, SpannedOption, SubdiagnosticKind,
|
||||
should_generate_arg, type_is_bool, type_is_unit, type_matches_path, FieldInfo, FieldInnerTy,
|
||||
FieldMap, HasFieldMap, SetOnce, SpannedOption, SubdiagnosticKind,
|
||||
};
|
||||
use proc_macro2::{Ident, Span, TokenStream};
|
||||
use quote::{format_ident, quote, quote_spanned};
|
||||
|
@ -125,15 +125,15 @@ impl DiagnosticDeriveVariantBuilder {
|
|||
}
|
||||
|
||||
/// Generates calls to `span_label` and similar functions based on the attributes on fields or
|
||||
/// calls to `set_arg` when no attributes are present.
|
||||
/// calls to `arg` when no attributes are present.
|
||||
pub(crate) fn body(&mut self, variant: &VariantInfo<'_>) -> TokenStream {
|
||||
let mut body = quote! {};
|
||||
// Generate `set_arg` calls first..
|
||||
for binding in variant.bindings().iter().filter(|bi| should_generate_set_arg(bi.ast())) {
|
||||
// Generate `arg` calls first..
|
||||
for binding in variant.bindings().iter().filter(|bi| should_generate_arg(bi.ast())) {
|
||||
body.extend(self.generate_field_code(binding));
|
||||
}
|
||||
// ..and then subdiagnostic additions.
|
||||
for binding in variant.bindings().iter().filter(|bi| !should_generate_set_arg(bi.ast())) {
|
||||
for binding in variant.bindings().iter().filter(|bi| !should_generate_arg(bi.ast())) {
|
||||
body.extend(self.generate_field_attrs_code(binding));
|
||||
}
|
||||
body
|
||||
|
@ -253,7 +253,7 @@ impl DiagnosticDeriveVariantBuilder {
|
|||
let ident = format_ident!("{}", ident); // strip `r#` prefix, if present
|
||||
|
||||
quote! {
|
||||
diag.set_arg(
|
||||
diag.arg(
|
||||
stringify!(#ident),
|
||||
#field_binding
|
||||
);
|
||||
|
@ -312,7 +312,7 @@ impl DiagnosticDeriveVariantBuilder {
|
|||
let name = ident.to_string();
|
||||
match (&attr.meta, name.as_str()) {
|
||||
// Don't need to do anything - by virtue of the attribute existing, the
|
||||
// `set_arg` call will not be generated.
|
||||
// `arg` call will not be generated.
|
||||
(Meta::Path(_), "skip_arg") => return Ok(quote! {}),
|
||||
(Meta::Path(_), "primary_span") => {
|
||||
match self.kind {
|
||||
|
@ -320,7 +320,7 @@ impl DiagnosticDeriveVariantBuilder {
|
|||
report_error_if_not_applied_to_span(attr, &info)?;
|
||||
|
||||
return Ok(quote! {
|
||||
diag.set_span(#binding);
|
||||
diag.span(#binding);
|
||||
});
|
||||
}
|
||||
DiagnosticDeriveKind::LintDiagnostic => {
|
||||
|
|
|
@ -6,8 +6,8 @@ use crate::diagnostics::error::{
|
|||
use crate::diagnostics::utils::{
|
||||
build_field_mapping, build_suggestion_code, is_doc_comment, new_code_ident,
|
||||
report_error_if_not_applied_to_applicability, report_error_if_not_applied_to_span,
|
||||
should_generate_set_arg, AllowMultipleAlternatives, FieldInfo, FieldInnerTy, FieldMap,
|
||||
HasFieldMap, SetOnce, SpannedOption, SubdiagnosticKind,
|
||||
should_generate_arg, AllowMultipleAlternatives, FieldInfo, FieldInnerTy, FieldMap, HasFieldMap,
|
||||
SetOnce, SpannedOption, SubdiagnosticKind,
|
||||
};
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
|
@ -214,7 +214,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
|
|||
}
|
||||
|
||||
/// Generates the code for a field with no attributes.
|
||||
fn generate_field_set_arg(&mut self, binding_info: &BindingInfo<'_>) -> TokenStream {
|
||||
fn generate_field_arg(&mut self, binding_info: &BindingInfo<'_>) -> TokenStream {
|
||||
let diag = &self.parent.diag;
|
||||
|
||||
let field = binding_info.ast();
|
||||
|
@ -225,7 +225,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
|
|||
let ident = format_ident!("{}", ident); // strip `r#` prefix, if present
|
||||
|
||||
quote! {
|
||||
#diag.set_arg(
|
||||
#diag.arg(
|
||||
stringify!(#ident),
|
||||
#field_binding
|
||||
);
|
||||
|
@ -505,7 +505,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
|
|||
.variant
|
||||
.bindings()
|
||||
.iter()
|
||||
.filter(|binding| !should_generate_set_arg(binding.ast()))
|
||||
.filter(|binding| !should_generate_arg(binding.ast()))
|
||||
.map(|binding| self.generate_field_attr_code(binding, kind_stats))
|
||||
.collect();
|
||||
|
||||
|
@ -593,8 +593,8 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
|
|||
.variant
|
||||
.bindings()
|
||||
.iter()
|
||||
.filter(|binding| should_generate_set_arg(binding.ast()))
|
||||
.map(|binding| self.generate_field_set_arg(binding))
|
||||
.filter(|binding| should_generate_arg(binding.ast()))
|
||||
.map(|binding| self.generate_field_arg(binding))
|
||||
.collect();
|
||||
|
||||
let formatting_init = &self.formatting_init;
|
||||
|
|
|
@ -584,7 +584,7 @@ pub(super) enum SubdiagnosticKind {
|
|||
suggestion_kind: SuggestionKind,
|
||||
applicability: SpannedOption<Applicability>,
|
||||
/// Identifier for variable used for formatted code, e.g. `___code_0`. Enables separation
|
||||
/// of formatting and diagnostic emission so that `set_arg` calls can happen in-between..
|
||||
/// of formatting and diagnostic emission so that `arg` calls can happen in-between..
|
||||
code_field: syn::Ident,
|
||||
/// Initialization logic for `code_field`'s variable, e.g.
|
||||
/// `let __formatted_code = /* whatever */;`
|
||||
|
@ -863,9 +863,9 @@ impl quote::IdentFragment for SubdiagnosticKind {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if `field` should generate a `set_arg` call rather than any other diagnostic
|
||||
/// Returns `true` if `field` should generate a `arg` call rather than any other diagnostic
|
||||
/// call (like `span_label`).
|
||||
pub(super) fn should_generate_set_arg(field: &Field) -> bool {
|
||||
pub(super) fn should_generate_arg(field: &Field) -> bool {
|
||||
// Perhaps this should be an exhaustive list...
|
||||
field.attrs.iter().all(|attr| is_doc_comment(attr))
|
||||
}
|
||||
|
|
|
@ -500,10 +500,10 @@ pub(crate) struct MultipleCandidates {
|
|||
impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for MultipleCandidates {
|
||||
fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> {
|
||||
let mut diag = DiagnosticBuilder::new(dcx, level, fluent::metadata_multiple_candidates);
|
||||
diag.set_arg("crate_name", self.crate_name);
|
||||
diag.set_arg("flavor", self.flavor);
|
||||
diag.arg("crate_name", self.crate_name);
|
||||
diag.arg("flavor", self.flavor);
|
||||
diag.code(error_code!(E0464));
|
||||
diag.set_span(self.span);
|
||||
diag.span(self.span);
|
||||
for (i, candidate) in self.candidates.iter().enumerate() {
|
||||
diag.note(format!("candidate #{}: {}", i + 1, candidate.display()));
|
||||
}
|
||||
|
@ -596,10 +596,10 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for InvalidMetadataFiles {
|
|||
#[track_caller]
|
||||
fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> {
|
||||
let mut diag = DiagnosticBuilder::new(dcx, level, fluent::metadata_invalid_meta_files);
|
||||
diag.set_arg("crate_name", self.crate_name);
|
||||
diag.set_arg("add_info", self.add_info);
|
||||
diag.arg("crate_name", self.crate_name);
|
||||
diag.arg("add_info", self.add_info);
|
||||
diag.code(error_code!(E0786));
|
||||
diag.set_span(self.span);
|
||||
diag.span(self.span);
|
||||
for crate_rejection in self.crate_rejections {
|
||||
diag.note(crate_rejection);
|
||||
}
|
||||
|
@ -623,12 +623,12 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for CannotFindCrate {
|
|||
#[track_caller]
|
||||
fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> {
|
||||
let mut diag = DiagnosticBuilder::new(dcx, level, fluent::metadata_cannot_find_crate);
|
||||
diag.set_arg("crate_name", self.crate_name);
|
||||
diag.set_arg("current_crate", self.current_crate);
|
||||
diag.set_arg("add_info", self.add_info);
|
||||
diag.set_arg("locator_triple", self.locator_triple.triple());
|
||||
diag.arg("crate_name", self.crate_name);
|
||||
diag.arg("current_crate", self.current_crate);
|
||||
diag.arg("add_info", self.add_info);
|
||||
diag.arg("locator_triple", self.locator_triple.triple());
|
||||
diag.code(error_code!(E0463));
|
||||
diag.set_span(self.span);
|
||||
diag.span(self.span);
|
||||
if (self.crate_name == sym::std || self.crate_name == sym::core)
|
||||
&& self.locator_triple != TargetTriple::from_triple(config::host_triple())
|
||||
{
|
||||
|
|
|
@ -314,14 +314,14 @@ pub fn struct_lint_level(
|
|||
}
|
||||
Level::ForceWarn(Some(expect_id)) => rustc_errors::Level::Warning(Some(expect_id)),
|
||||
Level::Warn | Level::ForceWarn(None) => rustc_errors::Level::Warning(None),
|
||||
Level::Deny | Level::Forbid => rustc_errors::Level::Error { lint: true },
|
||||
Level::Deny | Level::Forbid => rustc_errors::Level::Error,
|
||||
};
|
||||
let mut err = DiagnosticBuilder::new(sess.dcx(), err_level, "");
|
||||
if let Some(span) = span {
|
||||
err.set_span(span);
|
||||
err.span(span);
|
||||
}
|
||||
|
||||
err.set_is_lint();
|
||||
err.is_lint();
|
||||
|
||||
// If this code originates in a foreign macro, aka something that this crate
|
||||
// did not itself author, then it's likely that there's nothing this crate
|
||||
|
@ -348,7 +348,7 @@ pub fn struct_lint_level(
|
|||
|
||||
// Delay evaluating and setting the primary message until after we've
|
||||
// suppressed the lint due to macros.
|
||||
err.set_primary_message(msg);
|
||||
err.primary_message(msg);
|
||||
|
||||
// Lint diagnostics that are covered by the expect level will not be emitted outside
|
||||
// the compiler. It is therefore not necessary to add any information for the user.
|
||||
|
|
|
@ -2,14 +2,10 @@ use super::{AllocId, AllocRange, Pointer, Scalar};
|
|||
|
||||
use crate::error;
|
||||
use crate::mir::{ConstAlloc, ConstValue};
|
||||
use crate::query::TyCtxtAt;
|
||||
use crate::ty::{layout, tls, Ty, TyCtxt, ValTree};
|
||||
|
||||
use rustc_data_structures::sync::Lock;
|
||||
use rustc_errors::{
|
||||
struct_span_err, DiagnosticArgValue, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed,
|
||||
IntoDiagnosticArg,
|
||||
};
|
||||
use rustc_errors::{DiagnosticArgValue, DiagnosticMessage, ErrorGuaranteed, IntoDiagnosticArg};
|
||||
use rustc_macros::HashStable;
|
||||
use rustc_session::CtfeBacktrace;
|
||||
use rustc_span::{def_id::DefId, Span, DUMMY_SP};
|
||||
|
@ -90,10 +86,6 @@ pub type EvalToConstValueResult<'tcx> = Result<ConstValue<'tcx>, ErrorHandled>;
|
|||
/// This is needed in `thir::pattern::lower_inline_const`.
|
||||
pub type EvalToValTreeResult<'tcx> = Result<Option<ValTree<'tcx>>, ErrorHandled>;
|
||||
|
||||
pub fn struct_error<'tcx>(tcx: TyCtxtAt<'tcx>, msg: &str) -> DiagnosticBuilder<'tcx> {
|
||||
struct_span_err!(tcx.dcx(), tcx.span, E0080, "{}", msg)
|
||||
}
|
||||
|
||||
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
||||
static_assert_size!(InterpErrorInfo<'_>, 8);
|
||||
|
||||
|
|
|
@ -142,12 +142,11 @@ use crate::ty::GenericArgKind;
|
|||
use crate::ty::{self, Instance, Ty, TyCtxt};
|
||||
|
||||
pub use self::error::{
|
||||
struct_error, BadBytesAccess, CheckAlignMsg, CheckInAllocMsg, ErrorHandled,
|
||||
EvalToAllocationRawResult, EvalToConstValueResult, EvalToValTreeResult, ExpectedKind,
|
||||
InterpError, InterpErrorInfo, InterpResult, InvalidMetaKind, InvalidProgramInfo,
|
||||
MachineStopType, Misalignment, PointerKind, ReportedErrorInfo, ResourceExhaustionInfo,
|
||||
ScalarSizeMismatch, UndefinedBehaviorInfo, UnsupportedOpInfo, ValidationErrorInfo,
|
||||
ValidationErrorKind,
|
||||
BadBytesAccess, CheckAlignMsg, CheckInAllocMsg, ErrorHandled, EvalToAllocationRawResult,
|
||||
EvalToConstValueResult, EvalToValTreeResult, ExpectedKind, InterpError, InterpErrorInfo,
|
||||
InterpResult, InvalidMetaKind, InvalidProgramInfo, MachineStopType, Misalignment, PointerKind,
|
||||
ReportedErrorInfo, ResourceExhaustionInfo, ScalarSizeMismatch, UndefinedBehaviorInfo,
|
||||
UnsupportedOpInfo, ValidationErrorInfo, ValidationErrorKind,
|
||||
};
|
||||
|
||||
pub use self::value::Scalar;
|
||||
|
|
|
@ -55,7 +55,6 @@ pub mod mono;
|
|||
pub mod patch;
|
||||
pub mod pretty;
|
||||
mod query;
|
||||
pub mod spanview;
|
||||
mod statement;
|
||||
mod syntax;
|
||||
pub mod tcx;
|
||||
|
|
|
@ -5,7 +5,6 @@ use std::io::{self, Write as _};
|
|||
use std::path::{Path, PathBuf};
|
||||
|
||||
use super::graphviz::write_mir_fn_graphviz;
|
||||
use super::spanview::write_mir_fn_spanview;
|
||||
use rustc_ast::InlineAsmTemplatePiece;
|
||||
use rustc_middle::mir::interpret::{
|
||||
alloc_range, read_target_uint, AllocBytes, AllocId, Allocation, GlobalAlloc, Pointer,
|
||||
|
@ -141,16 +140,6 @@ fn dump_matched_mir_node<'tcx, F>(
|
|||
write_mir_fn_graphviz(tcx, body, false, &mut file)?;
|
||||
};
|
||||
}
|
||||
|
||||
if let Some(spanview) = tcx.sess.opts.unstable_opts.dump_mir_spanview {
|
||||
let _: io::Result<()> = try {
|
||||
let file_basename = dump_file_basename(tcx, pass_num, pass_name, disambiguator, body);
|
||||
let mut file = create_dump_file_with_basename(tcx, &file_basename, "html")?;
|
||||
if body.source.def_id().is_local() {
|
||||
write_mir_fn_spanview(tcx, body, spanview, &file_basename, &mut file)?;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the file basename portion (without extension) of a filename path
|
||||
|
|
|
@ -1,642 +0,0 @@
|
|||
use rustc_middle::hir;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_session::config::MirSpanview;
|
||||
use rustc_span::{BytePos, Pos};
|
||||
|
||||
use std::cmp;
|
||||
use std::io::{self, Write};
|
||||
|
||||
pub const TOOLTIP_INDENT: &str = " ";
|
||||
|
||||
const CARET: char = '\u{2038}'; // Unicode `CARET`
|
||||
const ANNOTATION_LEFT_BRACKET: char = '\u{298a}'; // Unicode `Z NOTATION RIGHT BINDING BRACKET`
|
||||
const ANNOTATION_RIGHT_BRACKET: char = '\u{2989}'; // Unicode `Z NOTATION LEFT BINDING BRACKET`
|
||||
const NEW_LINE_SPAN: &str = "</span>\n<span class=\"line\">";
|
||||
const HEADER: &str = r#"<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">"#;
|
||||
const START_BODY: &str = r#"</head>
|
||||
<body>"#;
|
||||
const FOOTER: &str = r#"</body>
|
||||
</html>"#;
|
||||
|
||||
const STYLE_SECTION: &str = r#"<style>
|
||||
.line {
|
||||
counter-increment: line;
|
||||
}
|
||||
.line:before {
|
||||
content: counter(line) ": ";
|
||||
font-family: Menlo, Monaco, monospace;
|
||||
font-style: italic;
|
||||
width: 3.8em;
|
||||
display: inline-block;
|
||||
text-align: right;
|
||||
filter: opacity(50%);
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
.code {
|
||||
color: #dddddd;
|
||||
background-color: #222222;
|
||||
font-family: Menlo, Monaco, monospace;
|
||||
line-height: 1.4em;
|
||||
border-bottom: 2px solid #222222;
|
||||
white-space: pre;
|
||||
display: inline-block;
|
||||
}
|
||||
.odd {
|
||||
background-color: #55bbff;
|
||||
color: #223311;
|
||||
}
|
||||
.even {
|
||||
background-color: #ee7756;
|
||||
color: #551133;
|
||||
}
|
||||
.code {
|
||||
--index: calc(var(--layer) - 1);
|
||||
padding-top: calc(var(--index) * 0.15em);
|
||||
filter:
|
||||
hue-rotate(calc(var(--index) * 25deg))
|
||||
saturate(calc(100% - (var(--index) * 2%)))
|
||||
brightness(calc(100% - (var(--index) * 1.5%)));
|
||||
}
|
||||
.annotation {
|
||||
color: #4444ff;
|
||||
font-family: monospace;
|
||||
font-style: italic;
|
||||
display: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
body:active .annotation {
|
||||
/* requires holding mouse down anywhere on the page */
|
||||
display: inline-block;
|
||||
}
|
||||
span:hover .annotation {
|
||||
/* requires hover over a span ONLY on its first line */
|
||||
display: inline-block;
|
||||
}
|
||||
</style>"#;
|
||||
|
||||
/// Metadata to highlight the span of a MIR BasicBlock, Statement, or Terminator.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SpanViewable {
|
||||
pub bb: BasicBlock,
|
||||
pub span: Span,
|
||||
pub id: String,
|
||||
pub tooltip: String,
|
||||
}
|
||||
|
||||
/// Write a spanview HTML+CSS file to analyze MIR element spans.
|
||||
pub fn write_mir_fn_spanview<'tcx, W>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
spanview: MirSpanview,
|
||||
title: &str,
|
||||
w: &mut W,
|
||||
) -> io::Result<()>
|
||||
where
|
||||
W: Write,
|
||||
{
|
||||
let def_id = body.source.def_id();
|
||||
let hir_body = hir_body(tcx, def_id);
|
||||
if hir_body.is_none() {
|
||||
return Ok(());
|
||||
}
|
||||
let body_span = hir_body.unwrap().value.span;
|
||||
let mut span_viewables = Vec::new();
|
||||
for (bb, data) in body.basic_blocks.iter_enumerated() {
|
||||
match spanview {
|
||||
MirSpanview::Statement => {
|
||||
for (i, statement) in data.statements.iter().enumerate() {
|
||||
if let Some(span_viewable) =
|
||||
statement_span_viewable(tcx, body_span, bb, i, statement)
|
||||
{
|
||||
span_viewables.push(span_viewable);
|
||||
}
|
||||
}
|
||||
if let Some(span_viewable) = terminator_span_viewable(tcx, body_span, bb, data) {
|
||||
span_viewables.push(span_viewable);
|
||||
}
|
||||
}
|
||||
MirSpanview::Terminator => {
|
||||
if let Some(span_viewable) = terminator_span_viewable(tcx, body_span, bb, data) {
|
||||
span_viewables.push(span_viewable);
|
||||
}
|
||||
}
|
||||
MirSpanview::Block => {
|
||||
if let Some(span_viewable) = block_span_viewable(tcx, body_span, bb, data) {
|
||||
span_viewables.push(span_viewable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
write_document(tcx, fn_span(tcx, def_id), span_viewables, title, w)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Generate a spanview HTML+CSS document for the given local function `def_id`, and a pre-generated
|
||||
/// list `SpanViewable`s.
|
||||
pub fn write_document<'tcx, W>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
spanview_span: Span,
|
||||
mut span_viewables: Vec<SpanViewable>,
|
||||
title: &str,
|
||||
w: &mut W,
|
||||
) -> io::Result<()>
|
||||
where
|
||||
W: Write,
|
||||
{
|
||||
let mut from_pos = spanview_span.lo();
|
||||
let end_pos = spanview_span.hi();
|
||||
let source_map = tcx.sess.source_map();
|
||||
let start = source_map.lookup_char_pos(from_pos);
|
||||
let indent_to_initial_start_col = " ".repeat(start.col.to_usize());
|
||||
debug!(
|
||||
"spanview_span={:?}; source is:\n{}{}",
|
||||
spanview_span,
|
||||
indent_to_initial_start_col,
|
||||
source_map.span_to_snippet(spanview_span).expect("function should have printable source")
|
||||
);
|
||||
writeln!(w, "{HEADER}")?;
|
||||
writeln!(w, "<title>{title}</title>")?;
|
||||
writeln!(w, "{STYLE_SECTION}")?;
|
||||
writeln!(w, "{START_BODY}")?;
|
||||
write!(
|
||||
w,
|
||||
r#"<div class="code" style="counter-reset: line {}"><span class="line">{}"#,
|
||||
start.line - 1,
|
||||
indent_to_initial_start_col,
|
||||
)?;
|
||||
span_viewables.sort_unstable_by(|a, b| {
|
||||
let a = a.span;
|
||||
let b = b.span;
|
||||
if a.lo() == b.lo() {
|
||||
// Sort hi() in reverse order so shorter spans are attempted after longer spans.
|
||||
// This should give shorter spans a higher "layer", so they are not covered by
|
||||
// the longer spans.
|
||||
b.hi().partial_cmp(&a.hi())
|
||||
} else {
|
||||
a.lo().partial_cmp(&b.lo())
|
||||
}
|
||||
.unwrap()
|
||||
});
|
||||
let mut ordered_viewables = &span_viewables[..];
|
||||
const LOWEST_VIEWABLE_LAYER: usize = 1;
|
||||
let mut alt = false;
|
||||
while ordered_viewables.len() > 0 {
|
||||
debug!(
|
||||
"calling write_next_viewable with from_pos={}, end_pos={}, and viewables len={}",
|
||||
from_pos.to_usize(),
|
||||
end_pos.to_usize(),
|
||||
ordered_viewables.len()
|
||||
);
|
||||
let curr_id = &ordered_viewables[0].id;
|
||||
let (next_from_pos, next_ordered_viewables) = write_next_viewable_with_overlaps(
|
||||
tcx,
|
||||
from_pos,
|
||||
end_pos,
|
||||
ordered_viewables,
|
||||
alt,
|
||||
LOWEST_VIEWABLE_LAYER,
|
||||
w,
|
||||
)?;
|
||||
debug!(
|
||||
"DONE calling write_next_viewable, with new from_pos={}, \
|
||||
and remaining viewables len={}",
|
||||
next_from_pos.to_usize(),
|
||||
next_ordered_viewables.len()
|
||||
);
|
||||
assert!(
|
||||
from_pos != next_from_pos || ordered_viewables.len() != next_ordered_viewables.len(),
|
||||
"write_next_viewable_with_overlaps() must make a state change"
|
||||
);
|
||||
from_pos = next_from_pos;
|
||||
if next_ordered_viewables.len() != ordered_viewables.len() {
|
||||
ordered_viewables = next_ordered_viewables;
|
||||
if let Some(next_ordered_viewable) = ordered_viewables.first() {
|
||||
if &next_ordered_viewable.id != curr_id {
|
||||
alt = !alt;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if from_pos < end_pos {
|
||||
write_coverage_gap(tcx, from_pos, end_pos, w)?;
|
||||
}
|
||||
writeln!(w, r#"</span></div>"#)?;
|
||||
writeln!(w, "{FOOTER}")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Format a string showing the start line and column, and end line and column within a file.
|
||||
pub fn source_range_no_file(tcx: TyCtxt<'_>, span: Span) -> String {
|
||||
let source_map = tcx.sess.source_map();
|
||||
let start = source_map.lookup_char_pos(span.lo());
|
||||
let end = source_map.lookup_char_pos(span.hi());
|
||||
format!("{}:{}-{}:{}", start.line, start.col.to_usize() + 1, end.line, end.col.to_usize() + 1)
|
||||
}
|
||||
|
||||
fn statement_span_viewable<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body_span: Span,
|
||||
bb: BasicBlock,
|
||||
i: usize,
|
||||
statement: &Statement<'tcx>,
|
||||
) -> Option<SpanViewable> {
|
||||
let span = statement.source_info.span;
|
||||
if !body_span.contains(span) {
|
||||
return None;
|
||||
}
|
||||
let id = format!("{}[{}]", bb.index(), i);
|
||||
let tooltip = tooltip(tcx, &id, span, vec![statement.clone()], &None);
|
||||
Some(SpanViewable { bb, span, id, tooltip })
|
||||
}
|
||||
|
||||
fn terminator_span_viewable<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body_span: Span,
|
||||
bb: BasicBlock,
|
||||
data: &BasicBlockData<'tcx>,
|
||||
) -> Option<SpanViewable> {
|
||||
let term = data.terminator();
|
||||
let span = term.source_info.span;
|
||||
if !body_span.contains(span) {
|
||||
return None;
|
||||
}
|
||||
let id = format!("{}:{}", bb.index(), term.kind.name());
|
||||
let tooltip = tooltip(tcx, &id, span, vec![], &data.terminator);
|
||||
Some(SpanViewable { bb, span, id, tooltip })
|
||||
}
|
||||
|
||||
fn block_span_viewable<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body_span: Span,
|
||||
bb: BasicBlock,
|
||||
data: &BasicBlockData<'tcx>,
|
||||
) -> Option<SpanViewable> {
|
||||
let span = compute_block_span(data, body_span);
|
||||
if !body_span.contains(span) {
|
||||
return None;
|
||||
}
|
||||
let id = format!("{}", bb.index());
|
||||
let tooltip = tooltip(tcx, &id, span, data.statements.clone(), &data.terminator);
|
||||
Some(SpanViewable { bb, span, id, tooltip })
|
||||
}
|
||||
|
||||
fn compute_block_span(data: &BasicBlockData<'_>, body_span: Span) -> Span {
|
||||
let mut span = data.terminator().source_info.span;
|
||||
for statement_span in data.statements.iter().map(|statement| statement.source_info.span) {
|
||||
// Only combine Spans from the root context, and within the function's body_span.
|
||||
if statement_span.ctxt().is_root() && body_span.contains(statement_span) {
|
||||
span = span.to(statement_span);
|
||||
}
|
||||
}
|
||||
span
|
||||
}
|
||||
|
||||
/// Recursively process each ordered span. Spans that overlap will have progressively varying
|
||||
/// styles, such as increased padding for each overlap. Non-overlapping adjacent spans will
|
||||
/// have alternating style choices, to help distinguish between them if, visually adjacent.
|
||||
/// The `layer` is incremented for each overlap, and the `alt` bool alternates between true
|
||||
/// and false, for each adjacent non-overlapping span. Source code between the spans (code
|
||||
/// that is not in any coverage region) has neutral styling.
|
||||
fn write_next_viewable_with_overlaps<'tcx, 'b, W>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
mut from_pos: BytePos,
|
||||
mut to_pos: BytePos,
|
||||
ordered_viewables: &'b [SpanViewable],
|
||||
alt: bool,
|
||||
layer: usize,
|
||||
w: &mut W,
|
||||
) -> io::Result<(BytePos, &'b [SpanViewable])>
|
||||
where
|
||||
W: Write,
|
||||
{
|
||||
let debug_indent = " ".repeat(layer);
|
||||
let (viewable, mut remaining_viewables) =
|
||||
ordered_viewables.split_first().expect("ordered_viewables should have some");
|
||||
|
||||
if from_pos < viewable.span.lo() {
|
||||
debug!(
|
||||
"{}advance from_pos to next SpanViewable (from from_pos={} to viewable.span.lo()={} \
|
||||
of {:?}), with to_pos={}",
|
||||
debug_indent,
|
||||
from_pos.to_usize(),
|
||||
viewable.span.lo().to_usize(),
|
||||
viewable.span,
|
||||
to_pos.to_usize()
|
||||
);
|
||||
let hi = cmp::min(viewable.span.lo(), to_pos);
|
||||
write_coverage_gap(tcx, from_pos, hi, w)?;
|
||||
from_pos = hi;
|
||||
if from_pos < viewable.span.lo() {
|
||||
debug!(
|
||||
"{}EARLY RETURN: stopped before getting to next SpanViewable, at {}",
|
||||
debug_indent,
|
||||
from_pos.to_usize()
|
||||
);
|
||||
return Ok((from_pos, ordered_viewables));
|
||||
}
|
||||
}
|
||||
|
||||
if from_pos < viewable.span.hi() {
|
||||
// Set to_pos to the end of this `viewable` to ensure the recursive calls stop writing
|
||||
// with room to print the tail.
|
||||
to_pos = cmp::min(viewable.span.hi(), to_pos);
|
||||
debug!(
|
||||
"{}update to_pos (if not closer) to viewable.span.hi()={}; to_pos is now {}",
|
||||
debug_indent,
|
||||
viewable.span.hi().to_usize(),
|
||||
to_pos.to_usize()
|
||||
);
|
||||
}
|
||||
|
||||
let mut subalt = false;
|
||||
while remaining_viewables.len() > 0 && remaining_viewables[0].span.overlaps(viewable.span) {
|
||||
let overlapping_viewable = &remaining_viewables[0];
|
||||
debug!("{}overlapping_viewable.span={:?}", debug_indent, overlapping_viewable.span);
|
||||
|
||||
let span =
|
||||
trim_span(viewable.span, from_pos, cmp::min(overlapping_viewable.span.lo(), to_pos));
|
||||
let mut some_html_snippet = if from_pos <= viewable.span.hi() || viewable.span.is_empty() {
|
||||
// `viewable` is not yet fully rendered, so start writing the span, up to either the
|
||||
// `to_pos` or the next `overlapping_viewable`, whichever comes first.
|
||||
debug!(
|
||||
"{}make html_snippet (may not write it if early exit) for partial span {:?} \
|
||||
of viewable.span {:?}",
|
||||
debug_indent, span, viewable.span
|
||||
);
|
||||
from_pos = span.hi();
|
||||
make_html_snippet(tcx, span, Some(viewable))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// Defer writing the HTML snippet (until after early return checks) ONLY for empty spans.
|
||||
// An empty Span with Some(html_snippet) is probably a tail marker. If there is an early
|
||||
// exit, there should be another opportunity to write the tail marker.
|
||||
if !span.is_empty() {
|
||||
if let Some(ref html_snippet) = some_html_snippet {
|
||||
debug!(
|
||||
"{}write html_snippet for that partial span of viewable.span {:?}",
|
||||
debug_indent, viewable.span
|
||||
);
|
||||
write_span(html_snippet, &viewable.tooltip, alt, layer, w)?;
|
||||
}
|
||||
some_html_snippet = None;
|
||||
}
|
||||
|
||||
if from_pos < overlapping_viewable.span.lo() {
|
||||
debug!(
|
||||
"{}EARLY RETURN: from_pos={} has not yet reached the \
|
||||
overlapping_viewable.span {:?}",
|
||||
debug_indent,
|
||||
from_pos.to_usize(),
|
||||
overlapping_viewable.span
|
||||
);
|
||||
// must have reached `to_pos` before reaching the start of the
|
||||
// `overlapping_viewable.span`
|
||||
return Ok((from_pos, ordered_viewables));
|
||||
}
|
||||
|
||||
if from_pos == to_pos
|
||||
&& !(from_pos == overlapping_viewable.span.lo() && overlapping_viewable.span.is_empty())
|
||||
{
|
||||
debug!(
|
||||
"{}EARLY RETURN: from_pos=to_pos={} and overlapping_viewable.span {:?} is not \
|
||||
empty, or not from_pos",
|
||||
debug_indent,
|
||||
to_pos.to_usize(),
|
||||
overlapping_viewable.span
|
||||
);
|
||||
// `to_pos` must have occurred before the overlapping viewable. Return
|
||||
// `ordered_viewables` so we can continue rendering the `viewable`, from after the
|
||||
// `to_pos`.
|
||||
return Ok((from_pos, ordered_viewables));
|
||||
}
|
||||
|
||||
if let Some(ref html_snippet) = some_html_snippet {
|
||||
debug!(
|
||||
"{}write html_snippet for that partial span of viewable.span {:?}",
|
||||
debug_indent, viewable.span
|
||||
);
|
||||
write_span(html_snippet, &viewable.tooltip, alt, layer, w)?;
|
||||
}
|
||||
|
||||
debug!(
|
||||
"{}recursively calling write_next_viewable with from_pos={}, to_pos={}, \
|
||||
and viewables len={}",
|
||||
debug_indent,
|
||||
from_pos.to_usize(),
|
||||
to_pos.to_usize(),
|
||||
remaining_viewables.len()
|
||||
);
|
||||
// Write the overlaps (and the overlaps' overlaps, if any) up to `to_pos`.
|
||||
let curr_id = &remaining_viewables[0].id;
|
||||
let (next_from_pos, next_remaining_viewables) = write_next_viewable_with_overlaps(
|
||||
tcx,
|
||||
from_pos,
|
||||
to_pos,
|
||||
remaining_viewables,
|
||||
subalt,
|
||||
layer + 1,
|
||||
w,
|
||||
)?;
|
||||
debug!(
|
||||
"{}DONE recursively calling write_next_viewable, with new from_pos={}, and remaining \
|
||||
viewables len={}",
|
||||
debug_indent,
|
||||
next_from_pos.to_usize(),
|
||||
next_remaining_viewables.len()
|
||||
);
|
||||
assert!(
|
||||
from_pos != next_from_pos
|
||||
|| remaining_viewables.len() != next_remaining_viewables.len(),
|
||||
"write_next_viewable_with_overlaps() must make a state change"
|
||||
);
|
||||
from_pos = next_from_pos;
|
||||
if next_remaining_viewables.len() != remaining_viewables.len() {
|
||||
remaining_viewables = next_remaining_viewables;
|
||||
if let Some(next_ordered_viewable) = remaining_viewables.first() {
|
||||
if &next_ordered_viewable.id != curr_id {
|
||||
subalt = !subalt;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if from_pos <= viewable.span.hi() {
|
||||
let span = trim_span(viewable.span, from_pos, to_pos);
|
||||
debug!(
|
||||
"{}After overlaps, writing (end span?) {:?} of viewable.span {:?}",
|
||||
debug_indent, span, viewable.span
|
||||
);
|
||||
if let Some(ref html_snippet) = make_html_snippet(tcx, span, Some(viewable)) {
|
||||
from_pos = span.hi();
|
||||
write_span(html_snippet, &viewable.tooltip, alt, layer, w)?;
|
||||
}
|
||||
}
|
||||
debug!("{}RETURN: No more overlap", debug_indent);
|
||||
Ok((
|
||||
from_pos,
|
||||
if from_pos < viewable.span.hi() { ordered_viewables } else { remaining_viewables },
|
||||
))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn write_coverage_gap<W>(tcx: TyCtxt<'_>, lo: BytePos, hi: BytePos, w: &mut W) -> io::Result<()>
|
||||
where
|
||||
W: Write,
|
||||
{
|
||||
let span = Span::with_root_ctxt(lo, hi);
|
||||
if let Some(ref html_snippet) = make_html_snippet(tcx, span, None) {
|
||||
write_span(html_snippet, "", false, 0, w)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn write_span<W>(
|
||||
html_snippet: &str,
|
||||
tooltip: &str,
|
||||
alt: bool,
|
||||
layer: usize,
|
||||
w: &mut W,
|
||||
) -> io::Result<()>
|
||||
where
|
||||
W: Write,
|
||||
{
|
||||
let maybe_alt_class = if layer > 0 { if alt { " odd" } else { " even" } } else { "" };
|
||||
let maybe_title_attr = if !tooltip.is_empty() {
|
||||
format!(" title=\"{}\"", escape_attr(tooltip))
|
||||
} else {
|
||||
"".to_owned()
|
||||
};
|
||||
if layer == 1 {
|
||||
write!(w, "<span>")?;
|
||||
}
|
||||
for (i, line) in html_snippet.lines().enumerate() {
|
||||
if i > 0 {
|
||||
write!(w, "{NEW_LINE_SPAN}")?;
|
||||
}
|
||||
write!(
|
||||
w,
|
||||
r#"<span class="code{maybe_alt_class}" style="--layer: {layer}"{maybe_title_attr}>{line}</span>"#
|
||||
)?;
|
||||
}
|
||||
// Check for and translate trailing newlines, because `str::lines()` ignores them
|
||||
if html_snippet.ends_with('\n') {
|
||||
write!(w, "{NEW_LINE_SPAN}")?;
|
||||
}
|
||||
if layer == 1 {
|
||||
write!(w, "</span>")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn make_html_snippet(
|
||||
tcx: TyCtxt<'_>,
|
||||
span: Span,
|
||||
some_viewable: Option<&SpanViewable>,
|
||||
) -> Option<String> {
|
||||
let source_map = tcx.sess.source_map();
|
||||
let snippet = source_map
|
||||
.span_to_snippet(span)
|
||||
.unwrap_or_else(|err| bug!("span_to_snippet error for span {:?}: {:?}", span, err));
|
||||
let html_snippet = if let Some(viewable) = some_viewable {
|
||||
let is_head = span.lo() == viewable.span.lo();
|
||||
let is_tail = span.hi() == viewable.span.hi();
|
||||
let mut labeled_snippet = if is_head {
|
||||
format!(r#"<span class="annotation">{}{}</span>"#, viewable.id, ANNOTATION_LEFT_BRACKET)
|
||||
} else {
|
||||
"".to_owned()
|
||||
};
|
||||
if span.is_empty() {
|
||||
if is_head && is_tail {
|
||||
labeled_snippet.push(CARET);
|
||||
}
|
||||
} else {
|
||||
labeled_snippet.push_str(&escape_html(&snippet));
|
||||
};
|
||||
if is_tail {
|
||||
labeled_snippet.push_str(&format!(
|
||||
r#"<span class="annotation">{}{}</span>"#,
|
||||
ANNOTATION_RIGHT_BRACKET, viewable.id
|
||||
));
|
||||
}
|
||||
labeled_snippet
|
||||
} else {
|
||||
escape_html(&snippet)
|
||||
};
|
||||
if html_snippet.is_empty() { None } else { Some(html_snippet) }
|
||||
}
|
||||
|
||||
fn tooltip<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
spanview_id: &str,
|
||||
span: Span,
|
||||
statements: Vec<Statement<'tcx>>,
|
||||
terminator: &Option<Terminator<'tcx>>,
|
||||
) -> String {
|
||||
let source_map = tcx.sess.source_map();
|
||||
let mut text = Vec::new();
|
||||
text.push(format!("{}: {}:", spanview_id, &source_map.span_to_embeddable_string(span)));
|
||||
for statement in statements {
|
||||
let source_range = source_range_no_file(tcx, statement.source_info.span);
|
||||
text.push(format!(
|
||||
"\n{}{}: {}: {:?}",
|
||||
TOOLTIP_INDENT,
|
||||
source_range,
|
||||
statement.kind.name(),
|
||||
statement
|
||||
));
|
||||
}
|
||||
if let Some(term) = terminator {
|
||||
let source_range = source_range_no_file(tcx, term.source_info.span);
|
||||
text.push(format!(
|
||||
"\n{}{}: {}: {:?}",
|
||||
TOOLTIP_INDENT,
|
||||
source_range,
|
||||
term.kind.name(),
|
||||
term.kind
|
||||
));
|
||||
}
|
||||
text.join("")
|
||||
}
|
||||
|
||||
fn trim_span(span: Span, from_pos: BytePos, to_pos: BytePos) -> Span {
|
||||
trim_span_hi(trim_span_lo(span, from_pos), to_pos)
|
||||
}
|
||||
|
||||
fn trim_span_lo(span: Span, from_pos: BytePos) -> Span {
|
||||
if from_pos <= span.lo() { span } else { span.with_lo(cmp::min(span.hi(), from_pos)) }
|
||||
}
|
||||
|
||||
fn trim_span_hi(span: Span, to_pos: BytePos) -> Span {
|
||||
if to_pos >= span.hi() { span } else { span.with_hi(cmp::max(span.lo(), to_pos)) }
|
||||
}
|
||||
|
||||
fn fn_span(tcx: TyCtxt<'_>, def_id: DefId) -> Span {
|
||||
let fn_decl_span = tcx.def_span(def_id);
|
||||
if let Some(body_span) = hir_body(tcx, def_id).map(|hir_body| hir_body.value.span) {
|
||||
if fn_decl_span.eq_ctxt(body_span) { fn_decl_span.to(body_span) } else { body_span }
|
||||
} else {
|
||||
fn_decl_span
|
||||
}
|
||||
}
|
||||
|
||||
fn hir_body(tcx: TyCtxt<'_>, def_id: DefId) -> Option<&rustc_hir::Body<'_>> {
|
||||
let hir_node = tcx.hir().get_if_local(def_id).expect("expected DefId is local");
|
||||
hir::map::associated_body(hir_node).map(|(_, fn_body_id)| tcx.hir().body(fn_body_id))
|
||||
}
|
||||
|
||||
fn escape_html(s: &str) -> String {
|
||||
s.replace('&', "&").replace('<', "<").replace('>', ">")
|
||||
}
|
||||
|
||||
fn escape_attr(s: &str) -> String {
|
||||
s.replace('&', "&")
|
||||
.replace('\"', """)
|
||||
.replace('\'', "'")
|
||||
.replace('<', "<")
|
||||
.replace('>', ">")
|
||||
}
|
|
@ -289,7 +289,7 @@ pub enum ObligationCauseCode<'tcx> {
|
|||
/// Type of each variable must be `Sized`.
|
||||
VariableType(hir::HirId),
|
||||
/// Argument type must be `Sized`.
|
||||
SizedArgumentType(Option<Span>),
|
||||
SizedArgumentType(Option<hir::HirId>),
|
||||
/// Return type must be `Sized`.
|
||||
SizedReturnType,
|
||||
/// Yield type must be `Sized`.
|
||||
|
|
|
@ -467,11 +467,11 @@ impl<'a> IntoDiagnostic<'a> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> {
|
|||
level,
|
||||
fluent::mir_build_non_exhaustive_patterns_type_not_empty,
|
||||
);
|
||||
diag.set_span(self.span);
|
||||
diag.span(self.span);
|
||||
diag.code(error_code!(E0004));
|
||||
let peeled_ty = self.ty.peel_refs();
|
||||
diag.set_arg("ty", self.ty);
|
||||
diag.set_arg("peeled_ty", peeled_ty);
|
||||
diag.arg("ty", self.ty);
|
||||
diag.arg("peeled_ty", peeled_ty);
|
||||
|
||||
if let ty::Adt(def, _) = peeled_ty.kind() {
|
||||
let def_span = self
|
||||
|
@ -855,7 +855,7 @@ impl<'tcx> AddToDiagnostic for AdtDefinedHere<'tcx> {
|
|||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
diag.set_arg("ty", self.ty);
|
||||
diag.arg("ty", self.ty);
|
||||
let mut spans = MultiSpan::from(self.adt_def_span);
|
||||
|
||||
for Variant { span } in self.variants {
|
||||
|
|
|
@ -133,7 +133,6 @@
|
|||
|
||||
use std::collections::hash_map::{Entry, OccupiedEntry};
|
||||
|
||||
use crate::simplify::remove_dead_blocks;
|
||||
use crate::MirPass;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_index::bit_set::BitSet;
|
||||
|
@ -241,12 +240,6 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation {
|
|||
apply_merges(body, tcx, &merges, &merged_locals);
|
||||
}
|
||||
|
||||
if round_count != 0 {
|
||||
// Merging can introduce overlap between moved arguments and/or call destination in an
|
||||
// unreachable code, which validator considers to be ill-formed.
|
||||
remove_dead_blocks(body);
|
||||
}
|
||||
|
||||
trace!(round_count);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,11 +67,11 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for RequiresUnsafe {
|
|||
fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> {
|
||||
let mut diag = DiagnosticBuilder::new(dcx, level, fluent::mir_transform_requires_unsafe);
|
||||
diag.code(rustc_errors::DiagnosticId::Error("E0133".to_string()));
|
||||
diag.set_span(self.span);
|
||||
diag.span(self.span);
|
||||
diag.span_label(self.span, self.details.label());
|
||||
let desc = dcx.eagerly_translate_to_string(self.details.label(), [].into_iter());
|
||||
diag.set_arg("details", desc);
|
||||
diag.set_arg("op_in_unsafe_fn_allowed", self.op_in_unsafe_fn_allowed);
|
||||
diag.arg("details", desc);
|
||||
diag.arg("op_in_unsafe_fn_allowed", self.op_in_unsafe_fn_allowed);
|
||||
self.details.add_subdiagnostics(&mut diag);
|
||||
if let Some(sp) = self.enclosing {
|
||||
diag.span_label(sp, fluent::mir_transform_not_inherited);
|
||||
|
@ -122,16 +122,16 @@ impl RequiresUnsafeDetail {
|
|||
}
|
||||
CallToFunctionWith { ref missing, ref build_enabled } => {
|
||||
diag.help(fluent::mir_transform_target_feature_call_help);
|
||||
diag.set_arg(
|
||||
diag.arg(
|
||||
"missing_target_features",
|
||||
DiagnosticArgValue::StrListSepByAnd(
|
||||
missing.iter().map(|feature| Cow::from(feature.as_str())).collect(),
|
||||
),
|
||||
);
|
||||
diag.set_arg("missing_target_features_count", missing.len());
|
||||
diag.arg("missing_target_features_count", missing.len());
|
||||
if !build_enabled.is_empty() {
|
||||
diag.note(fluent::mir_transform_target_feature_call_note);
|
||||
diag.set_arg(
|
||||
diag.arg(
|
||||
"build_target_features",
|
||||
DiagnosticArgValue::StrListSepByAnd(
|
||||
build_enabled
|
||||
|
@ -140,7 +140,7 @@ impl RequiresUnsafeDetail {
|
|||
.collect(),
|
||||
),
|
||||
);
|
||||
diag.set_arg("build_target_features_count", build_enabled.len());
|
||||
diag.arg("build_target_features_count", build_enabled.len());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -183,7 +183,7 @@ impl<'a> DecorateLint<'a, ()> for UnsafeOpInUnsafeFn {
|
|||
fn decorate_lint<'b>(self, diag: &'b mut DiagnosticBuilder<'a, ()>) {
|
||||
let dcx = diag.dcx().expect("lint should not yet be emitted");
|
||||
let desc = dcx.eagerly_translate_to_string(self.details.label(), [].into_iter());
|
||||
diag.set_arg("details", desc);
|
||||
diag.arg("details", desc);
|
||||
diag.span_label(self.details.span, self.details.label());
|
||||
self.details.add_subdiagnostics(diag);
|
||||
|
||||
|
@ -213,7 +213,7 @@ impl<'a, P: std::fmt::Debug> DecorateLint<'a, ()> for AssertLint<P> {
|
|||
let assert_kind = self.panic();
|
||||
let message = assert_kind.diagnostic_message();
|
||||
assert_kind.add_args(&mut |name, value| {
|
||||
diag.set_arg(name, value);
|
||||
diag.arg(name, value);
|
||||
});
|
||||
diag.span_label(span, message);
|
||||
}
|
||||
|
@ -280,9 +280,9 @@ impl<'a> DecorateLint<'a, ()> for MustNotSupend<'_, '_> {
|
|||
diag.subdiagnostic(reason);
|
||||
}
|
||||
diag.span_help(self.src_sp, fluent::_subdiag::help);
|
||||
diag.set_arg("pre", self.pre);
|
||||
diag.set_arg("def_path", self.tcx.def_path_str(self.def_id));
|
||||
diag.set_arg("post", self.post);
|
||||
diag.arg("pre", self.pre);
|
||||
diag.arg("def_path", self.tcx.def_path_str(self.def_id));
|
||||
diag.arg("post", self.post);
|
||||
}
|
||||
|
||||
fn msg(&self) -> rustc_errors::DiagnosticMessage {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
//! This pass statically detects code which has undefined behaviour or is likely to be erroneous.
|
||||
//! It can be used to locate problems in MIR building or optimizations. It assumes that all code
|
||||
//! can be executed, so it has false positives.
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_index::bit_set::BitSet;
|
||||
use rustc_middle::mir::visit::{PlaceContext, Visitor};
|
||||
use rustc_middle::mir::*;
|
||||
|
@ -11,7 +12,6 @@ use rustc_mir_dataflow::{Analysis, ResultsCursor};
|
|||
use std::borrow::Cow;
|
||||
|
||||
pub fn lint_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, when: String) {
|
||||
let reachable_blocks = traversal::reachable_as_bitset(body);
|
||||
let always_live_locals = &always_storage_live_locals(body);
|
||||
|
||||
let maybe_storage_live = MaybeStorageLive::new(Cow::Borrowed(always_live_locals))
|
||||
|
@ -24,17 +24,19 @@ pub fn lint_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, when: String) {
|
|||
.iterate_to_fixpoint()
|
||||
.into_results_cursor(body);
|
||||
|
||||
Lint {
|
||||
let mut lint = Lint {
|
||||
tcx,
|
||||
when,
|
||||
body,
|
||||
is_fn_like: tcx.def_kind(body.source.def_id()).is_fn_like(),
|
||||
always_live_locals,
|
||||
reachable_blocks,
|
||||
maybe_storage_live,
|
||||
maybe_storage_dead,
|
||||
places: Default::default(),
|
||||
};
|
||||
for (bb, data) in traversal::reachable(body) {
|
||||
lint.visit_basic_block_data(bb, data);
|
||||
}
|
||||
.visit_body(body);
|
||||
}
|
||||
|
||||
struct Lint<'a, 'tcx> {
|
||||
|
@ -43,9 +45,9 @@ struct Lint<'a, 'tcx> {
|
|||
body: &'a Body<'tcx>,
|
||||
is_fn_like: bool,
|
||||
always_live_locals: &'a BitSet<Local>,
|
||||
reachable_blocks: BitSet<BasicBlock>,
|
||||
maybe_storage_live: ResultsCursor<'a, 'tcx, MaybeStorageLive<'a>>,
|
||||
maybe_storage_dead: ResultsCursor<'a, 'tcx, MaybeStorageDead<'a>>,
|
||||
places: FxHashSet<PlaceRef<'tcx>>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Lint<'a, 'tcx> {
|
||||
|
@ -67,7 +69,7 @@ impl<'a, 'tcx> Lint<'a, 'tcx> {
|
|||
|
||||
impl<'a, 'tcx> Visitor<'tcx> for Lint<'a, 'tcx> {
|
||||
fn visit_local(&mut self, local: Local, context: PlaceContext, location: Location) {
|
||||
if self.reachable_blocks.contains(location.block) && context.is_use() {
|
||||
if context.is_use() {
|
||||
self.maybe_storage_dead.seek_after_primary_effect(location);
|
||||
if self.maybe_storage_dead.get().contains(local) {
|
||||
self.fail(location, format!("use of local {local:?}, which has no storage here"));
|
||||
|
@ -76,18 +78,28 @@ impl<'a, 'tcx> Visitor<'tcx> for Lint<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
|
||||
match statement.kind {
|
||||
StatementKind::StorageLive(local) => {
|
||||
if self.reachable_blocks.contains(location.block) {
|
||||
self.maybe_storage_live.seek_before_primary_effect(location);
|
||||
if self.maybe_storage_live.get().contains(local) {
|
||||
match &statement.kind {
|
||||
StatementKind::Assign(box (dest, rvalue)) => {
|
||||
if let Rvalue::Use(Operand::Copy(src) | Operand::Move(src)) = rvalue {
|
||||
// The sides of an assignment must not alias. Currently this just checks whether
|
||||
// the places are identical.
|
||||
if dest == src {
|
||||
self.fail(
|
||||
location,
|
||||
format!("StorageLive({local:?}) which already has storage here"),
|
||||
"encountered `Assign` statement with overlapping memory",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
StatementKind::StorageLive(local) => {
|
||||
self.maybe_storage_live.seek_before_primary_effect(location);
|
||||
if self.maybe_storage_live.get().contains(*local) {
|
||||
self.fail(
|
||||
location,
|
||||
format!("StorageLive({local:?}) which already has storage here"),
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
|
@ -95,9 +107,9 @@ impl<'a, 'tcx> Visitor<'tcx> for Lint<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
|
||||
match terminator.kind {
|
||||
match &terminator.kind {
|
||||
TerminatorKind::Return => {
|
||||
if self.is_fn_like && self.reachable_blocks.contains(location.block) {
|
||||
if self.is_fn_like {
|
||||
self.maybe_storage_live.seek_after_primary_effect(location);
|
||||
for local in self.maybe_storage_live.get().iter() {
|
||||
if !self.always_live_locals.contains(local) {
|
||||
|
@ -111,6 +123,28 @@ impl<'a, 'tcx> Visitor<'tcx> for Lint<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
TerminatorKind::Call { args, destination, .. } => {
|
||||
// The call destination place and Operand::Move place used as an argument might be
|
||||
// passed by a reference to the callee. Consequently they must be non-overlapping.
|
||||
// Currently this simply checks for duplicate places.
|
||||
self.places.clear();
|
||||
self.places.insert(destination.as_ref());
|
||||
let mut has_duplicates = false;
|
||||
for arg in args {
|
||||
if let Operand::Move(place) = arg {
|
||||
has_duplicates |= !self.places.insert(place.as_ref());
|
||||
}
|
||||
}
|
||||
if has_duplicates {
|
||||
self.fail(
|
||||
location,
|
||||
format!(
|
||||
"encountered overlapping memory in `Move` arguments to `Call` terminator: {:?}",
|
||||
terminator.kind,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
|
|
|
@ -109,14 +109,15 @@ fn run_passes_inner<'tcx>(
|
|||
phase_change: Option<MirPhase>,
|
||||
validate_each: bool,
|
||||
) {
|
||||
let lint = tcx.sess.opts.unstable_opts.lint_mir & !body.should_skip();
|
||||
let validate = validate_each & tcx.sess.opts.unstable_opts.validate_mir & !body.should_skip();
|
||||
let overridden_passes = &tcx.sess.opts.unstable_opts.mir_enable_passes;
|
||||
trace!(?overridden_passes);
|
||||
|
||||
let prof_arg = tcx.sess.prof.enabled().then(|| format!("{:?}", body.source.def_id()));
|
||||
|
||||
if !body.should_skip() {
|
||||
let validate = validate_each & tcx.sess.opts.unstable_opts.validate_mir;
|
||||
let lint = tcx.sess.opts.unstable_opts.lint_mir;
|
||||
|
||||
for pass in passes {
|
||||
let name = pass.name();
|
||||
|
||||
|
@ -162,7 +163,12 @@ fn run_passes_inner<'tcx>(
|
|||
body.pass_count = 0;
|
||||
|
||||
dump_mir_for_phase_change(tcx, body);
|
||||
if validate || new_phase == MirPhase::Runtime(RuntimePhase::Optimized) {
|
||||
|
||||
let validate =
|
||||
(validate_each & tcx.sess.opts.unstable_opts.validate_mir & !body.should_skip())
|
||||
|| new_phase == MirPhase::Runtime(RuntimePhase::Optimized);
|
||||
let lint = tcx.sess.opts.unstable_opts.lint_mir & !body.should_skip();
|
||||
if validate {
|
||||
validate_body(tcx, body, format!("after phase change to {}", new_phase.name()));
|
||||
}
|
||||
if lint {
|
||||
|
|
|
@ -51,7 +51,7 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for UnusedGenericParamsHint {
|
|||
fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> {
|
||||
let mut diag =
|
||||
DiagnosticBuilder::new(dcx, level, fluent::monomorphize_unused_generic_params);
|
||||
diag.set_span(self.span);
|
||||
diag.span(self.span);
|
||||
for (span, name) in self.param_spans.into_iter().zip(self.param_names) {
|
||||
// FIXME: I can figure out how to do a label with a fluent string with a fixed message,
|
||||
// or a label with a dynamic value in a hard-coded string, but I haven't figured out
|
||||
|
|
|
@ -1065,8 +1065,8 @@ impl<'a> IntoDiagnostic<'a> for ExpectedIdentifier {
|
|||
None => fluent::parse_expected_identifier_found_str,
|
||||
},
|
||||
);
|
||||
diag.set_span(self.span);
|
||||
diag.set_arg("token", self.token);
|
||||
diag.span(self.span);
|
||||
diag.arg("token", self.token);
|
||||
|
||||
if let Some(sugg) = self.suggest_raw {
|
||||
sugg.add_to_diagnostic(&mut diag);
|
||||
|
@ -1123,8 +1123,8 @@ impl<'a> IntoDiagnostic<'a> for ExpectedSemi {
|
|||
None => fluent::parse_expected_semi_found_str,
|
||||
},
|
||||
);
|
||||
diag.set_span(self.span);
|
||||
diag.set_arg("token", self.token);
|
||||
diag.span(self.span);
|
||||
diag.arg("token", self.token);
|
||||
|
||||
if let Some(unexpected_token_label) = self.unexpected_token_label {
|
||||
diag.span_label(unexpected_token_label, fluent::parse_label_unexpected_token);
|
||||
|
|
|
@ -7,9 +7,7 @@ use rustc_ast::ast::{self, AttrStyle};
|
|||
use rustc_ast::token::{self, CommentKind, Delimiter, Token, TokenKind};
|
||||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_ast::util::unicode::contains_text_flow_control_chars;
|
||||
use rustc_errors::{
|
||||
error_code, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, FatalAbort, StashKey,
|
||||
};
|
||||
use rustc_errors::{error_code, Applicability, DiagCtxt, Diagnostic, StashKey};
|
||||
use rustc_lexer::unescape::{self, EscapeError, Mode};
|
||||
use rustc_lexer::{Base, DocStyle, RawStrError};
|
||||
use rustc_lexer::{Cursor, LiteralKind};
|
||||
|
@ -252,7 +250,7 @@ impl<'a> StringReader<'a> {
|
|||
if starts_with_number {
|
||||
let span = self.mk_sp(start, self.pos);
|
||||
let mut diag = self.dcx().struct_err("lifetimes cannot start with a number");
|
||||
diag.set_span(span);
|
||||
diag.span(span);
|
||||
diag.stash(span, StashKey::LifetimeIsChar);
|
||||
}
|
||||
let ident = Symbol::intern(lifetime_name);
|
||||
|
@ -344,18 +342,6 @@ impl<'a> StringReader<'a> {
|
|||
token::Ident(sym, false)
|
||||
}
|
||||
|
||||
fn struct_fatal_span_char(
|
||||
&self,
|
||||
from_pos: BytePos,
|
||||
to_pos: BytePos,
|
||||
m: &str,
|
||||
c: char,
|
||||
) -> DiagnosticBuilder<'a, FatalAbort> {
|
||||
self.sess
|
||||
.dcx
|
||||
.struct_span_fatal(self.mk_sp(from_pos, to_pos), format!("{}: {}", m, escaped_char(c)))
|
||||
}
|
||||
|
||||
/// Detect usages of Unicode codepoints changing the direction of the text on screen and loudly
|
||||
/// complain about it.
|
||||
fn lint_unicode_text_flow(&self, start: BytePos) {
|
||||
|
@ -568,13 +554,16 @@ impl<'a> StringReader<'a> {
|
|||
}
|
||||
|
||||
fn report_non_started_raw_string(&self, start: BytePos, bad_char: char) -> ! {
|
||||
self.struct_fatal_span_char(
|
||||
start,
|
||||
self.pos,
|
||||
"found invalid character; only `#` is allowed in raw string delimitation",
|
||||
bad_char,
|
||||
)
|
||||
.emit()
|
||||
self.sess
|
||||
.dcx
|
||||
.struct_span_fatal(
|
||||
self.mk_sp(start, self.pos),
|
||||
format!(
|
||||
"found invalid character; only `#` is allowed in raw string delimitation: {}",
|
||||
escaped_char(bad_char)
|
||||
),
|
||||
)
|
||||
.emit()
|
||||
}
|
||||
|
||||
fn report_unterminated_raw_string(
|
||||
|
|
|
@ -154,7 +154,7 @@ fn try_file_to_source_file(
|
|||
let msg = format!("couldn't read {}: {}", path.display(), e);
|
||||
let mut diag = Diagnostic::new(Level::Fatal, msg);
|
||||
if let Some(sp) = spanopt {
|
||||
diag.set_span(sp);
|
||||
diag.span(sp);
|
||||
}
|
||||
diag
|
||||
})
|
||||
|
|
|
@ -174,7 +174,7 @@ impl<'a> Parser<'a> {
|
|||
) {
|
||||
Ok(Some(item)) => {
|
||||
// FIXME(#100717)
|
||||
err.set_arg("item", item.kind.descr());
|
||||
err.arg("item", item.kind.descr());
|
||||
err.span_label(item.span, fluent::parse_label_does_not_annotate_this);
|
||||
err.span_suggestion_verbose(
|
||||
replacement_span,
|
||||
|
|
|
@ -846,7 +846,7 @@ impl<'a> Parser<'a> {
|
|||
) =>
|
||||
{
|
||||
let n_hashes: u8 = *n_hashes;
|
||||
err.set_primary_message("too many `#` when terminating raw string");
|
||||
err.primary_message("too many `#` when terminating raw string");
|
||||
let str_span = self.prev_token.span;
|
||||
let mut span = self.token.span;
|
||||
let mut count = 0;
|
||||
|
@ -857,7 +857,7 @@ impl<'a> Parser<'a> {
|
|||
self.bump();
|
||||
count += 1;
|
||||
}
|
||||
err.set_span(span);
|
||||
err.span(span);
|
||||
err.span_suggestion(
|
||||
span,
|
||||
format!("remove the extra `#`{}", pluralize!(count)),
|
||||
|
|
|
@ -925,9 +925,8 @@ impl<'a> Parser<'a> {
|
|||
});
|
||||
}
|
||||
|
||||
expect_err.set_primary_message(
|
||||
"closure bodies that contain statements must be surrounded by braces",
|
||||
);
|
||||
expect_err
|
||||
.primary_message("closure bodies that contain statements must be surrounded by braces");
|
||||
|
||||
let preceding_pipe_span = closure_spans.closing_pipe;
|
||||
let following_token_span = self.token.span;
|
||||
|
@ -951,7 +950,7 @@ impl<'a> Parser<'a> {
|
|||
);
|
||||
expect_err.span_note(second_note, "the closure body may be incorrectly delimited");
|
||||
|
||||
expect_err.set_span(vec![preceding_pipe_span, following_token_span]);
|
||||
expect_err.span(vec![preceding_pipe_span, following_token_span]);
|
||||
|
||||
let opening_suggestion_str = " {".to_string();
|
||||
let closing_suggestion_str = "}".to_string();
|
||||
|
|
|
@ -2341,17 +2341,17 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
match terr {
|
||||
TypeError::ArgumentMutability(idx) | TypeError::ArgumentSorts(_, idx) => {
|
||||
if let Some(ty) = hir_sig.decl.inputs.get(idx) {
|
||||
diag.set_span(ty.span);
|
||||
diag.span(ty.span);
|
||||
cause.span = ty.span;
|
||||
} else if idx == hir_sig.decl.inputs.len() {
|
||||
let span = hir_sig.decl.output.span();
|
||||
diag.set_span(span);
|
||||
diag.span(span);
|
||||
cause.span = span;
|
||||
}
|
||||
}
|
||||
TypeError::ArgCount => {
|
||||
if let Some(ty) = hir_sig.decl.inputs.get(expected_sig.inputs().len()) {
|
||||
diag.set_span(ty.span);
|
||||
diag.span(ty.span);
|
||||
cause.span = ty.span;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -868,8 +868,8 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for InvalidAttrAtCrateLevel {
|
|||
fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> {
|
||||
let mut diag =
|
||||
DiagnosticBuilder::new(dcx, level, fluent::passes_invalid_attr_at_crate_level);
|
||||
diag.set_span(self.span);
|
||||
diag.set_arg("name", self.name);
|
||||
diag.span(self.span);
|
||||
diag.arg("name", self.name);
|
||||
// Only emit an error with a suggestion if we can create a string out
|
||||
// of the attribute span
|
||||
if let Some(span) = self.sugg_span {
|
||||
|
@ -881,7 +881,7 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for InvalidAttrAtCrateLevel {
|
|||
);
|
||||
}
|
||||
if let Some(item) = self.item {
|
||||
diag.set_arg("kind", item.kind);
|
||||
diag.arg("kind", item.kind);
|
||||
diag.span_label(item.span, fluent::passes_invalid_attr_at_crate_level_item);
|
||||
}
|
||||
diag
|
||||
|
@ -1018,9 +1018,9 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'_, G> for BreakNonLoop<'a> {
|
|||
#[track_caller]
|
||||
fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> {
|
||||
let mut diag = DiagnosticBuilder::new(dcx, level, fluent::passes_break_non_loop);
|
||||
diag.set_span(self.span);
|
||||
diag.span(self.span);
|
||||
diag.code(error_code!(E0571));
|
||||
diag.set_arg("kind", self.kind);
|
||||
diag.arg("kind", self.kind);
|
||||
diag.span_label(self.span, fluent::passes_label);
|
||||
if let Some(head) = self.head {
|
||||
diag.span_label(head, fluent::passes_label2);
|
||||
|
@ -1162,7 +1162,7 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for NakedFunctionsAsmBlock {
|
|||
#[track_caller]
|
||||
fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> {
|
||||
let mut diag = DiagnosticBuilder::new(dcx, level, fluent::passes_naked_functions_asm_block);
|
||||
diag.set_span(self.span);
|
||||
diag.span(self.span);
|
||||
diag.code(error_code!(E0787));
|
||||
for span in self.multiple_asms.iter() {
|
||||
diag.span_label(*span, fluent::passes_label_multiple_asm);
|
||||
|
@ -1273,11 +1273,11 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for NoMainErr {
|
|||
#[track_caller]
|
||||
fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> {
|
||||
let mut diag = DiagnosticBuilder::new(dcx, level, fluent::passes_no_main_function);
|
||||
diag.set_span(DUMMY_SP);
|
||||
diag.span(DUMMY_SP);
|
||||
diag.code(error_code!(E0601));
|
||||
diag.set_arg("crate_name", self.crate_name);
|
||||
diag.set_arg("filename", self.filename);
|
||||
diag.set_arg("has_filename", self.has_filename);
|
||||
diag.arg("crate_name", self.crate_name);
|
||||
diag.arg("filename", self.filename);
|
||||
diag.arg("has_filename", self.has_filename);
|
||||
let note = if !self.non_main_fns.is_empty() {
|
||||
for &span in &self.non_main_fns {
|
||||
diag.span_note(span, fluent::passes_here_is_main);
|
||||
|
@ -1294,7 +1294,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for NoMainErr {
|
|||
if self.file_empty {
|
||||
diag.note(note);
|
||||
} else {
|
||||
diag.set_span(self.sp.shrink_to_hi());
|
||||
diag.span(self.sp.shrink_to_hi());
|
||||
diag.span_label(self.sp.shrink_to_hi(), note);
|
||||
}
|
||||
|
||||
|
@ -1340,15 +1340,15 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for DuplicateLangItem {
|
|||
},
|
||||
);
|
||||
diag.code(error_code!(E0152));
|
||||
diag.set_arg("lang_item_name", self.lang_item_name);
|
||||
diag.set_arg("crate_name", self.crate_name);
|
||||
diag.set_arg("dependency_of", self.dependency_of);
|
||||
diag.set_arg("path", self.path);
|
||||
diag.set_arg("orig_crate_name", self.orig_crate_name);
|
||||
diag.set_arg("orig_dependency_of", self.orig_dependency_of);
|
||||
diag.set_arg("orig_path", self.orig_path);
|
||||
diag.arg("lang_item_name", self.lang_item_name);
|
||||
diag.arg("crate_name", self.crate_name);
|
||||
diag.arg("dependency_of", self.dependency_of);
|
||||
diag.arg("path", self.path);
|
||||
diag.arg("orig_crate_name", self.orig_crate_name);
|
||||
diag.arg("orig_dependency_of", self.orig_dependency_of);
|
||||
diag.arg("orig_path", self.orig_path);
|
||||
if let Some(span) = self.local_span {
|
||||
diag.set_span(span);
|
||||
diag.span(span);
|
||||
}
|
||||
if let Some(span) = self.first_defined_span {
|
||||
diag.span_note(span, fluent::passes_first_defined_span);
|
||||
|
|
|
@ -204,7 +204,7 @@ pub(crate) fn lint_nonexhaustive_missing_variants<'a, 'p, 'tcx>(
|
|||
|
||||
use rustc_errors::DecorateLint;
|
||||
let mut err = rcx.tcx.dcx().struct_span_warn(arm.pat.data().unwrap().span, "");
|
||||
err.set_primary_message(decorator.msg());
|
||||
err.primary_message(decorator.msg());
|
||||
decorator.decorate_lint(&mut err);
|
||||
err.emit();
|
||||
}
|
||||
|
|
|
@ -1383,7 +1383,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
|
|||
| PathSource::TupleStruct(span, _) => {
|
||||
// We want the main underline to cover the suggested code as well for
|
||||
// cleaner output.
|
||||
err.set_span(*span);
|
||||
err.span(*span);
|
||||
*span
|
||||
}
|
||||
_ => span,
|
||||
|
@ -1615,7 +1615,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
|
|||
let field_spans = match source {
|
||||
// e.g. `if let Enum::TupleVariant(field1, field2) = _`
|
||||
PathSource::TupleStruct(_, pattern_spans) => {
|
||||
err.set_primary_message(
|
||||
err.primary_message(
|
||||
"cannot match against a tuple struct which contains private fields",
|
||||
);
|
||||
|
||||
|
@ -1628,7 +1628,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
|
|||
span: call_span,
|
||||
..
|
||||
})) => {
|
||||
err.set_primary_message(
|
||||
err.primary_message(
|
||||
"cannot initialize a tuple struct which contains private fields",
|
||||
);
|
||||
self.suggest_alternative_construction_methods(
|
||||
|
|
|
@ -125,21 +125,6 @@ pub enum LtoCli {
|
|||
Unspecified,
|
||||
}
|
||||
|
||||
/// The different settings that the `-Z dump_mir_spanview` flag can have. `Statement` generates a
|
||||
/// document highlighting each span of every statement (including terminators). `Terminator` and
|
||||
/// `Block` highlight a single span per `BasicBlock`: the span of the block's `Terminator`, or a
|
||||
/// computed span for the block, representing the entire range, covering the block's terminator and
|
||||
/// all of its statements.
|
||||
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
|
||||
pub enum MirSpanview {
|
||||
/// Default `-Z dump_mir_spanview` or `-Z dump_mir_spanview=statement`
|
||||
Statement,
|
||||
/// `-Z dump_mir_spanview=terminator`
|
||||
Terminator,
|
||||
/// `-Z dump_mir_spanview=block`
|
||||
Block,
|
||||
}
|
||||
|
||||
/// The different settings that the `-C instrument-coverage` flag can have.
|
||||
///
|
||||
/// Coverage instrumentation now supports combining `-C instrument-coverage`
|
||||
|
@ -1162,7 +1147,6 @@ impl UnstableOptions {
|
|||
can_emit_warnings,
|
||||
treat_err_as_bug: self.treat_err_as_bug,
|
||||
dont_buffer_diagnostics: self.dont_buffer_diagnostics,
|
||||
report_delayed_bugs: self.report_delayed_bugs,
|
||||
macro_backtrace: self.macro_backtrace,
|
||||
deduplicate_diagnostics: self.deduplicate_diagnostics,
|
||||
track_diagnostics: self.track_diagnostics,
|
||||
|
@ -2051,23 +2035,14 @@ fn check_error_format_stability(
|
|||
early_dcx: &mut EarlyDiagCtxt,
|
||||
unstable_opts: &UnstableOptions,
|
||||
error_format: ErrorOutputType,
|
||||
json_rendered: HumanReadableErrorType,
|
||||
) {
|
||||
if !unstable_opts.unstable_options {
|
||||
if let ErrorOutputType::Json { pretty: true, json_rendered } = error_format {
|
||||
early_dcx.abort_if_error_and_set_error_format(ErrorOutputType::Json {
|
||||
pretty: false,
|
||||
json_rendered,
|
||||
});
|
||||
if let ErrorOutputType::Json { pretty: true, .. } = error_format {
|
||||
early_dcx.early_fatal("`--error-format=pretty-json` is unstable");
|
||||
}
|
||||
if let ErrorOutputType::HumanReadable(HumanReadableErrorType::AnnotateSnippet(_)) =
|
||||
error_format
|
||||
{
|
||||
early_dcx.abort_if_error_and_set_error_format(ErrorOutputType::Json {
|
||||
pretty: false,
|
||||
json_rendered,
|
||||
});
|
||||
early_dcx.early_fatal("`--error-format=human-annotate-rs` is unstable");
|
||||
}
|
||||
}
|
||||
|
@ -2665,7 +2640,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
|
|||
let mut unstable_opts = UnstableOptions::build(early_dcx, matches);
|
||||
let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(early_dcx, matches);
|
||||
|
||||
check_error_format_stability(early_dcx, &unstable_opts, error_format, json_rendered);
|
||||
check_error_format_stability(early_dcx, &unstable_opts, error_format);
|
||||
|
||||
if !unstable_opts.unstable_options && json_unused_externs.is_enabled() {
|
||||
early_dcx.early_fatal(
|
||||
|
|
|
@ -19,7 +19,7 @@ impl<'a> IntoDiagnostic<'a> for FeatureGateError {
|
|||
#[track_caller]
|
||||
fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a> {
|
||||
let mut diag = DiagnosticBuilder::new(dcx, level, self.explain);
|
||||
diag.set_span(self.span);
|
||||
diag.span(self.span);
|
||||
diag.code(error_code!(E0658));
|
||||
diag
|
||||
}
|
||||
|
|
|
@ -391,7 +391,6 @@ mod desc {
|
|||
pub const parse_strip: &str = "either `none`, `debuginfo`, or `symbols`";
|
||||
pub const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavorCli::one_of();
|
||||
pub const parse_optimization_fuel: &str = "crate=integer";
|
||||
pub const parse_mir_spanview: &str = "`statement` (default), `terminator`, or `block`";
|
||||
pub const parse_dump_mono_stats: &str = "`markdown` (default) or `json`";
|
||||
pub const parse_instrument_coverage: &str =
|
||||
"`all` (default), `branch`, `except-unused-generics`, `except-unused-functions`, or `off`";
|
||||
|
@ -866,29 +865,6 @@ mod parse {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn parse_mir_spanview(slot: &mut Option<MirSpanview>, v: Option<&str>) -> bool {
|
||||
if v.is_some() {
|
||||
let mut bool_arg = None;
|
||||
if parse_opt_bool(&mut bool_arg, v) {
|
||||
*slot = bool_arg.unwrap().then_some(MirSpanview::Statement);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
let Some(v) = v else {
|
||||
*slot = Some(MirSpanview::Statement);
|
||||
return true;
|
||||
};
|
||||
|
||||
*slot = Some(match v.trim_end_matches('s') {
|
||||
"statement" | "stmt" => MirSpanview::Statement,
|
||||
"terminator" | "term" => MirSpanview::Terminator,
|
||||
"block" | "basicblock" => MirSpanview::Block,
|
||||
_ => return false,
|
||||
});
|
||||
true
|
||||
}
|
||||
|
||||
pub(crate) fn parse_time_passes_format(slot: &mut TimePassesFormat, v: Option<&str>) -> bool {
|
||||
match v {
|
||||
None => true,
|
||||
|
@ -1601,11 +1577,6 @@ options! {
|
|||
"exclude the pass number when dumping MIR (used in tests) (default: no)"),
|
||||
dump_mir_graphviz: bool = (false, parse_bool, [UNTRACKED],
|
||||
"in addition to `.mir` files, create graphviz `.dot` files (default: no)"),
|
||||
dump_mir_spanview: Option<MirSpanview> = (None, parse_mir_spanview, [UNTRACKED],
|
||||
"in addition to `.mir` files, create `.html` files to view spans for \
|
||||
all `statement`s (including terminators), only `terminator` spans, or \
|
||||
computed `block` spans (one span encompassing a block's terminator and \
|
||||
all statements)."),
|
||||
dump_mono_stats: SwitchWithOptPath = (SwitchWithOptPath::Disabled,
|
||||
parse_switch_with_opt_path, [UNTRACKED],
|
||||
"output statistics about monomorphization collection"),
|
||||
|
@ -1841,8 +1812,6 @@ options! {
|
|||
remark_dir: Option<PathBuf> = (None, parse_opt_pathbuf, [UNTRACKED],
|
||||
"directory into which to write optimization remarks (if not specified, they will be \
|
||||
written to standard error output)"),
|
||||
report_delayed_bugs: bool = (false, parse_bool, [TRACKED],
|
||||
"immediately print bugs registered with `span_delayed_bug` (default: no)"),
|
||||
sanitizer: SanitizerSet = (SanitizerSet::empty(), parse_sanitizers, [TRACKED],
|
||||
"use a sanitizer"),
|
||||
sanitizer_cfi_canonical_jump_tables: Option<bool> = (Some(true), parse_opt_bool, [TRACKED],
|
||||
|
|
|
@ -17,8 +17,8 @@ use rustc_data_structures::profiling::{SelfProfiler, SelfProfilerRef};
|
|||
use rustc_data_structures::sync::{
|
||||
AtomicU64, DynSend, DynSync, Lock, Lrc, OneThread, Ordering::SeqCst,
|
||||
};
|
||||
use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitterWriter;
|
||||
use rustc_errors::emitter::{DynEmitter, EmitterWriter, HumanReadableErrorType};
|
||||
use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitter;
|
||||
use rustc_errors::emitter::{DynEmitter, HumanEmitter, HumanReadableErrorType};
|
||||
use rustc_errors::json::JsonEmitter;
|
||||
use rustc_errors::registry::Registry;
|
||||
use rustc_errors::{
|
||||
|
@ -1000,7 +1000,7 @@ fn default_emitter(
|
|||
let (short, color_config) = kind.unzip();
|
||||
|
||||
if let HumanReadableErrorType::AnnotateSnippet(_) = kind {
|
||||
let emitter = AnnotateSnippetEmitterWriter::new(
|
||||
let emitter = AnnotateSnippetEmitter::new(
|
||||
Some(source_map),
|
||||
bundle,
|
||||
fallback_bundle,
|
||||
|
@ -1009,7 +1009,7 @@ fn default_emitter(
|
|||
);
|
||||
Box::new(emitter.ui_testing(sopts.unstable_opts.ui_testing))
|
||||
} else {
|
||||
let emitter = EmitterWriter::stderr(color_config, fallback_bundle)
|
||||
let emitter = HumanEmitter::stderr(color_config, fallback_bundle)
|
||||
.fluent_bundle(bundle)
|
||||
.sm(Some(source_map))
|
||||
.short_message(short)
|
||||
|
@ -1504,7 +1504,7 @@ fn mk_emitter(output: ErrorOutputType) -> Box<DynEmitter> {
|
|||
let emitter: Box<DynEmitter> = match output {
|
||||
config::ErrorOutputType::HumanReadable(kind) => {
|
||||
let (short, color_config) = kind.unzip();
|
||||
Box::new(EmitterWriter::stderr(color_config, fallback_bundle).short_message(short))
|
||||
Box::new(HumanEmitter::stderr(color_config, fallback_bundle).short_message(short))
|
||||
}
|
||||
config::ErrorOutputType::Json { pretty, json_rendered } => Box::new(JsonEmitter::basic(
|
||||
pretty,
|
||||
|
|
|
@ -19,7 +19,7 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for TestOutput {
|
|||
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
let mut diag = DiagnosticBuilder::new(dcx, level, format!("{kind}({content})"));
|
||||
diag.set_span(span);
|
||||
diag.span(span);
|
||||
diag
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,12 +66,9 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for NegativePositiveConflict<'_
|
|||
) -> rustc_errors::DiagnosticBuilder<'_, G> {
|
||||
let mut diag =
|
||||
DiagnosticBuilder::new(dcx, level, fluent::trait_selection_negative_positive_conflict);
|
||||
diag.set_arg("trait_desc", self.trait_desc.print_only_trait_path().to_string());
|
||||
diag.set_arg(
|
||||
"self_desc",
|
||||
self.self_ty.map_or_else(|| "none".to_string(), |ty| ty.to_string()),
|
||||
);
|
||||
diag.set_span(self.impl_span);
|
||||
diag.arg("trait_desc", self.trait_desc.print_only_trait_path().to_string());
|
||||
diag.arg("self_desc", self.self_ty.map_or_else(|| "none".to_string(), |ty| ty.to_string()));
|
||||
diag.span(self.impl_span);
|
||||
diag.code(rustc_errors::error_code!(E0751));
|
||||
match self.negative_impl_span {
|
||||
Ok(span) => {
|
||||
|
@ -79,7 +76,7 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for NegativePositiveConflict<'_
|
|||
}
|
||||
Err(cname) => {
|
||||
diag.note(fluent::trait_selection_negative_implementation_in_crate);
|
||||
diag.set_arg("negative_impl_cname", cname.to_string());
|
||||
diag.arg("negative_impl_cname", cname.to_string());
|
||||
}
|
||||
}
|
||||
match self.positive_impl_span {
|
||||
|
@ -88,7 +85,7 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for NegativePositiveConflict<'_
|
|||
}
|
||||
Err(cname) => {
|
||||
diag.note(fluent::trait_selection_positive_implementation_in_crate);
|
||||
diag.set_arg("positive_impl_cname", cname.to_string());
|
||||
diag.arg("positive_impl_cname", cname.to_string());
|
||||
}
|
||||
}
|
||||
diag
|
||||
|
@ -115,7 +112,7 @@ impl AddToDiagnostic for AdjustSignatureBorrow {
|
|||
{
|
||||
match self {
|
||||
AdjustSignatureBorrow::Borrow { to_borrow } => {
|
||||
diag.set_arg("len", to_borrow.len());
|
||||
diag.arg("len", to_borrow.len());
|
||||
diag.multipart_suggestion_verbose(
|
||||
fluent::trait_selection_adjust_signature_borrow,
|
||||
to_borrow,
|
||||
|
@ -123,7 +120,7 @@ impl AddToDiagnostic for AdjustSignatureBorrow {
|
|||
);
|
||||
}
|
||||
AdjustSignatureBorrow::RemoveBorrow { remove_borrow } => {
|
||||
diag.set_arg("len", remove_borrow.len());
|
||||
diag.arg("len", remove_borrow.len());
|
||||
diag.multipart_suggestion_verbose(
|
||||
fluent::trait_selection_adjust_signature_remove_borrow,
|
||||
remove_borrow,
|
||||
|
|
|
@ -19,11 +19,10 @@ use rustc_errors::{
|
|||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::intravisit::{Map, Visitor};
|
||||
use rustc_hir::is_range_literal;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource, Node};
|
||||
use rustc_hir::{Expr, HirId};
|
||||
use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, HirId, Node};
|
||||
use rustc_infer::infer::error_reporting::TypeErrCtxt;
|
||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk};
|
||||
|
@ -2008,7 +2007,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
};
|
||||
|
||||
err.code(error_code!(E0746));
|
||||
err.set_primary_message("return type cannot have an unboxed trait object");
|
||||
err.primary_message("return type cannot have an unboxed trait object");
|
||||
err.children.clear();
|
||||
|
||||
let span = obligation.cause.span;
|
||||
|
@ -2713,7 +2712,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
if name == sym::Send { ("`Send`", "sent") } else { ("`Sync`", "shared") };
|
||||
|
||||
err.clear_code();
|
||||
err.set_primary_message(format!(
|
||||
err.primary_message(format!(
|
||||
"{future_or_coroutine} cannot be {trait_verb} between threads safely"
|
||||
));
|
||||
|
||||
|
@ -2801,7 +2800,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
.unwrap_or_else(|| format!("{future_or_coroutine} is not {trait_name}"));
|
||||
|
||||
span.push_span_label(original_span, message);
|
||||
err.set_span(span);
|
||||
err.span(span);
|
||||
|
||||
format!("is not {trait_name}")
|
||||
} else {
|
||||
|
@ -3200,35 +3199,80 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
err.help("unsized locals are gated as an unstable feature");
|
||||
}
|
||||
}
|
||||
ObligationCauseCode::SizedArgumentType(ty_span) => {
|
||||
if let Some(span) = ty_span {
|
||||
if let ty::PredicateKind::Clause(clause) = predicate.kind().skip_binder()
|
||||
&& let ty::ClauseKind::Trait(trait_pred) = clause
|
||||
&& let ty::Dynamic(..) = trait_pred.self_ty().kind()
|
||||
{
|
||||
let span = if let Ok(snippet) =
|
||||
self.tcx.sess.source_map().span_to_snippet(span)
|
||||
&& snippet.starts_with("dyn ")
|
||||
{
|
||||
let pos = snippet.len() - snippet[3..].trim_start().len();
|
||||
span.with_hi(span.lo() + BytePos(pos as u32))
|
||||
} else {
|
||||
span.shrink_to_lo()
|
||||
};
|
||||
err.span_suggestion_verbose(
|
||||
span,
|
||||
"you can use `impl Trait` as the argument type",
|
||||
"impl ".to_string(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
ObligationCauseCode::SizedArgumentType(hir_id) => {
|
||||
let mut ty = None;
|
||||
let borrowed_msg = "function arguments must have a statically known size, borrowed \
|
||||
types always have a known size";
|
||||
if let Some(hir_id) = hir_id
|
||||
&& let Some(hir::Node::Param(param)) = self.tcx.hir().find(hir_id)
|
||||
&& let Some(item) = self.tcx.hir().find_parent(hir_id)
|
||||
&& let Some(decl) = item.fn_decl()
|
||||
&& let Some(t) = decl.inputs.iter().find(|t| param.ty_span.contains(t.span))
|
||||
{
|
||||
// We use `contains` because the type might be surrounded by parentheses,
|
||||
// which makes `ty_span` and `t.span` disagree with each other, but one
|
||||
// fully contains the other: `foo: (dyn Foo + Bar)`
|
||||
// ^-------------^
|
||||
// ||
|
||||
// |t.span
|
||||
// param._ty_span
|
||||
ty = Some(t);
|
||||
} else if let Some(hir_id) = hir_id
|
||||
&& let Some(hir::Node::Ty(t)) = self.tcx.hir().find(hir_id)
|
||||
{
|
||||
ty = Some(t);
|
||||
}
|
||||
if let Some(ty) = ty {
|
||||
match ty.kind {
|
||||
hir::TyKind::TraitObject(traits, _, _) => {
|
||||
let (span, kw) = match traits {
|
||||
[first, ..] if first.span.lo() == ty.span.lo() => {
|
||||
// Missing `dyn` in front of trait object.
|
||||
(ty.span.shrink_to_lo(), "dyn ")
|
||||
}
|
||||
[first, ..] => (ty.span.until(first.span), ""),
|
||||
[] => span_bug!(ty.span, "trait object with no traits: {ty:?}"),
|
||||
};
|
||||
let needs_parens = traits.len() != 1;
|
||||
err.span_suggestion_verbose(
|
||||
span,
|
||||
"you can use `impl Trait` as the argument type",
|
||||
"impl ".to_string(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
let sugg = if !needs_parens {
|
||||
vec![(span.shrink_to_lo(), format!("&{kw}"))]
|
||||
} else {
|
||||
vec![
|
||||
(span.shrink_to_lo(), format!("&({kw}")),
|
||||
(ty.span.shrink_to_hi(), ")".to_string()),
|
||||
]
|
||||
};
|
||||
err.multipart_suggestion_verbose(
|
||||
borrowed_msg,
|
||||
sugg,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
hir::TyKind::Slice(_ty) => {
|
||||
err.span_suggestion_verbose(
|
||||
ty.span.shrink_to_lo(),
|
||||
"function arguments must have a statically known size, borrowed \
|
||||
slices always have a known size",
|
||||
"&",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
hir::TyKind::Path(_) => {
|
||||
err.span_suggestion_verbose(
|
||||
ty.span.shrink_to_lo(),
|
||||
borrowed_msg,
|
||||
"&",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
err.span_suggestion_verbose(
|
||||
span.shrink_to_lo(),
|
||||
"function arguments must have a statically known size, borrowed types \
|
||||
always have a known size",
|
||||
"&",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else {
|
||||
err.note("all function arguments must have a statically known size");
|
||||
}
|
||||
|
|
|
@ -816,7 +816,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
|
||||
ty::PredicateKind::ObjectSafe(trait_def_id) => {
|
||||
let violations = self.tcx.object_safety_violations(trait_def_id);
|
||||
report_object_safety_error(self.tcx, span, trait_def_id, violations)
|
||||
report_object_safety_error(self.tcx, span, None, trait_def_id, violations)
|
||||
}
|
||||
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(ty)) => {
|
||||
|
@ -924,7 +924,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
|
||||
TraitNotObjectSafe(did) => {
|
||||
let violations = self.tcx.object_safety_violations(did);
|
||||
report_object_safety_error(self.tcx, span, did, violations)
|
||||
report_object_safety_error(self.tcx, span, None, did, violations)
|
||||
}
|
||||
|
||||
SelectionError::NotConstEvaluatable(NotConstEvaluatable::MentionsInfer) => {
|
||||
|
@ -3163,14 +3163,14 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
) {
|
||||
match obligation_cause_code {
|
||||
ObligationCauseCode::RustCall => {
|
||||
err.set_primary_message("functions with the \"rust-call\" ABI must take a single non-self tuple argument");
|
||||
err.primary_message("functions with the \"rust-call\" ABI must take a single non-self tuple argument");
|
||||
}
|
||||
ObligationCauseCode::BindingObligation(def_id, _)
|
||||
| ObligationCauseCode::ItemObligation(def_id)
|
||||
if self.tcx.is_fn_trait(*def_id) =>
|
||||
{
|
||||
err.code(rustc_errors::error_code!(E0059));
|
||||
err.set_primary_message(format!(
|
||||
err.primary_message(format!(
|
||||
"type parameter to bare `{}` trait must be a tuple",
|
||||
self.tcx.def_path_str(*def_id)
|
||||
));
|
||||
|
|
|
@ -947,7 +947,7 @@ extern "rust-intrinsic" {
|
|||
/// own, or if it does not enable any significant optimizations.
|
||||
///
|
||||
/// This intrinsic does not have a stable counterpart.
|
||||
#[rustc_const_unstable(feature = "const_assume", issue = "76972")]
|
||||
#[rustc_const_stable(feature = "const_assume", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_nounwind]
|
||||
pub fn assume(b: bool);
|
||||
|
||||
|
|
|
@ -119,7 +119,6 @@
|
|||
#![feature(const_arguments_as_str)]
|
||||
#![feature(const_array_from_ref)]
|
||||
#![feature(const_array_into_iter_constructors)]
|
||||
#![feature(const_assume)]
|
||||
#![feature(const_bigint_helper_methods)]
|
||||
#![feature(const_black_box)]
|
||||
#![feature(const_caller_location)]
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#![feature(bigint_helper_methods)]
|
||||
#![feature(cell_update)]
|
||||
#![feature(const_align_offset)]
|
||||
#![feature(const_assume)]
|
||||
#![feature(const_align_of_val_raw)]
|
||||
#![feature(const_black_box)]
|
||||
#![feature(const_caller_location)]
|
||||
|
|
|
@ -1976,7 +1976,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
|
|||
}
|
||||
|
||||
if builder.config.profiler_enabled(target) {
|
||||
cmd.env("RUSTC_PROFILER_SUPPORT", "1");
|
||||
cmd.arg("--profiler-support");
|
||||
}
|
||||
|
||||
cmd.env("RUST_TEST_TMPDIR", builder.tempdir());
|
||||
|
|
|
@ -151,7 +151,6 @@ target | std | notes
|
|||
`i586-pc-windows-msvc` | * | 32-bit Windows w/o SSE [^x86_32-floats-x87]
|
||||
`i586-unknown-linux-gnu` | ✓ | 32-bit Linux w/o SSE (kernel 3.2, glibc 2.17) [^x86_32-floats-x87]
|
||||
`i586-unknown-linux-musl` | ✓ | 32-bit Linux w/o SSE, MUSL [^x86_32-floats-x87]
|
||||
[`i586-unknown-netbsd`](platform-support/netbsd.md) | ✓ | 32-bit x86, restricted to Pentium
|
||||
[`i686-linux-android`](platform-support/android.md) | ✓ | 32-bit x86 Android [^x86_32-floats-return-ABI]
|
||||
`i686-unknown-freebsd` | ✓ | 32-bit FreeBSD [^x86_32-floats-return-ABI]
|
||||
`i686-unknown-linux-musl` | ✓ | 32-bit Linux with MUSL [^x86_32-floats-return-ABI]
|
||||
|
@ -272,6 +271,7 @@ target | std | host | notes
|
|||
`hexagon-unknown-linux-musl` | ? | |
|
||||
`i386-apple-ios` | ✓ | | 32-bit x86 iOS [^x86_32-floats-return-ABI]
|
||||
[`i586-pc-nto-qnx700`](platform-support/nto-qnx.md) | * | | 32-bit x86 QNX Neutrino 7.0 RTOS [^x86_32-floats-return-ABI]
|
||||
[`i586-unknown-netbsd`](platform-support/netbsd.md) | ✓ | | 32-bit x86, restricted to Pentium
|
||||
`i686-apple-darwin` | ✓ | ✓ | 32-bit macOS (10.12+, Sierra+) [^x86_32-floats-return-ABI]
|
||||
`i686-pc-windows-msvc` | * | | 32-bit Windows XP support [^x86_32-floats-return-ABI]
|
||||
[`i686-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ | [^x86_32-floats-return-ABI]
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_data_structures::unord::UnordSet;
|
||||
use rustc_errors::emitter::{DynEmitter, EmitterWriter};
|
||||
use rustc_errors::emitter::{DynEmitter, HumanEmitter};
|
||||
use rustc_errors::json::JsonEmitter;
|
||||
use rustc_errors::TerminalUrl;
|
||||
use rustc_feature::UnstableFeatures;
|
||||
|
@ -138,7 +138,7 @@ pub(crate) fn new_dcx(
|
|||
ErrorOutputType::HumanReadable(kind) => {
|
||||
let (short, color_config) = kind.unzip();
|
||||
Box::new(
|
||||
EmitterWriter::stderr(color_config, fallback_bundle)
|
||||
HumanEmitter::stderr(color_config, fallback_bundle)
|
||||
.sm(source_map.map(|sm| sm as _))
|
||||
.short_message(short)
|
||||
.teach(unstable_opts.teach)
|
||||
|
|
|
@ -557,7 +557,7 @@ pub(crate) fn make_test(
|
|||
// crate already is included.
|
||||
let result = rustc_driver::catch_fatal_errors(|| {
|
||||
rustc_span::create_session_if_not_set_then(edition, |_| {
|
||||
use rustc_errors::emitter::{Emitter, EmitterWriter};
|
||||
use rustc_errors::emitter::{Emitter, HumanEmitter};
|
||||
use rustc_errors::DiagCtxt;
|
||||
use rustc_parse::parser::ForceCollect;
|
||||
use rustc_span::source_map::FilePathMapping;
|
||||
|
@ -572,11 +572,11 @@ pub(crate) fn make_test(
|
|||
rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
|
||||
false,
|
||||
);
|
||||
supports_color = EmitterWriter::stderr(ColorConfig::Auto, fallback_bundle.clone())
|
||||
supports_color = HumanEmitter::stderr(ColorConfig::Auto, fallback_bundle.clone())
|
||||
.diagnostic_width(Some(80))
|
||||
.supports_color();
|
||||
|
||||
let emitter = EmitterWriter::new(Box::new(io::sink()), fallback_bundle);
|
||||
let emitter = HumanEmitter::new(Box::new(io::sink()), fallback_bundle);
|
||||
|
||||
// FIXME(misdreavus): pass `-Z treat-err-as-bug` to the doctest parser
|
||||
let dcx = DiagCtxt::with_emitter(Box::new(emitter)).disable_warnings();
|
||||
|
@ -739,7 +739,7 @@ fn check_if_attr_is_complete(source: &str, edition: Edition) -> bool {
|
|||
}
|
||||
rustc_driver::catch_fatal_errors(|| {
|
||||
rustc_span::create_session_if_not_set_then(edition, |_| {
|
||||
use rustc_errors::emitter::EmitterWriter;
|
||||
use rustc_errors::emitter::HumanEmitter;
|
||||
use rustc_errors::DiagCtxt;
|
||||
use rustc_span::source_map::FilePathMapping;
|
||||
|
||||
|
@ -752,7 +752,7 @@ fn check_if_attr_is_complete(source: &str, edition: Edition) -> bool {
|
|||
false,
|
||||
);
|
||||
|
||||
let emitter = EmitterWriter::new(Box::new(io::sink()), fallback_bundle);
|
||||
let emitter = HumanEmitter::new(Box::new(io::sink()), fallback_bundle);
|
||||
|
||||
let dcx = DiagCtxt::with_emitter(Box::new(emitter)).disable_warnings();
|
||||
let sess = ParseSess::with_dcx(dcx, sm);
|
||||
|
|
|
@ -154,6 +154,28 @@ impl<'tcx> SpanMapVisitor<'tcx> {
|
|||
self.matches.insert(new_span, link_from_src);
|
||||
true
|
||||
}
|
||||
|
||||
fn handle_call(&mut self, hir_id: HirId, expr_hir_id: Option<HirId>, span: Span) {
|
||||
let hir = self.tcx.hir();
|
||||
let body_id = hir.enclosing_body_owner(hir_id);
|
||||
// FIXME: this is showing error messages for parts of the code that are not
|
||||
// compiled (because of cfg)!
|
||||
//
|
||||
// See discussion in https://github.com/rust-lang/rust/issues/69426#issuecomment-1019412352
|
||||
let typeck_results = self
|
||||
.tcx
|
||||
.typeck_body(hir.maybe_body_owned_by(body_id).expect("a body which isn't a body"));
|
||||
// Interestingly enough, for method calls, we need the whole expression whereas for static
|
||||
// method/function calls, we need the call expression specifically.
|
||||
if let Some(def_id) = typeck_results.type_dependent_def_id(expr_hir_id.unwrap_or(hir_id)) {
|
||||
let link = if def_id.as_local().is_some() {
|
||||
LinkFromSrc::Local(rustc_span(def_id, self.tcx))
|
||||
} else {
|
||||
LinkFromSrc::External(def_id)
|
||||
};
|
||||
self.matches.insert(span, link);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> {
|
||||
|
@ -191,27 +213,17 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> {
|
|||
}
|
||||
|
||||
fn visit_expr(&mut self, expr: &'tcx rustc_hir::Expr<'tcx>) {
|
||||
if let ExprKind::MethodCall(segment, ..) = expr.kind {
|
||||
let hir = self.tcx.hir();
|
||||
let body_id = hir.enclosing_body_owner(segment.hir_id);
|
||||
// FIXME: this is showing error messages for parts of the code that are not
|
||||
// compiled (because of cfg)!
|
||||
//
|
||||
// See discussion in https://github.com/rust-lang/rust/issues/69426#issuecomment-1019412352
|
||||
let typeck_results = self
|
||||
.tcx
|
||||
.typeck_body(hir.maybe_body_owned_by(body_id).expect("a body which isn't a body"));
|
||||
if let Some(def_id) = typeck_results.type_dependent_def_id(expr.hir_id) {
|
||||
let link = if def_id.as_local().is_some() {
|
||||
LinkFromSrc::Local(rustc_span(def_id, self.tcx))
|
||||
} else {
|
||||
LinkFromSrc::External(def_id)
|
||||
};
|
||||
self.matches.insert(segment.ident.span, link);
|
||||
match expr.kind {
|
||||
ExprKind::MethodCall(segment, ..) => {
|
||||
self.handle_call(segment.hir_id, Some(expr.hir_id), segment.ident.span)
|
||||
}
|
||||
ExprKind::Call(call, ..) => self.handle_call(call.hir_id, None, call.span),
|
||||
_ => {
|
||||
if self.handle_macro(expr.span) {
|
||||
// We don't want to go deeper into the macro.
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if self.handle_macro(expr.span) {
|
||||
// We don't want to go deeper into the macro.
|
||||
return;
|
||||
}
|
||||
intravisit::walk_expr(self, expr);
|
||||
}
|
||||
|
|
|
@ -1733,7 +1733,7 @@ fn report_diagnostic(
|
|||
};
|
||||
|
||||
if let Some(sp) = span {
|
||||
lint.set_span(sp);
|
||||
lint.span(sp);
|
||||
} else {
|
||||
// blah blah blah\nblah\nblah [blah] blah blah\nblah blah
|
||||
// ^ ~~~~
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::doc::{NEEDLESS_DOCTEST_MAIN, TEST_ATTR_IN_DOCTEST};
|
|||
use clippy_utils::diagnostics::span_lint;
|
||||
use rustc_ast::{CoroutineKind, Fn, FnRetTy, Item, ItemKind};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::emitter::EmitterWriter;
|
||||
use rustc_errors::emitter::HumanEmitter;
|
||||
use rustc_errors::DiagCtxt;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_parse::maybe_new_parser_from_source_str;
|
||||
|
@ -44,7 +44,7 @@ pub fn check(
|
|||
|
||||
let fallback_bundle =
|
||||
rustc_errors::fallback_fluent_bundle(rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), false);
|
||||
let emitter = EmitterWriter::new(Box::new(io::sink()), fallback_bundle);
|
||||
let emitter = HumanEmitter::new(Box::new(io::sink()), fallback_bundle);
|
||||
let dcx = DiagCtxt::with_emitter(Box::new(emitter)).disable_warnings();
|
||||
#[expect(clippy::arc_with_non_send_sync)] // `Lrc` is expected by with_dcx
|
||||
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
||||
|
|
|
@ -6,7 +6,7 @@ LL | fn bug<T>() -> impl Iterator<Item = [(); { |x: [u8]| x }]> {
|
|||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `[u8]`
|
||||
= help: unsized fn params are gated as an unstable feature
|
||||
help: function arguments must have a statically known size, borrowed types always have a known size
|
||||
help: function arguments must have a statically known size, borrowed slices always have a known size
|
||||
|
|
||||
LL | fn bug<T>() -> impl Iterator<Item = [(); { |x: &[u8]| x }]> {
|
||||
| +
|
||||
|
|
|
@ -387,6 +387,10 @@ pub struct Config {
|
|||
// Needed both to construct build_helper::git::GitConfig
|
||||
pub git_repository: String,
|
||||
pub nightly_branch: String,
|
||||
|
||||
/// True if the profiler runtime is enabled for this target.
|
||||
/// Used by the "needs-profiler-support" header in test files.
|
||||
pub profiler_support: bool,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
|
|
|
@ -178,6 +178,9 @@ pub struct TestProps {
|
|||
// Whether to tell `rustc` to remap the "src base" directory to a fake
|
||||
// directory.
|
||||
pub remap_src_base: bool,
|
||||
/// Extra flags to pass to `llvm-cov` when producing coverage reports.
|
||||
/// Only used by the "coverage-run" test mode.
|
||||
pub llvm_cov_flags: Vec<String>,
|
||||
}
|
||||
|
||||
mod directives {
|
||||
|
@ -216,6 +219,7 @@ mod directives {
|
|||
pub const MIR_UNIT_TEST: &'static str = "unit-test";
|
||||
pub const REMAP_SRC_BASE: &'static str = "remap-src-base";
|
||||
pub const COMPARE_OUTPUT_LINES_BY_SUBSET: &'static str = "compare-output-lines-by-subset";
|
||||
pub const LLVM_COV_FLAGS: &'static str = "llvm-cov-flags";
|
||||
// This isn't a real directive, just one that is probably mistyped often
|
||||
pub const INCORRECT_COMPILER_FLAGS: &'static str = "compiler-flags";
|
||||
}
|
||||
|
@ -265,6 +269,7 @@ impl TestProps {
|
|||
stderr_per_bitwidth: false,
|
||||
mir_unit_test: None,
|
||||
remap_src_base: false,
|
||||
llvm_cov_flags: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -321,16 +326,23 @@ impl TestProps {
|
|||
|r| r,
|
||||
);
|
||||
|
||||
if let Some(flags) = config.parse_name_value_directive(ln, COMPILE_FLAGS) {
|
||||
self.compile_flags.extend(
|
||||
flags
|
||||
.split("'")
|
||||
.enumerate()
|
||||
.flat_map(|(i, f)| {
|
||||
fn split_flags(flags: &str) -> Vec<String> {
|
||||
// Individual flags can be single-quoted to preserve spaces; see
|
||||
// <https://github.com/rust-lang/rust/pull/115948/commits/957c5db6>.
|
||||
flags
|
||||
.split("'")
|
||||
.enumerate()
|
||||
.flat_map(
|
||||
|(i, f)| {
|
||||
if i % 2 == 1 { vec![f] } else { f.split_whitespace().collect() }
|
||||
})
|
||||
.map(|s| s.to_owned()),
|
||||
);
|
||||
},
|
||||
)
|
||||
.map(move |s| s.to_owned())
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
if let Some(flags) = config.parse_name_value_directive(ln, COMPILE_FLAGS) {
|
||||
self.compile_flags.extend(split_flags(&flags));
|
||||
}
|
||||
if config.parse_name_value_directive(ln, INCORRECT_COMPILER_FLAGS).is_some() {
|
||||
panic!("`compiler-flags` directive should be spelled `compile-flags`");
|
||||
|
@ -488,6 +500,10 @@ impl TestProps {
|
|||
COMPARE_OUTPUT_LINES_BY_SUBSET,
|
||||
&mut self.compare_output_lines_by_subset,
|
||||
);
|
||||
|
||||
if let Some(flags) = config.parse_name_value_directive(ln, LLVM_COV_FLAGS) {
|
||||
self.llvm_cov_flags.extend(split_flags(&flags));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::common::{CompareMode, Config, Debugger};
|
||||
use crate::common::{CompareMode, Config, Debugger, Mode};
|
||||
use crate::header::IgnoreDecision;
|
||||
use std::collections::HashSet;
|
||||
|
||||
|
@ -208,6 +208,17 @@ pub(super) fn parse_cfg_name_directive<'a>(
|
|||
},
|
||||
message: "when comparing with {name}",
|
||||
}
|
||||
// Coverage tests run the same test file in multiple modes.
|
||||
// If a particular test should not be run in one of the modes, ignore it
|
||||
// with "ignore-mode-coverage-map" or "ignore-mode-coverage-run".
|
||||
condition! {
|
||||
name: format!("mode-{}", config.mode.to_str()),
|
||||
allowed_names: ContainsPrefixed {
|
||||
prefix: "mode-",
|
||||
inner: Mode::STR_VARIANTS,
|
||||
},
|
||||
message: "when the test mode is {name}",
|
||||
}
|
||||
|
||||
if prefix == "ignore" && outcome == MatchOutcome::Invalid {
|
||||
// Don't error out for ignore-tidy-* diretives, as those are not handled by compiletest.
|
||||
|
|
|
@ -238,7 +238,7 @@ impl CachedNeedsConditions {
|
|||
sanitizer_memtag: sanitizers.contains(&Sanitizer::Memtag),
|
||||
sanitizer_shadow_call_stack: sanitizers.contains(&Sanitizer::ShadowCallStack),
|
||||
sanitizer_safestack: sanitizers.contains(&Sanitizer::Safestack),
|
||||
profiler_support: std::env::var_os("RUSTC_PROFILER_SUPPORT").is_some(),
|
||||
profiler_support: config.profiler_support,
|
||||
xray: config.target_cfg().xray,
|
||||
|
||||
// For tests using the `needs-rust-lld` directive (e.g. for `-Clink-self-contained=+linker`),
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use std::io::Read;
|
||||
use std::path::Path;
|
||||
use std::str::FromStr;
|
||||
|
||||
use crate::common::{Config, Debugger};
|
||||
use crate::common::{Config, Debugger, Mode};
|
||||
use crate::header::{parse_normalization_string, EarlyProps, HeadersCache};
|
||||
|
||||
fn make_test_description<R: Read>(
|
||||
|
@ -55,6 +56,7 @@ fn test_parse_normalization_string() {
|
|||
|
||||
#[derive(Default)]
|
||||
struct ConfigBuilder {
|
||||
mode: Option<String>,
|
||||
channel: Option<String>,
|
||||
host: Option<String>,
|
||||
target: Option<String>,
|
||||
|
@ -62,9 +64,15 @@ struct ConfigBuilder {
|
|||
llvm_version: Option<String>,
|
||||
git_hash: bool,
|
||||
system_llvm: bool,
|
||||
profiler_support: bool,
|
||||
}
|
||||
|
||||
impl ConfigBuilder {
|
||||
fn mode(&mut self, s: &str) -> &mut Self {
|
||||
self.mode = Some(s.to_owned());
|
||||
self
|
||||
}
|
||||
|
||||
fn channel(&mut self, s: &str) -> &mut Self {
|
||||
self.channel = Some(s.to_owned());
|
||||
self
|
||||
|
@ -100,10 +108,16 @@ impl ConfigBuilder {
|
|||
self
|
||||
}
|
||||
|
||||
fn profiler_support(&mut self, s: bool) -> &mut Self {
|
||||
self.profiler_support = s;
|
||||
self
|
||||
}
|
||||
|
||||
fn build(&mut self) -> Config {
|
||||
let args = &[
|
||||
"compiletest",
|
||||
"--mode=ui",
|
||||
"--mode",
|
||||
self.mode.as_deref().unwrap_or("ui"),
|
||||
"--suite=ui",
|
||||
"--compile-lib-path=",
|
||||
"--run-lib-path=",
|
||||
|
@ -142,6 +156,9 @@ impl ConfigBuilder {
|
|||
if self.system_llvm {
|
||||
args.push("--system-llvm".to_owned());
|
||||
}
|
||||
if self.profiler_support {
|
||||
args.push("--profiler-support".to_owned());
|
||||
}
|
||||
|
||||
args.push("--rustc-path".to_string());
|
||||
// This is a subtle/fragile thing. On rust-lang CI, there is no global
|
||||
|
@ -340,6 +357,15 @@ fn sanitizers() {
|
|||
assert!(check_ignore(&config, "// needs-sanitizer-thread"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn profiler_support() {
|
||||
let config: Config = cfg().profiler_support(false).build();
|
||||
assert!(check_ignore(&config, "// needs-profiler-support"));
|
||||
|
||||
let config: Config = cfg().profiler_support(true).build();
|
||||
assert!(!check_ignore(&config, "// needs-profiler-support"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn asm_support() {
|
||||
let asms = [
|
||||
|
@ -530,3 +556,17 @@ fn families() {
|
|||
assert!(!check_ignore(&config, &format!("// ignore-{other}")));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ignore_mode() {
|
||||
for &mode in Mode::STR_VARIANTS {
|
||||
// Indicate profiler support so that "coverage-run" tests aren't skipped.
|
||||
let config: Config = cfg().mode(mode).profiler_support(true).build();
|
||||
let other = if mode == "coverage-run" { "coverage-map" } else { "coverage-run" };
|
||||
assert_ne!(mode, other);
|
||||
assert_eq!(config.mode, Mode::from_str(mode).unwrap());
|
||||
assert_ne!(config.mode, Mode::from_str(other).unwrap());
|
||||
assert!(check_ignore(&config, &format!("// ignore-mode-{mode}")));
|
||||
assert!(!check_ignore(&config, &format!("// ignore-mode-{other}")));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -142,6 +142,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
|
|||
.optflag("", "force-rerun", "rerun tests even if the inputs are unchanged")
|
||||
.optflag("", "only-modified", "only run tests that result been modified")
|
||||
.optflag("", "nocapture", "")
|
||||
.optflag("", "profiler-support", "is the profiler runtime enabled for this target")
|
||||
.optflag("h", "help", "show this message")
|
||||
.reqopt("", "channel", "current Rust channel", "CHANNEL")
|
||||
.optflag("", "git-hash", "run tests which rely on commit version being compiled into the binaries")
|
||||
|
@ -315,6 +316,8 @@ pub fn parse_config(args: Vec<String>) -> Config {
|
|||
|
||||
git_repository: matches.opt_str("git-repository").unwrap(),
|
||||
nightly_branch: matches.opt_str("nightly-branch").unwrap(),
|
||||
|
||||
profiler_support: matches.opt_present("profiler-support"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -575,6 +575,8 @@ impl<'test> TestCx<'test> {
|
|||
cmd.arg("--object");
|
||||
cmd.arg(bin);
|
||||
}
|
||||
|
||||
cmd.args(&self.props.llvm_cov_flags);
|
||||
});
|
||||
if !proc_res.status.success() {
|
||||
self.fatal_proc_rec("llvm-cov show failed!", &proc_res);
|
||||
|
|
|
@ -454,12 +454,12 @@ pub fn report_msg<'tcx>(
|
|||
let span = stacktrace.first().map_or(DUMMY_SP, |fi| fi.span);
|
||||
let sess = machine.tcx.sess;
|
||||
let level = match diag_level {
|
||||
DiagLevel::Error => Level::Error { lint: false },
|
||||
DiagLevel::Error => Level::Error,
|
||||
DiagLevel::Warning => Level::Warning(None),
|
||||
DiagLevel::Note => Level::Note,
|
||||
};
|
||||
let mut err = DiagnosticBuilder::<()>::new(sess.dcx(), level, title);
|
||||
err.set_span(span);
|
||||
err.span(span);
|
||||
|
||||
// Show main message.
|
||||
if span != DUMMY_SP {
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::path::Path;
|
|||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
use rustc_data_structures::sync::{IntoDynSyncSend, Lrc};
|
||||
use rustc_errors::emitter::{DynEmitter, Emitter, EmitterWriter};
|
||||
use rustc_errors::emitter::{DynEmitter, Emitter, HumanEmitter};
|
||||
use rustc_errors::translation::Translate;
|
||||
use rustc_errors::{ColorConfig, DiagCtxt, Diagnostic, Level as DiagnosticLevel};
|
||||
use rustc_session::parse::ParseSess as RawParseSess;
|
||||
|
@ -139,7 +139,7 @@ fn default_dcx(
|
|||
rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
|
||||
false,
|
||||
);
|
||||
Box::new(EmitterWriter::stderr(emit_color, fallback_bundle).sm(Some(source_map.clone())))
|
||||
Box::new(HumanEmitter::stderr(emit_color, fallback_bundle).sm(Some(source_map.clone())))
|
||||
};
|
||||
DiagCtxt::with_emitter(Box::new(SilentOnIgnoredFilesEmitter {
|
||||
has_non_ignorable_parser_errors: false,
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
LL| |// edition: 2021
|
||||
LL| |// ignore-mode-coverage-map
|
||||
LL| |// ignore-windows
|
||||
LL| |// llvm-cov-flags: --use-color
|
||||
LL| |
|
||||
LL| |// Verify that telling `llvm-cov` to use colored output actually works.
|
||||
LL| |// Ignored on Windows because we can't tell the tool to use ANSI escapes.
|
||||
LL| |
|
||||
LL| 1|fn main() {
|
||||
LL| [0;35m1[0m| for [0;41m_i[0m in 0..0 [0;41m{}[0m
|
||||
^0 ^0
|
||||
LL| 1|}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
// edition: 2021
|
||||
// ignore-mode-coverage-map
|
||||
// ignore-windows
|
||||
// llvm-cov-flags: --use-color
|
||||
|
||||
// Verify that telling `llvm-cov` to use colored output actually works.
|
||||
// Ignored on Windows because we can't tell the tool to use ANSI escapes.
|
||||
|
||||
fn main() {
|
||||
for _i in 0..0 {}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
LL| |// ignore-mode-coverage-map
|
||||
LL| |
|
||||
LL| 1|fn main() {}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
// ignore-mode-coverage-map
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,8 @@
|
|||
Function name: ignore_run::main
|
||||
Raw bytes (9): 0x[01, 01, 00, 01, 01, 03, 01, 00, 0d]
|
||||
Number of files: 1
|
||||
- file 0 => global file 1
|
||||
Number of expressions: 0
|
||||
Number of file 0 mappings: 1
|
||||
- Code(Counter(0)) at (prev + 3, 1) to (start + 0, 13)
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
// ignore-mode-coverage-run
|
||||
|
||||
fn main() {}
|
|
@ -8,14 +8,14 @@
|
|||
|
||||
bb0: {
|
||||
- _2 = _1;
|
||||
- _0 = opaque::<NotCopy>(move _1) -> [return: bb1, unwind continue];
|
||||
+ _0 = opaque::<NotCopy>(_1) -> [return: bb1, unwind continue];
|
||||
- _0 = opaque::<NotCopy>(move _1) -> [return: bb1, unwind unreachable];
|
||||
+ _0 = opaque::<NotCopy>(_1) -> [return: bb1, unwind unreachable];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
- _3 = move _2;
|
||||
- _0 = opaque::<NotCopy>(_3) -> [return: bb2, unwind continue];
|
||||
+ _0 = opaque::<NotCopy>(_1) -> [return: bb2, unwind continue];
|
||||
- _0 = opaque::<NotCopy>(_3) -> [return: bb2, unwind unreachable];
|
||||
+ _0 = opaque::<NotCopy>(_1) -> [return: bb2, unwind unreachable];
|
||||
}
|
||||
|
||||
bb2: {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue