Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix tyArray with 3 kids breaking concept #24444

Draft
wants to merge 4 commits into
base: devel
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 21 additions & 19 deletions compiler/semstmts.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1602,7 +1602,9 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
# we fill it out later. For magic generics like 'seq', it won't be filled
# so we use tyNone instead of nil to not crash for strange conversions
# like: mydata.seq
if s.typ.kind in {tyOpenArray, tyVarargs} and s.typ.len == 1:
if s.typ.kind == tyArray and s.typ.len == 2:
discard
elif s.typ.kind in {tyOpenArray, tyVarargs} and s.typ.len == 1:
# XXX investigate why `tySequence` cannot be added here for now.
discard
else:
Expand Down Expand Up @@ -1717,18 +1719,22 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
c.skipTypes = @[]

proc checkForMetaFields(c: PContext; n: PNode; hasError: var bool) =
proc checkMeta(c: PContext; n: PNode; t: PType; hasError: var bool; parent: PType) =
if t != nil and (t.isMetaType or t.kind == tyNone) and tfGenericTypeParam notin t.flags:
if t.kind == tyBuiltInTypeClass and t.len == 1 and t.elementType.kind == tyProc:
localError(c.config, n.info, ("'$1' is not a concrete type; " &
"for a callback without parameters use 'proc()'") % t.typeToString)
elif t.kind == tyNone and parent != nil:
# TODO: openarray has the `tfGenericTypeParam` flag & generics
# TODO: handle special cases (sink etc.) and views
proc errMsg(c: PContext; n: PNode; t: PType; parent: PType)=
if t.kind == tyBuiltInTypeClass and t.len == 1 and t.elementType.kind == tyProc:
localError(c.config, n.info, ("'$1' is not a concrete type; " &
"for a callback without parameters use 'proc()'") % t.typeToString)
elif parent != nil and parent != t:
# TODO: openarray has the `tfGenericTypeParam` flag & generics
# TODO: handle special cases (sink etc.) and views
if parent.kind in {tyRef, tyPtr} and t.kind == tyObject and parent[0] == t:
localError(c.config, n.info, errTIsNotAConcreteType % parent.typeToString)
elif t.kind == tyNone:
localError(c.config, n.info, errTIsNotAConcreteType % parent.typeToString)
else:
localError(c.config, n.info, errTIsNotAConcreteType % t.typeToString)
hasError = true
localError(c.config, n.info, (errTIsNotAConcreteType % t.typeToString) & (" for '$1'" % parent.typeToString))

else:
localError(c.config, n.info, errTIsNotAConcreteType % t.typeToString)

if n.isNil: return
case n.kind
Expand All @@ -1738,14 +1744,10 @@ proc checkForMetaFields(c: PContext; n: PNode; hasError: var bool) =
checkForMetaFields(c, n.lastSon, hasError)
of nkSym:
let t = n.sym.typ
case t.kind
of tySequence, tySet, tyArray, tyOpenArray, tyVar, tyLent, tyPtr, tyRef,
tyProc, tyGenericInvocation, tyGenericInst, tyAlias, tySink, tyOwned:
let start = ord(t.kind in {tyGenericInvocation, tyGenericInst})
for i in start..<t.len:
checkMeta(c, n, t[i], hasError, t)
else:
checkMeta(c, n, t, hasError, nil)
let comp = findUnspecifiedGenericsOrNil(t)
if comp != nil:
errMsg(c, n, comp, t)
hasError = true
else:
internalAssert c.config, false

Expand Down
27 changes: 27 additions & 0 deletions compiler/types.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2030,3 +2030,30 @@ proc genericRoot*(t: PType): PType =
result = t.sym.typ
else:
result = nil

proc findUnspecifiedGenericsOrNil*(t: PType): PType=
result = nil
if t == nil:
return nil
if tfHasMeta in t.flags:
result = t
if t.size == szIllegalRecursion:
return nil
let tmp = t.size
t.size = szIllegalRecursion
case t.kind
of tyMetaTypes, tyNone:
result = t
of tyStatic:
if t.n == nil:
result = t
of tySequence, tySet, tyArray, tyOpenArray, tyVar, tyLent, tyPtr, tyRef,
tyProc, tyGenericInvocation, tyGenericInst, tyAlias, tySink, tyOwned:
let start = ord(t.kind in {tyGenericInvocation, tyGenericInst})
for i in start..<t.len:
let tmp = findUnspecifiedGenericsOrNil(t[i])
if tmp != nil:
result = tmp
else:
discard
t.size = tmp
22 changes: 22 additions & 0 deletions tests/concepts/tconceptsv2.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
discard """
action: "run"
output: '''
A[array[0..0, int]]
A[seq[int]]
'''
"""
type
SomethingLike[T] = concept
proc len(s: Self): int
proc `[]`(s: Self; index: int): T

