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.)
Yashb404 2 weeks ago
parent bd24a5d · commit d637b32
-rw-r--r--crates/hir-ty/src/infer.rs4
-rw-r--r--crates/hir-ty/src/infer/expr.rs4
-rw-r--r--crates/hir/src/diagnostics.rs9
-rw-r--r--crates/ide-diagnostics/src/handlers/yield_outside_coroutine.rs34
-rw-r--r--crates/ide-diagnostics/src/lib.rs2
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)
}