Adopt PEP 484 type hints for C++ types exported to Python
diff --git a/example/eigen.py b/example/eigen.py
index 5f7ec51..18c8a45 100644
--- a/example/eigen.py
+++ b/example/eigen.py
@@ -106,3 +106,9 @@
 
 print("symmetric_lower %s" % ("OK" if (symmetric_lower(asymm) == symm_lower).all() else "FAILED"))
 print("symmetric_upper %s" % ("OK" if (symmetric_upper(asymm) == symm_upper).all() else "FAILED"))
+
+print(double_col.__doc__)
+print(double_row.__doc__)
+print(double_mat_rm.__doc__)
+print(sparse_passthrough_r.__doc__)
+print(sparse_passthrough_c.__doc__)
diff --git a/example/eigen.ref b/example/eigen.ref
index 755012f..626c604 100644
--- a/example/eigen.ref
+++ b/example/eigen.ref
@@ -53,3 +53,8 @@
 incr_diag OK
 symmetric_lower OK
 symmetric_upper OK
+double_col(arg0: numpy.ndarray[float32[m, 1]]) -> numpy.ndarray[float32[m, 1]]
+double_row(arg0: numpy.ndarray[float32[1, n]]) -> numpy.ndarray[float32[1, n]]
+double_mat_rm(arg0: numpy.ndarray[float32[m, n]]) -> numpy.ndarray[float32[m, n]]
+sparse_passthrough_r(arg0: scipy.sparse.csr_matrix[float32]) -> scipy.sparse.csr_matrix[float32]
+sparse_passthrough_c(arg0: scipy.sparse.csc_matrix[float32]) -> scipy.sparse.csc_matrix[float32]
diff --git a/example/example-arg-keywords-and-defaults.ref b/example/example-arg-keywords-and-defaults.ref
index 6889574..d3ca997 100644
--- a/example/example-arg-keywords-and-defaults.ref
+++ b/example/example-arg-keywords-and-defaults.ref
@@ -1,51 +1,51 @@
 Help on built-in function kw_func0 in module example
 
 kkww__ffuunncc00(...)
-    kw_func0(arg0: int, arg1: int) -> NoneType
+    kw_func0(arg0: int, arg1: int) -> None
 
 Help on built-in function kw_func1 in module example
 
 kkww__ffuunncc11(...)
-    kw_func1(x: int, y: int) -> NoneType
+    kw_func1(x: int, y: int) -> None
 
 Help on built-in function kw_func2 in module example
 
 kkww__ffuunncc22(...)
-    kw_func2(x: int=100L, y: int=200L) -> NoneType
+    kw_func2(x: int=100L, y: int=200L) -> None
 
 Help on built-in function kw_func3 in module example
 
 kkww__ffuunncc33(...)
-    kw_func3(data: unicode=u'Hello world!') -> NoneType
+    kw_func3(data: unicode=u'Hello world!') -> None
 
 Help on built-in function kw_func4 in module example
 
 kkww__ffuunncc44(...)
-    kw_func4(myList: list<int>=[13L, 17L]) -> NoneType
+    kw_func4(myList: List[int]=[13L, 17L]) -> None
 
 Help on built-in function kw_func_udl in module example
 
 kkww__ffuunncc__uuddll(...)
-    kw_func_udl(x: int, y: int=300L) -> NoneType
+    kw_func_udl(x: int, y: int=300L) -> None
 
 Help on built-in function kw_func_udl_z in module example
 
 kkww__ffuunncc__uuddll__zz(...)
-    kw_func_udl_z(x: int, y: int=0L) -> NoneType
+    kw_func_udl_z(x: int, y: int=0L) -> None
 
 Help on built-in function args_function in module example
 
 aarrggss__ffuunnccttiioonn(...)
-    args_function(*args) -> NoneType
+    args_function(*args) -> None
 
 Help on built-in function args_kwargs_function in module example
 
 aarrggss__kkwwaarrggss__ffuunnccttiioonn(...)
-    args_kwargs_function(*args, **kwargs) -> NoneType
+    args_kwargs_function(*args, **kwargs) -> None
 
 
-foo0(self: KWClass, arg0: int, arg1: float) -> NoneType
-foo1(self: KWClass, x: int, y: float) -> NoneType
+foo0(self: KWClass, arg0: int, arg1: float) -> None
+foo1(self: KWClass, x: int, y: float) -> None
 
 
 kw_func(x=5, y=10)
@@ -58,10 +58,10 @@
 kw_func(x=5, y=10)
 kw_func(x=5, y=10)
 Caught expected exception: Incompatible function arguments. The following argument types are supported:
-    1. (x: int=100L, y: int=200L) -> NoneType
+    1. (x: int=100L, y: int=200L) -> None
     Invoked with:
-kw_func4: 13 17 
-kw_func4: 1 2 3 
+kw_func4: 13 17
+kw_func4: 1 2 3
 kw_func(x=1234, y=5678)
 got argument: arg1_value
 got argument: arg2_value
diff --git a/example/example-callbacks.py b/example/example-callbacks.py
index 674174a..1d18c89 100755
--- a/example/example-callbacks.py
+++ b/example/example-callbacks.py
@@ -82,3 +82,6 @@
         print("All OK!")
     else:
         print("Problem!")
+
+print(test_callback3.__doc__)
+print(test_callback4.__doc__)
diff --git a/example/example-callbacks.ref b/example/example-callbacks.ref
index d6ab75e..7180b58 100644
--- a/example/example-callbacks.ref
+++ b/example/example-callbacks.ref
@@ -6,7 +6,7 @@
 Molly is a dog
 Woof!
 The following error is expected: Incompatible function arguments. The following argument types are supported:
-    1. (arg0: example.Dog) -> NoneType
+    1. (arg0: example.Dog) -> None
     Invoked with: <example.Pet object at 0>
 Callback function 1 called!
 False
@@ -36,3 +36,6 @@
 All OK!
 could not convert to a function pointer.
 All OK!
+
+test_callback3(arg0: Callable[[int], int]) -> None
+test_callback4() -> Callable[[int], int]
diff --git a/example/example-numpy-vectorize.py b/example/example-numpy-vectorize.py
index e21c1a5..322ce2a 100755
--- a/example/example-numpy-vectorize.py
+++ b/example/example-numpy-vectorize.py
@@ -32,3 +32,5 @@
 selective_func(np.array([1], dtype=np.int32))
 selective_func(np.array([1.0], dtype=np.float32))
 selective_func(np.array([1.0j], dtype=np.complex64))
+
+print(vectorized_func.__doc__)
diff --git a/example/example-numpy-vectorize.ref b/example/example-numpy-vectorize.ref
index 4885fc1..d2d5d9b 100644
--- a/example/example-numpy-vectorize.ref
+++ b/example/example-numpy-vectorize.ref
@@ -76,3 +76,4 @@
 Int branch taken. 
 Float branch taken. 
 Complex float branch taken. 
+vectorized_func(arg0: numpy.ndarray[int], arg1: numpy.ndarray[float], arg2: numpy.ndarray[float]) -> object
diff --git a/example/example-opaque-types.ref b/example/example-opaque-types.ref
index a6672fd..f8f1692 100644
--- a/example/example-opaque-types.ref
+++ b/example/example-opaque-types.ref
@@ -10,7 +10,7 @@
 Got void ptr : 0x7f9ba0f3c430
 Called ExampleMandA destructor (0)
 Caught expected exception: Incompatible function arguments. The following argument types are supported:
-    1. (capsule) -> NoneType
+    1. (arg0: capsule) -> None
     Invoked with: [1, 2, 3]
 None
 Got null str : 0x0
diff --git a/example/example-python-types.ref b/example/example-python-types.ref
index 2a0237c..a8c39e0 100644
--- a/example/example-python-types.ref
+++ b/example/example-python-types.ref
@@ -34,8 +34,8 @@
  |      x.__init__(...) initializes x; see help(type(x)) for signature
  |  
  |  ggeett__aarrrraayy(...)
- |      Signature : (example.ExamplePythonTypes) -> list<unicode>[2]
  |      
+ |      Signature : (example.ExamplePythonTypes) -> List[unicode[2]]
  |      Return a C++ array
  |  
  |  ggeett__ddiicctt(...)
@@ -44,8 +44,8 @@
  |      Return a Python dictionary
  |  
  |  ggeett__ddiicctt__22(...)
