Skip to content

Add missing case for SyntheticBounds #5475

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

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion compiler/src/dotty/tools/dotc/tastyreflect/CoreImpl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ trait CoreImpl extends scala.tasty.reflect.Core {
type LambdaTypeTree = tpd.LambdaTypeTree
type Bind = tpd.Bind
}
type TypeBoundsTree = tpd.Tree
type TypeBoundsTree = tpd.TypeBoundsTree
type WildcardType = tpd.TypeTree

type TypeOrBounds = Types.Type
type NoPrefix = Types.NoPrefix.type
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ trait TypeOrBoundsTreesOpsImpl extends scala.tasty.reflect.TypeOrBoundsTreeOps w
}

object Bind extends BindExtractor {
def unapply(x: TypeTree)(implicit ctx: Context): Option[(String, TypeBoundsTree)] = x match {
def unapply(x: TypeTree)(implicit ctx: Context): Option[(String, TypeOrBoundsTree)] = x match {
case x: tpd.Bind if x.name.isTypeName => Some((x.name.toString, x.body))
case _ => None
}
Expand All @@ -141,27 +141,33 @@ trait TypeOrBoundsTreesOpsImpl extends scala.tasty.reflect.TypeOrBoundsTreeOps w

def TypeBoundsTreeDeco(bounds: TypeBoundsTree): TypeBoundsTreeAPI = new TypeBoundsTreeAPI {
def tpe(implicit ctx: Context): TypeBounds = bounds.tpe.asInstanceOf[Types.TypeBounds]
def low(implicit ctx: Context): TypeTree = bounds.asInstanceOf[tpd.TypeBoundsTree].lo
def hi(implicit ctx: Context): TypeTree = bounds.asInstanceOf[tpd.TypeBoundsTree].hi
def low(implicit ctx: Context): TypeTree = bounds.lo
def hi(implicit ctx: Context): TypeTree = bounds.hi
}

object IsTypeBoundsTree extends IsTypeBoundsTreeExtractor {
def unapply(x: TypeOrBoundsTree)(implicit ctx: Context): Option[TypeBoundsTree] = x match {
case x: tpd.TypeBoundsTree => Some(x)
case x @ Trees.TypeTree() =>
// TODO only enums generate this kind of type bounds. Is this possible without enums? If not generate tpd.TypeBoundsTree for enums instead
x.tpe match {
case tpe: Types.TypeBounds =>
Some(tpd.TypeBoundsTree(tpd.TypeTree(tpe.lo).withPos(x.pos), tpd.TypeTree(tpe.hi).withPos(x.pos)))
case _ => None
}
case _ => None
}
}

object TypeBoundsTree extends TypeBoundsTreeExtractor {
def unapply(x: TypeOrBoundsTree)(implicit ctx: Context): Option[(TypeTree, TypeTree)] = x match {
case x: tpd.TypeBoundsTree => Some(x.lo, x.hi)
case IsTypeBoundsTree(x) => Some((x.lo, x.hi))
case _ => None
}
}

object SyntheticBounds extends SyntheticBoundsExtractor {
object WildcardTypeTree extends WildcardTypeTreeExtractor {
def unapply(x: TypeOrBoundsTree)(implicit ctx: Context): Boolean = x match {
case x @ Trees.TypeTree() => x.tpe.isInstanceOf[Types.TypeBounds]
case Trees.Ident(nme.WILDCARD) => x.tpe.isInstanceOf[Types.TypeBounds]
case _ => false
}
Expand Down
8 changes: 7 additions & 1 deletion library/src/scala/tasty/reflect/Core.scala
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ package scala.tasty.reflect
* | +- Bind
* |
* +- TypeBoundsTree
* +- SyntheticBounds
* +- WildcardTypeTree
*
* +- CaseDef
* +- TypeCaseDef
Expand Down Expand Up @@ -311,6 +311,12 @@ trait Core {
/** Type tree representing a type bound written in the source */
type TypeBoundsTree <: TypeOrBoundsTree

/** Type tree representing wildcard type bounds written in the source.
* The wildcard type `_` (for example in in `List[_]`) will be a type tree that
* represents a type but has `TypeBound`a inside.
*/
type WildcardType <: TypeOrBoundsTree

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the document is not precise. Given the following code:

val a: List[_] = List(1, "String")

The underscore become TypeBoundsTree(TypeTree( | scala.this.Nothing), TypeTree( | scala.this.Any) | )

Copy link
Contributor

@liufengyun liufengyun Nov 23, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can give the hypothesis in #5483 a second thought.

Even if we want to report errors for type trees:

  • it's completely acceptable for end users to see the error report on the whole type tree
  • they work for type alias and infered types as well
  • In practice, I conjecture that macro authors will check types to detect errors, and then just report errors on the whole type tree instead of inspecting the components of type trees & deal with inferred and aliased types.
fooMacro[List[Int]]
              ^^^

/** Type or bounds */
type TypeOrBounds <: AnyRef

Expand Down
8 changes: 4 additions & 4 deletions library/src/scala/tasty/reflect/Printers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,8 @@ trait Printers
this += "TypeTree.Block(" ++= aliases += ", " += tpt += ")"
case TypeBoundsTree(lo, hi) =>
this += "TypeBoundsTree(" += lo += ", " += hi += ")"
case SyntheticBounds() =>
this += s"SyntheticBounds()"
case WildcardTypeTree() =>
this += s"WildcardTypeTree()"
case TypeTree.MatchType(bound, selector, cases) =>
this += "TypeTree.MatchType(" += bound += ", " += selector += ", " ++= cases += ")"
}
Expand Down Expand Up @@ -996,7 +996,7 @@ trait Printers
this += arg.name
arg.rhs match {
case IsTypeBoundsTree(rhs) => printBoundsTree(rhs)
case rhs @ SyntheticBounds() =>
case rhs @ WildcardTypeTree() =>
printTypeOrBound(rhs.tpe)
case rhs @ TypeTree.TypeLambdaTree(tparams, body) =>
def printParam(t: TypeOrBoundsTree): Unit = t match {
Expand Down Expand Up @@ -1184,7 +1184,7 @@ trait Printers
printTypeTree(lo)
this += " <: "
printTypeTree(hi)
case tpt @ SyntheticBounds() =>
case tpt @ WildcardTypeTree() =>
printTypeOrBound(tpt.tpe)
case IsTypeTree(tpt) =>
printTypeTree(tpt)
Expand Down
2 changes: 1 addition & 1 deletion library/src/scala/tasty/reflect/TreeUtils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ trait TreeUtils
case TypeTree.Block(typedefs, tpt) => foldTypeTree(foldTrees(x, typedefs), tpt)
case TypeTree.MatchType(boundopt, selector, cases) =>
foldTypeCaseDefs(foldTypeTree(boundopt.fold(x)(foldTypeTree(x, _)), selector), cases)
case SyntheticBounds() => x
case WildcardTypeTree() => x
case TypeBoundsTree(lo, hi) => foldTypeTree(foldTypeTree(x, lo), hi)
}

Expand Down
10 changes: 5 additions & 5 deletions library/src/scala/tasty/reflect/TypeOrBoundsTreeOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ trait TypeOrBoundsTreeOps extends Core {

val Bind: BindExtractor
abstract class BindExtractor{
def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[(String, TypeBoundsTree)]
def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[(String, TypeOrBoundsTree)]
}

val Block: BlockExtractor
Expand Down Expand Up @@ -126,10 +126,10 @@ trait TypeOrBoundsTreeOps extends Core {
def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[(TypeTree, TypeTree)]
}

/** TypeBoundsTree containing an inferred type bounds */
val SyntheticBounds: SyntheticBoundsExtractor
abstract class SyntheticBoundsExtractor {
/** Matches a TypeBoundsTree containing inferred type bounds */
/** TypeBoundsTree containing wildcard type bounds */
val WildcardTypeTree: WildcardTypeTreeExtractor
abstract class WildcardTypeTreeExtractor {
/** Matches a TypeBoundsTree containing wildcard type bounds */
def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Boolean
}

Expand Down