mirror of
https://github.com/nim-lang/Nim.git
synced 2026-08-17 12:22:45 +00:00
progress
This commit is contained in:
@@ -148,6 +148,37 @@ proc isLocalSym(a: PEffects, s: PSym): bool =
|
||||
s.typ != nil and (s.kind in {skLet, skVar, skResult} or (s.kind == skParam and isOutParam(s.typ))) and
|
||||
sfGlobal notin s.flags and s.owner == a.owner
|
||||
|
||||
proc isRangeSupertype(conf: ConfigRef; wider, narrower: PType): bool =
|
||||
## Check if `wider` type fully contains `narrower` type
|
||||
## Returns true if narrower fits entirely within wider (safe conversion)
|
||||
if wider.isOrdinalType:
|
||||
let wideFirst = firstOrd(conf, wider)
|
||||
let wideLast = lastOrd(conf, wider)
|
||||
let narrowFirst = firstOrd(conf, narrower)
|
||||
let narrowLast = lastOrd(conf, narrower)
|
||||
result = narrowFirst >= wideFirst and narrowLast <= wideLast
|
||||
elif not narrower.isOrdinalType:
|
||||
let wideFirst = firstFloat(wider)
|
||||
let wideLast = lastFloat(wider)
|
||||
let narrowFirst = firstFloat(narrower)
|
||||
let narrowLast = lastFloat(narrower)
|
||||
result = narrowFirst >= wideFirst and narrowLast <= wideLast
|
||||
else:
|
||||
# int -> float ranges; warn
|
||||
result = false
|
||||
|
||||
proc shouldWarnRangeConversion(conf: ConfigRef; formalType, argType: PType): bool =
|
||||
## Determine if an implicit range conversion should warn
|
||||
## We warn on conversions that are likely to cause panics
|
||||
let f = formalType.skipTypes({tyGenericInst, tyAlias, tySink, tyDistinct})
|
||||
let a = argType.skipTypes({tyGenericInst, tyAlias, tySink, tyDistinct})
|
||||
if f.kind == tyRange:
|
||||
# Only warn if formal range doesn't fully contain argument range
|
||||
# Check if the ranges don't perfectly overlap
|
||||
result = not isRangeSupertype(conf, f, a)
|
||||
else:
|
||||
result = false
|
||||
|
||||
proc lockLocations(a: PEffects; pragma: PNode) =
|
||||
if pragma.kind != nkExprColonExpr:
|
||||
localError(a.config, pragma.info, "locks pragma without argument")
|
||||
@@ -1504,6 +1535,11 @@ proc track(tracked: PEffects, n: PNode) =
|
||||
message(tracked.config, n.info, warnPtrToCstringConv,
|
||||
$n[1].typ)
|
||||
|
||||
# Check for implicit range conversions
|
||||
if n.kind == nkHiddenStdConv and
|
||||
shouldWarnRangeConversion(tracked.config, n.typ, n[1].typ):
|
||||
message(tracked.config, n.info, warnImplicitRangeConversion,
|
||||
typeToString(n[1].typ) & " -> " & typeToString(n.typ))
|
||||
|
||||
let t = n.typ.skipTypes(abstractInst)
|
||||
if t.kind == tyEnum:
|
||||
|
||||
@@ -615,36 +615,7 @@ proc isGenericObjectOf(f, a: PType): bool =
|
||||
# use sym equality to check if the `tyGenericBody` types are equal
|
||||
result = aRoot != nil and f.sym == aRoot.sym
|
||||
|
||||
proc isRangeSupertype(conf: ConfigRef; wider, narrower: PType): bool =
|
||||
## Check if `wider` type fully contains `narrower` type
|
||||
## Returns true if narrower fits entirely within wider (safe conversion)
|
||||
if wider.isOrdinalType:
|
||||
let wideFirst = firstOrd(conf, wider)
|
||||
let wideLast = lastOrd(conf, wider)
|
||||
let narrowFirst = firstOrd(conf, narrower)
|
||||
let narrowLast = lastOrd(conf, narrower)
|
||||
result = narrowFirst >= wideFirst and narrowLast <= wideLast
|
||||
elif not narrower.isOrdinalType:
|
||||
let wideFirst = firstFloat(wider)
|
||||
let wideLast = lastFloat(wider)
|
||||
let narrowFirst = firstFloat(narrower)
|
||||
let narrowLast = lastFloat(narrower)
|
||||
result = narrowFirst >= wideFirst and narrowLast <= wideLast
|
||||
else:
|
||||
# int -> float ranges; ignore for now
|
||||
result = true
|
||||
|
||||
proc shouldWarnRangeConversion(conf: ConfigRef; formalType, argType: PType): bool =
|
||||
## Determine if an implicit range conversion should warn
|
||||
## We warn on conversions that are likely to cause panics
|
||||
let f = formalType.skipTypes({tyGenericInst, tyAlias, tySink, tyDistinct})
|
||||
let a = argType.skipTypes({tyGenericInst, tyAlias, tySink, tyDistinct})
|
||||
if f.kind == tyRange:
|
||||
# Only warn if formal range doesn't fully contain argument range
|
||||
# Check if the ranges don't perfectly overlap
|
||||
result = not isRangeSupertype(conf, f, a)
|
||||
else:
|
||||
result = false
|
||||
|
||||
proc isObjectSubtype(c: var TCandidate; a, f, fGenericOrigin: PType): int =
|
||||
var t = a
|
||||
@@ -2518,10 +2489,6 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType,
|
||||
|
||||
case r
|
||||
of isConvertible:
|
||||
# Check for problematic implicit range conversions
|
||||
if shouldWarnRangeConversion(c.config, f, a):
|
||||
message(c.config, arg.info, warnImplicitRangeConversion,
|
||||
typeToString(a) & " -> " & typeToString(f))
|
||||
if f.skipTypes({tyRange}).kind in {tyInt, tyUInt}:
|
||||
inc(m.convMatches)
|
||||
inc(m.convMatches)
|
||||
@@ -2542,10 +2509,6 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType,
|
||||
of isIntConv:
|
||||
# I'm too lazy to introduce another ``*matches`` field, so we conflate
|
||||
# ``isIntConv`` and ``isIntLit`` here:
|
||||
# Check for problematic implicit range conversions
|
||||
if shouldWarnRangeConversion(c.config, f, a):
|
||||
message(c.config, arg.info, warnImplicitRangeConversion,
|
||||
typeToString(a) & " -> " & typeToString(f))
|
||||
if f.skipTypes({tyRange}).kind notin {tyInt, tyUInt}:
|
||||
inc(m.intConvMatches)
|
||||
inc(m.intConvMatches)
|
||||
|
||||
Reference in New Issue
Block a user