Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1621,6 +1621,7 @@ impl Expr {
| ExprKind::While(..)
| ExprKind::Yield(YieldKind::Postfix(..))
| ExprKind::DirectConstArg(..)
| ExprKind::Rescope(..)
| ExprKind::Err(_)
| ExprKind::Dummy => prefix_attrs_precedence(&self.attrs),
}
Expand Down Expand Up @@ -1920,6 +1921,9 @@ pub enum ExprKind {
/// An mGCA `direct_const_arg!()` expression.
DirectConstArg(Box<Expr>),

/// `scope!('l => e)` or `extend!('l => e)`.
Rescope(RescopeKind, Label, Box<Expr>),

/// Placeholder for an expression that wasn't syntactically well formed in some way.
Err(ErrorGuaranteed),

Expand Down Expand Up @@ -1968,6 +1972,13 @@ pub enum UnsafeBinderCastKind {
Unwrap,
}

/// Differentiates between the re-scoping constructs `scope!` and `extend!`
#[derive(Clone, Copy, Encodable, Decodable, Debug, PartialEq, Eq, StableHash, Walkable)]
pub enum RescopeKind {
Scope,
Extend,
}

/// The explicit `Self` type in a "qualified path".
///
/// The actual path, including the trait and the associated item, is stored
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_ast/src/util/classify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ pub fn leading_labeled_expr(mut expr: &ast::Expr) -> bool {
| Yield(..)
| UnsafeBinderCast(..)
| DirectConstArg(..)
| Rescope(..)
| Err(..)
| Dummy => return false,
}
Expand Down Expand Up @@ -245,6 +246,7 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<TrailingBrace<'_>> {
| Yeet(None)
| UnsafeBinderCast(..)
| DirectConstArg(..)
| Rescope(..)
| Err(_)
| Dummy => {
break None;
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_ast/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,7 @@ macro_rules! common_visitor_and_walkers {
RangeEnd,
RangeSyntax,
Recovered,
RescopeKind,
RestrictionKind,
Safety,
StaticItem,
Expand Down Expand Up @@ -1074,6 +1075,8 @@ macro_rules! common_visitor_and_walkers {
visit_visitable!($($mut)? vis, kind, expr, ty),
ExprKind::DirectConstArg(expr) =>
visit_visitable!($($mut)? vis, expr),
ExprKind::Rescope(kind, label, expr) =>
visit_visitable!($($mut)? vis, kind, label, expr),
ExprKind::Err(_guar) => {}
ExprKind::Dummy => {}
}
Expand Down
27 changes: 18 additions & 9 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
}),
),

ExprKind::Rescope(kind, label, expr) => {
if let Some(target_id) = self.label_target_id(e.id) {
let target = hir::RescopeTarget { label: *label, target_id };
hir::ExprKind::Rescope(*kind, target, self.lower_expr(expr))
} else {
// FIXME(super_let): we could recover here to at least do type-checking
let guar = self.dcx().span_err(label.ident.span, "label not found");
hir::ExprKind::Err(guar)
}
}

ExprKind::Dummy => {
span_bug!(e.span, "lowered ExprKind::Dummy")
}
Expand Down Expand Up @@ -1549,17 +1560,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
Some(Label { ident: self.lower_ident(label.ident) })
}

fn label_target_id(&mut self, source: NodeId) -> Option<HirId> {
let target_id = self.owner.get_label_res(source)?;
let local_id = self.ident_and_label_to_local_id[&target_id];
Some(HirId { owner: self.current_hir_id_owner, local_id })
}

fn lower_loop_destination(&mut self, destination: Option<(NodeId, Label)>) -> hir::Destination {
let target_id = match destination {
Some((id, _)) => {
if let Some(loop_id) = self.owner.get_label_res(id) {
let local_id = self.ident_and_label_to_local_id[&loop_id];
let loop_hir_id = HirId { owner: self.current_hir_id_owner, local_id };
Ok(loop_hir_id)
} else {
Err(hir::LoopIdError::UnresolvedLabel)
}
}
Some((id, _)) => self.label_target_id(id).ok_or(hir::LoopIdError::UnresolvedLabel),
None => {
self.loop_scope.map(|id| Ok(id)).unwrap_or(Err(hir::LoopIdError::OutsideLoopScope))
}
Expand Down
18 changes: 18 additions & 0 deletions compiler/rustc_ast_pretty/src/pprust/state/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -873,6 +873,24 @@ impl<'a> State<'a> {
self.end(ib);
self.pclose();
}
ast::ExprKind::Rescope(kind, label, expr) => {
let mac_str = match kind {
ast::RescopeKind::Scope => "core::scope!",
ast::RescopeKind::Extend => "core::extend!",
};
self.word(mac_str);
self.popen();
let ib = self.ibox(0);

self.print_ident(label.ident);
self.nbsp();
self.word("=>");
self.space();
self.print_expr(expr, FixupContext::default());

self.end(ib);
self.pclose();
}
ast::ExprKind::Err(_) => {
self.popen();
self.word("/*ERROR*/");
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_builtin_macros/src/assert/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
| ExprKind::Become(_)
| ExprKind::Yield(_)
| ExprKind::DirectConstArg(_)
| ExprKind::Rescope(_, _, _)
| ExprKind::UnsafeBinderCast(..) => {}
}
}
Expand Down
23 changes: 17 additions & 6 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use rustc_ast::{
pub use rustc_ast::{
AssignOp, AssignOpKind, AttrId, AttrStyle, BinOp, BinOpKind, BindingMode, BorrowKind,
BoundConstness, BoundPolarity, ByRef, CaptureBy, DelimArgs, ImplPolarity, IsAuto,
MetaItemInner, MetaItemLit, Movability, Mutability, Pinnedness, UnOp,
MetaItemInner, MetaItemLit, Movability, Mutability, Pinnedness, RescopeKind, UnOp,
};
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::FxIndexSet;
Expand Down Expand Up @@ -2617,6 +2617,7 @@ impl Expr<'_> {
| ExprKind::OffsetOf(..)
| ExprKind::Path(..)
| ExprKind::Repeat(..)
| ExprKind::Rescope(..)
| ExprKind::Struct(..)
| ExprKind::Tup(_)
| ExprKind::Type(..)
Expand Down Expand Up @@ -2649,10 +2650,10 @@ impl Expr<'_> {
// Type ascription inherits its place expression kind from its
// operand. See:
// 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),
// The same applies to unsafe binder casts and re-scoping expressions.
ExprKind::Type(e, _)
| ExprKind::UnsafeBinderCast(_, e, _)
| ExprKind::Rescope(_, _, e) => e.is_place_expr(allow_projections_from),

ExprKind::Unary(UnOp::Deref, _) => true,

Expand Down Expand Up @@ -2757,7 +2758,8 @@ impl Expr<'_> {
| ExprKind::Index(base, _, _)
| ExprKind::AddrOf(.., base)
| ExprKind::Cast(base, _)
| ExprKind::UnsafeBinderCast(_, base, _) => {
| ExprKind::UnsafeBinderCast(_, base, _)
| ExprKind::Rescope(_, _, 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.
Expand Down Expand Up @@ -3051,6 +3053,9 @@ pub enum ExprKind<'hir> {
/// e.g. `unsafe<'a> &'a i32` <=> `&i32`.
UnsafeBinderCast(UnsafeBinderCastKind, &'hir Expr<'hir>, Option<&'hir Ty<'hir>>),

/// `scope!('l => e)` or `extend!('l => e)`.
Rescope(RescopeKind, RescopeTarget, &'hir Expr<'hir>),

/// A placeholder for an expression that wasn't syntactically well formed in some way.
Err(rustc_span::ErrorGuaranteed),
}
Expand Down Expand Up @@ -3223,6 +3228,12 @@ pub struct Destination {
pub target_id: Result<HirId, LoopIdError>,
}

#[derive(Copy, Clone, Debug, PartialEq, StableHash)]
pub struct RescopeTarget {
pub label: Label,
pub target_id: HirId,
}

/// The yield kind that caused an `ExprKind::Yield`.
#[derive(Copy, Clone, Debug, StableHash)]
pub enum YieldSource {
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_hir/src/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -941,6 +941,10 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
visit_opt!(visitor, visit_ty_unambig, ty);
}
ExprKind::Lit(lit) => try_visit!(visitor.visit_lit(*hir_id, lit, false)),
ExprKind::Rescope(_kind, ref target, ref expr) => {
try_visit!(visitor.visit_label(&target.label));
try_visit!(visitor.visit_expr(expr));
}
ExprKind::Err(_) => {}
}
V::Result::output()
Expand Down
Loading
Loading