-
Notifications
You must be signed in to change notification settings - Fork 13.1k
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
Conversation
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 |
@bors try @rust-timer queue |
Awaiting bors try build completion. @rustbot label: +S-waiting-on-perf |
⌛ Trying commit e9da4729d53073f1d7f785ffe3f05e6b60905743 with merge 5e7403551353c282c2f168ba6ff1b451eecb45a7... |
fn to_result(self) -> Result<T, Self::Error> { | ||
self | ||
} | ||
} |
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.
How does this work without specialization and not result in conflicting impls?
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.
As I understand it, trying to unify Result<$0, _>
with $0
(to check whether one of the impl
s 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 impl
s.
// `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() }; |
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.
Why not directly use layout_tcx_at_span()
in layout_of
?
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.
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.
☀️ Try build successful - checks-actions |
Queued 5e7403551353c282c2f168ba6ff1b451eecb45a7 with parent 6cfa773, future comparison URL. |
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 |
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? |
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 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 |
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.
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
.
@bors r+ |
📌 Commit f53c93c has been approved by |
☀️ Test successful - checks-actions |
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).
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`
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`
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`
After #88337, there's no longer any uses of
LayoutOf
withinrustc_target
itself, so I realized I could move the trait torustc_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>
genericimpl
chain, and eachLayoutOf
still corresponds to oneimpl
(ofLayoutOfHelpers
) for the specific context.After this PR, this is what's needed to get
trait LayoutOf
(with thelayout_of
method) implemented on some context type:TyCtxt
, viaHasTyCtxt
ParamEnv
, viaHasParamEnv
LayoutError
s into the desired error type!
can be paired with havingcx.layout_of(...)
returnTyAndLayout
withoutResult<...>
around it, such as used by codegenLayoutOfHelpers
trait (and so is specifying the type ofcx.layout_of(...)
)When going through this path (and not bypassing it with a manual
impl
ofLayoutOf
), 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 blanketimpl
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 theFnAbi
methods inrustc_target
, since they're much more tied torustc
concepts.r? @nagisa cc @oli-obk @bjorn3