Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #22466 from WaterWhisperer/diag-E0596
feat: add diagnostic for E0596
| -rw-r--r-- | crates/hir-ty/src/infer.rs | 4 | ||||
| -rw-r--r-- | crates/hir-ty/src/infer/pat.rs | 2 | ||||
| -rw-r--r-- | crates/hir/src/diagnostics.rs | 10 | ||||
| -rw-r--r-- | crates/ide-diagnostics/src/handlers/mut_ref_in_imm_ref_pat.rs | 37 | ||||
| -rw-r--r-- | crates/ide-diagnostics/src/lib.rs | 2 |
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, |