abstract class Crystal::Type
inherits Reference
¶
Abstract base class of all types
Included modules
Crystal::Annotatable
Direct known subclasses
Crystal::GenericClassInstanceMetaclassType
Crystal::GenericInstanceType
Crystal::GenericModuleInstanceMetaclassType
Crystal::LiteralType
Crystal::NamedType
Crystal::TypeParameter
Crystal::TypeSplat
Crystal::UnionType
Crystal::VirtualMetaclassType
Crystal::VirtualType
Constants¶
ONE_ARG = [Arg.new("a1")]
¶
[Arg.new("a1")]
SuggestableDefName = /\A[a-z_]/
¶
/\A[a-z_]/
Class methods¶
Methods¶
#abstract_leaf?
¶
Returns true
if this type is abstract and it has no
concrete subclasses. This can happen if this type has abstract
subclasses, or non-abstract generic subclasses without instantiations.
#all?
¶
Yields self and returns true if the block returns a truthy value. UnionType overrides it and yields all types in turn and returns true if for each of them the block returns true.
#all_subclasses
¶
Returns all subclasses of this type, including subclasses of subclasses recursively.
#allowed_in_lib?
¶
Returns true
if this type can be used in a lib declaration:
in a fun, struct/union member, or typedef.
#allows_instance_vars?
¶
Returns true
if this type can have instance vars.
Primitive types, and types like Reference and Object,
can't have instance vars.
#can_be_stored?
¶
Returns true
if this type can be assigned to an instance or class
variable, or used in a generic type argument.
As of now, abstract base type such as Object, Reference, Value,
Int, and unbound generic types such as Array(T)
, can't be stored.
#check_restriction_exception
¶
Checks whether an exception needs to be raised because of a restriction failure. Only overwritten by literal types (NumberLiteralType and SymbolLiteralType) when they produce an ambiguous call.
#class_var_owner
¶
Returns the type that owns class vars for a type.
This method returns self, but subclasses might override. For example, a metaclass' class_var_owner is the instance type.
#defs : Hash(String, Array(DefWithMetadata))?
¶
: Hash(String, Array(DefWithMetadata))?
Returns the methods defined in this type, indexed by their name. This does not include methods defined in ancestors.
#devirtualize
¶
Returns the non-virtual type of a given type (returns self if self is already non-virtual)
#each_namespace(& : ModuleType -> ) : Nil
¶
(& : ModuleType -> ) : Nil
Yields each namespace this type belongs to, excluding the Program
itself.
#extern?
¶
Returns true
if this is an extern C struct or union (extern_union?
tells which one)
#has_inner_pointers?
¶
Returns true
if the type has inner pointers.
This is useful to know because if a type doesn't have
inner pointers we can use malloc_atomic
instead of
malloc
in Pointer.malloc
for a tiny performance boost.
This behaviour is documented in Pointer.malloc
#has_protected_access_to?(type, allow_same_namespace = true)
¶
(type, allow_same_namespace = true)
Determines if self
can access type assuming it's a protected
access.
If allow_same_namespace
is true (the default), protected
also means
the types are in the same namespace. Otherwise, it means they are just
in the same type hierarchy.
#implicitly_converted_in_c_to?(expected_type)
¶
(expected_type)
Returns true
if this type can be implicitly converted to
expected_type
when this is a lib fun argument, without
involving to_unsafe
or numeric conversions.
For example nil
can be passed to an argument of type pointer.
#inspect(io : IO) : Nil
¶
(io : IO) : Nil
Appends a String representation of this object which includes its class name, its object address and the values of all instance variables.
class Person
def initialize(@name : String, @age : Int32)
end
end
Person.new("John", 32).inspect # => #<Person:0x10fd31f20 @name="John", @age=32>
#lookup_defs(name : String, all_defs : Array(Def), lookup_ancestors_for_new : Bool? = false)
¶
(name : String, all_defs : Array(Def), lookup_ancestors_for_new : Bool? = false)
#lookup_macro(name, args : Array, named_args)
¶
(name, args : Array, named_args)
Looks up a macro with the given name and matching the given args
and named_args. Returns:
- a Macro
, if found
- nil
, if not found
- DefInMacroLookup
if not found and a Def was found instead
In the case of DefInMacroLookup
, it means that macros shouldn't
be looked up in implicit enclosing scopes such as Object
or the Program.
#lookup_macros(name)
¶
(name)
Looks up macros with the given name. Returns:
- an Array of Macro if found
- nil
if not found
- DefInMacroLookup
if not found and some Defs were found instead
#lookup_matches(signature, owner = self, path_lookup = self, matches_array = nil, analyze_all = false)
¶
(signature, owner = self, path_lookup = self, matches_array = nil, analyze_all = false)
#lookup_matches_with_modules(signature, owner = self, path_lookup = self, matches_array = nil, analyze_all = false)
¶
(signature, owner = self, path_lookup = self, matches_array = nil, analyze_all = false)
#lookup_matches_without_parents(signature, owner = self, path_lookup = self, matches_array = nil, analyze_all = false)
¶
(signature, owner = self, path_lookup = self, matches_array = nil, analyze_all = false)
#lookup_new_in_ancestors?
¶
Should new
be looked up in ancestors?
This is true
if this type doesn't define any
initialize
methods.
#lookup_path(names : Array(String), lookup_in_namespace = true, include_private = false, location = nil) : Type | ASTNode | Nil
¶
(names : Array(String), lookup_in_namespace = true, include_private = false, location = nil) : Type | ASTNode | Nil
Looks up a path (for example: Foo::Bar::Baz
) relative to self
.
For example, given:
class Foo
class Bar
class Baz
end
end
end
If self
is Foo
and we invoke lookup_path(["Bar", "Baz"])
on it,
we'll get Foo::Bar::Baz
as the return value.
The path is searched in the current type's ancestors, and optionally in its namespace, according to lookup_in_namespace.
Returns nil
if the path can't be found.
include_private controls whether private types are found inside other types (when doing Foo::Bar, Bar won't be found if it's private).
location can be passed and is the location where the lookup happens, and is useful to find file-private types.
The result can be an ASTNode
in the case the path denotes a type variable
whose variable is an ASTNode
. One such example is the N
of StaticArray(T, N)
for some instantiated StaticArray
.
If the path is global (for example ::Foo::Bar), the search starts at the top level.
#lookup_path(path : Path, lookup_in_namespace = true, include_private = false, location = path.location) : Type | ASTNode | Nil
¶
(path : Path, lookup_in_namespace = true, include_private = false, location = path.location) : Type | ASTNode | Nil
Looks up a path (for example: Foo::Bar::Baz
) relative to self
.
For example, given:
class Foo
class Bar
class Baz
end
end
end
If self
is Foo
and we invoke lookup_path(["Bar", "Baz"])
on it,
we'll get Foo::Bar::Baz
as the return value.
The path is searched in the current type's ancestors, and optionally in its namespace, according to lookup_in_namespace.
Returns nil
if the path can't be found.
include_private controls whether private types are found inside other types (when doing Foo::Bar, Bar won't be found if it's private).
location can be passed and is the location where the lookup happens, and is useful to find file-private types.
The result can be an ASTNode
in the case the path denotes a type variable
whose variable is an ASTNode
. One such example is the N
of StaticArray(T, N)
for some instantiated StaticArray
.
If the path is global (for example ::Foo::Bar), the search starts at the top level.
#lookup_path_item(name : String, lookup_in_namespace, include_private, location) : Type | ASTNode | Nil
¶
(name : String, lookup_in_namespace, include_private, location) : Type | ASTNode | Nil
Looks up a single path item relative to *self`.
If lookup_in_namespace is true
, if the type is not found
in self
or self
's parents, the path item is searched in this
type's namespace. This parameter is useful because when writing
Foo::Bar::Baz
, Foo
should be searched in enclosing namespaces,
but Bar
and Baz
not.
#lookup_type(node : ASTNode, self_type = self.instance_type, allow_typeof = true, free_vars : Hash(String, TypeVar)? = nil, find_root_generic_type_parameters = true) : Type
¶
(node : ASTNode, self_type = self.instance_type, allow_typeof = true, free_vars : Hash(String, TypeVar)? = nil, find_root_generic_type_parameters = true) : Type
Searches the type that corresponds to the given node, relative
to self
.
This method handles AST nodes in the type grammar:
- Path: Foo::Bar::Baz
- Union: T | U
- Metaclass: T.class
- Generic: Foo(T)
- ProcNotation: T -> U
- TypeOf: typeof(...)
- Self: self
Passing other AST nodes will raise an exception.
self_type is the type that will be used when self
is encountered
in the node.
If allow_typeof is false
, this method raises if there's a typeof
in the given node.
If free_vars is given, when resolving a Path, types will be first searched in the given Hash.
If find_root_generic_type_parameters is true
(the default), type parameters
relative to self_type
will be found. If false
, they won't be found.
For example, given:
class Foo
class Bar(T)
end
class Baz
end
end
If self
is Foo
and Bar(Baz)
is given, the result will be Foo::Bar(Baz)
.
#lookup_type?(node : ASTNode, self_type = self.instance_type, allow_typeof = true, free_vars : Hash(String, TypeVar)? = nil, find_root_generic_type_parameters = true) : Type?
¶
(node : ASTNode, self_type = self.instance_type, allow_typeof = true, free_vars : Hash(String, TypeVar)? = nil, find_root_generic_type_parameters = true) : Type?
Similar to lookup_type
, but returns nil
if a type can't be found.
#lookup_type_var(node : Path, free_vars : Hash(String, TypeVar)? = nil, find_root_generic_type_parameters = true, remove_alias = true) : Type | ASTNode
¶
(node : Path, free_vars : Hash(String, TypeVar)? = nil, find_root_generic_type_parameters = true, remove_alias = true) : Type | ASTNode
Similar to lookup_type
, but the result might also be an ASTNode, for example when
looking N
relative to a StaticArray.
#lookup_type_var?(node : Path, free_vars : Hash(String, TypeVar)? = nil, raise = false, find_root_generic_type_parameters = true) : Type | ASTNode | Nil
¶
(node : Path, free_vars : Hash(String, TypeVar)? = nil, raise = false, find_root_generic_type_parameters = true) : Type | ASTNode | Nil
Similar to lookup_type_var
, but might return nil
.
#macros : Hash(String, Array(Macro))?
¶
: Hash(String, Array(Macro))?
Returns all macros defines in this type, indexed by their name. This does not include methods defined in ancestors.
#metaclass : Type
¶
: Type
Returns this type's metaclass, which holds class methods for this type.
#namespace : ModuleType
¶
: ModuleType
The namespace this type belongs to. Every type belongs to
a namespace, and, when not explicit, the namespace is the Program
itself.
#opaque_id
¶
An opaque id of every type. 0 for Nil, non zero for others, so we can sort types by opaque_id and have Nil in the beginning.
#packed?
¶
Returns true
if this type has the @[Packed]
annotation on it
(only applicable for C structs)
#passed_as_self?
¶
Returns true
if this type is passed as a self
argument
in the codegen phase. For example a method whose receiver is
the Program, or a Metaclass, doesn't have a self
argument.
#passed_by_value?
¶
Returns true
if this type passed by value (if it's not a primitive type).
In the codegen phase these types are passed as byval pointers.
#reference_like?
¶
Returns true
if this type inherits from Reference
or if this
is a union type where all types are reference types or nil.
In this case this type can be represented with a single pointer.
#replace_type_parameters(instance) : Type
¶
(instance) : Type
Replace type parameters in this type with the type parameters of the given instance type.
#sizeof_type
¶
Returns the type that has to be used in sizeof and instance_sizeof computations
#to_s(io : IO) : Nil
¶
(io : IO) : Nil
Appends a short String representation of this object which includes its class name and its object address.
class Person
def initialize(@name : String, @age : Int32)
end
end
Person.new("John", 32).to_s # => #<Person:0x10a199f20>
abstract
#to_s_with_options(io : IO, skip_union_parens : Bool = false, generic_args : Bool = true, codegen : Bool = false) : Nil
¶
(io : IO, skip_union_parens : Bool = false, generic_args : Bool = true, codegen : Bool = false) : Nil
#type_var?(name)
¶
(name)
Returns true if name if an unbound type variable in this (generic) type.