Proposed Changes and Restrictions For Implicit Conversions

It can be generally allowed for exports but not for imports. It’s a question of evaluation order. Say you have

import f(x).a
...
a + a

when is f(x) evaluated? I believe it would have to be evaluated at the point where the import appears, so the code would rewrite to

val $temp = f(x)
...
$temp.a + $temp.a

The alternative semantics would rewrite at the point of access, i.e.:

...
f(x).a + f(x).a

That would not only surprising and potentially costly. It would not work at all if we import a type since type prefixes may not be expressions. On the other hand, evaluating at the point of import does not work either since we get into a mess for toplevel imports outside a class. So, it was a wise decision to restrict import prefixes to stable identifiers and we should keep it.

For exports, we have the same question.

export f(x).{a, b}

must mean

private val $temp = f(x)
def a = $temp.a
def b = $temp.b

since otherwise we could not export types. This time we do not have a problem with that interpretation, since vals are allowed wherever exports are allowed. Note that for extension methods
the two evaluation strategies lead to the same result.

extension (x: T)
  export f(x).a

rewrites to either

def a(x: T) = val $temp = f(x); $temp.a

or

def a(x: T) = f(x).a

but those two are equivalent.

Are there any downsides to it, that I’m not seeing right now, that led to the original design where the exported members had to be stable identifiere?

Just that we modeled exports after imports, and this would introduce a deviation between the two.

4 Likes