diff --git a/src/cast.c b/src/cast.c index 5db33c49d4dc..ec1ddce77b61 100644 --- a/src/cast.c +++ b/src/cast.c @@ -131,6 +131,12 @@ Expression *ErrorExp::implicitCastTo(Scope *sc, Type *t) return this; } +Expression *FuncExp::implicitCastTo(Scope *sc, Type *t) +{ + //printf("FuncExp::implicitCastTo type = %p %s, t = %s\n", type, type ? type->toChars() : NULL, t->toChars()); + return inferType(t); +} + /******************************************* * Return !=0 if we can implicitly convert this to type t. * Don't do the actual cast. @@ -719,12 +725,24 @@ MATCH DelegateExp::implicitConvTo(Type *t) MATCH FuncExp::implicitConvTo(Type *t) { - //printf("FuncExp::implicitCastTo type = %p %s, t = %s\n", type, type ? type->toChars() : NULL, t->toChars()); - if (type && type != Type::tvoid && tok == TOKreserved && type->ty == Tpointer - && (t->ty == Tpointer || t->ty == Tdelegate)) - { // Allow implicit function to delegate conversion - if (type->nextOf()->covariant(t->nextOf()) == 1) - return t->ty == Tpointer ? MATCHconst : MATCHconvert; + //printf("FuncExp::implicitConvTo type = %p %s, t = %s\n", type, type ? type->toChars() : NULL, t->toChars()); + Expression *e = inferType(t, 1); + if (e) + { + if (e != this) + return e->implicitConvTo(t); + + /* MATCHconst: Conversion from implicit to explicit function pointer + * MATCHconvert: Conversion from impliict funciton pointer to delegate + */ + if (tok == TOKreserved && type->ty == Tpointer && + (t->ty == Tpointer || t->ty == Tdelegate)) + { + if (type == t) + return MATCHexact; + if (type->nextOf()->covariant(t->nextOf()) == 1) + return t->ty == Tpointer ? MATCHconst : MATCHconvert; + } } return Expression::implicitConvTo(t); } @@ -1491,15 +1509,11 @@ Expression *DelegateExp::castTo(Scope *sc, Type *t) Expression *FuncExp::castTo(Scope *sc, Type *t) { //printf("FuncExp::castTo type = %s, t = %s\n", type->toChars(), t->toChars()); - if (tok == TOKreserved) - { assert(type && type != Type::tvoid); - if (type->ty == Tpointer && t->ty == Tdelegate) - { - Expression *e = copy(); - e->type = new TypeDelegate(fd->type); - e->type = e->type->semantic(loc, sc); - return e; - } + Expression *e = inferType(t, 1); + if (e) + { if (e != this) + e = e->castTo(sc, t); + return e; } return Expression::castTo(sc, t); } diff --git a/src/expression.c b/src/expression.c index d29a6b06adc3..335a08cdfd84 100644 --- a/src/expression.c +++ b/src/expression.c @@ -756,13 +756,12 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf, nargs++; } else if (arg->op == TOKfunction) - { FuncExp *fe = (FuncExp *)arg; + { Type *pt = p->type; if (tf->varargs == 2 && i + 1 == nparams && pt->nextOf()) pt = pt->nextOf(); - fe->setType(pt); - arg = fe->semantic(sc); - arguments->tdata()[i] = arg; + arg = ((FuncExp *)arg)->inferType(pt); + arguments->tdata()[i] = arg; } if (tf->varargs == 2 && i + 1 == nparams) @@ -3783,14 +3782,6 @@ Expression *StructLiteralExp::semantic(Scope *sc) telem = telem->toBasetype()->nextOf(); } - if (e->op == TOKfunction) - { e = ((FuncExp *)e)->inferType(sc, telem); - if (!e) - { error("cannot infer function literal type from %s", telem->toChars()); - e = new ErrorExp(); - } - } - e = e->implicitCastTo(sc, telem); elements->tdata()[i] = e; @@ -4951,7 +4942,6 @@ FuncExp::FuncExp(Loc loc, FuncLiteralDeclaration *fd, TemplateDeclaration *td) this->td = td; tok = fd->tok; // save original kind of function/delegate/(infer) tded = NULL; - scope = NULL; } Expression *FuncExp::syntaxCopy() @@ -4967,9 +4957,6 @@ Expression *FuncExp::semantic(Scope *sc) #endif if (!type || type == Type::tvoid) { - // save for later use - scope = sc; - // Set target of return type inference if (tded && !fd->type->nextOf()) { TypeFunction *tfv = NULL; @@ -4993,19 +4980,7 @@ Expression *FuncExp::semantic(Scope *sc) type = Type::tvoid; // temporary type return this; } - else - { - Expression *e = inferType(sc, tded); - if (e) - { e = e->castTo(sc, tded); - e = e->semantic(sc); - } - if (!e) - { error("cannot infer function literal type"); - e = new ErrorExp(); - } - return e; - } + return inferType(tded); } unsigned olderrors = global.errors; @@ -5051,9 +5026,6 @@ Expression *FuncExp::semantic(Scope *sc) // used from CallExp::semantic() Expression *FuncExp::semantic(Scope *sc, Expressions *arguments) { - assert(!tded); - assert(!scope); - if ((!type || type == Type::tvoid) && td && arguments && arguments->dim) { for (size_t k = 0; k < arguments->dim; k++) @@ -5097,24 +5069,27 @@ Expression *FuncExp::semantic(Scope *sc, Expressions *arguments) return semantic(sc); } -Expression *FuncExp::inferType(Scope *sc, Type *to) +Expression *FuncExp::inferType(Type *to, int flag) { - //printf("inferType sc = %p, to = %s\n", sc, to->toChars()); - if (!sc) - { // used from TypeFunction::callMatch() - assert(scope); - sc = scope; + Expression *e = NULL; + + Type *t = to; + if (t->ty == Tdelegate) + { if (tok == TOKfunction) + goto L1; + t = t->nextOf(); + } + else if (t->ty == Tpointer && t->nextOf()->ty == Tfunction) + { if (tok == TOKdelegate) + goto L1; + t = t->nextOf(); } + else + goto L1; - Expression *e = NULL; if (td) { /// Parameter types inference from - assert(!type || type == Type::tvoid); - Type *t = to; - if (t->ty == Tdelegate || - t->ty == Tpointer && t->nextOf()->ty == Tfunction) - { t = t->nextOf(); - } + assert(td->scope); if (t->ty == Tfunction) { TypeFunction *tfv = (TypeFunction *)t; @@ -5137,7 +5112,7 @@ Expression *FuncExp::inferType(Scope *sc, Type *to) { p = Parameter::getNth(tfv->parameters, u); if (p->type->ty == Tident) return NULL; - Type *tprm = p->type->semantic(loc, sc); + Type *tprm = p->type->semantic(loc, td->scope); tiargs->push(tprm); u = dim; // break inner loop } @@ -5145,22 +5120,36 @@ Expression *FuncExp::inferType(Scope *sc, Type *to) } TemplateInstance *ti = new TemplateInstance(loc, td, tiargs); - e = (new ScopeExp(loc, ti))->semantic(sc); + e = (new ScopeExp(loc, ti))->semantic(td->scope); } } } - else + else if (type) { - assert(type && type != Type::tvoid); // semantic is already done - e = this; - } + assert(type != Type::tvoid); // semantic is already done - if (e) - { // Check implicit function to delegate conversion - if (e->implicitConvTo(to)) - e = e->castTo(sc, to); + // Allow conversion from implicit function pointer to delegate + if (tok == TOKreserved && type->ty == Tpointer && + to->ty == Tdelegate) + { + Type *typen = type->nextOf(); + assert(typen->deco); + if (typen->covariant(to->nextOf()) == 1) + { + FuncExp *fe = (FuncExp *)copy(); + fe->tok = TOKdelegate; + fe->type = (new TypeDelegate(typen))->merge(); + e = fe; + //e = fe->Expression::implicitCastTo(sc, to); + } + } else - e = NULL; + e = this; + } +L1: + if (!flag && !e) + { error("cannot infer function literal type from %s", to->toChars()); + e = new ErrorExp(); } return e; } @@ -7234,12 +7223,13 @@ Expression *CallExp::resolveUFCS(Scope *sc) Expression *key = arguments->tdata()[0]; key = key->semantic(sc); key = resolveProperties(sc, key); - if (!key->rvalue()) - return new ErrorExp(); TypeAArray *taa = (TypeAArray *)tthis; key = key->implicitCastTo(sc, taa->index); + if (!key->rvalue()) + return new ErrorExp(); + return new RemoveExp(loc, ethis, key); } else if (ident == Id::apply || ident == Id::applyReverse) @@ -8655,26 +8645,6 @@ Expression *CastExp::semantic(Scope *sc) Type *t1b = e1->type->toBasetype(); Type *tob = to->toBasetype(); - if (e1->op == TOKfunction && - (tob->ty == Tdelegate || tob->ty == Tpointer && tob->nextOf()->ty == Tfunction)) - { - FuncExp *fe = (FuncExp *)e1; - Expression *e = NULL; - if (e1->type == Type::tvoid) - { - e = fe->inferType(sc, tob); - } - else if (e1->type->ty == Tpointer && e1->type->nextOf()->ty == Tfunction && - fe->tok == TOKreserved && - tob->ty == Tdelegate) - { - if (fe->implicitConvTo(tob)) - e = fe->castTo(sc, tob); - } - if (e) - e1 = e->semantic(sc); - } - if (tob->ty == Tstruct && !tob->equals(t1b) ) @@ -10080,27 +10050,6 @@ Expression *AssignExp::semantic(Scope *sc) Type *t1 = e1->type->toBasetype(); - if (t1->ty == Tdelegate || (t1->ty == Tpointer && t1->nextOf()->ty == Tfunction) - && e2->op == TOKfunction) - { - FuncExp *fe = (FuncExp *)e2; - if (e2->type == Type::tvoid) - { - e2 = fe->inferType(sc, t1); - } - else if (e2->type->ty == Tpointer && e2->type->nextOf()->ty == Tfunction && - fe->tok == TOKreserved && - t1->ty == Tdelegate) - { - if (fe->implicitConvTo(t1)) - e2 = fe->castTo(sc, t1); - } - if (!e2) - { error("cannot infer function literal type from %s", t1->toChars()); - e2 = new ErrorExp(); - } - } - /* If it is an assignment from a 'foreign' type, * check for operator overloading. */ @@ -10242,6 +10191,8 @@ Expression *AssignExp::semantic(Scope *sc) } } + if (e2->op == TOKfunction) + e2 = ((FuncExp *)e2)->inferType(t1); if (!e2->rvalue()) return new ErrorExp(); @@ -10379,10 +10330,9 @@ CatAssignExp::CatAssignExp(Loc loc, Expression *e1, Expression *e2) } Expression *CatAssignExp::semantic(Scope *sc) -{ Expression *e; - +{ //printf("CatAssignExp::semantic() %s\n", toChars()); - e = op_overload(sc); + Expression *e = op_overload(sc); if (e) return e; @@ -10398,12 +10348,14 @@ Expression *CatAssignExp::semantic(Scope *sc) e1 = e1->modifiableLvalue(sc, e1); Type *tb1 = e1->type->toBasetype(); - Type *tb2 = e2->type->toBasetype(); + Type *tb1next = tb1->nextOf(); + if (e2->op == TOKfunction) + e2 = ((FuncExp *)e2)->inferType(tb1next); if (!e2->rvalue()) return new ErrorExp(); - Type *tb1next = tb1->nextOf(); + Type *tb2 = e2->type->toBasetype(); if ((tb1->ty == Tarray) && (tb2->ty == Tarray || tb2->ty == Tsarray) && diff --git a/src/expression.h b/src/expression.h index a65afb497d16..3e3cbdd74c28 100644 --- a/src/expression.h +++ b/src/expression.h @@ -656,16 +656,16 @@ struct FuncExp : Expression TemplateDeclaration *td; enum TOK tok; Type *tded; - Scope *scope; FuncExp(Loc loc, FuncLiteralDeclaration *fd, TemplateDeclaration *td = NULL); Expression *syntaxCopy(); Expression *semantic(Scope *sc); Expression *semantic(Scope *sc, Expressions *arguments); Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *implicitCastTo(Scope *sc, Type *t); MATCH implicitConvTo(Type *t); Expression *castTo(Scope *sc, Type *t); - Expression *inferType(Scope *sc, Type *t); + Expression *inferType(Type *t, int flag = 0); void setType(Type *t); char *toChars(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); diff --git a/src/init.c b/src/init.c index 1f64f2ec3f1d..256dcf5ac110 100644 --- a/src/init.c +++ b/src/init.c @@ -854,12 +854,6 @@ Initializer *ExpInitializer::semantic(Scope *sc, Type *t, int needInterpret) Type *ExpInitializer::inferType(Scope *sc) { //printf("ExpInitializer::inferType() %s\n", toChars()); - if (exp->op == TOKfunction && ((FuncExp *)exp)->td) - { - exp->error("cannot infer type from ambiguous function literal %s", exp->toChars()); - return Type::terror; - } - exp = exp->semantic(sc); exp = resolveProperties(sc, exp); diff --git a/src/mtype.c b/src/mtype.c index ddd5b010632a..72be78f93f33 100644 --- a/src/mtype.c +++ b/src/mtype.c @@ -5730,9 +5730,8 @@ int TypeFunction::callMatch(Expression *ethis, Expressions *args, int flag) assert(arg); if (arg->op == TOKfunction) - { FuncExp *fe = (FuncExp *)arg; - Type *pt = p->type; - arg = ((FuncExp *)arg)->inferType(NULL, pt); + { + arg = ((FuncExp *)arg)->inferType(p->type, 1); if (!arg) goto L1; // try typesafe variadics } @@ -5819,9 +5818,8 @@ int TypeFunction::callMatch(Expression *ethis, Expressions *args, int flag) assert(arg); #if 1 if (arg->op == TOKfunction) - { FuncExp *fe = (FuncExp *)arg; - Type *pt = tb->nextOf(); - arg = ((FuncExp *)arg)->inferType(NULL, pt); + { + arg = ((FuncExp *)arg)->inferType(tb->nextOf(), 1); if (!arg) goto Nomatch; } diff --git a/src/template.c b/src/template.c index f49f69bbecb9..249b65b44134 100644 --- a/src/template.c +++ b/src/template.c @@ -1415,19 +1415,22 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec if (farg->op == TOKfunction) { FuncExp *fe = (FuncExp *)farg; Type *tp = fparam->type; - if (tp->ty == Tdelegate && - fe->type->ty == Tpointer && fe->type->nextOf()->ty == Tfunction && - fe->tok == TOKreserved) - { Type *tdg = new TypeDelegate(fe->type->nextOf()); - tdg = tdg->semantic(loc, sc); - farg = fe->inferType(sc, tdg); - } - else if (fe->type == Type::tvoid) + Expression *e = fe->inferType(tp, 1); + if (!e) { - farg = fe->inferType(sc, tp); - if (!farg) - goto Lvarargs; + if (tp->ty == Tdelegate && + fe->tok == TOKreserved && + fe->type->ty == Tpointer && fe->type->nextOf()->ty == Tfunction) + { + fe = (FuncExp *)fe->copy(); + fe->tok = TOKdelegate; + fe->type = (new TypeDelegate(fe->type->nextOf()))->merge(); + e = fe; + } + else + e = farg; } + farg = e; argtype = farg->type; } @@ -1541,19 +1544,23 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec if (arg->op == TOKfunction) { FuncExp *fe = (FuncExp *)arg; Type *tp = tb->nextOf(); - if (tp->ty == Tdelegate && - fe->type->ty == Tpointer && fe->type->nextOf()->ty == Tfunction && - fe->tok == TOKreserved) - { tp = new TypeDelegate(fe->type->nextOf()); - tp = tp->semantic(loc, sc); - arg = fe->inferType(sc, tp); - } - else if (arg->type == Type::tvoid) + + Expression *e = fe->inferType(tp, 1); + if (!e) { - arg = fe->inferType(sc, tp); - if (!arg) - goto Lnomatch; + if (tp->ty == Tdelegate && + fe->tok == TOKreserved && + fe->type->ty == Tpointer && fe->type->nextOf()->ty == Tfunction) + { + fe = (FuncExp *)fe->copy(); + fe->tok = TOKdelegate; + fe->type = (new TypeDelegate(fe->type->nextOf()))->merge(); + e = fe; + } + else + e = arg; } + arg = e; } MATCH m; diff --git a/test/runnable/funclit.d b/test/runnable/funclit.d index bf995ab37f31..76aa7480839b 100644 --- a/test/runnable/funclit.d +++ b/test/runnable/funclit.d @@ -280,6 +280,27 @@ void test8() static assert(!__traits(compiles, { auto s2 = S((a, b) => a); })); } +/***************************************************/ +// on concat operation + +void test9() +{ + int function(int)[] a2; + a2 ~= x => x; +} + +/***************************************************/ +// on associative array key + +void test10() +{ + int[int function()] aa; + assert(!aa.remove(() => 1)); + + int[int function(int)] aa2; + assert(!aa2.remove(x => 1)); +} + /***************************************************/ // 3235 @@ -387,6 +408,8 @@ int main() test6(); test7(); test8(); + test9(); + test10(); test3235(); test6714(); test7193();