Turn some of the errors back into warnings

This commit is contained in:
Zahary Karadjov 2020-04-01 03:33:32 +03:00 • committed by Andreas Rumpf
commit be95f8fdfa
7 changed files with 63 additions and 33 deletions

View file

@ -37,6 +37,8 @@ type
warnUnusedImportX, warnUnusedImportX,
warnInheritFromException, warnInheritFromException,
warnEachIdentIsTuple, warnEachIdentIsTuple,
warnUnsafeSetLen,
warnUnsafeDefault,
warnProveInit, warnProveField, warnProveIndex, warnProveInit, warnProveField, warnProveIndex,
warnStaticIndexCheck, warnGcUnsafe, warnGcUnsafe2, warnStaticIndexCheck, warnGcUnsafe, warnGcUnsafe2,
warnUninit, warnGcMem, warnDestructor, warnLockLevel, warnResultShadowed, warnUninit, warnGcMem, warnDestructor, warnLockLevel, warnResultShadowed,
@ -87,6 +89,9 @@ const
warnUnusedImportX: "imported and not used: '$1'", warnUnusedImportX: "imported and not used: '$1'",
warnInheritFromException: "inherit from a more precise exception type like ValueError, IOError or OSError", warnInheritFromException: "inherit from a more precise exception type like ValueError, IOError or OSError",
warnEachIdentIsTuple: "each identifier is a tuple", 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.", 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", warnProveField: "cannot prove that field '$1' is accessible",
warnProveIndex: "cannot prove index '$1' is valid", warnProveIndex: "cannot prove index '$1' is valid",
@ -146,6 +151,7 @@ const
"TypelessParam", "UseBase", "WriteToForeignHeap", "TypelessParam", "UseBase", "WriteToForeignHeap",
"UnsafeCode", "UnusedImport", "InheritFromException", "UnsafeCode", "UnusedImport", "InheritFromException",
"EachIdentIsTuple", "EachIdentIsTuple",
"UnsafeSetLen", "UnsafeDefault",
"ProveInit", "ProveField", "ProveIndex", "ProveInit", "ProveField", "ProveIndex",
"IndexCheck", "GcUnsafe", "GcUnsafe2", "Uninit", "IndexCheck", "GcUnsafe", "GcUnsafe2", "Uninit",
"GcMem", "Destructor", "LockLevel", "ResultShadowed", "GcMem", "Destructor", "LockLevel", "ResultShadowed",

View file

@ -2267,20 +2267,6 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
of mSizeOf: of mSizeOf:
markUsed(c, n.info, s) markUsed(c, n.info, s)
result = semSizeof(c, setMs(n, 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: else:
result = semDirectOp(c, n, flags) result = semDirectOp(c, n, flags)

View file

@ -530,4 +530,19 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
result = semQuantifier(c, n) result = semQuantifier(c, n)
of mOld: of mOld:
result = semOld(c, n) 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

View file

@ -336,6 +336,11 @@ proc semConstructTypeAux(c: PContext,
let base = t[0] let base = t[0]
if base == nil: break if base == nil: break
t = skipTypes(base, skipPtrs) 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 constrCtx.needsFullInit = constrCtx.needsFullInit or
tfNeedsFullInit in t.flags tfNeedsFullInit in t.flags

View file

@ -254,7 +254,7 @@ proc useVar(a: PEffects, n: PNode) =
a.init.add s.id a.init.add s.id
elif s.id notin a.init: elif s.id notin a.init:
if s.typ.requiresInit: if s.typ.requiresInit:
localError(a.config, n.info, errProveInit, s.name.s) message(a.config, n.info, warnProveInit, s.name.s)
else: else:
message(a.config, n.info, warnUninit, s.name.s) message(a.config, n.info, warnUninit, s.name.s)
# prevent superfluous warnings about the same variable: # 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! # var s: seq[notnil]; newSeq(s, 0) is a special case!
discard discard
else: else:
localError(tracked.config, arg.info, errProveInit, $arg) message(tracked.config, arg.info, warnProveInit, $arg)
# check required for 'nim check': # check required for 'nim check':
if n[1].typ.len > 0: 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}: s.kind in {skProc, skFunc, skConverter, skMethod}:
var res = s.ast[resultPos].sym # get result symbol var res = s.ast[resultPos].sym # get result symbol
if res.id notin t.init: 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 p = s.ast[pragmasPos]
let raisesSpec = effectSpec(p, wRaises) let raisesSpec = effectSpec(p, wRaises)
if not isNil(raisesSpec): if not isNil(raisesSpec):

View file

@ -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(b: notNilRef, c: notNilRef) # there is a missing not nil field
reject THasNotNils() # again, missing fields reject THasNotNils() # again, missing fields
accept THasNotNils(a: notNilRef, b: notNilRef) # it's OK to omit a non-mandatory field accept THasNotNils(a: notNilRef, b: notNilRef) # it's OK to omit a non-mandatory field
reject default(THasNotNils) # produces only warning: reject default(THasNotNils)
reject userDefinedDefault(THasNotNils) # produces only warning: reject userDefinedDefault(THasNotNils)
reject default(TRefObjNotNil) # produces only warning: reject default(TRefObjNotNil)
reject userDefinedDefault(TRefObjNotNil) # produces only warning: reject userDefinedDefault(TRefObjNotNil)
reject genericDefault(TRefObjNotNil) # produces only warning: reject genericDefault(TRefObjNotNil)
# missing not nils in base # missing not nils in base
reject TBaseHasNotNils() reject TBaseHasNotNils()
reject default(TBaseHasNotNils) # produces only warning: reject default(TBaseHasNotNils)
reject userDefinedDefault(TBaseHasNotNils) # produces only warning: reject userDefinedDefault(TBaseHasNotNils)
reject genericDefault(TBaseHasNotNils) # produces only warning: reject genericDefault(TBaseHasNotNils)
# once you take care of them, it's ok # once you take care of them, it's ok
accept TBaseHasNotNils(a: notNilRef, b: notNilRef, choice: D) 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)(b: "x"))
reject((ref PartialRequiresInit)()) reject((ref PartialRequiresInit)())
reject default(PartialRequiresInit) # produces only warning: reject default(PartialRequiresInit)
reject userDefinedDefault(PartialRequiresInit) # produces only warning: reject userDefinedDefault(PartialRequiresInit)
reject: reject:
var obj: PartialRequiresInit var obj: PartialRequiresInit
@ -181,8 +181,8 @@ reject((ref FullRequiresInit)(a: 10))
reject((ref FullRequiresInit)(b: 20)) reject((ref FullRequiresInit)(b: 20))
reject((ref FullRequiresInit)()) reject((ref FullRequiresInit)())
reject default(FullRequiresInit) # produces only warning: reject default(FullRequiresInit)
reject userDefinedDefault(FullRequiresInit) # produces only warning: reject userDefinedDefault(FullRequiresInit)
reject: reject:
var obj: FullRequiresInit 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, 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(a: notNilRef, b: notNilRef, c: nil, e: 10) # d should not be missing
reject FullRequiresInitWithParent() reject FullRequiresInitWithParent()
reject default(FullRequiresInitWithParent) # produces only warning: reject default(FullRequiresInitWithParent)
reject userDefinedDefault(FullRequiresInitWithParent) # produces only warning: reject userDefinedDefault(FullRequiresInitWithParent)
reject: reject:
var obj: FullRequiresInitWithParent var obj: FullRequiresInitWithParent
@ -203,28 +203,36 @@ accept default(TNestedChoices)
accept: accept:
var obj: TNestedChoices var obj: TNestedChoices
#[# produces only warning:
reject: reject:
# This proc is illegal, because it tries to produce # This proc is illegal, because it tries to produce
# a default object of a type that requires initialization: # a default object of a type that requires initialization:
proc defaultHasNotNils: THasNotNils = proc defaultHasNotNils: THasNotNils =
discard discard
#]#
#[# produces only warning:
reject: reject:
# You cannot cheat by using the result variable to specify # You cannot cheat by using the result variable to specify
# only some of the fields # only some of the fields
proc invalidPartialTHasNotNils: THasNotNils = proc invalidPartialTHasNotNils: THasNotNils =
result.c = nilRef result.c = nilRef
#]#
#[# produces only warning:
reject: reject:
# The same applies for requiresInit types # The same applies for requiresInit types
proc invalidPartialRequiersInit: PartialRequiresInit = proc invalidPartialRequiersInit: PartialRequiresInit =
result.b = "x" result.b = "x"
#]#
#[# produces only warning:
# All code paths must return a value when the result requires initialization: # All code paths must return a value when the result requires initialization:
reject: reject:
proc ifWithoutAnElse: THasNotNils = proc ifWithoutAnElse: THasNotNils =
if stdin.readLine == "": if stdin.readLine == "":
return THasNotNils(a: notNilRef, b: notNilRef, c: nilRef) return THasNotNils(a: notNilRef, b: notNilRef, c: nilRef)
#]#
accept: accept:
# All code paths must return a value when the result requires initialization: # All code paths must return a value when the result requires initialization:
@ -234,6 +242,7 @@ accept:
else: else:
return THasNotNIls(a: notNilRef, b: notNilRef) return THasNotNIls(a: notNilRef, b: notNilRef)
#[# produces only warning:
reject: reject:
proc caseWithoutAllCasesCovered: FullRequiresInit = proc caseWithoutAllCasesCovered: FullRequiresInit =
# Please note that these is no else branch here: # Please note that these is no else branch here:
@ -242,6 +251,7 @@ reject:
return FullRequiresInit(a: 10, b: 20) return FullRequiresInit(a: 10, b: 20)
of "y": of "y":
return FullRequiresInit(a: 30, b: 40) return FullRequiresInit(a: 30, b: 40)
#]#
accept: accept:
proc wellFormedCase: FullRequiresInit = proc wellFormedCase: FullRequiresInit =
@ -276,18 +286,24 @@ block:
var one = legalSeq[0] var one = legalSeq[0]
var twoAgain = legalSeq.pop var twoAgain = legalSeq.pop
#[# produces only warning:
# It's not possible to tell the sequence to create elements # It's not possible to tell the sequence to create elements
# for us though: # for us though:
reject: reject:
var illegalSeq = newSeq[IllegalToConstruct](10) var illegalSeq = newSeq[IllegalToConstruct](10)
#]#
#[# produces only warning:
reject: reject:
var illegalSeq: seq[IllegalToConstruct] var illegalSeq: seq[IllegalToConstruct]
newSeq(illegalSeq, 10) newSeq(illegalSeq, 10)
#]#
#[# produces only warning:
reject: reject:
var illegalSeq: seq[IllegalToConstruct] var illegalSeq: seq[IllegalToConstruct]
illegalSeq.setLen 10 illegalSeq.setLen 10
#]#
# You can still use newSeqOfCap to write efficient code: # You can still use newSeqOfCap to write efficient code:
var anotherLegalSequence = newSeqOfCap[IllegalToConstruct](10) var anotherLegalSequence = newSeqOfCap[IllegalToConstruct](10)
@ -363,8 +379,10 @@ block:
reject: reject:
var x: IllegalPair var x: IllegalPair
#[# produces only warning:
reject: reject:
var s = newSeq[IllegalPair](10) var s = newSeq[IllegalPair](10)
#]#
# Specific issues: # Specific issues:
# #

View file

@ -113,5 +113,5 @@ block t3038:
Type = ref object of RootObj Type = ref object of RootObj
SubType[T] = ref object of Type SubType[T] = ref object of Type
data: Data[T] data: Data[T]
SubSubType = ref object of SubType SubSubType = ref object of SubType[int]
SubSubSubType = ref object of SubSubType SubSubSubType = ref object of SubSubType