Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate rustc_passes diagnostics #102110

Merged
merged 29 commits into from
Oct 12, 2022
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
bde80f7
Add lint for diagnostic migration
rdvdev2 Aug 22, 2022
2f74d1d
Migrate weak_lang_items.rs
rdvdev2 Aug 22, 2022
17a4a68
Migrate derivable diagnostics in lang_items.rs
rdvdev2 Sep 1, 2022
0315d7c
Migrate derivable diagnostics in check_attr.rs
rdvdev2 Sep 2, 2022
2c3351c
Migrate InvalidAttrAtCrateLevel
rdvdev2 Sep 2, 2022
c24a873
always put ftl message on next line, resolve all but 1 output compari…
CleanCut Sep 21, 2022
b8e03cf
use consistent names
CleanCut Sep 22, 2022
1222541
resolve merge conflict from cherry-picking 6a47326a0452cc8d5cb5767650…
diegooliveira Sep 14, 2022
c103c30
migrate the rest of weak_lang_items.rs to translateable diagnostics
CleanCut Sep 22, 2022
1e86226
migrate debugger_visualizer.rs to translateable diagnostics
CleanCut Sep 22, 2022
f8ebc72
errors: add `emit_note`/`create_note`
davidtwco Sep 1, 2022
3a74833
use cherry-picked commit from #100754 to emit note without error
CleanCut Sep 22, 2022
0609c0f
migrate diagnostic_items.rs to translateable diagnostics
CleanCut Sep 23, 2022
40d5f00
migrate layout_test.rs to translateable diagnostics
CleanCut Sep 23, 2022
c457abe
migrate lib_features.rs to translateable diagnostics
CleanCut Sep 24, 2022
572f341
migrate check_const.rs to translateable diagnostics
CleanCut Sep 24, 2022
69766e4
migrate loops.rs to translateable diagnostics
CleanCut Sep 26, 2022
96f92ea
migrate naked_functions.rs to translateable diagnostics
CleanCut Sep 27, 2022
b17ec43
migrate entry.rs to translateable diagnostics
CleanCut Sep 28, 2022
f0afb88
migrate lang_items.rs to translateable diagnostics
CleanCut Oct 1, 2022
a7aa185
migrate dead.rs to translateable diagnostics
CleanCut Oct 2, 2022
3fe8e00
migrate the rest of check_attr.rs to translateable diagnostics
CleanCut Oct 2, 2022
be4059d
migrate stability.rs to translateable diagnostics
CleanCut Oct 3, 2022
965dbf6
First batch of review feedback changes from #102110
CleanCut Oct 3, 2022
8e07a85
Remove code that was removed in master, and the corresponding diagnostic
CleanCut Oct 5, 2022
57eba4f
avoid string dispatch in fluent
CleanCut Oct 5, 2022
31c269a
avoid string dispatch in fluent
CleanCut Oct 7, 2022
50e2795
remove out-of-date fixme
CleanCut Oct 10, 2022
5ef1c03
make up your mind, rustfmt
CleanCut Oct 10, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions compiler/rustc_error_messages/locales/en-US/middle.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,12 @@ middle_limit_invalid =

middle_const_eval_non_int =
constant evaluation of enum discriminant resulted in non-integer

middle_unknown_layout =
the type `{$ty}` has an unknown layout

middle_values_too_big =
values of the type `{$ty}` are too big for the current architecture

middle_cannot_be_normalized =
unable to determine layout for `{$ty}` because `{$failure_ty}` cannot be normalized
559 changes: 478 additions & 81 deletions compiler/rustc_error_messages/locales/en-US/passes.ftl

Large diffs are not rendered by default.

50 changes: 50 additions & 0 deletions compiler/rustc_errors/src/diagnostic_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,56 @@ impl EmissionGuarantee for () {
}
}

/// Marker type which enables implementation of `create_note` and `emit_note` functions for
/// note-without-error struct diagnostics.
#[derive(Copy, Clone)]
pub struct Noted;

impl<'a> DiagnosticBuilder<'a, Noted> {
/// Convenience function for internal use, clients should use one of the
/// `struct_*` methods on [`Handler`].
pub(crate) fn new_note(handler: &'a Handler, message: impl Into<DiagnosticMessage>) -> Self {
let diagnostic = Diagnostic::new_with_code(Level::Note, None, message);
Self::new_diagnostic_note(handler, diagnostic)
}

/// Creates a new `DiagnosticBuilder` with an already constructed
/// diagnostic.
pub(crate) fn new_diagnostic_note(handler: &'a Handler, diagnostic: Diagnostic) -> Self {
debug!("Created new diagnostic");
Self {
inner: DiagnosticBuilderInner {
state: DiagnosticBuilderState::Emittable(handler),
diagnostic: Box::new(diagnostic),
},
_marker: PhantomData,
}
}
}

impl EmissionGuarantee for Noted {
fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self {
match db.inner.state {
// First `.emit()` call, the `&Handler` is still available.
DiagnosticBuilderState::Emittable(handler) => {
db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
handler.emit_diagnostic(&mut db.inner.diagnostic);
}
// `.emit()` was previously called, disallowed from repeating it.
DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {}
}

Noted
}

fn make_diagnostic_builder(
handler: &Handler,
msg: impl Into<DiagnosticMessage>,
) -> DiagnosticBuilder<'_, Self> {
DiagnosticBuilder::new_note(handler, msg)
}
}

impl<'a> DiagnosticBuilder<'a, !> {
/// Convenience function for internal use, clients should use one of the
/// `struct_*` methods on [`Handler`].
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_errors/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ pub use diagnostic::{
AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgFromDisplay,
DiagnosticArgValue, DiagnosticId, DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic,
};
pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee};
pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee, Noted};
use std::backtrace::Backtrace;

/// A handler deals with errors and other compiler output.
Expand Down
21 changes: 20 additions & 1 deletion compiler/rustc_middle/src/ty/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,10 +191,29 @@ pub enum LayoutError<'tcx> {

impl<'a> IntoDiagnostic<'a, !> for LayoutError<'a> {
fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, !> {
handler.struct_fatal(self.to_string())
let mut diag = handler.struct_fatal("");

match self {
LayoutError::Unknown(ty) => {
diag.set_arg("ty", ty);
diag.set_primary_message(rustc_errors::fluent::middle::unknown_layout);
}
LayoutError::SizeOverflow(ty) => {
diag.set_arg("ty", ty);
diag.set_primary_message(rustc_errors::fluent::middle::values_too_big);
}
LayoutError::NormalizationFailure(ty, e) => {
diag.set_arg("ty", ty);
diag.set_arg("failure_ty", e.get_type_for_failure());
diag.set_primary_message(rustc_errors::fluent::middle::cannot_be_normalized);
}
}
diag
}
}

// FIXME: Once the other errors that embed this error have been converted to translateable
// diagnostics, this Display impl should be removed.
impl<'tcx> fmt::Display for LayoutError<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
Expand Down
151 changes: 61 additions & 90 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@
//! conflicts between multiple such attributes attached to the same
//! item.

