Skip to content

Commit c59acb0

Browse files
committed
Fix clash of enum shared discriminant
gcc/rust/ChangeLog: * backend/rust-compile-item.cc (CompileItem::visit): Use HIR::Enum visit * backend/rust-compile-item.h: Fix clash of enum shared discriminant * backend/rust-compile-type.cc (check_variant_record_collision): Likewise (TyTyResolveCompile::visit): Likewise.
1 parent 3c94954 commit c59acb0

File tree

3 files changed

+67
-6
lines changed

3 files changed

+67
-6
lines changed

gcc/rust/backend/rust-compile-item.cc

+11
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,17 @@ CompileItem::visit (HIR::Function &function)
265265
ctx->pop_const_context ();
266266
}
267267

268+
void
269+
CompileItem::visit (HIR::Enum &e)
270+
{
271+
TyTy::BaseType *resolved_type = nullptr;
272+
bool ok = ctx->get_tyctx ()->lookup_type (e.get_mappings ().get_hirid (),
273+
&resolved_type);
274+
rust_assert (ok);
275+
276+
tree type = TyTyResolveCompile::compile (ctx, resolved_type);
277+
reference = type;
278+
}
268279
void
269280
CompileItem::visit (HIR::ImplBlock &impl_block)
270281
{

gcc/rust/backend/rust-compile-item.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class CompileItem : private HIRCompileBase, protected HIR::HIRStmtVisitor
4848
void visit (HIR::ImplBlock &impl_block) override;
4949
void visit (HIR::ExternBlock &extern_block) override;
5050
void visit (HIR::Module &module) override;
51-
51+
void visit (HIR::Enum &) override;
5252
// Empty visit for unused Stmt HIR nodes.
5353
void visit (HIR::TupleStruct &) override {}
5454
void visit (HIR::EnumItem &) override {}
@@ -62,7 +62,6 @@ class CompileItem : private HIRCompileBase, protected HIR::HIRStmtVisitor
6262
void visit (HIR::UseDeclaration &) override {}
6363
void visit (HIR::TypeAlias &) override {}
6464
void visit (HIR::StructStruct &) override {}
65-
void visit (HIR::Enum &) override {}
6665
void visit (HIR::Union &) override {}
6766
void visit (HIR::Trait &) override {}
6867
void visit (HIR::EmptyStmt &) override {}

gcc/rust/backend/rust-compile-type.cc

+55-4
Original file line numberDiff line numberDiff line change
@@ -239,14 +239,63 @@ TyTyResolveCompile::visit (const TyTy::FnPtr &type)
239239
type.get_ident ().locus);
240240
}
241241

242+
void
243+
check_variant_record_collision (Context *ctx, const TyTy::ADTType &type,
244+
std::vector<tree> &variant_records)
245+
{
246+
// bdbt: we're checking if shared discriminants crash with each other or
247+
// not. lets make a map from uhwi to hir id. A clash of uhwi in a variant
248+
// record to which said record can be converted uhwi is indicative of
249+
// issue 3351 of gccrs
250+
251+
std::map<HOST_WIDE_INT, std::vector<size_t>> shwi_to_index;
252+
for (size_t i = 0; i < variant_records.size (); i++)
253+
{
254+
TyTy::VariantDef *variant = type.get_variants ().at (i);
255+
if (variant->has_discriminant ())
256+
{
257+
tree discriminant_expr
258+
= CompileExpr::Compile (variant->get_discriminant (), ctx);
259+
tree folded_expr = fold_expr (discriminant_expr);
260+
if (folded_expr == error_mark_node)
261+
{
262+
// if we have discriminant but we fail to fold it, ICE
263+
rust_unreachable ();
264+
}
265+
HOST_WIDE_INT discriminant_integer = tree_to_shwi (folded_expr);
266+
shwi_to_index[discriminant_integer].push_back (i);
267+
}
268+
}
269+
270+
for (const auto &map_item : shwi_to_index)
271+
{
272+
auto discriminant_integer = map_item.first;
273+
const auto &index_vector = map_item.second;
274+
// collision doesn't happen, move to next item
275+
if (index_vector.size () <= 1)
276+
continue;
277+
278+
rich_location r (line_table, type.get_locus ());
279+
std::string assigned_here_msg
280+
= "`" + std::to_string (discriminant_integer) + "`" + " assigned here";
281+
for (auto index : index_vector)
282+
{
283+
TyTy::VariantDef *variant = type.get_variants ().at (index);
284+
r.add_fixit_replace (variant->get_discriminant ().get_locus (),
285+
assigned_here_msg.c_str ());
286+
}
287+
rust_error_at (r, ErrorCode::E0081,
288+
"discriminant value %qld assigned more than once",
289+
discriminant_integer);
290+
}
291+
}
242292
void
243293
TyTyResolveCompile::visit (const TyTy::ADTType &type)
244294
{
245295
tree type_record = error_mark_node;
246296
if (!type.is_enum ())
247297
{
248298
rust_assert (type.number_of_variants () == 1);
249-
250299
TyTy::VariantDef &variant = *type.get_variants ().at (0);
251300
std::vector<Backend::typed_identifier> fields;
252301
for (size_t i = 0; i < variant.num_fields (); i++)
@@ -349,9 +398,11 @@ TyTyResolveCompile::visit (const TyTy::ADTType &type)
349398
// add them to the list
350399
variant_records.push_back (named_variant_record);
351400
}
352-
353-
// now we need to make the actual union, but first we need to make
354-
// named_type TYPE_DECL's out of the variants
401+
// TODO: bdbt set up defid and a map (or set?) to check if we have
402+
// checked for collision already.
403+
check_variant_record_collision (ctx, type, variant_records);
404+
// the actual union, but first we need to make named_type TYPE_DECL's out
405+
// of the variants
355406

356407
size_t i = 0;
357408
std::vector<Backend::typed_identifier> enum_fields;

0 commit comments

Comments
 (0)