Skip to content

Commit cbfe46d

Browse files
Merge branch 'master' into add-transparent-6
2 parents c36433e + 33afaa2 commit cbfe46d

27 files changed

+586
-38
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package dotty.tools.dotc.tastyreflect
2+
3+
import dotty.tools.dotc.core.Symbols._
4+
5+
trait SymbolOpsImpl extends scala.tasty.reflect.SymbolOps with TastyCoreImpl {
6+
7+
def SymbolDeco(symbol: Symbol): SymbolAPI = new SymbolAPI {
8+
def isEmpty: Boolean = symbol eq NoSymbol
9+
def localContext(implicit ctx: Context): Context = ctx.withOwner(symbol)
10+
def tree(implicit ctx: Context): Option[Definition] =
11+
if (isEmpty) None else Some(FromSymbol.definitionFromSym(symbol))
12+
}
13+
14+
}

compiler/src/dotty/tools/dotc/tastyreflect/TastyCoreImpl.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,5 +50,7 @@ trait TastyCoreImpl extends scala.tasty.reflect.TastyCore {
5050
type Position = util.SourcePosition
5151

5252
type Constant = Constants.Constant
53-
53+
54+
type Symbol = core.Symbols.Symbol
55+
5456
}

compiler/src/dotty/tools/dotc/tastyreflect/TastyImpl.scala

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,21 @@ package dotty.tools.dotc.tastyreflect
22

33
import dotty.tools.dotc.core._
44

5-
class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty with TastyCoreImpl with CaseDefOpsImpl with ConstantOpsImpl with ContextOpsImpl with IdOpsImpl with ImportSelectorOpsImpl with QuotedOpsImpl with PatternOpsImpl with PositionOpsImpl with PrintersImpl with SignatureOpsImpl with StandardDefinitions with TreeOpsImpl with TypeOrBoundsTreesOpsImpl with TypeOrBoundsOpsImpl
5+
class TastyImpl(val rootContext: Contexts.Context)
6+
extends scala.tasty.Tasty
7+
with TastyCoreImpl
8+
with CaseDefOpsImpl
9+
with ConstantOpsImpl
10+
with ContextOpsImpl
11+
with IdOpsImpl
12+
with ImportSelectorOpsImpl
13+
with QuotedOpsImpl
14+
with PatternOpsImpl
15+
with PositionOpsImpl
16+
with PrintersImpl
17+
with SignatureOpsImpl
18+
with StandardDefinitions
19+
with SymbolOpsImpl
20+
with TreeOpsImpl
21+
with TypeOrBoundsTreesOpsImpl
22+
with TypeOrBoundsOpsImpl

compiler/src/dotty/tools/dotc/tastyreflect/TreeOpsImpl.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with TastyCoreImpl with He
1313

1414
def TreeDeco(tree: Tree): TreeAPI = new TreeAPI {
1515
def pos(implicit ctx: Context): Position = tree.pos
16+
def symbol(implicit ctx: Context): Symbol = tree.symbol
17+
1618
}
1719

1820
object IsPackageClause extends IsPackageClauseExtractor {
@@ -30,7 +32,7 @@ trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with TastyCoreImpl with He
3032
}
3133

3234
def PackageClauseDeco(pack: PackageClause): PackageClauseAPI = new PackageClauseAPI {
33-
def definition(implicit ctx: Context): Definition = packageDefFromSym(pack.symbol)
35+
3436
}
3537

3638
// ----- Statements -----------------------------------------------

compiler/src/dotty/tools/dotc/typer/Inliner.scala