- |      Signature : (example.ExamplePythonTypes) -> dict<unicode, unicode>
  |      
+ |      Signature : (example.ExamplePythonTypes) -> Dict[unicode, unicode]
  |      Return a C++ dictionary
  |  
  |  ggeett__lliisstt(...)
@@ -54,8 +54,8 @@
  |      Return a Python list
  |  
  |  ggeett__lliisstt__22(...)
- |      Signature : (example.ExamplePythonTypes) -> list<unicode>
  |      
+ |      Signature : (example.ExamplePythonTypes) -> List[unicode]
  |      Return a C++ list
  |  
  |  ggeett__sseett(...)
@@ -69,53 +69,53 @@
  |      Return a C++ set
  |  
  |  ppaaiirr__ppaasssstthhrroouugghh(...)
- |      Signature : (example.ExamplePythonTypes, (bool, unicode)) -> (unicode, bool)
  |      
+ |      Signature : (example.ExamplePythonTypes, Tuple[bool, unicode]) -> Tuple[unicode, bool]
  |      Return a pair in reversed order
  |  
  |  pprriinntt__aarrrraayy(...)
- |      Signature : (example.ExamplePythonTypes, list<unicode>[2]) -> NoneType
  |      
+ |      Signature : (example.ExamplePythonTypes, List[unicode[2]]) -> None
  |      Print entries of a C++ array
  |  
  |  pprriinntt__ddiicctt(...)
- |      Signature : (example.ExamplePythonTypes, dict) -> NoneType
  |      
+ |      Signature : (example.ExamplePythonTypes, dict) -> None
  |      Print entries of a Python dictionary
  |  
  |  pprriinntt__ddiicctt__22(...)
- |      Signature : (example.ExamplePythonTypes, dict<unicode, unicode>) -> NoneType
  |      
+ |      Signature : (example.ExamplePythonTypes, Dict[unicode, unicode]) -> None
  |      Print entries of a C++ dictionary
  |  
  |  pprriinntt__lliisstt(...)
- |      Signature : (example.ExamplePythonTypes, list) -> NoneType
  |      
+ |      Signature : (example.ExamplePythonTypes, list) -> None
  |      Print entries of a Python list
  |  
  |  pprriinntt__lliisstt__22(...)
- |      Signature : (example.ExamplePythonTypes, list<unicode>) -> NoneType
  |      
+ |      Signature : (example.ExamplePythonTypes, List[unicode]) -> None
  |      Print entries of a C++ list
  |  
  |  pprriinntt__sseett(...)
- |      Signature : (example.ExamplePythonTypes, set) -> NoneType
  |      
+ |      Signature : (example.ExamplePythonTypes, set) -> None
  |      Print entries of a Python set
  |  
  |  pprriinntt__sseett__22(...)
- |      Signature : (example.ExamplePythonTypes, set<unicode>) -> NoneType
  |      
+ |      Signature : (example.ExamplePythonTypes, Set[unicode]) -> None
  |      Print entries of a C++ set
  |  
  |  tthhrrooww__eexxcceeppttiioonn(...)
- |      Signature : (example.ExamplePythonTypes) -> NoneType
  |      
+ |      Signature : (example.ExamplePythonTypes) -> None
  |      Throw an exception
  |  
  |  ttuuppllee__ppaasssstthhrroouugghh(...)
- |      Signature : (example.ExamplePythonTypes, (bool, unicode, int)) -> (int, unicode, bool)
  |      
+ |      Signature : (example.ExamplePythonTypes, Tuple[bool, unicode, int]) -> Tuple[int, unicode, bool]
  |      Return a triple in reversed order
  |  
  |  ----------------------------------------------------------------------
diff --git a/example/issues.ref b/example/issues.ref
index 90d8ce1..acb1ed0 100644
--- a/example/issues.ref
+++ b/example/issues.ref
@@ -6,7 +6,7 @@
 [3, 5, 7, 9, 11, 13, 15]
 0==0, 1==1, 2==2, 3==3, 4==4, 5==5, 6==6, 7==7, 8==8, 9==9, 
 Failed as expected: Incompatible function arguments. The following argument types are supported:
-    1. (arg0: example.issues.ElementA) -> NoneType
+    1. (arg0: example.issues.ElementA) -> None
     Invoked with: None
 Failed as expected: Incompatible function arguments. The following argument types are supported:
     1. (arg0: int) -> int
diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h
index 91928ad..1127abc 100644
--- a/include/pybind11/cast.h
+++ b/include/pybind11/cast.h
@@ -399,7 +399,7 @@
     static handle cast(void_type, return_value_policy /* policy */, handle /* parent */) {
         return handle(Py_None).inc_ref();
     }
-    PYBIND11_TYPE_CASTER(void_type, _("NoneType"));
+    PYBIND11_TYPE_CASTER(void_type, _("None"));
 };
 
 template <> class type_caster<void> : public type_caster<void_type> {
@@ -440,7 +440,7 @@
 
     template <typename T> using cast_op_type = void*&;
     operator void *&() { return value; }
-    static PYBIND11_DESCR name() { return _("capsule"); }
+    static PYBIND11_DESCR name() { return type_descr(_("capsule")); }
 private:
     void *value = nullptr;
 };
@@ -615,8 +615,8 @@
 
     static PYBIND11_DESCR name() {
         return type_descr(
-            _("(") + type_caster<typename intrinsic_type<T1>::type>::name() +
-            _(", ") + type_caster<typename intrinsic_type<T2>::type>::name() + _(")"));
+            _("Tuple[") + type_caster<typename intrinsic_type<T1>::type>::name() +
+            _(", ") + type_caster<typename intrinsic_type<T2>::type>::name() + _("]"));
     }
 
     template <typename T> using cast_op_type = type;
@@ -671,11 +671,12 @@
         return cast(src, policy, parent, typename make_index_sequence<size>::type());
     }
 
+    static PYBIND11_DESCR element_names() {
+        return detail::concat(type_caster<typename intrinsic_type<Tuple>::type>::name()...);
+    }
+    
     static PYBIND11_DESCR name() {
-        return type_descr(
-               _("(") +
-               detail::concat(type_caster<typename intrinsic_type<Tuple>::type>::name()...) +
-               _(")"));
+        return type_descr(_("Tuple[") + element_names() + _("]"));
     }
 
     template <typename ReturnValue, typename Func> typename std::enable_if<!std::is_void<ReturnValue>::value, ReturnValue>::type call(Func &&f) {
diff --git a/include/pybind11/eigen.h b/include/pybind11/eigen.h
index 9c531fa..41da5c5 100644
--- a/include/pybind11/eigen.h
+++ b/include/pybind11/eigen.h
@@ -161,8 +161,8 @@
         }
     }
 
-    PYBIND11_TYPE_CASTER(Type, _("numpy.ndarray[dtype=") + npy_format_descriptor<Scalar>::name() +
-            _(", shape=(") + rows() + _(", ") + cols() + _(")]"));
+    PYBIND11_TYPE_CASTER(Type, _("numpy.ndarray[") + npy_format_descriptor<Scalar>::name() +
+            _("[") + rows() + _(", ") + cols() + _("]]"));
 
 protected:
     template <typename T = Type, typename std::enable_if<T::RowsAtCompileTime == Eigen::Dynamic, int>::type = 0>
@@ -321,7 +321,7 @@
         ).release();
     }
 
-    PYBIND11_TYPE_CASTER(Type, _<(Type::Flags & Eigen::RowMajorBit) != 0>("scipy.sparse.csr_matrix[dtype=", "scipy.sparse.csc_matrix[dtype=")
+    PYBIND11_TYPE_CASTER(Type, _<(Type::Flags & Eigen::RowMajorBit) != 0>("scipy.sparse.csr_matrix[", "scipy.sparse.csc_matrix[")
             + npy_format_descriptor<Scalar>::name() + _("]"));
 };
 
diff --git a/include/pybind11/functional.h b/include/pybind11/functional.h
index d289f61..e82e520 100644
--- a/include/pybind11/functional.h
+++ b/include/pybind11/functional.h
@@ -65,10 +65,10 @@
             return cpp_function(std::forward<Func>(f_), policy).release();
     }
 
-    PYBIND11_TYPE_CASTER(type, _("function<") +
-            type_caster<std::tuple<Args...>>::name() + _(" -> ") +
+    PYBIND11_TYPE_CASTER(type, _("Callable[[") +
+            type_caster<std::tuple<Args...>>::element_names() + _("], ") +
             type_caster<retval_type>::name() +
-            _(">"));
+            _("]"));
 };
 
 NAMESPACE_END(detail)
