Accept `let` as an expression
diff --git a/src/expr.rs b/src/expr.rs
index 9440c1c..27dae63 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -41,7 +41,7 @@
     ///     Expr::Cast(expr) => {
     ///         /* ... */
     ///     }
-    ///     Expr::IfLet(expr) => {
+    ///     Expr::If(expr) => {
     ///         /* ... */
     ///     }
     ///     /* ... */
@@ -55,8 +55,8 @@
     /// with the same name `expr` we effectively imbue our variable with all of
     /// the data fields provided by the variant that it turned out to be. So for
     /// example above if we ended up in the `MethodCall` case then we get to use
-    /// `expr.receiver`, `expr.args` etc; if we ended up in the `IfLet` case we
-    /// get to use `expr.pat`, `expr.then_branch`, `expr.else_branch`.
+    /// `expr.receiver`, `expr.args` etc; if we ended up in the `If` case we get
+    /// to use `expr.cond`, `expr.then_branch`, `expr.else_branch`.
     ///
     /// The pattern is similar if the input expression is borrowed:
     ///
@@ -216,11 +216,22 @@
             pub ty: Box<Type>,
         }),
 
+        /// A `let` guard: `let Some(x) = opt`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Let(ExprLet #full {
+            pub attrs: Vec<Attribute>,
+            pub let_token: Token![let],
+            pub pats: Punctuated<Pat, Token![|]>,
+            pub eq_token: Token![=],
+            pub expr: Box<Expr>,
+        }),
+
         /// An `if` expression with an optional `else` block: `if expr { ... }
         /// else { ... }`.
         ///
-        /// The `else` branch expression may only be an `If`, `IfLet`, or
-        /// `Block` expression, not any of the other types of expression.
+        /// The `else` branch expression may only be an `If` or `Block`
+        /// expression, not any of the other types of expression.
         ///
         /// *This type is available if Syn is built with the `"full"` feature.*
         pub If(ExprIf #full {
@@ -231,24 +242,6 @@
             pub else_branch: Option<(Token![else], Box<Expr>)>,
         }),
 
-        /// An `if let` expression with an optional `else` block: `if let pat =
-        /// expr { ... } else { ... }`.
-        ///
-        /// The `else` branch expression may only be an `If`, `IfLet`, or
-        /// `Block` expression, not any of the other types of expression.
-        ///
-        /// *This type is available if Syn is built with the `"full"` feature.*
-        pub IfLet(ExprIfLet #full {
-            pub attrs: Vec<Attribute>,
-            pub if_token: Token![if],
-            pub let_token: Token![let],
-            pub pats: Punctuated<Pat, Token![|]>,
-            pub eq_token: Token![=],
-            pub expr: Box<Expr>,
-            pub then_branch: Block,
-            pub else_branch: Option<(Token![else], Box<Expr>)>,
-        }),
-
         /// A while loop: `while expr { ... }`.
         ///
         /// *This type is available if Syn is built with the `"full"` feature.*
@@ -260,20 +253,6 @@
             pub body: Block,
         }),
 
-        /// A while-let loop: `while let pat = expr { ... }`.
-        ///
-        /// *This type is available if Syn is built with the `"full"` feature.*
-        pub WhileLet(ExprWhileLet #full {
-            pub attrs: Vec<Attribute>,
-            pub label: Option<Label>,
-            pub while_token: Token![while],
-            pub let_token: Token![let],
-            pub pats: Punctuated<Pat, Token![|]>,
-            pub eq_token: Token![=],
-            pub expr: Box<Expr>,
-            pub body: Block,
-        }),
-
         /// A for loop: `for pat in expr { ... }`.
         ///
         /// *This type is available if Syn is built with the `"full"` feature.*
@@ -583,10 +562,9 @@
             | Expr::Lit(ExprLit { ref mut attrs, .. })
             | Expr::Cast(ExprCast { ref mut attrs, .. })
             | Expr::Type(ExprType { ref mut attrs, .. })
+            | Expr::Let(ExprLet { ref mut attrs, .. })
             | Expr::If(ExprIf { ref mut attrs, .. })
-            | Expr::IfLet(ExprIfLet { ref mut attrs, .. })
             | Expr::While(ExprWhile { ref mut attrs, .. })
-            | Expr::WhileLet(ExprWhileLet { ref mut attrs, .. })
             | Expr::ForLoop(ExprForLoop { ref mut attrs, .. })
             | Expr::Loop(ExprLoop { ref mut attrs, .. })
             | Expr::Match(ExprMatch { ref mut attrs, .. })
@@ -1008,10 +986,8 @@
         Expr::Unsafe(..)
         | Expr::Block(..)
         | Expr::If(..)
-        | Expr::IfLet(..)
         | Expr::Match(..)
         | Expr::While(..)
-        | Expr::WhileLet(..)
         | Expr::Loop(..)
         | Expr::ForLoop(..)
         | Expr::Async(..)
@@ -1532,18 +1508,12 @@
             expr_ret(input, allow_struct).map(Expr::Return)
         } else if input.peek(token::Bracket) {
             array_or_repeat(input)
+        } else if input.peek(Token![let]) {
+            input.call(expr_let).map(Expr::Let)
         } else if input.peek(Token![if]) {
-            if input.peek2(Token![let]) {
-                input.call(expr_if_let).map(Expr::IfLet)
-            } else {
-                input.call(expr_if).map(Expr::If)
-            }
+            input.call(expr_if).map(Expr::If)
         } else if input.peek(Token![while]) {
-            if input.peek2(Token![let]) {
-                input.call(expr_while_let).map(Expr::WhileLet)
-            } else {
-                input.call(expr_while).map(Expr::While)
-            }
+            input.call(expr_while).map(Expr::While)
         } else if input.peek(Token![for]) {
             input.call(expr_for_loop).map(Expr::ForLoop)
         } else if input.peek(Token![loop]) {
@@ -1561,11 +1531,7 @@
         } else if input.peek(Lifetime) {
             let the_label: Label = input.parse()?;
             let mut expr = if input.peek(Token![while]) {
-                if input.peek2(Token![let]) {
-                    Expr::WhileLet(input.call(expr_while_let)?)
-                } else {
-                    Expr::While(input.call(expr_while)?)
-                }
+                Expr::While(input.call(expr_while)?)
             } else if input.peek(Token![for]) {
                 Expr::ForLoop(input.call(expr_for_loop)?)
             } else if input.peek(Token![loop]) {
@@ -1576,8 +1542,7 @@
                 return Err(input.error("expected loop or block expression"));
             };
             match expr {
-                Expr::WhileLet(ExprWhileLet { ref mut label, .. })
-                | Expr::While(ExprWhile { ref mut label, .. })
+                Expr::While(ExprWhile { ref mut label, .. })
                 | Expr::ForLoop(ExprForLoop { ref mut label, .. })
                 | Expr::Loop(ExprLoop { ref mut label, .. })
                 | Expr::Block(ExprBlock { ref mut label, .. }) => *label = Some(the_label),
@@ -1741,17 +1706,9 @@
     fn expr_early(input: ParseStream) -> Result<Expr> {
         let mut attrs = input.call(Attribute::parse_outer)?;
         let mut expr = if input.peek(Token![if]) {
-            if input.peek2(Token![let]) {
-                Expr::IfLet(input.call(expr_if_let)?)
-            } else {
-                Expr::If(input.call(expr_if)?)
-            }
+            Expr::If(input.call(expr_if)?)
         } else if input.peek(Token![while]) {
-            if input.peek2(Token![let]) {
-                Expr::WhileLet(input.call(expr_while_let)?)
-            } else {
-                Expr::While(input.call(expr_while)?)
-            }
+            Expr::While(input.call(expr_while)?)
         } else if input.peek(Token![for]) {
             Expr::ForLoop(input.call(expr_for_loop)?)
         } else if input.peek(Token![loop]) {
@@ -1823,10 +1780,9 @@
     }
 
     #[cfg(feature = "full")]
-    fn expr_if_let(input: ParseStream) -> Result<ExprIfLet> {
-        Ok(ExprIfLet {
+    fn expr_let(input: ParseStream) -> Result<ExprLet> {
+        Ok(ExprLet {
             attrs: Vec::new(),
-            if_token: input.parse()?,
             let_token: input.parse()?,
             pats: {
                 let mut pats = Punctuated::new();
@@ -1842,14 +1798,6 @@
             },
             eq_token: input.parse()?,
             expr: Box::new(input.call(expr_no_struct)?),
-            then_branch: input.parse()?,
-            else_branch: {
-                if input.peek(Token![else]) {
-                    Some(input.call(else_block)?)
-                } else {
-                    None
-                }
-            },
         })
     }
 
@@ -1876,11 +1824,7 @@
 
         let lookahead = input.lookahead1();
         let else_branch = if input.peek(Token![if]) {
-            if input.peek2(Token![let]) {
-                input.call(expr_if_let).map(Expr::IfLet)?
-            } else {
-                input.call(expr_if).map(Expr::If)?
-            }
+            input.call(expr_if).map(Expr::If)?
         } else if input.peek(token::Brace) {
             Expr::Block(ExprBlock {
                 attrs: Vec::new(),
@@ -2140,45 +2084,6 @@
     }
 
     #[cfg(feature = "full")]
-    fn expr_while_let(input: ParseStream) -> Result<ExprWhileLet> {
-        let label: Option<Label> = input.parse()?;
-        let while_token: Token![while] = input.parse()?;
-        let let_token: Token![let] = input.parse()?;
-
-        let mut pats = Punctuated::new();
-        let value: Pat = input.parse()?;
-        pats.push_value(value);
-        while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
-            let punct = input.parse()?;
-            pats.push_punct(punct);
-            let value: Pat = input.parse()?;
-            pats.push_value(value);
-        }
-
-        let eq_token: Token![=] = input.parse()?;
-        let expr = expr_no_struct(input)?;
-
-        let content;
-        let brace_token = braced!(content in input);
-        let inner_attrs = content.call(Attribute::parse_inner)?;
-        let stmts = content.call(Block::parse_within)?;
-
-        Ok(ExprWhileLet {
-            attrs: inner_attrs,
-            label: label,
-            while_token: while_token,
-            let_token: let_token,
-            pats: pats,
-            eq_token: eq_token,
-            expr: Box::new(expr),
-            body: Block {
-                brace_token: brace_token,
-                stmts: stmts,
-            },
-        })
-    }
-
-    #[cfg(feature = "full")]
     impl Parse for Label {
         fn parse(input: ParseStream) -> Result<Self> {
             Ok(Label {
@@ -3204,7 +3109,7 @@
             // If we are not one of the valid expressions to exist in an else
             // clause, wrap ourselves in a block.
             match **else_ {
-                Expr::If(_) | Expr::IfLet(_) | Expr::Block(_) => {
+                Expr::If(_) | Expr::Block(_) => {
                     else_.to_tokens(tokens);
                 }
                 _ => {
@@ -3217,6 +3122,17 @@
     }
 
     #[cfg(feature = "full")]
+    impl ToTokens for ExprLet {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.let_token.to_tokens(tokens);
+            self.pats.to_tokens(tokens);
+            self.eq_token.to_tokens(tokens);
+            wrap_bare_struct(tokens, &self.expr);
+        }
+    }
+
+    #[cfg(feature = "full")]
     impl ToTokens for ExprIf {
         fn to_tokens(&self, tokens: &mut TokenStream) {
             outer_attrs_to_tokens(&self.attrs, tokens);
@@ -3228,20 +3144,6 @@
     }
 
     #[cfg(feature = "full")]
-    impl ToTokens for ExprIfLet {
-        fn to_tokens(&self, tokens: &mut TokenStream) {
-            outer_attrs_to_tokens(&self.attrs, tokens);
-            self.if_token.to_tokens(tokens);
-            self.let_token.to_tokens(tokens);
-            self.pats.to_tokens(tokens);
-            self.eq_token.to_tokens(tokens);
-            wrap_bare_struct(tokens, &self.expr);
-            self.then_branch.to_tokens(tokens);
-            maybe_wrap_else(tokens, &self.else_branch);
-        }
-    }
-
-    #[cfg(feature = "full")]
     impl ToTokens for ExprWhile {
         fn to_tokens(&self, tokens: &mut TokenStream) {
             outer_attrs_to_tokens(&self.attrs, tokens);
@@ -3256,23 +3158,6 @@
     }
 
     #[cfg(feature = "full")]
-    impl ToTokens for ExprWhileLet {
-        fn to_tokens(&self, tokens: &mut TokenStream) {
-            outer_attrs_to_tokens(&self.attrs, tokens);
-            self.label.to_tokens(tokens);
-            self.while_token.to_tokens(tokens);
-            self.let_token.to_tokens(tokens);
-            self.pats.to_tokens(tokens);
-            self.eq_token.to_tokens(tokens);
-            wrap_bare_struct(tokens, &self.expr);
-            self.body.brace_token.surround(tokens, |tokens| {
-                inner_attrs_to_tokens(&self.attrs, tokens);
-                tokens.append_all(&self.body.stmts);
-            });
-        }
-    }
-
-    #[cfg(feature = "full")]
     impl ToTokens for ExprForLoop {
         fn to_tokens(&self, tokens: &mut TokenStream) {
             outer_attrs_to_tokens(&self.attrs, tokens);