Skip to content

Commit

Permalink
Semantic: no impl found error
Browse files Browse the repository at this point in the history
  • Loading branch information
ivanjermakov committed Mar 18, 2024
1 parent 1768ccd commit 09699d8
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 14 deletions.
7 changes: 7 additions & 0 deletions src/semantic/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,13 @@ export const missingVarInitError = (ctx: Context, varDef: VarDef): SemanticError
return semanticError(38, ctx, varDef, msg)
}

export const noImplFoundError = (ctx: Context, name: Name, methodDef: MethodDef, operand: Operand): SemanticError => {
const traitVid = vidToString(methodDef.rel.implDef.vid)
const operandType = virtualTypeToString(operand.type!)
const msg = `no impl of trait \`${traitVid}\` found for type \`${operandType}\``
return semanticError(39, ctx, name, msg)
}

export const errorError = (ctx: Context, name: Name): SemanticError => {
return semanticError(0, ctx, name, `message`)
}
8 changes: 3 additions & 5 deletions src/semantic/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -772,12 +772,10 @@ export const checkCallArgs = (node: AstNode<any>, args: Operand[], paramTypes: V
checkClosureExpr(arg.type.closure, ctx, node, paramType)
arg.type = arg.type.closure.type
}
const argType = arg.type ?? unknownType

if (!isAssignable(argType, paramType, ctx)) {
addError(ctx, typeError(ctx, arg, argType, paramType))
if (!isAssignable(arg.type!, paramType, ctx)) {
addError(ctx, typeError(ctx, arg, arg.type!, paramType))
}

upcast(arg, argType, paramType, ctx)
upcast(arg, arg.type!, paramType, ctx)
}
}
15 changes: 12 additions & 3 deletions src/semantic/instance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Name, Operand } from '../ast/operand'
import { Context, addError } from '../scope'
import { getInstanceForType, resolveGenericImpls, resolveMethodImpl } from '../scope/trait'
import { vidFromString, vidToString } from '../scope/util'
import { MethodDef, VirtualIdentifier, resolveVid } from '../scope/vid'
import { MethodDef, VirtualIdentifier, resolveVid, typeKinds } from '../scope/vid'
import { VirtualFnType, VirtualType, combine, genericToVirtual, typeToVirtual } from '../typecheck'
import {
makeFnGenericMap,
Expand All @@ -17,6 +17,7 @@ import { selfType } from '../typecheck/type'
import { assert } from '../util/todo'
import {
narrowFieldAccessError,
noImplFoundError,
notFoundError,
privateAccessError,
unexpectedNamedArgError,
Expand Down Expand Up @@ -117,18 +118,26 @@ export const checkMethodCall = (expr: UnaryExpr, mCall: MethodCallOp, ctx: Conte
}

mCall.call.methodDef = ref.def
const genericMaps = makeMethodGenericMaps(operand, ref.def, mCall, ctx)
const fnType = <VirtualFnType>ref.def.fn.type

// TODO: check required type args (that cannot be inferred via `resolveFnGenerics`)
mCall.typeArgs.forEach(typeArg => checkType(typeArg, ctx))

const genericMaps = makeMethodGenericMaps(operand, ref.def, mCall, ctx)
const args = ref.def.fn.static ? mCall.call.args.map(a => a.expr) : [operand, ...mCall.call.args.map(a => a.expr)]
const paramTypes = fnType.paramTypes.map(pt => resolveType(pt, genericMaps, ctx))
checkCallArgs(mCall, args, paramTypes, ctx)

const operandTypeRef = resolveVid(typeVid, ctx, typeKinds)
if (ref.def.rel.instanceDef.kind === 'trait-def') {
mCall.call.impl = resolveMethodImpl(operand.type!, ref.def, ctx)
const resolved = resolveMethodImpl(operand.type!, ref.def, ctx)
if (resolved) {
mCall.call.impl = resolved
} else {
if (operandTypeRef && operandTypeRef.def.kind !== 'trait-def' && operandTypeRef.def.kind !== 'generic') {
addError(ctx, noImplFoundError(ctx, mCall.name, ref.def, operand))
}
}
} else {
mCall.call.impl = ref.def.rel
}
Expand Down
12 changes: 6 additions & 6 deletions src/std/list.no
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,19 @@ impl Show for List<String> {
}
}

impl Copy for Int {
fn copy(self): Self {
copy(self)
}
}

impl <T: Show> Show for List<T> {
fn show(self): String {
// TODO: method ref
self.iter().map(|d| { d.show() }).collect<List<String>>().show()
}
}

impl Copy for Int {
fn copy(self): Self {
copy(self)
}
}

pub type ListIter<T>(
list: List<T>,
// TODO: this logic breaks if list size changes during iteration.
Expand Down

0 comments on commit 09699d8

Please sign in to comment.