1
Fork 0

Migrate rustc_hir_analysis to session diagnostic

Part 4: Finishing `check/mod.rs` file
This commit is contained in:
Obei Sideg 2023-04-14 18:02:41 +03:00
parent fa4cc63a6b
commit 06ff310cf9
5 changed files with 253 additions and 84 deletions

View file

@ -225,3 +225,40 @@ hir_analysis_functions_names_duplicated = functions names are duplicated
hir_analysis_simd_ffi_highly_experimental = use of SIMD type{$snip} in FFI is highly experimental and may result in invalid code hir_analysis_simd_ffi_highly_experimental = use of SIMD type{$snip} in FFI is highly experimental and may result in invalid code
.help = add `#![feature(simd_ffi)]` to the crate attributes to enable .help = add `#![feature(simd_ffi)]` to the crate attributes to enable
hir_analysis_impl_not_marked_default = `{$ident}` specializes an item from a parent `impl`, but that item is not marked `default`
.label = cannot specialize default item `{$ident}`
.ok_label = parent `impl` is here
.note = to specialize, `{$ident}` in the parent `impl` must be marked `default`
hir_analysis_impl_not_marked_default_err = `{$ident}` specializes an item from a parent `impl`, but that item is not marked `default`
.note = parent implementation is in crate `{$cname}`
hir_analysis_missing_trait_item = not all trait items implemented, missing: `{$missing_items_msg}`
.label = missing `{$missing_items_msg}` in implementation
hir_analysis_missing_trait_item_suggestion = implement the missing item: `{$snippet}`
hir_analysis_missing_trait_item_label = `{$item}` from trait
hir_analysis_missing_one_of_trait_item = not all trait items implemented, missing one of: `{$missing_items_msg}`
.label = missing one of `{$missing_items_msg}` in implementation
.note = required because of this annotation
hir_analysis_missing_trait_item_unstable = not all trait items implemented, missing: `{$missing_item_name}`
.note = default implementation of `{$missing_item_name}` is unstable
.some_note = use of unstable library feature '{$feature}': {$r}
.none_note = use of unstable library feature '{$feature}'
hir_analysis_transparent_enum_variant = transparent enum needs exactly one variant, but has {$number}
.label = needs exactly one variant, but has {$number}
.many_label = too many variants in `{$path}`
.multi_label = variant here
hir_analysis_transparent_non_zero_sized_enum = the variant of a transparent {$desc} needs at most one non-zero-sized field, but has {$field_count}
.label = needs at most one non-zero-sized field, but has {$field_count}
.labels = this field is non-zero-sized
hir_analysis_transparent_non_zero_sized = transparent {$desc} needs at most one non-zero-sized field, but has {$field_count}
.label = needs at most one non-zero-sized field, but has {$field_count}
.labels = this field is non-zero-sized

View file

