mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-21 03:50:43 +00:00
Turn some of the errors back into warnings
This commit is contained in:
committed by
Andreas Rumpf
parent
ce9a4ed124
commit
be95f8fdfa
@@ -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",
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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:
|
||||
#
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user