Files
scriptc/tests/diagnostics/contract-acyclic.ts
T
Malte Ubl 3ce9370b35 Acyclic contract type: classes and object types that cannot lie on a cycle
`class C implements Acyclic`, `interface I extends Acyclic` and
`type T = Acyclic<{ ... }>` promise that no chain of references leads
from such an object back to itself. The check is the cycle analysis that
decides tracing, so a proven type carries no cycle-collector header. When
it does not hold, SC7007 shows the cycle: the path of fields, and why it
can close (a field assigned after construction, with the first such
write; an array, Map or Set; a function, dynamic or promise field; a
subclass sharing the layout). cycle-analysis.ts gains explainCycle over
the same graph with edge labels; computeTraced is unchanged.

Acyclic elsewhere is reported with SC7006. Docs, @scriptc/types,
corpus 4642, diagnostics snapshots and TypeScript baselines included.
2026-10-11 16:30:24 -07:00

60 lines
1.3 KiB
TypeScript

// Acyclic contracts that do not hold: each diagnostic shows a reference
// cycle that can form.
import type { Acyclic } from "@scriptc/types";
class ListNode implements Acyclic {
value: number;
next: ListNode | undefined = undefined;
constructor(value: number) {
this.value = value;
}
}
class Task implements Acyclic {
readonly name: string;
readonly done: () => void;
constructor(name: string, done: () => void) {
this.name = name;
this.done = done;
}
}
class Graph implements Acyclic {
readonly nodes: GraphNode[] = [];
}
class GraphNode {
readonly graph: Graph;
constructor(graph: Graph) {
this.graph = graph;
}
}
class Shape implements Acyclic {
readonly id: number;
constructor(id: number) {
this.id = id;
}
}
class Group extends Shape {
readonly members: Shape[] = [];
}
interface Cell extends Acyclic {
value: number;
link: Cell | null;
}
const a = new ListNode(1);
a.next = new ListNode(2);
a.next.next = a;
const t: Task = new Task("t", () => console.log(t.name));
const g = new Graph();
g.nodes.push(new GraphNode(g));
const group = new Group(1);
group.members.push(group);
const c: Cell = { value: 1, link: null };
c.link = c;
console.log(a.value, t.name, g.nodes.length, group.members.length, c.value);