Workaround issue using Box with union

Addresses issue found relating to https://gitlab.com/arctic-fox/spectator/-/issues/81
See https://github.com/crystal-lang/crystal/issues/11839
This commit is contained in:
Michael Miller 2023-03-27 18:37:50 -06:00
parent 3852606b28
commit 9cbb5d2cf7
No known key found for this signature in database
GPG key ID: AC78B32D30CE34A2
2 changed files with 18 additions and 13 deletions

View file

@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Fixed
- Fix memoized value (`let`) with a union type causing segfault. [#81](https://gitlab.com/arctic-fox/spectator/-/issues/81)
## [0.11.6] - 2023-01-26
### Added

View file

@ -13,18 +13,13 @@ module Spectator
# Creates a wrapper for the specified value.
def initialize(value)
@pointer = Box.box(value)
@pointer = Value.new(value).as(Void*)
end
# Retrieves the previously wrapped value.
# The *type* of the wrapped value must match otherwise an error will be raised.
def get(type : T.class) : T forall T
{% begin %}
{% if T.nilable? %}
@pointer.null? ? nil :
{% end %}
Box(T).unbox(@pointer)
{% end %}
@pointer.unsafe_as(Value(T)).get
end
# Retrieves the previously wrapped value.
@ -39,12 +34,20 @@ module Spectator
# type = wrapper.get { Int32 } # Returns Int32
# ```
def get(& : -> T) : T forall T
{% begin %}
{% if T.nilable? %}
@pointer.null? ? nil :
{% end %}
Box(T).unbox(@pointer)
{% end %}
@pointer.unsafe_as(Value(T)).get
end
# Wrapper for a value.
# Similar to `Box`, but doesn't segfault on nil and unions.
private class Value(T)
# Creates the wrapper.
def initialize(@value : T)
end
# Retrieves the value.
def get : T
@value
end
end
end
end