class Base
@@current : self?
property prev : self?
def push_self_to_current
@prev = @@current
@@current = self
end
end
class Gen(T) < Base
end
Gen(Int32).new.push_self_to_current
result in compiler error
cast from Crystal::GenericClassInstanceType to Crystal::ClassVarContainer failed, at /home/firejox/develop/crystal/src/compiler/crystal/semantic/semantic_visitor.cr:436
0x74d7a7: *CallStack::unwind:Array(Pointer(Void)) at ??
0x74d73a: *CallStack#initialize:Array(Pointer(Void)) at ??
0x74d70a: *CallStack::new:CallStack at ??
0x73fa0e: *raise<TypeCastError>:NoReturn at ??
0x1131bf5: ??? at ??
0x11318ad: *Crystal::MainVisitor#lookup_class_var<Crystal::ClassVar>:Crystal::MetaTypeVar at ??
0x11339ed: *Crystal::MainVisitor#visit_class_var<Crystal::ClassVar>:Crystal::MetaTypeVar at ??
0x113c990: *Crystal::MainVisitor#visit<Crystal::ClassVar>:Bool at ??
0xb97d03: *Crystal::ASTNode+ at ??
0x113d50d: *Crystal::MainVisitor#type_assign<Crystal::InstanceVar, Crystal::ASTNode+, Crystal::Assign>:Nil at ??
0x113cd26: *Crystal::MainVisitor#visit<Crystal::Assign>:Bool at ??
0xb97d65: *Crystal::ASTNode+ at ??
0xc0cd59: *Crystal::Expressions#accept_children<Crystal::MainVisitor>:Array(Crystal::ASTNode+) at ??
0xb9a01e: *Crystal::ASTNode+ at ??
0xf04e18: *Crystal::Call#instantiate<Crystal::Matches, Crystal::Type+, Nil, (Array(Crystal::NamedArgumentType) | Nil)>:Array(Crystal::Def+) at ??
0xeff6dc: *Crystal::Call#lookup_matches_in_type<Crystal::Type+, Array(Crystal::Type+), (Array(Crystal::NamedArgumentType) | Nil), Nil, String, Bool>:Array(Crystal::Def+) at ??
0xefdb6d: *Crystal::Call#lookup_matches_in<Crystal::Type+, Array(Crystal::Type+), (Array(Crystal::NamedArgumentType) | Nil), Nil, String, Bool>:Array(Crystal::Def+) at ??
0xf0598a: *Crystal::Call#lookup_matches_in<Crystal::Type+, Array(Crystal::Type+), (Array(Crystal::NamedArgumentType) | Nil)>:Array(Crystal::Def+) at ??
0xee3f66: *Crystal::Call#lookup_matches_without_splat<Array(Crystal::Type+), (Array(Crystal::NamedArgumentType) | Nil)>:Array(Crystal::Def+) at ??
0xee33d2: *Crystal::Call#lookup_matches:Array(Crystal::Def+) at ??
0xec585f: *Crystal::Call#recalculate:(Array(Crystal::ASTNode+) | Array(Crystal::Def+) | Nil) at ??
0x1134d2c: *Crystal::MainVisitor#visit<Crystal::Call>:Bool at ??
0xb97f51: *Crystal::ASTNode+ at ??
0xc0cd59: *Crystal::Expressions#accept_children<Crystal::MainVisitor>:Array(Crystal::ASTNode+) at ??
0xb9a01e: *Crystal::ASTNode+ at ??
0x885f4b: *Crystal::Program#visit_main<Crystal::ASTNode+, Crystal::MainVisitor, Bool>:Crystal::ASTNode+ at ??
0x885efe: *Crystal::Program#visit_main:process_finished_hooks<Crystal::ASTNode+, Bool>:Crystal::ASTNode+ at ??
0x87b179: *Crystal::Program#semantic<Crystal::ASTNode+, Bool>:Crystal::ASTNode+ at ??
0xfccea4: *Crystal::Compiler#compile<Array(Crystal::Compiler::Source), String>:Crystal::Compiler::Result at ??
0xfd3ab9: *Crystal::Command::CompilerConfig#compile<String>:Crystal::Compiler::Result at ??
0x8530ed: *Crystal::Command#run_command<Bool>:Nil at ??
0x84f1e1: *Crystal::Command#run:(Array(Crystal::ImplementationTrace) | Array(Crystal::Init::View+:Class) | Array(String) | Bool | Crystal::Compiler::Result | Hash(String, String) | IO::FileDescriptor | Nil) at ??
0x84e8db: *Crystal::Command::run<Array(String)>:(Array(Crystal::ImplementationTrace) | Array(Crystal::Init::View+:Class) | Array(String) | Bool | Crystal::Compiler::Result | Hash(String, String) | IO::FileDescriptor | Nil) at ??
0x84e899: *Crystal::Command::run:(Array(Crystal::ImplementationTrace) | Array(Crystal::Init::View+:Class) | Array(String) | Bool | Crystal::Compiler::Result | Hash(String, String) | IO::FileDescriptor | Nil) at ??
0x72af79: ??? at ??
0x739a99: main at ??
0x7f7b69018291: __libc_start_main at ??
0x72a0fa: _start at ??
0x0: ??? at ??
Crystal 0.20.1+55 [60bf3cd] (2016-12-16)
https://play.crystal-lang.org#/r/1ghv
Hmmm.. Right now one can't use class variables in generic types:
class Foo(T)
@@bar = 1 # Error: can't use class variables in generic types
end
This is probably why it explodes in the above case, the variable is being inherited by generic types.
I think the correct solution to this is to allow class variables in generic types, and every generic instance will share the same value. Then the above example will start to work.
Next code is parsed normally when there is nor eference to #new:
class Dummy(T)
@@counter = 0
def self.new
@@counter += 1
super
end
end
But with:
it { Dummy(Bool).new.should_not be_nil }
It fails with:
Error in line 1: while requiring
"./spec/simple.cr": cast fromCrystal::GenericClassInstanceTypetoCrystal::ClassVarContainerfailed, at /crystal/src/compiler/crystal/semantic/semantic_visitor.cr:464:5:464
So it looks to be still broken :(
Crystal 0.24.2 [4f9ed8d03] (2018-03-08)
LLVM: 4.0.0
Default target: x86_64-unknown-linux-gnu
Most helpful comment
Hmmm.. Right now one can't use class variables in generic types:
This is probably why it explodes in the above case, the variable is being inherited by generic types.
I think the correct solution to this is to allow class variables in generic types, and every generic instance will share the same value. Then the above example will start to work.