Skip to content

f-interpolator parity #9939

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
som-snytt opened this issue Oct 2, 2020 · 9 comments · Fixed by #13367
Closed

f-interpolator parity #9939

som-snytt opened this issue Oct 2, 2020 · 9 comments · Fixed by #13367

Comments

@som-snytt
Copy link
Contributor

Minimized code

scala> f"${3.14}%.2f rounds to ${3}%d"
1 |f"${3.14}%.2f rounds to ${3}%d"
  |                          ^
  |                          type mismatch;
  |                           found   : Double
  |                           required: Int
  | This location contains code that was inlined from rs$line$2:1

scala> f"${java.lang.Boolean.valueOf(false)}%b"   // any boxed value
1 |f"${java.lang.Boolean.valueOf(false)}%b"
  |    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |    type mismatch;
  |     found   : Boolean
  |     required: Boolean
  | This location contains code that was inlined from rs$line$17:1

scala> f"${BigInt(120)}%d"
1 |f"${BigInt(120)}%d"
  |    ^^^^^^^^^^^
  |    type mismatch;
  |     found   : math.BigInt
  |     required: Int
  | This location contains code that was inlined from rs$line$27:1

scala> f"${BigDecimal(3.4)}%e"
1 |f"${BigDecimal(3.4)}%e"
  |    ^^^^^^^^^^^^^^^
  |    type mismatch;
  |     found   : math.BigDecimal
  |     required: Double
  | This location contains code that was inlined from rs$line$30:1

scala> f"${3L}%e"
1 |f"${3L}%e"
  |    ^^
  |    type mismatch;
  |     found   : Long
  |     required: Double
  | This location contains code that was inlined from rs$line$31:1

Output

// as shown

Expectation

scala 2.13.3> f"${3.14}%.2f rounds to ${3}%d"
val res0: String = 3.14 rounds to 3

scala 2.13.3> f"${java.lang.Boolean.valueOf(false)}%b"
val res0: String = false

scala 2.13.3> f"${BigInt(120)}%d"
val res5: String = 120

scala 2.13.3> f"${BigDecimal(3.4)}%e"
val res8: String = 3.400000e+00

scala 2.13.3> f"${3L}%e"
val res11: String = 3.000000e+00
@som-snytt
Copy link
Contributor Author

scala> f"${0}%n"
val res1: String = "
"

@som-snytt
Copy link
Contributor Author

scala> f"${0}%d"
val res9: String = 0

scala> f"${0}%%d"
val res10: String = %d

scala> f"${0}%%%d"
val res11: String = %0

scala> f"${0}%%%%d"
val res12: String = %%d

scala> f"${0}%%%%%d"
val res13: String = %%0

expected

scala 2.13.3> f"${0}%d"
val res21: String = 0

scala 2.13.3> f"${0}%%d"
val res22: String = 0%d

scala 2.13.3> f"${0}%%%d"
                      ^
              error: conversions must follow a splice; use %% for literal %, %n for newline

scala 2.13.3> f"${0}%%%%d"
val res24: String = 0%%d

scala 2.13.3> f"${0}%%%%%d"
                        ^
              error: conversions must follow a splice; use %% for literal %, %n for newline

@nicolasstucki
Copy link
Contributor

I guess we should just port the implementation from Scala 2. We can port it in StringContextChecker.

@nicolasstucki nicolasstucki removed their assignment Oct 5, 2020
@som-snytt
Copy link
Contributor Author

I took a few minutes to try these examples from the scala 2 tests, and a minute more to look at fixing. I'll try to make time, modulo day job and pandemic sleep schedule. It's not obvious that keeping the old code is desirable. Also, it's tiresome to hear "String.format is slow." It would be nice to have ff or "fast format" interpolator that compiled to pretty printers. The challenge is to support all the format features.

@b-studios
Copy link
Contributor

Thanks @som-snytt for looking into it, I assigned you to the issue.

@som-snytt
Copy link
Contributor Author

som-snytt commented Jan 30, 2021

Compare

Starting scala3 REPL...
scala> f"%"
1 |f"%"
  |  ^
  |  Missing conversion operator in '%'; use %% for literal %, %n for newline

scala> val x: Int = 5                                                           
     | val y: Int = 2
