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
Merged
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
73 changes: 73 additions & 0 deletions text/0000-add-error-macro.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
- Feature Name: compile\_error\_macro
- Start Date: 2016-08-01
- RFC PR: (leave this empty)
- Rust Issue: (leave this empty)

# Summary
[summary]: #summary

This RFC proposes adding a new macro to `libcore`, `compile_error!` which will
unconditionally cause compilation to fail with the given error message when
encountered.

# Motivation
[motivation]: #motivation

Crates which work with macros or annotations such as `cfg` have no tools to
communicate error cases in a meaningful way on stable. For example, given the
following macro:

```rust
macro_rules! give_me_foo_or_bar {
(foo) => {};
(bar) => {};
}
```

when invoked with `baz`, the error message will be `error: no rules expected the
token baz`. In a real world scenario, this error may actually occur deep in a
stack of macro calls, with an even more confusing error message. With this RFC,
the macro author could provide the following:

```rust
macro_rules! give_me_foo_or_bar {
(foo) => {};
(bar) => {};
($x:ident) => {
compile_error!("This macro only accepts `foo` or `bar`");
}
}
```

When combined with attributes, this also provides a way for authors to validate
combinations of features.

```rust
#[cfg(not(any(feature = "postgresql", feature = "sqlite")))]
compile_error!("At least one backend must be used with this crate. \
Please specify `features = ["postgresql"]` or `features = ["sqlite"]`")
```

# Detailed design
[design]: #detailed-design

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.
Copy link
Member

Choose a reason for hiding this comment

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

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

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!.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

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
Copy link
Member

Choose a reason for hiding this comment

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

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]: #alternatives

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

Choose a reason for hiding this comment

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

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.

Copy link
Member

Choose a reason for hiding this comment

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

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


# Unresolved questions
[unresolved]: #unresolved-questions

None