diff --git a/src/semantic/index.ts b/src/semantic/index.ts index 27923a53..bb5637a2 100644 --- a/src/semantic/index.ts +++ b/src/semantic/index.ts @@ -357,12 +357,16 @@ const checkFnDef = (fnDef: FnDef, ctx: Context): void => { upcast(rs, rs.type!, returnTypeResolved, ctx) }) } else { - if (!module.compiled && instScope?.rel.instanceDef.kind !== 'trait-def') { + if (!instScope) { addWarning(ctx, noBodyFnError(ctx, fnDef)) + } else { + if (instScope?.rel.instanceDef.kind !== 'trait-def') { + addError(ctx, noBodyFnError(ctx, fnDef)) + } } - if (instScope?.rel.instanceDef.kind === 'trait-def' && fnDef.pub) { - addWarning(ctx, unnecessaryPubMethodError(ctx, fnDef)) - } + } + if (instScope?.rel.instanceDef.kind === 'trait-def' && fnDef.pub) { + addWarning(ctx, unnecessaryPubMethodError(ctx, fnDef)) } } diff --git a/src/semantic/semantic.spec.ts b/src/semantic/semantic.spec.ts index 22c3389f..51a4f961 100644 --- a/src/semantic/semantic.spec.ts +++ b/src/semantic/semantic.spec.ts @@ -701,4 +701,28 @@ fn main() { expect(ctx.errors.map(e => e.message)).toEqual(['missing variable initialization']) }) }) + + describe('fn def', () => { + it('fn no body', () => { + const code = `\ +type Node { + Node(node: Node), + Leaf(t: T) +} + +impl Node { + fn child() +} + +fn main() { + let n = Node(Node(Leaf(5))) + n.child().child() +}` + const ctx = check(code) + expect(ctx.errors.map(e => e.message)).toEqual([ + 'fn `child` has no body', + 'method `std::unit::Unit::child` not found' + ]) + }) + }) }) diff --git a/src/typecheck/generic.ts b/src/typecheck/generic.ts index a742f7c0..9d316955 100644 --- a/src/typecheck/generic.ts +++ b/src/typecheck/generic.ts @@ -6,7 +6,7 @@ import { VirtualFnType, VirtualType } from './index' import { holeType, selfType } from './type' export const makeFnGenericMap = (fnType: VirtualFnType, argTypes: VirtualType[]): Map => { - assert(argTypes.length <= fnType.paramTypes.length, 'fn args > params') + if (argTypes.length > fnType.paramTypes.length) return new Map() return argTypes .map((argType, i) => { const param = fnType.paramTypes[i]