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

Scala 3.5 Warning Message Regarding Implicit Resolution #753

Open
mikail-khan opened this issue Nov 6, 2024 · 2 comments
Open

Scala 3.5 Warning Message Regarding Implicit Resolution #753

mikail-khan opened this issue Nov 6, 2024 · 2 comments

Comments

@mikail-khan
Copy link

mikail-khan commented Nov 6, 2024

Given the following opaque type:

import scala.math.BigDecimal

import zio.*
import zio.json.*
import zio.prelude.{Equal, Validation}
import zio.schema.Schema

object Price {

  opaque type Price = BigDecimal

  // Factory method with Validation to ensure non-negative Price
  def make(amount: BigDecimal): Validation[Chunk[String], Price] =
    Validation.fromPredicateWith(Chunk("Price must be non-negative"))(amount)(_ >= 0)

  // JSON codec for Price using zio-json, with conversions to handle java.math.BigDecimal
  given JsonCodec[Price] = JsonCodec.bigDecimal.transformOrFail(
    amount => make(BigDecimal(amount)).toEither.left.map(_.mkString(", ")), // Handle Chunk errors
    price => unwrap(price).bigDecimal // Converts scala.math.BigDecimal to java.math.BigDecimal
  )

  // Extension method to unwrap the Price back to BigDecimal
  extension (price: Price) {
    def unwrap: BigDecimal = price
  }

  // Schema for Price using zio-schema, with validation to ensure non-negative
  given Schema[Price] =
    Schema[BigDecimal].transformOrFail(
      amount => make(amount).toEither.left.map(_.mkString(", ")), // Handle Chunk errors
      price => Right(unwrap(price))
    )

  // Equality instance for Price using zio.prelude
  given Equal[Price] = Equal.default

}

I receive the following compiler warning:

[warn] 40 |    Schema[BigDecimal].transformOrFail(
[warn]    |                      ^
[warn]    |Result of implicit search for zio.schema.Schema[BigDecimal] will change.
[warn]    |Current result given_Schema_Price will be no longer eligible
[warn]    |  because it is not defined before the search position.
[warn]    |Result with new rules: zio.schema.Schema.bigDecimal.
[warn]    |To opt into the new rules, compile with `-source future` or use
[warn]    |the `scala.language.future` language import.
[warn]    |
[warn]    |To fix the problem without the language import, you could try one of the following:
[warn]    |  - use a `given ... with` clause as the enclosing given,
[warn]    |  - rearrange definitions so that given_Schema_Price comes earlier,
[warn]    |  - use an explicit argument.
[warn]    |This will be an error in Scala 3.5 and later.

How do I future proof my code?

I tried to import zio.schema.Schema.bigDecimal but it does not get used.

I tried to replace the implicit definition as suggested in the warning message to:

  given Schema[Price] with {
    Schema[BigDecimal].transformOrFail(
      amount => make(amount).toEither.left.map(_.mkString(", ")), // Handle Chunk errors
      price => Right(unwrap(price))
    )
  }

but I get:

[error] 40 |  given Schema[Price] with {
[error]    |        ^
[error]    |        Cannot extend sealed trait Schema in a different source file
[error]    |
[error]    | longer explanation available when compiling with `-explain`
@mikail-khan
Copy link
Author

One solution is to not use Scala's BigDecimal but Java's BigDecimal and then use Schema.primivitve

import zio.*
import zio.json.*
import zio.prelude.{Equal, Validation}
import zio.schema.Schema

import java.math.BigDecimal

object Price {

  opaque type Price = BigDecimal

  // Factory method with Validation to ensure non-negative Price
  def make(amount: BigDecimal): Validation[Chunk[String], Price] =
    Validation.fromPredicateWith(Chunk("Price must be non-negative"))(amount)((b: BigDecimal) =>
      b.compareTo(BigDecimal.ZERO) >= 0
    )

  // JSON codec for Price using zio-json, with conversions to handle java.math.BigDecimal
  given JsonCodec[Price] = JsonCodec.bigDecimal.transformOrFail(
    amount => make(amount).toEither.left.map(_.mkString(", ")), // Handle Chunk errors
    price => unwrap(price) // Converts scala.math.BigDecimal to java.math.BigDecimal
  )

  // Extension method to unwrap the Price back to BigDecimal
  extension (price: Price) {
    def unwrap: BigDecimal = price
  }

  // Schema for Price using zio-schema, with validation to ensure non-negative
  given Schema[Price] =
    Schema
      .primitive[BigDecimal]
      .transformOrFail(
        amount => make(amount).toEither.left.map(_.mkString(", ")), // Handle Chunk errors
        price => Right(unwrap(price))
      )

  // Equality instance for Price using zio.prelude
  given Equal[Price] = Equal.default

}

@987Nabil
Copy link
Contributor

987Nabil commented Nov 13, 2024

Try to add a implicit Schema of your need as an input for the given, so using Schema[BigDecimal] on the left hand side

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

No branches or pull requests

2 participants