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 `compile_error!` macro to libstd #1695

Merged
merged 2 commits into from Mar 28, 2017

Conversation

Projects
None yet
@sgrif
Copy link
Contributor

sgrif commented Aug 1, 2016

Rendered

@sfackler

This comment has been minimized.

Copy link
Member

sfackler commented Aug 1, 2016

I'd love something like this. I'm currently forcing type errors to do these kinds of checks, but that's not a great user experience: https://github.com/sfackler/rust-postgres/blob/306a6a9d187167b864ed5b28147b5da176549f58/src/feature_check.rs

@alexcrichton alexcrichton added the T-libs label Aug 1, 2016

@alexcrichton

This comment has been minimized.

Copy link
Member

alexcrichton commented Aug 1, 2016

Tagging as T-libs, but also relevant to the @rust-lang/lang team as it would essentially be adding a new macro the language (e.g. libcore wouldn't define it)

@Stebalien

This comment has been minimized.

Copy link
Contributor

Stebalien commented Aug 1, 2016

This would make macro libraries like horrorshow suck significantly less. However, it would actually be nice to pass a custom span to compile_error!. This way DSLs (like horrorshow) could tell the user where their mistake is.

@golddranks

This comment has been minimized.

Copy link

golddranks commented Aug 1, 2016

What about error message localizations (as there has been some discussion recently about supporting localized compiler error messages)? Even if compile_error! wouldn't support localization in the end, I'd like them to be mentioned so it won't go unconsidered.

@sgrif

This comment has been minimized.

Copy link
Contributor Author

sgrif commented Aug 1, 2016

@golddranks I'd imagine that localization will include some sort of way to detect them using cfg attributes, so it could be accomplished via:

#[cfg(locale = "en_US")]
compile_error!("LOOKOUT!");

#[cfg(locale = "de")]
compile_error!("ACHTUNG!");
The span given for the failure should be the invocation of the `compile_error!`
macro. The macro must take exactly one argument, which is a string literal. The
macro will then call `span_err` with the provided message on the expansion
context, and will not expand to any further code.

This comment has been minimized.

@nrc

nrc Aug 1, 2016

Member

Would it be worth accepting a format string rather than a plain string literal? Errors seem like the kind of thing that would be commonly customised?

Is it also worth accepting alternative spans some how? That seems like a useful tool, but I don't have an idea for how it would work.

This comment has been minimized.

@sgrif

sgrif Aug 1, 2016

Author Contributor

Given that this entirely at compile time, I'm not sure that there's anything that we could format that wouldn't be equally handled by concat!.

This comment has been minimized.

@sgrif

sgrif Aug 1, 2016

Author Contributor

The only way I can think of to accept alternative spans would be to take a file/line number/char number triple, which I think is fine as an option if folks are in favor of it.

# Drawbacks
[drawbacks]: #drawbacks

None

This comment has been minimized.

@nrc

nrc Aug 1, 2016

Member

It adds another language-aware macro.

When we do have proc macros, there will be overlap between this feature and more sophisticated error handling for proc macros which might be exposed to macro_rules somehow.

[alternatives]: #alternatives

Wait for the stabilization of procedural macros, at which point a crate could
provide this functionality.

This comment has been minimized.

@nrc

nrc Aug 1, 2016

Member

Seems there is some overlap with static_assert!, which iirc, was removed. It would be worth contrasting the two and motivating why this is worth adding, but static_assert! was removed.

This comment has been minimized.

@kennytm

kennytm Aug 2, 2016

Member

IIRC Rust did not had static_assert!, but the awkward #[static_assert] (#1096).

@sfackler sfackler self-assigned this Aug 1, 2016

@kennytm

This comment has been minimized.

Copy link
Member

kennytm commented Aug 2, 2016

cc #1146.

On nightly there are the static_assert and compile_msg crates.

@nikomatsakis

This comment has been minimized.

Copy link
Contributor

nikomatsakis commented Aug 2, 2016

I am in favor of this general idea (along with some kind of static-assert, but I guess that (could be) a separate thing). The question of how to "specify" a span is interesting -- I am presuming this error would be reported during macro expansion?

@sciyoshi

This comment has been minimized.

Copy link

sciyoshi commented Aug 4, 2016

👍, I think this is a good first step towards improving the readability of macro errors in general. How would custom spans be specified? @sgrif any thoughts on also including a compile_warning! macro?

@sgrif

This comment has been minimized.

Copy link
Contributor Author

sgrif commented Aug 7, 2016

I am presuming this error would be reported during macro expansion?

Correct. The implementation would essentially just be a procedural macro which passes its single argument to cx.span_err.

The question of how to "specify" a span is interesting

I'm really not sure that there's a compelling use case for that, as you really don't generally have span information without procedural macros in the first place.

any thoughts on also including a compile_warning! macro?

Seems like a reasonable addition if others are in favor of it.

@Stebalien

This comment has been minimized.

Copy link
Contributor

Stebalien commented Aug 7, 2016

I'm really not sure that there's a compelling use case for that, as you really don't generally have span information without procedural macros in the first place.

Is the span information not attached to the tokens passed to a macro? I'd like to be able point out which token in the macro input caused the macro expansion to fail (and why).

@briansmith

This comment has been minimized.

Copy link

briansmith commented Aug 20, 2016

Semantically, this would be just a special case of static_assert!(false, msg), right? Does it make sense to have both this and static_assert!? IMO, no, because they overlap too much. Consider, in particular, static_assert!(cfg!(locale = "de"), "ACHTUNG!"), in constrast to the example mentioned above.

@eddyb

This comment has been minimized.

Copy link
Member

eddyb commented Aug 20, 2016

@briansmith static_assert!, to actually evaluate its first argument, would have to run after type-checking instead of erroring at expansion time, which could result in other derived errors showing up first.
It might not be a bad idea to only have a "static assert", although consider:

// A potential desugaring, assuming CTFE that turns panics into compile errors.
const _: () = assert!(cfg!(locale = "de"), "ACHTUNG!");

I'm not sure if being able to implement static_assert! like that makes the macro unnecessary, but it certainly would affect the design.

@shepmaster

This comment has been minimized.

Copy link
Member

shepmaster commented Sep 15, 2016

I always imagined that something like this would be implemented as a panic! inside of a const fn (which is what it appears @eddyb mentions).

@eddyb

This comment has been minimized.

Copy link
Member

eddyb commented Sep 15, 2016

@shepmaster I would like @solson to confirm it, but I'm pretty sure miri already supports panic! as a compiler error (but not unwinding or running destructors).

@solson

This comment has been minimized.

Copy link
Member

solson commented Sep 15, 2016

@shepmaster @eddyb Miri can't reach the internal panic machinery inside panic!() quite yet, but turning uncaught unwinds into compiler errors was always the plan.

@DanielKeep

This comment has been minimized.

Copy link

DanielKeep commented Nov 7, 2016

Just popping by to note that the "force a type error on a constant" trick doesn't work in macros any more: the compiler just points at the macro invocation, and never shows the erroneous construct.

Right now, I have no way of catching and reporting input mistakes to the user. Can we get something, anything for this?

@aturon

This comment has been minimized.

Copy link
Member

aturon commented Feb 1, 2017

Ping @sfackler

@sfackler

This comment has been minimized.

Copy link
Member

sfackler commented Feb 1, 2017

Ah yes hello! I'd like to FCP to merge - while this will be implementable in the future via third party syntax extensions, it's a common enough workflow that I feel it's good to natively support it.

@rfcbot fcp merge

@rfcbot

This comment has been minimized.

Copy link

rfcbot commented Feb 1, 2017

Team member @sfackler has proposed to merge this. The next step is review by the rest of the tagged teams:

No concerns currently listed.

Once these reviewers reach consensus, this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!

See this document for info about what commands tagged team members can give me.

@kennytm

This comment has been minimized.

Copy link
Member

kennytm commented Feb 2, 2017

To someone having permission:
@rfcbot concern compile_warning

Do we include compile_warning! as well? #1695 (comment) #1695 (comment)

@sfackler

This comment has been minimized.

Copy link
Member

sfackler commented Feb 6, 2017

Ah good point. I'd probably say we add it since it's a pretty straightforward addition.

@iliekturtles

This comment has been minimized.

Copy link

iliekturtles commented Feb 19, 2017

What about no_std libraries? Should/can the macros be in libcore?

@solson

This comment has been minimized.

Copy link
Member

solson commented Feb 19, 2017

@iliekturtles Good call, it seems to me like they can and should be in libcore.

@sgrif

This comment has been minimized.

Copy link
Contributor Author

sgrif commented Feb 26, 2017

I think compile_warning! should be left to a separate RFC if it is deemed useful. It has more questions around it than compile_error! does (how does it interact with #[deny(warnings)], is it #[allow]able? How is the lint specified), and has a less obvious use case. I've updated the RFC to specify libcore instead of libstd

@KalitaAlexey

This comment has been minimized.

Copy link

KalitaAlexey commented Feb 27, 2017

@sgrif,
As you want to add the macro to the libcore, you should rename the PR to mention libcore instead of libstd.

@alexcrichton

This comment has been minimized.

Copy link
Member

alexcrichton commented Feb 28, 2017

ping @BurntSushi (checkbox)

@rfcbot

This comment has been minimized.

Copy link

rfcbot commented Mar 14, 2017

🔔 This is now entering its final comment period, as per the review above. 🔔

@CasualX

This comment has been minimized.

Copy link

CasualX commented Mar 23, 2017

As a neat workaround you can (ab)use the env! macro :) your warning message is unlikely to exist as an env var so you will get an error.

I asked if this feature existed some time ago in /r/rust

@rfcbot

This comment has been minimized.

Copy link

rfcbot commented Mar 24, 2017

The final comment period is now complete.

@sfackler

This comment has been minimized.

Copy link
Member

sfackler commented Mar 28, 2017

The comment period has elapsed, and this RFC is accepted! Tracking issue: rust-lang/rust#40872

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.