A[T] = object
x: T

proc initA*(x: SomethingLike): auto =
A[type x](x: x)

var a: array[1, int]
var s: seq[int]
echo typeof(initA(a))
echo typeof(initA(s))
25 changes: 13 additions & 12 deletions tests/errmsgs/tmetaobjectfields.nim
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
discard """
cmd: "nim check --hints:off $file"
matrix: "--hints:off"
action: "reject"
nimout: '''
tmetaobjectfields.nim(26, 5) Error: 'array' is not a concrete type
tmetaobjectfields.nim(30, 5) Error: 'seq' is not a concrete type
tmetaobjectfields.nim(34, 5) Error: 'set' is not a concrete type
tmetaobjectfields.nim(37, 3) Error: 'sink' is not a concrete type
tmetaobjectfields.nim(39, 3) Error: 'lent' is not a concrete type
tmetaobjectfields.nim(56, 16) Error: 'seq' is not a concrete type
tmetaobjectfields.nim(60, 5) Error: 'ptr' is not a concrete type
tmetaobjectfields.nim(61, 5) Error: 'ref' is not a concrete type
tmetaobjectfields.nim(62, 5) Error: 'auto' is not a concrete type
tmetaobjectfields.nim(63, 5) Error: 'UncheckedArray' is not a concrete type
tmetaobjectfields.nim(68, 5) Error: 'object' is not a concrete type
tmetaobjectfields.nim(72, 5) Error: 'Type3011:ObjectType' is not a concrete type
tmetaobjectfields.nim(27, 5) Error: 'T' is not a concrete type for 'array'
tmetaobjectfields.nim(31, 5) Error: 'seq' is not a concrete type
tmetaobjectfields.nim(35, 5) Error: 'set' is not a concrete type
tmetaobjectfields.nim(38, 3) Error: 'sink' is not a concrete type
tmetaobjectfields.nim(40, 3) Error: 'lent' is not a concrete type
tmetaobjectfields.nim(57, 16) Error: 'seq' is not a concrete type
tmetaobjectfields.nim(61, 5) Error: 'ptr' is not a concrete type
tmetaobjectfields.nim(62, 5) Error: 'ref' is not a concrete type
tmetaobjectfields.nim(63, 5) Error: 'auto' is not a concrete type
tmetaobjectfields.nim(64, 5) Error: 'UncheckedArray' is not a concrete type
tmetaobjectfields.nim(69, 5) Error: 'object' is not a concrete type for 'ref object'
tmetaobjectfields.nim(73, 5) Error: 'Type3011' is not a concrete type
'''
"""

Expand Down
7 changes: 4 additions & 3 deletions tests/generics/tmetafield.nim
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
discard """
cmd: "nim check $options $file"
matrix: "--hints:off"
action: "reject"
nimout: '''
tmetafield.nim(26, 5) Error: 'proc' is not a concrete type; for a callback without parameters use 'proc()'
tmetafield.nim(27, 5) Error: 'Foo' is not a concrete type
tmetafield.nim(29, 5) Error: invalid type: 'proc' in this context: 'TBaseMed' for var
tmetafield.nim(27, 5) Error: 'proc' is not a concrete type; for a callback without parameters use 'proc()'
tmetafield.nim(28, 5) Error: 'Foo' is not a concrete type for 'seq[Foo]'
tmetafield.nim(30, 5) Error: invalid type: 'proc' in this context: 'TBaseMed' for var
'''
"""

Expand Down
2 changes: 1 addition & 1 deletion tests/generics/twrong_generic_object.nim
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
discard """
errormsg: "'Node' is not a concrete type"
errormsg: "'Node:ObjectType' is not a concrete type for 'seq[Node]'"
line: 11
"""
# bug #2509
Expand Down