Add unwrap_unsafe_binder and wrap_unsafe_binder macro operators
This commit is contained in:
parent
2a9e358c72
commit
3f97c6be8d
25 changed files with 222 additions and 12 deletions
|
@ -1382,6 +1382,7 @@ impl Expr {
|
|||
| ExprKind::Tup(_)
|
||||
| ExprKind::Type(..)
|
||||
| ExprKind::Underscore
|
||||
| ExprKind::UnsafeBinderCast(..)
|
||||
| ExprKind::While(..)
|
||||
| ExprKind::Err(_)
|
||||
| ExprKind::Dummy => ExprPrecedence::Unambiguous,
|
||||
|
@ -1509,7 +1510,13 @@ pub enum ExprKind {
|
|||
/// `'label: for await? pat in iter { block }`
|
||||
///
|
||||
/// This is desugared to a combination of `loop` and `match` expressions.
|
||||
ForLoop { pat: P<Pat>, iter: P<Expr>, body: P<Block>, label: Option<Label>, kind: ForLoopKind },
|
||||
ForLoop {
|
||||
pat: P<Pat>,
|
||||
iter: P<Expr>,
|
||||
body: P<Block>,
|
||||
label: Option<Label>,
|
||||
kind: ForLoopKind,
|
||||
},
|
||||
/// Conditionless loop (can be exited with `break`, `continue`, or `return`).
|
||||
///
|
||||
/// `'label: loop { block }`
|
||||
|
@ -1614,6 +1621,8 @@ pub enum ExprKind {
|
|||
/// A `format_args!()` expression.
|
||||
FormatArgs(P<FormatArgs>),
|
||||
|
||||
UnsafeBinderCast(UnsafeBinderCastKind, P<Expr>, Option<P<Ty>>),
|
||||
|
||||
/// Placeholder for an expression that wasn't syntactically well formed in some way.
|
||||
Err(ErrorGuaranteed),
|
||||
|
||||
|
@ -1652,6 +1661,16 @@ impl GenBlockKind {
|
|||
}
|
||||
}
|
||||
|
||||
/// Whether we're unwrapping or wrapping an unsafe binder
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Encodable, Decodable, HashStable_Generic)]
|
||||
pub enum UnsafeBinderCastKind {
|
||||
// e.g. `&i32` -> `unsafe<'a> &'a i32`
|
||||
Wrap,
|
||||
// e.g. `unsafe<'a> &'a i32` -> `&i32`
|
||||
Unwrap,
|
||||
}
|
||||
|
||||
/// The explicit `Self` type in a "qualified path". The actual
|
||||
/// path, including the trait and the associated item, is stored
|
||||
/// separately. `position` represents the index of the associated
|
||||
|
|
|
@ -1780,6 +1780,12 @@ pub fn walk_expr<T: MutVisitor>(vis: &mut T, Expr { kind, id, span, attrs, token
|
|||
ExprKind::TryBlock(body) => vis.visit_block(body),
|
||||
ExprKind::Lit(_token) => {}
|
||||
ExprKind::IncludedBytes(_bytes) => {}
|
||||
ExprKind::UnsafeBinderCast(_kind, expr, ty) => {
|
||||
vis.visit_expr(expr);
|
||||
if let Some(ty) = ty {
|
||||
vis.visit_ty(ty);
|
||||
}
|
||||
}
|
||||
ExprKind::Err(_guar) => {}
|
||||
ExprKind::Dummy => {}
|
||||
}
|
||||
|
|
|
@ -152,6 +152,7 @@ pub fn leading_labeled_expr(mut expr: &ast::Expr) -> bool {
|
|||
| Underscore
|
||||
| Yeet(..)
|
||||
| Yield(..)
|
||||
| UnsafeBinderCast(..)
|
||||
| Err(..)
|
||||
| Dummy => return false,
|
||||
}
|
||||
|
@ -232,6 +233,7 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<TrailingBrace<'_>> {
|
|||
| Paren(_)
|
||||
| Try(_)
|
||||
| Yeet(None)
|
||||
| UnsafeBinderCast(..)
|
||||
| Err(_)
|
||||
| Dummy => break None,
|
||||
}
|
||||
|
|
|
@ -1230,6 +1230,10 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V
|
|||
ExprKind::TryBlock(body) => try_visit!(visitor.visit_block(body)),
|
||||
ExprKind::Lit(_token) => {}
|
||||
ExprKind::IncludedBytes(_bytes) => {}
|
||||
ExprKind::UnsafeBinderCast(_kind, expr, ty) => {
|
||||
try_visit!(visitor.visit_expr(expr));
|
||||
visit_opt!(visitor, visit_ty, ty);
|
||||
}
|
||||
ExprKind::Err(_guar) => {}
|
||||
ExprKind::Dummy => {}
|
||||
}
|
||||
|
|
|
@ -379,6 +379,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()),
|
||||
ExprKind::Err(guar) => hir::ExprKind::Err(*guar),
|
||||
|
||||
ExprKind::UnsafeBinderCast(kind, expr, ty) => hir::ExprKind::UnsafeBinderCast(
|
||||
*kind,
|
||||
self.lower_expr(expr),
|
||||
ty.as_ref().map(|ty| {
|
||||
self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Cast))
|
||||
}),
|
||||
),
|
||||
|
||||
ExprKind::Dummy => {
|
||||
span_bug!(e.span, "lowered ExprKind::Dummy")
|
||||
}
|
||||
|
|
|
@ -565,6 +565,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
|||
gate_all!(return_type_notation, "return type notation is experimental");
|
||||
gate_all!(pin_ergonomics, "pinned reference syntax is experimental");
|
||||
gate_all!(unsafe_fields, "`unsafe` fields are experimental");
|
||||
gate_all!(unsafe_binders, "unsafe binder types are experimental");
|
||||
|
||||
if !visitor.features.never_patterns() {
|
||||
if let Some(spans) = spans.get(&sym::never_patterns) {
|
||||
|
|
|
@ -772,6 +772,25 @@ impl<'a> State<'a> {
|
|||
self.word_nbsp("try");
|
||||
self.print_block_with_attrs(blk, attrs)
|
||||
}
|
||||
ast::ExprKind::UnsafeBinderCast(kind, expr, ty) => {
|
||||
self.word("builtin # ");
|
||||
match kind {
|
||||
ast::UnsafeBinderCastKind::Wrap => self.word("wrap_binder"),
|
||||
ast::UnsafeBinderCastKind::Unwrap => self.word("unwrap_binder"),
|
||||
}
|
||||
self.popen();
|
||||
self.ibox(0);
|
||||
self.print_expr(expr, FixupContext::default());
|
||||
|
||||
if let Some(ty) = ty {
|
||||
self.word(",");
|
||||
self.space();
|
||||
self.print_type(ty);
|
||||
}
|
||||
|
||||
self.end();
|
||||
self.pclose();
|
||||
}
|
||||
ast::ExprKind::Err(_) => {
|
||||
self.popen();
|
||||
self.word("/*ERROR*/");
|
||||
|
|
|
@ -323,7 +323,8 @@ impl<'cx, 'a> Context<'cx, 'a> {
|
|||
| ExprKind::While(_, _, _)
|
||||
| ExprKind::Yeet(_)
|
||||
| ExprKind::Become(_)
|
||||
| ExprKind::Yield(_) => {}
|
||||
| ExprKind::Yield(_)
|
||||
| ExprKind::UnsafeBinderCast(..) => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -635,6 +635,8 @@ declare_features! (
|
|||
/// Allows creation of instances of a struct by moving fields that have
|
||||
/// not changed from prior instances of the same struct (RFC #2528)
|
||||
(unstable, type_changing_struct_update, "1.58.0", Some(86555)),
|
||||
/// Allows using `unsafe<'a> &'a T` unsafe binder types.
|
||||
(incomplete, unsafe_binders, "CURRENT_RUSTC_VERSION", Some(130516)),
|
||||
/// Allows declaring fields `unsafe`.
|
||||
(incomplete, unsafe_fields, "CURRENT_RUSTC_VERSION", Some(132922)),
|
||||
/// Allows const generic parameters to be defined with types that
|
||||
|
|
|
@ -8,7 +8,7 @@ use rustc_ast::{
|
|||
};
|
||||
pub use rustc_ast::{
|
||||
BinOp, BinOpKind, BindingMode, BorrowKind, BoundConstness, BoundPolarity, ByRef, CaptureBy,
|
||||
ImplPolarity, IsAuto, Movability, Mutability, UnOp,
|
||||
ImplPolarity, IsAuto, Movability, Mutability, UnOp, UnsafeBinderCastKind,
|
||||
};
|
||||
use rustc_data_structures::fingerprint::Fingerprint;
|
||||
use rustc_data_structures::sorted_map::SortedMap;
|
||||
|
@ -1740,6 +1740,7 @@ impl Expr<'_> {
|
|||
| ExprKind::Struct(..)
|
||||
| ExprKind::Tup(_)
|
||||
| ExprKind::Type(..)
|
||||
| ExprKind::UnsafeBinderCast(..)
|
||||
| ExprKind::Err(_) => ExprPrecedence::Unambiguous,
|
||||
|
||||
ExprKind::DropTemps(ref expr, ..) => expr.precedence(),
|
||||
|
@ -1769,6 +1770,9 @@ impl Expr<'_> {
|
|||
// https://github.com/rust-lang/rfcs/blob/master/text/0803-type-ascription.md#type-ascription-and-temporaries
|
||||
ExprKind::Type(ref e, _) => e.is_place_expr(allow_projections_from),
|
||||
|
||||
// Unsafe binder cast preserves place-ness of the sub-expression.
|
||||
ExprKind::UnsafeBinderCast(_, e, _) => e.is_place_expr(allow_projections_from),
|
||||
|
||||
ExprKind::Unary(UnOp::Deref, _) => true,
|
||||
|
||||
ExprKind::Field(ref base, _) | ExprKind::Index(ref base, _, _) => {
|
||||
|
@ -1850,7 +1854,8 @@ impl Expr<'_> {
|
|||
| ExprKind::Field(base, _)
|
||||
| ExprKind::Index(base, _, _)
|
||||
| ExprKind::AddrOf(.., base)
|
||||
| ExprKind::Cast(base, _) => {
|
||||
| ExprKind::Cast(base, _)
|
||||
| ExprKind::UnsafeBinderCast(_, base, _) => {
|
||||
// This isn't exactly true for `Index` and all `Unary`, but we are using this
|
||||
// method exclusively for diagnostics and there's a *cultural* pressure against
|
||||
// them being used only for its side-effects.
|
||||
|
@ -2144,6 +2149,10 @@ pub enum ExprKind<'hir> {
|
|||
/// A suspension point for coroutines (i.e., `yield <expr>`).
|
||||
Yield(&'hir Expr<'hir>, YieldSource),
|
||||
|
||||
/// Operators which can be used to interconvert `unsafe` binder types.
|
||||
/// e.g. `unsafe<'a> &'a i32` <=> `&i32`.
|
||||
UnsafeBinderCast(UnsafeBinderCastKind, &'hir Expr<'hir>, Option<&'hir Ty<'hir>>),
|
||||
|
||||
/// A placeholder for an expression that wasn't syntactically well formed in some way.
|
||||
Err(rustc_span::ErrorGuaranteed),
|
||||
}
|
||||
|
|
|
@ -857,6 +857,10 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
|
|||
ExprKind::Yield(ref subexpression, _) => {
|
||||
try_visit!(visitor.visit_expr(subexpression));
|
||||
}
|
||||
ExprKind::UnsafeBinderCast(_kind, expr, ty) => {
|
||||
try_visit!(visitor.visit_expr(expr));
|
||||
visit_opt!(visitor, visit_ty, ty);
|
||||
}
|
||||
ExprKind::Lit(_) | ExprKind::Err(_) => {}
|
||||
}
|
||||
V::Result::output()
|
||||
|
|
|
@ -1542,6 +1542,19 @@ impl<'a> State<'a> {
|
|||
|
||||
self.word(")");
|
||||
}
|
||||
hir::ExprKind::UnsafeBinderCast(kind, expr, ty) => {
|
||||
match kind {
|
||||
hir::UnsafeBinderCastKind::Wrap => self.word("wrap_binder!("),
|
||||
hir::UnsafeBinderCastKind::Unwrap => self.word("unwrap_binder!("),
|
||||
}
|
||||
self.print_expr(expr);
|
||||
if let Some(ty) = ty {
|
||||
self.word(",");
|
||||
self.space();
|
||||
self.print_type(ty);
|
||||
}
|
||||
self.word(")");
|
||||
}
|
||||
hir::ExprKind::Yield(expr, _) => {
|
||||
self.word_space("yield");
|
||||
self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Jump);
|
||||
|
|
|
@ -329,6 +329,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// Assignment does call `drop_in_place`, though, but its safety
|
||||
// requirements are not the same.
|
||||
ExprKind::AddrOf(..) | hir::ExprKind::Field(..) => false,
|
||||
|
||||
// Place-preserving expressions only constitute reads if their
|
||||
// parent expression constitutes a read.
|
||||
ExprKind::Type(..) | ExprKind::UnsafeBinderCast(..) => {
|
||||
self.expr_guaranteed_to_constitute_read_for_never(expr)
|
||||
}
|
||||
|
||||
ExprKind::Assign(lhs, _, _) => {
|
||||
// Only the LHS does not constitute a read
|
||||
expr.hir_id != lhs.hir_id
|
||||
|
@ -353,7 +360,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
| ExprKind::Binary(_, _, _)
|
||||
| ExprKind::Unary(_, _)
|
||||
| ExprKind::Cast(_, _)
|
||||
| ExprKind::Type(_, _)
|
||||
| ExprKind::DropTemps(_)
|
||||
| ExprKind::If(_, _, _)
|
||||
| ExprKind::Closure(_)
|
||||
|
@ -564,7 +570,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
self.check_expr_index(base, idx, expr, brackets_span)
|
||||
}
|
||||
ExprKind::Yield(value, _) => self.check_expr_yield(value, expr),
|
||||
hir::ExprKind::Err(guar) => Ty::new_error(tcx, guar),
|
||||
ExprKind::UnsafeBinderCast(kind, expr, ty) => {
|
||||
self.check_expr_unsafe_binder_cast(kind, expr, ty, expected)
|
||||
}
|
||||
ExprKind::Err(guar) => Ty::new_error(tcx, guar),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1634,6 +1643,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_expr_unsafe_binder_cast(
|
||||
&self,
|
||||
_kind: hir::UnsafeBinderCastKind,
|
||||
expr: &'tcx hir::Expr<'tcx>,
|
||||
_hir_ty: Option<&'tcx hir::Ty<'tcx>>,
|
||||
_expected: Expectation<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
let guar =
|
||||
self.dcx().struct_span_err(expr.span, "unsafe binders are not yet implemented").emit();
|
||||
Ty::new_error(self.tcx, guar)
|
||||
}
|
||||
|
||||
fn check_expr_array(
|
||||
&self,
|
||||
args: &'tcx [hir::Expr<'tcx>],
|
||||
|
|
|
@ -341,6 +341,10 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
|||
self.walk_expr(subexpr)?;
|
||||
}
|
||||
|
||||
hir::ExprKind::UnsafeBinderCast(_, subexpr, _) => {
|
||||
self.walk_expr(subexpr)?;
|
||||
}
|
||||
|
||||
hir::ExprKind::Unary(hir::UnOp::Deref, base) => {
|
||||
// *base
|
||||
self.walk_expr(base)?;
|
||||
|
@ -1360,7 +1364,10 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
|||
self.cat_res(expr.hir_id, expr.span, expr_ty, res)
|
||||
}
|
||||
|
||||
// both type ascription and unsafe binder casts don't affect
|
||||
// the place-ness of the subexpression.
|
||||
hir::ExprKind::Type(e, _) => self.cat_expr(e),
|
||||
hir::ExprKind::UnsafeBinderCast(_, e, _) => self.cat_expr(e),
|
||||
|
||||
hir::ExprKind::AddrOf(..)
|
||||
| hir::ExprKind::Call(..)
|
||||
|
|
|
@ -192,6 +192,8 @@ fn is_temporary_rvalue(expr: &Expr<'_>) -> bool {
|
|||
| ExprKind::DropTemps(..)
|
||||
| ExprKind::Let(..) => false,
|
||||
|
||||
ExprKind::UnsafeBinderCast(..) => false,
|
||||
|
||||
// Not applicable
|
||||
ExprKind::Type(..) | ExprKind::Err(..) => false,
|
||||
}
|
||||
|
|
|
@ -422,6 +422,7 @@ impl<'tcx, 'a> Visitor<'tcx> for FindSignificantDropper<'tcx, 'a> {
|
|||
hir::ExprKind::Unary(_, expr)
|
||||
| hir::ExprKind::Cast(expr, _)
|
||||
| hir::ExprKind::Type(expr, _)
|
||||
| hir::ExprKind::UnsafeBinderCast(_, expr, _)
|
||||
| hir::ExprKind::Yield(expr, _)
|
||||
| hir::ExprKind::AddrOf(_, _, expr)
|
||||
| hir::ExprKind::Match(expr, _, _)
|
||||
|
|
|
@ -915,6 +915,11 @@ impl<'tcx> Cx<'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
hir::ExprKind::UnsafeBinderCast(_kind, _source, _ty) => {
|
||||
unreachable!("unsafe binders are not yet implemented")
|
||||
}
|
||||
|
||||
hir::ExprKind::DropTemps(source) => ExprKind::Use { source: self.mirror_expr(source) },
|
||||
hir::ExprKind::Array(fields) => ExprKind::Array { fields: self.mirror_exprs(fields) },
|
||||
hir::ExprKind::Tup(fields) => ExprKind::Tuple { fields: self.mirror_exprs(fields) },
|
||||
|
|
|
@ -15,7 +15,7 @@ use rustc_ast::visit::{Visitor, walk_expr};
|
|||
use rustc_ast::{
|
||||
self as ast, AnonConst, Arm, AttrStyle, AttrVec, BinOp, BinOpKind, BlockCheckMode, CaptureBy,
|
||||
ClosureBinder, DUMMY_NODE_ID, Expr, ExprField, ExprKind, FnDecl, FnRetTy, Label, MacCall,
|
||||
MetaItemLit, Movability, Param, RangeLimits, StmtKind, Ty, TyKind, UnOp,
|
||||
MetaItemLit, Movability, Param, RangeLimits, StmtKind, Ty, TyKind, UnOp, UnsafeBinderCastKind,
|
||||
};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
|
@ -1931,6 +1931,12 @@ impl<'a> Parser<'a> {
|
|||
Ok(match ident.name {
|
||||
sym::offset_of => Some(this.parse_expr_offset_of(lo)?),
|
||||
sym::type_ascribe => Some(this.parse_expr_type_ascribe(lo)?),
|
||||
sym::wrap_binder => {
|
||||
Some(this.parse_expr_unsafe_binder_cast(lo, UnsafeBinderCastKind::Wrap)?)
|
||||
}
|
||||
sym::unwrap_binder => {
|
||||
Some(this.parse_expr_unsafe_binder_cast(lo, UnsafeBinderCastKind::Unwrap)?)
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
})
|
||||
|
@ -2006,6 +2012,17 @@ impl<'a> Parser<'a> {
|
|||
Ok(self.mk_expr(span, ExprKind::Type(expr, ty)))
|
||||
}
|
||||
|
||||
pub(crate) fn parse_expr_unsafe_binder_cast(
|
||||
&mut self,
|
||||
lo: Span,
|
||||
kind: UnsafeBinderCastKind,
|
||||
) -> PResult<'a, P<Expr>> {
|
||||
let expr = self.parse_expr()?;
|
||||
let ty = if self.eat(&TokenKind::Comma) { Some(self.parse_ty()?) } else { None };
|
||||
let span = lo.to(self.token.span);
|
||||
Ok(self.mk_expr(span, ExprKind::UnsafeBinderCast(kind, expr, ty)))
|
||||
}
|
||||
|
||||
/// Returns a string literal if the next token is a string literal.
|
||||
/// In case of error returns `Some(lit)` if the next token is a literal with a wrong kind,
|
||||
/// and returns `None` if the next token is not literal at all.
|
||||
|
@ -4019,7 +4036,9 @@ impl MutVisitor for CondChecker<'_> {
|
|||
mut_visit::walk_expr(self, e);
|
||||
self.forbid_let_reason = forbid_let_reason;
|
||||
}
|
||||
ExprKind::Cast(ref mut op, _) | ExprKind::Type(ref mut op, _) => {
|
||||
ExprKind::Cast(ref mut op, _)
|
||||
| ExprKind::Type(ref mut op, _)
|
||||
| ExprKind::UnsafeBinderCast(_, ref mut op, _) => {
|
||||
let forbid_let_reason = self.forbid_let_reason;
|
||||
self.forbid_let_reason = Some(OtherForbidden);
|
||||
self.visit_expr(op);
|
||||
|
|
|
@ -315,9 +315,40 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
|
|||
|
||||
fn visit_expr(&mut self, e: &'v hir::Expr<'v>) {
|
||||
record_variants!((self, e, e.kind, Some(e.hir_id), hir, Expr, ExprKind), [
|
||||
ConstBlock, Array, Call, MethodCall, Tup, Binary, Unary, Lit, Cast, Type, DropTemps,
|
||||
Let, If, Loop, Match, Closure, Block, Assign, AssignOp, Field, Index, Path, AddrOf,
|
||||
Break, Continue, Ret, Become, InlineAsm, OffsetOf, Struct, Repeat, Yield, Err
|
||||
ConstBlock,
|
||||
Array,
|
||||
Call,
|
||||
MethodCall,
|
||||
Tup,
|
||||
Binary,
|
||||
Unary,
|
||||
Lit,
|
||||
Cast,
|
||||
Type,
|
||||
DropTemps,
|
||||
Let,
|
||||
If,
|
||||
Loop,
|
||||
Match,
|
||||
Closure,
|
||||
Block,
|
||||
Assign,
|
||||
AssignOp,
|
||||
Field,
|
||||
Index,
|
||||
Path,
|
||||
AddrOf,
|
||||
Break,
|
||||
Continue,
|
||||
Ret,
|
||||
Become,
|
||||
InlineAsm,
|
||||
OffsetOf,
|
||||
Struct,
|
||||
Repeat,
|
||||
Yield,
|
||||
UnsafeBinderCast,
|
||||
Err
|
||||
]);
|
||||
hir_visit::walk_expr(self, e)
|
||||
}
|
||||
|
@ -572,7 +603,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
|
|||
If, While, ForLoop, Loop, Match, Closure, Block, Await, TryBlock, Assign,
|
||||
AssignOp, Field, Index, Range, Underscore, Path, AddrOf, Break, Continue, Ret,
|
||||
InlineAsm, FormatArgs, OffsetOf, MacCall, Struct, Repeat, Paren, Try, Yield, Yeet,
|
||||
Become, IncludedBytes, Gen, Err, Dummy
|
||||
Become, IncludedBytes, Gen, UnsafeBinderCast, Err, Dummy
|
||||
]
|
||||
);
|
||||
ast_visit::walk_expr(self, e)
|
||||
|
|
|
@ -447,6 +447,7 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
|
|||
| hir::ExprKind::InlineAsm(..)
|
||||
| hir::ExprKind::OffsetOf(..)
|
||||
| hir::ExprKind::Type(..)
|
||||
| hir::ExprKind::UnsafeBinderCast(..)
|
||||
| hir::ExprKind::Err(_)
|
||||
| hir::ExprKind::Path(hir::QPath::TypeRelative(..))
|
||||
| hir::ExprKind::Path(hir::QPath::LangItem(..)) => {}
|
||||
|
@ -1051,6 +1052,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
|||
hir::ExprKind::AddrOf(_, _, ref e)
|
||||
| hir::ExprKind::Cast(ref e, _)
|
||||
| hir::ExprKind::Type(ref e, _)
|
||||
| hir::ExprKind::UnsafeBinderCast(_, ref e, _)
|
||||
| hir::ExprKind::DropTemps(ref e)
|
||||
| hir::ExprKind::Unary(_, ref e)
|
||||
| hir::ExprKind::Repeat(ref e, _) => self.propagate_through_expr(e, succ),
|
||||
|
@ -1443,6 +1445,7 @@ fn check_expr<'tcx>(this: &mut Liveness<'_, 'tcx>, expr: &'tcx Expr<'tcx>) {
|
|||
| hir::ExprKind::Path(_)
|
||||
| hir::ExprKind::Yield(..)
|
||||
| hir::ExprKind::Type(..)
|
||||
| hir::ExprKind::UnsafeBinderCast(..)
|
||||
| hir::ExprKind::Err(_) => {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -186,6 +186,7 @@ impl CheckInlineAssembly {
|
|||
| ExprKind::Lit(..)
|
||||
| ExprKind::Cast(..)
|
||||
| ExprKind::Type(..)
|
||||
| ExprKind::UnsafeBinderCast(..)
|
||||
| ExprKind::Loop(..)
|
||||
| ExprKind::Match(..)
|
||||
| ExprKind::If(..)
|
||||
|
|
|
@ -2104,6 +2104,7 @@ symbols! {
|
|||
unreachable_macro,
|
||||
unrestricted_attribute_tokens,
|
||||
unsafe_attributes,
|
||||
unsafe_binders,
|
||||
unsafe_block_in_unsafe_fn,
|
||||
unsafe_cell,
|
||||
unsafe_cell_raw_get,
|
||||
|
@ -2127,6 +2128,7 @@ symbols! {
|
|||
unwind_attributes,
|
||||
unwind_safe_trait,
|
||||
unwrap,
|
||||
unwrap_binder,
|
||||
unwrap_or,
|
||||
use_extern_macros,
|
||||
use_nested_groups,
|
||||
|
@ -2185,6 +2187,7 @@ symbols! {
|
|||
windows,
|
||||
windows_subsystem,
|
||||
with_negative_coherence,
|
||||
wrap_binder,
|
||||
wrapping_add,
|
||||
wrapping_div,
|
||||
wrapping_mul,
|
||||
|
|
|
@ -354,6 +354,8 @@ pub mod random;
|
|||
pub mod range;
|
||||
pub mod result;
|
||||
pub mod sync;
|
||||
#[unstable(feature = "unsafe_binders", issue = "130516")]
|
||||
pub mod unsafe_binder;
|
||||
|
||||
pub mod fmt;
|
||||
pub mod hash;
|
||||
|
|
25
library/core/src/unsafe_binder.rs
Normal file
25
library/core/src/unsafe_binder.rs
Normal file
|
@ -0,0 +1,25 @@
|
|||
//! Operators used to turn types into unsafe binders and back.
|
||||
|
||||
/// Unwrap an unsafe binder into its underlying type.
|
||||
#[allow_internal_unstable(builtin_syntax)]
|
||||
#[unstable(feature = "unsafe_binders", issue = "130516")]
|
||||
pub macro unwrap_binder {
|
||||
($expr:expr) => {
|
||||
builtin # unwrap_binder ( $expr )
|
||||
},
|
||||
($expr:expr ; $ty:ty) => {
|
||||
builtin # unwrap_binder ( $expr, $ty )
|
||||
},
|
||||
}
|
||||
|
||||
/// Wrap a type into an unsafe binder.
|
||||
#[allow_internal_unstable(builtin_syntax)]
|
||||
#[unstable(feature = "unsafe_binders", issue = "130516")]
|
||||
pub macro wrap_binder {
|
||||
($expr:expr) => {
|
||||
builtin # wrap_binder ( $expr )
|
||||
},
|
||||
($expr:expr ; $ty:ty) => {
|
||||
builtin # wrap_binder ( $expr, $ty )
|
||||
},
|
||||
}
|
|
@ -544,6 +544,8 @@ pub use core::u64;
|
|||
#[stable(feature = "i128", since = "1.26.0")]
|
||||
#[allow(deprecated, deprecated_in_future)]
|
||||
pub use core::u128;
|
||||
#[unstable(feature = "unsafe_binders", issue = "130516")]
|
||||
pub use core::unsafe_binder;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[allow(deprecated, deprecated_in_future)]
|
||||
pub use core::usize;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue