Skip to content

Comments

fix regression for GDC: make return type of _d_assocarrayliteralTX consistent with V[K] in the AST#22612

Open
rainers wants to merge 1 commit intodlang:stablefrom
rainers:aa_literal_cast
Open

fix regression for GDC: make return type of _d_assocarrayliteralTX consistent with V[K] in the AST#22612
rainers wants to merge 1 commit intodlang:stablefrom
rainers:aa_literal_cast

Conversation

@rainers
Copy link
Member

@rainers rainers commented Feb 22, 2026

@ibuclaw good enough for #21066 (comment) ?

@dlang-bot
Copy link
Contributor

Thanks for your pull request, @rainers!

Bugzilla references

Your PR doesn't reference any Bugzilla issue.

If your PR contains non-trivial changes, please reference a Bugzilla issue or create a manual changelog.

Testing this PR locally

If you don't have a local development environment setup, you can use Digger to test this PR:

dub run digger -- build "stable + dmd#22612"

@ibuclaw
Copy link
Member

ibuclaw commented Feb 22, 2026

@ibuclaw the dmd glue layer doesn't really know about associative arrays anymore (but to assert on missing lowerings or to swtitch to it for literals), so I assume that it uses void* as a representation, see also TYaarray. I also don't see anything in the original code using a wrapper struct in 05ed167#diff-77d45d18f4adde2459ebdfef916f5f5fc2050101dc7803278121ddf526dbaccaL4212. Could you just use a pointer in GDC aswell?

Hmm, I thought it was specified as a struct with a single pointer field in the language ABI spec, but apparently it's always been defined as:

Associative arrays consist of a pointer to an opaque, implementation defined type.

The struct actually came from the old library implementation (all the way back from D1) and used as the parameter type all the hooks.

The new implementation still inherits this though and the various reinterpret casts can be read as:

auto toAA(struct PodAA aa)
{
    return *(cast(struct AA!(K, V)*)&aa);
}

As it's a bit late to change the ABI now. I'd probably err towards leaving GDC to return AssocArrayLiteralExp's as a constructor in the backend. Unless LDC interpreted the ABI of AAs as being a struct type too @kinke ?

@rainers
Copy link
Member Author

rainers commented Feb 22, 2026

This PR adds a cast from Impl!(K,V)* to V[K] to the AST of AA literals. As all other hooks accept V[K], too, doesn't that allow the glue/backend to use any representation?

@kinke
Copy link
Contributor

kinke commented Feb 22, 2026

I vaguely recall a former problem wrt. plain void* and struct { void* } - druntime using the latter somewhere (struct AA or so), but the glue code emitting fwd declarations of the known old runtime hooks using plain void* to simplify things; IIRC, we changed it to alias AA = void* in the old druntime module to get it to compile. These problems went away with the new lowerings; internally, the IR representation of an AA is a plain (opaque) pointer.

@kinke
Copy link
Contributor

kinke commented Feb 23, 2026

Ah, that's debuginfo only - okay there we represent it as struct. It's always been a void* in IR otherwise for as far as I can remember. And no problems with latest stable in that regard, although I can't rule out there are some existing IR workarounds/casts in place which made this PR not required.

@ibuclaw
Copy link
Member

ibuclaw commented Feb 23, 2026

@kinke ok.

@rainers I get.

file.d:X:Y: error: conversion to non-scalar type requested

Which is pendantically true. :-)

I never actually noticed this behaviour before.

int[int] toAA(void* ptr)
{
    return cast(int[int])ptr;
}
int[int] toAA(short* ptr)
{
    return cast(int[int])ptr;
}
int[int] toAA(float* ptr)
{
    return cast(int[int])ptr;
}
struct S{}
int[int] toAA(S* ptr)
{
    return cast(int[int])ptr;
}
class C{}
int[int] toAA(C ptr)
{
    return cast(int[int])ptr;
}
int[int] toAA(void function() ptr)
{
    return cast(int[int])ptr;
}

DMD happily compiles all the above, how bizarre.

Edit: And you can cast all the above back to an AA again, because why not?

@ibuclaw
Copy link
Member

ibuclaw commented Feb 23, 2026

DMD happily compiles all the above, how bizarre.

@kinke

0  ldc2      0x000058fb66f0c588 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) + 40
1  ldc2      0x000058fb66f09f8c llvm::sys::RunSignalHandlers() + 188
2  ldc2      0x000058fb66f0d2e1
3  libc.so.6 0x00007335ad4ba330
4  ldc2      0x000058fb6721d2cc DtoDynamicCastObject(Loc, DValue*, Type*) + 172
5  ldc2      0x000058fb6721cc4d DtoCastClass(Loc, DValue*, Type*) + 957
6  ldc2      0x000058fb67209fdd DtoCast(Loc, DValue*, Type*) + 829
7  ldc2      0x000058fb67271909
8  ldc2      0x000058fb67256884
9  ldc2      0x000058fb6725f52b
10 ldc2      0x000058fb671f6ad1 DtoDefineFunction(FuncDeclaration*, bool) + 6961
11 ldc2      0x000058fb67222c72 codegenModule(IRState*, Module*) + 4258
12 ldc2      0x000058fb672c7765 ldc::CodeGenerator::emit(Module*) + 213
13 ldc2      0x000058fb635bb9f7 codegenModules(Array<Module*>&) + 951
14 ldc2      0x000058fb635458f7 mars_tryMain(Param&, Array<char const*>&) + 2023
15 ldc2      0x000058fb635be640 cppmain() + 8528
16 ldc2      0x000058fb674ad97d _D2rt6dmain212_d_run_main2UAAamPUQgZiZ6runAllMFZv + 77
17 ldc2      0x000058fb674ad75e _d_run_main2 + 462
18 ldc2      0x000058fb674ad57d _d_run_main + 141
19 ldc2      0x000058fb672c442c main + 716
20 libc.so.6 0x00007335ad49f1ca
21 libc.so.6 0x00007335ad49f28b __libc_start_main + 139
22 ldc2      0x000058fb635c31e5 _start + 37
Segmentation fault (core dumped)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants