-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Fix ICE involving calling Instance.ty
during const evaluation
#67800
Conversation
r? @varkor (rust_highfive has picked a reviewer for you, use r? to override) |
Instance.ty
durign const evaluationInstance.ty
during const evaluation
51b9fa5
to
1e08f9e
Compare
This comment has been minimized.
This comment has been minimized.
1e08f9e
to
7e86561
Compare
This comment has been minimized.
This comment has been minimized.
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
@bors try @rust-timer queue |
Awaiting bors try build completion |
⌛ Trying commit b9dcd9814b4f8b37cfe0b0136cc10ed7797d30eb with merge c8783d8cf524e2ceaad6d300e62e58e68a6d22cf... |
☀️ Try build successful - checks-azure |
Queued c8783d8cf524e2ceaad6d300e62e58e68a6d22cf with parent 4877e16, future comparison URL. |
For some reason, the bot didn't comment saying that benchmarking completed. It looks like this change had no perf impact above the noise floor, as I had hoped. |
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.
Code and perf look good to me and the change seems reasonable enough but I don't think I know enough about the resolver to sign off on this myself. Perhaps @oli-obk or someone else could take a look as well?
Fixes rust-lang#67639 `Instance.ty` assumes that we are in a fully monomorphic context (e.g. codegen), and can therefore use an empty `ParamEnv` when performing normalization. Howver, the MIR constant evaluator code ends up calling `Instance.ty` as a result of us attemptign to 'speculatively' const-evaluate generic functions during const propagation. As a result, we may end up with projections involving type parameters (e.g. <T as MyTrait>::Bar>) in the type we are trying to normalize. Normalization expects us to have proper predicates in the `ParamEnv` for such projections, and will ICE if we don't. This commit adds a new method `Instance.ty_env`, which takes a `ParamEnv` for use during normalization. The MIR const-evaluator code is changed to use this method, passing in the proper `ParamEnv` for the context at hand.
Co-Authored-By: Wesley Wiser <wwiser@gmail.com>
b9dcd98
to
33caf0b
Compare
@oli-obk: Updated |
@@ -2301,7 +2301,7 @@ impl<'tcx> ty::Instance<'tcx> { | |||
// or should go through `FnAbi` instead, to avoid losing any | |||
// adjustments `FnAbi::of_instance` might be performing. | |||
fn fn_sig_for_fn_abi(&self, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> { | |||
let ty = self.ty(tcx); | |||
let ty = self.monomorphic_ty(tcx); |
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.
It's not obvious to me that this is correct. Ca you go up the call chain and see if there are any noncodegen uses?
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.
The only caller is FnAbi:of_instance
, which is only called from codegen.
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.
We need to stop assuming that codegen = monomorphic.
📌 Commit 336b902 has been approved by |
… r=oli-obk Fix ICE involving calling `Instance.ty` during const evaluation Fixes rust-lang#67639 `Instance.ty` assumes that we are in a fully monomorphic context (e.g. codegen), and can therefore use an empty `ParamEnv` when performing normalization. Howver, the MIR constant evaluator code ends up calling `Instance.ty` as a result of us attemptign to 'speculatively' const-evaluate generic functions during const propagation. As a result, we may end up with projections involving type parameters (e.g. <T as MyTrait>::Bar>) in the type we are trying to normalize. Normalization expects us to have proper predicates in the `ParamEnv` for such projections, and will ICE if we don't. This commit adds a new method `Instance.ty_env`, which takes a `ParamEnv` for use during normalization. The MIR const-evaluator code is changed to use this method, passing in the proper `ParamEnv` for the context at hand.
Rollup of 6 pull requests Successful merges: - #67800 (Fix ICE involving calling `Instance.ty` during const evaluation) - #67873 (change remove to have a PartialEq bound) - #67897 (Use `as_deref()` to replace `as_ref().map(...)`) - #67906 (Silence `TooGeneric` error) - #67912 (macros: typo fix) - #67915 (Use Self instead of $type) Failed merges: r? @ghost
pub fn ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { | ||
/// Returns the `Ty` corresponding to this `Instance`, | ||
/// with generic substitutions applied and lifetimes erased. | ||
/// | ||
/// This method can only be called when the 'substs' for this Instance | ||
/// are fully monomorphic (no `ty::Param`'s are present). | ||
/// This is usually the case (e.g. during codegen). | ||
/// However, during constant evaluation, we may want | ||
/// to try to resolve a `Instance` using generic parameters | ||
/// (e.g. when we are attempting to to do const-propagation). | ||
/// In this case, `Instance.ty_env` should be used to provide | ||
/// the `ParamEnv` for our generic context. | ||
pub fn monomorphic_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { | ||
let ty = tcx.type_of(self.def.def_id()); | ||
// There shouldn't be any params - if there are, then | ||
// Instance.ty_env should have been used to provide the proper | ||
// ParamEnv | ||
if self.substs.has_param_types() { | ||
bug!("Instance.ty called for type {:?} with params in substs: {:?}", ty, self.substs); | ||
} | ||
tcx.subst_and_normalize_erasing_regions(self.substs, ty::ParamEnv::reveal_all(), &ty) | ||
} | ||
|
||
/// Like `Instance.ty`, but allows a `ParamEnv` to be specified for use during | ||
/// normalization. This method is only really useful during constant evaluation, | ||
/// where we are dealing with potentially generic types. | ||
pub fn ty_env(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> { | ||
let ty = tcx.type_of(self.def.def_id()); | ||
tcx.subst_and_normalize_erasing_regions(self.substs, param_env, &ty) | ||
} |
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 would keep a single ty
method and force callers to pass in ty::ParamEnv::reveal_all()
(eventually all of codegen should have to keep track of a ParamEnv
anyway, because of @davidtwco's work on partial monomorphization).
Fixes #67639
Instance.ty
assumes that we are in a fully monomorphic context (e.g.codegen), and can therefore use an empty
ParamEnv
when performingnormalization. Howver, the MIR constant evaluator code ends up calling
Instance.ty
as a result of us attemptign to 'speculatively'const-evaluate generic functions during const propagation.
As a result,
we may end up with projections involving type parameters
(e.g. ::Bar>) in the type we are trying to normalize.
Normalization expects us to have proper predicates in the
ParamEnv
forsuch projections, and will ICE if we don't.
This commit adds a new method
Instance.ty_env
, which takes aParamEnv
for use during normalization. The MIR const-evaluator code ischanged to use this method, passing in the proper
ParamEnv
for thecontext at hand.