Skip to content

Commit 458d4da

Browse files
committed
Auto merge of rust-lang#110821 - matthiaskrgr:rollup-mzxrvw7, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - rust-lang#110556 (Switch to `EarlyBinder` for `explicit_item_bounds`) - rust-lang#110615 (Add `impl_tag!` macro to implement `Tag` for tagged pointer easily) - rust-lang#110649 (Fix no_global_oom_handling build) - rust-lang#110671 (Consider polarity in new solver) - rust-lang#110783 (Fix ICE on --print=... i/o errors) - rust-lang#110796 (Updating Wake example to use new 'pin!' macro) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 666fee2 + 77752a0 commit 458d4da

File tree

41 files changed

+495
-145
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+495
-145
lines changed

Diff for: compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -702,7 +702,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
702702
.copied()
703703
.find_map(find_fn_kind_from_did),
704704
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => tcx
705-
.bound_explicit_item_bounds(def_id)
705+
.explicit_item_bounds(def_id)
706706
.subst_iter_copied(tcx, substs)
707707
.find_map(find_fn_kind_from_did),
708708
ty::Closure(_, substs) => match substs.as_closure().kind() {

Diff for: compiler/rustc_data_structures/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#![feature(unwrap_infallible)]
3232
#![feature(strict_provenance)]
3333
#![feature(ptr_alignment_type)]
34+
#![feature(macro_metavar_expr)]
3435
#![allow(rustc::default_hash_types)]
3536
#![allow(rustc::potential_query_instability)]
3637
#![deny(rustc::untranslatable_diagnostic)]

Diff for: compiler/rustc_data_structures/src/tagged_ptr.rs

+25-6
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use crate::aligned::Aligned;
2424

2525
mod copy;
2626
mod drop;
27+
mod impl_tag;
2728

2829
pub use copy::CopyTaggedPtr;
2930
pub use drop::TaggedPtr;
@@ -141,6 +142,30 @@ pub unsafe trait Tag: Copy {
141142
unsafe fn from_usize(tag: usize) -> Self;
142143
}
143144

145+
/// Returns the number of bits available for use for tags in a pointer to `T`
146+
/// (this is based on `T`'s alignment).
147+
pub const fn bits_for<T: ?Sized + Aligned>() -> u32 {
148+
crate::aligned::align_of::<T>().as_nonzero().trailing_zeros()
149+
}
150+
151+
/// Returns the correct [`Tag::BITS`] constant for a set of tag values.
152+
pub const fn bits_for_tags(mut tags: &[usize]) -> u32 {
153+
let mut bits = 0;
154+
155+
while let &[tag, ref rest @ ..] = tags {
156+
tags = rest;
157+
158+
// bits required to represent `tag`,
159+
// position of the most significant 1
160+
let b = usize::BITS - tag.leading_zeros();
161+
if b > bits {
162+
bits = b;
163+
}
164+
}
165+
166+
bits
167+
}
168+
144169
unsafe impl<T: ?Sized + Aligned> Pointer for Box<T> {
145170
const BITS: u32 = bits_for::<Self::Target>();
146171

@@ -221,12 +246,6 @@ unsafe impl<'a, T: 'a + ?Sized + Aligned> Pointer for &'a mut T {
221246
}
222247
}
223248

224-
/// Returns the number of bits available for use for tags in a pointer to `T`
225-
/// (this is based on `T`'s alignment).
226-
pub const fn bits_for<T: ?Sized + Aligned>() -> u32 {
227-
crate::aligned::align_of::<T>().as_nonzero().trailing_zeros()
228-
}
229-
230249
/// A tag type used in [`CopyTaggedPtr`] and [`TaggedPtr`] tests.
231250
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
232251
#[cfg(test)]
+144
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
/// Implements [`Tag`] for a given type.
2+
///
3+
/// You can use `impl_tag` on structs and enums.
4+
/// You need to specify the type and all its possible values,
5+
/// which can only be paths with optional fields.
6+
///
7+
/// [`Tag`]: crate::tagged_ptr::Tag
8+
///
9+
/// # Examples
10+
///
11+
/// Basic usage:
12+
///
13+
/// ```
14+
/// #![feature(macro_metavar_expr)]
15+
/// use rustc_data_structures::{impl_tag, tagged_ptr::Tag};
16+
///
17+
/// #[derive(Copy, Clone, PartialEq, Debug)]
18+
/// enum SomeTag {
19+
/// A,
20+
/// B,
21+
/// X { v: bool },
22+
/// Y(bool, bool),
23+
/// }
24+
///
25+
/// impl_tag! {
26+
/// // The type for which the `Tag` will be implemented
27+
/// impl Tag for SomeTag;
28+
/// // You need to specify all possible tag values:
29+
/// SomeTag::A, // 0
30+
/// SomeTag::B, // 1
31+
/// // For variants with fields, you need to specify the fields:
32+
/// SomeTag::X { v: true }, // 2
33+
/// SomeTag::X { v: false }, // 3
34+
/// // For tuple variants use named syntax:
35+
/// SomeTag::Y { 0: true, 1: true }, // 4
36+
/// SomeTag::Y { 0: false, 1: true }, // 5
37+
/// SomeTag::Y { 0: true, 1: false }, // 6
38+
/// SomeTag::Y { 0: false, 1: false }, // 7
39+
/// }
40+
///
41+
/// // Tag values are assigned in order:
42+
/// assert_eq!(SomeTag::A.into_usize(), 0);
43+
/// assert_eq!(SomeTag::X { v: false }.into_usize(), 3);
44+
/// assert_eq!(SomeTag::Y(false, true).into_usize(), 5);
45+
///
46+
/// assert_eq!(unsafe { SomeTag::from_usize(1) }, SomeTag::B);
47+
/// assert_eq!(unsafe { SomeTag::from_usize(2) }, SomeTag::X { v: true });
48+
/// assert_eq!(unsafe { SomeTag::from_usize(7) }, SomeTag::Y(false, false));
49+
/// ```
50+
///
51+
/// Structs are supported:
52+
///
53+
/// ```
54+
/// #![feature(macro_metavar_expr)]
55+
/// # use rustc_data_structures::impl_tag;
56+
/// #[derive(Copy, Clone)]
57+
/// struct Flags { a: bool, b: bool }
58+
///
59+
/// impl_tag! {
60+
/// impl Tag for Flags;
61+
/// Flags { a: true, b: true },
62+
/// Flags { a: false, b: true },
63+
/// Flags { a: true, b: false },
64+
/// Flags { a: false, b: false },
65+
/// }
66+
/// ```
67+
///
68+
/// Not specifying all values results in a compile error:
69+
///
70+
/// ```compile_fail,E0004
71+
/// #![feature(macro_metavar_expr)]
72+
/// # use rustc_data_structures::impl_tag;
73+
/// #[derive(Copy, Clone)]
74+
/// enum E {
75+
/// A,
76+
/// B,
77+
/// }
78+
///
79+
/// impl_tag! {
80+
/// impl Tag for E;
81+
/// E::A,
82+
/// }
83+
/// ```
84+
#[macro_export]
85+
macro_rules! impl_tag {
86+
(
87+
impl Tag for $Self:ty;
88+
$(
89+
$($path:ident)::* $( { $( $fields:tt )* })?,
90+
)*
91+
) => {
92+
// Safety:
93+
// `bits_for_tags` is called on the same `${index()}`-es as
94+
// `into_usize` returns, thus `BITS` constant is correct.
95+
unsafe impl $crate::tagged_ptr::Tag for $Self {
96+
const BITS: u32 = $crate::tagged_ptr::bits_for_tags(&[
97+
$(
98+
${index()},
99+
$( ${ignore(path)} )*
100+
)*
101+
]);
102+
103+
#[inline]
104+
fn into_usize(self) -> usize {
105+
// This forbids use of repeating patterns (`Enum::V`&`Enum::V`, etc)
106+
// (or at least it should, see <https://github.com/rust-lang/rust/issues/110613>)
107+
#[forbid(unreachable_patterns)]
108+
match self {
109+
// `match` is doing heavy lifting here, by requiring exhaustiveness
110+
$(
111+
$($path)::* $( { $( $fields )* } )? => ${index()},
112+
)*
113+
}
114+
}
115+
116+
#[inline]
117+
unsafe fn from_usize(tag: usize) -> Self {
118+
match tag {
119+
$(
120+
${index()} => $($path)::* $( { $( $fields )* } )?,
121+
)*
122+
123+
// Safety:
124+
// `into_usize` only returns `${index()}` of the same
125+
// repetition as we are filtering above, thus if this is
126+
// reached, the safety contract of this function was
127+
// already breached.
128+
_ => unsafe {
129+
debug_assert!(
130+
false,
131+
"invalid tag: {tag}\
132+
(this is a bug in the caller of `from_usize`)"
133+
);
134+
std::hint::unreachable_unchecked()
135+
},
136+
}
137+
}
138+
139+
}
140+
};
141+
}
142+
143+
#[cfg(test)]
144+
mod tests;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#[test]
2+
fn bits_constant() {
3+
use crate::tagged_ptr::Tag;
4+
5+
#[derive(Copy, Clone)]
6+
struct Unit;
7+
impl_tag! { impl Tag for Unit; Unit, }
8+
assert_eq!(Unit::BITS, 0);
9+
10+
#[derive(Copy, Clone)]
11+
enum Enum3 {
12+
A,
13+
B,
14+
C,
15+
}
16+
impl_tag! { impl Tag for Enum3; Enum3::A, Enum3::B, Enum3::C, }
17+
assert_eq!(Enum3::BITS, 2);
18+
19+
#[derive(Copy, Clone)]
20+
struct Eight(bool, bool, bool);
21+
impl_tag! {
22+
impl Tag for Eight;
23+
Eight { 0: true, 1: true, 2: true },
24+
Eight { 0: true, 1: true, 2: false },
25+
Eight { 0: true, 1: false, 2: true },
26+
Eight { 0: true, 1: false, 2: false },
27+
Eight { 0: false, 1: true, 2: true },
28+
Eight { 0: false, 1: true, 2: false },
29+
Eight { 0: false, 1: false, 2: true },
30+
Eight { 0: false, 1: false, 2: false },
31+
}
32+
33+
assert_eq!(Eight::BITS, 3);
34+
}

0 commit comments

Comments
 (0)