This program exhibits at least 2 different issues:
struct S() {
align(1):
bool x;
public int* i;
public void initialize(int* i) {
this.i = i;
}
}
S!() r1;
// pragma(msg, "r1.initialize:", typeof(r1.initialize)); // <-- magical line
pragma(msg, "S!().initialize:", typeof(S!().initialize));
Now this program compiles and the pragma msg emits:
"S!().initialize:void(int* i)"
Issue A) this is wrong, because inside a template, it should infer the method to be pure nothrow @nogc, but it doesn't.
Issue B) if you uncomment the magical line, the pragma msgs now emit:
"r1.initialize:pure nothrow @nogc @safe void(int* i)
S!().initialize:pure nothrow @nogc @safe void(int* i)"
so the first pragma(msg) changes the inferred type of initialize to correctly include "pure nothrow @nogc" but *incorrectly* include "@safe" (it isn't @safe because it assigns a misaligned pointer!)
-----------------
A) So a typeof() computation on a type has side-effects.
B) The attribute inference is too narrow without it
C) The attribute inference is too wide with it
-----------------
I've minimized to this example when debugging linker errors - where different compilation contexts inferred "@safe pure" differently on an expression.
Comment #1 by snarwin+bugzilla — 2021-08-08T14:26:08Z
More reduced version of the inconsistent attribute inference issue:
---
struct S() {
public void initialize() {}
}
version(NotInferred)
// void()
pragma(msg, typeof(S!().initialize));
else
// pure nothrow @nogc @safe void()
pragma(msg, typeof(S!()().initialize));
---
More reduced version of the alignment issue:
---
struct S {
align(1) int* p;
}
auto fun(int* p) {
S s;
s.p = p;
return s;
}
// pure nothrow @nogc @safe S(int* p)
pragma(msg, typeof(fun));
---
I am not sure the second one is actually a bug. The language spec section on pointers [1] does not say anything about misaligned pointer variables potentially causing undefined behavior, and I have not been able to come up with an example that uses such a variable to cause undefined behavior in @safe code.
For now, I've edited the name of this bugzilla issue to refer to the attribute-inference issue in the first example, since that one's definitely a bug.
[1] https://dlang.org/spec/arrays.html#pointers
Comment #2 by eyal — 2021-08-08T14:57:39Z
If you change your second to:
struct S {
ubyte x;
align(1) int* p;
}
// @safe <-- will fail to build with this attribute, but it will infer as @safe!
auto fun(int* p) {
S s;
s.p = p;
return s;
}
// pure nothrow @nogc @safe S(int* p)
pragma(msg, typeof(fun));
i.e: make the ptr be at offset 1, misaligned - it will infer as @safe, but refuse to type-check with @safe
Comment #3 by robert.schadek — 2024-12-13T19:17:58Z