Skip to content

Commit

Permalink
mirtypes: fix regression with cyclic generic object types (#1398)
Browse files Browse the repository at this point in the history
## Summary

Fix cyclic generic object types instantiated with tuple types as one
of the arguments causing C compiler errors under some circumstances.

## Details

* the type merging logic in `mirtypes` now uses `sighashes`, which is
  able to handle cyclic types
* previously, `Obj[(int,)]` and `Obj[tuple[x: int]]` were not being
  merged into one when `Obj` is cyclic
* this led to C compiler errors when assigning between such types, or
  when the type has hooks (explicit or synthesized) that are called
  • Loading branch information
zerbina authored Aug 5, 2024
1 parent f5d8ce9 commit f110824
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 5 deletions.
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

0 comments on commit f110824

Please sign in to comment.