From 03d759ab90ee7075a2908396e77827f8183bb2f4 Mon Sep 17 00:00:00 2001 From: Sergio Benitez Date: Wed, 28 Apr 2021 01:18:20 -0700 Subject: [PATCH] Make type macros inelgible as sentinels. --- core/codegen/src/syn_ext.rs | 2 +- core/lib/src/sentinel.rs | 35 +++++++++++++++++++++++++++++++---- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/core/codegen/src/syn_ext.rs b/core/codegen/src/syn_ext.rs index 5f70918f..27b81cde 100644 --- a/core/codegen/src/syn_ext.rs +++ b/core/codegen/src/syn_ext.rs @@ -137,7 +137,7 @@ impl TypeExt for syn::Type { self.0 = false; return; } - ImplTrait(_) | Infer(_) => { + ImplTrait(_) | Infer(_) | Macro(_) => { self.0 = false; return; } diff --git a/core/lib/src/sentinel.rs b/core/lib/src/sentinel.rs index 5cb205bc..4182aac1 100644 --- a/core/lib/src/sentinel.rs +++ b/core/lib/src/sentinel.rs @@ -152,14 +152,14 @@ use crate::{Rocket, Ignite}; /// /// **Note:** _Rocket actively discourages using `impl Trait` in route /// signatures. In addition to impeding sentinel discovery, doing so decreases -/// the ability to gleam handler functionality based on its type signature._ +/// the ability to gleam a handler's functionality based on its type signature._ /// /// The return type of the route `f` depends on its implementation. At present, /// it is not possible to name the underlying concrete type of an `impl Trait` /// at compile-time and thus not possible to determine if it implements -/// `Sentinel`. As such, existentials _are not_ eligible to be sentinels. This -/// limitation applies per embedded type: the directly named `AnotherSentinel` -/// type continues to be eligible to be a sentinel. +/// `Sentinel`. As such, existentials _are not_ eligible to be sentinels. +/// However, this limitation applies per embedding, so the inner, directly named +/// `AnotherSentinel` type continues to be eligible to be a sentinel. /// /// When possible, prefer to name all types: /// @@ -202,6 +202,33 @@ use crate::{Rocket, Ignite}; /// cases, a type alias _will_ "consider" embeddings. Nevertheless, prefer to /// write concrete types when possible. /// +/// ## Type Macros +/// +/// It is impossible to determine, a priori, what a type macro will expand to. +/// As such, Rocket is unable to determine which sentinels, if any, a type macro +/// references, and thus no sentinels are discovered from type macros. +/// +/// Even approximations are impossible. For example, consider the following: +/// +/// ```rust +/// # use rocket::*; +/// macro_rules! MyType { +/// (State<'_, u32>) => (&'_ rocket::Config) +/// } +/// +/// #[get("/")] +/// fn f(guard: MyType![State<'_, u32>]) { +/// /* ... */ +/// } +/// ``` +/// +/// While the `MyType![State<'_, u32>]` type _appears_ to contain a `State` +/// sentinel, the macro actually expands to `&'_ rocket::Config`, which is _not_ +/// the `State` sentinel. +/// +/// You should prefer not to use type macros, or if necessary, restrict your use +/// to those that always expand to types without sentinels. +/// /// # Custom Sentinels /// /// Any type can implement `Sentinel`, and the implementation can arbitrarily