From b45e065dfb4eb977acaf15bbddd65ff5361555b0 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 5 Dec 2023 21:53:18 +0000 Subject: [PATCH] Make some matches exhaustive to avoid bugs, fix tools --- .../rustc_ast_passes/src/ast_validation.rs | 11 +++-- compiler/rustc_builtin_macros/src/test.rs | 30 +++++++++--- compiler/rustc_lint/src/early.rs | 23 +++++---- compiler/rustc_resolve/src/def_collector.rs | 48 ++++++++++--------- .../clippy/clippy_utils/src/ast_utils.rs | 3 +- src/tools/rustfmt/src/closures.rs | 1 + src/tools/rustfmt/src/utils.rs | 1 + 7 files changed, 71 insertions(+), 46 deletions(-) diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 6811548fff39a..0644c4cd6be4c 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1271,14 +1271,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> { // Functions cannot both be `const async` or `const gen` if let Some(&FnHeader { constness: Const::Yes(cspan), - coroutine_kind: - Some( - CoroutineKind::Async { span: aspan, .. } - | CoroutineKind::Gen { span: aspan, .. }, - ), + coroutine_kind: Some(coro_kind), .. }) = fk.header() { + let aspan = match coro_kind { + CoroutineKind::Async { span: aspan, .. } + | CoroutineKind::Gen { span: aspan, .. } + | CoroutineKind::AsyncGen { span: aspan, .. } => aspan, + }; // FIXME(gen_blocks): Report a different error for `const gen` self.err_handler().emit_err(errors::ConstAndAsync { spans: vec![cspan, aspan], diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index be4fd5dd36f95..794be25955d63 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -541,12 +541,30 @@ fn check_test_signature( return Err(sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "unsafe" })); } - if let Some(ast::CoroutineKind::Async { span, .. }) = f.sig.header.coroutine_kind { - return Err(sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "async" })); - } - - if let Some(ast::CoroutineKind::Gen { span, .. }) = f.sig.header.coroutine_kind { - return Err(sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "gen" })); + if let Some(coro_kind) = f.sig.header.coroutine_kind { + match coro_kind { + ast::CoroutineKind::Async { span, .. } => { + return Err(sd.emit_err(errors::TestBadFn { + span: i.span, + cause: span, + kind: "async", + })); + } + ast::CoroutineKind::Gen { span, .. } => { + return Err(sd.emit_err(errors::TestBadFn { + span: i.span, + cause: span, + kind: "gen", + })); + } + ast::CoroutineKind::AsyncGen { span, .. } => { + return Err(sd.emit_err(errors::TestBadFn { + span: i.span, + cause: span, + kind: "async gen", + })); + } + } } // If the termination trait is active, the compiler will check that the output diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 1673356ed1d4f..80c6feaa26936 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -162,11 +162,10 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> // 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 Some( - ast::CoroutineKind::Async { closure_id, .. } - | ast::CoroutineKind::Gen { closure_id, .. }, - ) = sig.header.coroutine_kind - { + if let Some(coro_kind) = sig.header.coroutine_kind { + let (ast::CoroutineKind::Async { closure_id, .. } + | ast::CoroutineKind::Gen { closure_id, .. } + | ast::CoroutineKind::AsyncGen { closure_id, .. }) = coro_kind; self.check_id(closure_id); } } @@ -227,13 +226,13 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> // it does not have a corresponding AST node match e.kind { ast::ExprKind::Closure(box ast::Closure { - coroutine_kind: - Some( - ast::CoroutineKind::Async { closure_id, .. } - | ast::CoroutineKind::Gen { closure_id, .. }, - ), - .. - }) => self.check_id(closure_id), + coroutine_kind: Some(coro_kind), .. + }) => { + let (ast::CoroutineKind::Async { closure_id, .. } + | ast::CoroutineKind::Gen { closure_id, .. } + | ast::CoroutineKind::AsyncGen { closure_id, .. }) = coro_kind; + self.check_id(closure_id); + } _ => {} } lint_callback!(self, check_expr_post, e); diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 4a62a2c462561..186dd28b142e6 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -156,29 +156,33 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) { if let FnKind::Fn(_, _, sig, _, generics, body) = fn_kind { - if let Some( - CoroutineKind::Async { closure_id, .. } | CoroutineKind::Gen { closure_id, .. }, - ) = sig.header.coroutine_kind - { - self.visit_generics(generics); - - // For async functions, we need to create their inner defs inside of a - // closure to match their desugared representation. Besides that, - // we must mirror everything that `visit::walk_fn` below does. - self.visit_fn_header(&sig.header); - for param in &sig.decl.inputs { - self.visit_param(param); - } - self.visit_fn_ret_ty(&sig.decl.output); - // If this async fn has no body (i.e. it's an async fn signature in a trait) - // then the closure_def will never be used, and we should avoid generating a - // def-id for it. - if let Some(body) = body { - let closure_def = - self.create_def(closure_id, kw::Empty, DefKind::Closure, span); - self.with_parent(closure_def, |this| this.visit_block(body)); + match sig.header.coroutine_kind { + Some( + CoroutineKind::Async { closure_id, .. } + | CoroutineKind::Gen { closure_id, .. } + | CoroutineKind::AsyncGen { closure_id, .. }, + ) => { + self.visit_generics(generics); + + // For async functions, we need to create their inner defs inside of a + // closure to match their desugared representation. Besides that, + // we must mirror everything that `visit::walk_fn` below does. + self.visit_fn_header(&sig.header); + for param in &sig.decl.inputs { + self.visit_param(param); + } + self.visit_fn_ret_ty(&sig.decl.output); + // If this async fn has no body (i.e. it's an async fn signature in a trait) + // then the closure_def will never be used, and we should avoid generating a + // def-id for it. + if let Some(body) = body { + let closure_def = + self.create_def(closure_id, kw::Empty, DefKind::Closure, span); + self.with_parent(closure_def, |this| this.visit_block(body)); + } + return; } - return; + None => {} } } diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index 8373627d6a0ec..b4fe67023d86b 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -566,7 +566,8 @@ pub fn eq_fn_sig(l: &FnSig, r: &FnSig) -> bool { fn eq_opt_coroutine_kind(l: Option, r: Option) -> bool { match (l, r) { (Some(CoroutineKind::Async { .. }), Some(CoroutineKind::Async { .. })) - | (Some(CoroutineKind::Gen { .. }), Some(CoroutineKind::Gen { .. })) => true, + | (Some(CoroutineKind::Gen { .. }), Some(CoroutineKind::Gen { .. })) + | (Some(CoroutineKind::AsyncGen { .. }), Some(CoroutineKind::AsyncGen { .. })) => true, (None, None) => true, _ => false, } diff --git a/src/tools/rustfmt/src/closures.rs b/src/tools/rustfmt/src/closures.rs index 8970889cfd1d1..6e1263e987464 100644 --- a/src/tools/rustfmt/src/closures.rs +++ b/src/tools/rustfmt/src/closures.rs @@ -266,6 +266,7 @@ fn rewrite_closure_fn_decl( let coro = match coroutine_kind { Some(ast::CoroutineKind::Async { .. }) => "async ", Some(ast::CoroutineKind::Gen { .. }) => "gen ", + Some(ast::CoroutineKind::AsyncGen { .. }) => "async gen ", None => "", }; let mover = if matches!(capture, ast::CaptureBy::Value { .. }) { diff --git a/src/tools/rustfmt/src/utils.rs b/src/tools/rustfmt/src/utils.rs index 4392763cea681..7d7bbf1152905 100644 --- a/src/tools/rustfmt/src/utils.rs +++ b/src/tools/rustfmt/src/utils.rs @@ -79,6 +79,7 @@ pub(crate) fn format_coro(coroutine_kind: &ast::CoroutineKind) -> &'static str { match coroutine_kind { ast::CoroutineKind::Async { .. } => "async ", ast::CoroutineKind::Gen { .. } => "gen ", + ast::CoroutineKind::AsyncGen { .. } => "async gen ", } }