提交 b4d71ea6 编写于 作者: N Niko Matsakis

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.
上级 d5ef3e26
......@@ -10,7 +10,7 @@
use hir::def_id::DefId;
use ty::{self, Ty, TypeFoldable, Substs, TyCtxt};
use ty::subst::{Kind, Subst};
use ty::subst::Kind;
use traits;
use syntax::abi::Abi;
use util::ppaux;
......@@ -311,7 +311,7 @@ fn fn_once_adapter_instance<'a, 'tcx>(
let self_ty = tcx.mk_closure_from_closure_substs(
closure_did, substs);
let sig = tcx.fn_sig(closure_did).subst(tcx, substs.substs);
let sig = substs.closure_sig(closure_did, tcx);
let sig = tcx.erase_late_bound_regions_and_normalize(&sig);
assert_eq!(sig.inputs().len(), 1);
let substs = tcx.mk_substs([
......
......@@ -29,7 +29,7 @@
use rustc::traits;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::layout::{HasDataLayout, LayoutOf};
use rustc::ty::subst::{Kind, Subst, Substs};
use rustc::ty::subst::{Kind, Substs};
use rustc::hir;
use libc::{c_uint, c_char};
......@@ -393,7 +393,7 @@ pub fn ty_fn_sig<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
ty::TyFnPtr(_) => ty.fn_sig(ccx.tcx()),
ty::TyClosure(def_id, substs) => {
let tcx = ccx.tcx();
let sig = tcx.fn_sig(def_id).subst(tcx, substs.substs);
let sig = substs.closure_sig(def_id, tcx);
let env_ty = tcx.closure_env_ty(def_id, substs).unwrap();
sig.map_bound(|sig| tcx.mk_fn_sig(
......
......@@ -20,7 +20,7 @@
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc::ty::layout::{self, LayoutOf, Size};
use rustc::ty::cast::{CastTy, IntTy};
use rustc::ty::subst::{Kind, Substs, Subst};
use rustc::ty::subst::{Kind, Substs};
use rustc_apfloat::{ieee, Float, Status};
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
use base;
......@@ -658,8 +658,7 @@ fn const_rvalue(&self, rvalue: &mir::Rvalue<'tcx>,
.find(|it| it.kind == ty::AssociatedKind::Method)
.unwrap().def_id;
// Now create its substs [Closure, Tuple]
let input = tcx.fn_sig(def_id)
.subst(tcx, substs.substs).input(0);
let input = substs.closure_sig(def_id, tcx).input(0);
let input = tcx.erase_late_bound_regions_and_normalize(&input);
let substs = tcx.mk_substs([operand.ty, input]
.iter().cloned().map(Kind::from));
......
......@@ -12,7 +12,7 @@
use rustc::middle::lang_items::DropInPlaceFnLangItem;
use rustc::traits;
use rustc::ty::adjustment::CustomCoerceUnsized;
use rustc::ty::subst::{Kind, Subst};
use rustc::ty::subst::Kind;
use rustc::ty::{self, Ty, TyCtxt};
pub use rustc::ty::Instance;
......@@ -34,7 +34,7 @@ fn fn_once_adapter_instance<'a, 'tcx>(
let self_ty = tcx.mk_closure_from_closure_substs(
closure_did, substs);
let sig = tcx.fn_sig(closure_did).subst(tcx, substs.substs);
let sig = substs.closure_sig(closure_did, tcx);
let sig = tcx.erase_late_bound_regions_and_normalize(&sig);
assert_eq!(sig.inputs().len(), 1);
let substs = tcx.mk_substs([
......
......@@ -1268,15 +1268,23 @@ fn fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
))
}
NodeExpr(&hir::Expr { node: hir::ExprClosure(..), hir_id, .. }) => {
let tables = tcx.typeck_tables_of(def_id);
match tables.node_id_to_type(hir_id).sty {
ty::TyClosure(closure_def_id, closure_substs) => {
assert_eq!(def_id, closure_def_id);
return closure_substs.closure_sig(closure_def_id, tcx);
}
ref t => bug!("closure with non-closure type: {:?}", t),
}
NodeExpr(&hir::Expr { node: hir::ExprClosure(..), .. }) => {
// In order to property accommodate regions during NLL
// inference, `fn_sig` query only works for top-level
// functions. This is because closures often contain erased regions
// in their signatures that are understood by NLL inference but not other
// parts of the system -- these do not appear in the generics and hence
// are not properly substituted away without some care.
//
// To get the signature of a closure, you should use the
// `closure_sig` method on the `ClosureSubsts`:
//
// closure_substs.closure_sig(def_id, tcx)
//
// or, inside of an inference context, you can use
//
// infcx.closure_sig(def_id, closure_substs)
bug!("to get the signature of a closure, use `closure_sig()` not `fn_sig()`");
}
x => {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册