Re: Allow top-level "implicit class"es by folding them into containing package-object

Jason Zaugg <[email protected]> Wed, 07 Dec 2016 10:31:42 +0000
Newsgroups gmane.comp.lang.scala
Message-ID <CAG3_yeUwRuX4wjKa9_bpx38UcCjRmyW0XbT_=9nShAY8MgnKzA@mail.gmail.com>
--001a114049a689994805430f0769
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

On Wed, 7 Dec 2016 at 18:51 martin odersky <[email protected]> wrote:

> On Wed, Dec 7, 2016 at 5:28 AM, Jason Zaugg <[email protected]> wrote:
>
> Unfortunately we have a number of assumptions in our toolchain (mostly
> driven by the requirement of separate+incremental compilation), that each
> class file comes from a single source file. Package objects are modelled =
as
> an object with the name package, so like any other object they must be
> defined within a single source file (by convention, named package.scala.)
>
>
> I believe instead that we should allow top level implicit classes and
> treat it as though it introduced companion object of type Function1[Wrapp=
ed,
> Wrapper]. The companion itself would be seen as an implicit. The call to
> Wrapper.apply(wrapped) couId be translated to new Wrapper(wrapped) in
> order to make later optimizations for implicit classes work as expected. =
We
> already do this for calls to the companion apply methods of case classes.
>
>
> But there's another problem: How do you figure out that a top-level class
> is implicit? The compiler has only the name of the file as an entry in th=
e
> enclosing package scope. It would have to look inside the file to find ou=
t
> whether it contained an implicit class. That would break all our
> assumptions about separate compilation.
>

Good point. To fit in with that constraint, we'd need some scheme to encode
the implicit modifier into the name of a some class. For instance, we could
do something like:

implicit class RichString(val s: String) {
   /*synthetic*/ class Implicit$ // added by the compiler
}

=E2=80=8B
There is precedent for adding synthetic inner classes (e.g javac does to
add to the signatures of "access constructors":
https://gist.github.com/retronym/8ca8026f5b7eb981b53f5c8923d50f54)

-jason

--=20
You received this message because you are subscribed to the Google Groups "=
scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to [email protected].
For more options, visit https://groups.google.com/d/optout.

--001a114049a689994805430f0769
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><br><div class=3D"gmail_quote"><div dir=3D"ltr">On Wed=
, 7 Dec 2016 at 18:51 martin odersky &lt;<a href=3D"mailto:[email protected]=
m">[email protected]</a>&gt; wrote:<br></div><blockquote class=3D"gmail_quo=
te" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"=
><div dir=3D"ltr" class=3D"gmail_msg"><div class=3D"gmail_extra gmail_msg">=
<div class=3D"gmail_quote gmail_msg">On Wed, Dec 7, 2016 at 5:28 AM, Jason =
Zaugg <span dir=3D"ltr" class=3D"gmail_msg">&lt;<a href=3D"mailto:jzaugg@gm=
ail.com" class=3D"gmail_msg" target=3D"_blank">[email protected]</a>&gt;</sp=
an> wrote:<br class=3D"gmail_msg"><blockquote class=3D"gmail_quote gmail_ms=
g" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">=
<div dir=3D"ltr" class=3D"gmail_msg"><p style=3D"font-size:small;margin:1.2=
em 0px" class=3D"gmail_msg"></p><div class=3D"m_-4429256695741974100m_-1002=
852262469377768markdown-here-wrapper gmail_msg"><p style=3D"margin:1.2em 0p=
x!important" class=3D"gmail_msg">Unfortunately we have a number of assumpti=
ons in our toolchain (mostly driven by the requirement of separate+incremen=
tal compilation), that each class file comes from a single source file. Pac=
kage objects are modelled as an object with the name package, so like any o=
ther object they must be defined within a single source file (by convention=
, named <code style=3D"font-size:0.85em;font-family:Consolas,Inconsolata,Co=
urier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;bo=
rder:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-ra=
dius:3px;display:inline" class=3D"gmail_msg">package.scala</code>.)</p><p s=
tyle=3D"margin:1.2em 0px!important" class=3D"gmail_msg"><br class=3D"gmail_=
msg">I believe instead that we should allow top level implicit classes and =
treat it as though it introduced companion object of type <code style=3D"fo=
nt-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0p=
x 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,23=
4,234);background-color:rgb(248,248,248);border-radius:3px;display:inline" =
class=3D"gmail_msg">Function1[Wrapped, Wrapper]</code>. The companion itsel=
f would be seen as an implicit. The call to <code style=3D"font-size:0.85em=
;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;paddi=
ng:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);backgro=
und-color:rgb(248,248,248);border-radius:3px;display:inline" class=3D"gmail=
_msg">Wrapper.apply(wrapped)</code> couId be translated to <code style=3D"f=
ont-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0=
px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,2=
34,234);background-color:rgb(248,248,248);border-radius:3px;display:inline"=
 class=3D"gmail_msg">new Wrapper(wrapped)</code> in order to make later opt=
imizations for implicit classes work as expected. We already do this for ca=
lls to the companion apply methods of case classes.</p></div></div></blockq=
uote><div class=3D"gmail_msg"><br class=3D"gmail_msg"></div></div></div></d=
iv><div dir=3D"ltr" class=3D"gmail_msg"><div class=3D"gmail_extra gmail_msg=
"><div class=3D"gmail_quote gmail_msg"><div class=3D"gmail_msg">But there&#=
39;s another problem: How do you figure out that a top-level class is impli=
cit? The compiler has only the name of the file as an entry in the enclosin=
g package scope. It would have to look inside the file to find out whether =
it contained an implicit class. That would break all our assumptions about =
separate compilation.</div></div></div></div></blockquote><div><br></div><d=
iv>Good point. To fit in with that constraint, we&#39;d need some scheme to=
 encode the implicit modifier into the name of a some class. For instance, =
we could do something like:<br></div><div class=3D"markdown-here-wrapper" s=
tyle=3D""><pre style=3D"font-size:0.85em;font-family:Consolas,Inconsolata,C=
ourier,monospace;font-size:1em;line-height:1.2em;margin:1.2em 0px"><code st=
yle=3D"font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;=
margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid r=
gb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display=
:inline;white-space:pre;overflow:auto;border-radius:3px;border:1px solid rg=
b(204,204,204);padding:0.5em 0.7em;display:block!important">implicit class =
RichString(val s: String) {
   /*synthetic*/ class Implicit$ // added by the compiler
}
</code></pre><div title=3D"MDH:PGRpdj5gYGA8YnI+aW1wbGljaXQgY2xhc3MgUmljaFN0=
cmluZyh2YWwgczogU3RyaW5nKSB7PGJy
PiZuYnNwOyAmbmJzcDsvKnN5bnRoZXRpYyovIGNsYXNzIEltcGxpY2l0JCAvLyBhZGRlZCBieSB=
0
aGUgY29tcGlsZXI8L2Rpdj48ZGl2Pn08L2Rpdj48ZGl2PmBgYDwvZGl2Pg=3D=3D" style=3D"=
height:0;width:0;max-height:0;max-width:0;overflow:hidden;font-size:0em;pad=
ding:0;margin:0">=E2=80=8B</div></div><div></div><div>There is precedent fo=
r adding synthetic inner classes (e.g javac does to add to the signatures o=
f &quot;access constructors&quot;:=C2=A0<a href=3D"https://gist.github.com/=
retronym/8ca8026f5b7eb981b53f5c8923d50f54">https://gist.github.com/retronym=
/8ca8026f5b7eb981b53f5c8923d50f54</a>)</div><div><br></div><div>-jason</div=
></div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;scala-language&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:[email protected]">scal=
[email protected]</a>.<br />
For more options, visit <a href=3D"https://groups.google.com/d/optout">http=
s://groups.google.com/d/optout</a>.<br />

--001a114049a689994805430f0769--