diff options
Diffstat (limited to 'compiler')
11 files changed, 146 insertions, 111 deletions
diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs index 1c507678489..b37b82dd089 100644 --- a/compiler/rustc_builtin_macros/src/deriving/clone.rs +++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs @@ -2,8 +2,7 @@ use crate::deriving::generic::ty::*; use crate::deriving::generic::*; use crate::deriving::path_std; -use rustc_ast::ptr::P; -use rustc_ast::{self as ast, Expr, Generics, ItemKind, MetaItem, VariantData}; +use rustc_ast::{self as ast, Generics, ItemKind, MetaItem, VariantData}; use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::Span; @@ -98,7 +97,7 @@ fn cs_clone_simple( trait_span: Span, substr: &Substructure<'_>, is_union: bool, -) -> P<Expr> { +) -> BlockOrExpr { let mut stmts = Vec::new(); let mut process_variant = |variant: &VariantData| { for field in variant.fields() { @@ -139,8 +138,7 @@ fn cs_clone_simple( ), } } - stmts.push(cx.stmt_expr(cx.expr_deref(trait_span, cx.expr_self(trait_span)))); - cx.expr_block(cx.block(trait_span, stmts)) + BlockOrExpr::new_mixed(stmts, cx.expr_deref(trait_span, cx.expr_self(trait_span))) } fn cs_clone( @@ -148,7 +146,7 @@ fn cs_clone( cx: &mut ExtCtxt<'_>, trait_span: Span, substr: &Substructure<'_>, -) -> P<Expr> { +) -> BlockOrExpr { let ctor_path; let all_fields; let fn_path = cx.std_path(&[sym::clone, sym::Clone, sym::clone]); @@ -177,7 +175,7 @@ fn cs_clone( } } - match *vdata { + let expr = match *vdata { VariantData::Struct(..) => { let fields = all_fields .iter() @@ -201,5 +199,6 @@ fn cs_clone( cx.expr_call(trait_span, path, subcalls) } VariantData::Unit(..) => cx.expr_path(ctor_path), - } + }; + BlockOrExpr::new_expr(expr) } diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs index cb2ad283a19..59f8fbc4a08 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs @@ -2,8 +2,7 @@ use crate::deriving::generic::ty::*; use crate::deriving::generic::*; use crate::deriving::path_std; -use rustc_ast::ptr::P; -use rustc_ast::{self as ast, Expr, MetaItem}; +use rustc_ast::{self as ast, MetaItem}; use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; @@ -52,7 +51,7 @@ fn cs_total_eq_assert( cx: &mut ExtCtxt<'_>, trait_span: Span, substr: &Substructure<'_>, -) -> P<Expr> { +) -> BlockOrExpr { let mut stmts = Vec::new(); let mut process_variant = |variant: &ast::VariantData| { for field in variant.fields() { @@ -78,5 +77,5 @@ fn cs_total_eq_assert( } _ => cx.span_bug(trait_span, "unexpected substructure in `derive(Eq)`"), } - cx.expr_block(cx.block(trait_span, stmts)) + BlockOrExpr::new_stmts(stmts) } diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs index c7850cd4b4c..4795b72a780 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs @@ -3,7 +3,7 @@ use crate::deriving::generic::*; use crate::deriving::path_std; use rustc_ast::ptr::P; -use rustc_ast::{self as ast, Expr, MetaItem}; +use rustc_ast::{self as ast, MetaItem}; use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; @@ -51,7 +51,7 @@ pub fn ordering_collapsed( cx.expr_call_global(span, fn_cmp_path, vec![lft, rgt]) } -pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P<Expr> { +pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr { let test_id = Ident::new(sym::cmp, span); let equals_path = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal])); @@ -70,7 +70,7 @@ pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P< // cmp => cmp // } // - cs_fold( + let expr = cs_fold( // foldr nests the if-elses correctly, leaving the first field // as the outermost one, and the last as the innermost. false, @@ -107,5 +107,6 @@ pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P< cx, span, substr, - ) + ); + BlockOrExpr::new_expr(expr) } diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs index ca5ca29eb82..f58e303b8f0 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs @@ -15,8 +15,6 @@ pub fn expand_deriving_partial_eq( item: &Annotatable, push: &mut dyn FnMut(Annotatable), ) { - // structures are equal if all fields are equal, and non equal, if - // any fields are not equal or if the enum variants are different fn cs_op( cx: &mut ExtCtxt<'_>, span: Span, @@ -24,7 +22,7 @@ pub fn expand_deriving_partial_eq( op: BinOpKind, combiner: BinOpKind, base: bool, - ) -> P<Expr> { + ) -> BlockOrExpr { let op = |cx: &mut ExtCtxt<'_>, span: Span, self_f: P<Expr>, other_fs: &[P<Expr>]| { let [other_f] = other_fs else { cx.span_bug(span, "not exactly 2 arguments in `derive(PartialEq)`"); @@ -33,7 +31,7 @@ pub fn expand_deriving_partial_eq( cx.expr_binary(span, op, self_f, other_f.clone()) }; - cs_fold1( + let expr = cs_fold1( true, // use foldl |cx, span, subexpr, self_f, other_fs| { let eq = op(cx, span, self_f, other_fs); @@ -52,13 +50,14 @@ pub fn expand_deriving_partial_eq( cx, span, substr, - ) + ); + BlockOrExpr::new_expr(expr) } - fn cs_eq(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P<Expr> { + fn cs_eq(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr { cs_op(cx, span, substr, BinOpKind::Eq, BinOpKind::And, true) } - fn cs_ne(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P<Expr> { + fn cs_ne(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr { cs_op(cx, span, substr, BinOpKind::Ne, BinOpKind::Or, false) } diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs index 07db82fee93..891485ab8ff 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs @@ -2,8 +2,7 @@ use crate::deriving::generic::ty::*; use crate::deriving::generic::*; use crate::deriving::{path_std, pathvec_std}; -use rustc_ast::ptr::P; -use rustc_ast::{Expr, MetaItem}; +use rustc_ast::MetaItem; use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; @@ -48,7 +47,7 @@ pub fn expand_deriving_partial_ord( trait_def.expand(cx, mitem, item, push) } -pub fn cs_partial_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P<Expr> { +pub fn cs_partial_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr { let test_id = Ident::new(sym::cmp, span); let ordering = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal])); let ordering_expr = cx.expr_path(ordering.clone()); @@ -69,7 +68,7 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_ // cmp => cmp // } // - cs_fold( + let expr = cs_fold( // foldr nests the if-elses correctly, leaving the first field // as the outermost one, and the last as the innermost. false, @@ -110,5 +109,6 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_ cx, span, substr, - ) + ); + BlockOrExpr::new_expr(expr) } diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index 1411c60c0bf..e0489828760 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -2,8 +2,7 @@ use crate::deriving::generic::ty::*; use crate::deriving::generic::*; use crate::deriving::path_std; -use rustc_ast::ptr::P; -use rustc_ast::{self as ast, Expr, MetaItem}; +use rustc_ast::{self as ast, MetaItem}; use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::Span; @@ -42,7 +41,7 @@ pub fn expand_deriving_debug( trait_def.expand(cx, mitem, item, push) } -fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P<Expr> { +fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr { let (ident, vdata, fields) = match substr.fields { Struct(vdata, fields) => (substr.type_ident, *vdata, fields), EnumMatching(_, _, v, fields) => (v.ident, &v.data, fields), @@ -74,7 +73,8 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_> if fields.is_empty() { // Special case for no fields. let fn_path_write_str = cx.std_path(&[sym::fmt, sym::Formatter, sym::write_str]); - cx.expr_call_global(span, fn_path_write_str, vec![fmt, name]) + let expr = cx.expr_call_global(span, fn_path_write_str, vec![fmt, name]); + BlockOrExpr::new_expr(expr) } else if fields.len() <= CUTOFF { // Few enough fields that we can use a specific-length method. let debug = if is_struct { @@ -100,7 +100,8 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_> let field = cx.expr_addr_of(field.span, field); args.push(field); } - cx.expr_call_global(span, fn_path_debug, args) + let expr = cx.expr_call_global(span, fn_path_debug, args); + BlockOrExpr::new_expr(expr) } else { // Enough fields that we must use the any-length method. let mut name_exprs = Vec::with_capacity(fields.len()); @@ -176,8 +177,6 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_> stmts.push(names_let.unwrap()); } stmts.push(values_let); - stmts.push(cx.stmt_expr(expr)); - - cx.expr_block(cx.block(span, stmts)) + BlockOrExpr::new_mixed(stmts, expr) } } diff --git a/compiler/rustc_builtin_macros/src/deriving/decodable.rs b/compiler/rustc_builtin_macros/src/deriving/decodable.rs index 16154fb4d03..b9f2a750822 100644 --- a/compiler/rustc_builtin_macros/src/deriving/decodable.rs +++ b/compiler/rustc_builtin_macros/src/deriving/decodable.rs @@ -62,7 +62,7 @@ fn decodable_substructure( trait_span: Span, substr: &Substructure<'_>, krate: Symbol, -) -> P<Expr> { +) -> BlockOrExpr { let decoder = substr.nonself_args[0].clone(); let recurse = vec![ Ident::new(krate, trait_span), @@ -74,7 +74,7 @@ fn decodable_substructure( let blkarg = Ident::new(sym::_d, trait_span); let blkdecoder = cx.expr_ident(trait_span, blkarg); - match *substr.fields { + let expr = match *substr.fields { StaticStruct(_, ref summary) => { let nfields = match *summary { Unnamed(ref fields, _) => fields.len(), @@ -173,7 +173,8 @@ fn decodable_substructure( ) } _ => cx.bug("expected StaticEnum or StaticStruct in derive(Decodable)"), - } + }; + BlockOrExpr::new_expr(expr) } /// Creates a decoder for a single enum variant/struct: diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index d41b25343b0..90d5cdbc0a0 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -1,11 +1,10 @@ use crate::deriving::generic::ty::*; use crate::deriving::generic::*; -use rustc_ast::ptr::P; +use rustc_ast as ast; use rustc_ast::walk_list; use rustc_ast::EnumDef; use rustc_ast::VariantData; -use rustc_ast::{Expr, MetaItem}; use rustc_errors::Applicability; use rustc_expand::base::{Annotatable, DummyResult, ExtCtxt}; use rustc_span::symbol::Ident; @@ -16,7 +15,7 @@ use smallvec::SmallVec; pub fn expand_deriving_default( cx: &mut ExtCtxt<'_>, span: Span, - mitem: &MetaItem, + mitem: &ast::MetaItem, item: &Annotatable, push: &mut dyn FnMut(Annotatable), ) { @@ -59,12 +58,12 @@ fn default_struct_substructure( trait_span: Span, substr: &Substructure<'_>, summary: &StaticFields, -) -> P<Expr> { +) -> BlockOrExpr { // Note that `kw::Default` is "default" and `sym::Default` is "Default"! let default_ident = cx.std_path(&[kw::Default, sym::Default, kw::Default]); let default_call = |span| cx.expr_call_global(span, default_ident.clone(), Vec::new()); - match summary { + let expr = match summary { Unnamed(ref fields, is_tuple) => { if !is_tuple { cx.expr_ident(trait_span, substr.type_ident) @@ -80,31 +79,27 @@ fn default_struct_substructure( .collect(); cx.expr_struct_ident(trait_span, substr.type_ident, default_fields) } - } + }; + BlockOrExpr::new_expr(expr) } fn default_enum_substructure( cx: &mut ExtCtxt<'_>, trait_span: Span, enum_def: &EnumDef, -) -> P<Expr> { - let Ok(default_variant) = extract_default_variant(cx, enum_def, trait_span) else { - return DummyResult::raw_expr(trait_span, true); +) -> BlockOrExpr { + let expr = if let Ok(default_variant) = extract_default_variant(cx, enum_def, trait_span) + && let Ok(_) = validate_default_attribute(cx, default_variant) + { + // We now know there is exactly one unit variant with exactly one `#[default]` attribute. + cx.expr_path(cx.path( + default_variant.span, + vec![Ident::new(kw::SelfUpper, default_variant.span), default_variant.ident], + )) + } else { + DummyResult::raw_expr(trait_span, true) }; - - // At this point, we know that there is exactly one variant with a `#[default]` attribute. The - // attribute hasn't yet been validated. - - if let Err(()) = validate_default_attribute(cx, default_variant) { - return DummyResult::raw_expr(trait_span, true); - } - - // We now know there is exactly one unit variant with exactly one `#[default]` attribute. - - cx.expr_path(cx.path( - default_variant.span, - vec![Ident::new(kw::SelfUpper, default_variant.span), default_variant.ident], - )) + BlockOrExpr::new_expr(expr) } fn extract_default_variant<'a>( diff --git a/compiler/rustc_builtin_macros/src/deriving/encodable.rs b/compiler/rustc_builtin_macros/src/deriving/encodable.rs index 7dc0584618d..0dfce114bfc 100644 --- a/compiler/rustc_builtin_macros/src/deriving/encodable.rs +++ b/compiler/rustc_builtin_macros/src/deriving/encodable.rs @@ -89,8 +89,7 @@ use crate::deriving::generic::ty::*; use crate::deriving::generic::*; use crate::deriving::pathvec_std; -use rustc_ast::ptr::P; -use rustc_ast::{Expr, ExprKind, MetaItem, Mutability}; +use rustc_ast::{ExprKind, MetaItem, Mutability}; use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::Span; @@ -147,7 +146,7 @@ fn encodable_substructure( trait_span: Span, substr: &Substructure<'_>, krate: Symbol, -) -> P<Expr> { +) -> BlockOrExpr { let encoder = substr.nonself_args[0].clone(); // throw an underscore in front to suppress unused variable warnings let blkarg = Ident::new(sym::_e, trait_span); @@ -208,7 +207,7 @@ fn encodable_substructure( let fn_emit_struct_path = cx.def_site_path(&[sym::rustc_serialize, sym::Encoder, sym::emit_struct]); - cx.expr_call_global( + let expr = cx.expr_call_global( trait_span, fn_emit_struct_path, vec![ @@ -217,7 +216,8 @@ fn encodable_substructure( cx.expr_usize(trait_span, fields.len()), blk, ], - ) + ); + BlockOrExpr::new_expr(expr) } EnumMatching(idx, _, variant, ref fields) => { @@ -279,12 +279,12 @@ fn encodable_substructure( let blk = cx.lambda1(trait_span, call, blkarg); let fn_emit_enum_path: Vec<_> = cx.def_site_path(&[sym::rustc_serialize, sym::Encoder, sym::emit_enum]); - let ret = cx.expr_call_global( + let expr = cx.expr_call_global( trait_span, fn_emit_enum_path, vec![encoder, cx.expr_str(trait_span, substr.type_ident.name), blk], ); - cx.expr_block(cx.block(trait_span, vec![me, cx.stmt_expr(ret)])) + BlockOrExpr::new_mixed(vec![me], expr) } _ => cx.bug("expected Struct or EnumMatching in derive(Encodable)"), diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 2a9e37081e0..e2d82b181a1 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -296,7 +296,7 @@ pub enum SubstructureFields<'a> { /// Combine the values of all the fields together. The last argument is /// all the fields of all the structures. pub type CombineSubstructureFunc<'a> = - Box<dyn FnMut(&mut ExtCtxt<'_>, Span, &Substructure<'_>) -> P<Expr> + 'a>; + Box<dyn FnMut(&mut ExtCtxt<'_>, Span, &Substructure<'_>) -> BlockOrExpr + 'a>; /// Deal with non-matching enum variants. The slice is the identifiers holding /// the variant index value for each of the `Self` arguments. @@ -314,6 +314,48 @@ struct TypeParameter { ty: P<ast::Ty>, } +// The code snippets built up for derived code are sometimes used as blocks +// (e.g. in a function body) and sometimes used as expressions (e.g. in a match +// arm). This structure avoids committing to either form until necessary, +// avoiding the insertion of any unnecessary blocks. +// +// The statements come before the expression. +pub struct BlockOrExpr(Vec<ast::Stmt>, Option<P<Expr>>); + +impl BlockOrExpr { + pub fn new_stmts(stmts: Vec<ast::Stmt>) -> BlockOrExpr { + BlockOrExpr(stmts, None) + } + + pub fn new_expr(expr: P<Expr>) -> BlockOrExpr { + BlockOrExpr(vec![], Some(expr)) + } + + pub fn new_mixed(stmts: Vec<ast::Stmt>, expr: P<Expr>) -> BlockOrExpr { + BlockOrExpr(stmts, Some(expr)) + } + + // Converts it into a block. + fn into_block(mut self, cx: &ExtCtxt<'_>, span: Span) -> P<ast::Block> { + if let Some(expr) = self.1 { + self.0.push(cx.stmt_expr(expr)); + } + cx.block(span, self.0) + } + + // Converts it into an expression. + fn into_expr(self, cx: &ExtCtxt<'_>, span: Span) -> P<Expr> { + if self.0.is_empty() { + match self.1 { + None => cx.expr_block(cx.block(span, vec![])), + Some(expr) => expr, + } + } else { + cx.expr_block(self.into_block(cx, span)) + } + } +} + /// This method helps to extract all the type parameters referenced from a /// type. For a type parameter `<T>`, it looks for either a `TyPath` that /// is not global and starts with `T`, or a `TyQPath`. @@ -827,7 +869,7 @@ impl<'a> MethodDef<'a> { type_ident: Ident, nonself_args: &[P<Expr>], fields: &SubstructureFields<'_>, - ) -> P<Expr> { + ) -> BlockOrExpr { let span = trait_.span; let substructure = Substructure { type_ident, nonself_args, fields }; let mut f = self.combine_substructure.borrow_mut(); @@ -902,7 +944,7 @@ impl<'a> MethodDef<'a> { generics: &Generics, explicit_self: Option<ast::ExplicitSelf>, arg_types: Vec<(Ident, P<ast::Ty>)>, - body: P<Expr>, + body: BlockOrExpr, ) -> P<ast::AssocItem> { let span = trait_.span; // Create the generics that aren't for `Self`. @@ -921,7 +963,7 @@ impl<'a> MethodDef<'a> { let method_ident = Ident::new(self.name, span); let fn_decl = cx.fn_decl(args, ast::FnRetTy::Ty(ret_type)); - let body_block = cx.block_expr(body); + let body_block = body.into_block(cx, span); let trait_lo_sp = span.shrink_to_lo(); @@ -986,7 +1028,7 @@ impl<'a> MethodDef<'a> { nonself_args: &[P<Expr>], use_temporaries: bool, is_packed: bool, - ) -> P<Expr> { + ) -> BlockOrExpr { let mut raw_fields = Vec::new(); // Vec<[fields of self], [fields of next Self arg], [etc]> let span = trait_.span; let mut patterns = Vec::new(); @@ -1047,16 +1089,14 @@ impl<'a> MethodDef<'a> { ); if !is_packed { - body.span = span; body } else { // Do the let-destructuring. let mut stmts: Vec<_> = iter::zip(self_args, patterns) .map(|(arg_expr, pat)| cx.stmt_let_pat(span, pat, arg_expr.clone())) .collect(); - stmts.push(cx.stmt_expr(body)); - - cx.expr_block(cx.block(span, stmts)) + stmts.extend(std::mem::take(&mut body.0)); + BlockOrExpr(stmts, body.1) } } @@ -1067,7 +1107,7 @@ impl<'a> MethodDef<'a> { struct_def: &VariantData, type_ident: Ident, nonself_args: &[P<Expr>], - ) -> P<Expr> { + ) -> BlockOrExpr { let summary = trait_.summarise_struct(cx, struct_def); self.call_substructure_method( @@ -1130,7 +1170,7 @@ impl<'a> MethodDef<'a> { type_ident: Ident, mut self_args: Vec<P<Expr>>, nonself_args: &[P<Expr>], - ) -> P<Expr> { + ) -> BlockOrExpr { let span = trait_.span; let variants = &enum_def.variants; @@ -1253,13 +1293,9 @@ impl<'a> MethodDef<'a> { // Self arg, assuming all are instances of VariantK. // Build up code associated with such a case. let substructure = EnumMatching(index, variants.len(), variant, field_tuples); - let arm_expr = self.call_substructure_method( - cx, - trait_, - type_ident, - nonself_args, - &substructure, - ); + let arm_expr = self + .call_substructure_method(cx, trait_, type_ident, nonself_args, &substructure) + .into_expr(cx, span); cx.arm(span, single_pat, arm_expr) }) @@ -1271,13 +1307,16 @@ impl<'a> MethodDef<'a> { // The index and actual variant aren't meaningful in this case, // so just use whatever let substructure = EnumMatching(0, variants.len(), v, Vec::new()); - Some(self.call_substructure_method( - cx, - trait_, - type_ident, - nonself_args, - &substructure, - )) + Some( + self.call_substructure_method( + cx, + trait_, + type_ident, + nonself_args, + &substructure, + ) + .into_expr(cx, span), + ) } _ if variants.len() > 1 && self_args.len() > 1 => { // Since we know that all the arguments will match if we reach @@ -1341,13 +1380,15 @@ impl<'a> MethodDef<'a> { } } - let arm_expr = self.call_substructure_method( - cx, - trait_, - type_ident, - nonself_args, - &catch_all_substructure, - ); + let arm_expr = self + .call_substructure_method( + cx, + trait_, + type_ident, + nonself_args, + &catch_all_substructure, + ) + .into_expr(cx, span); // Final wrinkle: the self_args are expressions that deref // down to desired places, but we cannot actually deref @@ -1371,8 +1412,7 @@ impl<'a> MethodDef<'a> { // } let all_match = cx.expr_match(span, match_arg, match_arms); let arm_expr = cx.expr_if(span, discriminant_test, all_match, Some(arm_expr)); - index_let_stmts.push(cx.stmt_expr(arm_expr)); - cx.expr_block(cx.block(span, index_let_stmts)) + BlockOrExpr(index_let_stmts, Some(arm_expr)) } else if variants.is_empty() { // As an additional wrinkle, For a zero-variant enum A, // currently the compiler @@ -1423,7 +1463,7 @@ impl<'a> MethodDef<'a> { // derive Debug on such a type could here generate code // that needs the feature gate enabled.) - deriving::call_unreachable(cx, span) + BlockOrExpr(vec![], Some(deriving::call_unreachable(cx, span))) } else { // Final wrinkle: the self_args are expressions that deref // down to desired places, but we cannot actually deref @@ -1432,7 +1472,7 @@ impl<'a> MethodDef<'a> { // `(*self, *__arg_0, ...)` into `(&*self, &*__arg_0, ...)`. self_args.map_in_place(|self_arg| cx.expr_addr_of(span, self_arg)); let match_arg = cx.expr(span, ast::ExprKind::Tup(self_args)); - cx.expr_match(span, match_arg, match_arms) + BlockOrExpr(vec![], Some(cx.expr_match(span, match_arg, match_arms))) } } @@ -1443,7 +1483,7 @@ impl<'a> MethodDef<'a> { enum_def: &EnumDef, type_ident: Ident, nonself_args: &[P<Expr>], - ) -> P<Expr> { + ) -> BlockOrExpr { let summary = enum_def .variants .iter() diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs index 9790449c4b3..c3f7d09886b 100644 --- a/compiler/rustc_builtin_macros/src/deriving/hash.rs +++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs @@ -2,8 +2,7 @@ use crate::deriving::generic::ty::*; use crate::deriving::generic::*; use crate::deriving::{self, path_std, pathvec_std}; -use rustc_ast::ptr::P; -use rustc_ast::{Expr, MetaItem, Mutability}; +use rustc_ast::{MetaItem, Mutability}; use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_span::symbol::sym; use rustc_span::Span; @@ -45,7 +44,11 @@ pub fn expand_deriving_hash( hash_trait_def.expand(cx, mitem, item, push); } -fn hash_substructure(cx: &mut ExtCtxt<'_>, trait_span: Span, substr: &Substructure<'_>) -> P<Expr> { +fn hash_substructure( + cx: &mut ExtCtxt<'_>, + trait_span: Span, + substr: &Substructure<'_>, +) -> BlockOrExpr { let [state_expr] = substr.nonself_args else { cx.span_bug(trait_span, "incorrect number of arguments in `derive(Hash)`"); }; @@ -81,6 +84,5 @@ fn hash_substructure(cx: &mut ExtCtxt<'_>, trait_span: Span, substr: &Substructu stmts.extend( fields.iter().map(|FieldInfo { ref self_, span, .. }| call_hash(*span, self_.clone())), ); - - cx.expr_block(cx.block(trait_span, stmts)) + BlockOrExpr::new_stmts(stmts) } |
