diff --git a/compiler/ast.nim b/compiler/ast.nim index 4d45f0e55..a4630732b 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -517,8 +517,10 @@ type tfPartial, # type is declared as 'partial' tfNotNil, # type cannot be 'nil' - tfNeedsInit, # type constains a "not nil" constraint somewhere or some - # other type so that it requires initialization + tfHasRequiresInit,# type constains a "not nil" constraint somewhere or + # a `requiresInit` field, so the default zero init + # is not appropriate + tfRequiresInit, # all fields of the type must be initialized tfVarIsPtr, # 'var' type is translated like 'ptr' even in C++ mode tfHasMeta, # type contains "wildcard" sub-types such as generic params # or other type classes @@ -1484,11 +1486,11 @@ proc propagateToOwner*(owner, elem: PType; propagateHasAsgn = true) = if owner.kind in {tyGenericInst, tyGenericBody, tyGenericInvocation}: owner.flags.incl tfNotNil elif owner.kind notin HaveTheirOwnEmpty: - owner.flags.incl tfNeedsInit + owner.flags.incl tfHasRequiresInit - if tfNeedsInit in elem.flags: + if tfRequiresInit in elem.flags: if owner.kind in HaveTheirOwnEmpty: discard - else: owner.flags.incl tfNeedsInit + else: owner.flags.incl tfHasRequiresInit if elem.isMetaType: owner.flags.incl tfHasMeta diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 6056afb6c..e4b72bed7 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -1088,7 +1088,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int, of wRequiresInit: noVal(c, it) if sym.typ == nil: invalidPragma(c, it) - else: incl(sym.typ.flags, tfNeedsInit) + else: incl(sym.typ.flags, tfRequiresInit) of wByRef: noVal(c, it) if sym == nil or sym.typ == nil: diff --git a/compiler/semobjconstr.nim b/compiler/semobjconstr.nim index 489bc6684..bc1e85425 100644 --- a/compiler/semobjconstr.nim +++ b/compiler/semobjconstr.nim @@ -138,7 +138,7 @@ proc fieldsPresentInInitExpr(c: PContext, fieldsRecList, initExpr: PNode): strin proc missingMandatoryFields(c: PContext, fieldsRecList, initExpr: PNode): string = for r in directFieldsInRecList(fieldsRecList): - if {tfNotNil, tfNeedsInit} * r.sym.typ.flags != {}: + if {tfNotNil, tfRequiresInit} * r.sym.typ.flags != {}: let assignment = locateFieldInInitExpr(c, r.sym, initExpr) if assignment == nil: if result.len == 0: @@ -358,15 +358,10 @@ proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode = # It's possible that the object was not fully initialized while # specifying a .requiresInit. pragma. - # XXX: Turn this into an error in the next release - if tfNeedsInit in t.flags and initResult != initFull: - # XXX: Disable this warning for now, because tfNeedsInit is propagated - # too aggressively from fields to object types (and this is not correct - # in case objects) - when false: message(n.info, warnUser, + if tfRequiresInit in t.flags and initResult != initFull: + localError(c.config, n.info, "object type uses the 'requiresInit' pragma, but not all fields " & - "have been initialized. future versions of Nim will treat this as " & - "an error") + "have been initialized.") # Since we were traversing the object fields, it's possible that # not all of the fields specified in the constructor was visited. diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index 4658f5454..65dce3ed8 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -184,7 +184,7 @@ proc initVar(a: PEffects, n: PNode; volatileCheck: bool) = proc initVarViaNew(a: PEffects, n: PNode) = if n.kind != nkSym: return let s = n.sym - if {tfNeedsInit, tfNotNil} * s.typ.flags <= {tfNotNil}: + if {tfRequiresInit, tfNotNil} * s.typ.flags <= {tfNotNil}: # 'x' is not nil, but that doesn't mean its "not nil" children # are initialized: initVar(a, n, volatileCheck=true) @@ -253,7 +253,7 @@ proc useVar(a: PEffects, n: PNode) = # If the variable is explicitly marked as .noinit. do not emit any error a.init.add s.id elif s.id notin a.init: - if {tfNeedsInit, tfNotNil} * s.typ.flags != {}: + if {tfRequiresInit, tfNotNil} * s.typ.flags != {}: message(a.config, n.info, warnProveInit, s.name.s) else: message(a.config, n.info, warnUninit, s.name.s) @@ -838,7 +838,7 @@ proc track(tracked: PEffects, n: PNode) = # may not look like an assignment, but it is: let arg = n[1] initVarViaNew(tracked, arg) - if arg.typ.len != 0 and {tfNeedsInit} * arg.typ.lastSon.flags != {}: + if arg.typ.len != 0 and {tfRequiresInit} * arg.typ.lastSon.flags != {}: if a.sym.magic == mNewSeq and n[2].kind in {nkCharLit..nkUInt64Lit} and n[2].intVal == 0: # var s: seq[notnil]; newSeq(s, 0) is a special case! @@ -1203,7 +1203,7 @@ proc trackProc*(c: PContext; s: PSym, body: PNode) = createTypeBoundOps(t, typ, param.info) if not isEmptyType(s.typ[0]) and - ({tfNeedsInit, tfNotNil} * s.typ[0].flags != {} or + ({tfRequiresInit, tfNotNil} * s.typ[0].flags != {} or s.typ[0].skipTypes(abstractInst).kind == tyVar) and s.kind in {skProc, skFunc, skConverter, skMethod}: var res = s.ast[resultPos].sym # get result symbol diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index b45c42fe1..057972f0a 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -336,7 +336,7 @@ proc semIdentDef(c: PContext, n: PNode, kind: TSymKind): PSym = proc checkNilable(c: PContext; v: PSym) = if {sfGlobal, sfImportc} * v.flags == {sfGlobal} and - {tfNotNil, tfNeedsInit} * v.typ.flags != {}: + {tfNotNil, tfRequiresInit} * v.typ.flags != {}: if v.astdef.isNil: message(c.config, v.info, warnProveInit, v.name.s) elif tfNotNil in v.typ.flags and not v.astdef.typ.isNil and tfNotNil notin v.astdef.typ.flags: diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 7cddc7520..92e7b8bd2 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -139,7 +139,7 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType = if isPure and (let conflict = strTableInclReportConflict(symbols, e); conflict != nil): wrongRedefinition(c, e.info, e.name.s, conflict.info) inc(counter) - if tfNotNil in e.typ.flags and not hasNull: incl(result.flags, tfNeedsInit) + if tfNotNil in e.typ.flags and not hasNull: incl(result.flags, tfRequiresInit) proc semSet(c: PContext, n: PNode, prev: PType): PType = result = newOrPrevType(tySet, prev, c) @@ -254,15 +254,15 @@ proc semRange(c: PContext, n: PNode, prev: PType): PType = result = semRangeAux(c, n[1], prev) let n = result.n if n[0].kind in {nkCharLit..nkUInt64Lit} and n[0].intVal > 0: - incl(result.flags, tfNeedsInit) + incl(result.flags, tfRequiresInit) elif n[1].kind in {nkCharLit..nkUInt64Lit} and n[1].intVal < 0: - incl(result.flags, tfNeedsInit) + incl(result.flags, tfRequiresInit) elif n[0].kind in {nkFloatLit..nkFloat64Lit} and n[0].floatVal > 0.0: - incl(result.flags, tfNeedsInit) + incl(result.flags, tfRequiresInit) elif n[1].kind in {nkFloatLit..nkFloat64Lit} and n[1].floatVal < 0.0: - incl(result.flags, tfNeedsInit) + incl(result.flags, tfRequiresInit) else: if n[1].kind == nkInfix and considerQuotedIdent(c, n[1][0]).s == "..<": localError(c.config, n[0].info, "range types need to be constructed with '..', '..<' is not supported") diff --git a/tests/types/temptyseqs.nim b/tests/types/temptyseqs.nim index 28c3b87b8..6e7b58ced 100644 --- a/tests/types/temptyseqs.nim +++ b/tests/types/temptyseqs.nim @@ -75,16 +75,16 @@ varargso("foo", "bar", "baz") type Flago = enum - tfNeedsInit, tfNotNil + tfRequiresInit, tfNotNil -var s: set[Flago] = {tfNeedsInit} +var s: set[Flago] = {tfRequiresInit} -if {tfNeedsInit, tfNotNil} * s != {}: +if {tfRequiresInit, tfNotNil} * s != {}: echo "yes" else: echo "no" -if {tfNeedsInit, tfNotNil} * s <= {tfNotNil}: +if {tfRequiresInit, tfNotNil} * s <= {tfNotNil}: echo "yes" else: echo "no"