diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index bac00bbee1300..6d884830799bd 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -725,7 +725,7 @@ proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType: PTyp # nkBracket nodes can also be produced by the VM as seq constant nodes # in which case, we cannot produce a new array type for the node, # as this might lose type info even when the node has array type - let constructType = n.typ.isNil + let constructType = n.typ.isNil or n.typ.kind == tyFromExpr var expectedElementType, expectedIndexType: PType = nil var expectedBase: PType = nil if constructType: @@ -797,17 +797,26 @@ proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType: PTyp localError(c.config, x.info, "invalid order in array constructor") x = x[1] - let xx = semExprWithType(c, x, {efTypeAllowed}, expectedElementType) - result.add xx - if constructType: - typ = commonType(c, typ, xx.typ) + if typ.kind == tyFromExpr and c.inGenericContext > 0: + result.add semGenericStmt(c, x) + else: + let xx = semExprWithType(c, x, {efTypeAllowed}, expectedElementType) + result.add xx + if constructType: + typ = commonType(c, typ, xx.typ) #n[i] = semExprWithType(c, x, {}) #result.add fitNode(c, typ, n[i]) inc(lastIndex) - if constructType: - addSonSkipIntLit(result.typ, typ, c.idgen) - for i in 0.. 0: + if constructType: + result.typ() = nil # current result.typ is invalid, index type is nil + result.typ() = makeTypeFromExpr(c, result.copyTree) + return + else: + if constructType: + addSonSkipIntLit(result.typ, typ, c.idgen) + for i in 0.. 0: + n[i] = semGenericStmt(c, n[i]) + elif isRange(n[i]): checkSonsLen(n[i], 3, c.config) n[i][1] = semExprWithType(c, n[i][1], {efTypeAllowed}, expectedElementType) n[i][2] = semExprWithType(c, n[i][2], {efTypeAllowed}, expectedElementType) @@ -2811,7 +2822,10 @@ proc semSetConstr(c: PContext, n: PNode, expectedType: PType = nil): PNode = if doSetType: typ = skipTypes(n[i].typ, {tyGenericInst, tyVar, tyLent, tyOrdinal, tyAlias, tySink}) if doSetType: - if not isOrdinalType(typ, allowEnumWithHoles=true): + if typ.kind == tyFromExpr and c.inGenericContext > 0: + # propagate it as set element type + discard + elif not isOrdinalType(typ, allowEnumWithHoles=true): localError(c.config, n.info, errOrdinalTypeExpected % typeToString(typ, preferDesc)) typ = makeRangeType(c, 0, MaxSetElements-1, n.info) elif isIntLit(typ): @@ -2825,11 +2839,16 @@ proc semSetConstr(c: PContext, n: PNode, expectedType: PType = nil): PNode = typ = makeRangeType(c, 0, MaxSetElements-1, n.info) if expectedElementType == nil: expectedElementType = typ - addSonSkipIntLit(result.typ, typ, c.idgen) + if typ.kind == tyFromExpr and c.inGenericContext > 0: + result.typ() = makeTypeFromExpr(c, result.copyTree) + else: + addSonSkipIntLit(result.typ, typ, c.idgen) for i in 0.. 0: + m = n[i] + elif isRange(n[i]): m = newNodeI(nkRange, info) m.add fitNode(c, typ, n[i][1], info) m.add fitNode(c, typ, n[i][2], info) diff --git a/tests/proc/tgenericdefaultparam.nim b/tests/proc/tgenericdefaultparam.nim index 7bce591ce5ee2..d20af411ed1eb 100644 --- a/tests/proc/tgenericdefaultparam.nim +++ b/tests/proc/tgenericdefaultparam.nim @@ -96,3 +96,25 @@ block: # issue #24121 proc baz[T: FooBar](x: T, y = foo(x)): string = y doAssert baz(Foo(123)) == "b" doAssert baz(Bar(123)) == "c" + +block: # issue #24484 + type E = enum A + proc foo[T](t: set[T] = {T.A}) = + discard + foo[E]() + + proc bar[T](t: set[T] = {T(0), 5}) = + doAssert t == {0, 5} + bar[uint8]() + doAssert not compiles(bar[string]()) + +block: # issue #24484, array version + type E = enum A + proc foo[T](t: openArray[T] = [T.A]) = + discard + foo[E]() + + proc bar[T](t: openArray[T] = [T(0), 5]) = + doAssert t == [T(0), 5] + bar[uint8]() +