Skip to content

Instantly share code, notes, and snippets.

@pbackus
Last active April 8, 2022 15:11
Show Gist options
  • Save pbackus/1638523a5b6ea3ce2c0a73358cff4dc6 to your computer and use it in GitHub Desktop.
Save pbackus/1638523a5b6ea3ce2c0a73358cff4dc6 to your computer and use it in GitHub Desktop.
TailUnqual - a template that breaks qualifier transitivity
module tail_unqual;
import std.traits: isPointer;
import std.stdint: uintptr_t;
private union HiddenPointer
{
// Stores a pointer, cast to an integer.
uintptr_t address;
// Enables GC scanning and makes the compiler treat
// this as a type with unsafe values.
void* unused;
}
private void forceImpure() @safe nothrow @nogc {}
struct TailUnqual(P)
if (isPointer!P)
{
private HiddenPointer data;
this(return scope P ptr) inout
{
data.address = cast(uintptr_t) ptr;
}
@trusted @property
P ptr() inout
{
// This is safe because:
// - `address` is always the active field of `data`.
// - `data.address` was originally cast from a `P`.
// - `forceImpure` ensures that the compiler does not
// consider this a pure factory function.
// - The explicit `return scope` attribute on the
// constructor's argument ensures that this cannot be
// used to escape a `scope` pointer.
forceImpure();
return cast(P) data.address;
}
alias ptr this;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment