Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #22466 from WaterWhisperer/diag-E0596
feat: add diagnostic for E0596
Chayim Refael Friedman 2 weeks ago
parent 354087b · parent 3b5a1b3 · commit 972c4e7
-rw-r--r--crates/hir-ty/src/infer.rs4
-rw-r--r--crates/hir-ty/src/infer/pat.rs2
-rw-r--r--crates/hir/src/diagnostics.rs10
-rw-r--r--crates/ide-diagnostics/src/handlers/mut_ref_in_imm_ref_pat.rs37
-rw-r--r--crates/ide-diagnostics/src/lib.rs2
5 files changed, 54 insertions, 1 deletions
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index 616701f80c..a09dcaafbb 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -409,6 +409,10 @@ pub enum InferenceDiagnostic {
expr: ExprId,
found: StoredTy,
},
+ MutRefInImmRefPat {
+ #[type_visitable(ignore)]
+ pat: PatId,
+ },
CannotImplicitlyDerefTraitObject {
#[type_visitable(ignore)]
pat: PatId,
diff --git a/crates/hir-ty/src/infer/pat.rs b/crates/hir-ty/src/infer/pat.rs
index 915da943ca..81ba37726c 100644
--- a/crates/hir-ty/src/infer/pat.rs
+++ b/crates/hir-ty/src/infer/pat.rs
@@ -916,7 +916,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
if matches!(bm.0, ByRef::Yes(Mutability::Mut))
&& let MutblCap::WeaklyNot = pat_info.max_ref_mutbl
{
- // FIXME: Emit an error: cannot borrow as mutable inside an `&` pattern.
+ self.push_diagnostic(InferenceDiagnostic::MutRefInImmRefPat { pat });
}
// ...and store it in a side table:
diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs
index ed073cb437..616b063419 100644
--- a/crates/hir/src/diagnostics.rs
+++ b/crates/hir/src/diagnostics.rs
@@ -135,6 +135,7 @@ diagnostics![AnyDiagnostic<'db> ->
MissingMatchArms,
MissingUnsafe,
MovedOutOfRef<'db>,
+ MutRefInImmRefPat,
MutableRefBinding,
NeedMut,
NonExhaustiveLet,
@@ -338,6 +339,11 @@ pub struct CannotBeDereferenced<'db> {
}
#[derive(Debug)]
+pub struct MutRefInImmRefPat {
+ pub pat: InFile<ExprOrPatPtr>,
+}
+
+#[derive(Debug)]
pub struct CannotImplicitlyDerefTraitObject<'db> {
pub pat: InFile<ExprOrPatPtr>,
pub found: Type<'db>,
@@ -960,6 +966,10 @@ impl<'db> AnyDiagnostic<'db> {
let expr = expr_syntax(*expr)?;
CannotBeDereferenced { expr, found: new_ty(found.as_ref()) }.into()
}
+ InferenceDiagnostic::MutRefInImmRefPat { pat } => {
+ let pat = pat_syntax(*pat)?.map(Into::into);
+ MutRefInImmRefPat { pat }.into()
+ }
InferenceDiagnostic::CannotImplicitlyDerefTraitObject { pat, found } => {
let pat = pat_syntax(*pat)?.map(Into::into);
CannotImplicitlyDerefTraitObject { pat, found: new_ty(found.as_ref()) }.into()
diff --git a/crates/ide-diagnostics/src/handlers/mut_ref_in_imm_ref_pat.rs b/crates/ide-diagnostics/src/handlers/mut_ref_in_imm_ref_pat.rs
new file mode 100644
index 0000000000..d3c83be359
--- /dev/null
+++ b/crates/ide-diagnostics/src/handlers/mut_ref_in_imm_ref_pat.rs
@@ -0,0 +1,37 @@
+use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext};
+
+// Diagnostic: mut-ref-in-imm-ref-pat
+//
+// This diagnostic is triggered when a binding tries to mutably borrow through
+// an `&` pattern.
+pub(crate) fn mut_ref_in_imm_ref_pat(
+ ctx: &DiagnosticsContext<'_, '_>,
+ d: &hir::MutRefInImmRefPat,
+) -> Diagnostic {
+ Diagnostic::new_with_syntax_node_ptr(
+ ctx,
+ DiagnosticCode::RustcHardError("E0596"),
+ "cannot borrow as mutable inside an `&` pattern",
+ d.pat.map(Into::into),
+ )
+ .stable()
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::tests::check_diagnostics;
+
+ #[test]
+ fn mut_ref_in_imm_ref_pat() {
+ check_diagnostics(
+ r#"
+#![feature(ref_pat_eat_one_layer_2024)]
+
+fn main() {
+ let &ref mut _x = &mut 0;
+ //^^^^^^^^^^ error: cannot borrow as mutable inside an `&` pattern
+}
+"#,
+ );
+ }
+}
diff --git a/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs
index ea0d2d954e..e7d74252d2 100644
--- a/crates/ide-diagnostics/src/lib.rs
+++ b/crates/ide-diagnostics/src/lib.rs
@@ -65,6 +65,7 @@ mod handlers {
pub(crate) mod missing_match_arms;
pub(crate) mod missing_unsafe;
pub(crate) mod moved_out_of_ref;
+ pub(crate) mod mut_ref_in_imm_ref_pat;
pub(crate) mod mutability_errors;
pub(crate) mod mutable_ref;
pub(crate) mod no_such_field;
@@ -479,6 +480,7 @@ pub fn semantic_diagnostics(
AnyDiagnostic::MissingMatchArms(d) => handlers::missing_match_arms::missing_match_arms(&ctx, &d),
AnyDiagnostic::MissingUnsafe(d) => handlers::missing_unsafe::missing_unsafe(&ctx, &d),
AnyDiagnostic::MovedOutOfRef(d) => handlers::moved_out_of_ref::moved_out_of_ref(&ctx, &d),
+ AnyDiagnostic::MutRefInImmRefPat(d) => handlers::mut_ref_in_imm_ref_pat::mut_ref_in_imm_ref_pat(&ctx, &d),
AnyDiagnostic::MutableRefBinding(d) => handlers::mutable_ref::mutable_ref_binding(&ctx, &d),
AnyDiagnostic::NeedMut(d) => match handlers::mutability_errors::need_mut(&ctx, &d) {
Some(it) => it,