diff --git a/maud_macros/src/build.rs b/maud_macros/src/build.rs
index 1371957..a0a52c2 100644
--- a/maud_macros/src/build.rs
+++ b/maud_macros/src/build.rs
@@ -1,5 +1,6 @@
 use proc_macro::{Delimiter, Group, Literal, Span, TokenStream, TokenTree};
 use proc_macro::quote;
+
 use maud_htmlescape::Escaper;
 
 pub struct Builder {
@@ -111,19 +112,13 @@ impl Builder {
         // If the condition contains an opening brace `{`,
         // wrap it in parentheses to avoid parse errors
         if cond.clone().into_iter().any(|token| match token {
-            TokenTree::Group(grp) => { 
-                if grp.delimiter() == Delimiter::Brace {
-                    true
-                } else {
-                    false
-                }
-            },
+            TokenTree::Group(group) => group.delimiter() == Delimiter::Brace,
             _ => false,
         }) {
-            let mut g = Group::new(Delimiter::Parenthesis, cond);
+            let mut group = Group::new(Delimiter::Parenthesis, cond);
             // NOTE: Do we need to do this?
-            g.set_span(cond_span);
-            cond = TokenStream::from(TokenTree::Group(g));
+            group.set_span(cond_span);
+            cond = TokenStream::from(TokenTree::Group(group));
         }
         self.push(quote!(if $cond { $body }));
     }
diff --git a/maud_macros/src/lib.rs b/maud_macros/src/lib.rs
index 1755f9d..0885fd5 100644
--- a/maud_macros/src/lib.rs
+++ b/maud_macros/src/lib.rs
@@ -1,8 +1,11 @@
 #![feature(proc_macro)]
-#![feature(pattern_parentheses)]
 
 #![doc(html_root_url = "https://docs.rs/maud_macros/0.17.2")]
 
+// TokenStream values are reference counted, and the mental overhead of tracking
+// lifetimes outweighs the marginal gains from explicit borrowing
+#![cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))]
+
 extern crate literalext;
 extern crate maud_htmlescape;
 extern crate proc_macro;
@@ -28,7 +31,6 @@ pub fn html_debug(input: TokenStream) -> TokenStream {
 }
 
 fn expand(input: TokenStream) -> TokenStream {
- 
     let output_ident = TokenTree::Term(Term::new("__maud_output", Span::def_site()));
     // Heuristic: the size of the resulting markup tends to correlate with the
     // code size of the template itself
@@ -40,7 +42,7 @@ fn expand(input: TokenStream) -> TokenStream {
     };
     quote!({
         extern crate maud;
-        let mut $output_ident = String::with_capacity($size_hint as usize);
+        let mut $output_ident = String::with_capacity($size_hint);
         $stmts
         maud::PreEscaped($output_ident)
     })
diff --git a/maud_macros/src/parse.rs b/maud_macros/src/parse.rs
index 2108ce8..d1562b5 100644
--- a/maud_macros/src/parse.rs
+++ b/maud_macros/src/parse.rs
@@ -4,12 +4,9 @@ use proc_macro::{
     Literal,
     Spacing,
     Span,
-    Term,
     TokenStream,
     TokenTree,
 };
-
-use proc_macro::token_stream;
 use std::iter;
 use std::mem;
 
@@ -30,7 +27,7 @@ struct Parser {
     output_ident: TokenTree,
     /// Indicates whether we're inside an attribute node.
     in_attr: bool,
-    input: token_stream::IntoIter,
+    input: <TokenStream as IntoIterator>::IntoIter,
 }
 
 impl Iterator for Parser {
@@ -99,15 +96,14 @@ impl Parser {
         loop {
             match self.peek2() {
                 None => return Ok(()),
-                Some((TokenTree::Op(o), _)) if o.op() == ';' => self.advance(),
-                Some((TokenTree::Op(o), Some(TokenTree::Term(term)))) if o.op() == '@' && term.as_str() == "let" => {
+                Some((TokenTree::Op(op), _)) if op.op() == ';' => self.advance(),
+                Some((TokenTree::Op(op), Some(TokenTree::Term(term)))) if op.op() == '@' && term.as_str() == "let" => {
                     // When emitting a `@let`, wrap the rest of the block in a
                     // new block to avoid scoping issues
-                    let keyword = Term::new(term.as_str(), term.span());
                     self.advance2();
                     builder.push({
                         let mut builder = self.builder();
-                        builder.push(TokenTree::Term(keyword));
+                        builder.push(TokenTree::Term(term));
                         self.let_expr(&mut builder)?;
                         self.markups(&mut builder)?;
                         TokenTree::Group(Group::new(Delimiter::Brace, builder.build()))
@@ -131,18 +127,17 @@ impl Parser {
                 self.literal(lit, builder)?;
             },
             // Special form
-            TokenTree::Op(o) if o.op() == '@' => {
+            TokenTree::Op(op) if op.op() == '@' => {
                 self.advance();
                 match self.next() {
                     Some(TokenTree::Term(term)) => {
-                        let keyword = Term::new(term.as_str(), term.span());
-                        builder.push(TokenTree::Term(keyword));
+                        builder.push(TokenTree::Term(term));
                         match term.as_str() {
                             "if" => self.if_expr(builder)?,
                             "while" => self.while_expr(builder)?,
                             "for" => self.for_expr(builder)?,
                             "match" => self.match_expr(builder)?,
-                            "let" => return self.error(format!("@let only works inside a block")),
+                            "let" => return self.error("let only works inside a block"),
                             other => return self.error(format!("unknown keyword `@{}`", other)),
                         }
                     },
@@ -155,14 +150,14 @@ impl Parser {
                 self.element(&name, builder)?;
             },
             // Splice
-            TokenTree::Group(ref grp) if grp.delimiter() == Delimiter::Parenthesis => {
+            TokenTree::Group(ref group) if group.delimiter() == Delimiter::Parenthesis => {
                 self.advance();
-                builder.splice(grp.stream());
+                builder.splice(group.stream());
             },
             // Block
-            TokenTree::Group(ref grp) if grp.delimiter() == Delimiter::Brace => {
+            TokenTree::Group(ref group) if group.delimiter() == Delimiter::Brace => {
                 self.advance();
-                self.with_input(grp.stream()).markups(builder)?;
+                self.with_input(group.stream()).markups(builder)?;
             },
             // ???
             _ => return self.error("invalid syntax"),
@@ -186,8 +181,7 @@ impl Parser {
     fn if_expr(&mut self, builder: &mut Builder) -> ParseResult<()> {
         loop {
             match self.next() {
-                Some(TokenTree::Group(ref block)) 
-                if block.delimiter() == Delimiter::Brace => {
+                Some(TokenTree::Group(ref block)) if block.delimiter() == Delimiter::Brace => {
                     let block = self.block(block.stream(), block.span())?;
                     builder.push(block);
                     break;
@@ -204,28 +198,27 @@ impl Parser {
     /// The leading `@else if` or `@else` should *not* already be consumed.
     fn else_if_expr(&mut self, builder: &mut Builder) -> ParseResult<()> {
         match self.peek2() {
-            Some((TokenTree::Op(o), Some(TokenTree::Term(else_keyword)))) 
-            if o.op() == '@' && else_keyword.as_str() == "else" => {
+            Some((
+                TokenTree::Op(op),
+                Some(TokenTree::Term(else_keyword)),
+            )) if op.op() == '@' && else_keyword.as_str() == "else" => {
                 self.advance2();
-                let else_keyword = Term::new("else", else_keyword.span());
                 builder.push(TokenTree::Term(else_keyword));
                 match self.peek() {
                     // `@else if`
                     Some(TokenTree::Term(if_keyword)) if if_keyword.as_str() == "if" => {
                         self.advance();
-                        let if_keyword = Term::new("if", if_keyword.span());
                         builder.push(TokenTree::Term(if_keyword));
                         self.if_expr(builder)?;
                     },
                     // Just an `@else`
                     _ => {
-                        // match brace `{`
                         match self.next() {
-                            Some(TokenTree::Group(ref grp)) if grp.delimiter() == Delimiter::Brace => {
-                                let block = self.block(grp.stream(), grp.span())?;
+                            Some(TokenTree::Group(ref group)) if group.delimiter() == Delimiter::Brace => {
+                                let block = self.block(group.stream(), group.span())?;
                                 builder.push(block);
                             },
-                            _ => { return self.error("expected body for @else"); },
+                            _ => return self.error("expected body for @else"),
                         }
                     },
                 }
@@ -261,7 +254,6 @@ impl Parser {
         loop {
             match self.next() {
                 Some(TokenTree::Term(in_keyword)) if in_keyword.as_str() == "in" => {
-                    let in_keyword = Term::new("in", in_keyword.span());
                     builder.push(TokenTree::Term(in_keyword));
                     break;
                 },
@@ -290,8 +282,10 @@ impl Parser {
         loop {
             match self.next() {
                 Some(TokenTree::Group(ref body)) if body.delimiter() == Delimiter::Brace => {
+                    let span = body.span();
                     let body = self.with_input(body.stream()).match_arms()?;
-                    let body = Group::new(Delimiter::Brace, body);
+                    let mut body = Group::new(Delimiter::Brace, body);
+                    body.set_span(span);
                     builder.push(TokenTree::Group(body));
                     break;
                 },
@@ -311,10 +305,10 @@ impl Parser {
     }
 
     fn match_arm(&mut self) -> ParseResult<Option<TokenStream>> {
-        let mut pat: Vec<TokenTree> = Vec::new();
+        let mut pat = Vec::new();
         loop {
             match self.peek2() {
-                Some((TokenTree::Op(eq), Some(TokenTree::Op(gt)))) 
+                Some((TokenTree::Op(eq), Some(TokenTree::Op(gt))))
                 if eq.op() == '=' && gt.op() == '>' && eq.spacing() == Spacing::Joint => {
                     self.advance2();
                     pat.push(TokenTree::Op(eq));
@@ -336,10 +330,10 @@ impl Parser {
         let body = match self.next() {
             // $pat => { $stmts }
             Some(TokenTree::Group(ref body)) if body.delimiter() == Delimiter::Brace => {
-                let body: TokenTree = self.block(body.stream(), body.span())?;
+                let body = self.block(body.stream(), body.span())?;
                 // Trailing commas are optional if the match arm is a braced block
-                if let Some(TokenTree::Op(o)) = self.peek() {
-                    if o.op() == ',' {
+                if let Some(TokenTree::Op(op)) = self.peek() {
+                    if op.op() == ',' {
                         self.advance();
                     }
                 }
@@ -376,10 +370,10 @@ impl Parser {
             match self.next() {
                 Some(token) => {
                     match token {
-                        TokenTree::Op(ref o) if o.op() == '=' => {
+                        TokenTree::Op(ref op) if op.op() == '=' => {
                             builder.push(token.clone());
                             break;
-                        }
+                        },
                         _ => builder.push(token),
                     }
                 },
@@ -390,7 +384,7 @@ impl Parser {
             match self.next() {
                 Some(token) => {
                     match token {
-                        TokenTree::Op(ref o) if o.op() == ';' => {
+                        TokenTree::Op(ref op) if op.op() == ';' => {
                             builder.push(token.clone());
                             break;
                         },
@@ -437,7 +431,7 @@ impl Parser {
             let token_after = attempt.next();
             match (maybe_name, token_after) {
                 // Non-empty attribute
-                (Ok(ref name), Some(TokenTree::Op(ref o))) if o.op() == '=' => {
+                (Ok(ref name), Some(TokenTree::Op(ref op))) if op.op() == '=' => {
                     self.commit(attempt);
                     builder.attribute_start(&name);
                     {
@@ -449,7 +443,7 @@ impl Parser {
                     builder.attribute_end();
                 },
                 // Empty attribute
-                (Ok(ref name), Some(TokenTree::Op(ref o))) if o.op() == '?' => {
+                (Ok(ref name), Some(TokenTree::Op(ref op))) if op.op() == '?' => {
                     self.commit(attempt);
                     if let Some((cond, cond_span)) = self.attr_toggler() {
                         // Toggle the attribute based on a boolean expression
@@ -465,7 +459,7 @@ impl Parser {
                     }
                 },
                 // Class shorthand
-                (Err(_), Some(TokenTree::Op(o))) if o.op() == '.' => {
+                (Err(_), Some(TokenTree::Op(op))) if op.op() == '.' => {
                     self.commit(attempt);
                     let class_name = self.name()?;
                     if let Some((cond, cond_span)) = self.attr_toggler() {
@@ -477,7 +471,7 @@ impl Parser {
                     }
                 },
                 // ID shorthand
-                (Err(_), Some(TokenTree::Op(o))) if o.op() == '#' => {
+                (Err(_), Some(TokenTree::Op(op))) if op.op() == '#' => {
                     self.commit(attempt);
                     ids.push(self.name()?);
                 },
@@ -517,8 +511,8 @@ impl Parser {
             Some(TokenTree::Group(ref grp)) if grp.delimiter() == Delimiter::Bracket => {
                 self.advance();
                 Some((grp.stream(), grp.span()))
-            }
-            _ => None
+            },
+            _ => None,
         }
     }
 
@@ -533,7 +527,7 @@ impl Parser {
         let mut expect_ident = false;
         loop {
             expect_ident = match self.peek() {
-                Some(TokenTree::Op(o)) if o.op() == '-' => {
+                Some(TokenTree::Op(op)) if op.op() == '-' => {
                     self.advance();
                     s.push('-');
                     true
@@ -553,8 +547,8 @@ impl Parser {
     /// if necessary.
     fn namespaced_name(&mut self) -> ParseResult<String> {
         let mut s = self.name()?;
-        if let Some(TokenTree::Op(o)) = self.peek() {
-            if o.op() == ':' {
+        if let Some(TokenTree::Op(op)) = self.peek() {
+            if op.op() == ':' {
                 self.advance();
                 s.push(':');
                 s.push_str(&self.name()?);
@@ -565,9 +559,11 @@ impl Parser {
 
     /// Parses the given token stream as a Maud expression, returning a block of
     /// Rust code.
-    fn block(&mut self, body: TokenStream, _span: Span) -> ParseResult<TokenTree> {
+    fn block(&mut self, body: TokenStream, span: Span) -> ParseResult<TokenTree> {
         let mut builder = self.builder();
         self.with_input(body).markups(&mut builder)?;
-        Ok(TokenTree::Group(Group::new(Delimiter::Brace, builder.build())))
+        let mut group = Group::new(Delimiter::Brace, builder.build());
+        group.set_span(span);
+        Ok(TokenTree::Group(group))
     }
 }