# # # The Nim Compiler # (c) Copyright 2020 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. # proc checkForSink*(config: ConfigRef; idgen: IdGenerator; owner: PSym; arg: PNode) = #[ Patterns we seek to detect: someLocation = p # ---> p: sink T passToSink(p) # p: sink ObjConstr(fieldName: p) [p, q] # array construction # Open question: var local = p # sink parameter? passToSink(local) ]# if optSinkInference notin config.options: return case arg.kind of nkSym: if arg.sym.kind == skParam and arg.sym.owner == owner and owner.typ != nil and owner.typ.kind == tyProc and arg.sym.typ.hasDestructor and arg.sym.typ.kind notin {tyVar, tySink, tyOwned}: # Watch out: cannot do this inference for procs with forward # declarations. if sfWasForwarded notin owner.flags: let argType = arg.sym.typ let sinkType = newType(tySink, nextTypeId(idgen), owner) sinkType.size = argType.size sinkType.align = argType.align sinkType.paddingAtEnd = argType.paddingAtEnd sinkType.add argType arg.sym.typ = sinkType owner.typ[arg.sym.position+1] = sinkType #message(config, arg.info, warnUser, # ("turned '$1' to a sink parameter") % [$arg]) #echo config $ arg.info, " turned into a sink parameter ", arg.sym.name.s elif sfWasForwarded notin arg.sym.flags: # we only report every potential 'sink' parameter only once: incl arg.sym.flags, sfWasForwarded message(config, arg.info, hintPerformance, "could not turn '$1' to a sink parameter" % [arg.sym.name.s]) #echo config $ arg.info, " candidate for a sink parameter here" of nkStmtList, nkStmtListExpr, nkBlockStmt, nkBlockExpr: if not isEmptyType(arg.typ): checkForSink(config, idgen, owner, arg.lastSon) of nkIfStmt, nkIfExpr, nkWhen: for branch in arg: let value = branch.lastSon if not isEmptyType(value.typ): checkForSink(config, idgen, owner, value) of nkCaseStmt: for i in 1..