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

Provide layout_of automatically (given tcx + param_env + error handling). #88499

Merged
merged 3 commits into from
Sep 5, 2021

Conversation

eddyb
Copy link
Member

@eddyb eddyb commented Aug 30, 2021

After #88337, there's no longer any uses of LayoutOf within rustc_target itself, so I realized I could move the trait to rustc_middle::ty::layout and redesign it a bit.

This is similar to #88338 (and supersedes it), but at no ergonomic loss, since there's no funky C: LayoutOf<Ty = Ty> -> Ty: TyAbiInterface<C> generic impl chain, and each LayoutOf still corresponds to one impl (of LayoutOfHelpers) for the specific context.

After this PR, this is what's needed to get trait LayoutOf (with the layout_of method) implemented on some context type:

  • TyCtxt, via HasTyCtxt
  • ParamEnv, via HasParamEnv
  • a way to transform LayoutErrors into the desired error type
    • an error type of ! can be paired with having cx.layout_of(...) return TyAndLayout without Result<...> around it, such as used by codegen
    • this is done through a new LayoutOfHelpers trait (and so is specifying the type of cx.layout_of(...))

When going through this path (and not bypassing it with a manual impl of LayoutOf), the end result is that only the error case can be customized, the query itself and the success paths are guaranteed to be uniform.

(EDIT: just noticed that because of the supertrait relationship, you cannot actually implement LayoutOf yourself, the blanket impl fully covers all possible context types that could ever implement it)

Part of the motivation for this shape of API is that I've been working on querifying FnAbi::of_*, and what I want/need to introduce for that looks a lot like the setup in this PR - in particular, it's harder to express the FnAbi methods in rustc_target, since they're much more tied to rustc concepts.

r? @nagisa cc @oli-obk @bjorn3

@rust-highfive
Copy link
Collaborator

Some changes occured to the CTFE / Miri engine

cc @rust-lang/miri

Some changes occured to rustc_codegen_cranelift

cc @bjorn3

Some changes occurred in src/tools/clippy.

cc @rust-lang/clippy

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Aug 30, 2021
@eddyb
Copy link
Member Author

eddyb commented Aug 30, 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 Aug 30, 2021
@bors
Copy link
Contributor

bors commented Aug 30, 2021

⌛ Trying commit e9da4729d53073f1d7f785ffe3f05e6b60905743 with merge 5e7403551353c282c2f168ba6ff1b451eecb45a7...

fn to_result(self) -> Result<T, Self::Error> {
self
}
}
Copy link
Member

Choose a reason for hiding this comment

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

How does this work without specialization and not result in conflicting impls?

Copy link
Member Author

Choose a reason for hiding this comment

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

As I understand it, trying to unify Result<$0, _> with $0 (to check whether one of the impls applies in the context of the other one) will fail because its sole "solution" is an infinitely nested Result<Result<Result<... - in the literature, I believe this is called an "occurs check".

A crucial component of this, btw, is that MaybeResult is generic over the Ok/T type, instead of having it associated like the Err/Error type - if it was an associated type, it would indeed overlap.

This also shows up when implementing From: impl<T> From<T> for T doesn't involve specialization to avoid conflicting with your own different impls.

