Support method turbofish with const generics
diff --git a/src/expr.rs b/src/expr.rs
index 016d063..76c666f 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -48,10 +48,7 @@
             pub receiver: Box<Expr>,
             pub dot_token: Token![.],
             pub method: Ident,
-            pub colon2_token: Option<Token![::]>,
-            pub lt_token: Option<Token![<]>,
-            pub typarams: Delimited<Type, Token![,]>,
-            pub gt_token: Option<Token![>]>,
+            pub turbofish: Option<MethodTurbofish>,
             pub paren_token: token::Paren,
             pub args: Delimited<Expr, Token![,]>,
         }),
@@ -468,6 +465,30 @@
 
 #[cfg(feature = "full")]
 ast_struct! {
+    pub struct MethodTurbofish {
+        pub colon2_token: Token![::],
+        pub lt_token: Token![<],
+        pub args: Delimited<GenericMethodArgument, Token![,]>,
+        pub gt_token: Token![>],
+    }
+}
+
+#[cfg(feature = "full")]
+ast_enum! {
+    /// A individual generic argument like `T`.
+    pub enum GenericMethodArgument {
+        /// The type parameters for this path segment, if present.
+        Type(Type),
+        /// Const expression. Must be inside of a block.
+        ///
+        /// NOTE: Identity expressions are represented as Type arguments, as
+        /// they are indistinguishable syntactically.
+        Const(Expr),
+    }
+}
+
+#[cfg(feature = "full")]
+ast_struct! {
     /// A field-value pair in a struct literal.
     pub struct FieldValue {
         /// Attributes tagged on the field.
@@ -727,7 +748,7 @@
 #[cfg(feature = "parsing")]
 pub mod parsing {
     use super::*;
-    use ty::parsing::qpath;
+    use ty::parsing::{qpath, ty_no_eq_after};
 
     #[cfg(feature = "full")]
     use proc_macro2::{Delimiter, Span, TokenNode, TokenStream};
@@ -1388,19 +1409,14 @@
     named!(and_method_call -> ExprMethodCall, do_parse!(
         dot: punct!(.) >>
         method: syn!(Ident) >>
-        typarams: option!(do_parse!(
-            colon2: punct!(::) >>
-            lt: punct!(<) >>
-            tys: call!(Delimited::parse_terminated) >>
-            gt: punct!(>) >>
-            (colon2, lt, tys, gt)
+        turbofish: option!(tuple!(
+            punct!(::),
+            punct!(<),
+            call!(Delimited::parse_terminated),
+            punct!(>)
         )) >>
         args: parens!(call!(Delimited::parse_terminated)) >>
         ({
-            let (colon2, lt, tys, gt) = match typarams {
-                Some((a, b, c, d)) => (Some(a), Some(b), Some(c), Some(d)),
-                None => (None, None, None, None),
-            };
             ExprMethodCall {
                 attrs: Vec::new(),
                 // this expr will get overwritten after being returned
@@ -1413,18 +1429,26 @@
                 }).into()),
 
                 method: method,
+                turbofish: turbofish.map(|fish| MethodTurbofish {
+                    colon2_token: fish.0,
+                    lt_token: fish.1,
+                    args: fish.2,
+                    gt_token: fish.3,
+                }),
                 args: args.0,
                 paren_token: args.1,
                 dot_token: dot,
-                lt_token: lt,
-                gt_token: gt,
-                colon2_token: colon2,
-                typarams: tys.unwrap_or_default(),
             }
         })
     ));
 
     #[cfg(feature = "full")]
+    impl Synom for GenericMethodArgument {
+        // TODO parse const generics as well
+        named!(parse -> Self, map!(ty_no_eq_after, GenericMethodArgument::Type));
+    }
+
+    #[cfg(feature = "full")]
     impl Synom for ExprTuple {
         named!(parse -> Self, do_parse!(
             elems: parens!(call!(Delimited::parse_terminated)) >>
@@ -2452,12 +2476,7 @@
             self.receiver.to_tokens(tokens);
             self.dot_token.to_tokens(tokens);
             self.method.to_tokens(tokens);
-            if !self.typarams.is_empty() {
-                TokensOrDefault(&self.colon2_token).to_tokens(tokens);
-                TokensOrDefault(&self.lt_token).to_tokens(tokens);
-                self.typarams.to_tokens(tokens);
-                TokensOrDefault(&self.gt_token).to_tokens(tokens);
-            }
+            self.turbofish.to_tokens(tokens);
             self.paren_token.surround(tokens, |tokens| {
                 self.args.to_tokens(tokens);
             });
@@ -2465,6 +2484,26 @@
     }
 
     #[cfg(feature = "full")]
+    impl ToTokens for MethodTurbofish {
+        fn to_tokens(&self, tokens: &mut Tokens) {
+            self.colon2_token.to_tokens(tokens);
+            self.lt_token.to_tokens(tokens);
+            self.args.to_tokens(tokens);
+            self.gt_token.to_tokens(tokens);
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for GenericMethodArgument {
+        fn to_tokens(&self, tokens: &mut Tokens) {
+            match *self {
+                GenericMethodArgument::Type(ref t) => t.to_tokens(tokens),
+                GenericMethodArgument::Const(ref c) => c.to_tokens(tokens),
+            }
+        }
+    }
+
+    #[cfg(feature = "full")]
     impl ToTokens for ExprTuple {
         fn to_tokens(&self, tokens: &mut Tokens) {
             tokens.append_all(self.attrs.outer());
diff --git a/src/gen/fold.rs b/src/gen/fold.rs
index 54993ef..25ddbc6 100644
--- a/src/gen/fold.rs
+++ b/src/gen/fold.rs
@@ -189,6 +189,8 @@
 fn fold_foreign_item_type(&mut self, i: ForeignItemType) -> ForeignItemType { fold_foreign_item_type(self, i) }
 
 fn fold_generic_argument(&mut self, i: GenericArgument) -> GenericArgument { fold_generic_argument(self, i) }
+# [ cfg ( feature = "full" ) ]
+fn fold_generic_method_argument(&mut self, i: GenericMethodArgument) -> GenericMethodArgument { fold_generic_method_argument(self, i) }
 
 fn fold_generic_param(&mut self, i: GenericParam) -> GenericParam { fold_generic_param(self, i) }
 
@@ -263,6 +265,8 @@
 fn fold_meta_name_value(&mut self, i: MetaNameValue) -> MetaNameValue { fold_meta_name_value(self, i) }
 # [ cfg ( feature = "full" ) ]
 fn fold_method_sig(&mut self, i: MethodSig) -> MethodSig { fold_method_sig(self, i) }
+# [ cfg ( feature = "full" ) ]
+fn fold_method_turbofish(&mut self, i: MethodTurbofish) -> MethodTurbofish { fold_method_turbofish(self, i) }
 
 fn fold_mut_type(&mut self, i: MutType) -> MutType { fold_mut_type(self, i) }
 
@@ -1221,10 +1225,7 @@
         receiver: Box::new(_visitor.fold_expr(* _i . receiver)),
         dot_token: Token ! [ . ](tokens_helper(_visitor, &(_i . dot_token).0)),
         method: _visitor.fold_ident(_i . method),
-        colon2_token: (_i . colon2_token).map(|it| { Token ! [ :: ](tokens_helper(_visitor, &(it).0)) }),
-        lt_token: (_i . lt_token).map(|it| { Token ! [ < ](tokens_helper(_visitor, &(it).0)) }),
-        typarams: FoldHelper::lift(_i . typarams, |it| { _visitor.fold_type(it) }),
-        gt_token: (_i . gt_token).map(|it| { Token ! [ > ](tokens_helper(_visitor, &(it).0)) }),
+        turbofish: (_i . turbofish).map(|it| { _visitor.fold_method_turbofish(it) }),
         paren_token: Paren(tokens_helper(_visitor, &(_i . paren_token).0)),
         args: FoldHelper::lift(_i . args, |it| { _visitor.fold_expr(it) }),
     }
@@ -1517,6 +1518,22 @@
         }
     }
 }
+# [ cfg ( feature = "full" ) ]
+pub fn fold_generic_method_argument<V: Folder + ?Sized>(_visitor: &mut V, _i: GenericMethodArgument) -> GenericMethodArgument {
+    use ::GenericMethodArgument::*;
+    match _i {
+        Type(_binding_0, ) => {
+            Type (
+                _visitor.fold_type(_binding_0),
+            )
+        }
+        Const(_binding_0, ) => {
+            Const (
+                _visitor.fold_expr(_binding_0),
+            )
+        }
+    }
+}
 
 pub fn fold_generic_param<V: Folder + ?Sized>(_visitor: &mut V, _i: GenericParam) -> GenericParam {
     use ::GenericParam::*;
@@ -2045,6 +2062,15 @@
         decl: _visitor.fold_fn_decl(_i . decl),
     }
 }
+# [ cfg ( feature = "full" ) ]
+pub fn fold_method_turbofish<V: Folder + ?Sized>(_visitor: &mut V, _i: MethodTurbofish) -> MethodTurbofish {
+    MethodTurbofish {
+        colon2_token: Token ! [ :: ](tokens_helper(_visitor, &(_i . colon2_token).0)),
+        lt_token: Token ! [ < ](tokens_helper(_visitor, &(_i . lt_token).0)),
+        args: FoldHelper::lift(_i . args, |it| { _visitor.fold_generic_method_argument(it) }),
+        gt_token: Token ! [ > ](tokens_helper(_visitor, &(_i . gt_token).0)),
+    }
+}
 
 pub fn fold_mut_type<V: Folder + ?Sized>(_visitor: &mut V, _i: MutType) -> MutType {
     MutType {
diff --git a/src/gen/visit.rs b/src/gen/visit.rs
index b6fc36d..d00b2b2 100644
--- a/src/gen/visit.rs
+++ b/src/gen/visit.rs
@@ -185,6 +185,8 @@
 fn visit_foreign_item_type(&mut self, i: &'ast ForeignItemType) { visit_foreign_item_type(self, i) }
 
 fn visit_generic_argument(&mut self, i: &'ast GenericArgument) { visit_generic_argument(self, i) }
+# [ cfg ( feature = "full" ) ]
+fn visit_generic_method_argument(&mut self, i: &'ast GenericMethodArgument) { visit_generic_method_argument(self, i) }
 
 fn visit_generic_param(&mut self, i: &'ast GenericParam) { visit_generic_param(self, i) }
 
@@ -259,6 +261,8 @@
 fn visit_meta_name_value(&mut self, i: &'ast MetaNameValue) { visit_meta_name_value(self, i) }
 # [ cfg ( feature = "full" ) ]
 fn visit_method_sig(&mut self, i: &'ast MethodSig) { visit_method_sig(self, i) }
+# [ cfg ( feature = "full" ) ]
+fn visit_method_turbofish(&mut self, i: &'ast MethodTurbofish) { visit_method_turbofish(self, i) }
 
 fn visit_mut_type(&mut self, i: &'ast MutType) { visit_mut_type(self, i) }
 
@@ -982,10 +986,7 @@
     _visitor.visit_expr(& * _i . receiver);
     tokens_helper(_visitor, &(& _i . dot_token).0);
     _visitor.visit_ident(& _i . method);
-    if let Some(ref it) = _i . colon2_token { tokens_helper(_visitor, &(it).0) };
-    if let Some(ref it) = _i . lt_token { tokens_helper(_visitor, &(it).0) };
-    for el in & _i . typarams { let it = el.item(); _visitor.visit_type(it) };
-    if let Some(ref it) = _i . gt_token { tokens_helper(_visitor, &(it).0) };
+    if let Some(ref it) = _i . turbofish { _visitor.visit_method_turbofish(it) };
     tokens_helper(_visitor, &(& _i . paren_token).0);
     for el in & _i . args { let it = el.item(); _visitor.visit_expr(it) };
 }
@@ -1209,6 +1210,18 @@
         }
     }
 }
+# [ cfg ( feature = "full" ) ]
+pub fn visit_generic_method_argument<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast GenericMethodArgument) {
+    use ::GenericMethodArgument::*;
+    match *_i {
+        Type(ref _binding_0, ) => {
+            _visitor.visit_type(_binding_0);
+        }
+        Const(ref _binding_0, ) => {
+            _visitor.visit_expr(_binding_0);
+        }
+    }
+}
 
 pub fn visit_generic_param<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast GenericParam) {
     use ::GenericParam::*;
@@ -1617,6 +1630,13 @@
     _visitor.visit_ident(& _i . ident);
     _visitor.visit_fn_decl(& _i . decl);
 }
+# [ cfg ( feature = "full" ) ]
+pub fn visit_method_turbofish<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast MethodTurbofish) {
+    tokens_helper(_visitor, &(& _i . colon2_token).0);
+    tokens_helper(_visitor, &(& _i . lt_token).0);
+    for el in & _i . args { let it = el.item(); _visitor.visit_generic_method_argument(it) };
+    tokens_helper(_visitor, &(& _i . gt_token).0);
+}
 
 pub fn visit_mut_type<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast MutType) {
     _visitor.visit_mutability(& _i . mutability);
diff --git a/src/gen/visit_mut.rs b/src/gen/visit_mut.rs
index 0eff02e..353c246 100644
--- a/src/gen/visit_mut.rs
+++ b/src/gen/visit_mut.rs
@@ -185,6 +185,8 @@
 fn visit_foreign_item_type_mut(&mut self, i: &mut ForeignItemType) { visit_foreign_item_type_mut(self, i) }
 
 fn visit_generic_argument_mut(&mut self, i: &mut GenericArgument) { visit_generic_argument_mut(self, i) }
+# [ cfg ( feature = "full" ) ]
+fn visit_generic_method_argument_mut(&mut self, i: &mut GenericMethodArgument) { visit_generic_method_argument_mut(self, i) }
 
 fn visit_generic_param_mut(&mut self, i: &mut GenericParam) { visit_generic_param_mut(self, i) }
 
@@ -259,6 +261,8 @@
 fn visit_meta_name_value_mut(&mut self, i: &mut MetaNameValue) { visit_meta_name_value_mut(self, i) }
 # [ cfg ( feature = "full" ) ]
 fn visit_method_sig_mut(&mut self, i: &mut MethodSig) { visit_method_sig_mut(self, i) }
+# [ cfg ( feature = "full" ) ]
+fn visit_method_turbofish_mut(&mut self, i: &mut MethodTurbofish) { visit_method_turbofish_mut(self, i) }
 
 fn visit_mut_type_mut(&mut self, i: &mut MutType) { visit_mut_type_mut(self, i) }
 
@@ -982,10 +986,7 @@
     _visitor.visit_expr_mut(& mut * _i . receiver);
     tokens_helper(_visitor, &mut (& mut _i . dot_token).0);
     _visitor.visit_ident_mut(& mut _i . method);
-    if let Some(ref mut it) = _i . colon2_token { tokens_helper(_visitor, &mut (it).0) };
-    if let Some(ref mut it) = _i . lt_token { tokens_helper(_visitor, &mut (it).0) };
-    for mut el in & mut _i . typarams { let it = el.item_mut(); _visitor.visit_type_mut(it) };
-    if let Some(ref mut it) = _i . gt_token { tokens_helper(_visitor, &mut (it).0) };
+    if let Some(ref mut it) = _i . turbofish { _visitor.visit_method_turbofish_mut(it) };
     tokens_helper(_visitor, &mut (& mut _i . paren_token).0);
     for mut el in & mut _i . args { let it = el.item_mut(); _visitor.visit_expr_mut(it) };
 }
@@ -1209,6 +1210,18 @@
         }
     }
 }
+# [ cfg ( feature = "full" ) ]
+pub fn visit_generic_method_argument_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut GenericMethodArgument) {
+    use ::GenericMethodArgument::*;
+    match *_i {
+        Type(ref mut _binding_0, ) => {
+            _visitor.visit_type_mut(_binding_0);
+        }
+        Const(ref mut _binding_0, ) => {
+            _visitor.visit_expr_mut(_binding_0);
+        }
+    }
+}
 
 pub fn visit_generic_param_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut GenericParam) {
     use ::GenericParam::*;
@@ -1617,6 +1630,13 @@
     _visitor.visit_ident_mut(& mut _i . ident);
     _visitor.visit_fn_decl_mut(& mut _i . decl);
 }
+# [ cfg ( feature = "full" ) ]
+pub fn visit_method_turbofish_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut MethodTurbofish) {
+    tokens_helper(_visitor, &mut (& mut _i . colon2_token).0);
+    tokens_helper(_visitor, &mut (& mut _i . lt_token).0);
+    for mut el in & mut _i . args { let it = el.item_mut(); _visitor.visit_generic_method_argument_mut(it) };
+    tokens_helper(_visitor, &mut (& mut _i . gt_token).0);
+}
 
 pub fn visit_mut_type_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut MutType) {
     _visitor.visit_mutability_mut(& mut _i . mutability);
diff --git a/src/lib.rs b/src/lib.rs
index 8fbed2b..8350b7b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -41,8 +41,8 @@
                ExprUnary, ExprUnsafe, ExprWhile, ExprWhileLet, ExprYield};
 
 #[cfg(feature = "full")]
-pub use expr::{Arm, BindingMode, Block, CaptureBy, FieldPat, FieldValue, Index, Local,
-               Member, Pat, PatBox, PatIdent, PatLit, PatPath, PatRange, PatRef, PatSlice,
+pub use expr::{Arm, BindingMode, Block, CaptureBy, FieldPat, FieldValue, GenericMethodArgument, Index, Local,
+               Member, MethodTurbofish, Pat, PatBox, PatIdent, PatLit, PatPath, PatRange, PatRef, PatSlice,
                PatStruct, PatTuple, PatTupleStruct, PatWild, RangeLimits, Stmt};
 
 mod generics;
diff --git a/src/ty.rs b/src/ty.rs
index 5448a3a..a474156 100644
--- a/src/ty.rs
+++ b/src/ty.rs
@@ -731,7 +731,7 @@
         ));
     }
 
-    named!(ty_no_eq_after -> Type, terminated!(syn!(Type), not!(punct!(=))));
+    named!(pub ty_no_eq_after -> Type, terminated!(syn!(Type), not!(punct!(=))));
 
     impl Path {
         named!(pub parse_mod_style -> Self, do_parse!(