]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #42931 - arielb1:statement-visitor, r=eddyb
authorbors <bors@rust-lang.org>
Wed, 28 Jun 2017 08:47:29 +0000 (08:47 +0000)
committerbors <bors@rust-lang.org>
Wed, 28 Jun 2017 08:47:29 +0000 (08:47 +0000)
re-add the call to `super_statement` in EraseRegions

The move gathering code is sensitive to type-equality - that is rather
un-robust and I plan to fix it eventually, but that's a more invasive
change. And we want to fix the visitor anyway.

Fixes #42903.

r? @eddyb

83 files changed:
src/libcore/num/f32.rs
src/libcore/num/f64.rs
src/librustc/ich/impls_ty.rs
src/librustc/infer/mod.rs
src/librustc/middle/effect.rs
src/librustc/middle/intrinsicck.rs
src/librustc/traits/object_safety.rs
src/librustc/traits/project.rs
src/librustc/traits/select.rs
src/librustc/ty/context.rs
src/librustc/ty/fast_reject.rs
src/librustc/ty/flags.rs
src/librustc/ty/item_path.rs
src/librustc/ty/maps.rs
src/librustc/ty/mod.rs
src/librustc/ty/relate.rs
src/librustc/ty/structural_impls.rs
src/librustc/ty/sty.rs
src/librustc/ty/util.rs
src/librustc/ty/walk.rs
src/librustc/util/ppaux.rs
src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs
src/librustc_const_eval/pattern.rs
src/librustc_lint/builtin.rs
src/librustc_lint/types.rs
src/librustc_metadata/cstore_impl.rs
src/librustc_metadata/decoder.rs
src/librustc_metadata/encoder.rs
src/librustc_metadata/schema.rs
src/librustc_mir/build/expr/into.rs
src/librustc_mir/hair/cx/expr.rs
src/librustc_mir/shim.rs
src/librustc_mir/transform/inline.rs
src/librustc_mir/transform/qualify_consts.rs
src/librustc_mir/transform/type_check.rs
src/librustc_privacy/lib.rs
src/librustc_trans/back/symbol_names.rs
src/librustc_trans/collector.rs
src/librustc_trans/common.rs
src/librustc_trans/debuginfo/metadata.rs
src/librustc_trans/debuginfo/type_names.rs
src/librustc_trans/intrinsic.rs
src/librustc_trans/mir/block.rs
src/librustc_trans/mir/constant.rs
src/librustc_trans/mir/rvalue.rs
src/librustc_trans/monomorphize.rs
src/librustc_trans/trans_item.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/callee.rs
src/librustc_typeck/check/cast.rs
src/librustc_typeck/check/coercion.rs
src/librustc_typeck/check/compare_method.rs
src/librustc_typeck/check/demand.rs
src/librustc_typeck/check/intrinsic.rs
src/librustc_typeck/check/method/confirm.rs
src/librustc_typeck/check/method/mod.rs
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/wfcheck.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/diagnostics.rs
src/librustc_typeck/lib.rs
src/librustc_typeck/variance/constraints.rs
src/librustc_typeck/variance/mod.rs
src/librustc_typeck/variance/solve.rs
src/librustc_typeck/variance/terms.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/libstd/f32.rs
src/libstd/f64.rs
src/libsyntax_ext/deriving/clone.rs
src/libsyntax_ext/deriving/debug.rs
src/libsyntax_ext/deriving/encodable.rs
src/libsyntax_ext/deriving/generic/mod.rs
src/libsyntax_ext/deriving/hash.rs
src/test/compile-fail/associated-types-path-2.rs
src/test/compile-fail/invalid-intrinsic.rs
src/test/compile-fail/on-unimplemented/multiple-impls.rs
src/test/compile-fail/on-unimplemented/on-impl.rs
src/test/compile-fail/variance-region-bounds.rs [deleted file]
src/test/compile-fail/variance-trait-bounds.rs
src/test/compile-fail/variance-types-bounds.rs
src/test/run-pass/deriving-hash.rs

index cb28035682d650607409d522448243413a03630b..ebc30dc8b61fb0fd390e16a745728c89d60cdc3f 100644 (file)
@@ -205,18 +205,25 @@ fn signum(self) -> f32 {
         }
     }
 
-    /// Returns `true` if `self` is positive, including `+0.0` and
-    /// `Float::infinity()`.
+    /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
+    /// positive sign bit and positive infinity.
     #[inline]
     fn is_sign_positive(self) -> bool {
-        self > 0.0 || (1.0 / self) == INFINITY
+        !self.is_sign_negative()
     }
 
-    /// Returns `true` if `self` is negative, including `-0.0` and
-    /// `Float::neg_infinity()`.
+    /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
+    /// negative sign bit and negative infinity.
     #[inline]
     fn is_sign_negative(self) -> bool {
-        self < 0.0 || (1.0 / self) == NEG_INFINITY
+        // IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
+        // applies to zeros and NaNs as well.
+        #[repr(C)]
+        union F32Bytes {
+            f: f32,
+            b: u32
+        }
+        unsafe { F32Bytes { f: self }.b & 0x8000_0000 != 0 }
     }
 
     /// Returns the reciprocal (multiplicative inverse) of the number.
index ac6b1e67cd2785b17154e76062210bb6f6f76f8c..1a1fe4d86e0d093ccb3dab01139374948a88023b 100644 (file)
@@ -205,18 +205,23 @@ fn signum(self) -> f64 {
         }
     }
 
-    /// Returns `true` if `self` is positive, including `+0.0` and
-    /// `Float::infinity()`.
+    /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
+    /// positive sign bit and positive infinity.
     #[inline]
     fn is_sign_positive(self) -> bool {
-        self > 0.0 || (1.0 / self) == INFINITY
+        !self.is_sign_negative()
     }
 
-    /// Returns `true` if `self` is negative, including `-0.0` and
-    /// `Float::neg_infinity()`.
+    /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
+    /// negative sign bit and negative infinity.
     #[inline]
     fn is_sign_negative(self) -> bool {
-        self < 0.0 || (1.0 / self) == NEG_INFINITY
+        #[repr(C)]
+        union F64Bytes {
+            f: f64,
+            b: u64
+        }
+        unsafe { F64Bytes { f: self }.b & 0x8000_0000_0000_0000 != 0 }
     }
 
     /// Returns the reciprocal (multiplicative inverse) of the number.
index 4e78d79ef87378e8d1376a1f4a5b368d7fe7facb..4f365a97f4ceba1719af50f475bf9b06e1068263 100644 (file)
@@ -524,10 +524,9 @@ fn hash_stable<W: StableHasherResult>(&self,
                 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);
index f96e8c389d68d87db962994d2941e56309572e54..d5020b12ee00e12c5e86295d92ad75a9a8219c03 100644 (file)
@@ -1369,7 +1369,11 @@ pub fn closure_kind(&self,
         Some(self.tcx.closure_kind(def_id))
     }
 
-    pub fn closure_type(&self, def_id: DefId) -> ty::PolyFnSig<'tcx> {
+    /// Obtain the signature of a function or closure.
+    /// For closures, unlike `tcx.fn_sig(def_id)`, this method will
+    /// work during the type-checking of the enclosing function and
+    /// return the closure signature in its partially inferred state.
+    pub fn fn_sig(&self, def_id: DefId) -> ty::PolyFnSig<'tcx> {
         if let Some(tables) = self.in_progress_tables {
             if let Some(id) = self.tcx.hir.as_local_node_id(def_id) {
                 if let Some(&ty) = tables.borrow().closure_tys.get(&id) {
@@ -1378,7 +1382,7 @@ pub fn closure_type(&self, def_id: DefId) -> ty::PolyFnSig<'tcx> {
             }
         }
 
-        self.tcx.closure_type(def_id)
+        self.tcx.fn_sig(def_id)
     }
 }
 
index 74e1225f3948b92e9ab52e93f016ba48271a3d9e..eab5a8f910331184187caac0a7dd822df61afd86 100644 (file)
@@ -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 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
         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 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
                 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) => {
index f180ae53b8ae1926868ad9794595f772c8e31f85..fde207e4b2f79f75922a2fb36ef74ce9739ad07b 100644 (file)
@@ -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 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
         } 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);
