diff options
-rw-r--r-- | compiler/commands.nim | 2 | ||||
-rw-r--r-- | compiler/options.nim | 2 | ||||
-rw-r--r-- | compiler/semcall.nim | 7 | ||||
-rw-r--r-- | compiler/semexprs.nim | 8 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 7 | ||||
-rw-r--r-- | doc/advopt.txt | 3 | ||||
-rw-r--r-- | doc/manual/generics.txt | 4 | ||||
-rw-r--r-- | tests/concepts/tgraph.nim | 29 | ||||
-rw-r--r-- | web/news.txt | 3 |
9 files changed, 59 insertions, 6 deletions
diff --git a/compiler/commands.nim b/compiler/commands.nim index 6b2f074e8..2ed3f92a9 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -434,6 +434,8 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) = of "linedir": processOnOffSwitch({optLineDir}, arg, pass, info) of "assertions", "a": processOnOffSwitch({optAssert}, arg, pass, info) of "deadcodeelim": processOnOffSwitchG({optDeadCodeElim}, arg, pass, info) + of "reportconceptfailures": + processOnOffSwitchG({optReportConceptFailures}, arg, pass, info) of "threads": processOnOffSwitchG({optThreads}, arg, pass, info) #if optThreads in gGlobalOptions: incl(gNotes, warnGcUnsafe) diff --git a/compiler/options.nim b/compiler/options.nim index 98224a11d..6dd917ad4 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -40,7 +40,7 @@ type # please make sure we have under 32 options TGlobalOption* = enum # **keep binary compatible** gloptNone, optForceFullMake, optDeadCodeElim, optListCmd, optCompileOnly, optNoLinking, - optSafeCode, # only allow safe code + optReportConceptFailures, # report 'compiles' or 'concept' matching failures optCDebug, # turn on debugging information optGenDynLib, # generate a dynamic library optGenStaticLib, # generate a static library diff --git a/compiler/semcall.nim b/compiler/semcall.nim index 381093531..d8838e347 100644 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -95,7 +95,7 @@ proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) = # Gives a detailed error message; this is separated from semOverloadedCall, # as semOverlodedCall is already pretty slow (and we need this information # only in case of an error). - if c.compilesContextId > 0: + if c.compilesContextId > 0 and optReportConceptFailures notin gGlobalOptions: # fail fast: globalError(n.info, errTypeMismatch, "") if errors.isNil or errors.len == 0: @@ -133,7 +133,10 @@ proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) = add(candidates, "\n") if candidates != "": add(result, "\n" & msgKindToString(errButExpected) & "\n" & candidates) - localError(n.info, errGenerated, result) + if c.compilesContextId > 0 and optReportConceptFailures in gGlobalOptions: + globalError(n.info, errGenerated, result) + else: + localError(n.info, errGenerated, result) proc gatherUsedSyms(c: PContext, usedSyms: var seq[PNode]) = for scope in walkScopes(c.currentScope): diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 664102b75..f1016595a 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -292,8 +292,6 @@ proc semConv(c: PContext, n: PNode): PNode = proc semCast(c: PContext, n: PNode): PNode = ## Semantically analyze a casting ("cast[type](param)") - if optSafeCode in gGlobalOptions: localError(n.info, errCastNotInSafeMode) - #incl(c.p.owner.flags, sfSideEffect) checkSonsLen(n, 2) result = newNodeI(nkCast, n.info) result.typ = semTypeNode(c, n.sons[0], nil) @@ -1659,11 +1657,13 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = let oldInGenericInst = c.inGenericInst let oldProcCon = c.p c.generics = @[] + var err: string try: result = semExpr(c, n, flags) if msgs.gErrorCounter != oldErrorCount: result = nil except ERecoverableError: - discard + if optReportConceptFailures in gGlobalOptions: + err = getCurrentExceptionMsg() # undo symbol table changes (as far as it's possible): c.compilesContextId = oldCompilesId c.generics = oldGenerics @@ -1677,6 +1677,8 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = errorOutputs = oldErrorOutputs msgs.gErrorCounter = oldErrorCount msgs.gErrorMax = oldErrorMax + if optReportConceptFailures in gGlobalOptions and not err.isNil: + localError(n.info, err) proc semCompiles(c: PContext, n: PNode, flags: TExprFlags): PNode = # we replace this node by a 'true' or 'false' node: diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 642f50330..9fda8c860 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -684,6 +684,13 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation = of tyAnything: return if f.kind == tyAnything: isGeneric else: isNone + + of tyUserTypeClass, tyUserTypeClassInst: + # consider this: 'var g: Node' *within* a concept where 'Node' + # is a concept too (tgraph) + let x = typeRel(c, a, f, false) + if x >= isGeneric: + return isGeneric else: discard case f.kind diff --git a/doc/advopt.txt b/doc/advopt.txt index 18a5a527b..02849498f 100644 --- a/doc/advopt.txt +++ b/doc/advopt.txt @@ -52,6 +52,9 @@ Advanced options: --embedsrc embeds the original source code as comments in the generated output --threadanalysis:on|off turn thread analysis on|off + --reportConceptFailures:on|off + show errors for 'system.compiles' and concept + evaluation --tlsEmulation:on|off turn thread local storage emulation on|off --taintMode:on|off turn taint mode on|off --implicitStatic:on|off turn implicit compile time evaluation on|off diff --git a/doc/manual/generics.txt b/doc/manual/generics.txt index c6206d030..a73e22988 100644 --- a/doc/manual/generics.txt +++ b/doc/manual/generics.txt @@ -246,6 +246,10 @@ Much like generics, concepts are instantiated exactly once for each tested type and any static code included within them is also executed once. +**Hint**: Since concepts are still very rough at the edges there is a +command line switch ``--reportConceptFailures:on`` to make debugging +concept related type failures more easy. + Symbol lookup in generics ------------------------- diff --git a/tests/concepts/tgraph.nim b/tests/concepts/tgraph.nim new file mode 100644 index 000000000..a0177a043 --- /dev/null +++ b/tests/concepts/tgraph.nim @@ -0,0 +1,29 @@ +discard """ + output: '''XY is Node +MyGraph is Graph''' +""" +# bug #3452 +import math + +type + Node* = concept n + `==`(n, n) is bool + + Graph* = concept g + var x: Node + distance(g, x, x) is float + + XY* = tuple[x, y: int] + + MyGraph* = object + points: seq[XY] + +if XY is Node: + echo "XY is Node" + +proc distance*( g: MyGraph, a, b: XY): float = + sqrt( pow(float(a.x - b.x), 2) + pow(float(a.y - b.y), 2) ) + +if MyGraph is Graph: + echo "MyGraph is Graph" + diff --git a/web/news.txt b/web/news.txt index d1a730ea5..f0485f75b 100644 --- a/web/news.txt +++ b/web/news.txt @@ -151,6 +151,9 @@ can be found `here <https://nimworkshop.splashthat.com/>`_. (issue `#2599 <https://github.com/nim-lang/Nim/issues/2599>`_). - The compiler now supports a `bitsize pragma <docs/manual.html#pragmas-bitsize-pragma>`_ for constructing bitfields. + - Added a new ``--reportConceptFailures`` switch for better debugging of + concept related type mismatches. This can also be used to debug + ``system.compiles`` failures. Language Additions |