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

Remove SymbolStr #91957

Merged
merged 3 commits into from
Dec 19, 2021
Merged

Remove SymbolStr #91957

merged 3 commits into from
Dec 19, 2021

Conversation

nnethercote
Copy link
Contributor

This was originally proposed in #74554 (comment). As well as removing the icky SymbolStr type, it allows the removal of a lot of & and * occurrences.

Best reviewed one commit at a time.

r? @oli-obk

By changing `as_str()` to take `&self` instead of `self`, we can just
return `&str`. We're still lying about lifetimes, but it's a smaller lie
than before, where `SymbolStr` contained a (fake) `&'static str`!
@rust-highfive
Copy link
Collaborator

Some changes occured to rustc_codegen_cranelift

cc @bjorn3

Some changes occurred in src/tools/rustfmt.

cc @calebcartwright

Some changes occurred in clean/types.rs.

cc @camelid

Some changes occured to the CTFE / Miri engine

cc @rust-lang/miri

Some changes occurred in intra-doc-links.

cc @jyn514

Some changes occurred in src/tools/clippy.

cc @rust-lang/clippy

Some changes occured to rustc_codegen_gcc

cc @antoyo

@rustbot rustbot added T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue. labels Dec 15, 2021
@rust-highfive
Copy link
Collaborator

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @oli-obk (or someone else) soon.

Please see the contribution instructions for more information.

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Dec 15, 2021
/// as `&self`, but actually tied to the lifetime of the underlying
/// interner. Interners are long-lived, and there are very few of them, and
/// this function is typically used for short-lived things, so in practice
/// it works out ok.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I would be happy to see a better description than this, if anyone has one to offer.

@oli-obk
Copy link
Contributor

oli-obk commented Dec 15, 2021

@bors try @rust-timer queue

@rust-timer
Copy link
Collaborator

Awaiting bors try build completion.

@rustbot label: +S-waiting-on-perf

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Dec 15, 2021
@bors
Copy link
Contributor

bors commented Dec 15, 2021

⌛ Trying commit b1c934e with merge 2b0871127a9ec9258077c392af12778176772fa1...

@bors
Copy link
Contributor

bors commented Dec 15, 2021

☀️ Try build successful - checks-actions
Build commit: 2b0871127a9ec9258077c392af12778176772fa1 (2b0871127a9ec9258077c392af12778176772fa1)

@rust-timer
Copy link
Collaborator

Queued 2b0871127a9ec9258077c392af12778176772fa1 with parent 3ee016a, future comparison URL.

Comment on lines +1659 to +1663
/// Note that the lifetime of the return value is a lie. It's not the same
/// as `&self`, but actually tied to the lifetime of the underlying
/// interner. Interners are long-lived, and there are very few of them, and
/// this function is typically used for short-lived things, so in practice
/// it works out ok.
Copy link
Member

@camelid camelid Dec 15, 2021

Choose a reason for hiding this comment

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

I made a few edits. Feel free to apply none, some, or all:

Suggested change
/// Note that the lifetime of the return value is a lie. It's not the same
/// as `&self`, but actually tied to the lifetime of the underlying
/// interner. Interners are long-lived, and there are very few of them, and
/// this function is typically used for short-lived things, so in practice
/// it works out ok.
/// Note that the lifetime of the return value is a lie, so this function
/// is unsound. The runtime lifetime is not the same as `&self`;
/// it's actually tied to the lifetime of the underlying interner.
/// Interners are long-lived, there are very few of them, and
/// this function is typically used for short-lived things; so in practice
/// it works out ok.

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (2b0871127a9ec9258077c392af12778176772fa1): comparison url.

Summary: This change led to very large relevant mixed results 🤷 in compiler performance.

  • Very large improvement in instruction counts (up to -5.7% on incr-unchanged builds of inflate)
  • Small regression in instruction counts (up to 0.8% on incr-patched: println builds of coercions)

If you disagree with this performance assessment, please file an issue in rust-lang/rustc-perf.

Benchmarking this pull request likely means that it is perf-sensitive, so we're automatically marking it as not fit for rolling up. While you can manually mark this PR as fit for rollup, we strongly recommend not doing so since this PR led to changes in compiler perf.

Next Steps: If you can justify the regressions found in this try perf run, please indicate this with @rustbot label: +perf-regression-triaged along with sufficient written justification. If you cannot justify the regressions please fix the regressions and do another perf run. If the next run shows neutral or positive results, the label will be automatically removed.

@bors rollup=never
@rustbot label: +S-waiting-on-review -S-waiting-on-perf +perf-regression

@rustbot rustbot added perf-regression Performance regression. and removed S-waiting-on-perf Status: Waiting on a perf run to be completed. labels Dec 15, 2021
/// requires locking the symbol interner.
///
/// Note that the lifetime of the return value is a lie. See
/// `Symbol::as_str()` for details.
Copy link
Member

Choose a reason for hiding this comment

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

Uh, do we really want to have unsound functions in widely used crate-public APIs?

I very strongly feel that the answer is "no"...

Copy link
Member

Choose a reason for hiding this comment

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

FWIW, the API was already unsound before this, the comment just makes it slightly more obvious.

Copy link
Member

Choose a reason for hiding this comment

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

OTOH If anything this allows less code than the previous API (since the old return type outlived 'static), so I am confused why new warnings about unsoundness are coming up now.

Copy link
Member

Choose a reason for hiding this comment

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

Ah I found #91957 (comment), it was collapsed.

Copy link
Contributor

Choose a reason for hiding this comment

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

well, we already had unsound functions in widely used rustc internal APIs. This PR just makes it less easy to abuse, so the PR by itself is not making the situation worse.

The only real way to fix this is to start tracking lifetimes for it everywhere, which is a much bigger change.

If we got rid of the use case of running a compiler twice in the same process we could probably just never drop the interner and then everything would be sound?

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't get this argument. as_str now produces something that you can't really pass around at all, where SymbolStr had no lifetime binding it to Symbol. Sure you can send Symbol around, but you could do that before?

Copy link
Member

Choose a reason for hiding this comment

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

The &str is Send and Sync either way.

Copy link
Member

@RalfJung RalfJung Dec 15, 2021

Choose a reason for hiding this comment

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

The &str is Send and Sync either way.

Hm yeah that is fair. One could even implement the new API based on the old one in safe code (by leaking some memory), as you showed.

Copy link
Member

Choose a reason for hiding this comment

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

I think the only potential downside of the new API is that it makes it more annoying to unsoundly use it. Before, you would have had to store all the SymbolStrs somewhere, but now you just need the Symbols to come from a long-lived source.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think the only potential downside of the new API is that it makes it more annoying to unsoundly use it

Is that a downside? Sounds like a good thing to me 😄

@nnethercote
Copy link
Contributor Author

To be entirely sound the .as_str() method would need to be replaced with a .with_str() method taking a closure.

I looked at this a while back. There are several hundred uses of Symbol::as_str() and Ident::as_str(). For a lot of use cases it would be fine because the &str is used in a single place, often with a predicate like this:

if !ident.as_str().is_ascii() { ... }

But there are plenty of uses where a local &str is obtained and then that's used in multiple places within that function, with those uses often separated by multiple lines, and rewriting things within a closure to fit a with would be painful.

@jyn514
Copy link
Member

jyn514 commented Dec 15, 2021

Can we add a lifetime to Symbol that matches the lifetime of the interner? Something like fn intern(&self) -> Symbol<'_>; and all the preinterned symbols would have lifetime Symbol<'static>.

@bjorn3
Copy link
Member

bjorn3 commented Dec 15, 2021

I expect that to be painful as Symbol is used in various places where there is no existing context to tie a lifetime to.

@jyn514
Copy link
Member

jyn514 commented Dec 16, 2021

What do you mean? Symbols can't be used before the interner is constructed or intern() will panic.

@bjorn3
Copy link
Member

bjorn3 commented Dec 16, 2021

Currently no context that could contain a reference to the interner is passed around at a lot of places. Instead the TLS is used to obain the interner. Adding a lifetime to Symbol will require plumbing through a reference to the interner to a lot of places.

@oli-obk
Copy link
Contributor

oli-obk commented Dec 16, 2021

@bors r+

Let's move this along, it's a strict improvement, even if it doesn't fix the unsoundness

@bors
Copy link
Contributor

bors commented Dec 16, 2021

📌 Commit b1c934e has been approved by oli-obk

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Dec 16, 2021
@bors
Copy link
Contributor

bors commented Dec 19, 2021

⌛ Testing commit b1c934e with merge a41a692...

@bors
Copy link
Contributor

bors commented Dec 19, 2021

☀️ Test successful - checks-actions
Approved by: oli-obk
Pushing a41a692 to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Dec 19, 2021
@bors bors merged commit a41a692 into rust-lang:master Dec 19, 2021
@rustbot rustbot added this to the 1.59.0 milestone Dec 19, 2021
@rust-highfive
Copy link
Collaborator

📣 Toolstate changed by #91957!

Tested on commit a41a692.
Direct link to PR: #91957

💔 miri on windows: test-pass → build-fail (cc @oli-obk @RalfJung @eddyb).
💔 miri on linux: test-pass → build-fail (cc @oli-obk @RalfJung @eddyb).

rust-highfive added a commit to rust-lang-nursery/rust-toolstate that referenced this pull request Dec 19, 2021
Tested on commit rust-lang/rust@a41a692.
Direct link to PR: <rust-lang/rust#91957>

💔 miri on windows: test-pass → build-fail (cc @oli-obk @RalfJung @eddyb).
💔 miri on linux: test-pass → build-fail (cc @oli-obk @RalfJung @eddyb).
@rust-timer
Copy link
Collaborator

Finished benchmarking commit (a41a692): comparison url.

Summary: This change led to moderate relevant mixed results 🤷 in compiler performance.

  • Small improvement in instruction counts (up to -0.2% on full builds of externs)
  • Moderate regression in instruction counts (up to 3.1% on incr-patched: println builds of regression-31157)

If you disagree with this performance assessment, please file an issue in rust-lang/rustc-perf.

Next Steps: If you can justify the regressions found in this perf run, please indicate this with @rustbot label: +perf-regression-triaged along with sufficient written justification. If you cannot justify the regressions please open an issue or create a new PR that fixes the regressions, add a comment linking to the newly created issue or PR, and then add the perf-regression-triaged label to this PR.

@rustbot label: +perf-regression

@camelid
Copy link
Member

camelid commented Dec 19, 2021

regression-31157 opt seems to have been showing spurious perf changes recently. It happened to me on a rustdoc PR, where it's impossible for there to be perf changes for an opt build (since only doc builds can have changes).

fn to_stable_hash_key(&self, _: &CTX) -> SymbolStr {
self.as_str()
fn to_stable_hash_key(&self, _: &CTX) -> String {
self.as_str().to_string()
Copy link
Contributor

Choose a reason for hiding this comment

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

We could return &'static str here. It would propagate the lifetime lie, but basically the same as before.

@nnethercote nnethercote deleted the rm-SymbolStr branch December 20, 2021 06:14
bors added a commit to rust-lang-ci/rust that referenced this pull request Dec 20, 2021
Remove `SymbolStr`

This was originally proposed in rust-lang#74554 (comment). As well as removing the icky `SymbolStr` type, it allows the removal of a lot of `&` and `*` occurrences.

Best reviewed one commit at a time.

r? `@oli-obk`
@rylev
Copy link
Member

rylev commented Dec 21, 2021

This seems likely to be noise as a result of the issue tracked in rust-lang/rustc-perf#1126 -- marking as triaged, not something we should address directly.

@rustbot label +perf-regression-triaged

@rustbot rustbot added the perf-regression-triaged The performance regression has been triaged. label Dec 21, 2021
flip1995 pushed a commit to flip1995/rust that referenced this pull request Dec 30, 2021
Remove `SymbolStr`

This was originally proposed in rust-lang#74554 (comment). As well as removing the icky `SymbolStr` type, it allows the removal of a lot of `&` and `*` occurrences.

Best reviewed one commit at a time.

r? `@oli-obk`
bjorn3 pushed a commit to bjorn3/rust that referenced this pull request Dec 31, 2021
Remove `SymbolStr`

This was originally proposed in rust-lang#74554 (comment). As well as removing the icky `SymbolStr` type, it allows the removal of a lot of `&` and `*` occurrences.

Best reviewed one commit at a time.

r? `@oli-obk`
@nnethercote nnethercote mentioned this pull request Jan 28, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged-by-bors This PR was explicitly merged by bors. perf-regression Performance regression. perf-regression-triaged The performance regression has been triaged. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet