Skip to content

Commit

Permalink
redo frontend work
Browse files Browse the repository at this point in the history
This commit is a port of the changes done by @semtexzv, as described
in this comment:
rust-lang/rfcs#1888 (comment)

All locations that need further work are marked with:
FIXME(explicit_tail_calls)
  • Loading branch information
phi-go committed Apr 19, 2023
1 parent e49122f commit a632bad
Show file tree
Hide file tree
Showing 47 changed files with 248 additions and 7 deletions.
3 changes: 3 additions & 0 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1270,6 +1270,7 @@ impl Expr {
ExprKind::Break(..) => ExprPrecedence::Break,
ExprKind::Continue(..) => ExprPrecedence::Continue,
ExprKind::Ret(..) => ExprPrecedence::Ret,
ExprKind::Become(..) => ExprPrecedence::Ret,
ExprKind::InlineAsm(..) => ExprPrecedence::InlineAsm,
ExprKind::MacCall(..) => ExprPrecedence::Mac,
ExprKind::Struct(..) => ExprPrecedence::Struct,
Expand Down Expand Up @@ -1465,6 +1466,8 @@ pub enum ExprKind {
Continue(Option<Label>),
/// A `return`, with an optional value to be returned.
Ret(Option<P<Expr>>),
/// A `become`, with the required value to be returned.
Become(P<Expr>),

/// Output of the `asm!()` macro.
InlineAsm(P<InlineAsm>),
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_ast/src/mut_visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1451,6 +1451,9 @@ pub fn noop_visit_expr<T: MutVisitor>(
ExprKind::Ret(expr) => {
visit_opt(expr, |expr| vis.visit_expr(expr));
}
ExprKind::Become(expr) => {
vis.visit_expr(expr);
}
ExprKind::Yeet(expr) => {
visit_opt(expr, |expr| vis.visit_expr(expr));
}
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 @@ -902,6 +902,9 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
ExprKind::Ret(optional_expression) => {
walk_list!(visitor, visit_expr, optional_expression);
}
ExprKind::Become(expression) => {
visitor.visit_expr(expression);
}
ExprKind::Yeet(optional_expression) => {
walk_list!(visitor, visit_expr, optional_expression);
}
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
let e = e.as_ref().map(|x| self.lower_expr(x));
hir::ExprKind::Ret(e)
}
ExprKind::Become(e) => {
let e = self.lower_expr(e);
hir::ExprKind::Become(e)
}
ExprKind::Yeet(sub_expr) => self.lower_expr_yeet(e.span, sub_expr.as_deref()),
ExprKind::InlineAsm(asm) => {
hir::ExprKind::InlineAsm(self.lower_inline_asm(e.span, asm))
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_ast_passes/src/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,10 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
gate_all!(inline_const_pat, "inline-const in pattern position is experimental");
gate_all!(associated_const_equality, "associated const equality is incomplete");
gate_all!(yeet_expr, "`do yeet` expression is experimental");
gate_all!(
explicit_tail_calls,
"explicit tails calls using the `become` keyword is experimental"
);
gate_all!(dyn_star, "`dyn*` trait objects are experimental");
gate_all!(const_closures, "const closures are experimental");

Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_ast_pretty/src/pprust/state/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,11 @@ impl<'a> State<'a> {
self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
}
}
ast::ExprKind::Become(expr) => {
self.word("become");
self.word(" ");
self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
}
ast::ExprKind::Yeet(result) => {
self.word("do");
self.word(" ");
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 @@ -308,6 +308,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
| ExprKind::Match(_, _)
| ExprKind::Path(_, _)
| ExprKind::Ret(_)
| ExprKind::Become(_)
| ExprKind::Try(_)
| ExprKind::TryBlock(_)
| ExprKind::Type(_, _)
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/active.rs
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,8 @@ declare_features! (
(active, exclusive_range_pattern, "1.11.0", Some(37854), None),
/// Allows exhaustive pattern matching on types that contain uninhabited types.
(active, exhaustive_patterns, "1.13.0", Some(51085), None),
/// Allows guaranteeing tail call elimination using the `become` keyword.
(active, explicit_tail_calls, "1.70.0", Some(66666), None), // FIXME(explicit_tail_calls)
/// Allows using `efiapi`, `sysv64` and `win64` as calling convention
/// for functions with varargs.
(active, extended_varargs_abi_support, "1.65.0", Some(100189), None),
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1714,6 +1714,7 @@ impl Expr<'_> {
ExprKind::Break(..) => ExprPrecedence::Break,
ExprKind::Continue(..) => ExprPrecedence::Continue,
ExprKind::Ret(..) => ExprPrecedence::Ret,
ExprKind::Become(..) => ExprPrecedence::Ret,
ExprKind::InlineAsm(..) => ExprPrecedence::InlineAsm,
ExprKind::Struct(..) => ExprPrecedence::Struct,
ExprKind::Repeat(..) => ExprPrecedence::Repeat,
Expand Down Expand Up @@ -1770,6 +1771,7 @@ impl Expr<'_> {
| ExprKind::Break(..)
| ExprKind::Continue(..)
| ExprKind::Ret(..)
| ExprKind::Become(..)
| ExprKind::Let(..)
| ExprKind::Loop(..)
| ExprKind::Assign(..)
Expand Down Expand Up @@ -1859,6 +1861,7 @@ impl Expr<'_> {
| ExprKind::Break(..)
| ExprKind::Continue(..)
| ExprKind::Ret(..)
| ExprKind::Become(..)
| ExprKind::Let(..)
| ExprKind::Loop(..)
| ExprKind::Assign(..)
Expand Down Expand Up @@ -2018,6 +2021,8 @@ pub enum ExprKind<'hir> {
Continue(Destination),
/// A `return`, with an optional value to be returned.
Ret(Option<&'hir Expr<'hir>>),
/// A `become`, with a value to be returned.
Become(&'hir Expr<'hir>),

/// Inline assembly (from `asm!`), with its outputs and inputs.
InlineAsm(&'hir InlineAsm<'hir>),
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_hir/src/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,9 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
ExprKind::Ret(ref optional_expression) => {
walk_list!(visitor, visit_expr, optional_expression);
}
ExprKind::Become(ref expression) => {
visitor.visit_expr(expression);
}
ExprKind::InlineAsm(ref asm) => {
visitor.visit_inline_asm(asm, expression.hir_id);
}
Expand Down
12 changes: 9 additions & 3 deletions compiler/rustc_hir_pretty/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1080,9 +1080,10 @@ impl<'a> State<'a> {
// parses as the erroneous construct `if (return {})`, not `if (return) {}`.
fn cond_needs_par(expr: &hir::Expr<'_>) -> bool {
match expr.kind {
hir::ExprKind::Break(..) | hir::ExprKind::Closure { .. } | hir::ExprKind::Ret(..) => {
true
}
hir::ExprKind::Break(..)
| hir::ExprKind::Closure { .. }
| hir::ExprKind::Ret(..)
| hir::ExprKind::Become(..) => true,
_ => contains_exterior_struct_lit(expr),
}
}
Expand Down Expand Up @@ -1547,6 +1548,11 @@ impl<'a> State<'a> {
self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
}
}
hir::ExprKind::Become(expr) => {
self.word("become");
self.word(" ");
self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
}
hir::ExprKind::InlineAsm(asm) => {
self.word("asm!");
self.print_inline_asm(asm);
Expand Down
24 changes: 24 additions & 0 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
ExprKind::Ret(ref expr_opt) => self.check_expr_return(expr_opt.as_deref(), expr),
ExprKind::Become(ref become_expr) => self.check_expr_become(become_expr, expr),
ExprKind::Let(let_expr) => self.check_expr_let(let_expr),
ExprKind::Loop(body, _, source, _) => {
self.check_expr_loop(body, source, expected, expr)
Expand Down Expand Up @@ -811,6 +812,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.tcx.types.never
}

fn check_expr_become(
&self,
_expr: &'tcx hir::Expr<'tcx>,
_base_expr: &'tcx hir::Expr<'tcx>,
) -> Ty<'tcx> {
bug!("become is not supported yet"); // FIXME(explicit_tail_calls)
// // FIXME: Checks
// // 1: That the the expr is a func call
// // 2: That the calling context is a function, not a closure
// // 3: That the function arguments & ret type match

// match &expr.kind {
// hir::ExprKind::Call(..) => {}
// _ => {
// let mut err = self.tcx.sess.struct_span_err(expr.span, "become must always call a function");
// err.span_label(expr.span, "this is not a function call");
// err.emit();
// }
// }
// // Defer other type checking to return. might not be totally correct, but it'll work for now
// self.check_expr_return(Some(expr), _base_expr)
}

/// `explicit_return` is `true` if we're checking an explicit `return expr`,
/// and `false` if we're checking a trailing expression.
pub(super) fn check_return_expr(
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_hir_typeck/src/expr_use_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,10 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
}
}

hir::ExprKind::Become(ref expr) => {
self.consume_expr(expr);
}

hir::ExprKind::Assign(lhs, rhs, _) => {
self.mutate_expr(lhs);
self.consume_expr(rhs);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ impl<'a, 'tcx> DropRangeVisitor<'a, 'tcx> {
| ExprKind::Break(..)
| ExprKind::Continue(..)
| ExprKind::Ret(..)
| ExprKind::Become(..)
| ExprKind::InlineAsm(..)
| ExprKind::Struct(..)
| ExprKind::Repeat(..)
Expand Down Expand Up @@ -490,6 +491,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DropRangeVisitor<'a, 'tcx> {
| ExprKind::Path(..)
| ExprKind::Repeat(..)
| ExprKind::Ret(..)
| ExprKind::Become(..)
| ExprKind::Struct(..)
| ExprKind::Tup(..)
| ExprKind::Type(..)
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir_typeck/src/mem_categorization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
| hir::ExprKind::AssignOp(..)
| hir::ExprKind::Closure { .. }
| hir::ExprKind::Ret(..)
| hir::ExprKind::Become(..)
| hir::ExprKind::Unary(..)
| hir::ExprKind::Yield(..)
| hir::ExprKind::MethodCall(..)
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_middle/src/thir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,10 @@ pub enum ExprKind<'tcx> {
Return {
value: Option<ExprId>,
},
/// A `become` expression.
Become {
value: ExprId,
},
/// An inline `const` block, e.g. `const {}`.
ConstBlock {
did: DefId,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/thir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp
visitor.visit_expr(&visitor.thir()[value])
}
}
Become { value } => visitor.visit_expr(&visitor.thir()[value]),
ConstBlock { did: _, substs: _ } => {}
Repeat { value, count: _ } => {
visitor.visit_expr(&visitor.thir()[value]);
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_mir_build/src/build/expr/as_place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
| ExprKind::Break { .. }
| ExprKind::Continue { .. }
| ExprKind::Return { .. }
| ExprKind::Become { .. }
| ExprKind::Literal { .. }
| ExprKind::NamedConst { .. }
| ExprKind::NonHirLiteral { .. }
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
| ExprKind::Break { .. }
| ExprKind::Continue { .. }
| ExprKind::Return { .. }
| ExprKind::Become { .. }
| ExprKind::InlineAsm { .. }
| ExprKind::PlaceTypeAscription { .. }
| ExprKind::ValueTypeAscription { .. } => {
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_mir_build/src/build/expr/category.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ impl Category {
| ExprKind::Block { .. }
| ExprKind::Break { .. }
| ExprKind::Continue { .. }
| ExprKind::Return { .. } =>
| ExprKind::Return { .. }
| ExprKind::Become { .. } =>
// FIXME(#27840) these probably want their own
// category, like "nonterminating"
{
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_mir_build/src/build/expr/into.rs
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
block.unit()
}

ExprKind::Become { .. } => {
bug!("expr_into_dest not yet implemented for `become`."); // FIXME(explicit_tail_calls)
}

// Avoid creating a temporary
ExprKind::VarRef { .. }
| ExprKind::UpvarRef { .. }
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_mir_build/src/check_unsafety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
| ExprKind::Closure { .. }
| ExprKind::Continue { .. }
| ExprKind::Return { .. }
| ExprKind::Become { .. }
| ExprKind::Yield { .. }
| ExprKind::Loop { .. }
| ExprKind::Let { .. }
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_mir_build/src/thir/cx/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,7 @@ impl<'tcx> Cx<'tcx> {
ExprKind::Repeat { value: self.mirror_expr(v), count: *count }
}
hir::ExprKind::Ret(ref v) => ExprKind::Return { value: v.map(|v| self.mirror_expr(v)) },
hir::ExprKind::Become(v) => ExprKind::Become { value: self.mirror_expr(v) },
hir::ExprKind::Break(dest, ref value) => match dest.target_id {
Ok(target_id) => ExprKind::Break {
label: region::Scope { id: target_id.local_id, data: region::ScopeData::Node },
Expand Down
9 changes: 9 additions & 0 deletions compiler/rustc_mir_build/src/thir/print.rs
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,15 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {

print_indented!(self, "}", depth_lvl);
}
Become { .. } => {
bug!("print_expr: `Become` is not implemented yet."); // FIXME(explicit_tail_calls)
// print_indented!(self, "Become {", depth_lvl);
// print_indented!(self, "value:", depth_lvl + 1);

// self.print_expr(*value, depth_lvl + 2);

// print_indented!(self, "}", depth_lvl);
}
ConstBlock { did, substs } => {
print_indented!(self, "ConstBlock {", depth_lvl);
print_indented!(self, format!("did: {:?}", did), depth_lvl + 1);
Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_parse/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1400,6 +1400,9 @@ impl<'a> Parser<'a> {
self.parse_try_block(lo)
} else if self.eat_keyword(kw::Return) {
self.parse_expr_return()
} else if self.eat_keyword(kw::Become) {
self.sess.gated_spans.gate(sym::explicit_tail_calls, self.prev_token.span);
self.parse_expr_become()
} else if self.eat_keyword(kw::Continue) {
self.parse_expr_continue(lo)
} else if self.eat_keyword(kw::Break) {
Expand Down Expand Up @@ -1699,6 +1702,14 @@ impl<'a> Parser<'a> {
self.maybe_recover_from_bad_qpath(expr)
}

/// Parse `"become" expr?`.
fn parse_expr_become(&mut self) -> PResult<'a, P<Expr>> {
let lo = self.prev_token.span;
let kind = ExprKind::Become(self.parse_expr()?);
let expr = self.mk_expr(lo.to(self.prev_token.span), kind);
self.maybe_recover_from_bad_qpath(expr)
}

/// Parse `"do" "yeet" expr?`.
fn parse_expr_yeet(&mut self) -> PResult<'a, P<Expr>> {
let lo = self.token.span;
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_passes/src/hir_stats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
[
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, InlineAsm, Struct, Repeat, Yield, Err
Path, AddrOf, Break, Continue, Ret, Become, InlineAsm, Struct, Repeat, Yield, Err
]
);
hir_visit::walk_expr(self, e)
Expand Down Expand Up @@ -567,7 +567,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
[
Array, ConstBlock, Call, MethodCall, Tup, Binary, Unary, Lit, Cast, Type, Let,
If, While, ForLoop, Loop, Match, Closure, Block, Async, Await, TryBlock, Assign,
AssignOp, Field, Index, Range, Underscore, Path, AddrOf, Break, Continue, Ret,
AssignOp, Field, Index, Range, Underscore, Path, AddrOf, Break, Continue, Ret, Become,
InlineAsm, FormatArgs, MacCall, Struct, Repeat, Paren, Try, Yield, Yeet, IncludedBytes, Err
]
);
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_passes/src/liveness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,7 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
| hir::ExprKind::Lit(_)
| hir::ExprKind::ConstBlock(..)
| hir::ExprKind::Ret(..)
| hir::ExprKind::Become(..)
| hir::ExprKind::Block(..)
| hir::ExprKind::Assign(..)
| hir::ExprKind::AssignOp(..)
Expand Down Expand Up @@ -965,6 +966,11 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
self.propagate_through_opt_expr(o_e.as_deref(), self.exit_ln)
}

hir::ExprKind::Become(ref expr) => {
// Ignore succ and subst exit_ln.
self.propagate_through_expr(expr, self.exit_ln)
}

hir::ExprKind::Break(label, ref opt_expr) => {
// Find which label this break jumps to
let target = match label.target_id {
Expand Down Expand Up @@ -1412,6 +1418,7 @@ fn check_expr<'tcx>(this: &mut Liveness<'_, 'tcx>, expr: &'tcx Expr<'tcx>) {
| hir::ExprKind::DropTemps(..)
| hir::ExprKind::Unary(..)
| hir::ExprKind::Ret(..)
| hir::ExprKind::Become(..)
| hir::ExprKind::Break(..)
| hir::ExprKind::Continue(..)
| hir::ExprKind::Lit(_)
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_passes/src/naked_functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ impl<'tcx> CheckInlineAssembly<'tcx> {
| ExprKind::Break(..)
| ExprKind::Continue(..)
| ExprKind::Ret(..)
| ExprKind::Become(..)
| ExprKind::Struct(..)
| ExprKind::Repeat(..)
| ExprKind::Yield(..) => {
Expand Down
Loading

0 comments on commit a632bad

Please sign in to comment.