index 0e3a53129d157fe2af455cacd25a59597c87b22f..c6c052fa4b1bc100b8bd034126464cd2d71d4bc8 100644 (file)
@@ -260,7 +260,7 @@ fn virtual_call_violation_for_method(self,
 
         // 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);
index 787452121d375c841f51665ea8b23706ded59789..c356e53234d9c3e3248eb17138fce58c9f012e19 100644 (file)
@@ -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>(
@@ -1149,7 +1159,7 @@ fn confirm_closure_candidate<'cx, 'gcx, 'tcx>(
     -> Progress<'tcx>
 {
     let closure_typer = selcx.closure_typer();
-    let closure_type = closure_typer.closure_type(vtable.closure_def_id)
+    let closure_type = closure_typer.fn_sig(vtable.closure_def_id)
         .subst(selcx.tcx(), vtable.substs.substs);
     let Normalized {
         value: closure_type,
index 10710d963a0156731420bb942f34badff52ddd87..a66b6b863541e2446170291ace748b925f95c010 100644 (file)
@@ -1404,19 +1404,15 @@ fn assemble_fn_pointer_candidates(&mut self,
             }
 
             // 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 @@ fn confirm_fn_pointer_candidate(&mut self, obligation: &TraitObligation<'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 @@ fn confirm_fn_pointer_candidate(&mut self, obligation: &TraitObligation<'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,
@@ -2799,7 +2802,7 @@ fn closure_trait_ref_unnormalized(&mut self,
                                       substs: ty::ClosureSubsts<'tcx>)
                                       -> ty::PolyTraitRef<'tcx>
     {
-        let closure_type = self.infcx.closure_type(closure_def_id)
+        let closure_type = self.infcx.fn_sig(closure_def_id)
             .subst(self.tcx(), substs.substs);
         let ty::Binder((trait_ref, _)) =
             self.tcx().closure_trait_ref_and_return_type(obligation.predicate.def_id(),
index 2d81606329e57d89e530101e7a1cb116b85a7f59..5f869fc5567ee186d58a7641505634de882a94b9 100644 (file)
@@ -1378,9 +1378,8 @@ pub fn mk_bool(self) -> Ty<'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> {
index 3d2cc4c598a22ea66677cc53010e271920c0c3e2..68f85ba7d33e23dc87beb3ab93134b71352c6edd 100644 (file)
@@ -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(_) => {
index 46afa6ee7d011d48053d892c02cd4cdc1ec65b83..d5aa9f55ff0c4e34beb5942070f79ba6bee1f78b 100644 (file)
@@ -155,9 +155,8 @@ fn add_sty(&mut self, st: &ty::TypeVariants) {
                 self.add_tys(&ts[..]);
             }
 
-            &ty::TyFnDef(_, substs, f) => {
+            &ty::TyFnDef(_, substs) => {
                 self.add_substs(substs);
-                self.add_fn_sig(f);
             }
 
             &ty::TyFnPtr(f) => {
index 09a3bcd06138056afaa89b6641d415a5b8ab4c56..b9896e0cecf5dac93d19cebe75950af51194daf8 100644 (file)
@@ -348,7 +348,7 @@ pub fn characteristic_def_id_of_type(ty: Ty) -> Option<DefId> {
                                       .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 |
index 524cf57472bc86dca71d4210e93381decd9df056..a6c59d4c2235436fc1e6f739b02c34ea76fa2bfc 100644 (file)
@@ -875,13 +875,12 @@ fn default() -> Self {
     /// for trans. This is also the only query that can fetch non-local MIR, at present.
     [] optimized_mir: Mir(DefId) -> &'tcx mir::Mir<'tcx>,
 
-    /// Records the type of each closure. The def ID is the ID of the
+    /// Type of each closure. The def ID is the ID of the
     /// expression defining the closure.
     [] closure_kind: ItemSignature(DefId) -> ty::ClosureKind,
 
-    /// Records the type of each closure. The def ID is the ID of the
-    /// expression defining the closure.
-    [] closure_type: ItemSignature(DefId) -> ty::PolyFnSig<'tcx>,
+    /// The signature of functions and closures.
+    [] fn_sig: ItemSignature(DefId) -> ty::PolyFnSig<'tcx>,
 
     /// Caches CoerceUnsized kinds for impls on custom types.
     [] coerce_unsized_info: ItemSignature(DefId)
index 13e46a265c6953c6d6305910975cb274ea6ba49c..f4d0867d130001846310f4bf0ce373ed5ad96ff1 100644 (file)
@@ -206,7 +206,7 @@ pub fn signature<'a, 'tcx>(&self, tcx: &TyCtxt<'a, 'tcx, 'tcx>) -> String {
                 // 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 => {
index d4f06a902eeaa46221b45ead63abfcb74ea69cb0..2e9780572c9b40bfa8d4ac2a1b1aafee64fb9835 100644 (file)
@@ -291,7 +291,7 @@ fn relate<'a, 'gcx, R>(relation: &mut R,
         if a.def_id != b.def_id {
             Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id)))
         } else {
-            let substs = relation.relate_item_substs(a.def_id, a.substs, b.substs)?;
+            let substs = relate_substs(relation, None, a.substs, b.substs)?;
             Ok(ty::TraitRef { def_id: a.def_id, substs: substs })
         }
     }
@@ -308,7 +308,7 @@ fn relate<'a, 'gcx, R>(relation: &mut R,
         if a.def_id != b.def_id {
             Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id)))
         } else {
-            let substs = relation.relate_item_substs(a.def_id, a.substs, b.substs)?;
+            let substs = relate_substs(relation, None, a.substs, b.substs)?;
             Ok(ty::ExistentialTraitRef { def_id: a.def_id, substs: substs })
         }
     }
@@ -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))
+            let substs = relation.relate_item_substs(a_def_id, a_substs, b_substs)?;
+            Ok(tcx.mk_fn_def(a_def_id, substs))
         }
 
         (&ty::TyFnPtr(a_fty), &ty::TyFnPtr(b_fty)) =>
index 1e2689243903e3a7c2f81f186d78ea4b2f09f0d9..d05262965d7fd6daf8505f23bcdd7bb51c842c8b 100644 (file)
@@ -531,10 +531,8 @@ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F)
             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 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
             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),
index 6923a6d21d63f1dec1cc499cffd9154338189b66..ed3312d88a38420babc569919be055fe161b30f3 100644 (file)
@@ -14,7 +14,7 @@
 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 @@ pub fn builtin_index(&self) -> Option<Ty<'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)
         }
     }
index 1bbc767348563142d80d820066eb1ebdcbaf13dd..98ef7918fef82ac263afe005a05ddd94a86e0e93 100644 (file)
@@ -679,7 +679,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
             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());
index d7954953aba856902fb1829b0d8d30db6f60d71e..71844abfe534c14b8e6cf5dcd0f6e97de1325467 100644 (file)
@@ -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);
index 1fa63577196664437c73e45b208bdfdc6a5ec56a..eb6bffc29c56171ecc37cd1d07a7cc0571defb39 100644 (file)
@@ -753,8 +753,14 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                 }
                 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, "}}")
             }
index 2c55460fb301b3ed55fab6c16e2eea04560e2ae1..4bef191b113bd66816416df4614fe65146c6c794 100644 (file)
@@ -161,18 +161,13 @@ fn is_rustc_peek<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                            terminator: &'a Option<mir::Terminator<'tcx>>)
                            -> 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));
                     }
                 }
             }
index d175920e8a6baf895abb18522c26e55295cf5954..0a966b0c170712dceabb786c3b72e1e8f81bcc7f 100644 (file)
@@ -12,7 +12,7 @@
 
 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 @@ fn lower_variant_or_leaf(
                 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 {
index 9800012917c504475cc494efa845d302c6b47f1f..ad154f9b8153106b73263b07b5fa92f1a2ef7198 100644 (file)
@@ -1154,24 +1154,16 @@ fn get_transmute_from_to<'a, 'tcx>
                 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"
         }
     }
index 32bde42b5261f64b4d6c25ffa0317698bb3d235c..ac3977bd216e7a4587f293ffb4c961635c391766 100644 (file)
@@ -659,7 +659,7 @@ fn check_type_for_ffi_and_report_errors(&mut self, sp: Span, ty: Ty<'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) {
index c49712086d52c2aff46e5483d7629f275535cbce..502eab44dac52d7c116aa6103b77fae04bc15079 100644 (file)
@@ -106,7 +106,7 @@ pub fn provide<$lt>(providers: &mut Providers<$lt>) {
     mir_const_qualif => { cdata.mir_const_qualif(def_id.index) }
     typeck_tables_of => { cdata.item_body_tables(def_id.index, tcx) }
     closure_kind => { cdata.closure_kind(def_id.index) }
-    closure_type => { cdata.closure_ty(def_id.index, tcx) }
+    fn_sig => { cdata.fn_sig(def_id.index, tcx) }
     inherent_impls => { Rc::new(cdata.get_inherent_implementations_for_type(def_id.index)) }
     is_const_fn => { cdata.is_const_fn(def_id.index) }
     is_foreign_item => { cdata.is_foreign_item(def_id.index) }
index 728ab30bb17dc6a63e1fc649f5a07271a9f60952..3e6d06ec86ff89530f3ca014e92db8f870300997 100644 (file)
@@ -1084,14 +1084,20 @@ pub fn closure_kind(&self, closure_id: DefIndex) -> ty::ClosureKind {
         }
     }
 
-    pub fn closure_ty(&self,
-                      closure_id: DefIndex,
-                      tcx: TyCtxt<'a, 'tcx, 'tcx>)
-                      -> ty::PolyFnSig<'tcx> {
-        match self.entry(closure_id).kind {
-            EntryKind::Closure(data) => data.decode(self).ty.decode((self, tcx)),
+    pub fn fn_sig(&self,
+                  id: DefIndex,
+                  tcx: TyCtxt<'a, 'tcx, 'tcx>)
+                  -> ty::PolyFnSig<'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]
index 2a504c4c07794ed25114833a5d67895a67befebc..e9701b95002d4dc5d4706ffe6e1c94c29a7051cb 100644 (file)
@@ -16,6 +16,7 @@
 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 @@ fn encode_enum_variant_info(&mut self,
             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();
@@ -518,7 +524,11 @@ fn encode_enum_variant_info(&mut self,
 
             ty: Some(self.encode_item_type(def_id)),
             inherent_impls: LazySeq::empty(),
-            variances: LazySeq::empty(),
+            variances: if variant.ctor_kind == CtorKind::Fn {
+                self.encode_variances_of(def_id)
+            } else {
+                LazySeq::empty()
+            },
             generics: Some(self.encode_generics(def_id)),
             predicates: Some(self.encode_predicates(def_id)),
 
@@ -617,6 +627,11 @@ fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry<
             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();
@@ -641,7 +656,11 @@ fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry<
 
             ty: Some(self.encode_item_type(def_id)),
             inherent_impls: LazySeq::empty(),
-            variances: LazySeq::empty(),
+            variances: if variant.ctor_kind == CtorKind::Fn {
+                self.encode_variances_of(def_id)
+            } else {
+                LazySeq::empty()
+            },
             generics: Some(self.encode_generics(def_id)),
             predicates: Some(self.encode_predicates(def_id)),
 
@@ -695,7 +714,8 @@ fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> {
                     };
                     FnData {
                         constness: hir::Constness::NotConst,
-                        arg_names: arg_names
+                        arg_names: arg_names,
+                        sig: self.lazy(&tcx.fn_sig(def_id)),
                     }
                 } else {
                     bug!()
@@ -732,7 +752,11 @@ fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> {
                 }
             },
             inherent_impls: LazySeq::empty(),
-            variances: LazySeq::empty(),
+            variances: if trait_item.kind == ty::AssociatedKind::Method {
+                self.encode_variances_of(def_id)
+            } else {
+                LazySeq::empty()
+            },
             generics: Some(self.encode_generics(def_id)),
             predicates: Some(self.encode_predicates(def_id)),
 
@@ -747,6 +771,8 @@ fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'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 +794,7 @@ fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'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!()
@@ -806,7 +833,11 @@ fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> {
 
             ty: Some(self.encode_item_type(def_id)),
             inherent_impls: LazySeq::empty(),
-            variances: LazySeq::empty(),
+            variances: if impl_item.kind == ty::AssociatedKind::Method {
+                self.encode_variances_of(def_id)
+            } else {
+                LazySeq::empty()
+            },
             generics: Some(self.encode_generics(def_id)),
             predicates: Some(self.encode_predicates(def_id)),
 
@@ -881,6 +912,7 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
                 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 +942,7 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
                     ctor_kind: variant.ctor_kind,
                     discr: variant.discr,
                     struct_ctor: struct_ctor,
+                    ctor_sig: None,
                 }), repr_options)
             }
             hir::ItemUnion(..) => {
@@ -920,6 +953,7 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
                     ctor_kind: variant.ctor_kind,
                     discr: variant.discr,
                     struct_ctor: None,
+                    ctor_sig: None,
                 }), repr_options)
             }
             hir::ItemDefaultImpl(..) => {
@@ -1037,7 +1071,7 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
                 hir::ItemEnum(..) |
                 hir::ItemStruct(..) |
                 hir::ItemUnion(..) |
-                hir::ItemTrait(..) => self.encode_variances_of(def_id),
+                hir::ItemFn(..) => self.encode_variances_of(def_id),
                 _ => LazySeq::empty(),
             },
             generics: match item.node {
@@ -1175,7 +1209,7 @@ fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'tcx> {
 
         let data = ClosureData {
             kind: tcx.closure_kind(def_id),
-            ty: self.lazy(&tcx.closure_type(def_id)),
+            sig: self.lazy(&tcx.fn_sig(def_id)),
         };
 
         Entry {
@@ -1363,6 +1397,7 @@ fn encode_info_for_foreign_item(&mut self,
                 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))
             }
