diff --git a/compiler/semcall.nim b/compiler/semcall.nim index 4240bc603be43..7040c1ac66d74 100644 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -595,7 +595,7 @@ proc inferWithMetatype(c: PContext, formal: PType, result = copyTree(arg) result.typ = formal -proc updateDefaultParams(call: PNode) = +proc updateDefaultParams(c: PContext, call: PNode) = # In generic procs, the default parameter may be unique for each # instantiation (see tlateboundgenericparams). # After a call is resolved, we need to re-assign any default value @@ -605,8 +605,18 @@ proc updateDefaultParams(call: PNode) = let calleeParams = call[0].sym.typ.n for i in 1..= 2 and (let t = n[1].typ; diff --git a/compiler/seminst.nim b/compiler/seminst.nim index 84ae9a26fe6c7..b187f9ed8c0c7 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -253,9 +253,13 @@ proc instantiateProcType(c: PContext, pt: TypeMapping, var typeToFit = resulti let needsStaticSkipping = resulti.kind == tyFromExpr + let needsTypeDescSkipping = resulti.kind == tyTypeDesc and tfUnresolved in resulti.flags result[i] = replaceTypeVarsT(cl, resulti) if needsStaticSkipping: result[i] = result[i].skipTypes({tyStatic}) + if needsTypeDescSkipping: + result[i] = result[i].skipTypes({tyTypeDesc}) + typeToFit = result[i] # ...otherwise, we use the instantiated type in `fitNode` if (typeToFit.kind != tyTypeDesc or typeToFit.base.kind != tyNone) and @@ -292,6 +296,8 @@ proc instantiateProcType(c: PContext, pt: TypeMapping, # the user calls an explicit instantiation of the proc (this is # the only way the default value might be inserted). param.ast = errorNode(c, def) + # we know the node is empty, we need the actual type for error message + param.ast.typ = def.typ else: param.ast = fitNodePostMatch(c, typeToFit, converted) param.typ = result[i] diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index af9b29718f4d7..f2865347f7889 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -2790,14 +2790,16 @@ proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) = m.firstMismatch.formal = formal break else: + # mirrored with updateDefaultParams: if formal.ast.kind == nkEmpty: # The default param value is set to empty in `instantiateProcType` # when the type of the default expression doesn't match the type # of the instantiated proc param: - localError(c.config, m.call.info, - ("The default parameter '$1' has incompatible type " & - "with the explicitly requested proc instantiation") % - formal.name.s) + pushInfoContext(c.config, m.call.info, + if m.calleeSym != nil: m.calleeSym.detailedInfo else: "") + typeMismatch(c.config, formal.ast.info, formal.typ, formal.ast.typ, formal.ast) + popInfoContext(c.config) + formal.ast.typ = errorType(c) if nfDefaultRefsParam in formal.ast.flags: m.call.flags.incl nfDefaultRefsParam var defaultValue = copyTree(formal.ast) diff --git a/tests/proc/twrongdefaultvalue.nim b/tests/proc/twrongdefaultvalue.nim new file mode 100644 index 0000000000000..2c36c224704a1 --- /dev/null +++ b/tests/proc/twrongdefaultvalue.nim @@ -0,0 +1,25 @@ +discard """ + cmd: "nim check $file" + action: reject + nimout: ''' +twrongdefaultvalue.nim(20, 12) template/generic instantiation of `doit` from here +twrongdefaultvalue.nim(17, 37) Error: type mismatch: got but expected 'Item[system.string]' +twrongdefaultvalue.nim(25, 3) template/generic instantiation of `foo` from here +twrongdefaultvalue.nim(23, 33) Error: type mismatch: got but expected 'int' +''' +""" + +block: # issue #21258 + type Item[T] = object + pos: int + proc initItem[T](p:int=10000) : Item[T] = + result = Item[T](p) + proc doit[T](x:Item[T], s:Item[T]=initItem) : string = + return $x.pos + let x = Item[string](pos:100) + echo doit(x) + +block: # issue #21258, reduced case + proc foo[T](x: seq[T], y: T = "foo") = + discard + foo @[1, 2, 3]