From 5e2c54977202a0a245dca4bfd5171ced47bed487 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 29 Mar 2024 20:40:45 -0400 Subject: [PATCH 1/3] Assert that ADTs have the right number of substs --- compiler/rustc_middle/src/ty/sty.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 57a675e4453b8..b5e619f1e2a3c 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)) } From bc1f1ef2c82c5c84e0d90c5c5d261444fba9ffec Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 29 Mar 2024 21:21:41 -0400 Subject: [PATCH 2/3] Stop removing substs from Adt type in coherence --- compiler/rustc_hir_analysis/messages.ftl | 2 ++ .../src/coherence/orphan.rs | 28 +++++++++++-------- compiler/rustc_hir_analysis/src/errors.rs | 15 +++++++++- 3 files changed, 32 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 9bf4d63267a39..d8a90d62dac69 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 ca8a635ab5eb9..92e8c45950919 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,8 +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()); + // FIXME: Someone needs to just turn these into `Subdiag`s and attach + // them to the `Diag` after creating the error. + let mut opaque = vec![]; + let mut foreign = vec![]; + let mut name = vec![]; + let mut pointer = vec![]; + let mut ty_diag = vec![]; + let mut adt = vec![]; let mut sugg = None; for &(mut ty, is_target_ty) in &tys { let span = if matches!(is_target_ty, IsFirstInputType::Yes) { @@ -296,15 +302,6 @@ 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, @@ -366,6 +363,10 @@ fn emit_orphan_check_error<'tcx>( } pointer.push(errors::OnlyCurrentTraitsPointer { span, pointer: ty }); } + ty::Adt(adt_def, _) => adt.push(errors::OnlyCurrentTraitsAdt { + span, + name: tcx.def_path_str(adt_def.did()), + }), _ => ty_diag.push(errors::OnlyCurrentTraitsTy { span, ty }), } } @@ -379,6 +380,7 @@ fn emit_orphan_check_error<'tcx>( name, pointer, ty: ty_diag, + adt, sugg, }, _ if self_ty.is_primitive() => errors::OnlyCurrentTraits::Primitive { @@ -389,6 +391,7 @@ fn emit_orphan_check_error<'tcx>( name, pointer, ty: ty_diag, + adt, sugg, }, _ => errors::OnlyCurrentTraits::Arbitrary { @@ -399,6 +402,7 @@ fn emit_orphan_check_error<'tcx>( name, pointer, ty: ty_diag, + adt, sugg, }, }; diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index fb919714afd38..6595ee542e030 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1395,6 +1395,8 @@ pub enum OnlyCurrentTraits<'a> { #[subdiagnostic] ty: Vec>, #[subdiagnostic] + adt: Vec, + #[subdiagnostic] sugg: Option>, }, #[diag(hir_analysis_only_current_traits_primitive, code = E0117)] @@ -1415,6 +1417,8 @@ pub enum OnlyCurrentTraits<'a> { #[subdiagnostic] ty: Vec>, #[subdiagnostic] + adt: Vec, + #[subdiagnostic] sugg: Option>, }, #[diag(hir_analysis_only_current_traits_arbitrary, code = E0117)] @@ -1435,6 +1439,8 @@ pub enum OnlyCurrentTraits<'a> { #[subdiagnostic] ty: Vec>, #[subdiagnostic] + adt: Vec, + #[subdiagnostic] sugg: Option>, }, } @@ -1445,7 +1451,6 @@ pub struct OnlyCurrentTraitsOpaque { #[primary_span] pub span: Span, } - #[derive(Subdiagnostic)] #[label(hir_analysis_only_current_traits_foreign)] pub struct OnlyCurrentTraitsForeign { @@ -1477,6 +1482,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, From f487d8339086eb3bf0c0aec5fac7d343c5d8fa46 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 29 Mar 2024 22:23:10 -0400 Subject: [PATCH 3/3] Stop doing so much to handle subdiagnostics --- .../src/coherence/orphan.rs | 162 ++++++++---------- compiler/rustc_hir_analysis/src/errors.rs | 44 +---- 2 files changed, 69 insertions(+), 137 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index 92e8c45950919..1770f7b4e917c 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -283,15 +283,14 @@ fn emit_orphan_check_error<'tcx>( let self_ty = trait_ref.self_ty(); Err(match err { traits::OrphanCheckErr::NonLocalInputType(tys) => { - // FIXME: Someone needs to just turn these into `Subdiag`s and attach - // them to the `Diag` after creating the error. - let mut opaque = vec![]; - let mut foreign = vec![]; - let mut name = vec![]; - let mut pointer = vec![]; - let mut ty_diag = vec![]; - let mut adt = vec![]; - 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` @@ -303,110 +302,85 @@ fn emit_orphan_check_error<'tcx>( ty = tcx.erase_regions(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::Adt(adt_def, _) => adt.push(errors::OnlyCurrentTraitsAdt { - span, - name: tcx.def_path_str(adt_def.did()), - }), - _ => 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, - adt, - sugg, - }, - _ if self_ty.is_primitive() => errors::OnlyCurrentTraits::Primitive { - span: sp, - note: (), - opaque, - foreign, - name, - pointer, - ty: ty_diag, - adt, - sugg, - }, - _ => errors::OnlyCurrentTraits::Arbitrary { - span: sp, - note: (), - opaque, - foreign, - name, - pointer, - ty: ty_diag, - adt, - 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 6595ee542e030..2d4742fa1dc4a 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,20 +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] - adt: Vec, - #[subdiagnostic] - sugg: Option>, }, #[diag(hir_analysis_only_current_traits_primitive, code = E0117)] Primitive { @@ -1406,20 +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] - adt: Vec, - #[subdiagnostic] - sugg: Option>, }, #[diag(hir_analysis_only_current_traits_arbitrary, code = E0117)] Arbitrary { @@ -1428,20 +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] - adt: Vec, - #[subdiagnostic] - sugg: Option>, }, }