Skip to content

Commit 0a79683

Browse files
committed
turn rustc_box into an intrinsic
1 parent bf6f8a4 commit 0a79683

File tree

13 files changed

+137
-138
lines changed

13 files changed

+137
-138
lines changed

compiler/rustc_feature/src/builtin_attrs.rs

-5
Original file line numberDiff line numberDiff line change
@@ -933,11 +933,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
933933
"#[rustc_has_incoherent_inherent_impls] allows the addition of incoherent inherent impls for \
934934
the given type by annotating all impl items with #[rustc_allow_incoherent_impl]."
935935
),
936-
rustc_attr!(
937-
rustc_box, AttributeType::Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::No,
938-
"#[rustc_box] allows creating boxes \
939-
and it is only intended to be used in `alloc`."
940-
),
941936

942937
BuiltinAttribute {
943938
name: sym::rustc_diagnostic_item,

compiler/rustc_hir_analysis/src/check/intrinsic.rs

+3
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -
8686
| sym::assert_inhabited
8787
| sym::assert_zero_valid
8888
| sym::assert_mem_uninitialized_valid
89+
| sym::box_new
8990
| sym::breakpoint
9091
| sym::size_of
9192
| sym::min_align_of
@@ -606,6 +607,8 @@ pub fn check_intrinsic_type(
606607

607608
sym::ub_checks => (0, 0, Vec::new(), tcx.types.bool),
608609

610+
sym::box_new => (1, 0, vec![param(0)], Ty::new_box(tcx, param(0))),
611+
609612
sym::simd_eq
610613
| sym::simd_ne
611614
| sym::simd_lt

compiler/rustc_mir_build/src/errors.rs

-19
Original file line numberDiff line numberDiff line change
@@ -1067,25 +1067,6 @@ pub(crate) enum MiscPatternSuggestion {
10671067
},
10681068
}
10691069

1070-
#[derive(Diagnostic)]
1071-
#[diag(mir_build_rustc_box_attribute_error)]
1072-
pub(crate) struct RustcBoxAttributeError {
1073-
#[primary_span]
1074-
pub(crate) span: Span,
1075-
#[subdiagnostic]
1076-
pub(crate) reason: RustcBoxAttrReason,
1077-
}
1078-
1079-
#[derive(Subdiagnostic)]
1080-
pub(crate) enum RustcBoxAttrReason {
1081-
#[note(mir_build_attributes)]
1082-
Attributes,
1083-
#[note(mir_build_not_box)]
1084-
NotBoxNew,
1085-
#[note(mir_build_missing_box)]
1086-
MissingBox,
1087-
}
1088-
10891070
#[derive(LintDiagnostic)]
10901071
#[diag(mir_build_rust_2024_incompatible_pat)]
10911072
pub(crate) struct Rust2024IncompatiblePat<'a> {

compiler/rustc_mir_build/src/thir/cx/expr.rs

+18-39
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ use rustc_middle::{bug, span_bug};
2020
use rustc_span::{Span, sym};
2121
use tracing::{debug, info, instrument, trace};
2222

23-
use crate::errors;
2423
use crate::thir::cx::Cx;
2524
use crate::thir::util::UserAnnotatedTyHelpers;
2625

@@ -380,45 +379,25 @@ impl<'tcx> Cx<'tcx> {
380379
from_hir_call: true,
381380
fn_span: expr.span,
382381
}
383-
} else {
384-
let attrs = tcx.hir().attrs(expr.hir_id);
385-
if attrs.iter().any(|a| a.name_or_empty() == sym::rustc_box) {
386-
if attrs.len() != 1 {
387-
tcx.dcx().emit_err(errors::RustcBoxAttributeError {
388-
span: attrs[0].span,
389-
reason: errors::RustcBoxAttrReason::Attributes,
390-
});
391-
} else if let Some(box_item) = tcx.lang_items().owned_box() {
392-
if let hir::ExprKind::Path(hir::QPath::TypeRelative(ty, fn_path)) =
393-
fun.kind
394-
&& let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind
395-
&& path.res.opt_def_id().is_some_and(|did| did == box_item)
396-
&& fn_path.ident.name == sym::new
397-
&& let [value] = args
398-
{
399-
return Expr {
400-
temp_lifetime: TempLifetime {
401-
temp_lifetime,
402-
backwards_incompatible,
403-
},
404-
ty: expr_ty,
405-
span: expr.span,
406-
kind: ExprKind::Box { value: self.mirror_expr(value) },
407-
};
408-
} else {
409-
tcx.dcx().emit_err(errors::RustcBoxAttributeError {
410-
span: expr.span,
411-
reason: errors::RustcBoxAttrReason::NotBoxNew,
412-
});
413-
}
414-
} else {
415-
tcx.dcx().emit_err(errors::RustcBoxAttributeError {
416-
span: attrs[0].span,
417-
reason: errors::RustcBoxAttrReason::MissingBox,
418-
});
419-
}
382+
} else if let ty::FnDef(def_id, _) = self.typeck_results().expr_ty(fun).kind()
383+
&& let Some(intrinsic) = self.tcx.intrinsic(def_id)
384+
&& intrinsic.name == sym::box_new
385+
{
386+
// We don't actually evaluate `fun` here, so make sure that doesn't miss any side-effects.
387+
if !matches!(fun.kind, hir::ExprKind::Path(_)) {
388+
span_bug!(
389+
expr.span,
390+
"`box_new` intrinsic can only be called via path expression"
391+
);
420392
}
421-
393+
let value = &args[0];
394+
return Expr {
395+
temp_lifetime: TempLifetime { temp_lifetime, backwards_incompatible },
396+
ty: expr_ty,
397+
span: expr.span,
398+
kind: ExprKind::Box { value: self.mirror_expr(value) },
399+
};
400+
} else {
422401
// Tuple-like ADTs are represented as ExprKind::Call. We convert them here.
423402
let adt_data = if let hir::ExprKind::Path(ref qpath) = fun.kind
424403
&& let Some(adt_def) = expr_ty.ty_adt_def()

compiler/rustc_span/src/symbol.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1696,7 +1696,6 @@ symbols! {
16961696
rustc_as_ptr,
16971697
rustc_attrs,
16981698
rustc_autodiff,
1699-
rustc_box,
17001699
rustc_builtin_macro,
17011700
rustc_capture_analysis,
17021701
rustc_clean,

library/alloc/src/alloc.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ unsafe impl Allocator for Global {
339339
}
340340
}
341341

342-
/// The allocator for unique pointers.
342+
/// The allocator for `Box`.
343343
#[cfg(all(not(no_global_oom_handling), not(test)))]
344344
#[lang = "exchange_malloc"]
345345
#[inline]

library/alloc/src/boxed.rs

+21-2
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,26 @@ pub struct Box<
233233
#[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
234234
>(Unique<T>, A);
235235

236+
/// Magic intrinsic to synthesize a `box <expr>` expression.
237+
/// Ends up calling the `exchange_malloc` lang item and then moves the argument
238+
/// into the newly allocated memory.
239+
#[cfg(not(bootstrap))]
240+
#[rustc_intrinsic]
241+
#[rustc_intrinsic_must_be_overridden]
242+
#[unstable(feature = "liballoc_internals", issue = "none")]
243+
pub fn box_new<T>(_x: T) -> Box<T> {
244+
unreachable!()
245+
}
246+
247+
/// Transition function for the next bootstrap bump.
248+
#[cfg(bootstrap)]
249+
#[unstable(feature = "liballoc_internals", issue = "none")]
250+
#[inline(always)]
251+
pub fn box_new<T>(x: T) -> Box<T> {
252+
#[rustc_box]
253+
Box::new(x)
254+
}
255+
236256
impl<T> Box<T> {
237257
/// Allocates memory on the heap and then places `x` into it.
238258
///
@@ -250,8 +270,7 @@ impl<T> Box<T> {
250270
#[rustc_diagnostic_item = "box_new"]
251271
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
252272
pub fn new(x: T) -> Self {
253-
#[rustc_box]
254-
Box::new(x)
273+
return box_new(x);
255274
}
256275

257276
/// Constructs a new box with uninitialized contents.

library/alloc/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@
180180
#![feature(staged_api)]
181181
#![feature(stmt_expr_attributes)]
182182
#![feature(strict_provenance_lints)]
183+
#![feature(intrinsics)]
183184
#![feature(unboxed_closures)]
184185
#![feature(unsized_fn_params)]
185186
#![feature(with_negative_coherence)]

library/alloc/src/macros.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,9 @@ macro_rules! vec {
4848
);
4949
($($x:expr),+ $(,)?) => (
5050
<[_]>::into_vec(
51-
// This rustc_box is not required, but it produces a dramatic improvement in compile
51+
// Using the intrinsic produces a dramatic improvement in compile
5252
// time when constructing arrays with many elements.
53-
#[rustc_box]
54-
$crate::boxed::Box::new([$($x),+])
53+
$crate::boxed::box_new([$($x),+])
5554
)
5655
);
5756
}

tests/ui/attributes/rustc-box.rs

-18
This file was deleted.

tests/ui/attributes/rustc-box.stderr

-34
This file was deleted.

tests/ui/unpretty/box.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
//@ compile-flags: -Zunpretty=hir
1+
//@ compile-flags: -Zunpretty=thir-tree
22
//@ check-pass
33

4-
#![feature(stmt_expr_attributes, rustc_attrs)]
4+
#![feature(liballoc_internals)]
55

66
fn main() {
7-
let _ = #[rustc_box]
8-
Box::new(1);
7+
let _ = std::boxed::box_new(1);
98
}

tests/ui/unpretty/box.stdout

+88-12
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,90 @@
1-
//@ compile-flags: -Zunpretty=hir
2-
//@ check-pass
1+
DefId(0:3 ~ box[efb9]::main):
2+
params: [
3+
]
4+
body:
5+
Expr {
6+
ty: ()
7+
temp_lifetime: TempLifetime { temp_lifetime: Some(Node(11)), backwards_incompatible: None }
8+
span: $DIR/box.rs:6:11: 8:2 (#0)
9+
kind:
10+
Scope {
11+
region_scope: Node(11)
12+
lint_level: Explicit(HirId(DefId(0:3 ~ box[efb9]::main).11))
13+
value:
14+
Expr {
15+
ty: ()
16+
temp_lifetime: TempLifetime { temp_lifetime: Some(Node(11)), backwards_incompatible: None }
17+
span: $DIR/box.rs:6:11: 8:2 (#0)
18+
kind:
19+
Block {
20+
targeted_by_break: false
21+
span: $DIR/box.rs:6:11: 8:2 (#0)
22+
region_scope: Node(1)
23+
safety_mode: Safe
24+
stmts: [
25+
Stmt {
26+
kind: Let {
27+
remainder_scope: Remainder { block: 1, first_statement_index: 0}
28+
init_scope: Node(2)
29+
pattern:
30+
Pat: {
31+
ty: std::boxed::Box<i32, std::alloc::Global>
32+
span: $DIR/box.rs:7:9: 7:10 (#0)
33+
kind: PatKind {
34+
Wild
35+
}
36+
}
37+
,
38+
initializer: Some(
39+
Expr {
40+
ty: std::boxed::Box<i32, std::alloc::Global>
41+
temp_lifetime: TempLifetime { temp_lifetime: Some(Node(2)), backwards_incompatible: None }
42+
span: $DIR/box.rs:7:13: 7:35 (#0)
43+
kind:
44+
Scope {
45+
region_scope: Node(3)
46+
lint_level: Explicit(HirId(DefId(0:3 ~ box[efb9]::main).3))
47+
value:
48+
Expr {
49+
ty: std::boxed::Box<i32, std::alloc::Global>
50+
temp_lifetime: TempLifetime { temp_lifetime: Some(Node(2)), backwards_incompatible: None }
51+
span: $DIR/box.rs:7:13: 7:35 (#0)
52+
kind:
53+
Box {
54+
Expr {
55+
ty: i32
56+
temp_lifetime: TempLifetime { temp_lifetime: Some(Node(2)), backwards_incompatible: None }
57+
span: $DIR/box.rs:7:33: 7:34 (#0)
58+
kind:
59+
Scope {
60+
region_scope: Node(8)
61+
lint_level: Explicit(HirId(DefId(0:3 ~ box[efb9]::main).8))
62+
value:
63+
Expr {
64+
ty: i32
65+
temp_lifetime: TempLifetime { temp_lifetime: Some(Node(2)), backwards_incompatible: None }
66+
span: $DIR/box.rs:7:33: 7:34 (#0)
67+
kind:
68+
Literal( lit: Spanned { node: Int(Pu128(1), Unsuffixed), span: $DIR/box.rs:7:33: 7:34 (#0) }, neg: false)
69+
70+
}
71+
}
72+
}
73+
}
74+
}
75+
}
76+
}
77+
)
78+
else_block: None
79+
lint_level: Explicit(HirId(DefId(0:3 ~ box[efb9]::main).9))
80+
span: $DIR/box.rs:7:5: 7:35 (#0)
81+
}
82+
}
83+
]
84+
expr: []
85+
}
86+
}
87+
}
88+
}
389

4-
#![feature(stmt_expr_attributes, rustc_attrs)]
5-
#[prelude_import]
6-
use ::std::prelude::rust_2015::*;
7-
#[macro_use]
8-
extern crate std;
990

10-
fn main() {
11-
let _ =
12-
#[rustc_box]
13-
Box::new(1);
14-
}

0 commit comments

Comments
 (0)