Make type macros inelgible as sentinels.

This commit is contained in:
Sergio Benitez 2021-04-28 01:18:20 -07:00
parent 9ad4fb2781
commit 03d759ab90
2 changed files with 32 additions and 5 deletions

View File

@ -137,7 +137,7 @@ impl TypeExt for syn::Type {
self.0 = false;
return;
}
ImplTrait(_) | Infer(_) => {
ImplTrait(_) | Infer(_) | Macro(_) => {
self.0 = false;
return;
}

View File

@ -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