Skip to content

Commit

Permalink
Merge pull request #5881 from WalterBright/fix14162
Browse files Browse the repository at this point in the history
fix Issue 14162 - Erratic inference of @safe for lambdas
  • Loading branch information
andralex committed Jun 28, 2016
2 parents 9008756 + 366378a commit 1116591
Show file tree
Hide file tree
Showing 9 changed files with 117 additions and 101 deletions.
22 changes: 5 additions & 17 deletions src/func.d
Expand Up @@ -604,21 +604,6 @@ extern (C++) class FuncDeclaration : Declaration
TypeFunction tf = cast(TypeFunction)type;
if (sc.func)
{
/* If the parent is @safe, then this function defaults to safe too.
*/
if (tf.trust == TRUSTdefault)
{
FuncDeclaration fd = sc.func;

/* If the parent's @safe-ty is inferred, then this function's @safe-ty needs
* to be inferred first.
* If this function's @safe-ty is inferred, then it needs to be infeerd first.
* (local template function inside @safe function can be inferred to @system).
*/
if (fd.isSafeBypassingInference() && !isInstantiated())
tf.trust = TRUSTsafe; // default to @safe
}

/* If the nesting parent is pure without inference,
* then this function defaults to pure too.
*
Expand Down Expand Up @@ -1275,8 +1260,11 @@ extern (C++) class FuncDeclaration : Declaration
* the function body.
*/
TemplateInstance ti;
if (fbody &&
(isFuncLiteralDeclaration() || (storage_class & STCinference) || (inferRetType && !isCtorDeclaration()) || isInstantiated() && !isVirtualMethod() &&
if (fbody && !isVirtualMethod() &&
/********** this is for backwards compatibility for the moment ********/
(sc.func && (!isMember() || sc.func.isSafeBypassingInference() && !isInstantiated()) ||
isFuncLiteralDeclaration() || (storage_class & STCinference) || (inferRetType && !isCtorDeclaration()) ||
isInstantiated() &&
((ti = parent.isTemplateInstance()) is null || ti.isTemplateMixin() || ti.tempdecl.ident == ident)))
{
if (f.purity == PUREimpure) // purity not specified
Expand Down
20 changes: 10 additions & 10 deletions test/compilable/testInference.d
Expand Up @@ -375,9 +375,9 @@ void test9148a() pure
x++;
}
foo1();
static assert(is(typeof(&foo1) == void delegate() pure));
static assert(is(typeof(&foo1) == void delegate() pure nothrow @nogc @safe));
foo2();
static assert(is(typeof(&foo2) == void delegate() pure));
static assert(is(typeof(&foo2) == void delegate() pure nothrow @nogc @safe));

void bar1() immutable /+pure+/
{
Expand All @@ -390,9 +390,9 @@ void test9148a() pure
static assert(!__traits(compiles, x++));
}
bar1();
static assert(is(typeof(&bar1) == void delegate() pure immutable));
static assert(is(typeof(&bar1) == void delegate() pure immutable nothrow @nogc @safe));
bar2();
static assert(is(typeof(&bar2) == void delegate() pure immutable));
static assert(is(typeof(&bar2) == void delegate() pure immutable nothrow @nogc @safe));

struct S
{
Expand Down Expand Up @@ -437,28 +437,28 @@ void test9148a() pure
void test9148b() pure nothrow @nogc @safe
{
void nf() {}
static assert(is(typeof(&nf) == void delegate() @safe pure));
static assert(is(typeof(&nf) == void delegate() pure nothrow @nogc @safe));

struct NS
{
void mf() {}
static void sf() {}
}
NS ns;
static assert(is(typeof(&ns.mf) == void delegate() @safe pure));
static assert(is(typeof(&NS.sf) == void function() @safe));
static assert(is(typeof(&ns.mf) == void delegate() pure nothrow @nogc @safe));
static assert(is(typeof(&NS.sf) == void function() pure nothrow @nogc @safe));

static void sf() {}
static assert(is(typeof(&sf) == void function() @safe));
static assert(is(typeof(&sf) == void function() pure nothrow @nogc @safe));

static struct SS
{
void mf() {}
static void sf() {}
}
SS ss;
static assert(is(typeof(&ss.mf) == void delegate() @safe));
static assert(is(typeof(&SS.sf) == void function() @safe));
static assert(is(typeof(&ss.mf) == void delegate() pure nothrow @nogc @safe));
static assert(is(typeof(&SS.sf) == void function() pure nothrow @nogc @safe));
}

void impureSystem9148b() {}
Expand Down
60 changes: 30 additions & 30 deletions test/runnable/functype.d
Expand Up @@ -6,43 +6,43 @@ void testfp()
{
static int func1(int n = 1) { return n; }
static int func2(int n ) { return n; }
static assert(typeof(func1).stringof == "int(int n = 1)");
static assert(typeof(func2).stringof == "int(int n)");
static assert(typeof(func1).stringof == "pure nothrow @nogc @safe int(int n = 1)");
static assert(typeof(func2).stringof == "pure nothrow @nogc @safe int(int n)");
static assert( is(typeof(func1()))); // OK
static assert(!is(typeof(func2()))); // NG

alias typeof(func1) Func1;
alias typeof(func2) Func2;
static assert(is(Func1 == Func2));
static assert(Func1.stringof == "int(int n = 1)");
static assert(Func2.stringof == "int(int n)");
static assert(Func1.stringof == "pure nothrow @nogc @safe int(int n = 1)");
static assert(Func2.stringof == "pure nothrow @nogc @safe int(int n)");

auto fp1 = &func1;
auto fp2 = &func2;
static assert(typeof(fp1).stringof == "int function(int n = 1)");
static assert(typeof(fp2).stringof == "int function(int n)");
static assert(typeof(fp1).stringof == "int function(int n = 1) pure nothrow @nogc @safe");
static assert(typeof(fp2).stringof == "int function(int n) pure nothrow @nogc @safe");
static assert( is(typeof(fp1()))); // OK
static assert(!is(typeof(fp2()))); // NG

alias typeof(fp1) Fp1;
alias typeof(fp2) Fp2;
static assert(is(Fp1 == Fp2));
static assert(Fp1.stringof == "int function(int n = 1)");
static assert(Fp2.stringof == "int function(int n)");
static assert(Fp1.stringof == "int function(int n = 1) pure nothrow @nogc @safe");
static assert(Fp2.stringof == "int function(int n) pure nothrow @nogc @safe");

typeof(fp1) fp3 = fp1;
typeof(fp2) fp4 = fp2;
static assert(is(typeof(fp3) == typeof(fp4)));
static assert(typeof(fp3).stringof == "int function(int n = 1)");
static assert(typeof(fp4).stringof == "int function(int n)");
static assert(typeof(fp3).stringof == "int function(int n = 1) pure nothrow @nogc @safe");
static assert(typeof(fp4).stringof == "int function(int n) pure nothrow @nogc @safe");
static assert( is(typeof(fp3()))); // OK
static assert(!is(typeof(fp4()))); // NG

alias typeof(fp3) Fp3;
alias typeof(fp4) Fp4;
static assert(is(Fp3 == Fp4));
static assert(Fp3.stringof == "int function(int n = 1)");
static assert(Fp4.stringof == "int function(int n)");
static assert(Fp3.stringof == "int function(int n = 1) pure nothrow @nogc @safe");
static assert(Fp4.stringof == "int function(int n) pure nothrow @nogc @safe");

auto fplit1 = function(int n = 1) { return n; };
auto fplit2 = function(int n ) { return n; };
Expand All @@ -54,42 +54,42 @@ void testdg()
{
int nest1(int n = 1) { return n; }
int nest2(int n ) { return n; }
static assert(typeof(nest1).stringof == "int(int n = 1)");
static assert(typeof(nest2).stringof == "int(int n)");
static assert(typeof(nest1).stringof == "pure nothrow @nogc @safe int(int n = 1)");
static assert(typeof(nest2).stringof == "pure nothrow @nogc @safe int(int n)");
static assert( is(typeof(nest1()))); // OK
static assert(!is(typeof(nest2()))); // NG

alias typeof(nest1) Nest1;
alias typeof(nest2) Nest2;
static assert(is(Nest1 == Nest2));
static assert(Nest1.stringof == "int(int n = 1)");
static assert(Nest2.stringof == "int(int n)");
static assert(Nest1.stringof == "pure nothrow @nogc @safe int(int n = 1)");
static assert(Nest2.stringof == "pure nothrow @nogc @safe int(int n)");

auto dg1 = &nest1;
auto dg2 = &nest2;
static assert(typeof(dg1).stringof == "int delegate(int n = 1)");
static assert(typeof(dg2).stringof == "int delegate(int n)");
static assert(typeof(dg1).stringof == "int delegate(int n = 1) pure nothrow @nogc @safe");
static assert(typeof(dg2).stringof == "int delegate(int n) pure nothrow @nogc @safe");
static assert( is(typeof(dg1()))); // OK
static assert(!is(typeof(dg2()))); // NG

alias typeof(dg1) Dg1;
alias typeof(dg2) Dg2;
static assert(is(Dg1 == Dg2));
static assert(Dg1.stringof == "int delegate(int n = 1)");
static assert(Dg2.stringof == "int delegate(int n)");
static assert(Dg1.stringof == "int delegate(int n = 1) pure nothrow @nogc @safe");
static assert(Dg2.stringof == "int delegate(int n) pure nothrow @nogc @safe");

typeof(dg1) dg3 = dg1;
typeof(dg2) dg4 = dg2;
static assert(typeof(dg3).stringof == "int delegate(int n = 1)");
static assert(typeof(dg4).stringof == "int delegate(int n)");
static assert(typeof(dg3).stringof == "int delegate(int n = 1) pure nothrow @nogc @safe");
static assert(typeof(dg4).stringof == "int delegate(int n) pure nothrow @nogc @safe");
static assert( is(typeof(dg3()))); // OK
static assert(!is(typeof(dg4()))); // NG

alias typeof(dg3) Dg3;
alias typeof(dg4) Dg4;
static assert(is(Dg3 == Dg4));
static assert(Dg3.stringof == "int delegate(int n = 1)");
static assert(Dg4.stringof == "int delegate(int n)");
static assert(Dg3.stringof == "int delegate(int n = 1) pure nothrow @nogc @safe");
static assert(Dg4.stringof == "int delegate(int n) pure nothrow @nogc @safe");

auto dglit1 = delegate(int n = 1) { return n; };
auto dglit2 = delegate(int n ) { return n; };
Expand Down Expand Up @@ -127,8 +127,8 @@ template StringOf(T)
void testti()
{
int[] test(int[] a = []) { return a; }
static assert(typeof(test).stringof == "int[](int[] a = [])");
static assert(StringOf!(typeof(test)) == "int[](int[])");
static assert(typeof(test).stringof == "pure nothrow @nogc @safe int[](int[] a = [])");
static assert(StringOf!(typeof(test)) == "pure nothrow @nogc @safe int[](int[])");

float function(float x = 0F) fp = x => x;
static assert(typeof(fp).stringof == "float function(float x = " ~ (0F).stringof ~ ")");
Expand Down Expand Up @@ -240,17 +240,17 @@ void test8579()
auto fn2 = &func2;
static assert(is(typeof(fn1) == typeof(fn2)));
assert( typeid(fn1) is typeid(fn2) );
static assert(typeof(fn1).stringof == "void function(int i, double j = " ~ (1.0).stringof ~ ")");
static assert(typeof(fn2).stringof == "void function(int x, double y)");
static assert(typeof(fn1).stringof == "void function(int i, double j = " ~ (1.0).stringof ~ ") pure nothrow @nogc @safe");
static assert(typeof(fn2).stringof == "void function(int x, double y) pure nothrow @nogc @safe");

static int func3(int x, double y) { return 0; }
static int func4(int i, double j = 1.0) { return 0; }
auto fn3 = &func3;
auto fn4 = &func4;
static assert(is(typeof(fn3) == typeof(fn4)));
assert( typeid(fn3) is typeid(fn4) );
static assert(typeof(fn3).stringof == "int function(int x, double y)");
static assert(typeof(fn4).stringof == "int function(int i, double j = " ~ (1.0).stringof ~ ")");
static assert(typeof(fn3).stringof == "int function(int x, double y) pure nothrow @nogc @safe");
static assert(typeof(fn4).stringof == "int function(int i, double j = " ~ (1.0).stringof ~ ") pure nothrow @nogc @safe");
}

/***************************************************/
Expand Down
4 changes: 2 additions & 2 deletions test/runnable/mangle.d
Expand Up @@ -84,7 +84,7 @@ static assert(TFoo2774!int.mangleof == "6mangle15__T8TFoo2774TiZ");
void test2774()
{
int foo2774(int n) { return 0; }
static assert(foo2774.mangleof == "_D6mangle8test2774FZ7foo2774MFiZi");
static assert(foo2774.mangleof == "_D6mangle8test2774FZ7foo2774MFNaNbNiNfiZi");
}

/*******************************************/
Expand Down Expand Up @@ -462,7 +462,7 @@ void test12217(int)
template X(T) {}

static assert( S.mangleof == "S6mangle9test12217FiZ1S");
static assert( bar.mangleof == "_D6mangle9test12217FiZ3barMFZv");
static assert( bar.mangleof == "_D6mangle9test12217FiZ3barMFNaNbNiNfZv");
static assert( var.mangleof == "_D6mangle9test12217FiZ3vari");
static assert(X!int.mangleof == "6mangle9test12217FiZ8__T1XTiZ");
}
Expand Down
4 changes: 2 additions & 2 deletions test/runnable/mixin1.d
Expand Up @@ -1386,8 +1386,8 @@ int test14243()
{
int var = 1;
mixin Mix14243e!12;
static assert(is(typeof(&foo) == int delegate() @safe nothrow));
static assert(is(typeof(&bar) == int function() @safe nothrow));
static assert(is(typeof(&foo) == int delegate() @safe nothrow pure @nogc));
static assert(is(typeof(&bar) == int function() @safe nothrow pure @nogc));
static assert(S.sizeof == int.sizeof); // s is static struct
assert(foo() == 1);
assert(bar() == 12);
Expand Down
12 changes: 6 additions & 6 deletions test/runnable/testconst.d
Expand Up @@ -2160,7 +2160,7 @@ void test5473()
static void g(){};
}

void dummy(){}
void dummy();
alias typeof(dummy) VoidFunc;

const C c = new C;
Expand Down Expand Up @@ -2729,11 +2729,11 @@ void test12524(inout(int))
/************************************/
// 6941

static assert((const(shared(int[])[])).stringof == "const(shared(int[])[])"); // fail
static assert((const(shared(int[])[])).stringof == "const(shared(int[])[])"); // fail
static assert((const(shared(int[])[])).stringof != "const(shared(const(int[]))[])"); // fail

static assert((inout(shared(int[])[])).stringof == "inout(shared(int[])[])"); // fail
static assert((inout(shared(int[])[])).stringof != "inout(shared(inout(int[]))[])"); // fail
static assert((inout(shared(int[])[])).stringof == "inout(shared(int[])[])"); // fail
static assert((inout(shared(int[])[])).stringof != "inout(shared(inout(int[]))[])"); // fail

/************************************/
// 6872
Expand Down Expand Up @@ -3427,15 +3427,15 @@ inout(int)* function(inout(int)*) fptr10761(inout(int)*)
{
static inout(int)* screwUp(inout(int)* x) { return x; }
auto fp = &screwUp;
static assert(is(typeof(fp) == inout(int)* function(inout(int)*)));
static assert(is(typeof(fp) == inout(int)* function(inout(int)*) pure nothrow @nogc @safe));
return fp;
}

inout(int)* delegate(inout(int)*) nest10761(inout(int)* x)
{
inout(int)* screwUp(inout(int)* _) { return x; }
auto dg = &screwUp;
static assert(is(typeof(dg) == inout(int)* delegate(inout(int)*)));
static assert(is(typeof(dg) == inout(int)* delegate(inout(int)*) pure nothrow @nogc @safe));
return dg;
}

Expand Down

0 comments on commit 1116591

Please sign in to comment.