Skip to content

Commit 91509c9

Browse files
authored
Rollup merge of rust-lang#102110 - CleanCut:migrate_rustc_passes_diagnostics, r=davidtwco
Migrate rustc_passes diagnostics Picks up abandoned work from rust-lang#100870 I would like to do this collaboratively, as there is a lot of work! Here's the process: - Comment below that you are willing to help and I will add you as a collaborator to my `rust` fork (that gives you write access) - Indicate which file/task you would like to work on (so we don't duplicate work) from the list below - Do the work, push up a commit, comment that you're done with that file/task - Repeat until done 😄 ### Files to Migrate (in `compiler/rustc_passes/src/`) - [x] check_attr.rs `@CleanCut` - [x] check_const.rs `@CleanCut` - [x] dead.rs `@CleanCut` - [x] debugger_visualizer.rs `@CleanCut` - [x] diagnostic_items.rs `@CleanCut` - [x] entry.rs `@CleanCut` - [x] lang_items.rs `@CleanCut` - [x] layout_test.rs `@CleanCut` - [x] lib_features.rs `@CleanCut` - [x] ~liveness.rs~ `@CleanCut` Nothing to do - [x] loops.rs `@CleanCut` - [x] naked_functions.rs `@CleanCut` - [x] stability.rs `@CleanCut` - [x] weak_lang_items.rs `@CleanCut` ### Tasks - [x] Rebase on current `master` `@CleanCut` - [x] Review work from [the earlier PR](rust-lang#100870) and make sure it all looks good - [x] compiler/rustc_error_messages/locales/en-US/passes.ftl `@CleanCut` - [x] compiler/rustc_passes/src/check_attr.rs `@CleanCut` - [x] compiler/rustc_passes/src/errors.rs `@CleanCut` - [x] compiler/rustc_passes/src/lang_items.rs `@CleanCut` - [x] compiler/rustc_passes/src/lib.rs `@CleanCut` - [x] compiler/rustc_passes/src/weak_lang_items.rs `@CleanCut`
2 parents 3655784 + 5ef1c03 commit 91509c9

24 files changed

+1793
-756
lines changed

compiler/rustc_error_messages/locales/en-US/middle.ftl

+9
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,12 @@ middle_limit_invalid =
1818
1919
middle_const_eval_non_int =
2020
constant evaluation of enum discriminant resulted in non-integer
21+
22+
middle_unknown_layout =
23+
the type `{$ty}` has an unknown layout
24+
25+
middle_values_too_big =
26+
values of the type `{$ty}` are too big for the current architecture
27+
28+
middle_cannot_be_normalized =
29+
unable to determine layout for `{$ty}` because `{$failure_ty}` cannot be normalized

compiler/rustc_error_messages/locales/en-US/passes.ftl

+478-81
Large diffs are not rendered by default.

compiler/rustc_errors/src/diagnostic_builder.rs

+50
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,56 @@ impl EmissionGuarantee for () {
255255
}
256256
}
257257

258+
/// Marker type which enables implementation of `create_note` and `emit_note` functions for
259+
/// note-without-error struct diagnostics.
260+
#[derive(Copy, Clone)]
261+
pub struct Noted;
262+
263+
impl<'a> DiagnosticBuilder<'a, Noted> {
264+
/// Convenience function for internal use, clients should use one of the
265+
/// `struct_*` methods on [`Handler`].
266+
pub(crate) fn new_note(handler: &'a Handler, message: impl Into<DiagnosticMessage>) -> Self {
267+
let diagnostic = Diagnostic::new_with_code(Level::Note, None, message);
268+
Self::new_diagnostic_note(handler, diagnostic)
269+
}
270+
271+
/// Creates a new `DiagnosticBuilder` with an already constructed
272+
/// diagnostic.
273+
pub(crate) fn new_diagnostic_note(handler: &'a Handler, diagnostic: Diagnostic) -> Self {
274+
debug!("Created new diagnostic");
275+
Self {
276+
inner: DiagnosticBuilderInner {
277+
state: DiagnosticBuilderState::Emittable(handler),
278+
diagnostic: Box::new(diagnostic),
279+
},
280+
_marker: PhantomData,
281+
}
282+
}
283+
}
284+
285+
impl EmissionGuarantee for Noted {
286+
fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self {
287+
match db.inner.state {
288+
// First `.emit()` call, the `&Handler` is still available.
289+
DiagnosticBuilderState::Emittable(handler) => {
290+
db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
291+
handler.emit_diagnostic(&mut db.inner.diagnostic);
292+
}
293+
// `.emit()` was previously called, disallowed from repeating it.
294+
DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {}
295+
}
296+
297+
Noted
298+
}
299+
300+
fn make_diagnostic_builder(
301+
handler: &Handler,
302+
msg: impl Into<DiagnosticMessage>,
303+
) -> DiagnosticBuilder<'_, Self> {
304+
DiagnosticBuilder::new_note(handler, msg)
305+
}
306+
}
307+
258308
impl<'a> DiagnosticBuilder<'a, !> {
259309
/// Convenience function for internal use, clients should use one of the
260310
/// `struct_*` methods on [`Handler`].

compiler/rustc_errors/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ pub use diagnostic::{
374374
AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgFromDisplay,
375375
DiagnosticArgValue, DiagnosticId, DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic,
376376
};
377-
pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee};
377+
pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee, Noted};
378378
use std::backtrace::Backtrace;
379379

