Skip to content

Commit 3692075

Browse files
authored
Rollup merge of rust-lang#67800 - Aaron1011:fix/mir-generic-instance, 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.
2 parents 33640f0 + 336b902 commit 3692075

File tree

12 files changed

+73
-13
lines changed

12 files changed

+73
-13
lines changed

src/librustc/ty/instance.rs

+26-1
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,35 @@ pub enum InstanceDef<'tcx> {
6262
}
6363

6464
impl<'tcx> Instance<'tcx> {
65-
pub fn ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
65+
/// Returns the `Ty` corresponding to this `Instance`,
66+
/// with generic substitutions applied and lifetimes erased.
67+
///
68+
/// This method can only be called when the 'substs' for this Instance
69+
/// are fully monomorphic (no `ty::Param`'s are present).
70+
/// This is usually the case (e.g. during codegen).
71+
/// However, during constant evaluation, we may want
72+
/// to try to resolve a `Instance` using generic parameters
73+
/// (e.g. when we are attempting to to do const-propagation).
74+
/// In this case, `Instance.ty_env` should be used to provide
75+
/// the `ParamEnv` for our generic context.
76+
pub fn monomorphic_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
6677
let ty = tcx.type_of(self.def.def_id());
78+
// There shouldn't be any params - if there are, then
79+
// Instance.ty_env should have been used to provide the proper
80+
// ParamEnv
81+
if self.substs.has_param_types() {
82+
bug!("Instance.ty called for type {:?} with params in substs: {:?}", ty, self.substs);
83+
}
6784
tcx.subst_and_normalize_erasing_regions(self.substs, ty::ParamEnv::reveal_all(), &ty)
6885
}
86+
87+
/// Like `Instance.ty`, but allows a `ParamEnv` to be specified for use during
88+
/// normalization. This method is only really useful during constant evaluation,
89+
/// where we are dealing with potentially generic types.
90+
pub fn ty_env(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> {
91+
let ty = tcx.type_of(self.def.def_id());
92+
tcx.subst_and_normalize_erasing_regions(self.substs, param_env, &ty)
93+
}
6994
}
7095

7196
impl<'tcx> InstanceDef<'tcx> {

src/librustc/ty/layout.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2301,7 +2301,7 @@ impl<'tcx> ty::Instance<'tcx> {
23012301
// or should go through `FnAbi` instead, to avoid losing any
23022302
// adjustments `FnAbi::of_instance` might be performing.
23032303
fn fn_sig_for_fn_abi(&self, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> {
2304-
let ty = self.ty(tcx);
2304+
let ty = self.monomorphic_ty(tcx);
23052305
match ty.kind {
23062306
ty::FnDef(..) |
23072307
// Shims currently have type FnPtr. Not sure this should remain.

src/librustc_codegen_llvm/callee.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ pub fn get_fn(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) -> &'ll Value
3636
}
3737

3838
let sym = tcx.symbol_name(instance).name.as_str();
39-
debug!("get_fn({:?}: {:?}) => {}", instance, instance.ty(cx.tcx()), sym);
39+
debug!("get_fn({:?}: {:?}) => {}", instance, instance.monomorphic_ty(cx.tcx()), sym);
4040

4141
let fn_abi = FnAbi::of_instance(cx, instance, &[]);
4242

src/librustc_codegen_llvm/consts.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ impl CodegenCx<'ll, 'tcx> {
204204
def_id
205205
);
206206

207-
let ty = instance.ty(self.tcx);
207+
let ty = instance.monomorphic_ty(self.tcx);
208208
let sym = self.tcx.symbol_name(instance).name;
209209

210210
debug!("get_static: sym={} instance={:?}", sym, instance);
@@ -361,7 +361,7 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> {
361361
};
362362

363363
let instance = Instance::mono(self.tcx, def_id);
364-
let ty = instance.ty(self.tcx);
364+
let ty = instance.monomorphic_ty(self.tcx);
365365
let llty = self.layout_of(ty).llvm_type(self);
366366
let g = if val_llty == llty {
367367
g

src/librustc_codegen_llvm/debuginfo/metadata.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2287,7 +2287,7 @@ pub fn create_global_var_metadata(cx: &CodegenCx<'ll, '_>, def_id: DefId, global
22872287
};
22882288

22892289
let is_local_to_unit = is_node_local_to_unit(cx, def_id);
2290-
let variable_type = Instance::mono(cx.tcx, def_id).ty(cx.tcx);
2290+
let variable_type = Instance::mono(cx.tcx, def_id).monomorphic_ty(cx.tcx);
22912291
let type_metadata = type_metadata(cx, variable_type, span);
22922292
let var_name = SmallCStr::new(&tcx.item_name(def_id).as_str());
22932293
let linkage_name = if no_mangle {

src/librustc_codegen_llvm/intrinsic.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
8989
span: Span,
9090
) {
9191
let tcx = self.tcx;
92-
let callee_ty = instance.ty(tcx);
92+
let callee_ty = instance.monomorphic_ty(tcx);
9393

9494
let (def_id, substs) = match callee_ty.kind {
9595
ty::FnDef(def_id, substs) => (def_id, substs),

src/librustc_codegen_llvm/mono_item.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> {
2222
symbol_name: &str,
2323
) {
2424
let instance = Instance::mono(self.tcx, def_id);
25-
let ty = instance.ty(self.tcx);
25+
let ty = instance.monomorphic_ty(self.tcx);
2626
let llty = self.layout_of(ty).llvm_type(self);
2727

2828
let g = self.define_global(symbol_name, llty).unwrap_or_else(|| {

src/librustc_mir/const_eval/eval_queries.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ pub fn const_eval_validated_provider<'tcx>(
221221
// We call `const_eval` for zero arg intrinsics, too, in order to cache their value.
222222
// Catch such calls and evaluate them instead of trying to load a constant's MIR.
223223
if let ty::InstanceDef::Intrinsic(def_id) = key.value.instance.def {
224-
let ty = key.value.instance.ty(tcx);
224+
let ty = key.value.instance.ty_env(tcx, key.param_env);
225225
let substs = match ty.kind {
226226
ty::FnDef(_, substs) => substs,
227227
_ => bug!("intrinsic with type {:?}", ty),

src/librustc_mir/interpret/terminator.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
204204
// ABI check
205205
{
206206
let callee_abi = {
207-
let instance_ty = instance.ty(*self.tcx);
207+
let instance_ty = instance.ty_env(*self.tcx, self.param_env);
208208
match instance_ty.kind {
209209
ty::FnDef(..) => instance_ty.fn_sig(*self.tcx).abi(),
210210
ty::Closure(..) => Abi::RustCall,

src/librustc_mir/interpret/traits.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
140140
// to determine the type.
141141
let drop_instance = self.memory.get_fn(drop_fn)?.as_instance()?;
142142
trace!("Found drop fn: {:?}", drop_instance);
143-
let fn_sig = drop_instance.ty(*self.tcx).fn_sig(*self.tcx);
143+
let fn_sig = drop_instance.ty_env(*self.tcx, self.param_env).fn_sig(*self.tcx);
144144
let fn_sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, &fn_sig);
145145
// The drop function takes `*mut T` where `T` is the type being dropped, so get that.
146146
let args = fn_sig.inputs();

src/librustc_mir/monomorphize/collector.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ fn collect_items_rec<'tcx>(
358358
// Sanity check whether this ended up being collected accidentally
359359
debug_assert!(should_monomorphize_locally(tcx, &instance));
360360

361-
let ty = instance.ty(tcx);
361+
let ty = instance.monomorphic_ty(tcx);
362362
visit_drop_use(tcx, ty, true, &mut neighbors);
363363

364364
recursion_depth_reset = None;
@@ -1002,7 +1002,8 @@ impl ItemLikeVisitor<'v> for RootCollector<'_, 'v> {
10021002
def_id_to_string(self.tcx, def_id)
10031003
);
10041004

1005-
let ty = Instance::new(def_id, InternalSubsts::empty()).ty(self.tcx);
1005+
let ty =
1006+
Instance::new(def_id, InternalSubsts::empty()).monomorphic_ty(self.tcx);
10061007
visit_drop_use(self.tcx, ty, true, self.output);
10071008
}
10081009
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// compile-flags: -Z mir-opt-level=3
2+
// build-pass
3+
4+
// This used to ICE in const-prop due
5+
// to an empty ParamEnv being used during normalization
6+
// of a generic type
7+
8+
9+
fn main() {
10+
join_all::<u32>();
11+
}
12+
13+
trait Foo {
14+
type Item;
15+
}
16+
17+
impl Foo for u32 {
18+
type Item = u8;
19+
}
20+
21+
trait Bar {
22+
type Item2;
23+
}
24+
25+
impl Bar for u8 {
26+
type Item2 = u64;
27+
}
28+
29+
fn join_all<I>()
30+
where I: Foo,
31+
I::Item: Bar
32+
{
33+
Vec::<<I::Item as Bar>::Item2>::new(); // ICE occurs processing this line
34+
}

0 commit comments

Comments
 (0)