diff options
| author | hkalbasi <hamidrezakalbasi@protonmail.com> | 2023-03-02 13:52:12 +0330 |
|---|---|---|
| committer | hkalbasi <hamidrezakalbasi@protonmail.com> | 2023-03-06 21:09:09 +0330 |
| commit | bf0f99f15ddc00ddc49eb357764a58aaf7a93b02 (patch) | |
| tree | 60c416bdad4a4dc87c5a1ddcca340a5afe0c6644 | |
| parent | 6377d50bd137424a38f2f71bb3eba29d74d02210 (diff) | |
| download | rust-bf0f99f15ddc00ddc49eb357764a58aaf7a93b02.tar.gz rust-bf0f99f15ddc00ddc49eb357764a58aaf7a93b02.zip | |
Fix overloaded deref unused mut false positive
| -rw-r--r-- | crates/hir-ty/src/mir/eval.rs | 12 | ||||
| -rw-r--r-- | crates/hir-ty/src/mir/lower.rs | 11 | ||||
| -rw-r--r-- | crates/ide-diagnostics/src/handlers/mutability_errors.rs | 28 |
3 files changed, 45 insertions, 6 deletions
diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs index b0b09fcd53b..c5d843d9ebd 100644 --- a/crates/hir-ty/src/mir/eval.rs +++ b/crates/hir-ty/src/mir/eval.rs @@ -263,12 +263,14 @@ impl Evaluator<'_> { for proj in &p.projection { match proj { ProjectionElem::Deref => { - match &ty.data(Interner).kind { - TyKind::Ref(_, _, inner) => { - ty = inner.clone(); + ty = match &ty.data(Interner).kind { + TyKind::Raw(_, inner) | TyKind::Ref(_, _, inner) => inner.clone(), + _ => { + return Err(MirEvalError::TypeError( + "Overloaded deref in MIR is disallowed", + )) } - _ => not_supported!("dereferencing smart pointers"), - } + }; let x = from_bytes!(usize, self.read_memory(addr, self.ptr_size())?); addr = Address::from_usize(x); } diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs index f9a66286b28..8e7fb091c03 100644 --- a/crates/hir-ty/src/mir/lower.rs +++ b/crates/hir-ty/src/mir/lower.rs @@ -129,6 +129,12 @@ impl MirLowerCtx<'_> { } Expr::UnaryOp { expr, op } => match op { hir_def::expr::UnaryOp::Deref => { + if !matches!( + self.expr_ty(*expr).kind(Interner), + TyKind::Ref(..) | TyKind::Raw(..) + ) { + return None; + } let mut r = self.lower_expr_as_place(*expr)?; r.projection.push(ProjectionElem::Deref); Some(r) @@ -210,7 +216,7 @@ impl MirLowerCtx<'_> { Adjust::Deref(None) => { r.projection.push(ProjectionElem::Deref); } - Adjust::Deref(Some(_)) => not_supported!("overloaded dereference"), + Adjust::Deref(Some(_)) => not_supported!("implicit overloaded dereference"), Adjust::Borrow(AutoBorrow::Ref(m) | AutoBorrow::RawPtr(m)) => { let tmp = self.temp(adjustment.target.clone())?; self.push_assignment( @@ -757,6 +763,9 @@ impl MirLowerCtx<'_> { Expr::Box { .. } => not_supported!("box expression"), Expr::UnaryOp { expr, op } => match op { hir_def::expr::UnaryOp::Deref => { + if !matches!(self.expr_ty(*expr).kind(Interner), TyKind::Ref(..) | TyKind::Raw(..)) { + not_supported!("explicit overloaded deref"); + } let (mut tmp, Some(current)) = self.lower_expr_to_some_place(*expr, current)? else { return Ok(None); }; diff --git a/crates/ide-diagnostics/src/handlers/mutability_errors.rs b/crates/ide-diagnostics/src/handlers/mutability_errors.rs index a6aa069e27b..1203a961247 100644 --- a/crates/ide-diagnostics/src/handlers/mutability_errors.rs +++ b/crates/ide-diagnostics/src/handlers/mutability_errors.rs @@ -526,4 +526,32 @@ fn f(x: [(i32, u8); 10]) { "#, ); } + + #[test] + fn overloaded_deref() { + check_diagnostics( + r#" +//- minicore: deref_mut +use core::ops::{Deref, DerefMut}; + +struct Foo; +impl Deref for Foo { + type Target = i32; + fn deref(&self) -> &i32 { + &5 + } +} +impl DerefMut for Foo { + fn deref_mut(&mut self) -> &mut i32 { + &mut 5 + } +} +fn f() { + // FIXME: remove this mut and detect error + let mut x = Foo; + let y = &mut *x; +} +"#, + ); + } } |
