Make some matches exhaustive to avoid bugs, fix tools
This commit is contained in:
parent
a208bae00e
commit
44911b7c67
8 changed files with 71 additions and 45 deletions
|
@ -1035,6 +1035,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
let (Some(coroutine_kind), Some(body)) = (coroutine_kind, body) else {
|
let (Some(coroutine_kind), Some(body)) = (coroutine_kind, body) else {
|
||||||
return self.lower_fn_body_block(span, decl, body);
|
return self.lower_fn_body_block(span, decl, body);
|
||||||
};
|
};
|
||||||
|
// FIXME(gen_blocks): Introduce `closure_id` method and remove ALL destructuring.
|
||||||
let (CoroutineKind::Async { closure_id, .. }
|
let (CoroutineKind::Async { closure_id, .. }
|
||||||
| CoroutineKind::Gen { closure_id, .. }
|
| CoroutineKind::Gen { closure_id, .. }
|
||||||
| CoroutineKind::AsyncGen { closure_id, .. }) = coroutine_kind;
|
| CoroutineKind::AsyncGen { closure_id, .. }) = coroutine_kind;
|
||||||
|
|
|
@ -1271,14 +1271,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||||
// Functions cannot both be `const async` or `const gen`
|
// Functions cannot both be `const async` or `const gen`
|
||||||
if let Some(&FnHeader {
|
if let Some(&FnHeader {
|
||||||
constness: Const::Yes(cspan),
|
constness: Const::Yes(cspan),
|
||||||
coroutine_kind:
|
coroutine_kind: Some(coro_kind),
|
||||||
Some(
|
|
||||||
CoroutineKind::Async { span: aspan, .. }
|
|
||||||
| CoroutineKind::Gen { span: aspan, .. },
|
|
||||||
),
|
|
||||||
..
|
..
|
||||||
}) = fk.header()
|
}) = 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`
|
// FIXME(gen_blocks): Report a different error for `const gen`
|
||||||
self.err_handler().emit_err(errors::ConstAndAsync {
|
self.err_handler().emit_err(errors::ConstAndAsync {
|
||||||
spans: vec![cspan, aspan],
|
spans: vec![cspan, aspan],
|
||||||
|
|
|
@ -541,12 +541,30 @@ fn check_test_signature(
|
||||||
return Err(sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "unsafe" }));
|
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 {
|
if let Some(coro_kind) = f.sig.header.coroutine_kind {
|
||||||
return Err(sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "async" }));
|
match coro_kind {
|
||||||
}
|
ast::CoroutineKind::Async { span, .. } => {
|
||||||
|
return Err(sd.emit_err(errors::TestBadFn {
|
||||||
if let Some(ast::CoroutineKind::Gen { span, .. }) = f.sig.header.coroutine_kind {
|
span: i.span,
|
||||||
return Err(sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "gen" }));
|
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
|
// If the termination trait is active, the compiler will check that the output
|
||||||
|
|
|
@ -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
|
// Explicitly check for lints associated with 'closure_id', since
|
||||||
// it does not have a corresponding AST node
|
// it does not have a corresponding AST node
|
||||||
if let ast_visit::FnKind::Fn(_, _, sig, _, _, _) = fk {
|
if let ast_visit::FnKind::Fn(_, _, sig, _, _, _) = fk {
|
||||||
if let Some(
|
if let Some(coro_kind) = sig.header.coroutine_kind {
|
||||||
ast::CoroutineKind::Async { closure_id, .. }
|
let (ast::CoroutineKind::Async { closure_id, .. }
|
||||||
| ast::CoroutineKind::Gen { closure_id, .. },
|
| ast::CoroutineKind::Gen { closure_id, .. }
|
||||||
) = sig.header.coroutine_kind
|
| ast::CoroutineKind::AsyncGen { closure_id, .. }) = coro_kind;
|
||||||
{
|
|
||||||
self.check_id(closure_id);
|
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
|
// it does not have a corresponding AST node
|
||||||
match e.kind {
|
match e.kind {
|
||||||
ast::ExprKind::Closure(box ast::Closure {
|
ast::ExprKind::Closure(box ast::Closure {
|
||||||
coroutine_kind:
|
coroutine_kind: Some(coro_kind), ..
|
||||||
Some(
|
}) => {
|
||||||
ast::CoroutineKind::Async { closure_id, .. }
|
let (ast::CoroutineKind::Async { closure_id, .. }
|
||||||
| ast::CoroutineKind::Gen { closure_id, .. },
|
| ast::CoroutineKind::Gen { closure_id, .. }
|
||||||
),
|
| ast::CoroutineKind::AsyncGen { closure_id, .. }) = coro_kind;
|
||||||
..
|
self.check_id(closure_id);
|
||||||
}) => self.check_id(closure_id),
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
lint_callback!(self, check_expr_post, e);
|
lint_callback!(self, check_expr_post, e);
|
||||||
|
|
|
@ -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) {
|
fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) {
|
||||||
if let FnKind::Fn(_, _, sig, _, generics, body) = fn_kind {
|
if let FnKind::Fn(_, _, sig, _, generics, body) = fn_kind {
|
||||||
if let Some(
|
match sig.header.coroutine_kind {
|
||||||
CoroutineKind::Async { closure_id, .. } | CoroutineKind::Gen { closure_id, .. },
|
Some(
|
||||||
) = sig.header.coroutine_kind
|
CoroutineKind::Async { closure_id, .. }
|
||||||
{
|
| CoroutineKind::Gen { closure_id, .. }
|
||||||
self.visit_generics(generics);
|
| CoroutineKind::AsyncGen { closure_id, .. },
|
||||||
|
) => {
|
||||||
|
self.visit_generics(generics);
|
||||||
|
|
||||||
// For async functions, we need to create their inner defs inside of a
|
// For async functions, we need to create their inner defs inside of a
|
||||||
// closure to match their desugared representation. Besides that,
|
// closure to match their desugared representation. Besides that,
|
||||||
// we must mirror everything that `visit::walk_fn` below does.
|
// we must mirror everything that `visit::walk_fn` below does.
|
||||||
self.visit_fn_header(&sig.header);
|
self.visit_fn_header(&sig.header);
|
||||||
for param in &sig.decl.inputs {
|
for param in &sig.decl.inputs {
|
||||||
self.visit_param(param);
|
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;
|
||||||
}
|
}
|
||||||
self.visit_fn_ret_ty(&sig.decl.output);
|
None => {}
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -566,7 +566,8 @@ pub fn eq_fn_sig(l: &FnSig, r: &FnSig) -> bool {
|
||||||
fn eq_opt_coroutine_kind(l: Option<CoroutineKind>, r: Option<CoroutineKind>) -> bool {
|
fn eq_opt_coroutine_kind(l: Option<CoroutineKind>, r: Option<CoroutineKind>) -> bool {
|
||||||
match (l, r) {
|
match (l, r) {
|
||||||
(Some(CoroutineKind::Async { .. }), Some(CoroutineKind::Async { .. }))
|
(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,
|
(None, None) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
|
|
|
@ -275,6 +275,7 @@ fn rewrite_closure_fn_decl(
|
||||||
let coro = match coroutine_kind {
|
let coro = match coroutine_kind {
|
||||||
Some(ast::CoroutineKind::Async { .. }) => "async ",
|
Some(ast::CoroutineKind::Async { .. }) => "async ",
|
||||||
Some(ast::CoroutineKind::Gen { .. }) => "gen ",
|
Some(ast::CoroutineKind::Gen { .. }) => "gen ",
|
||||||
|
Some(ast::CoroutineKind::AsyncGen { .. }) => "async gen ",
|
||||||
None => "",
|
None => "",
|
||||||
};
|
};
|
||||||
let mover = if matches!(capture, ast::CaptureBy::Value { .. }) {
|
let mover = if matches!(capture, ast::CaptureBy::Value { .. }) {
|
||||||
|
|
|
@ -79,6 +79,7 @@ pub(crate) fn format_coro(coroutine_kind: &ast::CoroutineKind) -> &'static str {
|
||||||
match coroutine_kind {
|
match coroutine_kind {
|
||||||
ast::CoroutineKind::Async { .. } => "async ",
|
ast::CoroutineKind::Async { .. } => "async ",
|
||||||
ast::CoroutineKind::Gen { .. } => "gen ",
|
ast::CoroutineKind::Gen { .. } => "gen ",
|
||||||
|
ast::CoroutineKind::AsyncGen { .. } => "async gen ",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue