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

NonZero lang item. #499

Closed
wants to merge 1 commit into from
Closed

NonZero lang item. #499

wants to merge 1 commit into from

Conversation

luqmana
Copy link
Member

@luqmana luqmana commented Dec 6, 2014

No description provided.

@luqmana luqmana changed the title Create 0000-non-zero-lang-item.md NonZero lang item. Dec 6, 2014
As part of this we'd introduce a new lang item:
```
#[lang = "non_zero"]
struct NonZero<T>(T);
Copy link

Choose a reason for hiding this comment

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

What happens if I put a non-pointer, non-integral type in NonZero?

Copy link
Member Author

Choose a reason for hiding this comment

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

With the initial implementation in rust-lang/rust#19536 it doesn't do anything special. It would just act as any other struct there and the optimization wouldn't kick in.

Copy link

Choose a reason for hiding this comment

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

That seems like a reasonable approach, but I think we may want to make it an error to use NonZero for non-supported types.

Copy link
Member Author

Choose a reason for hiding this comment

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

Hmm, we could probably actually do that just by limiting the types constructor will accept.

Copy link

Choose a reason for hiding this comment

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

I think it should be baked into the compiler, because there is no trait for the types we'd like to fit here. We could possibly write a marker-only trait with unsafe traits and default traits.

@killercup
Copy link
Member

Rendered

@Thiez
Copy link

Thiez commented Dec 9, 2014

This appears to be just a special case for a more general case of being able to limit the possible values a type can take. For instance, we know &x cannot be a null pointer, that is, let ptr = &x as *const _ as uint, ptr != 0. But we also know that ptr != 1, and ptr != 2... In fact, unless we're writing an operating system it should be correct to assume that the entire 4k page starting at address zero is unmapped, so ptr >= 4096. So really we could have a type NonZeroTo4096.

Could Rust benefit from being able to limit ranges more than just NonZero?

@Manishearth
Copy link
Member

@Thiez Sort of, in the sense that enums of the form

enum Foo<T> {
Bar(NonZeroTo4096<T>),
Baz,
Quux,
// up to 4094 more variants
}

would be optimized. But this doesn't seem like a rather common usage.

@nikomatsakis nikomatsakis self-assigned this Dec 11, 2014
@brson brson assigned nrc and nikomatsakis and unassigned nikomatsakis and nrc Dec 11, 2014
@nikomatsakis
Copy link
Contributor

@luqmana Obviously, this is a good thing to have. We discussed this in triage today. Current thinking is that we would like to close this RFC for now. There is already a tracking issue #278 indicating that this is a desirable feature to add to rust at some point after 1.0. It seems that there are enough use cases here that it's worth trying to think through the public-facing interface in more detail.

However, it's still worth optimizing common cases like Option<Rc<int>> and so on. Therefore, we'd like to land your patch, but ensure that the NonZero lang item is not publicly exported from libstd. This way it cannot be used without a feature gate (since accessing items directly from crates in the facade will be feature-gated, as is declaring lang items manually).

What do you think?

@luqmana
Copy link
Member Author

luqmana commented Dec 11, 2014

@nikomatsakis That works for me. As for not exporting the lang item, initially I just placed it in core::ptr and used it from libcollections & liballoc. But due to libstd have a pub use core::ptr it would be available through std. I'm pretty sure there isn't a way to say export everything but this right now.

@sfackler
Copy link
Member

Seems like you can shove it in its own module.

@pythonesque
Copy link
Contributor

@Manishearth I actually do think it would be a useful feature to have. I have wanted it quite often.

@nikomatsakis
Copy link
Contributor

In accordance with #499 (comment), closing this PR.

bors added a commit to rust-lang/rust that referenced this pull request Dec 29, 2014
This extends the nullable enum opt to traverse beyond just the first level to find possible fields to use as the discriminant. So now, it'll work through structs, tuples, and fixed sized arrays. This also introduces a new lang item, NonZero, that you can use to wrap raw pointers or integral types to indicate to rustc that the underlying value is known to never be 0/NULL. We then use this in Vec, Rc and Arc to have them also benefit from the nullable enum opt.

As per rust-lang/rfcs#499 NonZero is not exposed via the `libstd` facade.

```
x86_64 Linux:
                        T       Option<T> (Before)      Option<T> (After)
----------------------------------------------------------------------------------
Vec<int>                24          32                      24
String                  24          32                      24
Rc<int>                 8           16                      8
Arc<int>                8           16                      8
[Box<int>, ..2]         16          24                      16
(String, uint)          32          40                      32
```

Fixes #19419.
Fixes #13194.
Fixes #9378.
Fixes #7576.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants