diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs
index f945ba68e8e..ac53bdbefcf 100644
--- a/src/librustc/middle/check_const.rs
+++ b/src/librustc/middle/check_const.rs
@@ -111,20 +111,11 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) {
                            expression");
             }
         }
-        ast::ExprPath(ref pth) => {
-            // NB: In the future you might wish to relax this slightly
-            // to handle on-demand instantiation of functions via
-            // foo::<bar> in a const. Currently that is only done on
-            // a path in trans::callee that only works in block contexts.
-            if !pth.segments.iter().all(|segment| segment.parameters.is_empty()) {
-                span_err!(v.tcx.sess, e.span, E0013,
-                          "paths in constants may only refer to items without \
-                           type parameters");
-            }
+        ast::ExprPath(_) => {
             match v.tcx.def_map.borrow()[e.id] {
                 DefStatic(..) | DefConst(..) |
-                DefFn(..) | DefStruct(_) |
-                DefVariant(_, _, _) => {}
+                DefFn(..) | DefStaticMethod(..) | DefMethod(..) |
+                DefStruct(_) | DefVariant(_, _, _) => {}
 
                 def => {
                     debug!("(checking const) found bad def: {}", def);
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 8325cebf1ed..31c3ca4199f 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -559,14 +559,14 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                id, expr_ty.repr(self.tcx()), def);
 
         match def {
-          def::DefStruct(..) | def::DefVariant(..) | def::DefFn(..) |
-          def::DefStaticMethod(..) | def::DefConst(..) => {
+          def::DefStruct(..) | def::DefVariant(..) | def::DefConst(..) |
+          def::DefFn(..) | def::DefStaticMethod(..) |  def::DefMethod(..) => {
                 Ok(self.cat_rvalue_node(id, span, expr_ty))
           }
           def::DefMod(_) | def::DefForeignMod(_) | def::DefUse(_) |
           def::DefTrait(_) | def::DefTy(..) | def::DefPrimTy(_) |
           def::DefTyParam(..) | def::DefTyParamBinder(..) | def::DefRegion(_) |
-          def::DefLabel(_) | def::DefSelfTy(..) | def::DefMethod(..) |
+          def::DefLabel(_) | def::DefSelfTy(..) |
           def::DefAssociatedTy(..) | def::DefAssociatedPath(..)=> {
               Ok(Rc::new(cmt_ {
                   id:id,
diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs
index 58cb2ebd256..986c96e1cdf 100644
--- a/src/librustc_trans/trans/base.rs
+++ b/src/librustc_trans/trans/base.rs
@@ -511,7 +511,7 @@ pub fn get_res_dtor<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         // Since we're in trans we don't care for any region parameters
         let substs = subst::Substs::erased(substs.types.clone());
 
-        let (val, _) = monomorphize::monomorphic_fn(ccx, did, &substs, None);
+        let (val, _, _) = monomorphize::monomorphic_fn(ccx, did, &substs, None);
 
         val
     } else if did.krate == ast::LOCAL_CRATE {
diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs
index f001786bec4..c8d3a973a35 100644
--- a/src/librustc_trans/trans/callee.rs
+++ b/src/librustc_trans/trans/callee.rs
@@ -38,6 +38,7 @@ use trans::cleanup::CleanupMethods;
 use trans::closure;
 use trans::common;
 use trans::common::*;
+use trans::consts;
 use trans::datum::*;
 use trans::expr;
 use trans::glue;
@@ -152,7 +153,8 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
                     _ => false
                 }
             } => {
-                let substs = node_id_substs(bcx, ExprId(ref_expr.id));
+                let substs = node_id_substs(bcx.ccx(), ExprId(ref_expr.id),
+                                            bcx.fcx.param_substs);
                 Callee {
                     bcx: bcx,
                     data: NamedTupleConstructor(substs, 0)
@@ -162,23 +164,28 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
                 ty::ty_bare_fn(_, ref f) => f.abi == synabi::RustIntrinsic,
                 _ => false
             } => {
-                let substs = node_id_substs(bcx, ExprId(ref_expr.id));
+                let substs = node_id_substs(bcx.ccx(), ExprId(ref_expr.id),
+                                            bcx.fcx.param_substs);
                 let def_id = inline::maybe_instantiate_inline(bcx.ccx(), did);
                 Callee { bcx: bcx, data: Intrinsic(def_id.node, substs) }
             }
             def::DefFn(did, _) | def::DefMethod(did, _, def::FromImpl(_)) |
             def::DefStaticMethod(did, def::FromImpl(_)) => {
-                fn_callee(bcx, trans_fn_ref(bcx, did, ExprId(ref_expr.id)))
+                fn_callee(bcx, trans_fn_ref(bcx.ccx(), did, ExprId(ref_expr.id),
+                                            bcx.fcx.param_substs).val)
             }
             def::DefStaticMethod(meth_did, def::FromTrait(trait_did)) |
             def::DefMethod(meth_did, _, def::FromTrait(trait_did)) => {
-                fn_callee(bcx, meth::trans_static_method_callee(bcx, meth_did,
+                fn_callee(bcx, meth::trans_static_method_callee(bcx.ccx(),
+                                                                meth_did,
                                                                 trait_did,
-                                                                ref_expr.id))
+                                                                ref_expr.id,
+                                                                bcx.fcx.param_substs).val)
             }
             def::DefVariant(tid, vid, _) => {
                 let vinfo = ty::enum_variant_with_id(bcx.tcx(), tid, vid);
-                let substs = node_id_substs(bcx, ExprId(ref_expr.id));
+                let substs = node_id_substs(bcx.ccx(), ExprId(ref_expr.id),
+                                            bcx.fcx.param_substs);
 
                 // Nullary variants are not callable
                 assert!(vinfo.args.len() > 0u);
@@ -189,7 +196,8 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
                 }
             }
             def::DefStruct(_) => {
-                let substs = node_id_substs(bcx, ExprId(ref_expr.id));
+                let substs = node_id_substs(bcx.ccx(), ExprId(ref_expr.id),
+                                            bcx.fcx.param_substs);
                 Callee {
                     bcx: bcx,
                     data: NamedTupleConstructor(substs, 0)
@@ -217,15 +225,19 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
 
 /// Translates a reference (with id `ref_id`) to the fn/method with id `def_id` into a function
 /// pointer. This may require monomorphization or inlining.
-pub fn trans_fn_ref(bcx: Block, def_id: ast::DefId, node: ExprOrMethodCall) -> ValueRef {
+pub fn trans_fn_ref<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+                              def_id: ast::DefId,
+                              node: ExprOrMethodCall,
+                              param_substs: &subst::Substs<'tcx>)
+                              -> Datum<'tcx, Rvalue> {
     let _icx = push_ctxt("trans_fn_ref");
 
-    let substs = node_id_substs(bcx, node);
+    let substs = node_id_substs(ccx, node, param_substs);
     debug!("trans_fn_ref(def_id={}, node={}, substs={})",
-           def_id.repr(bcx.tcx()),
+           def_id.repr(ccx.tcx()),
            node,
-           substs.repr(bcx.tcx()));
-    trans_fn_ref_with_substs(bcx, def_id, node, substs)
+           substs.repr(ccx.tcx()));
+    trans_fn_ref_with_substs(ccx, def_id, node, param_substs, substs)
 }
 
 fn trans_fn_ref_with_substs_to_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
@@ -235,10 +247,11 @@ fn trans_fn_ref_with_substs_to_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                                   -> Callee<'blk, 'tcx> {
     Callee {
         bcx: bcx,
-        data: Fn(trans_fn_ref_with_substs(bcx,
+        data: Fn(trans_fn_ref_with_substs(bcx.ccx(),
                                           def_id,
                                           ExprId(ref_id),
-                                          substs)),
+                                          bcx.fcx.param_substs,
+                                          substs).val),
     }
 }
 
@@ -364,28 +377,30 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
 ///
 /// # Parameters
 ///
-/// - `bcx`: the current block where the reference to the fn occurs
+/// - `ccx`: the crate context
 /// - `def_id`: def id of the fn or method item being referenced
 /// - `node`: node id of the reference to the fn/method, if applicable.
 ///   This parameter may be zero; but, if so, the resulting value may not
 ///   have the right type, so it must be cast before being used.
+/// - `param_substs`: if the `node` is in a polymorphic function, these
+///   are the substitutions required to monomorphize its type
 /// - `substs`: values for each of the fn/method's parameters
-pub fn trans_fn_ref_with_substs<'blk, 'tcx>(
-    bcx: Block<'blk, 'tcx>,      //
-    def_id: ast::DefId,          // def id of fn
-    node: ExprOrMethodCall,      // node id of use of fn; may be zero if N/A
-    substs: subst::Substs<'tcx>) // vtables for the call
-    -> ValueRef
+pub fn trans_fn_ref_with_substs<'a, 'tcx>(
+    ccx: &CrateContext<'a, 'tcx>,
+    def_id: ast::DefId,
+    node: ExprOrMethodCall,
+    param_substs: &subst::Substs<'tcx>,
+    substs: subst::Substs<'tcx>)
+    -> Datum<'tcx, Rvalue>
 {
     let _icx = push_ctxt("trans_fn_ref_with_substs");
-    let ccx = bcx.ccx();
-    let tcx = bcx.tcx();
+    let tcx = ccx.tcx();
 
-    debug!("trans_fn_ref_with_substs(bcx={}, def_id={}, node={}, \
-            substs={})",
-           bcx.to_str(),
+    debug!("trans_fn_ref_with_substs(def_id={}, node={}, \
+            param_substs={}, substs={})",
            def_id.repr(tcx),
            node,
+           param_substs.repr(tcx),
            substs.repr(tcx));
 
     assert!(substs.types.all(|t| !ty::type_needs_infer(*t)));
@@ -443,15 +458,15 @@ pub fn trans_fn_ref_with_substs<'blk, 'tcx>(
                     (true, source_id, new_substs)
                 }
                 ty::TypeTraitItem(_) => {
-                    bcx.tcx().sess.bug("trans_fn_ref_with_vtables() tried \
-                                        to translate an associated type?!")
+                    tcx.sess.bug("trans_fn_ref_with_vtables() tried \
+                                  to translate an associated type?!")
                 }
             }
         }
     };
 
     // If this is an unboxed closure, redirect to it.
-    match closure::get_or_create_declaration_if_unboxed_closure(bcx,
+    match closure::get_or_create_declaration_if_unboxed_closure(ccx,
                                                                 def_id,
                                                                 &substs) {
         None => {}
@@ -494,24 +509,27 @@ pub fn trans_fn_ref_with_substs<'blk, 'tcx>(
             MethodCallKey(_) => None,
         };
 
-        let (val, must_cast) =
+        let (val, fn_ty, must_cast) =
             monomorphize::monomorphic_fn(ccx, def_id, &substs, opt_ref_id);
-        let mut val = val;
         if must_cast && node != ExprId(0) {
             // Monotype of the REFERENCE to the function (type params
             // are subst'd)
             let ref_ty = match node {
-                ExprId(id) => node_id_type(bcx, id),
+                ExprId(id) => ty::node_id_to_type(tcx, id),
                 MethodCallKey(method_call) => {
-                    let t = (*bcx.tcx().method_map.borrow())[method_call].ty;
-                    monomorphize_type(bcx, t)
+                    (*tcx.method_map.borrow())[method_call].ty
                 }
             };
-
-            val = PointerCast(
-                bcx, val, type_of::type_of_fn_from_ty(ccx, ref_ty).ptr_to());
+            let ref_ty = monomorphize::apply_param_substs(tcx,
+                                                          param_substs,
+                                                          &ref_ty);
+            let llptrty = type_of::type_of_fn_from_ty(ccx, ref_ty).ptr_to();
+            if llptrty != val_ty(val) {
+                let val = consts::ptrcast(val, llptrty);
+                return Datum::new(val, ref_ty, Rvalue::new(ByValue));
+            }
         }
-        return val;
+        return Datum::new(val, fn_ty, Rvalue::new(ByValue));
     }
 
     // Type scheme of the function item (may have type params)
@@ -556,12 +574,12 @@ pub fn trans_fn_ref_with_substs<'blk, 'tcx>(
     let llptrty = llty.ptr_to();
     if val_ty(val) != llptrty {
         debug!("trans_fn_ref_with_vtables(): casting pointer!");
-        val = BitCast(bcx, val, llptrty);
+        val = consts::ptrcast(val, llptrty);
     } else {
         debug!("trans_fn_ref_with_vtables(): not casting pointer!");
     }
 
-    val
+    Datum::new(val, fn_type, Rvalue::new(ByValue))
 }
 
 // ______________________________________________________________________
diff --git a/src/librustc_trans/trans/cleanup.rs b/src/librustc_trans/trans/cleanup.rs
index 59ba56bbbc8..79a5898e3d3 100644
--- a/src/librustc_trans/trans/cleanup.rs
+++ b/src/librustc_trans/trans/cleanup.rs
@@ -726,7 +726,10 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx
         // specify any of the types for the function, we just make it a symbol
         // that LLVM can later use.
         let llpersonality = match pad_bcx.tcx().lang_items.eh_personality() {
-            Some(def_id) => callee::trans_fn_ref(pad_bcx, def_id, ExprId(0)),
+            Some(def_id) => {
+                callee::trans_fn_ref(pad_bcx.ccx(), def_id, ExprId(0),
+                                     pad_bcx.fcx.param_substs).val
+            }
             None => {
                 let mut personality = self.ccx.eh_personality().borrow_mut();
                 match *personality {
diff --git a/src/librustc_trans/trans/closure.rs b/src/librustc_trans/trans/closure.rs
index cb5302f7234..7b394cef192 100644
--- a/src/librustc_trans/trans/closure.rs
+++ b/src/librustc_trans/trans/closure.rs
@@ -20,6 +20,7 @@ use trans::build::*;
 use trans::cleanup::{CleanupMethods, ScopeId};
 use trans::common::*;
 use trans::datum::{Datum, DatumBlock, Expr, Lvalue, rvalue_scratch_datum};
+use trans::datum::{Rvalue, ByValue};
 use trans::debuginfo;
 use trans::expr;
 use trans::monomorphize::{self, MonoId};
@@ -453,22 +454,21 @@ pub fn trans_expr_fn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
 /// Returns the LLVM function declaration for an unboxed closure, creating it
 /// if necessary. If the ID does not correspond to a closure ID, returns None.
-pub fn get_or_create_declaration_if_unboxed_closure<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                                                closure_id: ast::DefId,
-                                                                substs: &Substs<'tcx>)
-                                                                -> Option<ValueRef> {
-    let ccx = bcx.ccx();
+pub fn get_or_create_declaration_if_unboxed_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+                                                              closure_id: ast::DefId,
+                                                              substs: &Substs<'tcx>)
+                                                              -> Option<Datum<'tcx, Rvalue>> {
     if !ccx.tcx().unboxed_closures.borrow().contains_key(&closure_id) {
         // Not an unboxed closure.
         return None
     }
 
-    let function_type = ty::node_id_to_type(bcx.tcx(), closure_id.node);
-    let function_type = monomorphize::apply_param_substs(bcx.tcx(), substs, &function_type);
+    let function_type = ty::node_id_to_type(ccx.tcx(), closure_id.node);
+    let function_type = monomorphize::apply_param_substs(ccx.tcx(), substs, &function_type);
 
     // Normalize type so differences in regions and typedefs don't cause
     // duplicate declarations
-    let function_type = ty::normalize_ty(bcx.tcx(), function_type);
+    let function_type = ty::normalize_ty(ccx.tcx(), function_type);
     let params = match function_type.sty {
         ty::ty_unboxed_closure(_, _, ref substs) => substs.types.clone(),
         _ => unreachable!()
@@ -479,10 +479,10 @@ pub fn get_or_create_declaration_if_unboxed_closure<'blk, 'tcx>(bcx: Block<'blk,
     };
 
     match ccx.unboxed_closure_vals().borrow().get(&mono_id) {
-        Some(llfn) => {
+        Some(&llfn) => {
             debug!("get_or_create_declaration_if_unboxed_closure(): found \
                     closure");
-            return Some(*llfn)
+            return Some(Datum::new(llfn, function_type, Rvalue::new(ByValue)))
         }
         None => {}
     }
@@ -502,7 +502,7 @@ pub fn get_or_create_declaration_if_unboxed_closure<'blk, 'tcx>(bcx: Block<'blk,
            ccx.tn().type_to_string(val_ty(llfn)));
     ccx.unboxed_closure_vals().borrow_mut().insert(mono_id, llfn);
 
-    Some(llfn)
+    Some(Datum::new(llfn, function_type, Rvalue::new(ByValue)))
 }
 
 pub fn trans_unboxed_closure<'blk, 'tcx>(
@@ -519,7 +519,7 @@ pub fn trans_unboxed_closure<'blk, 'tcx>(
 
     let closure_id = ast_util::local_def(id);
     let llfn = get_or_create_declaration_if_unboxed_closure(
-        bcx,
+        bcx.ccx(),
         closure_id,
         bcx.fcx.param_substs).unwrap();
 
@@ -539,7 +539,7 @@ pub fn trans_unboxed_closure<'blk, 'tcx>(
     trans_closure(bcx.ccx(),
                   decl,
                   body,
-                  llfn,
+                  llfn.val,
                   bcx.fcx.param_substs,
                   id,
                   &[],
diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs
index 87a1862186a..e8dee19ed54 100644
--- a/src/librustc_trans/trans/common.rs
+++ b/src/librustc_trans/trans/common.rs
@@ -28,6 +28,7 @@ use middle::subst::{self, Subst, Substs};
 use trans::base;
 use trans::build;
 use trans::cleanup;
+use trans::consts;
 use trans::datum;
 use trans::debuginfo;
 use trans::machine;
@@ -803,12 +804,9 @@ pub fn C_cstr(cx: &CrateContext, s: InternedString, null_terminated: bool) -> Va
 // NB: Do not use `do_spill_noroot` to make this into a constant string, or
 // you will be kicked off fast isel. See issue #4352 for an example of this.
 pub fn C_str_slice(cx: &CrateContext, s: InternedString) -> ValueRef {
-    unsafe {
-        let len = s.get().len();
-        let cs = llvm::LLVMConstPointerCast(C_cstr(cx, s, false),
-                                            Type::i8p(cx).to_ref());
-        C_named_struct(cx.tn().find_type("str_slice").unwrap(), &[cs, C_uint(cx, len)])
-    }
+    let len = s.get().len();
+    let cs = consts::ptrcast(C_cstr(cx, s, false), Type::i8p(cx));
+    C_named_struct(cx.tn().find_type("str_slice").unwrap(), &[cs, C_uint(cx, len)])
 }
 
 pub fn C_binary_slice(cx: &CrateContext, data: &[u8]) -> ValueRef {
@@ -824,7 +822,7 @@ pub fn C_binary_slice(cx: &CrateContext, data: &[u8]) -> ValueRef {
         llvm::LLVMSetGlobalConstant(g, True);
         llvm::SetLinkage(g, llvm::InternalLinkage);
 
-        let cs = llvm::LLVMConstPointerCast(g, Type::i8p(cx).to_ref());
+        let cs = consts::ptrcast(g, Type::i8p(cx));
         C_struct(cx, &[cs, C_uint(cx, len)], false)
     }
 }
@@ -1095,11 +1093,11 @@ pub enum ExprOrMethodCall {
     MethodCallKey(ty::MethodCall)
 }
 
-pub fn node_id_substs<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                  node: ExprOrMethodCall)
-                                  -> subst::Substs<'tcx>
-{
-    let tcx = bcx.tcx();
+pub fn node_id_substs<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+                                node: ExprOrMethodCall,
+                                param_substs: &subst::Substs<'tcx>)
+                                -> subst::Substs<'tcx> {
+    let tcx = ccx.tcx();
 
     let substs = match node {
         ExprId(id) => {
@@ -1111,15 +1109,13 @@ pub fn node_id_substs<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     };
 
     if substs.types.any(|t| ty::type_needs_infer(*t)) {
-        bcx.sess().bug(
-            format!("type parameters for node {} include inference types: \
-                     {}",
-                    node,
-                    substs.repr(bcx.tcx()))[]);
+        tcx.sess.bug(format!("type parameters for node {} include inference types: {}",
+                             node, substs.repr(tcx))[]);
     }
 
-    let substs = substs.erase_regions();
-    bcx.monomorphize(&substs)
+    monomorphize::apply_param_substs(tcx,
+                                     param_substs,
+                                     &substs.erase_regions())
 }
 
 pub fn langcall(bcx: Block,
diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs
index 4f8554195e5..b17e852d7cb 100644
--- a/src/librustc_trans/trans/consts.rs
+++ b/src/librustc_trans/trans/consts.rs
@@ -14,13 +14,13 @@ use llvm;
 use llvm::{ConstFCmp, ConstICmp, SetLinkage, PrivateLinkage, ValueRef, Bool, True, False};
 use llvm::{IntEQ, IntNE, IntUGT, IntUGE, IntULT, IntULE, IntSGT, IntSGE, IntSLT, IntSLE,
            RealOEQ, RealOGT, RealOGE, RealOLT, RealOLE, RealONE};
-use metadata::csearch;
 use middle::{const_eval, def};
 use trans::{adt, closure, consts, debuginfo, expr, inline, machine};
 use trans::base::{self, push_ctxt};
 use trans::common::*;
 use trans::type_::Type;
 use trans::type_of;
+use middle::subst::Substs;
 use middle::ty::{self, Ty};
 use util::ppaux::{Repr, ty_to_string};
 
@@ -79,11 +79,9 @@ pub fn const_lit(cx: &CrateContext, e: &ast::Expr, lit: &ast::Lit)
     }
 }
 
-pub fn const_ptrcast(cx: &CrateContext, a: ValueRef, t: Type) -> ValueRef {
+pub fn ptrcast(val: ValueRef, ty: Type) -> ValueRef {
     unsafe {
-        let b = llvm::LLVMConstPointerCast(a, t.ptr_to().to_ref());
-        assert!(cx.const_globals().borrow_mut().insert(b as int, a).is_none());
-        b
+        llvm::LLVMConstPointerCast(val, ty.to_ref())
     }
 }
 
@@ -258,7 +256,9 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, e: &ast::Expr)
                                     match ty.sty {
                                         ty::ty_vec(unit_ty, Some(len)) => {
                                             let llunitty = type_of::type_of(cx, unit_ty);
-                                            let llptr = const_ptrcast(cx, llconst, llunitty);
+                                            let llptr = ptrcast(llconst, llunitty.ptr_to());
+                                            assert!(cx.const_globals().borrow_mut()
+                                                      .insert(llptr as int, llconst).is_none());
                                             assert_eq!(abi::FAT_PTR_ADDR, 0);
                                             assert_eq!(abi::FAT_PTR_EXTRA, 1);
                                             llconst = C_struct(cx, &[
@@ -523,7 +523,7 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr) -> ValueRef {
                 }
               }
               (expr::cast_pointer, expr::cast_pointer) => {
-                llvm::LLVMConstPointerCast(v, llty.to_ref())
+                ptrcast(v, llty)
               }
               (expr::cast_integral, expr::cast_pointer) => {
                 llvm::LLVMConstIntToPtr(v, llty.to_ref())
@@ -616,36 +616,38 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr) -> ValueRef {
                 C_array(llunitty, vs[])
             }
           }
-          ast::ExprPath(ref pth) => {
-            // Assert that there are no type parameters in this path.
-            assert!(pth.segments.iter().all(|seg| !seg.parameters.has_types()));
-
-            let opt_def = cx.tcx().def_map.borrow().get(&e.id).cloned();
-            match opt_def {
-                Some(def::DefFn(def_id, _)) => {
-                    if !ast_util::is_local(def_id) {
-                        let ty = csearch::get_type(cx.tcx(), def_id).ty;
-                        base::trans_external_path(cx, def_id, ty)
-                    } else {
-                        assert!(ast_util::is_local(def_id));
-                        base::get_item_val(cx, def_id.node)
-                    }
+          ast::ExprPath(_) => {
+            let def = cx.tcx().def_map.borrow()[e.id];
+            match def {
+                def::DefFn(..) | def::DefStaticMethod(..) | def::DefMethod(..) => {
+                    expr::trans_def_fn_unadjusted(cx, e, def, &Substs::trans_empty()).val
                 }
-                Some(def::DefConst(def_id)) => {
+                def::DefConst(def_id) => {
                     get_const_val(cx, def_id)
                 }
-                Some(def::DefVariant(enum_did, variant_did, _)) => {
-                    let ety = ty::expr_ty(cx.tcx(), e);
-                    let repr = adt::represent_type(cx, ety);
+                def::DefVariant(enum_did, variant_did, _) => {
                     let vinfo = ty::enum_variant_with_id(cx.tcx(),
                                                          enum_did,
                                                          variant_did);
-                    adt::trans_const(cx, &*repr, vinfo.disr_val, &[])
+                    if vinfo.args.len() > 0 {
+                        // N-ary variant.
+                        expr::trans_def_fn_unadjusted(cx, e, def, &Substs::trans_empty()).val
+                    } else {
+                        // Nullary variant.
+                        let ety = ty::expr_ty(cx.tcx(), e);
+                        let repr = adt::represent_type(cx, ety);
+                        adt::trans_const(cx, &*repr, vinfo.disr_val, &[])
+                    }
                 }
-                Some(def::DefStruct(_)) => {
+                def::DefStruct(_) => {
                     let ety = ty::expr_ty(cx.tcx(), e);
-                    let llty = type_of::type_of(cx, ety);
-                    C_null(llty)
+                    if let ty::ty_bare_fn(..) = ety.sty {
+                        // Tuple struct.
+                        expr::trans_def_fn_unadjusted(cx, e, def, &Substs::trans_empty()).val
+                    } else {
+                        // Unit struct.
+                        C_null(type_of::type_of(cx, ety))
+                    }
                 }
                 _ => {
                     cx.sess().span_bug(e.span, "expected a const, fn, struct, \
diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs
index c525e6fcfe3..68557289d52 100644
--- a/src/librustc_trans/trans/expr.rs
+++ b/src/librustc_trans/trans/expr.rs
@@ -853,7 +853,9 @@ fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     match def {
         def::DefFn(..) | def::DefStaticMethod(..) | def::DefMethod(..) |
         def::DefStruct(_) | def::DefVariant(..) => {
-            trans_def_fn_unadjusted(bcx, ref_expr, def)
+            let datum = trans_def_fn_unadjusted(bcx.ccx(), ref_expr, def,
+                                                bcx.fcx.param_substs);
+            DatumBlock::new(bcx, datum.to_expr_datum())
         }
         def::DefStatic(did, _) => {
             // There are two things that may happen here:
@@ -1250,7 +1252,9 @@ fn trans_def_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             let variant_info = ty::enum_variant_with_id(bcx.tcx(), tid, vid);
             if variant_info.args.len() > 0u {
                 // N-ary variant.
-                let llfn = callee::trans_fn_ref(bcx, vid, ExprId(ref_expr.id));
+                let llfn = callee::trans_fn_ref(bcx.ccx(), vid,
+                                                ExprId(ref_expr.id),
+                                                bcx.fcx.param_substs).val;
                 Store(bcx, llfn, lldest);
                 return bcx;
             } else {
@@ -1281,34 +1285,33 @@ fn trans_def_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     }
 }
 
-fn trans_def_fn_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                       ref_expr: &ast::Expr,
-                                       def: def::Def)
-                                       -> DatumBlock<'blk, 'tcx, Expr> {
+pub fn trans_def_fn_unadjusted<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+                                         ref_expr: &ast::Expr,
+                                         def: def::Def,
+                                         param_substs: &subst::Substs<'tcx>)
+                                         -> Datum<'tcx, Rvalue> {
     let _icx = push_ctxt("trans_def_datum_unadjusted");
 
-    let llfn = match def {
+    match def {
         def::DefFn(did, _) |
         def::DefStruct(did) | def::DefVariant(_, did, _) |
         def::DefStaticMethod(did, def::FromImpl(_)) |
         def::DefMethod(did, _, def::FromImpl(_)) => {
-            callee::trans_fn_ref(bcx, did, ExprId(ref_expr.id))
+            callee::trans_fn_ref(ccx, did, ExprId(ref_expr.id), param_substs)
         }
         def::DefStaticMethod(impl_did, def::FromTrait(trait_did)) |
         def::DefMethod(impl_did, _, def::FromTrait(trait_did)) => {
-            meth::trans_static_method_callee(bcx, impl_did,
-                                             trait_did, ref_expr.id)
+            meth::trans_static_method_callee(ccx, impl_did,
+                                             trait_did, ref_expr.id,
+                                             param_substs)
         }
         _ => {
-            bcx.tcx().sess.span_bug(ref_expr.span, format!(
+            ccx.tcx().sess.span_bug(ref_expr.span, format!(
                     "trans_def_fn_unadjusted invoked on: {} for {}",
                     def,
-                    ref_expr.repr(bcx.tcx()))[]);
+                    ref_expr.repr(ccx.tcx()))[]);
         }
-    };
-
-    let fn_ty = expr_ty(bcx, ref_expr);
-    DatumBlock::new(bcx, Datum::new(llfn, fn_ty, RvalueExpr(Rvalue::new(ByValue))))
+    }
 }
 
 /// Translates a reference to a local variable or argument. This always results in an lvalue datum.
diff --git a/src/librustc_trans/trans/glue.rs b/src/librustc_trans/trans/glue.rs
index 0ff53a1af71..c0497041813 100644
--- a/src/librustc_trans/trans/glue.rs
+++ b/src/librustc_trans/trans/glue.rs
@@ -26,6 +26,7 @@ use trans::build::*;
 use trans::callee;
 use trans::cleanup;
 use trans::cleanup::CleanupMethods;
+use trans::consts;
 use trans::common::*;
 use trans::datum;
 use trans::debuginfo;
@@ -577,9 +578,7 @@ pub fn emit_tydescs(ccx: &CrateContext) {
         // before being put into the tydesc because we only have a singleton
         // tydesc type. Then we'll recast each function to its real type when
         // calling it.
-        let drop_glue = unsafe {
-            llvm::LLVMConstPointerCast(get_drop_glue(ccx, ti.ty), glue_fn_ty.to_ref())
-        };
+        let drop_glue = consts::ptrcast(get_drop_glue(ccx, ti.ty), glue_fn_ty);
         ccx.stats().n_real_glues.set(ccx.stats().n_real_glues.get() + 1);
 
         let tydesc = C_named_struct(ccx.tydesc_type(),
diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs
index ca17f3558ae..c13516134c2 100644
--- a/src/librustc_trans/trans/meth.rs
+++ b/src/librustc_trans/trans/meth.rs
@@ -122,9 +122,10 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         ty::MethodStaticUnboxedClosure(did) => {
             Callee {
                 bcx: bcx,
-                data: Fn(callee::trans_fn_ref(bcx,
+                data: Fn(callee::trans_fn_ref(bcx.ccx(),
                                               did,
-                                              MethodCallKey(method_call))),
+                                              MethodCallKey(method_call),
+                                              bcx.fcx.param_substs).val),
             }
         }
 
@@ -166,30 +167,31 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     }
 }
 
-pub fn trans_static_method_callee(bcx: Block,
-                                  method_id: ast::DefId,
-                                  trait_id: ast::DefId,
-                                  expr_id: ast::NodeId)
-                                  -> ValueRef
+pub fn trans_static_method_callee<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+                                            method_id: ast::DefId,
+                                            trait_id: ast::DefId,
+                                            expr_id: ast::NodeId,
+                                            param_substs: &subst::Substs<'tcx>)
+                                            -> Datum<'tcx, Rvalue>
 {
     let _icx = push_ctxt("meth::trans_static_method_callee");
-    let ccx = bcx.ccx();
+    let tcx = ccx.tcx();
 
     debug!("trans_static_method_callee(method_id={}, trait_id={}, \
             expr_id={})",
            method_id,
-           ty::item_path_str(bcx.tcx(), trait_id),
+           ty::item_path_str(tcx, trait_id),
            expr_id);
 
     let mname = if method_id.krate == ast::LOCAL_CRATE {
-        match bcx.tcx().map.get(method_id.node) {
+        match tcx.map.get(method_id.node) {
             ast_map::NodeTraitItem(method) => {
                 let ident = match *method {
                     ast::RequiredMethod(ref m) => m.ident,
                     ast::ProvidedMethod(ref m) => m.pe_ident(),
                     ast::TypeTraitItem(_) => {
-                        bcx.tcx().sess.bug("trans_static_method_callee() on \
-                                            an associated type?!")
+                        tcx.sess.bug("trans_static_method_callee() on \
+                                      an associated type?!")
                     }
                 };
                 ident.name
@@ -197,7 +199,7 @@ pub fn trans_static_method_callee(bcx: Block,
             _ => panic!("callee is not a trait method")
         }
     } else {
-        csearch::get_item_path(bcx.tcx(), method_id).last().unwrap().name()
+        csearch::get_item_path(tcx, method_id).last().unwrap().name()
     };
     debug!("trans_static_method_callee: method_id={}, expr_id={}, \
             name={}", method_id, expr_id, token::get_name(mname));
@@ -205,7 +207,7 @@ pub fn trans_static_method_callee(bcx: Block,
     // Find the substitutions for the fn itself. This includes
     // type parameters that belong to the trait but also some that
     // belong to the method:
-    let rcvr_substs = node_id_substs(bcx, ExprId(expr_id));
+    let rcvr_substs = node_id_substs(ccx, ExprId(expr_id), param_substs);
     let subst::SeparateVecsPerParamSpace {
         types: rcvr_type,
         selfs: rcvr_self,
@@ -238,11 +240,11 @@ pub fn trans_static_method_callee(bcx: Block,
         Substs::erased(VecPerParamSpace::new(rcvr_type,
                                              rcvr_self,
                                              Vec::new()));
-    let trait_substs = bcx.tcx().mk_substs(trait_substs);
-    debug!("trait_substs={}", trait_substs.repr(bcx.tcx()));
+    let trait_substs = tcx.mk_substs(trait_substs);
+    debug!("trait_substs={}", trait_substs.repr(tcx));
     let trait_ref = ty::Binder(Rc::new(ty::TraitRef { def_id: trait_id,
                                                       substs: trait_substs }));
-    let vtbl = fulfill_obligation(bcx.ccx(),
+    let vtbl = fulfill_obligation(ccx,
                                   DUMMY_SP,
                                   trait_ref);
 
@@ -282,17 +284,13 @@ pub fn trans_static_method_callee(bcx: Block,
                                                      rcvr_method));
 
             let mth_id = method_with_name(ccx, impl_did, mname);
-            let llfn = trans_fn_ref_with_substs(bcx, mth_id, ExprId(expr_id),
-                                                callee_substs);
-
-            let callee_ty = node_id_type(bcx, expr_id);
-            let llty = type_of_fn_from_ty(ccx, callee_ty).ptr_to();
-            PointerCast(bcx, llfn, llty)
+            trans_fn_ref_with_substs(ccx, mth_id, ExprId(expr_id),
+                                     param_substs,
+                                     callee_substs)
         }
         _ => {
-            bcx.tcx().sess.bug(
-                format!("static call to invalid vtable: {}",
-                        vtbl.repr(bcx.tcx()))[]);
+            tcx.sess.bug(format!("static call to invalid vtable: {}",
+                                 vtbl.repr(tcx))[]);
         }
     }
 }
@@ -346,20 +344,22 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                     bcx, MethodCallKey(method_call), vtable_impl.substs);
 
             // translate the function
-            let llfn = trans_fn_ref_with_substs(bcx,
+            let llfn = trans_fn_ref_with_substs(bcx.ccx(),
                                                 mth_id,
                                                 MethodCallKey(method_call),
-                                                callee_substs);
+                                                bcx.fcx.param_substs,
+                                                callee_substs).val;
 
             Callee { bcx: bcx, data: Fn(llfn) }
         }
         traits::VtableUnboxedClosure(closure_def_id, substs) => {
             // The substitutions should have no type parameters remaining
             // after passing through fulfill_obligation
-            let llfn = trans_fn_ref_with_substs(bcx,
+            let llfn = trans_fn_ref_with_substs(bcx.ccx(),
                                                 closure_def_id,
                                                 MethodCallKey(method_call),
-                                                substs);
+                                                bcx.fcx.param_substs,
+                                                substs).val;
 
             Callee {
                 bcx: bcx,
@@ -400,7 +400,7 @@ fn combine_impl_and_methods_tps<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 {
     let ccx = bcx.ccx();
 
-    let node_substs = node_id_substs(bcx, node);
+    let node_substs = node_id_substs(ccx, node, bcx.fcx.param_substs);
 
     debug!("rcvr_substs={}", rcvr_substs.repr(ccx.tcx()));
     debug!("node_substs={}", node_substs.repr(ccx.tcx()));
@@ -684,10 +684,11 @@ pub fn get_vtable<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             }
             traits::VtableUnboxedClosure(closure_def_id, substs) => {
                 let llfn = trans_fn_ref_with_substs(
-                    bcx,
+                    bcx.ccx(),
                     closure_def_id,
                     ExprId(0),
-                    substs.clone());
+                    bcx.fcx.param_substs,
+                    substs.clone()).val;
 
                 (vec!(llfn)).into_iter()
             }
@@ -788,10 +789,11 @@ fn emit_vtable_methods<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                     Some(C_null(Type::nil(ccx).ptr_to())).into_iter()
                 } else {
                     let fn_ref = trans_fn_ref_with_substs(
-                        bcx,
+                        ccx,
                         m_id,
                         ExprId(0),
-                        substs.clone());
+                        bcx.fcx.param_substs,
+                        substs.clone()).val;
 
                     // currently, at least, by-value self is not object safe
                     assert!(m.explicit_self != ty::ByValueExplicitSelfCategory);
diff --git a/src/librustc_trans/trans/monomorphize.rs b/src/librustc_trans/trans/monomorphize.rs
index 51a6bc3bfd5..e6db462a342 100644
--- a/src/librustc_trans/trans/monomorphize.rs
+++ b/src/librustc_trans/trans/monomorphize.rs
@@ -38,7 +38,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                 fn_id: ast::DefId,
                                 psubsts: &subst::Substs<'tcx>,
                                 ref_id: Option<ast::NodeId>)
-    -> (ValueRef, bool) {
+    -> (ValueRef, Ty<'tcx>, bool) {
     debug!("monomorphic_fn(\
             fn_id={}, \
             real_substs={}, \
@@ -58,11 +58,14 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         params: psubsts.types.clone()
     };
 
+    let item_ty = ty::lookup_item_type(ccx.tcx(), fn_id).ty;
+    let mono_ty = item_ty.subst(ccx.tcx(), psubsts);
+
     match ccx.monomorphized().borrow().get(&hash_id) {
         Some(&val) => {
             debug!("leaving monomorphic fn {}",
             ty::item_path_str(ccx.tcx(), fn_id));
-            return (val, false);
+            return (val, mono_ty, false);
         }
         None => ()
     }
@@ -75,8 +78,6 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
            psubsts.repr(ccx.tcx()),
            hash_id);
 
-    let tpt = ty::lookup_item_type(ccx.tcx(), fn_id);
-    let llitem_ty = tpt.ty;
 
     let map_node = session::expect(
         ccx.sess(),
@@ -91,13 +92,12 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     if let ast_map::NodeForeignItem(_) = map_node {
         if ccx.tcx().map.get_foreign_abi(fn_id.node) != abi::RustIntrinsic {
             // Foreign externs don't have to be monomorphized.
-            return (get_item_val(ccx, fn_id.node), true);
+            return (get_item_val(ccx, fn_id.node), mono_ty, true);
         }
     }
 
-    debug!("monomorphic_fn about to subst into {}", llitem_ty.repr(ccx.tcx()));
+    debug!("monomorphic_fn about to subst into {}", item_ty.repr(ccx.tcx()));
 
-    let mono_ty = llitem_ty.subst(ccx.tcx(), psubsts);
     debug!("mono_ty = {} (post-substitution)", mono_ty.repr(ccx.tcx()));
 
     let mono_ty = normalize_associated_type(ccx.tcx(), &mono_ty);
@@ -283,7 +283,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     ccx.monomorphizing().borrow_mut().insert(fn_id, depth);
 
     debug!("leaving monomorphic fn {}", ty::item_path_str(ccx.tcx(), fn_id));
-    (lldecl, true)
+    (lldecl, mono_ty, true)
 }
 
 #[derive(PartialEq, Eq, Hash, Show)]
diff --git a/src/librustc_trans/trans/tvec.rs b/src/librustc_trans/trans/tvec.rs
index f8d0d4f5c7b..de71a1c2217 100644
--- a/src/librustc_trans/trans/tvec.rs
+++ b/src/librustc_trans/trans/tvec.rs
@@ -19,6 +19,7 @@ use trans::build::*;
 use trans::cleanup;
 use trans::cleanup::CleanupMethods;
 use trans::common::*;
+use trans::consts;
 use trans::datum::*;
 use trans::expr::{Dest, Ignore, SaveIn};
 use trans::expr;
@@ -213,15 +214,13 @@ pub fn trans_lit_str<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     match dest {
         Ignore => bcx,
         SaveIn(lldest) => {
-            unsafe {
-                let bytes = str_lit.get().len();
-                let llbytes = C_uint(bcx.ccx(), bytes);
-                let llcstr = C_cstr(bcx.ccx(), str_lit, false);
-                let llcstr = llvm::LLVMConstPointerCast(llcstr, Type::i8p(bcx.ccx()).to_ref());
-                Store(bcx, llcstr, GEPi(bcx, lldest, &[0u, abi::FAT_PTR_ADDR]));
-                Store(bcx, llbytes, GEPi(bcx, lldest, &[0u, abi::FAT_PTR_EXTRA]));
-                bcx
-            }
+            let bytes = str_lit.get().len();
+            let llbytes = C_uint(bcx.ccx(), bytes);
+            let llcstr = C_cstr(bcx.ccx(), str_lit, false);
+            let llcstr = consts::ptrcast(llcstr, Type::i8p(bcx.ccx()));
+            Store(bcx, llcstr, GEPi(bcx, lldest, &[0u, abi::FAT_PTR_ADDR]));
+            Store(bcx, llbytes, GEPi(bcx, lldest, &[0u, abi::FAT_PTR_EXTRA]));
+            bcx
         }
     }
 }
diff --git a/src/test/run-pass/const-polymorphic-paths.rs b/src/test/run-pass/const-polymorphic-paths.rs
new file mode 100644
index 00000000000..25c1464adfa
--- /dev/null
+++ b/src/test/run-pass/const-polymorphic-paths.rs
@@ -0,0 +1,84 @@
+// 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.
+
+#![feature(macro_rules)]
+
+use std::collections::Bitv;
+use std::default::Default;
+use std::iter::FromIterator;
+use std::option::IntoIter as OptionIter;
+use std::rand::Rand;
+use std::rand::XorShiftRng as DummyRng;
+// FIXME the glob std::prelude::*; import of Vec is missing non-static inherent methods.
+use std::vec::Vec;
+
+#[derive(PartialEq, Eq)]
+struct Newt<T>(T);
+
+fn id<T>(x: T) -> T { x }
+fn eq<T: Eq>(a: T, b: T) -> bool { a == b }
+fn u8_as_i8(x: u8) -> i8 { x as i8 }
+fn odd(x: uint) -> bool { x % 2 == 1 }
+fn dummy_rng() -> DummyRng { DummyRng::new_unseeded() }
+
+macro_rules! tests {
+    ($($expr:expr: $ty:ty /($($test:expr),*);)+) => (pub fn main() {$({
+        const C: $ty = $expr;
+        static S: $ty = $expr;
+        assert!(eq(C($($test),*), $expr($($test),*)));
+        assert!(eq(S($($test),*), $expr($($test),*)));
+        assert!(eq(C($($test),*), S($($test),*)));
+    })+})
+}
+
+tests! {
+    // Free function.
+    id: fn(int) -> int /(5);
+    id::<int>: fn(int) -> int /(5);
+
+    // Enum variant constructor.
+    Some: fn(int) -> Option<int> /(5);
+    Some::<int>: fn(int) -> Option<int> /(5);
+
+    // Tuple struct constructor.
+    Newt: fn(int) -> Newt<int> /(5);
+    Newt::<int>: fn(int) -> Newt<int> /(5);
+
+    // Inherent static methods.
+    Vec::new: fn() -> Vec<()> /();
+    Vec::<()>::new: fn() -> Vec<()> /();
+    Vec::with_capacity: fn(uint) -> Vec<()> /(5);
+    Vec::<()>::with_capacity: fn(uint) -> Vec<()> /(5);
+    Bitv::from_fn: fn(uint, fn(uint) -> bool) -> Bitv /(5, odd);
+    Bitv::from_fn::<fn(uint) -> bool>: fn(uint, fn(uint) -> bool) -> Bitv /(5, odd);
+
+    // Inherent non-static method.
+    Vec::map_in_place: fn(Vec<u8>, fn(u8) -> i8) -> Vec<i8>
+        /(vec![b'f', b'o', b'o'], u8_as_i8);
+    Vec::map_in_place::<i8, fn(u8) -> i8>: fn(Vec<u8>, fn(u8) -> i8) -> Vec<i8>
+        /(vec![b'f', b'o', b'o'], u8_as_i8);
+    // FIXME these break with "type parameter might not appear here pointing at `<u8>`.
+    // Vec::<u8>::map_in_place: fn(Vec<u8>, fn(u8) -> i8) -> Vec<i8>
+    //     /(vec![b'f', b'o', b'o'], u8_as_i8);
+    // Vec::<u8>::map_in_place::<i8, fn(u8) -> i8>: fn(Vec<u8>, fn(u8) -> i8) -> Vec<i8>
+    //     /(vec![b'f', b'o', b'o'], u8_as_i8);
+
+    // Trait static methods.
+    // FIXME qualified path expressions aka UFCS i.e. <T as Trait>::method.
+    Default::default: fn() -> int /();
+    Rand::rand: fn(&mut DummyRng) -> int /(&mut dummy_rng());
+    Rand::rand::<DummyRng>: fn(&mut DummyRng) -> int /(&mut dummy_rng());
+
+    // Trait non-static methods.
+    Clone::clone: fn(&int) -> int /(&5);
+    FromIterator::from_iter: fn(OptionIter<int>) -> Vec<int> /(Some(5).into_iter());
+    FromIterator::from_iter::<OptionIter<int>>: fn(OptionIter<int>) -> Vec<int>
+        /(Some(5).into_iter());
+}