Skip to content

Commit

Permalink
Rollup merge of rust-lang#102110 - CleanCut:migrate_rustc_passes_diag…
Browse files Browse the repository at this point in the history
…nostics, 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`
  • Loading branch information
Dylan-DPC committed Oct 11, 2022
2 parents 3655784 + 5ef1c03 commit 91509c9
Show file tree
Hide file tree
Showing 24 changed files with 1,793 additions and 756 deletions.
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(
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

0 comments on commit 91509c9

Please sign in to comment.