sigmatch.nim 99 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810
  1. #
  2. #
  3. # The Nim Compiler
  4. # (c) Copyright 2013 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. ## This module implements the signature matching for resolving
  10. ## the call to overloaded procs, generic procs and operators.
  11. import
  12. intsets, ast, astalgo, semdata, types, msgs, renderer, lookups, semtypinst,
  13. magicsys, idents, lexer, options, parampatterns, strutils, trees,
  14. linter, lineinfos, lowerings, modulegraphs, concepts
  15. when defined(nimPreviewSlimSystem):
  16. import std/assertions
  17. type
  18. MismatchKind* = enum
  19. kUnknown, kAlreadyGiven, kUnknownNamedParam, kTypeMismatch, kVarNeeded,
  20. kMissingParam, kExtraArg, kPositionalAlreadyGiven
  21. MismatchInfo* = object
  22. kind*: MismatchKind # reason for mismatch
  23. arg*: int # position of provided arguments that mismatches
  24. formal*: PSym # parameter that mismatches against provided argument
  25. # its position can differ from `arg` because of varargs
  26. TCandidateState* = enum
  27. csEmpty, csMatch, csNoMatch
  28. CandidateError* = object
  29. sym*: PSym
  30. firstMismatch*: MismatchInfo
  31. diagnostics*: seq[string]
  32. enabled*: bool
  33. CandidateErrors* = seq[CandidateError]
  34. TCandidate* = object
  35. c*: PContext
  36. exactMatches*: int # also misused to prefer iters over procs
  37. genericMatches: int # also misused to prefer constraints
  38. subtypeMatches: int
  39. intConvMatches: int # conversions to int are not as expensive
  40. convMatches: int
  41. state*: TCandidateState
  42. callee*: PType # may not be nil!
  43. calleeSym*: PSym # may be nil
  44. calleeScope*: int # scope depth:
  45. # is this a top-level symbol or a nested proc?
  46. call*: PNode # modified call
  47. bindings*: TIdTable # maps types to types
  48. magic*: TMagic # magic of operation
  49. baseTypeMatch: bool # needed for conversions from T to openarray[T]
  50. # for example
  51. fauxMatch*: TTypeKind # the match was successful only due to the use
  52. # of error or wildcard (unknown) types.
  53. # this is used to prevent instantiations.
  54. genericConverter*: bool # true if a generic converter needs to
  55. # be instantiated
  56. coerceDistincts*: bool # this is an explicit coercion that can strip away
  57. # a distrinct type
  58. typedescMatched*: bool
  59. isNoCall*: bool # misused for generic type instantiations C[T]
  60. inferredTypes: seq[PType] # inferred types during the current signature
  61. # matching. they will be reset if the matching
  62. # is not successful. may replace the bindings
  63. # table in the future.
  64. diagnostics*: seq[string] # \
  65. # when diagnosticsEnabled, the matching process
  66. # will collect extra diagnostics that will be
  67. # displayed to the user.
  68. # triggered when overload resolution fails
  69. # or when the explain pragma is used. may be
  70. # triggered with an idetools command in the
  71. # future.
  72. inheritancePenalty: int # to prefer closest father object type
  73. firstMismatch*: MismatchInfo # mismatch info for better error messages
  74. diagnosticsEnabled*: bool
  75. TTypeRelFlag* = enum
  76. trDontBind
  77. trNoCovariance
  78. trBindGenericParam # bind tyGenericParam even with trDontBind
  79. trIsOutParam
  80. TTypeRelFlags* = set[TTypeRelFlag]
  81. const
  82. isNilConversion = isConvertible # maybe 'isIntConv' fits better?
  83. proc markUsed*(c: PContext; info: TLineInfo, s: PSym)
  84. proc markOwnerModuleAsUsed*(c: PContext; s: PSym)
  85. template hasFauxMatch*(c: TCandidate): bool = c.fauxMatch != tyNone
  86. proc initCandidateAux(ctx: PContext,
  87. c: var TCandidate, callee: PType) {.inline.} =
  88. c.c = ctx
  89. c.exactMatches = 0
  90. c.subtypeMatches = 0
  91. c.convMatches = 0
  92. c.intConvMatches = 0
  93. c.genericMatches = 0
  94. c.state = csEmpty
  95. c.firstMismatch = MismatchInfo()
  96. c.callee = callee
  97. c.call = nil
  98. c.baseTypeMatch = false
  99. c.genericConverter = false
  100. c.inheritancePenalty = 0
  101. proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PType) =
  102. initCandidateAux(ctx, c, callee)
  103. c.calleeSym = nil
  104. initIdTable(c.bindings)
  105. proc put(c: var TCandidate, key, val: PType) {.inline.} =
  106. ## Given: proc foo[T](x: T); foo(4)
  107. ## key: 'T'
  108. ## val: 'int' (typeof(4))
  109. when false:
  110. let old = PType(idTableGet(c.bindings, key))
  111. if old != nil:
  112. echo "Putting ", typeToString(key), " ", typeToString(val), " and old is ", typeToString(old)
  113. if typeToString(old) == "float32":
  114. writeStackTrace()
  115. if c.c.module.name.s == "temp3":
  116. echo "binding ", key, " -> ", val
  117. idTablePut(c.bindings, key, val.skipIntLit(c.c.idgen))
  118. proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PSym,
  119. binding: PNode, calleeScope = -1,
  120. diagnosticsEnabled = false) =
  121. initCandidateAux(ctx, c, callee.typ)
  122. c.calleeSym = callee
  123. if callee.kind in skProcKinds and calleeScope == -1:
  124. if callee.originatingModule == ctx.module:
  125. c.calleeScope = 2
  126. var owner = callee
  127. while true:
  128. owner = owner.skipGenericOwner
  129. if owner.kind == skModule: break
  130. inc c.calleeScope
  131. else:
  132. c.calleeScope = 1
  133. else:
  134. c.calleeScope = calleeScope
  135. c.diagnostics = @[] # if diagnosticsEnabled: @[] else: nil
  136. c.diagnosticsEnabled = diagnosticsEnabled
  137. c.magic = c.calleeSym.magic
  138. initIdTable(c.bindings)
  139. if binding != nil and callee.kind in routineKinds:
  140. var typeParams = callee.ast[genericParamsPos]
  141. for i in 1..min(typeParams.len, binding.len-1):
  142. var formalTypeParam = typeParams[i-1].typ
  143. var bound = binding[i].typ
  144. if bound != nil:
  145. if formalTypeParam.kind == tyTypeDesc:
  146. if bound.kind != tyTypeDesc:
  147. bound = makeTypeDesc(ctx, bound)
  148. else:
  149. bound = bound.skipTypes({tyTypeDesc})
  150. put(c, formalTypeParam, bound)
  151. proc newCandidate*(ctx: PContext, callee: PSym,
  152. binding: PNode, calleeScope = -1): TCandidate =
  153. initCandidate(ctx, result, callee, binding, calleeScope)
  154. proc newCandidate*(ctx: PContext, callee: PType): TCandidate =
  155. initCandidate(ctx, result, callee)
  156. proc copyCandidate(a: var TCandidate, b: TCandidate) =
  157. a.c = b.c
  158. a.exactMatches = b.exactMatches
  159. a.subtypeMatches = b.subtypeMatches
  160. a.convMatches = b.convMatches
  161. a.intConvMatches = b.intConvMatches
  162. a.genericMatches = b.genericMatches
  163. a.state = b.state
  164. a.callee = b.callee
  165. a.calleeSym = b.calleeSym
  166. a.call = copyTree(b.call)
  167. a.baseTypeMatch = b.baseTypeMatch
  168. copyIdTable(a.bindings, b.bindings)
  169. proc typeRel*(c: var TCandidate, f, aOrig: PType,
  170. flags: TTypeRelFlags = {}): TTypeRelation
  171. proc checkGeneric(a, b: TCandidate): int =
  172. let c = a.c
  173. let aa = a.callee
  174. let bb = b.callee
  175. var winner = 0
  176. for i in 1..<min(aa.len, bb.len):
  177. var ma = newCandidate(c, bb[i])
  178. let tra = typeRel(ma, bb[i], aa[i], {trDontBind})
  179. var mb = newCandidate(c, aa[i])
  180. let trb = typeRel(mb, aa[i], bb[i], {trDontBind})
  181. if tra == isGeneric and trb == isNone:
  182. if winner == -1: return 0
  183. winner = 1
  184. if trb == isGeneric and tra == isNone:
  185. if winner == 1: return 0
  186. winner = -1
  187. result = winner
  188. proc sumGeneric(t: PType): int =
  189. # count the "genericness" so that Foo[Foo[T]] has the value 3
  190. # and Foo[T] has the value 2 so that we know Foo[Foo[T]] is more
  191. # specific than Foo[T].
  192. var t = t
  193. var isvar = 1
  194. while true:
  195. case t.kind
  196. of tyGenericInst, tyArray, tyRef, tyPtr, tyDistinct, tyUncheckedArray,
  197. tyOpenArray, tyVarargs, tySet, tyRange, tySequence, tyGenericBody,
  198. tyLent, tyOwned:
  199. t = t.lastSon
  200. inc result
  201. of tyOr:
  202. var maxBranch = 0
  203. for branch in t.sons:
  204. let branchSum = sumGeneric(branch)
  205. if branchSum > maxBranch: maxBranch = branchSum
  206. inc result, maxBranch
  207. break
  208. of tyVar:
  209. t = t[0]
  210. inc result
  211. inc isvar
  212. of tyTypeDesc:
  213. t = t.lastSon
  214. if t.kind == tyEmpty: break
  215. inc result
  216. of tyGenericInvocation, tyTuple, tyProc, tyAnd:
  217. result += ord(t.kind in {tyGenericInvocation, tyAnd})
  218. for i in 0..<t.len:
  219. if t[i] != nil:
  220. result += sumGeneric(t[i])
  221. break
  222. of tyStatic:
  223. return sumGeneric(t[0]) + 1
  224. of tyGenericParam, tyUntyped, tyTyped: break
  225. of tyAlias, tySink: t = t.lastSon
  226. of tyBool, tyChar, tyEnum, tyObject, tyPointer,
  227. tyString, tyCstring, tyInt..tyInt64, tyFloat..tyFloat128,
  228. tyUInt..tyUInt64, tyCompositeTypeClass:
  229. return isvar
  230. else:
  231. return 0
  232. proc complexDisambiguation(a, b: PType): int =
  233. # 'a' matches better if *every* argument matches better or equal than 'b'.
  234. var winner = 0
  235. for i in 1..<min(a.len, b.len):
  236. let x = a[i].sumGeneric
  237. let y = b[i].sumGeneric
  238. if x != y:
  239. if winner == 0:
  240. if x > y: winner = 1
  241. else: winner = -1
  242. elif x > y:
  243. if winner != 1:
  244. # contradiction
  245. return 0
  246. else:
  247. if winner != -1:
  248. return 0
  249. result = winner
  250. when false:
  251. var x, y: int
  252. for i in 1..<a.len: x += a[i].sumGeneric
  253. for i in 1..<b.len: y += b[i].sumGeneric
  254. result = x - y
  255. proc writeMatches*(c: TCandidate) =
  256. echo "Candidate '", c.calleeSym.name.s, "' at ", c.c.config $ c.calleeSym.info
  257. echo " exact matches: ", c.exactMatches
  258. echo " generic matches: ", c.genericMatches
  259. echo " subtype matches: ", c.subtypeMatches
  260. echo " intconv matches: ", c.intConvMatches
  261. echo " conv matches: ", c.convMatches
  262. echo " inheritance: ", c.inheritancePenalty
  263. proc cmpCandidates*(a, b: TCandidate): int =
  264. result = a.exactMatches - b.exactMatches
  265. if result != 0: return
  266. result = a.genericMatches - b.genericMatches
  267. if result != 0: return
  268. result = a.subtypeMatches - b.subtypeMatches
  269. if result != 0: return
  270. result = a.intConvMatches - b.intConvMatches
  271. if result != 0: return
  272. result = a.convMatches - b.convMatches
  273. if result != 0: return
  274. # the other way round because of other semantics:
  275. result = b.inheritancePenalty - a.inheritancePenalty
  276. if result != 0: return
  277. # check for generic subclass relation
  278. result = checkGeneric(a, b)
  279. if result != 0: return
  280. # prefer more specialized generic over more general generic:
  281. result = complexDisambiguation(a.callee, b.callee)
  282. # only as a last resort, consider scoping:
  283. if result != 0: return
  284. result = a.calleeScope - b.calleeScope
  285. proc argTypeToString(arg: PNode; prefer: TPreferedDesc): string =
  286. if arg.kind in nkSymChoices:
  287. result = typeToString(arg[0].typ, prefer)
  288. for i in 1..<arg.len:
  289. result.add(" | ")
  290. result.add typeToString(arg[i].typ, prefer)
  291. elif arg.typ == nil:
  292. result = "void"
  293. else:
  294. result = arg.typ.typeToString(prefer)
  295. template describeArgImpl(c: PContext, n: PNode, i: int, startIdx = 1; prefer = preferName) =
  296. var arg = n[i]
  297. if n[i].kind == nkExprEqExpr:
  298. result.add renderTree(n[i][0])
  299. result.add ": "
  300. if arg.typ.isNil and arg.kind notin {nkStmtList, nkDo}:
  301. # XXX we really need to 'tryExpr' here!
  302. arg = c.semOperand(c, n[i][1])
  303. n[i].typ = arg.typ
  304. n[i][1] = arg
  305. else:
  306. if arg.typ.isNil and arg.kind notin {nkStmtList, nkDo, nkElse,
  307. nkOfBranch, nkElifBranch,
  308. nkExceptBranch}:
  309. arg = c.semOperand(c, n[i])
  310. n[i] = arg
  311. if arg.typ != nil and arg.typ.kind == tyError: return
  312. result.add argTypeToString(arg, prefer)
  313. proc describeArg*(c: PContext, n: PNode, i: int, startIdx = 1; prefer = preferName): string =
  314. describeArgImpl(c, n, i, startIdx, prefer)
  315. proc describeArgs*(c: PContext, n: PNode, startIdx = 1; prefer = preferName): string =
  316. result = ""
  317. for i in startIdx..<n.len:
  318. describeArgImpl(c, n, i, startIdx, prefer)
  319. if i != n.len - 1: result.add ", "
  320. proc concreteType(c: TCandidate, t: PType; f: PType = nil): PType =
  321. case t.kind
  322. of tyTypeDesc:
  323. if c.isNoCall: result = t
  324. else: result = nil
  325. of tySequence, tySet:
  326. if t[0].kind == tyEmpty: result = nil
  327. else: result = t
  328. of tyGenericParam, tyAnything, tyConcept:
  329. result = t
  330. while true:
  331. result = PType(idTableGet(c.bindings, t))
  332. if result == nil:
  333. break # it's ok, no match
  334. # example code that triggers it:
  335. # proc sort[T](cmp: proc(a, b: T): int = cmp)
  336. if result.kind != tyGenericParam: break
  337. of tyGenericInvocation:
  338. result = nil
  339. of tyOwned:
  340. # bug #11257: the comparison system.`==`[T: proc](x, y: T) works
  341. # better without the 'owned' type:
  342. if f != nil and f.len > 0 and f[0].skipTypes({tyBuiltInTypeClass}).kind == tyProc:
  343. result = t.lastSon
  344. else:
  345. result = t
  346. else:
  347. result = t # Note: empty is valid here
  348. proc handleRange(c: PContext, f, a: PType, min, max: TTypeKind): TTypeRelation =
  349. if a.kind == f.kind:
  350. result = isEqual
  351. else:
  352. let ab = skipTypes(a, {tyRange})
  353. let k = ab.kind
  354. let nf = c.config.normalizeKind(f.kind)
  355. let na = c.config.normalizeKind(k)
  356. if k == f.kind: result = isSubrange
  357. elif k == tyInt and f.kind in {tyRange, tyInt..tyInt64,
  358. tyUInt..tyUInt64} and
  359. isIntLit(ab) and getInt(ab.n) >= firstOrd(nil, f) and
  360. getInt(ab.n) <= lastOrd(nil, f):
  361. # passing 'nil' to firstOrd/lastOrd here as type checking rules should
  362. # not depend on the target integer size configurations!
  363. # integer literal in the proper range; we want ``i16 + 4`` to stay an
  364. # ``int16`` operation so we declare the ``4`` pseudo-equal to int16
  365. result = isFromIntLit
  366. elif a.kind == tyInt and nf == c.config.targetSizeSignedToKind:
  367. result = isIntConv
  368. elif a.kind == tyUInt and nf == c.config.targetSizeUnsignedToKind:
  369. result = isIntConv
  370. elif f.kind == tyInt and na in {tyInt8 .. pred(c.config.targetSizeSignedToKind)}:
  371. result = isIntConv
  372. elif f.kind == tyUInt and na in {tyUInt8 .. pred(c.config.targetSizeUnsignedToKind)}:
  373. result = isIntConv
  374. elif k >= min and k <= max:
  375. result = isConvertible
  376. elif a.kind == tyRange and
  377. # Make sure the conversion happens between types w/ same signedness
  378. (f.kind in {tyInt..tyInt64} and a[0].kind in {tyInt..tyInt64} or
  379. f.kind in {tyUInt8..tyUInt32} and a[0].kind in {tyUInt8..tyUInt32}) and
  380. a.n[0].intVal >= firstOrd(nil, f) and a.n[1].intVal <= lastOrd(nil, f):
  381. # passing 'nil' to firstOrd/lastOrd here as type checking rules should
  382. # not depend on the target integer size configurations!
  383. result = isConvertible
  384. else: result = isNone
  385. proc isConvertibleToRange(c: PContext, f, a: PType): bool =
  386. if f.kind in {tyInt..tyInt64, tyUInt..tyUInt64} and
  387. a.kind in {tyInt..tyInt64, tyUInt..tyUInt64}:
  388. case f.kind
  389. of tyInt8: result = isIntLit(a) or a.kind in {tyInt8}
  390. of tyInt16: result = isIntLit(a) or a.kind in {tyInt8, tyInt16}
  391. of tyInt32: result = isIntLit(a) or a.kind in {tyInt8, tyInt16, tyInt32}
  392. # This is wrong, but seems like there's a lot of code that relies on it :(
  393. of tyInt, tyUInt: result = true
  394. # of tyInt: result = isIntLit(a) or a.kind in {tyInt8 .. c.config.targetSizeSignedToKind}
  395. of tyInt64: result = isIntLit(a) or a.kind in {tyInt8, tyInt16, tyInt32, tyInt, tyInt64}
  396. of tyUInt8: result = isIntLit(a) or a.kind in {tyUInt8}
  397. of tyUInt16: result = isIntLit(a) or a.kind in {tyUInt8, tyUInt16}
  398. of tyUInt32: result = isIntLit(a) or a.kind in {tyUInt8, tyUInt16, tyUInt32}
  399. # of tyUInt: result = isIntLit(a) or a.kind in {tyUInt8 .. c.config.targetSizeUnsignedToKind}
  400. of tyUInt64: result = isIntLit(a) or a.kind in {tyUInt8, tyUInt16, tyUInt32, tyUInt64}
  401. else: result = false
  402. elif f.kind in {tyFloat..tyFloat128}:
  403. # `isIntLit` is correct and should be used above as well, see PR:
  404. # https://github.com/nim-lang/Nim/pull/11197
  405. result = isIntLit(a) or a.kind in {tyFloat..tyFloat128}
  406. proc handleFloatRange(f, a: PType): TTypeRelation =
  407. if a.kind == f.kind:
  408. result = isEqual
  409. else:
  410. let ab = skipTypes(a, {tyRange})
  411. var k = ab.kind
  412. if k == f.kind: result = isSubrange
  413. elif isFloatLit(ab): result = isFromIntLit
  414. elif isIntLit(ab): result = isConvertible
  415. elif k >= tyFloat and k <= tyFloat128:
  416. # conversion to "float32" is not as good:
  417. if f.kind == tyFloat32: result = isConvertible
  418. else: result = isIntConv
  419. else: result = isNone
  420. proc genericParamPut(c: var TCandidate; last, fGenericOrigin: PType) =
  421. if fGenericOrigin != nil and last.kind == tyGenericInst and
  422. last.len-1 == fGenericOrigin.len:
  423. for i in 1..<fGenericOrigin.len:
  424. let x = PType(idTableGet(c.bindings, fGenericOrigin[i]))
  425. if x == nil:
  426. put(c, fGenericOrigin[i], last[i])
  427. proc isObjectSubtype(c: var TCandidate; a, f, fGenericOrigin: PType): int =
  428. var t = a
  429. assert t.kind == tyObject
  430. var depth = 0
  431. var last = a
  432. while t != nil and not sameObjectTypes(f, t):
  433. assert t.kind == tyObject
  434. t = t[0]
  435. if t == nil: break
  436. last = t
  437. t = skipTypes(t, skipPtrs)
  438. inc depth
  439. if t != nil:
  440. genericParamPut(c, last, fGenericOrigin)
  441. result = depth
  442. else:
  443. result = -1
  444. type
  445. SkippedPtr = enum skippedNone, skippedRef, skippedPtr
  446. proc skipToObject(t: PType; skipped: var SkippedPtr): PType =
  447. var r = t
  448. # we're allowed to skip one level of ptr/ref:
  449. var ptrs = 0
  450. while r != nil:
  451. case r.kind
  452. of tyGenericInvocation:
  453. r = r[0]
  454. of tyRef:
  455. inc ptrs
  456. skipped = skippedRef
  457. r = r.lastSon
  458. of tyPtr:
  459. inc ptrs
  460. skipped = skippedPtr
  461. r = r.lastSon
  462. of tyGenericBody, tyGenericInst, tyAlias, tySink, tyOwned:
  463. r = r.lastSon
  464. else:
  465. break
  466. if r.kind == tyObject and ptrs <= 1: result = r
  467. proc isGenericSubtype(c: var TCandidate; a, f: PType, d: var int, fGenericOrigin: PType): bool =
  468. assert f.kind in {tyGenericInst, tyGenericInvocation, tyGenericBody}
  469. var askip = skippedNone
  470. var fskip = skippedNone
  471. var t = a.skipToObject(askip)
  472. let r = f.skipToObject(fskip)
  473. if r == nil: return false
  474. var depth = 0
  475. var last = a
  476. # XXX sameObjectType can return false here. Need to investigate
  477. # why that is but sameObjectType does way too much work here anyway.
  478. while t != nil and r.sym != t.sym and askip == fskip:
  479. t = t[0]
  480. if t == nil: break
  481. last = t
  482. t = t.skipToObject(askip)
  483. inc depth
  484. if t != nil and askip == fskip:
  485. genericParamPut(c, last, fGenericOrigin)
  486. d = depth
  487. result = true
  488. proc minRel(a, b: TTypeRelation): TTypeRelation =
  489. if a <= b: result = a
  490. else: result = b
  491. proc recordRel(c: var TCandidate, f, a: PType): TTypeRelation =
  492. result = isNone
  493. if sameType(f, a):
  494. result = isEqual
  495. elif a.len == f.len:
  496. result = isEqual
  497. let firstField = if f.kind == tyTuple: 0
  498. else: 1
  499. for i in firstField..<f.len:
  500. var m = typeRel(c, f[i], a[i])
  501. if m < isSubtype: return isNone
  502. result = minRel(result, m)
  503. if f.n != nil and a.n != nil:
  504. for i in 0..<f.n.len:
  505. # check field names:
  506. if f.n[i].kind != nkSym: return isNone
  507. elif a.n[i].kind != nkSym: return isNone
  508. else:
  509. var x = f.n[i].sym
  510. var y = a.n[i].sym
  511. if f.kind == tyObject and typeRel(c, x.typ, y.typ) < isSubtype:
  512. return isNone
  513. if x.name.id != y.name.id: return isNone
  514. proc allowsNil(f: PType): TTypeRelation {.inline.} =
  515. result = if tfNotNil notin f.flags: isSubtype else: isNone
  516. proc inconsistentVarTypes(f, a: PType): bool {.inline.} =
  517. result = (f.kind != a.kind and
  518. (f.kind in {tyVar, tyLent, tySink} or a.kind in {tyVar, tyLent, tySink})) or
  519. isOutParam(f) != isOutParam(a)
  520. proc procParamTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
  521. ## For example we have:
  522. ## ```
  523. ## proc myMap[T,S](sIn: seq[T], f: proc(x: T): S): seq[S] = ...
  524. ## proc innerProc[Q,W](q: Q): W = ...
  525. ## ```
  526. ## And we want to match: myMap(@[1,2,3], innerProc)
  527. ## This proc (procParamTypeRel) will do the following steps in
  528. ## three different calls:
  529. ## - matches f=T to a=Q. Since f is metatype, we resolve it
  530. ## to int (which is already known at this point). So in this case
  531. ## Q=int mapping will be saved to c.bindings.
  532. ## - matches f=S to a=W. Both of these metatypes are unknown, so we
  533. ## return with isBothMetaConvertible to ask for rerun.
  534. ## - matches f=S to a=W. At this point the return type of innerProc
  535. ## is known (we get it from c.bindings). We can use that value
  536. ## to match with f, and save back to c.bindings.
  537. var
  538. f = f
  539. a = a
  540. if a.isMetaType:
  541. let aResolved = PType(idTableGet(c.bindings, a))
  542. if aResolved != nil:
  543. a = aResolved
  544. if a.isMetaType:
  545. if f.isMetaType:
  546. # We are matching a generic proc (as proc param)
  547. # to another generic type appearing in the proc
  548. # signature. There is a chance that the target
  549. # type is already fully-determined, so we are
  550. # going to try resolve it
  551. if c.call != nil:
  552. f = generateTypeInstance(c.c, c.bindings, c.call.info, f)
  553. else:
  554. f = nil
  555. if f == nil or f.isMetaType:
  556. # no luck resolving the type, so the inference fails
  557. return isBothMetaConvertible
  558. # Note that this typeRel call will save a's resolved type into c.bindings
  559. let reverseRel = typeRel(c, a, f)
  560. if reverseRel >= isGeneric:
  561. result = isInferred
  562. #inc c.genericMatches
  563. else:
  564. # Note that this typeRel call will save f's resolved type into c.bindings
  565. # if f is metatype.
  566. result = typeRel(c, f, a)
  567. if result <= isSubrange or inconsistentVarTypes(f, a):
  568. result = isNone
  569. #if result == isEqual:
  570. # inc c.exactMatches
  571. proc procTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
  572. case a.kind
  573. of tyProc:
  574. if f.len != a.len: return
  575. result = isEqual # start with maximum; also correct for no
  576. # params at all
  577. template checkParam(f, a) =
  578. result = minRel(result, procParamTypeRel(c, f, a))
  579. if result == isNone: return
  580. # Note: We have to do unification for the parameters before the
  581. # return type!
  582. for i in 1..<f.len:
  583. checkParam(f[i], a[i])
  584. if f[0] != nil:
  585. if a[0] != nil:
  586. checkParam(f[0], a[0])
  587. else:
  588. return isNone
  589. elif a[0] != nil:
  590. return isNone
  591. result = getProcConvMismatch(c.c.config, f, a, result)[1]
  592. when useEffectSystem:
  593. if compatibleEffects(f, a) != efCompat: return isNone
  594. when defined(drnim):
  595. if not c.c.graph.compatibleProps(c.c.graph, f, a): return isNone
  596. of tyNil:
  597. result = f.allowsNil
  598. else: discard
  599. proc typeRangeRel(f, a: PType): TTypeRelation {.noinline.} =
  600. template checkRange[T](a0, a1, f0, f1: T): TTypeRelation =
  601. if a0 == f0 and a1 == f1:
  602. isEqual
  603. elif a0 >= f0 and a1 <= f1:
  604. isConvertible
  605. elif a0 <= f1 and f0 <= a1:
  606. # X..Y and C..D overlap iff (X <= D and C <= Y)
  607. isConvertible
  608. else:
  609. isNone
  610. if f.isOrdinalType:
  611. checkRange(firstOrd(nil, a), lastOrd(nil, a), firstOrd(nil, f), lastOrd(nil, f))
  612. else:
  613. checkRange(firstFloat(a), lastFloat(a), firstFloat(f), lastFloat(f))
  614. proc matchUserTypeClass*(m: var TCandidate; ff, a: PType): PType =
  615. var
  616. c = m.c
  617. typeClass = ff.skipTypes({tyUserTypeClassInst})
  618. body = typeClass.n[3]
  619. matchedConceptContext: TMatchedConcept
  620. prevMatchedConcept = c.matchedConcept
  621. prevCandidateType = typeClass[0][0]
  622. if prevMatchedConcept != nil:
  623. matchedConceptContext.prev = prevMatchedConcept
  624. matchedConceptContext.depth = prevMatchedConcept.depth + 1
  625. if prevMatchedConcept.depth > 4:
  626. localError(m.c.graph.config, body.info, $body & " too nested for type matching")
  627. return nil
  628. openScope(c)
  629. matchedConceptContext.candidateType = a
  630. typeClass[0][0] = a
  631. c.matchedConcept = addr(matchedConceptContext)
  632. defer:
  633. c.matchedConcept = prevMatchedConcept
  634. typeClass[0][0] = prevCandidateType
  635. closeScope(c)
  636. var typeParams: seq[(PSym, PType)]
  637. if ff.kind == tyUserTypeClassInst:
  638. for i in 1..<(ff.len - 1):
  639. var
  640. typeParamName = ff.base[i-1].sym.name
  641. typ = ff[i]
  642. param: PSym
  643. alreadyBound = PType(idTableGet(m.bindings, typ))
  644. if alreadyBound != nil: typ = alreadyBound
  645. template paramSym(kind): untyped =
  646. newSym(kind, typeParamName, nextSymId(c.idgen), typeClass.sym, typeClass.sym.info, {})
  647. block addTypeParam:
  648. for prev in typeParams:
  649. if prev[1].id == typ.id:
  650. param = paramSym prev[0].kind
  651. param.typ = prev[0].typ
  652. break addTypeParam
  653. case typ.kind
  654. of tyStatic:
  655. param = paramSym skConst
  656. param.typ = typ.exactReplica
  657. #copyType(typ, nextTypeId(c.idgen), typ.owner)
  658. if typ.n == nil:
  659. param.typ.flags.incl tfInferrableStatic
  660. else:
  661. param.ast = typ.n
  662. of tyUnknown:
  663. param = paramSym skVar
  664. param.typ = typ.exactReplica
  665. #copyType(typ, nextTypeId(c.idgen), typ.owner)
  666. else:
  667. param = paramSym skType
  668. param.typ = if typ.isMetaType:
  669. c.newTypeWithSons(tyInferred, @[typ])
  670. else:
  671. makeTypeDesc(c, typ)
  672. typeParams.add((param, typ))
  673. addDecl(c, param)
  674. var
  675. oldWriteHook: typeof(m.c.config.writelnHook)
  676. diagnostics: seq[string]
  677. errorPrefix: string
  678. flags: TExprFlags = {}
  679. collectDiagnostics = m.diagnosticsEnabled or
  680. sfExplain in typeClass.sym.flags
  681. if collectDiagnostics:
  682. oldWriteHook = m.c.config.writelnHook
  683. # XXX: we can't write to m.diagnostics directly, because
  684. # Nim doesn't support capturing var params in closures
  685. diagnostics = @[]
  686. flags = {efExplain}
  687. m.c.config.writelnHook = proc (s: string) =
  688. if errorPrefix.len == 0: errorPrefix = typeClass.sym.name.s & ":"
  689. let msg = s.replace("Error:", errorPrefix)
  690. if oldWriteHook != nil: oldWriteHook msg
  691. diagnostics.add msg
  692. var checkedBody = c.semTryExpr(c, body.copyTree, flags)
  693. if collectDiagnostics:
  694. m.c.config.writelnHook = oldWriteHook
  695. for msg in diagnostics:
  696. m.diagnostics.add msg
  697. m.diagnosticsEnabled = true
  698. if checkedBody == nil: return nil
  699. # The inferrable type params have been identified during the semTryExpr above.
  700. # We need to put them in the current sigmatch's binding table in order for them
  701. # to be resolvable while matching the rest of the parameters
  702. for p in typeParams:
  703. put(m, p[1], p[0].typ)
  704. if ff.kind == tyUserTypeClassInst:
  705. result = generateTypeInstance(c, m.bindings, typeClass.sym.info, ff)
  706. else:
  707. result = ff.exactReplica
  708. #copyType(ff, nextTypeId(c.idgen), ff.owner)
  709. result.n = checkedBody
  710. proc shouldSkipDistinct(m: TCandidate; rules: PNode, callIdent: PIdent): bool =
  711. # XXX This is bad as 'considerQuotedIdent' can produce an error!
  712. if rules.kind == nkWith:
  713. for r in rules:
  714. if considerQuotedIdent(m.c, r) == callIdent: return true
  715. return false
  716. else:
  717. for r in rules:
  718. if considerQuotedIdent(m.c, r) == callIdent: return false
  719. return true
  720. proc maybeSkipDistinct(m: TCandidate; t: PType, callee: PSym): PType =
  721. if t != nil and t.kind == tyDistinct and t.n != nil and
  722. shouldSkipDistinct(m, t.n, callee.name):
  723. result = t.base
  724. else:
  725. result = t
  726. proc tryResolvingStaticExpr(c: var TCandidate, n: PNode,
  727. allowUnresolved = false): PNode =
  728. # Consider this example:
  729. # type Value[N: static[int]] = object
  730. # proc foo[N](a: Value[N], r: range[0..(N-1)])
  731. # Here, N-1 will be initially nkStaticExpr that can be evaluated only after
  732. # N is bound to a concrete value during the matching of the first param.
  733. # This proc is used to evaluate such static expressions.
  734. let instantiated = replaceTypesInBody(c.c, c.bindings, n, nil,
  735. allowMetaTypes = allowUnresolved)
  736. result = c.c.semExpr(c.c, instantiated)
  737. proc inferStaticParam*(c: var TCandidate, lhs: PNode, rhs: BiggestInt): bool =
  738. # This is a simple integer arithimetic equation solver,
  739. # capable of deriving the value of a static parameter in
  740. # expressions such as (N + 5) / 2 = rhs
  741. #
  742. # Preconditions:
  743. #
  744. # * The input of this proc must be semantized
  745. # - all templates should be expanded
  746. # - aby constant folding possible should already be performed
  747. #
  748. # * There must be exactly one unresolved static parameter
  749. #
  750. # Result:
  751. #
  752. # The proc will return true if the static types was successfully
  753. # inferred. The result will be bound to the original static type
  754. # in the TCandidate.
  755. #
  756. if lhs.kind in nkCallKinds and lhs[0].kind == nkSym:
  757. case lhs[0].sym.magic
  758. of mAddI, mAddU, mInc, mSucc:
  759. if lhs[1].kind == nkIntLit:
  760. return inferStaticParam(c, lhs[2], rhs - lhs[1].intVal)
  761. elif lhs[2].kind == nkIntLit:
  762. return inferStaticParam(c, lhs[1], rhs - lhs[2].intVal)
  763. of mDec, mSubI, mSubU, mPred:
  764. if lhs[1].kind == nkIntLit:
  765. return inferStaticParam(c, lhs[2], lhs[1].intVal - rhs)
  766. elif lhs[2].kind == nkIntLit:
  767. return inferStaticParam(c, lhs[1], rhs + lhs[2].intVal)
  768. of mMulI, mMulU:
  769. if lhs[1].kind == nkIntLit:
  770. if rhs mod lhs[1].intVal == 0:
  771. return inferStaticParam(c, lhs[2], rhs div lhs[1].intVal)
  772. elif lhs[2].kind == nkIntLit:
  773. if rhs mod lhs[2].intVal == 0:
  774. return inferStaticParam(c, lhs[1], rhs div lhs[2].intVal)
  775. of mDivI, mDivU:
  776. if lhs[1].kind == nkIntLit:
  777. if lhs[1].intVal mod rhs == 0:
  778. return inferStaticParam(c, lhs[2], lhs[1].intVal div rhs)
  779. elif lhs[2].kind == nkIntLit:
  780. return inferStaticParam(c, lhs[1], lhs[2].intVal * rhs)
  781. of mShlI:
  782. if lhs[2].kind == nkIntLit:
  783. return inferStaticParam(c, lhs[1], rhs shr lhs[2].intVal)
  784. of mShrI:
  785. if lhs[2].kind == nkIntLit:
  786. return inferStaticParam(c, lhs[1], rhs shl lhs[2].intVal)
  787. of mAshrI:
  788. if lhs[2].kind == nkIntLit:
  789. return inferStaticParam(c, lhs[1], ashr(rhs, lhs[2].intVal))
  790. of mUnaryMinusI:
  791. return inferStaticParam(c, lhs[1], -rhs)
  792. of mUnaryPlusI:
  793. return inferStaticParam(c, lhs[1], rhs)
  794. else: discard
  795. elif lhs.kind == nkSym and lhs.typ.kind == tyStatic and lhs.typ.n == nil:
  796. var inferred = newTypeWithSons(c.c, tyStatic, lhs.typ.sons)
  797. inferred.n = newIntNode(nkIntLit, rhs)
  798. put(c, lhs.typ, inferred)
  799. if c.c.matchedConcept != nil:
  800. # inside concepts, binding is currently done with
  801. # direct mutation of the involved types:
  802. lhs.typ.n = inferred.n
  803. return true
  804. return false
  805. proc failureToInferStaticParam(conf: ConfigRef; n: PNode) =
  806. let staticParam = n.findUnresolvedStatic
  807. let name = if staticParam != nil: staticParam.sym.name.s
  808. else: "unknown"
  809. localError(conf, n.info, "cannot infer the value of the static param '" & name & "'")
  810. proc inferStaticsInRange(c: var TCandidate,
  811. inferred, concrete: PType): TTypeRelation =
  812. let lowerBound = tryResolvingStaticExpr(c, inferred.n[0],
  813. allowUnresolved = true)
  814. let upperBound = tryResolvingStaticExpr(c, inferred.n[1],
  815. allowUnresolved = true)
  816. template doInferStatic(e: PNode, r: Int128) =
  817. var exp = e
  818. var rhs = r
  819. if inferStaticParam(c, exp, toInt64(rhs)):
  820. return isGeneric
  821. else:
  822. failureToInferStaticParam(c.c.config, exp)
  823. if lowerBound.kind == nkIntLit:
  824. if upperBound.kind == nkIntLit:
  825. if lengthOrd(c.c.config, concrete) == upperBound.intVal - lowerBound.intVal + 1:
  826. return isGeneric
  827. else:
  828. return isNone
  829. doInferStatic(upperBound, lengthOrd(c.c.config, concrete) + lowerBound.intVal - 1)
  830. elif upperBound.kind == nkIntLit:
  831. doInferStatic(lowerBound, getInt(upperBound) + 1 - lengthOrd(c.c.config, concrete))
  832. template subtypeCheck() =
  833. if result <= isSubrange and f.lastSon.skipTypes(abstractInst).kind in {
  834. tyRef, tyPtr, tyVar, tyLent, tyOwned}:
  835. result = isNone
  836. proc isCovariantPtr(c: var TCandidate, f, a: PType): bool =
  837. # this proc is always called for a pair of matching types
  838. assert f.kind == a.kind
  839. template baseTypesCheck(lhs, rhs: PType): bool =
  840. lhs.kind notin {tyPtr, tyRef, tyVar, tyLent, tyOwned} and
  841. typeRel(c, lhs, rhs, {trNoCovariance}) == isSubtype
  842. case f.kind
  843. of tyRef, tyPtr, tyOwned:
  844. return baseTypesCheck(f.base, a.base)
  845. of tyGenericInst:
  846. let body = f.base
  847. return body == a.base and
  848. a.len == 3 and
  849. tfWeakCovariant notin body[0].flags and
  850. baseTypesCheck(f[1], a[1])
  851. else:
  852. return false
  853. when false:
  854. proc maxNumericType(prev, candidate: PType): PType =
  855. let c = candidate.skipTypes({tyRange})
  856. template greater(s) =
  857. if c.kind in s: result = c
  858. case prev.kind
  859. of tyInt: greater({tyInt64})
  860. of tyInt8: greater({tyInt, tyInt16, tyInt32, tyInt64})
  861. of tyInt16: greater({tyInt, tyInt32, tyInt64})
  862. of tyInt32: greater({tyInt64})
  863. of tyUInt: greater({tyUInt64})
  864. of tyUInt8: greater({tyUInt, tyUInt16, tyUInt32, tyUInt64})
  865. of tyUInt16: greater({tyUInt, tyUInt32, tyUInt64})
  866. of tyUInt32: greater({tyUInt64})
  867. of tyFloat32: greater({tyFloat64, tyFloat128})
  868. of tyFloat64: greater({tyFloat128})
  869. else: discard
  870. template skipOwned(a) =
  871. if a.kind == tyOwned: a = a.skipTypes({tyOwned, tyGenericInst})
  872. proc typeRel(c: var TCandidate, f, aOrig: PType,
  873. flags: TTypeRelFlags = {}): TTypeRelation =
  874. # typeRel can be used to establish various relationships between types:
  875. #
  876. # 1) When used with concrete types, it will check for type equivalence
  877. # or a subtype relationship.
  878. #
  879. # 2) When used with a concrete type against a type class (such as generic
  880. # signature of a proc), it will check whether the concrete type is a member
  881. # of the designated type class.
  882. #
  883. # 3) When used with two type classes, it will check whether the types
  884. # matching the first type class are a strict subset of the types matching
  885. # the other. This allows us to compare the signatures of generic procs in
  886. # order to give preferrence to the most specific one:
  887. #
  888. # seq[seq[any]] is a strict subset of seq[any] and hence more specific.
  889. result = isNone
  890. assert(f != nil)
  891. when declared(deallocatedRefId):
  892. let corrupt = deallocatedRefId(cast[pointer](f))
  893. if corrupt != 0:
  894. c.c.config.quitOrRaise "it's corrupt " & $corrupt
  895. if f.kind == tyUntyped:
  896. if aOrig != nil: put(c, f, aOrig)
  897. return isGeneric
  898. assert(aOrig != nil)
  899. var
  900. useTypeLoweringRuleInTypeClass = c.c.matchedConcept != nil and
  901. not c.isNoCall and
  902. f.kind != tyTypeDesc and
  903. tfExplicit notin aOrig.flags and
  904. tfConceptMatchedTypeSym notin aOrig.flags
  905. aOrig = if useTypeLoweringRuleInTypeClass:
  906. aOrig.skipTypes({tyTypeDesc})
  907. else:
  908. aOrig
  909. if aOrig.kind == tyInferred:
  910. let prev = aOrig.previouslyInferred
  911. if prev != nil:
  912. return typeRel(c, f, prev, flags)
  913. else:
  914. var candidate = f
  915. case f.kind
  916. of tyGenericParam:
  917. var prev = PType(idTableGet(c.bindings, f))
  918. if prev != nil: candidate = prev
  919. of tyFromExpr:
  920. let computedType = tryResolvingStaticExpr(c, f.n).typ
  921. case computedType.kind
  922. of tyTypeDesc:
  923. candidate = computedType.base
  924. of tyStatic:
  925. candidate = computedType
  926. else:
  927. # XXX What is this non-sense? Error reporting in signature matching?
  928. discard "localError(f.n.info, errTypeExpected)"
  929. else:
  930. discard
  931. result = typeRel(c, aOrig.base, candidate, flags)
  932. if result != isNone:
  933. c.inferredTypes.add aOrig
  934. aOrig.add candidate
  935. result = isEqual
  936. return
  937. template doBind: bool = trDontBind notin flags
  938. # var, sink and static arguments match regular modifier-free types
  939. var a = maybeSkipDistinct(c, aOrig.skipTypes({tyStatic, tyVar, tyLent, tySink}), c.calleeSym)
  940. # XXX: Theoretically, maybeSkipDistinct could be called before we even
  941. # start the param matching process. This could be done in `prepareOperand`
  942. # for example, but unfortunately `prepareOperand` is not called in certain
  943. # situation when nkDotExpr are rotated to nkDotCalls
  944. if aOrig.kind in {tyAlias, tySink}:
  945. return typeRel(c, f, lastSon(aOrig), flags)
  946. if a.kind == tyGenericInst and
  947. skipTypes(f, {tyStatic, tyVar, tyLent, tySink}).kind notin {
  948. tyGenericBody, tyGenericInvocation,
  949. tyGenericInst, tyGenericParam} + tyTypeClasses:
  950. return typeRel(c, f, lastSon(a), flags)
  951. if a.isResolvedUserTypeClass:
  952. return typeRel(c, f, a.lastSon, flags)
  953. template bindingRet(res) =
  954. if doBind:
  955. let bound = aOrig.skipTypes({tyRange}).skipIntLit(c.c.idgen)
  956. put(c, f, bound)
  957. return res
  958. template considerPreviousT(body: untyped) =
  959. var prev = PType(idTableGet(c.bindings, f))
  960. if prev == nil: body
  961. else: return typeRel(c, prev, a, flags)
  962. case a.kind
  963. of tyOr:
  964. # XXX: deal with the current dual meaning of tyGenericParam
  965. c.typedescMatched = true
  966. # seq[int|string] vs seq[number]
  967. # both int and string must match against number
  968. # but ensure that '[T: A|A]' matches as good as '[T: A]' (bug #2219):
  969. result = isGeneric
  970. for branch in a.sons:
  971. let x = typeRel(c, f, branch, flags + {trDontBind})
  972. if x == isNone: return isNone
  973. if x < result: result = x
  974. return result
  975. of tyAnd:
  976. # XXX: deal with the current dual meaning of tyGenericParam
  977. c.typedescMatched = true
  978. # seq[Sortable and Iterable] vs seq[Sortable]
  979. # only one match is enough
  980. for branch in a.sons:
  981. let x = typeRel(c, f, branch, flags + {trDontBind})
  982. if x != isNone:
  983. return if x >= isGeneric: isGeneric else: x
  984. return isNone
  985. of tyIterable:
  986. if f.kind != tyIterable: return isNone
  987. of tyNot:
  988. case f.kind
  989. of tyNot:
  990. # seq[!int] vs seq[!number]
  991. # seq[float] matches the first, but not the second
  992. # we must turn the problem around:
  993. # is number a subset of int?
  994. return typeRel(c, a.lastSon, f.lastSon, flags)
  995. else:
  996. # negative type classes are essentially infinite,
  997. # so only the `any` type class is their superset
  998. return if f.kind == tyAnything: isGeneric
  999. else: isNone
  1000. of tyAnything:
  1001. if f.kind == tyAnything: return isGeneric
  1002. else: return isNone
  1003. of tyUserTypeClass, tyUserTypeClassInst:
  1004. if c.c.matchedConcept != nil and c.c.matchedConcept.depth <= 4:
  1005. # consider this: 'var g: Node' *within* a concept where 'Node'
  1006. # is a concept too (tgraph)
  1007. inc c.c.matchedConcept.depth
  1008. let x = typeRel(c, a, f, flags + {trDontBind})
  1009. if x >= isGeneric:
  1010. return isGeneric
  1011. else: discard
  1012. case f.kind
  1013. of tyEnum:
  1014. if a.kind == f.kind and sameEnumTypes(f, a): result = isEqual
  1015. elif sameEnumTypes(f, skipTypes(a, {tyRange})): result = isSubtype
  1016. of tyBool, tyChar:
  1017. if a.kind == f.kind: result = isEqual
  1018. elif skipTypes(a, {tyRange}).kind == f.kind: result = isSubtype
  1019. of tyRange:
  1020. if a.kind == f.kind:
  1021. if f.base.kind == tyNone: return isGeneric
  1022. result = typeRel(c, base(f), base(a), flags)
  1023. # bugfix: accept integer conversions here
  1024. #if result < isGeneric: result = isNone
  1025. if result notin {isNone, isGeneric}:
  1026. # resolve any late-bound static expressions
  1027. # that may appear in the range:
  1028. for i in 0..1:
  1029. if f.n[i].kind == nkStaticExpr:
  1030. f.n[i] = tryResolvingStaticExpr(c, f.n[i])
  1031. result = typeRangeRel(f, a)
  1032. else:
  1033. let f = skipTypes(f, {tyRange})
  1034. if f.kind == a.kind and (f.kind != tyEnum or sameEnumTypes(f, a)):
  1035. result = isIntConv
  1036. elif isConvertibleToRange(c.c, f, a):
  1037. result = isConvertible # a convertible to f
  1038. of tyInt: result = handleRange(c.c, f, a, tyInt8, c.c.config.targetSizeSignedToKind)
  1039. of tyInt8: result = handleRange(c.c, f, a, tyInt8, tyInt8)
  1040. of tyInt16: result = handleRange(c.c, f, a, tyInt8, tyInt16)
  1041. of tyInt32: result = handleRange(c.c, f, a, tyInt8, tyInt32)
  1042. of tyInt64: result = handleRange(c.c, f, a, tyInt, tyInt64)
  1043. of tyUInt: result = handleRange(c.c, f, a, tyUInt8, c.c.config.targetSizeUnsignedToKind)
  1044. of tyUInt8: result = handleRange(c.c, f, a, tyUInt8, tyUInt8)
  1045. of tyUInt16: result = handleRange(c.c, f, a, tyUInt8, tyUInt16)
  1046. of tyUInt32: result = handleRange(c.c, f, a, tyUInt8, tyUInt32)
  1047. of tyUInt64: result = handleRange(c.c, f, a, tyUInt, tyUInt64)
  1048. of tyFloat: result = handleFloatRange(f, a)
  1049. of tyFloat32: result = handleFloatRange(f, a)
  1050. of tyFloat64: result = handleFloatRange(f, a)
  1051. of tyFloat128: result = handleFloatRange(f, a)
  1052. of tyVar:
  1053. let flags = if isOutParam(f): flags + {trIsOutParam} else: flags
  1054. if aOrig.kind == f.kind and (isOutParam(aOrig) == isOutParam(f)):
  1055. result = typeRel(c, f.base, aOrig.base, flags)
  1056. else:
  1057. result = typeRel(c, f.base, aOrig, flags + {trNoCovariance})
  1058. subtypeCheck()
  1059. of tyLent:
  1060. if aOrig.kind == f.kind:
  1061. result = typeRel(c, f.base, aOrig.base, flags)
  1062. else:
  1063. result = typeRel(c, f.base, aOrig, flags + {trNoCovariance})
  1064. subtypeCheck()
  1065. of tyArray:
  1066. case a.kind
  1067. of tyArray:
  1068. var fRange = f[0]
  1069. var aRange = a[0]
  1070. if fRange.kind == tyGenericParam:
  1071. var prev = PType(idTableGet(c.bindings, fRange))
  1072. if prev == nil:
  1073. put(c, fRange, a[0])
  1074. fRange = a
  1075. else:
  1076. fRange = prev
  1077. let ff = f[1].skipTypes({tyTypeDesc})
  1078. # This typeDesc rule is wrong, see bug #7331
  1079. let aa = a[1] #.skipTypes({tyTypeDesc})
  1080. if f[0].kind != tyGenericParam and aa.kind == tyEmpty:
  1081. result = isGeneric
  1082. else:
  1083. result = typeRel(c, ff, aa, flags)
  1084. if result < isGeneric:
  1085. if nimEnableCovariance and
  1086. trNoCovariance notin flags and
  1087. ff.kind == aa.kind and
  1088. isCovariantPtr(c, ff, aa):
  1089. result = isSubtype
  1090. else:
  1091. return isNone
  1092. if fRange.rangeHasUnresolvedStatic:
  1093. return inferStaticsInRange(c, fRange, a)
  1094. elif c.c.matchedConcept != nil and aRange.rangeHasUnresolvedStatic:
  1095. return inferStaticsInRange(c, aRange, f)
  1096. else:
  1097. if lengthOrd(c.c.config, fRange) != lengthOrd(c.c.config, aRange):
  1098. result = isNone
  1099. else: discard
  1100. of tyUncheckedArray:
  1101. if a.kind == tyUncheckedArray:
  1102. result = typeRel(c, base(f), base(a), flags)
  1103. if result < isGeneric: result = isNone
  1104. else: discard
  1105. of tyOpenArray, tyVarargs:
  1106. # varargs[untyped] is special too but handled earlier. So we only need to
  1107. # handle varargs[typed]:
  1108. if f.kind == tyVarargs:
  1109. if tfVarargs in a.flags:
  1110. return typeRel(c, f.base, a.lastSon, flags)
  1111. if f[0].kind == tyTyped: return
  1112. template matchArrayOrSeq(aBase: PType) =
  1113. let ff = f.base
  1114. let aa = aBase
  1115. let baseRel = typeRel(c, ff, aa, flags)
  1116. if baseRel >= isGeneric:
  1117. result = isConvertible
  1118. elif nimEnableCovariance and
  1119. trNoCovariance notin flags and
  1120. ff.kind == aa.kind and
  1121. isCovariantPtr(c, ff, aa):
  1122. result = isConvertible
  1123. case a.kind
  1124. of tyOpenArray, tyVarargs:
  1125. result = typeRel(c, base(f), base(a), flags)
  1126. if result < isGeneric: result = isNone
  1127. of tyArray:
  1128. if (f[0].kind != tyGenericParam) and (a[1].kind == tyEmpty):
  1129. return isSubtype
  1130. matchArrayOrSeq(a[1])
  1131. of tySequence:
  1132. if (f[0].kind != tyGenericParam) and (a[0].kind == tyEmpty):
  1133. return isConvertible
  1134. matchArrayOrSeq(a[0])
  1135. of tyString:
  1136. if f.kind == tyOpenArray:
  1137. if f[0].kind == tyChar:
  1138. result = isConvertible
  1139. elif f[0].kind == tyGenericParam and a.len > 0 and
  1140. typeRel(c, base(f), base(a), flags) >= isGeneric:
  1141. result = isConvertible
  1142. else: discard
  1143. of tySequence:
  1144. case a.kind
  1145. of tySequence:
  1146. if (f[0].kind != tyGenericParam) and (a[0].kind == tyEmpty):
  1147. result = isSubtype
  1148. else:
  1149. let ff = f[0]
  1150. let aa = a[0]
  1151. result = typeRel(c, ff, aa, flags)
  1152. if result < isGeneric:
  1153. if nimEnableCovariance and
  1154. trNoCovariance notin flags and
  1155. ff.kind == aa.kind and
  1156. isCovariantPtr(c, ff, aa):
  1157. result = isSubtype
  1158. else:
  1159. result = isNone
  1160. elif tfNotNil in f.flags and tfNotNil notin a.flags:
  1161. result = isNilConversion
  1162. of tyNil: result = isNone
  1163. else: discard
  1164. of tyOrdinal:
  1165. if isOrdinalType(a, allowEnumWithHoles = optNimV1Emulation in c.c.config.globalOptions):
  1166. var x = if a.kind == tyOrdinal: a[0] else: a
  1167. if f[0].kind == tyNone:
  1168. result = isGeneric
  1169. else:
  1170. result = typeRel(c, f[0], x, flags)
  1171. if result < isGeneric: result = isNone
  1172. elif a.kind == tyGenericParam:
  1173. result = isGeneric
  1174. of tyForward:
  1175. #internalError("forward type in typeRel()")
  1176. result = isNone
  1177. of tyNil:
  1178. skipOwned(a)
  1179. if a.kind == f.kind: result = isEqual
  1180. of tyTuple:
  1181. if a.kind == tyTuple: result = recordRel(c, f, a)
  1182. of tyObject:
  1183. if a.kind == tyObject:
  1184. if sameObjectTypes(f, a):
  1185. result = isEqual
  1186. # elif tfHasMeta in f.flags: result = recordRel(c, f, a)
  1187. elif trIsOutParam notin flags:
  1188. var depth = isObjectSubtype(c, a, f, nil)
  1189. if depth > 0:
  1190. inc(c.inheritancePenalty, depth)
  1191. result = isSubtype
  1192. of tyDistinct:
  1193. a = a.skipTypes({tyOwned, tyGenericInst, tyRange})
  1194. if a.kind == tyDistinct:
  1195. if sameDistinctTypes(f, a): result = isEqual
  1196. #elif f.base.kind == tyAnything: result = isGeneric # issue 4435
  1197. elif c.coerceDistincts: result = typeRel(c, f.base, a, flags)
  1198. elif c.coerceDistincts: result = typeRel(c, f.base, a, flags)
  1199. of tySet:
  1200. if a.kind == tySet:
  1201. if f[0].kind != tyGenericParam and a[0].kind == tyEmpty:
  1202. result = isSubtype
  1203. else:
  1204. result = typeRel(c, f[0], a[0], flags)
  1205. if result < isGeneric:
  1206. if result <= isConvertible:
  1207. result = isNone
  1208. elif tfIsConstructor notin a.flags:
  1209. # set constructors are a bit special...
  1210. result = isNone
  1211. of tyPtr, tyRef:
  1212. skipOwned(a)
  1213. if a.kind == f.kind:
  1214. # ptr[R, T] can be passed to ptr[T], but not the other way round:
  1215. if a.len < f.len: return isNone
  1216. for i in 0..<f.len-1:
  1217. if typeRel(c, f[i], a[i], flags) == isNone: return isNone
  1218. result = typeRel(c, f.lastSon, a.lastSon, flags + {trNoCovariance})
  1219. subtypeCheck()
  1220. if result <= isIntConv: result = isNone
  1221. elif tfNotNil in f.flags and tfNotNil notin a.flags:
  1222. result = isNilConversion
  1223. elif a.kind == tyNil: result = f.allowsNil
  1224. else: discard
  1225. of tyProc:
  1226. skipOwned(a)
  1227. result = procTypeRel(c, f, a)
  1228. if result != isNone and tfNotNil in f.flags and tfNotNil notin a.flags:
  1229. result = isNilConversion
  1230. of tyOwned:
  1231. case a.kind
  1232. of tyOwned:
  1233. result = typeRel(c, lastSon(f), lastSon(a), flags)
  1234. of tyNil: result = f.allowsNil
  1235. else: discard
  1236. of tyPointer:
  1237. skipOwned(a)
  1238. case a.kind
  1239. of tyPointer:
  1240. if tfNotNil in f.flags and tfNotNil notin a.flags:
  1241. result = isNilConversion
  1242. else:
  1243. result = isEqual
  1244. of tyNil: result = f.allowsNil
  1245. of tyProc:
  1246. if a.callConv != ccClosure: result = isConvertible
  1247. of tyPtr:
  1248. # 'pointer' is NOT compatible to regionized pointers
  1249. # so 'dealloc(regionPtr)' fails:
  1250. if a.len == 1: result = isConvertible
  1251. of tyCstring: result = isConvertible
  1252. else: discard
  1253. of tyString:
  1254. case a.kind
  1255. of tyString:
  1256. if tfNotNil in f.flags and tfNotNil notin a.flags:
  1257. result = isNilConversion
  1258. else:
  1259. result = isEqual
  1260. of tyNil: result = isNone
  1261. else: discard
  1262. of tyCstring:
  1263. # conversion from string to cstring is automatic:
  1264. case a.kind
  1265. of tyCstring:
  1266. if tfNotNil in f.flags and tfNotNil notin a.flags:
  1267. result = isNilConversion
  1268. else:
  1269. result = isEqual
  1270. of tyNil: result = f.allowsNil
  1271. of tyString: result = isConvertible
  1272. of tyPtr:
  1273. if isDefined(c.c.config, "nimPreviewCstringConversion"):
  1274. result = isNone
  1275. else:
  1276. if a.len == 1:
  1277. let pointsTo = a[0].skipTypes(abstractInst)
  1278. if pointsTo.kind == tyChar: result = isConvertible
  1279. elif pointsTo.kind == tyUncheckedArray and pointsTo[0].kind == tyChar:
  1280. result = isConvertible
  1281. elif pointsTo.kind == tyArray and firstOrd(nil, pointsTo[0]) == 0 and
  1282. skipTypes(pointsTo[0], {tyRange}).kind in {tyInt..tyInt64} and
  1283. pointsTo[1].kind == tyChar:
  1284. result = isConvertible
  1285. else: discard
  1286. of tyEmpty, tyVoid:
  1287. if a.kind == f.kind: result = isEqual
  1288. of tyAlias, tySink:
  1289. result = typeRel(c, lastSon(f), a, flags)
  1290. of tyIterable:
  1291. if a.kind == tyIterable:
  1292. if f.len == 1:
  1293. result = typeRel(c, lastSon(f), lastSon(a), flags)
  1294. else:
  1295. # f.len = 3, for some reason
  1296. result = isGeneric
  1297. else:
  1298. result = isNone
  1299. of tyGenericInst:
  1300. var prev = PType(idTableGet(c.bindings, f))
  1301. let origF = f
  1302. var f = if prev == nil: f else: prev
  1303. let roota = a.skipGenericAlias
  1304. let rootf = f.skipGenericAlias
  1305. if a.kind == tyGenericInst:
  1306. if roota.base == rootf.base:
  1307. let nextFlags = flags + {trNoCovariance}
  1308. var hasCovariance = false
  1309. # YYYY
  1310. result = isEqual
  1311. for i in 1..<rootf.len-1:
  1312. let ff = rootf[i]
  1313. let aa = roota[i]
  1314. let res = typeRel(c, ff, aa, nextFlags)
  1315. if res != isNone and res != isEqual: result = isGeneric
  1316. if res notin {isEqual, isGeneric}:
  1317. if trNoCovariance notin flags and ff.kind == aa.kind:
  1318. let paramFlags = rootf.base[i-1].flags
  1319. hasCovariance =
  1320. if tfCovariant in paramFlags:
  1321. if tfWeakCovariant in paramFlags:
  1322. isCovariantPtr(c, ff, aa)
  1323. else:
  1324. ff.kind notin {tyRef, tyPtr} and res == isSubtype
  1325. else:
  1326. tfContravariant in paramFlags and
  1327. typeRel(c, aa, ff, flags) == isSubtype
  1328. if hasCovariance:
  1329. continue
  1330. return isNone
  1331. if prev == nil: put(c, f, a)
  1332. else:
  1333. let fKind = rootf.lastSon.kind
  1334. if fKind in {tyAnd, tyOr}:
  1335. result = typeRel(c, lastSon(f), a, flags)
  1336. if result != isNone: put(c, f, a)
  1337. return
  1338. var aAsObject = roota.lastSon
  1339. if fKind in {tyRef, tyPtr}:
  1340. if aAsObject.kind == tyObject:
  1341. # bug #7600, tyObject cannot be passed
  1342. # as argument to tyRef/tyPtr
  1343. return isNone
  1344. elif aAsObject.kind == fKind:
  1345. aAsObject = aAsObject.base
  1346. if aAsObject.kind == tyObject and trIsOutParam notin flags:
  1347. let baseType = aAsObject.base
  1348. if baseType != nil:
  1349. c.inheritancePenalty += 1
  1350. let ret = typeRel(c, f, baseType, flags)
  1351. return if ret in {isEqual,isGeneric}: isSubtype else: ret
  1352. result = isNone
  1353. else:
  1354. assert lastSon(origF) != nil
  1355. result = typeRel(c, lastSon(origF), a, flags)
  1356. if result != isNone and a.kind != tyNil:
  1357. put(c, f, a)
  1358. of tyGenericBody:
  1359. considerPreviousT:
  1360. if a == f or a.kind == tyGenericInst and a.skipGenericAlias[0] == f:
  1361. bindingRet isGeneric
  1362. let ff = lastSon(f)
  1363. if ff != nil:
  1364. result = typeRel(c, ff, a, flags)
  1365. of tyGenericInvocation:
  1366. var x = a.skipGenericAlias
  1367. let concpt = f[0].skipTypes({tyGenericBody})
  1368. var preventHack = concpt.kind == tyConcept
  1369. if x.kind == tyOwned and f[0].kind != tyOwned:
  1370. preventHack = true
  1371. x = x.lastSon
  1372. # XXX: This is very hacky. It should be moved back into liftTypeParam
  1373. if x.kind in {tyGenericInst, tyArray} and
  1374. c.calleeSym != nil and
  1375. c.calleeSym.kind in {skProc, skFunc} and c.call != nil and not preventHack:
  1376. let inst = prepareMetatypeForSigmatch(c.c, c.bindings, c.call.info, f)
  1377. #echo "inferred ", typeToString(inst), " for ", f
  1378. return typeRel(c, inst, a, flags)
  1379. if x.kind == tyGenericInvocation:
  1380. if f[0] == x[0]:
  1381. for i in 1..<f.len:
  1382. let tr = typeRel(c, f[i], x[i], flags)
  1383. if tr <= isSubtype: return
  1384. result = isGeneric
  1385. elif x.kind == tyGenericInst and f[0] == x[0] and
  1386. x.len - 1 == f.len:
  1387. for i in 1..<f.len:
  1388. if x[i].kind == tyGenericParam:
  1389. internalError(c.c.graph.config, "wrong instantiated type!")
  1390. elif typeRel(c, f[i], x[i], flags) <= isSubtype:
  1391. # Workaround for regression #4589
  1392. if f[i].kind != tyTypeDesc: return
  1393. result = isGeneric
  1394. elif x.kind == tyGenericInst and concpt.kind == tyConcept:
  1395. result = if concepts.conceptMatch(c.c, concpt, x, c.bindings, f): isGeneric
  1396. else: isNone
  1397. else:
  1398. let genericBody = f[0]
  1399. var askip = skippedNone
  1400. var fskip = skippedNone
  1401. let aobj = x.skipToObject(askip)
  1402. let fobj = genericBody.lastSon.skipToObject(fskip)
  1403. var depth = -1
  1404. if fobj != nil and aobj != nil and askip == fskip:
  1405. depth = isObjectSubtype(c, aobj, fobj, f)
  1406. result = typeRel(c, genericBody, x, flags)
  1407. if result != isNone:
  1408. # see tests/generics/tgeneric3.nim for an example that triggers this
  1409. # piece of code:
  1410. #
  1411. # proc internalFind[T,D](n: PNode[T,D], key: T): ref TItem[T,D]
  1412. # proc internalPut[T,D](ANode: ref TNode[T,D], Akey: T, Avalue: D,
  1413. # Oldvalue: var D): ref TNode[T,D]
  1414. # var root = internalPut[int, int](nil, 312, 312, oldvalue)
  1415. # var it1 = internalFind(root, 312) # cannot instantiate: 'D'
  1416. #
  1417. # we steal the generic parameters from the tyGenericBody:
  1418. for i in 1..<f.len:
  1419. let x = PType(idTableGet(c.bindings, genericBody[i-1]))
  1420. if x == nil:
  1421. discard "maybe fine (for e.g. a==tyNil)"
  1422. elif x.kind in {tyGenericInvocation, tyGenericParam}:
  1423. internalError(c.c.graph.config, "wrong instantiated type!")
  1424. else:
  1425. let key = f[i]
  1426. let old = PType(idTableGet(c.bindings, key))
  1427. if old == nil:
  1428. put(c, key, x)
  1429. elif typeRel(c, old, x, flags + {trDontBind}) == isNone:
  1430. return isNone
  1431. if result == isNone:
  1432. # Here object inheriting from generic/specialized generic object
  1433. # crossing path with metatypes/aliases, so we need to separate them
  1434. # by checking sym.id
  1435. let genericSubtype = isGenericSubtype(c, x, f, depth, f)
  1436. if not (genericSubtype and aobj.sym.id != fobj.sym.id) and aOrig.kind != tyGenericBody:
  1437. depth = -1
  1438. if depth >= 0:
  1439. c.inheritancePenalty += depth
  1440. # bug #4863: We still need to bind generic alias crap, so
  1441. # we cannot return immediately:
  1442. result = if depth == 0: isGeneric else: isSubtype
  1443. of tyAnd:
  1444. considerPreviousT:
  1445. result = isEqual
  1446. for branch in f.sons:
  1447. let x = typeRel(c, branch, aOrig, flags)
  1448. if x < isSubtype: return isNone
  1449. # 'and' implies minimum matching result:
  1450. if x < result: result = x
  1451. if result > isGeneric: result = isGeneric
  1452. bindingRet result
  1453. of tyOr:
  1454. considerPreviousT:
  1455. result = isNone
  1456. let oldInheritancePenalty = c.inheritancePenalty
  1457. var maxInheritance = 0
  1458. for branch in f.sons:
  1459. c.inheritancePenalty = 0
  1460. let x = typeRel(c, branch, aOrig, flags)
  1461. maxInheritance = max(maxInheritance, c.inheritancePenalty)
  1462. # 'or' implies maximum matching result:
  1463. if x > result: result = x
  1464. if result >= isIntConv:
  1465. if result > isGeneric: result = isGeneric
  1466. bindingRet result
  1467. else:
  1468. result = isNone
  1469. c.inheritancePenalty = oldInheritancePenalty + maxInheritance
  1470. of tyNot:
  1471. considerPreviousT:
  1472. for branch in f.sons:
  1473. if typeRel(c, branch, aOrig, flags) != isNone:
  1474. return isNone
  1475. bindingRet isGeneric
  1476. of tyAnything:
  1477. considerPreviousT:
  1478. var concrete = concreteType(c, a)
  1479. if concrete != nil and doBind:
  1480. put(c, f, concrete)
  1481. return isGeneric
  1482. of tyBuiltInTypeClass:
  1483. considerPreviousT:
  1484. let targetKind = f[0].kind
  1485. let effectiveArgType = a.skipTypes({tyRange, tyGenericInst,
  1486. tyBuiltInTypeClass, tyAlias, tySink, tyOwned})
  1487. let typeClassMatches = targetKind == effectiveArgType.kind and
  1488. not effectiveArgType.isEmptyContainer
  1489. if typeClassMatches or
  1490. (targetKind in {tyProc, tyPointer} and effectiveArgType.kind == tyNil):
  1491. put(c, f, a)
  1492. return isGeneric
  1493. else:
  1494. return isNone
  1495. of tyUserTypeClassInst, tyUserTypeClass:
  1496. if f.isResolvedUserTypeClass:
  1497. result = typeRel(c, f.lastSon, a, flags)
  1498. else:
  1499. considerPreviousT:
  1500. if aOrig == f: return isEqual
  1501. var matched = matchUserTypeClass(c, f, aOrig)
  1502. if matched != nil:
  1503. bindConcreteTypeToUserTypeClass(matched, a)
  1504. if doBind: put(c, f, matched)
  1505. result = isGeneric
  1506. elif a.len > 0 and a.lastSon == f:
  1507. # Needed for checking `Y` == `Addable` in the following
  1508. #[
  1509. type
  1510. Addable = concept a, type A
  1511. a + a is A
  1512. MyType[T: Addable; Y: static T] = object
  1513. ]#
  1514. result = isGeneric
  1515. else:
  1516. result = isNone
  1517. of tyConcept:
  1518. result = if concepts.conceptMatch(c.c, f, a, c.bindings, nil): isGeneric
  1519. else: isNone
  1520. of tyCompositeTypeClass:
  1521. considerPreviousT:
  1522. let roota = a.skipGenericAlias
  1523. let rootf = f.lastSon.skipGenericAlias
  1524. if a.kind == tyGenericInst and roota.base == rootf.base:
  1525. for i in 1..<rootf.len-1:
  1526. let ff = rootf[i]
  1527. let aa = roota[i]
  1528. result = typeRel(c, ff, aa, flags)
  1529. if result == isNone: return
  1530. if ff.kind == tyRange and result != isEqual: return isNone
  1531. else:
  1532. result = typeRel(c, rootf.lastSon, a, flags)
  1533. if result != isNone:
  1534. put(c, f, a)
  1535. result = isGeneric
  1536. of tyGenericParam:
  1537. let doBindGP = doBind or trBindGenericParam in flags
  1538. var x = PType(idTableGet(c.bindings, f))
  1539. if x == nil:
  1540. if c.callee.kind == tyGenericBody and not c.typedescMatched:
  1541. # XXX: The fact that generic types currently use tyGenericParam for
  1542. # their parameters is really a misnomer. tyGenericParam means "match
  1543. # any value" and what we need is "match any type", which can be encoded
  1544. # by a tyTypeDesc params. Unfortunately, this requires more substantial
  1545. # changes in semtypinst and elsewhere.
  1546. if tfWildcard in a.flags:
  1547. result = isGeneric
  1548. elif a.kind == tyTypeDesc:
  1549. if f.len == 0:
  1550. result = isGeneric
  1551. else:
  1552. internalAssert c.c.graph.config, a.len > 0
  1553. c.typedescMatched = true
  1554. var aa = a
  1555. while aa.kind in {tyTypeDesc, tyGenericParam} and aa.len > 0:
  1556. aa = lastSon(aa)
  1557. if aa.kind in {tyGenericParam} + tyTypeClasses:
  1558. # If the constraint is a genericParam or typeClass this isGeneric
  1559. return isGeneric
  1560. result = typeRel(c, f.base, aa, flags)
  1561. if result > isGeneric: result = isGeneric
  1562. elif c.isNoCall:
  1563. if doBindGP:
  1564. let concrete = concreteType(c, a, f)
  1565. if concrete == nil: return isNone
  1566. put(c, f, concrete)
  1567. result = isGeneric
  1568. else:
  1569. result = isNone
  1570. else:
  1571. # check if 'T' has a constraint as in 'proc p[T: Constraint](x: T)'
  1572. if f.len > 0 and f[0].kind != tyNone:
  1573. let oldInheritancePenalty = c.inheritancePenalty
  1574. result = typeRel(c, f[0], a, flags + {trDontBind,trBindGenericParam})
  1575. if doBindGP and result notin {isNone, isGeneric}:
  1576. let concrete = concreteType(c, a, f)
  1577. if concrete == nil: return isNone
  1578. put(c, f, concrete)
  1579. # bug #6526
  1580. if result in {isEqual, isSubtype}:
  1581. # 'T: Class' is a *better* match than just 'T'
  1582. # but 'T: Subclass' is even better:
  1583. c.inheritancePenalty = oldInheritancePenalty - c.inheritancePenalty -
  1584. 100 * ord(result == isEqual)
  1585. result = isGeneric
  1586. elif a.kind == tyTypeDesc:
  1587. # somewhat special typing rule, the following is illegal:
  1588. # proc p[T](x: T)
  1589. # p(int)
  1590. result = isNone
  1591. else:
  1592. result = isGeneric
  1593. if result == isGeneric:
  1594. var concrete = a
  1595. if tfWildcard in a.flags:
  1596. a.sym.transitionGenericParamToType()
  1597. a.flags.excl tfWildcard
  1598. else:
  1599. concrete = concreteType(c, a, f)
  1600. if concrete == nil:
  1601. return isNone
  1602. if doBindGP:
  1603. put(c, f, concrete)
  1604. elif result > isGeneric:
  1605. result = isGeneric
  1606. elif a.kind == tyEmpty:
  1607. result = isGeneric
  1608. elif x.kind == tyGenericParam:
  1609. result = isGeneric
  1610. else:
  1611. result = typeRel(c, x, a, flags) # check if it fits
  1612. if result > isGeneric: result = isGeneric
  1613. of tyStatic:
  1614. let prev = PType(idTableGet(c.bindings, f))
  1615. if prev == nil:
  1616. if aOrig.kind == tyStatic:
  1617. if f.base.kind notin {tyNone, tyGenericParam}:
  1618. result = typeRel(c, f.base, a, flags)
  1619. if result != isNone and f.n != nil:
  1620. if not exprStructuralEquivalent(f.n, aOrig.n):
  1621. result = isNone
  1622. elif f.base.kind == tyGenericParam:
  1623. # Handling things like `type A[T; Y: static T] = object`
  1624. if f.base.len > 0: # There is a constraint, handle it
  1625. result = typeRel(c, f.base.lastSon, a, flags)
  1626. else:
  1627. # No constraint
  1628. if tfGenericTypeParam in f.flags:
  1629. result = isGeneric
  1630. else:
  1631. # for things like `proc fun[T](a: static[T])`
  1632. result = typeRel(c, f.base, a, flags)
  1633. else:
  1634. result = isGeneric
  1635. if result != isNone: put(c, f, aOrig)
  1636. elif aOrig.n != nil and aOrig.n.typ != nil:
  1637. result = if f.base.kind != tyNone:
  1638. typeRel(c, f.lastSon, aOrig.n.typ, flags)
  1639. else: isGeneric
  1640. if result != isNone:
  1641. var boundType = newTypeWithSons(c.c, tyStatic, @[aOrig.n.typ])
  1642. boundType.n = aOrig.n
  1643. put(c, f, boundType)
  1644. else:
  1645. result = isNone
  1646. elif prev.kind == tyStatic:
  1647. if aOrig.kind == tyStatic:
  1648. result = typeRel(c, prev.lastSon, a, flags)
  1649. if result != isNone and prev.n != nil:
  1650. if not exprStructuralEquivalent(prev.n, aOrig.n):
  1651. result = isNone
  1652. else: result = isNone
  1653. else:
  1654. # XXX endless recursion?
  1655. #result = typeRel(c, prev, aOrig, flags)
  1656. result = isNone
  1657. of tyInferred:
  1658. let prev = f.previouslyInferred
  1659. if prev != nil:
  1660. result = typeRel(c, prev, a, flags)
  1661. else:
  1662. result = typeRel(c, f.base, a, flags)
  1663. if result != isNone:
  1664. c.inferredTypes.add f
  1665. f.add a
  1666. of tyTypeDesc:
  1667. var prev = PType(idTableGet(c.bindings, f))
  1668. if prev == nil:
  1669. # proc foo(T: typedesc, x: T)
  1670. # when `f` is an unresolved typedesc, `a` could be any
  1671. # type, so we should not perform this check earlier
  1672. if a.kind != tyTypeDesc:
  1673. if a.kind == tyGenericParam and tfWildcard in a.flags:
  1674. # TODO: prevent `a` from matching as a wildcard again
  1675. result = isGeneric
  1676. else:
  1677. result = isNone
  1678. elif f.base.kind == tyNone:
  1679. result = isGeneric
  1680. else:
  1681. result = typeRel(c, f.base, a.base, flags)
  1682. if result != isNone:
  1683. put(c, f, a)
  1684. else:
  1685. if tfUnresolved in f.flags:
  1686. result = typeRel(c, prev.base, a, flags)
  1687. elif a.kind == tyTypeDesc:
  1688. result = typeRel(c, prev.base, a.base, flags)
  1689. else:
  1690. result = isNone
  1691. of tyTyped:
  1692. if aOrig != nil:
  1693. put(c, f, aOrig)
  1694. result = isGeneric
  1695. of tyProxy:
  1696. result = isEqual
  1697. of tyFromExpr:
  1698. # fix the expression, so it contains the already instantiated types
  1699. if f.n == nil or f.n.kind == nkEmpty: return isGeneric
  1700. let reevaluated = tryResolvingStaticExpr(c, f.n)
  1701. case reevaluated.typ.kind
  1702. of tyTypeDesc:
  1703. result = typeRel(c, a, reevaluated.typ.base, flags)
  1704. of tyStatic:
  1705. result = typeRel(c, a, reevaluated.typ.base, flags)
  1706. if result != isNone and reevaluated.typ.n != nil:
  1707. if not exprStructuralEquivalent(aOrig.n, reevaluated.typ.n):
  1708. result = isNone
  1709. else:
  1710. # bug #14136: other types are just like 'tyStatic' here:
  1711. result = typeRel(c, a, reevaluated.typ, flags)
  1712. if result != isNone and reevaluated.typ.n != nil:
  1713. if not exprStructuralEquivalent(aOrig.n, reevaluated.typ.n):
  1714. result = isNone
  1715. of tyNone:
  1716. if a.kind == tyNone: result = isEqual
  1717. else:
  1718. internalError c.c.graph.config, " unknown type kind " & $f.kind
  1719. when false:
  1720. var nowDebug = false
  1721. var dbgCount = 0
  1722. proc typeRel(c: var TCandidate, f, aOrig: PType,
  1723. flags: TTypeRelFlags = {}): TTypeRelation =
  1724. if nowDebug:
  1725. echo f, " <- ", aOrig
  1726. inc dbgCount
  1727. if dbgCount == 2:
  1728. writeStackTrace()
  1729. result = typeRelImpl(c, f, aOrig, flags)
  1730. if nowDebug:
  1731. echo f, " <- ", aOrig, " res ", result
  1732. proc cmpTypes*(c: PContext, f, a: PType): TTypeRelation =
  1733. var m = newCandidate(c, f)
  1734. result = typeRel(m, f, a)
  1735. proc getInstantiatedType(c: PContext, arg: PNode, m: TCandidate,
  1736. f: PType): PType =
  1737. result = PType(idTableGet(m.bindings, f))
  1738. if result == nil:
  1739. result = generateTypeInstance(c, m.bindings, arg, f)
  1740. if result == nil:
  1741. internalError(c.graph.config, arg.info, "getInstantiatedType")
  1742. result = errorType(c)
  1743. proc implicitConv(kind: TNodeKind, f: PType, arg: PNode, m: TCandidate,
  1744. c: PContext): PNode =
  1745. result = newNodeI(kind, arg.info)
  1746. if containsGenericType(f):
  1747. if not m.hasFauxMatch:
  1748. result.typ = getInstantiatedType(c, arg, m, f).skipTypes({tySink})
  1749. else:
  1750. result.typ = errorType(c)
  1751. else:
  1752. result.typ = f.skipTypes({tySink, tyVar})
  1753. if result.typ == nil: internalError(c.graph.config, arg.info, "implicitConv")
  1754. result.add c.graph.emptyNode
  1755. result.add arg
  1756. proc isLValue(c: PContext; n: PNode, isOutParam = false): bool {.inline.} =
  1757. let aa = isAssignable(nil, n)
  1758. case aa
  1759. of arLValue, arLocalLValue, arStrange:
  1760. result = true
  1761. of arDiscriminant:
  1762. result = c.inUncheckedAssignSection > 0
  1763. of arAddressableConst:
  1764. let sym = getRoot(n)
  1765. result = strictDefs in c.features and sym != nil and sym.kind == skLet and isOutParam
  1766. else:
  1767. result = false
  1768. proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType,
  1769. arg: PNode): PNode =
  1770. result = nil
  1771. for i in 0..<c.converters.len:
  1772. var src = c.converters[i].typ[1]
  1773. var dest = c.converters[i].typ[0]
  1774. # for generic type converters we need to check 'src <- a' before
  1775. # 'f <- dest' in order to not break the unification:
  1776. # see tests/tgenericconverter:
  1777. let srca = typeRel(m, src, a)
  1778. if srca notin {isEqual, isGeneric, isSubtype}: continue
  1779. # What's done below matches the logic in ``matchesAux``
  1780. let constraint = c.converters[i].typ.n[1].sym.constraint
  1781. if not constraint.isNil and not matchNodeKinds(constraint, arg):
  1782. continue
  1783. if src.kind in {tyVar, tyLent} and not isLValue(c, arg):
  1784. continue
  1785. let destIsGeneric = containsGenericType(dest)
  1786. if destIsGeneric:
  1787. dest = generateTypeInstance(c, m.bindings, arg, dest)
  1788. let fdest = typeRel(m, f, dest)
  1789. if fdest in {isEqual, isGeneric} and not (dest.kind == tyLent and f.kind in {tyVar}):
  1790. markUsed(c, arg.info, c.converters[i])
  1791. var s = newSymNode(c.converters[i])
  1792. s.typ = c.converters[i].typ
  1793. s.info = arg.info
  1794. result = newNodeIT(nkHiddenCallConv, arg.info, dest)
  1795. result.add s
  1796. # We build the call expression by ourselves in order to avoid passing this
  1797. # expression trough the semantic check phase once again so let's make sure
  1798. # it is correct
  1799. var param: PNode = nil
  1800. if srca == isSubtype:
  1801. param = implicitConv(nkHiddenSubConv, src, copyTree(arg), m, c)
  1802. elif src.kind in {tyVar}:
  1803. # Analyse the converter return type
  1804. param = newNodeIT(nkHiddenAddr, arg.info, s.typ[1])
  1805. param.add copyTree(arg)
  1806. else:
  1807. param = copyTree(arg)
  1808. result.add param
  1809. if dest.kind in {tyVar, tyLent}:
  1810. dest.flags.incl tfVarIsPtr
  1811. result = newDeref(result)
  1812. inc(m.convMatches)
  1813. if not m.genericConverter:
  1814. m.genericConverter = srca == isGeneric or destIsGeneric
  1815. return result
  1816. proc localConvMatch(c: PContext, m: var TCandidate, f, a: PType,
  1817. arg: PNode): PNode =
  1818. # arg.typ can be nil in 'suggest':
  1819. if isNil(arg.typ): return nil
  1820. # sem'checking for 'echo' needs to be re-entrant:
  1821. # XXX we will revisit this issue after 0.10.2 is released
  1822. if f == arg.typ and arg.kind == nkHiddenStdConv: return arg
  1823. var call = newNodeI(nkCall, arg.info)
  1824. call.add(f.n.copyTree)
  1825. call.add(arg.copyTree)
  1826. # XXX: This would be much nicer if we don't use `semTryExpr` and
  1827. # instead we directly search for overloads with `resolveOverloads`:
  1828. result = c.semTryExpr(c, call, {efNoSem2Check})
  1829. if result != nil:
  1830. if result.typ == nil: return nil
  1831. # bug #13378, ensure we produce a real generic instantiation:
  1832. result = c.semExpr(c, call)
  1833. # resulting type must be consistent with the other arguments:
  1834. var r = typeRel(m, f[0], result.typ)
  1835. if r < isGeneric: return nil
  1836. if result.kind == nkCall: result.transitionSonsKind(nkHiddenCallConv)
  1837. inc(m.convMatches)
  1838. if r == isGeneric:
  1839. result.typ = getInstantiatedType(c, arg, m, base(f))
  1840. m.baseTypeMatch = true
  1841. proc incMatches(m: var TCandidate; r: TTypeRelation; convMatch = 1) =
  1842. case r
  1843. of isConvertible, isIntConv: inc(m.convMatches, convMatch)
  1844. of isSubtype, isSubrange: inc(m.subtypeMatches)
  1845. of isGeneric, isInferred, isBothMetaConvertible: inc(m.genericMatches)
  1846. of isFromIntLit: inc(m.intConvMatches, 256)
  1847. of isInferredConvertible:
  1848. inc(m.convMatches)
  1849. of isEqual: inc(m.exactMatches)
  1850. of isNone: discard
  1851. template matchesVoidProc(t: PType): bool =
  1852. (t.kind == tyProc and t.len == 1 and t[0] == nil) or
  1853. (t.kind == tyBuiltInTypeClass and t[0].kind == tyProc)
  1854. proc paramTypesMatchAux(m: var TCandidate, f, a: PType,
  1855. argSemantized, argOrig: PNode): PNode =
  1856. var
  1857. fMaybeStatic = f.skipTypes({tyDistinct})
  1858. arg = argSemantized
  1859. a = a
  1860. c = m.c
  1861. if tfHasStatic in fMaybeStatic.flags:
  1862. # XXX: When implicit statics are the default
  1863. # this will be done earlier - we just have to
  1864. # make sure that static types enter here
  1865. # Zahary: weaken tyGenericParam and call it tyGenericPlaceholder
  1866. # and finally start using tyTypedesc for generic types properly.
  1867. # Araq: This would only shift the problems around, in 'proc p[T](x: T)'
  1868. # the T is NOT a typedesc.
  1869. if a.kind == tyGenericParam and tfWildcard in a.flags:
  1870. a.assignType(f)
  1871. # put(m.bindings, f, a)
  1872. return argSemantized
  1873. if a.kind == tyStatic:
  1874. if m.callee.kind == tyGenericBody and
  1875. a.n == nil and
  1876. tfGenericTypeParam notin a.flags:
  1877. return newNodeIT(nkType, argOrig.info, makeTypeFromExpr(c, arg))
  1878. elif arg.kind != nkEmpty:
  1879. var evaluated = c.semTryConstExpr(c, arg)
  1880. if evaluated != nil:
  1881. # Don't build the type in-place because `evaluated` and `arg` may point
  1882. # to the same object and we'd end up creating recursive types (#9255)
  1883. let typ = newTypeS(tyStatic, c)
  1884. typ.sons = @[evaluated.typ]
  1885. typ.n = evaluated
  1886. arg = copyTree(arg) # fix #12864
  1887. arg.typ = typ
  1888. a = typ
  1889. else:
  1890. if m.callee.kind == tyGenericBody:
  1891. if f.kind == tyStatic and typeRel(m, f.base, a) != isNone:
  1892. result = makeStaticExpr(m.c, arg)
  1893. result.typ.flags.incl tfUnresolved
  1894. result.typ.n = arg
  1895. return
  1896. let oldInheritancePenalty = m.inheritancePenalty
  1897. var r = typeRel(m, f, a)
  1898. # This special typing rule for macros and templates is not documented
  1899. # anywhere and breaks symmetry. It's hard to get rid of though, my
  1900. # custom seqs example fails to compile without this:
  1901. if r != isNone and m.calleeSym != nil and
  1902. m.calleeSym.kind in {skMacro, skTemplate}:
  1903. # XXX: duplicating this is ugly, but we cannot (!) move this
  1904. # directly into typeRel using return-like templates
  1905. incMatches(m, r)
  1906. if f.kind == tyTyped:
  1907. return arg
  1908. elif f.kind == tyTypeDesc:
  1909. return arg
  1910. elif f.kind == tyStatic and arg.typ.n != nil:
  1911. return arg.typ.n
  1912. else:
  1913. return argSemantized # argOrig
  1914. # If r == isBothMetaConvertible then we rerun typeRel.
  1915. # bothMetaCounter is for safety to avoid any infinite loop,
  1916. # I don't have any example when it is needed.
  1917. # lastBindingsLenth is used to check whether m.bindings remains the same,
  1918. # because in that case there is no point in continuing.
  1919. var bothMetaCounter = 0
  1920. var lastBindingsLength = -1
  1921. while r == isBothMetaConvertible and
  1922. lastBindingsLength != m.bindings.counter and
  1923. bothMetaCounter < 100:
  1924. lastBindingsLength = m.bindings.counter
  1925. inc(bothMetaCounter)
  1926. if arg.kind in {nkProcDef, nkFuncDef, nkIteratorDef} + nkLambdaKinds:
  1927. result = c.semInferredLambda(c, m.bindings, arg)
  1928. elif arg.kind != nkSym:
  1929. return nil
  1930. else:
  1931. let inferred = c.semGenerateInstance(c, arg.sym, m.bindings, arg.info)
  1932. result = newSymNode(inferred, arg.info)
  1933. inc(m.convMatches)
  1934. arg = result
  1935. r = typeRel(m, f, arg.typ)
  1936. case r
  1937. of isConvertible:
  1938. if f.skipTypes({tyRange}).kind in {tyInt, tyUInt}:
  1939. inc(m.convMatches)
  1940. inc(m.convMatches)
  1941. result = implicitConv(nkHiddenStdConv, f, arg, m, c)
  1942. of isIntConv:
  1943. # I'm too lazy to introduce another ``*matches`` field, so we conflate
  1944. # ``isIntConv`` and ``isIntLit`` here:
  1945. if f.skipTypes({tyRange}).kind notin {tyInt, tyUInt}:
  1946. inc(m.intConvMatches)
  1947. inc(m.intConvMatches)
  1948. result = implicitConv(nkHiddenStdConv, f, arg, m, c)
  1949. of isSubtype:
  1950. inc(m.subtypeMatches)
  1951. if f.kind == tyTypeDesc:
  1952. result = arg
  1953. else:
  1954. result = implicitConv(nkHiddenSubConv, f, arg, m, c)
  1955. of isSubrange:
  1956. inc(m.subtypeMatches)
  1957. if f.kind in {tyVar}:
  1958. result = arg
  1959. else:
  1960. result = implicitConv(nkHiddenStdConv, f, arg, m, c)
  1961. of isInferred, isInferredConvertible:
  1962. if arg.kind in {nkProcDef, nkFuncDef, nkIteratorDef} + nkLambdaKinds:
  1963. result = c.semInferredLambda(c, m.bindings, arg)
  1964. elif arg.kind != nkSym:
  1965. return nil
  1966. elif arg.sym.kind in {skMacro, skTemplate}:
  1967. return nil
  1968. else:
  1969. if arg.sym.ast == nil:
  1970. return nil
  1971. let inferred = c.semGenerateInstance(c, arg.sym, m.bindings, arg.info)
  1972. result = newSymNode(inferred, arg.info)
  1973. if r == isInferredConvertible:
  1974. inc(m.convMatches)
  1975. result = implicitConv(nkHiddenStdConv, f, result, m, c)
  1976. else:
  1977. inc(m.genericMatches)
  1978. of isGeneric:
  1979. inc(m.genericMatches)
  1980. if arg.typ == nil:
  1981. result = arg
  1982. elif skipTypes(arg.typ, abstractVar-{tyTypeDesc}).kind == tyTuple or
  1983. m.inheritancePenalty > oldInheritancePenalty:
  1984. result = implicitConv(nkHiddenSubConv, f, arg, m, c)
  1985. elif arg.typ.isEmptyContainer:
  1986. result = arg.copyTree
  1987. result.typ = getInstantiatedType(c, arg, m, f)
  1988. else:
  1989. result = arg
  1990. of isBothMetaConvertible:
  1991. # This is the result for the 101th time.
  1992. result = nil
  1993. of isFromIntLit:
  1994. # too lazy to introduce another ``*matches`` field, so we conflate
  1995. # ``isIntConv`` and ``isIntLit`` here:
  1996. inc(m.intConvMatches, 256)
  1997. result = implicitConv(nkHiddenStdConv, f, arg, m, c)
  1998. of isEqual:
  1999. inc(m.exactMatches)
  2000. result = arg
  2001. let ff = skipTypes(f, abstractVar-{tyTypeDesc})
  2002. if ff.kind == tyTuple or
  2003. (arg.typ != nil and skipTypes(arg.typ, abstractVar-{tyTypeDesc}).kind == tyTuple):
  2004. result = implicitConv(nkHiddenSubConv, f, arg, m, c)
  2005. of isNone:
  2006. # do not do this in ``typeRel`` as it then can't infer T in ``ref T``:
  2007. if a.kind in {tyProxy, tyUnknown}:
  2008. inc(m.genericMatches)
  2009. m.fauxMatch = a.kind
  2010. return arg
  2011. elif a.kind == tyVoid and f.matchesVoidProc and argOrig.kind == nkStmtList:
  2012. # lift do blocks without params to lambdas
  2013. # now deprecated
  2014. message(c.config, argOrig.info, warnStmtListLambda)
  2015. let p = c.graph
  2016. let lifted = c.semExpr(c, newProcNode(nkDo, argOrig.info, body = argOrig,
  2017. params = nkFormalParams.newTree(p.emptyNode), name = p.emptyNode, pattern = p.emptyNode,
  2018. genericParams = p.emptyNode, pragmas = p.emptyNode, exceptions = p.emptyNode), {})
  2019. if f.kind == tyBuiltInTypeClass:
  2020. inc m.genericMatches
  2021. put(m, f, lifted.typ)
  2022. inc m.convMatches
  2023. return implicitConv(nkHiddenStdConv, f, lifted, m, c)
  2024. result = userConvMatch(c, m, f, a, arg)
  2025. # check for a base type match, which supports varargs[T] without []
  2026. # constructor in a call:
  2027. if result == nil and f.kind == tyVarargs:
  2028. if f.n != nil:
  2029. # Forward to the varargs converter
  2030. result = localConvMatch(c, m, f, a, arg)
  2031. else:
  2032. r = typeRel(m, base(f), a)
  2033. case r
  2034. of isGeneric:
  2035. inc(m.convMatches)
  2036. result = copyTree(arg)
  2037. result.typ = getInstantiatedType(c, arg, m, base(f))
  2038. m.baseTypeMatch = true
  2039. of isFromIntLit:
  2040. inc(m.intConvMatches, 256)
  2041. result = implicitConv(nkHiddenStdConv, f[0], arg, m, c)
  2042. m.baseTypeMatch = true
  2043. of isEqual:
  2044. inc(m.convMatches)
  2045. result = copyTree(arg)
  2046. m.baseTypeMatch = true
  2047. of isSubtype: # bug #4799, varargs accepting subtype relation object
  2048. inc(m.subtypeMatches)
  2049. if base(f).kind == tyTypeDesc:
  2050. result = arg
  2051. else:
  2052. result = implicitConv(nkHiddenSubConv, base(f), arg, m, c)
  2053. m.baseTypeMatch = true
  2054. else:
  2055. result = userConvMatch(c, m, base(f), a, arg)
  2056. if result != nil: m.baseTypeMatch = true
  2057. proc paramTypesMatch*(m: var TCandidate, f, a: PType,
  2058. arg, argOrig: PNode): PNode =
  2059. if arg == nil or arg.kind notin nkSymChoices:
  2060. result = paramTypesMatchAux(m, f, a, arg, argOrig)
  2061. else:
  2062. # CAUTION: The order depends on the used hashing scheme. Thus it is
  2063. # incorrect to simply use the first fitting match. However, to implement
  2064. # this correctly is inefficient. We have to copy `m` here to be able to
  2065. # roll back the side effects of the unification algorithm.
  2066. let c = m.c
  2067. var
  2068. x = newCandidate(c, m.callee)
  2069. y = newCandidate(c, m.callee)
  2070. z = newCandidate(c, m.callee)
  2071. x.calleeSym = m.calleeSym
  2072. y.calleeSym = m.calleeSym
  2073. z.calleeSym = m.calleeSym
  2074. var best = -1
  2075. for i in 0..<arg.len:
  2076. if arg[i].sym.kind in {skProc, skFunc, skMethod, skConverter,
  2077. skIterator, skMacro, skTemplate, skEnumField}:
  2078. copyCandidate(z, m)
  2079. z.callee = arg[i].typ
  2080. if tfUnresolved in z.callee.flags: continue
  2081. z.calleeSym = arg[i].sym
  2082. # XXX this is still all wrong: (T, T) should be 2 generic matches
  2083. # and (int, int) 2 exact matches, etc. Essentially you cannot call
  2084. # typeRel here and expect things to work!
  2085. let r = typeRel(z, f, arg[i].typ)
  2086. incMatches(z, r, 2)
  2087. if r != isNone:
  2088. z.state = csMatch
  2089. case x.state
  2090. of csEmpty, csNoMatch:
  2091. x = z
  2092. best = i
  2093. of csMatch:
  2094. let cmp = cmpCandidates(x, z)
  2095. if cmp < 0:
  2096. best = i
  2097. x = z
  2098. elif cmp == 0:
  2099. y = z # z is as good as x
  2100. if x.state == csEmpty:
  2101. result = nil
  2102. elif y.state == csMatch and cmpCandidates(x, y) == 0:
  2103. if x.state != csMatch:
  2104. internalError(m.c.graph.config, arg.info, "x.state is not csMatch")
  2105. # ambiguous: more than one symbol fits!
  2106. # See tsymchoice_for_expr as an example. 'f.kind == tyUntyped' should match
  2107. # anyway:
  2108. if f.kind in {tyUntyped, tyTyped}: result = arg
  2109. else: result = nil
  2110. else:
  2111. # only one valid interpretation found:
  2112. markUsed(m.c, arg.info, arg[best].sym)
  2113. onUse(arg.info, arg[best].sym)
  2114. result = paramTypesMatchAux(m, f, arg[best].typ, arg[best], argOrig)
  2115. when false:
  2116. if m.calleeSym != nil and m.calleeSym.name.s == "[]":
  2117. echo m.c.config $ arg.info, " for ", m.calleeSym.name.s, " ", m.c.config $ m.calleeSym.info
  2118. writeMatches(m)
  2119. proc setSon(father: PNode, at: int, son: PNode) =
  2120. let oldLen = father.len
  2121. if oldLen <= at:
  2122. setLen(father.sons, at + 1)
  2123. father[at] = son
  2124. # insert potential 'void' parameters:
  2125. #for i in oldLen..<at:
  2126. # father[i] = newNodeIT(nkEmpty, son.info, getSysType(tyVoid))
  2127. # we are allowed to modify the calling node in the 'prepare*' procs:
  2128. proc prepareOperand(c: PContext; formal: PType; a: PNode): PNode =
  2129. if formal.kind == tyUntyped and formal.len != 1:
  2130. # {tyTypeDesc, tyUntyped, tyTyped, tyProxy}:
  2131. # a.typ == nil is valid
  2132. result = a
  2133. elif a.typ.isNil:
  2134. if formal.kind == tyIterable:
  2135. let flags = {efDetermineType, efAllowStmt, efWantIterator, efWantIterable}
  2136. result = c.semOperand(c, a, flags)
  2137. else:
  2138. # XXX This is unsound! 'formal' can differ from overloaded routine to
  2139. # overloaded routine!
  2140. let flags = {efDetermineType, efAllowStmt}
  2141. #if formal.kind == tyIterable: {efDetermineType, efWantIterator}
  2142. #else: {efDetermineType, efAllowStmt}
  2143. #elif formal.kind == tyTyped: {efDetermineType, efWantStmt}
  2144. #else: {efDetermineType}
  2145. result = c.semOperand(c, a, flags)
  2146. else:
  2147. result = a
  2148. considerGenSyms(c, result)
  2149. if result.kind != nkHiddenDeref and result.typ.kind in {tyVar, tyLent} and c.matchedConcept == nil:
  2150. result = newDeref(result)
  2151. proc prepareOperand(c: PContext; a: PNode): PNode =
  2152. if a.typ.isNil:
  2153. result = c.semOperand(c, a, {efDetermineType})
  2154. else:
  2155. result = a
  2156. considerGenSyms(c, result)
  2157. proc prepareNamedParam(a: PNode; c: PContext) =
  2158. if a[0].kind != nkIdent:
  2159. var info = a[0].info
  2160. a[0] = newIdentNode(considerQuotedIdent(c, a[0]), info)
  2161. proc arrayConstr(c: PContext, n: PNode): PType =
  2162. result = newTypeS(tyArray, c)
  2163. rawAddSon(result, makeRangeType(c, 0, 0, n.info))
  2164. addSonSkipIntLit(result, skipTypes(n.typ,
  2165. {tyGenericInst, tyVar, tyLent, tyOrdinal}), c.idgen)
  2166. proc arrayConstr(c: PContext, info: TLineInfo): PType =
  2167. result = newTypeS(tyArray, c)
  2168. rawAddSon(result, makeRangeType(c, 0, -1, info))
  2169. rawAddSon(result, newTypeS(tyEmpty, c)) # needs an empty basetype!
  2170. proc incrIndexType(t: PType) =
  2171. assert t.kind == tyArray
  2172. inc t[0].n[1].intVal
  2173. template isVarargsUntyped(x): untyped =
  2174. x.kind == tyVarargs and x[0].kind == tyUntyped
  2175. proc findFirstArgBlock(m: var TCandidate, n: PNode): int =
  2176. # see https://github.com/nim-lang/RFCs/issues/405
  2177. result = int.high
  2178. for a2 in countdown(n.len-1, 0):
  2179. # checking `nfBlockArg in n[a2].flags` wouldn't work inside templates
  2180. if n[a2].kind != nkStmtList: break
  2181. let formalLast = m.callee.n[m.callee.n.len - (n.len - a2)]
  2182. if formalLast.kind == nkSym and formalLast.sym.ast == nil:
  2183. result = a2
  2184. else: break
  2185. proc matchesAux(c: PContext, n, nOrig: PNode, m: var TCandidate, marker: var IntSet) =
  2186. template noMatch() =
  2187. c.mergeShadowScope #merge so that we don't have to resem for later overloads
  2188. m.state = csNoMatch
  2189. m.firstMismatch.arg = a
  2190. m.firstMismatch.formal = formal
  2191. return
  2192. template checkConstraint(n: untyped) {.dirty.} =
  2193. if not formal.constraint.isNil:
  2194. if matchNodeKinds(formal.constraint, n):
  2195. # better match over other routines with no such restriction:
  2196. inc(m.genericMatches, 100)
  2197. else:
  2198. noMatch()
  2199. if formal.typ.kind in {tyVar}:
  2200. let argConverter = if arg.kind == nkHiddenDeref: arg[0] else: arg
  2201. if argConverter.kind == nkHiddenCallConv:
  2202. if argConverter.typ.kind notin {tyVar}:
  2203. m.firstMismatch.kind = kVarNeeded
  2204. noMatch()
  2205. elif not (isLValue(c, n, isOutParam(formal.typ))):
  2206. m.firstMismatch.kind = kVarNeeded
  2207. noMatch()
  2208. m.state = csMatch # until proven otherwise
  2209. m.firstMismatch = MismatchInfo()
  2210. m.call = newNodeIT(n.kind, n.info, m.callee.base)
  2211. m.call.add n[0]
  2212. var
  2213. a = 1 # iterates over the actual given arguments
  2214. f = if m.callee.kind != tyGenericBody: 1
  2215. else: 0 # iterates over formal parameters
  2216. arg: PNode # current prepared argument
  2217. formalLen = m.callee.n.len
  2218. formal = if formalLen > 1: m.callee.n[1].sym else: nil # current routine parameter
  2219. container: PNode = nil # constructed container
  2220. let firstArgBlock = findFirstArgBlock(m, n)
  2221. while a < n.len:
  2222. c.openShadowScope
  2223. if a >= formalLen-1 and f < formalLen and m.callee.n[f].typ.isVarargsUntyped:
  2224. formal = m.callee.n[f].sym
  2225. incl(marker, formal.position)
  2226. if n[a].kind == nkHiddenStdConv:
  2227. doAssert n[a][0].kind == nkEmpty and
  2228. n[a][1].kind in {nkBracket, nkArgList}
  2229. # Steal the container and pass it along
  2230. setSon(m.call, formal.position + 1, n[a][1])
  2231. else:
  2232. if container.isNil:
  2233. container = newNodeIT(nkArgList, n[a].info, arrayConstr(c, n.info))
  2234. setSon(m.call, formal.position + 1, container)
  2235. else:
  2236. incrIndexType(container.typ)
  2237. container.add n[a]
  2238. elif n[a].kind == nkExprEqExpr:
  2239. # named param
  2240. m.firstMismatch.kind = kUnknownNamedParam
  2241. # check if m.callee has such a param:
  2242. prepareNamedParam(n[a], c)
  2243. if n[a][0].kind != nkIdent:
  2244. localError(c.config, n[a].info, "named parameter has to be an identifier")
  2245. noMatch()
  2246. formal = getNamedParamFromList(m.callee.n, n[a][0].ident)
  2247. if formal == nil:
  2248. # no error message!
  2249. noMatch()
  2250. if containsOrIncl(marker, formal.position):
  2251. m.firstMismatch.kind = kAlreadyGiven
  2252. # already in namedParams, so no match
  2253. # we used to produce 'errCannotBindXTwice' here but see
  2254. # bug #3836 of why that is not sound (other overload with
  2255. # different parameter names could match later on):
  2256. when false: localError(n[a].info, errCannotBindXTwice, formal.name.s)
  2257. noMatch()
  2258. m.baseTypeMatch = false
  2259. m.typedescMatched = false
  2260. n[a][1] = prepareOperand(c, formal.typ, n[a][1])
  2261. n[a].typ = n[a][1].typ
  2262. arg = paramTypesMatch(m, formal.typ, n[a].typ,
  2263. n[a][1], n[a][1])
  2264. m.firstMismatch.kind = kTypeMismatch
  2265. if arg == nil:
  2266. noMatch()
  2267. checkConstraint(n[a][1])
  2268. if m.baseTypeMatch:
  2269. #assert(container == nil)
  2270. container = newNodeIT(nkBracket, n[a].info, arrayConstr(c, arg))
  2271. container.add arg
  2272. setSon(m.call, formal.position + 1, container)
  2273. if f != formalLen - 1: container = nil
  2274. else:
  2275. setSon(m.call, formal.position + 1, arg)
  2276. inc f
  2277. else:
  2278. # unnamed param
  2279. if f >= formalLen:
  2280. # too many arguments?
  2281. if tfVarargs in m.callee.flags:
  2282. # is ok... but don't increment any counters...
  2283. # we have no formal here to snoop at:
  2284. n[a] = prepareOperand(c, n[a])
  2285. if skipTypes(n[a].typ, abstractVar-{tyTypeDesc}).kind==tyString:
  2286. m.call.add implicitConv(nkHiddenStdConv,
  2287. getSysType(c.graph, n[a].info, tyCstring),
  2288. copyTree(n[a]), m, c)
  2289. else:
  2290. m.call.add copyTree(n[a])
  2291. elif formal != nil and formal.typ.kind == tyVarargs:
  2292. m.firstMismatch.kind = kTypeMismatch
  2293. # beware of the side-effects in 'prepareOperand'! So only do it for
  2294. # varargs matching. See tests/metatype/tstatic_overloading.
  2295. m.baseTypeMatch = false
  2296. m.typedescMatched = false
  2297. incl(marker, formal.position)
  2298. n[a] = prepareOperand(c, formal.typ, n[a])
  2299. arg = paramTypesMatch(m, formal.typ, n[a].typ,
  2300. n[a], nOrig[a])
  2301. if arg != nil and m.baseTypeMatch and container != nil:
  2302. container.add arg
  2303. incrIndexType(container.typ)
  2304. checkConstraint(n[a])
  2305. else:
  2306. noMatch()
  2307. else:
  2308. m.firstMismatch.kind = kExtraArg
  2309. noMatch()
  2310. else:
  2311. if m.callee.n[f].kind != nkSym:
  2312. internalError(c.config, n[a].info, "matches")
  2313. noMatch()
  2314. if flexibleOptionalParams in c.features and a >= firstArgBlock:
  2315. f = max(f, m.callee.n.len - (n.len - a))
  2316. formal = m.callee.n[f].sym
  2317. m.firstMismatch.kind = kTypeMismatch
  2318. if containsOrIncl(marker, formal.position) and container.isNil:
  2319. m.firstMismatch.kind = kPositionalAlreadyGiven
  2320. # positional param already in namedParams: (see above remark)
  2321. when false: localError(n[a].info, errCannotBindXTwice, formal.name.s)
  2322. noMatch()
  2323. if formal.typ.isVarargsUntyped:
  2324. if container.isNil:
  2325. container = newNodeIT(nkArgList, n[a].info, arrayConstr(c, n.info))
  2326. setSon(m.call, formal.position + 1, container)
  2327. else:
  2328. incrIndexType(container.typ)
  2329. container.add n[a]
  2330. else:
  2331. m.baseTypeMatch = false
  2332. m.typedescMatched = false
  2333. n[a] = prepareOperand(c, formal.typ, n[a])
  2334. arg = paramTypesMatch(m, formal.typ, n[a].typ,
  2335. n[a], nOrig[a])
  2336. if arg == nil:
  2337. noMatch()
  2338. if m.baseTypeMatch:
  2339. assert formal.typ.kind == tyVarargs
  2340. #assert(container == nil)
  2341. if container.isNil:
  2342. container = newNodeIT(nkBracket, n[a].info, arrayConstr(c, arg))
  2343. container.typ.flags.incl tfVarargs
  2344. else:
  2345. incrIndexType(container.typ)
  2346. container.add arg
  2347. setSon(m.call, formal.position + 1,
  2348. implicitConv(nkHiddenStdConv, formal.typ, container, m, c))
  2349. #if f != formalLen - 1: container = nil
  2350. # pick the formal from the end, so that 'x, y, varargs, z' works:
  2351. f = max(f, formalLen - n.len + a + 1)
  2352. elif formal.typ.kind != tyVarargs or container == nil:
  2353. setSon(m.call, formal.position + 1, arg)
  2354. inc f
  2355. container = nil
  2356. else:
  2357. # we end up here if the argument can be converted into the varargs
  2358. # formal (e.g. seq[T] -> varargs[T]) but we have already instantiated
  2359. # a container
  2360. #assert arg.kind == nkHiddenStdConv # for 'nim check'
  2361. # this assertion can be off
  2362. localError(c.config, n[a].info, "cannot convert $1 to $2" % [
  2363. typeToString(n[a].typ), typeToString(formal.typ) ])
  2364. noMatch()
  2365. checkConstraint(n[a])
  2366. if m.state == csMatch and not (m.calleeSym != nil and m.calleeSym.kind in {skTemplate, skMacro}):
  2367. c.mergeShadowScope
  2368. else:
  2369. c.closeShadowScope
  2370. inc a
  2371. # for some edge cases (see tdont_return_unowned_from_owned test case)
  2372. m.firstMismatch.arg = a
  2373. m.firstMismatch.formal = formal
  2374. proc semFinishOperands*(c: PContext, n: PNode) =
  2375. # this needs to be called to ensure that after overloading resolution every
  2376. # argument has been sem'checked:
  2377. for i in 1..<n.len:
  2378. n[i] = prepareOperand(c, n[i])
  2379. proc partialMatch*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
  2380. # for 'suggest' support:
  2381. var marker = initIntSet()
  2382. matchesAux(c, n, nOrig, m, marker)
  2383. proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
  2384. if m.magic in {mArrGet, mArrPut}:
  2385. m.state = csMatch
  2386. m.call = n
  2387. # Note the following doesn't work as it would produce ambiguities.
  2388. # Instead we patch system.nim, see bug #8049.
  2389. when false:
  2390. inc m.genericMatches
  2391. inc m.exactMatches
  2392. return
  2393. var marker = initIntSet()
  2394. matchesAux(c, n, nOrig, m, marker)
  2395. if m.state == csNoMatch: return
  2396. # check that every formal parameter got a value:
  2397. for f in 1..<m.callee.n.len:
  2398. let formal = m.callee.n[f].sym
  2399. if not containsOrIncl(marker, formal.position):
  2400. if formal.ast == nil:
  2401. if formal.typ.kind == tyVarargs:
  2402. # For consistency with what happens in `matchesAux` select the
  2403. # container node kind accordingly
  2404. let cnKind = if formal.typ.isVarargsUntyped: nkArgList else: nkBracket
  2405. var container = newNodeIT(cnKind, n.info, arrayConstr(c, n.info))
  2406. setSon(m.call, formal.position + 1,
  2407. implicitConv(nkHiddenStdConv, formal.typ, container, m, c))
  2408. else:
  2409. # no default value
  2410. m.state = csNoMatch
  2411. m.firstMismatch.kind = kMissingParam
  2412. m.firstMismatch.formal = formal
  2413. break
  2414. else:
  2415. if formal.ast.kind == nkEmpty:
  2416. # The default param value is set to empty in `instantiateProcType`
  2417. # when the type of the default expression doesn't match the type
  2418. # of the instantiated proc param:
  2419. localError(c.config, m.call.info,
  2420. ("The default parameter '$1' has incompatible type " &
  2421. "with the explicitly requested proc instantiation") %
  2422. formal.name.s)
  2423. if nfDefaultRefsParam in formal.ast.flags:
  2424. m.call.flags.incl nfDefaultRefsParam
  2425. var defaultValue = copyTree(formal.ast)
  2426. if defaultValue.kind == nkNilLit:
  2427. defaultValue = implicitConv(nkHiddenStdConv, formal.typ, defaultValue, m, c)
  2428. # proc foo(x: T = 0.0)
  2429. # foo()
  2430. if {tfImplicitTypeParam, tfGenericTypeParam} * formal.typ.flags != {}:
  2431. let existing = PType(idTableGet(m.bindings, formal.typ))
  2432. if existing == nil or existing.kind == tyTypeDesc:
  2433. # see bug #11600:
  2434. put(m, formal.typ, defaultValue.typ)
  2435. defaultValue.flags.incl nfDefaultParam
  2436. setSon(m.call, formal.position + 1, defaultValue)
  2437. # forget all inferred types if the overload matching failed
  2438. if m.state == csNoMatch:
  2439. for t in m.inferredTypes:
  2440. if t.len > 1: t.sons.setLen 1
  2441. proc argtypeMatches*(c: PContext, f, a: PType, fromHlo = false): bool =
  2442. var m = newCandidate(c, f)
  2443. let res = paramTypesMatch(m, f, a, c.graph.emptyNode, nil)
  2444. #instantiateGenericConverters(c, res, m)
  2445. # XXX this is used by patterns.nim too; I think it's better to not
  2446. # instantiate generic converters for that
  2447. if not fromHlo:
  2448. res != nil
  2449. else:
  2450. # pattern templates do not allow for conversions except from int literal
  2451. res != nil and m.convMatches == 0 and m.intConvMatches in [0, 256]
  2452. proc instTypeBoundOp*(c: PContext; dc: PSym; t: PType; info: TLineInfo;
  2453. op: TTypeAttachedOp; col: int): PSym {.nosinks.} =
  2454. var m = newCandidate(c, dc.typ)
  2455. if col >= dc.typ.len:
  2456. localError(c.config, info, "cannot instantiate: '" & dc.name.s & "'")
  2457. return nil
  2458. var f = dc.typ[col]
  2459. if op == attachedDeepCopy:
  2460. if f.kind in {tyRef, tyPtr}: f = f.lastSon
  2461. else:
  2462. if f.kind in {tyVar}: f = f.lastSon
  2463. if typeRel(m, f, t) == isNone:
  2464. localError(c.config, info, "cannot instantiate: '" & dc.name.s & "'")
  2465. else:
  2466. result = c.semGenerateInstance(c, dc, m.bindings, info)
  2467. if op == attachedDeepCopy:
  2468. assert sfFromGeneric in result.flags
  2469. include suggest
  2470. when not declared(tests):
  2471. template tests(s: untyped) = discard
  2472. tests:
  2473. var dummyOwner = newSym(skModule, getIdent("test_module"), nil, unknownLineInfo)
  2474. proc `|` (t1, t2: PType): PType =
  2475. result = newType(tyOr, dummyOwner)
  2476. result.rawAddSon(t1)
  2477. result.rawAddSon(t2)
  2478. proc `&` (t1, t2: PType): PType =
  2479. result = newType(tyAnd, dummyOwner)
  2480. result.rawAddSon(t1)
  2481. result.rawAddSon(t2)
  2482. proc `!` (t: PType): PType =
  2483. result = newType(tyNot, dummyOwner)
  2484. result.rawAddSon(t)
  2485. proc seq(t: PType): PType =
  2486. result = newType(tySequence, dummyOwner)
  2487. result.rawAddSon(t)
  2488. proc array(x: int, t: PType): PType =
  2489. result = newType(tyArray, dummyOwner)
  2490. var n = newNodeI(nkRange, unknownLineInfo)
  2491. n.add newIntNode(nkIntLit, 0)
  2492. n.add newIntNode(nkIntLit, x)
  2493. let range = newType(tyRange, dummyOwner)
  2494. result.rawAddSon(range)
  2495. result.rawAddSon(t)
  2496. suite "type classes":
  2497. let
  2498. int = newType(tyInt, dummyOwner)
  2499. float = newType(tyFloat, dummyOwner)
  2500. string = newType(tyString, dummyOwner)
  2501. ordinal = newType(tyOrdinal, dummyOwner)
  2502. any = newType(tyAnything, dummyOwner)
  2503. number = int | float
  2504. var TFoo = newType(tyObject, dummyOwner)
  2505. TFoo.sym = newSym(skType, getIdent"TFoo", dummyOwner, unknownLineInfo)
  2506. var T1 = newType(tyGenericParam, dummyOwner)
  2507. T1.sym = newSym(skType, getIdent"T1", dummyOwner, unknownLineInfo)
  2508. T1.sym.position = 0
  2509. var T2 = newType(tyGenericParam, dummyOwner)
  2510. T2.sym = newSym(skType, getIdent"T2", dummyOwner, unknownLineInfo)
  2511. T2.sym.position = 1
  2512. setup:
  2513. var c = newCandidate(nil, nil)
  2514. template yes(x, y) =
  2515. test astToStr(x) & " is " & astToStr(y):
  2516. check typeRel(c, y, x) == isGeneric
  2517. template no(x, y) =
  2518. test astToStr(x) & " is not " & astToStr(y):
  2519. check typeRel(c, y, x) == isNone
  2520. yes seq(any), array(10, int) | seq(any)
  2521. # Sure, seq[any] is directly included
  2522. yes seq(int), seq(any)
  2523. yes seq(int), seq(number)
  2524. # Sure, the int sequence is certainly
  2525. # part of the number sequences (and all sequences)
  2526. no seq(any), seq(float)
  2527. # Nope, seq[any] includes types that are not seq[float] (e.g. seq[int])
  2528. yes seq(int|string), seq(any)
  2529. # Sure
  2530. yes seq(int&string), seq(any)
  2531. # Again
  2532. yes seq(int&string), seq(int)
  2533. # A bit more complicated
  2534. # seq[int&string] is not a real type, but it's analogous to
  2535. # seq[Sortable and Iterable], which is certainly a subset of seq[Sortable]
  2536. no seq(int|string), seq(int|float)
  2537. # Nope, seq[string] is not included in not included in
  2538. # the seq[int|float] set
  2539. no seq(!(int|string)), seq(string)
  2540. # A sequence that is neither seq[int] or seq[string]
  2541. # is obviously not seq[string]
  2542. no seq(!int), seq(number)
  2543. # Now your head should start to hurt a bit
  2544. # A sequence that is not seq[int] is not necessarily a number sequence
  2545. # it could well be seq[string] for example
  2546. yes seq(!(int|string)), seq(!string)
  2547. # all sequnece types besides seq[int] and seq[string]
  2548. # are subset of all sequence types that are not seq[string]
  2549. no seq(!(int|string)), seq(!(string|TFoo))
  2550. # Nope, seq[TFoo] is included in the first set, but not in the second
  2551. no seq(!string), seq(!number)
  2552. # Nope, seq[int] in included in the first set, but not in the second
  2553. yes seq(!number), seq(any)
  2554. yes seq(!int), seq(any)
  2555. no seq(any), seq(!any)
  2556. no seq(!int), seq(!any)
  2557. yes int, ordinal
  2558. no string, ordinal