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

Make rustc_target usable outside of rustc #103693

Merged
merged 3 commits into from
Nov 24, 2022
Merged

Conversation

HKalbasi
Copy link
Member

I'm working on showing type size in rust-analyzer (rust-lang/rust-analyzer#13490) and I currently copied rustc code inside rust-analyzer, which works, but is bad. With this change, I would become able to use rustc_target and rustc_index directly in r-a, reducing the amount of copy needed.

This PR contains some feature flag to put nightly features behind them to make crates buildable on the stable compiler + makes layout related types generic over index type + removes interning of nested layouts.

@rustbot
Copy link
Collaborator

rustbot commented Oct 28, 2022

r? @petrochenkov

(rustbot has picked a reviewer for you, use r? to override)

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. 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 Oct 28, 2022
@petrochenkov
Copy link
Contributor

Which parts of rustc_target do you need for rust-analyzer?
Maybe it's some more or less self-contained subset that can be factored out to a separate crate instead?

I'm going to nominate this for @rust-lang/compiler to gather feedback.

@petrochenkov petrochenkov added S-waiting-on-team Status: Awaiting decision from the relevant subteam (see the T-<team> label). I-compiler-nominated Nominated for discussion during a compiler team meeting. and removed T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Oct 28, 2022
@HKalbasi
Copy link
Member Author

Things I need overall are rustc_target::abi::*, rustc_index::IndexVec, rustc_middle::ty::ReprOptions and some of codes in rustc_ty_utils::layout. It might make sense to move all of them to a rustc_layout crate?

@thomcc
Copy link
Member

thomcc commented Oct 28, 2022

IIRC there are a few parts of this that would be useful for cc too (perhaps unsurprisingly).

@mati865
Copy link
Contributor

mati865 commented Oct 29, 2022

Intellij-rust would also be interested in using such crate so there are more reasons to do that.

@petrochenkov
Copy link
Contributor

It might make sense to move all of them to a rustc_layout crate?

I've heard something about this idea before, from @eddyb maybe?

@oli-obk
Copy link
Contributor

oli-obk commented Oct 29, 2022

What's the way you plan to use this crate? Download the rustc-src component and build it from there?

@HKalbasi
Copy link
Member Author

No, I want to use auto published versions in crates.io, similar to how rustc_lexer is used in rust analyzer.

@oli-obk
Copy link
Contributor

oli-obk commented Oct 29, 2022

OK, so from our end we don't need to have any stability across releases? Just publish breaking version bumps when they happen?

@eddyb
Copy link
Member

eddyb commented Nov 1, 2022

It might make sense to move all of them to a rustc_layout crate?

I've heard something about this idea before, from @eddyb maybe?

Thanks for pinging me, though I'm not sure how useful I can be for this specific usecase.

One of the old thoughts (circa 2017 IIRC?) about the whole ABI (incl. type layout) abstraction system in rustc_target, was indeed to let it be reusable, as long as a compiler has a close enough concept of "interned types" and can compute layouts from those types.

Naming-wise, I prefer putting "type layout" under the larger umbrella of "ABI", i.e. I've been wanting to rename ty::layout to ty::abi, but perhaps @RalfJung has conflicting opinions (and mine aren't that strong anyway).

In terms of making the Rust type -> layout computation reusable (which I would put in rustc_target::abi::layout, or if that seems like bundling too much together, rustc_abi::layout - in fact, rustc_target::spec could became rustc_abi::target_spec, and still keep everything together in one crate, but maybe that's going too far?)
the way I would do it is make a simpler categorization of Rust types (halfway between Ty and Layout), so that the rustc-specific code creates shallow values/calls methods to "explain" Ty (erasing e.g. the distinction between enum/struct/tuples/closures, pretending ! is just an empty enum, etc. etc.) to the hypothetical reusable code that computes the complete Layout.

However if you want to be 1:1 compatible with rustc, this may be an X/Y problem, because rustc's logic both changes over time and is dependent on compilation flags and e.g. internal details of incremental-stable hashing (for e.g. the randomized padding mode - similar to how you cannot predict the value of TypeId for a type without a lot of rustc's code).

