diff options
Diffstat (limited to 'compiler/sigmatch.nim')
-rw-r--r-- | compiler/sigmatch.nim | 94 |
1 files changed, 63 insertions, 31 deletions
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 407e34619..d66e8d121 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -13,9 +13,9 @@ import intsets, ast, astalgo, semdata, types, msgs, renderer, lookups, semtypinst, magicsys, condsyms, idents, lexer, options, parampatterns, strutils, trees, - linter, lineinfos + linter, lineinfos, lowerings, modulegraphs -when defined(booting) or defined(nimsuggest): +when (defined(booting) or defined(nimsuggest)) and not defined(leanCompiler): import docgen type @@ -186,7 +186,7 @@ proc sumGeneric(t: PType): int = var isvar = 1 while true: case t.kind - of tyGenericInst, tyArray, tyRef, tyPtr, tyDistinct, + of tyGenericInst, tyArray, tyRef, tyPtr, tyDistinct, tyUncheckedArray, tyOpenArray, tyVarargs, tySet, tyRange, tySequence, tyGenericBody, tyLent: t = t.lastSon @@ -432,7 +432,7 @@ proc handleFloatRange(f, a: PType): TTypeRelation = else: result = isNone proc genericParamPut(c: var TCandidate; last, fGenericOrigin: PType) = - if fGenericOrigin != nil and last.kind == tyGenericInst and + if fGenericOrigin != nil and last.kind == tyGenericInst and last.len-1 == fGenericOrigin.len: for i in countup(1, sonsLen(fGenericOrigin) - 1): let x = PType(idTableGet(c.bindings, fGenericOrigin.sons[i])) @@ -728,7 +728,7 @@ proc matchUserTypeClass*(m: var TCandidate; ff, a: PType): PType = else: makeTypeDesc(c, typ) - typeParams.safeAdd((param, typ)) + typeParams.add((param, typ)) addDecl(c, param) @@ -757,7 +757,7 @@ proc matchUserTypeClass*(m: var TCandidate; ff, a: PType): PType = if collectDiagnostics: m.c.config.writelnHook = oldWriteHook for msg in diagnostics: - m.diagnostics.safeAdd msg + m.diagnostics.add msg m.diagnosticsEnabled = true if checkedBody == nil: return nil @@ -1027,15 +1027,15 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType, result = typeRel(c, aOrig.base, candidate) if result != isNone: - c.inferredTypes.safeAdd aOrig + c.inferredTypes.add aOrig aOrig.sons.add candidate result = isEqual return template doBind: bool = trDontBind notin flags - # var and static arguments match regular modifier-free types - var a = maybeSkipDistinct(c, aOrig.skipTypes({tyStatic, tyVar, tyLent}), c.calleeSym) + # var, sink and static arguments match regular modifier-free types + var a = maybeSkipDistinct(c, aOrig.skipTypes({tyStatic, tyVar, tyLent, tySink}), c.calleeSym) # XXX: Theoretically, maybeSkipDistinct could be called before we even # start the param matching process. This could be done in `prepareOperand` # for example, but unfortunately `prepareOperand` is not called in certain @@ -1045,7 +1045,7 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType, return typeRel(c, f, lastSon(aOrig)) if a.kind == tyGenericInst and - skipTypes(f, {tyVar, tyLent}).kind notin { + skipTypes(f, {tyVar, tyLent, tySink}).kind notin { tyGenericBody, tyGenericInvocation, tyGenericInst, tyGenericParam} + tyTypeClasses: return typeRel(c, f, lastSon(a)) @@ -1199,15 +1199,18 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType, if lengthOrd(c.c.config, fRange) != lengthOrd(c.c.config, aRange): result = isNone else: discard + of tyUncheckedArray: + if a.kind == tyUncheckedArray: + result = typeRel(c, base(f), base(a)) + if result < isGeneric: result = isNone + else: discard of tyOpenArray, tyVarargs: # varargs[expr] is special too but handled earlier. So we only need to # handle varargs[stmt] which is the same as varargs[typed]: if f.kind == tyVarargs: if tfVarargs in a.flags: return typeRel(c, f.base, a.lastSon) - if tfOldSchoolExprStmt in f.sons[0].flags: - if f.sons[0].kind == tyExpr: return - elif f.sons[0].kind == tyStmt: return + if f.sons[0].kind == tyStmt: return template matchArrayOrSeq(aBase: PType) = let ff = f.base @@ -1292,7 +1295,7 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType, of tyDistinct: if a.kind == tyDistinct: if sameDistinctTypes(f, a): result = isEqual - elif f.base.kind == tyAnything: result = isGeneric + #elif f.base.kind == tyAnything: result = isGeneric # issue 4435 elif c.coerceDistincts: result = typeRel(c, f.base, a) elif a.kind == tyNil and f.base.kind in NilableTypes: result = f.allowsNil @@ -1362,6 +1365,8 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType, if a.len == 1: let pointsTo = a.sons[0].skipTypes(abstractInst) if pointsTo.kind == tyChar: result = isConvertible + elif pointsTo.kind == tyUncheckedArray and pointsTo.sons[0].kind == tyChar: + result = isConvertible elif pointsTo.kind == tyArray and firstOrd(nil, pointsTo.sons[0]) == 0 and skipTypes(pointsTo.sons[0], {tyRange}).kind in {tyInt..tyInt64} and pointsTo.sons[1].kind == tyChar: @@ -1376,6 +1381,7 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType, of tyGenericInst: var prev = PType(idTableGet(c.bindings, f)) + let origF = f var f = if prev == nil: f else: prev let roota = a.skipGenericAlias @@ -1433,7 +1439,8 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType, result = isNone else: - result = typeRel(c, lastSon(f), a) + assert lastSon(origF) != nil + result = typeRel(c, lastSon(origF), a) if result != isNone and a.kind != tyNil: put(c, f, a) @@ -1718,7 +1725,7 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType, else: result = typeRel(c, f.base, a) if result != isNone: - c.inferredTypes.safeAdd f + c.inferredTypes.add f f.sons.add a of tyTypeDesc: @@ -1749,7 +1756,7 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType, result = isNone of tyStmt: - if aOrig != nil and tfOldSchoolExprStmt notin f.flags: + if aOrig != nil: put(c, f, aOrig) result = isGeneric @@ -1817,29 +1824,45 @@ proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType, let srca = typeRel(m, src, a) if srca notin {isEqual, isGeneric, isSubtype}: continue + # What's done below matches the logic in ``matchesAux`` let constraint = c.converters[i].typ.n[1].sym.constraint if not constraint.isNil and not matchNodeKinds(constraint, arg): continue + if src.kind in {tyVar, tyLent} and not arg.isLValue: + continue let destIsGeneric = containsGenericType(dest) if destIsGeneric: dest = generateTypeInstance(c, m.bindings, arg, dest) let fdest = typeRel(m, f, dest) - if fdest in {isEqual, isGeneric}: + if fdest in {isEqual, isGeneric} and not (dest.kind == tyLent and f.kind == tyVar): markUsed(c.config, arg.info, c.converters[i], c.graph.usageSym) var s = newSymNode(c.converters[i]) s.typ = c.converters[i].typ s.info = arg.info result = newNodeIT(nkHiddenCallConv, arg.info, dest) addSon(result, s) + # We build the call expression by ourselves in order to avoid passing this + # expression trough the semantic check phase once again so let's make sure + # it is correct var param: PNode = nil if srca == isSubtype: param = implicitConv(nkHiddenSubConv, src, copyTree(arg), m, c) + elif src.kind == tyVar: + # Analyse the converter return type + param = newNodeIT(nkHiddenAddr, arg.info, s.typ[1]) + param.addSon(copyTree(arg)) else: param = copyTree(arg) addSon(result, param) + + if dest.kind in {tyVar, tyLent}: + dest.flags.incl tfVarIsPtr + result = newDeref(result) + inc(m.convMatches) - m.genericConverter = srca == isGeneric or destIsGeneric + if m.genericConverter == false: + m.genericConverter = srca == isGeneric or destIsGeneric return result proc localConvMatch(c: PContext, m: var TCandidate, f, a: PType, @@ -1909,10 +1932,13 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType, else: var evaluated = c.semTryConstExpr(c, arg) if evaluated != nil: - arg.typ = newTypeS(tyStatic, c) - arg.typ.sons = @[evaluated.typ] - arg.typ.n = evaluated - a = arg.typ + # Don't build the type in-place because `evaluated` and `arg` may point + # to the same object and we'd end up creating recursive types (#9255) + let typ = newTypeS(tyStatic, c) + typ.sons = @[evaluated.typ] + typ.n = evaluated + arg.typ = typ + a = typ else: if m.callee.kind == tyGenericBody: if f.kind == tyStatic and typeRel(m, f.base, a) != isNone: @@ -2129,7 +2155,7 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType, else: # only one valid interpretation found: markUsed(m.c.config, arg.info, arg.sons[best].sym, m.c.graph.usageSym) - styleCheckUse(arg.info, arg.sons[best].sym) + onUse(arg.info, arg.sons[best].sym) result = paramTypesMatchAux(m, f, arg.sons[best].typ, arg.sons[best], argOrig) when false: @@ -2193,8 +2219,7 @@ proc incrIndexType(t: PType) = inc t.sons[0].n.sons[1].intVal template isVarargsUntyped(x): untyped = - x.kind == tyVarargs and x.sons[0].kind == tyExpr and - tfOldSchoolExprStmt notin x.sons[0].flags + x.kind == tyVarargs and x.sons[0].kind == tyExpr proc matchesAux(c: PContext, n, nOrig: PNode, m: var TCandidate, marker: var IntSet) = @@ -2206,8 +2231,15 @@ proc matchesAux(c: PContext, n, nOrig: PNode, else: m.state = csNoMatch return + if formal.typ.kind == tyVar: - if not n.isLValue: + let arg_converter = if arg.kind == nkHiddenDeref: arg[0] else: arg + if arg_converter.kind == nkHiddenCallConv: + if arg_converter.typ.kind != tyVar: + m.state = csNoMatch + m.mutabilityProblem = uint8(f-1) + return + elif not n.isLValue: m.state = csNoMatch m.mutabilityProblem = uint8(f-1) return @@ -2218,6 +2250,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode, else: 0 # iterates over the actual given arguments a = 1 + arg: PNode # current prepared argument m.state = csMatch # until proven otherwise m.call = newNodeI(n.kind, n.info) @@ -2272,7 +2305,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode, m.typedescMatched = false n.sons[a].sons[1] = prepareOperand(c, formal.typ, n.sons[a].sons[1]) n.sons[a].typ = n.sons[a].sons[1].typ - var arg = paramTypesMatch(m, formal.typ, n.sons[a].typ, + arg = paramTypesMatch(m, formal.typ, n.sons[a].typ, n.sons[a].sons[1], n.sons[a].sons[1]) if arg == nil: m.state = csNoMatch @@ -2309,7 +2342,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode, m.typedescMatched = false incl(marker, formal.position) n.sons[a] = prepareOperand(c, formal.typ, n.sons[a]) - var arg = paramTypesMatch(m, formal.typ, n.sons[a].typ, + arg = paramTypesMatch(m, formal.typ, n.sons[a].typ, n.sons[a], nOrig.sons[a]) if arg != nil and m.baseTypeMatch and container != nil: addSon(container, arg) @@ -2343,7 +2376,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode, m.baseTypeMatch = false m.typedescMatched = false n.sons[a] = prepareOperand(c, formal.typ, n.sons[a]) - var arg = paramTypesMatch(m, formal.typ, n.sons[a].typ, + arg = paramTypesMatch(m, formal.typ, n.sons[a].typ, n.sons[a], nOrig.sons[a]) if arg == nil: m.state = csNoMatch @@ -2600,4 +2633,3 @@ tests: yes int, ordinal no string, ordinal - |