Open dhardy opened 3 months ago
At the moment if you do any emit_as()
on a diagnostic, the diagnostic is emitted directly at the call site on nightly. On stable it returns the appropriate tokens to create the compile_error!()
. This is to say: on nightly, it works exactly as you suggest. On stable, it does the second of the two options you suggest.
This isn't what I want since Diagnostic::emit_as_item_tokens
returns a TokenStream
(as do all other emit_as_...
). Well, I could use this if I then drop the result.
I mean, I could keep track of emitted_diagnostics: TokenStream
myself (via a static/thread-local value or via an extra field in many different structs representing parsed input), and then fold this into the output somewhere. This is not exactly trivial, which is why I'm suggesting it be added as library functionality.
The unmaintained proc-macro-error
crate supports emit_error!
and emit_warning!
as item statements which return no result, which is what I want. Admittedly, emit_warning!
does nothing on stable, but it supports the desired usage pattern and should be fixable once macro diagnostics finally get stabilised.
With warnings in particular (but potentially also with errors), it may be preferable to emit a diagnostic then continue generating macro output.
Until we get better support for proc-macro errors (or more general lints) in rustc, I see only two ways of achieving this:
fn Diagnostic::emit(self) -> ()
which uses the nightly API if available, otherwiseDiagnosticSet
), then report via the usual method of injectingcompile_error
into the output (assuming the output is a list of items). This is problematic, both in that a user function call must be used to generate this output (which might be forgotten) and in that the output might be an expression (could be transformed but not merely appended to).There isn't exactly a good option, but this is an important capability to have, and (especially option 1) should ease transition to whatever custom lint system Rust eventually adopts.