Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enum instrinsics #3348

Closed
philberty opened this issue Jan 6, 2025 · 3 comments · Fixed by #3426 or #3425
Closed

enum instrinsics #3348

philberty opened this issue Jan 6, 2025 · 3 comments · Fixed by #3426 or #3425

Comments

@philberty
Copy link
Member

philberty commented Jan 6, 2025

#[lang = "sized"]
pub trait Sized {}

/// Compiler-internal trait used to indicate the type of enum discriminants.
///
/// This trait is automatically implemented for every type and does not add any
/// guarantees to [`mem::Discriminant`]. It is **undefined behavior** to transmute
/// between `DiscriminantKind::Discriminant` and `mem::Discriminant`.
///
/// [`mem::Discriminant`]: crate::mem::Discriminant
#[unstable(
    feature = "discriminant_kind",
    issue = "none",
    reason = "this trait is unlikely to ever be stabilized, use `mem::discriminant` instead"
)]
#[lang = "discriminant_kind"]
pub trait DiscriminantKind {
    /// The type of the discriminant, which must satisfy the trait
    /// bounds required by `mem::Discriminant`.
    #[lang = "discriminant_type"]
    type Discriminant: Clone + Copy + Debug + Eq + PartialEq + Hash + Send + Sync + Unpin;
}

extern "rust-intrinsic" {
    /// Returns the value of the discriminant for the variant in 'v',
    /// cast to a `u64`; if `T` has no discriminant, returns 0.
    ///
    /// The stabilized version of this intrinsic is [`core::mem::discriminant`](crate::mem::discriminant).
    #[rustc_const_unstable(feature = "const_discriminant", issue = "69821")]
    pub fn discriminant_value<T>(v: &T) -> <T as DiscriminantKind>::Discriminant;

    /// Returns the number of variants of the type `T` cast to a `usize`;
    /// if `T` has no variants, returns 0. Uninhabited variants will be counted.
    ///
    /// The to-be-stabilized version of this intrinsic is [`mem::variant_count`].
    #[rustc_const_unstable(feature = "variant_count", issue = "73662")]
    pub fn variant_count<T>() -> usize;
}

enum BookFormat {
    Paperback,
    Hardback,
    Ebook,
}

pub fn main() {
    let a = BookFormat::Paperback;
    let b = Bookform::HardBack;

    unsafe {
        let c = discriminant_value(a);
        let d = discriminant_value(b);

        let e = variant_count(a);
        let f = variant_count(b);
    }
}
@philberty
Copy link
Member Author

#![feature(intrinsics)]

#[lang = "sized"]
pub trait Sized {}

enum BookFormat {
    Paperback,
    Hardback,
    Ebook,
}

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() {
    let a = BookFormat::Paperback;

    unsafe {
        let c: isize = core::intrinsics::discriminant_value(&a);
    }
}

philberty added a commit that referenced this issue Feb 10, 2025
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 #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 <[email protected]>
@philberty
Copy link
Member Author

This compiler explorer link shows that the repr option does affect the type checking here the documentation around this intrinsic seems wrong to me in libcore: https://godbolt.org/z/x63Gr6xdK

github-merge-queue bot pushed a commit that referenced this issue Feb 11, 2025
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 #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 <[email protected]>
philberty added a commit that referenced this issue Feb 11, 2025
Addresses #3348

gcc/rust/ChangeLog:

	* backend/rust-compile-intrinsic.cc (variant_count_handler): new intrinsic

gcc/testsuite/ChangeLog:

	* rust/execute/torture/enum_intrinsics2.rs: New test.

Signed-off-by: Philip Herron <[email protected]>
@philberty
Copy link
Member Author

#3425
#3426

@github-project-automation github-project-automation bot moved this from Todo to Done in libcore 1.49 Feb 11, 2025
tschwinge pushed a commit that referenced this issue Feb 12, 2025
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 #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 <[email protected]>
tschwinge pushed a commit that referenced this issue Feb 12, 2025
Addresses #3348

gcc/rust/ChangeLog:

	* backend/rust-compile-intrinsic.cc (variant_count_handler): new intrinsic

gcc/testsuite/ChangeLog:

	* rust/execute/torture/enum_intrinsics2.rs: New test.

Signed-off-by: Philip Herron <[email protected]>
dkm pushed a commit that referenced this issue Feb 27, 2025
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 #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 <[email protected]>
dkm pushed a commit that referenced this issue Feb 27, 2025
Addresses #3348

gcc/rust/ChangeLog:

	* backend/rust-compile-intrinsic.cc (variant_count_handler): new intrinsic

gcc/testsuite/ChangeLog:

	* rust/execute/torture/enum_intrinsics2.rs: New test.

Signed-off-by: Philip Herron <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment