Unnamed repository; edit this file 'description' to name the repository.
feat: Report E0627 for yield expressions outside of coroutines
This resolves a FIXME in `hir-ty` by correctly reporting when a `yield`
expression is used outside of a valid coroutine context, surfacing it to
the IDE as `E0627`.
This addresses one of the missing type inference diagnostics tracked in rust-lang/rust-analyzer#22140.
(Note: AI was used as a tool to help write and review this code contribution.)
| -rw-r--r-- | crates/hir-ty/src/infer.rs | 4 | ||||
| -rw-r--r-- | crates/hir-ty/src/infer/expr.rs | 4 | ||||
| -rw-r--r-- | crates/hir/src/diagnostics.rs | 9 | ||||
| -rw-r--r-- | crates/ide-diagnostics/src/handlers/yield_outside_coroutine.rs | 34 | ||||
| -rw-r--r-- | crates/ide-diagnostics/src/lib.rs | 2 |
5 files changed, 52 insertions, 1 deletions
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs index a09dcaafbb..5558d8fd47 100644 --- a/crates/hir-ty/src/infer.rs +++ b/crates/hir-ty/src/infer.rs @@ -508,6 +508,10 @@ pub enum InferenceDiagnostic { #[type_visitable(ignore)] pat: PatId, }, + YieldOutsideCoroutine { + #[type_visitable(ignore)] + expr: ExprId, + }, } #[derive(Debug, PartialEq, Eq, Clone)] diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index 5f752da3d0..3356c4d78a 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/crates/hir-ty/src/infer/expr.rs @@ -597,7 +597,9 @@ impl<'db> InferenceContext<'_, 'db> { } resume_ty } else { - // FIXME: report error (yield expr in non-coroutine) + self.push_diagnostic(InferenceDiagnostic::YieldOutsideCoroutine { + expr: tgt_expr, + }); self.types.types.error } } diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs index 616b063419..d99ed37d7e 100644 --- a/crates/hir/src/diagnostics.rs +++ b/crates/hir/src/diagnostics.rs @@ -178,6 +178,7 @@ diagnostics![AnyDiagnostic<'db> -> TypeMustBeKnown<'db>, UnionExprMustHaveExactlyOneField, UnimplementedTrait<'db>, + YieldOutsideCoroutine, ]; #[derive(Debug)] @@ -671,6 +672,11 @@ pub struct MutableRefBinding { pub pat: InFile<ExprOrPatPtr>, } +#[derive(Debug)] +pub struct YieldOutsideCoroutine { + pub expr: InFile<ExprOrPatPtr>, +} + impl<'db> AnyDiagnostic<'db> { pub(crate) fn body_validation_diagnostic( db: &'db dyn HirDatabase, @@ -1102,6 +1108,9 @@ impl<'db> AnyDiagnostic<'db> { let pat = pat_syntax(*pat)?.map(Into::into); MutableRefBinding { pat }.into() } + &InferenceDiagnostic::YieldOutsideCoroutine { expr } => { + YieldOutsideCoroutine { expr: expr_syntax(expr)? }.into() + } }) } diff --git a/crates/ide-diagnostics/src/handlers/yield_outside_coroutine.rs b/crates/ide-diagnostics/src/handlers/yield_outside_coroutine.rs new file mode 100644 index 0000000000..39288c2817 --- /dev/null +++ b/crates/ide-diagnostics/src/handlers/yield_outside_coroutine.rs @@ -0,0 +1,34 @@ +use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext}; + +// Diagnostic: yield-outside-of-coroutine +// +// This diagnostic is triggered if the `yield` keyword is used outside of a coroutine. +pub(crate) fn yield_outside_coroutine( + ctx: &DiagnosticsContext<'_, '_>, + d: &hir::YieldOutsideCoroutine, +) -> Diagnostic { + Diagnostic::new_with_syntax_node_ptr( + ctx, + DiagnosticCode::RustcHardError("E0627"), + "yield expression outside of coroutine", + d.expr.map(|it| it.into()), + ) +} + +#[cfg(test)] +mod tests { + use crate::tests::check_diagnostics; + + #[test] + fn yield_in_regular_function() { + check_diagnostics( + r#" +//- minicore: coroutine +fn foo() { + yield 1; + //^^^^^^^ error: yield expression outside of coroutine +} +"#, + ); + } +} diff --git a/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs index e7d74252d2..5a14d1bba8 100644 --- a/crates/ide-diagnostics/src/lib.rs +++ b/crates/ide-diagnostics/src/lib.rs @@ -101,6 +101,7 @@ mod handlers { pub(crate) mod unresolved_module; pub(crate) mod unused_must_use; pub(crate) mod unused_variables; + pub(crate) mod yield_outside_coroutine; // The handlers below are unusual, the implement the diagnostics as well. pub(crate) mod field_shorthand; @@ -553,6 +554,7 @@ pub fn semantic_diagnostics( AnyDiagnostic::UnimplementedTrait(d) => handlers::unimplemented_trait::unimplemented_trait(&ctx, &d), AnyDiagnostic::FruInDestructuringAssignment(d) => handlers::fru_in_destructuring_assignment::fru_in_destructuring_assignment(&ctx, &d), AnyDiagnostic::ExplicitDropMethodUse(d) => handlers::explicit_drop_method_use::explicit_drop_method_use(&ctx, &d), + AnyDiagnostic::YieldOutsideCoroutine(d) => handlers::yield_outside_coroutine::yield_outside_coroutine(&ctx, &d), }; res.push(d) } |