mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 21:13:37 +00:00
Fix overloaded deref unused mut false positive
This commit is contained in:
parent
6377d50bd1
commit
bf0f99f15d
3 changed files with 45 additions and 6 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -523,6 +523,34 @@ fn f(x: [(i32, u8); 10]) {
|
|||
//^^^^^ 💡 error: cannot mutate immutable variable `a`
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[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;
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue