Skip to content
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

Add a Ranged wrapper struct to replace the rustc_scalar_range_valid attributes #103724

Closed
wants to merge 1 commit into from

Conversation

oli-obk
Copy link
Contributor

@oli-obk oli-obk commented Oct 29, 2022

r? @joshtriplett

blocked on a decision on rust-lang/rfcs#3334

This PR removes the attribute and instead adds a type to the standard library that takes a field type and a const generic range to constraint that field type. All the previous logic that was required in the compiler to make the attribute sound has been removed and replaced by library functions and privacy rules.

It also eliminated all uses of cfg_attr(pointer_width=xxx), as we can now just use const eval and usize/isize to abstract over the pointer sized integer ranges.

The main limitation of the current implementation is that struct Foo<T, const C: T>(T); is not legal Rust yet. It is impossible as of yet to use generic parameters as the type of generic constants. Even with this limitation, I believe the compiler simplifications brought by this PR are important enough to warrant reconsidering the attribute stabilization RFC. Though I do not expect this type to get stabilized before const generics of generic types.

Zulip discussion on this topic

@oli-obk oli-obk added the S-blocked Status: Blocked on something else such as an RFC or other implementation work. label Oct 29, 2022
@rustbot
Copy link
Collaborator

rustbot commented Oct 29, 2022

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @joshtriplett (or someone else) soon.

Please see the contribution instructions for more information.

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Oct 29, 2022
@rust-log-analyzer

This comment has been minimized.

library/core/src/time.rs Outdated Show resolved Hide resolved
Copy link
Member

@jhpratt jhpratt left a comment

Choose a reason for hiding this comment

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

Quick look at the diff LGTM, aside from CI of course. Just the one nit that was already mentioned.

library/core/src/time.rs Outdated Show resolved Hide resolved
@rustbot rustbot added the A-translation Area: Translation infrastructure, and migrating existing diagnostics to SessionDiagnostic label Oct 30, 2022
@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@oli-obk
Copy link
Contributor Author

oli-obk commented Nov 2, 2022

@bors try @rust-timer queue

@rust-timer
Copy link
Collaborator

Awaiting bors try build completion.

@rustbot label: +S-waiting-on-perf

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Nov 2, 2022
@bors
Copy link
Contributor

bors commented Nov 2, 2022

⌛ Trying commit 7fba3595ed0357e7c844ca106473c4cc968dc4d9 with merge 6a3b3432328dc85a19d780ed0e3b8be54628d292...

@bors
Copy link
Contributor

bors commented Nov 2, 2022

☀️ Try build successful - checks-actions
Build commit: 6a3b3432328dc85a19d780ed0e3b8be54628d292 (6a3b3432328dc85a19d780ed0e3b8be54628d292)

@rust-timer
Copy link
Collaborator

Queued 6a3b3432328dc85a19d780ed0e3b8be54628d292 with parent edf0182, future comparison URL.

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (6a3b3432328dc85a19d780ed0e3b8be54628d292): comparison URL.

Overall result: ❌✅ regressions and improvements - ACTION NEEDED

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

Next Steps: If you can justify the regressions found in this try perf run, please indicate this with @rustbot label: +perf-regression-triaged along with sufficient written justification. If you cannot justify the regressions please fix the regressions and do another perf run. If the next run shows neutral or positive results, the label will be automatically removed.

@bors rollup=never
@rustbot label: +S-waiting-on-review -S-waiting-on-perf +perf-regression

Warning ⚠: The following benchmark(s) failed to build:

  • rustc
  • regression-31157

Instruction count

This is a highly reliable metric that was used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
2.3% [0.3%, 7.6%] 77
Regressions ❌
(secondary)
2.4% [0.2%, 15.2%] 44
Improvements ✅
(primary)
-0.8% [-2.5%, -0.2%] 115
Improvements ✅
(secondary)
-1.6% [-5.3%, -0.2%] 91
All ❌✅ (primary) 0.4% [-2.5%, 7.6%] 192

Max RSS (memory usage)

Results

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.

mean range count
Regressions ❌
(primary)
3.5% [1.6%, 6.0%] 8
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
-2.6% [-5.7%, -0.5%] 11
Improvements ✅
(secondary)
-3.1% [-6.5%, -1.0%] 18
All ❌✅ (primary) -0.0% [-5.7%, 6.0%] 19

Cycles

Results

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.

mean range count
Regressions ❌
(primary)
3.5% [0.8%, 8.3%] 48
Regressions ❌
(secondary)
5.7% [1.9%, 14.7%] 12
Improvements ✅
(primary)
-1.9% [-2.2%, -1.7%] 4
Improvements ✅
(secondary)
-5.2% [-7.0%, -2.5%] 8
All ❌✅ (primary) 3.1% [-2.2%, 8.3%] 52

@rustbot rustbot added perf-regression Performance regression. and removed S-waiting-on-perf Status: Waiting on a perf run to be completed. labels Nov 3, 2022
@oli-obk
Copy link
Contributor Author

oli-obk commented Nov 3, 2022

@bors try @rust-timer queue

@rust-timer
Copy link
Collaborator

Awaiting bors try build completion.

@rustbot label: +S-waiting-on-perf

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Nov 3, 2022
@bors
Copy link
Contributor

bors commented Nov 3, 2022

⌛ Trying commit e5c9675481e48da4a88e473f0d5c39a4d2f11fd6 with merge 8983d23afaf5483644a8983f75cb575b8e430d59...

@bors
Copy link
Contributor

bors commented Nov 3, 2022

☀️ Try build successful - checks-actions
Build commit: 8983d23afaf5483644a8983f75cb575b8e430d59 (8983d23afaf5483644a8983f75cb575b8e430d59)

@rust-timer
Copy link
Collaborator

Queued 8983d23afaf5483644a8983f75cb575b8e430d59 with parent 432b1a4, future comparison URL.

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (8983d23afaf5483644a8983f75cb575b8e430d59): comparison URL.

Overall result: ❌✅ regressions and improvements - ACTION NEEDED

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

Next Steps: If you can justify the regressions found in this try perf run, please indicate this with @rustbot label: +perf-regression-triaged along with sufficient written justification. If you cannot justify the regressions please fix the regressions and do another perf run. If the next run shows neutral or positive results, the label will be automatically removed.

@bors rollup=never
@rustbot label: +S-waiting-on-review -S-waiting-on-perf +perf-regression

Warning ⚠: The following benchmark(s) failed to build:

  • regression-31157

Instruction count

This is a highly reliable metric that was used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
0.7% [0.2%, 2.2%] 99
Regressions ❌
(secondary)
1.4% [0.2%, 6.1%] 39
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-1.3% [-3.1%, -0.3%] 22
All ❌✅ (primary) 0.7% [0.2%, 2.2%] 99

Max RSS (memory usage)

Results

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.

mean range count
Regressions ❌
(primary)
3.9% [1.3%, 10.1%] 6
Regressions ❌
(secondary)
2.5% [1.3%, 4.7%] 3
Improvements ✅
(primary)
-5.1% [-6.0%, -3.8%] 3
Improvements ✅
(secondary)
-3.6% [-4.2%, -2.2%] 6
All ❌✅ (primary) 0.9% [-6.0%, 10.1%] 9

Cycles

Results

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.

mean range count
Regressions ❌
(primary)
1.6% [0.9%, 2.9%] 30
Regressions ❌
(secondary)
2.7% [1.8%, 4.7%] 15
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 1.6% [0.9%, 2.9%] 30

@rustbot rustbot removed the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Nov 3, 2022
@bors
Copy link
Contributor

bors commented Nov 19, 2022

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

bors added a commit to rust-lang-ci/rust that referenced this pull request Nov 27, 2022
Various cleanups around scalar layout restrictions

Pulled out of rust-lang#103724
@oli-obk oli-obk mentioned this pull request Nov 29, 2022
@scottmcm
Copy link
Member

Big 👍 from me! The RFC about attributes had to spend so much effort on describing parsing rules and such that just completely disappear if it can go into const generics as normal Rust values that already have all that defined, and it's more useful to boot to be able to make it generic!

@oli-obk
Copy link
Contributor Author

oli-obk commented Dec 10, 2022

Unfortunately I don't believe we can eliminate the perf regression unless we codegen repr(transparent) field accesses to the non-zst field as transmutes. LLVM seems to have a hard time figuring out all those field accesses in boxes

@joshtriplett
Copy link
Member

joshtriplett commented Jan 19, 2023

@oli-obk You've convinced me. I'm going to close RFC 3334 in favor of this.

I do agree that we shouldn't stabilize this until we can write the range in terms of the T. And I do still think we should have a straightforward (unsafe) way to get a &mut T. But apart from that, I think we should ship this, and I'd be happy to see this PR merged as unstable if you believe we'll be able to switch it to use a range of T in the not too distant future.

Given a range based on T, how would you propose handling NonZeroI32, or something else with a niche in the middle?

@oli-obk
Copy link
Contributor Author

oli-obk commented Jan 19, 2023

Given a range based on T, how would you propose handling NonZeroI32, or something else with a niche in the middle?

The ranges given are wraparound, so there's no issue with 1..=-1 as a range, even if as an iterator that doesn't work.

And I do still think we should have a straightforward (unsafe) way to get a &mut T. But apart from that, I think we should ship this, and I'd be happy to see this PR merged as unstable if you believe we'll be able to switch it to use a range of T in the not too distant future.

The LLVM perf regression due to the extra field access is still fairly annoying and I am exploring not adding a level of indirection, but desugaring the existing unstable attributes to a (not surface-syntax representable) pattern type. Pattern types are essentially a pair of an existing type and a pattern that restricts said type to a subset. So for example u32 is 1.. or u32 matches 1...

If this experiment succeeds for fields of the NonZero and NonNull types, I will write up a proper proposal to add it to the surface syntax and replacing the existing struct NonZero and struct NonNull with type NonZeroU32 = u32 is 1.. and type NonNull<T> = (*const T) is {std::ptr::null<T>().wrapping_offset(1)}...

These pattern types have all the same advantages of this PR's wrapper struct, but avoids nesting things unnecessarily in structs.

#[unstable(feature = "ranged_int", issue = "none")]
#[rustc_const_unstable(feature = "ranged_int", issue = "none")]
#[inline(always)]
pub const fn get(self) -> T {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do the get and new_unchecked implementations require T: CheckInRange when they don't seem to need it? And if it is needed, shouldn't the struct itself or at least the Deref implementation also have this requirement? Otherwise, you can easily bypass the requirement with transmute (for new_unchecked) and deref (for get), the latter of which would be the most concerning since it's safe and usually automatic.

/// A helper trait until we can declare `struct Ranged<T, const RANGE: RangeInclusive<T>>(T);`.
/// This is not meant to ever be stabilized.
#[unstable(feature = "ranged_int", issue = "none")]
pub trait CheckInRange {
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't the CheckInRange trait be unsafe to implement since Ranged::new depends on its correct implementation?

@clarfonthey
Copy link
Contributor

This is definitely something that can be fixed later, but one clear thing that will need to be worked around is how Ranged interplays with strict provenance. Right now, even though NonNull internally just assumes that provenance isn't actually stored inside the type, it doesn't guarantee this because it's opaque. So, this probably means that we'd want to ensure that Ranged for pointers is at least under a separate feature flag, or maybe RangedPtr can be a separate type.

@oli-obk
Copy link
Contributor Author

oli-obk commented Feb 2, 2023

Closing in favor of #107606

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-translation Area: Translation infrastructure, and migrating existing diagnostics to SessionDiagnostic perf-regression Performance regression. S-blocked Status: Blocked on something else such as an RFC or other implementation work. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.