@ -74,7 +74,7 @@ pub use check::check_abi;
use check::check_mod_item_types; use check::check_mod_item_types;
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder}; use rustc_errors::{pluralize, struct_span_err, Diagnostic, DiagnosticBuilder};
use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::Visitor; use rustc_hir::intravisit::Visitor;
use rustc_index::bit_set::BitSet; use rustc_index::bit_set::BitSet;
@ -90,6 +90,7 @@ use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits::error_reporting::suggestions::ReturnsVisitor; use rustc_trait_selection::traits::error_reporting::suggestions::ReturnsVisitor;
use std::num::NonZeroU32; use std::num::NonZeroU32;
use crate::errors;
use crate::require_c_abi_if_c_variadic; use crate::require_c_abi_if_c_variadic;
use crate::util::common::indenter; use crate::util::common::indenter;
@ -171,29 +172,13 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId) {
fn report_forbidden_specialization(tcx: TyCtxt<'_>, impl_item: DefId, parent_impl: DefId) { fn report_forbidden_specialization(tcx: TyCtxt<'_>, impl_item: DefId, parent_impl: DefId) {
let span = tcx.def_span(impl_item); let span = tcx.def_span(impl_item);
let ident = tcx.item_name(impl_item); let ident = tcx.item_name(impl_item);
let mut err = struct_span_err!(
tcx.sess,
span,
E0520,
"`{}` specializes an item from a parent `impl`, but that item is not marked `default`",
ident,
);
err.span_label(span, format!("cannot specialize default item `{}`", ident));
match tcx.span_of_impl(parent_impl) { let err = match tcx.span_of_impl(parent_impl) {
Ok(span) => { Ok(sp) => errors::ImplNotMarkedDefault::Ok { span, ident, ok_label: sp },
err.span_label(span, "parent `impl` is here"); Err(cname) => errors::ImplNotMarkedDefault::Err { span, ident, cname },
err.note(&format!( };
"to specialize, `{}` in the parent `impl` must be marked `default`",
ident
));
}
Err(cname) => {
err.note(&format!("parent implementation is in crate `{cname}`"));
}
}
err.emit(); tcx.sess.emit_err(err);
} }
fn missing_items_err( fn missing_items_err(
@ -211,15 +196,6 @@ fn missing_items_err(
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join("`, `"); .join("`, `");
let impl_span = tcx.def_span(impl_def_id);
let mut err = struct_span_err!(
tcx.sess,
impl_span,
E0046,
"not all trait items implemented, missing: `{missing_items_msg}`",
);
err.span_label(impl_span, format!("missing `{missing_items_msg}` in implementation"));
// `Span` before impl block closing brace. // `Span` before impl block closing brace.
let hi = full_impl_span.hi() - BytePos(1); let hi = full_impl_span.hi() - BytePos(1);
// Point at the place right before the closing brace of the relevant `impl` to suggest // Point at the place right before the closing brace of the relevant `impl` to suggest
@ -228,6 +204,8 @@ fn missing_items_err(
// Obtain the level of indentation ending in `sugg_sp`. // Obtain the level of indentation ending in `sugg_sp`.
let padding = let padding =
tcx.sess.source_map().indentation_before(sugg_sp).unwrap_or_else(|| String::new()); tcx.sess.source_map().indentation_before(sugg_sp).unwrap_or_else(|| String::new());
let (mut missing_trait_item, mut missing_trait_item_none, mut missing_trait_item_label) =
(Vec::new(), Vec::new(), Vec::new());
for &trait_item in missing_items { for &trait_item in missing_items {
let snippet = suggestion_signature( let snippet = suggestion_signature(
@ -236,16 +214,30 @@ fn missing_items_err(
tcx.impl_trait_ref(impl_def_id).unwrap().subst_identity(), tcx.impl_trait_ref(impl_def_id).unwrap().subst_identity(),
); );
let code = format!("{}{}\n{}", padding, snippet, padding); let code = format!("{}{}\n{}", padding, snippet, padding);
let msg = format!("implement the missing item: `{snippet}`");
let appl = Applicability::HasPlaceholders;
if let Some(span) = tcx.hir().span_if_local(trait_item.def_id) { if let Some(span) = tcx.hir().span_if_local(trait_item.def_id) {
err.span_label(span, format!("`{}` from trait", trait_item.name)); missing_trait_item_label
err.tool_only_span_suggestion(sugg_sp, &msg, code, appl); .push(errors::MissingTraitItemLabel { span, item: trait_item.name });
missing_trait_item.push(errors::MissingTraitItemSuggestion {
span: sugg_sp,
code,
snippet,
});
} else { } else {
err.span_suggestion_hidden(sugg_sp, &msg, code, appl); missing_trait_item_none.push(errors::MissingTraitItemSuggestionNone {
span: sugg_sp,
code,
snippet,
})
} }
} }
err.emit();
tcx.sess.emit_err(errors::MissingTraitItem {
span: tcx.span_of_impl(impl_def_id.to_def_id()).unwrap(),
missing_items_msg,
missing_trait_item_label,
missing_trait_item,
missing_trait_item_none,
});
} }
fn missing_items_must_implement_one_of_err( fn missing_items_must_implement_one_of_err(
@ -257,19 +249,11 @@ fn missing_items_must_implement_one_of_err(
let missing_items_msg = let missing_items_msg =
missing_items.iter().map(Ident::to_string).collect::<Vec<_>>().join("`, `"); missing_items.iter().map(Ident::to_string).collect::<Vec<_>>().join("`, `");
let mut err = struct_span_err!( tcx.sess.emit_err(errors::MissingOneOfTraitItem {
tcx.sess, span: impl_span,
impl_span, note: annotation_span,
E0046, missing_items_msg,
"not all trait items implemented, missing one of: `{missing_items_msg}`", });
);
err.span_label(impl_span, format!("missing one of `{missing_items_msg}` in implementation"));
if let Some(annotation_span) = annotation_span {
err.span_note(annotation_span, "required because of this annotation");
}
err.emit();
} }
fn default_body_is_unstable( fn default_body_is_unstable(
@ -281,25 +265,31 @@ fn default_body_is_unstable(
issue: Option<NonZeroU32>, issue: Option<NonZeroU32>,
) { ) {
let missing_item_name = tcx.associated_item(item_did).name; let missing_item_name = tcx.associated_item(item_did).name;
let use_of_unstable_library_feature_note = match reason { let (mut some_note, mut none_note, mut reason_str) = (false, false, String::new());
Some(r) => format!("use of unstable library feature '{feature}': {r}"), match reason {
None => format!("use of unstable library feature '{feature}'"), Some(r) => {
some_note = true;
reason_str = r.to_string();
}
None => none_note = true,
}; };
let mut err = struct_span_err!( let mut err = tcx.sess.create_err(errors::MissingTraitItemUnstable {
tcx.sess, span: impl_span,
impl_span, some_note,
E0046, none_note,
"not all trait items implemented, missing: `{missing_item_name}`", missing_item_name,
); feature,
err.note(format!("default implementation of `{missing_item_name}` is unstable")); reason: reason_str,
err.note(use_of_unstable_library_feature_note); });
rustc_session::parse::add_feature_diagnostics_for_issue( rustc_session::parse::add_feature_diagnostics_for_issue(
&mut err, &mut err,
&tcx.sess.parse_sess, &tcx.sess.parse_sess,
feature, feature,
rustc_feature::GateIssue::Library(issue), rustc_feature::GateIssue::Library(issue),
); );
err.emit(); err.emit();
} }
@ -488,16 +478,18 @@ fn bad_variant_count<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>, sp: Span, d
.iter() .iter()
.map(|variant| tcx.hir().span_if_local(variant.def_id).unwrap()) .map(|variant| tcx.hir().span_if_local(variant.def_id).unwrap())
.collect(); .collect();
let msg = format!("needs exactly one variant, but has {}", adt.variants().len(),); let (mut spans, mut many) = (Vec::new(), None);
let mut err = struct_span_err!(tcx.sess, sp, E0731, "transparent enum {msg}");
err.span_label(sp, &msg);
if let [start @ .., end] = &*variant_spans { if let [start @ .., end] = &*variant_spans {
for variant_span in start { spans = start.to_vec();
err.span_label(*variant_span, ""); many = Some(*end);
}
err.span_label(*end, &format!("too many variants in `{}`", tcx.def_path_str(did)));
} }
err.emit(); tcx.sess.emit_err(errors::TransparentEnumVariant {
span: sp,
spans,
many,
number: adt.variants().len(),
path: tcx.def_path_str(did),
});
} }
/// Emit an error when encountering two or more non-zero-sized fields in a transparent /// Emit an error when encountering two or more non-zero-sized fields in a transparent
@ -509,21 +501,21 @@ fn bad_non_zero_sized_fields<'tcx>(
field_spans: impl Iterator<Item = Span>, field_spans: impl Iterator<Item = Span>,
sp: Span, sp: Span,
) { ) {
let msg = format!("needs at most one non-zero-sized field, but has {field_count}"); if adt.is_enum() {
let mut err = struct_span_err!( tcx.sess.emit_err(errors::TransparentNonZeroSizedEnum {
tcx.sess, span: sp,
sp, spans: field_spans.collect(),
E0690, field_count,
"{}transparent {} {}", desc: adt.descr(),
if adt.is_enum() { "the variant of a " } else { "" }, });
adt.descr(), } else {
msg, tcx.sess.emit_err(errors::TransparentNonZeroSized {
); span: sp,
err.span_label(sp, &msg); spans: field_spans.collect(),
for sp in field_spans { field_count,
err.span_label(sp, "this field is non-zero-sized"); desc: adt.descr(),
});
} }
err.emit();
} }
// FIXME: Consider moving this method to a more fitting place. // FIXME: Consider moving this method to a more fitting place.

View file

@ -631,3 +631,141 @@ pub(crate) struct SIMDFFIHighlyExperimental {
pub span: Span, pub span: Span,
pub snip: String, pub snip: String,
} }
#[derive(Diagnostic)]
pub enum ImplNotMarkedDefault {
#[diag(hir_analysis_impl_not_marked_default, code = "E0520")]
#[note]
Ok {
#[primary_span]
#[label]
span: Span,
#[label(hir_analysis_ok_label)]
ok_label: Span,
ident: Symbol,
},
#[diag(hir_analysis_impl_not_marked_default_err, code = "E0520")]
#[note]
Err {
#[primary_span]
#[label]
span: Span,
cname: Symbol,
ident: Symbol,
},
}
#[derive(Diagnostic)]
#[diag(hir_analysis_missing_trait_item, code = "E0046")]
pub(crate) struct MissingTraitItem {
#[primary_span]
#[label]
pub span: Span,
#[subdiagnostic]
pub missing_trait_item_label: Vec<MissingTraitItemLabel>,
#[subdiagnostic]
pub missing_trait_item: Vec<MissingTraitItemSuggestion>,
#[subdiagnostic]
pub missing_trait_item_none: Vec<MissingTraitItemSuggestionNone>,
pub missing_items_msg: String,
}
#[derive(Subdiagnostic)]
#[label(hir_analysis_missing_trait_item_label)]
pub(crate) struct MissingTraitItemLabel {
#[primary_span]
pub span: Span,
pub item: Symbol,
}
#[derive(Subdiagnostic)]
#[suggestion(
hir_analysis_missing_trait_item_suggestion,
style = "tool-only",
applicability = "has-placeholders",
code = "{code}"
)]
pub(crate) struct MissingTraitItemSuggestion {
#[primary_span]
pub span: Span,
pub code: String,
pub snippet: String,
}
#[derive(Subdiagnostic)]
#[suggestion(
hir_analysis_missing_trait_item_suggestion,
style = "hidden",
applicability = "has-placeholders",
code = "{code}"
)]
pub(crate) struct MissingTraitItemSuggestionNone {
#[primary_span]
pub span: Span,
pub code: String,
pub snippet: String,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_missing_one_of_trait_item, code = "E0046")]
pub(crate) struct MissingOneOfTraitItem {
#[primary_span]
#[label]
pub span: Span,
#[note]
pub note: Option<Span>,
pub missing_items_msg: String,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_missing_trait_item_unstable, code = "E0046")]
#[note]
pub(crate) struct MissingTraitItemUnstable {
#[primary_span]
pub span: Span,
#[note(hir_analysis_some_note)]
pub some_note: bool,
#[note(hir_analysis_none_note)]
pub none_note: bool,
pub missing_item_name: Symbol,
pub feature: Symbol,
pub reason: String,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_transparent_enum_variant, code = "E0731")]
pub(crate) struct TransparentEnumVariant {
#[primary_span]
#[label]
pub span: Span,
#[label(hir_analysis_multi_label)]
pub spans: Vec<Span>,
#[label(hir_analysis_many_label)]
pub many: Option<Span>,
pub number: usize,
pub path: String,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_transparent_non_zero_sized_enum, code = "E0690")]
pub(crate) struct TransparentNonZeroSizedEnum<'a> {
#[primary_span]
#[label]
pub span: Span,
#[label(hir_analysis_labels)]
pub spans: Vec<Span>,
pub field_count: usize,
pub desc: &'a str,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_transparent_non_zero_sized, code = "E0690")]
pub(crate) struct TransparentNonZeroSized<'a> {
#[primary_span]
#[label]
pub span: Span,
#[label(hir_analysis_labels)]
pub spans: Vec<Span>,
pub field_count: usize,
pub desc: &'a str,
}

View file

@ -58,7 +58,7 @@ error[E0731]: transparent enum needs exactly one variant, but has 2
LL | enum MultipleVariants { LL | enum MultipleVariants {
| ^^^^^^^^^^^^^^^^^^^^^ needs exactly one variant, but has 2 | ^^^^^^^^^^^^^^^^^^^^^ needs exactly one variant, but has 2
LL | Foo(String), LL | Foo(String),
| --- | --- variant here
LL | Bar, LL | Bar,
| --- too many variants in `MultipleVariants` | --- too many variants in `MultipleVariants`

View file

@ -5,6 +5,8 @@ LL | enum Foo {
| ^^^^^^^^ needs exactly one variant, but has 2 | ^^^^^^^^ needs exactly one variant, but has 2
LL | A(u8), B(u8), LL | A(u8), B(u8),
| - - too many variants in `Foo` | - - too many variants in `Foo`
| |
| variant here
error: aborting due to previous error error: aborting due to previous error