diff options
author | Saem Ghani <saemghani+github@gmail.com> | 2021-02-15 00:51:05 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-15 09:51:05 +0100 |
commit | 260a5dacb7a3854d6d6aa18d9996b88bfcd13cc6 (patch) | |
tree | 175b30daf8594641e5f47e0576914e73fd386594 | |
parent | b68ecc82cb404dbbd291320139955794e88c24ff (diff) | |
download | Nim-260a5dacb7a3854d6d6aa18d9996b88bfcd13cc6.tar.gz |
fixed dot operator recursive loop & macro suggest (#16922)
* basic stability improvements; refs nimsuggest * fixed dot operator recursive loop & macro suggest * hacky fix for run away dot operator sem check Committing this mostly to make the issue more clear. Perhaps get better feedback. * semExprWithType seems like a better place to check * fixed error messages const case expressions * Clean-up test * stopped the dot operator madness No longer get infinite recursion when seming broken code with a dot operator macro like in jsffi. Co-authored-by: Araq <rumpf_a@web.de>
-rw-r--r-- | compiler/semexprs.nim | 18 | ||||
-rw-r--r-- | compiler/semtypinst.nim | 2 | ||||
-rw-r--r-- | compiler/vm.nim | 4 | ||||
-rw-r--r-- | compiler/vmgen.nim | 5 | ||||
-rw-r--r-- | nimsuggest/tests/twithin_macro.nim | 6 | ||||
-rw-r--r-- | nimsuggest/tests/twithin_macro_prefix.nim | 7 | ||||
-rw-r--r-- | tests/errmsgs/t10734.nim | 15 | ||||
-rw-r--r-- | tests/js/t11166.nim | 18 |
8 files changed, 51 insertions, 24 deletions
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index bac2daa2e..c1365a83d 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -66,10 +66,17 @@ proc semOperand(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = proc semExprCheck(c: PContext, n: PNode, flags: TExprFlags): PNode = rejectEmptyNode(n) result = semExpr(c, n, flags+{efWantValue}) - if result.kind == nkEmpty: + + let + isEmpty = result.kind == nkEmpty + isTypeError = result.typ != nil and result.typ.kind == tyError + + if isEmpty or isTypeError: # bug #12741, redundant error messages are the lesser evil here: localError(c.config, n.info, errExprXHasNoType % renderTree(result, {renderNoComments})) + + if isEmpty: # do not produce another redundant error message: result = errorNode(c, n) @@ -79,6 +86,9 @@ proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = localError(c.config, n.info, errExprXHasNoType % renderTree(result, {renderNoComments})) result.typ = errorType(c) + elif result.typ.kind == tyError: + # associates the type error to the current owner + result.typ = errorType(c) else: if result.typ.kind in {tyVar, tyLent}: result = newDeref(result) @@ -887,6 +897,9 @@ proc setGenericParams(c: PContext, n: PNode) = n[i].typ = semTypeNode(c, n[i], nil) proc afterCallActions(c: PContext; n, orig: PNode, flags: TExprFlags): PNode = + if efNoSemCheck notin flags and n.typ != nil and n.typ.kind == tyError: + return errorNode(c, n) + result = n let callee = result[0].sym case callee.kind @@ -1368,6 +1381,9 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode = return tryReadingTypeField(c, n, i, ty.base) elif isTypeExpr(n.sons[0]): return tryReadingTypeField(c, n, i, ty) + elif ty.kind == tyError: + # a type error doesn't have any builtin fields + return nil if ty.kind in tyUserTypeClasses and ty.isResolvedUserTypeClass: ty = ty.lastSon diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim index 07fe6b27d..f9ac6ccca 100644 --- a/compiler/semtypinst.nim +++ b/compiler/semtypinst.nim @@ -229,6 +229,8 @@ proc replaceTypeVarsN(cl: var TReplTypeVars, n: PNode; start=0): PNode = n = reResolveCallsWithTypedescParams(cl, n) result = if cl.allowMetaTypes: n else: cl.c.semExpr(cl.c, n) + if not cl.allowMetaTypes: + assert result.kind notin nkCallKinds else: if n.len > 0: newSons(result, n.len) diff --git a/compiler/vm.nim b/compiler/vm.nim index 0c9c0ec33..246d9d4d2 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -2184,7 +2184,7 @@ const evalPass* = makePass(myOpen, myProcess, myClose) proc evalConstExprAux(module: PSym; idgen: IdGenerator; g: ModuleGraph; prc: PSym, n: PNode, mode: TEvalMode): PNode = - if g.config.errorCounter > 0: return n + #if g.config.errorCounter > 0: return n let n = transformExpr(g, idgen, module, n) setupGlobalCtx(module, g, idgen) var c = PCtx g.vm @@ -2262,7 +2262,7 @@ proc errorNode(idgen: IdGenerator; owner: PSym, n: PNode): PNode = proc evalMacroCall*(module: PSym; idgen: IdGenerator; g: ModuleGraph; templInstCounter: ref int; n, nOrig: PNode, sym: PSym): PNode = - if g.config.errorCounter > 0: return errorNode(idgen, module, n) + #if g.config.errorCounter > 0: return errorNode(idgen, module, n) # XXX globalError() is ugly here, but I don't know a better solution for now inc(g.config.evalMacroCounter) diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index 6790276a9..d74bd44d8 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -505,7 +505,10 @@ proc genCase(c: PCtx; n: PNode; dest: var TDest) = let it = n[i] if it.len == 1: # else stmt: - c.gen(it[0], dest) + if it[0].kind != nkNilLit or it[0].typ != nil: + # an nkNilLit with nil for typ implies there is no else branch, this + # avoids unused related errors as we've already consumed the dest + c.gen(it[0], dest) else: let b = rawGenLiteral(c, it) c.gABx(it, opcBranch, tmp, b) diff --git a/nimsuggest/tests/twithin_macro.nim b/nimsuggest/tests/twithin_macro.nim index 2f5e278c4..d79dae1be 100644 --- a/nimsuggest/tests/twithin_macro.nim +++ b/nimsuggest/tests/twithin_macro.nim @@ -41,15 +41,11 @@ echo r.age_human_yrs() echo r discard """ -disabled:true -$nimsuggest --tester $file +$nimsuggest --tester --maxresults:5 $file >sug $1 sug;;skField;;age;;int;;$file;;6;;6;;"";;100;;None sug;;skField;;name;;string;;$file;;5;;6;;"";;100;;None sug;;skMethod;;twithin_macro.age_human_yrs;;proc (self: Animal): int;;$file;;8;;9;;"";;100;;None sug;;skMethod;;twithin_macro.vocalize;;proc (self: Animal): string;;$file;;7;;9;;"";;100;;None sug;;skMethod;;twithin_macro.vocalize;;proc (self: Rabbit): string;;$file;;23;;9;;"";;100;;None -sug;;skMacro;;twithin_macro.class;;proc (head: untyped, body: untyped): untyped{.gcsafe, locks: <unknown>.};;$file;;4;;6;;"";;50;;None* """ - -# TODO: disabled due to semantic error reporting in nimsuggest results diff --git a/nimsuggest/tests/twithin_macro_prefix.nim b/nimsuggest/tests/twithin_macro_prefix.nim index 1c06397c5..dd3810818 100644 --- a/nimsuggest/tests/twithin_macro_prefix.nim +++ b/nimsuggest/tests/twithin_macro_prefix.nim @@ -46,10 +46,3 @@ $nimsuggest --tester $file sug;;skField;;age;;int;;$file;;6;;6;;"";;100;;Prefix sug;;skMethod;;twithin_macro_prefix.age_human_yrs;;proc (self: Animal): int;;$file;;8;;9;;"";;100;;Prefix """ - -#[ -TODO: additional calls to `>sug $1` produces different output with errors, - possibly related to cached results from the first analysis, which refers - to expanded macros/templates which rely on imported symbols from `system` - module that are not present in this module. -]# diff --git a/tests/errmsgs/t10734.nim b/tests/errmsgs/t10734.nim index 32ee5415e..4e73db7cd 100644 --- a/tests/errmsgs/t10734.nim +++ b/tests/errmsgs/t10734.nim @@ -2,13 +2,14 @@ discard """ cmd: "nim check $file" errormsg: "" nimout: ''' -t10734.nim(18, 1) Error: invalid indentation -t10734.nim(18, 6) Error: invalid indentation -t10734.nim(19, 7) Error: expression expected, but found '[EOF]' -t10734.nim(17, 5) Error: 'proc' is not a concrete type; for a callback without parameters use 'proc()' -t10734.nim(18, 6) Error: undeclared identifier: 'p' -t10734.nim(18, 6) Error: 'p' cannot be assigned to -t10734.nim(16, 3) Hint: 'T' is declared but not used [XDeclaredButNotUsed] +t10734.nim(19, 1) Error: invalid indentation +t10734.nim(19, 6) Error: invalid indentation +t10734.nim(20, 7) Error: expression expected, but found '[EOF]' +t10734.nim(18, 5) Error: 'proc' is not a concrete type; for a callback without parameters use 'proc()' +t10734.nim(19, 6) Error: undeclared identifier: 'p' +t10734.nim(19, 6) Error: expression 'p' has no type (or is ambiguous) +t10734.nim(19, 6) Error: 'p' cannot be assigned to +t10734.nim(17, 3) Hint: 'T' is declared but not used [XDeclaredButNotUsed] ''' """ diff --git a/tests/js/t11166.nim b/tests/js/t11166.nim index 8dd77925c..e98ccda10 100644 --- a/tests/js/t11166.nim +++ b/tests/js/t11166.nim @@ -1,4 +1,20 @@ +discard """ + output: ''' +test1 +test2 +''' +""" + import jsffi +type + C = object + props: int + +var c: C + when compiles(c.props): - echo "test" + echo "test1" + +when not compiles(d.props): + echo "test2" |