sinkparameter_inference.nim 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  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. if optSinkInference notin config.options: return
  20. case arg.kind
  21. of nkSym:
  22. if arg.sym.kind == skParam and
  23. arg.sym.owner == owner and
  24. owner.typ != nil and owner.typ.kind == tyProc and
  25. arg.sym.typ.hasDestructor and
  26. arg.sym.typ.kind notin {tyVar, tySink, tyOwned}:
  27. # Watch out: cannot do this inference for procs with forward
  28. # declarations.
  29. if sfWasForwarded notin owner.flags:
  30. let argType = arg.sym.typ
  31. let sinkType = newType(tySink, nextTypeId(idgen), owner)
  32. sinkType.size = argType.size
  33. sinkType.align = argType.align
  34. sinkType.paddingAtEnd = argType.paddingAtEnd
  35. sinkType.add argType
  36. arg.sym.typ = sinkType
  37. owner.typ[arg.sym.position+1] = sinkType
  38. #message(config, arg.info, warnUser,
  39. # ("turned '$1' to a sink parameter") % [$arg])
  40. #echo config $ arg.info, " turned into a sink parameter ", arg.sym.name.s
  41. elif sfWasForwarded notin arg.sym.flags:
  42. # we only report every potential 'sink' parameter only once:
  43. incl arg.sym.flags, sfWasForwarded
  44. message(config, arg.info, hintPerformance,
  45. "could not turn '$1' to a sink parameter" % [arg.sym.name.s])
  46. #echo config $ arg.info, " candidate for a sink parameter here"
  47. of nkStmtList, nkStmtListExpr, nkBlockStmt, nkBlockExpr:
  48. if not isEmptyType(arg.typ):
  49. checkForSink(config, idgen, owner, arg.lastSon)
  50. of nkIfStmt, nkIfExpr, nkWhen:
  51. for branch in arg:
  52. let value = branch.lastSon
  53. if not isEmptyType(value.typ):
  54. checkForSink(config, idgen, owner, value)
  55. of nkCaseStmt:
  56. for i in 1..<arg.len:
  57. let value = arg[i].lastSon
  58. if not isEmptyType(value.typ):
  59. checkForSink(config, idgen, owner, value)
  60. of nkTryStmt:
  61. checkForSink(config, idgen, owner, arg[0])
  62. else:
  63. discard "nothing to do"