From 250d93df9a3c7617965ae2314b55085da241befe Mon Sep 17 00:00:00 2001
From: Chris Wong <lambda.fairy@gmail.com>
Date: Mon, 28 Sep 2020 11:06:44 +1000
Subject: [PATCH] =?UTF-8?q?Enable=20stable=20support=20=F0=9F=8E=89=20(#21?=
 =?UTF-8?q?9)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Infer whether nightly features are available using rustc_version. If this fails, assume stable.

Closes #214
---
 .travis.yml           | 18 ++++++------------
 README.md             |  9 ---------
 benchmarks/Cargo.toml |  3 ---
 maud/Cargo.toml       |  6 +++---
 maud/build.rs         |  8 ++++++++
 maud/src/lib.rs       | 10 +++++-----
 maud/tests/errors.rs  |  3 +++
 rust-toolchain        |  1 -
 8 files changed, 25 insertions(+), 33 deletions(-)
 create mode 100644 maud/build.rs
 delete mode 100644 rust-toolchain

diff --git a/.travis.yml b/.travis.yml
index 31bd92f..db09cfd 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -9,15 +9,7 @@ jobs:
         - |
           RUN_CLIPPY=true
           rustup component add clippy --toolchain=nightly || RUN_CLIPPY=false
-        # As of right now, these need to be tested individually becuase `--workspace`
-        # (which is implied by `workspace = true`) cannot be used with `--features`
-        # This _may_ be resolved with the `--package` flag, however this requires
-        # opting in to a `-Z` unstable feature as of time of commit.
-        #
-        # Follow https://github.com/rust-lang/cargo/issues/5364 for updates.
-        - cargo test --manifest-path maud/Cargo.toml --features actix-web,iron,rocket
-        - cargo test --manifest-path maud_htmlescape/Cargo.toml
-        - cargo test --manifest-path maud_macros/Cargo.toml
+        - cargo test --all --all-features
         - |
           if $RUN_CLIPPY; then
             CLIPPY_STATUS=0
@@ -26,12 +18,14 @@ jobs:
             done
             (exit $CLIPPY_STATUS)
           fi
-    - name: "Unstable"
+    - name: "Stable"
+      rust: stable
       script:
-        - cargo test --all --all-features
+        # Skip `--all-features` because stable Rocket isn't released yet
+        - cargo test --all
     - name: "Benchmarks"
       script:
-        - (cd benchmarks && cargo test --benches --features unstable)
+        - (cd benchmarks && cargo test --benches)
     - name: "Documentation"
       script:
         - (cd docs && make -j$(nproc))
diff --git a/README.md b/README.md
index 9a7454b..20a008e 100644
--- a/README.md
+++ b/README.md
@@ -7,18 +7,9 @@
 
 Maud is an HTML template engine for Rust. It's implemented as a macro, `html!`, which compiles your markup to specialized Rust code. This unique approach makes Maud templates blazing fast, super type-safe, and easy to deploy.
 
-Note that Maud depends on the unstable [procedural macro API][rustissue], and so requires the nightly version of Rust.
-
 For more info on Maud, see the [official book][book].
 
 [book]: https://maud.lambda.xyz/
 [booksrc]: https://github.com/lambda-fairy/maud/tree/master/docs
 [apiref]: https://docs.rs/maud/
 [changelog]: https://github.com/lambda-fairy/maud/blob/master/CHANGELOG.md
-[rustissue]: https://github.com/rust-lang/rust/issues/38356
-
-## Stability
-
-As of version 0.11, I am satisfied with the core syntax and semantics of the library. Development at this stage is focused on adding features and fixing bugs.
-
-The underlying procedural macro API is still unstable though, so updating your compiler may break things. Please file an issue when this happens!
diff --git a/benchmarks/Cargo.toml b/benchmarks/Cargo.toml
index fe8ec2f..adcce70 100644
--- a/benchmarks/Cargo.toml
+++ b/benchmarks/Cargo.toml
@@ -4,9 +4,6 @@ version = "0.1.2"
 authors = ["Chris Wong <lambda.fairy@gmail.com>"]
 edition = "2018"
 
-[features]
-unstable = ["maud/unstable"]
-
 [dependencies]
 maud = { path = "../maud" }
 handlebars = "*"
diff --git a/maud/Cargo.toml b/maud/Cargo.toml
index af8f9ef..91555b1 100644
--- a/maud/Cargo.toml
+++ b/maud/Cargo.toml
@@ -17,9 +17,6 @@ default = []
 # Web framework integrations
 actix-web = ["actix-web-dep", "futures"]
 
-# Unstable features
-unstable = []
-
 [dependencies]
 maud_htmlescape = { version = "0.17.0", path = "../maud_htmlescape" }
 maud_macros = { version = "0.22.0", path = "../maud_macros" }
@@ -28,6 +25,9 @@ rocket = { version = ">= 0.3, < 0.5", optional = true }
 futures = { version = "0.3.0", optional = true }
 actix-web-dep = { version = "2.0.0", optional = true, default-features = false, package = "actix-web" }
 
+[build-dependencies]
+rustc_version = "0.2.3"
+
 [dev-dependencies]
 trybuild = { version = "1.0.33", features = ["diff"] }
 
diff --git a/maud/build.rs b/maud/build.rs
new file mode 100644
index 0000000..e842d94
--- /dev/null
+++ b/maud/build.rs
@@ -0,0 +1,8 @@
+use rustc_version::{version_meta, Channel};
+
+fn main() {
+    match version_meta().map(|v| v.channel).unwrap_or(Channel::Stable) {
+        Channel::Dev | Channel::Nightly => println!("cargo:rustc-cfg=unstable"),
+        Channel::Beta | Channel::Stable => {}
+    }
+}
diff --git a/maud/src/lib.rs b/maud/src/lib.rs
index 7a4f53f..9100587 100644
--- a/maud/src/lib.rs
+++ b/maud/src/lib.rs
@@ -1,4 +1,4 @@
-#![cfg_attr(feature = "unstable", feature(min_specialization))]
+#![cfg_attr(unstable, feature(min_specialization))]
 
 //! A macro for writing HTML templates.
 //!
@@ -78,28 +78,28 @@ pub trait Render {
     }
 }
 
-#[cfg(not(feature = "unstable"))]
+#[cfg(not(unstable))]
 impl<T: fmt::Display + ?Sized> Render for T {
     fn render_to(&self, w: &mut String) {
         let _ = write!(Escaper::new(w), "{}", self);
     }
 }
 
-#[cfg(feature = "unstable")]
+#[cfg(unstable)]
 impl<T: fmt::Display + ?Sized> Render for T {
     default fn render_to(&self, w: &mut String) {
         let _ = write!(Escaper::new(w), "{}", self);
     }
 }
 
-#[cfg(feature = "unstable")]
+#[cfg(unstable)]
 impl Render for String {
     fn render_to(&self, w: &mut String) {
         let _ = Escaper::new(w).write_str(self);
     }
 }
 
-#[cfg(feature = "unstable")]
+#[cfg(unstable)]
 impl Render for str {
     fn render_to(&self, w: &mut String) {
         let _ = Escaper::new(w).write_str(self);
diff --git a/maud/tests/errors.rs b/maud/tests/errors.rs
index fa31fd1..e294f7d 100644
--- a/maud/tests/errors.rs
+++ b/maud/tests/errors.rs
@@ -1,3 +1,6 @@
+// Diagnostics look slightly different on stable Rust
+#![cfg(unstable)]
+
 use trybuild::TestCases;
 
 #[test]
diff --git a/rust-toolchain b/rust-toolchain
deleted file mode 100644
index bf867e0..0000000
--- a/rust-toolchain
+++ /dev/null
@@ -1 +0,0 @@
-nightly