Bug 24253 – fn "is not accessible from module" with overload reflection regressed in v2.105

Status
NEW
Severity
regression
Priority
P5
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2023-11-20T18:03:50Z
Last change time
2024-12-13T19:31:55Z
Assigned to
No Owner
Creator
Adam D. Ruppe
Moved to GitHub: dmd#20362 →

Comments

Comment #0 by destructionator — 2023-11-20T18:03:50Z
Must have two modules so `private` applies: --- // bug.d import bug2; private void fooImpl() { } void main() { mvd!fooImpl(); } --- And: --- // bug2.d void mvd(alias fn)() { auto this_ = null; // we could call `fn` directly here since we got an alias ov: foreach(overload; __traits(getOverloads, __traits(parent, fn), __traits(identifier, fn))) { __traits(child, this_, overload)(); // but cannot use through traits } } --- You actually don't need the overload loop here, you could remove that to minimize further ``` void mvd(alias fn)() { auto this_ = null; fn(); // this allowed //__traits(child, this_, fn)(); // this is not } ``` But I wanted to show the loop to give you an idea of the real world use case this is affecting; it is a multiple virtual dispatch implementation. Interestingly, in dmd 2.098: ``` fn; // bug2.d(3): Deprecation: Function `bug.fooImpl` of type `void()` is not accessible from module `bug2` fn(); // perfectly OK; it let me call it through the alias, but not reference it ``` Which is a bit bizarre. I suspect the fix was intended to treat these two cases the same, but it awkward in any case. Anyway, the error when calling the function was introduced by this commit: https://github.com/dlang/dmd/commit/421ebfe8b5777707c7a415f64523bedf6ff2dd66 Before that, it worked without issue, after that, it deprecated, then a future commit (36043ded818506936790be55f9353d6132527541) turned the deprecation into an error. The first release to fail with this was https://dlang.org/changelog/2.105.0.html
Comment #1 by default_357-line — 2023-11-23T08:08:47Z
Fwiw, that only ever worked "by coincidence" because the access check only checked for structs and classes, and typeof(null) is a nullptr_t, which is neither. I see what I did wrong in my PR, but I'm not sure that just putting the previous check back in is the way to go. It was always weird. Problem is that sema has a way to disable access check on a scope (SCOPE.noaccesscheck), but afterwards the __traits(child) just becomes `this_.fooImpl`, which is then rechecked in sema3 and fails access. I'd need a way to mark the *access itself*, ie. the DotExp, as "no access check".
Comment #2 by robert.schadek — 2024-12-13T19:31:55Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/20362 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB