-
Notifications
You must be signed in to change notification settings - Fork 13k
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
Don't keep {Closure,Generator}Substs synthetics in an Instance. #74341
Conversation
@bors try @rust-timer queue |
Awaiting bors try build completion |
⌛ Trying commit 6e4b8ef with merge fb73d5197a7ff8fff33c852694de43fdca79aa0a... |
@@ -224,7 +224,6 @@ impl Visitor<'tcx> for CollectItemTypesVisitor<'tcx> { | |||
if let hir::ExprKind::Closure(..) = expr.kind { | |||
let def_id = self.tcx.hir().local_def_id(expr.hir_id); | |||
self.tcx.ensure().generics_of(def_id); | |||
self.tcx.ensure().type_of(def_id); |
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 removed this line to make 29 UI tests pass - their only failure mode was missing some of the errors.
I believe what's happening is that this would now trigger type-checking the body of the closure, before bodies are normally type-checked, and so it trips on an "abort if any errors" check.
Can we start removing those "checkpoints" that turn regular errors into fatal ones, given how on-demand some of the various checks are nowadays? cc @estebank
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 think there are only a handful of FatalError.raise()
s left, and the ones that do remain do so because they'd require a much larger refactor to get rid of them.
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 they're because of having to return a value, I suspect using Result<T, ErrorReported>
could work well.
(But I meant "abort if there were any errors" "checkpoints", which we can just remove)
☀️ Try build successful - checks-actions, checks-azure |
Queued fb73d5197a7ff8fff33c852694de43fdca79aa0a with parent c724b67, future comparison URL. |
Finished benchmarking try commit (fb73d5197a7ff8fff33c852694de43fdca79aa0a): comparison url. |
Most of the wins are in some "patched incremental" benchmarks doing less codegen, I'm guessing something about a closure changes and it previously was treated as the identity of the closure instance changing, which was unnecessary and wasteful. Do note that the numbers are all "patched incremental", with negligible effects on anything else. Maybe |
tcx.mk_closure(def_id, substs) | ||
} | ||
Node::Expr(&Expr { kind: ExprKind::Closure(..), .. }) => { | ||
tcx.typeck_tables_of(def_id.expect_local()).node_type(hir_id) |
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 feels wrong to me. We basically undid a move much like this for generators, though partly it was to avoid those type error problems you were referring to with your other change.
But also it is just surprising to me to have type_of
require us to type-check the closure. For every other def-id, getting type_of
doesn't require a full type-check, but rather returns a "fully generic" type. i.e., I would expet the type of a closure or generator ought to be expressed as a purely generic type like Closure<P0...Pn>
, much like we'd expect for a function, not one that embeds full types like Closure<..., (u32, u64)>
or whatever. Do we have any other example that works like that?
Anyway, what is the exact motivation here? It's confusing 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.
Ah, ok, I see, the point is that you want Instance
to be able to substitute only the base_params
and to still get a valid type... hmm. Interesting. I'm not sure what I think about it. I'm surprised this gives much of a win, can you explain why it does?
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 we do land this, I feel like we need some kind of comment..somewhere...that explains this rather subtle point. I guess it would be best to document it on the ClosureSubsts
and GeneratorSubsts
structs.
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.
Ah, ok, I see, the point is that you want
Instance
to be able to substitute only thebase_params
and to still get a valid type... hmm. Interesting. I'm not sure what I think about it.
Me neither, I think I'd prefer if we could implement e.g. fn_sig
on closures instead, and use that from Instance
.
I could look into that approach once #74314 lands.
I'm surprised this gives much of a win, can you explain why it does?
All the wins are incremental, so it probably only makes sense if a closure changes its capture set/types, although that would still imply codegen is needed?
Or maybe non-generic closures are involved, which would now result in an Instance
with empty substs, which may be handled differently by CGUs.
Ping from triage: @nikomatsakis I believe this PR needs your review?
@eddyb I'm seeing that #74314 has landed now, did you have time to look into this? |
(This is now EDIT: Oops, I'm new to triage. |
I'm still vaguely against this PR, because it makes closures/generators "force" type check to complete just to do |
I'm going to close this PR for inactivity. @eddyb if you want to discuss this approach (or the |
Based on #74314, which removes the main use of synthetic type parameters in closure/generator
ty::Generics
This PR keeps the "synthetics" (closure kind/signature/upvar types, or similar information for generators) only in the
Ty
(Closure
/Generator
) substitutions (used during inference and for type layout), but not inInstance
s which are used to refer to the MIR body of the closure during codegen (and the MIR body doesn't refer to the "synthetics" at all).I originally started work on this to change the codegen behavior of closures with no type/const generics in scope (and have them not be deduplicated across crates), as per #74283 (comment) - but have since given up on that line of experimentation.
It might still improve some performance or help with @davidtwco polymorphization work, but it's not clear that it will.
r? @nikomatsakis