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

Polymorphic Numeric Constants #1945

Closed
wants to merge 4 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions text/0000-polymorphic-numeric-constants.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
- Feature Name: polymorphic_numeric_constant
- Start Date: 2017-04-06
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's hope we have a time machine built in Rust :-)

- RFC PR: (leave this empty)
- Rust Issue: (leave this empty)

# Summary
[summary]: #summary

Allows numeric constants to be defined without specifying an explicit type. Each time that constant is used, the type will be inferred as if it was a numeric literal without any suffix.

# Motivation
[motivation]: #motivation

The major motivation for this is FFI bindings, in particular when converting a constant of the form `#define FOO 273`. The equivalent in Rust would be `pub const FOO: ??? = 273;`, but figuring out which type to use can often be difficult. In some cases it can even be impossible, where a given constant is used in multiple places each with a different type. In `winapi` alone there are over twenty five thousand constants, and those decisions make up a significant amount of time when writing the bindings and cannot be automated. Even worse, if the wrong decision is made, it cannot later be changed in the future without causing a breaking change. Polymorphic numeric constants would solve this completely.

Even crates which aren't FFI bindings, but provide a variety of numerical constants can benefit from this feature.

# Detailed design
[design]: #detailed-design

Allow polymorphic numeric constants to be defined like so:

```Rust
const INTEGER = 273;
const FLOAT = 4.2;
```

When a polymorphic numeric constant is used, it will be equivalent to using the literal directly, and type inference will function identically. Thus the following two statements are identical in behavior (assuming `a` and `b` are later used identically) :

```Rust
let a = INTEGER + 5;
let b = 273 + 5;
```

The type of a polymorphic numeric constant can be different each time it is used. Thus the following is valid:

```Rust
let a: i32 = INTEGER;
let b: u32 = INTEGER;
```

It may also be desirable to create constants using simple constant expressions, for example:

```Rust
const ROOM_TEMPERATURE = INTEGER + 20;
```

However, this would be much more complicated to support than simply polymorphic integer constants and can be reserved for a future extension if necessary.

No support for inferring integer constants as floats or vice versa is being proposed.

# How We Teach This
[how-we-teach-this]: #how-we-teach-this

Just call them polymorphic integer constants or polymorphic float constants or polymorphic numeric constants.

Teach them as an extension of standard constants.

People who use such constants won't even notice the difference so there's no pressing need to teach it right away.

It will require additions to all the documentation with regards to constants.

# Drawbacks
[drawbacks]: #drawbacks

* New feature that has to be supported.
* Can get in the way of a future RFC for inferred constants.

# Alternatives
[alternatives]: #alternatives

* One alternative is to use macro constants, which involves defining a macro for each constant, and invoking the constant via `FOO!()` instead of `FOO`. It is verbose and ugly, clutters the global macro namespace, and will probably uncover some performance regression in rustc. Macros 2.0 may get rid of the global namespace pollution, and an RFC could make calling the macro as simple as `FOO!` but it is still far from ideal.
Copy link
Member

Choose a reason for hiding this comment

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

Macros would be my favoured solution since it doesn't require extending the type system in any way. We would make these much less verbose to declare and scopable as part of macros 2.0. We could try and handle not requiring the (). It doesn't seem far from ideal at that point.

* The status quo of having to decide on a type for each constant, or provide multiple versions of the constant each with a different type.

# Unresolved questions
[unresolved]: #unresolved-questions

* Is this the right syntax? Is there other syntax that would be preferable?
* Currently you can explicitly specify the type of an integer literal via suffixes. How would a user explicitly specify the type of a constant? Type ascription?
* Do we support constant expressions involving arithmetic? What about arbitrary const fn support? This may end up requiring more generalized polymorphic generic support.