Last active
April 8, 2022 15:11
-
-
Save pbackus/1638523a5b6ea3ce2c0a73358cff4dc6 to your computer and use it in GitHub Desktop.
TailUnqual - a template that breaks qualifier transitivity
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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