diff options
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/semexprs.nim | 18 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 6 |
2 files changed, 21 insertions, 3 deletions
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 70206c6f9..beb3719e8 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -2074,12 +2074,10 @@ proc semYield(c: PContext, n: PNode): PNode = if c.p.owner == nil or c.p.owner.kind != skIterator: localError(c.config, n.info, errYieldNotAllowedHere) elif n[0].kind != nkEmpty: - n[0] = semExprWithType(c, n[0]) # check for type compatibility: var iterType = c.p.owner.typ let restype = iterType[0] + n[0] = semExprWithType(c, n[0], {}, restype) # check for type compatibility: if restype != nil: - if restype.kind != tyUntyped: - n[0] = fitNode(c, restype, n[0], n.info) if n[0].typ == nil: internalError(c.config, n.info, "semYield") if resultTypeIsInferrable(restype): @@ -2087,6 +2085,8 @@ proc semYield(c: PContext, n: PNode): PNode = iterType[0] = inferred if c.p.resultSym != nil: c.p.resultSym.typ = inferred + else: + n[0] = fitNode(c, restype, n[0], n.info) semYieldVarResult(c, n, restype) else: @@ -2767,6 +2767,12 @@ proc semTupleFieldsConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType # can check if field name matches expected type here let expectedElemType = if expected != nil: expected[i] else: nil n[i][1] = semExprWithType(c, n[i][1], {}, expectedElemType) + if expectedElemType != nil and + (expectedElemType.kind != tyNil and not hasEmpty(expectedElemType)): + # hasEmpty/nil check is to not break existing code like + # `const foo = [(1, {}), (2, {false})]`, + # `const foo = if true: (0, nil) else: (1, new(int))` + n[i][1] = fitNode(c, expectedElemType, n[i][1], n[i][1].info) if n[i][1].typ.kind == tyTypeDesc: localError(c.config, n[i][1].info, "typedesc not allowed as tuple field.") @@ -2793,6 +2799,12 @@ proc semTuplePositionsConstr(c: PContext, n: PNode, flags: TExprFlags; expectedT for i in 0..<n.len: let expectedElemType = if expected != nil: expected[i] else: nil n[i] = semExprWithType(c, n[i], {}, expectedElemType) + if expectedElemType != nil and + (expectedElemType.kind != tyNil and not hasEmpty(expectedElemType)): + # hasEmpty/nil check is to not break existing code like + # `const foo = [(1, {}), (2, {false})]`, + # `const foo = if true: (0, nil) else: (1, new(int))` + n[i] = fitNode(c, expectedElemType, n[i], n[i].info) addSonSkipIntLit(typ, n[i].typ, c.idgen) result.typ = typ diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 9e99353d1..b4d875981 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -587,8 +587,14 @@ proc recordRel(c: var TCandidate, f, a: PType, flags: TTypeRelFlags): TTypeRelat let firstField = if f.kind == tyTuple: 0 else: 1 for _, ff, aa in tupleTypePairs(f, a): + let oldInheritancePenalty = c.inheritancePenalty var m = typeRel(c, ff, aa, flags) if m < isSubtype: return isNone + if m == isSubtype and c.inheritancePenalty > oldInheritancePenalty: + # we can't process individual element type conversions from a + # type conversion for the whole tuple + # subtype relations need type conversions when inheritance is used + return isNone result = minRel(result, m) if f.n != nil and a.n != nil: for i in 0..<f.n.len: |