Skip to content

Cannot export extension methods from a generic type #16002

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
deusaquilus opened this issue Sep 8, 2022 · 2 comments
Closed

Cannot export extension methods from a generic type #16002

deusaquilus opened this issue Sep 8, 2022 · 2 comments

Comments

@deusaquilus
Copy link
Contributor

deusaquilus commented Sep 8, 2022

Compiler version

3.2.0

Minimized code

I'm not sure if this is a bug, a feature, or something else but it is impossible to export methods from a generic type. The important of this kind of feature is that if it existed, it would be (probably) be possible to replace Quill's implicit conversion Quoted[T] => T with implicit exports (so long as the exported method themselves are inline).

  class Wrapped[T](t: T) {
    def unwrap:T = ???
  }

  extension [T](t: Wrapped[T])
    def unwrapped: T = t.unwrap
    export unwrapped.*

Wrapped("blah").toUpperCase()

Output

[error] 27 |      PrintMac(Wrapped("blah").toUpperCase())
[error]    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^
[error]    |value toUpperCase is not a member of org.deusaquilus.ImplicitConf.Wrapped[String], but could be made available as an extension method.

Expectation

It should recognize that .toUpperCase() exists on Wrapped[String] because it exists on String.

The functionality should be equivalent to this (which works):

  extension (t: Wrapped[String])
    def unwrapped: String = t.unwrap
    export unwrapped.*

  Wrapped("blah").toUpperCase()

Of if inline is used,

  extension (inline t: Wrapped[String])
    inline def unwrapped: String = t.unwrap
    export unwrapped.*

Wrapped("blah").toUpperCase()
// Which in the AST should be encoded as:
Wrapped("blah").unwrap.toUpperCase()

it should be equivalent to this:

extension (inline t: Wrapped[String])
    inline def unwrapped: String = t.unwrap
    inline def toUpperCase(): String = unwrapped.toUpperCase()

Wrapped("blah").toUpperCase()

Quill's unquotation Quoted[T] => T function specifically relies on this kind of pattern (i.e. the input t has to be directly spliced).

@deusaquilus deusaquilus added itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label labels Sep 8, 2022
@odersky
Copy link
Contributor

odersky commented Sep 9, 2022

That will indeed not work. The exported members are chosen where the extension is defined. I don't see another possibility.

@odersky odersky added itype:language enhancement stat:wontfix and removed itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label labels Sep 9, 2022
@odersky odersky closed this as completed Sep 9, 2022
@deusaquilus
Copy link
Contributor Author

deusaquilus commented Sep 9, 2022

@odersky I’m totally stuck then. Is there any other way I could potentially do automatic conversion of Quoted[T] => T without implicit conversion or in some way that is planned for long term support? Everything that is currently proposed wouldn’t work.

I need to somehow be able to implicitly convert Quoted[T] to T inside of Quill quote { … } blocks or the Quill API wouldn’t work.

My original thoughts were here.
https://contributors.scala-lang.org/t/proposed-changes-and-restrictions-for-implicit-conversions/4923/167?u=deusaquilus

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants