-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
RFC: Generalize #[macro_registrar] to #[plugin_registrar] #86
Merged
Merged
Changes from 1 commit
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
- Start Date: 2014-05-22 | ||
- RFC PR #: | ||
- Rust Issue #: | ||
|
||
# Summary | ||
|
||
Generalize the `#[macro_registrar]` feature so it can register other kinds of compiler plugins. | ||
|
||
# Motivation | ||
|
||
I want to implement [loadable lints](https://github.com/mozilla/rust/issues/14067) and use them for project-specific static analysis passes in Servo. Landing this first will allow more evolution of the plugin system without breaking source compatibility for existing users. | ||
|
||
# Detailed design | ||
|
||
To register a procedural macro in current Rust: | ||
|
||
~~~ .rs | ||
use syntax::ast::Name; | ||
use syntax::parse::token; | ||
use syntax::ext::base::{SyntaxExtension, BasicMacroExpander, NormalTT}; | ||
|
||
#[macro_registrar] | ||
pub fn macro_registrar(register: |Name, SyntaxExtension|) { | ||
register(token::intern("named_entities"), | ||
NormalTT(box BasicMacroExpander { | ||
expander: named_entities::expand, | ||
span: None | ||
}, | ||
None)); | ||
} | ||
~~~ | ||
|
||
I propose an interface like | ||
|
||
~~~ .rs | ||
use syntax::parse::token; | ||
use syntax::ext::Registry; | ||
use syntax::ext::base::{BasicMacroExpander, NormalTT}; | ||
|
||
#[plugin_registrar] | ||
pub fn plugin_registrar(reg: &mut Registry) { | ||
reg.register_macro(token::intern("named_entities"), | ||
NormalTT(box BasicMacroExpander { | ||
expander: named_entities::expand, | ||
span: None | ||
}, | ||
None)); | ||
} | ||
~~~ | ||
|
||
Then the struct `Registry` could provide additional methods such as `register_lint` as those features are implemented. | ||
|
||
It could also provide convenience methods: | ||
|
||
~~~ .rs | ||
use syntax::ext::Registry; | ||
|
||
#[plugin_registrar] | ||
pub fn plugin_registrar(reg: &mut Registry) { | ||
reg.register_simple_macro("named_entities", named_entities::expand); | ||
} | ||
~~~ | ||
|
||
# Drawbacks | ||
|
||
Breaking change for existing procedural macros. | ||
|
||
More moving parts. | ||
|
||
# Alternatives | ||
|
||
We could add `#[lint_registrar]` etc. alongside `#[macro_registrar]`. This seems like it will produce more duplicated effort all around. It doesn't provide convenience methods, and it won't support API evolution as well. | ||
|
||
# Unresolved questions | ||
|
||
Naming bikeshed. | ||
|
||
Should `Registry` be provided by `libsyntax`, when it's used to register more than just syntax extensions? | ||
|
||
What set of convenience methods should we provide? |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question. Whatever library provides it will need to be linked by all syntax extensions. If it stays in
libsyntax
, that seems odd for a lint registry, although lints presumably need to use the AST and therefore need to link againstlibsyntax
anyway.Of course, supporting lints also poses a problem. I haven't really looked at them before, but they apparently use a
Context
type defined inlibrustc
. Sincelibrustc
links againstlibsyntax
,libsyntax
can't very well link againstlibrustc
. Extracting the registry to a separate library doesn't help, because it would have to link againstlibrustc
to get the sameContext
type, andlibrustc
would have to link against it.I see a few options here:
rustc::middle::lint::Context
out oflibrustc
and put it inlibsyntax
or a brand new library. This probably isn't doable, it has a few otherlibrustc
types embedded in it.librustc
andlibsyntax
can then provide trait implementations for lints and syntax extensions.The third is the most complicated, but allows this little library to stand on its own, and for syntax extensions to only link against either
libsyntax
orlibrustc
as needed.