Skip to content

Exponential Expansion of Shared Type Aliases #403

Description

@Sahilgill24

Project version

0.7.2

Project

compiler

What happened?

The compiler can represent nested type aliases very compactly by sharing their underlying Arc nodes. This means a sequence of aliases such as:

type A0 = u8;
type A1 = (A0, A0);
type A2 = (A1, A1);
type A3 = (A2, A2);
...

forms a small DAG rather than storing the fully expanded type. With N aliases, the stored representation is therefore roughly linear in size.

when this type is later used impl From<&ResolvedType> for StructuralType (src/types.rs:1175) traverses the type using post_order_iter(). The TreeLike implementation for &ResolvedType (src/types.rs:571) returns the child Arcs, but the traversal does not deduplicate already-seen nodes by pointer identity.

As a result, when the same alias is referenced multiple times, the compiler walks the same underlying subtree again for every path that reaches it. So a depth of N can therefore result in roughly 2^N leaf visits.
This was my observation.

depth 16: 0.39 s
depth 20: 5.74 s
depth 22: 23.9 s

Minimal reproduction steps

This is one of the examples that demonstrates the bug

type A0 = u8;
type A1 = (A0, A0);
type A2 = (A1, A1);
type A3 = (A2, A2);
type A4 = (A3, A3);
type A5 = (A4, A4);
type A6 = (A5, A5);
type A7 = (A6, A6);
type A8 = (A7, A7);
type A9 = (A8, A8);
...
type A30 = (A29, A29);
fn main() { let _x: A30 = witness::W; }

trying to compile this leads to the compiler being hung.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions