Expose span locations on stable
diff --git a/.travis.yml b/.travis.yml
index c3bfa6c..89da724 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -11,6 +11,7 @@
       script:
         - cargo test
         - cargo test --no-default-features
+        - cargo test --features span-locations
         - RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo test
         - RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo test --no-default-features
         - cargo update -Z minimal-versions && cargo build
@@ -25,6 +26,7 @@
 script:
   - cargo test
   - cargo test --no-default-features
+  - cargo test --features span-locations
   - RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo test
   - RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo test --no-default-features
 
diff --git a/Cargo.toml b/Cargo.toml
index 929314e..4d48b66 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -29,6 +29,10 @@
 proc-macro = []
 default = ["proc-macro"]
 
+# Expose methods Span::start and Span::end which give the line/column location
+# of a token.
+span-locations = []
+
 # This feature no longer means anything.
 nightly = []
 
diff --git a/build.rs b/build.rs
index 6973ca7..6c01121 100644
--- a/build.rs
+++ b/build.rs
@@ -31,6 +31,12 @@
 // "super_unstable"
 //     Implement the semver exempt API in terms of the nightly-only proc_macro
 //     API. Enabled when using procmacro2_semver_exempt on a nightly compiler.
+//
+// "span_locations"
+//     Provide methods Span::start and Span::end which give the line/column
+//     location of a token. Enabled by procmacro2_semver_exempt or the
+//     "span-locations" Cargo cfg. This is behind a cfg because tracking
+//     location inside spans is a performance hit.
 
 use std::env;
 use std::process::Command;
@@ -50,17 +56,22 @@
         println!("cargo:rustc-cfg=u128");
     }
 
-    if !enable_use_proc_macro(&target) {
-        return;
-    }
-    println!("cargo:rustc-cfg=use_proc_macro");
-
     let semver_exempt = cfg!(procmacro2_semver_exempt);
     if semver_exempt {
         // https://github.com/alexcrichton/proc-macro2/issues/147
         println!("cargo:rustc-cfg=procmacro2_semver_exempt");
     }
 
+    if semver_exempt || cfg!(feature = "span-locations") {
+        println!("cargo:rustc-cfg=span_locations");
+    }
+
+    if !enable_use_proc_macro(&target) {
+        return;
+    }
+
+    println!("cargo:rustc-cfg=use_proc_macro");
+
     // Rust 1.29 stabilized the necessary APIs in the `proc_macro` crate
     if version.nightly || version.minor >= 29 && !semver_exempt {
         println!("cargo:rustc-cfg=wrap_proc_macro");
diff --git a/src/fallback.rs b/src/fallback.rs
index 7f3cc4e..928c747 100644
--- a/src/fallback.rs
+++ b/src/fallback.rs
@@ -1,6 +1,4 @@
-#![cfg_attr(not(procmacro2_semver_exempt), allow(dead_code))]
-
-#[cfg(procmacro2_semver_exempt)]
+#[cfg(span_locations)]
 use std::cell::RefCell;
 #[cfg(procmacro2_semver_exempt)]
 use std::cmp;
@@ -35,7 +33,7 @@
     }
 }
 
-#[cfg(procmacro2_semver_exempt)]
+#[cfg(span_locations)]
 fn get_cursor(src: &str) -> Cursor {
     // Create a dummy file & add it to the codemap
     CODEMAP.with(|cm| {
@@ -49,7 +47,7 @@
     })
 }
 
-#[cfg(not(procmacro2_semver_exempt))]
+#[cfg(not(span_locations))]
 fn get_cursor(src: &str) -> Cursor {
     Cursor { rest: src }
 }
@@ -225,27 +223,41 @@
     pub column: usize,
 }
 
-#[cfg(procmacro2_semver_exempt)]
+#[cfg(span_locations)]
 thread_local! {
     static CODEMAP: RefCell<Codemap> = RefCell::new(Codemap {
         // NOTE: We start with a single dummy file which all call_site() and
         // def_site() spans reference.
-        files: vec![FileInfo {
-            name: "<unspecified>".to_owned(),
-            span: Span { lo: 0, hi: 0 },
-            lines: vec![0],
+        files: vec![{
+            #[cfg(procmacro2_semver_exempt)]
+            {
+                FileInfo {
+                    name: "<unspecified>".to_owned(),
+                    span: Span { lo: 0, hi: 0 },
+                    lines: vec![0],
+                }
+            }
+
+            #[cfg(not(procmacro2_semver_exempt))]
+            {
+                FileInfo {
+                    span: Span { lo: 0, hi: 0 },
+                    lines: vec![0],
+                }
+            }
         }],
     });
 }
 
-#[cfg(procmacro2_semver_exempt)]
+#[cfg(span_locations)]
 struct FileInfo {
+    #[cfg(procmacro2_semver_exempt)]
     name: String,
     span: Span,
     lines: Vec<usize>,
 }
 
-#[cfg(procmacro2_semver_exempt)]
+#[cfg(span_locations)]
 impl FileInfo {
     fn offset_line_column(&self, offset: usize) -> LineColumn {
         assert!(self.span_within(Span {
@@ -271,7 +283,7 @@
 }
 
 /// Computesthe offsets of each line in the given source string.
-#[cfg(procmacro2_semver_exempt)]
+#[cfg(span_locations)]
 fn lines_offsets(s: &str) -> Vec<usize> {
     let mut lines = vec![0];
     let mut prev = 0;
@@ -282,12 +294,12 @@
     lines
 }
 
-#[cfg(procmacro2_semver_exempt)]
+#[cfg(span_locations)]
 struct Codemap {
     files: Vec<FileInfo>,
 }
 
-#[cfg(procmacro2_semver_exempt)]
+#[cfg(span_locations)]
 impl Codemap {
     fn next_start_pos(&self) -> u32 {
         // Add 1 so there's always space between files.
@@ -306,12 +318,20 @@
             hi: lo + (src.len() as u32),
         };
 
+        #[cfg(procmacro2_semver_exempt)]
         self.files.push(FileInfo {
             name: name.to_owned(),
             span: span,
             lines: lines,
         });
 
+        #[cfg(not(procmacro2_semver_exempt))]
+        self.files.push(FileInfo {
+            span: span,
+            lines: lines,
+        });
+        let _ = name;
+
         span
     }
 
@@ -327,27 +347,29 @@
 
 #[derive(Clone, Copy, PartialEq, Eq)]
 pub struct Span {
-    #[cfg(procmacro2_semver_exempt)]
+    #[cfg(span_locations)]
     lo: u32,
-    #[cfg(procmacro2_semver_exempt)]
+    #[cfg(span_locations)]
     hi: u32,
 }
 
 impl Span {
-    #[cfg(not(procmacro2_semver_exempt))]
+    #[cfg(not(span_locations))]
     pub fn call_site() -> Span {
         Span {}
     }
 
-    #[cfg(procmacro2_semver_exempt)]
+    #[cfg(span_locations)]
     pub fn call_site() -> Span {
         Span { lo: 0, hi: 0 }
     }
 
+    #[cfg(procmacro2_semver_exempt)]
     pub fn def_site() -> Span {
         Span::call_site()
     }
 
+    #[cfg(procmacro2_semver_exempt)]
     pub fn resolved_at(&self, _other: Span) -> Span {
         // Stable spans consist only of line/column information, so
         // `resolved_at` and `located_at` only select which span the
@@ -355,6 +377,7 @@
         *self
     }
 
+    #[cfg(procmacro2_semver_exempt)]
     pub fn located_at(&self, other: Span) -> Span {
         other
     }
@@ -370,7 +393,7 @@
         })
     }
 
-    #[cfg(procmacro2_semver_exempt)]
+    #[cfg(span_locations)]
     pub fn start(&self) -> LineColumn {
         CODEMAP.with(|cm| {
             let cm = cm.borrow();
@@ -379,7 +402,7 @@
         })
     }
 
-    #[cfg(procmacro2_semver_exempt)]
+    #[cfg(span_locations)]
     pub fn end(&self) -> LineColumn {
         CODEMAP.with(|cm| {
             let cm = cm.borrow();
@@ -448,10 +471,12 @@
         self.span
     }
 
+    #[cfg(procmacro2_semver_exempt)]
     pub fn span_open(&self) -> Span {
         self.span
     }
 
+    #[cfg(procmacro2_semver_exempt)]
     pub fn span_close(&self) -> Span {
         self.span
     }
@@ -788,16 +813,16 @@
     Ok((input, TokenStream { inner: trees }))
 }
 
-#[cfg(not(procmacro2_semver_exempt))]
+#[cfg(not(span_locations))]
 fn spanned<'a, T>(
     input: Cursor<'a>,
     f: fn(Cursor<'a>) -> PResult<'a, T>,
 ) -> PResult<'a, (T, ::Span)> {
     let (a, b) = f(skip_whitespace(input))?;
-    Ok((a, ((b, ::Span::_new_stable(Span {})))))
+    Ok((a, ((b, ::Span::_new_stable(Span::call_site())))))
 }
 
-#[cfg(procmacro2_semver_exempt)]
+#[cfg(span_locations)]
 fn spanned<'a, T>(
     input: Cursor<'a>,
     f: fn(Cursor<'a>) -> PResult<'a, T>,
diff --git a/src/lib.rs b/src/lib.rs
index 70b25e9..5b96ad3 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -80,10 +80,8 @@
 
 // Proc-macro2 types in rustdoc of other crates get linked to here.
 #![doc(html_root_url = "https://docs.rs/proc-macro2/0.4.26")]
-#![cfg_attr(
-    super_unstable,
-    feature(proc_macro_raw_ident, proc_macro_span, proc_macro_def_site)
-)]
+#![cfg_attr(nightly, feature(proc_macro_span))]
+#![cfg_attr(super_unstable, feature(proc_macro_raw_ident, proc_macro_def_site))]
 
 #[cfg(use_proc_macro)]
 extern crate proc_macro;
@@ -302,7 +300,7 @@
 /// A line-column pair representing the start or end of a `Span`.
 ///
 /// This type is semver exempt and not exposed by default.
-#[cfg(procmacro2_semver_exempt)]
+#[cfg(span_locations)]
 pub struct LineColumn {
     /// The 1-indexed line in the source file on which the span starts or ends
     /// (inclusive).
@@ -401,8 +399,8 @@
 
     /// Get the starting line/column in the source file for this span.
     ///
-    /// This method is semver exempt and not exposed by default.
-    #[cfg(procmacro2_semver_exempt)]
+    /// This method requires the `"span-locations"` feature to be enabled.
+    #[cfg(span_locations)]
     pub fn start(&self) -> LineColumn {
         let imp::LineColumn { line, column } = self.inner.start();
         LineColumn {
@@ -413,8 +411,8 @@
 
     /// Get the ending line/column in the source file for this span.
     ///
-    /// This method is semver exempt and not exposed by default.
-    #[cfg(procmacro2_semver_exempt)]
+    /// This method requires the `"span-locations"` feature to be enabled.
+    #[cfg(span_locations)]
     pub fn end(&self) -> LineColumn {
         let imp::LineColumn { line, column } = self.inner.end();
         LineColumn {
diff --git a/src/strnom.rs b/src/strnom.rs
index 6f32062..96789d5 100644
--- a/src/strnom.rs
+++ b/src/strnom.rs
@@ -9,18 +9,18 @@
 #[derive(Copy, Clone, Eq, PartialEq)]
 pub struct Cursor<'a> {
     pub rest: &'a str,
-    #[cfg(procmacro2_semver_exempt)]
+    #[cfg(span_locations)]
     pub off: u32,
 }
 
 impl<'a> Cursor<'a> {
-    #[cfg(not(procmacro2_semver_exempt))]
+    #[cfg(not(span_locations))]
     pub fn advance(&self, amt: usize) -> Cursor<'a> {
         Cursor {
             rest: &self.rest[amt..],
         }
     }
-    #[cfg(procmacro2_semver_exempt)]
+    #[cfg(span_locations)]
     pub fn advance(&self, amt: usize) -> Cursor<'a> {
         Cursor {
             rest: &self.rest[amt..],
diff --git a/src/wrapper.rs b/src/wrapper.rs
index 11d1a3b..c45dff8 100644
--- a/src/wrapper.rs
+++ b/src/wrapper.rs
@@ -1,5 +1,3 @@
-#![cfg_attr(not(super_unstable), allow(dead_code))]
-
 use std::fmt;
 use std::iter;
 use std::panic::{self, PanicInfo};
@@ -413,6 +411,7 @@
     }
 }
 
+#[cfg(any(super_unstable, feature = "span-locations"))]
 pub struct LineColumn {
     pub line: usize,
     pub column: usize,
@@ -475,13 +474,16 @@
         }
     }
 
-    #[cfg(super_unstable)]
+    #[cfg(any(super_unstable, feature = "span-locations"))]
     pub fn start(&self) -> LineColumn {
         match self {
+            #[cfg(nightly)]
             Span::Compiler(s) => {
                 let proc_macro::LineColumn { line, column } = s.start();
                 LineColumn { line, column }
             }
+            #[cfg(not(nightly))]
+            Span::Compiler(_) => LineColumn { line: 0, column: 0 },
             Span::Fallback(s) => {
                 let fallback::LineColumn { line, column } = s.start();
                 LineColumn { line, column }
@@ -489,13 +491,16 @@
         }
     }
 
-    #[cfg(super_unstable)]
+    #[cfg(any(super_unstable, feature = "span-locations"))]
     pub fn end(&self) -> LineColumn {
         match self {
+            #[cfg(nightly)]
             Span::Compiler(s) => {
                 let proc_macro::LineColumn { line, column } = s.end();
                 LineColumn { line, column }
             }
+            #[cfg(not(nightly))]
+            Span::Compiler(_) => LineColumn { line: 0, column: 0 },
             Span::Fallback(s) => {
                 let fallback::LineColumn { line, column } = s.end();
                 LineColumn { line, column }
diff --git a/tests/test.rs b/tests/test.rs
index 6da1283..055ebfd 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -137,7 +137,7 @@
     fail("r#_");
 }
 
-#[cfg(procmacro2_semver_exempt)]
+#[cfg(span_locations)]
 #[test]
 fn span_test() {
     use proc_macro2::TokenTree;