mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-03 07:04:49 +00:00
Fix explicit deref problems in closure capture
This commit is contained in:
parent
1ee88db412
commit
7cb4318331
4 changed files with 90 additions and 4 deletions
|
@ -190,6 +190,16 @@ impl InferenceContext<'_> {
|
|||
}
|
||||
return Some(place);
|
||||
}
|
||||
Expr::UnaryOp { expr, op: UnaryOp::Deref } => {
|
||||
if matches!(
|
||||
self.expr_ty_after_adjustments(*expr).kind(Interner),
|
||||
TyKind::Ref(..) | TyKind::Raw(..)
|
||||
) {
|
||||
let mut place = self.place_of_expr(*expr)?;
|
||||
place.projections.push(ProjectionElem::Deref);
|
||||
return Some(place);
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
None
|
||||
|
@ -371,7 +381,12 @@ impl InferenceContext<'_> {
|
|||
}
|
||||
Expr::Field { expr, name: _ } => self.select_from_expr(*expr),
|
||||
Expr::UnaryOp { expr, op: UnaryOp::Deref } => {
|
||||
if let Some((f, _)) = self.result.method_resolution(tgt_expr) {
|
||||
if matches!(
|
||||
self.expr_ty_after_adjustments(*expr).kind(Interner),
|
||||
TyKind::Ref(..) | TyKind::Raw(..)
|
||||
) {
|
||||
self.select_from_expr(*expr);
|
||||
} else if let Some((f, _)) = self.result.method_resolution(tgt_expr) {
|
||||
let mutability = 'b: {
|
||||
if let Some(deref_trait) =
|
||||
self.resolve_lang_item(LangItem::DerefMut).and_then(|x| x.as_trait())
|
||||
|
@ -461,10 +476,20 @@ impl InferenceContext<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
fn expr_ty(&mut self, expr: ExprId) -> Ty {
|
||||
fn expr_ty(&self, expr: ExprId) -> Ty {
|
||||
self.result[expr].clone()
|
||||
}
|
||||
|
||||
fn expr_ty_after_adjustments(&self, e: ExprId) -> Ty {
|
||||
let mut ty = None;
|
||||
if let Some(x) = self.result.expr_adjustments.get(&e) {
|
||||
if let Some(x) = x.last() {
|
||||
ty = Some(x.target.clone());
|
||||
}
|
||||
}
|
||||
ty.unwrap_or_else(|| self.expr_ty(e))
|
||||
}
|
||||
|
||||
fn is_upvar(&self, place: &HirPlace) -> bool {
|
||||
let b = &self.body[place.local];
|
||||
if let Some(c) = self.current_closure {
|
||||
|
@ -701,7 +726,9 @@ impl InferenceContext<'_> {
|
|||
};
|
||||
self.consume_expr(*body);
|
||||
for item in &self.current_captures {
|
||||
if matches!(item.kind, CaptureKind::ByRef(BorrowKind::Mut { .. })) {
|
||||
if matches!(item.kind, CaptureKind::ByRef(BorrowKind::Mut { .. }))
|
||||
&& !item.place.projections.contains(&ProjectionElem::Deref)
|
||||
{
|
||||
// FIXME: remove the `mutated_bindings_in_closure` completely and add proper fake reads in
|
||||
// MIR. I didn't do that due duplicate diagnostics.
|
||||
self.result.mutated_bindings_in_closure.insert(item.place.local);
|
||||
|
|
|
@ -40,6 +40,15 @@ fn ref_simple() {
|
|||
y
|
||||
}
|
||||
}
|
||||
size_and_align_expr! {
|
||||
minicore: copy, deref_mut;
|
||||
stmts: [
|
||||
let y: &mut i32 = &mut 5;
|
||||
]
|
||||
|x: i32| {
|
||||
*y += x;
|
||||
}
|
||||
}
|
||||
size_and_align_expr! {
|
||||
minicore: copy;
|
||||
stmts: [
|
||||
|
@ -50,6 +59,16 @@ fn ref_simple() {
|
|||
x
|
||||
}
|
||||
}
|
||||
size_and_align_expr! {
|
||||
minicore: copy, deref_mut;
|
||||
stmts: [
|
||||
struct X(i32, i64);
|
||||
let x: &mut X = &mut X(2, 6);
|
||||
]
|
||||
|| {
|
||||
(*x).0 as i64 + x.1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue