question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

macro crushes invariant type variables to Nothing

See original GitHub issue

Skunk’s sql interpolator has a bug in which I am unable to abstract over interpolated Encoder[A]s because the type arguments are crushed to Nothing. I have minimized it in the following dumb but small macros.

Compiler version

3.0.0-RC3

Minimized code

Here is a pair of transparent macros. One takes any expression, and if it’s a Set it returns it, annotated with its own type. The other does the same, but with List.

package test

import scala.quoted._

object Test {

  // Invariant (Set)

  def inv(arg: Expr[Any])(using Quotes): Expr[Any] =
    arg match {
      case '{ $h : Set[h] } => '{ $h : Set[h] }
    }

  transparent inline def inv(inline arg: Any): Any =
    ${ inv('arg) }

  // Covariant (List)

  def cov(arg: Expr[Any])(using Quotes): Expr[Any] =
    arg match {
      case '{ $h : List[h] } => '{ $h : List[h] }
    }

  transparent inline def cov(inline arg: Any): Any =
    ${ cov('arg) }

}

Here are some examples. In both cases calling the macros with concrete types works correctly; the passed expression is inlined with the correct type annotation. But in the case where the type argument is a type variable the covariant case works (the type is List[A]) but in the invariant case the type is Set[Nothing] rather than Set[A].

package test

val inv1: Set[Boolean] = Test.inv(Set(true))
def inv2[A](a: Set[A]): Set[A] = Test.inv(a) // doesn't compile; Set[Nothing] is inferred

val cov1: List[Boolean] = Test.cov(List(true))
def cov2[A](a: List[A]): List[A] = Test.cov(a)

Expectation

My expectation is that this mechanism shouldn’t be sensitive to variance.

Notes

The annotated type is important in the code I generate. If I simplify the returned expressions above to simply h then the examples work, but I can’t do this in the actual macro because it causes inference failures downstream.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:28 (23 by maintainers)

github_iconTop GitHub Comments

3reactions
smartercommented, Jan 12, 2022

Some good news: it looks like https://github.com/lampepfl/dotty/pull/14026 at least fixed the soundness hole pointed out by @LPTK above which means I did my job correctly 😅 :

def inv3[A](a: Set[A]): Set[Nothing] = Test.inv(a) // error:
//                                     ^^^^^^^^^^^
//                                     Found:    Set[A(param)1]
//                                     Required: Set[Nothing]

(I’m not familiar with QuoteMatcher so I can’t comment on what is needed to actually infer A here instead of an unknown abstract type)

1reaction
LPTKcommented, Feb 8, 2022

Ah ok sure, good to know! I missed this was in the pos tests. Would be nice to fix the comment still 😬

Read more comments on GitHub >

github_iconTop Results From Across the Web

VBA: null, nothing and more (or less)
nothing is a literal identifier that is only applicable to variables that are declared as objects or variant. The value nothing represents an...
Read more >
vba - Is there a need to set Objects to Nothing
Setting a variable to Nothing is the way to decrease the the reference counter explicitly.
Read more >
The Complete Guide to Ranges and Cells in Excel VBA
This post covers everything you need to know about using Cells and Ranges in VBA. It covers offsets, reading, writing, using rows and ......
Read more >
Nothing keyword (VBA)
The Nothing keyword is used to disassociate an object variable from an actual object. Use the Set statement to assign Nothing to an...
Read more >
Metaprogramming · The Julia Language
In short, macros must ensure that the variables they introduce in their returned expressions do not accidentally clash with existing variables in the ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found