Skip to content

Commit

Permalink
Revert 9rnsr/fix9230 and 9rnsr/fix8408
Browse files Browse the repository at this point in the history
- Revert "Merge pull request #1418 from 9rnsr/fix9230"

  This reverts commit c42d35b, reversing
  changes made to 9f2d9ea.

- Revert "Merge pull request #1110 from 9rnsr/fix8408"

  This reverts commit b6a8093, reversing
  changes made to 3b06132.
  • Loading branch information
9rnsr committed Feb 5, 2013
1 parent 3c1a1f3 commit b65d12a
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 245 deletions.
2 changes: 0 additions & 2 deletions src/func.c
Expand Up @@ -3063,8 +3063,6 @@ enum PURE FuncDeclaration::isPureBypassingInference()
{
if (flags & FUNCFLAGpurityInprocess)
return PUREfwdref;
else if (type->nextOf() == NULL)
return PUREfwdref;
else
return isPure();
}
Expand Down
174 changes: 42 additions & 132 deletions src/mtype.c
Expand Up @@ -5778,168 +5778,78 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
}


Type *getIndirection(Type *t)
{
t = t->toBasetype();

if (t->ty == Tsarray)
{ while (t->ty == Tsarray)
t = t->nextOf()->toBasetype();
}
if (t->ty == Tarray || t->ty == Tpointer)
return t->nextOf()->toBasetype();
if (t->ty == Taarray || t->ty == Tclass)
return t;
if (t->ty == Tstruct)
return t->hasPointers() ? t : NULL; // TODO

// should consider TypeDelegate?
return NULL;
}

