Skip to content
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

erasedValue[V] does not work with function return type 'V' #19294

Closed
erikerlandson opened this issue Dec 18, 2023 · 6 comments
Closed

erasedValue[V] does not work with function return type 'V' #19294

erikerlandson opened this issue Dec 18, 2023 · 6 comments

Comments

@erikerlandson
Copy link

Compiler version

3.3.1

Minimized code

object repro:
    // no return type works
    inline def works[V] =
        inline compiletime.erasedValue[V] match
            case _: Int => 1
            case _ => compiletime.error("nope")

    // adding return type 'V' is compile error
    inline def fails[V]: V =
        inline compiletime.erasedValue[V] match
            case _: Int => 1
            case _ => compiletime.error("nope")

Output

The function fails[V]: V gives a compile error:

[error] -- [E007] Type Mismatch Error: ... 
[error] 150 |            case _: Int => 1
[error]     |                           ^
[error]     |                           Found:    (1 : Int)
[error]     |                           Required: V

Expectation

I was hoping to be able to specify return type (in this case V) as long as it is consistent with the inline-generated code. Note, I did also try using transparent inline def ... but that does not work either.

Just leaving the return type off is a possibility, but seems like an anti-pattern, and at least using transparent inline seems like it could properly check all the types at compile time.

@erikerlandson erikerlandson added itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label labels Dec 18, 2023
@sjrd
Copy link
Member

sjrd commented Dec 18, 2023

If V = 0, erasedValue[V] matches case _: Int but 1 is not a valid value of V. The compiler is right not to let you do that.

@sjrd sjrd closed this as not planned Won't fix, can't repro, duplicate, stale Dec 18, 2023
@sjrd sjrd added itype:invalid and removed itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label labels Dec 18, 2023
@erikerlandson
Copy link
Author

Using asInstanceOf is a workaround:

    // asInstanceOf is a workaround
    inline def workaround[V]: V =
        inline compiletime.erasedValue[V] match
            case _: Int => 1.asInstanceOf[V]
            case _ => compiletime.error("nope")

@erikerlandson
Copy link
Author

asInstanceOf doesn't seem to add any overhead:

Compiled from "quantity.scala"
public final class coulomb.repro$ implements java.io.Serializable {
  public static final coulomb.repro$ MODULE$;

  public static {};
    Code:
       0: new           #2                  // class coulomb/repro$
       3: dup
       4: invokespecial #19                 // Method "<init>":()V
       7: putstatic     #21                 // Field MODULE$:Lcoulomb/repro$;
      10: iconst_1
      11: putstatic     #23                 // Field t1:I
      14: iconst_1
      15: putstatic     #25                 // Field t2:I
      18: return

  public int t1();
    Code:
       0: getstatic     #23                 // Field t1:I
       3: ireturn

  public int t2();
    Code:
       0: getstatic     #25                 // Field t2:I
       3: ireturn
}

@erikerlandson
Copy link
Author

It would be nice to be able to match on Int but specifically not literal types. There is a way to say "Int & Singleton" but not "Int that is not Singleton"

@sjrd
Copy link
Member

sjrd commented Dec 18, 2023

It's not possible because it makes no sense. Types can be substituted for better types (i.e., subtypes) through inlining. If we allowed that kind of constraint, something that is valid before inlining might become invalid after inlining.

@erikerlandson
Copy link
Author

A note about why the .isInstanceOf workaround works: by default scala widens singleton type parameters to their generic types (e.g. it widens a singleton type 0 to Int). To bind the singleton type you need to quality as V <: Singleton:
https://dotty.epfl.ch/api/scala/Singleton.html#

So in my repro example, the return type V is in fact Int even if one gives it 0 as the type parameter, and .asInstanceOf[V] will not fail.

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