diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 9bf4d63267a..d8a90d62dac 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -295,6 +295,8 @@ hir_analysis_not_supported_delegation =
{$descr} is not supported yet
.label = callee defined here
+hir_analysis_only_current_traits_adt = `{$name}` is not defined in the current crate
+
hir_analysis_only_current_traits_arbitrary = only traits defined in the current crate can be implemented for arbitrary types
hir_analysis_only_current_traits_foreign = this is not defined in the current crate because this is a foreign trait
diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index ca8a635ab5e..1770f7b4e91 100644
--- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -4,7 +4,7 @@
use crate::errors;
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
-use rustc_middle::ty::{self, AliasKind, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{self, AliasKind, TyCtxt, TypeVisitableExt};
use rustc_span::def_id::LocalDefId;
use rustc_span::Span;
use rustc_trait_selection::traits::{self, IsFirstInputType};
@@ -283,9 +283,14 @@ fn emit_orphan_check_error<'tcx>(
let self_ty = trait_ref.self_ty();
Err(match err {
traits::OrphanCheckErr::NonLocalInputType(tys) => {
- let (mut opaque, mut foreign, mut name, mut pointer, mut ty_diag) =
- (Vec::new(), Vec::new(), Vec::new(), Vec::new(), Vec::new());
- let mut sugg = None;
+ let mut diag = tcx.dcx().create_err(match self_ty.kind() {
+ ty::Adt(..) => errors::OnlyCurrentTraits::Outside { span: sp, note: () },
+ _ if self_ty.is_primitive() => {
+ errors::OnlyCurrentTraits::Primitive { span: sp, note: () }
+ }
+ _ => errors::OnlyCurrentTraits::Arbitrary { span: sp, note: () },
+ });
+
for &(mut ty, is_target_ty) in &tys {
let span = if matches!(is_target_ty, IsFirstInputType::Yes) {
// Point at `D` in `impl for C in D`
@@ -296,113 +301,86 @@ fn emit_orphan_check_error<'tcx>(
};
ty = tcx.erase_regions(ty);
- ty = match ty.kind() {
- // Remove the type arguments from the output, as they are not relevant.
- // You can think of this as the reverse of `resolve_vars_if_possible`.
- // That way if we had `Vec`, we will properly attribute the
- // problem to `Vec` and avoid confusing the user if they were to see
- // `MyType` in the error.
- ty::Adt(def, _) => Ty::new_adt(tcx, *def, ty::List::empty()),
- _ => ty,
- };
-
- fn push_to_foreign_or_name<'tcx>(
- is_foreign: bool,
- foreign: &mut Vec,
- name: &mut Vec>,
- span: Span,
- sname: &'tcx str,
- ) {
- if is_foreign {
- foreign.push(errors::OnlyCurrentTraitsForeign { span })
- } else {
- name.push(errors::OnlyCurrentTraitsName { span, name: sname });
- }
- }
let is_foreign =
!trait_ref.def_id.is_local() && matches!(is_target_ty, IsFirstInputType::No);
match *ty.kind() {
ty::Slice(_) => {
- push_to_foreign_or_name(
- is_foreign,
- &mut foreign,
- &mut name,
- span,
- "slices",
- );
+ if is_foreign {
+ diag.subdiagnostic(
+ tcx.dcx(),
+ errors::OnlyCurrentTraitsForeign { span },
+ );
+ } else {
+ diag.subdiagnostic(
+ tcx.dcx(),
+ errors::OnlyCurrentTraitsName { span, name: "slices" },
+ );
+ }
}
ty::Array(..) => {
- push_to_foreign_or_name(
- is_foreign,
- &mut foreign,
- &mut name,
- span,
- "arrays",
- );
+ if is_foreign {
+ diag.subdiagnostic(
+ tcx.dcx(),
+ errors::OnlyCurrentTraitsForeign { span },
+ );
+ } else {
+ diag.subdiagnostic(
+ tcx.dcx(),
+ errors::OnlyCurrentTraitsName { span, name: "arrays" },
+ );
+ }
}
ty::Tuple(..) => {
- push_to_foreign_or_name(
- is_foreign,
- &mut foreign,
- &mut name,
- span,
- "tuples",
- );
+ if is_foreign {
+ diag.subdiagnostic(
+ tcx.dcx(),
+ errors::OnlyCurrentTraitsForeign { span },
+ );
+ } else {
+ diag.subdiagnostic(
+ tcx.dcx(),
+ errors::OnlyCurrentTraitsName { span, name: "tuples" },
+ );
+ }
}
ty::Alias(ty::Opaque, ..) => {
- opaque.push(errors::OnlyCurrentTraitsOpaque { span })
+ diag.subdiagnostic(tcx.dcx(), errors::OnlyCurrentTraitsOpaque { span });
}
ty::RawPtr(ptr_ty, mutbl) => {
if !self_ty.has_param() {
- let mut_key = mutbl.prefix_str();
- sugg = Some(errors::OnlyCurrentTraitsPointerSugg {
- wrapper_span: self_ty_span,
- struct_span: full_impl_span.shrink_to_lo(),
- mut_key,
- ptr_ty,
- });
+ diag.subdiagnostic(
+ tcx.dcx(),
+ errors::OnlyCurrentTraitsPointerSugg {
+ wrapper_span: self_ty_span,
+ struct_span: full_impl_span.shrink_to_lo(),
+ mut_key: mutbl.prefix_str(),
+ ptr_ty,
+ },
+ );
}
- pointer.push(errors::OnlyCurrentTraitsPointer { span, pointer: ty });
+ diag.subdiagnostic(
+ tcx.dcx(),
+ errors::OnlyCurrentTraitsPointer { span, pointer: ty },
+ );
+ }
+ ty::Adt(adt_def, _) => {
+ diag.subdiagnostic(
+ tcx.dcx(),
+ errors::OnlyCurrentTraitsAdt {
+ span,
+ name: tcx.def_path_str(adt_def.did()),
+ },
+ );
+ }
+ _ => {
+ diag.subdiagnostic(tcx.dcx(), errors::OnlyCurrentTraitsTy { span, ty });
}
- _ => ty_diag.push(errors::OnlyCurrentTraitsTy { span, ty }),
}
}
- let err_struct = match self_ty.kind() {
- ty::Adt(..) => errors::OnlyCurrentTraits::Outside {
- span: sp,
- note: (),
- opaque,
- foreign,
- name,
- pointer,
- ty: ty_diag,
- sugg,
- },
- _ if self_ty.is_primitive() => errors::OnlyCurrentTraits::Primitive {
- span: sp,
- note: (),
- opaque,
- foreign,
- name,
- pointer,
- ty: ty_diag,
- sugg,
- },
- _ => errors::OnlyCurrentTraits::Arbitrary {
- span: sp,
- note: (),
- opaque,
- foreign,
- name,
- pointer,
- ty: ty_diag,
- sugg,
- },
- };
- tcx.dcx().emit_err(err_struct)
+ diag.emit()
}
traits::OrphanCheckErr::UncoveredTy(param_ty, local_type) => {
let mut sp = sp;
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index fb919714afd..2d4742fa1dc 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -1376,7 +1376,7 @@ pub struct TyParamSome<'a> {
}
#[derive(Diagnostic)]
-pub enum OnlyCurrentTraits<'a> {
+pub enum OnlyCurrentTraits {
#[diag(hir_analysis_only_current_traits_outside, code = E0117)]
Outside {
#[primary_span]
@@ -1384,18 +1384,6 @@ pub enum OnlyCurrentTraits<'a> {
span: Span,
#[note(hir_analysis_only_current_traits_note)]
note: (),
- #[subdiagnostic]
- opaque: Vec,
- #[subdiagnostic]
- foreign: Vec,
- #[subdiagnostic]
- name: Vec>,
- #[subdiagnostic]
- pointer: Vec>,
- #[subdiagnostic]
- ty: Vec>,
- #[subdiagnostic]
- sugg: Option>,
},
#[diag(hir_analysis_only_current_traits_primitive, code = E0117)]
Primitive {
@@ -1404,18 +1392,6 @@ pub enum OnlyCurrentTraits<'a> {
span: Span,
#[note(hir_analysis_only_current_traits_note)]
note: (),
- #[subdiagnostic]
- opaque: Vec,
- #[subdiagnostic]
- foreign: Vec,
- #[subdiagnostic]
- name: Vec>,
- #[subdiagnostic]
- pointer: Vec>,
- #[subdiagnostic]
- ty: Vec>,
- #[subdiagnostic]
- sugg: Option>,
},
#[diag(hir_analysis_only_current_traits_arbitrary, code = E0117)]
Arbitrary {
@@ -1424,18 +1400,6 @@ pub enum OnlyCurrentTraits<'a> {
span: Span,
#[note(hir_analysis_only_current_traits_note)]
note: (),
- #[subdiagnostic]
- opaque: Vec,
- #[subdiagnostic]
- foreign: Vec,
- #[subdiagnostic]
- name: Vec>,
- #[subdiagnostic]
- pointer: Vec>,
- #[subdiagnostic]
- ty: Vec>,
- #[subdiagnostic]
- sugg: Option>,
},
}
@@ -1445,7 +1409,6 @@ pub struct OnlyCurrentTraitsOpaque {
#[primary_span]
pub span: Span,
}
-
#[derive(Subdiagnostic)]
#[label(hir_analysis_only_current_traits_foreign)]
pub struct OnlyCurrentTraitsForeign {
@@ -1477,6 +1440,14 @@ pub struct OnlyCurrentTraitsTy<'a> {
pub ty: Ty<'a>,
}
+#[derive(Subdiagnostic)]
+#[label(hir_analysis_only_current_traits_adt)]
+pub struct OnlyCurrentTraitsAdt {
+ #[primary_span]
+ pub span: Span,
+ pub name: String,
+}
+
#[derive(Subdiagnostic)]
#[multipart_suggestion(
hir_analysis_only_current_traits_pointer_sugg,
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 57a675e4453..b5e619f1e2a 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1624,6 +1624,13 @@ pub fn new_imm_ptr(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
#[inline]
pub fn new_adt(tcx: TyCtxt<'tcx>, def: AdtDef<'tcx>, args: GenericArgsRef<'tcx>) -> Ty<'tcx> {
+ debug_assert_eq!(
+ tcx.generics_of(def.did()).count(),
+ args.len(),
+ "wrong number of args for ADT: {:#?} vs {:#?}",
+ tcx.generics_of(def.did()).params,
+ args
+ );
Ty::new(tcx, Adt(def, args))
}