Skip to content
Closed
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
24 changes: 22 additions & 2 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1583,6 +1583,8 @@ impl Expr {
| ExprKind::Loop(..)
| ExprKind::MacCall(..)
| ExprKind::Match(..)
| ExprKind::Perform(..)
| ExprKind::Handle(..)
| ExprKind::MethodCall(..)
| ExprKind::OffsetOf(..)
| ExprKind::Paren(..)
Expand Down Expand Up @@ -1767,6 +1769,10 @@ pub enum ExprKind {
Loop(Box<Block>, Option<Label>, Span),
/// A `match` block.
Match(Box<Expr>, ThinVec<Arm>, MatchKind),
/// A `perform` expression (`perform op(args)`).
Perform(Box<Expr>, Span),
/// A `handle` expression (`handle expr with { pat => expr, ... }`).
Handle(Box<Expr>, ThinVec<Arm>, Span),
/// A closure (e.g., `move |a, b, c| a + b + c`).
Closure(Box<Closure>),
/// A block (`'label: { ... }`).
Expand Down Expand Up @@ -3544,6 +3550,7 @@ impl Item {
| ItemKind::Union(_, generics, _) => Some(&generics),
ItemKind::Trait(i) => Some(&i.generics),
ItemKind::Impl(i) => Some(&i.generics),
ItemKind::Effect(i) => Some(&i.generics),
}
}
}
Expand Down Expand Up @@ -3758,7 +3765,13 @@ pub struct ConstItem {
pub define_opaque: Option<ThinVec<(NodeId, Path)>>,
}

// Adding a new variant? Please update `test_item` in `tests/ui/macros/stringify.rs`.
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Effect {
pub ident: Ident,
pub generics: Generics,
pub operations: ThinVec<Box<FnSig>>,
}

#[derive(Clone, Encodable, Decodable, Debug)]
pub enum ItemKind {
/// An `extern crate` item, with the optional *original* crate name if the crate was renamed.
Expand Down Expand Up @@ -3817,6 +3830,10 @@ pub enum ItemKind {
///
/// E.g., `trait Foo = Bar + Quux;`.
TraitAlias(Ident, Generics, GenericBounds),
/// An effect declaration (`effect`).
///
/// E.g., `effect E { fn op() -> (); }`.
Effect(Box<Effect>),
/// An implementation.
///
/// E.g., `impl<A> Foo<A> { .. }` or `impl<A> Trait for Foo<A> { .. }`.
Expand Down Expand Up @@ -3850,6 +3867,7 @@ impl ItemKind {
| ItemKind::Union(ident, ..)
| ItemKind::Trait(box Trait { ident, .. })
| ItemKind::TraitAlias(ident, ..)
| ItemKind::Effect(box Effect { ident, .. })
| ItemKind::MacroDef(ident, _)
| ItemKind::Delegation(box Delegation { ident, .. }) => Some(ident),

Expand All @@ -3867,7 +3885,7 @@ impl ItemKind {
use ItemKind::*;
match self {
Use(..) | Static(..) | Const(..) | Fn(..) | Mod(..) | GlobalAsm(..) | TyAlias(..)
| Struct(..) | Union(..) | Trait(..) | TraitAlias(..) | MacroDef(..)
| Struct(..) | Union(..) | Trait(..) | TraitAlias(..) | Effect(..) | MacroDef(..)
| Delegation(..) | DelegationMac(..) => "a",
ExternCrate(..) | ForeignMod(..) | MacCall(..) | Enum(..) | Impl { .. } => "an",
}
Expand All @@ -3889,6 +3907,7 @@ impl ItemKind {
ItemKind::Union(..) => "union",
ItemKind::Trait(..) => "trait",
ItemKind::TraitAlias(..) => "trait alias",
ItemKind::Effect(..) => "effect",
ItemKind::MacCall(..) => "item macro invocation",
ItemKind::MacroDef(..) => "macro definition",
ItemKind::Impl { .. } => "implementation",
Expand All @@ -3907,6 +3926,7 @@ impl ItemKind {
| Self::Union(_, generics, _)
| Self::Trait(box Trait { generics, .. })
| Self::TraitAlias(_, generics, _)
| Self::Effect(box Effect { generics, .. })
| Self::Impl(Impl { generics, .. }) => Some(generics),
_ => None,
}
Expand Down
20 changes: 20 additions & 0 deletions compiler/rustc_ast/src/mut_visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,26 @@ macro_rules! define_named_walk {
};
}

impl<V: MutVisitor> MutVisitable<V> for FnSig {
type Extra = ();
fn visit_mut(&mut self, visitor: &mut V, _extra: Self::Extra) {
self.header.visit_mut(visitor, ());
self.decl.visit_mut(visitor, ());
// span ignored
}
}

impl<V: MutVisitor> MutVisitable<V> for Effect {
type Extra = ();
fn visit_mut(&mut self, visitor: &mut V, _extra: Self::Extra) {
self.ident.visit_mut(visitor, ());
self.generics.visit_mut(visitor, ());
for op in &mut self.operations {
op.visit_mut(visitor, ());
}
}
}

super::common_visitor_and_walkers!((mut) MutVisitor);

macro_rules! generate_flat_map_visitor_fns {
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_ast/src/util/classify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ pub fn leading_labeled_expr(mut expr: &ast::Expr) -> bool {
| Field(e, _)
| Index(e, _, _)
| Match(e, _, MatchKind::Postfix)
| Perform(e, _)
| Handle(e, _, _)
| Range(Some(e), _, _)
| Try(e) => {
expr = e;
Expand Down Expand Up @@ -179,6 +181,8 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<TrailingBrace<'_>> {
| Binary(_, _, e)
| Break(_, Some(e))
| Let(_, e, _, _)
| Perform(e, _)
| Handle(e, _, _)
| Range(_, Some(e), _)
| Ret(Some(e))
| Unary(_, e)
Expand Down
36 changes: 36 additions & 0 deletions compiler/rustc_ast/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -839,6 +839,8 @@ macro_rules! common_visitor_and_walkers {
visit_visitable!($($mut)? vis, ident, generics);
visit_visitable_with!($($mut)? vis, bounds, BoundKind::Bound)
}
ItemKind::Effect(effect) =>
visit_visitable!($($mut)? vis, effect),
ItemKind::MacCall(m) =>
visit_visitable!($($mut)? vis, m),
ItemKind::MacroDef(ident, def) =>
Expand Down Expand Up @@ -1051,13 +1053,27 @@ macro_rules! common_visitor_and_walkers {
visit_visitable!($($mut)? vis, bytes),
ExprKind::UnsafeBinderCast(kind, expr, ty) =>
visit_visitable!($($mut)? vis, kind, expr, ty),
ExprKind::Perform(expr, span) =>
visit_visitable!($($mut)? vis, expr, span),
ExprKind::Handle(expr, arms, span) =>
visit_visitable!($($mut)? vis, expr, arms, span),
ExprKind::Err(_guar) => {}
ExprKind::Dummy => {}
}

visit_span(vis, span)
});

impl_walkable!(|&$($mut)? $($lt)? self: Effect, vis: &mut V| {
let Effect { ident, generics, operations } = self;
try_visit!(vis.visit_ident(ident));
try_visit!(vis.visit_generics(generics));
for op in operations {
visit_visitable!($($mut)? vis, op);
}
V::Result::output()
});

define_named_walk!($(($mut))? $Visitor$(<$lt>)?
pub fn walk_anon_const(AnonConst);
pub fn walk_arm(Arm);
Expand Down Expand Up @@ -1114,6 +1130,26 @@ macro_rules! common_visitor_and_walkers {
};
}

impl<'a, V: Visitor<'a>> Visitable<'a, V> for FnSig {
type Extra = ();
fn visit(&'a self, visitor: &mut V, _extra: Self::Extra) -> V::Result {
try_visit!(self.header.visit(visitor, ()));
try_visit!(self.decl.visit(visitor, ()));
// span ignored
V::Result::output()
}
}

impl<'a, V: Visitor<'a>> Visitable<'a, V> for Effect {
type Extra = ();
fn visit(&'a self, visitor: &mut V, _extra: Self::Extra) -> V::Result {
try_visit!(self.ident.visit(visitor, ()));
try_visit!(self.generics.visit(visitor, ()));
// operations ignored
V::Result::output()
}
}

common_visitor_and_walkers!(Visitor<'a>);

macro_rules! generate_list_visit_fns {
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
}

ExprKind::MacCall(_) => panic!("{:?} shouldn't exist here", e.span),

ExprKind::Perform(_, _) => todo!("Perform expression lowering"),
ExprKind::Handle(_, _, _) => todo!("Handle expression lowering"),
};

hir::Expr { hir_id: expr_hir_id, kind, span: self.lower_span(e.span) }
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
ItemKind::MacCall(..) | ItemKind::DelegationMac(..) => {
panic!("macros should have been expanded by now")
}

ItemKind::Effect(_) => todo!("Effect item lowering"),
}
}

Expand Down
19 changes: 19 additions & 0 deletions compiler/rustc_ast_pretty/src/pprust/state/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -843,6 +843,25 @@ impl<'a> State<'a> {
self.end(ib);
self.pclose();
}
ast::ExprKind::Perform(expr, _) => {
self.word_nbsp("perform");
self.print_expr(expr, fixup.rightmost_subexpression());
}
ast::ExprKind::Handle(expr, arms, _) => {
let cb = self.cbox(0);
let ib = self.ibox(0);
self.word_nbsp("handle");
self.print_expr_as_cond(expr);
self.space();
self.word_nbsp("with");
self.bopen(ib);
self.print_inner_attributes_no_trailing_hardbreak(attrs);
for arm in arms {
self.print_arm(arm);
}
let empty = attrs.is_empty() && arms.is_empty();
self.bclose(expr.span, empty, cb);
}
ast::ExprKind::Err(_) => {
self.popen();
self.word("/*ERROR*/");
Expand Down
16 changes: 16 additions & 0 deletions compiler/rustc_ast_pretty/src/pprust/state/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,22 @@ impl<'a> State<'a> {
deleg.suffixes.as_ref().map_or(DelegationKind::Glob, |s| DelegationKind::List(s)),
&deleg.body,
),
ast::ItemKind::Effect(effect) => {
let (cb, ib) = self.head(visibility_qualified(&item.vis, "effect"));
self.print_ident(effect.ident);
self.print_generic_params(&effect.generics.params);
self.print_where_clause(&effect.generics.where_clause);
self.space();
self.bopen(ib);
self.print_inner_attributes(&item.attrs);
for sig in &effect.operations {
self.hardbreak_if_not_bol();
self.print_fn(&sig.decl, sig.header, None, &ast::Generics::default());
self.word(";");
}
let empty = item.attrs.is_empty() && effect.operations.is_empty();
self.bclose(item.span, empty, cb);
}
}
self.ann.post(self, AnnNode::Item(item))
}
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_builtin_macros/src/assert/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,9 @@ impl<'cx, 'a> Context<'cx, 'a> {
| ExprKind::Yeet(_)
| ExprKind::Become(_)
| ExprKind::Yield(_)
| ExprKind::UnsafeBinderCast(..) => {}
| ExprKind::UnsafeBinderCast(..)
| ExprKind::Perform(_, _)
| ExprKind::Handle(_, _, _) => {}
}
}

Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_hir/src/target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ pub enum Target {
Union,
Trait,
TraitAlias,
Effect,
Impl { of_trait: bool },
Expression,
Statement,
Expand Down Expand Up @@ -102,6 +103,7 @@ impl Target {
| Target::Union
| Target::Trait
| Target::TraitAlias
| Target::Effect
| Target::Impl { .. }
| Target::Expression
| Target::Statement
Expand Down Expand Up @@ -181,6 +183,7 @@ impl Target {
ast::ItemKind::Union(..) => Target::Union,
ast::ItemKind::Trait(..) => Target::Trait,
ast::ItemKind::TraitAlias(..) => Target::TraitAlias,
ast::ItemKind::Effect(..) => Target::Effect,
ast::ItemKind::Impl(ref i) => Target::Impl { of_trait: i.of_trait.is_some() },
ast::ItemKind::MacCall(..) => Target::MacroCall,
ast::ItemKind::MacroDef(..) => Target::MacroDef,
Expand Down Expand Up @@ -282,6 +285,7 @@ impl Target {
Target::Union => "union",
Target::Trait => "trait",
Target::TraitAlias => "trait alias",
Target::Effect => "effect",
Target::Impl { .. } => "implementation block",
Target::Expression => "expression",
Target::Statement => "statement",
Expand Down Expand Up @@ -332,6 +336,7 @@ impl Target {
Target::Union => "unions",
Target::Trait => "traits",
Target::TraitAlias => "trait aliases",
Target::Effect => "effects",
Target::Impl { of_trait: false } => "inherent impl blocks",
Target::Impl { of_trait: true } => "trait impl blocks",
Target::Expression => "expressions",
Expand Down
50 changes: 49 additions & 1 deletion compiler/rustc_parse/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1535,6 +1535,52 @@ impl<'a> Parser<'a> {
this.parse_expr_let(restrictions)
} else if this.eat_keyword(exp!(Underscore)) {
Ok(this.mk_expr(this.prev_token.span, ExprKind::Underscore))
} else if this.eat_keyword(exp!(Perform)) {
let lo = this.prev_token.span;
let expr = this.parse_expr()?;
let span = lo.to(expr.span);
Ok(this.mk_expr(span, ExprKind::Perform(expr, span)))
} else if this.eat_keyword(exp!(Handle)) {
let lo = this.prev_token.span;
let expr = this.parse_expr()?;
this.expect_keyword(exp!(With))?;
this.expect(exp!(OpenBrace))?;
let attrs = this.parse_inner_attributes()?;
let mut arms = ThinVec::new();
while this.token != token::CloseBrace {
match this.parse_arm() {
Ok(arm) => arms.push(arm),
Err(e) => {
// Recover by skipping to the end of the block.
let guar = e.emit();
this.recover_stmt();
let span = lo.to(this.token.span);
if this.token == token::CloseBrace {
this.bump();
}
// Always push at least one arm to make the handle non-empty
arms.push(Arm {
attrs: Default::default(),
pat: this.mk_pat(span, ast::PatKind::Err(guar)),
guard: None,
body: Some(this.mk_expr_err(span, guar)),
span,
id: DUMMY_NODE_ID,
is_placeholder: false,
});
let span = lo.to(this.prev_token.span);
return Ok(this.mk_expr_with_attrs(
span,
ExprKind::Handle(expr, arms, span),
attrs,
));
}
}
}
let hi = this.token.span;
this.bump();
let span = lo.to(hi);
Ok(this.mk_expr_with_attrs(span, ExprKind::Handle(expr, arms, span), attrs))
} else if this.token_uninterpolated_span().at_least_rust_2018() {
// `Span::at_least_rust_2018()` is somewhat expensive; don't get it repeatedly.
let at_async = this.check_keyword(exp!(Async));
Expand Down Expand Up @@ -4185,7 +4231,9 @@ impl MutVisitor for CondChecker<'_> {
| ExprKind::Call(_, _)
| ExprKind::MethodCall(_)
| ExprKind::Tup(_)
| ExprKind::Paren(_) => {
| ExprKind::Paren(_)
| ExprKind::Perform(_, _)
| ExprKind::Handle(_, _, _) => {
let forbid_let_reason = self.forbid_let_reason;
self.forbid_let_reason = Some(OtherForbidden);
mut_visit::walk_expr(self, e);
Expand Down
Loading
Loading