Skip to content

Commit 7663319

Browse files
committed
Auto merge of rust-lang#15860 - HKalbasi:fix-capture-raw-pointer, r=HKalbasi
Truncate closure capture place for raw pointer fix rust-lang/rust-analyzer#15670 (comment)
2 parents ebb9ed9 + 3bcdb7d commit 7663319

File tree

3 files changed

+48
-0
lines changed

3 files changed

+48
-0
lines changed

Diff for: crates/hir-ty/src/chalk_ext.rs

+5
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ pub trait TyExt {
2828
fn is_unknown(&self) -> bool;
2929
fn contains_unknown(&self) -> bool;
3030
fn is_ty_var(&self) -> bool;
31+
fn is_union(&self) -> bool;
3132

3233
fn as_adt(&self) -> Option<(hir_def::AdtId, &Substitution)>;
3334
fn as_builtin(&self) -> Option<BuiltinType>;
@@ -96,6 +97,10 @@ impl TyExt for Ty {
9697
matches!(self.kind(Interner), TyKind::InferenceVar(_, _))
9798
}
9899

100+
fn is_union(&self) -> bool {
101+
matches!(self.adt_id(Interner), Some(AdtId(hir_def::AdtId::UnionId(_))))
102+
}
103+
99104
fn as_adt(&self) -> Option<(hir_def::AdtId, &Substitution)> {
100105
match self.kind(Interner) {
101106
TyKind::Adt(AdtId(adt), parameters) => Some((*adt, parameters)),

Diff for: crates/hir-ty/src/infer/closure.rs

+27
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,32 @@ impl InferenceContext<'_> {
735735
self.walk_expr(expr);
736736
}
737737

738+
fn restrict_precision_for_unsafe(&mut self) {
739+
for capture in &mut self.current_captures {
740+
let mut ty = self.table.resolve_completely(self.result[capture.place.local].clone());
741+
if ty.as_raw_ptr().is_some() || ty.is_union() {
742+
capture.kind = CaptureKind::ByRef(BorrowKind::Shared);
743+
capture.place.projections.truncate(0);
744+
continue;
745+
}
746+
for (i, p) in capture.place.projections.iter().enumerate() {
747+
ty = p.projected_ty(
748+
ty,
749+
self.db,
750+
|_, _, _| {
751+
unreachable!("Closure field only happens in MIR");
752+
},
753+
self.owner.module(self.db.upcast()).krate(),
754+
);
755+
if ty.as_raw_ptr().is_some() || ty.is_union() {
756+
capture.kind = CaptureKind::ByRef(BorrowKind::Shared);
757+
capture.place.projections.truncate(i + 1);
758+
break;
759+
}
760+
}
761+
}
762+
}
763+
738764
fn adjust_for_move_closure(&mut self) {
739765
for capture in &mut self.current_captures {
740766
if let Some(first_deref) =
@@ -924,6 +950,7 @@ impl InferenceContext<'_> {
924950
self.result.mutated_bindings_in_closure.insert(item.place.local);
925951
}
926952
}
953+
self.restrict_precision_for_unsafe();
927954
// closure_kind should be done before adjust_for_move_closure
928955
let closure_kind = self.closure_kind();
929956
match capture_by {

Diff for: crates/ide-diagnostics/src/handlers/mutability_errors.rs

+16
Original file line numberDiff line numberDiff line change
@@ -1225,6 +1225,22 @@ fn foo(mut foo: Foo) {
12251225
};
12261226
call_me();
12271227
}
1228+
"#,
1229+
);
1230+
}
1231+
1232+
#[test]
1233+
fn regression_15670() {
1234+
check_diagnostics(
1235+
r#"
1236+
//- minicore: fn
1237+
1238+
pub struct A {}
1239+
pub unsafe fn foo(a: *mut A) {
1240+
let mut b = || -> *mut A { &mut *a };
1241+
//^^^^^ 💡 warn: variable does not need to be mutable
1242+
let _ = b();
1243+
}
12281244
"#,
12291245
);
12301246
}

0 commit comments

Comments
 (0)