-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Implement the unsafe-fields RFC. #132915
base: master
Are you sure you want to change the base?
Implement the unsafe-fields RFC. #132915
Conversation
Some changes occurred in src/tools/rustfmt cc @rust-lang/rustfmt |
This comment has been minimized.
This comment has been minimized.
4cbe0ee
to
2cda185
Compare
Changes to the size of AST and/or HIR nodes. cc @nnethercote |
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.
Thanks for implementing this! Here's a first round of comments. :-)
This comment has been minimized.
This comment has been minimized.
2cda185
to
e83abf1
Compare
This comment has been minimized.
This comment has been minimized.
e83abf1
to
d25841e
Compare
This comment has been minimized.
This comment has been minimized.
d25841e
to
6a5fbe3
Compare
ff9aee3
to
db32d80
Compare
@bors try @rust-timer queue |
This comment has been minimized.
This comment has been minimized.
Draft implementation of unsafe-fields. RFC: rust-lang/rfcs#3458 Tracking: - rust-lang#132922 r? jswrenn
☀️ Try build successful - checks-actions |
This comment has been minimized.
This comment has been minimized.
Finished benchmarking commit (ce25ffa): comparison URL. Overall result: ❌✅ regressions and improvements - no action neededBenchmarking this pull request likely means that it is perf-sensitive, so we're automatically marking it as not fit for rolling up. While you can manually mark this PR as fit for rollup, we strongly recommend not doing so since this PR may lead to changes in compiler perf. @bors rollup=never Instruction countThis is the most reliable metric that we have; it was used to determine the overall result at the top of this comment. However, even this metric can sometimes exhibit noise.
Max RSS (memory usage)Results (primary -0.7%)This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
CyclesResults (secondary 1.7%)This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
Binary sizeResults (primary 0.2%, secondary 0.3%)This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
Bootstrap: 787.726s -> 783.8s (-0.50%) |
The UI testing checklist I'd like to see completed before we merge this:
|
db32d80
to
44c1339
Compare
Changes to the size of AST and/or HIR nodes. cc @nnethercote |
This comment has been minimized.
This comment has been minimized.
44c1339
to
c133735
Compare
☔ The latest upstream changes (presumably #133212) made this pull request unmergeable. Please resolve the merge conflicts. |
c133735
to
3a0a424
Compare
3a0a424
to
b5d31a4
Compare
☔ The latest upstream changes (presumably #133280) made this pull request unmergeable. Please resolve the merge conflicts. |
b5d31a4
to
94e9d7e
Compare
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.
This is looking pretty good. Be sure to update the commit message, too! It's no longer a draft implementation — it's just an implementation. :-)
safe_field: u32, | ||
} | ||
|
||
impl WithUnsafeField { |
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.
Can you add a test tracking the behavior of this:
&raw const self.unsafe_field
I think (but am not completely certain) it's safe, but we should probably require unsafe
in the initial implementation.
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 think I would prefer this to be unsafe
-- of course, to do something with the result of this that could possibly cause problems requires some other form of unsafe somewhere else (I think...), but making this unsafe
is IMO nice because it improves locality-of-safety:
let ptr = &raw const self.unsafe_field;
// lots of code
unsafe { do_something_with_ptr }
I think it'd be nice to have some sign somewhere that ptr
actually comes from an unsafe field.
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 think (but am not completely certain) it's safe
It's not safe. All field accesses are "inbounds", so they need to point to valid memory to even take the offset.
94e9d7e
to
0ddfeb9
Compare
This comment has been minimized.
This comment has been minimized.
Co-Authored-By: Jacob Pratt <jacob@jhpratt.dev>
0ddfeb9
to
d796143
Compare
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.
Generally looks okay. I've got some minor comments about style and code deduplication.
fn parse_unsafe_field(&mut self) -> Safety { | ||
// not using parse_safety as that also accepts `safe`. | ||
if self.eat_keyword(kw::Unsafe) { | ||
let span = self.prev_token.uninterpolated_span(); |
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.
Why are you gating the uninterpolated span? Everywhere else in the parser seems to gate on prev_token.span
.
if let ty::Adt(adt_def, ..) = pat.ty.kind() { | ||
for pat in subpatterns { | ||
let field = &pat.field; | ||
if adt_def.variants().iter().next().unwrap().fields[*field].safety |
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 think you should use non_enum_variant
here:
if adt_def.variants().iter().next().unwrap().fields[*field].safety | |
if adt_def.non_enum_variant().fields[*field].safety |
I don't think(?) we use PatKind::Leaf
for enums ever.
if let ty::Adt(adt_def, ..) = pat.ty.kind() { | ||
for pat in subpatterns { | ||
let field = &pat.field; |
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.
Why are you taking a ref of a FieldIdx
, just to deref it below?
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.
Just inline this into the .fields[&pat.field]
below.
@@ -1599,6 +1599,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { | |||
f.did.index | |||
})); | |||
|
|||
for field in &variant.fields { | |||
self.tables.safety.set_some(field.did.index, field.safety); |
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.
record!(self.tables.safety[field.did] <- field.safety);
for variant in def.variants() { | ||
for field in &variant.fields { |
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.
This can be a single for loop with def.all_fields()
.
continue; | ||
}; | ||
|
||
if !allowed_union_or_unsafe_field(field_ty, tcx, typing_env) { |
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.
tiny nit: always pass tcx as the first field
let (field_span, ty_span) = match tcx.hir().get_if_local(field.did) { | ||
// We are currently checking the type this field came from, so it must be local. | ||
Some(Node::Field(field)) => (field.span, field.ty.span), | ||
_ => unreachable!("mir field has to correspond to hir field"), |
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.
This comment doesn't really make sense. This isn't a "MIR" field, it's just the middle typing layer.
I think this can be simplified to field.did.expect_local()
, though, no need for the match.
} else if field_ty.needs_drop(tcx, typing_env) { | ||
// This should never happen. But we can get here e.g. in case of name resolution errors. | ||
tcx.dcx() | ||
.span_delayed_bug(span, "we should never accept maybe-dropping union fields"); |
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.
union -> unsafe?
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.
also, this could perhaps be moved into allowed_union_or_unsafe_field
to deduplicate this logic further.
@@ -1464,6 +1506,7 @@ fn check_enum(tcx: TyCtxt<'_>, def_id: LocalDefId) { | |||
|
|||
detect_discriminant_duplicate(tcx, def); | |||
check_transparent(tcx, def); | |||
check_unsafe_fields(tcx, tcx.def_span(def_id), def_id); |
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.
no need to pass the def span of the def id we're already passing in.
RFC: rust-lang/rfcs#3458
Tracking:
r? jswrenn