diff --git a/compiler/procfind.nim b/compiler/procfind.nim index fde4d22ea8..4a1fb5ac8c 100755 --- a/compiler/procfind.nim +++ b/compiler/procfind.nim @@ -29,7 +29,7 @@ proc equalGenericParams(procA, procB: PNode): bool = a = procA.sons[i].sym b = procB.sons[i].sym if (a.name.id != b.name.id) or - not sameTypeOrNil(a.typ, b.typ, {TypeDescExactMatch}): return + not sameTypeOrNil(a.typ, b.typ, {TypeDescExactMatch}): return if (a.ast != nil) and (b.ast != nil): if not ExprStructuralEquivalent(a.ast, b.ast): return result = true @@ -44,7 +44,7 @@ proc SearchForProc*(c: PContext, fn: PSym, tos: int): PSym = if equalGenericParams(result.ast.sons[genericParamsPos], fn.ast.sons[genericParamsPos]): case equalParams(result.typ.n, fn.typ.n) - of paramsEqual: + of paramsEqual: return of paramsIncompatible: LocalError(fn.info, errNotOverloadable, fn.name.s) diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index c48434eb78..1f2511694c 100755 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -12,18 +12,18 @@ import intsets, ast, astalgo, semdata, types, msgs, renderer, lookups, semtypinst, - magicsys, condsyms, idents, lexer, options + magicsys, condsyms, idents, lexer, options, parampatterns type TCandidateState* = enum csEmpty, csMatch, csNoMatch TCandidate* {.final.} = object - exactMatches*: int + exactMatches*: int # also misused to prefer iters over procs + genericMatches: int # also misused to prefer constraints subtypeMatches: int intConvMatches: int # conversions to int are not as expensive convMatches: int - genericMatches: int state*: TCandidateState callee*: PType # may not be nil! calleeSym*: PSym # may be nil @@ -773,6 +773,15 @@ proc setSon(father: PNode, at: int, son: PNode) = proc matchesAux*(c: PContext, n, nOrig: PNode, m: var TCandidate, marker: var TIntSet) = + template checkConstraint(n: expr) {.immediate, dirty.} = + if not formal.constraint.isNil: + if matchNodeKinds(formal.constraint, n): + # better match over other routines with no such restriction: + inc(m.genericMatches, 100) + else: + m.state = csNoMatch + return + var f = 1 # iterates over formal parameters var a = 1 # iterates over the actual given arguments m.state = csMatch # until proven otherwise @@ -805,7 +814,8 @@ proc matchesAux*(c: PContext, n, nOrig: PNode, n.sons[a].sons[1], nOrig.sons[a].sons[1]) if arg == nil: m.state = csNoMatch - return + return + checkConstraint(n.sons[a].sons[1]) if m.baseTypeMatch: assert(container == nil) container = newNodeI(nkBracket, n.sons[a].info) @@ -862,6 +872,7 @@ proc matchesAux*(c: PContext, n, nOrig: PNode, if f != formalLen - 1: container = nil else: setSon(m.call, formal.position + 1, arg) + checkConstraint(n.sons[a]) inc(a) inc(f) diff --git a/compiler/types.nim b/compiler/types.nim index 825b1027a0..23d202fdf4 100755 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -632,7 +632,8 @@ proc SameTypeOrNil*(a, b: PType, flags: TTypeCmpFlags = {}): bool = result = SameTypeAux(a, b, c) proc equalParam(a, b: PSym): TParamsEquality = - if SameTypeOrNil(a.typ, b.typ, {TypeDescExactMatch}): + if SameTypeOrNil(a.typ, b.typ, {TypeDescExactMatch}) and + ExprStructuralEquivalent(a.constraint, b.constraint): if a.ast == b.ast: result = paramsEqual elif a.ast != nil and b.ast != nil: diff --git a/tests/run/tastoverload1.nim b/tests/run/tastoverload1.nim new file mode 100644 index 0000000000..c8705547af --- /dev/null +++ b/tests/run/tastoverload1.nim @@ -0,0 +1,21 @@ +discard """ + output: '''string literal +no string literal +no string literal''' +""" + +proc optLit(a: string{lit}) = + echo "string literal" + +proc optLit(a: string) = + echo "no string literal" + +const + constant = "abc" + +var + variable = "xyz" + +optLit("literal") +optLit(constant) +optLit(variable) diff --git a/todo.txt b/todo.txt index 870265ac3b..c5b5eb4e7f 100755 --- a/todo.txt +++ b/todo.txt @@ -6,6 +6,7 @@ version 0.9.2 overloading - ``hoist`` pragma for loop hoisting: can be easily done with AST overloading + global + - document overloading based on ASTs - test&finish first class iterators: * nested iterators