summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_hir_analysis/src/check/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_hir_analysis/src/check/mod.rs')
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs201
1 files changed, 107 insertions, 94 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 8fe4c44fc..3971a4c01 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -74,11 +74,11 @@ pub use check::check_abi;
use check::check_mod_item_types;
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::intravisit::Visitor;
use rustc_index::bit_set::BitSet;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{InternalSubsts, SubstsRef};
use rustc_session::parse::feature_err;
@@ -90,6 +90,7 @@ use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits::error_reporting::suggestions::ReturnsVisitor;
use std::num::NonZeroU32;
+use crate::errors;
use crate::require_c_abi_if_c_variadic;
use crate::util::common::indenter;
@@ -171,34 +172,18 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId) {
fn report_forbidden_specialization(tcx: TyCtxt<'_>, impl_item: DefId, parent_impl: DefId) {
let span = tcx.def_span(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) {
- Ok(span) => {
- err.span_label(span, "parent `impl` is here");
- 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();
+ let err = match tcx.span_of_impl(parent_impl) {
+ Ok(sp) => errors::ImplNotMarkedDefault::Ok { span, ident, ok_label: sp },
+ Err(cname) => errors::ImplNotMarkedDefault::Err { span, ident, cname },
+ };
+
+ tcx.sess.emit_err(err);
}
fn missing_items_err(
tcx: TyCtxt<'_>,
- impl_span: Span,
+ impl_def_id: LocalDefId,
missing_items: &[ty::AssocItem],
full_impl_span: Span,
) {
@@ -211,14 +196,6 @@ fn missing_items_err(
.collect::<Vec<_>>()
.join("`, `");
- 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.
let hi = full_impl_span.hi() - BytePos(1);
// Point at the place right before the closing brace of the relevant `impl` to suggest
@@ -227,20 +204,40 @@ fn missing_items_err(
// Obtain the level of indentation ending in `sugg_sp`.
let padding =
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 {
- let snippet = suggestion_signature(trait_item, tcx);
+ let snippet = suggestion_signature(
+ tcx,
+ trait_item,
+ tcx.impl_trait_ref(impl_def_id).unwrap().subst_identity(),
+ );
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) {
- err.span_label(span, format!("`{}` from trait", trait_item.name));
- err.tool_only_span_suggestion(sugg_sp, &msg, code, appl);
+ missing_trait_item_label
+ .push(errors::MissingTraitItemLabel { span, item: trait_item.name });
+ missing_trait_item.push(errors::MissingTraitItemSuggestion {
+ span: sugg_sp,
+ code,
+ snippet,
+ });
} 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(
@@ -252,19 +249,11 @@ fn missing_items_must_implement_one_of_err(
let missing_items_msg =
missing_items.iter().map(Ident::to_string).collect::<Vec<_>>().join("`, `");
- let mut err = struct_span_err!(
- tcx.sess,
- impl_span,
- E0046,
- "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();
+ tcx.sess.emit_err(errors::MissingOneOfTraitItem {
+ span: impl_span,
+ note: annotation_span,
+ missing_items_msg,
+ });
}
fn default_body_is_unstable(
@@ -276,36 +265,42 @@ fn default_body_is_unstable(
issue: Option<NonZeroU32>,
) {
let missing_item_name = tcx.associated_item(item_did).name;
- let use_of_unstable_library_feature_note = match reason {
- Some(r) => format!("use of unstable library feature '{feature}': {r}"),
- None => format!("use of unstable library feature '{feature}'"),
+ let (mut some_note, mut none_note, mut reason_str) = (false, false, String::new());
+ match reason {
+ Some(r) => {
+ some_note = true;
+ reason_str = r.to_string();
+ }
+ None => none_note = true,
};
- let mut err = struct_span_err!(
- tcx.sess,
- impl_span,
- E0046,
- "not all trait items implemented, missing: `{missing_item_name}`",
- );
- err.note(format!("default implementation of `{missing_item_name}` is unstable"));
- err.note(use_of_unstable_library_feature_note);
+ let mut err = tcx.sess.create_err(errors::MissingTraitItemUnstable {
+ span: impl_span,
+ some_note,
+ none_note,
+ missing_item_name,
+ feature,
+ reason: reason_str,
+ });
+
rustc_session::parse::add_feature_diagnostics_for_issue(
&mut err,
&tcx.sess.parse_sess,
feature,
rustc_feature::GateIssue::Library(issue),
);
+
err.emit();
}
/// Re-sugar `ty::GenericPredicates` in a way suitable to be used in structured suggestions.
fn bounds_from_generic_predicates<'tcx>(
tcx: TyCtxt<'tcx>,
- predicates: ty::GenericPredicates<'tcx>,
+ predicates: impl IntoIterator<Item = (ty::Predicate<'tcx>, Span)>,
) -> (String, String) {
let mut types: FxHashMap<Ty<'tcx>, Vec<DefId>> = FxHashMap::default();
let mut projections = vec![];
- for (predicate, _) in predicates.predicates {
+ for (predicate, _) in predicates {
debug!("predicate {:?}", predicate);
let bound_predicate = predicate.kind();
match bound_predicate.skip_binder() {
@@ -367,7 +362,7 @@ fn fn_sig_suggestion<'tcx>(
tcx: TyCtxt<'tcx>,
sig: ty::FnSig<'tcx>,
ident: Ident,
- predicates: ty::GenericPredicates<'tcx>,
+ predicates: impl IntoIterator<Item = (ty::Predicate<'tcx>, Span)>,
assoc: ty::AssocItem,
) -> String {
let args = sig
@@ -436,7 +431,17 @@ pub fn ty_kind_suggestion(ty: Ty<'_>) -> Option<&'static str> {
/// Return placeholder code for the given associated item.
/// Similar to `ty::AssocItem::suggestion`, but appropriate for use as the code snippet of a
/// structured suggestion.
-fn suggestion_signature(assoc: ty::AssocItem, tcx: TyCtxt<'_>) -> String {
+fn suggestion_signature<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ assoc: ty::AssocItem,
+ impl_trait_ref: ty::TraitRef<'tcx>,
+) -> String {
+ let substs = ty::InternalSubsts::identity_for_item(tcx, assoc.def_id).rebase_onto(
+ tcx,
+ assoc.container_id(tcx),
+ impl_trait_ref.with_self_ty(tcx, tcx.types.self_param).substs,
+ );
+
match assoc.kind {
ty::AssocKind::Fn => {
// We skip the binder here because the binder would deanonymize all
@@ -445,16 +450,22 @@ fn suggestion_signature(assoc: ty::AssocItem, tcx: TyCtxt<'_>) -> String {
// regions just fine, showing `fn(&MyType)`.
fn_sig_suggestion(
tcx,
- tcx.fn_sig(assoc.def_id).subst_identity().skip_binder(),
+ tcx.fn_sig(assoc.def_id).subst(tcx, substs).skip_binder(),
assoc.ident(tcx),
- tcx.predicates_of(assoc.def_id),
+ tcx.predicates_of(assoc.def_id).instantiate_own(tcx, substs),
assoc,
)
}
- ty::AssocKind::Type => format!("type {} = Type;", assoc.name),
+ ty::AssocKind::Type => {
+ let (generics, where_clauses) = bounds_from_generic_predicates(
+ tcx,
+ tcx.predicates_of(assoc.def_id).instantiate_own(tcx, substs),
+ );
+ format!("type {}{generics} = /* Type */{where_clauses};", assoc.name)
+ }
ty::AssocKind::Const => {
let ty = tcx.type_of(assoc.def_id).subst_identity();
- let val = ty_kind_suggestion(ty).unwrap_or("value");
+ let val = ty_kind_suggestion(ty).unwrap_or("todo!()");
format!("const {}: {} = {};", assoc.name, ty, val)
}
}
@@ -467,16 +478,18 @@ fn bad_variant_count<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>, sp: Span, d
.iter()
.map(|variant| tcx.hir().span_if_local(variant.def_id).unwrap())
.collect();
- let msg = format!("needs exactly one variant, but has {}", adt.variants().len(),);
- let mut err = struct_span_err!(tcx.sess, sp, E0731, "transparent enum {msg}");
- err.span_label(sp, &msg);
+ let (mut spans, mut many) = (Vec::new(), None);
if let [start @ .., end] = &*variant_spans {
- for variant_span in start {
- err.span_label(*variant_span, "");
- }
- err.span_label(*end, &format!("too many variants in `{}`", tcx.def_path_str(did)));
+ spans = start.to_vec();
+ many = Some(*end);
}
- 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
@@ -488,21 +501,21 @@ fn bad_non_zero_sized_fields<'tcx>(
field_spans: impl Iterator<Item = Span>,
sp: Span,
) {
- let msg = format!("needs at most one non-zero-sized field, but has {field_count}");
- let mut err = struct_span_err!(
- tcx.sess,
- sp,
- E0690,
- "{}transparent {} {}",
- if adt.is_enum() { "the variant of a " } else { "" },
- adt.descr(),
- msg,
- );
- err.span_label(sp, &msg);
- for sp in field_spans {
- err.span_label(sp, "this field is non-zero-sized");
+ if adt.is_enum() {
+ tcx.sess.emit_err(errors::TransparentNonZeroSizedEnum {
+ span: sp,
+ spans: field_spans.collect(),
+ field_count,
+ desc: adt.descr(),
+ });
+ } else {
+ tcx.sess.emit_err(errors::TransparentNonZeroSized {
+ span: sp,
+ spans: field_spans.collect(),
+ field_count,
+ desc: adt.descr(),
+ });
}
- err.emit();
}
// FIXME: Consider moving this method to a more fitting place.