Rollup merge of #67800 - Aaron1011:fix/mir-generic-instance, r=oli-obk
Fix ICE involving calling `Instance.ty` during const evaluation Fixes #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.
This commit is contained in:
commit
3692075049
12 changed files with 73 additions and 13 deletions
|
|
@ -62,10 +62,35 @@ pub enum InstanceDef<'tcx> {
|
|||
}
|
||||
|
||||
impl<'tcx> Instance<'tcx> {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> InstanceDef<'tcx> {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
match ty.kind {
|
||||
ty::FnDef(..) |
|
||||
// Shims currently have type FnPtr. Not sure this should remain.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue