diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index bf648388f4e..d6c2bfacf66 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1311,7 +1311,7 @@ pub struct Closure { pub binder: ClosureBinder, pub capture_clause: CaptureBy, pub constness: Const, - pub coro_kind: CoroutineKind, + pub coro_kind: Option, pub movability: Movability, pub fn_decl: P, pub body: P, @@ -2417,8 +2417,6 @@ pub enum CoroutineKind { Async { span: Span, closure_id: NodeId, return_impl_trait_id: NodeId }, /// `gen`, which evaluates to `impl Iterator` Gen { span: Span, closure_id: NodeId, return_impl_trait_id: NodeId }, - /// Neither `async` nor `gen` - None, } impl CoroutineKind { @@ -2430,14 +2428,12 @@ pub fn is_gen(self) -> bool { matches!(self, CoroutineKind::Gen { .. }) } - /// In this case this is an `async` return, the `NodeId` for the generated `impl Trait` item. - pub fn opt_return_id(self) -> Option<(NodeId, Span)> { + /// In this case this is an `async` or `gen` return, the `NodeId` for the generated `impl Trait` + /// item. + pub fn return_id(self) -> (NodeId, Span) { match self { CoroutineKind::Async { return_impl_trait_id, span, .. } - | CoroutineKind::Gen { return_impl_trait_id, span, .. } => { - Some((return_impl_trait_id, span)) - } - CoroutineKind::None => None, + | CoroutineKind::Gen { return_impl_trait_id, span, .. } => (return_impl_trait_id, span), } } } @@ -2842,7 +2838,7 @@ pub struct FnHeader { /// The `unsafe` keyword, if any pub unsafety: Unsafe, /// Whether this is `async`, `gen`, or nothing. - pub coro_kind: CoroutineKind, + pub coro_kind: Option, /// The `const` keyword, if any pub constness: Const, /// The `extern` keyword and corresponding ABI string, if any @@ -2854,7 +2850,7 @@ impl FnHeader { pub fn has_qualifiers(&self) -> bool { let Self { unsafety, coro_kind, constness, ext } = self; matches!(unsafety, Unsafe::Yes(_)) - || !matches!(coro_kind, CoroutineKind::None) + || coro_kind.is_some() || matches!(constness, Const::Yes(_)) || !matches!(ext, Extern::None) } @@ -2862,12 +2858,7 @@ pub fn has_qualifiers(&self) -> bool { impl Default for FnHeader { fn default() -> FnHeader { - FnHeader { - unsafety: Unsafe::No, - coro_kind: CoroutineKind::None, - constness: Const::No, - ext: Extern::None, - } + FnHeader { unsafety: Unsafe::No, coro_kind: None, constness: Const::No, ext: Extern::None } } } diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index f9f767862f5..c6aa7a6ae37 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -878,7 +878,6 @@ pub fn noop_visit_coro_kind(coro_kind: &mut CoroutineKind, vis: & vis.visit_id(closure_id); vis.visit_id(return_impl_trait_id); } - CoroutineKind::None => {} } } @@ -1173,7 +1172,7 @@ fn visit_const_item( pub fn noop_visit_fn_header(header: &mut FnHeader, vis: &mut T) { let FnHeader { unsafety, coro_kind, constness, ext: _ } = header; visit_constness(constness, vis); - vis.visit_coro_kind(coro_kind); + coro_kind.as_mut().map(|coro_kind| vis.visit_coro_kind(coro_kind)); visit_unsafety(unsafety, vis); } @@ -1416,7 +1415,7 @@ pub fn noop_visit_expr( }) => { vis.visit_closure_binder(binder); visit_constness(constness, vis); - vis.visit_coro_kind(coro_kind); + coro_kind.as_mut().map(|coro_kind| vis.visit_coro_kind(coro_kind)); vis.visit_capture_by(capture_clause); vis.visit_fn_decl(fn_decl); vis.visit_expr(body); diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 5846f17c539..3556ee02bd7 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -202,8 +202,10 @@ pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> { fn_decl_span, fn_arg_span, }) => match coro_kind { - CoroutineKind::Async { closure_id, .. } - | CoroutineKind::Gen { closure_id, .. } => self.lower_expr_async_closure( + Some( + CoroutineKind::Async { closure_id, .. } + | CoroutineKind::Gen { closure_id, .. }, + ) => self.lower_expr_async_closure( binder, *capture_clause, e.id, @@ -214,7 +216,7 @@ pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> { *fn_decl_span, *fn_arg_span, ), - CoroutineKind::None => self.lower_expr_closure( + None => self.lower_expr_closure( binder, *capture_clause, e.id, @@ -933,13 +935,7 @@ fn lower_expr_closure( let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params); // Lower outside new scope to preserve `is_in_loop_condition`. - let fn_decl = self.lower_fn_decl( - decl, - closure_id, - fn_decl_span, - FnDeclKind::Closure, - CoroutineKind::None, - ); + let fn_decl = self.lower_fn_decl(decl, closure_id, fn_decl_span, FnDeclKind::Closure, None); let c = self.arena.alloc(hir::Closure { def_id: self.local_def_id(closure_id), @@ -1054,13 +1050,8 @@ fn lower_expr_async_closure( // We need to lower the declaration outside the new scope, because we // have to conserve the state of being inside a loop condition for the // closure argument types. - let fn_decl = self.lower_fn_decl( - &outer_decl, - closure_id, - fn_decl_span, - FnDeclKind::Closure, - CoroutineKind::None, - ); + let fn_decl = + self.lower_fn_decl(&outer_decl, closure_id, fn_decl_span, FnDeclKind::Closure, None); let c = self.arena.alloc(hir::Closure { def_id: self.local_def_id(closure_id), diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 5d32e1a78f1..a23a77f45be 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -602,7 +602,7 @@ fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir i.id, sig.span, FnDeclKind::ExternFn, - CoroutineKind::None, + None, ), this.lower_fn_params_to_names(fdec), ) @@ -841,7 +841,6 @@ fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> { }, ), AssocItemKind::Fn(box Fn { sig, generics, body, .. }) => { - self.current_item = Some(i.span); let body_id = self.lower_maybe_coroutine_body( i.span, hir_id, @@ -1025,15 +1024,16 @@ fn lower_maybe_coroutine_body( span: Span, fn_id: hir::HirId, decl: &FnDecl, - coro_kind: CoroutineKind, + coro_kind: Option, body: Option<&Block>, ) -> hir::BodyId { - let (closure_id, body) = match (coro_kind, body) { - ( - CoroutineKind::Async { closure_id, .. } | CoroutineKind::Gen { closure_id, .. }, - Some(body), - ) => (closure_id, body), - _ => return self.lower_fn_body_block(span, decl, body), + let (Some(coro_kind), Some(body)) = (coro_kind, body) else { + return self.lower_fn_body_block(span, decl, body); + }; + let closure_id = match coro_kind { + CoroutineKind::Async { closure_id, .. } | CoroutineKind::Gen { closure_id, .. } => { + closure_id + } }; self.lower_body(|this| { @@ -1218,7 +1218,6 @@ fn lower_maybe_coroutine_body( hir::CoroutineSource::Fn, mkbody, ), - CoroutineKind::None => unreachable!("we must have either an async fn or a gen fn"), }; let hir_id = this.lower_node_id(closure_id); @@ -1235,7 +1234,7 @@ fn lower_method_sig( sig: &FnSig, id: NodeId, kind: FnDeclKind, - coro_kind: CoroutineKind, + coro_kind: Option, ) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) { let header = self.lower_fn_header(sig.header); let itctx = ImplTraitContext::Universal; @@ -1247,7 +1246,7 @@ fn lower_method_sig( } fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader { - let asyncness = if let CoroutineKind::Async { span, .. } = h.coro_kind { + let asyncness = if let Some(CoroutineKind::Async { span, .. }) = h.coro_kind { hir::IsAsync::Async(span) } else { hir::IsAsync::NotAsync diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 92650f0c47e..a35b1513e14 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1359,13 +1359,7 @@ fn lower_ty_direct(&mut self, t: &Ty, itctx: &ImplTraitContext) -> hir::Ty<'hir> generic_params, unsafety: self.lower_unsafety(f.unsafety), abi: self.lower_extern(f.ext), - decl: self.lower_fn_decl( - &f.decl, - t.id, - t.span, - FnDeclKind::Pointer, - CoroutineKind::None, - ), + decl: self.lower_fn_decl(&f.decl, t.id, t.span, FnDeclKind::Pointer, None), param_names: self.lower_fn_params_to_names(&f.decl), })) } @@ -1800,7 +1794,7 @@ fn lower_fn_decl( fn_node_id: NodeId, fn_span: Span, kind: FnDeclKind, - coro: CoroutineKind, + coro: Option, ) -> &'hir hir::FnDecl<'hir> { let c_variadic = decl.c_variadic(); @@ -1830,11 +1824,11 @@ fn lower_fn_decl( })); let output = match coro { - CoroutineKind::Async { .. } | CoroutineKind::Gen { .. } => { + Some(coro) => { let fn_def_id = self.local_def_id(fn_node_id); self.lower_coroutine_fn_ret_ty(&decl.output, fn_def_id, coro, kind, fn_span) } - CoroutineKind::None => match &decl.output { + None => match &decl.output { FnRetTy::Ty(ty) => { let context = if kind.return_impl_trait_allowed() { let fn_def_id = self.local_def_id(fn_node_id); @@ -1911,9 +1905,6 @@ fn lower_coroutine_fn_ret_ty( let opaque_ty_node_id = match coro { CoroutineKind::Async { return_impl_trait_id, .. } | CoroutineKind::Gen { return_impl_trait_id, .. } => return_impl_trait_id, - CoroutineKind::None => { - unreachable!("lower_coroutine_fn_ret_ty must be called with either Async or Gen") - } }; let captured_lifetimes: Vec<_> = self @@ -1971,7 +1962,6 @@ fn lower_coroutine_fn_output_type_to_future_bound( let (symbol, lang_item) = match coro { CoroutineKind::Async { .. } => (hir::FN_OUTPUT_NAME, hir::LangItem::Future), CoroutineKind::Gen { .. } => (hir::ITERATOR_ITEM_NAME, hir::LangItem::Iterator), - CoroutineKind::None => panic!("attemping to lower output type of non-coroutine fn"), }; let future_args = self.arena.alloc(hir::GenericArgs { diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index ce680afdc3e..311ab96aba0 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1268,13 +1268,18 @@ fn visit_fn(&mut self, fk: FnKind<'a>, span: Span, id: NodeId) { self.check_c_variadic_type(fk); - // Functions cannot both be `const async` + // Functions cannot both be `const async` or `const gen` if let Some(&FnHeader { constness: Const::Yes(cspan), - coro_kind: CoroutineKind::Async { span: aspan, .. }, + coro_kind: + Some( + CoroutineKind::Async { span: aspan, .. } + | CoroutineKind::Gen { span: aspan, .. }, + ), .. }) = fk.header() { + // FIXME(eholk): Report a different error for `const gen` self.err_handler().emit_err(errors::ConstAndAsync { spans: vec![cspan, aspan], cspan, diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 1e69674d30a..1ad28ffbf2b 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1492,7 +1492,6 @@ fn print_explicit_self(&mut self, explicit_self: &ast::ExplicitSelf) { fn print_coro_kind(&mut self, coro_kind: ast::CoroutineKind) { match coro_kind { - ast::CoroutineKind::None => {} ast::CoroutineKind::Gen { .. } => { self.word_nbsp("gen"); } @@ -1691,7 +1690,7 @@ fn print_ty_fn( fn print_fn_header_info(&mut self, header: ast::FnHeader) { self.print_constness(header.constness); - self.print_coro_kind(header.coro_kind); + header.coro_kind.map(|coro_kind| self.print_coro_kind(coro_kind)); self.print_unsafety(header.unsafety); match header.ext { diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index d8641e745d0..0082d6e350e 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -423,7 +423,7 @@ pub(super) fn print_expr_outer_attr_style(&mut self, expr: &ast::Expr, is_inline self.print_closure_binder(binder); self.print_constness(*constness); self.print_movability(*movability); - self.print_coro_kind(*coro_kind); + coro_kind.map(|coro_kind| self.print_coro_kind(coro_kind)); self.print_capture_clause(*capture_clause); self.print_fn_params_and_ret(fn_decl, true); diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index 8f4234b4138..38fdddf5834 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -541,7 +541,7 @@ fn check_test_signature( return Err(sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "unsafe" })); } - if let ast::CoroutineKind::Async { span, .. } = f.sig.header.coro_kind { + if let Some(ast::CoroutineKind::Async { span, .. }) = f.sig.header.coro_kind { return Err(sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "async" })); } diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index 49b52d265d6..794e11d87d1 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -547,7 +547,7 @@ pub fn lambda(&self, span: Span, ids: Vec, body: P) -> P, span: Span, id: ast::NodeId) { // Explicitly check for lints associated with 'closure_id', since // it does not have a corresponding AST node if let ast_visit::FnKind::Fn(_, _, sig, _, _, _) = fk { - if let ast::CoroutineKind::Async { closure_id, .. } - | ast::CoroutineKind::Gen { closure_id, .. } = sig.header.coro_kind + if let Some( + ast::CoroutineKind::Async { closure_id, .. } + | ast::CoroutineKind::Gen { closure_id, .. }, + ) = sig.header.coro_kind { self.check_id(closure_id); } @@ -226,8 +228,10 @@ fn visit_expr_post(&mut self, e: &'a ast::Expr) { match e.kind { ast::ExprKind::Closure(box ast::Closure { coro_kind: - ast::CoroutineKind::Async { closure_id, .. } - | ast::CoroutineKind::Gen { closure_id, .. }, + Some( + ast::CoroutineKind::Async { closure_id, .. } + | ast::CoroutineKind::Gen { closure_id, .. }, + ), .. }) => self.check_id(closure_id), _ => {} diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 8a09d4e0549..8482824ec4b 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -10,7 +10,7 @@ use crate::errors; use crate::maybe_recover_from_interpolated_ty_qpath; use ast::mut_visit::{noop_visit_expr, MutVisitor}; -use ast::{GenBlockKind, Pat, Path, PathSegment}; +use ast::{CoroutineKind, GenBlockKind, Pat, Path, PathSegment}; use core::mem; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Token, TokenKind}; @@ -21,9 +21,7 @@ use rustc_ast::visit::Visitor; use rustc_ast::{self as ast, AttrStyle, AttrVec, CaptureBy, ExprField, UnOp, DUMMY_NODE_ID}; use rustc_ast::{AnonConst, BinOp, BinOpKind, FnDecl, FnRetTy, MacCall, Param, Ty, TyKind}; -use rustc_ast::{ - Arm, BlockCheckMode, CoroutineKind, Expr, ExprKind, Label, Movability, RangeLimits, -}; +use rustc_ast::{Arm, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits}; use rustc_ast::{ClosureBinder, MetaItemLit, StmtKind}; use rustc_ast_pretty::pprust; use rustc_data_structures::stack::ensure_sufficient_stack; @@ -2239,7 +2237,7 @@ fn parse_expr_closure(&mut self) -> PResult<'a, P> { let asyncness = if self.token.uninterpolated_span().at_least_rust_2018() { self.parse_asyncness(Case::Sensitive) } else { - CoroutineKind::None + None }; let capture_clause = self.parse_capture_clause()?; @@ -2263,7 +2261,7 @@ fn parse_expr_closure(&mut self) -> PResult<'a, P> { } }; - if let CoroutineKind::Async { span, .. } = asyncness { + if let Some(CoroutineKind::Async { span, .. }) = asyncness { // Feature-gate `async ||` closures. self.sess.gated_spans.gate(sym::async_closure, span); } diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 2bee4d5d5c6..589fc46b722 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -2401,7 +2401,7 @@ pub(super) fn parse_fn_front_matter( let ext_start_sp = self.token.span; let ext = self.parse_extern(case); - if let CoroutineKind::Async { span, .. } = asyncness { + if let Some(CoroutineKind::Async { span, .. }) = asyncness { if span.is_rust_2015() { self.sess.emit_err(errors::AsyncFnIn2015 { span, @@ -2410,13 +2410,13 @@ pub(super) fn parse_fn_front_matter( } } - if let CoroutineKind::Gen { span, .. } = genness { + if let Some(CoroutineKind::Gen { span, .. }) = genness { self.sess.gated_spans.gate(sym::gen_blocks, span); } if let ( - CoroutineKind::Async { span: async_span, .. }, - CoroutineKind::Gen { span: gen_span, .. }, + Some(CoroutineKind::Async { span: async_span, .. }), + Some(CoroutineKind::Gen { span: gen_span, .. }), ) = (asyncness, genness) { self.sess.emit_err(errors::AsyncGenFn { span: async_span.to(gen_span) }); @@ -2452,16 +2452,18 @@ enum WrongKw { } } else if self.check_keyword(kw::Async) { match asyncness { - CoroutineKind::Async { span, .. } => Some(WrongKw::Duplicated(span)), - CoroutineKind::Gen { .. } => { + Some(CoroutineKind::Async { span, .. }) => { + Some(WrongKw::Duplicated(span)) + } + Some(CoroutineKind::Gen { .. }) => { panic!("not sure how to recover here") } - CoroutineKind::None => { - recover_asyncness = CoroutineKind::Async { + None => { + recover_asyncness = Some(CoroutineKind::Async { span: self.token.span, closure_id: DUMMY_NODE_ID, return_impl_trait_id: DUMMY_NODE_ID, - }; + }); Some(WrongKw::Misplaced(unsafe_start_sp)) } } @@ -2566,9 +2568,9 @@ enum WrongKw { } let coro_kind = match asyncness { - CoroutineKind::Async { .. } => asyncness, - CoroutineKind::Gen { .. } => unreachable!("asycness cannot be Gen"), - CoroutineKind::None => genness, + Some(CoroutineKind::Async { .. }) => asyncness, + Some(CoroutineKind::Gen { .. }) => unreachable!("asycness cannot be Gen"), + None => genness, }; Ok(FnHeader { constness, unsafety, coro_kind, ext }) diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index a9da3043117..2816386cbad 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1125,30 +1125,30 @@ pub(crate) fn is_keyword_ahead(&self, dist: usize, kws: &[Symbol]) -> bool { } /// Parses asyncness: `async` or nothing. - fn parse_asyncness(&mut self, case: Case) -> CoroutineKind { + fn parse_asyncness(&mut self, case: Case) -> Option { if self.eat_keyword_case(kw::Async, case) { let span = self.prev_token.uninterpolated_span(); - CoroutineKind::Async { + Some(CoroutineKind::Async { span, closure_id: DUMMY_NODE_ID, return_impl_trait_id: DUMMY_NODE_ID, - } + }) } else { - CoroutineKind::None + None } } /// Parses genness: `gen` or nothing. - fn parse_genness(&mut self, case: Case) -> CoroutineKind { + fn parse_genness(&mut self, case: Case) -> Option { if self.token.span.at_least_rust_2024() && self.eat_keyword_case(kw::Gen, case) { let span = self.prev_token.uninterpolated_span(); - CoroutineKind::Gen { + Some(CoroutineKind::Gen { span, closure_id: DUMMY_NODE_ID, return_impl_trait_id: DUMMY_NODE_ID, - } + }) } else { - CoroutineKind::None + None } } diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index a8e147a05b0..73487f4af0e 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -609,7 +609,7 @@ fn parse_ty_bare_fn( // cover it. self.sess.emit_err(FnPointerCannotBeConst { span: whole_span, qualifier: span }); } - if let ast::CoroutineKind::Async { span, .. } = coro_kind { + if let Some(ast::CoroutineKind::Async { span, .. }) = coro_kind { self.sess.emit_err(FnPointerCannotBeAsync { span: whole_span, qualifier: span }); } // FIXME(eholk): emit a similar error for `gen fn()` diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index c43ec99f42a..ab5d3b368eb 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -156,9 +156,9 @@ fn visit_item(&mut self, i: &'a Item) { fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) { if let FnKind::Fn(_, _, sig, _, generics, body) = fn_kind { - // FIXME(eholk): handle `async gen fn` - if let CoroutineKind::Async { closure_id, .. } | CoroutineKind::Gen { closure_id, .. } = - sig.header.coro_kind + if let Some( + CoroutineKind::Async { closure_id, .. } | CoroutineKind::Gen { closure_id, .. }, + ) = sig.header.coro_kind { self.visit_generics(generics); @@ -285,11 +285,11 @@ fn visit_expr(&mut self, expr: &'a Expr) { // we must create two defs. let closure_def = self.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span); match closure.coro_kind { - CoroutineKind::Async { closure_id, .. } - | CoroutineKind::Gen { closure_id, .. } => { - self.create_def(closure_id, kw::Empty, DefKind::Closure, expr.span) - } - CoroutineKind::None => closure_def, + Some( + CoroutineKind::Async { closure_id, .. } + | CoroutineKind::Gen { closure_id, .. }, + ) => self.create_def(closure_id, kw::Empty, DefKind::Closure, expr.span), + None => closure_def, } } ExprKind::Gen(_, _, _) => { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 2f7d1835113..c5d6574af60 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -916,7 +916,9 @@ fn visit_fn(&mut self, fn_kind: FnKind<'ast>, sp: Span, fn_id: NodeId) { &sig.decl.output, ); - if let Some((async_node_id, _)) = sig.header.coro_kind.opt_return_id() { + if let Some((async_node_id, _)) = + sig.header.coro_kind.map(|coro_kind| coro_kind.return_id()) + { this.record_lifetime_params_for_impl_trait(async_node_id); } }, @@ -940,7 +942,8 @@ fn visit_fn(&mut self, fn_kind: FnKind<'ast>, sp: Span, fn_id: NodeId) { this.visit_generics(generics); let declaration = &sig.decl; - let async_node_id = sig.header.coro_kind.opt_return_id(); + let async_node_id = + sig.header.coro_kind.map(|coro_kind| coro_kind.return_id()); this.with_lifetime_rib( LifetimeRibKind::AnonymousCreateParameter { @@ -4289,7 +4292,7 @@ fn resolve_expr(&mut self, expr: &'ast Expr, parent: Option<&'ast Expr>) { // resolve the arguments within the proper scopes so that usages of them inside the // closure are detected as upvars rather than normal closure arg usages. ExprKind::Closure(box ast::Closure { - coro_kind: CoroutineKind::Async { .. }, + coro_kind: Some(CoroutineKind::Async { .. }), ref fn_decl, ref body, .. diff --git a/src/tools/clippy/clippy_lints/src/doc/mod.rs b/src/tools/clippy/clippy_lints/src/doc/mod.rs index ec4abc21f48..0c623dba369 100644 --- a/src/tools/clippy/clippy_lints/src/doc/mod.rs +++ b/src/tools/clippy/clippy_lints/src/doc/mod.rs @@ -700,7 +700,7 @@ fn has_needless_main(code: String, edition: Edition) -> bool { ItemKind::Fn(box Fn { sig, body: Some(block), .. }) if item.ident.name == sym::main => { - let is_async = sig.header.coro_kind.is_async(); + let is_async = sig.header.coro_kind.map_or(false, |coro| coro.is_async()); let returns_nothing = match &sig.decl.output { FnRetTy::Default(..) => true, FnRetTy::Ty(ty) if ty.kind.is_unit() => true, diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index ac9da383b93..12403bbff3c 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -206,7 +206,7 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool { ) => { eq_closure_binder(lb, rb) && lc == rc - && la.is_async() == ra.is_async() + && la.map_or(false, |la| la.is_async()) == ra.map_or(false, |ra| ra.is_async()) && lm == rm && eq_fn_decl(lf, rf) && eq_expr(le, re) @@ -563,9 +563,18 @@ pub fn eq_fn_sig(l: &FnSig, r: &FnSig) -> bool { eq_fn_decl(&l.decl, &r.decl) && eq_fn_header(&l.header, &r.header) } +fn eq_opt_coro_kind(l: Option, r: Option) -> bool { + match (l, r) { + (Some(CoroutineKind::Async { .. }), Some(CoroutineKind::Async { .. })) + | (Some(CoroutineKind::Gen { .. }), Some(CoroutineKind::Gen { .. })) => true, + (None, None) => true, + _ => false, + } +} + pub fn eq_fn_header(l: &FnHeader, r: &FnHeader) -> bool { matches!(l.unsafety, Unsafe::No) == matches!(r.unsafety, Unsafe::No) - && (l.coro_kind.is_async() == r.coro_kind.is_async() || l.coro_kind.is_gen() == r.coro_kind.is_gen()) + && eq_opt_coro_kind(l.coro_kind, r.coro_kind) && matches!(l.constness, Const::No) == matches!(r.constness, Const::No) && eq_ext(&l.ext, &r.ext) } diff --git a/src/tools/rustfmt/src/closures.rs b/src/tools/rustfmt/src/closures.rs index 23cd6e4c092..d79218e78ee 100644 --- a/src/tools/rustfmt/src/closures.rs +++ b/src/tools/rustfmt/src/closures.rs @@ -29,7 +29,7 @@ pub(crate) fn rewrite_closure( binder: &ast::ClosureBinder, constness: ast::Const, capture: ast::CaptureBy, - coro_kind: &ast::CoroutineKind, + coro_kind: &Option, movability: ast::Movability, fn_decl: &ast::FnDecl, body: &ast::Expr, @@ -233,7 +233,7 @@ fn rewrite_closure_fn_decl( binder: &ast::ClosureBinder, constness: ast::Const, capture: ast::CaptureBy, - coro_kind: &ast::CoroutineKind, + coro_kind: &Option, movability: ast::Movability, fn_decl: &ast::FnDecl, body: &ast::Expr, @@ -263,8 +263,13 @@ fn rewrite_closure_fn_decl( } else { "" }; - let is_async = if coro_kind.is_async() { "async " } else { "" }; - let is_gen = if coro_kind.is_gen() { "gen " } else { "" }; + let (is_async, is_gen) = if let Some(coro_kind) = coro_kind { + let is_async = if coro_kind.is_async() { "async " } else { "" }; + let is_gen = if coro_kind.is_gen() { "gen " } else { "" }; + (is_async, is_gen) + } else { + ("", "") + }; let mover = if matches!(capture, ast::CaptureBy::Value { .. }) { "move " } else { diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index 0a1f823fe87..4dff65f8cd0 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -287,7 +287,7 @@ pub(crate) struct FnSig<'a> { decl: &'a ast::FnDecl, generics: &'a ast::Generics, ext: ast::Extern, - coro_kind: Cow<'a, ast::CoroutineKind>, + coro_kind: Cow<'a, Option>, constness: ast::Const, defaultness: ast::Defaultness, unsafety: ast::Unsafe, @@ -343,7 +343,8 @@ fn to_str(&self, context: &RewriteContext<'_>) -> String { result.push_str(&*format_visibility(context, self.visibility)); result.push_str(format_defaultness(self.defaultness)); result.push_str(format_constness(self.constness)); - result.push_str(format_coro(&self.coro_kind)); + self.coro_kind + .map(|coro_kind| result.push_str(format_coro(&coro_kind))); result.push_str(format_unsafety(self.unsafety)); result.push_str(&format_extern( self.ext, diff --git a/src/tools/rustfmt/src/utils.rs b/src/tools/rustfmt/src/utils.rs index 18d8f0cdbd7..5805e417c04 100644 --- a/src/tools/rustfmt/src/utils.rs +++ b/src/tools/rustfmt/src/utils.rs @@ -79,7 +79,6 @@ pub(crate) fn format_coro(coro_kind: &ast::CoroutineKind) -> &'static str { match coro_kind { ast::CoroutineKind::Async { .. } => "async ", ast::CoroutineKind::Gen { .. } => "gen ", - ast::CoroutineKind::None => "", } }