Skip to content

#![register_{attribute,lint}_tool] #3808

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

Open
wants to merge 14 commits into
base: master
Choose a base branch
from

Conversation

jyn514
Copy link
Member

@jyn514 jyn514 commented May 6, 2025

Rendered

Co-authored by @BD103.

Thank you to everyone who gave feedback on early versions of this RFC.

- mention that `rustdoc -w json` will include the attributes
- fix semver-checks spelling
- apparently adding `inline` can be a breaking change 🙄
@jyn514
Copy link
Member Author

jyn514 commented May 6, 2025

going to go ahead and ping all the authors of extern tools that i know, in no particular order:

@obi1kenobi
Copy link
Member

I would happily use this in cargo-semver-checks. Users keep asking for things like "how can I disable lint X on item Y"; right now the only options we can offer them are:

  • disable the lint everywhere
  • mark the module #[doc(hidden)], thereby making it non-public API

Both of those are very blunt instruments, and thoroughly unsatisfying as an answer to our users. This RFC addresses those problems directly. I'm excited to see it.

@Zalathar Zalathar added the T-lang Relevant to the language team, which will review and decide on the RFC. label May 6, 2025

The tool prelude is separated into the tool attribute prelude (which is in the type namespace) and the lint prelude (which is only active inside lint controls).

The tool attribute prelude is changed to take precedence over the [Extern prelude]. The tool attribute prelude is only considered when resolving in an attribute macro; types in other positions, such as `fn foo() -> rustfmt::x`, do not consider the tool prelude. This is to avoid unnecessary breakage when the meaning is clear.
Copy link
Contributor

Choose a reason for hiding this comment

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

This effectively introduces two sub-namespaces to type namespace, which is a relatively large change.
For macro namespace we introduced it because there was basically no choice due to macro modularization breakage, but here we are free to not introduce complications.

Copy link
Member Author

@jyn514 jyn514 May 6, 2025

Choose a reason for hiding this comment

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

That's true; we won't break any existing stable code because the breakage only happens when people explicitly write register_attribute_tool. The breakage I'm trying to avoid is not writing it -> writing it, so people are more likely to adopt it. but it seems reasonable to just say "write out ::rustfmt::x", maybe with a MachineApplicable lint, and then the resolution rules can be simpler.

- We could "just not do this". That makes it harder to write external tools, and in practice just means that people use `cfg_attr` instead of a namespace, which seems strictly worse.
- We could relax the constraint that tool names cannot conflict with local items. This requires tools to do name resolution; but in practice I do not think we can expect tools to do this, and we must assume that the tool will behave differently than the compiler (`rustfmt` already does this today).
- We could add a syntax to disambiguate tool names from local items. That would add inconsistency with the existing built-in tool attributes, and requires tool authors to parse both the new and existing syntax.
- We could drop the change to name resolution, such that extern crates continue to take precedence over tools. This allows no way to use a tool and a crate with the same name, unless we add a new syntax.
Copy link
Contributor

Choose a reason for hiding this comment

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

I think that's what I'd just do.
(Perhaps together with the "ambiguity is always an error" change if we can pull it off, to maximize future possibilities.)

rustfmt misinterpreting mod rustfmt { pub use my_attr_macro as skip; } for #[rustfmt::skip] isn't really an issue in practice, and for tools working post-expansion this is not an issue even in theory.

extern crate rustfmt as my_rustfmt is a good enough way to avoid breaking a tool when you need a crate with the same name.

Copy link
Member Author

Choose a reason for hiding this comment

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

to be clear, you are suggesting that the following be a hard error?

#![register_attribute_tool(pyo3)]
extern crate pyo3;
#[pyo3::pymodule]  // error: ambiguous between tool and crate
struct Foo {}

I think that would not be ideal, but I guess I could live with it as long as #[::pyo3::pymodule] is still allowed. I feel somewhat strongly that #[::pyo3::pymodule] should not give an error, the extern crate as workaround is not very well known. even if people use it as my_pyo3 = { package = "pyo3" } in Cargo.toml it's still a bit indirect.

cc @mejrs

Copy link
Contributor