use crate::errors;
use crate::errors::{
self, AttrApplication, DebugVisualizerUnreadable, InvalidAttrAtCrateLevel, ObjectLifetimeErr,
OnlyHasEffectOn, TransparentIncompatible, UnrecognizedReprHint,
};
use rustc_ast::{ast, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem};
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{fluent, struct_span_err, Applicability, MultiSpan};
use rustc_errors::{fluent, Applicability, MultiSpan};
use rustc_expand::base::resolve_path;
use rustc_feature::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
use rustc_hir as hir;
Expand Down Expand Up @@ -164,17 +167,17 @@ impl CheckAttrVisitor<'_> {
sym::no_mangle => self.check_no_mangle(hir_id, attr, span, target),
sym::deprecated => self.check_deprecated(hir_id, attr, span, target),
sym::macro_use | sym::macro_escape => self.check_macro_use(hir_id, attr, target),
sym::path => self.check_generic_attr(hir_id, attr, target, &[Target::Mod]),
sym::path => self.check_generic_attr(hir_id, attr, target, Target::Mod),
sym::plugin_registrar => self.check_plugin_registrar(hir_id, attr, target),
sym::macro_export => self.check_macro_export(hir_id, attr, target),
sym::ignore | sym::should_panic | sym::proc_macro_derive => {
self.check_generic_attr(hir_id, attr, target, &[Target::Fn])
self.check_generic_attr(hir_id, attr, target, Target::Fn)
}
sym::automatically_derived => {
self.check_generic_attr(hir_id, attr, target, &[Target::Impl])
self.check_generic_attr(hir_id, attr, target, Target::Impl)
}
sym::no_implicit_prelude => {
self.check_generic_attr(hir_id, attr, target, &[Target::Mod])
self.check_generic_attr(hir_id, attr, target, Target::Mod)
}
sym::rustc_object_lifetime_default => self.check_object_lifetime_default(hir_id),
_ => {}
Expand Down Expand Up @@ -351,31 +354,17 @@ impl CheckAttrVisitor<'_> {
hir_id: HirId,
attr: &Attribute,
target: Target,
allowed_targets: &[Target],
allowed_target: Target,
) {
if !allowed_targets.iter().any(|t| t == &target) {
let name = attr.name_or_empty();
let mut i = allowed_targets.iter();
// Pluralize
let b = i.next().map_or_else(String::new, |t| t.to_string() + "s");
let supported_names = i.enumerate().fold(b, |mut b, (i, allowed_target)| {
if allowed_targets.len() > 2 && i == allowed_targets.len() - 2 {
b.push_str(", and ");
} else if allowed_targets.len() == 2 && i == allowed_targets.len() - 2 {
b.push_str(" and ");
} else {
b.push_str(", ");
}
// Pluralize
b.push_str(&(allowed_target.to_string() + "s"));
b
});
self.tcx.struct_span_lint_hir(
if target != allowed_target {
self.tcx.emit_spanned_lint(
CleanCut marked this conversation as resolved.
Show resolved Hide resolved
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
&format!("`#[{name}]` only has an effect on {}", supported_names),
|lint| lint,
OnlyHasEffectOn {
attr_name: attr.name_or_empty(),
target_name: allowed_target.name().replace(" ", "_"),
},
);
}
}
Expand Down Expand Up @@ -432,7 +421,7 @@ impl CheckAttrVisitor<'_> {
ObjectLifetimeDefault::Param(def_id) => tcx.item_name(def_id).to_string(),
ObjectLifetimeDefault::Ambiguous => "Ambiguous".to_owned(),
};
tcx.sess.span_err(p.span, &repr);
tcx.sess.emit_err(ObjectLifetimeErr { span: p.span, repr });
}
}
}
Expand Down Expand Up @@ -1605,12 +1594,17 @@ impl CheckAttrVisitor<'_> {
continue;
}

let (article, allowed_targets) = match hint.name_or_empty() {
match hint.name_or_empty() {
sym::C => {
is_c = true;
match target {
Target::Struct | Target::Union | Target::Enum => continue,
_ => ("a", "struct, enum, or union"),
_ => {
self.tcx.sess.emit_err(AttrApplication::StructEnumUnion {
hint_span: hint.span(),
span,
});
}
}
}
sym::align => {
Expand All @@ -1626,20 +1620,30 @@ impl CheckAttrVisitor<'_> {

match target {
Target::Struct | Target::Union | Target::Enum | Target::Fn => continue,
_ => ("a", "struct, enum, function, or union"),
_ => {
self.tcx.sess.emit_err(AttrApplication::StructEnumFunctionUnion {
hint_span: hint.span(),
span,
});
}
}
}
sym::packed => {
if target != Target::Struct && target != Target::Union {
("a", "struct or union")
self.tcx.sess.emit_err(AttrApplication::StructUnion {
hint_span: hint.span(),
span,
});
} else {
continue;
}
}
sym::simd => {
is_simd = true;
if target != Target::Struct {
("a", "struct")
self.tcx
.sess
.emit_err(AttrApplication::Struct { hint_span: hint.span(), span });
} else {
continue;
}
Expand All @@ -1648,7 +1652,12 @@ impl CheckAttrVisitor<'_> {
is_transparent = true;
match target {
Target::Struct | Target::Union | Target::Enum => continue,
_ => ("a", "struct, enum, or union"),
_ => {
self.tcx.sess.emit_err(AttrApplication::StructEnumUnion {
hint_span: hint.span(),
span,
});
}
}
}
sym::i8
Expand All @@ -1665,35 +1674,18 @@ impl CheckAttrVisitor<'_> {
| sym::usize => {
int_reprs += 1;
if target != Target::Enum {
("an", "enum")
self.tcx
.sess
.emit_err(AttrApplication::Enum { hint_span: hint.span(), span });
} else {
continue;
}
}
_ => {
struct_span_err!(
self.tcx.sess,
hint.span(),
E0552,
"unrecognized representation hint"
)
.help("valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, \
`i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`")
.emit();

self.tcx.sess.emit_err(UnrecognizedReprHint { span: hint.span() });
continue;
}
};

struct_span_err!(
self.tcx.sess,
hint.span(),
E0517,
"{}",
&format!("attribute should be applied to {article} {allowed_targets}")
)
.span_label(span, &format!("not {article} {allowed_targets}"))
.emit();
}

// Just point at all repr hints if there are any incompatibilities.
Expand All @@ -1703,14 +1695,9 @@ impl CheckAttrVisitor<'_> {
// Error on repr(transparent, <anything else>).
if is_transparent && hints.len() > 1 {
let hint_spans: Vec<_> = hint_spans.clone().collect();
struct_span_err!(
self.tcx.sess,
hint_spans,
E0692,
"transparent {} cannot have other repr hints",
target
)
.emit();
self.tcx
.sess
.emit_err(TransparentIncompatible { hint_spans, target: target.to_string() });
}
// Warn on repr(u8, u16), repr(C, simd), and c-like-enum-repr(C, u8)
if (int_reprs > 1)
Expand Down Expand Up @@ -1862,14 +1849,12 @@ impl CheckAttrVisitor<'_> {

match std::fs::File::open(&file) {
Ok(_) => true,
Err(err) => {
self.tcx
.sess
.struct_span_err(
meta_item.span,
&format!("couldn't read {}: {}", file.display(), err),
)
.emit();
Err(error) => {
self.tcx.sess.emit_err(DebugVisualizerUnreadable {
span: meta_item.span,
file: &file,
error,
});
false
}
}
Expand Down Expand Up @@ -2180,25 +2165,11 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
if attr.style == AttrStyle::Inner {
for attr_to_check in ATTRS_TO_CHECK {
if attr.has_name(*attr_to_check) {
let mut err = tcx.sess.struct_span_err(
attr.span,
&format!(
"`{}` attribute cannot be used at crate level",
attr_to_check.to_ident_string()
),
);
// Only emit an error with a suggestion if we can create a
// string out of the attribute span
if let Ok(src) = tcx.sess.source_map().span_to_snippet(attr.span) {
let replacement = src.replace("#!", "#");
err.span_suggestion_verbose(
attr.span,
"perhaps you meant to use an outer attribute",
replacement,
rustc_errors::Applicability::MachineApplicable,
);
}
err.emit();
tcx.sess.emit_err(InvalidAttrAtCrateLevel {
span: attr.span,
snippet: tcx.sess.source_map().span_to_snippet(attr.span).ok(),
name: *attr_to_check,
});
}
}
}
Expand Down
Loading