Skip to content

Commit b4d71ea

Browse files
committed
make fn_sig().subst() ICE when used with a closure
It's inefficient, and the substitution there doesn't account for the extra regions used by NLL inference, so it's a bad thing to encourage. As it happens all callers already know if they have a closure or not, from what I can tell.
1 parent d5ef3e2 commit b4d71ea

File tree

5 files changed

+25
-18
lines changed

5 files changed

+25
-18
lines changed

src/librustc/ty/instance.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use hir::def_id::DefId;
1212
use ty::{self, Ty, TypeFoldable, Substs, TyCtxt};
13-
use ty::subst::{Kind, Subst};
13+
use ty::subst::Kind;
1414
use traits;
1515
use syntax::abi::Abi;
1616
use util::ppaux;
@@ -311,7 +311,7 @@ fn fn_once_adapter_instance<'a, 'tcx>(
311311
let self_ty = tcx.mk_closure_from_closure_substs(
312312
closure_did, substs);
313313

314-
let sig = tcx.fn_sig(closure_did).subst(tcx, substs.substs);
314+
let sig = substs.closure_sig(closure_did, tcx);
315315
let sig = tcx.erase_late_bound_regions_and_normalize(&sig);
316316
assert_eq!(sig.inputs().len(), 1);
317317
let substs = tcx.mk_substs([

src/librustc_trans/common.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use value::Value;
2929
use rustc::traits;
3030
use rustc::ty::{self, Ty, TyCtxt};
3131
use rustc::ty::layout::{HasDataLayout, LayoutOf};
32-
use rustc::ty::subst::{Kind, Subst, Substs};
32+
use rustc::ty::subst::{Kind, Substs};
3333
use rustc::hir;
3434

3535
use libc::{c_uint, c_char};
@@ -393,7 +393,7 @@ pub fn ty_fn_sig<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
393393
ty::TyFnPtr(_) => ty.fn_sig(ccx.tcx()),
394394
ty::TyClosure(def_id, substs) => {
395395
let tcx = ccx.tcx();
396-
let sig = tcx.fn_sig(def_id).subst(tcx, substs.substs);
396+
let sig = substs.closure_sig(def_id, tcx);
397397

398398
let env_ty = tcx.closure_env_ty(def_id, substs).unwrap();
399399
sig.map_bound(|sig| tcx.mk_fn_sig(

src/librustc_trans/mir/constant.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use rustc::mir::tcx::PlaceTy;
2020
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
2121
use rustc::ty::layout::{self, LayoutOf, Size};
2222
use rustc::ty::cast::{CastTy, IntTy};
23-
use rustc::ty::subst::{Kind, Substs, Subst};
23+
use rustc::ty::subst::{Kind, Substs};
2424
use rustc_apfloat::{ieee, Float, Status};
2525
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
2626
use base;
@@ -658,8 +658,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
658658
.find(|it| it.kind == ty::AssociatedKind::Method)
659659
.unwrap().def_id;
660660
// Now create its substs [Closure, Tuple]
661-
let input = tcx.fn_sig(def_id)
662-
.subst(tcx, substs.substs).input(0);
661+
let input = substs.closure_sig(def_id, tcx).input(0);
663662
let input = tcx.erase_late_bound_regions_and_normalize(&input);
664663
let substs = tcx.mk_substs([operand.ty, input]
665664
.iter().cloned().map(Kind::from));

src/librustc_trans_utils/monomorphize.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use rustc::hir::def_id::DefId;
1212
use rustc::middle::lang_items::DropInPlaceFnLangItem;
1313
use rustc::traits;
1414
use rustc::ty::adjustment::CustomCoerceUnsized;
15-
use rustc::ty::subst::{Kind, Subst};
15+
use rustc::ty::subst::Kind;
1616
use rustc::ty::{self, Ty, TyCtxt};
1717

1818
pub use rustc::ty::Instance;
@@ -34,7 +34,7 @@ fn fn_once_adapter_instance<'a, 'tcx>(
3434
let self_ty = tcx.mk_closure_from_closure_substs(
3535
closure_did, substs);
3636

37-
let sig = tcx.fn_sig(closure_did).subst(tcx, substs.substs);
37+
let sig = substs.closure_sig(closure_did, tcx);
3838
let sig = tcx.erase_late_bound_regions_and_normalize(&sig);
3939
assert_eq!(sig.inputs().len(), 1);
4040
let substs = tcx.mk_substs([

src/librustc_typeck/collect.rs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1268,15 +1268,23 @@ fn fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
12681268
))
12691269
}
12701270

1271-
NodeExpr(&hir::Expr { node: hir::ExprClosure(..), hir_id, .. }) => {
1272-
let tables = tcx.typeck_tables_of(def_id);
1273-
match tables.node_id_to_type(hir_id).sty {
1274-
ty::TyClosure(closure_def_id, closure_substs) => {
1275-
assert_eq!(def_id, closure_def_id);
1276-
return closure_substs.closure_sig(closure_def_id, tcx);
1277-
}
1278-
ref t => bug!("closure with non-closure type: {:?}", t),
1279-
}
1271+
NodeExpr(&hir::Expr { node: hir::ExprClosure(..), .. }) => {
1272+
// In order to property accommodate regions during NLL
1273+
// inference, `fn_sig` query only works for top-level
1274+
// functions. This is because closures often contain erased regions
1275+
// in their signatures that are understood by NLL inference but not other
1276+
// parts of the system -- these do not appear in the generics and hence
1277+
// are not properly substituted away without some care.
1278+
//
1279+
// To get the signature of a closure, you should use the
1280+
// `closure_sig` method on the `ClosureSubsts`:
1281+
//
1282+
// closure_substs.closure_sig(def_id, tcx)
1283+
//
1284+
// or, inside of an inference context, you can use
1285+
//
1286+
// infcx.closure_sig(def_id, closure_substs)
1287+
bug!("to get the signature of a closure, use `closure_sig()` not `fn_sig()`");
12801288
}
12811289

12821290
x => {

0 commit comments

Comments
 (0)