-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Specify the behavior of file!
#134442
base: master
Are you sure you want to change the base?
Specify the behavior of file!
#134442
Conversation
This takes the current behavior of `file!` and documents it so it is safe to make assumptions about. For example, Cargo could provide a `CARGO_RUSTC_CURRENT_DIR` as a base path for `file!`. Example use cases - Being able to look up test assets relative to the current file ([example](https://github.com/rust-lang/cargo/blob/b9026bf654d7fac283465e58b8b76742244ef07d/tests/testsuite/cargo_add/add_basic/mod.rs#L34)) - Inline snapshotting libraries being able to update Rust source code ([example](https://github.com/rust-lang/cargo/blob/b9026bf654d7fac283465e58b8b76742244ef07d/tests/testsuite/alt_registry.rs#L36-L45)) See rust-lang/cargo#3946 for more context. T-libs-api discussed two solutions in rust-lang/libs-team#478 - `file_absolute!`: - Has less meaning in other build tools like buck2 - Bakes in the assumption that a full path is available (e.g. with trim-paths) - Specifying `file!`s behavior (this PR): - Leaves it to the user to deal with trim-paths - Even though `file!` is currently unspecified, changing it would likely have too large of an impact on the ecosystem at this time. A future possibility is that rustc could have a flag that controls modifies the base path used for `file!`. That seems purely additive with specifying the behavior and we do not want to block on it. It would also likely be too disruptive for Cargo users (as mentioned). However, we tried to keep this in mind when specifying the behavior.
rustbot has assigned @workingjubilee. Use |
I assume @rust-lang/libs-api would want to review the text but, from what I understand, T-lang is the ultimate decider on built-in macros. |
This documents the existing behavior, and it is hedging about potential future changes (compiler command-line options). Nonetheless, since this could be interpreted as a new guarantee, it's a potential one-way door, so: @rfcbot merge Nominating for T-lang discussion. |
Team member @joshtriplett has proposed to merge this. The next step is review by the rest of the tagged team members: Concerns:
Once a majority of reviewers approve (and at most 2 approvals are outstanding), 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! cc @rust-lang/lang-advisors: FCP proposed for lang, please feel free to register concerns. |
@rfcbot reviewed |
1 similar comment
@rfcbot reviewed |
🔔 This is now entering its final comment period, as per the review above. 🔔 |
library/core/src/macros/mod.rs
Outdated
/// The file name is derived from the source path passed to the Rust compiler and any path operations | ||
/// performed on top of that (e.g. `#[path = "<child>"]` is joined to the current `file!`), |
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.
This seems confusing. You mean in the "child" module in question? Isn't that just, necessarily, the source path "passed to the Rust compiler"?
It seems like it's trying to mention this example as if it's an exception, when in reality "finding the path to an out-of-line module" is always a "path operation".
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.
This made sense to me as written. The filepath passed to the Rust compiler is always only the path of the root module. In every other module, the value of file!
is the result of a sequence of well-specifiable path operations performed on the root module's path.
For example in rustc path/to/root.rs
containing a #[path = "some/where.rs"]
module, file!
in the submodule would be "path/to/some/where.rs".
This paragraph is indicating that "path/to/some/where.rs" is derived from (sensitive to) 2 things:
-
The root module's source path as passed to the Rust compiler. So if you had run
rustc /absolute/path/to/root.rs
instead, orrustc ./wat/../path/to/root.rs
, you should expect that the submodule'sfile!
would be different, even though neither the root module nor child module has changed location in the filesystem. Ed's documentation is pointing out the important fact that the path passed to the compiler is relevant. -
The sequence through which we arrive from the root module to the module containing the
file!
call site, whether that'smod
or#[path = …]
orinclude!(…)
. If you change that, you should expect thatfile!
can return something different in the child module.
From your comment, it is not clear to me what possible unintended interpretation of the documentation is taking place. Is it about whether #[path = "<child>"]
constitutes a "path passed to the Rust compiler"? (It does not. The path passed to the Rust compiler refers to a command-line argument.)
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.
If it's confusing to an expert, then perhaps we might benefit by saying more or saying it differently. In fact, much of what you wrote by way of explanation could itself make sense in the documentation.
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.
#[path]
usually is an exceptional case (because it is designed to allow exceptional cases). mentioning an exceptional case without describing the normal case can mislead people in a number of directions. this includes the situation when the exceptional case is functionally identical to the normal case.- "what operations the compiler performs on filesystem paths such that I can understand what
file!
will give the name of" is not really addressed by the documentation at hand. it seems about 200 additional words was needed to describe what those are? - the purpose of our public-facing API documentation is to be useful to people who are not familiar with the vagaries of the matter at hand.
- we already have documentation that better describes the way files are discovered on the filesystem, and are probably better served by relating things back to it and expanding it if necessary: https://doc.rust-lang.org/reference/items/modules.html#module-source-filenames
- @dtolnay you seem to have noticed that remarks that are overly terse are hard to interpret. are you sure you were correct in interpreting "This seems confusing" as "I am confused"?
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.
Yes, if it was confusing, let's improve it. However, I don't see dtolnay's comments saying we shouldn't but providing an anchor for the conversation to find what aspect was confusing (and it was nice to get confirmation that I wasn't so far off the mark as a contributor). Thats important for understanding how to fix it. I find it helpful because I'm not fully clear on what the initial feedback is (it makes it sound like I'm saying <child>
is the root source module?).
So going off of the more specific points and with dtolnay's wording, I've made some tweaks. I hope they helped. In giving feedback, please help me understand why it seems confusing so we can discuss points on it.
I chose #[path]
because I felt it was simpler to provide an example (mod file vs non-mod, directory vs file mod, etc) but has some confusing parts as well (still conditioned on mod-file vs non-mod. I found making the example more concrete can bypass those cases and switched to using mod foo;
.
I hadn't thought of delegating to the reference but in looking at the reference, I worry that doing so would also be confusing because its framed around answering a different question (the module system) with assumptions like paths are relative to the source module's directory. I could see possibly linking to it for more details.
Something I want to be cautious about is distracting from the core messages of this documentation. The core point of file!
is whats currently documented. The core message of this new documentation is the base directory for relative paths while the rest is context to understand it and the limitations (maybe I'm being biased by my workflows).
@rfcbot reviewed |
@rustbot labels -I-lang-nominated We discussed this in our lang call today. It's now in FCP. |
library/core/src/macros/mod.rs
Outdated
/// The file name is derived from the root module's source path passed to the Rust compiler | ||
/// (e.g. `./src/lib.rs`) | ||
/// end the sequence the compiler takes to get from root module to the module containing `file!`. | ||
/// (e.g. inside `mod foo;` in `./src/lib.rs`, `file!` would be `./src/foo.rs`), |
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.
...or ./src/foo/mod.rs
:) Perhaps something like:
/// (e.g. inside `mod foo;` in `./src/lib.rs`, `file!` would be `./src/foo.rs`), | |
/// (e.g. if the root file of the crate is `./src/lib.rs`, and within that | |
/// crate there is a module `foo` whose source file is `./src/foo.rs`, then | |
/// `file!` called within will return `./src/foo.rs`), |
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.
Since there is a complete sentence before this, I think the parentheses could be removed and "e.g." replaced with "For example,".
As-is this parenthetical clause starts a sentence and then is followed by , modified by any...
, I think that trailer is meant to go with the first sentence (before this example) in either case.
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.
Agreed. The full stop ahead of the parenthetical seems an error, as the sentence does continue after the parenthetical. As you say, probably it'd be better to keep the sentence together and state the "For example" after it.
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.
I pulled the example out into a sentence at the end so that the longer example doesn't break the flow of the explanation.
ed56c74
to
2d3a81a
Compare
library/core/src/macros/mod.rs
Outdated
/// | ||
/// The expanded expression has type `&'static str`, and the returned file is not the invocation | ||
/// of the `file!` macro itself, but rather the first macro invocation leading up to the | ||
/// invocation of the `file!` macro. |
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.
I am just a daily rust user, not a compiler expert but I have used file macro before and I think this sentence is relatively hard to grasp. I think an example could help.
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.
I understood it as follows: If file!()
is called from another macro, then it returns the name of the file where the outer macro is called, not the file where the literal file!()
invocation is.
If that's correct, the original description is clear to me.
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.
Sorry if it looked like I was implying the documentation was wrong. That was not my intention, I was just asking for an example because it usually helps to understand things. If y'all think it's clear enough, feel free to resolve that thread.
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.
While it can be useful to find ways to improve documentation, this is out of scope of this PR. This was only called out because I didn't pay enough attention when I re-wrapped the lines and my editor and the author of this section's disagreed on the line wraps. I have since reverted that change.
The current implementation of There is a conflict between use of |
@rfcbot concern tension-between-uses
That's a good point. Let's discuss that and confirm whether we're still happy here. |
I don't think those two uses conflict here. If you want to use a library (e.g. a testing framework) that relies on having paths in The documentation says what the default behavior is, and notes that compiler options might change that behavior. |
This takes the current behavior of
file!
and documents it so it is safe to make assumptions about.For example, Cargo could provide a
CARGO_RUSTC_CURRENT_DIR
as a base path forfile!
.Example use cases
See rust-lang/cargo#3946 for more context.
T-libs-api discussed two solutions in rust-lang/libs-team#478
file_absolute!
:file!
s behavior (this PR):file!
is currently unspecified, changing it would likely have too large of an impact on the ecosystem at this time.A future possibility is that rustc could have a flag that controls modifies the base path used for
file!
.That seems purely additive with specifying the behavior and we do not want to block on it.
It would also likely be too disruptive for Cargo users (as mentioned). However, we tried to keep this in mind when specifying the behavior.