diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 4e78d79ef87..4f365a97f4c 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -524,10 +524,9 @@ for ty::TypeVariants<'tcx> region.hash_stable(hcx, hasher); pointee_ty.hash_stable(hcx, hasher); } - TyFnDef(def_id, substs, ref sig) => { + TyFnDef(def_id, substs) => { def_id.hash_stable(hcx, hasher); substs.hash_stable(hcx, hasher); - sig.hash_stable(hcx, hasher); } TyFnPtr(ref sig) => { sig.hash_stable(hcx, hasher); diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index 74e1225f394..eab5a8f9103 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -12,7 +12,7 @@ //! `unsafe`. use self::RootUnsafeContext::*; -use ty::{self, Ty, TyCtxt}; +use ty::{self, TyCtxt}; use lint; use syntax::ast; @@ -40,14 +40,6 @@ enum RootUnsafeContext { UnsafeBlock(ast::NodeId), } -fn type_is_unsafe_function(ty: Ty) -> bool { - match ty.sty { - ty::TyFnDef(.., f) | - ty::TyFnPtr(f) => f.unsafety() == hir::Unsafety::Unsafe, - _ => false, - } -} - struct EffectCheckVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, tables: &'a ty::TypeckTables<'tcx>, @@ -174,10 +166,11 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> { match expr.node { hir::ExprMethodCall(..) => { let def_id = self.tables.type_dependent_defs[&expr.id].def_id(); - let base_type = self.tcx.type_of(def_id); - debug!("effect: method call case, base type is {:?}", - base_type); - if type_is_unsafe_function(base_type) { + let sig = self.tcx.fn_sig(def_id); + debug!("effect: method call case, signature is {:?}", + sig); + + if sig.0.unsafety == hir::Unsafety::Unsafe { self.require_unsafe(expr.span, "invocation of unsafe method") } @@ -186,8 +179,13 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> { let base_type = self.tables.expr_ty_adjusted(base); debug!("effect: call case, base type is {:?}", base_type); - if type_is_unsafe_function(base_type) { - self.require_unsafe(expr.span, "call to unsafe function") + match base_type.sty { + ty::TyFnDef(..) | ty::TyFnPtr(_) => { + if base_type.fn_sig(self.tcx).unsafety() == hir::Unsafety::Unsafe { + self.require_unsafe(expr.span, "call to unsafe function") + } + } + _ => {} } } hir::ExprUnary(hir::UnDeref, ref base) => { diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs index f180ae53b8a..fde207e4b2f 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -66,11 +66,8 @@ fn unpack_option_like<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl<'a, 'tcx> ExprVisitor<'a, 'tcx> { fn def_id_is_transmute(&self, def_id: DefId) -> bool { - let intrinsic = match self.tcx.type_of(def_id).sty { - ty::TyFnDef(.., bfty) => bfty.abi() == RustIntrinsic, - _ => return false - }; - intrinsic && self.tcx.item_name(def_id) == "transmute" + self.tcx.fn_sig(def_id).abi() == RustIntrinsic && + self.tcx.item_name(def_id) == "transmute" } fn check_transmute(&self, span: Span, from: Ty<'tcx>, to: Ty<'tcx>) { @@ -153,22 +150,14 @@ impl<'a, 'tcx> Visitor<'tcx> for ExprVisitor<'a, 'tcx> { } else { Def::Err }; - match def { - Def::Fn(did) if self.def_id_is_transmute(did) => { + if let Def::Fn(did) = def { + if self.def_id_is_transmute(did) { let typ = self.tables.node_id_to_type(expr.id); - let typ = self.tcx.lift_to_global(&typ).unwrap(); - match typ.sty { - ty::TyFnDef(.., sig) if sig.abi() == RustIntrinsic => { - let from = sig.inputs().skip_binder()[0]; - let to = *sig.output().skip_binder(); - self.check_transmute(expr.span, from, to); - } - _ => { - span_bug!(expr.span, "transmute wasn't a bare fn?!"); - } - } + let sig = typ.fn_sig(self.tcx); + let from = sig.inputs().skip_binder()[0]; + let to = *sig.output().skip_binder(); + self.check_transmute(expr.span, from, to); } - _ => {} } intravisit::walk_expr(self, expr); diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 0e3a53129d1..c6c052fa4b1 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -260,7 +260,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // The `Self` type is erased, so it should not appear in list of // arguments or return type apart from the receiver. - let ref sig = self.type_of(method.def_id).fn_sig(); + let ref sig = self.fn_sig(method.def_id); for input_ty in &sig.skip_binder().inputs()[1..] { if self.contains_illegal_self_type_reference(trait_def_id, input_ty) { return Some(MethodViolationCode::ReferencesSelf); diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index f71f75dbaa8..c356e53234d 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -1137,9 +1137,19 @@ fn confirm_fn_pointer_candidate<'cx, 'gcx, 'tcx>( -> Progress<'tcx> { let fn_type = selcx.infcx().shallow_resolve(fn_pointer_vtable.fn_ty); - let sig = fn_type.fn_sig(); + let sig = fn_type.fn_sig(selcx.tcx()); + let Normalized { + value: sig, + obligations + } = normalize_with_depth(selcx, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth+1, + &sig); + confirm_callable_candidate(selcx, obligation, sig, util::TupleArgumentsFlag::Yes) .with_addl_obligations(fn_pointer_vtable.nested) + .with_addl_obligations(obligations) } fn confirm_closure_candidate<'cx, 'gcx, 'tcx>( diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index c68b8ee14b8..a66b6b86354 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1404,19 +1404,15 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } // provide an impl, but only for suitable `fn` pointers - ty::TyFnDef(.., ty::Binder(ty::FnSig { - unsafety: hir::Unsafety::Normal, - abi: Abi::Rust, - variadic: false, - .. - })) | - ty::TyFnPtr(ty::Binder(ty::FnSig { - unsafety: hir::Unsafety::Normal, - abi: Abi::Rust, - variadic: false, - .. - })) => { - candidates.vec.push(FnPointerCandidate); + ty::TyFnDef(..) | ty::TyFnPtr(_) => { + if let ty::Binder(ty::FnSig { + unsafety: hir::Unsafety::Normal, + abi: Abi::Rust, + variadic: false, + .. + }) = self_ty.fn_sig(self.tcx()) { + candidates.vec.push(FnPointerCandidate); + } } _ => { } @@ -2348,7 +2344,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // ok to skip binder; it is reintroduced below let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder()); - let sig = self_ty.fn_sig(); + let sig = self_ty.fn_sig(self.tcx()); let trait_ref = self.tcx().closure_trait_ref_and_return_type(obligation.predicate.def_id(), self_ty, @@ -2356,11 +2352,18 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { util::TupleArgumentsFlag::Yes) .map_bound(|(trait_ref, _)| trait_ref); + let Normalized { value: trait_ref, obligations } = + project::normalize_with_depth(self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + &trait_ref); + self.confirm_poly_trait_refs(obligation.cause.clone(), obligation.param_env, obligation.predicate.to_poly_trait_ref(), trait_ref)?; - Ok(VtableFnPointerData { fn_ty: self_ty, nested: vec![] }) + Ok(VtableFnPointerData { fn_ty: self_ty, nested: obligations }) } fn confirm_closure_candidate(&mut self, diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 2d81606329e..5f869fc5567 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1378,9 +1378,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn mk_fn_def(self, def_id: DefId, - substs: &'tcx Substs<'tcx>, - fty: PolyFnSig<'tcx>) -> Ty<'tcx> { - self.mk_ty(TyFnDef(def_id, substs, fty)) + substs: &'tcx Substs<'tcx>) -> Ty<'tcx> { + self.mk_ty(TyFnDef(def_id, substs)) } pub fn mk_fn_ptr(self, fty: PolyFnSig<'tcx>) -> Ty<'tcx> { diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs index 3d2cc4c598a..68f85ba7d33 100644 --- a/src/librustc/ty/fast_reject.rs +++ b/src/librustc/ty/fast_reject.rs @@ -68,6 +68,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, // view of possibly unifying simplify_type(tcx, mt.ty, can_simplify_params) } + ty::TyFnDef(def_id, _) | ty::TyClosure(def_id, _) => { Some(ClosureSimplifiedType(def_id)) } @@ -75,7 +76,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, ty::TyTuple(ref tys, _) => { Some(TupleSimplifiedType(tys.len())) } - ty::TyFnDef(.., ref f) | ty::TyFnPtr(ref f) => { + ty::TyFnPtr(ref f) => { Some(FunctionSimplifiedType(f.skip_binder().inputs().len())) } ty::TyProjection(_) | ty::TyParam(_) => { diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 46afa6ee7d0..d5aa9f55ff0 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -155,9 +155,8 @@ impl FlagComputation { self.add_tys(&ts[..]); } - &ty::TyFnDef(_, substs, f) => { + &ty::TyFnDef(_, substs) => { self.add_substs(substs); - self.add_fn_sig(f); } &ty::TyFnPtr(f) => { diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 09a3bcd0613..b9896e0cecf 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -348,7 +348,7 @@ pub fn characteristic_def_id_of_type(ty: Ty) -> Option { .filter_map(|ty| characteristic_def_id_of_type(ty)) .next(), - ty::TyFnDef(def_id, ..) | + ty::TyFnDef(def_id, _) | ty::TyClosure(def_id, _) => Some(def_id), ty::TyBool | diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 13e46a265c6..f4d0867d130 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -206,7 +206,7 @@ impl AssociatedItem { // late-bound regions, and we don't want method signatures to show up // `as for<'r> fn(&'r MyType)`. Pretty-printing handles late-bound // regions just fine, showing `fn(&MyType)`. - format!("{}", tcx.type_of(self.def_id).fn_sig().skip_binder()) + format!("{}", tcx.fn_sig(self.def_id).skip_binder()) } ty::AssociatedKind::Type => format!("type {};", self.name.to_string()), ty::AssociatedKind::Const => { diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index d4f06a902ee..9345e504701 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -440,13 +440,11 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, } } - (&ty::TyFnDef(a_def_id, a_substs, a_fty), - &ty::TyFnDef(b_def_id, b_substs, b_fty)) + (&ty::TyFnDef(a_def_id, a_substs), &ty::TyFnDef(b_def_id, b_substs)) if a_def_id == b_def_id => { let substs = relate_substs(relation, None, a_substs, b_substs)?; - let fty = relation.relate(&a_fty, &b_fty)?; - Ok(tcx.mk_fn_def(a_def_id, substs, fty)) + Ok(tcx.mk_fn_def(a_def_id, substs)) } (&ty::TyFnPtr(a_fty), &ty::TyFnPtr(b_fty)) => diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 1e268924390..d05262965d7 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -531,10 +531,8 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { ty::TyDynamic(ref trait_ty, ref region) => ty::TyDynamic(trait_ty.fold_with(folder), region.fold_with(folder)), ty::TyTuple(ts, defaulted) => ty::TyTuple(ts.fold_with(folder), defaulted), - ty::TyFnDef(def_id, substs, f) => { - ty::TyFnDef(def_id, - substs.fold_with(folder), - f.fold_with(folder)) + ty::TyFnDef(def_id, substs) => { + ty::TyFnDef(def_id, substs.fold_with(folder)) } ty::TyFnPtr(f) => ty::TyFnPtr(f.fold_with(folder)), ty::TyRef(ref r, tm) => { @@ -568,9 +566,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { ty::TyDynamic(ref trait_ty, ref reg) => trait_ty.visit_with(visitor) || reg.visit_with(visitor), ty::TyTuple(ts, _) => ts.visit_with(visitor), - ty::TyFnDef(_, substs, ref f) => { - substs.visit_with(visitor) || f.visit_with(visitor) - } + ty::TyFnDef(_, substs) => substs.visit_with(visitor), ty::TyFnPtr(ref f) => f.visit_with(visitor), ty::TyRef(r, ref tm) => r.visit_with(visitor) || tm.visit_with(visitor), ty::TyClosure(_did, ref substs) => substs.visit_with(visitor), diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 6923a6d21d6..ed3312d88a3 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -14,7 +14,7 @@ use hir::def_id::DefId; use hir::map::DefPathHash; use middle::region; -use ty::subst::Substs; +use ty::subst::{Substs, Subst}; use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable}; use ty::{Slice, TyS}; use ty::subst::Kind; @@ -138,7 +138,7 @@ pub enum TypeVariants<'tcx> { /// The anonymous type of a function declaration/definition. Each /// function has a unique type. - TyFnDef(DefId, &'tcx Substs<'tcx>, PolyFnSig<'tcx>), + TyFnDef(DefId, &'tcx Substs<'tcx>), /// A pointer to a function. Written as `fn() -> i32`. TyFnPtr(PolyFnSig<'tcx>), @@ -1329,9 +1329,12 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } } - pub fn fn_sig(&self) -> PolyFnSig<'tcx> { + pub fn fn_sig(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> PolyFnSig<'tcx> { match self.sty { - TyFnDef(.., f) | TyFnPtr(f) => f, + TyFnDef(def_id, substs) => { + tcx.fn_sig(def_id).subst(tcx, substs) + } + TyFnPtr(f) => f, _ => bug!("Ty::fn_sig() called on non-fn type: {:?}", self) } } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 1bbc7673485..98ef7918fef 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -679,7 +679,7 @@ impl<'a, 'gcx, 'tcx, W> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tcx, W> TyRef(_, m) => self.hash(m.mutbl), TyClosure(def_id, _) | TyAnon(def_id, _) | - TyFnDef(def_id, ..) => self.def_id(def_id), + TyFnDef(def_id, _) => self.def_id(def_id), TyAdt(d, _) => self.def_id(d.did), TyFnPtr(f) => { self.hash(f.unsafety()); diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs index d7954953aba..71844abfe53 100644 --- a/src/librustc/ty/walk.rs +++ b/src/librustc/ty/walk.rs @@ -115,9 +115,8 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) { ty::TyTuple(ts, _) => { stack.extend(ts.iter().cloned().rev()); } - ty::TyFnDef(_, substs, ft) => { + ty::TyFnDef(_, substs) => { stack.extend(substs.types().rev()); - push_sig_subtypes(stack, ft); } ty::TyFnPtr(ft) => { push_sig_subtypes(stack, ft); diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 1fa63577196..eb6bffc29c5 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -753,8 +753,14 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> { } write!(f, ")") } - TyFnDef(def_id, substs, ref bare_fn) => { - write!(f, "{} {{", bare_fn.0)?; + TyFnDef(def_id, substs) => { + ty::tls::with(|tcx| { + let mut sig = tcx.fn_sig(def_id); + if let Some(substs) = tcx.lift(&substs) { + sig = sig.subst(tcx, substs); + } + write!(f, "{} {{", sig.0) + })?; parameterized(f, substs, def_id, &[])?; write!(f, "}}") } diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs b/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs index 2c55460fb30..4bef191b113 100644 --- a/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs +++ b/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs @@ -161,18 +161,13 @@ fn is_rustc_peek<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, terminator: &'a Option>) -> Option<(&'a [mir::Operand<'tcx>], Span)> { if let Some(mir::Terminator { ref kind, source_info, .. }) = *terminator { - if let mir::TerminatorKind::Call { func: ref oper, ref args, .. } = *kind - { - if let mir::Operand::Constant(ref func) = *oper - { - if let ty::TyFnDef(def_id, _, sig) = func.ty.sty - { - let abi = sig.abi(); + if let mir::TerminatorKind::Call { func: ref oper, ref args, .. } = *kind { + if let mir::Operand::Constant(ref func) = *oper { + if let ty::TyFnDef(def_id, _) = func.ty.sty { + let abi = tcx.fn_sig(def_id).abi(); let name = tcx.item_name(def_id); - if abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic { - if name == "rustc_peek" { - return Some((args, source_info.span)); - } + if abi == Abi::RustIntrinsic && name == "rustc_peek" { + return Some((args, source_info.span)); } } } diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs index d175920e8a6..0a966b0c170 100644 --- a/src/librustc_const_eval/pattern.rs +++ b/src/librustc_const_eval/pattern.rs @@ -12,7 +12,7 @@ use eval; use rustc::middle::const_val::{ConstEvalErr, ConstVal}; use rustc::mir::{Field, BorrowKind, Mutability}; -use rustc::ty::{self, TyCtxt, AdtDef, Ty, TypeVariants, Region}; +use rustc::ty::{self, TyCtxt, AdtDef, Ty, Region}; use rustc::ty::subst::{Substs, Kind}; use rustc::hir::{self, PatKind, RangeEnd}; use rustc::hir::def::{Def, CtorKind}; @@ -549,8 +549,8 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { let adt_def = self.tcx.adt_def(enum_id); if adt_def.variants.len() > 1 { let substs = match ty.sty { - TypeVariants::TyAdt(_, substs) => substs, - TypeVariants::TyFnDef(_, substs, _) => substs, + ty::TyAdt(_, substs) | + ty::TyFnDef(_, substs) => substs, _ => bug!("inappropriate type for def: {:?}", ty.sty), }; PatternKind::Variant { diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 9800012917c..ad154f9b815 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1154,24 +1154,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes { if !def_id_is_transmute(cx, did) { return None; } - let typ = cx.tables.node_id_to_type(expr.id); - match typ.sty { - ty::TyFnDef(.., bare_fn) if bare_fn.abi() == RustIntrinsic => { - let from = bare_fn.inputs().skip_binder()[0]; - let to = *bare_fn.output().skip_binder(); - return Some((&from.sty, &to.sty)); - } - _ => (), - } + let sig = cx.tables.node_id_to_type(expr.id).fn_sig(cx.tcx); + let from = sig.inputs().skip_binder()[0]; + let to = *sig.output().skip_binder(); + return Some((&from.sty, &to.sty)); } None } fn def_id_is_transmute(cx: &LateContext, def_id: DefId) -> bool { - match cx.tcx.type_of(def_id).sty { - ty::TyFnDef(.., bfty) if bfty.abi() == RustIntrinsic => (), - _ => return false, - } + cx.tcx.fn_sig(def_id).abi() == RustIntrinsic && cx.tcx.item_name(def_id) == "transmute" } } diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 32bde42b526..ac3977bd216 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -659,7 +659,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { fn check_foreign_fn(&mut self, id: ast::NodeId, decl: &hir::FnDecl) { let def_id = self.cx.tcx.hir.local_def_id(id); - let sig = self.cx.tcx.type_of(def_id).fn_sig(); + let sig = self.cx.tcx.fn_sig(def_id); let sig = self.cx.tcx.erase_late_bound_regions(&sig); for (input_ty, input_hir) in sig.inputs().iter().zip(&decl.inputs) { diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 77f01d5c28c..3e6d06ec86f 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -1085,13 +1085,19 @@ impl<'a, 'tcx> CrateMetadata { } pub fn fn_sig(&self, - closure_id: DefIndex, + id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::PolyFnSig<'tcx> { - match self.entry(closure_id).kind { - EntryKind::Closure(data) => data.decode(self).sig.decode((self, tcx)), + let sig = match self.entry(id).kind { + EntryKind::Fn(data) | + EntryKind::ForeignFn(data) => data.decode(self).sig, + EntryKind::Method(data) => data.decode(self).fn_data.sig, + EntryKind::Variant(data) | + EntryKind::Struct(data, _) => data.decode(self).ctor_sig.unwrap(), + EntryKind::Closure(data) => data.decode(self).sig, _ => bug!(), - } + }; + sig.decode((self, tcx)) } #[inline] diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 860b553959f..34b25a4b7e4 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -16,6 +16,7 @@ use schema::*; use rustc::middle::cstore::{LinkMeta, LinkagePreference, NativeLibrary, EncodedMetadata, EncodedMetadataHashes, EncodedMetadataHash}; +use rustc::hir::def::CtorKind; use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId, LOCAL_CRATE}; use rustc::hir::map::definitions::{DefPathTable, GlobalMetaDataKind}; use rustc::ich::Fingerprint; @@ -499,6 +500,11 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { ctor_kind: variant.ctor_kind, discr: variant.discr, struct_ctor: None, + ctor_sig: if variant.ctor_kind == CtorKind::Fn { + Some(self.lazy(&tcx.fn_sig(def_id))) + } else { + None + } }; let enum_id = tcx.hir.as_local_node_id(enum_did).unwrap(); @@ -617,6 +623,11 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { ctor_kind: variant.ctor_kind, discr: variant.discr, struct_ctor: Some(def_id.index), + ctor_sig: if variant.ctor_kind == CtorKind::Fn { + Some(self.lazy(&tcx.fn_sig(def_id))) + } else { + None + } }; let struct_id = tcx.hir.as_local_node_id(adt_def_id).unwrap(); @@ -695,7 +706,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { }; FnData { constness: hir::Constness::NotConst, - arg_names: arg_names + arg_names: arg_names, + sig: self.lazy(&tcx.fn_sig(def_id)), } } else { bug!() @@ -747,6 +759,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> { debug!("IsolatedEncoder::encode_info_for_impl_item({:?})", def_id); + let tcx = self.tcx; + let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap(); let ast_item = self.tcx.hir.expect_impl_item(node_id); let impl_item = self.tcx.associated_item(def_id); @@ -768,6 +782,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { FnData { constness: sig.constness, arg_names: self.encode_fn_arg_names_for_body(body), + sig: self.lazy(&tcx.fn_sig(def_id)), } } else { bug!() @@ -881,6 +896,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { let data = FnData { constness: constness, arg_names: self.encode_fn_arg_names_for_body(body), + sig: self.lazy(&tcx.fn_sig(def_id)), }; EntryKind::Fn(self.lazy(&data)) @@ -910,6 +926,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { ctor_kind: variant.ctor_kind, discr: variant.discr, struct_ctor: struct_ctor, + ctor_sig: None, }), repr_options) } hir::ItemUnion(..) => { @@ -920,6 +937,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { ctor_kind: variant.ctor_kind, discr: variant.discr, struct_ctor: None, + ctor_sig: None, }), repr_options) } hir::ItemDefaultImpl(..) => { @@ -1363,6 +1381,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { let data = FnData { constness: hir::Constness::NotConst, arg_names: self.encode_fn_arg_names(names), + sig: self.lazy(&tcx.fn_sig(def_id)), }; EntryKind::ForeignFn(self.lazy(&data)) } diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 36977cb5db2..9ef5b940830 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -343,18 +343,18 @@ pub enum EntryKind<'tcx> { Type, Enum(ReprOptions), Field, - Variant(Lazy), - Struct(Lazy, ReprOptions), - Union(Lazy, ReprOptions), - Fn(Lazy), - ForeignFn(Lazy), + Variant(Lazy>), + Struct(Lazy>, ReprOptions), + Union(Lazy>, ReprOptions), + Fn(Lazy>), + ForeignFn(Lazy>), Mod(Lazy), MacroDef(Lazy), Closure(Lazy>), Trait(Lazy>), Impl(Lazy>), DefaultImpl(Lazy>), - Method(Lazy), + Method(Lazy>), AssociatedType(AssociatedContainer), AssociatedConst(AssociatedContainer, u8), } @@ -439,27 +439,33 @@ pub struct MacroDef { impl_stable_hash_for!(struct MacroDef { body, legacy }); #[derive(RustcEncodable, RustcDecodable)] -pub struct FnData { +pub struct FnData<'tcx> { pub constness: hir::Constness, pub arg_names: LazySeq, + pub sig: Lazy>, } -impl_stable_hash_for!(struct FnData { constness, arg_names }); +impl_stable_hash_for!(struct FnData<'tcx> { constness, arg_names, sig }); #[derive(RustcEncodable, RustcDecodable)] -pub struct VariantData { +pub struct VariantData<'tcx> { pub ctor_kind: CtorKind, pub discr: ty::VariantDiscr, /// If this is a struct's only variant, this /// is the index of the "struct ctor" item. pub struct_ctor: Option, + + /// If this is a tuple struct or variant + /// ctor, this is its "function" signature. + pub ctor_sig: Option>>, } -impl_stable_hash_for!(struct VariantData { +impl_stable_hash_for!(struct VariantData<'tcx> { ctor_kind, discr, - struct_ctor + struct_ctor, + ctor_sig }); #[derive(RustcEncodable, RustcDecodable)] @@ -543,12 +549,12 @@ impl AssociatedContainer { } #[derive(RustcEncodable, RustcDecodable)] -pub struct MethodData { - pub fn_data: FnData, +pub struct MethodData<'tcx> { + pub fn_data: FnData<'tcx>, pub container: AssociatedContainer, pub has_self: bool, } -impl_stable_hash_for!(struct MethodData { fn_data, container, has_self }); +impl_stable_hash_for!(struct MethodData<'tcx> { fn_data, container, has_self }); #[derive(RustcEncodable, RustcDecodable)] pub struct ClosureData<'tcx> { diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index b7abc707a38..326c1df69eb 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -205,11 +205,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // FIXME(canndrew): This is_never should probably be an is_uninhabited let diverges = expr.ty.is_never(); let intrinsic = match ty.sty { - ty::TyFnDef(def_id, _, ref f) if - f.abi() == Abi::RustIntrinsic || - f.abi() == Abi::PlatformIntrinsic => - { - Some(this.hir.tcx().item_name(def_id).as_str()) + ty::TyFnDef(def_id, _) => { + let f = ty.fn_sig(this.hir.tcx()); + if f.abi() == Abi::RustIntrinsic || + f.abi() == Abi::PlatformIntrinsic { + Some(this.hir.tcx().item_name(def_id).as_str()) + } else { + None + } } _ => None }; diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 474feefabbb..0010f312ef9 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -19,7 +19,6 @@ use rustc::middle::const_val::ConstVal; use rustc::ty::{self, AdtKind, VariantDef, Ty}; use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow}; use rustc::ty::cast::CastKind as TyCastKind; -use rustc::ty::subst::Subst; use rustc::hir; impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { @@ -586,7 +585,7 @@ fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, }); Expr { temp_lifetime: temp_lifetime, - ty: cx.tcx.type_of(def_id).subst(cx.tcx, substs), + ty: cx.tcx().mk_fn_def(def_id, substs), span: expr.span, kind: ExprKind::Literal { literal: Literal::Value { diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 54779cbe301..11ad5d1509d 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -58,7 +58,7 @@ fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, // types in the MIR. They will be substituted again with // the param-substs, but because they are concrete, this // will not do any harm. - let sig = tcx.erase_late_bound_regions(&ty.fn_sig()); + let sig = tcx.erase_late_bound_regions(&ty.fn_sig(tcx)); let arg_tys = sig.inputs(); build_call_shim( @@ -153,8 +153,8 @@ fn build_drop_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, } else { Substs::identity_for_item(tcx, def_id) }; - let fn_ty = tcx.type_of(def_id).subst(tcx, substs); - let sig = tcx.erase_late_bound_regions(&fn_ty.fn_sig()); + let sig = tcx.fn_sig(def_id).subst(tcx, substs); + let sig = tcx.erase_late_bound_regions(&sig); let span = tcx.def_span(def_id); let source_info = SourceInfo { span, scope: ARGUMENT_VISIBILITY_SCOPE }; @@ -276,8 +276,8 @@ fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, call_kind={:?}, untuple_args={:?})", def_id, rcvr_adjustment, call_kind, untuple_args); - let fn_ty = tcx.type_of(def_id); - let sig = tcx.erase_late_bound_regions(&fn_ty.fn_sig()); + let sig = tcx.fn_sig(def_id); + let sig = tcx.erase_late_bound_regions(&sig); let span = tcx.def_span(def_id); debug!("build_call_shim: sig={:?}", sig); @@ -409,11 +409,8 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>, { let tcx = infcx.tcx; let def_id = tcx.hir.local_def_id(ctor_id); - let sig = match tcx.type_of(def_id).sty { - ty::TyFnDef(_, _, fty) => tcx.no_late_bound_regions(&fty) - .expect("LBR in ADT constructor signature"), - _ => bug!("unexpected type for ctor {:?}", def_id) - }; + let sig = tcx.no_late_bound_regions(&tcx.fn_sig(def_id)) + .expect("LBR in ADT constructor signature"); let sig = tcx.erase_regions(&sig); let (adt_def, substs) = match sig.output().sty { diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 0ac35a5fdd4..5f80c7bee14 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -87,7 +87,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { let terminator = bb_data.terminator(); if let TerminatorKind::Call { func: Operand::Constant(ref f), .. } = terminator.kind { - if let ty::TyFnDef(callee_def_id, substs, _) = f.ty.sty { + if let ty::TyFnDef(callee_def_id, substs) = f.ty.sty { callsites.push_back(CallSite { callee: callee_def_id, substs: substs, @@ -131,7 +131,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { let terminator = bb_data.terminator(); if let TerminatorKind::Call { func: Operand::Constant(ref f), .. } = terminator.kind { - if let ty::TyFnDef(callee_def_id, substs, _) = f.ty.sty { + if let ty::TyFnDef(callee_def_id, substs) = f.ty.sty { // Don't inline the same function multiple times. if callsite.callee != callee_def_id { callsites.push_back(CallSite { @@ -270,8 +270,9 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { } TerminatorKind::Call {func: Operand::Constant(ref f), .. } => { - if let ty::TyFnDef(.., f) = f.ty.sty { + if let ty::TyFnDef(def_id, _) = f.ty.sty { // Don't give intrinsics the extra penalty for calls + let f = tcx.fn_sig(def_id); if f.abi() == Abi::RustIntrinsic || f.abi() == Abi::PlatformIntrinsic { cost += INSTR_COST; } else { diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 05a6cdd57ff..91d6ce60b39 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -750,8 +750,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { let fn_ty = func.ty(self.mir, self.tcx); let (is_shuffle, is_const_fn) = match fn_ty.sty { - ty::TyFnDef(def_id, _, f) => { - (f.abi() == Abi::PlatformIntrinsic && + ty::TyFnDef(def_id, _) => { + (self.tcx.fn_sig(def_id).abi() == Abi::PlatformIntrinsic && self.tcx.item_name(def_id).as_str().starts_with("simd_shuffle"), self.tcx.is_const_fn(def_id)) } diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index efde39ad6a4..7e6fccf3019 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -462,7 +462,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { let func_ty = func.ty(mir, tcx); debug!("check_terminator: call, func_ty={:?}", func_ty); let sig = match func_ty.sty { - ty::TyFnDef(.., sig) | ty::TyFnPtr(sig) => sig, + ty::TyFnDef(..) | ty::TyFnPtr(_) => func_ty.fn_sig(tcx), _ => { span_mirbug!(self, term, "call to non-function {:?}", func_ty); return; diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index fb7258d4266..9eb96fea527 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -400,7 +400,13 @@ impl<'b, 'a, 'tcx> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> { } fn ty(&mut self) -> &mut Self { - self.ev.tcx.type_of(self.item_def_id).visit_with(self); + let ty = self.ev.tcx.type_of(self.item_def_id); + ty.visit_with(self); + if let ty::TyFnDef(def_id, _) = ty.sty { + if def_id == self.item_def_id { + self.ev.tcx.fn_sig(def_id).visit_with(self); + } + } self } @@ -910,7 +916,13 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> { } fn ty(&mut self) -> &mut Self { - self.tcx.type_of(self.item_def_id).visit_with(self); + let ty = self.tcx.type_of(self.item_def_id); + ty.visit_with(self); + if let ty::TyFnDef(def_id, _) = ty.sty { + if def_id == self.item_def_id { + self.tcx.fn_sig(def_id).visit_with(self); + } + } self } diff --git a/src/librustc_trans/back/symbol_names.rs b/src/librustc_trans/back/symbol_names.rs index 8e14335ceac..10b66fb1991 100644 --- a/src/librustc_trans/back/symbol_names.rs +++ b/src/librustc_trans/back/symbol_names.rs @@ -154,6 +154,13 @@ fn get_symbol_hash<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, assert!(!item_type.has_erasable_regions()); hasher.visit_ty(item_type); + // If this is a function, we hash the signature as well. + // This is not *strictly* needed, but it may help in some + // situations, see the `run-make/a-b-a-linker-guard` test. + if let ty::TyFnDef(..) = item_type.sty { + item_type.fn_sig(tcx).visit_with(&mut hasher); + } + // also include any type parameters (for generic items) if let Some(substs) = substs { assert!(!substs.has_erasable_regions()); diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index d723cf32571..3c502eec549 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -587,7 +587,7 @@ fn visit_fn_use<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, is_direct_call: bool, output: &mut Vec>) { - if let ty::TyFnDef(def_id, substs, _) = ty.sty { + if let ty::TyFnDef(def_id, substs) = ty.sty { let instance = monomorphize::resolve(scx, def_id, substs); visit_instance_use(scx, instance, is_direct_call, output); } diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index 0db74c9454a..9b0803908b1 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -495,9 +495,9 @@ pub fn ty_fn_sig<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, -> ty::PolyFnSig<'tcx> { match ty.sty { - ty::TyFnDef(_, _, sig) => sig, + ty::TyFnDef(..) | // Shims currently have type TyFnPtr. Not sure this should remain. - ty::TyFnPtr(sig) => sig, + 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); diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index 95ceec610ea..0cc19936011 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -488,7 +488,6 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, debug!("type_metadata: {:?}", t); - let sty = &t.sty; let ptr_metadata = |ty: Ty<'tcx>| { match ty.sty { ty::TySlice(typ) => { @@ -518,7 +517,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } }; - let MetadataCreationResult { metadata, already_stored_in_typemap } = match *sty { + let MetadataCreationResult { metadata, already_stored_in_typemap } = match t.sty { ty::TyNever | ty::TyBool | ty::TyChar | @@ -557,10 +556,10 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, Err(metadata) => return metadata, } } - ty::TyFnDef(.., sig) | ty::TyFnPtr(sig) => { + ty::TyFnDef(..) | ty::TyFnPtr(_) => { let fn_metadata = subroutine_type_metadata(cx, unique_type_id, - sig, + t.fn_sig(cx.tcx()), usage_site_span).metadata; match debug_context(cx).type_map .borrow() @@ -610,7 +609,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, usage_site_span).finalize(cx) } _ => { - bug!("debuginfo: unexpected type in type_metadata: {:?}", sty) + bug!("debuginfo: unexpected type in type_metadata: {:?}", t) } }; diff --git a/src/librustc_trans/debuginfo/type_names.rs b/src/librustc_trans/debuginfo/type_names.rs index 13ff6646e66..bfca4fec706 100644 --- a/src/librustc_trans/debuginfo/type_names.rs +++ b/src/librustc_trans/debuginfo/type_names.rs @@ -96,8 +96,8 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, push_type_params(cx, principal.substs, output); } }, - ty::TyFnDef(.., sig) | - ty::TyFnPtr(sig) => { + ty::TyFnDef(..) | ty::TyFnPtr(_) => { + let sig = t.fn_sig(cx.tcx()); if sig.unsafety() == hir::Unsafety::Unsafe { output.push_str("unsafe "); } diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs index de908bb24a7..9956c28e641 100644 --- a/src/librustc_trans/intrinsic.rs +++ b/src/librustc_trans/intrinsic.rs @@ -95,11 +95,12 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, let ccx = bcx.ccx; let tcx = ccx.tcx(); - let (def_id, substs, sig) = match callee_ty.sty { - ty::TyFnDef(def_id, substs, sig) => (def_id, substs, sig), + let (def_id, substs) = match callee_ty.sty { + ty::TyFnDef(def_id, substs) => (def_id, substs), _ => bug!("expected fn item type, found {}", callee_ty) }; + let sig = callee_ty.fn_sig(tcx); let sig = tcx.erase_late_bound_regions_and_normalize(&sig); let arg_tys = sig.inputs(); let ret_ty = sig.output(); @@ -986,7 +987,7 @@ fn generic_simd_intrinsic<'a, 'tcx>( let tcx = bcx.tcx(); - let sig = tcx.erase_late_bound_regions_and_normalize(&callee_ty.fn_sig()); + let sig = tcx.erase_late_bound_regions_and_normalize(&callee_ty.fn_sig(tcx)); let arg_tys = sig.inputs(); // every intrinsic takes a SIMD vector as its first argument diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index 8863c7ffae6..16972a1b1ae 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -404,20 +404,18 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { // Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar. let callee = self.trans_operand(&bcx, func); - let (instance, mut llfn, sig) = match callee.ty.sty { - ty::TyFnDef(def_id, substs, sig) => { + let (instance, mut llfn) = match callee.ty.sty { + ty::TyFnDef(def_id, substs) => { (Some(monomorphize::resolve(bcx.ccx.shared(), def_id, substs)), - None, - sig) + None) } - ty::TyFnPtr(sig) => { - (None, - Some(callee.immediate()), - sig) + ty::TyFnPtr(_) => { + (None, Some(callee.immediate())) } _ => bug!("{} is not callable", callee.ty) }; let def = instance.map(|i| i.def); + let sig = callee.ty.fn_sig(bcx.tcx()); let sig = bcx.tcx().erase_late_bound_regions_and_normalize(&sig); let abi = sig.abi; diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 60886b2b35f..fcb4b25e6fe 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -334,7 +334,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { let fn_ty = func.ty(self.mir, tcx); let fn_ty = self.monomorphize(&fn_ty); let (def_id, substs) = match fn_ty.sty { - ty::TyFnDef(def_id, substs, _) => (def_id, substs), + ty::TyFnDef(def_id, substs) => (def_id, substs), _ => span_bug!(span, "calling {:?} (of type {}) in constant", func, fn_ty) }; @@ -560,7 +560,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { let val = match *kind { mir::CastKind::ReifyFnPointer => { match operand.ty.sty { - ty::TyFnDef(def_id, substs, _) => { + ty::TyFnDef(def_id, substs) => { callee::resolve_and_get_fn(self.ccx, def_id, substs) } _ => { diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index 61e537c9cc0..4bd5091a4f3 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -180,7 +180,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { let val = match *kind { mir::CastKind::ReifyFnPointer => { match operand.ty.sty { - ty::TyFnDef(def_id, substs, _) => { + ty::TyFnDef(def_id, substs) => { OperandValue::Immediate( callee::resolve_and_get_fn(bcx.ccx, def_id, substs)) } diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans/monomorphize.rs index a5fe70a2fd7..1f6a262162d 100644 --- a/src/librustc_trans/monomorphize.rs +++ b/src/librustc_trans/monomorphize.rs @@ -165,9 +165,11 @@ pub fn resolve<'a, 'tcx>( } else { let item_type = def_ty(scx, def_id, substs); let def = match item_type.sty { - ty::TyFnDef(_, _, f) if - f.abi() == Abi::RustIntrinsic || - f.abi() == Abi::PlatformIntrinsic => + ty::TyFnDef(..) if { + let f = item_type.fn_sig(scx.tcx()); + f.abi() == Abi::RustIntrinsic || + f.abi() == Abi::PlatformIntrinsic + } => { debug!(" => intrinsic"); ty::InstanceDef::Intrinsic(def_id) diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index 0dc2bc85e30..f59f6850da1 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -401,8 +401,9 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { output); } }, - ty::TyFnDef(.., sig) | - ty::TyFnPtr(sig) => { + ty::TyFnDef(..) | + ty::TyFnPtr(_) => { + let sig = t.fn_sig(self.tcx); if sig.unsafety() == hir::Unsafety::Unsafe { output.push_str("unsafe "); } diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index bdd8169b84f..68726a7b1c4 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -619,7 +619,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Type check the path. let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id); // Replace constructor type with constructed type for tuple struct patterns. - let pat_ty = pat_ty.fn_sig().output(); + let pat_ty = pat_ty.fn_sig(tcx).output(); let pat_ty = tcx.no_late_bound_regions(&pat_ty).expect("expected fn type"); self.demand_eqtype(pat.span, expected, pat_ty); diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 7cd372f3f00..a0801a74866 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -196,8 +196,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { expected: Expectation<'tcx>) -> Ty<'tcx> { let (fn_sig, def_span) = match callee_ty.sty { - ty::TyFnDef(def_id, .., sig) => { - (sig, self.tcx.hir.span_if_local(def_id)) + ty::TyFnDef(def_id, _) => { + (callee_ty.fn_sig(self.tcx), self.tcx.hir.span_if_local(def_id)) } ty::TyFnPtr(sig) => (sig, None), ref t => { diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index ea08f1f624e..46d304976dc 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -356,8 +356,9 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { (Some(t_from), Some(t_cast)) => (t_from, t_cast), // Function item types may need to be reified before casts. (None, Some(t_cast)) => { - if let ty::TyFnDef(.., f) = self.expr_ty.sty { + if let ty::TyFnDef(..) = self.expr_ty.sty { // Attempt a coercion to a fn pointer type. + let f = self.expr_ty.fn_sig(fcx.tcx); let res = fcx.try_coerce(self.expr, self.expr_ty, self.expr_diverges, diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index c5fd1f56320..17d02223716 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -210,13 +210,13 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { } match a.sty { - ty::TyFnDef(.., a_f) => { + ty::TyFnDef(..) => { // Function items are coercible to any closure // type; function pointers are not (that would // require double indirection). // Additionally, we permit coercion of function // items to drop the unsafe qualifier. - self.coerce_from_fn_item(a, a_f, b) + self.coerce_from_fn_item(a, b) } ty::TyFnPtr(a_f) => { // We permit coercion of fn pointers to drop the @@ -600,7 +600,6 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { fn coerce_from_fn_item(&self, a: Ty<'tcx>, - fn_ty_a: ty::PolyFnSig<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> { //! Attempts to coerce from the type of a Rust function item @@ -612,9 +611,17 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { match b.sty { ty::TyFnPtr(_) => { - let a_fn_pointer = self.tcx.mk_fn_ptr(fn_ty_a); - self.coerce_from_safe_fn(a_fn_pointer, fn_ty_a, b, - simple(Adjust::ReifyFnPointer), simple(Adjust::ReifyFnPointer)) + let a_sig = a.fn_sig(self.tcx); + let InferOk { value: a_sig, mut obligations } = + self.normalize_associated_types_in_as_infer_ok(self.cause.span, &a_sig); + + let a_fn_pointer = self.tcx.mk_fn_ptr(a_sig); + let InferOk { value, obligations: o2 } = + self.coerce_from_safe_fn(a_fn_pointer, a_sig, b, + simple(Adjust::ReifyFnPointer), simple(Adjust::ReifyFnPointer))?; + + obligations.extend(o2); + Ok(InferOk { value, obligations }) } _ => self.unify_and(a, b, identity), } @@ -775,42 +782,41 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Special-case that coercion alone cannot handle: // Two function item types of differing IDs or Substs. - match (&prev_ty.sty, &new_ty.sty) { - (&ty::TyFnDef(a_def_id, a_substs, a_fty), &ty::TyFnDef(b_def_id, b_substs, b_fty)) => { - // The signature must always match. - let fty = self.at(cause, self.param_env) - .trace(prev_ty, new_ty) - .lub(&a_fty, &b_fty) - .map(|ok| self.register_infer_ok_obligations(ok))?; + if let (&ty::TyFnDef(..), &ty::TyFnDef(..)) = (&prev_ty.sty, &new_ty.sty) { + // Don't reify if the function types have a LUB, i.e. they + // are the same function and their parameters have a LUB. + let lub_ty = self.commit_if_ok(|_| { + self.at(cause, self.param_env) + .lub(prev_ty, new_ty) + .map(|ok| self.register_infer_ok_obligations(ok)) + }); - if a_def_id == b_def_id { - // Same function, maybe the parameters match. - let substs = self.commit_if_ok(|_| { - self.at(cause, self.param_env) - .trace(prev_ty, new_ty) - .lub(&a_substs, &b_substs) - .map(|ok| self.register_infer_ok_obligations(ok)) - }); - - if let Ok(substs) = substs { - // We have a LUB of prev_ty and new_ty, just return it. - return Ok(self.tcx.mk_fn_def(a_def_id, substs, fty)); - } - } - - // Reify both sides and return the reified fn pointer type. - let fn_ptr = self.tcx.mk_fn_ptr(fty); - for expr in exprs.iter().map(|e| e.as_coercion_site()).chain(Some(new)) { - // The only adjustment that can produce an fn item is - // `NeverToAny`, so this should always be valid. - self.apply_adjustments(expr, vec![Adjustment { - kind: Adjust::ReifyFnPointer, - target: fn_ptr - }]); - } - return Ok(fn_ptr); + if lub_ty.is_ok() { + // We have a LUB of prev_ty and new_ty, just return it. + return lub_ty; } - _ => {} + + // The signature must match. + let a_sig = prev_ty.fn_sig(self.tcx); + let a_sig = self.normalize_associated_types_in(new.span, &a_sig); + let b_sig = new_ty.fn_sig(self.tcx); + let b_sig = self.normalize_associated_types_in(new.span, &b_sig); + let sig = self.at(cause, self.param_env) + .trace(prev_ty, new_ty) + .lub(&a_sig, &b_sig) + .map(|ok| self.register_infer_ok_obligations(ok))?; + + // Reify both sides and return the reified fn pointer type. + let fn_ptr = self.tcx.mk_fn_ptr(sig); + for expr in exprs.iter().map(|e| e.as_coercion_site()).chain(Some(new)) { + // The only adjustment that can produce an fn item is + // `NeverToAny`, so this should always be valid. + self.apply_adjustments(expr, vec![Adjustment { + kind: Adjust::ReifyFnPointer, + target: fn_ptr + }]); + } + return Ok(fn_ptr); } let mut coerce = Coerce::new(self, cause.clone()); diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 29742469f84..fd5147d76e8 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -256,17 +256,10 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Compute skolemized form of impl and trait method tys. let tcx = infcx.tcx; - let m_sig = |method: &ty::AssociatedItem| { - match tcx.type_of(method.def_id).sty { - ty::TyFnDef(_, _, f) => f, - _ => bug!() - } - }; - let (impl_sig, _) = infcx.replace_late_bound_regions_with_fresh_var(impl_m_span, infer::HigherRankedType, - &m_sig(impl_m)); + &tcx.fn_sig(impl_m.def_id)); let impl_sig = inh.normalize_associated_types_in(impl_m_span, impl_m_node_id, @@ -277,7 +270,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let trait_sig = inh.liberate_late_bound_regions( impl_m.def_id, - &m_sig(trait_m)); + &tcx.fn_sig(trait_m.def_id)); let trait_sig = trait_sig.subst(tcx, trait_to_skol_substs); let trait_sig = @@ -507,8 +500,7 @@ fn compare_self_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty::ImplContainer(_) => impl_trait_ref.self_ty(), ty::TraitContainer(_) => tcx.mk_self_type() }; - let method_ty = tcx.type_of(method.def_id); - let self_arg_ty = *method_ty.fn_sig().input(0).skip_binder(); + let self_arg_ty = *tcx.fn_sig(method.def_id).input(0).skip_binder(); match ExplicitSelf::determine(untransformed_self_ty, self_arg_ty) { ExplicitSelf::ByValue => "self".to_string(), ExplicitSelf::ByReference(_, hir::MutImmutable) => "&self".to_string(), @@ -637,14 +629,8 @@ fn compare_number_of_method_arguments<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_m: &ty::AssociatedItem, trait_item_span: Option) -> Result<(), ErrorReported> { - let m_fty = |method: &ty::AssociatedItem| { - match tcx.type_of(method.def_id).sty { - ty::TyFnDef(_, _, f) => f, - _ => bug!() - } - }; - let impl_m_fty = m_fty(impl_m); - let trait_m_fty = m_fty(trait_m); + let impl_m_fty = tcx.fn_sig(impl_m.def_id); + let trait_m_fty = tcx.fn_sig(trait_m.def_id); let trait_number_args = trait_m_fty.inputs().skip_binder().len(); let impl_number_args = impl_m_fty.inputs().skip_binder().len(); if trait_number_args != impl_number_args { diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 1b6f96cf651..287c591c118 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -143,12 +143,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn has_no_input_arg(&self, method: &AssociatedItem) -> bool { match method.def() { Def::Method(def_id) => { - match self.tcx.type_of(def_id).sty { - ty::TypeVariants::TyFnDef(_, _, sig) => { - sig.inputs().skip_binder().len() == 1 - } - _ => false, - } + self.tcx.fn_sig(def_id).inputs().skip_binder().len() == 1 } _ => false, } diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 4d9f50b0fc0..3acfbd1d844 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -13,7 +13,6 @@ use intrinsics; use rustc::traits::{ObligationCause, ObligationCauseCode}; -use rustc::ty::subst::Substs; use rustc::ty::{self, TyCtxt, Ty}; use rustc::util::nodemap::FxHashMap; use require_same_types; @@ -35,22 +34,22 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, output: Ty<'tcx>) { let def_id = tcx.hir.local_def_id(it.id); - let substs = Substs::for_item(tcx, def_id, - |_, _| tcx.types.re_erased, - |def, _| tcx.mk_param_from_def(def)); + match it.node { + hir::ForeignItemFn(..) => {} + _ => { + struct_span_err!(tcx.sess, it.span, E0619, + "intrinsic must be a function") + .span_label(it.span, "expected a function") + .emit(); + return; + } + } - let fty = tcx.mk_fn_def(def_id, substs, ty::Binder(tcx.mk_fn_sig( - inputs.into_iter(), - output, - false, - hir::Unsafety::Unsafe, - abi - ))); let i_n_tps = tcx.generics_of(def_id).types.len(); if i_n_tps != n_tps { let span = match it.node { hir::ForeignItemFn(_, _, ref generics) => generics.span, - hir::ForeignItemStatic(..) => it.span + _ => bug!() }; struct_span_err!(tcx.sess, span, E0094, @@ -59,14 +58,18 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, i_n_tps, n_tps) .span_label(span, format!("expected {} type parameter", n_tps)) .emit(); - } else { - require_same_types(tcx, - &ObligationCause::new(it.span, - it.id, - ObligationCauseCode::IntrinsicType), - tcx.type_of(def_id), - fty); + return; } + + let fty = tcx.mk_fn_ptr(ty::Binder(tcx.mk_fn_sig( + inputs.into_iter(), + output, + false, + hir::Unsafety::Unsafe, + abi + ))); + let cause = ObligationCause::new(it.span, it.id, ObligationCauseCode::IntrinsicType); + require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(def_id)), fty); } /// Remember to add all intrinsics here, in librustc_trans/trans/intrinsic.rs, @@ -376,7 +379,7 @@ pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut structural_to_nomimal = FxHashMap(); - let sig = tcx.type_of(def_id).fn_sig(); + let sig = tcx.fn_sig(def_id); let sig = tcx.no_late_bound_regions(&sig).unwrap(); if intr.inputs.len() != sig.inputs().len() { span_err!(tcx.sess, it.span, E0444, diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 36bd6657389..209245187b1 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -375,7 +375,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { debug!("method_predicates after subst = {:?}", method_predicates); - let sig = self.tcx.type_of(def_id).fn_sig(); + let sig = self.tcx.fn_sig(def_id); // Instantiate late-bound regions and substitute the trait // parameters into the method type to get the actual method type. diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 73c1215f275..4f4169ac93d 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -235,7 +235,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // NB: Instantiate late-bound regions first so that // `instantiate_type_scheme` can normalize associated types that // may reference those regions. - let fn_sig = tcx.type_of(def_id).fn_sig(); + let fn_sig = tcx.fn_sig(def_id); let fn_sig = self.replace_late_bound_regions_with_fresh_var(span, infer::FnCall, &fn_sig).0; diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 2518a1739f7..ee9a347ae95 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -673,7 +673,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { expected: ty::Ty<'tcx>) -> bool { match method.def() { Def::Method(def_id) => { - let fty = self.tcx.type_of(def_id).fn_sig(); + let fty = self.tcx.fn_sig(def_id); self.probe(|_| { let substs = self.fresh_substs_for_item(self.span, method.def_id); let output = fty.output().subst(self.tcx, substs); @@ -1288,7 +1288,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { impl_ty: Ty<'tcx>, substs: &Substs<'tcx>) -> Ty<'tcx> { - let self_ty = self.tcx.type_of(method).fn_sig().input(0); + let self_ty = self.tcx.fn_sig(method).input(0); debug!("xform_self_ty(impl_ty={:?}, self_ty={:?}, substs={:?})", impl_ty, self_ty, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index b92a78987a3..701de029b2b 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -718,20 +718,12 @@ pub fn provide(providers: &mut Providers) { typeck_item_bodies, typeck_tables_of, has_typeck_tables, - fn_sig, closure_kind, adt_destructor, ..*providers }; } -fn fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - def_id: DefId) - -> ty::PolyFnSig<'tcx> { - let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); - tcx.typeck_tables_of(def_id).closure_tys[&node_id] -} - fn closure_kind<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::ClosureKind { @@ -844,7 +836,7 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, Inherited::build(tcx, def_id).enter(|inh| { let param_env = tcx.param_env(def_id); let fcx = if let Some(decl) = fn_decl { - let fn_sig = tcx.type_of(def_id).fn_sig(); + let fn_sig = tcx.fn_sig(def_id); check_abi(tcx, span, fn_sig.abi()); @@ -2173,7 +2165,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { -> ty::TypeAndMut<'tcx> { // extract method return type, which will be &T; - // all LB regions should have been instantiated during method lookup let ret_ty = method.sig.output(); // method returns &T, but the type as visible to user is T, so deref @@ -2580,8 +2571,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty::TyUint(ast::UintTy::U8) | ty::TyUint(ast::UintTy::U16) => { variadic_error(tcx.sess, arg.span, arg_ty, "c_uint"); } - ty::TyFnDef(.., f) => { - let ptr_ty = self.tcx.mk_fn_ptr(f); + ty::TyFnDef(..) => { + let ptr_ty = self.tcx.mk_fn_ptr(arg_ty.fn_sig(self.tcx)); let ptr_ty = self.resolve_type_vars_if_possible(&ptr_ty); variadic_error(tcx.sess, arg.span, arg_ty, &format!("{}", ptr_ty)); } diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 26f708e9345..cbda1227742 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -177,12 +177,11 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { } ty::AssociatedKind::Method => { reject_shadowing_type_parameters(fcx.tcx, item.def_id); - let method_ty = fcx.tcx.type_of(item.def_id); - let method_ty = fcx.normalize_associated_types_in(span, &method_ty); + let sig = fcx.tcx.fn_sig(item.def_id); + let sig = fcx.normalize_associated_types_in(span, &sig); let predicates = fcx.tcx.predicates_of(item.def_id) .instantiate_identity(fcx.tcx); let predicates = fcx.normalize_associated_types_in(span, &predicates); - let sig = method_ty.fn_sig(); this.check_fn_or_method(fcx, span, sig, &predicates, item.def_id, &mut implied_bounds); let sig_if_method = sig_if_method.expect("bad signature for method"); @@ -331,9 +330,8 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { fn check_item_fn(&mut self, item: &hir::Item) { self.for_item(item).with_fcx(|fcx, this| { let def_id = fcx.tcx.hir.local_def_id(item.id); - let ty = fcx.tcx.type_of(def_id); - let item_ty = fcx.normalize_associated_types_in(item.span, &ty); - let sig = item_ty.fn_sig(); + let sig = fcx.tcx.fn_sig(def_id); + let sig = fcx.normalize_associated_types_in(item.span, &sig); let predicates = fcx.tcx.predicates_of(def_id).instantiate_identity(fcx.tcx); let predicates = fcx.normalize_associated_types_in(item.span, &predicates); @@ -461,9 +459,9 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { let span = method_sig.decl.inputs[0].span; - let method_ty = fcx.tcx.type_of(method.def_id); - let fty = fcx.normalize_associated_types_in(span, &method_ty); - let sig = fcx.liberate_late_bound_regions(method.def_id, &fty.fn_sig()); + let sig = fcx.tcx.fn_sig(method.def_id); + let sig = fcx.normalize_associated_types_in(span, &sig); + let sig = fcx.liberate_late_bound_regions(method.def_id, &sig); debug!("check_method_receiver: sig={:?}", sig); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index fb3bcd31e21..fd6dda5ccf4 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -97,6 +97,7 @@ pub fn provide(providers: &mut Providers) { type_param_predicates, trait_def, adt_def, + fn_sig, impl_trait_ref, impl_polarity, is_foreign_item, @@ -447,6 +448,9 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) { tcx.generics_of(def_id); tcx.type_of(def_id); tcx.predicates_of(def_id); + if let hir::ForeignItemFn(..) = item.node { + tcx.fn_sig(def_id); + } } } hir::ItemEnum(ref enum_definition, _) => { @@ -497,6 +501,9 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) { tcx.generics_of(def_id); tcx.type_of(def_id); tcx.predicates_of(def_id); + if let hir::ItemFn(..) = it.node { + tcx.fn_sig(def_id); + } } } } @@ -511,6 +518,9 @@ fn convert_trait_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_item_id: ast: hir::TraitItemKind::Type(_, Some(_)) | hir::TraitItemKind::Method(..) => { tcx.type_of(def_id); + if let hir::TraitItemKind::Method(..) = trait_item.node { + tcx.fn_sig(def_id); + } } hir::TraitItemKind::Type(_, None) => {} @@ -524,6 +534,9 @@ fn convert_impl_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_item_id: ast::N tcx.generics_of(def_id); tcx.type_of(def_id); tcx.predicates_of(def_id); + if let hir::ImplItemKind::Method(..) = tcx.hir.expect_impl_item(impl_item_id).node { + tcx.fn_sig(def_id); + } } fn convert_variant_ctor<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -963,10 +976,9 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, match tcx.hir.get(node_id) { NodeTraitItem(item) => { match item.node { - TraitItemKind::Method(ref sig, _) => { - let fty = AstConv::ty_of_fn(&icx, sig.unsafety, sig.abi, &sig.decl); + TraitItemKind::Method(..) => { let substs = Substs::identity_for_item(tcx, def_id); - tcx.mk_fn_def(def_id, substs, fty) + tcx.mk_fn_def(def_id, substs) } TraitItemKind::Const(ref ty, _) | TraitItemKind::Type(_, Some(ref ty)) => icx.to_ty(ty), @@ -978,10 +990,9 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, NodeImplItem(item) => { match item.node { - ImplItemKind::Method(ref sig, _) => { - let fty = AstConv::ty_of_fn(&icx, sig.unsafety, sig.abi, &sig.decl); + ImplItemKind::Method(..) => { let substs = Substs::identity_for_item(tcx, def_id); - tcx.mk_fn_def(def_id, substs, fty) + tcx.mk_fn_def(def_id, substs) } ImplItemKind::Const(ref ty, _) => icx.to_ty(ty), ImplItemKind::Type(ref ty) => { @@ -1001,10 +1012,9 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ItemTy(ref t, _) | ItemImpl(.., ref t, _) => { icx.to_ty(t) } - ItemFn(ref decl, unsafety, _, abi, _, _) => { - let tofd = AstConv::ty_of_fn(&icx, unsafety, abi, &decl); + ItemFn(..) => { let substs = Substs::identity_for_item(tcx, def_id); - tcx.mk_fn_def(def_id, substs, tofd) + tcx.mk_fn_def(def_id, substs) } ItemEnum(..) | ItemStruct(..) | @@ -1029,11 +1039,10 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } NodeForeignItem(foreign_item) => { - let abi = tcx.hir.get_foreign_abi(node_id); - match foreign_item.node { - ForeignItemFn(ref fn_decl, _, _) => { - compute_type_of_foreign_fn_decl(tcx, def_id, fn_decl, abi) + ForeignItemFn(..) => { + let substs = Substs::identity_for_item(tcx, def_id); + tcx.mk_fn_def(def_id, substs) } ForeignItemStatic(ref t, _) => icx.to_ty(t) } @@ -1041,21 +1050,13 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, NodeStructCtor(&ref def) | NodeVariant(&Spanned { node: hir::Variant_ { data: ref def, .. }, .. }) => { - let ty = tcx.type_of(tcx.hir.get_parent_did(node_id)); match *def { - VariantData::Unit(..) | VariantData::Struct(..) => ty, - VariantData::Tuple(ref fields, _) => { - let inputs = fields.iter().map(|f| { - tcx.type_of(tcx.hir.local_def_id(f.id)) - }); + VariantData::Unit(..) | VariantData::Struct(..) => { + tcx.type_of(tcx.hir.get_parent_did(node_id)) + } + VariantData::Tuple(..) => { let substs = Substs::identity_for_item(tcx, def_id); - tcx.mk_fn_def(def_id, substs, ty::Binder(tcx.mk_fn_sig( - inputs, - ty, - false, - hir::Unsafety::Normal, - abi::Abi::Rust - ))) + tcx.mk_fn_def(def_id, substs) } } } @@ -1105,6 +1106,58 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } +fn fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId) + -> ty::PolyFnSig<'tcx> { + use rustc::hir::map::*; + use rustc::hir::*; + + let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); + + let icx = ItemCtxt::new(tcx, def_id); + + match tcx.hir.get(node_id) { + NodeTraitItem(&hir::TraitItem { node: TraitItemKind::Method(ref sig, _), .. }) | + NodeImplItem(&hir::ImplItem { node: ImplItemKind::Method(ref sig, _), .. }) => { + AstConv::ty_of_fn(&icx, sig.unsafety, sig.abi, &sig.decl) + } + + NodeItem(&hir::Item { node: ItemFn(ref decl, unsafety, _, abi, _, _), .. }) => { + AstConv::ty_of_fn(&icx, unsafety, abi, decl) + } + + NodeForeignItem(&hir::ForeignItem { node: ForeignItemFn(ref fn_decl, _, _), .. }) => { + let abi = tcx.hir.get_foreign_abi(node_id); + compute_sig_of_foreign_fn_decl(tcx, def_id, fn_decl, abi) + } + + NodeStructCtor(&VariantData::Tuple(ref fields, _)) | + NodeVariant(&Spanned { node: hir::Variant_ { + data: VariantData::Tuple(ref fields, _), .. + }, .. }) => { + let ty = tcx.type_of(tcx.hir.get_parent_did(node_id)); + let inputs = fields.iter().map(|f| { + tcx.type_of(tcx.hir.local_def_id(f.id)) + }); + ty::Binder(tcx.mk_fn_sig( + inputs, + ty, + false, + hir::Unsafety::Normal, + abi::Abi::Rust + )) + } + + NodeExpr(&hir::Expr { node: hir::ExprClosure(..), .. }) => { + tcx.typeck_tables_of(def_id).closure_tys[&node_id] + } + + x => { + bug!("unexpected sort of node in fn_sig(): {:?}", x); + } + } +} + fn impl_trait_ref<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Option> { @@ -1502,12 +1555,12 @@ fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx, 'tcx>, } } -fn compute_type_of_foreign_fn_decl<'a, 'tcx>( +fn compute_sig_of_foreign_fn_decl<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, decl: &hir::FnDecl, abi: abi::Abi) - -> Ty<'tcx> + -> ty::PolyFnSig<'tcx> { let fty = AstConv::ty_of_fn(&ItemCtxt::new(tcx, def_id), hir::Unsafety::Unsafe, abi, decl); @@ -1533,8 +1586,7 @@ fn compute_type_of_foreign_fn_decl<'a, 'tcx>( } } - let substs = Substs::identity_for_item(tcx, def_id); - tcx.mk_fn_def(def_id, substs, fty) + fty } fn is_foreign_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index b2fa2cc7c61..bf5adc8644d 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4736,4 +4736,5 @@ register_diagnostics! { E0568, // auto-traits can not have predicates, E0588, // packed struct cannot transitively contain a `[repr(align)]` struct E0592, // duplicate definitions with name `{}` + E0619, // intrinsic must be a function } diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 9e99af633d5..519e1ca6e5a 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -198,22 +198,21 @@ fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } _ => () } - let substs = tcx.intern_substs(&[]); - let se_ty = tcx.mk_fn_def(main_def_id, substs, - ty::Binder(tcx.mk_fn_sig( + let se_ty = tcx.mk_fn_ptr(ty::Binder( + tcx.mk_fn_sig( iter::empty(), tcx.mk_nil(), false, hir::Unsafety::Normal, Abi::Rust - )) - ); + ) + )); require_same_types( tcx, &ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType), se_ty, - main_t); + tcx.mk_fn_ptr(tcx.fn_sig(main_def_id))); } _ => { span_bug!(main_span, @@ -248,9 +247,8 @@ fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, _ => () } - let substs = tcx.intern_substs(&[]); - let se_ty = tcx.mk_fn_def(start_def_id, substs, - ty::Binder(tcx.mk_fn_sig( + let se_ty = tcx.mk_fn_ptr(ty::Binder( + tcx.mk_fn_sig( [ tcx.types.isize, tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8)) @@ -259,14 +257,14 @@ fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, false, hir::Unsafety::Normal, Abi::Rust - )) - ); + ) + )); require_same_types( tcx, &ObligationCause::new(start_span, start_id, ObligationCauseCode::StartFunctionType), se_ty, - start_t); + tcx.mk_fn_ptr(tcx.fn_sig(start_def_id))); } _ => { span_bug!(start_span, diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index c434edb1c31..4c09d90f853 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -382,6 +382,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { // leaf type -- noop } + ty::TyFnDef(..) | ty::TyClosure(..) | ty::TyAnon(..) => { bug!("Unexpected closure type in variance computation"); @@ -466,7 +467,6 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { } } - ty::TyFnDef(.., sig) | ty::TyFnPtr(sig) => { self.add_constraints_from_sig(current, sig, variance); } diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index aeade470482..fa5a999adf1 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -149,7 +149,7 @@ pub fn build_external_trait(cx: &DocContext, did: DefId) -> clean::Trait { } fn build_external_function(cx: &DocContext, did: DefId) -> clean::Function { - let sig = cx.tcx.type_of(did).fn_sig(); + let sig = cx.tcx.fn_sig(did); let constness = if cx.tcx.is_const_fn(did) { hir::Constness::Const diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 8fc8ccd0cfd..478e2fc5085 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1367,7 +1367,7 @@ impl<'tcx> Clean for ty::AssociatedItem { ty::AssociatedKind::Method => { let generics = (cx.tcx.generics_of(self.def_id), &cx.tcx.predicates_of(self.def_id)).clean(cx); - let sig = cx.tcx.type_of(self.def_id).fn_sig(); + let sig = cx.tcx.fn_sig(self.def_id); let mut decl = (self.def_id, sig).clean(cx); if self.method_has_self_argument { @@ -1842,17 +1842,21 @@ impl<'tcx> Clean for ty::Ty<'tcx> { mutability: mt.mutbl.clean(cx), type_: box mt.ty.clean(cx), }, - ty::TyFnDef(.., sig) | - ty::TyFnPtr(sig) => BareFunction(box BareFunctionDecl { - unsafety: sig.unsafety(), - generics: Generics { - lifetimes: Vec::new(), - type_params: Vec::new(), - where_predicates: Vec::new() - }, - decl: (cx.tcx.hir.local_def_id(ast::CRATE_NODE_ID), sig).clean(cx), - abi: sig.abi(), - }), + ty::TyFnDef(..) | + ty::TyFnPtr(_) => { + let ty = cx.tcx.lift(self).unwrap(); + let sig = ty.fn_sig(cx.tcx); + BareFunction(box BareFunctionDecl { + unsafety: sig.unsafety(), + generics: Generics { + lifetimes: Vec::new(), + type_params: Vec::new(), + where_predicates: Vec::new() + }, + decl: (cx.tcx.hir.local_def_id(ast::CRATE_NODE_ID), sig).clean(cx), + abi: sig.abi(), + }) + } ty::TyAdt(def, substs) => { let did = def.did; let kind = match def.adt_kind() { diff --git a/src/test/compile-fail/invalid-intrinsic.rs b/src/test/compile-fail/invalid-intrinsic.rs index 2aa2546cb9f..c42d78c323e 100644 --- a/src/test/compile-fail/invalid-intrinsic.rs +++ b/src/test/compile-fail/invalid-intrinsic.rs @@ -11,6 +11,6 @@ #![feature(intrinsics)] extern "rust-intrinsic" { pub static breakpoint : unsafe extern "rust-intrinsic" fn(); - //~^ ERROR intrinsic has wrong type + //~^ ERROR intrinsic must be a function } -fn main() { unsafe { breakpoint(); } } \ No newline at end of file +fn main() { unsafe { breakpoint(); } }