summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorSaem Ghani <saemghani+github@gmail.com>2021-02-15 00:51:05 -0800
committerGitHub <noreply@github.com>2021-02-15 09:51:05 +0100
commit260a5dacb7a3854d6d6aa18d9996b88bfcd13cc6 (patch)
tree175b30daf8594641e5f47e0576914e73fd386594
parentb68ecc82cb404dbbd291320139955794e88c24ff (diff)
downloadNim-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.nim18
-rw-r--r--compiler/semtypinst.nim2
-rw-r--r--compiler/vm.nim4
-rw-r--r--compiler/vmgen.nim5
-rw-r--r--nimsuggest/tests/twithin_macro.nim6
-rw-r--r--nimsuggest/tests/twithin_macro_prefix.nim7
-rw-r--r--tests/errmsgs/t10734.nim15
-rw-r--r--tests/js/t11166.nim18
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"