R21BREAKINGfunctionAsync to Sync
Flags when an async function becomes synchronous. Callers using .then(), .catch(), or await will crash at runtime.
Applies to
TypeScriptPythonGoJavaRust
Why it matters
The reverse of R11. Callers that
await the function or chain .then() on the result will get runtime errors because the return value is no longer a Promise.Example
Before (async)
// data.ts
export async function fetchData(url: string): Promise<Data> {
const res = await fetch(url);
return res.json();
}
// caller
const data = await fetchData("/api/users");After (sync)
// data.ts (BREAKING)
export function fetchData(url: string): Data {
return cache.get(url); // now synchronous, reads from cache
}
// caller — NOW BROKEN
const data = await fetchData("/api/users");
// 'await' on a non-Promise is a no-op in loose mode,
// but .then() would crash: fetchData(...).then is not a functionWhat you see in the terminal
$ npx dg check
[BREAKING] fetchData (signature_change)
src/data.ts:2
Function changed from async to sync. Callers using await or .then() will encounter runtime errors.How detection works
The classifier checks if the old signature had async: true and the new signature has async: false. It also checks if the return type changed from Promise to T.
Real-world scenario
A data fetching function is refactored to read from a cache instead of making network requests. It no longer needs to be async. All callers using `.then()` chains will crash because the return value is no longer a Promise.
Edge cases
- await on a non-Promise is actually a no-op in JavaScript — the value is wrapped in Promise.resolve()
- But .then() and .catch() calls will throw TypeError