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). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased] ## [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 ## [0.11.6] - 2023-01-26
### Added ### Added

View file

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