@@ -1381,7 +1416,10 @@ fn encode_info_for_foreign_item(&mut self,
 
             ty: Some(self.encode_item_type(def_id)),
             inherent_impls: LazySeq::empty(),
-            variances: LazySeq::empty(),
+            variances: match nitem.node {
+                hir::ForeignItemFn(..) => self.encode_variances_of(def_id),
+                _ => LazySeq::empty(),
+            },
             generics: Some(self.encode_generics(def_id)),
             predicates: Some(self.encode_predicates(def_id)),
 
index 1337f90efa74d56c9ff900887e928ef67f8848ee..9ef5b9408303d7f886ad74a3a145e2a872d6665b 100644 (file)
@@ -343,18 +343,18 @@ pub enum EntryKind<'tcx> {
     Type,
     Enum(ReprOptions),
     Field,
-    Variant(Lazy<VariantData>),
-    Struct(Lazy<VariantData>, ReprOptions),
-    Union(Lazy<VariantData>, ReprOptions),
-    Fn(Lazy<FnData>),
-    ForeignFn(Lazy<FnData>),
+    Variant(Lazy<VariantData<'tcx>>),
+    Struct(Lazy<VariantData<'tcx>>, ReprOptions),
+    Union(Lazy<VariantData<'tcx>>, ReprOptions),
+    Fn(Lazy<FnData<'tcx>>),
+    ForeignFn(Lazy<FnData<'tcx>>),
     Mod(Lazy<ModData>),
     MacroDef(Lazy<MacroDef>),
     Closure(Lazy<ClosureData<'tcx>>),
     Trait(Lazy<TraitData<'tcx>>),
     Impl(Lazy<ImplData<'tcx>>),
     DefaultImpl(Lazy<ImplData<'tcx>>),
-    Method(Lazy<MethodData>),
+    Method(Lazy<MethodData<'tcx>>),
     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<ast::Name>,
+    pub sig: Lazy<ty::PolyFnSig<'tcx>>,
 }
 
-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<DefIndex>,
+
+    /// If this is a tuple struct or variant
+    /// ctor, this is its "function" signature.
+    pub ctor_sig: Option<Lazy<ty::PolyFnSig<'tcx>>>,
 }
 
-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,16 +549,16 @@ pub fn defaultness(&self) -> hir::Defaultness {
 }
 
 #[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> {
     pub kind: ty::ClosureKind,
-    pub ty: Lazy<ty::PolyFnSig<'tcx>>,
+    pub sig: Lazy<ty::PolyFnSig<'tcx>>,
 }
-impl_stable_hash_for!(struct ClosureData<'tcx> { kind, ty });
+impl_stable_hash_for!(struct ClosureData<'tcx> { kind, sig });
index b7abc707a380dd8ec2c6058aa2b33cbc4517b372..326c1df69ebebd364c4990d2cadccd097c64985c 100644 (file)
@@ -205,11 +205,14 @@ pub fn into_expr(&mut self,
                 // 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
                 };
index 474feefabbb88dcc12d14967818e0217031e5805..0010f312ef9852e13bfe166f4c0a0c6768fa76cb 100644 (file)
@@ -19,7 +19,6 @@
 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 {
index 54779cbe30126c9484c1034c8f519691c66cf58d..11ad5d1509d29bcd17b2cd0bb1c541986de4cf31 100644 (file)
@@ -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 {
index 0ac35a5fdd4722bd625317bfba4afe3e03643731..5f80c7bee147832ca51ef19283df30b27a76e3f5 100644 (file)
@@ -87,7 +87,7 @@ fn run_pass(&self, caller_mir: &mut Mir<'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 @@ fn run_pass(&self, caller_mir: &mut Mir<'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 @@ fn should_inline(&self,
                 }
 
                 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 {
index 05a6cdd57ffceed98be29fe1f1ce1fbcfb22dd43..91d6ce60b39044809ea169ab71f798d8fcc1ac36 100644 (file)
@@ -750,8 +750,8 @@ fn visit_terminator_kind(&mut self,
 
             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))
                 }
index efde39ad6a4c11323dd44b88c964910f2bc39efc..7e6fccf30192ce626dbc072efd9b4948bf41b747 100644 (file)
@@ -462,7 +462,7 @@ fn check_terminator(&mut self,
                 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;
index fb7258d42662253c012e2e08890af8e59236c773..9eb96fea52778e6677d09a28deacfd1ee99d15fe 100644 (file)
@@ -400,7 +400,13 @@ fn predicates(&mut self) -> &mut Self {
     }
 
     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 @@ fn predicates(&mut self) -> &mut Self {
     }
 
     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
     }
 
index 8e14335ceacb9950a2d8ffe9cddc52114db062bc..10b66fb1991087a351150bcc8ec921a8cd7ce349 100644 (file)
@@ -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());
index d723cf325718ea86de681f451e32c53091ffad08..3c502eec549b27413ccc5208c35a2b1c5bef0c90 100644 (file)
@@ -587,7 +587,7 @@ fn visit_fn_use<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
                           is_direct_call: bool,
                           output: &mut Vec<TransItem<'tcx>>)
 {
-    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);
     }
index a6f3fb709a01b67f5cc4532f74e4d7809041c005..9b0803908b162582e1dc86bbdc152f4b4f3a4dc5 100644 (file)
@@ -495,12 +495,12 @@ 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.closure_type(def_id).subst(tcx, substs.substs);
+            let sig = tcx.fn_sig(def_id).subst(tcx, substs.substs);
 
             let env_region = ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrEnv);
             let env_ty = match tcx.closure_kind(def_id) {
index 95ceec610eaa37894e49b62ccfe4a4fa9810714b..0cc1993601119597c7d2e553f9abd8126a1d70d8 100644 (file)
@@ -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)
         }
     };
 
index 13ff6646e666256f40772cb96a7d8934e6cb52d7..bfca4fec706eda94267e9779c79320c94d18866a 100644 (file)
@@ -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 ");
             }
index de908bb24a7abb522a1d99f9bd15a557f327188d..9956c28e6412139d2f2fc2fddc106b74b020a104 100644 (file)
@@ -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 @@ macro_rules! require_simd {
 
 
     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
index 8863c7ffae6f4f38c959059ed0891b728fc75639..16972a1b1ae249a9683776534d2e241de7a85c66 100644 (file)
@@ -404,20 +404,18 @@ fn trans_terminator(&mut self,
                 // 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;
 
index 16ef32ccf5777b7a6c121c3564dd898ecca3de3e..fcb4b25e6fe88d6a8bf6d6f7584ade9bad7ef86c 100644 (file)
@@ -334,7 +334,7 @@ fn trans(&mut self) -> Result<Const<'tcx>, ConstEvalErr<'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 @@ fn const_rvalue(&self, rvalue: &mir::Rvalue<'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)
                             }
                             _ => {
@@ -579,7 +579,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.closure_type(def_id)
+                                let input = tcx.fn_sig(def_id)
                                     .subst(tcx, substs.substs).input(0);
                                 let input = tcx.erase_late_bound_regions_and_normalize(&input);
                                 let substs = tcx.mk_substs([operand.ty, input]
index 61e537c9cc0c9488f5e1e85e5a646a2cd214b6c7..4bd5091a4f35f8069ea4225e58a17a3a07916468 100644 (file)
@@ -180,7 +180,7 @@ pub fn trans_rvalue_operand(&mut self,
                 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))
                             }
index d27eeb2b64667b712d8f1939cae832eb3a828dab..1f6a262162d3950021550cba8a44dce92be8777d 100644 (file)
@@ -40,7 +40,7 @@ fn fn_once_adapter_instance<'a, 'tcx>(
     let self_ty = tcx.mk_closure_from_closure_substs(
         closure_did, substs);
 
-    let sig = tcx.closure_type(closure_did).subst(tcx, substs.substs);
+    let sig = tcx.fn_sig(closure_did).subst(tcx, substs.substs);
     let sig = tcx.erase_late_bound_regions_and_normalize(&sig);
     assert_eq!(sig.inputs().len(), 1);
     let substs = tcx.mk_substs([
@@ -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)
index 0dc2bc85e30e63d4722daf3d5eedf2acb812eb34..f59f6850da103de65ee6f877b7f635c63cbc6e20 100644 (file)
@@ -401,8 +401,9 @@ pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String) {
                         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 ");
                 }
index bdd8169b84fe7ffcdf58726dee2875c8356fb1c2..68726a7b1c4ebe111a7c53f35cf7ca2d63bd0774 100644 (file)
@@ -619,7 +619,7 @@ fn check_pat_tuple_struct(&self,
         // 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);
 
index 385ed7eb0e3842c750999ba88f79f1e0614103ae..a0801a7486654580f86ef2e6a8e5717fba2c6342 100644 (file)
@@ -108,7 +108,7 @@ fn try_overloaded_call_step(&self,
                 // haven't yet decided on whether the closure is fn vs
                 // fnmut vs fnonce. If so, we have to defer further processing.
                 if self.closure_kind(def_id).is_none() {
-                    let closure_ty = self.closure_type(def_id).subst(self.tcx, substs.substs);
+                    let closure_ty = self.fn_sig(def_id).subst(self.tcx, substs.substs);
                     let fn_sig = self.replace_late_bound_regions_with_fresh_var(call_expr.span,
                                                                    infer::FnCall,
                                                                    &closure_ty)
@@ -196,8 +196,8 @@ fn confirm_builtin_call(&self,
                             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 => {
index ea08f1f624e679ca0bfdd6adc84a4e95e3a2d29f..46d304976dc635b11585a36ba061e301b90b9cba 100644 (file)
@@ -356,8 +356,9 @@ fn do_check(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Result<CastKind, CastError>
             (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,
index 30ac7b4bfb9be8d14a4c069e48c6b81184598324..17d02223716827e7fbf3530496abaabdf0fb648a 100644 (file)
@@ -210,13 +210,13 @@ fn coerce(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'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 @@ fn coerce_from_fn_pointer(&self,
 
     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 @@ fn coerce_from_fn_item(&self,
 
         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),
         }
@@ -639,7 +646,7 @@ fn coerce_closure_to_fn(&self,
                 //     `extern "rust-call" fn((arg0,arg1,...)) -> _`
                 // to
                 //     `fn(arg0,arg1,...) -> _`
-                let sig = self.closure_type(def_id_a).subst(self.tcx, substs_a.substs);
+                let sig = self.fn_sig(def_id_a).subst(self.tcx, substs_a.substs);
                 let converted_sig = sig.map_bound(|s| {
                     let params_iter = match s.inputs()[0].sty {
                         ty::TyTuple(params, _) => {
@@ -775,42 +782,41 @@ fn try_find_coercion_lub<E>(&self,
 
         // 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 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));
-                    }
-                }
+        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 lub_ty.is_ok() {
+                // We have a LUB of prev_ty and new_ty, just return it.
+                return lub_ty;
+            }
 
-                // 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);
+            // 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());
index 29742469f84d95d8077c113b0f02df22214bff89..fd5147d76e8fdb72ebed4dbc0c0bac2cfcddce93 100644 (file)
@@ -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<Span>)
                                                 -> 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 {
index 1b6f96cf65137f3fcda3d25d2822d2a4c7986a6f..287c591c1183d5e12f12fb9461b439b5995f6169 100644 (file)
@@ -143,12 +143,7 @@ fn get_best_match(&self, methods: &[AssociatedItem]) -> Vec<String> {
     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,
         }
index 4d9f50b0fc0c94d6e925c9f94a282a671454ac30..3acfbd1d844038183f92c32ea1b24433e353ed4d 100644 (file)
@@ -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,
index 36bd665738951ff3c29a47871b72be393771ea83..209245187b13fd8bdc4903f266af7ccde2e051c1 100644 (file)
@@ -375,7 +375,7 @@ fn instantiate_method_sig(&mut self,
 
         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.
index 73c1215f275fbd8612ba0dbdab7ce4b47cc7be49..4f4169ac93d1b3d98027be9149eb20a868ef72b0 100644 (file)
@@ -235,7 +235,7 @@ pub fn lookup_method_in_trait(&self,
         // 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;
index 2518a1739f73e69a85cdee096002de109a09fd01..ee9a347ae95111b299c963ebb98a3ce554fae271 100644 (file)
@@ -673,7 +673,7 @@ pub fn matches_return_type(&self, method: &ty::AssociatedItem,
                                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 @@ fn xform_method_self_ty(&self,
                             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,
index 2bf24d5b3504c534942e943d13cb2352fefe02bb..701de029b2bd5362bf9941574246d416eb3ab70d 100644 (file)
@@ -718,20 +718,12 @@ pub fn provide(providers: &mut Providers) {
         typeck_item_bodies,
         typeck_tables_of,
         has_typeck_tables,
-        closure_type,
         closure_kind,
         adt_destructor,
         ..*providers
     };
 }
 
-fn closure_type<'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 @@ fn make_overloaded_lvalue_return_type(&self,
                                           -> 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 @@ fn variadic_error<'tcx>(s: &Session, span: Span, t: Ty<'tcx>, cast_ty: &str) {
                     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));
                     }
index 26f708e934562ba704458f0c361e4dd7d81eda8f..cbda1227742ca32d5756e27344e204cd02736915 100644 (file)
@@ -177,12 +177,11 @@ fn check_associated_item(&mut self,
                 }
                 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 @@ fn check_trait(&mut self, item: &hir::Item) {
     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 @@ fn check_method_receiver<'fcx, 'tcx>(&mut self,
 
         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);
 
index fb3bcd31e21fcbaffe0dbcf0bca3cd3a9a34f315..fd6dda5ccf4a72e9c81be10c6bef8beec7c4f7ca 100644 (file)
@@ -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<ty::TraitRef<'tcx>> {
@@ -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>,
index b2fa2cc7c61d2524f98696fa025c412d174091df..bf5adc8644d516af15cf2cb71c802e7c9d7d28c2 100644 (file)
@@ -4736,4 +4736,5 @@ fn i_am_a_function() {}
     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
 }
index 9e99af633d517579ee64c07c23de9745a1e95f6c..519e1ca6e5a3c31a34d81c4a47427c6f387cacb1 100644 (file)
@@ -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,
index c434edb1c31ab38c595c47559a54d2cba187db45..f4963619370e41ef2b1cc8f6e746b00596f62ace 100644 (file)
 //! We walk the set of items and, for each member, generate new constraints.
 
 use hir::def_id::DefId;
-use middle::resolve_lifetime as rl;
 use rustc::dep_graph::{AssertDepGraphSafe, DepKind};
 use rustc::ty::subst::Substs;
 use rustc::ty::{self, Ty, TyCtxt};
-use rustc::hir::map as hir_map;
 use syntax::ast;
 use rustc::hir;
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
@@ -61,10 +59,10 @@ pub struct Constraint<'a> {
 ///     }
 ///
 /// then while we are visiting `Bar<T>`, the `CurrentItem` would have
-/// the def-id and generics of `Foo`.
-pub struct CurrentItem<'a> {
+/// the def-id and the start of `Foo`'s inferreds.
+pub struct CurrentItem {
     def_id: DefId,
-    generics: &'a ty::Generics,
+    inferred_start: InferredIndex,
 }
 
 pub fn add_constraints_from_crate<'a, 'tcx>(terms_cx: TermsContext<'a, 'tcx>)
@@ -91,8 +89,59 @@ pub fn add_constraints_from_crate<'a, 'tcx>(terms_cx: TermsContext<'a, 'tcx>)
 
 impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> {
     fn visit_item(&mut self, item: &hir::Item) {
+        match item.node {
+            hir::ItemStruct(ref struct_def, _) |
+            hir::ItemUnion(ref struct_def, _) => {
+                self.visit_node_helper(item.id);
+
+                if let hir::VariantData::Tuple(..) = *struct_def {
+                    self.visit_node_helper(struct_def.id());
+                }
+            }
+
+            hir::ItemEnum(ref enum_def, _) => {
+                self.visit_node_helper(item.id);
+
+                for variant in &enum_def.variants {
+                    if let hir::VariantData::Tuple(..) = variant.node.data {
+                        self.visit_node_helper(variant.node.data.id());
+                    }
+                }
+            }
+
+            hir::ItemFn(..) => {
+                self.visit_node_helper(item.id);
+            }
+
+            hir::ItemForeignMod(ref foreign_mod) => {
+                for foreign_item in &foreign_mod.items {
+                    if let hir::ForeignItemFn(..) = foreign_item.node {
+                        self.visit_node_helper(foreign_item.id);
+                    }
+                }
+            }
+
+            _ => {}
+        }
+    }
+
+    fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) {
+        if let hir::TraitItemKind::Method(..) = trait_item.node {
+            self.visit_node_helper(trait_item.id);
+        }
+    }
+
+    fn visit_impl_item(&mut self, impl_item: &hir::ImplItem) {
+        if let hir::ImplItemKind::Method(..) = impl_item.node {
+            self.visit_node_helper(impl_item.id);
+        }
+    }
+}
+
+impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
+    fn visit_node_helper(&mut self, id: ast::NodeId) {
         let tcx = self.terms_cx.tcx;
-        let def_id = tcx.hir.local_def_id(item.id);
+        let def_id = tcx.hir.local_def_id(id);
 
         // Encapsulate constructing the constraints into a task we can
         // reference later. This can go away once the red-green
@@ -100,20 +149,11 @@ fn visit_item(&mut self, item: &hir::Item) {
         //
         // See README.md for a detailed discussion
         // on dep-graph management.
-        match item.node {
-            hir::ItemEnum(..) |
-            hir::ItemStruct(..) |
-            hir::ItemUnion(..) => {
-                let dep_node = def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints);
-                tcx.dep_graph.with_task(dep_node,
-                                        AssertDepGraphSafe(self),
-                                        def_id,
-                                        visit_item_task);
-            }
-            _ => {
-                // Nothing to do here, skip the task.
-            }
-        }
+        let dep_node = def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints);
+        tcx.dep_graph.with_task(dep_node,
+                                AssertDepGraphSafe(self),
+                                def_id,
+                                visit_item_task);
 
         fn visit_item_task<'a, 'tcx>(ccx: AssertDepGraphSafe<&mut ConstraintContext<'a, 'tcx>>,
                                      def_id: DefId)
@@ -122,197 +162,57 @@ fn visit_item_task<'a, 'tcx>(ccx: AssertDepGraphSafe<&mut ConstraintContext<'a,
         }
     }
 
-    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
-    }
-
-    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
-    }
-}
-
-/// Is `param_id` a lifetime according to `map`?
-fn is_lifetime(map: &hir_map::Map, param_id: ast::NodeId) -> bool {
-    match map.find(param_id) {
-        Some(hir_map::NodeLifetime(..)) => true,
-        _ => false,
-    }
-}
-
-impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
     fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
         self.terms_cx.tcx
     }
 
     fn build_constraints_for_item(&mut self, def_id: DefId) {
         let tcx = self.tcx();
-        let id = self.tcx().hir.as_local_node_id(def_id).unwrap();
-        let item = tcx.hir.expect_item(id);
-        debug!("visit_item item={}", tcx.hir.node_to_string(item.id));
+        debug!("build_constraints_for_item({})", tcx.item_path_str(def_id));
 
-        match item.node {
-            hir::ItemEnum(..) |
-            hir::ItemStruct(..) |
-            hir::ItemUnion(..) => {
-                let generics = tcx.generics_of(def_id);
-                let current_item = &CurrentItem { def_id, generics };
+        // Skip items with no generics - there's nothing to infer in them.
+        if tcx.generics_of(def_id).count() == 0 {
+            return;
+        }
 
+        let id = tcx.hir.as_local_node_id(def_id).unwrap();
+        let inferred_start = self.terms_cx.inferred_starts[&id];
+        let current_item = &CurrentItem { def_id, inferred_start };
+        match tcx.type_of(def_id).sty {
+            ty::TyAdt(def, _) => {
                 // Not entirely obvious: constraints on structs/enums do not
                 // affect the variance of their type parameters. See discussion
                 // in comment at top of module.
                 //
                 // self.add_constraints_from_generics(generics);
 
-                for field in tcx.adt_def(def_id).all_fields() {
+                for field in def.all_fields() {
                     self.add_constraints_from_ty(current_item,
                                                  tcx.type_of(field.did),
                                                  self.covariant);
                 }
             }
 
-            hir::ItemTrait(..) |
-            hir::ItemExternCrate(_) |
-            hir::ItemUse(..) |
-            hir::ItemStatic(..) |
-            hir::ItemConst(..) |
-            hir::ItemFn(..) |
-            hir::ItemMod(..) |
-            hir::ItemForeignMod(..) |
-            hir::ItemGlobalAsm(..) |
-            hir::ItemTy(..) |
-            hir::ItemImpl(..) |
-            hir::ItemDefaultImpl(..) => {
-                span_bug!(item.span, "`build_constraints_for_item` invoked for non-type-def");
+            ty::TyFnDef(..) => {
+                self.add_constraints_from_sig(current_item,
+                                              tcx.fn_sig(def_id),
+                                              self.covariant);
             }
-        }
-    }
-
-    /// Load the generics for another item, adding a corresponding
-    /// relation into the dependencies to indicate that the variance
-    /// for `current` relies on `def_id`.
-    fn read_generics(&mut self, current: &CurrentItem, def_id: DefId) -> &'tcx ty::Generics {
-        let generics = self.tcx().generics_of(def_id);
-        if self.tcx().dep_graph.is_fully_enabled() {
-            self.dependencies.add(current.def_id, def_id);
-        }
-        generics
-    }
 
-    fn opt_inferred_index(&self, param_id: ast::NodeId) -> Option<&InferredIndex> {
-        self.terms_cx.inferred_map.get(&param_id)
-    }
-
-    fn find_binding_for_lifetime(&self, param_id: ast::NodeId) -> ast::NodeId {
-        let tcx = self.terms_cx.tcx;
-        assert!(is_lifetime(&tcx.hir, param_id));
-        match tcx.named_region_map.defs.get(&param_id) {
-            Some(&rl::Region::EarlyBound(_, lifetime_decl_id)) => lifetime_decl_id,
-            Some(_) => bug!("should not encounter non early-bound cases"),
-
-            // The lookup should only fail when `param_id` is
-            // itself a lifetime binding: use it as the decl_id.
-            None => param_id,
-        }
-
-    }
-
-    /// Is `param_id` a type parameter for which we infer variance?
-    fn is_to_be_inferred(&self, param_id: ast::NodeId) -> bool {
-        let result = self.terms_cx.inferred_map.contains_key(&param_id);
-
-        // To safe-guard against invalid inferred_map constructions,
-        // double-check if variance is inferred at some use of a type
-        // parameter (by inspecting parent of its binding declaration
-        // to see if it is introduced by a type or by a fn/impl).
-
-        let check_result = |this: &ConstraintContext| -> bool {
-            let tcx = this.terms_cx.tcx;
-            let decl_id = this.find_binding_for_lifetime(param_id);
-            // Currently only called on lifetimes; double-checking that.
-            assert!(is_lifetime(&tcx.hir, param_id));
-            let parent_id = tcx.hir.get_parent(decl_id);
-            let parent = tcx.hir
-                .find(parent_id)
-                .unwrap_or_else(|| bug!("tcx.hir missing entry for id: {}", parent_id));
-
-            let is_inferred;
-            macro_rules! cannot_happen { () => { {
-                bug!("invalid parent: {} for {}",
-                     tcx.hir.node_to_string(parent_id),
-                     tcx.hir.node_to_string(param_id));
-            } } }
-
-            match parent {
-                hir_map::NodeItem(p) => {
-                    match p.node {
-                        hir::ItemTy(..) |
-                        hir::ItemEnum(..) |
-                        hir::ItemStruct(..) |
-                        hir::ItemUnion(..) |
-                        hir::ItemTrait(..) => is_inferred = true,
-                        hir::ItemFn(..) => is_inferred = false,
-                        _ => cannot_happen!(),
-                    }
-                }
-                hir_map::NodeTraitItem(..) => is_inferred = false,
-                hir_map::NodeImplItem(..) => is_inferred = false,
-                _ => cannot_happen!(),
-            }
-
-            return is_inferred;
-        };
-
-        assert_eq!(result, check_result(self));
-
-        return result;
-    }
-
-    /// Returns a variance term representing the declared variance of the type/region parameter
-    /// with the given id.
-    fn declared_variance(&self,
-                         param_def_id: DefId,
-                         item_def_id: DefId,
-                         index: usize)
-                         -> VarianceTermPtr<'a> {
-        assert_eq!(param_def_id.krate, item_def_id.krate);
-
-        if let Some(param_node_id) = self.tcx().hir.as_local_node_id(param_def_id) {
-            // Parameter on an item defined within current crate:
-            // variance not yet inferred, so return a symbolic
-            // variance.
-            if let Some(&InferredIndex(index)) = self.opt_inferred_index(param_node_id) {
-                self.terms_cx.inferred_infos[index].term
-            } else {
-                // If there is no inferred entry for a type parameter,
-                // it must be declared on a (locally defiend) trait -- they don't
-                // get inferreds because they are always invariant.
-                if cfg!(debug_assertions) {
-                    let item_node_id = self.tcx().hir.as_local_node_id(item_def_id).unwrap();
-                    let item = self.tcx().hir.expect_item(item_node_id);
-                    let success = match item.node {
-                        hir::ItemTrait(..) => true,
-                        _ => false,
-                    };
-                    if !success {
-                        bug!("parameter {:?} has no inferred, but declared on non-trait: {:?}",
-                             item_def_id,
-                             item);
-                    }
-                }
-                self.invariant
+            _ => {
+                span_bug!(tcx.def_span(def_id),
+                          "`build_constraints_for_item` unsupported for this item");
             }
-        } else {
-            // Parameter on an item defined within another crate:
-            // variance already inferred, just look it up.
-            let variances = self.tcx().variances_of(item_def_id);
-            self.constant_term(variances[index])
         }
     }
 
     fn add_constraint(&mut self,
-                      InferredIndex(index): InferredIndex,
+                      current: &CurrentItem,
+                      index: u32,
                       variance: VarianceTermPtr<'a>) {
         debug!("add_constraint(index={}, variance={:?})", index, variance);
         self.constraints.push(Constraint {
-            inferred: InferredIndex(index),
+            inferred: InferredIndex(current.inferred_start.0 + index as usize),
             variance: variance,
         });
     }
@@ -354,15 +254,26 @@ fn add_constraints_from_trait_ref(&mut self,
         debug!("add_constraints_from_trait_ref: trait_ref={:?} variance={:?}",
                trait_ref,
                variance);
+        self.add_constraints_from_invariant_substs(current, trait_ref.substs, variance);
+    }
 
-        let trait_generics = self.tcx().generics_of(trait_ref.def_id);
+    fn add_constraints_from_invariant_substs(&mut self,
+                                             current: &CurrentItem,
+                                             substs: &Substs<'tcx>,
+                                             variance: VarianceTermPtr<'a>) {
+        debug!("add_constraints_from_invariant_substs: substs={:?} variance={:?}",
+               substs,
+               variance);
 
-        self.add_constraints_from_substs(current,
-                                         trait_ref.def_id,
-                                         &trait_generics.types,
-                                         &trait_generics.regions,
-                                         trait_ref.substs,
-                                         variance);
+        // Trait are always invariant so we can take advantage of that.
+        let variance_i = self.invariant(variance);
+        for ty in substs.types() {
+            self.add_constraints_from_ty(current, ty, variance_i);
+        }
+
+        for region in substs.regions() {
+            self.add_constraints_from_region(current, region, variance_i);
+        }
     }
 
     /// Adds constraints appropriate for an instance of `ty` appearing
@@ -382,8 +293,8 @@ fn add_constraints_from_ty(&mut self,
                 // leaf type -- noop
             }
 
-            ty::TyClosure(..) |
-            ty::TyAnon(..) => {
+            ty::TyFnDef(..) |
+            ty::TyClosure(..) => {
                 bug!("Unexpected closure type in variance computation");
             }
 
@@ -409,26 +320,15 @@ fn add_constraints_from_ty(&mut self,
             }
 
             ty::TyAdt(def, substs) => {
-                let adt_generics = self.read_generics(current, def.did);
-
-                self.add_constraints_from_substs(current,
-                                                 def.did,
-                                                 &adt_generics.types,
-                                                 &adt_generics.regions,
-                                                 substs,
-                                                 variance);
+                self.add_constraints_from_substs(current, def.did, substs, variance);
             }
 
             ty::TyProjection(ref data) => {
-                let trait_ref = &data.trait_ref;
-                let trait_generics = self.tcx().generics_of(trait_ref.def_id);
-
-                self.add_constraints_from_substs(current,
-                                                 trait_ref.def_id,
-                                                 &trait_generics.types,
-                                                 &trait_generics.regions,
-                                                 trait_ref.substs,
-                                                 variance);
+                self.add_constraints_from_trait_ref(current, data.trait_ref, variance);
+            }
+
+            ty::TyAnon(_, substs) => {
+                self.add_constraints_from_invariant_substs(current, substs, variance);
             }
 
             ty::TyDynamic(ref data, r) => {
@@ -447,26 +347,9 @@ fn add_constraints_from_ty(&mut self,
             }
 
             ty::TyParam(ref data) => {
-                assert_eq!(current.generics.parent, None);
-                let mut i = data.idx as usize;
-                if !current.generics.has_self || i > 0 {
-                    i -= current.generics.regions.len();
-                }
-                let def_id = current.generics.types[i].def_id;
-                let node_id = self.tcx().hir.as_local_node_id(def_id).unwrap();
-                match self.terms_cx.inferred_map.get(&node_id) {
-                    Some(&index) => {
-                        self.add_constraint(index, variance);
-                    }
-                    None => {
-                        // We do not infer variance for type parameters
-                        // declared on methods. They will not be present
-                        // in the inferred_map.
-                    }
-                }
+                self.add_constraint(current, data.idx, variance);
             }
 
-            ty::TyFnDef(.., sig) |
             ty::TyFnPtr(sig) => {
                 self.add_constraints_from_sig(current, sig, variance);
             }
@@ -489,8 +372,6 @@ fn add_constraints_from_ty(&mut self,
     fn add_constraints_from_substs(&mut self,
                                    current: &CurrentItem,
                                    def_id: DefId,
-                                   type_param_defs: &[ty::TypeParameterDef],
-                                   region_param_defs: &[ty::RegionParameterDef],
                                    substs: &Substs<'tcx>,
                                    variance: VarianceTermPtr<'a>) {
         debug!("add_constraints_from_substs(def_id={:?}, substs={:?}, variance={:?})",
@@ -498,21 +379,45 @@ fn add_constraints_from_substs(&mut self,
                substs,
                variance);
 
-        for p in type_param_defs {
-            let variance_decl = self.declared_variance(p.def_id, def_id, p.index as usize);
+        // We don't record `inferred_starts` entries for empty generics.
+        if substs.is_empty() {
+            return;
+        }
+
+        // Add a corresponding relation into the dependencies to
+        // indicate that the variance for `current` relies on `def_id`.
+        if self.tcx().dep_graph.is_fully_enabled() {
+            self.dependencies.add(current.def_id, def_id);
+        }
+
+        let (local, remote) = if let Some(id) = self.tcx().hir.as_local_node_id(def_id) {
+            (Some(self.terms_cx.inferred_starts[&id]), None)
+        } else {
+            (None, Some(self.tcx().variances_of(def_id)))
+        };
+
+        for (i, k) in substs.iter().enumerate() {
+            let variance_decl = if let Some(InferredIndex(start)) = local {
+                // Parameter on an item defined within current crate:
+                // variance not yet inferred, so return a symbolic
+                // variance.
+                self.terms_cx.inferred_terms[start + i]
+            } else {
+                // Parameter on an item defined within another crate:
+                // variance already inferred, just look it up.
+                self.constant_term(remote.as_ref().unwrap()[i])
+            };
             let variance_i = self.xform(variance, variance_decl);
-            let substs_ty = substs.type_for_def(p);
             debug!("add_constraints_from_substs: variance_decl={:?} variance_i={:?}",
                    variance_decl,
                    variance_i);
-            self.add_constraints_from_ty(current, substs_ty, variance_i);
-        }
-
-        for p in region_param_defs {
-            let variance_decl = self.declared_variance(p.def_id, def_id, p.index as usize);
-            let variance_i = self.xform(variance, variance_decl);
-            let substs_r = substs.region_for_def(p);
-            self.add_constraints_from_region(current, substs_r, variance_i);
+            if let Some(ty) = k.as_type() {
+                self.add_constraints_from_ty(current, ty, variance_i);
+            } else if let Some(r) = k.as_region() {
+                self.add_constraints_from_region(current, r, variance_i);
+            } else {
+                bug!();
+            }
         }
     }
 
@@ -537,21 +442,14 @@ fn add_constraints_from_region(&mut self,
                                    variance: VarianceTermPtr<'a>) {
         match *region {
             ty::ReEarlyBound(ref data) => {
-                assert_eq!(current.generics.parent, None);
-                let i = data.index as usize - current.generics.has_self as usize;
-                let def_id = current.generics.regions[i].def_id;
-                let node_id = self.tcx().hir.as_local_node_id(def_id).unwrap();
-                if self.is_to_be_inferred(node_id) {
-                    let &index = self.opt_inferred_index(node_id).unwrap();
-                    self.add_constraint(index, variance);
-                }
+                self.add_constraint(current, data.index, variance);
             }
 
             ty::ReStatic => {}
 
             ty::ReLateBound(..) => {
-                // We do not infer variance for region parameters on
-                // methods or in fn types.
+                // Late-bound regions do not get substituted the same
+                // way early-bound regions do, so we skip them here.
             }
 
             ty::ReFree(..) |
index 8f9f40ca40b037ee75e157651546a6a2e14604c7..7a9f35545e2f383defa9c09444aac638c0793c63 100644 (file)
@@ -54,45 +54,63 @@ fn crate_variances<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum)
 
 fn variances_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId)
                             -> Rc<Vec<ty::Variance>> {
-    let item_id = tcx.hir.as_local_node_id(item_def_id).expect("expected local def-id");
-    let item = tcx.hir.expect_item(item_id);
-    match item.node {
-        hir::ItemTrait(..) => {
-            // Traits are always invariant.
-            let generics = tcx.generics_of(item_def_id);
-            assert!(generics.parent.is_none());
-            Rc::new(vec![ty::Variance::Invariant; generics.count()])
-        }
+    let id = tcx.hir.as_local_node_id(item_def_id).expect("expected local def-id");
+    let unsupported = || {
+        // Variance not relevant.
+        span_bug!(tcx.hir.span(id), "asked to compute variance for wrong kind of item")
+    };
+    match tcx.hir.get(id) {
+        hir::map::NodeItem(item) => match item.node {
+            hir::ItemEnum(..) |
+            hir::ItemStruct(..) |
+            hir::ItemUnion(..) |
+            hir::ItemFn(..) => {}
 
-        hir::ItemEnum(..) |
-        hir::ItemStruct(..) |
-        hir::ItemUnion(..) => {
-            // Everything else must be inferred.
+            _ => unsupported()
+        },
 
-            // Lacking red/green, we read the variances for all items here
-            // but ignore the dependencies, then re-synthesize the ones we need.
-            let crate_map = tcx.dep_graph.with_ignore(|| tcx.crate_variances(LOCAL_CRATE));
-            let dep_node = item_def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints);
-            tcx.dep_graph.read(dep_node);
-            for &dep_def_id in crate_map.dependencies.less_than(&item_def_id) {
-                if dep_def_id.is_local() {
-                    let dep_node = dep_def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints);
-                    tcx.dep_graph.read(dep_node);
-                } else {
-                    let dep_node = dep_def_id.to_dep_node(tcx, DepKind::ItemVariances);
-                    tcx.dep_graph.read(dep_node);
-                }
-            }
-
-            crate_map.variances.get(&item_def_id)
-                               .unwrap_or(&crate_map.empty_variance)
-                               .clone()
-        }
+        hir::map::NodeTraitItem(item) => match item.node {
+            hir::TraitItemKind::Method(..) => {}
+
+            _ => unsupported()
+        },
+
+        hir::map::NodeImplItem(item) => match item.node {
+            hir::ImplItemKind::Method(..) => {}
+
+            _ => unsupported()
+        },
+
+        hir::map::NodeForeignItem(item) => match item.node {
+            hir::ForeignItemFn(..) => {}
 
-        _ => {
-            // Variance not relevant.
-            span_bug!(item.span, "asked to compute variance for wrong kind of item")
+            _ => unsupported()
+        },
+
+        hir::map::NodeVariant(_) | hir::map::NodeStructCtor(_) => {}
+
+        _ => unsupported()
+    }
+
+    // Everything else must be inferred.
+
+    // Lacking red/green, we read the variances for all items here
+    // but ignore the dependencies, then re-synthesize the ones we need.
+    let crate_map = tcx.dep_graph.with_ignore(|| tcx.crate_variances(LOCAL_CRATE));
+    let dep_node = item_def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints);
+    tcx.dep_graph.read(dep_node);
+    for &dep_def_id in crate_map.dependencies.less_than(&item_def_id) {
+        if dep_def_id.is_local() {
+            let dep_node = dep_def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints);
+            tcx.dep_graph.read(dep_node);
+        } else {
+            let dep_node = dep_def_id.to_dep_node(tcx, DepKind::ItemVariances);
+            tcx.dep_graph.read(dep_node);
         }
     }
+
+    crate_map.variances.get(&item_def_id)
+                       .unwrap_or(&crate_map.empty_variance)
+                       .clone()
 }
 
index af8ad491ec00e7075ba0a5c3e2a56922bdb30ef5..495eb95419a90876581ef3165507f97373e7c417 100644 (file)
@@ -36,15 +36,18 @@ struct SolveContext<'a, 'tcx: 'a> {
 pub fn solve_constraints(constraints_cx: ConstraintContext) -> ty::CrateVariancesMap {
     let ConstraintContext { terms_cx, dependencies, constraints, .. } = constraints_cx;
 
-    let solutions = terms_cx.inferred_infos
-        .iter()
-        .map(|ii| ii.initial_variance)
-        .collect();
+    let mut solutions = vec![ty::Bivariant; terms_cx.inferred_terms.len()];
+    for &(id, ref variances) in &terms_cx.lang_items {
+        let InferredIndex(start) = terms_cx.inferred_starts[&id];
+        for (i, &variance) in variances.iter().enumerate() {
+            solutions[start + i] = variance;
+        }
+    }
 
     let mut solutions_cx = SolveContext {
-        terms_cx: terms_cx,
-        constraints: constraints,
-        solutions: solutions,
+        terms_cx,
+        constraints,
+        solutions,
     };
     solutions_cx.solve();
     let variances = solutions_cx.create_map();
@@ -71,12 +74,9 @@ fn solve(&mut self) {
                 let old_value = self.solutions[inferred];
                 let new_value = glb(variance, old_value);
                 if old_value != new_value {
-                    debug!("Updating inferred {} (node {}) \
+                    debug!("Updating inferred {} \
                             from {:?} to {:?} due to {:?}",
                            inferred,
-                           self.terms_cx
-                                   .inferred_infos[inferred]
-                               .param_id,
                            old_value,
                            new_value,
                            term);
@@ -89,49 +89,28 @@ fn solve(&mut self) {
     }
 
     fn create_map(&self) -> FxHashMap<DefId, Rc<Vec<ty::Variance>>> {
-        // Collect all the variances for a particular item and stick
-        // them into the variance map. We rely on the fact that we
-        // generate all the inferreds for a particular item
-        // consecutively (that is, we collect solutions for an item
-        // until we see a new item id, and we assume (1) the solutions
-        // are in the same order as the type parameters were declared
-        // and (2) all solutions or a given item appear before a new
-        // item id).
-
         let tcx = self.terms_cx.tcx;
 
-        let mut map = FxHashMap();
-
         let solutions = &self.solutions;
-        let inferred_infos = &self.terms_cx.inferred_infos;
-        let mut index = 0;
-        let num_inferred = self.terms_cx.num_inferred();
-        while index < num_inferred {
-            let item_id = inferred_infos[index].item_id;
-
-            let mut item_variances = vec![];
-
-            while index < num_inferred && inferred_infos[index].item_id == item_id {
-                let info = &inferred_infos[index];
-                let variance = solutions[index];
-                debug!("Index {} Info {} Variance {:?}",
-                       index,
-                       info.index,
-                       variance);
-
-                assert_eq!(item_variances.len(), info.index);
-                item_variances.push(variance);
-                index += 1;
-            }
+        self.terms_cx.inferred_starts.iter().map(|(&id, &InferredIndex(start))| {
+            let def_id = tcx.hir.local_def_id(id);
+            let generics = tcx.generics_of(def_id);
 
-            debug!("item_id={} item_variances={:?}", item_id, item_variances);
+            let mut variances = solutions[start..start+generics.count()].to_vec();
 
-            let item_def_id = tcx.hir.local_def_id(item_id);
+            debug!("id={} variances={:?}", id, variances);
 
-            map.insert(item_def_id, Rc::new(item_variances));
-        }
+            // Functions can have unused type parameters: make those invariant.
+            if let ty::TyFnDef(..) = tcx.type_of(def_id).sty {
+                for variance in &mut variances {
+                    if *variance == ty::Bivariant {
+                        *variance = ty::Invariant;
+                    }
+                }
+            }
 
-        map
+            (def_id, Rc::new(variances))
+        }).collect()
     }
 
     fn evaluate(&self, term: VarianceTermPtr<'a>) -> ty::Variance {
index ad787c57e76f2a60ee49739eef874e17c4ae5665..38457146a9714deebfa958aafa42959bed515e39 100644 (file)
@@ -22,7 +22,6 @@
 use arena::TypedArena;
 use rustc::ty::{self, TyCtxt};
 use std::fmt;
-use std::rc::Rc;
 use syntax::ast;
 use rustc::hir;
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
@@ -63,31 +62,17 @@ pub struct TermsContext<'a, 'tcx: 'a> {
     pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
     pub arena: &'a TypedArena<VarianceTerm<'a>>,
 
-    pub empty_variances: Rc<Vec<ty::Variance>>,
-
     // For marker types, UnsafeCell, and other lang items where
     // variance is hardcoded, records the item-id and the hardcoded
     // variance.
     pub lang_items: Vec<(ast::NodeId, Vec<ty::Variance>)>,
 
-    // Maps from the node id of a type/generic parameter to the
-    // corresponding inferred index.
-    pub inferred_map: NodeMap<InferredIndex>,
-
-    // Maps from an InferredIndex to the info for that variable.
-    pub inferred_infos: Vec<InferredInfo<'a>>,
-}
-
-pub struct InferredInfo<'a> {
-    pub item_id: ast::NodeId,
-    pub index: usize,
-    pub param_id: ast::NodeId,
-    pub term: VarianceTermPtr<'a>,
+    // Maps from the node id of an item to the first inferred index
+    // used for its type & region parameters.
+    pub inferred_starts: NodeMap<InferredIndex>,
 
-    // Initial value to use for this parameter when inferring
-    // variance. For most parameters, this is Bivariant. But for lang
-    // items and input type parameters on traits, it is different.
-    pub initial_variance: ty::Variance,
+    // Maps from an InferredIndex to the term for that variable.
+    pub inferred_terms: Vec<VarianceTermPtr<'a>>,
 }
 
 pub fn determine_parameters_to_be_inferred<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -96,14 +81,10 @@ pub fn determine_parameters_to_be_inferred<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>
     let mut terms_cx = TermsContext {
         tcx: tcx,
         arena: arena,
-        inferred_map: NodeMap(),
-        inferred_infos: Vec::new(),
+        inferred_starts: NodeMap(),
+        inferred_terms: vec![],
 
         lang_items: lang_items(tcx),
-
-        // cache and share the variance struct used for items with
-        // no type/region parameters
-        empty_variances: Rc::new(vec![]),
     };
 
     // See README.md for a discussion on dep-graph management.
@@ -135,67 +116,28 @@ fn lang_items(tcx: TyCtxt) -> Vec<(ast::NodeId, Vec<ty::Variance>)> {
 }
 
 impl<'a, 'tcx> TermsContext<'a, 'tcx> {
-    fn add_inferreds_for_item(&mut self,
-                              item_id: ast::NodeId,
-                              generics: &hir::Generics) {
-        //! Add "inferreds" for the generic parameters declared on this
-        //! item. This has a lot of annoying parameters because we are
-        //! trying to drive this from the AST, rather than the
-        //! ty::Generics, so that we can get span info -- but this
-        //! means we must accommodate syntactic distinctions.
-        //!
+    fn add_inferreds_for_item(&mut self, id: ast::NodeId) {
+        let tcx = self.tcx;
+        let def_id = tcx.hir.local_def_id(id);
+        let count = tcx.generics_of(def_id).count();
 
-        // NB: In the code below for writing the results back into the
-        // `CrateVariancesMap`, we rely on the fact that all inferreds
-        // for a particular item are assigned continuous indices.
-
-        for (p, i) in generics.lifetimes.iter().zip(0..) {
-            let id = p.lifetime.id;
-            self.add_inferred(item_id, i, id);
-        }
-
-        for (p, i) in generics.ty_params.iter().zip(generics.lifetimes.len()..) {
-            self.add_inferred(item_id, i, p.id);
+        if count == 0 {
+            return;
         }
-    }
 
-    fn add_inferred(&mut self, item_id: ast::NodeId, index: usize, param_id: ast::NodeId) {
-        let inf_index = InferredIndex(self.inferred_infos.len());
-        let term = self.arena.alloc(InferredTerm(inf_index));
-        let initial_variance = self.pick_initial_variance(item_id, index);
-        self.inferred_infos.push(InferredInfo {
-            item_id: item_id,
-            index: index,
-            param_id: param_id,
-            term: term,
-            initial_variance: initial_variance,
-        });
-        let newly_added = self.inferred_map.insert(param_id, inf_index).is_none();
+        // Record the start of this item's inferreds.
+        let start = self.inferred_terms.len();
+        let newly_added = self.inferred_starts.insert(id, InferredIndex(start)).is_none();
         assert!(newly_added);
 
-        debug!("add_inferred(item_path={}, \
-                item_id={}, \
-                index={}, \
-                param_id={}, \
-                inf_index={:?}, \
-                initial_variance={:?})",
-               self.tcx.item_path_str(self.tcx.hir.local_def_id(item_id)),
-               item_id,
-               index,
-               param_id,
-               inf_index,
-               initial_variance);
-    }
-
-    fn pick_initial_variance(&self, item_id: ast::NodeId, index: usize) -> ty::Variance {
-        match self.lang_items.iter().find(|&&(n, _)| n == item_id) {
-            Some(&(_, ref variances)) => variances[index],
-            None => ty::Bivariant,
-        }
-    }
+        // NB: In the code below for writing the results back into the
+        // `CrateVariancesMap`, we rely on the fact that all inferreds
+        // for a particular item are assigned continuous indices.
 
-    pub fn num_inferred(&self) -> usize {
-        self.inferred_infos.len()
+        let arena = self.arena;
+        self.inferred_terms.extend((start..start+count).map(|i| {
+            &*arena.alloc(InferredTerm(InferredIndex(i)))
+        }));
     }
 }
 
@@ -205,30 +147,50 @@ fn visit_item(&mut self, item: &hir::Item) {
                self.tcx.hir.node_to_string(item.id));
 
         match item.node {
-            hir::ItemEnum(_, ref generics) |
-            hir::ItemStruct(_, ref generics) |
-            hir::ItemUnion(_, ref generics) => {
-                self.add_inferreds_for_item(item.id, generics);
+            hir::ItemStruct(ref struct_def, _) |
+            hir::ItemUnion(ref struct_def, _) => {
+                self.add_inferreds_for_item(item.id);
+
+                if let hir::VariantData::Tuple(..) = *struct_def {
+                    self.add_inferreds_for_item(struct_def.id());
+                }
+            }
+
+            hir::ItemEnum(ref enum_def, _) => {
+                self.add_inferreds_for_item(item.id);
+
+                for variant in &enum_def.variants {
+                    if let hir::VariantData::Tuple(..) = variant.node.data {
+                        self.add_inferreds_for_item(variant.node.data.id());
+                    }
+                }
+            }
+
+            hir::ItemFn(..) => {
+                self.add_inferreds_for_item(item.id);
             }
 
-            hir::ItemTrait(..) |
-            hir::ItemExternCrate(_) |
-            hir::ItemUse(..) |
-            hir::ItemDefaultImpl(..) |
-            hir::ItemImpl(..) |
-            hir::ItemStatic(..) |
-            hir::ItemConst(..) |
-            hir::ItemFn(..) |
-            hir::ItemMod(..) |
-            hir::ItemForeignMod(..) |
-            hir::ItemGlobalAsm(..) |
-            hir::ItemTy(..) => {}
+            hir::ItemForeignMod(ref foreign_mod) => {
+                for foreign_item in &foreign_mod.items {
+                    if let hir::ForeignItemFn(..) = foreign_item.node {
+                        self.add_inferreds_for_item(foreign_item.id);
+                    }
+                }
+            }
+
+            _ => {}
         }
     }
 
-    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+    fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) {
+        if let hir::TraitItemKind::Method(..) = trait_item.node {
+            self.add_inferreds_for_item(trait_item.id);
+        }
     }
 
-    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
+    fn visit_impl_item(&mut self, impl_item: &hir::ImplItem) {
+        if let hir::ImplItemKind::Method(..) = impl_item.node {
+            self.add_inferreds_for_item(impl_item.id);
+        }
     }
 }
index aeade47048223bef2b88e0c0a5781f789f50f646..fa5a999adf1960c00dfb57d52365d19397d25a79 100644 (file)
@@ -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
index 8fc8ccd0cfd92eba6b8f7a0ae2258494fb9dc558..478e2fc5085d19fe8dba0e3fcc7ea6ac6d30e777 100644 (file)
@@ -1367,7 +1367,7 @@ fn clean(&self, cx: &DocContext) -> Item {
             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 @@ fn clean(&self, cx: &DocContext) -> Type {
                 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() {
index 6134b0b882c5bb80c133ee57b3cbd165294b3451..7d79fb078116f568cd6124af01b6beac93108c97 100644 (file)
@@ -363,39 +363,29 @@ pub fn abs(self) -> f32 { num::Float::abs(self) }
     #[inline]
     pub fn signum(self) -> f32 { num::Float::signum(self) }
 
-    /// Returns `true` if `self`'s sign bit is positive, including
-    /// `+0.0` and `INFINITY`.
+    /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
+    /// positive sign bit and positive infinity.
     ///
     /// ```
-    /// use std::f32;
-    ///
-    /// let nan = f32::NAN;
     /// let f = 7.0_f32;
     /// let g = -7.0_f32;
     ///
     /// assert!(f.is_sign_positive());
     /// assert!(!g.is_sign_positive());
-    /// // Requires both tests to determine if is `NaN`
-    /// assert!(!nan.is_sign_positive() && !nan.is_sign_negative());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn is_sign_positive(self) -> bool { num::Float::is_sign_positive(self) }
 
-    /// Returns `true` if `self`'s sign is negative, including `-0.0`
-    /// and `NEG_INFINITY`.
+    /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
+    /// negative sign bit and negative infinity.
     ///
     /// ```
-    /// use std::f32;
-    ///
-    /// let nan = f32::NAN;
     /// let f = 7.0f32;
     /// let g = -7.0f32;
     ///
     /// assert!(!f.is_sign_negative());
     /// assert!(g.is_sign_negative());
-    /// // Requires both tests to determine if is `NaN`.
-    /// assert!(!nan.is_sign_positive() && !nan.is_sign_negative());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -1184,7 +1174,7 @@ fn test_nan() {
         assert!(!nan.is_infinite());
         assert!(!nan.is_finite());
         assert!(!nan.is_normal());
-        assert!(!nan.is_sign_positive());
+        assert!(nan.is_sign_positive());
         assert!(!nan.is_sign_negative());
         assert_eq!(Fp::Nan, nan.classify());
     }
@@ -1428,7 +1418,8 @@ fn test_is_sign_positive() {
         assert!(!(-1f32).is_sign_positive());
         assert!(!NEG_INFINITY.is_sign_positive());
         assert!(!(1f32/NEG_INFINITY).is_sign_positive());
-        assert!(!NAN.is_sign_positive());
+        assert!(NAN.is_sign_positive());
+        assert!(!(-NAN).is_sign_positive());
     }
 
     #[test]
@@ -1441,6 +1432,7 @@ fn test_is_sign_negative() {
         assert!(NEG_INFINITY.is_sign_negative());
         assert!((1f32/NEG_INFINITY).is_sign_negative());
         assert!(!NAN.is_sign_negative());
+        assert!((-NAN).is_sign_negative());
     }
 
     #[test]
index e8d25cfbf949a93c9f9ac81216d3ee16133be22f..d5b0cd3a1fc796b5493cfab84ce3adaadecfbaf7 100644 (file)
@@ -301,21 +301,15 @@ pub fn abs(self) -> f64 { num::Float::abs(self) }
     #[inline]
     pub fn signum(self) -> f64 { num::Float::signum(self) }
 
-    /// Returns `true` if `self`'s sign bit is positive, including
-    /// `+0.0` and `INFINITY`.
+    /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
+    /// positive sign bit and positive infinity.
     ///
     /// ```
-    /// use std::f64;
-    ///
-    /// let nan: f64 = f64::NAN;
-    ///
     /// let f = 7.0_f64;
     /// let g = -7.0_f64;
     ///
     /// assert!(f.is_sign_positive());
     /// assert!(!g.is_sign_positive());
-    /// // Requires both tests to determine if is `NaN`
-    /// assert!(!nan.is_sign_positive() && !nan.is_sign_negative());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -326,21 +320,15 @@ pub fn is_sign_positive(self) -> bool { num::Float::is_sign_positive(self) }
     #[inline]
     pub fn is_positive(self) -> bool { num::Float::is_sign_positive(self) }
 
-    /// Returns `true` if `self`'s sign is negative, including `-0.0`
-    /// and `NEG_INFINITY`.
+    /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
+    /// negative sign bit and negative infinity.
     ///
     /// ```
-    /// use std::f64;
-    ///
-    /// let nan = f64::NAN;
-    ///
     /// let f = 7.0_f64;
     /// let g = -7.0_f64;
     ///
     /// assert!(!f.is_sign_negative());
     /// assert!(g.is_sign_negative());
-    /// // Requires both tests to determine if is `NaN`.
-    /// assert!(!nan.is_sign_positive() && !nan.is_sign_negative());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -1101,7 +1089,7 @@ fn test_nan() {
         assert!(!nan.is_infinite());
         assert!(!nan.is_finite());
         assert!(!nan.is_normal());
-        assert!(!nan.is_sign_positive());
+        assert!(nan.is_sign_positive());
         assert!(!nan.is_sign_negative());
         assert_eq!(Fp::Nan, nan.classify());
     }
@@ -1347,7 +1335,8 @@ fn test_is_sign_positive() {
         assert!(!(-1f64).is_sign_positive());
         assert!(!NEG_INFINITY.is_sign_positive());
         assert!(!(1f64/NEG_INFINITY).is_sign_positive());
-        assert!(!NAN.is_sign_positive());
+        assert!(NAN.is_sign_positive());
+        assert!(!(-NAN).is_sign_positive());
     }
 
     #[test]
@@ -1360,6 +1349,7 @@ fn test_is_sign_negative() {
         assert!(NEG_INFINITY.is_sign_negative());
         assert!((1f64/NEG_INFINITY).is_sign_negative());
         assert!(!NAN.is_sign_negative());
+        assert!((-NAN).is_sign_negative());
     }
 
     #[test]
index 1993d6ebe5b493fc778e74c0455301da599da3b3..35a2a2513f4e250264e2e8642bb18c8e9b2bc5ce 100644 (file)
@@ -167,7 +167,7 @@ fn cs_clone(name: &str,
             all_fields = af;
             vdata = vdata_;
         }
-        EnumMatching(_, variant, ref af) => {
+        EnumMatching(.., variant, ref af) => {
             ctor_path = cx.path(trait_span, vec![substr.type_ident, variant.node.name]);
             all_fields = af;
             vdata = &variant.node.data;
index ec4cb815960d1b6b35ca03f4eec966b90e384819..38ed596098b2123e83618ca7b296c0e137ccb250 100644 (file)
@@ -60,7 +60,7 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<E
     // based on the "shape".
     let (ident, is_struct) = match *substr.fields {
         Struct(vdata, _) => (substr.type_ident, vdata.is_struct()),
-        EnumMatching(_, v, _) => (v.node.name, v.node.data.is_struct()),
+        EnumMatching(_, _, v, _) => (v.node.name, v.node.data.is_struct()),
         EnumNonMatchingCollapsed(..) |
         StaticStruct(..) |
         StaticEnum(..) => cx.span_bug(span, "nonsensical .fields in `#[derive(Debug)]`"),
index 33f742282c1726a95e12818a69d3000a6b989272..1e19cd994192e15a9b3ef634ebcfbde63122b35d 100644 (file)
@@ -237,7 +237,7 @@ fn encodable_substructure(cx: &mut ExtCtxt,
                                      blk])
         }
 
-        EnumMatching(idx, variant, ref fields) => {
+        EnumMatching(idx, _, variant, ref fields) => {
             // We're not generating an AST that the borrow checker is expecting,
             // so we need to generate a unique local variable to take the
             // mutable loan out on, otherwise we get conflicts which don't
index 3a15b82d19f691de1e974a87f152c57700d21fbc..4acd65bbf8652cd0f1c216463b1fc6fff982240c 100644 (file)
@@ -305,10 +305,10 @@ pub enum StaticFields {
 /// A summary of the possible sets of fields.
 pub enum SubstructureFields<'a> {
     Struct(&'a ast::VariantData, Vec<FieldInfo<'a>>),
-    /// Matching variants of the enum: variant index, ast::Variant,
+    /// Matching variants of the enum: variant index, variant count, ast::Variant,
     /// fields: the field name is only non-`None` in the case of a struct
     /// variant.
-    EnumMatching(usize, &'a ast::Variant, Vec<FieldInfo<'a>>),
+    EnumMatching(usize, usize, &'a ast::Variant, Vec<FieldInfo<'a>>),
 
     /// Non-matching variants of the enum, but with all state hidden from
     /// the consequent code.  The first component holds `Ident`s for all of
@@ -1252,7 +1252,7 @@ fn build_enum_match_tuple<'b>(&self,
                 // expressions for referencing every field of every
                 // Self arg, assuming all are instances of VariantK.
                 // Build up code associated with such a case.
-                let substructure = EnumMatching(index, variant, field_tuples);
+                let substructure = EnumMatching(index, variants.len(), variant, field_tuples);
                 let arm_expr = self.call_substructure_method(cx,
                                                              trait_,
                                                              type_ident,
@@ -1269,12 +1269,13 @@ fn build_enum_match_tuple<'b>(&self,
                 // We need a default case that handles the fieldless variants.
                 // The index and actual variant aren't meaningful in this case,
                 // so just use whatever
+                let substructure = EnumMatching(0, variants.len(), v, Vec::new());
                 Some(self.call_substructure_method(cx,
                                                    trait_,
                                                    type_ident,
                                                    &self_args[..],
                                                    nonself_args,
-                                                   &EnumMatching(0, v, Vec::new())))
+                                                   &substructure))
             }
             _ if variants.len() > 1 && self_args.len() > 1 => {
                 // Since we know that all the arguments will match if we reach
index 97d7f2ce8003ea8c77481da3104e4647a773b0c1..a341c21d0a126cbc5667a74fd58e7358c6a10993 100644 (file)
@@ -81,7 +81,7 @@ fn hash_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure)
     let mut stmts = Vec::new();
 
     let fields = match *substr.fields {
-        Struct(_, ref fs) => fs,
+        Struct(_, ref fs) | EnumMatching(_, 1, .., ref fs) => fs,
         EnumMatching(.., ref fs) => {
             let variant_value = deriving::call_intrinsic(cx,
                                                          trait_span,
index cdb7dff692c146dd6fb762c4c1cdcba8b970946b..d62f6b0f1a37140aa870e30cbcc5313533396926 100644 (file)
@@ -38,11 +38,13 @@ pub fn f1_int_uint() {
 pub fn f1_uint_uint() {
     f1(2u32, 4u32);
     //~^ ERROR `u32: Foo` is not satisfied
+    //~| ERROR `u32: Foo` is not satisfied
 }
 
 pub fn f1_uint_int() {
     f1(2u32, 4i32);
     //~^ ERROR `u32: Foo` is not satisfied
+    //~| ERROR `u32: Foo` is not satisfied
 }
 
 pub fn f2_int() {
index 2aa2546cb9fe124b0ca324be16ed9c3e430193df..c42d78c323e3ce643d1fff53e2afeec0e130b131 100644 (file)
@@ -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(); } }
index 0df8c41ffe1a8e52ae7fa2f710305af478c78348..15375936b898c80de754ba8191984790bda0e5e4 100644 (file)
@@ -44,12 +44,18 @@ fn main() {
     //~^ ERROR E0277
     //~| NOTE trait message
     //~| NOTE required by
+    //~| ERROR E0277
+    //~| NOTE trait message
     Index::index(&[] as &[i32], Foo(2u32));
     //~^ ERROR E0277
     //~| NOTE on impl for Foo
     //~| NOTE required by
+    //~| ERROR E0277
+    //~| NOTE on impl for Foo
     Index::index(&[] as &[i32], Bar(2u32));
     //~^ ERROR E0277
     //~| NOTE on impl for Bar
     //~| NOTE required by
+    //~| ERROR E0277
+    //~| NOTE on impl for Bar
 }
index 79021cd03ccc13e6fa12f35d6f1ab23c28338252..66d612baab4e8648b80a6275cf9c318e8aba0988 100644 (file)
@@ -33,4 +33,6 @@ fn main() {
     //~^ ERROR E0277
     //~| NOTE a usize is required
     //~| NOTE required by
+    //~| ERROR E0277
+    //~| NOTE a usize is required
 }
diff --git a/src/test/compile-fail/variance-region-bounds.rs b/src/test/compile-fail/variance-region-bounds.rs
deleted file mode 100644 (file)
index 41d204a..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Check that `T:'a` is contravariant in T.
-
-#![feature(rustc_attrs)]
-
-#[rustc_variance]
-trait Foo: 'static { //~ ERROR [o]
-}
-
-#[rustc_variance]
-trait Bar<T> { //~ ERROR [o, o]
-    fn do_it(&self)
-        where T: 'static;
-}
-
-fn main() { }
index 58fb785c48ca7b24a70c92e2cd5c9e897b6c9230..9b88e38e085546feb68ef1435e7aa7a66334b182 100644 (file)
 // Check that bounds on type parameters (other than `Self`) do not
 // influence variance.
 
-#[rustc_variance]
-trait Getter<T> { //~ ERROR [o, o]
+trait Getter<T> {
     fn get(&self) -> T;
 }
 
-#[rustc_variance]
-trait Setter<T> { //~ ERROR [o, o]
+trait Setter<T> {
     fn get(&self, T);
 }
 
@@ -34,20 +32,6 @@ enum TestEnum<U,T:Setter<U>> { //~ ERROR [*, +]
     Foo(T)
 }
 
-#[rustc_variance]
-trait TestTrait<U,T:Setter<U>> { //~ ERROR [o, o, o]
-    fn getter(&self, u: U) -> T;
-}
-
-#[rustc_variance]
-trait TestTrait2<U> : Getter<U> { //~ ERROR [o, o]
-}
-
-#[rustc_variance]
-trait TestTrait3<U> { //~ ERROR [o, o]
-    fn getter<T:Getter<U>>(&self);
-}
-
 #[rustc_variance]
 struct TestContraStruct<U,T:Setter<U>> { //~ ERROR [*, +]
     t: T
index 2df94cc907a9cf88517497712bb4218e90caca3b..5075dd2ceedc093ba972f70c5d952e6332bdc508 100644 (file)
@@ -36,37 +36,14 @@ struct TestIndirect2<A:'static, B:'static> { //~ ERROR [o, o]
     m: TestMut<B, A>
 }
 
-#[rustc_variance]
-trait Getter<A> { //~ ERROR [o, o]
+trait Getter<A> {
     fn get(&self) -> A;
 }
 
-#[rustc_variance]
-trait Setter<A> { //~ ERROR [o, o]
-    fn set(&mut self, a: A);
-}
-
-#[rustc_variance]
-trait GetterSetter<A> { //~ ERROR [o, o]
-    fn get(&self) -> A;
+trait Setter<A> {
     fn set(&mut self, a: A);
 }
 
-#[rustc_variance]
-trait GetterInTypeBound<A> { //~ ERROR [o, o]
-    // Here, the use of `A` in the method bound *does* affect
-    // variance.  Think of it as if the method requested a dictionary
-    // for `T:Getter<A>`.  Since this dictionary is an input, it is
-    // contravariant, and the Getter is covariant w/r/t A, yielding an
-    // overall contravariant result.
-    fn do_it<T:Getter<A>>(&self);
-}
-
-#[rustc_variance]
-trait SetterInTypeBound<A> { //~ ERROR [o, o]
-    fn do_it<T:Setter<A>>(&self);
-}
-
 #[rustc_variance]
 struct TestObject<A, R> { //~ ERROR [o, o]
     n: Box<Setter<A>+Send>,
index 91bfc2f9201b7796cbf713117c3e6618b295ffb3..18b2fbe015b425ee89c4c4cb87242fbf975a022a 100644 (file)
@@ -45,8 +45,8 @@ fn write(&mut self, bytes: &[u8]) {
     }
 }
 
-fn fake_hash(v: &mut Vec<u8>, e: E) {
-    e.hash(&mut FakeHasher(v));
+fn fake_hash<A: Hash>(v: &mut Vec<u8>, a: A) {
+    a.hash(&mut FakeHasher(v));
 }
 
 fn main() {
@@ -69,4 +69,13 @@ fn main() {
     fake_hash(&mut va, E::A);
     fake_hash(&mut vb, E::B);
     assert!(va != vb);
+
+    // issue #39137: single variant enum hash should not hash discriminant
+    #[derive(Hash)]
+    enum SingleVariantEnum {
+        A(u8),
+    }
+    let mut v = vec![];
+    fake_hash(&mut v, SingleVariantEnum::A(17));
+    assert_eq!(vec![17], v);
 }