Replace tfHasRequiresInit with a more accurate mechanism

The new mechanism can deal with more complex scenarios such as
not nil field appearing in a non-default case object branch or
a field within a generic object that may depend on a when branch.

The commit also plugs another hole: the user is no longer able
to create illegal default values through seq.setLen(N).
This commit is contained in:
Zahary Karadjov 2020-03-30 18:56:03 +03:00 • committed by Andreas Rumpf
commit ce9a4ed124
11 changed files with 179 additions and 43 deletions

View file

@ -2267,13 +2267,19 @@ 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
let typ = result[1].typ.base
if typ.kind == tyObject:
checkDefaultConstruction(c, typ, n.info)
elif typ.kind in {tyRef, tyPtr} and tfNotNil in typ.flags:
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)