Skip to content

Commit 99e5ad9

Browse files
Add unwrap_unsafe_binder and wrap_unsafe_binder macro operators
1 parent 25a754c commit 99e5ad9

File tree

32 files changed

+338
-20
lines changed

32 files changed

+338
-20
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1328,6 +1328,7 @@ impl Expr {
13281328
| ExprKind::Type(..)
13291329
| ExprKind::OffsetOf(..)
13301330
| ExprKind::FormatArgs(..)
1331+
| ExprKind::UnsafeBinderCast(..)
13311332
| ExprKind::MacCall(..) => ExprPrecedence::Mac,
13321333
ExprKind::Err(_) | ExprKind::Dummy => ExprPrecedence::Err,
13331334
}
@@ -1454,7 +1455,13 @@ pub enum ExprKind {
14541455
/// `'label: for await? pat in iter { block }`
14551456
///
14561457
/// This is desugared to a combination of `loop` and `match` expressions.
1457-
ForLoop { pat: P<Pat>, iter: P<Expr>, body: P<Block>, label: Option<Label>, kind: ForLoopKind },
1458+
ForLoop {
1459+
pat: P<Pat>,
1460+
iter: P<Expr>,
1461+
body: P<Block>,
1462+
label: Option<Label>,
1463+
kind: ForLoopKind,
1464+
},
14581465
/// Conditionless loop (can be exited with `break`, `continue`, or `return`).
14591466
///
14601467
/// `'label: loop { block }`
@@ -1559,6 +1566,8 @@ pub enum ExprKind {
15591566
/// A `format_args!()` expression.
15601567
FormatArgs(P<FormatArgs>),
15611568

1569+
UnsafeBinderCast(UnsafeBinderCastKind, P<Expr>, Option<P<Ty>>),
1570+
15621571
/// Placeholder for an expression that wasn't syntactically well formed in some way.
15631572
Err(ErrorGuaranteed),
15641573

@@ -1597,6 +1606,16 @@ impl GenBlockKind {
15971606
}
15981607
}
15991608

1609+
/// Whether we're unwrapping or wrapping an unsafe binder
1610+
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1611+
#[derive(Encodable, Decodable, HashStable_Generic)]
1612+
pub enum UnsafeBinderCastKind {
1613+
// e.g. `&i32` -> `unsafe<'a> &'a i32`
1614+
Wrap,
1615+
// e.g. `unsafe<'a> &'a i32` -> `&i32`
1616+
Unwrap,
1617+
}
1618+
16001619
/// The explicit `Self` type in a "qualified path". The actual
16011620
/// path, including the trait and the associated item, is stored
16021621
/// separately. `position` represents the index of the associated

compiler/rustc_ast/src/mut_visit.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1620,6 +1620,12 @@ pub fn walk_expr<T: MutVisitor>(vis: &mut T, Expr { kind, id, span, attrs, token
16201620
ExprKind::TryBlock(body) => vis.visit_block(body),
16211621
ExprKind::Lit(_token) => {}
16221622
ExprKind::IncludedBytes(_bytes) => {}
1623+
ExprKind::UnsafeBinderCast(_kind, expr, ty) => {
1624+
vis.visit_expr(expr);
1625+
if let Some(ty) = ty {
1626+
vis.visit_ty(ty);
1627+
}
1628+
}
16231629
ExprKind::Err(_guar) => {}
16241630
ExprKind::Dummy => {}
16251631
}

compiler/rustc_ast/src/util/classify.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ pub fn leading_labeled_expr(mut expr: &ast::Expr) -> bool {
152152
| Underscore
153153
| Yeet(..)
154154
| Yield(..)
155+
| UnsafeBinderCast(..)
155156
| Err(..)
156157
| Dummy => return false,
157158
}
@@ -232,6 +233,7 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<TrailingBrace<'_>> {
232233
| Paren(_)
233234
| Try(_)
234235
| Yeet(None)
236+
| UnsafeBinderCast(..)
235237
| Err(_)
236238
| Dummy => break None,
237239
}

compiler/rustc_ast/src/visit.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,6 +1187,10 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V
11871187
ExprKind::TryBlock(body) => try_visit!(visitor.visit_block(body)),
11881188
ExprKind::Lit(_token) => {}
11891189
ExprKind::IncludedBytes(_bytes) => {}
1190+
ExprKind::UnsafeBinderCast(_kind, expr, ty) => {
1191+
try_visit!(visitor.visit_expr(expr));
1192+
visit_opt!(visitor, visit_ty, ty);
1193+
}
11901194
ExprKind::Err(_guar) => {}
11911195
ExprKind::Dummy => {}
11921196
}

compiler/rustc_ast_lowering/src/expr.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
339339
ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()),
340340
ExprKind::Err(guar) => hir::ExprKind::Err(*guar),
341341

342+
ExprKind::UnsafeBinderCast(kind, expr, ty) => hir::ExprKind::UnsafeBinderCast(
343+
*kind,
344+
self.lower_expr(expr),
345+
ty.as_ref().map(|ty| {
346+
self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Cast))
347+
}),
348+
),
349+
342350
ExprKind::Dummy => {
343351
span_bug!(e.span, "lowered ExprKind::Dummy")
344352
}

compiler/rustc_ast_pretty/src/pprust/state/expr.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,25 @@ impl<'a> State<'a> {
726726
self.word_nbsp("try");
727727
self.print_block_with_attrs(blk, attrs)
728728
}
729+
ast::ExprKind::UnsafeBinderCast(kind, expr, ty) => {
730+
self.word("builtin # ");
731+
match kind {
732+
ast::UnsafeBinderCastKind::Wrap => self.word("wrap_unsafe_binder"),
733+
ast::UnsafeBinderCastKind::Unwrap => self.word("unwrap_unsafe_binder"),
734+
}
735+
self.popen();
736+
self.ibox(0);
737+
self.print_expr(expr, FixupContext::default());
738+
739+
if let Some(ty) = ty {
740+
self.word(",");
741+
self.space();
742+
self.print_type(ty);
743+
}
744+
745+
self.end();
746+
self.pclose();
747+
}
729748
ast::ExprKind::Err(_) => {
730749
self.popen();
731750
self.word("/*ERROR*/");

compiler/rustc_builtin_macros/src/assert/context.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,8 @@ impl<'cx, 'a> Context<'cx, 'a> {
323323
| ExprKind::While(_, _, _)
324324
| ExprKind::Yeet(_)
325325
| ExprKind::Become(_)
326-
| ExprKind::Yield(_) => {}
326+
| ExprKind::Yield(_)
327+
| ExprKind::UnsafeBinderCast(..) => {}
327328
}
328329
}
329330

compiler/rustc_hir/src/hir.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_ast::{
88
};
99
pub use rustc_ast::{
1010
BinOp, BinOpKind, BindingMode, BorrowKind, ByRef, CaptureBy, ImplPolarity, IsAuto, Movability,
11-
Mutability, UnOp,
11+
Mutability, UnOp, UnsafeBinderCastKind,
1212
};
1313
use rustc_data_structures::fingerprint::Fingerprint;
1414
use rustc_data_structures::sorted_map::SortedMap;
@@ -1747,9 +1747,10 @@ impl Expr<'_> {
17471747
ExprKind::Struct(..) => ExprPrecedence::Struct,
17481748
ExprKind::Repeat(..) => ExprPrecedence::Repeat,
17491749
ExprKind::Yield(..) => ExprPrecedence::Yield,
1750-
ExprKind::Type(..) | ExprKind::InlineAsm(..) | ExprKind::OffsetOf(..) => {
1751-
ExprPrecedence::Mac
1752-
}
1750+
ExprKind::Type(..)
1751+
| ExprKind::InlineAsm(..)
1752+
| ExprKind::OffsetOf(..)
1753+
| ExprKind::UnsafeBinderCast(..) => ExprPrecedence::Mac,
17531754
ExprKind::Err(_) => ExprPrecedence::Err,
17541755
}
17551756
}
@@ -1777,6 +1778,9 @@ impl Expr<'_> {
17771778
// https://github.com/rust-lang/rfcs/blob/master/text/0803-type-ascription.md#type-ascription-and-temporaries
17781779
ExprKind::Type(ref e, _) => e.is_place_expr(allow_projections_from),
17791780

1781+
// Unsafe binder cast preserves place-ness of the sub-expression.
1782+
ExprKind::UnsafeBinderCast(_, e, _) => e.is_place_expr(allow_projections_from),
1783+
17801784
ExprKind::Unary(UnOp::Deref, _) => true,
17811785

17821786
ExprKind::Field(ref base, _) | ExprKind::Index(ref base, _, _) => {
@@ -1858,7 +1862,8 @@ impl Expr<'_> {
18581862
| ExprKind::Field(base, _)
18591863
| ExprKind::Index(base, _, _)
18601864
| ExprKind::AddrOf(.., base)
1861-
| ExprKind::Cast(base, _) => {
1865+
| ExprKind::Cast(base, _)
1866+
| ExprKind::UnsafeBinderCast(_, base, _) => {
18621867
// This isn't exactly true for `Index` and all `Unary`, but we are using this
18631868
// method exclusively for diagnostics and there's a *cultural* pressure against
18641869
// them being used only for its side-effects.
@@ -2115,6 +2120,10 @@ pub enum ExprKind<'hir> {
21152120
/// A suspension point for coroutines (i.e., `yield <expr>`).
21162121
Yield(&'hir Expr<'hir>, YieldSource),
21172122

2123+
/// Operators which can be used to interconvert `unsafe` binder types.
2124+
/// e.g. `unsafe<'a> &'a i32` <=> `&i32`.
2125+
UnsafeBinderCast(UnsafeBinderCastKind, &'hir Expr<'hir>, Option<&'hir Ty<'hir>>),
2126+
21182127
/// A placeholder for an expression that wasn't syntactically well formed in some way.
21192128
Err(rustc_span::ErrorGuaranteed),
21202129
}

compiler/rustc_hir/src/intravisit.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -862,6 +862,10 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
862862
ExprKind::Yield(ref subexpression, _) => {
863863
try_visit!(visitor.visit_expr(subexpression));
864864
}
865+
ExprKind::UnsafeBinderCast(_kind, expr, ty) => {
866+
try_visit!(visitor.visit_expr(expr));
867+
visit_opt!(visitor, visit_ty, ty);
868+
}
865869
ExprKind::Lit(_) | ExprKind::Err(_) => {}
866870
}
867871
V::Result::output()

compiler/rustc_hir_pretty/src/lib.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1537,6 +1537,19 @@ impl<'a> State<'a> {
15371537

15381538
self.word(")");
15391539
}
1540+
hir::ExprKind::UnsafeBinderCast(kind, expr, ty) => {
1541+
match kind {
1542+
hir::UnsafeBinderCastKind::Wrap => self.word("wrap_unsafe_binder!("),
1543+
hir::UnsafeBinderCastKind::Unwrap => self.word("unwrap_unsafe_binder!("),
1544+
}
1545+
self.print_expr(expr);
1546+
if let Some(ty) = ty {
1547+
self.word(",");
1548+
self.space();
1549+
self.print_type(ty);
1550+
}
1551+
self.word(")");
1552+
}
15401553
hir::ExprKind::Yield(expr, _) => {
15411554
self.word_space("yield");
15421555
self.print_expr_maybe_paren(expr, parser::PREC_JUMP);

0 commit comments

Comments
 (0)