mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-08 14:03:23 +00:00
Unchecked arrays now have their own type (#9267)
This commit is contained in:
@@ -363,7 +363,9 @@ type
|
||||
tyUInt, tyUInt8, tyUInt16, tyUInt32, tyUInt64,
|
||||
tyOptAsRef, tySink, tyLent,
|
||||
tyVarargs,
|
||||
tyUnused,
|
||||
tyUncheckedArray
|
||||
# An array with boundaries [0,+∞]
|
||||
|
||||
tyProxy # used as errornous type (for idetools)
|
||||
|
||||
tyBuiltInTypeClass
|
||||
@@ -657,7 +659,7 @@ type
|
||||
mNHint, mNWarning, mNError,
|
||||
mInstantiationInfo, mGetTypeInfo,
|
||||
mNimvm, mIntDefine, mStrDefine, mRunnableExamples,
|
||||
mException, mBuiltinType, mSymOwner
|
||||
mException, mBuiltinType, mSymOwner, mUncheckedArray
|
||||
|
||||
# things that we can evaluate safely at compile time, even if not asked for it:
|
||||
const
|
||||
|
||||
@@ -856,6 +856,15 @@ proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
|
||||
else:
|
||||
genRecordField(p, e.sons[0], d)
|
||||
|
||||
proc genUncheckedArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) =
|
||||
var a, b: TLoc
|
||||
initLocExpr(p, x, a)
|
||||
initLocExpr(p, y, b)
|
||||
var ty = skipTypes(a.t, abstractVarRange + abstractPtrs + tyUserTypeClasses)
|
||||
d.inheritLocation(a)
|
||||
putIntoDest(p, d, n, ropecg(p.module, "$1[$2]", rdLoc(a), rdCharLoc(b)),
|
||||
a.storage)
|
||||
|
||||
proc genArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) =
|
||||
var a, b: TLoc
|
||||
initLocExpr(p, x, a)
|
||||
@@ -949,6 +958,7 @@ proc genBracketExpr(p: BProc; n: PNode; d: var TLoc) =
|
||||
var ty = skipTypes(n.sons[0].typ, abstractVarRange + tyUserTypeClasses)
|
||||
if ty.kind in {tyRef, tyPtr}: ty = skipTypes(ty.lastSon, abstractVarRange)
|
||||
case ty.kind
|
||||
of tyUncheckedArray: genUncheckedArrayElem(p, n, n.sons[0], n.sons[1], d)
|
||||
of tyArray: genArrayElem(p, n, n.sons[0], n.sons[1], d)
|
||||
of tyOpenArray, tyVarargs: genOpenArrayElem(p, n, n.sons[0], n.sons[1], d)
|
||||
of tySequence, tyString: genSeqElem(p, n, n.sons[0], n.sons[1], d)
|
||||
|
||||
@@ -139,7 +139,7 @@ proc mapType(conf: ConfigRef; typ: PType): TCTypeKind =
|
||||
of tyBool: result = ctBool
|
||||
of tyChar: result = ctChar
|
||||
of tySet: result = mapSetType(conf, typ)
|
||||
of tyOpenArray, tyArray, tyVarargs: result = ctArray
|
||||
of tyOpenArray, tyArray, tyVarargs, tyUncheckedArray: result = ctArray
|
||||
of tyObject, tyTuple: result = ctStruct
|
||||
of tyUserTypeClasses:
|
||||
doAssert typ.isResolvedUserTypeClass
|
||||
@@ -161,7 +161,7 @@ proc mapType(conf: ConfigRef; typ: PType): TCTypeKind =
|
||||
of tyPtr, tyVar, tyLent, tyRef, tyOptAsRef:
|
||||
var base = skipTypes(typ.lastSon, typedescInst)
|
||||
case base.kind
|
||||
of tyOpenArray, tyArray, tyVarargs: result = ctPtrToArray
|
||||
of tyOpenArray, tyArray, tyVarargs, tyUncheckedArray: result = ctPtrToArray
|
||||
of tySet:
|
||||
if mapSetType(conf, base) == ctArray: result = ctPtrToArray
|
||||
else: result = ctPtr
|
||||
@@ -747,6 +747,12 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
|
||||
else:
|
||||
result = rope("TGenericSeq")
|
||||
add(result, seqStar(m))
|
||||
of tyUncheckedArray:
|
||||
result = getTypeName(m, origTyp, sig)
|
||||
m.typeCache[sig] = result
|
||||
if not isImportedType(t):
|
||||
let foo = getTypeDescAux(m, t.sons[0], check)
|
||||
addf(m.s[cfsTypes], "typedef $1 $2[1];$n", [foo, result])
|
||||
of tyArray:
|
||||
var n: BiggestInt = lengthOrd(m.config, t)
|
||||
if n <= 0: n = 1 # make an array of at least one element
|
||||
@@ -1218,7 +1224,7 @@ proc genTypeInfo(m: BModule, t: PType; info: TLineInfo): Rope =
|
||||
if m.config.selectedGC >= gcMarkAndSweep:
|
||||
let markerProc = genTraverseProc(m, origType, sig)
|
||||
addf(m.s[cfsTypeInit3], "$1.marker = $2;$n", [result, markerProc])
|
||||
of tyPtr, tyRange: genTypeInfoAux(m, t, t, result, info)
|
||||
of tyPtr, tyRange, tyUncheckedArray: genTypeInfoAux(m, t, t, result, info)
|
||||
of tyArray: genArrayInfo(m, t, result, info)
|
||||
of tySet: genSetInfo(m, t, result, info)
|
||||
of tyEnum: genEnumInfo(m, t, result, info)
|
||||
|
||||
@@ -82,6 +82,7 @@ proc initDefines*(symbols: StringTableRef) =
|
||||
defineSymbol("nimNoNilSeqs")
|
||||
defineSymbol("nimNoNilSeqs2")
|
||||
defineSymbol("nimHasUserErrors")
|
||||
defineSymbol("nimUncheckedArrayTyp")
|
||||
|
||||
defineSymbol("nimHasNilSeqs")
|
||||
for f in low(Feature)..high(Feature):
|
||||
|
||||
@@ -179,7 +179,7 @@ proc mapType(typ: PType): TJSTypeKind =
|
||||
of tyFloat..tyFloat128: result = etyFloat
|
||||
of tySet: result = etyObject # map a set to a table
|
||||
of tyString, tySequence, tyOpt: result = etySeq
|
||||
of tyObject, tyArray, tyTuple, tyOpenArray, tyVarargs:
|
||||
of tyObject, tyArray, tyTuple, tyOpenArray, tyVarargs, tyUncheckedArray:
|
||||
result = etyObject
|
||||
of tyNil: result = etyNull
|
||||
of tyGenericParam, tyGenericBody, tyGenericInvocation,
|
||||
@@ -195,7 +195,7 @@ proc mapType(typ: PType): TJSTypeKind =
|
||||
else: result = etyNone
|
||||
of tyProc: result = etyProc
|
||||
of tyCString: result = etyString
|
||||
of tyUnused, tyOptAsRef: doAssert(false, "mapType")
|
||||
of tyOptAsRef: doAssert(false, "mapType")
|
||||
|
||||
proc mapType(p: PProc; typ: PType): TJSTypeKind =
|
||||
result = mapType(typ)
|
||||
|
||||
@@ -197,7 +197,7 @@ proc liftBodyAux(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
case t.kind
|
||||
of tyNone, tyEmpty, tyVoid: discard
|
||||
of tyPointer, tySet, tyBool, tyChar, tyEnum, tyInt..tyUInt64, tyCString,
|
||||
tyPtr, tyRef, tyOpt:
|
||||
tyPtr, tyRef, tyOpt, tyUncheckedArray:
|
||||
defaultOp(c, t, body, x, y)
|
||||
of tyArray:
|
||||
if {tfHasAsgn, tfUncheckedArray} * t.flags == {tfHasAsgn}:
|
||||
@@ -260,7 +260,7 @@ proc liftBodyAux(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
of tyOrdinal, tyRange, tyInferred,
|
||||
tyGenericInst, tyStatic, tyVar, tyLent, tyAlias, tySink:
|
||||
liftBodyAux(c, lastSon(t), body, x, y)
|
||||
of tyUnused, tyOptAsRef: internalError(c.c.config, "liftBodyAux")
|
||||
of tyOptAsRef: internalError(c.c.config, "liftBodyAux")
|
||||
|
||||
proc newProcType(info: TLineInfo; owner: PSym): PType =
|
||||
result = newType(tyProc, owner)
|
||||
|
||||
@@ -1365,7 +1365,7 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
|
||||
case arr.kind
|
||||
of tyArray, tyOpenArray, tyVarargs, tySequence, tyString,
|
||||
tyCString:
|
||||
tyCString, tyUncheckedArray:
|
||||
if n.len != 2: return nil
|
||||
n.sons[0] = makeDeref(n.sons[0])
|
||||
for i in countup(1, sonsLen(n) - 1):
|
||||
|
||||
@@ -1511,6 +1511,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
case s.magic
|
||||
of mArray: result = semArray(c, n, prev)
|
||||
of mOpenArray: result = semContainer(c, n, tyOpenArray, "openarray", prev)
|
||||
of mUncheckedArray: result = semContainer(c, n, tyUncheckedArray, "uncheckedarray", prev)
|
||||
of mRange: result = semRange(c, n, prev)
|
||||
of mSet: result = semSet(c, n, prev)
|
||||
of mOrdinal: result = semOrdinal(c, n, prev)
|
||||
@@ -1751,6 +1752,8 @@ proc processMagicType(c: PContext, m: PSym) =
|
||||
rawAddSon(m.typ, newTypeS(tyNone, c))
|
||||
of mSet:
|
||||
setMagicType(c.config, m, tySet, 0)
|
||||
of mUncheckedArray:
|
||||
setMagicType(c.config, m, tyUncheckedArray, 0)
|
||||
of mSeq:
|
||||
setMagicType(c.config, m, tySequence, 0)
|
||||
if c.config.selectedGc == gcDestructors:
|
||||
|
||||
@@ -186,7 +186,7 @@ proc sumGeneric(t: PType): int =
|
||||
var isvar = 1
|
||||
while true:
|
||||
case t.kind
|
||||
of tyGenericInst, tyArray, tyRef, tyPtr, tyDistinct,
|
||||
of tyGenericInst, tyArray, tyRef, tyPtr, tyDistinct, tyUncheckedArray,
|
||||
tyOpenArray, tyVarargs, tySet, tyRange, tySequence, tyGenericBody,
|
||||
tyLent:
|
||||
t = t.lastSon
|
||||
@@ -1199,6 +1199,11 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
|
||||
if lengthOrd(c.c.config, fRange) != lengthOrd(c.c.config, aRange):
|
||||
result = isNone
|
||||
else: discard
|
||||
of tyUncheckedArray:
|
||||
if a.kind == tyUncheckedArray:
|
||||
result = typeRel(c, base(f), base(a))
|
||||
if result < isGeneric: result = isNone
|
||||
else: discard
|
||||
of tyOpenArray, tyVarargs:
|
||||
# varargs[expr] is special too but handled earlier. So we only need to
|
||||
# handle varargs[stmt] which is the same as varargs[typed]:
|
||||
@@ -1362,6 +1367,8 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
|
||||
if a.len == 1:
|
||||
let pointsTo = a.sons[0].skipTypes(abstractInst)
|
||||
if pointsTo.kind == tyChar: result = isConvertible
|
||||
elif pointsTo.kind == tyUncheckedArray and pointsTo.sons[0].kind == tyChar:
|
||||
result = isConvertible
|
||||
elif pointsTo.kind == tyArray and firstOrd(nil, pointsTo.sons[0]) == 0 and
|
||||
skipTypes(pointsTo.sons[0], {tyRange}).kind in {tyInt..tyInt64} and
|
||||
pointsTo.sons[1].kind == tyChar:
|
||||
|
||||
@@ -396,7 +396,7 @@ const
|
||||
"float", "float32", "float64", "float128",
|
||||
"uint", "uint8", "uint16", "uint32", "uint64",
|
||||
"opt", "sink",
|
||||
"lent", "varargs[$1]", "unused", "Error Type",
|
||||
"lent", "varargs[$1]", "UncheckedArray[$1]", "Error Type",
|
||||
"BuiltInTypeClass", "UserTypeClass",
|
||||
"UserTypeClassInst", "CompositeTypeClass", "inferred",
|
||||
"and", "or", "not", "any", "static", "TypeFromExpr", "FieldAccessor",
|
||||
@@ -526,6 +526,8 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||
else:
|
||||
result = "array[" & typeToString(t.sons[0]) & ", " &
|
||||
typeToString(t.sons[1]) & ']'
|
||||
of tyUncheckedArray:
|
||||
result = "uncheckedArray[" & typeToString(t.sons[0]) & ']'
|
||||
of tySequence:
|
||||
result = "seq[" & typeToString(t.sons[0]) & ']'
|
||||
of tyOpt:
|
||||
@@ -638,6 +640,8 @@ proc firstOrd*(conf: ConfigRef; t: PType): BiggestInt =
|
||||
of tyOrdinal:
|
||||
if t.len > 0: result = firstOrd(conf, lastSon(t))
|
||||
else: internalError(conf, "invalid kind for firstOrd(" & $t.kind & ')')
|
||||
of tyUncheckedArray:
|
||||
result = 0
|
||||
else:
|
||||
internalError(conf, "invalid kind for firstOrd(" & $t.kind & ')')
|
||||
result = 0
|
||||
@@ -695,6 +699,8 @@ proc lastOrd*(conf: ConfigRef; t: PType; fixedUnsigned = false): BiggestInt =
|
||||
of tyOrdinal:
|
||||
if t.len > 0: result = lastOrd(conf, lastSon(t))
|
||||
else: internalError(conf, "invalid kind for lastOrd(" & $t.kind & ')')
|
||||
of tyUncheckedArray:
|
||||
result = high(BiggestInt)
|
||||
else:
|
||||
internalError(conf, "invalid kind for lastOrd(" & $t.kind & ')')
|
||||
result = 0
|
||||
@@ -1030,7 +1036,7 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
|
||||
if result and {ExactGenericParams, ExactTypeDescValues} * c.flags != {}:
|
||||
result = a.sym.position == b.sym.position
|
||||
of tyGenericInvocation, tyGenericBody, tySequence,
|
||||
tyOpenArray, tySet, tyRef, tyPtr, tyVar, tyLent, tySink,
|
||||
tyOpenArray, tySet, tyRef, tyPtr, tyVar, tyLent, tySink, tyUncheckedArray,
|
||||
tyArray, tyProc, tyVarargs, tyOrdinal, tyTypeClasses, tyOpt:
|
||||
cycleCheck()
|
||||
if a.kind == tyUserTypeClass and a.n != nil: return a.n == b.n
|
||||
@@ -1054,7 +1060,7 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
|
||||
cycleCheck()
|
||||
result = sameTypeAux(a.lastSon, b.lastSon, c)
|
||||
of tyNone: result = false
|
||||
of tyUnused, tyOptAsRef: result = false
|
||||
of tyOptAsRef: result = false
|
||||
|
||||
proc sameBackendType*(x, y: PType): bool =
|
||||
var c = initSameTypeClosure()
|
||||
@@ -1210,7 +1216,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
|
||||
result = nil
|
||||
of tyOrdinal:
|
||||
if kind != skParam: result = t
|
||||
of tyGenericInst, tyDistinct, tyAlias, tyInferred:
|
||||
of tyGenericInst, tyDistinct, tyAlias, tyInferred, tyUncheckedArray:
|
||||
result = typeAllowedAux(marker, lastSon(t), kind, flags)
|
||||
of tyRange:
|
||||
if skipTypes(t.sons[0], abstractInst-{tyTypeDesc}).kind notin
|
||||
@@ -1252,7 +1258,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
|
||||
# for now same as error node; we say it's a valid type as it should
|
||||
# prevent cascading errors:
|
||||
result = nil
|
||||
of tyUnused, tyOptAsRef: result = t
|
||||
of tyOptAsRef: result = t
|
||||
|
||||
proc typeAllowed*(t: PType, kind: TSymKind; flags: TTypeAllowedFlags = {}): PType =
|
||||
# returns 'nil' on success and otherwise the part of the type that is
|
||||
@@ -1430,6 +1436,8 @@ proc computeSizeAux(conf: ConfigRef; typ: PType, a: var BiggestInt): BiggestInt
|
||||
of tyStatic:
|
||||
result = if typ.n != nil: computeSizeAux(conf, typ.lastSon, a)
|
||||
else: szUnknownSize
|
||||
of tyUncheckedArray:
|
||||
result = 0
|
||||
else:
|
||||
#internalError("computeSizeAux()")
|
||||
result = szUnknownSize
|
||||
|
||||
@@ -98,6 +98,10 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo;
|
||||
of tyStmt: result = atomicType("stmt", mStmt)
|
||||
of tyVoid: result = atomicType("void", mVoid)
|
||||
of tyEmpty: result = atomicType("empty", mNone)
|
||||
of tyUncheckedArray:
|
||||
result = newNodeIT(nkBracketExpr, if t.n.isNil: info else: t.n.info, t)
|
||||
result.add atomicType("uncheckedArray", mUncheckedArray)
|
||||
result.add mapTypeToAst(t.sons[0], info)
|
||||
of tyArray:
|
||||
result = newNodeIT(nkBracketExpr, if t.n.isNil: info else: t.n.info, t)
|
||||
result.add atomicType("array", mArray)
|
||||
@@ -289,7 +293,7 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo;
|
||||
result.add atomicType("static", mNone)
|
||||
if t.n != nil:
|
||||
result.add t.n.copyTree
|
||||
of tyUnused, tyOptAsRef: assert(false, "mapTypeToAstX")
|
||||
of tyOptAsRef: assert(false, "mapTypeToAstX")
|
||||
|
||||
proc opMapTypeToAst*(cache: IdentCache; t: PType; info: TLineInfo): PNode =
|
||||
result = mapTypeToAstX(cache, t, info, false, true)
|
||||
|
||||
@@ -84,7 +84,7 @@ type
|
||||
wStdIn, wStdOut, wStdErr,
|
||||
|
||||
wInOut, wByCopy, wByRef, wOneWay,
|
||||
wBitsize,
|
||||
wBitsize
|
||||
|
||||
TSpecialWords* = set[TSpecialWord]
|
||||
|
||||
@@ -173,7 +173,7 @@ const
|
||||
"stdin", "stdout", "stderr",
|
||||
|
||||
"inout", "bycopy", "byref", "oneway",
|
||||
"bitsize",
|
||||
"bitsize"
|
||||
]
|
||||
|
||||
proc findStr*(a: openArray[string], s: string): int =
|
||||
|
||||
@@ -98,7 +98,7 @@ type
|
||||
ntyUInt, ntyUInt8, ntyUInt16, ntyUInt32, ntyUInt64,
|
||||
ntyUnused0, ntyUnused1, ntyUnused2,
|
||||
ntyVarargs,
|
||||
ntyUnused,
|
||||
ntyUncheckedArray,
|
||||
ntyError,
|
||||
ntyBuiltinTypeClass, ntyUserTypeClass, ntyUserTypeClassInst,
|
||||
ntyCompositeTypeClass, ntyInferred, ntyAnd, ntyOr, ntyNot,
|
||||
|
||||
@@ -253,7 +253,13 @@ type
|
||||
seq*{.magic: "Seq".}[T] ## Generic type to construct sequences.
|
||||
set*{.magic: "Set".}[T] ## Generic type to construct bit sets.
|
||||
|
||||
UncheckedArray* {.unchecked.}[T] = array[0, T]
|
||||
when defined(nimUncheckedArrayTyp):
|
||||
type
|
||||
UncheckedArray*{.magic: "UncheckedArray".}[T]
|
||||
## Array with no bounds checking
|
||||
else:
|
||||
type
|
||||
UncheckedArray*{.unchecked.}[T] = array[0,T]
|
||||
## Array with no bounds checking
|
||||
|
||||
when defined(nimHasOpt):
|
||||
|
||||
@@ -2,6 +2,7 @@ discard """
|
||||
nimout: '''proc (x: int): string => typeDesc[proc[string, int]]
|
||||
proc (x: int): void => typeDesc[proc[void, int]]
|
||||
proc (x: int) => typeDesc[proc[void, int]]'''
|
||||
x => uncheckedArray[int]
|
||||
"""
|
||||
|
||||
#2211
|
||||
@@ -15,3 +16,6 @@ macro showType(t:typed): untyped =
|
||||
showType(proc(x:int): string)
|
||||
showType(proc(x:int): void)
|
||||
showType(proc(x:int))
|
||||
|
||||
var x: UncheckedArray[int]
|
||||
showType(x)
|
||||
|
||||
Reference in New Issue
Block a user