Skip to content

Commit

Permalink
Error on non-constant parameters to a type. (#4215)
Browse files Browse the repository at this point in the history
At present, this is a crash bug. I don't know whether this is the best
fix, but I figure it'll work until zygoloid has a chance to look.
  • Loading branch information
jonmeow authored Aug 13, 2024
1 parent 23545bb commit a3a4c14
Show file tree
Hide file tree
Showing 9 changed files with 1,134 additions and 422 deletions.
25 changes: 25 additions & 0 deletions toolchain/check/generic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -415,4 +415,29 @@ auto ResolveSpecificDefinition(Context& context, SemIR::SpecificId specific_id)
return true;
}

auto RequireGenericParams(Context& context, SemIR::InstBlockId block_id)
-> void {
if (!block_id.is_valid() || block_id == SemIR::InstBlockId::Empty) {
return;
}

for (auto& inst_id : context.inst_blocks().Get(block_id)) {
if (!context.constant_values().Get(inst_id).is_constant()) {
CARBON_DIAGNOSTIC(GenericParamMustBeConstant, Error,
"Parameters of generic types must be constant.");
context.emitter().Emit(inst_id, GenericParamMustBeConstant);

// Replace the parameter with an invalid instruction so that we don't try
// constructing a generic based on it. Note this is updating the param
// refs block, not the actual params block, so will not be directly
// reflected in SemIR output.
inst_id = context.AddInstInNoBlock(
SemIR::LocIdAndInst::ReusingLoc<SemIR::Param>(
context.insts().GetLocId(inst_id),
{.type_id = SemIR::TypeId::Error,
.name_id = SemIR::NameId::Base}));
}
}
}

} // namespace Carbon::Check
7 changes: 7 additions & 0 deletions toolchain/check/generic.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ auto MakeSelfSpecific(Context& context, SemIR::GenericId generic_id)
auto ResolveSpecificDefinition(Context& context, SemIR::SpecificId specific_id)
-> bool;

// Requires that a param block only contains generics. Diagnoses and updates the
// block otherwise. This will typically be called once for each of implicit and
// explicit parameters, and must occur before constant evaluation of the
// parameterized instruction.
auto RequireGenericParams(Context& context, SemIR::InstBlockId block_id)
-> void;

} // namespace Carbon::Check

#endif // CARBON_TOOLCHAIN_CHECK_GENERIC_H_
3 changes: 3 additions & 0 deletions toolchain/check/handle_class.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,9 @@ static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id,
.self_type_id = SemIR::TypeId::Invalid,
.inheritance_kind = inheritance_kind}};

RequireGenericParams(context, class_info.implicit_param_refs_id);
RequireGenericParams(context, class_info.param_refs_id);

MergeOrAddName(context, node_id, name_context, class_decl_id, class_decl,
class_info, is_definition, is_extern,
introducer.modifier_set.GetAccessKind());
Expand Down
7 changes: 5 additions & 2 deletions toolchain/check/handle_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ static auto BuildInterfaceDecl(Context& context,
auto interface_decl_id =
context.AddPlaceholderInst(SemIR::LocIdAndInst(node_id, interface_decl));

SemIR::Interface interface_info = {name_context.MakeEntityWithParamsBase(
name, interface_decl_id, /*is_extern=*/false)};
RequireGenericParams(context, interface_info.implicit_param_refs_id);
RequireGenericParams(context, interface_info.param_refs_id);

// Check whether this is a redeclaration.
auto existing_id = context.decl_name_stack().LookupOrAddName(
name_context, interface_decl_id, introducer.modifier_set.GetAccessKind());
Expand Down Expand Up @@ -103,8 +108,6 @@ static auto BuildInterfaceDecl(Context& context,
// there was an error in the qualifier, we will have lost track of the
// interface name here. We should keep track of it even if the name is
// invalid.
SemIR::Interface interface_info = {name_context.MakeEntityWithParamsBase(
name, interface_decl_id, /*is_extern=*/false)};
interface_info.generic_id = FinishGenericDecl(context, interface_decl_id);
interface_decl.interface_id = context.interfaces().Add(interface_info);
if (interface_info.has_parameters()) {
Expand Down
204 changes: 154 additions & 50 deletions toolchain/check/testdata/class/no_prelude/generic_vs_params.carbon

Large diffs are not rendered by default.

Loading

0 comments on commit a3a4c14

Please sign in to comment.