summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--changelog.md2
-rw-r--r--compiler/lexer.nim27
-rw-r--r--compiler/semtypes.nim2
-rw-r--r--compiler/sigmatch.nim12
-rw-r--r--doc/manual.rst4
-rw-r--r--lib/posix/posix.nim40
-rw-r--r--lib/pure/asyncftpclient.nim1
-rw-r--r--lib/pure/ospaths.nim7
-rw-r--r--lib/pure/typetraits.nim7
-rw-r--r--tests/errmsgs/t6281.nim9
-rw-r--r--tests/lexer/tintegerliterals.nim9
-rw-r--r--tests/lexer/tinvalidintegerliteral3.nim7
-rw-r--r--tests/misc/tunsignedmisc.nim6
-rw-r--r--tests/statictypes/tstatictypes.nim9
-rw-r--r--tests/stdlib/tospaths.nim41
-rw-r--r--tests/typerel/t8172.nim11
16 files changed, 151 insertions, 43 deletions
diff --git a/changelog.md b/changelog.md
index bbe526124..0943d7836 100644
--- a/changelog.md
+++ b/changelog.md
@@ -20,6 +20,8 @@
 - The parser now warns about inconsistent spacing around binary operators as
   these can easily be confused with unary operators. This warning will likely
   become an error in the future.
+- The ``'c`` and ``'C'`` prefix for octal literals is now deprecated to
+  bring the language in line with the standard library (e.g. ``parseOct``).
 
 
 #### Breaking changes in the standard library
diff --git a/compiler/lexer.nim b/compiler/lexer.nim
index 375bf227d..9727d16a7 100644
--- a/compiler/lexer.nim
+++ b/compiler/lexer.nim
@@ -359,9 +359,8 @@ proc getNumber(L: var TLexer, result: var TToken) =
       inc(pos)
     L.bufpos = pos
 
-  proc lexMessageLitNum(L: var TLexer, msg: string, startpos: int) =
+  proc lexMessageLitNum(L: var TLexer, msg: string, startpos: int, msgKind = errGenerated) =
     # Used to get slightly human friendlier err messages.
-    # Note: the erroneous 'O' char in the character set is intentional
     const literalishChars = {'A'..'F', 'a'..'f', '0'..'9', 'X', 'x', 'o', 'O',
       'c', 'C', 'b', 'B', '_', '.', '\'', 'd', 'i', 'u'}
     var msgPos = L.bufpos
@@ -380,7 +379,7 @@ proc getNumber(L: var TLexer, result: var TToken) =
       add(t.literal, L.buf[L.bufpos])
       matchChars(L, t, {'0'..'9'})
     L.bufpos = msgPos
-    lexMessage(L, errGenerated, msg % t.literal)
+    lexMessage(L, msgKind, msg % t.literal)
 
   var
     startpos, endpos: int
@@ -388,7 +387,8 @@ proc getNumber(L: var TLexer, result: var TToken) =
     isBase10 = true
     numDigits = 0
   const
-    baseCodeChars = {'X', 'x', 'o', 'c', 'C', 'b', 'B'}
+    # 'c', 'C' is deprecated
+    baseCodeChars = {'X', 'x', 'o', 'b', 'B', 'c', 'C'}
     literalishChars = baseCodeChars + {'A'..'F', 'a'..'f', '0'..'9', '_', '\''}
     floatTypes = {tkFloatLit, tkFloat32Lit, tkFloat64Lit, tkFloat128Lit}
   result.tokType = tkIntLit   # int literal until we know better
@@ -398,17 +398,27 @@ proc getNumber(L: var TLexer, result: var TToken) =
   tokenBegin(result, startPos)
 
   # First stage: find out base, make verifications, build token literal string
-  if L.buf[L.bufpos] == '0' and L.buf[L.bufpos + 1] in baseCodeChars + {'O'}:
+  # {'c', 'C'} is added for deprecation reasons to provide a clear error message
+  if L.buf[L.bufpos] == '0' and L.buf[L.bufpos + 1] in baseCodeChars + {'c', 'C', 'O'}:
     isBase10 = false
     eatChar(L, result, '0')
     case L.buf[L.bufpos]