380380
/// A handler deals with errors and other compiler output.

compiler/rustc_middle/src/ty/layout.rs

+20-1
Original file line numberDiff line numberDiff line change
@@ -191,10 +191,29 @@ pub enum LayoutError<'tcx> {
191191

192192
impl<'a> IntoDiagnostic<'a, !> for LayoutError<'a> {
193193
fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, !> {
194-
handler.struct_fatal(self.to_string())
194+
let mut diag = handler.struct_fatal("");
195+
196+
match self {
197+
LayoutError::Unknown(ty) => {
198+
diag.set_arg("ty", ty);
199+
diag.set_primary_message(rustc_errors::fluent::middle::unknown_layout);
200+
}
201+
LayoutError::SizeOverflow(ty) => {
202+
diag.set_arg("ty", ty);
203+
diag.set_primary_message(rustc_errors::fluent::middle::values_too_big);
204+
}
205+
LayoutError::NormalizationFailure(ty, e) => {
206+
diag.set_arg("ty", ty);
207+
diag.set_arg("failure_ty", e.get_type_for_failure());
208+
diag.set_primary_message(rustc_errors::fluent::middle::cannot_be_normalized);
209+
}
210+
}
211+
diag
195212
}
196213
}
197214

215+
// FIXME: Once the other errors that embed this error have been converted to translateable
216+
// diagnostics, this Display impl should be removed.
198217
impl<'tcx> fmt::Display for LayoutError<'tcx> {
199218
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
200219
match *self {

compiler/rustc_passes/src/check_attr.rs

+61-90
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@
44
//! conflicts between multiple such attributes attached to the same
55
//! item.
66
7-
use crate::errors;
7+
use crate::errors::{
8+
self, AttrApplication, DebugVisualizerUnreadable, InvalidAttrAtCrateLevel, ObjectLifetimeErr,
9+
OnlyHasEffectOn, TransparentIncompatible, UnrecognizedReprHint,
10+
};
811
use rustc_ast::{ast, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem};
912
use rustc_data_structures::fx::FxHashMap;
10-
use rustc_errors::{fluent, struct_span_err, Applicability, MultiSpan};
13+
use rustc_errors::{fluent, Applicability, MultiSpan};
1114
use rustc_expand::base::resolve_path;
1215
use rustc_feature::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
1316
use rustc_hir as hir;
@@ -164,17 +167,17 @@ impl CheckAttrVisitor<'_> {
164167
sym::no_mangle => self.check_no_mangle(hir_id, attr, span, target),
165168
sym::deprecated => self.check_deprecated(hir_id, attr, span, target),
166169
sym::macro_use | sym::macro_escape => self.check_macro_use(hir_id, attr, target),
167-
sym::path => self.check_generic_attr(hir_id, attr, target, &[Target::Mod]),
170+
sym::path => self.check_generic_attr(hir_id, attr, target, Target::Mod),
168171
sym::plugin_registrar => self.check_plugin_registrar(hir_id, attr, target),
169172
sym::macro_export => self.check_macro_export(hir_id, attr, target),
170173
sym::ignore | sym::should_panic | sym::proc_macro_derive => {
171-
self.check_generic_attr(hir_id, attr, target, &[Target::Fn])
174+
self.check_generic_attr(hir_id, attr, target, Target::Fn)
172175
}
173176
sym::automatically_derived => {
174-
self.check_generic_attr(hir_id, attr, target, &[Target::Impl])
177+
self.check_generic_attr(hir_id, attr, target, Target::Impl)
175178
}
176179
sym::no_implicit_prelude => {
177-
self.check_generic_attr(hir_id, attr, target, &[Target::Mod])
180+
self.check_generic_attr(hir_id, attr, target, Target::Mod)
178181
}
179182
sym::rustc_object_lifetime_default => self.check_object_lifetime_default(hir_id),
180183
_ => {}
@@ -351,31 +354,17 @@ impl CheckAttrVisitor<'_> {
351354
hir_id: HirId,
352355
attr: &Attribute,
353356
target: Target,
354-
allowed_targets: &[Target],
357+
allowed_target: Target,
355358
) {
356-
if !allowed_targets.iter().any(|t| t == &target) {
357-
let name = attr.name_or_empty();
358-
let mut i = allowed_targets.iter();
359-
// Pluralize
360-
let b = i.next().map_or_else(String::new, |t| t.to_string() + "s");
361-
let supported_names = i.enumerate().fold(b, |mut b, (i, allowed_target)| {
362-
if allowed_targets.len() > 2 && i == allowed_targets.len() - 2 {
363-
b.push_str(", and ");
364-
} else if allowed_targets.len() == 2 && i == allowed_targets.len() - 2 {
365-
b.push_str(" and ");
366-
} else {
367-
b.push_str(", ");
368-
}
369-
// Pluralize
370-
b.push_str(&(allowed_target.to_string() + "s"));
371-
b
372-
});
373-
self.tcx.struct_span_lint_hir(
359+
if target != allowed_target {
360+
self.tcx.emit_spanned_lint(
374361
UNUSED_ATTRIBUTES,
375362
hir_id,
376363
attr.span,
377-
&format!("`#[{name}]` only has an effect on {}", supported_names),
378-
|lint| lint,
364+
OnlyHasEffectOn {
365+
attr_name: attr.name_or_empty(),
366+
target_name: allowed_target.name().replace(" ", "_"),
367+
},
379368
);
380369
}
381370
}
@@ -432,7 +421,7 @@ impl CheckAttrVisitor<'_> {
432421
ObjectLifetimeDefault::Param(def_id) => tcx.item_name(def_id).to_string(),
433422
ObjectLifetimeDefault::Ambiguous => "Ambiguous".to_owned(),
434423
};
435-
tcx.sess.span_err(p.span, &repr);
424+
tcx.sess.emit_err(ObjectLifetimeErr { span: p.span, repr });
436425
}
437426
}
438427
}
@@ -1605,12 +1594,17 @@ impl CheckAttrVisitor<'_> {
16051594
continue;
16061595
}
16071596

1608-
let (article, allowed_targets) = match hint.name_or_empty() {
1597+
match hint.name_or_empty() {
16091598
sym::C => {
16101599
is_c = true;
16111600
match target {
16121601
Target::Struct | Target::Union | Target::Enum => continue,
1613-
_ => ("a", "struct, enum, or union"),
1602+
_ => {
1603+
self.tcx.sess.emit_err(AttrApplication::StructEnumUnion {
1604+
hint_span: hint.span(),
1605+
span,
1606+
});
1607+
}
16141608
}
16151609
}
16161610
sym::align => {
@@ -1626,20 +1620,30 @@ impl CheckAttrVisitor<'_> {
16261620

16271621
match target {
16281622
Target::Struct | Target::Union | Target::Enum | Target::Fn => continue,
1629-
_ => ("a", "struct, enum, function, or union"),
1623+
_ => {
1624+
self.tcx.sess.emit_err(AttrApplication::StructEnumFunctionUnion {
1625+
hint_span: hint.span(),
1626+
span,
1627+
});
1628+
}
16301629
}
16311630
}
16321631
sym::packed => {
16331632
if target != Target::Struct && target != Target::Union {
1634-
("a", "struct or union")
1633+
self.tcx.sess.emit_err(AttrApplication::StructUnion {
1634+
hint_span: hint.span(),
1635+
span,
1636+
});
16351637
} else {
16361638
continue;
16371639
}
16381640
}
16391641
sym::simd => {
16401642
is_simd = true;
16411643
if target != Target::Struct {
1642-
("a", "struct")
1644+
self.tcx
1645+
.sess
1646+
.emit_err(AttrApplication::Struct { hint_span: hint.span(), span });
16431647
} else {
16441648
continue;
16451649
}
@@ -1648,7 +1652,12 @@ impl CheckAttrVisitor<'_> {
16481652
is_transparent = true;
16491653
match target {
16501654
Target::Struct | Target::Union | Target::Enum => continue,
1651-
_ => ("a", "struct, enum, or union"),
1655+
_ => {
1656+
self.tcx.sess.emit_err(AttrApplication::StructEnumUnion {
1657+
hint_span: hint.span(),
1658+
span,
1659+
});
1660+
}
16521661
}
16531662
}
16541663
sym::i8
@@ -1665,35 +1674,18 @@ impl CheckAttrVisitor<'_> {
16651674
| sym::usize => {
16661675
int_reprs += 1;
16671676
if target != Target::Enum {
1668-
("an", "enum")
1677+
self.tcx
1678+
.sess
1679+
.emit_err(AttrApplication::Enum { hint_span: hint.span(), span });
16691680
} else {
16701681
continue;
16711682
}
16721683
}
16731684
_ => {
1674-
struct_span_err!(
1675-
self.tcx.sess,
1676-
hint.span(),
1677-
E0552,
1678-
"unrecognized representation hint"
1679-
)
1680-
.help("valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, \
1681-
`i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`")
1682-
.emit();
1683-
1685+
self.tcx.sess.emit_err(UnrecognizedReprHint { span: hint.span() });
16841686
continue;
16851687
}
16861688
};
1687-
1688-
struct_span_err!(
1689-
self.tcx.sess,
1690-
hint.span(),
1691-
E0517,
1692-
"{}",
1693-
&format!("attribute should be applied to {article} {allowed_targets}")
1694-
)
1695-
.span_label(span, &format!("not {article} {allowed_targets}"))
1696-
.emit();
16971689
}
16981690

16991691
// Just point at all repr hints if there are any incompatibilities.
@@ -1703,14 +1695,9 @@ impl CheckAttrVisitor<'_> {
17031695
// Error on repr(transparent, <anything else>).
17041696
if is_transparent && hints.len() > 1 {
17051697
let hint_spans: Vec<_> = hint_spans.clone().collect();
1706-
struct_span_err!(
1707-
self.tcx.sess,
1708-
hint_spans,
1709-
E0692,
1710-
"transparent {} cannot have other repr hints",
1711-
target
1712-
)
1713-
.emit();
1698+
self.tcx
1699+
.sess
1700+
.emit_err(TransparentIncompatible { hint_spans, target: target.to_string() });
17141701
}
17151702
// Warn on repr(u8, u16), repr(C, simd), and c-like-enum-repr(C, u8)
17161703
if (int_reprs > 1)
@@ -1862,14 +1849,12 @@ impl CheckAttrVisitor<'_> {
18621849

18631850
match std::fs::File::open(&file) {
18641851
Ok(_) => true,
1865-
Err(err) => {
1866-
self.tcx
1867-
.sess
1868-
.struct_span_err(
1869-
meta_item.span,
1870-
&format!("couldn't read {}: {}", file.display(), err),
1871-
)
1872-
.emit();
1852+
Err(error) => {
1853+
self.tcx.sess.emit_err(DebugVisualizerUnreadable {
1854+
span: meta_item.span,
1855+
file: &file,
1856+
error,
1857+
});
18731858
false
18741859
}
18751860
}
@@ -2180,25 +2165,11 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
21802165
if attr.style == AttrStyle::Inner {
21812166
for attr_to_check in ATTRS_TO_CHECK {
21822167
if attr.has_name(*attr_to_check) {
2183-
let mut err = tcx.sess.struct_span_err(
2184-
attr.span,
2185-
&format!(
2186-
"`{}` attribute cannot be used at crate level",
2187-
attr_to_check.to_ident_string()
2188-
),
2189-
);
2190-
// Only emit an error with a suggestion if we can create a
2191-
// string out of the attribute span
2192-
if let Ok(src) = tcx.sess.source_map().span_to_snippet(attr.span) {
2193-
let replacement = src.replace("#!", "#");
2194-
err.span_suggestion_verbose(
2195-
attr.span,
2196-
"perhaps you meant to use an outer attribute",
2197-
replacement,
2198-
rustc_errors::Applicability::MachineApplicable,
2199-
);
2200-
}
2201-
err.emit();
2168+
tcx.sess.emit_err(InvalidAttrAtCrateLevel {
2169+
span: attr.span,
2170+
snippet: tcx.sess.source_map().span_to_snippet(attr.span).ok(),
2171+
name: *attr_to_check,
2172+
});
22022173
}
22032174
}
22042175
}

0 commit comments

Comments
 (0)