-
Notifications
You must be signed in to change notification settings - Fork 13.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MIR-borrowck: add permisson checks to fn access_lvalue
#45436
Conversation
r? @pnkfelix (rust_highfive has picked a reviewer for you, use r? to override) |
Triage ping @zilbuz! How's it going? Have any questions/need any help? |
☔ The latest upstream changes (presumably #45538) made this pull request unmergeable. Please resolve the merge conflicts. |
7424113
to
4652b33
Compare
src/librustc_mir/borrow_check.rs
Outdated
fn check_access_permissions(&self, (lvalue, span): (&Lvalue<'tcx>, Span), kind: ReadOrWrite) { | ||
match kind { | ||
Write(WriteKind::MutableBorrow(BorrowKind::Unique)) | ||
| Write(WriteKind::MutableBorrow(BorrowKind::Mut)) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: the |
goes at the end of the line before under typical style.
ty::TyRef(_, tnm) => { | ||
match tnm.mutbl { | ||
// lvalue represent an aliased location | ||
hir::MutImmutable => Err(lvalue), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, it appears we do allow the use of &mut
there. This example compiles:
fn foo(x: *const &mut u32) {
unsafe {
**x += 1;
}
}
fn main() { }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I was wrong in my writeup, we should just treat *const
the same as *mut
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Er, I meant this for the raw pointer cases below, sorry =) comment on wrong line
src/librustc_mir/borrow_check.rs
Outdated
/// Check the permissions for the given lvalue and read or write kind | ||
fn check_access_permissions(&self, (lvalue, span): (&Lvalue<'tcx>, Span), kind: ReadOrWrite) { | ||
match kind { | ||
Write(WriteKind::MutableBorrow(BorrowKind::Unique)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm I forgot about unique borrows when writing up those rules. They have a different set of conditions than mutable borrows. I think that this actually lines up perfectly with what I called can_host_mutable_ref
, which we could perhaps just call is_unique
. I forget why I changed it from that name. We should just call it is_unique
, and then check that Write(WriteKind::MutableBorrow(BorrowKind::Unique))
requires is_unique
.
src/librustc_mir/borrow_check.rs
Outdated
ty::TyRawPtr(tnm) => { | ||
match tnm.mutbl { | ||
// `*const` is assumed to be aliasable | ||
hir::MutImmutable => Err(lvalue), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is, this should be Ok(())
.
src/librustc_mir/borrow_check.rs
Outdated
} | ||
}, | ||
// Other projections are unique if the base is unique | ||
_ => self.can_host_mutable_ref(&proj.base) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer to avoid the _
here and instead just write out all the cases explicitly. _
makes it much harder to audit. My usual rule is something like this:
- If a new case were added to
ProjectionKind
, what is the chance that this match would be affected?
I'd say "pretty high", therefore we should avoid _
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should I use bug!("Deref of unexpected type")
here? Like in is_mutable()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sounds good
src/librustc_mir/borrow_check.rs
Outdated
} | ||
}, | ||
// Other projections are unique if the base is unique | ||
_ => self.can_host_mutable_ref(&proj.base) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here: avoid _
src/librustc_mir/borrow_check.rs
Outdated
| ProjectionElem::ConstantIndex { .. } | ||
| ProjectionElem::Subslice { .. } => Err(lvalue), | ||
// In general we can move from owned content if owner is mobile | ||
_ => self.is_mobile(&proj.base) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid _
here too.
src/librustc_mir/borrow_check.rs
Outdated
// dynamic drop elaboration | ||
ProjectionElem::Index(..) | ||
| ProjectionElem::ConstantIndex { .. } | ||
| ProjectionElem::Subslice { .. } => Err(lvalue), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style nit: |
at end.
src/librustc_mir/borrow_check.rs
Outdated
}, | ||
// All other projections are owned by their base path, so mutable if | ||
// base path is mutable | ||
_ => self.is_mutable(&proj.base) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid _
here (see other comments for rationale).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, in this particular case, I think we could keep the _
, but write bug!("deref of unexpected type: {:?}", base_ty)
-- deref should (I believe) only be for &T
, *const T
, or Box<T>
.
src/librustc_mir/borrow_check.rs
Outdated
}, | ||
// All other projections are owned by their base path, so mutable if | ||
// base path is mutable | ||
_ => self.is_mutable(&proj.base) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid _
here (see other comments for rationale).
src/librustc_mir/borrow_check.rs
Outdated
let local = &self.mir.local_decls[local]; | ||
if local.mutability == Mutability::Not { | ||
Err(lvalue) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style nit: we usually write } else {
src/librustc_mir/borrow_check.rs
Outdated
match *lvalue { | ||
Lvalue::Local(local) => { | ||
let local = &self.mir.local_decls[local]; | ||
if local.mutability == Mutability::Not { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer an (exhaustive) match
here, which makes it obvious that we've covered every case. I would say that we should keep if
for booleans.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great! I left a bunch of comments, but they are mostly style nits.
fn access_lvalue
fn access_lvalue
@bors r+ |
📌 Commit cbad2e5 has been approved by |
MIR-borrowck: add permisson checks to `fn access_lvalue` WIP : Some FIXME left and some broken tests. Fix #44837
☀️ Test successful - status-appveyor, status-travis |
Fix #44837