Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@safe check escapes trough template instantiating #20976

Open
zero-vector opened this issue Mar 11, 2025 · 4 comments
Open

@safe check escapes trough template instantiating #20976

zero-vector opened this issue Mar 11, 2025 · 4 comments
Assignees
Labels
Severity:safe @safe code

Comments

@zero-vector
Copy link

One can instantiate tempalate that violates @safe constrains.
I think it is a bug, as if the template declaration is already in @safe scope, it is detected.

template unsafe(T...) { enum unsafe = T[0]; }
@system enum SYS_VAL = 55;

void main() @safe {

    auto a = unsafe!SYS_VAL;      //  <-- This is undetected   

    template _unsafe(T...) {enum _unsafe = T[0];}
    auto b = _unsafe!SYS_VAL;    // Deprecation: cannot access `@system` variable `SYS_VAL` in @safe code

}
@zero-vector
Copy link
Author

This is a naive fix I came up with.

(somehow I am unable to append the patch, so here it is)

diff --git a/compiler/src/dmd/dsymbolsem.d b/compiler/src/dmd/dsymbolsem.d
index dd36a8fac7..bc151f834a 100644
--- a/compiler/src/dmd/dsymbolsem.d
+++ b/compiler/src/dmd/dsymbolsem.d
@@ -7055,6 +7055,7 @@ version (IN_LLVM)
     Scope* sc2;
     sc2 = _scope.push(tempinst);
     //printf("enclosing = %d, sc.parent = %s\n", tempinst.enclosing, sc.parent.toChars());
+    sc2.func = sc.func; // For @safe checks.
     sc2.parent = tempinst;
     sc2.tinst = tempinst;
     sc2.minst = tempinst.minst;

@thewilsonator thewilsonator added the Severity:safe @safe code label Mar 11, 2025
@thewilsonator
Copy link
Contributor

cc @pbackus could you please evaluate this and the proposed solution?

@pbackus
Copy link
Contributor

pbackus commented Mar 11, 2025

This is definitely a bug. Here's an example that actually causes UB in @safe code:

@system enum SYS_VAL = cast(int*) 0xDEADBEEF;
template unsafe(T...) { enum unsafe = T[0]; }

void main() @safe
{
    int oops = *unsafe!SYS_VAL;
}

I think the correct solution here is for enum unsafe inside the template to itself be inferred as a @system variable, because it has a @system initializer. That inference is part of DIP 1035, but it looks like it isn't implemented yet, because the following example also compiles:

@system enum SYS_VAL = cast(int*) 0xDEADBEEF;
int* p = SYS_VAL; // not inferred as @system

void main() @safe
{
    int oops = *p;
}

@pbackus
Copy link
Contributor

pbackus commented Mar 11, 2025

Last I heard @dkorpel was working on this, but he's probably been too busy dealing with the 2.110 release to get back to it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Severity:safe @safe code
Projects
None yet
Development

No branches or pull requests

3 participants