Parse associated type bounds in path
diff --git a/src/gen/fold.rs b/src/gen/fold.rs
index df96cc3..2b65e2e 100644
--- a/src/gen/fold.rs
+++ b/src/gen/fold.rs
@@ -93,6 +93,10 @@
     fn fold_const_param(&mut self, i: ConstParam) -> ConstParam {
         fold_const_param(self, i)
     }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_constraint(&mut self, i: Constraint) -> Constraint {
+        fold_constraint(self, i)
+    }
     #[cfg(feature = "derive")]
     fn fold_data(&mut self, i: Data) -> Data {
         fold_data(self, i)
@@ -1126,6 +1130,14 @@
         default: (_i.default).map(|it| _visitor.fold_expr(it)),
     }
 }
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_constraint<V: Fold + ?Sized>(_visitor: &mut V, _i: Constraint) -> Constraint {
+    Constraint {
+        ident: _visitor.fold_ident(_i.ident),
+        colon_token: Token ! [ : ](tokens_helper(_visitor, &_i.colon_token.spans)),
+        bounds: FoldHelper::lift(_i.bounds, |it| _visitor.fold_type_param_bound(it)),
+    }
+}
 #[cfg(feature = "derive")]
 pub fn fold_data<V: Fold + ?Sized>(_visitor: &mut V, _i: Data) -> Data {
     match _i {
@@ -1787,6 +1799,9 @@
         GenericArgument::Binding(_binding_0) => {
             GenericArgument::Binding(_visitor.fold_binding(_binding_0))
         }
+        GenericArgument::Constraint(_binding_0) => {
+            GenericArgument::Constraint(_visitor.fold_constraint(_binding_0))
+        }
         GenericArgument::Const(_binding_0) => {
             GenericArgument::Const(_visitor.fold_expr(_binding_0))
         }
diff --git a/src/gen/visit.rs b/src/gen/visit.rs
index 90b2607..ec84cd2 100644
--- a/src/gen/visit.rs
+++ b/src/gen/visit.rs
@@ -93,6 +93,10 @@
     fn visit_const_param(&mut self, i: &'ast ConstParam) {
         visit_const_param(self, i)
     }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_constraint(&mut self, i: &'ast Constraint) {
+        visit_constraint(self, i)
+    }
     #[cfg(feature = "derive")]
     fn visit_data(&mut self, i: &'ast Data) {
         visit_data(self, i)
@@ -1107,6 +1111,15 @@
         _visitor.visit_expr(it)
     };
 }
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_constraint<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast Constraint) {
+    _visitor.visit_ident(&_i.ident);
+    tokens_helper(_visitor, &_i.colon_token.spans);
+    for el in Punctuated::pairs(&_i.bounds) {
+        let it = el.value();
+        _visitor.visit_type_param_bound(it)
+    }
+}
 #[cfg(feature = "derive")]
 pub fn visit_data<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast Data) {
     match *_i {
@@ -1959,6 +1972,9 @@
         GenericArgument::Binding(ref _binding_0) => {
             _visitor.visit_binding(_binding_0);
         }
+        GenericArgument::Constraint(ref _binding_0) => {
+            _visitor.visit_constraint(_binding_0);
+        }
         GenericArgument::Const(ref _binding_0) => {
             _visitor.visit_expr(_binding_0);
         }
diff --git a/src/gen/visit_mut.rs b/src/gen/visit_mut.rs
index 9380c7e..4668c9b 100644
--- a/src/gen/visit_mut.rs
+++ b/src/gen/visit_mut.rs
@@ -97,6 +97,10 @@
     fn visit_const_param_mut(&mut self, i: &mut ConstParam) {
         visit_const_param_mut(self, i)
     }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_constraint_mut(&mut self, i: &mut Constraint) {
+        visit_constraint_mut(self, i)
+    }
     #[cfg(feature = "derive")]
     fn visit_data_mut(&mut self, i: &mut Data) {
         visit_data_mut(self, i)
@@ -1105,6 +1109,15 @@
         _visitor.visit_expr_mut(it)
     };
 }
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_constraint_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut Constraint) {
+    _visitor.visit_ident_mut(&mut _i.ident);
+    tokens_helper(_visitor, &mut _i.colon_token.spans);
+    for mut el in Punctuated::pairs_mut(&mut _i.bounds) {
+        let it = el.value_mut();
+        _visitor.visit_type_param_bound_mut(it)
+    }
+}
 #[cfg(feature = "derive")]
 pub fn visit_data_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut Data) {
     match *_i {
@@ -1933,6 +1946,9 @@
         GenericArgument::Binding(ref mut _binding_0) => {
             _visitor.visit_binding_mut(_binding_0);
         }
+        GenericArgument::Constraint(ref mut _binding_0) => {
+            _visitor.visit_constraint_mut(_binding_0);
+        }
         GenericArgument::Const(ref mut _binding_0) => {
             _visitor.visit_expr_mut(_binding_0);
         }
diff --git a/src/lib.rs b/src/lib.rs
index 2f05a3a..21621f0 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -427,8 +427,8 @@
 mod path;
 #[cfg(any(feature = "full", feature = "derive"))]
 pub use path::{
-    AngleBracketedGenericArguments, Binding, GenericArgument, ParenthesizedGenericArguments, Path,
-    PathArguments, PathSegment, QSelf,
+    AngleBracketedGenericArguments, Binding, Constraint, GenericArgument,
+    ParenthesizedGenericArguments, Path, PathArguments, PathSegment, QSelf,
 };
 
 #[cfg(feature = "parsing")]
diff --git a/src/path.rs b/src/path.rs
index 443bac6..693d71c 100644
--- a/src/path.rs
+++ b/src/path.rs
@@ -108,6 +108,8 @@
         /// A binding (equality constraint) on an associated type: the `Item =
         /// u8` in `Iterator<Item = u8>`.
         Binding(Binding),
+        /// An associated type bound: `Iterator<Item: Display>`.
+        Constraint(Constraint),
         /// A const expression. Must be inside of a block.
         ///
         /// NOTE: Identity expressions are represented as Type arguments, as
@@ -143,6 +145,18 @@
 }
 
 ast_struct! {
+    /// An associated type bound: `Iterator<Item: Display>`.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    pub struct Constraint {
+        pub ident: Ident,
+        pub colon_token: Token![:],
+        pub bounds: Punctuated<TypeParamBound, Token![+]>,
+    }
+}
+
+ast_struct! {
     /// Arguments of a function path segment: the `(A, B) -> C` in `Fn(A,B) ->
     /// C`.
     ///
@@ -213,6 +227,10 @@
 
             #[cfg(feature = "full")]
             {
+                if input.peek(Ident) && input.peek2(Token![:]) && !input.peek2(Token![::]) {
+                    return Ok(GenericArgument::Constraint(input.parse()?));
+                }
+
                 if input.peek(Lit) {
                     let lit = input.call(expr::parsing::expr_lit)?;
                     return Ok(GenericArgument::Const(Expr::Lit(lit)));
@@ -307,6 +325,32 @@
         }
     }
 
+    #[cfg(feature = "full")]
+    impl Parse for Constraint {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(Constraint {
+                ident: input.parse()?,
+                colon_token: input.parse()?,
+                bounds: {
+                    let mut bounds = Punctuated::new();
+                    loop {
+                        if input.peek(Token![,]) || input.peek(Token![>]) {
+                            break;
+                        }
+                        let value = input.parse()?;
+                        bounds.push_value(value);
+                        if !input.peek(Token![+]) {
+                            break;
+                        }
+                        let punct = input.parse()?;
+                        bounds.push_punct(punct);
+                    }
+                    bounds
+                },
+            })
+        }
+    }
+
     impl Path {
         /// Parse a `Path` containing no path arguments on any of its segments.
         ///
@@ -498,6 +542,7 @@
                 GenericArgument::Lifetime(ref lt) => lt.to_tokens(tokens),
                 GenericArgument::Type(ref ty) => ty.to_tokens(tokens),
                 GenericArgument::Binding(ref tb) => tb.to_tokens(tokens),
+                GenericArgument::Constraint(ref tc) => tc.to_tokens(tokens),
                 GenericArgument::Const(ref e) => match *e {
                     Expr::Lit(_) => e.to_tokens(tokens),
 
@@ -529,9 +574,15 @@
             // not been settled yet. https://github.com/rust-lang/rust/issues/44580
             let mut trailing_or_empty = true;
             for param in self.args.pairs() {
-                if let GenericArgument::Lifetime(_) = **param.value() {
-                    param.to_tokens(tokens);
-                    trailing_or_empty = param.punct().is_some();
+                match **param.value() {
+                    GenericArgument::Lifetime(_) => {
+                        param.to_tokens(tokens);
+                        trailing_or_empty = param.punct().is_some();
+                    }
+                    GenericArgument::Type(_)
+                    | GenericArgument::Binding(_)
+                    | GenericArgument::Constraint(_)
+                    | GenericArgument::Const(_) => {}
                 }
             }
             for param in self.args.pairs() {
@@ -543,16 +594,23 @@
                         param.to_tokens(tokens);
                         trailing_or_empty = param.punct().is_some();
                     }
-                    GenericArgument::Lifetime(_) | GenericArgument::Binding(_) => {}
+                    GenericArgument::Lifetime(_)
+                    | GenericArgument::Binding(_)
+                    | GenericArgument::Constraint(_) => {}
                 }
             }
             for param in self.args.pairs() {
-                if let GenericArgument::Binding(_) = **param.value() {
-                    if !trailing_or_empty {
-                        <Token![,]>::default().to_tokens(tokens);
-                        trailing_or_empty = true;
+                match **param.value() {
+                    GenericArgument::Binding(_) | GenericArgument::Constraint(_) => {
+                        if !trailing_or_empty {
+                            <Token![,]>::default().to_tokens(tokens);
+                            trailing_or_empty = true;
+                        }
+                        param.to_tokens(tokens);
                     }
-                    param.to_tokens(tokens);
+                    GenericArgument::Lifetime(_)
+                    | GenericArgument::Type(_)
+                    | GenericArgument::Const(_) => {}
                 }
             }
 
@@ -568,6 +626,14 @@
         }
     }
 
+    impl ToTokens for Constraint {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.ident.to_tokens(tokens);
+            self.colon_token.to_tokens(tokens);
+            self.bounds.to_tokens(tokens);
+        }
+    }
+
     impl ToTokens for ParenthesizedGenericArguments {
         fn to_tokens(&self, tokens: &mut TokenStream) {
             self.paren_token.surround(tokens, |tokens| {