Skip to content

Commit 29fb9ce

Browse files
committed
Fix inner ty check
1 parent 8095dd6 commit 29fb9ce

File tree

10 files changed

+268
-150
lines changed

10 files changed

+268
-150
lines changed

compiler/rustc_hir_analysis/messages.ftl

+5-3
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,14 @@ hir_analysis_const_impl_for_non_const_trait =
8080
8181
hir_analysis_const_param_ty_impl_on_infringing_inner_ty =
8282
the trait `ConstParamTy` cannot be implemented for this type
83-
.label = this {$def_descr} does not implement `ConstParamTy`
84-
.suggestion = consider annotating this {$def_descr} with `#[derive(ConstParamTy)]`
83+
.label = this type does not implement `ConstParamTy`
84+
85+
hir_analysis_const_param_ty_impl_on_infringing_inner_ty_sugg =
86+
consider annotating with `#[derive(ConstParamTy)]`
8587
8688
hir_analysis_const_param_ty_impl_on_non_adt =
8789
the trait `ConstParamTy` may not be implemented for this type
88-
.label = type is not a structure or enumeration
90+
.label = the type `{$ty}` is not a structure or enumeration
8991
9092
hir_analysis_const_specialize = cannot specialize on const impl with non-const impl
9193

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+22-25
Original file line numberDiff line numberDiff line change
@@ -939,6 +939,22 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
939939
Ok(())
940940
})
941941
} else {
942+
fn ty_is_local(ty: Ty<'_>) -> bool {
943+
match ty.kind() {
944+
ty::Adt(adt_def, ..) => adt_def.did().is_local(),
945+
// Arrays and slices use the inner type's `ConstParamTy`.
946+
ty::Array(ty, ..) => ty_is_local(*ty),
947+
ty::Slice(ty) => ty_is_local(*ty),
948+
// `&` references use the inner type's `ConstParamTy`.
949+
// `&mut` are not supported.
950+
ty::Ref(_, ty, ast::Mutability::Not) => ty_is_local(*ty),
951+
// Say that a tuple is local if any of its components are local.
952+
// This is not strictly correct, but it's likely that the user can fix the local component.
953+
ty::Tuple(tys) => tys.iter().any(|ty| ty_is_local(ty)),
954+
_ => false,
955+
}
956+
}
957+
942958
let mut diag = match ty.kind() {
943959
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Error(_) => return Ok(()),
944960
ty::FnPtr(_) => tcx.dcx().struct_span_err(
@@ -962,35 +978,16 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
962978
tcx,
963979
tcx.param_env(param.def_id),
964980
ty,
965-
cause,
981+
&cause,
966982
) {
967983
// Can never implement `ConstParamTy`, don't suggest anything.
968-
Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed) => false,
984+
Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed(..)) => false,
969985
// May be able to implement `ConstParamTy`. Only emit the feature help
970986
// if the type is local, since the user may be able to fix the local type.
971-
Err(ConstParamTyImplementationError::InfrigingFields(..)) => {
972-
fn ty_is_local(ty: Ty<'_>) -> bool {
973-
match ty.kind() {
974-
ty::Adt(adt_def, ..) => adt_def.did().is_local(),
975-
// Arrays and slices use the inner type's `ConstParamTy`.
976-
ty::Array(ty, ..) => ty_is_local(*ty),
977-
ty::Slice(ty) => ty_is_local(*ty),
978-
// `&` references use the inner type's `ConstParamTy`.
979-
// `&mut` are not supported.
980-
ty::Ref(_, ty, ast::Mutability::Not) => ty_is_local(*ty),
981-
// Say that a tuple is local if any of its components are local.
982-
// This is not strictly correct, but it's likely that the user can fix the local component.
983-
ty::Tuple(tys) => tys.iter().any(|ty| ty_is_local(ty)),
984-
_ => false,
985-
}
986-
}
987-
988-
ty_is_local(ty)
989-
}
990-
// Same as above.
991-
Err(ConstParamTyImplementationError::InfringingInnerTy(def_id)) => {
992-
def_id.is_local()
993-
}
987+
Err(
988+
ConstParamTyImplementationError::InfrigingFields(..)
989+
| ConstParamTyImplementationError::InfringingInnerTy(..),
990+
) => ty_is_local(ty),
994991
// Implments `ConstParamTy`, suggest adding the feature to enable.
995992
Ok(..) => true,
996993
};

compiler/rustc_hir_analysis/src/coherence/builtin.rs

+19-10
Original file line numberDiff line numberDiff line change
@@ -127,22 +127,31 @@ fn visit_implementation_of_const_param_ty(
127127
};
128128

129129
let cause = traits::ObligationCause::misc(span, impl_did);
130-
match type_allowed_to_implement_const_param_ty(tcx, param_env, self_type, cause) {
130+
match type_allowed_to_implement_const_param_ty(tcx, param_env, self_type, &cause) {
131131
Ok(()) => Ok(()),
132132
Err(ConstParamTyImplementationError::InfrigingFields(fields)) => {
133133
Err(infringing_fields_error(tcx, fields, LangItem::ConstParamTy, impl_did, span))
134134
}
135-
Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed) => {
136-
Err(tcx.dcx().emit_err(errors::ConstParamTyImplOnNonAdt { span }))
135+
Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed(ty)) => {
136+
Err(tcx.dcx().emit_err(errors::ConstParamTyImplOnNonAdt { span, ty }))
137137
}
138-
Err(ConstParamTyImplementationError::InfringingInnerTy(def_id)) => {
139-
let def_span = tcx.def_span(def_id);
140-
tcx.dcx().emit_err(errors::ConstParamTyImplOnInfringingInnerTy {
138+
Err(ConstParamTyImplementationError::InfringingInnerTy(def_ids)) => {
139+
let mut def_spans = vec![];
140+
let mut suggs = vec![];
141+
for def_id in def_ids {
142+
let def_span = tcx.def_span(def_id);
143+
def_spans.push(def_span);
144+
if def_id.is_local() {
145+
suggs.push(errors::ConstParamTyImplOnInfringingInnerTySugg {
146+
span: def_span.shrink_to_lo(),
147+
});
148+
}
149+
}
150+
Err(tcx.dcx().emit_err(errors::ConstParamTyImplOnInfringingInnerTy {
141151
span,
142-
def_span,
143-
def_descr: tcx.def_descr(def_id),
144-
sugg: def_id.is_local().then_some(def_span.shrink_to_lo()),
145-
});
152+
def_spans,
153+
suggs,
154+
}))
146155
}
147156
}
148157
}

compiler/rustc_hir_analysis/src/errors.rs

+17-9
Original file line numberDiff line numberDiff line change
@@ -221,10 +221,11 @@ pub struct CopyImplOnNonAdt {
221221

222222
#[derive(Diagnostic)]
223223
#[diag(hir_analysis_const_param_ty_impl_on_non_adt)]
224-
pub struct ConstParamTyImplOnNonAdt {
224+
pub struct ConstParamTyImplOnNonAdt<'tcx> {
225225
#[primary_span]
226226
#[label]
227227
pub span: Span,
228+
pub ty: Ty<'tcx>,
228229
}
229230

230231
#[derive(Diagnostic)]
@@ -233,14 +234,21 @@ pub struct ConstParamTyImplOnInfringingInnerTy {
233234
#[primary_span]
234235
pub span: Span,
235236
#[label]
236-
pub def_span: Span,
237-
pub def_descr: &'static str,
238-
#[suggestion(
239-
applicability = "maybe-incorrect",
240-
style = "verbose",
241-
code = "#[derive(ConstParamTy)]\n"
242-
)]
243-
pub sugg: Option<Span>,
237+
pub def_spans: Vec<Span>,
238+
#[subdiagnostic]
239+
pub suggs: Vec<ConstParamTyImplOnInfringingInnerTySugg>,
240+
}
241+
242+
#[derive(Subdiagnostic)]
243+
#[suggestion(
244+
hir_analysis_const_param_ty_impl_on_infringing_inner_ty_sugg,
245+
applicability = "maybe-incorrect",
246+
style = "verbose",
247+
code = "#[derive(ConstParamTy)]\n"
248+
)]
249+
pub struct ConstParamTyImplOnInfringingInnerTySugg {
250+
#[primary_span]
251+
pub span: Span,
244252
}
245253

246254
#[derive(Diagnostic)]

0 commit comments

Comments
 (0)