Lines changed: 88 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import Symbols._
1111
import Types._
1212
import Decorators._
1313
import Constants._
14-
import StdNames.nme
14+
import StdNames._
1515
import Contexts.Context
1616
import Names.{Name, TermName, EmptyTermName}
1717
import NameOps._
@@ -602,7 +602,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
602602
newOwners = ctx.owner :: Nil,
603603
substFrom = ddef.vparamss.head.map(_.symbol),
604604
substTo = argSyms)
605-
Block(bindingsBuf.toList, expander.transform(ddef.rhs))
605+
seq(bindingsBuf.toList, expander.transform(ddef.rhs))
606606
case _ => tree
607607
}
608608
case _ => tree
@@ -629,7 +629,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
629629
/** Try to match pattern `pat` against scrutinee reference `scrut`. If successful add
630630
* bindings for variables bound in this pattern to `bindingsBuf`.
631631
*/
632-
def reducePattern(bindingsBuf: mutable.ListBuffer[MemberDef], scrut: TermRef, pat: Tree): Boolean = {
632+
def reducePattern(bindingsBuf: mutable.ListBuffer[MemberDef], scrut: TermRef, pat: Tree)(implicit ctx: Context): Boolean = {
633633
val isImplicit = scrut.info == defn.ImplicitScrutineeTypeRef
634634

635635
def newBinding(name: TermName, flags: FlagSet, rhs: Tree): Symbol = {
@@ -655,8 +655,32 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
655655

656656
pat match {
657657
case Typed(pat1, tpt) =>
658+
val getBoundVars = new TreeAccumulator[List[TypeSymbol]] {
659+
def apply(syms: List[TypeSymbol], t: Tree)(implicit ctx: Context) = {
660+
val syms1 = t match {
661+
case t: Bind if t.symbol.isType && t.name != tpnme.WILDCARD =>
662+
t.symbol.asType :: syms
663+
case _ =>
664+
syms
665+
}
666+
foldOver(syms1, t)
667+
}
668+
}
669+
val boundVars = getBoundVars(Nil, tpt)
670+
for (bv <- boundVars) ctx.gadt.setBounds(bv, bv.info.bounds)
658671
if (isImplicit) searchImplicit(nme.WILDCARD, tpt)
659-
else scrut <:< tpt.tpe && reducePattern(bindingsBuf, scrut, pat1)
672+
else scrut <:< tpt.tpe && {
673+
for (bv <- boundVars) {
674+
bv.info = TypeAlias(ctx.gadt.bounds(bv).lo)
675+
// FIXME: This is very crude. We should approximate with lower or higher bound depending
676+
// on variance, and we should also take care of recursive bounds. Basically what
677+
// ConstraintHandler#approximation does. However, this only works for constrained paramrefs
678+
// not GADT-bound variables. Hopefully we will get some way to improve this when we
679+
// re-implement GADTs in terms of constraints.
680+
bindingsBuf += TypeDef(bv)
681+
}
682+
reducePattern(bindingsBuf, scrut, pat1)
683+
}
660684
case pat @ Bind(name: TermName, Typed(_, tpt)) if isImplicit =>
661685
searchImplicit(name, tpt)
662686
case pat @ Bind(name: TermName, body) =>
@@ -706,16 +730,19 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
706730
val scrutineeBinding = normalizeBinding(ValDef(scrutineeSym, scrutinee))
707731

708732
def reduceCase(cdef: untpd.CaseDef): MatchRedux = {
709-
def guardOK = cdef.guard.isEmpty || {
710-
typer.typed(cdef.guard, defn.BooleanType) match {
733+
val caseBindingsBuf = new mutable.ListBuffer[MemberDef]()
734+
def guardOK(implicit ctx: Context) = cdef.guard.isEmpty || {
735+
val guardCtx = ctx.fresh.setNewScope
736+
caseBindingsBuf.foreach(binding => guardCtx.enter(binding.symbol))
737+
typer.typed(cdef.guard, defn.BooleanType)(guardCtx) match {
711738
case ConstantValue(true) => true
712739
case _ => false
713740
}
714741
}
715-
val caseBindingsBuf = new mutable.ListBuffer[MemberDef]()
716742
if (scrutType != defn.ImplicitScrutineeTypeRef) caseBindingsBuf += scrutineeBinding
717-
val pat1 = typer.typedPattern(cdef.pat, scrutType)(typer.gadtContext(gadtSyms))
718-
if (reducePattern(caseBindingsBuf, scrutineeSym.termRef, pat1) && guardOK)
743+
val gadtCtx = typer.gadtContext(gadtSyms).addMode(Mode.GADTflexible)
744+
val pat1 = typer.typedPattern(cdef.pat, scrutType)(gadtCtx)
745+
if (reducePattern(caseBindingsBuf, scrutineeSym.termRef, pat1)(gadtCtx) && guardOK)
719746
Some((caseBindingsBuf.toList, cdef.body))
720747
else
721748
None
@@ -809,6 +836,8 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
809836
def dropUnusedDefs(bindings: List[MemberDef], tree: Tree)(implicit ctx: Context): (List[MemberDef], Tree) = {
810837
val refCount = newMutableSymbolMap[Int]
811838
val bindingOfSym = newMutableSymbolMap[MemberDef]
839+
val dealiased = new java.util.IdentityHashMap[Type, Type]()
840+
812841
def isInlineable(binding: MemberDef) = binding match {
813842
case DefDef(_, Nil, Nil, _, _) => true
814843
case vdef @ ValDef(_, _, _) => isPureExpr(vdef.rhs)
@@ -818,6 +847,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
818847
refCount(binding.symbol) = 0
819848
bindingOfSym(binding.symbol) = binding
820849
}
850+
821851
val countRefs = new TreeTraverser {
822852
override def traverse(t: Tree)(implicit ctx: Context) = {
823853
def updateRefCount(sym: Symbol, inc: Int) =
@@ -844,6 +874,45 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
844874
}
845875
} && !boundSym.is(TransparentImplicitMethod)
846876

877+
val (termBindings, typeBindings) = bindings.partition(_.symbol.isTerm)
878+
879+
/** drop any referenced type symbols from the given set of type symbols */
880+
val dealiasTypeBindings = new TreeMap {
881+
val boundTypes = typeBindings.map(_.symbol).toSet
882+
883+
val dealias = new TypeMap {
884+
override def apply(tp: Type) = dealiased.get(tp) match {
885+
case null =>
886+
val tp1 = mapOver {
887+
tp match {
888+
case tp: TypeRef if boundTypes.contains(tp.symbol) =>
889+
val TypeAlias(alias) = tp.info
890+
alias
891+
case _ => tp
892+
}
893+
}
894+
dealiased.put(tp, tp1)
895+
tp1
896+
case tp1 => tp1
897+
}
898+
}
899+
900+
override def transform(t: Tree)(implicit ctx: Context) = {
901+
val dealiasedType = dealias(t.tpe)
902+
val t1 = t match {
903+
case t: RefTree =>
904+
if (boundTypes.contains(t.symbol)) TypeTree(dealiasedType).withPos(t.pos)
905+
else t.withType(dealiasedType)
906+
case t: DefTree =>
907+
t.symbol.info = dealias(t.symbol.info)
908+
t
909+
case _ =>
910+
t.withType(dealiasedType)
911+
}
912+
super.transform(t1)
913+
}
914+
}
915+
847916
val inlineBindings = new TreeMap {
848917
override def transform(t: Tree)(implicit ctx: Context) = t match {
849918
case t: RefTree =>
@@ -859,17 +928,23 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
859928
case t: Apply =>
860929
val t1 = super.transform(t)
861930
if (t1 `eq` t) t else reducer.betaReduce(t1)
931+
case Block(Nil, expr) =>
932+
super.transform(expr)
862933
case _ =>
863934
super.transform(t)
864935
}
865936
}
866937

867-
val retained = bindings.filterConserve(binding => retain(binding.symbol))
868-
if (retained `eq` bindings) {
869-
(bindings, tree)
938+
val dealiasedTermBindings =
939+
termBindings.mapconserve(dealiasTypeBindings.transform).asInstanceOf[List[MemberDef]]
940+
val dealiasedTree = dealiasTypeBindings.transform(tree)
941+
942+
val retained = dealiasedTermBindings.filterConserve(binding => retain(binding.symbol))
943+
if (retained `eq` dealiasedTermBindings) {
944+
(dealiasedTermBindings, dealiasedTree)
870945
}
871946
else {
872-
val expanded = inlineBindings.transform(tree)
947+
val expanded = inlineBindings.transform(dealiasedTree)
873948
dropUnusedDefs(retained, expanded)
874949
}
875950
}

compiler/src/dotty/tools/dotc/typer/PrepareTransparent.scala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ object PrepareTransparent {
4949
def markTopLevelMatches(meth: Symbol, tree: untpd.Tree)(implicit ctx: Context): Unit = tree match {
5050
case tree: untpd.Match =>
5151
tree.putAttachment(TopLevelMatch, ())
52-
tree.cases.foreach(markTopLevelMatches(meth, _))
52+
for (cdef <- tree.cases) markTopLevelMatches(meth, cdef.body)
5353
case tree: untpd.Block =>
5454
markTopLevelMatches(meth, tree.expr)
5555
case _ =>
@@ -76,12 +76,14 @@ object PrepareTransparent {
7676
* by excluding all symbols properly contained in the inlined method.
7777
*
7878
* Constant vals don't need accessors since they are inlined in FirstTransform.
79+
* Transparent methods don't need accessors since they are inlined in Typer.
7980
*/
8081
def needsAccessor(sym: Symbol)(implicit ctx: Context) =
8182
sym.isTerm &&
8283
(sym.is(AccessFlags) || sym.privateWithin.exists) &&
8384
!sym.isContainedIn(inlineSym) &&
84-
!(sym.isStable && sym.info.widenTermRefExpr.isInstanceOf[ConstantType])
85+
!(sym.isStable && sym.info.widenTermRefExpr.isInstanceOf[ConstantType]) &&
86+
!sym.is(TransparentMethod)
8587

8688
def preTransform(tree: Tree)(implicit ctx: Context): Tree
8789

compiler/src/dotty/tools/dotc/util/Set.scala

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
/* NSC -- new Scala compiler
2-
* Copyright 2005-2012 LAMP/EPFL
3-
* @author Martin Odersky
4-
*/
51
package dotty.tools.dotc.util
62

73
/** A common class for lightweight sets.

library/src/scala/tasty/Tasty.scala

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,20 @@ package scala.tasty
22

33
import scala.tasty.reflect._
44

5-
abstract class Tasty extends TastyCore with CaseDefOps with ConstantOps with ContextOps with IdOps with ImportSelectorOps with QuotedOps with PatternOps with PositionOps with Printers with SignatureOps with StandardDefinitions with TreeOps with TypeOrBoundsTreeOps with TypeOrBoundsOps
5+
abstract class Tasty
6+
extends TastyCore
7+
with CaseDefOps
8+
with ConstantOps
9+
with ContextOps
10+
with IdOps
11+
with ImportSelectorOps
12+
with QuotedOps
13+
with PatternOps
14+
with PositionOps
15+
with Printers
16+
with SignatureOps
17+
with StandardDefinitions
18+
with SymbolOps
19+
with TreeOps
20+
with TypeOrBoundsTreeOps
21+
with TypeOrBoundsOps
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package scala.tasty
2+
package reflect
3+
4+
/** Tasty reflect symbol */
5+
trait SymbolOps extends TastyCore {
6+
7+
trait SymbolAPI {
8+
def isEmpty: Boolean
9+
def localContext(implicit ctx: Context): Context
10+
def tree(implicit ctx: Context): Option[Definition]
11+
}
12+
implicit def SymbolDeco(symbol: Symbol): SymbolAPI
13+
14+
}

library/src/scala/tasty/reflect/TastyCore.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ package scala.tasty.reflect
9696
*
9797
* +- Constant
9898
*
99+
* +- Symbol
100+
*
99101
* ```
100102
*/
101103
trait TastyCore {
@@ -158,4 +160,9 @@ trait TastyCore {
158160
/** Constant value represented as the constant itself */
159161
type Constant
160162

163+
/** Symbol of a definition.
164+
* Then can be compared with == to know if the definition is the same.
165+
*/
166+
type Symbol
167+
161168
}

library/src/scala/tasty/reflect/TreeOps.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ trait TreeOps extends TastyCore {
55

66
trait TreeAPI {
77
def pos(implicit ctx: Context): Position
8+
def symbol(implicit ctx: Context): Symbol
89
}
910
implicit def TreeDeco(tree: Tree): TreeAPI
1011

@@ -19,7 +20,7 @@ trait TreeOps extends TastyCore {
1920
}
2021

2122
trait PackageClauseAPI {
22-
def definition(implicit ctx: Context): Definition
23+
2324
}
2425
implicit def PackageClauseDeco(pack: PackageClause): PackageClauseAPI
2526

library/src/scala/tasty/util/TreeAccumulator.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ abstract class TreeAccumulator[X, T <: Tasty with Singleton](val tasty: T) {
1818
private def foldParents(x: X, trees: Iterable[Parent])(implicit ctx: Context): X = (x /: trees)(foldOverParent)
1919

2020
def foldOverTree(x: X, tree: Tree)(implicit ctx: Context): X = {
21-
def localCtx(definition: Definition): Context = definition.localContext
21+
def localCtx(definition: Definition): Context = definition.symbol.localContext
2222
tree match {
2323
case Term.Ident(_) =>
2424
x
@@ -74,7 +74,7 @@ abstract class TreeAccumulator[X, T <: Tasty with Singleton](val tasty: T) {
7474
case Import(expr, selectors) =>
7575
foldTree(x, expr)
7676
case IsPackageClause(clause @ PackageClause(pid, stats)) =>
77-
foldTrees(foldTree(x, pid), stats)(localCtx(clause.definition))
77+
foldTrees(foldTree(x, pid), stats)(clause.symbol.localContext)
7878
}
7979
}
8080

project/scripts/cmdTests

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ clear_out "$OUT"
5050
grep -qe "def main(args: scala.Array\[scala.Predef.String\]): scala.Unit =" "$tmp"
5151

5252
echo "testing scala.quoted.Expr.run from sbt dotr"
53-
"$SBT" ";dotty-compiler-bootstrapped/dotc -with-compiler tests/run-with-compiler/quote-run.scala; dotty-compiler-bootstrapped/dotr -with-compiler Test" > "$tmp"
53+
"$SBT" ";dotty-compiler-bootstrapped/dotc tests/run-with-compiler/quote-run.scala; dotty-compiler-bootstrapped/dotr -with-compiler Test" > "$tmp"
5454
grep -qe "val a: scala.Int = 3" "$tmp"
5555

5656

tests/pos/i1287/Foo.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
private object Foo {
2+
val x: Int = 1
3+
}

tests/pos/i1287/Test.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
object Test {
2+
val a = Foo.x
3+
}

0 commit comments

Comments
 (0)