So it would be useful to know the limitations you expect - you mention type size, and you could approximate that, but if you want to be exact, testing-oriented features like #[rustc_layout(debug)] are the most accurate option right now...

@rustbot rustbot added the T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap) label Nov 1, 2022
@rustbot
Copy link
Collaborator

rustbot commented Nov 1, 2022

Some changes occurred in src/tools/clippy

cc @rust-lang/clippy

@HKalbasi
Copy link
Member Author

HKalbasi commented Nov 1, 2022

I moved ReprOptions and parts of layout code in rustc_ty_utils to rustc_target::abi::layout.

In terms of making the Rust type -> layout computation reusable ...

I had the same thing in my mind and tried to implement it. There is now a function for unions, a function for structs and enums, one for never type, and a function for univariants which is used for closures and similars and inside implementation of structs. I think it covers most of the interesting parts, and the rest is some type-dependent boilerplate which trying to reuse them will cause more trouble than good, until a shared representation of types between rustc and rust-analyzer.

However if you want to be 1:1 compatible with rustc, this may be an X/Y problem, because rustc's logic both changes over time and is dependent on compilation flags and e.g. internal details of incremental-stable hashing (for e.g. the randomized padding mode - similar to how you cannot predict the value of TypeId for a type without a lot of rustc's code).

I want to be compatible with the latest stable rustc with a reasonable delay, and I think by frequently bumping the rustc_target it can be achieved. About compiler flags, I do want to support flags available on stable, but not supporting -Z randomize-layout and similar unstable flags is fine I think. But this is my opinion, @jonas-schievink do you consider not being 1:1 compatible with rustc as a deal breaker for showing type sizes in r-a?

@jonas-schievink
Copy link
Contributor

Probably not, we're not 100% compatible in other ways already.

@pnkfelix
Copy link
Member

pnkfelix commented Nov 3, 2022

So the big risks I can see here are:

  1. This is hopefully "just a big refactoring", but its hard to actually verify that it is a refactoring, apart from the fact that the tests all still pass without being modified. (Maybe that's the best we can hope for.)
  2. Is there some way to ensure that future changes don't break the usage patterns this person is seeking to support? (Could some unit tests on this PR somehow confirm this, or some other way of locally verifying that the exported forms of the crates "conform" to your expectations?)

@pnkfelix
Copy link
Member

pnkfelix commented Nov 3, 2022

As an example of what I meant by 2, @wesleywiser brought up the idea in the triage meeting of a CI check to make sure the crate compiles on stable.

@pnkfelix
Copy link
Member

pnkfelix commented Nov 3, 2022

We discussed this in T-compiler triage, see discussion here

Overall we think things can move forward here. There may be a number of creaky spots that we'll have to deal with (e.g. adding CI checks as mentioned above, and also the auto-publish scripts haven't actually been running for a while). But these issues need not block this PR.

@bors
Copy link
Contributor

bors commented Nov 24, 2022

📌 Commit 390a637 has been approved by oli-obk

It is now in the queue for this repository.

@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. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Nov 24, 2022
@bors
Copy link
Contributor

bors commented Nov 24, 2022

⌛ Testing commit 390a637 with merge b3bc6bf...

@bors
Copy link
Contributor

bors commented Nov 24, 2022

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

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (b3bc6bf): comparison URL.

Overall result: no relevant changes - no action needed

@rustbot label: -perf-regression

Instruction count

This benchmark run did not return any relevant results for this metric.

Max RSS (memory usage)

Results

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
3.1% [2.1%, 4.2%] 3
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-1.9% [-1.9%, -1.9%] 1
All ❌✅ (primary) - - 0

Cycles

Results

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
2.9% [2.8%, 3.0%] 3
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-2.0% [-2.0%, -2.0%] 1
All ❌✅ (primary) - - 0


