Make check_param_wf only go through the HIR in the error path

This commit is contained in:
Oli Scherer
2025-06-03 15:27:34 +00:00
parent 215009bd0c
commit cca072ca15
2 changed files with 31 additions and 26 deletions

View File

@@ -198,11 +198,9 @@ fn check_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGua
_ => unreachable!("{node:?}"), _ => unreachable!("{node:?}"),
}; };
if let Some(generics) = node.generics() { for param in &tcx.generics_of(def_id).own_params {
for param in generics.params {
res = res.and(check_param_wf(tcx, param)); res = res.and(check_param_wf(tcx, param));
} }
}
res res
} }
@@ -881,52 +879,54 @@ fn check_impl_item<'tcx>(
check_associated_item(tcx, impl_item.owner_id.def_id, span, method_sig) check_associated_item(tcx, impl_item.owner_id.def_id, span, method_sig)
} }
fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(), ErrorGuaranteed> { fn check_param_wf(tcx: TyCtxt<'_>, param: &ty::GenericParamDef) -> Result<(), ErrorGuaranteed> {
match param.kind { match param.kind {
// We currently only check wf of const params here. // We currently only check wf of const params here.
hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { .. } => Ok(()), ty::GenericParamDefKind::Lifetime | ty::GenericParamDefKind::Type { .. } => Ok(()),
// Const parameters are well formed if their type is structural match. // Const parameters are well formed if their type is structural match.
hir::GenericParamKind::Const { ty: hir_ty, default: _, synthetic: _ } => { ty::GenericParamDefKind::Const { .. } => {
let ty = tcx.type_of(param.def_id).instantiate_identity(); let ty = tcx.type_of(param.def_id).instantiate_identity();
let span = tcx.def_span(param.def_id);
let def_id = param.def_id.expect_local();
if tcx.features().unsized_const_params() { if tcx.features().unsized_const_params() {
enter_wf_checking_ctxt(tcx, tcx.local_parent(param.def_id), |wfcx| { enter_wf_checking_ctxt(tcx, tcx.local_parent(def_id), |wfcx| {
wfcx.register_bound( wfcx.register_bound(
ObligationCause::new( ObligationCause::new(span, def_id, ObligationCauseCode::ConstParam(ty)),
hir_ty.span,
param.def_id,
ObligationCauseCode::ConstParam(ty),
),
wfcx.param_env, wfcx.param_env,
ty, ty,
tcx.require_lang_item(LangItem::UnsizedConstParamTy, hir_ty.span), tcx.require_lang_item(LangItem::UnsizedConstParamTy, span),
); );
Ok(()) Ok(())
}) })
} else if tcx.features().adt_const_params() { } else if tcx.features().adt_const_params() {
enter_wf_checking_ctxt(tcx, tcx.local_parent(param.def_id), |wfcx| { enter_wf_checking_ctxt(tcx, tcx.local_parent(def_id), |wfcx| {
wfcx.register_bound( wfcx.register_bound(
ObligationCause::new( ObligationCause::new(span, def_id, ObligationCauseCode::ConstParam(ty)),
hir_ty.span,
param.def_id,
ObligationCauseCode::ConstParam(ty),
),
wfcx.param_env, wfcx.param_env,
ty, ty,
tcx.require_lang_item(LangItem::ConstParamTy, hir_ty.span), tcx.require_lang_item(LangItem::ConstParamTy, span),
); );
Ok(()) Ok(())
}) })
} else { } else {
let span = || {
let hir::GenericParamKind::Const { ty: &hir::Ty { span, .. }, .. } =
tcx.hir_node_by_def_id(def_id).expect_generic_param().kind
else {
bug!()
};
span
};
let mut diag = match ty.kind() { let mut diag = match ty.kind() {
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Error(_) => return Ok(()), ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Error(_) => return Ok(()),
ty::FnPtr(..) => tcx.dcx().struct_span_err( ty::FnPtr(..) => tcx.dcx().struct_span_err(
hir_ty.span, span(),
"using function pointers as const generic parameters is forbidden", "using function pointers as const generic parameters is forbidden",
), ),
ty::RawPtr(_, _) => tcx.dcx().struct_span_err( ty::RawPtr(_, _) => tcx.dcx().struct_span_err(
hir_ty.span, span(),
"using raw pointers as const generic parameters is forbidden", "using raw pointers as const generic parameters is forbidden",
), ),
_ => { _ => {
@@ -934,7 +934,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
ty.error_reported()?; ty.error_reported()?;
tcx.dcx().struct_span_err( tcx.dcx().struct_span_err(
hir_ty.span, span(),
format!( format!(
"`{ty}` is forbidden as the type of a const generic parameter", "`{ty}` is forbidden as the type of a const generic parameter",
), ),
@@ -944,7 +944,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
diag.note("the only supported types are integers, `bool`, and `char`"); diag.note("the only supported types are integers, `bool`, and `char`");
let cause = ObligationCause::misc(hir_ty.span, param.def_id); let cause = ObligationCause::misc(span(), def_id);
let adt_const_params_feature_string = let adt_const_params_feature_string =
" more complex and user defined types".to_string(); " more complex and user defined types".to_string();
let may_suggest_feature = match type_allowed_to_implement_const_param_ty( let may_suggest_feature = match type_allowed_to_implement_const_param_ty(

View File

@@ -1186,7 +1186,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
ty: Ty<'tcx>, ty: Ty<'tcx>,
obligation: &PredicateObligation<'tcx>, obligation: &PredicateObligation<'tcx>,
) -> Diag<'a> { ) -> Diag<'a> {
let span = obligation.cause.span; let param = obligation.cause.body_id;
let hir::GenericParamKind::Const { ty: &hir::Ty { span, .. }, .. } =
self.tcx.hir_node_by_def_id(param).expect_generic_param().kind
else {
bug!()
};
let mut diag = match ty.kind() { let mut diag = match ty.kind() {
ty::Float(_) => { ty::Float(_) => {