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

mend/within not working in an inline context #19

Open
NPCRUS opened this issue Nov 20, 2024 · 6 comments
Open

mend/within not working in an inline context #19

NPCRUS opened this issue Nov 20, 2024 · 6 comments

Comments

@NPCRUS
Copy link

NPCRUS commented Nov 20, 2024

trait Defooler[T] {
    def defool(a: String): Option[String]
  }
  object Defooler extends Derivation[Defooler] {
    inline def join[DerivationType <: Product](using ProductReflection[DerivationType]): Defooler[DerivationType] = ???

    inline def split[DerivationType](using SumReflection[DerivationType]): Defooler[DerivationType] = str =>
      mend {
        case e: VariantError =>
          Left(e.getMessage)
      }.within {
        delegate(str)([VariantType <: DerivationType] => defooler =>
          defooler.defool(str)  
        )
      }
  }

produces:

value within is not a member of Any.
An extension method was tried, but could not be fully constructed:

    contingency.within()

    failed with:

        value within: <overloaded contingency.within> does not take parameters

at .within

@propensive
Copy link
Owner

What happens if you change the return type of def defool to Either[String, String] or change the RHS of case e: VariantError to None?

@NPCRUS
Copy link
Author

NPCRUS commented Dec 2, 2024

I see it was an error on my side:
SAM type returns Option[String], but when mending i was returning Left[String, Nothing].
Nevertheless using correct return type within mend:

  1. returning None
  2. changing SAM to String => Either[String, String]

doesn't change the error at all

@propensive
Copy link
Owner

What happens if (just for diagnosis) you try something like this:

    inline def split[DerivationType](using SumReflection[DerivationType]): Defooler[DerivationType] =
      val unused = mend {
        case e: VariantError =>
          Left(e.getMessage)
      }.within {
        delegate("")([VariantType <: DerivationType] => defooler =>
          defooler.defool("")
        )
      }
      str => None

...or other variations? How much do you have to change to get it to compile (if you can at all)?

@NPCRUS
Copy link
Author

NPCRUS commented Dec 2, 2024

wow, i was actually able to quite strongly simplify the example producing the same error, so that it leaves the context of wisteria:

inline def simpleTest: Either[String, String] = 
    mend {
      case e: Exception =>
        Left(e.getMessage)
    }.within {
      abort(new Exception("oops"))
    }

once you remove inline it all compiles
@propensive if you agree, i can close this one and move this issue to contingency

@propensive propensive transferred this issue from propensive/wisteria Dec 2, 2024
@propensive
Copy link
Owner

It was straightforward enough to move it with the "transfer" button!

@propensive propensive changed the title Combination .mend(???).within(???) not working inside split block mend/within not working in an inline context Dec 2, 2024
@propensive
Copy link
Owner

propensive commented Dec 4, 2024

The problem is that the transparent inline method, mend (and its siblings, tend and so on), has a declared return type of Any but should always refine its type to some parameterization of Mend based on the cases that are declared. The extension method within would then applicable.

But inside an inline block, the surrounding inline is expanded before the inner mend is, so we know nothing more about the return type of mend { cases } at the point the compiler tries to find the right within extension method.

We could redefine the return type of mend to something fixed, but more precise. That would help to get within selected. But the mendWithin implementation of within needs more precise details of the type generated by the mend macro, just to typecheck its body.

We might be able to regenerate those type details in the mendWithin macro, but by then I think it's too late. The compiler would need to typecheck within's body before this, and that shouldn't work without knowing what cases are being handled.

In short, I'm not hopeful this can be fixed without some drastic changes. But I'll leave this open with the intention of investigating a bit more deeply.

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