Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Properly report error on const gen fn #130252

Merged
merged 2 commits into from
Sep 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2602,12 +2602,12 @@ impl CoroutineKind {
}
}

pub fn is_async(self) -> bool {
matches!(self, CoroutineKind::Async { .. })
}

pub fn is_gen(self) -> bool {
matches!(self, CoroutineKind::Gen { .. })
pub fn as_str(self) -> &'static str {
match self {
CoroutineKind::Async { .. } => "async",
CoroutineKind::Gen { .. } => "gen",
CoroutineKind::AsyncGen { .. } => "async gen",
}
}

pub fn closure_id(self) -> NodeId {
Expand Down
10 changes: 5 additions & 5 deletions compiler/rustc_ast_passes/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,15 @@ ast_passes_body_in_extern = incorrect `{$kind}` inside `extern` block

ast_passes_bound_in_context = bounds on `type`s in {$ctx} have no effect

ast_passes_const_and_async = functions cannot be both `const` and `async`
.const = `const` because of this
.async = `async` because of this
.label = {""}

ast_passes_const_and_c_variadic = functions cannot be both `const` and C-variadic
.const = `const` because of this
.variadic = C-variadic because of this

ast_passes_const_and_coroutine = functions cannot be both `const` and `{$coroutine_kind}`
.const = `const` because of this
.coroutine = `{$coroutine_kind}` because of this
.label = {""}

ast_passes_const_bound_trait_object = const trait bounds are not allowed in trait object types

ast_passes_const_without_body =
Expand Down
17 changes: 6 additions & 11 deletions compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1418,21 +1418,16 @@ impl<'a> Visitor<'a> for AstValidator<'a> {

// Functions cannot both be `const async` or `const gen`
if let Some(&FnHeader {
constness: Const::Yes(cspan),
constness: Const::Yes(const_span),
coroutine_kind: Some(coroutine_kind),
..
}) = fk.header()
{
let aspan = match coroutine_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.dcx().emit_err(errors::ConstAndAsync {
spans: vec![cspan, aspan],
cspan,
aspan,
self.dcx().emit_err(errors::ConstAndCoroutine {
spans: vec![coroutine_kind.span(), const_span],
const_span,
coroutine_span: coroutine_kind.span(),
coroutine_kind: coroutine_kind.as_str(),
span,
});
}
Expand Down
11 changes: 6 additions & 5 deletions compiler/rustc_ast_passes/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -657,16 +657,17 @@ pub(crate) enum TildeConstReason {
}

#[derive(Diagnostic)]
#[diag(ast_passes_const_and_async)]
pub(crate) struct ConstAndAsync {
#[diag(ast_passes_const_and_coroutine)]
pub(crate) struct ConstAndCoroutine {
#[primary_span]
pub spans: Vec<Span>,
#[label(ast_passes_const)]
pub cspan: Span,
#[label(ast_passes_async)]
pub aspan: Span,
pub const_span: Span,
#[label(ast_passes_coroutine)]
pub coroutine_span: Span,
#[label]
pub span: Span,
pub coroutine_kind: &'static str,
}

#[derive(Diagnostic)]
Expand Down
12 changes: 11 additions & 1 deletion src/tools/clippy/clippy_utils/src/ast_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
) => {
eq_closure_binder(lb, rb)
&& lc == rc
&& la.map_or(false, CoroutineKind::is_async) == ra.map_or(false, CoroutineKind::is_async)
&& eq_coroutine_kind(*la, *ra)
&& lm == rm
&& eq_fn_decl(lf, rf)
&& eq_expr(le, re)
Expand All @@ -241,6 +241,16 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
}
}

fn eq_coroutine_kind(a: Option<CoroutineKind>, b: Option<CoroutineKind>) -> bool {
match (a, b) {
(Some(CoroutineKind::Async { .. }), Some(CoroutineKind::Async { .. }))
| (Some(CoroutineKind::Gen { .. }), Some(CoroutineKind::Gen { .. }))
| (Some(CoroutineKind::AsyncGen { .. }), Some(CoroutineKind::AsyncGen { .. }))
| (None, None) => true,
_ => false,
}
}

pub fn eq_field(l: &ExprField, r: &ExprField) -> bool {
l.is_placeholder == r.is_placeholder
&& eq_id(l.ident, r.ident)
Expand Down
12 changes: 12 additions & 0 deletions tests/ui/coroutine/const_gen_fn.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//@ edition:2024
//@ compile-flags: -Zunstable-options

#![feature(gen_blocks)]

const gen fn a() {}
//~^ ERROR functions cannot be both `const` and `gen`

const async gen fn b() {}
//~^ ERROR functions cannot be both `const` and `async gen`

fn main() {}
20 changes: 20 additions & 0 deletions tests/ui/coroutine/const_gen_fn.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
error: functions cannot be both `const` and `gen`
--> $DIR/const_gen_fn.rs:6:1
|
LL | const gen fn a() {}
| ^^^^^-^^^----------
| | |
| | `gen` because of this
| `const` because of this
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems so obvious make it feels a bit redundant. 😄

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah... preexisting though


error: functions cannot be both `const` and `async gen`
--> $DIR/const_gen_fn.rs:9:1
|
LL | const async gen fn b() {}
| ^^^^^-^^^^^^^^^----------
| | |
| | `async gen` because of this
| `const` because of this

error: aborting due to 2 previous errors

Loading