67 changes: 67 additions & 0 deletions test/runnable/imports/link15194std.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
module imports.link15194std;

// std.algorithm.setopts

/* setUnion template function is instantiated in module link15194 as root,
* and linked into executable.
*
* - In "original case", due to link to typeid(const RBRange!(RBNode!int*)),
* unSpeculative should be called for the type of typeid operand.
*
* - In "additional case", typeid(const RBRange!(RBNode!int*)*) returns
* TypeInfo_Pointer instance. But later its 'next' field access will reference
* RBRange instance. Therefore typeid should also unSpeculative the bottom struct
* of operand type.
*/
version (A)
{
// additional case

TypeInfo setUnion(Rs...)(Rs )
{
return typeid(const Rs[0]*).next;

// semanticTypeInfo should also unSpaculate TypePointer.next.
}
}
else
{
// original case

struct SetUnion(Rs...)
{
pragma(msg, Rs);
Rs r;

// Rs[0] == RBRange!(RBNode!int*)
// Rs[1] == int[]

// size_t toHash() is implicitly generated by buildXtoHash.
// And from that,
// typeid(const RBRange!(RBNode!int*))
// and
// typeid(const int[])
// are referenced to invoke TypeInfo.getHash().
}

SetUnion!(Rs) setUnion(Rs...)(Rs )
{
return typeof(return)();
}
}

// std.container.rbtree

struct RBNode(V) {}

struct RBRange(N) {}

class RedBlackTree(Elem)
{
alias Range = RBRange!(RBNode!Elem*);

Range opSlice()
{
return Range();
}
}
16 changes: 16 additions & 0 deletions test/runnable/link15149.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// REQUIRED_ARGS: -g
// PERMUTE_ARGS: -inline -version=A
// EXTRA_SOURCES: imports/link15194b.d imports/link15194std.d
// COMPILE_SEPARATELY: -g

import imports.link15194std;
import imports.link15194b;

void main()
{
int[] foo;

// fun() returns new RedBlackTree!int. But it's instantiated in
// non-template non-root function, so it's left as speculative.
setUnion(fun()[], foo);
}