Skip to content

Commit

Permalink
Handle Ranges in dependent annotations
Browse files Browse the repository at this point in the history
# Conflicts:
#	compiler/src/dotty/tools/dotc/core/Types.scala
  • Loading branch information
odersky committed Aug 25, 2021
1 parent b3d7433 commit 645d988
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 13 deletions.
34 changes: 21 additions & 13 deletions compiler/src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5392,6 +5392,17 @@ object Types {
variance = saved
derivedLambdaType(tp)(ptypes1, this(restpe))

protected def isRange(tp: Type): Boolean = tp.isInstanceOf[Range]

private def diffType(ann: Tree): Type =
val acc = new TreeAccumulator[Type]:
def apply(x: Type, tree: Tree)(using Context): Type =
if isRange(x) then x
else
val tp1 = thisMap(tree.tpe)
foldOver(if tp1 =:= tree.tpe then x else tp1, tree)
acc(NoType, ann)

/** Map this function over given type */
def mapOver(tp: Type): Type = {
record(s"TypeMap mapOver ${getClass}")
Expand Down Expand Up @@ -5435,17 +5446,16 @@ object Types {

case tp @ AnnotatedType(underlying, annot) =>
val underlying1 = this(underlying)
val annot1 =
if underlying1 ne underlying then mapOver(annot)
else annot match
case ConcreteAnnotation(ann)
if ann.existsSubTree { t =>
val tpe = t.typeOpt
tpe.exists && !(this(tpe) =:= tpe)
} => mapOver(annot)
case _ => annot
if (underlying1 eq underlying) && (annot eq annot1) then tp
else derivedAnnotatedType(tp, underlying1, annot1)
if (underlying1 ne underlying) || annot.isInstanceOf[ConcreteAnnotation] then
val diff = diffType(annot.tree)
if isRange(diff) then
// Can't map a tree type to a Range, drop annotation instead
underlying1
else
val annot1 = if diff.exists then mapOver(annot) else annot
derivedAnnotatedType(tp, underlying1, annot1)
else
derivedAnnotatedType(tp, underlying1, annot)

case _: ThisType
| _: BoundType
Expand Down Expand Up @@ -5566,8 +5576,6 @@ object Types {

protected def emptyRange = range(defn.NothingType, defn.AnyType)

protected def isRange(tp: Type): Boolean = tp.isInstanceOf[Range]

protected def lower(tp: Type): Type = tp match {
case tp: Range => tp.lo
case _ => tp
Expand Down
7 changes: 7 additions & 0 deletions tests/pos/dependent-annot.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class C
class ann(x: Any*) extends annotation.Annotation

def f(y: Cap, z: Cap) =
def g(): C @ann(y, z) = ???
val ac: ((x: C) => Array[String @retains(x)]) = ???
val dc = ac(g())

0 comments on commit 645d988

Please sign in to comment.