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

Better interface for static assert #6676

Closed
emberian opened this issue May 22, 2013 · 14 comments · Fixed by #24910
Closed

Better interface for static assert #6676

emberian opened this issue May 22, 2013 · 14 comments · Fixed by #24910
Labels
A-attributes Area: Attributes (`#[…]`, `#![…]`)

Comments

@emberian
Copy link
Member

In #6670 I add a basic form of static assertions (as suggested by graydon in #6568), but it's not nice to use. The biggest problem with it is you need a static variable with a name, that goes through trans and ends up in the object file.

@kud1ing suggested static_assert!(), which I think is a nice API but would need some invasive changed to the compiler (I think, uncertain).

@graydon
Copy link
Contributor

graydon commented May 22, 2013

Eh. I'm actually kinda ok with the way it turned out. If it's non-pub it shouldn't wind up in the object file as a public symbol (if it does, we're doing-stuff-wrong in codegen) and we can potentially just mark it as a throw-me-away sort of value harder if LLVM requires further convincing.

Considering that static asserts in C are typically done by composing a negative-sized array and allowing the compiler to yell about that, I consider this implementation already pretty luxurious :)

@Kimundi
Copy link
Member

Kimundi commented May 24, 2013

How about having a static_assert!() thats just a wrapper around a automatically generated private static item with the #[static_assert] attribute?

@kud1ing
Copy link

kud1ing commented May 24, 2013

@Kimundi: if i understand you correctly, that's what i've suggested in #6670 (comment) but it seems not straightfoward to implement

@Kimundi
Copy link
Member

Kimundi commented May 24, 2013

Hm, but the current attribute-static item system works, no? Wouldn't a static_assert!() just be trivial sugar for that? Or is the 'generate a name'-part the hard one?

@emberian
Copy link
Member Author

I don't know how to implement a macro to do this, so feel free to take a shot at it 😺

@catamorphism
Copy link
Contributor

Visiting for triage. Doesn't seem like a release blocker.

@emberian
Copy link
Member Author

With hygiene, it should be much easier. @jbclements?

@huonw
Copy link
Member

huonw commented Sep 23, 2013

Triage: hygiene doesn't particularly help in this case, it's currently only for names created/bound with let.

A sketch:

macro_rules! static_assert {
    ($e:expr) => {
        mod assertion { // mod needed to put attributes on the `static`
            #[static_assert]
            static asssertion: bool = $e;
        }
    }
}

// static_assert!(true)
static_assert!(false)

fn main() {}

Uncommenting the static_assert!(false) gives a duplicate module error (as one might expect). If there was a gensym!() macro (for creating a completely new ident) this might help, but mod gensym!(assertion) { ... } is currently not valid as macros aren't allowed in place of Idents.

@kud1ing
Copy link

kud1ing commented Oct 15, 2013

Macros can now expand to items with attributes: #9783

@flaper87
Copy link
Contributor

triage bump. Nothing to add

@thestinger
Copy link
Contributor

It always needs to be crippled enough that it can't cause a compilation failure during expansion of generics. I think we should just remove the current attribute. It doesn't appear to have any real world use cases.

@steveklabnik
Copy link
Member

triage: nothing to add. We don't currently use static_assert anywhere in the codebase, which leads me to wonder if @thestinger isn't right here.

@steveklabnik steveklabnik added the A-attributes Area: Attributes (`#[…]`, `#![…]`) label Jan 23, 2015
steveklabnik added a commit to steveklabnik/rust that referenced this issue Apr 28, 2015
This was always a weird feature, and isn't being used in the compiler.
Static assertions should be done better than this.

Fixes rust-lang#13951
Fixes rust-lang#23008
Fixes rust-lang#6676

This is behind a feature gate, but that's still a

[breaking-change]
steveklabnik added a commit to steveklabnik/rust that referenced this issue Jun 3, 2015
This was always a weird feature, and isn't being used in the compiler.
Static assertions should be done better than this.

This implements RFC rust-lang#1096.

Fixes rust-lang#13951
Fixes rust-lang#23008
Fixes rust-lang#6676

This is behind a feature gate, but that's still a

[breaking-change]
bors added a commit that referenced this issue Jun 3, 2015
This was always a weird feature, and isn't being used in the compiler.
Static assertions should be done better than this.

Fixes #13951
Fixes #23008
Fixes #6676

This is behind a feature gate, but that's still a

[breaking-change]

(It's not entirely clear to me that this should or shouldn't have an RFC, but if it does, I'm fine blocking on such a thing.)
@nodakai
Copy link
Contributor

nodakai commented Mar 27, 2016

An implementation in standard Rust based on the array size trick:

macro_rules! static_assert {
    (type $t:ty; ) => (
        type __StaticAssert = $t;
    );

    (type $t:ty; $e:expr $(, $ee:expr)*) => (
        static_assert!(type ($t, [i8; 0 - ((false == ($e)) as usize)]); $($ee),*);
    );

    ($e:expr $(, $ee:expr)*) => (
        static_assert!(type [i8; 0 - ((false == ($e)) as usize)]; $($ee),*);
    );
}

// static_assert!(1 > 0);
static_assert!(1 > 0, 2 > 1, 3 > 2);

fn main() {
//    static_assert!(1 > 0);
    static_assert!(1 > 0);
}

In short, an invocation static_assert!(1 > 0, 2 > 1, 3 > 2, 3 > 1); expands to

type __StaticAssert =
    (((
       [i8; 0 - ((false == (1 > 0)) as usize)],
       [i8; 0 - ((false == (2 > 1)) as usize)]),
      [i8; 0 - ((false == (3 > 2)) as usize)]),
     [i8; 0 - ((false == (3 > 1)) as usize)]);

It is variadic because there will be a name collision between two invocations... Yes the usability is horrible.

@lilianmoraru
Copy link

I wish Rust would support more static features(I use them extensively in C++ in order to enforce correct API usage)...
I need to assert the simplest case: making sure the user doesn't pass an empty array/slice - and I cannot do it with the language...
It's awful that I have to "assert" at run-time for such a simple case...

dlrobertson pushed a commit to dlrobertson/rust that referenced this issue Nov 29, 2018
This was always a weird feature, and isn't being used in the compiler.
Static assertions should be done better than this.

This implements RFC rust-lang#1096.

Fixes rust-lang#13951
Fixes rust-lang#23008
Fixes rust-lang#6676

This is behind a feature gate, but that's still a

[breaking-change]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-attributes Area: Attributes (`#[…]`, `#![…]`)
Projects
None yet
Development

Successfully merging a pull request may close this issue.