# Imports

> Files are structs, and pub controls the boundary.

```zig
const std = @import("std");
const expect = std.testing.expect;

// A relative path imports another source file. The result is a struct type
// whose declarations are that file's `pub` declarations.
const shapes = @import("_shapes.zig");

test "use an imported declaration" {
    try expect(shapes.double(21) == 42);
}

test "imported types work like any other" {
    const c = shapes.Circle{ .radius = 2 };
    try expect(c.area() > 12.5 and c.area() < 12.6);
}

test "a file is a struct" {
    // `@This()` inside a file refers to that file's implicit struct type,
    // which is why `@import` can return something you access with `.`.
    try expect(@TypeOf(shapes) == type);
    try expect(shapes.pi > 3.14);
}

test "std is just another import" {
    // `@import("std")` is the same mechanism, resolved by the compiler
    // rather than by path.
    try expect(std.mem.eql(u8, "a", "a"));
}
```

*Runnable: compiled to WebAssembly and executed by CI against Zig master. (`02-language.imports`)*

`@import` takes a path and returns that file **as a struct type**:

```zig
const shapes = @import("_shapes.zig");
shapes.Circle{ .radius = 2 };
```

There is no separate module system to learn. A file is a struct, `@import`
evaluates it, and you access its declarations with `.` like any other struct.

## `pub` is the boundary

Only `pub` declarations are visible to importers. Everything else is private to
the file:

```zig
pub const pi = 3.14159;   // visible
const secret = 42;        // not
```

This is the whole visibility system: no `private`, no header files, no export
lists.

## `@import("std")` is not special

The standard library is imported by the same mechanism; the name is resolved by
the compiler rather than by path. Package dependencies declared in
`build.zig.zon` work the same way, imported by their package name.

## Import cycles

Two files may import each other. Zig resolves declarations lazily, so this
works as long as you do not create a genuine cycle in *values*: a `const` in A
whose initialiser needs a `const` in B whose initialiser needs the one in A.
