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

mirtypes: fix regression with cyclic generic object types #1398

Merged
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
16 changes: 11 additions & 5 deletions compiler/mir/mirtypes.nim
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ import
idioms
]

# XXX: sighashes are currently needed for merging generic instantiations, but
# this should ultimately happen earlier - in sem - already
from compiler/sem/sighashes import hashType, ConsiderFlag

type
TypeKind* = enum
tkVoid
Expand Down Expand Up @@ -133,9 +137,9 @@ type
canon: Table[HeaderId, TypeId]
## maps headers of canonical type descriptions to their type symbol

instances: Table[(int, HeaderId), TypeId]
## associates a generic type ID + instance body with a type symbol. This
## is used for eliminating same-shaped instantiations of a generic
instances: Table[SigHash, TypeId]
## associates the sighash of a generic type instance with a type symbol.
## This is used for eliminating same-shaped instantiations of a generic
## object type

idents: BiTable[string]
Expand Down Expand Up @@ -1045,9 +1049,11 @@ proc typeSymToMir(env: var TypeEnv, t: PType): TypeId =

# generic types support covariance for tuples. Pick an instance as the
# "canonical" one, so that - for example - ``Generic[(int,)]`` and
# ``Generic[tuple[x: int]]`` map to the same MIR type in the end
# ``Generic[tuple[x: int]]`` map to the same MIR type in the end. In order
# to support cyclic types, ``sighashes`` has to be used
if tfFromGeneric in t.flags and
(let c = env.instances.mgetOrPut((t.sym.owner.typ.id, canon), result);
(let c = env.instances.mgetOrPut(hashType(t, {CoType, CoDistinct}),
result);
c != result):
env.symbols[result].canon = c
else:
Expand Down
19 changes: 19 additions & 0 deletions tests/lang_callable/generics/tequal_instantiation_with_tuple.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
discard """
description: '''
Ensure that two instantiations of a cyclic generic object type are
considered equal at every level (type system, backend, run-time) when
one of them is instantiated with a named tuple and the other with an
unnamed one
'''
knownIssue.vm: "``vmtypegen`` considers the two types distinct"
"""

type Recursive[T] = object
# the same problem occurred when a ``ref`` type is used
self: ptr Recursive[T]
val: T

# it's important that both tuples are comprised of the exact same types
var x: Recursive[(int, int)]
var y: Recursive[tuple[a, b: int]]
x = y
Loading