diff --git a/changelog.md b/changelog.md index f87dadae633af..304aeb1f7b90e 100644 --- a/changelog.md +++ b/changelog.md @@ -12,6 +12,10 @@ rounding guarantees (via the avoid conflicts with `system.default`, so named argument usage for this parameter like `getOrDefault(..., default = ...)` will have to be changed. +- Typedesc field access on object/tuple types (e.g. `Foo[int].val`) is now + restricted to `typeof` context. Use `--legacy:typedescFieldAccess` to restore + the previous behavior of allowing it outside `typeof`. + - With `-d:nimPreviewCheckedClose`, the `close` function in the `std/syncio` module now raises an IO exception in case of an error. - Unknown warnings and hints now gives warnings `warnUnknownNotes` instead of diff --git a/compiler/options.nim b/compiler/options.nim index 7a28b1dc6f500..adc63e5687049 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -262,6 +262,9 @@ type procParamTypeBackendAliases ## Keep the old proc type compatibility rules that ignore backend ## c type aliases. + typedescFieldAccess + ## Allow typedesc field access on object/tuple types outside of + ## typeof context. SymbolFilesOption* = enum disabledSf, writeOnlySf, readOnlySf, v2Sf, stressTest diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index aa0489cd225f1..57e0c86221d78 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1500,7 +1500,8 @@ proc tryReadingTypeField(c: PContext, n: PNode, i: PIdent, ty: PType): PNode = markUsed(c, n.info, f) onUse(n.info, f) of tyObject, tyTuple: - if ty.n != nil and ty.n.kind == nkRecList: + if (c.inTypeofContext > 0 or typedescFieldAccess in c.config.legacyFeatures) and + ty.n != nil and ty.n.kind == nkRecList: let field = lookupInRecord(ty.n, i) if field != nil: n.typ = makeTypeDesc(c, field.typ) diff --git a/lib/pure/nimprof.nim b/lib/pure/nimprof.nim index bac2c35159165..46d28aafb4d55 100644 --- a/lib/pure/nimprof.nim +++ b/lib/pure/nimprof.nim @@ -186,7 +186,7 @@ proc writeProfile() {.noconv.} = var perProc = initCountTable[string]() for i in 0..entries-1: var dups = initHashSet[string]() - for ii in 0..high(StackTrace.lines): + for ii in 0..high(typeof(StackTrace.lines)): let procname = profileData[i].st[ii] if isNil(procname): break let p = $procname @@ -201,7 +201,7 @@ proc writeProfile() {.noconv.} = writeLine(f, "Entry: ", i+1, "/", entries, " Calls: ", profileData[i].total // totalCalls, " [sum: ", sum, "; ", sum // totalCalls, "]") - for ii in 0..high(StackTrace.lines): + for ii in 0..high(typeof(StackTrace.lines)): let procname = profileData[i].st[ii] let filename = profileData[i].st.files[ii] if isNil(procname): break diff --git a/tests/concepts/tmapconcept.nim b/tests/concepts/tmapconcept.nim index cc99737df4b7b..81e8d885a9710 100644 --- a/tests/concepts/tmapconcept.nim +++ b/tests/concepts/tmapconcept.nim @@ -39,7 +39,7 @@ static: ok seq[int] is Enumerable[int] ok seq[string] is Enumerable ok seq[int] is Enumerable[SomeNumber] - ok SparseSeq.data is Enumerable + ok typeof(SparseSeq.data) is Enumerable no seq[string] is Enumerable[int] no int is Enumerable no int is Enumerable[int] diff --git a/tests/metatype/ttypedesc3.nim b/tests/metatype/ttypedesc3.nim index d3a58853df9fb..dacd490e24a22 100644 --- a/tests/metatype/ttypedesc3.nim +++ b/tests/metatype/ttypedesc3.nim @@ -48,6 +48,6 @@ type Foo[T] = object val: T -var x: Foo[int].val +var x: typeof(Foo[int].val) inc(x) echo x diff --git a/tests/metatype/ttypedesc_field_legacy.nim b/tests/metatype/ttypedesc_field_legacy.nim new file mode 100644 index 0000000000000..96196c22a8085 --- /dev/null +++ b/tests/metatype/ttypedesc_field_legacy.nim @@ -0,0 +1,11 @@ +discard """ + matrix: "--legacy:typedescFieldAccess" + output: "4" +""" + +type + Foo[T] = object + val: T + +var x: Foo[int].val = 4 +echo x diff --git a/tests/pragmas/tcustom_pragma.nim b/tests/pragmas/tcustom_pragma.nim index 092d59bc744c9..3ee53a48e0167 100644 --- a/tests/pragmas/tcustom_pragma.nim +++ b/tests/pragmas/tcustom_pragma.nim @@ -330,7 +330,7 @@ TypeDef Baz {.expectedAst(typeAst).} = object x: string - static: doAssert Baz.x is string + static: doAssert typeof(Baz.x) is string const procAst = """ ProcDef