Skip to content

Commit db2f214

Browse files
committed
normalize fn sig as part of reification
1 parent 73d1ba1 commit db2f214

File tree

2 files changed

+124
-58
lines changed

2 files changed

+124
-58
lines changed

src/librustc_mir/transform/type_check.rs

Lines changed: 86 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use rustc::infer::region_constraints::RegionConstraintData;
1717
use rustc::traits::{self, FulfillmentContext};
1818
use rustc::ty::error::TypeError;
1919
use rustc::ty::fold::TypeFoldable;
20-
use rustc::ty::{self, Ty, TyCtxt, TypeVariants, ToPolyTraitRef};
20+
use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeVariants};
2121
use rustc::middle::const_val::ConstVal;
2222
use rustc::mir::*;
2323
use rustc::mir::tcx::PlaceTy;
@@ -193,13 +193,11 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
193193
assert_eq!(def_id, ty_def_id);
194194
substs
195195
}
196-
_ => {
197-
span_bug!(
198-
self.last_span,
199-
"unexpected type for constant function: {:?}",
200-
value.ty
201-
)
202-
}
196+
_ => span_bug!(
197+
self.last_span,
198+
"unexpected type for constant function: {:?}",
199+
value.ty
200+
),
203201
};
204202

205203
let instantiated_predicates =
@@ -585,12 +583,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
585583
span_mirbug!(self, "", "errors selecting obligation: {:?}", e);
586584
}
587585

588-
self.infcx.process_registered_region_obligations(
589-
&[],
590-
None,
591-
self.param_env,
592-
self.body_id,
593-
);
586+
self.infcx
587+
.process_registered_region_obligations(&[], None, self.param_env, self.body_id);
594588

595589
let data = self.infcx.take_and_reset_region_constraints();
596590
if !data.is_empty() {
@@ -1164,18 +1158,16 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
11641158
self.check_aggregate_rvalue(mir, rvalue, ak, ops, location)
11651159
}
11661160

1167-
Rvalue::Repeat(operand, const_usize) => {
1168-
if const_usize.as_u64() > 1 {
1169-
let operand_ty = operand.ty(mir, tcx);
1161+
Rvalue::Repeat(operand, const_usize) => if const_usize.as_u64() > 1 {
1162+
let operand_ty = operand.ty(mir, tcx);
11701163

1171-
let trait_ref = ty::TraitRef {
1172-
def_id: tcx.lang_items().copy_trait().unwrap(),
1173-
substs: tcx.mk_substs_trait(operand_ty, &[]),
1174-
};
1164+
let trait_ref = ty::TraitRef {
1165+
def_id: tcx.lang_items().copy_trait().unwrap(),
1166+
substs: tcx.mk_substs_trait(operand_ty, &[]),
1167+
};
11751168

1176-
self.prove_trait_ref(trait_ref, location);
1177-
}
1178-
}
1169+
self.prove_trait_ref(trait_ref, location);
1170+
},
11791171

11801172
Rvalue::NullaryOp(_, ty) => {
11811173
let trait_ref = ty::TraitRef {
@@ -1186,50 +1178,87 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
11861178
self.prove_trait_ref(trait_ref, location);
11871179
}
11881180

1189-
Rvalue::Cast(cast_kind, op, ty) => {
1190-
match cast_kind {
1191-
CastKind::ReifyFnPointer => {
1192-
let ty_fn_ptr_from = tcx.mk_fn_ptr(op.ty(mir, tcx).fn_sig(tcx));
1181+
Rvalue::Cast(cast_kind, op, ty) => match cast_kind {
1182+
CastKind::ReifyFnPointer => {
1183+
let fn_sig = op.ty(mir, tcx).fn_sig(tcx);
11931184

1194-
if let Err(terr) = self.eq_types(ty_fn_ptr_from, ty, location.at_self()) {
1195-
span_mirbug!(self, "", "casting {:?}", terr);
1196-
}
1197-
}
1185+
// The type that we see in the fcx is like
1186+
// `foo::<'a, 'b>`, where `foo` is the path to a
1187+
// function definition. When we extract the
1188+
// signature, it comes from the `fn_sig` query,
1189+
// and hence may contain unnormalized results.
1190+
let fn_sig = self.normalize(&fn_sig, location);
11981191

1199-
CastKind::ClosureFnPointer => {
1200-
let sig = match op.ty(mir, tcx).sty {
1201-
ty::TyClosure(def_id, substs) => {
1202-
substs.closure_sig_ty(def_id, tcx).fn_sig(tcx)
1203-
}
1204-
_ => bug!(),
1205-
};
1206-
let ty_fn_ptr_from = tcx.coerce_closure_fn_ty(sig);
1192+
let ty_fn_ptr_from = tcx.mk_fn_ptr(fn_sig);
12071193

1208-
if let Err(terr) = self.eq_types(ty_fn_ptr_from, ty, location.at_self()) {
1209-
span_mirbug!(self, "", "casting {:?}", terr);
1210-
}
1194+
if let Err(terr) = self.eq_types(ty_fn_ptr_from, ty, location.at_self()) {
1195+
span_mirbug!(
1196+
self,
1197+
rvalue,
1198+
"equating {:?} with {:?} yields {:?}",
1199+
ty_fn_ptr_from,
1200+
ty,
1201+
terr
1202+
);
12111203
}
1204+
}
12121205

1213-
CastKind::UnsafeFnPointer => {
1214-
let ty_fn_ptr_from = tcx.safe_to_unsafe_fn_ty(op.ty(mir, tcx).fn_sig(tcx));
1215-
1216-
if let Err(terr) = self.eq_types(ty_fn_ptr_from, ty, location.at_self()) {
1217-
span_mirbug!(self, "", "casting {:?}", terr);
1206+
CastKind::ClosureFnPointer => {
1207+
let sig = match op.ty(mir, tcx).sty {
1208+
ty::TyClosure(def_id, substs) => {
1209+
substs.closure_sig_ty(def_id, tcx).fn_sig(tcx)
12181210
}
1211+
_ => bug!(),
1212+
};
1213+
let ty_fn_ptr_from = tcx.coerce_closure_fn_ty(sig);
1214+
1215+
if let Err(terr) = self.eq_types(ty_fn_ptr_from, ty, location.at_self()) {
1216+
span_mirbug!(
1217+
self,
1218+
rvalue,
1219+
"equating {:?} with {:?} yields {:?}",
1220+
ty_fn_ptr_from,
1221+
ty,
1222+
terr
1223+
);
12191224
}
1225+
}
12201226

1221-
CastKind::Unsize => {
1222-
let trait_ref = ty::TraitRef {
1223-
def_id: tcx.lang_items().coerce_unsized_trait().unwrap(),
1224-
substs: tcx.mk_substs_trait(op.ty(mir, tcx), &[ty]),
1225-
};
1227+
CastKind::UnsafeFnPointer => {
1228+
let fn_sig = op.ty(mir, tcx).fn_sig(tcx);
1229+
1230+
// The type that we see in the fcx is like
1231+
// `foo::<'a, 'b>`, where `foo` is the path to a
1232+
// function definition. When we extract the
1233+
// signature, it comes from the `fn_sig` query,
1234+
// and hence may contain unnormalized results.
1235+
let fn_sig = self.normalize(&fn_sig, location);
12261236

1227-
self.prove_trait_ref(trait_ref, location);
1237+
let ty_fn_ptr_from = tcx.safe_to_unsafe_fn_ty(fn_sig);
1238+
1239+
if let Err(terr) = self.eq_types(ty_fn_ptr_from, ty, location.at_self()) {
1240+
span_mirbug!(
1241+
self,
1242+
rvalue,
1243+
"equating {:?} with {:?} yields {:?}",
1244+
ty_fn_ptr_from,
1245+
ty,
1246+
terr
1247+
);
12281248
}
1249+
}
12291250

1230-
CastKind::Misc => {}
1251+
CastKind::Unsize => {
1252+
let trait_ref = ty::TraitRef {
1253+
def_id: tcx.lang_items().coerce_unsized_trait().unwrap(),
1254+
substs: tcx.mk_substs_trait(op.ty(mir, tcx), &[ty]),
1255+
};
1256+
1257+
self.prove_trait_ref(trait_ref, location);
12311258
}
1232-
}
1259+
1260+
CastKind::Misc => {}
1261+
},
12331262

12341263
// FIXME: These other cases have to be implemented in future PRs
12351264
Rvalue::Use(..) |
@@ -1344,8 +1373,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
13441373
tcx.predicates_of(*def_id).instantiate(tcx, substs.substs)
13451374
}
13461375

1347-
AggregateKind::Array(_) |
1348-
AggregateKind::Tuple => ty::InstantiatedPredicates::empty(),
1376+
AggregateKind::Array(_) | AggregateKind::Tuple => ty::InstantiatedPredicates::empty(),
13491377
};
13501378

13511379
let predicates = self.normalize(&instantiated_predicates.predicates, location);
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// This code was creating an ICE in the MIR type checker. The reason
12+
// is that we are reifying a reference to a function (`foo::<'x>`),
13+
// which involves extracting its signature, but we were not
14+
// normalizing the signature afterwards. As a result, we sometimes got
15+
// errors around the `<u32 as Foo<'x>>::Value`, which can be
16+
// normalized to `f64`.
17+
18+
#![allow(dead_code)]
19+
20+
trait Foo<'x> {
21+
type Value;
22+
}
23+
24+
impl<'x> Foo<'x> for u32 {
25+
type Value = f64;
26+
}
27+
28+
struct Providers<'x> {
29+
foo: for<'y> fn(x: &'x u32, y: &'y u32) -> <u32 as Foo<'x>>::Value,
30+
}
31+
32+
fn foo<'y, 'x: 'x>(x: &'x u32, y: &'y u32) -> <u32 as Foo<'x>>::Value {
33+
*x as f64
34+
}
35+
36+
fn main() {
37+
Providers { foo };
38+
}

0 commit comments

Comments
 (0)