Choose a reason for hiding this comment

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

to be clear, you are suggesting that the following be a hard error?

Yes, just because if it's an error initially, then in the future we'll be able to backward compatibly do any of the resolution changes from this RFC (precedence, subnamespaces) if really necessary.

#[::pyo3::pymodule] should certainly work, there's no ambiguity there, ::foo only looks into extern prelude.

Copy link
Member Author

Choose a reason for hiding this comment

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

I thought of another complication. Say we want to add more built-in tools in the future, or to reserve a tool namespace today. If adding a built-in tool causes breakage because it makes crate names ambiguous, suddenly it's much harder to extend the namespace.

I guess we could have different rules for built-in tools than for registered tools, but that kinda sucks.

Copy link

Choose a reason for hiding this comment

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

I think that would not be ideal, but I guess I could live with it as long as #[::pyo3::pymodule] is still allowed.

I've thought about this and and having #[::pyo3::pymodule] work in this case but not #[pyo3::pymodule] seems like a bad idea to me. I think it'd be better if they both errored or if both worked. If we allow the former then it's gonna be one of those gotchas that everyone runs into. "Oh yeah you have to prefix the macro path with :: because otherwise it's ambiguous between the tool and the macro". I think I'd like to have them named the same but it might be better if authors are forced to choose different names.

Copy link
Member Author

Choose a reason for hiding this comment

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

I am very opposed to that idea. We should not be adding needless restrictions. If you don't want the tool/macro distinction to be confusing, you as the author can choose a different name for your tool. We should not prevent people from disambiguating their code (for one thing, it makes adding a new built-in tool over an edition much harder).

Copy link

Choose a reason for hiding this comment

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

you as the author can choose a different name for your tool

I do not disagree in principle, but I'm just a bit paranoid of the situation where someone chooses the crate name as their tool name without thinking about it very much and it ends up being awkward later on. Imagine a situation like:

  • author creates a library (without proc macros)
  • author creates a tool attribute with the same name, this works fine because of no proc macros
  • author later decides to add proc macros
  • (without prefix ::) these macros collide with the tool name
  • the author would have to decide to either rename the tool or tell the users to prefix the macros. The latter sounds like a noob trap.

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't think we can prevent this situation. The last thing still happens even if we prevent disambiguating the tool, we just force you to rename, we are strictly limiting your options.

Consider a different case: someone writes a crate, someone else writes a tool, they don't know about each other. you combine them and they conflict. I don't think we should force you in this case to use extern crate overlap as my_overlap, that seems strictly worse than allowing you to disambiguate at the call site.

@epage
Copy link
Contributor

epage commented May 6, 2025

I would happily use this in cargo-semver-checks. Users keep asking for things like "how can I disable lint X on item Y"; right now the only options we can offer them are:

* disable the lint everywhere

* mark the module `#[doc(hidden)]`, thereby making it non-public API

Both of those are very blunt instruments, and thoroughly unsatisfying as an answer to our users. This RFC addresses those problems directly. I'm excited to see it.

How would you be able to leverage this? irrc rustdoc gives you immediate attributes but not enough other attributes to resolve lint levels.

@jyn514
Copy link
Member Author

jyn514 commented May 6, 2025

How would you be able to leverage this? irrc rustdoc gives you immediate attributes but not enough other attributes to resolve lint levels.

this is not a rustdoc problem. this is a language level problem. semver-checks would have the same problem if it were using syn to parse; today, there is simply no place to put the attributes where rustc doesn't hard error.

@jyn514
Copy link
Member Author

jyn514 commented May 6, 2025

oh, i misunderstood, you were asking how semver-checks would use this if it were implemented. i would expect semver-checks to reimplement the precedence rules for lints, or to document that it doesn't support module-level lint controls. it doesn't have CLI flags, which means [lints] in Cargo.toml won't work, that's unfortunate. maybe rustdoc-json could expose those flags.

jyn514 added 2 commits May 6, 2025 09:02
- make cargo registration the main user interface
- specify that `no_implicit_prelude` does not affect tools
jyn514 added 2 commits May 6, 2025 09:29
- all ambiguity is forbidden, not just tool<->local ambiguity. as a
  result, there is no change to precedence order.
- no special-casing for attribute macros; tools are visible in any
  context in the type namespace
- the suggested way to add a new built-in tool is "wait for an edition"
Copy link

@celinval celinval left a comment

Choose a reason for hiding this comment

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

It's awesome to see this moving forward. Thanks!

For Kani, it's better to include @zhassan-aws / @carolynzech.


Like today, attributes and lints in a tool namespace are always considered used by the compiler. The compiler does not verify the contents of any tool attribute, except to verify that all attributes are syntactically valid [tool attributes].

Registering a predefined tool (`clippy`, `miri`, etc.) using `#![register_*_tool(...)]` is an error.
Copy link

Choose a reason for hiding this comment

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

Where will this list be maintained?

Also, today you can't add any attribute that starts with rustc. Will that still be the case?

Copy link
Member Author

Choose a reason for hiding this comment

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

You can see a full list at https://doc.rust-lang.org/nightly/reference/attributes.html#tool-attributes. That list is currently not as complete as the list in this RFC; I will make sure to update it.

Also, today you can't add any attribute that starts with rustc. Will that still be the case?

I assume you mean namespaced tool attributes like rustc::xxx, not "bare" attributes like rustc_const_stable. I expect those to still be banned. The story there is kind of a mess because there are rustc:: lints and they are feature-gated, but differently than the rest of the compiler's feature gates ... but I don't think we need to resolve that in this RFC. I will mention that the rustc:: tool namespace is currently and will continue to be reserved.

Copy link

@celinval celinval May 8, 2025

Choose a reason for hiding this comment

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

Yes, I mean namespaced tool attributes that starts with rustc, for example, rustc_foo::bar. Today you can register a tool rustc_foo, but the compiler will reject the attribute #[rustc_foo::bar] (playground link):

#![feature(register_tool)]
#![register_tool(rustc_foo)]

#[rustc_foo::bar]
fn main() {
    println!("🦀")
}

Copy link
Member Author

Choose a reason for hiding this comment

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

oh, i see. this is actually not coming from the register_tool code, this is the same code that rejects #[rustc_baz].

i think it is fairly reasonable to keep this reserved, but i can make sure it's rejected earlier in register_tool so that people aren't confused.

Copy link
Contributor

Choose a reason for hiding this comment

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

but i can make sure it's rejected earlier in register_tool so that people aren't confused.

I don't think it makes sense to prevent this, there are many other ways to make an unusable attribute that are not rejected, like mod rustc_something { pub use my_attribute; } or use my_attribute as rustc_something;, but we do not prohibit modules or imports containing rustc preventively.

Copy link

Choose a reason for hiding this comment

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

As long as we are consistent. Either it works without any hacks or it fails early on.

@scrabsha
Copy link

scrabsha commented May 7, 2025

I (static analysis software developer) would totally use this for any annotation that is not a contract. Thanks for your work!

Copy link

@carolynzech carolynzech left a comment

Choose a reason for hiding this comment

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

Thank you!

Comment on lines 10 to 11
- `#![register_lint_tool(tool_name)]` allows controlling namespaced lints with `#[warn(tool_name::lint_name)]`
- `#![register_attribute_tool(tool_name)]` allows using tool names in [inert attributes][inert] with `#[tool_name::attribute_name(token_tree)]`.
Copy link

Choose a reason for hiding this comment

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

May I suggest we use #![register_tool_{attribute|lint} instead? I was also wondering if we could have a #[register_tool] which would add the tool to both namespaces, the attribute and lint.

Copy link

Choose a reason for hiding this comment

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

I worry that register_tool_{attribute|lint} will imply we are registering individual attributes or individual lints, when that is not the case. If someone sees the attribute #![register_tool_lint(...)], I worry they'll do this:

#![register_tool_lint(bevy::panicking_methods)]
#![register_tool_lint(bevy::missing_reflect)]
#![register_tool_lint(bevy::duplicate_bevy_dependencies)]
// ...

I think the name register_lint_tool much better signals that it's for registering a tool, not a lint or attribute.

Copy link

Choose a reason for hiding this comment

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

Gotcha... That makes sense. Thanks

Copy link
Member

Choose a reason for hiding this comment

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

unless we allow nested tool name like com::example::tool1, I don't think #![register_tool_lint(bevy::panicking_methods)] will compile because the tool name can only be an $:ident not a $:path, so it is actually not an issue.

Footnotes

  1. #![warn(com::example::tool::lint)] is interpreted as having a tool name com.

Copy link
Member Author

Choose a reason for hiding this comment

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

sure, but why not avoid the confusion in the first place?

Copy link
Member Author

Choose a reason for hiding this comment

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

I have added #![register_tool] as an alias for adding both attributes.

Copy link
Member

Choose a reason for hiding this comment

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

sure, but why not avoid the confusion in the first place?

IMO #![register_tool(clippy)] is also confusing, it sounds like it will make rustc run the "tool" clippy by "registering" it to the compilation process. The standard reference refers to this as "tool name" rather than just "tool". I think #![register_tool_name(clippy)] would be clear, but #![register_attribute_tool_name(clippy)] is quite verbose.

Copy link
Member Author

Choose a reason for hiding this comment

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

That's not what "register" means. I think there is some amount of confusion possible, but I don't think it's likely enough that we need to make all the names longer. If people are adding these attributes, it's because the tool's docs told them to, and the docs should also say how to run the tool. If people are reading these attributes in existing code, then, well, I don't think it's that much more confusing than any other attribute in the language? #[inline] especially does not mean what most people think it means.

@ssbr
Copy link
Contributor

ssbr commented May 9, 2025

not sure who maintains crubit, maybe @ssbr ?

(Yup). FWIW, the main downside with this proposal is that it requires some extra work on the user's POV.

Here's the current Crubit workflow:

  • You depend on a crubit_annotate crate, which has a bunch of attribute-macros which will check that you have well-formed inputs, and expand to a structured doc-comment.
  • Crubit itself parses the doc-comment.

(We used to use tool attributes, before @cramertj created this new setup.)

Now, with the proposal, AIUI, to have a similar workflow using tool attributes, the user must both depend on the attribute macro crate, as well as independently register the tool attribute which the proc macro will generate. This is unfortunate -- the user needs to do two things, and needs to know the name of the tool attribute even if they never spell it.

I like the proc macro wrapper, because it can force compile-time errors even if you happen to not be running the tool at the moment. The metadata Crubit consumes is not necessarily simple and so does need some validation. My preference as far as user experiences go are that a proc macro can generate inert attributes without them being registered by the crate that uses the proc macro, or else that there's a globally-available tool attribute, similar to clang::annotate, so that we could generate something like rust::tool_attribute(crubit::attribute_name, extra, args, go, here). That way, the only thing the user needs to do is depend on the attribute macro crate, and not worry about what it does past that.

I'm hoping this helps. FWIW, we have a working process, and I think this proposal is certainly compatible with many paths forward that lead to what I want, and definitely doc-comments are a bit... egh. Thanks for all your work here, and thanks for soliciting more feedback! I really appreciate it.

Comment on lines 10 to 11
- `#![register_lint_tool(tool_name)]` allows controlling namespaced lints with `#[warn(tool_name::lint_name)]`
- `#![register_attribute_tool(tool_name)]` allows using tool names in [inert attributes][inert] with `#[tool_name::attribute_name(token_tree)]`.
Copy link
Member Author

Choose a reason for hiding this comment

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

I have added #![register_tool] as an alias for adding both attributes.