val x: Int = 5
val y: Int = 2

scala> f"x % y = ${x % y}%d"
java.util.UnknownFormatConversionException: Conversion = 'y'
  at java.base/java.util.Formatter$FormatSpecifier.conversion(Formatter.java:2839)
  at java.base/java.util.Formatter$FormatSpecifier.<init>(Formatter.java:2865)
  at java.base/java.util.Formatter.parse(Formatter.java:2713)
  at java.base/java.util.Formatter.format(Formatter.java:2655)
  at java.base/java.util.Formatter.format(Formatter.java:2609)
  at java.base/java.lang.String.format(String.java:3292)
  at scala.collection.StringOps$.format$extension(StringOps.scala:968)
  ... 27 elided

scala> f"%y"
1 |f"%y"
  |   ^^
  |   illegal conversion character 'y'

@som-snytt
Copy link
Contributor Author

Cf #10315

@som-snytt
Copy link
Contributor Author

som-snytt commented Jul 22, 2021

Classic example from Scanners:

error(f"illegal character '\\u$ch%04x'")

Doesn't do escaped slash, doesn't take char as int.

Edit: actually, doesn't do any escape processing. f"a\tb" You'd think somebody would notice that.

dos65 added a commit to dos65/dotty that referenced this issue Aug 22, 2021
Fixes the following sample from scala#9939:
```scala
scala> f"${3.14}%.2f rounds to ${3}%d"
1 |f"${3.14}%.2f rounds to ${3}%d"
  |                          ^
  |                          type mismatch;
  |                           found   : Double
  |                           required: Int
  | This location contains code that was inlined from rs$line$2:1
```

At the moment when StringInterpolation transfomation was perfomed instead
of receiving `List(Constant(3.0), Constant(3))` arguments they
were: `List(Constant(3.0), Constant(3.0))` (the second one was converted to double because of harmonization).
That caused the reported type mismatch.

In Scala2 harmonization doesn't happen if the resulting type is fully defined.
For f-interp it shouldn't happen too as it's resulting type is a `String`:
```scala
  def f[A >: Any](args: A*): String = macro ???
```
dos65 added a commit to dos65/dotty that referenced this issue Aug 22, 2021
Fixes the following sample from scala#9939:
```scala
scala> f"${3.14}%.2f rounds to ${3}%d"
1 |f"${3.14}%.2f rounds to ${3}%d"
  |                          ^
  |                          type mismatch;
  |                           found   : Double
  |                           required: Int
  | This location contains code that was inlined from rs$line$2:1
```

At the moment when StringInterpolation transformation was performed instead
of receiving `List(Constant(3.0), Constant(3))` arguments they
were: `List(Constant(3.0), Constant(3.0))` (the second one was converted to double because of harmonization).
That caused the reported type mismatch.

In Scala2 harmonization doesn't happen if the resulting type is fully defined.
For f-interp it shouldn't happen too as it's resulting type is a `String`:
```scala
  def f[A >: Any](args: A*): String = macro ???
```
@som-snytt
Copy link
Contributor Author

Noting the efficacy of [A >: Any] at the old ticket scala/bug#8512

@anatoliykmetyuk anatoliykmetyuk added this to the 3.2.0 milestone Oct 4, 2021
olsdavis pushed a commit to olsdavis/dotty that referenced this issue Apr 4, 2022
Fixes the following sample from scala#9939:
```scala
scala> f"${3.14}%.2f rounds to ${3}%d"
1 |f"${3.14}%.2f rounds to ${3}%d"
  |                          ^
  |                          type mismatch;
  |                           found   : Double
  |                           required: Int
  | This location contains code that was inlined from rs$line$2:1
```

At the moment when StringInterpolation transformation was performed instead
of receiving `List(Constant(3.0), Constant(3))` arguments they
were: `List(Constant(3.0), Constant(3.0))` (the second one was converted to double because of harmonization).
That caused the reported type mismatch.

In Scala2 harmonization doesn't happen if the resulting type is fully defined.
For f-interp it shouldn't happen too as it's resulting type is a `String`:
```scala
  def f[A >: Any](args: A*): String = macro ???
```
@Kordyjan Kordyjan modified the milestones: 3.2.0-RC1, 3.1.3 Aug 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants