diff --git a/maud_macros/src/parse.rs b/maud_macros/src/parse.rs
index 26c1460..0fba573 100644
--- a/maud_macros/src/parse.rs
+++ b/maud_macros/src/parse.rs
@@ -1,5 +1,6 @@
 use std::mem;
 use syntax::ast::{Expr, ExprParen, Lit, Stmt, TokenTree, TtDelimited, TtToken};
+use syntax::ext::quote::rt::ToTokens;
 use syntax::codemap::Span;
 use syntax::ext::base::ExtCtxt;
 use syntax::parse;
@@ -152,7 +153,7 @@ impl<'cx, 's, 'i> Parser<'cx, 's, 'i> {
 
     fn if_expr(&mut self, sp: Span) {
         // Parse the initial if
-        let mut cond_tts = vec![];
+        let mut if_cond = vec![];
         let if_body;
         loop { match self.input {
             [TtDelimited(sp, ref d), ..] if d.delim == DelimToken::Brace => {
@@ -162,11 +163,10 @@ impl<'cx, 's, 'i> Parser<'cx, 's, 'i> {
             },
             [ref tt, ..] => {
                 self.shift(1);
-                cond_tts.push(tt.clone());
+                if_cond.push(tt.clone());
             },
             [] => self.render.cx.span_fatal(sp, "expected body for this $if"),
         }}
-        let if_cond = self.new_rust_parser(cond_tts).parse_expr();
         // Parse the (optional) else
         let else_body = match self.input {
             [dollar!(), ident!(else_), ..] if else_.as_str() == "else" => {
@@ -298,7 +298,7 @@ impl<'cx, 's, 'i> Parser<'cx, 's, 'i> {
                     self.shift(1);
                     let cond = self.splice(tt.get_span());
                     // Silence "unnecessary parentheses" warnings
-                    let cond = strip_outer_parens(cond);
+                    let cond = strip_outer_parens(cond).to_tokens(self.render.cx);
                     let body = {
                         let mut r = self.render.fork();
                         r.attribute_empty(name.as_str());
diff --git a/maud_macros/src/render.rs b/maud_macros/src/render.rs
index 20b9810..de3972f 100644
--- a/maud_macros/src/render.rs
+++ b/maud_macros/src/render.rs
@@ -1,4 +1,4 @@
-use syntax::ast::{Expr, Ident, Pat, Stmt};
+use syntax::ast::{Expr, Ident, Pat, Stmt, TokenTree};
 use syntax::ext::base::ExtCtxt;
 use syntax::ext::build::AstBuilder;
 use syntax::parse::token;
@@ -126,7 +126,11 @@ impl<'cx, 's> Renderer<'cx, 's> {
         self.write(">");
     }
 
-    pub fn emit_if(&mut self, if_cond: P<Expr>, if_body: Vec<P<Stmt>>,
+    /// Emit an `if` expression.
+    ///
+    /// The condition is a token tree (not an expression) so we don't
+    /// need to special-case `if let`.
+    pub fn emit_if(&mut self, if_cond: Vec<TokenTree>, if_body: Vec<P<Stmt>>,
                    else_body: Option<Vec<P<Stmt>>>) {
         let stmt = match else_body {
             None => quote_stmt!(self.cx, if $if_cond { $if_body }),
diff --git a/maud_macros/tests/tests.rs b/maud_macros/tests/tests.rs
index 4ce1763..8defeec 100644
--- a/maud_macros/tests/tests.rs
+++ b/maud_macros/tests/tests.rs
@@ -202,6 +202,20 @@ mod control {
         }
     }
 
+    #[test]
+    fn if_let() {
+        for &(input, output) in [(Some("yay"), "yay"), (None, "oh noes")].iter() {
+            let s = html! {
+                $if let Some(value) = input {
+                    $value
+                } $else {
+                    "oh noes"
+                }
+            }.to_string();
+            assert_eq!(s, output);
+        }
+    }
+
     #[test]
     fn for_expr() {
         let ponies = ["Apple Bloom", "Scootaloo", "Sweetie Belle"];