sinkparameter_inference.nim 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. #
  2. #
  3. # The Nim Compiler
  4. # (c) Copyright 2020 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. proc checkForSink*(config: ConfigRef; idgen: IdGenerator; owner: PSym; arg: PNode) =
  10. #[ Patterns we seek to detect:
  11. someLocation = p # ---> p: sink T
  12. passToSink(p) # p: sink
  13. ObjConstr(fieldName: p)
  14. [p, q] # array construction
  15. # Open question:
  16. var local = p # sink parameter?
  17. passToSink(local)
  18. ]#
  19. case arg.kind
  20. of nkSym:
  21. if arg.sym.kind == skParam and
  22. arg.sym.owner == owner and
  23. owner.typ != nil and owner.typ.kind == tyProc and
  24. arg.sym.typ.hasDestructor and
  25. arg.sym.typ.kind notin {tyVar, tySink, tyOwned}:
  26. # Watch out: cannot do this inference for procs with forward
  27. # declarations.
  28. if sfWasForwarded notin owner.flags:
  29. let argType = arg.sym.typ
  30. let sinkType = newType(tySink, nextTypeId(idgen), owner)
  31. sinkType.size = argType.size
  32. sinkType.align = argType.align
  33. sinkType.paddingAtEnd = argType.paddingAtEnd
  34. sinkType.add argType
  35. arg.sym.typ = sinkType
  36. owner.typ[arg.sym.position+1] = sinkType
  37. #message(config, arg.info, warnUser,
  38. # ("turned '$1' to a sink parameter") % [$arg])
  39. #echo config $ arg.info, " turned into a sink parameter ", arg.sym.name.s
  40. elif sfWasForwarded notin arg.sym.flags:
  41. # we only report every potential 'sink' parameter only once:
  42. incl arg.sym.flags, sfWasForwarded
  43. message(config, arg.info, hintPerformance,
  44. "could not turn '$1' to a sink parameter" % [arg.sym.name.s])
  45. #echo config $ arg.info, " candidate for a sink parameter here"
  46. of nkStmtList, nkStmtListExpr, nkBlockStmt, nkBlockExpr:
  47. if not isEmptyType(arg.typ):
  48. checkForSink(config, idgen, owner, arg.lastSon)
  49. of nkIfStmt, nkIfExpr, nkWhen:
  50. for branch in arg:
  51. let value = branch.lastSon
  52. if not isEmptyType(value.typ):
  53. checkForSink(config, idgen, owner, value)
  54. of nkCaseStmt:
  55. for i in 1..<arg.len:
  56. let value = arg[i].lastSon
  57. if not isEmptyType(value.typ):
  58. checkForSink(config, idgen, owner, value)
  59. of nkTryStmt:
  60. checkForSink(config, idgen, owner, arg[0])
  61. else:
  62. discard "nothing to do"