pub struct Signature {
pub receiver: Option<Ty>,
pub params: Vec<Ty>,
pub ret: Ty,
}Expand description
A declaration’s boundary, as the checker resolved it for that body.
Every type here is the one the checker held while it walked this declaration’s body, not a re-derivation from the source: an annotation is resolved once, against the module it was written in, and this is that answer rather than a second reading of it.
The three parts are kept apart the way a declaration keeps them. params
is in declaration order and holds one entry per written parameter;
receiver is the type of self and is Some only for a method, so a
consumer that has to place arguments knows the receiver comes first
without inferring it from a count. ret is Ty::Unit for a declaration
with no ->, because a function with no declared return type returns
() and that is a settled type rather than an absence.
§Three kinds of declaration have one
A function or a method, written with a fn; a struct, whose initializer
Point(x: 0.0) is a call the checker synthesizes a signature for out of
the fields, so params is the field types in declaration order; and one
case of an enum, whose params is its payload types. The last two are
what publishes a declared type’s shape — the only other thing that knows
it is the lowering, which turns it into slot numbers and keeps no names.
A struct’s and a case’s types are the declaration’s own, so a generic
declaration records the Ty::Param it was written with; a consumer
holding a use completes them with Ty::instantiate.
Fields§
§receiver: Option<Ty>The type of self, for a method, and nothing for a free function.
params: Vec<Ty>The declared parameters, in declaration order, receiver excluded.
§Which question this answers
What a call supplies, not what the callee’s binding holds. The two are the same type for every parameter shape but one, and the exception is worth stating because a consumer that reads this field as the second question gets a wrong answer silently.
A variadic parameter is recorded as its element type, because a
call site passes elements: fn count(items: Int...) records Int
here. Inside the body items is the Array<Int> the callee made of
them, and nothing in this struct says so. A consumer that needs the
binding’s type reads variadic off the declaration’s own Param and
wraps — which is what cove_ir::lower does too, after first asking
this field and being told Int.
A var parameter needs no such note: it names the caller’s storage,
and the type of that storage is the type recorded here. What a var
changes is where the binding lives, not what it holds, and this
struct records no marking at all.
ret: TyWhat a call to this declaration answers.