Validate input in Term::new
diff --git a/src/stable.rs b/src/stable.rs
index abfeab3..ad9870c 100644
--- a/src/stable.rs
+++ b/src/stable.rs
@@ -403,6 +403,8 @@
 
 impl Term {
     pub fn new(string: &str, span: Span) -> Term {
+        validate_term(string);
+
         Term {
             intern: SYMBOLS.with(|s| s.borrow_mut().intern(string)),
             span: span,
@@ -426,6 +428,42 @@
     }
 }
 
+fn validate_term(string: &str) {
+    let validate = if string.starts_with('\'') {
+        &string[1..]
+    } else if string.starts_with("r#") {
+        &string[2..]
+    } else {
+        string
+    };
+
+    if validate.is_empty() {
+        panic!("Term is not allowed to be empty; use Option<Term>");
+    }
+
+    if validate.bytes().all(|digit| digit >= b'0' && digit <= b'9') {
+        panic!("Term cannot be a number; use Literal instead");
+    }
+
+    fn xid_ok(string: &str) -> bool {
+        let mut chars = string.chars();
+        let first = chars.next().unwrap();
+        if !(UnicodeXID::is_xid_start(first) || first == '_') {
+            return false;
+        }
+        for ch in chars {
+            if !UnicodeXID::is_xid_continue(ch) {
+                return false;
+            }
+        }
+        true
+    }
+
+    if !xid_ok(validate) {
+        panic!("{:?} is not a valid Term", string);
+    }
+}
+
 impl fmt::Debug for Term {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_tuple("Term").field(&self.as_str()).finish()
diff --git a/tests/test.rs b/tests/test.rs
index 7699d53..caed47c 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -5,9 +5,78 @@
 use proc_macro2::{Literal, Span, Term, TokenStream, TokenTree};
 
 #[test]
-fn symbols() {
-    assert_eq!(Term::new("foo", Span::call_site()).as_str(), "foo");
-    assert_eq!(Term::new("bar", Span::call_site()).as_str(), "bar");
+fn terms() {
+    assert_eq!(Term::new("String", Span::call_site()).as_str(), "String");
+    assert_eq!(Term::new("fn", Span::call_site()).as_str(), "fn");
+    assert_eq!(Term::new("_", Span::call_site()).as_str(), "_");
+}
+
+#[test]
+fn raw_terms() {
+    assert_eq!(Term::new("r#String", Span::call_site()).as_str(), "r#String");
+    assert_eq!(Term::new("r#fn", Span::call_site()).as_str(), "r#fn");
+    assert_eq!(Term::new("r#_", Span::call_site()).as_str(), "r#_");
+}
+
+#[test]
+fn lifetimes() {
+    assert_eq!(Term::new("'a", Span::call_site()).as_str(), "'a");
+    assert_eq!(Term::new("'static", Span::call_site()).as_str(), "'static");
+    assert_eq!(Term::new("'_", Span::call_site()).as_str(), "'_");
+}
+
+#[test]
+#[should_panic(expected = "Term is not allowed to be empty; use Option<Term>")]
+fn term_empty() {
+    Term::new("", Span::call_site());
+}
+
+#[test]
+#[should_panic(expected = "Term cannot be a number; use Literal instead")]
+fn term_number() {
+    Term::new("255", Span::call_site());
+}
+
+#[test]
+#[should_panic(expected = "\"a#\" is not a valid Term")]
+fn term_invalid() {
+    Term::new("a#", Span::call_site());
+}
+
+#[test]
+#[should_panic(expected = "Term is not allowed to be empty; use Option<Term>")]
+fn raw_term_empty() {
+    Term::new("r#", Span::call_site());
+}
+
+#[test]
+#[should_panic(expected = "Term cannot be a number; use Literal instead")]
+fn raw_term_number() {
+    Term::new("r#255", Span::call_site());
+}
+
+#[test]
+#[should_panic(expected = "\"r#a#\" is not a valid Term")]
+fn raw_term_invalid() {
+    Term::new("r#a#", Span::call_site());
+}
+
+#[test]
+#[should_panic(expected = "Term is not allowed to be empty; use Option<Term>")]
+fn lifetime_empty() {
+    Term::new("'", Span::call_site());
+}
+
+#[test]
+#[should_panic(expected = "Term cannot be a number; use Literal instead")]
+fn lifetime_number() {
+    Term::new("'255", Span::call_site());
+}
+
+#[test]
+#[should_panic(expected = r#""\'a#" is not a valid Term"#)]
+fn lifetime_invalid() {
+    Term::new("'a#", Span::call_site());
 }
 
 #[test]