// `TyCtxt::at`-like APIs to be able to do e.g. `cx.at(span).layout_of(ty)`.
#[inline]
fn spanned_layout_of(&self, ty: Ty<'tcx>, span: Span) -> Self::LayoutOfResult {
let span = if !span.is_dummy() { span } else { self.layout_tcx_at_span() };
Copy link
Member

Choose a reason for hiding this comment

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

Why not directly use layout_tcx_at_span() in layout_of?

Copy link
Member Author

Choose a reason for hiding this comment

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

Because then I have to either duplicate the rest of the body, or end up with silly codegen that calls layout_tcx_at_span twice.

Overall I don't like the current design (where spanned_layout_of exists), and the way miri handles this (where its tcx field is a TyCtxtAt that it keeps updating) feels superior.

@bors
Copy link
Contributor

bors commented Aug 30, 2021

☀️ Try build successful - checks-actions
Build commit: 5e7403551353c282c2f168ba6ff1b451eecb45a7 (5e7403551353c282c2f168ba6ff1b451eecb45a7)

@rust-timer
Copy link
Collaborator

Queued 5e7403551353c282c2f168ba6ff1b451eecb45a7 with parent 6cfa773, future comparison URL.

@rust-timer
Copy link
Collaborator

Finished benchmarking try commit (5e7403551353c282c2f168ba6ff1b451eecb45a7): comparison url.

Summary: This benchmark run did not return any relevant changes.

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.

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

@rustbot rustbot removed the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Aug 30, 2021
@eddyb
Copy link
Member Author

eddyb commented Aug 30, 2021

Happy with those perf results (I was worried something might accidentally get worse in the reshuffle, but that doesn't seem to be the case).


/// `Span` to use for `tcx.at(span)`, from `layout_of`.
// FIXME(eddyb) perhaps make this mandatory to get contexts to track it better?
Copy link
Member

Choose a reason for hiding this comment

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

I can see something like CodegenCx needing to get better at it, but I don't see how having TyCtxt track any sort of span would work? If we made this required, we would have to drop the LayoutOfHelpers impls for TyCtxt and only keep the TyCtxtAt.

Seems reasonable enough, but also sounds like a big undertaking.


#[inline]
fn layout_tcx_at_span(&self) -> Span {
self.tcx.span
Copy link
Member

Choose a reason for hiding this comment

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

Ha, I spent a couple minutes wondering where is there a span in TyCtxt. Took me a while to notice this is an impl on a LayoutCx, not directly TyCtxtAt.

@nagisa
Copy link
Member

nagisa commented Sep 5, 2021

@bors r+

@bors
Copy link
Contributor

bors commented Sep 5, 2021

📌 Commit f53c93c has been approved by nagisa

@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 Sep 5, 2021
@bors
Copy link
Contributor

bors commented Sep 5, 2021

⌛ Testing commit f53c93c with merge e2750ba...

@bors
Copy link
Contributor

bors commented Sep 5, 2021

☀️ Test successful - checks-actions
Approved by: nagisa
Pushing e2750ba to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Sep 5, 2021
@bors bors merged commit e2750ba into rust-lang:master Sep 5, 2021
@rustbot rustbot added this to the 1.57.0 milestone Sep 5, 2021
@rust-highfive
Copy link
Collaborator

📣 Toolstate changed by #88499!

Tested on commit e2750ba.
Direct link to PR: #88499

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

rust-highfive added a commit to rust-lang-nursery/rust-toolstate that referenced this pull request Sep 5, 2021
Tested on commit rust-lang/rust@e2750ba.
Direct link to PR: <rust-lang/rust#88499>

💔 miri on windows: test-pass → build-fail (cc @eddyb @oli-obk @RalfJung).
💔 miri on linux: test-pass → build-fail (cc @eddyb @oli-obk @RalfJung).
@eddyb eddyb deleted the layout-off branch September 5, 2021 22:11
flip1995 pushed a commit to flip1995/rust that referenced this pull request Sep 8, 2021
Provide `layout_of` automatically (given tcx + param_env + error handling).

After rust-lang#88337, there's no longer any uses of `LayoutOf` within `rustc_target` itself, so I realized I could move the trait to `rustc_middle::ty::layout` and redesign it a bit.

This is similar to rust-lang#88338 (and supersedes it), but at no ergonomic loss, since there's no funky `C: LayoutOf<Ty = Ty>` -> `Ty: TyAbiInterface<C>` generic `impl` chain, and each `LayoutOf` still corresponds to one `impl` (of `LayoutOfHelpers`) for the specific context.

After this PR, this is what's needed to get `trait LayoutOf` (with the `layout_of` method) implemented on some context type:
* `TyCtxt`, via `HasTyCtxt`
* `ParamEnv`, via `HasParamEnv`
* a way to transform `LayoutError`s into the desired error type
  * an error type of `!` can be paired with having `cx.layout_of(...)` return `TyAndLayout` *without* `Result<...>` around it, such as used by codegen
  * this is done through a new `LayoutOfHelpers` trait (and so is specifying the type of `cx.layout_of(...)`)

When going through this path (and not bypassing it with a manual `impl` of `LayoutOf`), the end result is that only the error case can be customized, the query itself and the success paths are guaranteed to be uniform.

(**EDIT**: just noticed that because of the supertrait relationship, you cannot actually implement `LayoutOf` yourself, the blanket `impl` fully covers all possible context types that could ever implement it)

Part of the motivation for this shape of API is that I've been working on querifying `FnAbi::of_*`, and what I want/need to introduce for that looks a lot like the setup in this PR - in particular, it's harder to express the `FnAbi` methods in `rustc_target`, since they're much more tied to `rustc` concepts.

r? `@nagisa` cc `@oli-obk` `@bjorn3`
bjorn3 pushed a commit to bjorn3/rust that referenced this pull request Sep 19, 2021
Provide `layout_of` automatically (given tcx + param_env + error handling).

After rust-lang#88337, there's no longer any uses of `LayoutOf` within `rustc_target` itself, so I realized I could move the trait to `rustc_middle::ty::layout` and redesign it a bit.

This is similar to rust-lang#88338 (and supersedes it), but at no ergonomic loss, since there's no funky `C: LayoutOf<Ty = Ty>` -> `Ty: TyAbiInterface<C>` generic `impl` chain, and each `LayoutOf` still corresponds to one `impl` (of `LayoutOfHelpers`) for the specific context.

After this PR, this is what's needed to get `trait LayoutOf` (with the `layout_of` method) implemented on some context type:
* `TyCtxt`, via `HasTyCtxt`
* `ParamEnv`, via `HasParamEnv`
* a way to transform `LayoutError`s into the desired error type
  * an error type of `!` can be paired with having `cx.layout_of(...)` return `TyAndLayout` *without* `Result<...>` around it, such as used by codegen
  * this is done through a new `LayoutOfHelpers` trait (and so is specifying the type of `cx.layout_of(...)`)

When going through this path (and not bypassing it with a manual `impl` of `LayoutOf`), the end result is that only the error case can be customized, the query itself and the success paths are guaranteed to be uniform.

(**EDIT**: just noticed that because of the supertrait relationship, you cannot actually implement `LayoutOf` yourself, the blanket `impl` fully covers all possible context types that could ever implement it)

Part of the motivation for this shape of API is that I've been working on querifying `FnAbi::of_*`, and what I want/need to introduce for that looks a lot like the setup in this PR - in particular, it's harder to express the `FnAbi` methods in `rustc_target`, since they're much more tied to `rustc` concepts.

r? `@nagisa` cc `@oli-obk` `@bjorn3`
bors added a commit to rust-lang-ci/rust that referenced this pull request Sep 19, 2021
Querify `FnAbi::of_{fn_ptr,instance}` as `fn_abi_of_{fn_ptr,instance}`.

*Note: opening this PR as draft because it's based on rust-lang#88499*

This more or less replicates the `LayoutOf::layout_of` setup from rust-lang#88499, to replace `FnAbi::of_{fn_ptr,instance}` with `FnAbiOf::fn_abi_of_{fn_ptr,instance}`, and also route them through queries (which `layout_of` has used for a while).

The two changes at the use sites (other than the names) are:
* return type is now wrapped in `&'tcx`
  * the value *is* interned, which may affect performance
* the `extra_args` list is now an interned `&'tcx ty::List<Ty<'tcx>>`
  * should be cheap (it's empty for anything other than C variadics)

Theoretically, a `FnAbiOfHelpers` implementer could choose to keep the `Result<...>` instead of eagerly erroring, but the only existing users of these APIs are codegen backends, so they don't (want to) take advantage of this.
At least miri could make use of this, since it prefers propagating errors (it "just" doesn't use `FnAbi` yet - cc `@RalfJung).`

The way this is done is probably less efficient than what is possible, because the queries handle the correctness-oriented API (i.e. the split into `fn` pointers vs instances), whereas a lower-level query could end up with more reuse between different instances with identical signatures.

r? `@nagisa` cc `@oli-obk` `@bjorn3`
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.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants