You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Under feature(capture_disjoint_fields), unsafe-checking has false positives under unsafe blocks #85561
#![allow(incomplete_features)]// narrow diagnostic output#![feature(capture_disjoint_fields)]// need this to witness the bug consistently in rustc's git history.fnmain(){let val:u8 = 5;let u8_ptr:*constu8 = &val;let _closure = || {unsafe{// Fails compilation with: // error[E0133]: dereference of raw pointer is unsafe and // requires unsafe function or block let tmp = *u8_ptr;
tmp
// Just dereferencing and returning directly compiles fine: // *u8_ptr}};}
I expected to see this happen: Code accepted by compiler
Instead, this happened:
error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
--> src/main.rs:12:23
|
12 | let tmp = *u8_ptr;
| ^^^^^^^ dereference of raw pointer
|
= note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
error: aborting due to previous error
For more information about this error, try `rustc --explain E0133`.
Note: This has same root cause as #85435. But, we're going to address #85435 with a targeted short-term fix (namely PR #85564), so that it won't hit stable. So I'm filing this bug to track fixing the root cause.
searched nightlies: from nightly-2021-03-04 to nightly-2021-05-21
regressed nightly: nightly-2021-03-17
searched commits: from 107896c to f5d8117
regressed commit: f5d8117
The reason we needed the fake reads was because we were trying to convert a less precise place into a closure capture.
Eg: let (a, _) = x and we'd try convert x into a closure capture even though x.0 was being captured. So we added fake reads for the entirety of x.
In the case of raw ptr dereference eg *(some_place), we are capturing some_place and matching on a more precise *(some_place) in the let. Restricting precision of the fake read shouldn't affect this scenario.
Before we jump into the approach outlined by @arora-aman : we are expecting to move the unsafe-checking from MIR to THIR, according to rust-lang/compiler-team#402 . Won't that shift also resolve this issue?
I'm not aware of that, I'll read through that. But I don't think we should be adding fake reads of raw pointers dereference anyway.
As I understand it, the fake reads are less precise closure captures to facilitate pattern matching (in both let and match) and we shouldn't be capturing raw pointer dereference.
It doesn't seem like rust-lang/compiler-team#402 is going to be done any time soon (and I am not entirely sure if that will fix the bug or not), wouldn't it be better for the time being to attempt @arora-aman's suggestion? It should be a quick fix
We are expecting to move the unsafe-checking from MIR to THIR, according to rust-lang/compiler-team#402 . Won't that shift also resolve this issue?
Since yesterday (#85555), dereferences of raw pointers is implemented in the THIR unsafety checker (gated under -Z thir-unsafeck), and it correctly does not report an error here.
I'm not sure how much time it will take to make the THIR unsafety checker the default once it is fully implemented, but the implementation itself is going rather fast (see rust-lang/project-thir-unsafeck#7).
let raw_ptr:*i32;let c = || {let x = *raw_ptr;
....
};
The MIR that will be generated will be something like
FakeRead(ForLet(span), *raw_ptr) // This deref is unsafe
_X = create the closure ...
The reason we have the fake read is to test that the right hand side of the let (and in other examples scrutinee of a match) have been initialized. Since the RHS of let/match scrutinee can be less precise than what a closure captures, we do a FakeRead them outside the closure so as to not capture them for the initialization test.
This means it's fine to do FakeRead an even less precise place, eg. in case of raw pointers don't FakeRead the deref projection.
So my proposal is to apply all the restrictions on closure captures around unsafe code (deref of raw ptr, reference into a repr packed struct) to the Fake Reads that are introduced for let/match on upvars in closure.
Activity
Revert portion of PR rust-lang#83521 that injected issue rust-lang#85435
pnkfelix commentedon May 21, 2021
searched nightlies: from nightly-2021-03-04 to nightly-2021-05-21
regressed nightly: nightly-2021-03-17
searched commits: from 107896c to f5d8117
regressed commit: f5d8117
bisected with cargo-bisect-rustc v0.6.0
Host triple: x86_64-unknown-linux-gnu
Reproduce with:
pnkfelix commentedon May 21, 2021
cc @roxelo
arora-aman commentedon May 21, 2021
So the solution to bug
wouldcould be to call the restrict capture precision functions in https://github.com/rust-lang/rust/blob/master/compiler/rustc_typeck/src/check/upvar.rs#L1589-L1593restrict_capture_precisionrestrict_repr_packed_field_ref_captureI think this would not cause problems because:
Eg:
let (a, _) = xand we'd try convertxinto a closure capture even thoughx.0was being captured. So we added fake reads for the entirety ofx.*(some_place), we are capturingsome_placeand matching on a more precise*(some_place)in the let. Restricting precision of the fake read shouldn't affect this scenario.pnkfelix commentedon May 21, 2021
Before we jump into the approach outlined by @arora-aman : we are expecting to move the unsafe-checking from MIR to THIR, according to rust-lang/compiler-team#402 . Won't that shift also resolve this issue?
arora-aman commentedon May 21, 2021
I'm not aware of that, I'll read through that. But I don't think we should be adding fake reads of raw pointers dereference anyway.
As I understand it, the fake reads are less precise closure captures to facilitate pattern matching (in both let and match) and we shouldn't be capturing raw pointer dereference.
roxelo commentedon May 21, 2021
It doesn't seem like rust-lang/compiler-team#402 is going to be done any time soon (and I am not entirely sure if that will fix the bug or not), wouldn't it be better for the time being to attempt @arora-aman's suggestion? It should be a quick fix
LeSeulArtichaut commentedon May 22, 2021
Since yesterday (#85555), dereferences of raw pointers is implemented in the THIR unsafety checker (gated under
-Z thir-unsafeck), and it correctly does not report an error here.I'm not sure how much time it will take to make the THIR unsafety checker the default once it is fully implemented, but the implementation itself is going rather fast (see rust-lang/project-thir-unsafeck#7).
nikomatsakis commentedon May 24, 2021
@arora-aman @roxelo can you spell out a bit more what is happening? What fake reads do we introduce?
arora-aman commentedon May 24, 2021
So when we have something like
The MIR that will be generated will be something like
The reason we have the fake read is to test that the right hand side of the let (and in other examples scrutinee of a match) have been initialized. Since the RHS of let/match scrutinee can be less precise than what a closure captures, we do a FakeRead them outside the closure so as to not capture them for the initialization test.
This means it's fine to do FakeRead an even less precise place, eg. in case of raw pointers don't FakeRead the deref projection.
So my proposal is to apply all the restrictions on closure captures around unsafe code (deref of raw ptr, reference into a repr packed struct) to the Fake Reads that are introduced for let/match on upvars in closure.
Updated MIR would then be:
nikomatsakis commentedon May 24, 2021
@rustbot assign @roxelo
nikomatsakis commentedon May 24, 2021
OK, I agree that adding the
FakeReadis wrong.Rollup merge of rust-lang#85564 - pnkfelix:issue-85435-readd-capture-…
Rollup merge of rust-lang#85564 - pnkfelix:issue-85435-readd-capture-…
Rollup merge of rust-lang#85564 - pnkfelix:issue-85435-readd-capture-…
Revert portion of PR rust-lang#83521 that injected issue rust-lang#85435
Rollup merge of rust-lang#85724 - sexxi-goose:rox-fix-issue-85435, r=…
Rollup merge of rust-lang#85724 - sexxi-goose:rox-fix-issue-85435, r=…