Merge remote-tracking branch 'origin/devel' into pr_saisir

This commit is contained in:
ringabout
2026-02-09 20:07:03 +08:00
9 changed files with 81 additions and 31 deletions

View File

@@ -983,7 +983,7 @@ proc genericParamToNif(n: PNode; parent: PNode; c: var TranslationContext) =
toNif n, parent, c
proc addExternName(sym: PSym; c: var TranslationContext) =
if sym.loc.snippet != nil:
if sym.loc.snippet != "":
c.b.addStrLit sym.loc.snippet
else:
c.b.addStrLit sym.name.s

View File

@@ -813,7 +813,7 @@ proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType: PTyp
inc(lastIndex)
if isGeneric:
for i in 0..<result.len:
if isIntLit(result[i].typ):
if result[i].typ != nil and isIntLit(result[i].typ):
# generic instantiation strips int lit type which makes conversions fail
result[i].typ = nil
result.typ = nil # current result.typ is invalid, index type is nil
@@ -2800,7 +2800,7 @@ proc semSetConstr(c: PContext, n: PNode, expectedType: PType = nil): PNode =
expectedElementType = typ
if isGeneric:
for i in 0..<n.len:
if isIntLit(n[i].typ):
if n[i].typ != nil and isIntLit(n[i].typ):
# generic instantiation strips int lit type which makes conversions fail
n[i].typ = nil
result.add n[i]
@@ -2913,7 +2913,7 @@ proc semTupleFieldsConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType
result.add n[i]
if isGeneric:
for i in 0..<result.len:
if isIntLit(result[i][1].typ):
if result[i][1].typ != nil and isIntLit(result[i][1].typ):
# generic instantiation strips int lit type which makes conversions fail
result[i][1].typ = nil
result.typ = makeTypeFromExpr(c, result.copyTree)
@@ -2954,7 +2954,7 @@ proc semTuplePositionsConstr(c: PContext, n: PNode, flags: TExprFlags; expectedT
addSonSkipIntLit(typ, n[i].typ.skipTypes({tySink}), c.idgen)
if isGeneric:
for i in 0..<result.len:
if isIntLit(result[i].typ):
if result[i].typ != nil and isIntLit(result[i].typ):
# generic instantiation strips int lit type which makes conversions fail
result[i].typ = nil
result.typ = makeTypeFromExpr(c, result.copyTree)

View File

@@ -1014,7 +1014,7 @@ proc skipGenericInvocation(t: PType): PType {.inline.} =
proc tryAddInheritedFields(c: PContext, check: var IntSet, pos: var int,
obj: PType, n: PNode, isPartial = false, innerObj: PType = nil): bool =
if ((not isPartial) and (obj.kind notin {tyObject, tyGenericParam} or tfFinal in obj.flags)) or
(innerObj != nil and obj.sym.id == innerObj.sym.id):
(innerObj != nil and obj.id == innerObj.id):
localError(c.config, n.info, "Cannot inherit from: '" & $obj & "'")
result = false
elif obj.kind == tyObject:

View File

@@ -1678,7 +1678,6 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
elif a.kind == tyGenericInst:
if roota.base == rootf.base:
let nextFlags = flags + {trNoCovariance}
var hasCovariance = false
# YYYY
result = isEqual
@@ -1690,7 +1689,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
if res notin {isEqual, isGeneric}:
if trNoCovariance notin flags and ff.kind == aa.kind:
let paramFlags = rootf.base[i-1].flags
hasCovariance =
let hasCovariance =
if tfCovariant in paramFlags:
if tfWeakCovariant in paramFlags:
isCovariantPtr(c, ff, aa)
@@ -1701,35 +1700,36 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
typeRel(c, aa, ff, flags) == isSubtype
if hasCovariance:
continue
result = isNone
break
return isNone
if prev == nil: put(c, f, a)
else:
let fKind = rootf.last.kind
if fKind in {tyAnd, tyOr}:
result = typeRel(c, last(f), a, flags)
if result != isNone: put(c, f, a)
if result != isNone:
if prev == nil: put(c, f, a)
return
var aAsObject = roota.last
let fKind = rootf.last.kind
if fKind in {tyAnd, tyOr}:
result = typeRel(c, last(f), a, flags)
if result != isNone: put(c, f, a)
return
if fKind in {tyRef, tyPtr}:
if aAsObject.kind == tyObject:
# bug #7600, tyObject cannot be passed
# as argument to tyRef/tyPtr
return isNone
elif aAsObject.kind == fKind:
aAsObject = aAsObject.base
var aAsObject = roota.last
if aAsObject.kind == tyObject and trIsOutParam notin flags:
let baseType = aAsObject.base
if baseType != nil:
if tfFinal notin aAsObject.flags:
inc c.inheritancePenalty, 1 + int(c.inheritancePenalty < 0)
let ret = typeRel(c, f, baseType, flags)
return if ret in {isEqual,isGeneric}: isSubtype else: ret
if fKind in {tyRef, tyPtr}:
if aAsObject.kind == tyObject:
# bug #7600, tyObject cannot be passed
# as argument to tyRef/tyPtr
return isNone
elif aAsObject.kind == fKind:
aAsObject = aAsObject.base
result = isNone
if aAsObject.kind == tyObject and trIsOutParam notin flags:
let baseType = aAsObject.base
if baseType != nil:
if tfFinal notin aAsObject.flags:
inc c.inheritancePenalty, 1 + int(c.inheritancePenalty < 0)
let ret = typeRel(c, f, baseType, flags)
return if ret in {isEqual,isGeneric}: isSubtype else: ret
else:
assert last(origF) != nil
result = typeRel(c, last(origF), a, flags)

View File

@@ -803,6 +803,8 @@ proc genNarrow(c: PCtx; n: PNode; dest: TDest) =
let first = c.genx(newIntTypeNode(firstOrd(c.config, t), intType))
let last = c.genx(newIntTypeNode(lastOrd(c.config, t), intType))
c.gABC(n, opcNarrowR, dest, first, last)
c.freeTemp(first)
c.freeTemp(last)
proc genNarrowU(c: PCtx; n: PNode; dest: TDest) =
let t = skipTypes(n.typ, abstractVar-{tyTypeDesc})

View File

@@ -38,6 +38,21 @@ proc `==`*[T](x, y: ptr T): bool {.magic: "EqRef", noSideEffect.}
proc `==`*[T: proc | iterator](x, y: T): bool {.magic: "EqProc", noSideEffect.}
## Checks that two `proc` variables refer to the same procedure.
when true:
# guard against string converted to cstring implicitly; see also #bug #25488
proc isNil*(x: string): bool {.noSideEffect, error: "'isNil' is invalid for 'string'".}
# bug #9149; ensure that 'typeof(nil)' does not match *too* well by using 'typeof(nil) | typeof(nil)',
# especially for converters, see tests/overload/tconverter_to_string.nim
# Eventually we will be able to remove this hack completely.
proc `==`*(x: string; y: typeof(nil) | typeof(nil)): bool {.error: "'nil' is invalid for 'string'".} =
discard
proc `==`*(x: typeof(nil) | typeof(nil); y: string): bool {.error: "'nil' is invalid for 'string'".} =
discard
proc `<=`*[Enum: enum](x, y: Enum): bool {.magic: "LeEnum", noSideEffect.}
proc `<=`*(x, y: string): bool {.magic: "LeStr", noSideEffect.} =
## Compares two strings and returns true if `x` is lexicographically

View File

@@ -892,3 +892,13 @@ block: # https://github.com/nim-lang/Nim/issues/20416
proc p2[T](sg:Container[T]) = discard
var v : Container[int]
p2(v)
block: # issue #25494
proc foo[T: enum](s = {T.low..T.high}) =
discard
type
MyEnum = enum
a, b, c
foo[MyEnum]()

16
tests/typerel/t25340.nim Normal file
View File

@@ -0,0 +1,16 @@
type
Foo[T] = object of T
template inheritanceCheck(a, b: untyped) =
doAssert a is b
doAssert b isnot a
inheritanceCheck Foo[RootObj], RootObj
inheritanceCheck Foo[Foo[RootObj]], RootObj
inheritanceCheck Foo[Foo[RootObj]], Foo[RootObj]
inheritanceCheck Foo[Foo[Foo[RootObj]]], RootObj
inheritanceCheck Foo[Foo[Foo[RootObj]]], Foo[RootObj]
inheritanceCheck Foo[Foo[Foo[RootObj]]], Foo[Foo[RootObj]]

View File

@@ -821,3 +821,10 @@ proc g1314(_: static bool) = discard
proc g1314(_: int) = discard
proc y1314() = g1314((; let k = 0; k))
y1314()
proc myProc(first: range[0..100]) =
var x = first
while x > 0:
dec(x)
const r = (myProc(3); 1)