typetoken 0.0.1

type tokens for branding via unique singletons
Documentation
//! a type token that can be used to uniquly tag an instance of a type.
//!
//! these are singleton types, only a single instance
//! of a given token type may exist.
//! to make checking this at compile time possible, tokens cannot be returned
//! from functions.

/// marker trait that a type is a type token.
///
/// this trait is safe to use in trait bounds, but MUST NOT be implemented by any code
/// outside of the `typetoken` crate.
pub unsafe trait Token {}

/// The heart of crate, generates a token singleton.
///
/// Every macro use site corresponds to a unique type,
/// and creates a value of that type.
/// the generated type will implement [`Token`].
///
/// The value contains an exclusive borrow also local to the macro use site
/// (and thus the type contains the lifetime of that borrow),
/// therefore no two values of the same type can exist at the same time.
///
/// The downside of this approach is that the token cannot outlive the
/// stack frame of function it was defined in.  for this reason, it is
/// generally advisable to construct tokens in `main()` if possible.
///
/// ## Examples
///
/// To get any use out of this crate, you generally need some generic interface
/// that takes two items of the tame generic type.
/// ```rust
/// # #[macro_use] extern crate typetoken;
/// use typetoken::Token;
/// fn assert_same_token<T: Token>(_: &T, _: &T) {}
/// fn main() {
///   token!(token1);
///   token!(token2);
///   assert_same_token(&token1, &token1);
///   assert_same_token(&token2, &token2);
/// }
/// ```
///
/// If used with a correctly designed interface, this can
/// catch programmer mistakes.
/// ```compile_fail
/// # #[macro_use] extern crate typetoken;
/// # use typetoken::Token;
/// # fn assert_same_token<T: Token>(_: &T, _: &T) {}
/// # fn main() {
/// token!(token1);
/// token!(token2);
/// assert_same_token(&token1, &token1);
/// assert_same_token(&token2, &token1); // oops, wrong token, compile error
/// # }
/// ```
///
/// Tokens should be unique in all circumstances, even if you do silly
/// things like define them on the same line
/// (this will make your error messages more confusing, so probably don't)
/// ```compile_fail
/// # #[macro_use] extern crate typetoken;
/// # use typetoken::Token;
/// # fn assert_same_token<T: Token>(_: &T, _: &T) {}
/// # fn main() {
/// token!(token1); token!(token2);
/// assert_same_token(&token1, &token1);
/// assert_same_token(&token2, &token1); // oops, wrong token, compile error
/// # }
/// ```
///
/// see the [`examples/`](https://codeberg.org/binarycat/typetoken/src/branch/trunk/examples)
/// directory for more practical usecases.
#[macro_export]
macro_rules! token {
	($name:ident) => {
		// mutable reference to regular reference disables lifetime covariance.
		// https://doc.rust-lang.org/nomicon/subtyping.html#variance
		let _guard_1 = ();
		let mut _guard_2 = &_guard_1;
		let $name = {
			// because it is in a block, this cannot be constructed outside
			// the macro.
			// TODO: is there an attribute to give an item a different name in error messages?
			struct TokenType<'a, const N: u32> {
				// make TokenType<'a> invariant with TokenType<'b>
				//
				// also leverage the exclusive nature of mutable borrows, this
				// prevents doing something like running `token!` in a loop and
				// collecting identical tokens.
				//
				// quinedot: The exclusive borrow means you can't get multiple
				// values out from the same macro call site at the same time
				// -- by returning from a function, yes, but also by being in
				// a loop, say. The idea is to plug a hole of many
				// unique-type-based singleton attempts: every (monomorphized)
				// expression has a particular type; if that code runs more than
				// once, the same type results each run, even if that type is
				// unique to the expression. So creating a value of
				// a "unique type" is not enough to
				// actually be a singleton at run time.
				//
				// thus, the extra lifetime paramater is required.
				_invariant: &'a mut &'a (),
			}
			// not actually required to provide any of listed guarantees,
			// but makes error messages slightly more readable.
			const THIS_LINE: u32 = line!();
			// the only "impl Token" that should ever exist
			unsafe impl<'a> $crate::Token for TokenType<'a, THIS_LINE> {}
			TokenType::<THIS_LINE>{ _invariant: &mut _guard_2 }
		};
	}	
}