-
Notifications
You must be signed in to change notification settings - Fork 606
explicitly keep the door open for some but not all subobject provenance #2338
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -39,6 +39,18 @@ r[undefined.alias] | |
|
|
||
| All this also applies when values of these types are passed in a (nested) field of a compound type, but not behind pointer indirections. | ||
|
|
||
| r[undefined.subobject] | ||
| * Using a pointer or reference outside the subrange of memory it is allowed to access. | ||
|
|
||
| Generally, a reference may only access the memory it [points to]. | ||
| This restriction also applies to all raw pointers derived from this reference. | ||
| The one exception is that a reference to an element of an array or slice may be used to access other elements of the same array or slice without immediately causing undefined behavior. | ||
| This exception also applies for nested arrays, but not for fields of values inside arrays. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we clarify what "this exception also applies for nested arrays" means? I presume it means that you can go from e.g.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is all just meant to say "as long as you're not projecting to a field, you're not restricted to a subobject". I am not sure what the best way to say that is. |
||
|
|
||
| Furthermore, a reference to a field of an enum may not be used to change the discriminant of said enum. | ||
| If the tag lies inside the range of memory accessible by the reference (as in the previous paragraph), then the reference may be used to *temporarily* change the discriminant of the enum without immediately causing undefined behavior, but the original discriminant must be restored before the lifetime of the reference ends. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does "as in the previous paragraph" refer to?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Writing the tag may violate subobject provenance. So temporarily changing the discriminant is only allowed if that discriminant actually lies within the memory range this pointer is allowed to mutate.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What if changing the discriminant has the effect of just doing a transmute? E.g.: #[repr(u8)]
enum Zero { Zero = 0 }
#[repr(u8)]
enum One { One = 1 }
enum Bit {
Zero(Zero),
One(One),
}If Rust chooses to niche-optimize
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
No. That's the kind of code @digama0 would like to disallow. I don't necessarily agree, but want to make some progress without having to resolve the question entirely, so this PR does not intend to allow it.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We often say that lifetimes are not relevant to opsem. What does the term "lifetime" mean in this context? Is this about crossing an API boundary (i.e., this is really a safety thing about what you're allowed to assume when an enum reference/pointer crosses an API boundary), or is this about SB/TB, or something else?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I use "lifetime" here for the same reason that it is already used one bullet point up the list: this isn't the final opsem, it is an approximation to give users some guidance. We don't want to specify when exactly provenance gets invalidated due to conflicting accesses. In SB/TB, this happens some time after the lifetime ends. But if we conservatively say that it happens exactly when the lifetime ends, that's a useful approximation. This is already the wording we use here, so I followed the same approach for this new item in the list. |
||
| This restriction also applies to all raw pointers derived from this reference. | ||
|
|
||
| r[undefined.immutable] | ||
| * Mutating immutable bytes. All bytes reachable through a [const-promoted] expression are immutable, as well as bytes reachable through borrows in `static` and `const` initializers that have been [lifetime-extended] to `'static`. The bytes owned by an immutable binding or immutable `static` are immutable, unless those bytes are part of an [`UnsafeCell<U>`]. | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
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.
How does this play with transmutes? Consider:
This goes from:
&Pairto&[usize; 8](a sound transmute)Presumably if we skipped the
&Pair -> &[usize; 8]step and instead constructedi0from&pair.first[0], this would be unsound because it would entail jumping betweenfirstandsecond.Two questions:
&Pair -> &[usize; 8], it would not be sound?View changes since the review
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.
The narrowing is attached to field projections. So as long as you don't do field projections, you retain access to the full allocation. Your example code does not do field projections, so it is fine.
Indeed, now there is a field projection that narrows the provenance.