Skip to content

Commit 20976ba

Browse files
committed
Auto merge of rust-lang#97293 - est31:remove_box, r=oli-obk
Add #[rustc_box] and use it inside alloc This commit adds an alternative content boxing syntax, and uses it inside alloc. ```Rust #![feature(box_syntax)] fn foo() { let foo = box bar; } ``` is equivalent to ```Rust #![feature(rustc_attrs)] fn foo() { let foo = #[rustc_box] Box::new(bar); } ``` The usage inside the very performance relevant code in liballoc is the only remaining relevant usage of box syntax in the compiler (outside of tests, which are comparatively easy to port). box syntax was originally designed to be used by all Rust developers. This introduces a replacement syntax more tailored to only being used inside the Rust compiler, and with it, lays the groundwork for eventually removing box syntax. [Earlier work](rust-lang#87781 (comment)) by `@nbdd0121` to lower `Box::new` to `box` during THIR -> MIR building ran into borrow checker problems, requiring the lowering to be adjusted in a way that led to [performance regressions](rust-lang#87781 (comment)). The proposed change in this PR lowers `#[rustc_box] Box::new` -> `box` in the AST -> HIR lowering step, which is way earlier in the compiler, and thus should cause less issues both performance wise as well as regarding type inference/borrow checking/etc. Hopefully, future work can move the lowering further back in the compiler, as long as there are no performance regressions.
2 parents 9598b4b + 0a24b94 commit 20976ba

File tree

8 files changed

+80
-11
lines changed

8 files changed

+80
-11
lines changed

compiler/rustc_ast_lowering/src/expr.rs

