fix cycles in extern modules

This commit is contained in:
nora 2023-11-05 16:48:13 +01:00
parent 3af8f4fc40
commit a699262671
2 changed files with 23 additions and 3 deletions

View file

@ -22,6 +22,8 @@ export type CrateLoader = (
export class GlobalContext { export class GlobalContext {
public error: ErrorHandler = new ErrorHandler(); public error: ErrorHandler = new ErrorHandler();
public finalizedCrates: Crate<Final>[] = []; public finalizedCrates: Crate<Final>[] = [];
// For cycle detection.
public cratesBeingLoaded: Set<string> = new Set<string>();
public crateId: Ids = new Ids(); public crateId: Ids = new Ids();
constructor(public opts: Options, public crateLoader: CrateLoader) {} constructor(public opts: Options, public crateLoader: CrateLoader) {}

View file

@ -90,9 +90,7 @@ export const loadCrate: CrateLoader = (
name: string, name: string,
span: Span, span: Span,
): DepCrate => { ): DepCrate => {
// We really, really want a good algorithm for finding crates. // If we've loaded the crate already, great.
// But right now we just look for files in the CWD.
const existing = gcx.finalizedCrates.find( const existing = gcx.finalizedCrates.find(
(crate) => crate.packageName === name, (crate) => crate.packageName === name,
); );
@ -102,6 +100,24 @@ export const loadCrate: CrateLoader = (
const crateId = gcx.crateId.next(); const crateId = gcx.crateId.next();
// If we have not loaded the crate yet, we may actually already be loading it.
// A cycle!!
if (gcx.cratesBeingLoaded.has(name)) {
return dummyErrorCrate(
crateId,
name,
gcx.error.emit(
new CompilerError(`cycle detected loading extern module ${name}`, span),
),
);
}
// Let's start loading the crate!
gcx.cratesBeingLoaded.add(name);
// We really, really want a good algorithm for finding crates.
// But right now we just look for files in the CWD.
const file = loadModuleFile(".", name, span); const file = loadModuleFile(".", name, span);
if (!file.ok) { if (!file.ok) {
return dummyErrorCrate(crateId, name, gcx.error.emit(file.err)); return dummyErrorCrate(crateId, name, gcx.error.emit(file.err));
@ -122,5 +138,7 @@ export const loadCrate: CrateLoader = (
const typecked = typeck(gcx, resolved); const typecked = typeck(gcx, resolved);
gcx.finalizedCrates.push(typecked); gcx.finalizedCrates.push(typecked);
// Crate is loaded, no cycles.
gcx.cratesBeingLoaded.delete(name);
return typecked; return typecked;
}; };