Skip to content

Commit 963bf52

Browse files
committed
Auto merge of #70705 - lcnr:generic_discriminant, r=nikomatsakis
Use `T`'s discriminant type in `mem::Discriminant<T>` instead of `u64`. fixes #70509 Adds the lang-item `discriminant_kind`. Updates the function signature of `intrinsics::discriminant_value`. Adds the *probably permanently unstable* trait `DiscriminantKind`. `mem::Discriminant` should now be smaller in some cases. r? @ghost
2 parents 82911b3 + 08b9b97 commit 963bf52

File tree

27 files changed

+450
-139
lines changed

27 files changed

+450
-139
lines changed

Diff for: src/doc/unstable-book/src/language-features/lang-items.md

+1
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ the source code.
287287
- `unsize`: `libcore/marker.rs`
288288
- `sync`: `libcore/marker.rs`
289289
- `phantom_data`: `libcore/marker.rs`
290+
- `discriminant_kind`: `libcore/marker.rs`
290291
- `freeze`: `libcore/marker.rs`
291292
- `debug_trait`: `libcore/fmt/mod.rs`
292293
- `non_zero`: `libcore/nonzero.rs`

Diff for: src/libcore/intrinsics.rs

+6
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@
5454
)]
5555
#![allow(missing_docs)]
5656

57+
#[cfg(not(bootstrap))]
58+
use crate::marker::DiscriminantKind;
5759
use crate::mem;
5860

5961
#[stable(feature = "drop_in_place", since = "1.8.0")]
@@ -1912,6 +1914,10 @@ extern "rust-intrinsic" {
19121914
/// The stabilized version of this intrinsic is
19131915
/// [`std::mem::discriminant`](../../std/mem/fn.discriminant.html)
19141916
#[rustc_const_unstable(feature = "const_discriminant", issue = "69821")]
1917+
#[cfg(not(bootstrap))]
1918+
pub fn discriminant_value<T>(v: &T) -> <T as DiscriminantKind>::Discriminant;
1919+
#[rustc_const_unstable(feature = "const_discriminant", issue = "69821")]
1920+
#[cfg(bootstrap)]
19151921
pub fn discriminant_value<T>(v: &T) -> u64;
19161922

19171923
/// Rust's "try catch" construct which invokes the function pointer `try_fn`

Diff for: src/libcore/marker.rs

+32
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
use crate::cell::UnsafeCell;
1010
use crate::cmp;
11+
use crate::fmt::Debug;
1112
use crate::hash::Hash;
1213
use crate::hash::Hasher;
1314

@@ -679,6 +680,37 @@ mod impls {
679680
unsafe impl<T: Send + ?Sized> Send for &mut T {}
680681
}
681682

683+
/// Compiler-internal trait used to indicate the type of enum discriminants.
684+
///
685+
/// This trait is automatically implemented for every type and does not add any
686+
/// guarantees to [`mem::Discriminant`]. It is **undefined behavior** to transmute
687+
/// between `DiscriminantKind::Discriminant` and `mem::Discriminant`.
688+
///
689+
/// [`mem::Discriminant`]: https://doc.rust-lang.org/stable/core/mem/struct.Discriminant.html
690+
#[unstable(
691+
feature = "discriminant_kind",
692+
issue = "none",
693+
reason = "this trait is unlikely to ever be stabilized, use `mem::discriminant` instead"
694+
)]
695+
#[cfg_attr(not(bootstrap), lang = "discriminant_kind")]
696+
pub trait DiscriminantKind {
697+
/// The type of the dicriminant, which must satisfy the trait
698+
/// bounds required by `mem::Discriminant`.
699+
type Discriminant: Clone + Copy + Debug + Eq + PartialEq + Hash + Send + Sync + Unpin;
700+
}
701+
702+
// Manually implement `DiscriminantKind` for all types during bootstrap
703+
// to reduce the required amount of conditional compilation.
704+
#[unstable(
705+
feature = "discriminant_kind",
706+
issue = "none",
707+
reason = "this trait is unlikely to ever be stabilized, use `mem::discriminant` instead"
708+
)]
709+
#[cfg(bootstrap)]
710+
impl<T: ?Sized> DiscriminantKind for T {
711+
type Discriminant = u64;
712+
}
713+
682714
/// Compiler-internal trait used to determine whether a type contains
683715
/// any `UnsafeCell` internally, but not through an indirection.
684716
/// This affects, for example, whether a `static` of that type is

Diff for: src/libcore/mem/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::cmp;
1010
use crate::fmt;
1111
use crate::hash;
1212
use crate::intrinsics;
13-
use crate::marker::{Copy, PhantomData, Sized};
13+
use crate::marker::{Copy, DiscriminantKind, Sized};
1414
use crate::ptr;
1515

1616
mod manually_drop;
@@ -930,7 +930,7 @@ pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
930930
///
931931
/// [`discriminant`]: fn.discriminant.html
932932
#[stable(feature = "discriminant_value", since = "1.21.0")]
933-
pub struct Discriminant<T>(u64, PhantomData<fn() -> T>);
933+
pub struct Discriminant<T>(<T as DiscriminantKind>::Discriminant);
934934

935935
// N.B. These trait implementations cannot be derived because we don't want any bounds on T.
936936

@@ -995,5 +995,5 @@ impl<T> fmt::Debug for Discriminant<T> {
995995
#[stable(feature = "discriminant_value", since = "1.21.0")]
996996
#[rustc_const_unstable(feature = "const_discriminant", issue = "69821")]
997997
pub const fn discriminant<T>(v: &T) -> Discriminant<T> {
998-
Discriminant(intrinsics::discriminant_value(v), PhantomData)
998+
Discriminant(intrinsics::discriminant_value(v))
999999
}

Diff for: src/librustc_builtin_macros/deriving/generic/mod.rs

+10-70
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,6 @@ use rustc_ast::ptr::P;
187187
use rustc_attr as attr;
188188
use rustc_data_structures::map_in_place::MapInPlace;
189189
use rustc_expand::base::{Annotatable, ExtCtxt};
190-
use rustc_session::parse::ParseSess;
191190
use rustc_span::source_map::respan;
192191
use rustc_span::symbol::{kw, sym, Ident, Symbol};
193192
use rustc_span::Span;
@@ -437,14 +436,7 @@ impl<'a> TraitDef<'a> {
437436
// This can only cause further compilation errors
438437
// downstream in blatantly illegal code, so it
439438
// is fine.
440-
self.expand_enum_def(
441-
cx,
442-
enum_def,
443-
&item.attrs,
444-
item.ident,
445-
generics,
446-
from_scratch,
447-
)
439+
self.expand_enum_def(cx, enum_def, item.ident, generics, from_scratch)
448440
}
449441
ast::ItemKind::Union(ref struct_def, ref generics) => {
450442
if self.supports_unions {
@@ -769,7 +761,6 @@ impl<'a> TraitDef<'a> {
769761
&self,
770762
cx: &mut ExtCtxt<'_>,
771763
enum_def: &'a EnumDef,
772-
type_attrs: &[ast::Attribute],
773764
type_ident: Ident,
774765
generics: &Generics,
775766
from_scratch: bool,
@@ -801,7 +792,6 @@ impl<'a> TraitDef<'a> {
801792
cx,
802793
self,
803794
enum_def,
804-
type_attrs,
805795
type_ident,
806796
self_args,
807797
&nonself_args[..],
@@ -816,38 +806,6 @@ impl<'a> TraitDef<'a> {
816806
}
817807
}
818808

819-
fn find_repr_type_name(sess: &ParseSess, type_attrs: &[ast::Attribute]) -> &'static str {
820-
let mut repr_type_name = "isize";
821-
for a in type_attrs {
822-
for r in &attr::find_repr_attrs(sess, a) {
823-
repr_type_name = match *r {
824-
attr::ReprPacked(_)
825-
| attr::ReprSimd
826-
| attr::ReprAlign(_)
827-
| attr::ReprTransparent
828-
| attr::ReprNoNiche => continue,
829-
830-
attr::ReprC => "i32",
831-
832-
attr::ReprInt(attr::SignedInt(ast::IntTy::Isize)) => "isize",
833-
attr::ReprInt(attr::SignedInt(ast::IntTy::I8)) => "i8",
834-
attr::ReprInt(attr::SignedInt(ast::IntTy::I16)) => "i16",
835-
attr::ReprInt(attr::SignedInt(ast::IntTy::I32)) => "i32",
836-
attr::ReprInt(attr::SignedInt(ast::IntTy::I64)) => "i64",
837-
attr::ReprInt(attr::SignedInt(ast::IntTy::I128)) => "i128",
838-
839-
attr::ReprInt(attr::UnsignedInt(ast::UintTy::Usize)) => "usize",
840-
attr::ReprInt(attr::UnsignedInt(ast::UintTy::U8)) => "u8",
841-
attr::ReprInt(attr::UnsignedInt(ast::UintTy::U16)) => "u16",
842-
attr::ReprInt(attr::UnsignedInt(ast::UintTy::U32)) => "u32",
843-
attr::ReprInt(attr::UnsignedInt(ast::UintTy::U64)) => "u64",
844-
attr::ReprInt(attr::UnsignedInt(ast::UintTy::U128)) => "u128",
845-
}
846-
}
847-
}
848-
repr_type_name
849-
}
850-
851809
impl<'a> MethodDef<'a> {
852810
fn call_substructure_method(
853811
&self,
@@ -1148,20 +1106,11 @@ impl<'a> MethodDef<'a> {
11481106
cx: &mut ExtCtxt<'_>,
11491107
trait_: &TraitDef<'b>,
11501108
enum_def: &'b EnumDef,
1151-
type_attrs: &[ast::Attribute],
11521109
type_ident: Ident,
11531110
self_args: Vec<P<Expr>>,
11541111
nonself_args: &[P<Expr>],
11551112
) -> P<Expr> {
1156-
self.build_enum_match_tuple(
1157-
cx,
1158-
trait_,
1159-
enum_def,
1160-
type_attrs,
1161-
type_ident,
1162-
self_args,
1163-
nonself_args,
1164-
)
1113+
self.build_enum_match_tuple(cx, trait_, enum_def, type_ident, self_args, nonself_args)
11651114
}
11661115

11671116
/// Creates a match for a tuple of all `self_args`, where either all
@@ -1181,11 +1130,11 @@ impl<'a> MethodDef<'a> {
11811130
11821131
/// ```{.text}
11831132
/// let __self0_vi = unsafe {
1184-
/// std::intrinsics::discriminant_value(&self) } as i32;
1133+
/// std::intrinsics::discriminant_value(&self) };
11851134
/// let __self1_vi = unsafe {
1186-
/// std::intrinsics::discriminant_value(&arg1) } as i32;
1135+
/// std::intrinsics::discriminant_value(&arg1) };
11871136
/// let __self2_vi = unsafe {
1188-
/// std::intrinsics::discriminant_value(&arg2) } as i32;
1137+
/// std::intrinsics::discriminant_value(&arg2) };
11891138
///
11901139
/// if __self0_vi == __self1_vi && __self0_vi == __self2_vi && ... {
11911140
/// match (...) {
@@ -1204,7 +1153,6 @@ impl<'a> MethodDef<'a> {
12041153
cx: &mut ExtCtxt<'_>,
12051154
trait_: &TraitDef<'b>,
12061155
enum_def: &'b EnumDef,
1207-
type_attrs: &[ast::Attribute],
12081156
type_ident: Ident,
12091157
mut self_args: Vec<P<Expr>>,
12101158
nonself_args: &[P<Expr>],
@@ -1392,39 +1340,31 @@ impl<'a> MethodDef<'a> {
13921340
//
13931341
if variants.len() > 1 && self_args.len() > 1 {
13941342
// Build a series of let statements mapping each self_arg
1395-
// to its discriminant value. If this is a C-style enum
1396-
// with a specific repr type, then casts the values to
1397-
// that type. Otherwise casts to `i32` (the default repr
1398-
// type).
1343+
// to its discriminant value.
13991344
//
14001345
// i.e., for `enum E<T> { A, B(1), C(T, T) }`, and a deriving
14011346
// with three Self args, builds three statements:
14021347
//
14031348
// ```
14041349
// let __self0_vi = unsafe {
1405-
// std::intrinsics::discriminant_value(&self) } as i32;
1350+
// std::intrinsics::discriminant_value(&self) };
14061351
// let __self1_vi = unsafe {
1407-
// std::intrinsics::discriminant_value(&arg1) } as i32;
1352+
// std::intrinsics::discriminant_value(&arg1) };
14081353
// let __self2_vi = unsafe {
1409-
// std::intrinsics::discriminant_value(&arg2) } as i32;
1354+
// std::intrinsics::discriminant_value(&arg2) };
14101355
// ```
14111356
let mut index_let_stmts: Vec<ast::Stmt> = Vec::with_capacity(vi_idents.len() + 1);
14121357

14131358
// We also build an expression which checks whether all discriminants are equal
14141359
// discriminant_test = __self0_vi == __self1_vi && __self0_vi == __self2_vi && ...
14151360
let mut discriminant_test = cx.expr_bool(sp, true);
14161361

1417-
let target_type_name = find_repr_type_name(&cx.parse_sess, type_attrs);
1418-
14191362
let mut first_ident = None;
14201363
for (&ident, self_arg) in vi_idents.iter().zip(&self_args) {
14211364
let self_addr = cx.expr_addr_of(sp, self_arg.clone());
14221365
let variant_value =
14231366
deriving::call_intrinsic(cx, sp, "discriminant_value", vec![self_addr]);
1424-
1425-
let target_ty = cx.ty_ident(sp, cx.ident_of(target_type_name, sp));
1426-
let variant_disr = cx.expr_cast(sp, variant_value, target_ty);
1427-
let let_stmt = cx.stmt_let(sp, false, ident, variant_disr);
1367+
let let_stmt = cx.stmt_let(sp, false, ident, variant_value);
14281368
index_let_stmts.push(let_stmt);
14291369

14301370
match first_ident {

Diff for: src/librustc_codegen_llvm/intrinsic.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -188,11 +188,11 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
188188
}
189189
"size_of" | "pref_align_of" | "min_align_of" | "needs_drop" | "type_id"
190190
| "type_name" => {
191-
let ty_name = self
191+
let value = self
192192
.tcx
193193
.const_eval_instance(ty::ParamEnv::reveal_all(), instance, None)
194194
.unwrap();
195-
OperandRef::from_const(self, ty_name, ret_ty).immediate_or_packed_pair(self)
195+
OperandRef::from_const(self, value, ret_ty).immediate_or_packed_pair(self)
196196
}
197197
// Effectively no-op
198198
"forget" => {
@@ -549,7 +549,13 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
549549
}
550550
}
551551

552-
"discriminant_value" => args[0].deref(self.cx()).codegen_get_discr(self, ret_ty),
552+
"discriminant_value" => {
553+
if ret_ty.is_integral() {
554+
args[0].deref(self.cx()).codegen_get_discr(self, ret_ty)
555+
} else {
556+
span_bug!(span, "Invalid discriminant type for `{:?}`", arg_tys[0])
557+
}
558+
}
553559

554560
name if name.starts_with("simd_") => {
555561
match generic_simd_intrinsic(self, name, callee_ty, args, ret_ty, llret_ty, span) {

Diff for: src/librustc_hir/lang_items.rs

+1
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ language_item_table! {
163163
CopyTraitLangItem, "copy", copy_trait, Target::Trait;
164164
CloneTraitLangItem, "clone", clone_trait, Target::Trait;
165165
SyncTraitLangItem, "sync", sync_trait, Target::Trait;
166+
DiscriminantKindTraitLangItem,"discriminant_kind", discriminant_kind_trait, Target::Trait;
166167
FreezeTraitLangItem, "freeze", freeze_trait, Target::Trait;
167168

168169
DropTraitLangItem, "drop", drop_trait, Target::Trait;

Diff for: src/librustc_middle/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#![feature(const_panic)]
3333
#![feature(const_transmute)]
3434
#![feature(core_intrinsics)]
35+
#![feature(discriminant_kind)]
3536
#![feature(drain_filter)]
3637
#![feature(never_type)]
3738
#![feature(exhaustive_patterns)]

Diff for: src/librustc_middle/traits/mod.rs

+12
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,9 @@ pub enum Vtable<'tcx, N> {
411411
/// Same as above, but for a function pointer type with the given signature.
412412
VtableFnPointer(VtableFnPointerData<'tcx, N>),
413413

414+
/// Vtable for a builtin `DeterminantKind` trait implementation.
415+
VtableDiscriminantKind(VtableDiscriminantKindData),
416+
414417
/// Vtable automatically generated for a generator.
415418
VtableGenerator(VtableGeneratorData<'tcx, N>),
416419

@@ -429,6 +432,7 @@ impl<'tcx, N> Vtable<'tcx, N> {
429432
VtableGenerator(c) => c.nested,
430433
VtableObject(d) => d.nested,
431434
VtableFnPointer(d) => d.nested,
435+
VtableDiscriminantKind(VtableDiscriminantKindData) => Vec::new(),
432436
VtableTraitAlias(d) => d.nested,
433437
}
434438
}
@@ -443,6 +447,7 @@ impl<'tcx, N> Vtable<'tcx, N> {
443447
VtableGenerator(c) => &c.nested[..],
444448
VtableObject(d) => &d.nested[..],
445449
VtableFnPointer(d) => &d.nested[..],
450+
VtableDiscriminantKind(VtableDiscriminantKindData) => &[],
446451
VtableTraitAlias(d) => &d.nested[..],
447452
}
448453
}
@@ -484,6 +489,9 @@ impl<'tcx, N> Vtable<'tcx, N> {
484489
fn_ty: p.fn_ty,
485490
nested: p.nested.into_iter().map(f).collect(),
486491
}),
492+
VtableDiscriminantKind(VtableDiscriminantKindData) => {
493+
VtableDiscriminantKind(VtableDiscriminantKindData)
494+
}
487495
VtableTraitAlias(d) => VtableTraitAlias(VtableTraitAliasData {
488496
alias_def_id: d.alias_def_id,
489497
substs: d.substs,
@@ -560,6 +568,10 @@ pub struct VtableFnPointerData<'tcx, N> {
560568
pub nested: Vec<N>,
561569
}
562570

571+
// FIXME(@lcnr): This should be refactored and merged with other builtin vtables.
572+
#[derive(Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
573+
pub struct VtableDiscriminantKindData;
574+
563575
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
564576
pub struct VtableTraitAliasData<'tcx, N> {
565577
pub alias_def_id: DefId,

0 commit comments

Comments
 (0)