+16-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,22 @@ impl<'hir> LoweringContext<'_, 'hir> {
4141
}
4242
ExprKind::Tup(ref elts) => hir::ExprKind::Tup(self.lower_exprs(elts)),
4343
ExprKind::Call(ref f, ref args) => {
44-
if let Some(legacy_args) = self.resolver.legacy_const_generic_args(f) {
44+
if e.attrs.get(0).map_or(false, |a| a.has_name(sym::rustc_box)) {
45+
if let [inner] = &args[..] && e.attrs.len() == 1 {
46+
let kind = hir::ExprKind::Box(self.lower_expr(&inner));
47+
let hir_id = self.lower_node_id(e.id);
48+
return hir::Expr { hir_id, kind, span: self.lower_span(e.span) };
49+
} else {
50+
self.sess
51+
.struct_span_err(
52+
e.span,
53+
"#[rustc_box] requires precisely one argument \
54+
and no other attributes are allowed",
55+
)
56+
.emit();
57+
hir::ExprKind::Err
58+
}
59+
} else if let Some(legacy_args) = self.resolver.legacy_const_generic_args(f) {
4560
self.lower_legacy_const_generics((**f).clone(), args.clone(), &legacy_args)
4661
} else {
4762
let f = self.lower_expr(f);

compiler/rustc_feature/src/builtin_attrs.rs

+6
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,12 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
675675
"#[rustc_has_incoherent_inherent_impls] allows the addition of incoherent inherent impls for \
676676
the given type by annotating all impl items with #[rustc_allow_incoherent_impl]."
677677
),
678+
rustc_attr!(
679+
rustc_box, AttributeType::Normal, template!(Word), ErrorFollowing,
680+
"#[rustc_box] allows creating boxes \
681+
and it is only intended to be used in `alloc`."
682+
),
683+
678684
BuiltinAttribute {
679685
name: sym::rustc_diagnostic_item,
680686
// FIXME: This can be `true` once we always use `tcx.is_diagnostic_item`.

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1173,6 +1173,7 @@ symbols! {
11731173
rustc_allow_const_fn_unstable,
11741174
rustc_allow_incoherent_impl,
11751175
rustc_attrs,
1176+
rustc_box,
11761177
rustc_builtin_macro,
11771178
rustc_capture_analysis,
11781179
rustc_clean,

library/alloc/src/boxed.rs

+26-4
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,25 @@ impl<T> Box<T> {
206206
/// ```
207207
/// let five = Box::new(5);
208208
/// ```
209-
#[cfg(not(no_global_oom_handling))]
209+
#[cfg(all(not(no_global_oom_handling), not(bootstrap)))]
210+
#[inline(always)]
211+
#[stable(feature = "rust1", since = "1.0.0")]
212+
#[must_use]
213+
pub fn new(x: T) -> Self {
214+
#[rustc_box]
215+
Box::new(x)
216+
}
217+
218+
/// Allocates memory on the heap and then places `x` into it.
219+
///
220+
/// This doesn't actually allocate if `T` is zero-sized.
221+
///
222+
/// # Examples
223+
///
224+
/// ```
225+
/// let five = Box::new(5);
226+
/// ```
227+
#[cfg(all(not(no_global_oom_handling), bootstrap))]
210228
#[inline(always)]
211229
#[stable(feature = "rust1", since = "1.0.0")]
212230
#[must_use]
@@ -273,7 +291,9 @@ impl<T> Box<T> {
273291
#[must_use]
274292
#[inline(always)]
275293
pub fn pin(x: T) -> Pin<Box<T>> {
276-
(box x).into()
294+
(#[cfg_attr(not(bootstrap), rustc_box)]
295+
Box::new(x))
296+
.into()
277297
}
278298

279299
/// Allocates memory on the heap then places `x` into it,
@@ -1219,7 +1239,8 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Box<T, A> {
12191239
impl<T: Default> Default for Box<T> {
12201240
/// Creates a `Box<T>`, with the `Default` value for T.
12211241
fn default() -> Self {
1222-
box T::default()
1242+
#[cfg_attr(not(bootstrap), rustc_box)]
1243+
Box::new(T::default())
12231244
}
12241245
}
12251246

@@ -1583,7 +1604,8 @@ impl<T, const N: usize> From<[T; N]> for Box<[T]> {
15831604
/// println!("{boxed:?}");
15841605
/// ```
15851606
fn from(array: [T; N]) -> Box<[T]> {
1586-
box array
1607+
#[cfg_attr(not(bootstrap), rustc_box)]
1608+
Box::new(array)
15871609
}
15881610
}
15891611

library/alloc/src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@
148148
#![feature(allocator_internals)]
149149
#![feature(allow_internal_unstable)]
150150
#![feature(associated_type_bounds)]
151-
#![feature(box_syntax)]
151+
#![cfg_attr(bootstrap, feature(box_syntax))]
152152
#![feature(cfg_sanitize)]
153153
#![feature(const_deref)]
154154
#![feature(const_mut_refs)]
@@ -171,6 +171,7 @@
171171
#![feature(rustc_attrs)]
172172
#![feature(slice_internals)]
173173
#![feature(staged_api)]
174+
#![feature(stmt_expr_attributes)]
174175
#![cfg_attr(test, feature(test))]
175176
#![feature(unboxed_closures)]
176177
#![feature(unsized_fn_params)]

library/alloc/src/macros.rs

+23-2
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,28 @@
3434
/// be mindful of side effects.
3535
///
3636
/// [`Vec`]: crate::vec::Vec
37-
#[cfg(all(not(no_global_oom_handling), not(test)))]
37+
#[cfg(all(not(no_global_oom_handling), not(test), not(bootstrap)))]
38+
#[macro_export]
39+
#[stable(feature = "rust1", since = "1.0.0")]
40+
#[rustc_diagnostic_item = "vec_macro"]
41+
#[allow_internal_unstable(rustc_attrs, liballoc_internals)]
42+
macro_rules! vec {
43+
() => (
44+
$crate::__rust_force_expr!($crate::vec::Vec::new())
45+
);
46+
($elem:expr; $n:expr) => (
47+
$crate::__rust_force_expr!($crate::vec::from_elem($elem, $n))
48+
);
49+
($($x:expr),+ $(,)?) => (
50+
$crate::__rust_force_expr!(<[_]>::into_vec(
51+
#[rustc_box]
52+
$crate::boxed::Box::new([$($x),+])
53+
))
54+
);
55+
}
56+
57+
/// Creates a `Vec` containing the arguments (bootstrap version).
58+
#[cfg(all(not(no_global_oom_handling), not(test), bootstrap))]
3859
#[macro_export]
3960
#[stable(feature = "rust1", since = "1.0.0")]
4061
#[rustc_diagnostic_item = "vec_macro"]
@@ -65,7 +86,7 @@ macro_rules! vec {
6586
$crate::vec::from_elem($elem, $n)
6687
);
6788
($($x:expr),*) => (
68-
$crate::slice::into_vec(box [$($x),*])
89+
$crate::slice::into_vec($crate::boxed::Box::new([$($x),*]))
6990
);
7091
($($x:expr,)*) => (vec![$($x),*])
7192
}

library/alloc/src/vec/mod.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -2987,12 +2987,15 @@ impl<T, const N: usize> From<[T; N]> for Vec<T> {
29872987
/// ```
29882988
#[cfg(not(test))]
29892989
fn from(s: [T; N]) -> Vec<T> {
2990-
<[T]>::into_vec(box s)
2990+
<[T]>::into_vec(
2991+
#[cfg_attr(not(bootstrap), rustc_box)]
2992+
Box::new(s),
2993+
)
29912994
}
29922995

29932996
#[cfg(test)]
29942997
fn from(s: [T; N]) -> Vec<T> {
2995-
crate::slice::into_vec(box s)
2998+
crate::slice::into_vec(Box::new(s))
29962999
}
29973000
}
29983001

src/test/ui/type/ascription/issue-47666.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: expected type, found `<[_]>::into_vec(box [0, 1])`
1+
error: expected type, found `<[_]>::into_vec(#[rustc_box] ::alloc::boxed::Box::new([0, 1]))`
22
--> $DIR/issue-47666.rs:3:25
33
|
44
LL | let _ = Option:Some(vec![0, 1]);

0 commit comments

Comments
 (0)