Skip to content

MIR-borrowck: add permisson checks to fn access_lvalue #45436

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Merged
merged 3 commits into from
Nov 14, 2017

Conversation

zilbuz
Copy link
Contributor

@zilbuz zilbuz commented Oct 21, 2017

Fix #44837

@rust-highfive
Copy link
Contributor

r? @pnkfelix

(rust_highfive has picked a reviewer for you, use r? to override)

@kennytm kennytm added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Oct 22, 2017
@carols10cents
Copy link
Member

Triage ping @zilbuz! How's it going? Have any questions/need any help?

@bors
Copy link
Collaborator

bors commented Nov 1, 2017

☔ The latest upstream changes (presumably #45538) made this pull request unmergeable. Please resolve the merge conflicts.

@nikomatsakis
Copy link
Contributor

r? @nikomatsakis

@zilbuz zilbuz force-pushed the issue-44837 branch 2 times, most recently from 7424113 to 4652b33 Compare November 12, 2017 11:44
fn check_access_permissions(&self, (lvalue, span): (&Lvalue<'tcx>, Span), kind: ReadOrWrite) {
match kind {
Write(WriteKind::MutableBorrow(BorrowKind::Unique))
| Write(WriteKind::MutableBorrow(BorrowKind::Mut)) => {
Copy link
Contributor

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),
Copy link
Contributor

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() { }

Copy link
Contributor

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.

Copy link
Contributor

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

/// 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))
Copy link
Contributor

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.

ty::TyRawPtr(tnm) => {
match tnm.mutbl {
// `*const` is assumed to be aliasable
hir::MutImmutable => Err(lvalue),
Copy link
Contributor

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(()).

}
},
// Other projections are unique if the base is unique
_ => self.can_host_mutable_ref(&proj.base)
Copy link
Contributor

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 _.

Copy link
Contributor Author

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()?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds good

}
},
// Other projections are unique if the base is unique
_ => self.can_host_mutable_ref(&proj.base)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here: avoid _

| ProjectionElem::ConstantIndex { .. }
| ProjectionElem::Subslice { .. } => Err(lvalue),
// In general we can move from owned content if owner is mobile
_ => self.is_mobile(&proj.base)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid _ here too.

// dynamic drop elaboration
ProjectionElem::Index(..)
| ProjectionElem::ConstantIndex { .. }
| ProjectionElem::Subslice { .. } => Err(lvalue),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style nit: | at end.

},
// All other projections are owned by their base path, so mutable if
// base path is mutable
_ => self.is_mutable(&proj.base)
Copy link
Contributor

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).

Copy link
Contributor

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>.

},
// All other projections are owned by their base path, so mutable if
// base path is mutable
_ => self.is_mutable(&proj.base)
Copy link
Contributor

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).

let local = &self.mir.local_decls[local];
if local.mutability == Mutability::Not {
Err(lvalue)
}
Copy link
Contributor

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 {

match *lvalue {
Lvalue::Local(local) => {
let local = &self.mir.local_decls[local];
if local.mutability == Mutability::Not {
Copy link
Contributor

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.

Copy link
Contributor

@nikomatsakis nikomatsakis left a 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.

@zilbuz zilbuz changed the title [WIP] MIR-borrowck: add permisson checks to fn access_lvalue MIR-borrowck: add permisson checks to fn access_lvalue Nov 13, 2017
@nikomatsakis
Copy link
Contributor

@bors r+

@bors
Copy link
Collaborator

bors commented Nov 13, 2017

📌 Commit cbad2e5 has been approved by nikomatsakis

@bors
Copy link
Collaborator

bors commented Nov 13, 2017

⌛ Testing commit cbad2e5 with merge 212d74f...

bors added a commit that referenced this pull request Nov 13, 2017
MIR-borrowck: add permisson checks to `fn access_lvalue`

WIP : Some FIXME left and some broken tests.

Fix #44837
@bors
Copy link
Collaborator

bors commented Nov 14, 2017

☀️ Test successful - status-appveyor, status-travis
Approved by: nikomatsakis
Pushing 212d74f to master...

@bors bors merged commit cbad2e5 into rust-lang:master Nov 14, 2017
@zilbuz zilbuz deleted the issue-44837 branch November 16, 2017 09:39
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants