https://gcc.gnu.org/g:3fd738ca7b346343853344a749d22815740fa114

commit 3fd738ca7b346343853344a749d22815740fa114
Author: Philip Herron <herron.phi...@googlemail.com>
Date:   Mon Feb 10 16:28:30 2025 +0000

    gccrs: add discriminant value intrinsic
    
    This is pretty nasty piece of rust in my opinion the return type of this
    intrinsic results into a lang item associated type:
    
      <T as DiscriminantKind>::Discriminant
    
    This is a special case which needs to support mapping onto the repr type
    of the associated ADT that is passed in, but defaults to iszie otherwise.
    
    This patch assumes we only come accross this case in a HIR::CALL_EXPR, so
    and makes assumutions that its always of this function signiture. I will
    do some checking in libcore to verify that assumption. More work is needed
    to parse the repr type on enums but the code is there to support this when
    its in to change the types etc.
    
    Addresses Rust-GCC#3348
    
    gcc/rust/ChangeLog:
    
            * backend/rust-compile-intrinsic.cc (discriminant_value_handler): 
new handler
            * typecheck/rust-hir-trait-resolve.cc 
(TraitItemReference::resolve_item): track the defid
            * typecheck/rust-hir-type-check-base.cc 
(TypeCheckBase::parse_repr_options): default isize
            * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): 
special case CallExpr
            * typecheck/rust-hir-type-check-item.cc (TypeCheckItem::visit): 
parse repr options enum
            * typecheck/rust-hir-type-check-type.cc (TypeCheckType::visit): 
remove bad diagnostic
            * typecheck/rust-tyty.cc (PlaceholderType::PlaceholderType): track 
defid
            (PlaceholderType::clone): likewise
            (PlaceholderType::get_def_id): likeiwse
            * typecheck/rust-tyty.h: placeholder track defid
            * util/rust-lang-item.cc: add new lang items
            * util/rust-lang-item.h: likewise
    
    gcc/testsuite/ChangeLog:
    
            * rust/execute/torture/enum_intrinsics1.rs: New test.
    
    Signed-off-by: Philip Herron <herron.phi...@googlemail.com>

Diff:
---
 gcc/rust/backend/rust-compile-intrinsic.cc         | 149 +++++++++++++++------
 gcc/rust/typecheck/rust-hir-trait-resolve.cc       |   1 +
 gcc/rust/typecheck/rust-hir-type-check-base.cc     |   4 +
 gcc/rust/typecheck/rust-hir-type-check-expr.cc     |  46 +++++++
 gcc/rust/typecheck/rust-hir-type-check-item.cc     |   7 +-
 gcc/rust/typecheck/rust-hir-type-check-type.cc     |   8 --
 gcc/rust/typecheck/rust-tyty.cc                    |  20 ++-
 gcc/rust/typecheck/rust-tyty.h                     |   8 +-
 gcc/rust/util/rust-lang-item.cc                    |   3 +
 gcc/rust/util/rust-lang-item.h                     |   3 +
 .../rust/execute/torture/enum_intrinsics1.rs       |  48 +++++++
 11 files changed, 235 insertions(+), 62 deletions(-)

diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc 
b/gcc/rust/backend/rust-compile-intrinsic.cc
index 3d624a0d6739..fffc33b3428c 100644
--- a/gcc/rust/backend/rust-compile-intrinsic.cc
+++ b/gcc/rust/backend/rust-compile-intrinsic.cc
@@ -17,7 +17,6 @@
 #include "rust-compile-intrinsic.h"
 #include "rust-compile-context.h"
 #include "rust-compile-type.h"
-#include "rust-compile-expr.h"
 #include "rust-compile-fnparam.h"
 #include "rust-builtins.h"
 #include "rust-diagnostics.h"
@@ -27,14 +26,10 @@
 #include "rust-tree.h"
 #include "tree-core.h"
 #include "rust-gcc.h"
-#include "print-tree.h"
 #include "fold-const.h"
 #include "langhooks.h"
-#include "rust-gcc.h"
 #include "rust-constexpr.h"
 
-#include "print-tree.h"
-
 // declaration taken from "stringpool.h"
 // the get_identifier macro causes compilation issues
 extern tree
@@ -93,6 +88,8 @@ static tree
 move_val_init_handler (Context *ctx, TyTy::FnType *fntype);
 static tree
 assume_handler (Context *ctx, TyTy::FnType *fntype);
+static tree
+discriminant_value_handler (Context *ctx, TyTy::FnType *fntype);
 
 enum class Prefetch
 {
@@ -217,45 +214,45 @@ sorry_handler (Context *ctx, TyTy::FnType *fntype)
 
 static const std::map<std::string,
                      std::function<tree (Context *, TyTy::FnType *)>>
-  generic_intrinsics = {
-    {"offset", offset_handler},
-    {"size_of", sizeof_handler},
-    {"transmute", transmute_handler},
-    {"rotate_left", rotate_left_handler},
-    {"rotate_right", rotate_right_handler},
-    {"wrapping_add", wrapping_op_handler (PLUS_EXPR)},
-    {"wrapping_sub", wrapping_op_handler (MINUS_EXPR)},
-    {"wrapping_mul", wrapping_op_handler (MULT_EXPR)},
-    {"add_with_overflow", op_with_overflow (PLUS_EXPR)},
-    {"sub_with_overflow", op_with_overflow (MINUS_EXPR)},
-    {"mul_with_overflow", op_with_overflow (MULT_EXPR)},
-    {"copy", copy_handler (true)},
-    {"copy_nonoverlapping", copy_handler (false)},
-    {"prefetch_read_data", prefetch_read_data},
-    {"prefetch_write_data", prefetch_write_data},
-    {"atomic_store_seqcst", atomic_store_handler (__ATOMIC_SEQ_CST)},
-    {"atomic_store_release", atomic_store_handler (__ATOMIC_RELEASE)},
-    {"atomic_store_relaxed", atomic_store_handler (__ATOMIC_RELAXED)},
-    {"atomic_store_unordered", atomic_store_handler (__ATOMIC_RELAXED)},
-    {"atomic_load_seqcst", atomic_load_handler (__ATOMIC_SEQ_CST)},
-    {"atomic_load_acquire", atomic_load_handler (__ATOMIC_ACQUIRE)},
-    {"atomic_load_relaxed", atomic_load_handler (__ATOMIC_RELAXED)},
-    {"atomic_load_unordered", atomic_load_handler (__ATOMIC_RELAXED)},
-    {"unchecked_add", unchecked_op_handler (PLUS_EXPR)},
-    {"unchecked_sub", unchecked_op_handler (MINUS_EXPR)},
-    {"unchecked_mul", unchecked_op_handler (MULT_EXPR)},
-    {"unchecked_div", unchecked_op_handler (TRUNC_DIV_EXPR)},
-    {"unchecked_rem", unchecked_op_handler (TRUNC_MOD_EXPR)},
-    {"unchecked_shl", unchecked_op_handler (LSHIFT_EXPR)},
-    {"unchecked_shr", unchecked_op_handler (RSHIFT_EXPR)},
-    {"uninit", uninit_handler},
-    {"move_val_init", move_val_init_handler},
-    {"likely", expect_handler (true)},
-    {"unlikely", expect_handler (false)},
-    {"assume", assume_handler},
-    {"try", try_handler (false)},
-    {"catch_unwind", try_handler (true)},
-};
+  generic_intrinsics
+  = {{"offset", offset_handler},
+     {"size_of", sizeof_handler},
+     {"transmute", transmute_handler},
+     {"rotate_left", rotate_left_handler},
+     {"rotate_right", rotate_right_handler},
+     {"wrapping_add", wrapping_op_handler (PLUS_EXPR)},
+     {"wrapping_sub", wrapping_op_handler (MINUS_EXPR)},
+     {"wrapping_mul", wrapping_op_handler (MULT_EXPR)},
+     {"add_with_overflow", op_with_overflow (PLUS_EXPR)},
+     {"sub_with_overflow", op_with_overflow (MINUS_EXPR)},
+     {"mul_with_overflow", op_with_overflow (MULT_EXPR)},
+     {"copy", copy_handler (true)},
+     {"copy_nonoverlapping", copy_handler (false)},
+     {"prefetch_read_data", prefetch_read_data},
+     {"prefetch_write_data", prefetch_write_data},
+     {"atomic_store_seqcst", atomic_store_handler (__ATOMIC_SEQ_CST)},
+     {"atomic_store_release", atomic_store_handler (__ATOMIC_RELEASE)},
+     {"atomic_store_relaxed", atomic_store_handler (__ATOMIC_RELAXED)},
+     {"atomic_store_unordered", atomic_store_handler (__ATOMIC_RELAXED)},
+     {"atomic_load_seqcst", atomic_load_handler (__ATOMIC_SEQ_CST)},
+     {"atomic_load_acquire", atomic_load_handler (__ATOMIC_ACQUIRE)},
+     {"atomic_load_relaxed", atomic_load_handler (__ATOMIC_RELAXED)},
+     {"atomic_load_unordered", atomic_load_handler (__ATOMIC_RELAXED)},
+     {"unchecked_add", unchecked_op_handler (PLUS_EXPR)},
+     {"unchecked_sub", unchecked_op_handler (MINUS_EXPR)},
+     {"unchecked_mul", unchecked_op_handler (MULT_EXPR)},
+     {"unchecked_div", unchecked_op_handler (TRUNC_DIV_EXPR)},
+     {"unchecked_rem", unchecked_op_handler (TRUNC_MOD_EXPR)},
+     {"unchecked_shl", unchecked_op_handler (LSHIFT_EXPR)},
+     {"unchecked_shr", unchecked_op_handler (RSHIFT_EXPR)},
+     {"uninit", uninit_handler},
+     {"move_val_init", move_val_init_handler},
+     {"likely", expect_handler (true)},
+     {"unlikely", expect_handler (false)},
+     {"assume", assume_handler},
+     {"try", try_handler (false)},
+     {"catch_unwind", try_handler (true)},
+     {"discriminant_value", discriminant_value_handler}};
 
 Intrinsics::Intrinsics (Context *ctx) : ctx (ctx) {}
 
@@ -1375,5 +1372,69 @@ try_handler_inner (Context *ctx, TyTy::FnType *fntype, 
bool is_new_api)
   return fndecl;
 }
 