+    of 'c', 'C':
+      lexMessageLitNum(L,
+                       "$1 will soon be invalid for oct literals; Use '0o' " &
+                       "for octals. 'c', 'C' prefix",
+                       startpos,
+                       warnDeprecated)
+      eatChar(L, result, 'c')
+      numDigits = matchUnderscoreChars(L, result, {'0'..'7'})
     of 'O':
-      lexMessageLitNum(L, "$1 is not a valid number; did you mean octal? Then use one of '0o', '0c' or '0C'.", startpos)
+      lexMessageLitNum(L, "$1 is an invalid int literal; For octal literals " &
+                          "use the '0o' prefix.", startpos)
     of 'x', 'X':
       eatChar(L, result, 'x')
       numDigits = matchUnderscoreChars(L, result, {'0'..'9', 'a'..'f', 'A'..'F'})
-    of 'o', 'c', 'C':
-      eatChar(L, result, 'c')
+    of 'o':
+      eatChar(L, result, 'o')
       numDigits = matchUnderscoreChars(L, result, {'0'..'7'})
     of 'b', 'B':
       eatChar(L, result, 'b')
@@ -511,6 +521,7 @@ proc getNumber(L: var TLexer, result: var TToken) =
           if L.buf[pos] != '_':
             xi = `shl`(xi, 1) or (ord(L.buf[pos]) - ord('0'))
           inc(pos)
+      # 'c', 'C' is deprecated
       of 'o', 'c', 'C':
         result.base = base8
         while pos < endpos:
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index dfd424705..17420111f 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -873,7 +873,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
     if base.isMetaType and procKind == skMacro:
       localError(c.config, info, errMacroBodyDependsOnGenericTypes % paramName)
     result = addImplicitGeneric(c.newTypeWithSons(tyStatic, @[base]))
-    result.flags.incl({tfHasStatic, tfUnresolved})
+    if result != nil: result.flags.incl({tfHasStatic, tfUnresolved})
 
   of tyTypeDesc:
     if tfUnresolved notin paramType.flags:
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 84e59349e..523783b36 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -2308,6 +2308,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
             m.firstMismatch = f
             return
           if m.baseTypeMatch:
+            assert formal.typ.kind == tyVarargs
             #assert(container == nil)
             if container.isNil:
               container = newNodeIT(nkBracket, n.sons[a].info, arrayConstr(c, arg))
@@ -2321,10 +2322,19 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
 
             # pick the formal from the end, so that 'x, y, varargs, z' works:
             f = max(f, formalLen - n.len + a + 1)
-          else:
+          elif formal.typ.kind != tyVarargs or container == nil:
             setSon(m.call, formal.position + 1, arg)
             inc(f)
             container = nil
+          else:
+            # we end up here if the argument can be converted into the varargs
+            # formal (eg. seq[T] -> varargs[T]) but we have already instantiated
+            # a container
+            assert arg.kind == nkHiddenStdConv
+            localError(c.config, n.sons[a].info, "cannot convert $1 to $2" % [
+              typeToString(n.sons[a].typ), typeToString(formal.typ) ])
+            m.state = csNoMatch
+            return
         checkConstraint(n.sons[a])
     inc(a)
 
diff --git a/doc/manual.rst b/doc/manual.rst
index 28fbfb199..5ca6da22e 100644
--- a/doc/manual.rst
+++ b/doc/manual.rst
@@ -413,7 +413,7 @@ Numerical constants are of a single type and have the form::
   bindigit = '0'..'1'
   HEX_LIT = '0' ('x' | 'X' ) hexdigit ( ['_'] hexdigit )*
   DEC_LIT = digit ( ['_'] digit )*
-  OCT_LIT = '0' ('o' | 'c' | 'C') octdigit ( ['_'] octdigit )*
+  OCT_LIT = '0' 'o' octdigit ( ['_'] octdigit )*
   BIN_LIT = '0' ('b' | 'B' ) bindigit ( ['_'] bindigit )*
 
   INT_LIT = HEX_LIT
@@ -444,7 +444,7 @@ Numerical constants are of a single type and have the form::
 
 As can be seen in the productions, numerical constants can contain underscores
 for readability. Integer and floating point literals may be given in decimal (no
-prefix), binary (prefix ``0b``), octal (prefix ``0o`` or ``0c``) and hexadecimal
+prefix), binary (prefix ``0b``), octal (prefix ``0o``) and hexadecimal
 (prefix ``0x``) notation.
 
 There exists a literal for each numerical type that is
diff --git a/lib/posix/posix.nim b/lib/posix/posix.nim
index 97b4124ec..c230e6598 100644
--- a/lib/posix/posix.nim
+++ b/lib/posix/posix.nim
@@ -36,26 +36,26 @@
 #      platforms - where do they come from and why are they here?
 when false:
   const
-    C_IRUSR = 0c000400 ## Read by owner.
-    C_IWUSR = 0c000200 ## Write by owner.
-    C_IXUSR = 0c000100 ## Execute by owner.
-    C_IRGRP = 0c000040 ## Read by group.
-    C_IWGRP = 0c000020 ## Write by group.
-    C_IXGRP = 0c000010 ## Execute by group.
-    C_IROTH = 0c000004 ## Read by others.
-    C_IWOTH = 0c000002 ## Write by others.
-    C_IXOTH = 0c000001 ## Execute by others.
-    C_ISUID = 0c004000 ## Set user ID.
-    C_ISGID = 0c002000 ## Set group ID.
-    C_ISVTX = 0c001000 ## On directories, restricted deletion flag.
-    C_ISDIR = 0c040000 ## Directory.
-    C_ISFIFO = 0c010000 ##FIFO.
-    C_ISREG = 0c100000 ## Regular file.
-    C_ISBLK = 0c060000 ## Block special.
-    C_ISCHR = 0c020000 ## Character special.
-    C_ISCTG = 0c110000 ## Reserved.
-    C_ISLNK = 0c120000 ## Symbolic link.</p>
-    C_ISSOCK = 0c140000 ## Socket.
+    C_IRUSR = 0o000400 ## Read by owner.
+    C_IWUSR = 0o000200 ## Write by owner.
+    C_IXUSR = 0o000100 ## Execute by owner.
+    C_IRGRP = 0o000040 ## Read by group.
+    C_IWGRP = 0o000020 ## Write by group.
+    C_IXGRP = 0o000010 ## Execute by group.
+    C_IROTH = 0o000004 ## Read by others.
+    C_IWOTH = 0o000002 ## Write by others.
+    C_IXOTH = 0o000001 ## Execute by others.
+    C_ISUID = 0o004000 ## Set user ID.
+    C_ISGID = 0o002000 ## Set group ID.
+    C_ISVTX = 0o001000 ## On directories, restricted deletion flag.
+    C_ISDIR = 0o040000 ## Directory.
+    C_ISFIFO = 0o010000 ##FIFO.
+    C_ISREG = 0o100000 ## Regular file.
+    C_ISBLK = 0o060000 ## Block special.
+    C_ISCHR = 0o020000 ## Character special.
+    C_ISCTG = 0o110000 ## Reserved.
+    C_ISLNK = 0o120000 ## Symbolic link.</p>
+    C_ISSOCK = 0o140000 ## Socket.
 
 const
   MM_NULLLBL* = nil
diff --git a/lib/pure/asyncftpclient.nim b/lib/pure/asyncftpclient.nim
index 019a18f55..3d6a9a015 100644
--- a/lib/pure/asyncftpclient.nim
+++ b/lib/pure/asyncftpclient.nim
@@ -304,6 +304,7 @@ proc retrFile*(ftp: AsyncFtpClient, file, dest: string,
     raise newException(ReplyError, "Reply has no file size.")
 
   await getFile(ftp, destFile, fileSize, onProgressChanged)
+  destFile.close()
 
 proc doUpload(ftp: AsyncFtpClient, file: File,
               onProgressChanged: ProgressChangedProc) {.async.} =
diff --git a/lib/pure/ospaths.nim b/lib/pure/ospaths.nim
index 905a65925..96996bba7 100644
--- a/lib/pure/ospaths.nim
+++ b/lib/pure/ospaths.nim
@@ -449,6 +449,9 @@ proc unixToNativePath*(path: string, drive=""): string {.
   when defined(unix):
     result = path
   else:
+    if path.len == 0:
+        return ""
+
     var start: int
     if path[0] == '/':
       # an absolute path
@@ -462,10 +465,10 @@ proc unixToNativePath*(path: string, drive=""): string {.
       else:
         result = $DirSep
       start = 1
-    elif path[0] == '.' and path[1] == '/':
+    elif path[0] == '.' and (path.len == 1 or path[1] == '/'):
       # current directory
       result = $CurDir
-      start = 2
+      start = when doslikeFileSystem: 1 else: 2
     else:
       result = ""
       start = 0
diff --git a/lib/pure/typetraits.nim b/lib/pure/typetraits.nim
index 2047abda4..e9579e824 100644
--- a/lib/pure/typetraits.nim
+++ b/lib/pure/typetraits.nim
@@ -59,9 +59,4 @@ proc supportsCopyMem*(t: typedesc): bool {.magic: "TypeTrait".}
 
 
 when isMainModule:
-  # echo type(42)
-  import streams
-  var ss = newStringStream()
-  ss.write($type(42)) # needs `$`
-  ss.setPosition(0)
-  doAssert ss.readAll() == "int"
+  doAssert $type(42) == "int"
diff --git a/tests/errmsgs/t6281.nim b/tests/errmsgs/t6281.nim
new file mode 100644
index 000000000..59fda5077
--- /dev/null
+++ b/tests/errmsgs/t6281.nim
@@ -0,0 +1,9 @@
+discard """
+errormsg: "invalid type: 'SomeNumber' in this context: 'seq[SomeNumber]' for var"
+line: 6
+"""
+
+var seqwat: seq[SomeNumber] = @[]
+
+proc foo(x: SomeNumber) =
+  seqwat.add(x)
\ No newline at end of file
diff --git a/tests/lexer/tintegerliterals.nim b/tests/lexer/tintegerliterals.nim
new file mode 100644
index 000000000..7420db144
--- /dev/null
+++ b/tests/lexer/tintegerliterals.nim
@@ -0,0 +1,9 @@
+# test the valid literals
+assert 0b10 == 2
+assert 0B10 == 2
+assert 0x10 == 16
+assert 0X10 == 16
+assert 0o10 == 8
+# the following is deprecated:
+assert 0c10 == 8
+assert 0C10 == 8
diff --git a/tests/lexer/tinvalidintegerliteral3.nim b/tests/lexer/tinvalidintegerliteral3.nim
new file mode 100644
index 000000000..9c2fe69df
--- /dev/null
+++ b/tests/lexer/tinvalidintegerliteral3.nim
@@ -0,0 +1,7 @@
+discard """
+  file: "tinvalidintegerliteral3.nim"
+  line: 7
+  errormsg: "0O5 is an invalid int literal; For octal literals use the '0o' prefix."
+"""
+
+echo 0O5
diff --git a/tests/misc/tunsignedmisc.nim b/tests/misc/tunsignedmisc.nim
index fc02eee19..b2a3849cf 100644
--- a/tests/misc/tunsignedmisc.nim
+++ b/tests/misc/tunsignedmisc.nim
@@ -9,7 +9,7 @@ discard """
 # 8 bit
 let ref1 = 128'u8 shr 7
 let hex1 = 0x80'u8 shr 7
-let oct1 = 0c200'u8 shr 7
+let oct1 = 0o200'u8 shr 7
 let dig1 = 0b10000000'u8 shr 7
 
 doAssert(ref1 == 1)
@@ -20,7 +20,7 @@ doAssert(ref1 == dig1)
 # 16 bit
 let ref2 = 32768'u16 shr 15
 let hex2 = 0x8000'u16 shr 15
-let oct2 = 0c100000'u16 shr 15
+let oct2 = 0o100000'u16 shr 15
 let dig2 = 0b1000000000000000'u16 shr 15
 
 doAssert(ref2 == 1)
@@ -31,7 +31,7 @@ doAssert(ref2 == dig2)
 # 32 bit
 let ref3 = 2147483648'u32 shr 31
 let hex3 = 0x80000000'u32 shr 31
-let oct3 = 0c20000000000'u32 shr 31
+let oct3 = 0o20000000000'u32 shr 31
 let dig3 = 0b10000000000000000000000000000000'u32 shr 31
 
 doAssert(ref3 == 1)
diff --git a/tests/statictypes/tstatictypes.nim b/tests/statictypes/tstatictypes.nim
index 789bd7588..2a3b7332d 100644
--- a/tests/statictypes/tstatictypes.nim
+++ b/tests/statictypes/tstatictypes.nim
@@ -107,3 +107,12 @@ when true:
     assert aw2.data.high == 6
     assert aw3.data.high == 9
 
+# #6077
+block:
+  type
+    Backend = enum
+      Cpu
+
+    Tensor[B: static[Backend]; T] = object
+
+    BackProp[B: static[Backend],T] = proc (gradient: Tensor[B,T]): Tensor[B,T]
diff --git a/tests/stdlib/tospaths.nim b/tests/stdlib/tospaths.nim
new file mode 100644
index 000000000..0ac7729d9
--- /dev/null
+++ b/tests/stdlib/tospaths.nim
@@ -0,0 +1,41 @@
+discard """

+  file: "tospaths.nim"

+  output: ""

+"""

+# test the ospaths module

+

+import os

+

+doAssert unixToNativePath("") == ""

+doAssert unixToNativePath(".") == $CurDir

+doAssert unixToNativePath("..") == $ParDir

+doAssert isAbsolute(unixToNativePath("/"))

+doAssert isAbsolute(unixToNativePath("/", "a"))

+doAssert isAbsolute(unixToNativePath("/a"))

+doAssert isAbsolute(unixToNativePath("/a", "a"))

+doAssert isAbsolute(unixToNativePath("/a/b"))

+doAssert isAbsolute(unixToNativePath("/a/b", "a"))

+doAssert unixToNativePath("a/b") == joinPath("a", "b")

+

+when defined(macos):

+    doAssert unixToNativePath("./") == ":"

+    doAssert unixToNativePath("./abc") == ":abc"

+    doAssert unixToNativePath("../abc") == "::abc"

+    doAssert unixToNativePath("../../abc") == ":::abc"

+    doAssert unixToNativePath("/abc", "a") == "abc"

+    doAssert unixToNativePath("/abc/def", "a") == "abc:def"

+elif doslikeFileSystem:

+    doAssert unixToNativePath("./") == ".\\"

+    doAssert unixToNativePath("./abc") == ".\\abc"

+    doAssert unixToNativePath("../abc") == "..\\abc"

+    doAssert unixToNativePath("../../abc") == "..\\..\\abc"

+    doAssert unixToNativePath("/abc", "a") == "a:\\abc"

+    doAssert unixToNativePath("/abc/def", "a") == "a:\\abc\\def"

+else:

+    #Tests for unix

+    doAssert unixToNativePath("./") == "./"

+    doAssert unixToNativePath("./abc") == "./abc"

+    doAssert unixToNativePath("../abc") == "../abc"

+    doAssert unixToNativePath("../../abc") == "../../abc"

+    doAssert unixToNativePath("/abc", "a") == "/abc"

+    doAssert unixToNativePath("/abc/def", "a") == "/abc/def"

diff --git a/tests/typerel/t8172.nim b/tests/typerel/t8172.nim
new file mode 100644
index 000000000..8e0b32932
--- /dev/null
+++ b/tests/typerel/t8172.nim
@@ -0,0 +1,11 @@
+discard """
+  line: 11
+  errormsg: "cannot convert array[0..0, string] to varargs[string]"
+"""
+
+proc f(v: varargs[string]) =
+  echo(v)
+
+f("b", "c")   # Works
+f(["b", "c"]) # Works
+f("b", ["c"]) # Fails