summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/lineinfos.nim6
-rw-r--r--compiler/semexprs.nim14
-rw-r--r--compiler/semmagic.nim17
-rw-r--r--compiler/semobjconstr.nim5
-rw-r--r--compiler/sempass2.nim6
-rw-r--r--tests/constructors/tinvalid_construction.nim46
-rw-r--r--tests/objects/tobjects_issues.nim2
7 files changed, 63 insertions, 33 deletions
diff --git a/compiler/lineinfos.nim b/compiler/lineinfos.nim
index 585a95c80..658863676 100644
--- a/compiler/lineinfos.nim
+++ b/compiler/lineinfos.nim
@@ -37,6 +37,8 @@ type
     warnUnusedImportX,
     warnInheritFromException,
     warnEachIdentIsTuple,
+    warnUnsafeSetLen,
+    warnUnsafeDefault,
     warnProveInit, warnProveField, warnProveIndex,
     warnStaticIndexCheck, warnGcUnsafe, warnGcUnsafe2,
     warnUninit, warnGcMem, warnDestructor, warnLockLevel, warnResultShadowed,
@@ -87,6 +89,9 @@ const
     warnUnusedImportX: "imported and not used: '$1'",
     warnInheritFromException: "inherit from a more precise exception type like ValueError, IOError or OSError",
     warnEachIdentIsTuple: "each identifier is a tuple",
+    warnUnsafeSetLen: "setLen can potentially expand the sequence, " &
+                      "but the element type '$1' doesn't have a valid default value",
+    warnUnsafeDefault: "The '$1' type doesn't have a valid default value",
     warnProveInit: "Cannot prove that '$1' is initialized. This will become a compile time error in the future.",
     warnProveField: "cannot prove that field '$1' is accessible",
     warnProveIndex: "cannot prove index '$1' is valid",
@@ -146,6 +151,7 @@ const
     "TypelessParam", "UseBase", "WriteToForeignHeap",
     "UnsafeCode", "UnusedImport", "InheritFromException",
     "EachIdentIsTuple",
+    "UnsafeSetLen", "UnsafeDefault",
     "ProveInit", "ProveField", "ProveIndex",
     "IndexCheck", "GcUnsafe", "GcUnsafe2", "Uninit",
     "GcMem", "Destructor", "LockLevel", "ResultShadowed",
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 56de00d56..5f82eb1e7 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -2267,20 +2267,6 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
   of mSizeOf:
     markUsed(c, n.info, s)
     result = semSizeof(c, setMs(n, s))
-  of mSetLengthSeq:
-    result = semDirectOp(c, n, flags)
-    let seqType = result[1].typ.skipTypes({tyPtr, tyRef, # in case we had auto-dereferencing
-                                           tyVar, tyGenericInst, tyOwned, tySink,
-                                           tyAlias, tyUserTypeClassInst})
-    if seqType.kind == tySequence and seqType.base.requiresInit:
-      localError(c.config, n.info, "setLen can potentially expand the sequence, " &
-                                   "but the element type $1 doesn't have a default value.",
-                                   [typeToString(seqType.base)])
-  of mDefault:
-    result = semDirectOp(c, n, flags)
-    c.config.internalAssert result[1].typ.kind == tyTypeDesc
-    if result[1].typ.base.requiresInit:
-      localError(c.config, n.info, "not nil types don't have a default value")
   else:
     result = semDirectOp(c, n, flags)
 
diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim
index 8c07d7d18..783846650 100644
--- a/compiler/semmagic.nim
+++ b/compiler/semmagic.nim
@@ -530,4 +530,19 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
     result = semQuantifier(c, n)
   of mOld:
     result = semOld(c, n)
