Ensure a location for monomorphization diagnostics in call argument deduction (#7401)

If the deduction fails while forming the parameter type, ensure that we
print an actual diagnostic saying what went wrong.

And always ensure that an invalid array bounds error points at a
location. The `inst_id` given to `EvalConstantInst` always has a
location, but the `bounds_id` instruction inside it may be canonical
when it's coming from inside a larger type. So when it is, fall back to
using the location of the whole array inst.
This commit is contained in:
Dana Jansens
2026-06-25 22:37:14 +00:00
committed by GitHub
parent bd8c565c74
commit 5aae6a1ca5
4 changed files with 87 additions and 13 deletions
+19 -7
View File
@@ -543,13 +543,6 @@ auto DeductionContext::CheckDeductionIsComplete() -> bool {
// that incorrectly.
auto binding_type_id = context().insts().Get(binding_id).type_id();
if (binding_type_id.is_symbolic()) {
auto param_type_const_id =
SubstConstant(context(), SemIR::LocId(binding_id),
binding_type_id.AsConstantId(), substitutions_);
CARBON_CHECK(param_type_const_id.has_value());
binding_type_id =
context().types().GetTypeIdForTypeConstantId(param_type_const_id);
Diagnostics::AnnotationScope annotate_diagnostics(
&context().emitter(), [&](auto& builder) {
if (diagnose_) {
@@ -557,6 +550,25 @@ auto DeductionContext::CheckDeductionIsComplete() -> bool {
builder);
}
});
{
Diagnostics::ContextScope diag_context(
&context().emitter(), [&](auto& builder) {
CARBON_DIAGNOSTIC(
SubstitutingGenericParamType, Context,
"constructed invalid specific for {0} from argument",
SemIR::TypeId);
builder.Context(loc_id_, SubstitutingGenericParamType,
binding_type_id);
});
auto param_type_const_id =
SubstConstant(context(), SemIR::LocId(binding_id),
binding_type_id.AsConstantId(), substitutions_);
CARBON_CHECK(param_type_const_id.has_value());
binding_type_id =
context().types().GetTypeIdForTypeConstantId(param_type_const_id);
}
auto converted_arg_id =
diagnose_ ? ConvertToValueOfType(context(), loc_id_, deduced_arg_id,
binding_type_id)
+11 -6
View File
@@ -66,6 +66,13 @@ auto EvalConstantInst(Context& context, SemIR::InstId inst_id,
"Unexpected inst {0} for template constant int", bound_inst);
return ConstantEvalResult::NewSamePhase(inst);
}
auto orig_inst = context.insts().GetAs<SemIR::ArrayType>(inst_id);
auto error_loc =
context.insts().GetCanonicalLocId(orig_inst.bound_id).has_value()
? orig_inst.bound_id
: inst_id;
// TODO: We should check that the size of the resulting array type
// fits in 64 bits, not just that the bound does. Should we use a
// 32-bit limit for 32-bit targets?
@@ -74,17 +81,15 @@ auto EvalConstantInst(Context& context, SemIR::InstId inst_id,
bound_val.isNegative()) {
CARBON_DIAGNOSTIC(ArrayBoundNegative, Error,
"array bound of {0} is negative", TypedInt);
context.emitter().Emit(
context.insts().GetAs<SemIR::ArrayType>(inst_id).bound_id,
ArrayBoundNegative, {.type = int_bound->type_id, .value = bound_val});
context.emitter().Emit(error_loc, ArrayBoundNegative,
{.type = int_bound->type_id, .value = bound_val});
return ConstantEvalResult::Error;
}
if (bound_val.getActiveBits() > 64) {
CARBON_DIAGNOSTIC(ArrayBoundTooLarge, Error,
"array bound of {0} is too large", TypedInt);
context.emitter().Emit(
context.insts().GetAs<SemIR::ArrayType>(inst_id).bound_id,
ArrayBoundTooLarge, {.type = int_bound->type_id, .value = bound_val});
context.emitter().Emit(error_loc, ArrayBoundTooLarge,
{.type = int_bound->type_id, .value = bound_val});
return ConstantEvalResult::Error;
}
return ConstantEvalResult::NewSamePhase(inst);
@@ -93,3 +93,59 @@ fn G(T:! Y) {
// CHECK:STDERR:
F(-1, T);
};
// --- fail_monomorphization_identify_in_call.carbon
library "[[@TEST_NAME]]";
interface Y {}
interface Z {
let Z1:! type;
}
constraint S(N:! Core.IntLiteral) {
extend require impls Z where .Z1 = array((), N);
}
fn F(N:! Core.IntLiteral, _:! S(N)) {}
fn G(T:! Z) {
// CHECK:STDERR: fail_monomorphization_identify_in_call.carbon:[[@LINE+10]]:3: error: facet type `S(-1)` can not be identified [ImplLookupInUnidentifiedFacetType]
// CHECK:STDERR: F(-1, T);
// CHECK:STDERR: ^~~~~~~~
// CHECK:STDERR: fail_monomorphization_identify_in_call.carbon:[[@LINE-9]]:24: note: array bound of -1 is negative [ArrayBoundNegative]
// CHECK:STDERR: extend require impls Z where .Z1 = array((), N);
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR: fail_monomorphization_identify_in_call.carbon:[[@LINE-9]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]
// CHECK:STDERR: fn F(N:! Core.IntLiteral, _:! S(N)) {}
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR:
F(-1, T);
};
// --- fail_monomorphization_during_deduction_in_call.carbon
library "[[@TEST_NAME]]";
interface Y {}
interface Z {
let Z1:! type;
}
constraint S(N:! Core.IntLiteral) {
extend require impls Z;
}
fn F(N:! Core.IntLiteral, _:! S(N) where .Z1 = array((), N)) {}
fn G(T:! Z) {
// CHECK:STDERR: fail_monomorphization_during_deduction_in_call.carbon:[[@LINE+10]]:3: error: constructed invalid specific for `S(N) where .(Z.Z1) = array((), N)` from argument [SubstitutingGenericParamType]
// CHECK:STDERR: F(-1, T);
// CHECK:STDERR: ^~~~~~~~
// CHECK:STDERR: fail_monomorphization_during_deduction_in_call.carbon:[[@LINE-6]]:27: note: array bound of -1 is negative [ArrayBoundNegative]
// CHECK:STDERR: fn F(N:! Core.IntLiteral, _:! S(N) where .Z1 = array((), N)) {}
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR: fail_monomorphization_during_deduction_in_call.carbon:[[@LINE-9]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]
// CHECK:STDERR: fn F(N:! Core.IntLiteral, _:! S(N) where .Z1 = array((), N)) {}
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR:
F(-1, T);
};
+1
View File
@@ -325,6 +325,7 @@ CARBON_DIAGNOSTIC_KIND(DeductionIncomplete)
CARBON_DIAGNOSTIC_KIND(DeductionInconsistent)
CARBON_DIAGNOSTIC_KIND(DeductionGenericHere)
CARBON_DIAGNOSTIC_KIND(InitializingGenericParam)
CARBON_DIAGNOSTIC_KIND(SubstitutingGenericParamType)
CARBON_DIAGNOSTIC_KIND(CompTimeArgumentNotConstant)
CARBON_DIAGNOSTIC_KIND(RuntimeConversionDuringCompTimeDeduction)