nim-lang / RFCs

A repository for your Nim proposals.
136 stars 26 forks source link

result assignment should stay optional, except for var/lent result #241

Closed timotheecour closed 4 years ago

timotheecour commented 4 years ago

goal: discuss this topic here and not in unrelated issues like https://github.com/nim-lang/Nim/pull/14777#issuecomment-649000045

Assignments like ' result = "" ' will become mandatory, we really want definite assignment analysis like C#, so don't remove them.

proposal

example

when true:
  var g0=0
  proc main(): var int =
    echo result # bug: should give CT error
    result.inc # bug: should give CT error
    result = 1 # ok, gives CT error
    result = g0 # ok
  main().inc

  proc main2(): (var int, int) =
    # currently not supported at all see https://github.com/nim-lang/Nim/issues/13975
    echo result[1] # should be ok
    echo result[0] # should be CT error
    result[0] = g0 # should be ok

rationale for P2,P3,P4

should not be controversial, it's just correctness (otherwise you get SIGSEGV at runtime); ditto with lent result

rationale for P1

The analysis is simple, and behaves as if result = default(typeof(result)) was the first statement.

links

arnetheduck commented 4 years ago

...or simply deprecate and eventually remove result and let users type var result = ...; return result which is explicit and doesn't introduce an implicit variable and a third return style that has few good use cases but costs confusion, compiler maintenance + extra compiler logic to make sure that usage of result is somewhat sane, macro difficulties etc.

andreaferretti commented 4 years ago

The only advantage I see in result return value optimization. It seems to me (but I don't know the internals of the compiler) that if all code paths only assign to result.somefield, it should be easy to optimize this and just create result on the previous stack frame, thereby avoiding a copy when returning.

It may be the case that this is difficult to do in general, or that it is easy to do with other ways of returning. But the picture I have in my mind is that result is a preallocated slot which lives before the current stack frame.

If result does not help with RVO, I agree with @arnetheduck that its complexities dwarf its advantages.

Araq commented 4 years ago

Definite assignment analysis (DAA) has little to do with result! And the motivation for it is like this:


var x: int # please check for me every branch assigns a value to 'x'
case selector
of caseA:
  if cond:
    x  = 3
  else:
    # more complex logic here
    # oops I forgot to assign to 'x' 
of caseB:
  x = 4
of caseC:
  x = 8

Nim's case statement checks for exhaustiveness, DAA is a nice extension.

See https://docs.oracle.com/javase/specs/jls/se6/html/defAssign.html for the rules we could simply take over from Java. It works.

Before Nim got default(T) certain patterns were hard to express without Nim's current implicit initialization but now that we have default(T) we could make the next steps, if your code depends on result = default(T) as the first statement of your proc, so write that down explicitly.

Araq commented 4 years ago

Closing because it misrepresents my proposal which is https://github.com/nim-lang/RFCs/issues/49