- Proc macros wish to register custom lints; see [`proc_macro_lint`]. We would have to establish some mechanism to prevent overlapping namespaces. Perhaps `warn(::project::lint_name)` could refer to the proc macro and `warn(project::lint_name)` would refer to any registered tool (only when a `project` tool is regisetered; in the common case where no tool is registered, `project::` would still refer to the proc macro).
- Projects may wish to have both a proc-macro crate with lints and a CLI with lints. To allow this, we would require `proc_macro_lint` to create an exhaustive list of lints that can be created, such that we can still run `unknown_lints` and do not need to create a new cooperation mechanism between `proc_macro_lint` and `register_lint_tool`, nor to require users of the project to distinguish the two with `::project` (see immediately above). We might still run into difficulty if the proc-macro lint namespace is only active while the proc-macro is expanding; it depends on how `proc_macro_lint` is specified. But I think it's ok to delay that discussion until `proc_macro_lint` gets an RFC.
- We could allow proc-macros to register a scoped tool, such that e.g. `#[serde::flatten]` is valid while the proc-macro is expanding, but not elsewhere in the crate. This is similar to [derive helpers], but namespaced. We would have to take care to avoid ambiguity between the scoped tool and globally registered tools in such a way that external tools still do not need to perform name resolution.
Copy link
Member Author

Choose a reason for hiding this comment

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

@ssbr i'm going to respond to you here so we can have things in threads; i think derive helpers are basically what you're asking for.

Now, with the proposal, AIUI, to have a similar workflow using tool attributes, the user must both depend on the attribute macro crate, as well as independently register the tool attribute which the proc macro will generate. This is unfortunate -- the user needs to do two things, and needs to know the name of the tool attribute even if they never spell it.

so, this reminds me strongly of derive macro helpers. i double checked just now and derive helpers are preserved by macro-expansion. so i expect you to continue to be able to use your proc-macro after this is stabilized, it would just use a different (non-namespaced) syntax. that seems ok - extending derive helpers to a namespace is a nice addition, but i don't think it's strictly necessary for you to keep using this. i don't see a need for proc macros to use the same syntax as hand-written code.

Copy link
Contributor

@ssbr ssbr May 9, 2025

Choose a reason for hiding this comment

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

Are derive macro helpers also able to be emitted by, well, non-derive macros? They could work, I don't think we tried them.

i don't see a need for proc macros to use the same syntax as hand-written code.

+1

Copy link
Member Author

Choose a reason for hiding this comment

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

i'm not sure if they are today, but that seems like a very reasonable extension RFC. i am not going to write that RFC but you are welcome to and i can give you pointers on how to get started.

i'll add this to future extensions.

# Future possibilities
[future-possibilities]: #future-possibilities

- We could allow registering tools in Cargo.toml (with a `package.tools` field?). This would avoid duplicating tool registration for each crate in the workspace. This depends on [`--crate-attr`] being stabilized.
Copy link
Contributor

Choose a reason for hiding this comment

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

We should also consider this process allowing registering tool-specific cfgs (e.g. cfg(kani))

We might want to consider a way for tools to define these entries and for users to pull them in somehow.

A tools table may have enough overlap with runnable dependencies that we may want to develop one with the other in mind.

We need to consider whether this table is a workspace table like [profiles] or a package table. For the former, we should auto-copy it to the package on publish like we do workspace.resolver. If the latter, we should consider whether workspace inheritance should be allowed.

Copy link
Member Author

@jyn514 jyn514 May 9, 2025

Choose a reason for hiding this comment

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

We should also consider this process allowing registering tool-specific cfgs (e.g. cfg(kani))

This seems reasonable, but not all tools support cfgs, so doing it for all tools defeats the point of check-cfg. So we would need some way to configure the behavior.

I would be extremely surprised to see someone building an external tool as a dependency. I can mention it I guess but I don't know that it makes sense to go out of our way to support it.

I don't have strong opinions on the other things, but I will mention them in future possibilities. I do feel weakly that this should be a package table that allows workspace inheritance, I don't think we need to restrict all packages in a workspace to use the same tools.


