Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit bf0f99f

Browse files
committed
Fix overloaded deref unused mut false positive
1 parent 6377d50 commit bf0f99f

File tree

3 files changed

+45
-6
lines changed

3 files changed

+45
-6
lines changed

crates/hir-ty/src/mir/eval.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -263,12 +263,14 @@ impl Evaluator<'_> {
263263
for proj in &p.projection {
264264
match proj {
265265
ProjectionElem::Deref => {
266-
match &ty.data(Interner).kind {
267-
TyKind::Ref(_, _, inner) => {
268-
ty = inner.clone();
266+
ty = match &ty.data(Interner).kind {
267+
TyKind::Raw(_, inner) | TyKind::Ref(_, _, inner) => inner.clone(),
268+
_ => {
269+
return Err(MirEvalError::TypeError(
270+
"Overloaded deref in MIR is disallowed",
271+
))
269272
}
270-
_ => not_supported!("dereferencing smart pointers"),
271-
}
273+
};
272274
let x = from_bytes!(usize, self.read_memory(addr, self.ptr_size())?);
273275
addr = Address::from_usize(x);
274276
}

crates/hir-ty/src/mir/lower.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,12 @@ impl MirLowerCtx<'_> {
129129
}
130130
Expr::UnaryOp { expr, op } => match op {
131131
hir_def::expr::UnaryOp::Deref => {
132+
if !matches!(
133+
self.expr_ty(*expr).kind(Interner),
134+
TyKind::Ref(..) | TyKind::Raw(..)
135+
) {
136+
return None;
137+
}
132138
let mut r = self.lower_expr_as_place(*expr)?;
133139
r.projection.push(ProjectionElem::Deref);
134140
Some(r)
@@ -210,7 +216,7 @@ impl MirLowerCtx<'_> {
210216
Adjust::Deref(None) => {
211217
r.projection.push(ProjectionElem::Deref);
212218
}
213-
Adjust::Deref(Some(_)) => not_supported!("overloaded dereference"),
219+
Adjust::Deref(Some(_)) => not_supported!("implicit overloaded dereference"),
214220
Adjust::Borrow(AutoBorrow::Ref(m) | AutoBorrow::RawPtr(m)) => {
215221
let tmp = self.temp(adjustment.target.clone())?;
216222
self.push_assignment(
@@ -757,6 +763,9 @@ impl MirLowerCtx<'_> {
757763
Expr::Box { .. } => not_supported!("box expression"),
758764
Expr::UnaryOp { expr, op } => match op {
759765
hir_def::expr::UnaryOp::Deref => {
766+
if !matches!(self.expr_ty(*expr).kind(Interner), TyKind::Ref(..) | TyKind::Raw(..)) {
767+
not_supported!("explicit overloaded deref");
768+
}
760769
let (mut tmp, Some(current)) = self.lower_expr_to_some_place(*expr, current)? else {
761770
return Ok(None);
762771
};

crates/ide-diagnostics/src/handlers/mutability_errors.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,34 @@ fn f(x: [(i32, u8); 10]) {
523523
//^^^^^ 💡 error: cannot mutate immutable variable `a`
524524
}
525525
}
526+
"#,
527+
);
528+
}
529+
530+
#[test]
531+
fn overloaded_deref() {
532+
check_diagnostics(
533+
r#"
534+
//- minicore: deref_mut
535+
use core::ops::{Deref, DerefMut};
536+
537+
struct Foo;
538+
impl Deref for Foo {
539+
type Target = i32;
540+
fn deref(&self) -> &i32 {
541+
&5
542+
}
543+
}
544+
impl DerefMut for Foo {
545+
fn deref_mut(&mut self) -> &mut i32 {
546+
&mut 5
547+
}
548+
}
549+
fn f() {
550+
// FIXME: remove this mut and detect error
551+
let mut x = Foo;
552+
let y = &mut *x;
553+
}
526554
"#,
527555
);
528556
}

0 commit comments

Comments
 (0)