about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl2
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/orphan.rs160
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs47
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs7
4 files changed, 87 insertions, 129 deletions
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<A>` in `impl<A, B> for C<B> in D<A>`
@@ -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<MyType>`, we will properly attribute the
-                    // problem to `Vec<T>` 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<errors::OnlyCurrentTraitsForeign>,
-                    name: &mut Vec<errors::OnlyCurrentTraitsName<'tcx>>,
-                    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<OnlyCurrentTraitsOpaque>,
-        #[subdiagnostic]
-        foreign: Vec<OnlyCurrentTraitsForeign>,
-        #[subdiagnostic]
-        name: Vec<OnlyCurrentTraitsName<'a>>,
-        #[subdiagnostic]
-        pointer: Vec<OnlyCurrentTraitsPointer<'a>>,
-        #[subdiagnostic]
-        ty: Vec<OnlyCurrentTraitsTy<'a>>,
-        #[subdiagnostic]
-        sugg: Option<OnlyCurrentTraitsPointerSugg<'a>>,
     },
     #[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<OnlyCurrentTraitsOpaque>,
-        #[subdiagnostic]
-        foreign: Vec<OnlyCurrentTraitsForeign>,
-        #[subdiagnostic]
-        name: Vec<OnlyCurrentTraitsName<'a>>,
-        #[subdiagnostic]
-        pointer: Vec<OnlyCurrentTraitsPointer<'a>>,
-        #[subdiagnostic]
-        ty: Vec<OnlyCurrentTraitsTy<'a>>,
-        #[subdiagnostic]
-        sugg: Option<OnlyCurrentTraitsPointerSugg<'a>>,
     },
     #[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<OnlyCurrentTraitsOpaque>,
-        #[subdiagnostic]
-        foreign: Vec<OnlyCurrentTraitsForeign>,
-        #[subdiagnostic]
-        name: Vec<OnlyCurrentTraitsName<'a>>,
-        #[subdiagnostic]
-        pointer: Vec<OnlyCurrentTraitsPointer<'a>>,
-        #[subdiagnostic]
-        ty: Vec<OnlyCurrentTraitsTy<'a>>,
-        #[subdiagnostic]
-        sugg: Option<OnlyCurrentTraitsPointerSugg<'a>>,
     },
 }
 
@@ -1445,7 +1409,6 @@ pub struct OnlyCurrentTraitsOpaque {
     #[primary_span]
     pub span: Span,
 }
-
 #[derive(Subdiagnostic)]
 #[label(hir_analysis_only_current_traits_foreign)]
 pub struct OnlyCurrentTraitsForeign {
@@ -1478,6 +1441,14 @@ pub struct OnlyCurrentTraitsTy<'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,
     applicability = "maybe-incorrect"
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 @@ impl<'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))
     }