Skip to main content

import

A declaration bringing another module's top-level declarations into this file's scope, either behind an alias or one element at a time. It names the target by the module's full name, package included.

An import needs a module to name, so every example here is two files. The line between them is where one file ends and the next begins.

module radar::sensors.contacts

extensible struct Contact {
    contact_id: uint32;
}

// ────────────────────────────

module radar::display.tracks
import radar::sensors.contacts as c

const watched: c.Contact = c.Contact { contact_id = 4; };

Forms​

An alias import is import M as a. An elements import is import M (Foo, Bar), and an element may be renamed for this file with =>.

  • An alias binds one name. Every top-level declaration of the target is reached through it as a.Name, and an enum member or variant constructor as a.Name.Member.
  • An elements import binds each named declaration under its own name, and its members with it.
  • Foo => Bar binds the declaration as Bar here. Its members come with it under the new name.
  • A module may be imported more than once — under several aliases, and by alias and by element at once.
  • An imported declaration keeps the qualified name of the module that declares it.
  • A contract is not an importable element.
module radar::sensors.contacts

enum Mode uint8 {
    Search = 0;
    Track = 1;
}

const max_range_m: int32 = 40000;

function clamp_range(v: int32) -> int32 = if v > max_range_m then max_range_m else v;

// ────────────────────────────

module radar::display.tracks
import radar::sensors.contacts as c
import radar::sensors.contacts (Mode => SensorMode, clamp_range)

const mode: SensorMode = SensorMode.Track;
const other: c.Mode = c.Mode.Search;
const held_m: int32 = clamp_range(50000);
Wildcard Imports

Flex has no wildcard import: every element an import brings in is named, either behind an alias or in the element list. The declaration behind an identifier is then always findable from the file that uses it.

Scope​

An import injects its names before any reference is resolved, so a declaration may use an imported name written above or below it.

  • A name an import binds may not collide with one this file declares, or with one another import binds.
  • A declaration reached through an import brings only itself. What its own body uses resolves in the module that declares it, so clamp_range above reads max_range_m without the caller importing it.
  • A module that is not part of the project resolves to nothing, and so does an element the target does not declare.

Errors​

Importing a module the project does not hold​

module radar::display.tracks
import radar::sensors.contacts as c   // error: unresolved-reference

Naming an element the module does not declare​

module radar::sensors.contacts

struct Contact { contact_id: uint32; }

// ────────────────────────────

module radar::display.tracks
import radar::sensors.contacts (TrackReport)   // error: unresolved-reference

An imported name this file already declares​

module radar::sensors.contacts

struct Contact { contact_id: uint32; }

// ────────────────────────────

module radar::display.tracks
import radar::sensors.contacts (Contact)   // error: import-conflict

struct Contact { contact_id: uint32; }

Importing a contract​

module radar::sensors.contacts

const max_range_m: int32 = 40000;

contract range_is_positive { assert max_range_m > 0; }

// ────────────────────────────

module radar::display.tracks
import radar::sensors.contacts (range_is_positive)   // error: unresolved-reference

The same element twice in one import​

module radar::sensors.contacts

struct Contact { contact_id: uint32; }

// ────────────────────────────

module radar::display.tracks
import radar::sensors.contacts (Contact, Contact)   // error: import-conflict, duplicate-import-element
  • module — the header an import names, and the one it has to follow.
  • identifiers — what the names on either side of => may be.