diff --git a/src/cast.c b/src/cast.c index 4432143c327a..082e8c8e52ec 100644 --- a/src/cast.c +++ b/src/cast.c @@ -576,6 +576,26 @@ MATCH AssocArrayLiteralExp::implicitConvTo(Type *t) return Expression::implicitConvTo(t); } +MATCH CallExp::implicitConvTo(Type *t) +{ +#if 0 + printf("CalLExp::implicitConvTo(this=%s, type=%s, t=%s)\n", + toChars(), type->toChars(), t->toChars()); +#endif + + MATCH m = Expression::implicitConvTo(t); + if (m) + return m; + + /* Allow the result of strongly pure functions to + * convert to immutable + */ + if (f && f->isPure() == PUREstrong) + return type->invariantOf()->implicitConvTo(t); + + return MATCHnomatch; +} + MATCH AddrExp::implicitConvTo(Type *t) { #if 0 diff --git a/src/expression.c b/src/expression.c index 03e8bc831822..f9fee23c5a38 100644 --- a/src/expression.c +++ b/src/expression.c @@ -6859,7 +6859,6 @@ Expression *CallExp::syntaxCopy() Expression *CallExp::semantic(Scope *sc) { TypeFunction *tf; - FuncDeclaration *f; Type *t1; int istemp; Objects *targsi = NULL; // initial list of template arguments diff --git a/src/expression.h b/src/expression.h index 5273a0e8773e..5efb654f6e3d 100644 --- a/src/expression.h +++ b/src/expression.h @@ -935,6 +935,7 @@ struct DotTypeExp : UnaExp struct CallExp : UnaExp { Expressions *arguments; // function arguments + FuncDeclaration *f; // symbol to call CallExp(Loc loc, Expression *e, Expressions *exps); CallExp(Loc loc, Expression *e); @@ -954,6 +955,7 @@ struct CallExp : UnaExp Expression *toLvalue(Scope *sc, Expression *e); int canThrow(bool mustNotThrow); Expression *addDtorHook(Scope *sc); + MATCH implicitConvTo(Type *t); int inlineCost(InlineCostState *ics); Expression *doInline(InlineDoState *ids); diff --git a/src/statement.c b/src/statement.c index d3f63e35d13b..d2c6599e1324 100644 --- a/src/statement.c +++ b/src/statement.c @@ -3521,6 +3521,13 @@ Statement *ReturnStatement::semantic(Scope *sc) } else if (tbret->ty != Tvoid) { + if (fd->isPureBypassingInference() == PUREstrong && + !exp->type->implicitConvTo(tret) && + exp->type->invariantOf()->implicitConvTo(tret)) + { + exp = exp->castTo(sc, exp->type->invariantOf()); + } + exp = exp->implicitCastTo(sc, tret); if (!((TypeFunction *)fd->type)->isref) exp = exp->optimize(WANTvalue); diff --git a/test/runnable/xtest46.d b/test/runnable/xtest46.d index f7119f8c82ba..db6d9e5f0b6b 100644 --- a/test/runnable/xtest46.d +++ b/test/runnable/xtest46.d @@ -1875,6 +1875,24 @@ void test99() /***************************************************/ +void test5081() +{ + static pure immutable(int[]) x() + { + return new int[](10); + } + + static pure int[] y() + { + return new int[](10); + } + + immutable a = x(); + immutable b = y(); +} + +/***************************************************/ + void test100() { string s; @@ -3617,6 +3635,7 @@ int main() test116(); test117(); test118(); + test5081(); test120();