-  else: result = n
+  of mSetLengthSeq:
+    result = n
+    let seqType = result[1].typ.skipTypes({tyPtr, tyRef, # in case we had auto-dereferencing
+                                           tyVar, tyGenericInst, tyOwned, tySink,
+                                           tyAlias, tyUserTypeClassInst})
+    if seqType.kind == tySequence and seqType.base.requiresInit:
+      message(c.config, n.info, warnUnsafeSetLen, typeToString(seqType.base))
+  of mDefault:
+    result = n
+    c.config.internalAssert result[1].typ.kind == tyTypeDesc
+    let constructed = result[1].typ.base
+    if constructed.requiresInit:
+      message(c.config, n.info, warnUnsafeDefault, typeToString(constructed))
+  else:
+    result = n
+
diff --git a/compiler/semobjconstr.nim b/compiler/semobjconstr.nim
index eb0589601..eeec42900 100644
--- a/compiler/semobjconstr.nim
+++ b/compiler/semobjconstr.nim
@@ -336,6 +336,11 @@ proc semConstructTypeAux(c: PContext,
     let base = t[0]
     if base == nil: break
     t = skipTypes(base, skipPtrs)
+    if t.kind == tyGenericParam:
+      # XXX: This is not supposed to happen, but apparently
+      # there are some issues in semtypinst. Luckily, it
+      # seems to affect only `computeRequiresInit`.
+      return
     constrCtx.needsFullInit = constrCtx.needsFullInit or
                               tfNeedsFullInit in t.flags
 
diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim
index 79d969fbb..a4e1dcf00 100644
--- a/compiler/sempass2.nim
+++ b/compiler/sempass2.nim
@@ -254,7 +254,7 @@ proc useVar(a: PEffects, n: PNode) =
       a.init.add s.id
     elif s.id notin a.init:
       if s.typ.requiresInit:
-        localError(a.config, n.info, errProveInit, s.name.s)
+        message(a.config, n.info, warnProveInit, s.name.s)
       else:
         message(a.config, n.info, warnUninit, s.name.s)
       # prevent superfluous warnings about the same variable:
@@ -844,7 +844,7 @@ proc track(tracked: PEffects, n: PNode) =
           # var s: seq[notnil];  newSeq(s, 0)  is a special case!
           discard
         else:
-          localError(tracked.config, arg.info, errProveInit, $arg)
+          message(tracked.config, arg.info, warnProveInit, $arg)
 
       # check required for 'nim check':
       if n[1].typ.len > 0:
@@ -1209,7 +1209,7 @@ proc trackProc*(c: PContext; s: PSym, body: PNode) =
      s.kind in {skProc, skFunc, skConverter, skMethod}:
     var res = s.ast[resultPos].sym # get result symbol
     if res.id notin t.init:
-      localError(g.config, body.info, errProveInit, "result")
+      message(g.config, body.info, warnProveInit, "result")
   let p = s.ast[pragmasPos]
   let raisesSpec = effectSpec(p, wRaises)
   if not isNil(raisesSpec):
diff --git a/tests/constructors/tinvalid_construction.nim b/tests/constructors/tinvalid_construction.nim
index e98b530bb..4b372d68a 100644
--- a/tests/constructors/tinvalid_construction.nim
+++ b/tests/constructors/tinvalid_construction.nim
@@ -113,18 +113,18 @@ reject THasNotNils(a: notNilRef, b: nilRef, c: nilRef)      # `b` shouldn't be n
 reject THasNotNils(b: notNilRef, c: notNilRef)              # there is a missing not nil field
 reject THasNotNils()                                        # again, missing fields
 accept THasNotNils(a: notNilRef, b: notNilRef)              # it's OK to omit a non-mandatory field
-reject default(THasNotNils)
-reject userDefinedDefault(THasNotNils)
+# produces only warning: reject default(THasNotNils)
+# produces only warning: reject userDefinedDefault(THasNotNils)
 
-reject default(TRefObjNotNil)
-reject userDefinedDefault(TRefObjNotNil)
-reject genericDefault(TRefObjNotNil)
+# produces only warning: reject default(TRefObjNotNil)
+# produces only warning: reject userDefinedDefault(TRefObjNotNil)
+# produces only warning: reject genericDefault(TRefObjNotNil)
 
 # missing not nils in base
 reject TBaseHasNotNils()
-reject default(TBaseHasNotNils)
-reject userDefinedDefault(TBaseHasNotNils)
-reject genericDefault(TBaseHasNotNils)
+# produces only warning: reject default(TBaseHasNotNils)
+# produces only warning: reject userDefinedDefault(TBaseHasNotNils)
+# produces only warning: reject genericDefault(TBaseHasNotNils)
 
 # once you take care of them, it's ok
 accept TBaseHasNotNils(a: notNilRef, b: notNilRef, choice: D)
@@ -163,8 +163,8 @@ accept((ref PartialRequiresInit)(a: 20))
 reject((ref PartialRequiresInit)(b: "x"))
 reject((ref PartialRequiresInit)())
 
-reject default(PartialRequiresInit)
-reject userDefinedDefault(PartialRequiresInit)
+# produces only warning: reject default(PartialRequiresInit)
+# produces only warning: reject userDefinedDefault(PartialRequiresInit)
 reject:
   var obj: PartialRequiresInit
 
@@ -181,8 +181,8 @@ reject((ref FullRequiresInit)(a: 10))
 reject((ref FullRequiresInit)(b: 20))
 reject((ref FullRequiresInit)())
 
-reject default(FullRequiresInit)
-reject userDefinedDefault(FullRequiresInit)
+# produces only warning: reject default(FullRequiresInit)
+# produces only warning: reject userDefinedDefault(FullRequiresInit)
 reject:
   var obj: FullRequiresInit
 
@@ -192,8 +192,8 @@ reject FullRequiresInitWithParent(a: notNilRef, b: nil, c: nil, e: 10, d: 20) #
 reject FullRequiresInitWithParent(a: notNilRef, b: notNilRef, e: 10, d: 20)   # c should not be missing
 reject FullRequiresInitWithParent(a: notNilRef, b: notNilRef, c: nil, e: 10)  # d should not be missing
 reject FullRequiresInitWithParent()
-reject default(FullRequiresInitWithParent)
-reject userDefinedDefault(FullRequiresInitWithParent)
+# produces only warning: reject default(FullRequiresInitWithParent)
+# produces only warning: reject userDefinedDefault(FullRequiresInitWithParent)
 reject:
   var obj: FullRequiresInitWithParent
 
@@ -203,28 +203,36 @@ accept default(TNestedChoices)
 accept:
   var obj: TNestedChoices
 
+#[# produces only warning:
 reject:
   # This proc is illegal, because it tries to produce
   # a default object of a type that requires initialization:
   proc defaultHasNotNils: THasNotNils =
     discard
+#]#
 
+#[# produces only warning:
 reject:
   # You cannot cheat by using the result variable to specify
   # only some of the fields
   proc invalidPartialTHasNotNils: THasNotNils =
     result.c = nilRef
+#]#
 
+#[# produces only warning:
 reject:
   # The same applies for requiresInit types
   proc invalidPartialRequiersInit: PartialRequiresInit =
     result.b = "x"
+#]#
 
+#[# produces only warning:
 # All code paths must return a value when the result requires initialization:
 reject:
   proc ifWithoutAnElse: THasNotNils =
     if stdin.readLine == "":
       return THasNotNils(a: notNilRef, b: notNilRef, c: nilRef)
+#]#
 
 accept:
   # All code paths must return a value when the result requires initialization:
@@ -234,6 +242,7 @@ accept:
     else:
       return THasNotNIls(a: notNilRef, b: notNilRef)
 
+#[# produces only warning:
 reject:
   proc caseWithoutAllCasesCovered: FullRequiresInit =
     # Please note that these is no else branch here:
@@ -242,6 +251,7 @@ reject:
       return FullRequiresInit(a: 10, b: 20)
     of "y":
       return FullRequiresInit(a: 30, b: 40)
+#]#
 
 accept:
   proc wellFormedCase: FullRequiresInit =
@@ -276,18 +286,24 @@ block:
   var one = legalSeq[0]
   var twoAgain = legalSeq.pop
 
+  #[# produces only warning:
   # It's not possible to tell the sequence to create elements
   # for us though:
   reject:
     var illegalSeq = newSeq[IllegalToConstruct](10)
+  #]#
 
+  #[# produces only warning:
   reject:
     var illegalSeq: seq[IllegalToConstruct]
     newSeq(illegalSeq, 10)
+  #]#
 
+  #[# produces only warning:
   reject:
     var illegalSeq: seq[IllegalToConstruct]
     illegalSeq.setLen 10
+  #]#
 
   # You can still use newSeqOfCap to write efficient code:
   var anotherLegalSequence = newSeqOfCap[IllegalToConstruct](10)
@@ -363,8 +379,10 @@ block:
   reject:
     var x: IllegalPair
 
+  #[# produces only warning:
   reject:
     var s = newSeq[IllegalPair](10)
+  #]#
 
 # Specific issues:
 #
diff --git a/tests/objects/tobjects_issues.nim b/tests/objects/tobjects_issues.nim
index fddfff7d5..f1a416d04 100644
--- a/tests/objects/tobjects_issues.nim
+++ b/tests/objects/tobjects_issues.nim
@@ -113,5 +113,5 @@ block t3038:
     Type = ref object of RootObj
     SubType[T] = ref object of Type
       data: Data[T]
-    SubSubType = ref object of SubType
+    SubSubType = ref object of SubType[int]
     SubSubSubType = ref object of SubSubType