Actually, this discussion makes me realize I’m not clear on what export
does when a class(-like) thing is exported. Condensed from @Swoorup example:
object Prelude:
export cats.effect.{IO, IOApp}
IO
is an abstract class and associated companion object. IOApp
refers to a trait and companion. What do these two exports do?
The Scala 3 export docs lead with “An export clause defines aliases for selected members of an object.” But I doubt that can literally apply here… since IO
/IOApp
aren’t “members” (in the usual sense of val
/def
/var
), nor is cats.effect
an object, but rather a package.
In preceeding posts, both @rssh and I have mentioned the generation of “forwarders” (synthetic methods that forward on references to the exported member). But I’m unclear, when eg IO
is exported, what forwarders are created?
This is most relevant because @rssh’s proposed extension to export
allowed it to declare “non-proxy exports” (ie exports without forwarders).
As he put it, to add “placement of exported definitions to the search path of enclosing scope”. I take this to mean: such an export affects the set of imports the compiler searches at the code site where the export is visible, as if an import was declared there.
I think Ruslan started from the position that, as a change to the specified behavior of export, this would require a distinguishing keyword, eg transparent
. The only other option would seem to be to realign or clarify the behavior of export when it refers to the contents of packages, that forwarders are not generated but rather the search path is expanded. I do think such an export
keyword would be doing “double duty” and this might be ambiguous.
Also, there are phase differences surely? Import search paths are a compile-time concept, while generated forwarders exist at runtime. Thus, @bjornregnell, I do think different keywords are required to delineate two different meanings of export
.