-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Ensure Enumerable#to_a
and Enumerable#tally
properly retain return type of T
#14447
Conversation
Welp, seems wasm and macos don't like this new spec? Also seemingly run into #13193 when manually running $ make std_spec
Using /usr/bin/llvm-config [version=17.0.6]
./bin/crystal build -D strict_multi_assign -D preview_overload_order -Dwithout_interpreter --exclude-warnings spec/std --exclude-warnings spec/compiler --exclude-warnings spec/primitives -o .build/std_spec spec/std_spec.cr
Using compiled compiler at .build/crystal
.build/std_spec --order=random
.build/std_spec: symbol lookup error: .build/std_spec: undefined symbol: __libc_start_main, version spec/std/spec/filters_spec.cr:124
make: *** [Makefile:106: std_spec] Error 127 But both |
#to_a
returns T
#itself
properly retains T
#itself
properly retains T
Enumerable
methods properly retains return type of T
Enumerable
methods properly retains return type of T
Enumerable#to_a
and Enumerable#tally
properly retain return type of T
Yeah, something's really funky about the failures on macos and wasm. How can this introduce an illegal instruction? 🤔 |
I'm actually able to reproduce this on my intel mac with LLVM 17. Reproduces when running the whole of I'll play around with it and see if I can get a more minimal example... Cut down the specs to:
require "spec"
module SomeInterface; end
private record One do
include SomeInterface
end
private record Two do
include SomeInterface
end
private struct InterfaceEnumerable
include Enumerable(SomeInterface)
def each(&)
yield One.new
yield Two.new
end
end
describe "Enumerable" do
it "tallies an interface type" do
InterfaceEnumerable.new.tally.should eq({One.new => 1, Two.new => 1})
end
end
require "spec"
module OtherInterface; end
private record One do
include OtherInterface
end
private record Two do
include OtherInterface
end
private struct InterfaceIndexable
include Indexable(OtherInterface)
def size
2
end
def unsafe_fetch(index : Int) : OtherInterface
case index
when 0 then One.new
when 1 then Two.new
else
raise ""
end
end
end
describe Indexable do
describe "#to_a" do
it "without a block of an interface type" do
InterfaceIndexable.new.to_a.should eq [One.new, Two.new]
end
end
end Running them together: $ ccrystal spec spec/std/indexable_spec.cr spec/std/enumerable_spec.cr --tap
Using compiled compiler at .build/crystal
ok 1 - Indexable(T) #to_a without a block of an interface type
Program exited because of an invalid instruction However creating a single file with the contents of both does not. |
I think the gist of this is it's caused by having two E.g. # test2.cr
module OtherInterface; end
private record One do
include OtherInterface
end
private record Two do
include OtherInterface
end
([One.new, Two.new] of OtherInterface) == [One.new, Two.new] Then: # test.cr
require "./test2"
module OtherInterface; end
private record One do
include OtherInterface
end
private record Two do
include OtherInterface
end
pp [One.new, Two.new] == [One.new, Two.new] Results in: $ crystal test.cr
Program exited because of an invalid instruction If I had to guess, I'd say something regarding the "private to the file" thing isn't working out exactly as we expect giving one or the other files a reference to the other? In regards to this PR, I'll rename the test types to not conflict and see if that helps. |
Fixes #14440