Unknown tool names in lints remain a hard error until the story for proc-macro lints is resolved (see [Future possibilities](#future-possibilities)).

`#![no_implicit_prelude]` does not affect tools.
Copy link
Member

Choose a reason for hiding this comment

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

What does this sentence mean?

(1) If by "tool" you mean "tool name", today #![no_implicit_prelude] does skip the tool prelude and thus remove all the tool names from the attributes (but not lints, perhaps a bug), so the "tool names" do get affected.

#![no_implicit_prelude]
#[deny(clippy::identity_op)] // unexpected, won't raise E0710 (unknown tool name)
#[rustfmt::skip] // expected, error[E0433]: failed to resolve: use of unresolved module or unlinked crate `rustfmt`
const X: u8 = 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 +0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0;

(2) If by "tool" you mean "tool invocation" then yes, the tool does not need to respect #![no_implicit_prelude]. For instance rustfmt recognizes the #[rustfmt::skip] here just fine. But tools that rely on rustc such as clippy will still be affected by E0433.

(3) Or "tool" here just mean the register_tool call and that the following behaves the same with or without #![no_implicit_prelude]?

#![no_implicit_prelude]
#![register_tool(bevy)] // always ok
#![register_tool(rustc)] // always error

Copy link
Member Author

Choose a reason for hiding this comment

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

I do mean 1), tool name. The RFC is specified in terms of the behavior that will be stabilized, not in terms of the current implementation.

@danielhenrymantilla
Copy link

Very nice! 🙌


I'm not understanding 100% the reasoning behind denying the ambiguous inert tool attribute vs. a genuine attribute, although maybe my confusion stems from rustfmt::skip being rather special / purely syntactical (although I could envision there being other purely-syntactical markers by some "cheap" tools or whatnot, right?).

Consider the following:

mod rustfmt {
    pub use ::tokio::main as skip;
}

#[rustfmt::skip]
async fn main()
             {}
  • this, currently, does compile perfectly fine;
  • and rustfmt does see the rustfmt::skip and does not reformat that fn main.

A tool (inert) attribute is just that, an inert / nothing-doing syntactical marker that the compiler is to let slide. But a genuine attribute, is just as much a syntactical marker as an inert attribute; so I do wonder about non-compiler-name-res-using tools such as rustfmt not making a difference between the two.

But I imagine that if a tool were to hook itself onto compiler machinery so as to actually involve name res and semantics, then a difference between a genuine attribute and an inert one could be made.

In which case, denying the ambiguity makes sense.

But all this may hint at some mention of the distinction between semantics-capable tools (e.g., able to resolve cfgs), vs. purely-syntactical ones being warranted? 🙂

Comment on lines +161 to +169
Ambiguity between a tool name and any other name in the type namespace is always a hard error. For example, this code would error:

```rust
#![register_tool(name)]

extern crate name;
#[name::skip] // ERROR: ambiguous
#[::name::skip] // OK
fn foo() {}
Copy link
Member Author

Choose a reason for hiding this comment

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

I'm not understanding 100% the reasoning behind denying the ambiguous inert tool attribute vs. a genuine attribute
A tool (inert) attribute is just that, an inert / nothing-doing syntactical marker that the compiler is to let slide. But a genuine attribute, is just as much a syntactical marker as an inert attribute; so I do wonder about non-compiler-name-res-using tools such as rustfmt not making a difference between the two.

But I imagine that if a tool were to hook itself onto compiler machinery so as to actually involve name res and semantics, then a difference between a genuine attribute and an inert one could be made.

In which case, denying the ambiguity makes sense.

@danielhenrymantilla i think you are imagining that the tool is responsible for checking there is no ambiguity. that is not the case. the compiler is responsible for checking there is no ambiguity, precisely because we want to allow tools that don't do name-res to still use attributes. it's ok if tools accept more code than the compiler, but i think it would be quite bad if the tool interpreted the code differently than the compiler (this is the same reason i have a big "please don't use attributes that change the meaning of the code" mention in the "tool author guide" section).

But all this may hint at some mention of the distinction between semantics-capable tools (e.g., able to resolve cfgs), vs. purely-syntactical ones being warranted? 🙂

i think distinguishing here is unnecessary complexity, and if we can get away with it we should just use the same rules for all of them. the exception here is between attribute_tool and lint_tool: since they don't affect name res for each other, we can make it easier to add lint-only tools that have the same name as an existing crate without causing breakage. but i don't think we should add more types of tools than necessary.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-lang Relevant to the language team, which will review and decide on the RFC.
Projects
None yet
Development

Successfully merging this pull request may close these issues.