diff options
-rw-r--r-- | compiler/semexprs.nim | 1 | ||||
-rw-r--r-- | compiler/semtypes.nim | 9 | ||||
-rw-r--r-- | compiler/semtypinst.nim | 5 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 20 | ||||
-rw-r--r-- | doc/manual.rst | 8 |
5 files changed, 25 insertions, 18 deletions
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 238ae0194..a9258fb62 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -857,6 +857,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode = else: result = m.call instGenericConvertersSons(c, result, m) + elif t != nil and t.kind == tyTypeDesc: if n.len == 1: return semObjConstr(c, n, flags) return semConv(c, n) diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index f0f22e87c..a0144500e 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -863,7 +863,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode, of tyStatic: if paramType.base.kind != tyNone and paramType.n != nil: - # this is a concrete type + # this is a concrete static value return if tfUnresolved in paramType.flags: return # already lifted let base = paramType.base.maybeLift @@ -1048,7 +1048,12 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, if typ == nil: typ = def.typ if typ.kind == tyTypeDesc: - # default typedesc values are mapped to the unbound typedesc type: + # consider a proc such as: + # proc takesType(T = int) + # a naive analysis may conclude that the proc type is type[int] + # which will prevent other types from matching - clearly a very + # surprising behavior. We must instead fix the expected type of + # the proc to be the unbound typedesc type: typ = newTypeWithSons(c, tyTypeDesc, @[newTypeS(tyNone, c)]) else: diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim index f02c45e46..22ea09af1 100644 --- a/compiler/semtypinst.nim +++ b/compiler/semtypinst.nim @@ -223,8 +223,9 @@ proc replaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym = # XXX: Bound symbols in default parameter expressions may reach here. # We cannot process them, becase `sym.n` may point to a proc body with - # cyclic references that will lead to an infinite recursion. Perhaps we - # should not use a black-list here, but a whitelist instead. + # cyclic references that will lead to an infinite recursion. + # Perhaps we should not use a black-list here, but a whitelist instead + # (e.g. skGenericParam and skType). # Note: `s.magic` may be `mType` in an example such as: # proc foo[T](a: T, b = myDefault(type(a))) if s.kind == skProc or s.magic != mNone: diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 0bb7c4fdd..784b5c11c 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -1089,13 +1089,8 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType, else: isNone of tyAnything: - if f.kind in {tyAnything}: - return isGeneric - - if tfWildCard in a.flags and f.kind == tyTypeDesc: - return isGeneric - - return isNone + if f.kind == tyAnything: return isGeneric + else: return isNone of tyUserTypeClass, tyUserTypeClassInst: if c.c.matchedConcept != nil and c.c.matchedConcept.depth <= 4: @@ -2366,6 +2361,14 @@ proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) = m.firstMismatch = f break else: + 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) if nfDefaultRefsParam in formal.ast.flags: m.call.flags.incl nfDefaultRefsParam var def = copyTree(formal.ast) @@ -2375,9 +2378,6 @@ proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) = put(m, formal.typ, def.typ) def.flags.incl nfDefaultParam setSon(m.call, formal.position + 1, def) - # XXX: Instead of setting a default value here, we may place a special - # marker value instead. Later, we will replace it in `semResolvedCall`. - # Unfortunately, this causes some breakage at the moment. inc(f) # forget all inferred types if the overload matching failed if m.state == csNoMatch: diff --git a/doc/manual.rst b/doc/manual.rst index 88dae89b0..c267c706f 100644 --- a/doc/manual.rst +++ b/doc/manual.rst @@ -5500,9 +5500,9 @@ Static params can also appear in the signatures of generic types: var m2: AffineTransform2D[string] # Error, `string` is not a `Number` Please note that ``static T`` is just a syntactic convenience for the -underlying generic type ``static[T]``. This means that you can omit the -type param to obtain the type class of all values, known at compile-time -and you can restrict the matched values by instantiating ``static`` with +underlying generic type ``static[T]``. The type param can be omitted +to obtain the type class of all values known at compile-time. A more +specific type class can be created by instantiating ``static`` with another type class. You can force the evaluation of a certain expression at compile-time by @@ -5529,7 +5529,7 @@ generic param is ommited, ``type`` denotes the type class of all types. As a syntactic convenience, you can also use ``type`` as a modifier. ``type int`` is considered the same as ``type[int]``. -Procs featuring ``type`` params will be considered implicitly generic. +Procs featuring ``type`` params are considered implicitly generic. They will be instantiated for each unique combination of supplied types and within the body of the proc, the name of each param will refer to the bound concrete type: |