/********************************************
* Do this lazily, as the parameter types might be forward referenced.
*/
void TypeFunction::purityLevel()
{
//printf("purityLevel(%s)\n", toChars());

TypeFunction *tf = this;
if (tf->purity == PUREfwdref && tf->next)
if (tf->purity == PUREfwdref)
{ /* Evaluate what kind of purity based on the modifiers for the parameters
*/
enum PURE purity = PUREstrong; // assume strong until something weakens it
size_t dim = Parameter::dim(tf->parameters);

if (dim)
tf->purity = PUREstrong; // assume strong until something weakens it
if (tf->parameters)
{
Type *tret = tf->next;
assert(tret);
Type *treti = tf->isref ? tret->toBasetype() : getIndirection(tret);
if (treti && (treti->mod & MODimmutable))
treti = NULL; // indirection is immutable
//printf(" tret = %s, treti = %s\n", tret->toChars(), treti ? treti->toChars() : "NULL");

size_t dim = Parameter::dim(tf->parameters);
for (size_t i = 0; i < dim; i++)
{ Parameter *fparam = Parameter::getNth(tf->parameters, i);
if (fparam->storageClass & STClazy)
{
purity = PUREweak;
tf->purity = PUREweak;
break;
}
if (fparam->storageClass & STCout)
{
purity = PUREweak;
tf->purity = PUREweak;
break;
}
if (!fparam->type)
continue;

Type *tprm = fparam->type;
Type *tprmi = fparam->storageClass & STCref ? tprm->toBasetype() : getIndirection(tprm);
//printf(" [%d] tprm = %s, tprmi = %s\n", i, tprm->toChars(), tprmi ? tprmi->toChars() : "NULL");

if (!tprmi || (tprmi->mod & MODimmutable))
continue; // there is no mutable indirection
if (tprmi->isMutable())
{ purity = PUREweak; // indirection is mutable
break;
if (fparam->storageClass & STCref)
{
if (!(fparam->type->mod & (MODconst | MODimmutable | MODwild)))
{ tf->purity = PUREweak;
break;
}
if (fparam->type->mod & MODconst)
{ tf->purity = PUREconst;
continue;
}
}
if (!treti)
continue; // mutable indirection is never returned

if (purity < PUREstrong)
Type *t = fparam->type->toBasetype();
if (!t->hasPointers())
continue;

// Determine the parameter is really PUREconst or not
assert(tprmi->mod & (MODconst | MODwild));
if (tprmi->constConv(treti)) // simple case
purity = PUREconst;
else if (tprmi->invariantOf()->equals(treti->invariantOf()))
if (t->mod & (MODimmutable | MODwild))
continue;
/* The rest of this is too strict; fix later.
* For example, the only pointer members of a struct may be immutable,
* which would maintain strong purity.
*/
if (t->mod & MODconst)
{ tf->purity = PUREconst;
continue;
else
{
/* The rest of this is little strict; fix later.
* For example:
*
* struct S { immutable* p; }
* pure S foo(const int* p);
*
* which would maintain strong purity.
*/
if (tprmi->hasPointers() || treti->hasPointers())
purity = PUREconst;
}

Type *tn = t->nextOf();
if (tn)
{ tn = tn->toBasetype();
if (tn->ty == Tpointer || tn->ty == Tarray)
{ /* Accept immutable(T)* and immutable(T)[] as being strongly pure
*/
if (tn->mod & (MODimmutable | MODwild))
continue;
if (tn->mod & MODconst)
{ tf->purity = PUREconst;
continue;
}
}
}
/* Should catch delegates and function pointers, and fold in their purity
*/
tf->purity = PUREweak; // err on the side of too strict
break;
}
}

//printf(" --> purity: %d\n", purity);
tf->purity = purity;
}
}

/********************************************
* FIXME: This function is a workaround for fixing Bugzilla 9210.
* In 2.061, TypeFunction::purityLevel() improved to make more functions
* strong purity, but immutable conversion on return statemet had broken by that.
* Because, it is essentially unrelated to PUREstrong. This function is
* necessary to check the convertibility.
*/
bool TypeFunction::hasMutableIndirectionParams()
{
TypeFunction *tf = this;
size_t dim = Parameter::dim(tf->parameters);
for (size_t i = 0; i < dim; i++)
{
Parameter *fparam = Parameter::getNth(tf->parameters, i);
if (fparam->storageClass & STClazy)
{
return true;
}
if (fparam->storageClass & STCout)
{
return true;
}
if (!fparam->type)
continue;
if (fparam->storageClass & STCref)
{
if (!(fparam->type->mod & (MODconst | MODimmutable | MODwild)))
return true;
if (fparam->type->mod & MODconst)
return true;
}
Type *t = fparam->type->toBasetype();
if (!t->hasPointers())
continue;
if (t->mod & (MODimmutable | MODwild))
continue;
/* The rest of this is too strict; fix later.
* For example, the only pointer members of a struct may be immutable,
* which would maintain strong purity.
*/
if (t->mod & MODconst)
return true;
Type *tn = t->nextOf();
if (tn)
{ tn = tn->toBasetype();
if (tn->ty == Tpointer || tn->ty == Tarray)
{ /* Accept immutable(T)* and immutable(T)[] as being strongly pure
*/
if (tn->mod & (MODimmutable | MODwild))
continue;
if (tn->mod & MODconst)
return true;
}
}
/* Should catch delegates and function pointers, and fold in their purity
*/
return true;
}
return false;
}


Expand Down
1 change: 0 additions & 1 deletion src/mtype.h
Expand Up @@ -657,7 +657,6 @@ struct TypeFunction : TypeNext
Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc);
void purityLevel();
bool hasMutableIndirectionParams();
void toDecoBuffer(OutBuffer *buf, int flag);
void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
void toCBufferWithAttributes(OutBuffer *buf, Identifier *ident, HdrGenState* hgs, TypeFunction *attrs, TemplateDeclaration *td);
Expand Down
5 changes: 1 addition & 4 deletions src/statement.c
Expand Up @@ -3922,10 +3922,7 @@ Statement *ReturnStatement::semantic(Scope *sc)
}
else if (tbret->ty != Tvoid)
{
assert(fd->type->ty == Tfunction);
TypeFunction *tf = (TypeFunction *)fd->type;
if (fd->isPureBypassingInference() != PUREimpure &&
!tf->hasMutableIndirectionParams() &&
if (fd->isPureBypassingInference() == PUREstrong &&
!exp->type->implicitConvTo(tret) &&
exp->type->invariantOf()->implicitConvTo(tret))
{
Expand Down
29 changes: 0 additions & 29 deletions test/fail_compilation/test9230.d

This file was deleted.

77 changes: 0 additions & 77 deletions test/runnable/testconst.d
Expand Up @@ -2743,82 +2743,6 @@ void test8212()
S8212 s2 = s8212;
}

/************************************/
// 8408

template hasMutableIndirection8408(T)
{
template Unqual(T)
{
static if (is(T U == shared(const U))) alias U Unqual;
else static if (is(T U == const U )) alias U Unqual;
else static if (is(T U == immutable U )) alias U Unqual;
else static if (is(T U == inout U )) alias U Unqual;
else static if (is(T U == shared U )) alias U Unqual;
else alias T Unqual;
}

enum hasMutableIndirection8408 = !is(typeof({ Unqual!T t = void; immutable T u = t; }));
}
static assert(!hasMutableIndirection8408!(int));
static assert(!hasMutableIndirection8408!(int[3]));
static assert( hasMutableIndirection8408!(Object));

auto dup8408(E)(inout(E)[] arr) pure @trusted
{
static if (hasMutableIndirection8408!E)
{
auto copy = new E[](arr.length);
copy[] = cast(E[])arr[]; // assume constant
return cast(inout(E)[])copy; // assume constant
}
else
{
auto copy = new E[](arr.length);
copy[] = arr[];
return copy;
}
}

void test8408()
{
void test(E, bool constConv)()
{
E[] marr = [E.init, E.init, E.init];
immutable E[] iarr = [E.init, E.init, E.init];

E[] m2m = marr.dup8408(); assert(m2m == marr);
immutable E[] i2i = iarr.dup8408(); assert(i2i == iarr);

static if (constConv)
{ // If dup() hss strong purity, implicit conversion is allowed
immutable E[] m2i = marr.dup8408(); assert(m2i == marr);
E[] i2m = iarr.dup8408(); assert(i2m == iarr);
}
else
{
static assert(!is(typeof({ immutable E[] m2i = marr.dup8408(); })));
static assert(!is(typeof({ E[] i2m = iarr.dup8408(); })));
}
}

class C {}
struct S1 { long n; }
struct S2 { int* p; }
struct T1 { S1 s; }
struct T2 { S2 s; }
struct T3 { S1 s1; S2 s2; }

test!(int , true )();
test!(int[3], true )();
test!(C , false)();
test!(S1 , true )();
test!(S2 , false)();
test!(T1 , true )();
test!(T2 , false)();
test!(T3 , false)();
}

/************************************/
// 8688

Expand Down Expand Up @@ -3001,7 +2925,6 @@ int main()
test8099();
test8201();
test8212();
test8408();
test8688();
test9046();
test9090();
Expand Down

0 comments on commit b65d12a

Please sign in to comment.