Unnamed repository; edit this file 'description' to name the repository.
Fix overloaded deref unused mut false positive
hkalbasi 2023-03-07
parent 6377d50 · commit bf0f99f
-rw-r--r--crates/hir-ty/src/mir/eval.rs12
-rw-r--r--crates/hir-ty/src/mir/lower.rs11
-rw-r--r--crates/ide-diagnostics/src/handlers/mutability_errors.rs28
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 b0b09fcd53..c5d843d9eb 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 f9a66286b2..8e7fb091c0 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 a6aa069e27..1203a96124 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;
+}
+"#,
+ );
+ }
}