-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
always reinstantiate nominal values of generic instantiations (#24425)
fixes #22479, fixes #24374, depends on #24429 and #24430 When instantiating generic types which directly have nominal types (object, distinct, ref/ptr object but not enums[^1]) as their values, the nominal type is now copied (in the case of ref objects, its child as well) so that it receives a fresh ID and `typeInst` field. Previously this only happened if it contained any generic types in its structure, as is the case for all other types. This solves #22479 and #24374 by virtue of the IDs being unique, which is what destructors check for. Technically types containing generic param fields work for the same reason. There is also the benefit that the `typeInst` field is correct. However issues like #22445 aren't solved because the compiler still uses structural object equality checks for inheritance etc. which could be removed in a later PR. Also fixes a pre-existing issue where destructors bound to object types with generic fields would not error when attempting to define a user destructor after the fact, but the error message doesn't show where the implicit destructor was created now since it was only created for another instance. To do this, a type flag is used that marks the generic type symbol when a generic instance has a destructor created. Reusing `tfCheckedForDestructor` for this doesn't work. Maybe there is a nicer design that isn't an overreliance on the ID mechanism, but the shortcomings of `tyGenericInst` are too ingrained in the compiler to use for this. I thought about maybe adding something like `tyNominalGenericInst`, but it's really much easier if the nominal type itself directly contains the information of its generic parameters, or at least its "symbol", which the design is heading towards. [^1]: See [this test](https://github.com/nim-lang/Nim/blob/21420d8b0976dc034feb90ab2878ae0dd63121ae/lib/std/enumutils.nim#L102) in enumutils. The field symbols `b0`/`b1` always have the uninstantiated type `B` because enum fields don't expect to be generic, so no generic instance of `B` matches its own symbols. Wouldn't expect anyone to use generic enums but maybe someone does.
- Loading branch information
Showing
9 changed files
with
118 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
discard """ | ||
output: ''' | ||
int | ||
float | ||
''' | ||
""" | ||
|
||
# issue #22479 | ||
|
||
type Obj[T] = object | ||
|
||
proc `=destroy`[T](self: var Obj[T]) = | ||
echo T | ||
|
||
block: | ||
let intObj = Obj[int]() | ||
|
||
block: | ||
let floatObj = Obj[float]() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
discard """ | ||
output: ''' | ||
created Phantom[system.float] with value 1 | ||
created Phantom[system.string] with value 2 | ||
created Phantom[system.byte] with value 3 | ||
destroyed Phantom[system.byte] with value 3 | ||
destroyed Phantom[system.string] with value 2 | ||
destroyed Phantom[system.float] with value 1 | ||
''' | ||
""" | ||
|
||
# issue #24374 | ||
|
||
type Phantom[T] = object | ||
value: int | ||
# markerField: T | ||
|
||
proc initPhantom[T](value: int): Phantom[T] = | ||
doAssert value >= 0 | ||
echo "created " & $Phantom[T] & " with value " & $value | ||
result = Phantom[T](value: value) | ||
|
||
proc `=wasMoved`[T](x: var Phantom[T]) = | ||
x.value = -1 | ||
|
||
proc `=destroy`[T](x: Phantom[T]) = | ||
if x.value >= 0: | ||
echo "destroyed " & $Phantom[T] & " with value " & $x.value | ||
|
||
let | ||
x = initPhantom[float](1) | ||
y = initPhantom[string](2) | ||
z = initPhantom[byte](3) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
discard """ | ||
joinable: false | ||
cmd: "nim check $file" | ||
errormsg: "cannot bind another '=destroy' to: Foo; previous declaration was constructed implicitly" | ||
line: 15 | ||
""" | ||
|
||
type | ||
Foo[T] = object | ||
x: T | ||
|
||
proc main = | ||
var f: Foo[int] | ||
|
||
proc `=destroy`[T](f: var Foo[T]) = | ||
discard |