@@ -239,14 +239,63 @@ TyTyResolveCompile::visit (const TyTy::FnPtr &type)
239
239
type.get_ident ().locus );
240
240
}
241
241
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
+ }
242
292
void
243
293
TyTyResolveCompile::visit (const TyTy::ADTType &type)
244
294
{
245
295
tree type_record = error_mark_node;
246
296
if (!type.is_enum ())
247
297
{
248
298
rust_assert (type.number_of_variants () == 1 );
249
-
250
299
TyTy::VariantDef &variant = *type.get_variants ().at (0 );
251
300
std::vector<Backend::typed_identifier> fields;
252
301
for (size_t i = 0 ; i < variant.num_fields (); i++)
@@ -349,9 +398,11 @@ TyTyResolveCompile::visit (const TyTy::ADTType &type)
349
398
// add them to the list
350
399
variant_records.push_back (named_variant_record);
351
400
}
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
355
406
356
407
size_t i = 0 ;
357
408
std::vector<Backend::typed_identifier> enum_fields;
0 commit comments