Thread overview
lazy import
5 days ago
xlogor
5 days ago
Paul Backus
5 days ago
xlogor
5 days ago
Paul Backus
5 days ago
monkyyy
5 days ago
xlogor
4 days ago
monkyyy
5 days ago

DIP Idea: Lazy Imports

I’d like to propose a DIP for adding lazy imports to D.

Motivation

D already has the lazy keyword for function parameters, which works wonders:

  • Arguments are only evaluated when (and if) actually used.
  • This avoids unnecessary work, prevents allocations, and gives a nice middle ground between eager and manual delegate passing.

It’s a proven feature that shows how well deferred evaluation fits into the language.

Currently, though, import in D is eager: all imported modules are parsed and semantically analyzed during compilation, regardless of whether their symbols are actually referenced. This can cause unnecessary compile-time costs, especially in large projects with deep dependency graphs.

A lazy import would extend the same philosophy of deferred evaluation to the module system: the compiler would defer full analysis of a module until it is actually needed (when a symbol from it is referenced). This reduces compile times and makes dependency management more efficient.

Proposed Syntax

lazy import std.big;

This would mean:

The compiler does not fully load/parse std.big at import time.

If no symbols from std.big are used, the module never impacts compilation.

If symbols are referenced, the compiler processes the module as usual.

Alternatively, the same effect could be achieved with an attribute-style approach:

@lazy import std.big;
5 days ago

On Friday, 3 October 2025 at 19:14:00 UTC, xlogor wrote:

>

A lazy import would extend the same philosophy of deferred evaluation to the module system: the compiler would defer full analysis of a module until it is actually needed (when a symbol from it is referenced). This reduces compile times and makes dependency management more efficient.

How will the compiler know whether a symbol from the module is referenced without parsing and semantically analyzing the module?

5 days ago

On Friday, 3 October 2025 at 19:14:00 UTC, xlogor wrote:

>

DIP Idea: Lazy Imports

I’d like to propose a DIP for adding lazy imports to D.

Motivation

D already has the lazy keyword for function parameters, which works wonders:

  • Arguments are only evaluated when (and if) actually used.
  • This avoids unnecessary work, prevents allocations, and gives a nice middle ground between eager and manual delegate passing.

It’s a proven feature that shows how well deferred evaluation fits into the language.

Currently, though, import in D is eager: all imported modules are parsed and semantically analyzed during compilation, regardless of whether their symbols are actually referenced. This can cause unnecessary compile-time costs, especially in large projects with deep dependency graphs.

A lazy import would extend the same philosophy of deferred evaluation to the module system: the compiler would defer full analysis of a module until it is actually needed (when a symbol from it is referenced). This reduces compile times and makes dependency management more efficient.

Proposed Syntax

lazy import std.big;

This would mean:

The compiler does not fully load/parse std.big at import time.

If no symbols from std.big are used, the module never impacts compilation.

If symbols are referenced, the compiler processes the module as usual.

Alternatively, the same effect could be achieved with an attribute-style approach:

@lazy import std.big;

All templates functions already are lazy, the std is slow because they get initialized; its a lack of initialization discipline combined with a worse of both worlds policys on templates.

5 days ago

On Friday, 3 October 2025 at 19:30:29 UTC, Paul Backus wrote:

>

On Friday, 3 October 2025 at 19:14:00 UTC, xlogor wrote:

>

A lazy import would extend the same philosophy of deferred evaluation to the module system: the compiler would defer full analysis of a module until it is actually needed (when a symbol from it is referenced). This reduces compile times and makes dependency management more efficient.

How will the compiler know whether a symbol from the module is referenced without parsing and semantically analyzing the module?

Perhaps this could be limited to renamed/static imports?

    lazy import big = std.big;
5 days ago

On Friday, 3 October 2025 at 20:18:45 UTC, monkyyy wrote:

>

On Friday, 3 October 2025 at 19:14:00 UTC, xlogor wrote:

>

DIP Idea: Lazy Imports

I’d like to propose a DIP for adding lazy imports to D.

Motivation

D already has the lazy keyword for function parameters, which works wonders:

  • Arguments are only evaluated when (and if) actually used.
  • This avoids unnecessary work, prevents al__cpLocations, and gives a nice middle ground between eager and manual delegate passing.

It’s a proven feature that shows how well deferred evaluation fits into the language.

Currently, though, import in D is eager: all imported modules are parsed and semantically analyzed during compilation, regardless of whether their symbols are actually referenced. This can cause unnecessary compile-time costs, especially in large projects with deep dependency graphs.

A lazy import would extend the same philosophy of deferred evaluation to the module system: the compiler would defer full analysis of a module until it is actually needed (when a symbol from it is referenced). This reduces compile times and makes dependency management more efficient.

Proposed Syntax

lazy import std.big;

This would mean:

The compiler does not fully load/parse std.big at import time.

If no symbols from std.big are used, the module never impacts compilation.

If symbols are referenced, the compiler processes the module as usual.

Alternatively, the same effect could be achieved with an attribute-style approach:

@lazy import std.big;

All templates functions already are lazy, the std is slow because they get initialized; its a lack of initialization discipline combined with a worse of both worlds policys on templates.

D compilers lack incremental compilation; lazy evaluation should be explored further.

5 days ago

On Saturday, 4 October 2025 at 08:54:16 UTC, xlogor wrote:

>

On Friday, 3 October 2025 at 19:30:29 UTC, Paul Backus wrote:

>

On Friday, 3 October 2025 at 19:14:00 UTC, xlogor wrote:

>

A lazy import would extend the same philosophy of deferred evaluation to the module system: the compiler would defer full analysis of a module until it is actually needed (when a symbol from it is referenced). This reduces compile times and makes dependency management more efficient.

How will the compiler know whether a symbol from the module is referenced without parsing and semantically analyzing the module?

Perhaps this could be limited to renamed/static imports?

    lazy import big = std.big;

I suppose that could work.

We could also consider treating renamed and static imports this way by default, without requiring the lazy keyword.

4 days ago

On Saturday, 4 October 2025 at 08:56:47 UTC, xlogor wrote:

>

On Friday, 3 October 2025 at 20:18:45 UTC, monkyyy wrote:

>

All templates functions already are lazy, the std is slow because they get initialized; its a lack of initialization discipline combined with a worse of both worlds policys on templates.

D compilers lack incremental compilation; lazy evaluation should be explored further.

Memorization only provides speed ups when it effects the whole pipeline. "Incremental compilation" which already exists and means a terrible idea where you build libs separately.

Push vs pull logistics clash and can easily produce worse of both world results. The c abi is push logistics, theres a push of files you given the compiler with headers and all golbal scope names these get pushed into a pipeline and a executable come out the other end. Templates, out of order evulation and in a sense modules, are pull logistics; modules need to be parsed but a (pure) template is not initialized as a named symbol until used, lerp!Rect maybe be valid but it doesn't exist until used, pulled.


The std and user base have a mix of takes on either embracing c norms or going with templates, you cant fix this with features. The std needs to have a compilation life time theory(we will see if the current plan improve things, Im mildly hopeful that the core vs upper end split will work by accident, but the core team are anti template)

The user base needs education or do find out what the hell these 90 minute compiles from a small minority come from.


We should go full "pull"; and incremental compilation is a "push" (anti-)feature. All imports are already lazy as they can be.

>

lazy import big = std.big;

If you want a lazy namespace so a import doesnt exist until called you could try

template big(){
  import big;
}

Then you call big!().writeln;

but this breaks the usual overload rules and ufcs so it cant be made a default behavior.

4 days ago
A proposal has been made for Python to add lazy imports.

https://pep-previews--4622.org.readthedocs.build/pep-0810/

These appear to be equivalent to our static imports + only evaluate that module on use.

-----

If a module is passed on the command line (and is a root), it cannot be lazy. It will be semantically analyzed in order.

This could only apply to import paths.

Furthermore the way the compiler works is in stages, a function body will be analyzed either when its required or after everything else in the module has been. For imports this extra step for function bodies is meant to be elided.

For this reason I see minimal benefit as it currently stands, given the above definitions.

Proof:

```d
module def;

void func() {
        sf;
}
```

```d
module app;
import def;

void main() {
        func;
}
```

```
$ dmd main.d
main.obj : error LNK2019: unresolved external symbol _D3def4funcFZv referenced in function _Dmain
main.exe : fatal error LNK1120: 1 unresolved externals
Error: linker exited with status 1120
       C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.41.34120\bin\HostX64\x64\link.exe /NOLOGO "main.obj"   /DEFAULTLIB:phobos64  /LIBPATH:"C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.41.34120\lib\x64" legacy_stdio_definitions.lib /LIBPATH:"C:\Program Files (x86)\Windows Kits\10\Lib\10.0.20348.0\ucrt\x64" /LIBPATH:"C:\Program Files (x86)\Windows Kits\10\lib\10.0.20348.0\um\x64"
Error: undefined reference to `void def.func()`
       referenced from `_Dmain`
       perhaps `.d` files need to be added on the command line, or use `-i` to compile imports
```