diff options
-rw-r--r-- | compiler/lookups.nim | 21 | ||||
-rw-r--r-- | compiler/pragmas.nim | 4 | ||||
-rw-r--r-- | compiler/semcall.nim | 13 | ||||
-rw-r--r-- | compiler/semexprs.nim | 2 | ||||
-rw-r--r-- | compiler/semgnrc.nim | 2 | ||||
-rw-r--r-- | compiler/semmagic.nim | 2 | ||||
-rw-r--r-- | compiler/semstmts.nim | 2 | ||||
-rw-r--r-- | compiler/semtempl.nim | 2 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 2 | ||||
-rw-r--r-- | doc/manual/type_rel.txt | 2 | ||||
-rw-r--r-- | lib/system/nimscript.nim | 2 | ||||
-rw-r--r-- | readme.md | 4 | ||||
-rw-r--r-- | tests/converter/tor_in_converter.nim | 23 | ||||
-rw-r--r-- | tests/generics/twrong_explicit_typeargs.nim | 2 | ||||
-rw-r--r-- | tests/lookups/test.nim | 17 |
15 files changed, 74 insertions, 26 deletions
diff --git a/compiler/lookups.nim b/compiler/lookups.nim index 9ca864406..df19a6afb 100644 --- a/compiler/lookups.nim +++ b/compiler/lookups.nim @@ -99,8 +99,11 @@ proc debugScopes*(c: PContext; limit=0) {.deprecated.} = proc searchInScopes*(c: PContext, s: PIdent, filter: TSymKinds): PSym = for scope in walkScopes(c.currentScope): - result = strTableGet(scope.symbols, s) - if result != nil and result.kind in filter: return + var ti: TIdentIter + var candidate = initIdentIter(ti, scope.symbols, s) + while candidate != nil: + if candidate.kind in filter: return candidate + candidate = nextIdentIter(ti, scope.symbols) result = nil proc errorSym*(c: PContext, n: PNode): PSym = @@ -266,13 +269,17 @@ proc lookUp*(c: PContext, n: PNode): PSym = type TLookupFlag* = enum - checkAmbiguity, checkUndeclared + checkAmbiguity, checkUndeclared, checkModule -proc qualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym = +proc qualifiedLookUp*(c: PContext, n: PNode, flags: set[TLookupFlag]): PSym = + const allExceptModule = {low(TSymKind)..high(TSymKind)}-{skModule,skPackage} case n.kind of nkIdent, nkAccQuoted: var ident = considerQuotedIdent(n) - result = searchInScopes(c, ident).skipAlias(n) + if checkModule in flags: + result = searchInScopes(c, ident).skipAlias(n) + else: + result = searchInScopes(c, ident, allExceptModule).skipAlias(n) if result == nil and checkUndeclared in flags: fixSpelling(n, ident, searchInScopes) localError(n.info, errUndeclaredIdentifier, ident.s) @@ -286,7 +293,7 @@ proc qualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym = errorUseQualifier(c, n.info, n.sym) of nkDotExpr: result = nil - var m = qualifiedLookUp(c, n.sons[0], flags*{checkUndeclared}) + var m = qualifiedLookUp(c, n.sons[0], (flags*{checkUndeclared})+{checkModule}) if m != nil and m.kind == skModule: var ident: PIdent = nil if n.sons[1].kind == nkIdent: @@ -331,7 +338,7 @@ proc initOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym = o.mode = oimDone of nkDotExpr: o.mode = oimOtherModule - o.m = qualifiedLookUp(c, n.sons[0]) + o.m = qualifiedLookUp(c, n.sons[0], {checkUndeclared, checkModule}) if o.m != nil and o.m.kind == skModule: var ident: PIdent = nil if n.sons[1].kind == nkIdent: diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 50d5bb1b5..781aab687 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -569,7 +569,7 @@ proc deprecatedStmt(c: PContext; pragma: PNode) = localError(pragma.info, "list of key:value pairs expected"); return for n in pragma: if n.kind in {nkExprColonExpr, nkExprEqExpr}: - let dest = qualifiedLookUp(c, n[1]) + let dest = qualifiedLookUp(c, n[1], {checkUndeclared}) let src = considerQuotedIdent(n[0]) let alias = newSym(skAlias, src, dest, n[0].info) incl(alias.flags, sfExported) @@ -594,7 +594,7 @@ proc pragmaGuard(c: PContext; it: PNode; kind: TSymKind): PSym = # and perform the lookup on demand instead. result = newSym(skUnknown, considerQuotedIdent(n), nil, n.info) else: - result = qualifiedLookUp(c, n) + result = qualifiedLookUp(c, n, {checkUndeclared}) proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, validPragmas: TSpecialWords): bool = diff --git a/compiler/semcall.nim b/compiler/semcall.nim index c62f53a62..97209167d 100644 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -396,12 +396,7 @@ proc explicitGenericSym(c: PContext, n: PNode, s: PSym): PNode = let formal = s.ast.sons[genericParamsPos].sons[i-1].typ let arg = n[i].typ let tm = typeRel(m, formal, arg, true) - if tm in {isNone, isConvertible}: - if formal.sonsLen > 0 and formal.sons[0].kind != tyNone: - typeMismatch(n, formal.sons[0], arg) - else: - typeMismatch(n, formal, arg) - break + if tm in {isNone, isConvertible}: return nil var newInst = generateInstance(c, s, m.bindings, n.info) markUsed(n.info, s) styleCheckUse(n.info, s) @@ -422,6 +417,7 @@ proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode = "; got " & $(n.len-1) & " type(s) but expected " & $expected) return n result = explicitGenericSym(c, n, s) + if result == nil: result = explicitGenericInstError(n) elif a.kind in {nkClosedSymChoice, nkOpenSymChoice}: # choose the generic proc with the proper number of type parameters. # XXX I think this could be improved by reusing sigmatch.paramTypesMatch. @@ -434,11 +430,12 @@ proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode = # it suffices that the candidate has the proper number of generic # type parameters: if safeLen(candidate.ast.sons[genericParamsPos]) == n.len-1: - result.add(explicitGenericSym(c, n, candidate)) + let x = explicitGenericSym(c, n, candidate) + if x != nil: result.add(x) # get rid of nkClosedSymChoice if not ambiguous: if result.len == 1 and a.kind == nkClosedSymChoice: result = result[0] - # candidateCount != 1: return explicitGenericInstError(n) + elif result.len == 0: result = explicitGenericInstError(n) else: result = explicitGenericInstError(n) diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 2d5e97fa1..70f795d4a 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1107,7 +1107,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode = # here at all! #if isSymChoice(n.sons[1]): return - var s = qualifiedLookUp(c, n, {checkAmbiguity, checkUndeclared}) + var s = qualifiedLookUp(c, n, {checkAmbiguity, checkUndeclared, checkModule}) if s != nil: if s.kind in OverloadableSyms: result = symChoice(c, n, s, scClosed) diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim index e4fd715da..9ea3efd0c 100644 --- a/compiler/semgnrc.nim +++ b/compiler/semgnrc.nim @@ -127,7 +127,7 @@ proc fuzzyLookup(c: PContext, n: PNode, flags: TSemGenericFlags, assert n.kind == nkDotExpr semIdeForTemplateOrGenericCheck(n, ctx.cursorInBody) - let luf = if withinMixin notin flags: {checkUndeclared} else: {} + let luf = if withinMixin notin flags: {checkUndeclared, checkModule} else: {checkModule} var s = qualifiedLookUp(c, n, luf) if s != nil: diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index 451745884..d9fec6275 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -133,7 +133,7 @@ proc semBindSym(c: PContext, n: PNode): PNode = return errorNode(c, n) let id = newIdentNode(getIdent(sl.strVal), n.info) - let s = qualifiedLookUp(c, id) + let s = qualifiedLookUp(c, id, {checkUndeclared}) if s != nil: # we need to mark all symbols: var sc = symChoice(c, id, s, TSymChoiceRule(isMixin.intVal)) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index f59acd7be..ab9ecd1a6 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -675,7 +675,7 @@ proc typeSectionLeftSidePass(c: PContext, n: PNode) = let name = a.sons[0] var s: PSym if name.kind == nkDotExpr: - s = qualifiedLookUp(c, name) + s = qualifiedLookUp(c, name, {checkUndeclared, checkModule}) if s.kind != skType or s.typ.skipTypes(abstractPtrs).kind != tyObject or tfPartial notin s.typ.skipTypes(abstractPtrs).flags: localError(name.info, "only .partial objects can be extended") else: diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim index 9341e2929..4d3b6d038 100644 --- a/compiler/semtempl.nim +++ b/compiler/semtempl.nim @@ -80,7 +80,7 @@ proc semBindStmt(c: PContext, n: PNode, toBind: var IntSet): PNode = # the same symbol! # This is however not true anymore for hygienic templates as semantic # processing for them changes the symbol table... - let s = qualifiedLookUp(c, a) + let s = qualifiedLookUp(c, a, {checkUndeclared}) if s != nil: # we need to mark all symbols: let sc = symChoice(c, n, s, scClosed) diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index df094402c..95f5f0b07 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -1031,6 +1031,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation = if x < isSubtype: return isNone # 'and' implies minimum matching result: if x < result: result = x + if result > isGeneric: result = isGeneric bindingRet result of tyOr: @@ -1041,6 +1042,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation = # 'or' implies maximum matching result: if x > result: result = x if result >= isSubtype: + if result > isGeneric: result = isGeneric bindingRet result else: result = isNone diff --git a/doc/manual/type_rel.txt b/doc/manual/type_rel.txt index b9b83919c..5b68f73aa 100644 --- a/doc/manual/type_rel.txt +++ b/doc/manual/type_rel.txt @@ -313,7 +313,7 @@ matches better than just ``T`` then. Automatic dereferencing ----------------------- -If the `experimental mode <experimental pragma>`_ is active and no other match +If the `experimental mode <#pragmas-experimental-pragma>`_ is active and no other match is found, the first argument ``a`` is dereferenced automatically if it's a pointer type and overloading resolution is tried with ``a[]`` instead. diff --git a/lib/system/nimscript.nim b/lib/system/nimscript.nim index cc96bcba8..ad2b154d4 100644 --- a/lib/system/nimscript.nim +++ b/lib/system/nimscript.nim @@ -234,7 +234,7 @@ proc cd*(dir: string) {.raises: [OSError].} = ## ## The change is permanent for the rest of the execution, since this is just ## a shortcut for `os.setCurrentDir() - ## <http://nim-lang.org/os.html#setCurrentDir,string>`_ . Use the `withDir() + ## <http://nim-lang.org/docs/os.html#setCurrentDir,string>`_ . Use the `withDir() ## <#withDir>`_ template if you want to perform a temporary change only. setCurrentDir(dir) checkOsError() diff --git a/readme.md b/readme.md index fbaa5fd32..f56b054d6 100644 --- a/readme.md +++ b/readme.md @@ -27,6 +27,8 @@ To build from source you will need: are: clang, Visual C++, Intel's C++ compiler * git or wget +**Note:** When installing ``gcc`` on Ubuntu (and likely other distros) ensure that the ``build-essentials`` package is installed also. + If you are on a fairly modern *nix system, the following steps should work: ``` @@ -47,7 +49,7 @@ The above steps can be performed on Windows in a similar fashion, the instead of ``build.sh``. The ``koch`` tool is the Nim build tool, more ``koch`` related options are -documented in [doc/koch.txt](doc/koch.txt). +documented in [doc/koch.rst](doc/koch.rst). ## Nimble [Nimble](https://github.com/nim-lang/nimble) is Nim's package manager. For the diff --git a/tests/converter/tor_in_converter.nim b/tests/converter/tor_in_converter.nim new file mode 100644 index 000000000..5674526a1 --- /dev/null +++ b/tests/converter/tor_in_converter.nim @@ -0,0 +1,23 @@ +discard """ + output: '''test +test''' +""" +# bug #4537 + +# nim js --d:nodejs + +type + Str = distinct string + +when true: + # crashes + converter convert(s: string | cstring): Str = Str($s) +else: + # works! + converter convert(s: string): Str = Str($s) + converter convert(s: cstring): Str = Str($s) + +proc echoStr(s: Str) = echo s.string + +echoStr("test") +echoStr("test".cstring) diff --git a/tests/generics/twrong_explicit_typeargs.nim b/tests/generics/twrong_explicit_typeargs.nim index 37d5b1e38..e47b38e99 100644 --- a/tests/generics/twrong_explicit_typeargs.nim +++ b/tests/generics/twrong_explicit_typeargs.nim @@ -1,5 +1,5 @@ discard """ - errormsg: "type mismatch: got (string) but expected 'int32 or int64'" + errormsg: "cannot instantiate: 'newImage[string]'" line: 16 """ diff --git a/tests/lookups/test.nim b/tests/lookups/test.nim new file mode 100644 index 000000000..a17d235a4 --- /dev/null +++ b/tests/lookups/test.nim @@ -0,0 +1,17 @@ +# This file needs to be called 'test' nim to provoke a clash +# with the unittest.test name. Issue # + +import unittest, macros + +# bug #4555 + +macro memo(n: untyped): typed = + result = n + +proc fastFib(n: int): int {.memo.} = 40 +proc fib(n: int): int = 40 + +suite "memoization": + test "recursive function memoization": + check fastFib(40) == fib(40) + |