diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 3aff04f78fb..539e33702aa 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -41,7 +41,22 @@ impl<'hir> LoweringContext<'_, 'hir> { } ExprKind::Tup(ref elts) => hir::ExprKind::Tup(self.lower_exprs(elts)), ExprKind::Call(ref f, ref args) => { - if let Some(legacy_args) = self.resolver.legacy_const_generic_args(f) { + if e.attrs.get(0).map_or(false, |a| a.has_name(sym::rustc_box)) { + if let [inner] = &args[..] && e.attrs.len() == 1 { + let kind = hir::ExprKind::Box(self.lower_expr(&inner)); + let hir_id = self.lower_node_id(e.id); + return hir::Expr { hir_id, kind, span: self.lower_span(e.span) }; + } else { + self.sess + .struct_span_err( + e.span, + "#[rustc_box] requires precisely one argument \ + and no other attributes are allowed", + ) + .emit(); + hir::ExprKind::Err + } + } else if let Some(legacy_args) = self.resolver.legacy_const_generic_args(f) { self.lower_legacy_const_generics((**f).clone(), args.clone(), &legacy_args) } else { let f = self.lower_expr(f); diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 8155e65a6db..5eb2be97f8b 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -675,6 +675,12 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ "#[rustc_has_incoherent_inherent_impls] allows the addition of incoherent inherent impls for \ the given type by annotating all impl items with #[rustc_allow_incoherent_impl]." ), + rustc_attr!( + rustc_box, AttributeType::Normal, template!(Word), ErrorFollowing, + "#[rustc_box] allows creating boxes \ + and it is only intended to be used in `alloc`." + ), + BuiltinAttribute { name: sym::rustc_diagnostic_item, // FIXME: This can be `true` once we always use `tcx.is_diagnostic_item`. diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 16162f1cc89..1954cdc0bff 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1173,6 +1173,7 @@ symbols! { rustc_allow_const_fn_unstable, rustc_allow_incoherent_impl, rustc_attrs, + rustc_box, rustc_builtin_macro, rustc_capture_analysis, rustc_clean, diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index e2c692b5299..35ac5c8ebf6 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -206,7 +206,25 @@ impl Box { /// ``` /// let five = Box::new(5); /// ``` - #[cfg(not(no_global_oom_handling))] + #[cfg(all(not(no_global_oom_handling), not(bootstrap)))] + #[inline(always)] + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] + pub fn new(x: T) -> Self { + #[rustc_box] + Box::new(x) + } + + /// Allocates memory on the heap and then places `x` into it. + /// + /// This doesn't actually allocate if `T` is zero-sized. + /// + /// # Examples + /// + /// ``` + /// let five = Box::new(5); + /// ``` + #[cfg(all(not(no_global_oom_handling), bootstrap))] #[inline(always)] #[stable(feature = "rust1", since = "1.0.0")] #[must_use] @@ -273,7 +291,9 @@ impl Box { #[must_use] #[inline(always)] pub fn pin(x: T) -> Pin> { - (box x).into() + (#[cfg_attr(not(bootstrap), rustc_box)] + Box::new(x)) + .into() } /// 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 { impl Default for Box { /// Creates a `Box`, with the `Default` value for T. fn default() -> Self { - box T::default() + #[cfg_attr(not(bootstrap), rustc_box)] + Box::new(T::default()) } } @@ -1583,7 +1604,8 @@ impl From<[T; N]> for Box<[T]> { /// println!("{boxed:?}"); /// ``` fn from(array: [T; N]) -> Box<[T]> { - box array + #[cfg_attr(not(bootstrap), rustc_box)] + Box::new(array) } } diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 35b8b386dce..710a3985266 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -148,7 +148,7 @@ #![feature(allocator_internals)] #![feature(allow_internal_unstable)] #![feature(associated_type_bounds)] -#![feature(box_syntax)] +#![cfg_attr(bootstrap, feature(box_syntax))] #![feature(cfg_sanitize)] #![feature(const_deref)] #![feature(const_mut_refs)] @@ -171,6 +171,7 @@ #![feature(rustc_attrs)] #![feature(slice_internals)] #![feature(staged_api)] +#![feature(stmt_expr_attributes)] #![cfg_attr(test, feature(test))] #![feature(unboxed_closures)] #![feature(unsized_fn_params)] diff --git a/library/alloc/src/macros.rs b/library/alloc/src/macros.rs index d9346daa109..37898b6655f 100644 --- a/library/alloc/src/macros.rs +++ b/library/alloc/src/macros.rs @@ -34,7 +34,28 @@ /// be mindful of side effects. /// /// [`Vec`]: crate::vec::Vec -#[cfg(all(not(no_global_oom_handling), not(test)))] +#[cfg(all(not(no_global_oom_handling), not(test), not(bootstrap)))] +#[macro_export] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_diagnostic_item = "vec_macro"] +#[allow_internal_unstable(rustc_attrs, liballoc_internals)] +macro_rules! vec { + () => ( + $crate::__rust_force_expr!($crate::vec::Vec::new()) + ); + ($elem:expr; $n:expr) => ( + $crate::__rust_force_expr!($crate::vec::from_elem($elem, $n)) + ); + ($($x:expr),+ $(,)?) => ( + $crate::__rust_force_expr!(<[_]>::into_vec( + #[rustc_box] + $crate::boxed::Box::new([$($x),+]) + )) + ); +} + +/// Creates a `Vec` containing the arguments (bootstrap version). +#[cfg(all(not(no_global_oom_handling), not(test), bootstrap))] #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "vec_macro"] @@ -65,7 +86,7 @@ macro_rules! vec { $crate::vec::from_elem($elem, $n) ); ($($x:expr),*) => ( - $crate::slice::into_vec(box [$($x),*]) + $crate::slice::into_vec($crate::boxed::Box::new([$($x),*])) ); ($($x:expr,)*) => (vec![$($x),*]) } diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 33cffa643e4..1c0cb6636a1 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2987,12 +2987,15 @@ impl From<[T; N]> for Vec { /// ``` #[cfg(not(test))] fn from(s: [T; N]) -> Vec { - <[T]>::into_vec(box s) + <[T]>::into_vec( + #[cfg_attr(not(bootstrap), rustc_box)] + Box::new(s), + ) } #[cfg(test)] fn from(s: [T; N]) -> Vec { - crate::slice::into_vec(box s) + crate::slice::into_vec(Box::new(s)) } } diff --git a/src/test/ui/type/ascription/issue-47666.stderr b/src/test/ui/type/ascription/issue-47666.stderr index 59b35292726..b59a73af9f9 100644 --- a/src/test/ui/type/ascription/issue-47666.stderr +++ b/src/test/ui/type/ascription/issue-47666.stderr @@ -1,4 +1,4 @@ -error: expected type, found `<[_]>::into_vec(box [0, 1])` +error: expected type, found `<[_]>::into_vec(#[rustc_box] ::alloc::boxed::Box::new([0, 1]))` --> $DIR/issue-47666.rs:3:25 | LL | let _ = Option:Some(vec![0, 1]);