Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue 9230 - Incorrect implicit immutable conversion occurs in pure function #1418

Merged
merged 2 commits into from Dec 28, 2012
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
61 changes: 61 additions & 0 deletions src/mtype.c
Expand Up @@ -5828,6 +5828,67 @@ void TypeFunction::purityLevel()
}
}

/********************************************
* 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 PUREstring. This function is
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/PUREstring/PUREstrong ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will fix.

* 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;
}


/********************************
* 'args' are being matched to function 'this'
Expand Down
1 change: 1 addition & 0 deletions src/mtype.h
Expand Up @@ -637,6 +637,7 @@ 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
4 changes: 3 additions & 1 deletion src/statement.c
Expand Up @@ -3954,7 +3954,9 @@ Statement *ReturnStatement::semantic(Scope *sc)
}
else if (tbret->ty != Tvoid)
{
if (fd->isPureBypassingInference() == PUREstrong &&
assert(fd->type->ty == Tfunction);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function still has to be pure, no? Was this check moved somewhere else?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ouch, it's my mistake. We should keep the check whether fd is really a pure function or not.

TypeFunction *tf = (TypeFunction *)fd->type;
if (!tf->hasMutableIndirectionParams() &&
!exp->type->implicitConvTo(tret) &&
exp->type->invariantOf()->implicitConvTo(tret))
{
Expand Down
10 changes: 10 additions & 0 deletions test/fail_compilation/test9230.d
@@ -0,0 +1,10 @@
/*
TEST_OUTPUT:
---
fail_compilation/test9230.d(9): Error: cannot implicitly convert expression (s) of type const(char[]) to string
---
*/

string foo(in char[] s) pure {
return s; //
}
19 changes: 15 additions & 4 deletions test/runnable/xtest46.d
Expand Up @@ -1966,18 +1966,29 @@ void test99()

void test5081()
{
static pure immutable(int[]) x()
static pure immutable(int[]) x1()
{
return new int[](10);
}
static pure immutable(int[]) x2(int len)
{
return new int[](len);
}
static pure immutable(int[]) x3(immutable(int[]) org)
{
return new int[](org.length);
}

immutable a1 = x1();
immutable a2 = x2(10);
immutable a3 = x3([1,2]);

static pure int[] y()
static pure int[] y1()
{
return new int[](10);
}

immutable a = x();
immutable b = y();
immutable b1 = y1();
}

/***************************************************/
Expand Down