Skip to content

Better interface for static assert #6676

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

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]
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
A-attributes Area: Attributes (`#[…]`, `#![…]`)
Projects
None yet
Development

Successfully merging a pull request may close this issue.