diff --git a/include/pybind11/numpy.h b/include/pybind11/numpy.h
index 0180d95..5d355e2 100644
--- a/include/pybind11/numpy.h
+++ b/include/pybind11/numpy.h
@@ -385,7 +385,7 @@
 };
 
 template <typename T, int Flags> struct handle_type_name<array_t<T, Flags>> {
-    static PYBIND11_DESCR name() { return _("numpy.ndarray[dtype=") + type_caster<T>::name() + _("]"); }
+    static PYBIND11_DESCR name() { return _("numpy.ndarray[") + type_caster<T>::name() + _("]"); }
 };
 
 NAMESPACE_END(detail)
diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h
index 26124ae..0016f37 100644
--- a/include/pybind11/pybind11.h
+++ b/include/pybind11/pybind11.h
@@ -135,8 +135,8 @@
         detail::process_attributes<Extra...>::init(extra..., rec);
 
         /* Generate a readable signature describing the function's arguments and return value types */
-        using detail::descr;
-        PYBIND11_DESCR signature = cast_in::name() + detail::_(" -> ") + cast_out::name();
+        using detail::descr; using detail::_;
+        PYBIND11_DESCR signature = _("(") + cast_in::element_names() + _(") -> ") + cast_out::name();
 
         /* Register the function with Python from generic (non-templated) code */
         initialize_generic(rec, signature.text(), signature.types(), sizeof...(Args));
@@ -183,7 +183,7 @@
 
             if (c == '{') {
                 // Write arg name for everything except *args, **kwargs and return type.
-                if (type_depth == 1 && text[char_index] != '*' && arg_index < args) {
+                if (type_depth == 0 && text[char_index] != '*' && arg_index < args) {
                     if (!rec->args.empty()) {
                         signature += rec->args[arg_index].name;
                     } else if (arg_index == 0 && rec->class_) {
@@ -196,7 +196,7 @@
                 ++type_depth;
             } else if (c == '}') {
                 --type_depth;
-                if (type_depth == 1) {
+                if (type_depth == 0) {
                     if (arg_index < rec->args.size() && rec->args[arg_index].descr) {
                         signature += "=";
                         signature += rec->args[arg_index].descr;
diff --git a/include/pybind11/stl.h b/include/pybind11/stl.h
index e0177de..2c47841 100644
--- a/include/pybind11/stl.h
+++ b/include/pybind11/stl.h
@@ -53,7 +53,7 @@
         return s.release();
     }
 
-    PYBIND11_TYPE_CASTER(type, _("set<") + key_conv::name() + _(">"));
+    PYBIND11_TYPE_CASTER(type, _("Set[") + key_conv::name() + _("]"));
 };
 
 template <typename Type, typename Key, typename Value> struct map_caster {
@@ -89,7 +89,7 @@
         return d.release();
     }
 
-    PYBIND11_TYPE_CASTER(type, _("dict<") + key_conv::name() + _(", ") + value_conv::name() + _(">"));
+    PYBIND11_TYPE_CASTER(type, _("Dict[") + key_conv::name() + _(", ") + value_conv::name() + _("]"));
 };
 
 template <typename Type, typename Value> struct list_caster {
@@ -128,7 +128,7 @@
         return l.release();
     }
 
-    PYBIND11_TYPE_CASTER(Type, _("list<") + value_conv::name() + _(">"));
+    PYBIND11_TYPE_CASTER(Type, _("List[") + value_conv::name() + _("]"));
 };
 
 template <typename Type, typename Alloc> struct type_caster<std::vector<Type, Alloc>>
@@ -168,7 +168,7 @@
         }
         return l.release();
     }
-    PYBIND11_TYPE_CASTER(array_type, _("list<") + value_conv::name() + _(">") + _("[") + _<Size>() + _("]"));
+    PYBIND11_TYPE_CASTER(array_type, _("List[") + value_conv::name() + _("[") + _<Size>() + _("]]"));
 };
 
 template <typename Key, typename Compare, typename Alloc> struct type_caster<std::set<Key, Compare, Alloc>>