pub struct Module {
pub name: ModuleName,
pub exports: Exports,
pub exposing_span: NodeSpan,
pub infixes: HashMap<Name, Infix>,
pub types: HashMap<Name, UnionType>,
pub classes: HashMap<Name, Class>,
pub instances: Vec<Instance>,
pub imported_instances: Vec<PublishedInstance>,
pub values: HashMap<Name, Value>,
pub broken: Vec<Broken>,
pub binding_foreign: bool,
pub incomplete: bool,
}Expand description
A resolved module
Fields§
§name: ModuleName§exports: Exports§exposing_span: NodeSpanWhere the header’s exposing (...) was written — parser::Module::exposing_span,
carried through. A diagnostic about what the module exposes as a whole points here.
infixes: HashMap<Name, Infix>Operator name to infix details
types: HashMap<Name, UnionType>§classes: HashMap<Name, Class>Every class declaration that canonicalized, by name. A member is not in
values: it has a signature and no body, and the class carries it.
instances: Vec<Instance>Every instance declaration that passed every check, in source order.
imported_instances: Vec<PublishedInstance>Every instance this module’s imports brought into scope, each once.
to_interface publishes them beside the module’s own, which
is what carries an instance to every module that can reach its declaring one.
values: HashMap<Name, Value>§broken: Vec<Broken>The value declarations that were written and have no canonical form, sorted by name.
A declaration is here when its annotation or its body did not canonicalize, or, in
a facade, when its signature was rejected by the per-declaration checks; an error
beside the module says which. It is also here when a declaration chunk that failed
to parse names it ([parser::Module::failed]), whatever else of it parsed; the
syntax error says why, and only its annotation, when one parsed, is checked. The
checks that run on the whole signature list before those (FacadeConstrained and
a facade’s malformed context, UnsafeOutsideFacade) report an error and leave the
declaration where the per-declaration checks put it. Outside a facade, a context
is part of its annotation, and a declaration whose context does not resolve is
here with no type.
Every other value declaration is in values, and no name is in
both. What survives of one is its annotation, when that canonicalized:
to_interface exposes it and the typer declares it, so a
caller of a broken declaration is checked against the type it was written with.
binding_foreign: boolTrue when this module is a module foreign facade.
Such modules have synthetic placeholder bodies and must not be type-checked.
incomplete: boolWhether a name could be missing from this module for a reason already reported.
Set when the module’s scope ended incomplete: an import did not resolve, an
import resolved to an Interface whose own
incomplete is set, a type, infix, class or
instance declaration failed, or a declaration chunk that names nothing failed to
parse. Also set when a
value declaration was written with an annotation that did not canonicalize, or is
named by a chunk that failed to parse and has no type, since its annotation may be
that chunk: those are the two ways a name goes missing from
to_interface while the module’s own scope is whole.
to_interface copies it to Interface::incomplete.
Implementations§
Source§impl Module
impl Module
Sourcepub fn to_interface(&self, file: Option<SourceFileId>) -> Interface
pub fn to_interface(&self, file: Option<SourceFileId>) -> Interface
Build the trimmed-down view of this module other modules import against.
file is the SourceFileId this module was read from, which is what lets
a later module’s diagnostic point back into this module’s source — see
Interface::file. It is a parameter rather than
something this method could work out because a canonical::Module does not
know it: only driver code does, and the sole caller
(dependencies::ModuleWalker::check_in_order) is driver code that has the
map from module name to file in hand. A caller with nothing to give — every
test that hand-builds an interface — passes None, and
Interface::source_span then declines to
build a cross-module label rather than building one at the wrong place.
§What the exposing (...) header removes here
This is the only place a module’s own Exports is read, and reading it
here is what makes a declaration left out of the header private (BUG-9).
self.values, self.types and self.infixes stay complete — the typer,
exhaustiveness and every later phase run against the whole
Module, because a private declaration is still callable from
inside the module that wrote it. Only this external view is trimmed, and
only by three rules:
- a value reaches the interface when the header exposes its name as
ExportType::Value, on top of the requirement that it carry a type annotation (Value::TypedValue).do_exportsreports an exposed, unannotated declaration (SPEC-5), and the declaration is left out here. ABrokendeclaration the header exposes reaches the interface the same way when its annotation canonicalized, with that annotation as its type, so an importer is checked against it; - an infix reaches it when the header exposes the operator;
- a union type reaches it when the header names it either way, but a
Sizeentry (ExportType::UnionPrivate) hands over the declaration with itsvariantsemptied, and records its name inInterface::opaque_unions. That is the opaque type: importers still get the name and its type variables —Interface::unionsis whereprocess_import’sPrivacy::Privatearm reads the arity from — and no constructor to build or match one with.
A class reaches it, with every member and the derivations it carries, when the
header names it (ExportType::Class).
Exports::Everything — a exposing (..) header — exposes every
declaration with every constructor, so nothing is dropped in that case.
§What the header does not remove
Every instance reaches the interface: the module’s own, and every one its imports
brought into scope (imported_instances). An instance
has no name for a header to list, and it has to be in scope in every module that
can reach the module declaring it, through however many imports, so each module
passes on what it received
(Type classes).
An exposed infix whose backing function is not itself separately exposed
— infix left 6 (+) = add with (+) in the header and add not, which
is every operator std/core declares — still needs add’s type
reachable, or an importer that brings (+) into scope has no type to
give a use of it. Interface::infix_functions carries exactly that,
kept out of values itself so add stays unreachable under its own
name.
Sourcepub fn emitted_arity(&self, value: &Value) -> usize
pub fn emitted_arity(&self, value: &Value) -> usize
How many parameters value, one of this module’s declarations, is emitted with:
the count a call has to supply to be a direct call.
For a declaration with a body that is Value::arity, the parameters it was
written with. A module foreign facade’s declaration is a signature with no
parameters to count, and its forwarding function takes one parameter per arrow in
the signature (Type::arrow_count), the plain parameter
list its companion’s
export takes.
to_interface records it for each exported value, so that
an importer’s call site is saturated at the same count this module’s own call
sites are.