blob: bb879957d4c0c22b524444c5d79f8cb0d966ee0e [file] [log] [blame]
/*
RUN_OUTPUT:
---
Success
---
*/
extern(C) int printf(const char*, ...);
/**********************************/
// https://issues.dlang.org/show_bug.cgi?id=7511
struct S7511(T)
{
// this is a pure function for T==int
T foo(T x)
{
return 2 * x;
}
}
void test7511a() pure
{
S7511!int s;
s.foo(2); // error -> OK
}
/**********************************/
// certain case - wrapper range
//import std.range;
@property bool empty(T)(in T[] a) { return !a.length; }
@property ref T front(T)(T[] a) { return a[0]; }
void popFront(T)(ref T[] a) { a = a[1 .. $]; }
struct S(T)
{
int foo()
{
auto t = T();
return t.bar();
}
}
struct Wrap(R)
{
R original;
this(T : R)(T t) { original = t; }
this(A...)(A args) { original = R(args); }
@property auto empty() { return original.empty; }
@property auto front() { return original.front; }
void popFront() { original.popFront(); }
}
void test7511b() pure @safe
{
static struct Iota
{
size_t curr;
size_t max;
@property bool empty() pure @safe { return curr == max; }
@property size_t front() pure @safe { return curr; }
void popFront() pure @safe { ++curr; }
}
{
auto a = Iota(0, 3);
size_t i = 0;
foreach (e; a) { assert(e == i++); } // OK
}
{
auto a = Wrap!(int[])([0,1,2]);
size_t i = 0;
foreach (e; a) { assert(e == i++); } // errors!
}
{
auto a = Wrap!Iota(0, 3);
size_t i = 0;
foreach (e; a) { assert(e == i++); } // errors!
}
}
/**********************************/
// with attribute inheritance
struct X
{
static int bar() pure nothrow @safe
{
return 1;
}
}
class Class(T)
{
int foo()
{ // inferred to pure nothrow @safe
return T.bar();
}
}
alias Class!X C;
class D : C
{
override int foo()
{ // inherits attributes from Class!X.foo
return 2;
}
}
void test7511c() pure nothrow @safe
{
// Disabled for Bigzilla 9952
/+
assert((new C()).foo() == 1);
assert((new D()).foo() == 2);
static assert(typeof(&C.init.foo).stringof == "int delegate() pure nothrow @safe");
static assert(typeof(&D.init.foo).stringof == "int delegate() pure nothrow @safe");
+/
}
/**********************************/
// curiously recurring template pattern (CRTP)
class BX(T, bool mutual)
{
int foo()
{
static if (mutual)
return (cast(T)this).foo();
else
return 0;
}
}
class D1 : BX!(D1, true)
{
alias typeof(super) B;
int val;
this(int n) { val = n; }
override int foo() { return val; }
}
class D2 : BX!(D2, false)
{
alias typeof(super) B;
int val;
this(int n) { val = n; }
override int foo() { return val; }
}
class D3 : BX!(D3, true)
{
alias typeof(super) B;
int val;
this(int n) { val = n; }
override int foo() pure nothrow { return val; }
}
class D4 : BX!(D4, false)
{
alias typeof(super) B;
int val;
this(int n) { val = n; }
override int foo() pure nothrow { return val; }
}
void test7511d()
{
// Disabled for Bigzilla 9952
/+
// mutual dependent and attribute inference impure, un-@safe, and may throw is default.
auto d1 = new D1(10);
static assert(is(typeof(&d1.B.foo) == int function()));
static assert(is(typeof(&d1.foo) == int delegate()));
assert(d1.foo() == 10);
// no mutual dependent.
auto d2 = new D2(10);
static assert(is(typeof(&d2.B.foo) == int function() pure nothrow @safe));
static assert(is(typeof(&d2 .foo) == int delegate() pure nothrow @safe));
assert(d2.foo() == 10);
// mutual dependent with explicit attribute specification.
auto d3 = new D3(10);
static assert(is(typeof(&d3.B.foo) == int function() pure nothrow));
static assert(is(typeof(&d3 .foo) == int delegate() pure nothrow));
assert(d3.foo() == 10);
// no mutual dependent with explicit attribute specification.
auto d4 = new D4(10);
static assert(is(typeof(&d4.B.foo) == int function() pure nothrow @safe));
static assert(is(typeof(&d4 .foo) == int delegate() pure nothrow @safe));
assert(d4.foo() == 10);
+/
}
/**********************************/
// https://issues.dlang.org/show_bug.cgi?id=9952
@system void writeln9952(int) {} // impure throwable
class C9952(T)
{
T foo()
{
return 2;
}
}
class D9952 : C9952!int
{
override int foo()
{
writeln9952(super.foo());
return 3;
}
}
void test9952()
{
static assert(typeof(&C9952!int.init.foo).stringof == "int delegate()");
static assert(typeof(&D9952 .init.foo).stringof == "int delegate()");
}
/**********************************/
// https://issues.dlang.org/show_bug.cgi?id=10373
template isMutable10373(T)
{
enum isMutable10373 = !is(T == const) && !is(T == immutable) && !is(T == inout);
}
struct Test10373a(T, int N = 0)
{
static if (N == 0) T[ ] mBuffer;
else T[N] mBuffer;
static if (is(T == class))
{}
else
{
T* at_(size_t n) { return &mBuffer[n]; }
static if (is(typeof(*at_(0) = T.init)))
{
T opIndexAssign(T v, size_t i)
{
return (*at_(i) = v);
}
}
}
}
struct Test10373b(T, int N = 0)
{
static if (is(T == class))
{}
else
{
T* at_(size_t n) { return &mBuffer[n]; }
static if (is(typeof(*at_(0) = T.init)))
{
T opIndexAssign(T v, size_t i)
{
return (*at_(i) = v);
}
}
}
static if (N == 0) T[ ] mBuffer;
else T[N] mBuffer;
}
struct Test10373c(T, int N = 0)
{
static if (is(T == class))
{}
else
{
T* at_(size_t n) { return &mBuffer[n]; }
static if (isMutable10373!T)
{
T opIndexAssign(T v, size_t i)
{
return (*at_(i) = v);
}
}
}
static if (N == 0) T[ ] mBuffer;
else T[N] mBuffer;
}
void test10373()
{
static assert(is(Test10373a!(int, 2)));
static assert(is(Test10373b!(int, 2)));
static assert(is(Test10373c!(int, 2)));
Test10373a!(int, 2) testa; // dmd2.062:OK dmd2.063:OK
Test10373b!(int, 2) testb; // dmd2.062:OK dmd2.063:NG
Test10373c!(int, 2) testc; // dmd2.062:OK dmd2.063:OK
}
/**********************************/
// https://issues.dlang.org/show_bug.cgi?id=10329
auto foo10329(T)(T arg)
{
auto bar()
{
return arg;
}
static assert(is(typeof(&bar) == T delegate() pure nothrow @nogc @safe));
return bar();
}
auto make10329(T)(T arg)
{
struct S
{
auto front() { return T.init; }
}
S s;
static assert(is(typeof(&s.front) == T delegate() pure nothrow @nogc @safe));
return s;
}
void test10329() pure nothrow @safe
{
assert(foo10329(1) == 1);
auto s = make10329(1);
assert(s.front() == 0);
}
/**********************************/
// https://issues.dlang.org/show_bug.cgi?id=11896
class Foo11896a(T = int)
{
static if (!__traits(isVirtualMethod, zoo)) {} else { Undefined x; }
static void bar() {}
static void bar(Foo11896a foo) {}
static void zoo()
{
bar(new Foo11896a);
}
}
Foo11896a!(int) baz11896a;
// ----
Frop11896b!(int) frop11896b;
mixin template baz11896b()
{
public void bar11896b() {}
}
mixin baz11896b;
class Foo11896b(T)
{
static if (! __traits(isVirtualMethod, zoo)) {}
static void zoo()
{
bar11896b();
}
}
class Frop11896b(T) : Foo11896b!T {}
// ----
static bool flag11896c = false;
class Bar11896c {}
class Foo11896c(T = Bar11896c)
{
static if (! __traits(isVirtualMethod, foo)) {}
alias Foo11896c!(T) this_type;
this()
{
flag11896c = true;
}
static public this_type foo()
{
auto c = new this_type();
return flag11896c ? c : null;
}
}
void test11896c()
{
alias Foo11896c!Bar11896c FooBar;
assert(FooBar.foo() !is null);
}
/**********************************/
// https://issues.dlang.org/show_bug.cgi?id=12392
void f12392(T)() {}
alias fa12392 = f12392;
void test12392() pure nothrow @safe
{
fa12392!int();
}
/**********************************/
int main()
{
test7511a();
test7511b();
test7511c();
test7511d();
test9952();
test10373();
test10329();
test11896c();
printf("Success\n");
return 0;
}