#[derive(PartialEq, Eq, Hash, Clone)]
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
pub struct LayoutS<V: Idx> {
Copy link
Member

Choose a reason for hiding this comment

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

If you removed the other Layout, can you please rename this back?

The S suffix is a historical accidental that has been recently re-perpetuated, and I've told some people about it but sadly without more communication it won't be systemically fixed.

(i.e. it's always a mistake to do, the correct thing looks more like LayoutData, etc. - or in this case, since the weird-new-style interning is gone again, just Layout).

Copy link
Member

Choose a reason for hiding this comment

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

cc @oli-obk who seems to have been cleaning up some of that noise

Copy link
Member Author

Choose a reason for hiding this comment

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

Layout is still there, in rustc_target, just nested layouts are not interned.

}

#[derive(PartialEq, Eq, Hash, Clone, Debug)]
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
Copy link
Member

Choose a reason for hiding this comment

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

These features should've been named dep-of-rustc or something, HashStable_Generic is internal and not available "on nightly".

Copy link
Member Author

Choose a reason for hiding this comment

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

Hmm, maybe nightly isn't the best name, but since the auto publish script will publish dependencies as well, it will work in a nightly compiler and doesn't need to be in rustc necessarily.

Comment on lines +1323 to +1324
impl Target {
pub fn parse_data_layout<'a>(&'a self) -> Result<TargetDataLayout, TargetDataLayoutErrors<'a>> {
Copy link
Member

Choose a reason for hiding this comment

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

I don't like that this is in the "spec" section, the syntax is not dictated by rustc target specs, it's a LLVM thing.

So maybe we need TargetDataLayout::parse_from_llvm_datalayout_string and then this method can keep the extra checks?

Comment on lines +3 to +14
#![cfg_attr(
feature = "nightly",
feature(
allow_internal_unstable,
extend_one,
min_specialization,
new_uninit,
step_trait,
stmt_expr_attributes,
test
)
)]
Copy link
Member

Choose a reason for hiding this comment

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

Oh, I see... So you want both a "nightly" feature and a "dep-of-rustc" feature (or however that's spelled) and then the latter should imply the former.

Comment on lines 22 to 27
rustc_index::newtype_index! {
pub struct VariantIdx {
derive [HashStable_Generic]
}
}

Copy link
Member

Choose a reason for hiding this comment

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

Why keep this here? Does RA want to substitute its own?

(Long-term it might make sense to have Layout take, as a generic parameter, some type that implements a trait with one associated parameter per type we want to customize etc. - instead of just adding more and more parameters - if the need arises, anyway)

Speaking of which, such a generic parameter would've allowed you to keep interning for variants, for rustc (which IIRC @nnethercote added intentionally), but use e.g. Box<Layout<...>> in other cases.

Copy link
Member Author

Choose a reason for hiding this comment

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

Why keep this here? Does RA want to substitute its own?

It needed to make changes rustc_macros, and r-a had an index system itself, so I choosed to do this.

Long-term it might make sense to have Layout take, as a generic parameter, some type that implements a trait with one associated parameter per type

Similar to chalk's interner. It make sense, but currently there is only one such argument. If we want to bring interning of nested layouts back (which doesn't showed itself in perf, maybe it only affects memory usage?) I can do that.

matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Dec 1, 2022
Extract llvm datalayout parsing out of spec module

fix rust-lang#103693 (comment)
Dylan-DPC added a commit to Dylan-DPC/rust that referenced this pull request Dec 1, 2022
Extract llvm datalayout parsing out of spec module

fix rust-lang#103693 (comment)
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Dec 1, 2022
Extract llvm datalayout parsing out of spec module

fix rust-lang#103693 (comment)
flip1995 pushed a commit to flip1995/rust that referenced this pull request Dec 1, 2022
Make rustc_target usable outside of rustc

I'm working on showing type size in rust-analyzer (rust-lang/rust-analyzer#13490) and I currently copied rustc code inside rust-analyzer, which works, but is bad. With this change, I would become able to use `rustc_target` and `rustc_index` directly in r-a, reducing the amount of copy needed.

This PR contains some feature flag to put nightly features behind them to make crates buildable on the stable compiler + makes layout related types generic over index type + removes interning of nested layouts.
@sunmy2019
Copy link

#117812 bisects to this

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. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap) T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.