+static tree
+discriminant_value_handler (Context *ctx, TyTy::FnType *fntype)
+{
+  rust_assert (fntype->get_params ().size () == 1);
+  rust_assert (fntype->get_return_type ()->is<TyTy::PlaceholderType> ());
+  rust_assert (fntype->has_substitutions ());
+  rust_assert (fntype->get_num_type_params () == 1);
+  auto &mapping = fntype->get_substs ().at (0);
+  auto param_ty = mapping.get_param_ty ();
+  rust_assert (param_ty->can_resolve ());
+  auto resolved = param_ty->resolve ();
+  auto p = static_cast<TyTy::PlaceholderType *> (fntype->get_return_type ());
+
+  TyTy::BaseType *return_type = nullptr;
+  bool ok = ctx->get_tyctx ()->lookup_builtin ("isize", &return_type);
+  rust_assert (ok);
+
+  bool is_adt = resolved->is<TyTy::ADTType> ();
+  bool is_enum = false;
+  if (is_adt)
+    {
+      const auto &adt = *static_cast<TyTy::ADTType *> (resolved);
+      return_type = adt.get_repr_options ().repr;
+      rust_assert (return_type != nullptr);
+      is_enum = adt.is_enum ();
+    }
+
+  p->set_associated_type (return_type->get_ref ());
+
+  tree lookup = NULL_TREE;
+  if (check_for_cached_intrinsic (ctx, fntype, &lookup))
+    return lookup;
+
+  auto fndecl = compile_intrinsic_function (ctx, fntype);
+
+  std::vector<Bvariable *> param_vars;
+  compile_fn_params (ctx, fntype, fndecl, &param_vars);
+
+  if (!Backend::function_set_parameters (fndecl, param_vars))
+    return error_mark_node;
+
+  enter_intrinsic_block (ctx, fndecl);
+
+  // BUILTIN disriminant_value FN BODY BEGIN
+
+  tree result = integer_zero_node;
+  if (is_enum)
+    {
+      tree val = Backend::var_expression (param_vars[0], UNDEF_LOCATION);
+      tree deref = build_fold_indirect_ref_loc (UNKNOWN_LOCATION, val);
+      result = Backend::struct_field_expression (deref, 0, UNKNOWN_LOCATION);
+    }
+
+  auto return_statement
+    = Backend::return_statement (fndecl, result, BUILTINS_LOCATION);
+  ctx->add_statement (return_statement);
+
+  // BUILTIN disriminant_value FN BODY END
+
+  finalize_intrinsic_block (ctx, fndecl);
+
+  return fndecl;
+}
+
 } // namespace Compile
 } // namespace Rust
diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc 
b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
index 0048ff55b445..ceb5b7a91b22 100644
--- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc
+++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
@@ -359,6 +359,7 @@ TraitItemReference::resolve_item (HIR::TraitItemType &type)
 {
   TyTy::BaseType *ty
     = new TyTy::PlaceholderType (type.get_name ().as_string (),
+                                type.get_mappings ().get_defid (),
                                 type.get_mappings ().get_hirid ());
   context->insert_type (type.get_mappings (), ty);
 }
diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.cc 
b/gcc/rust/typecheck/rust-hir-type-check-base.cc
index c1700fafdfc9..1c800a9c0ab9 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-base.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-base.cc
@@ -292,6 +292,10 @@ TypeCheckBase::parse_repr_options (const AST::AttrVec 
&attrs, location_t locus)
   repr.pack = 0;
   repr.align = 0;
 
+  // FIXME handle repr types....
+  bool ok = context->lookup_builtin ("isize", &repr.repr);
+  rust_assert (ok);
+
   for (const auto &attr : attrs)
     {
       bool is_repr = attr.get_path ().as_string () == Values::Attributes::REPR;
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc 
b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
index 2d9ec8359959..30fca00672bb 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
@@ -235,6 +235,52 @@ TypeCheckExpr::visit (HIR::CallExpr &expr)
     }
 
   infered = TyTy::TypeCheckCallExpr::go (function_tyty, expr, variant, 
context);
+
+  auto discriminant_type_lookup
+    = mappings.lookup_lang_item (LangItem::Kind::DISCRIMINANT_TYPE);
+  if (infered->is<TyTy::PlaceholderType> () && discriminant_type_lookup)
+    {
+      const auto &p = *static_cast<const TyTy::PlaceholderType *> (infered);
+      if (p.get_def_id () == discriminant_type_lookup.value ())
+       {
+         // this is a special case where this will actually return the repr of
+         // the enum. We dont currently support repr on enum yet to change the
+         // discriminant type but the default is always isize. We need to
+         // assert this is a generic function with one param
+         //
+         // fn<BookFormat> (v & T=BookFormat{Paperback) -> <placeholder:>
+         //
+         // note the default is isize
+
+         bool ok = context->lookup_builtin ("isize", &infered);
+         rust_assert (ok);
+
+         rust_assert (function_tyty->is<TyTy::FnType> ());
+         auto &fn = *static_cast<TyTy::FnType *> (function_tyty);
+         rust_assert (fn.has_substitutions ());
+         rust_assert (fn.get_num_type_params () == 1);
+         auto &mapping = fn.get_substs ().at (0);
+         auto param_ty = mapping.get_param_ty ();
+
+         if (!param_ty->can_resolve ())
+           {
+             // this could be a valid error need to test more weird cases and
+             // look at rustc
+             rust_internal_error_at (expr.get_locus (),
+                                     "something wrong computing return type");
+             return;
+           }
+
+         auto resolved = param_ty->resolve ();
+         bool is_adt = resolved->is<TyTy::ADTType> ();
+         if (is_adt)
+           {
+             const auto &adt = *static_cast<TyTy::ADTType *> (resolved);
+             infered = adt.get_repr_options ().repr;
+             rust_assert (infered != nullptr);
+           }
+       }
+    }
 }
 
 void
diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.cc 
b/gcc/rust/typecheck/rust-hir-type-check-item.cc
index eeea9b4fb1af..5a427c5ef480 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-item.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-item.cc
@@ -337,6 +337,11 @@ TypeCheckItem::visit (HIR::Enum &enum_decl)
   if (enum_decl.has_generics ())
     resolve_generic_params (enum_decl.get_generic_params (), substitutions);
 
+  // Process #[repr(X)] attribute, if any
+  const AST::AttrVec &attrs = enum_decl.get_outer_attrs ();
+  TyTy::ADTType::ReprOptions repr
+    = parse_repr_options (attrs, enum_decl.get_locus ());
+
   std::vector<TyTy::VariantDef *> variants;
   int64_t discriminant_value = 0;
   for (auto &variant : enum_decl.get_variants ())
@@ -375,7 +380,7 @@ TypeCheckItem::visit (HIR::Enum &enum_decl)
                         enum_decl.get_mappings ().get_hirid (),
                         enum_decl.get_identifier ().as_string (), ident,
                         TyTy::ADTType::ADTKind::ENUM, std::move (variants),
-                        std::move (substitutions));
+                        std::move (substitutions), repr);
 
   context->insert_type (enum_decl.get_mappings (), type);
   infered = type;
diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc 
b/gcc/rust/typecheck/rust-hir-type-check-type.cc
index ff6813a513d1..dd2dba39668e 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-type.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc
@@ -218,14 +218,6 @@ TypeCheckType::visit (HIR::QualifiedPathInType &path)
   if (trait_ref->is_error ())
     return;
 
-  // does this type actually implement this type-bound?
-  if (!TypeBoundsProbe::is_bound_satisfied_for_type (root, trait_ref))
-    {
-      rust_error_at (qual_path_type.get_locus (),
-                    "root does not satisfy specified trait-bound");
-      return;
-    }
-
   // get the predicate for the bound
   auto specified_bound = get_predicate_from_bound (qual_path_type.get_trait (),
                                                   qual_path_type.get_type ());
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 193217ba761c..0b85da4d297c 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -3483,20 +3483,20 @@ NeverType::clone () const
 
 // placeholder type
 
-PlaceholderType::PlaceholderType (std::string symbol, HirId ref,
+PlaceholderType::PlaceholderType (std::string symbol, DefId id, HirId ref,
                                  std::set<HirId> refs)
   : BaseType (ref, ref, KIND,
              {Resolver::CanonicalPath::create_empty (), BUILTINS_LOCATION},
              refs),
-    symbol (symbol)
+    symbol (symbol), defId (id)
 {}
 
-PlaceholderType::PlaceholderType (std::string symbol, HirId ref, HirId ty_ref,
-                                 std::set<HirId> refs)
+PlaceholderType::PlaceholderType (std::string symbol, DefId id, HirId ref,
+                                 HirId ty_ref, std::set<HirId> refs)
   : BaseType (ref, ty_ref, KIND,
              {Resolver::CanonicalPath::create_empty (), BUILTINS_LOCATION},
              refs),
-    symbol (symbol)
+    symbol (symbol), defId (id)
 {}
 
 std::string
@@ -3540,8 +3540,8 @@ PlaceholderType::can_eq (const BaseType *other, bool 
emit_errors) const
 BaseType *
 PlaceholderType::clone () const
 {
-  return new PlaceholderType (get_symbol (), get_ref (), get_ty_ref (),
-                             get_combined_refs ());
+  return new PlaceholderType (get_symbol (), get_def_id (), get_ref (),
+                             get_ty_ref (), get_combined_refs ());
 }
 
 void
@@ -3602,6 +3602,12 @@ PlaceholderType::is_equal (const BaseType &other) const
   return get_symbol ().compare (other2.get_symbol ()) == 0;
 }
 
+DefId
+PlaceholderType::get_def_id () const
+{
+  return defId;
+}
+
 // Projection type
 
 ProjectionType::ProjectionType (
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 3ac99d53ee5a..d91af33fd5b6 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -648,6 +648,7 @@ public:
     // parsing the #[repr] attribute.
     unsigned char align = 0;
     unsigned char pack = 0;
+    BaseType *repr = nullptr;
   };
 
   ADTType (HirId ref, std::string identifier, RustIdent ident, ADTKind 
adt_kind,
@@ -1530,9 +1531,9 @@ class PlaceholderType : public BaseType
 public:
   static constexpr auto KIND = TypeKind::PLACEHOLDER;
 
-  PlaceholderType (std::string symbol, HirId ref,
+  PlaceholderType (std::string symbol, DefId id, HirId ref,
                   std::set<HirId> refs = std::set<HirId> ());
-  PlaceholderType (std::string symbol, HirId ref, HirId ty_ref,
+  PlaceholderType (std::string symbol, DefId id, HirId ref, HirId ty_ref,
                   std::set<HirId> refs = std::set<HirId> ());
 
   void accept_vis (TyVisitor &vis) override;
@@ -1558,8 +1559,11 @@ public:
 
   bool is_equal (const BaseType &other) const override;
 
+  DefId get_def_id () const;
+
 private:
   std::string symbol;
+  DefId defId;
 };
 
 class ProjectionType : public BaseType, public SubstitutionRef
diff --git a/gcc/rust/util/rust-lang-item.cc b/gcc/rust/util/rust-lang-item.cc
index 9fcd325dba50..4b552e2b0b2c 100644
--- a/gcc/rust/util/rust-lang-item.cc
+++ b/gcc/rust/util/rust-lang-item.cc
@@ -115,6 +115,9 @@ const BiMap<std::string, LangItem::Kind> 
Rust::LangItem::lang_items = {{
 
   {"structural_peq", Kind::STRUCTURAL_PEQ},
   {"structural_teq", Kind::STRUCTURAL_TEQ},
+
+  {"discriminant_kind", Kind::DISCRIMINANT_KIND},
+  {"discriminant_type", Kind::DISCRIMINANT_TYPE},
 }};
 
 tl::optional<LangItem::Kind>
diff --git a/gcc/rust/util/rust-lang-item.h b/gcc/rust/util/rust-lang-item.h
index 61d6454e6606..1aaa88728e9c 100644
--- a/gcc/rust/util/rust-lang-item.h
+++ b/gcc/rust/util/rust-lang-item.h
@@ -147,6 +147,9 @@ public:
 
     STRUCTURAL_PEQ,
     STRUCTURAL_TEQ,
+
+    DISCRIMINANT_TYPE,
+    DISCRIMINANT_KIND,
   };
 
   static const BiMap<std::string, Kind> lang_items;
diff --git a/gcc/testsuite/rust/execute/torture/enum_intrinsics1.rs 
b/gcc/testsuite/rust/execute/torture/enum_intrinsics1.rs
new file mode 100644
index 000000000000..c30bbd3d3856
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/enum_intrinsics1.rs
@@ -0,0 +1,48 @@
+/* { dg-output "0\r*\n2\r*\n" } */
+#![feature(intrinsics)]
+
+#[lang = "sized"]
+pub trait Sized {}
+
+enum BookFormat {
+    Paperback,
+    Hardback,
+    Ebook,
+}
+
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+mod core {
+    mod intrinsics {
+        #[lang = "discriminant_kind"]
+        pub trait DiscriminantKind {
+            #[lang = "discriminant_type"]
+            type Discriminant;
+        }
+
+        extern "rust-intrinsic" {
+            pub fn discriminant_value<T>(v: &T) -> <T as 
DiscriminantKind>::Discriminant;
+        }
+    }
+}
+
+pub fn main() -> i32 {
+    let a = BookFormat::Paperback;
+    let b = BookFormat::Ebook;
+
+    unsafe {
+        let val1: isize = core::intrinsics::discriminant_value(&a);
+        let val2 = core::intrinsics::discriminant_value(&b);
+
+        let a = "%i\n";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, val1 as i32);
+        printf(c, val2 as i32);
+    }
+
+    0
+}

Reply via email to