Skip to content

Give to @odersky. #2439

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

Closed
wants to merge 66 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
ee558f7
Simplify: initial wip
DarkDimius Aug 29, 2016
58876df
Simplify: more WIP
DarkDimius Aug 29, 2016
7f5b19f
Simplify: implement constant folding.
DarkDimius Jun 27, 2016
b15c78c
Simplify: do not generate blocks with empty stats.
DarkDimius Jun 27, 2016
5447bdb
Simplify: devalify now also performs constant propagation
DarkDimius Jun 27, 2016
016a31b
Simplify: fix bug in bubbleUpNothing. Definitions should not be skipped.
DarkDimius Jun 27, 2016
c459f04
Simplify: improve constant folding & leave breadcrumbs for contributors
DarkDimius Jun 28, 2016
544206d
After-rebase fixes
DarkDimius Aug 29, 2016
a05305c
Simplify: fix owner corruption when inlining LabelDefs.
DarkDimius Aug 30, 2016
f3721a4
Start getting rid from Scala2 compiling artefacts.
DarkDimius Aug 30, 2016
0864cd5
Don't alias lazy vals
DarkDimius Aug 30, 2016
bbc5ee8
Don't create empty DefDefs if they should do nothing.
DarkDimius Aug 30, 2016
f892b96
Simplify: Fix bug with elimination of side-effects.
DarkDimius Aug 30, 2016
77910f1
Simplify: Don't partials-evaluate case-defs.
DarkDimius Aug 30, 2016
281e387
Simplify: make object inlining robust against Nothing.
DarkDimius Aug 30, 2016
628171d
Simplify: Fix several infinite cycles.
DarkDimius Aug 30, 2016
51085a9
Simplify: Don't drop lazy val reads.
DarkDimius Aug 31, 2016
5092b56
Simplify: jump jump: optimise label-defs that are themselves forwarders
DarkDimius Aug 31, 2016
85567a0
Simplify: start joining ifs if branches are similar.
DarkDimius Aug 31, 2016
d1fc42c
Simplify: String+ isn't symmetric
DarkDimius Aug 31, 2016
14d49cd
Simplify: fix a bug inside isSimilar
DarkDimius Aug 31, 2016
3921703
Simplify: don't remove by-name calls
DarkDimius Aug 31, 2016
2a13771
Simplify: don't remove infinite cycles :-)
DarkDimius Aug 31, 2016
67df3c4
Got tired of fixing Pattern*Factorization.
DarkDimius Aug 31, 2016
4cf1e88
simplify: Reading vals through successful casts should be allowed
DarkDimius Sep 2, 2016
befa6b8
simplify: Playing with optimising if expressions.
DarkDimius Sep 2, 2016
ce96d13
simplify: fixes to inlineLocalObjects.
DarkDimius Sep 2, 2016
e2e87cc
Simplify: add vilify transformation
DarkDimius Sep 2, 2016
af77535
Simplify: add dropGoodCasts that drops good casts in stat position.
DarkDimius Sep 2, 2016
23ccd57
Simplify: fix the fix of handling by-name arguments.
DarkDimius Sep 2, 2016
11dc293
Simplify: dropNoEffects now flattens blocks.
DarkDimius Sep 2, 2016
3dcac6f
Simplify: inline case-defs that have literal in rhs.
DarkDimius Sep 2, 2016
6d7f7cf
Simplify: Somes\options can be null :-(
DarkDimius Sep 2, 2016
f3f92a4
Make optimisation optional.
DarkDimius Sep 6, 2016
ee2f6a8
Simplify:inlineLocalObjects: don't inline mutable fields.
DarkDimius Sep 6, 2016
5d5fff8
Simplify: DropGoodCasts: Don't accumulate cast on garbage.
DarkDimius Sep 6, 2016
b5bd282
Simplify: devalify: correctly rebase New when prefix changes.
DarkDimius Sep 6, 2016
0708d12
Simplify:inlineLocalObjects: make more robust against complex labels.
DarkDimius Sep 6, 2016
036dd91
Simplify: NullCheck: as proposed by @jvican
DarkDimius Sep 6, 2016
c6512df
Simplify: fix and enable removeUnnecessaryNullChecks.
DarkDimius Sep 6, 2016
2a1ff19
Add missing NamedType import
jvican Sep 7, 2016
83f404c
Simplify: devalify: don't kick in on by-name params
jvican Sep 7, 2016
c074a91
Simplify: fix infinite recursion in followCases
DarkDimius Sep 20, 2016
707498d
Simplify: remove duplicate null tests.
DarkDimius Sep 20, 2016
9194cc0
Simplify: this can be dropped inside a block.
DarkDimius Sep 20, 2016
c3e721e
Finish rebase over dotty upstream
DarkDimius Mar 1, 2017
7848bb9
Document Simplify optimizations
OlivierBlanvillain Mar 2, 2017
3e894b0
Fix Erasure of uniqueRefDenotations with different underlying type.
DarkDimius Apr 11, 2017
6fbb5a8
Rewrite labelDefs phase
DarkDimius Apr 26, 2017
72d516e
Soften Ycheck scoping rules for local jumps after LabelDefs
DarkDimius Apr 27, 2017
6c42811
Fix compilation after rebase
OlivierBlanvillain Apr 28, 2017
9ef445f
Restore tests moved to disabled
OlivierBlanvillain Apr 28, 2017
4efe46d
Remove PatternConstantsFactorization & PatternTypeFactorization for now
OlivierBlanvillain Apr 28, 2017
dd1d88e
Run all tests with -optimise
OlivierBlanvillain Apr 28, 2017
f1ca33d
Formating / refactoring
OlivierBlanvillain Apr 28, 2017
45e2b4f
Remove usage of -optimise in ClassfileParser
OlivierBlanvillain Apr 28, 2017
8c1f3f4
Fix a few bugs in Simplify
OlivierBlanvillain Apr 28, 2017
f54a387
[TODO] fix tpd .toString hack
OlivierBlanvillain Apr 28, 2017
6d6aec4
WIP
OlivierBlanvillain May 11, 2017
694e743
Add missing `.ensureApplied` in `constantFold`.
OlivierBlanvillain May 11, 2017
e23acc8
bubbleUpNothing: do we want it? It breaks the last 4 failing tests
OlivierBlanvillain May 11, 2017
68df7c4
Kinda fix toString hack: testPicking w/o -optimise + tpd swtich
OlivierBlanvillain May 11, 2017
4f39455
One last issue with these tpd changes...
OlivierBlanvillain May 11, 2017
a32b5ca
Fix pickling tests failing with smarter tpd.
DarkDimius May 15, 2017
a8af838
Tpd: postpone unnecessary computations.
DarkDimius May 15, 2017
6f3aa3c
Handle corner case correctly
odersky May 16, 2017
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
104 changes: 14 additions & 90 deletions compiler/src/dotty/tools/backend/jvm/LabelDefs.scala
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,11 @@ import StdNames.nme
* Unreachable jumps will be eliminated by local dead code analysis.
* After JVM is smart enough to remove next-line jumps
*
* Note that Label DefDefs can be only nested in Block, otherwise no one would
* be able to call them Other DefDefs are eliminated
* Note that his phase Ychecking this phase required softening scoping rules
* as it intentionally allowed to break scoping rules inside methods for labels.
* This is modified by setting `labelsReordered` flag in Phases.
*
* @author Dmitry Petrashko
*/
class LabelDefs extends MiniPhaseTransform {
def phaseName: String = "labelDef"
Expand All @@ -90,76 +93,24 @@ class LabelDefs extends MiniPhaseTransform {
else {
collectLabelDefs.clear
val newRhs = collectLabelDefs.transform(tree.rhs)
val labelCalls = collectLabelDefs.labelCalls
var entryPoints = collectLabelDefs.parentLabelCalls
var labelDefs = collectLabelDefs.labelDefs
var callCounts = collectLabelDefs.callCounts

// make sure that for every label there's a single location it should return and single entry point
// if theres already a location that it returns to that's a failure
val disallowed = new mutable.HashMap[Symbol, Tree]()
queue.sizeHint(labelCalls.size + entryPoints.size)

def putLabelDefsNearCallees = new TreeMap() {

override def transform(tree: tpd.Tree)(implicit ctx: Context): tpd.Tree = {
tree match {
case t: Apply if (entryPoints.contains(t)) =>
entryPoints = entryPoints - t
labelLevel = labelLevel + 1
val r = Block(moveLabels(t), t)
labelLevel = labelLevel - 1
if (labelLevel == 0) beingAppended.clear()
r
case _ => if (entryPoints.nonEmpty && labelDefs.nonEmpty) super.transform(tree) else tree
}
case t: Apply if labelDefs.contains(t.symbol) =>
val labelDef = labelDefs(t.symbol)
labelDefs -= t.symbol

}
}
val labelDef2 = transform(labelDef)
Block(labelDef2:: Nil, t)

def moveLabels(entryPoint: Apply): List[Tree] = {
val entrySym = entryPoint.symbol
if ((entrySym is Flags.Label) && labelDefs.contains(entrySym)) {
val visitedNow = new mutable.HashMap[Symbol, Tree]()
val treesToAppend = new ArrayBuffer[Tree]() // order matters. parents should go first
treesToAppend += labelDefs(entrySym)
queue.clear()

var visited = 0
queue += entryPoint
while (visited < queue.size) {
val owningLabelDefSym = queue(visited).symbol
for (call <- labelCalls(owningLabelDefSym)) {
val callSym = call.symbol
if (!beingAppended.contains(callSym)) {
if (disallowed.contains(callSym)) {
val oldCall = disallowed(callSym)
ctx.error(s"Multiple return locations for Label $oldCall and $call", callSym.pos)
} else {
if ((!visitedNow.contains(callSym)) && labelDefs.contains(callSym)) {
val defTree = labelDefs(callSym)
visitedNow.put(callSym, defTree)
val callCount = callCounts(callSym)
if (callCount > 1) {
if (!treesToAppend.contains(defTree)) {
treesToAppend += defTree
queue += call

}
} else if (entryPoint.symbol ne callSym) entryPoints += call
}
}
}
}

visited += 1
case _ => if (labelDefs.nonEmpty) super.transform(tree) else tree
}
beingAppended ++= treesToAppend.map(_.symbol)
treesToAppend.toList.map(putLabelDefsNearCallees.transform)
} else Nil
}
}


val res = cpy.DefDef(tree)(rhs = putLabelDefsNearCallees.transform(newRhs))

res
Expand All @@ -168,22 +119,11 @@ class LabelDefs extends MiniPhaseTransform {

object collectLabelDefs extends TreeMap() {

// label calls from this DefDef
var parentLabelCalls: mutable.Set[Tree] = new mutable.HashSet[Tree]()
var callCounts: mutable.Map[Symbol, Int] = new mutable.HashMap[Symbol, Int]().withDefaultValue(0)

def shouldMoveLabel = true

// labelSymbol -> Defining tree
val labelDefs = new mutable.HashMap[Symbol, Tree]()
// owner -> all calls by this owner
val labelCalls = new mutable.HashMap[Symbol, mutable.Set[Tree]]()
var owner: Symbol = null

def clear = {
parentLabelCalls.clear()
labelDefs.clear()
labelCalls.clear()
}

override def transform(tree: tpd.Tree)(implicit ctx: Context): tpd.Tree = tree match {
Expand All @@ -196,30 +136,14 @@ class LabelDefs extends MiniPhaseTransform {
}
case t: DefDef =>
assert(t.symbol is Flags.Label)

val st = parentLabelCalls
parentLabelCalls = new mutable.HashSet[Tree]()
val symt = owner
owner = t.symbol

val r = super.transform(tree)

owner = symt
labelCalls(r.symbol) = parentLabelCalls
parentLabelCalls = st

if (shouldMoveLabel) {
labelDefs(r.symbol) = r
EmptyTree
} else r
labelDefs(r.symbol) = r
EmptyTree
case t: Apply if t.symbol is Flags.Label =>
val sym = t.symbol
parentLabelCalls = parentLabelCalls + t
if (owner != sym) callCounts(sym) = callCounts(sym) + 1
super.transform(tree)
case _ =>
super.transform(tree)

}
}
}
7 changes: 5 additions & 2 deletions compiler/src/dotty/tools/dotc/Compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import core.DenotTransformers.DenotTransformer
import core.Denotations.SingleDenotation

import dotty.tools.backend.jvm.{LabelDefs, GenBCode, CollectSuperCalls}
import dotty.tools.dotc.transform.linker.Simplify

/** The central class of the dotc compiler. The job of a compiler is to create
* runs, which process given `phases` in a given `rootContext`.
Expand Down Expand Up @@ -74,6 +75,7 @@ class Compiler {
new ElimByName, // Expand by-name parameter references
new AugmentScala2Traits, // Expand traits defined in Scala 2.11 to simulate old-style rewritings
new ResolveSuper, // Implement super accessors and add forwarders to trait methods
new Simplify, // Perform local optimizations, simplified versions of what linker does.
new PrimitiveForwarders, // Add forwarders to trait methods that have a mismatch between generic and primitives
new ArrayConstructors), // Intercept creation of (non-generic) arrays and intrinsify.
List(new Erasure), // Rewrite types to JVM model, erasing all type parameters, abstract types and refinements.
Expand All @@ -86,9 +88,10 @@ class Compiler {
new NonLocalReturns, // Expand non-local returns
new CapturedVars, // Represent vars captured by closures as heap objects
new Constructors, // Collect initialization code in primary constructors
// Note: constructors changes decls in transformTemplate, no InfoTransformers should be added after it
// Note: constructors changes decls in transformTemplate, no InfoTransformers should be added after it
new FunctionalInterfaces, // Rewrites closures to implement @specialized types of Functions.
new GetClass), // Rewrites getClass calls on primitive types.
new GetClass, // Rewrites getClass calls on primitive types.
new Simplify), // Perform local optimizations, simplified versions of what linker does.
List(new LambdaLift, // Lifts out nested functions to class scope, storing free variables in environments
// Note: in this mini-phase block scopes are incorrect. No phases that rely on scopes should be here
new ElimStaticThis, // Replace `this` references to static objects by global identifiers
Expand Down
32 changes: 25 additions & 7 deletions compiler/src/dotty/tools/dotc/ast/tpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -472,15 +472,27 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
}
}

override def Apply(tree: Tree)(fun: Tree, args: List[Tree])(implicit ctx: Context): Apply =
ta.assignType(untpd.cpy.Apply(tree)(fun, args), fun, args)
// Note: Reassigning the original type if `fun` and `args` have the same types as before
override def Apply(tree: Tree)(fun: Tree, args: List[Tree])(implicit ctx: Context): Apply = {
val untyped = untpd.cpy.Apply(tree)(fun, args)
if (untyped.ne(tree))
ta.assignType(untyped, fun, args)
else
tree.asInstanceOf[Apply]
}

// Note: Reassigning the original type if `fun` and `args` have the same types as before
// does not work here: The computed type depends on the widened function type, not
// the function type itself. A treetransform may keep the function type the
// same but its widened type might change.

override def TypeApply(tree: Tree)(fun: Tree, args: List[Tree])(implicit ctx: Context): TypeApply =
ta.assignType(untpd.cpy.TypeApply(tree)(fun, args), fun, args)
override def TypeApply(tree: Tree)(fun: Tree, args: List[Tree])(implicit ctx: Context): TypeApply = {
val untyped = untpd.cpy.TypeApply(tree)(fun, args)
if (untyped.ne(tree))
ta.assignType(untyped, fun, args)
else
tree.asInstanceOf[TypeApply]

}
// Same remark as for Apply

override def Literal(tree: Tree)(const: Constant)(implicit ctx: Context): Literal =
Expand Down Expand Up @@ -514,8 +526,14 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
}
}

override def Closure(tree: Tree)(env: List[Tree], meth: Tree, tpt: Tree)(implicit ctx: Context): Closure =
ta.assignType(untpd.cpy.Closure(tree)(env, meth, tpt), meth, tpt)
override def Closure(tree: Tree)(env: List[Tree], meth: Tree, tpt: Tree)(implicit ctx: Context): Closure = {
val untyped = untpd.cpy.Closure(tree)(env, meth, tpt)
val typed = ta.assignType(untyped, meth, tpt)
if (untyped.ne(tree))
typed
else
tree.asInstanceOf[Closure]
}
// Same remark as for Apply

override def Match(tree: Tree)(selector: Tree, cases: List[CaseDef])(implicit ctx: Context): Match = {
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/config/Printers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,5 @@ object Printers {
val pickling: Printer = noPrinter
val inlining: Printer = noPrinter
val exhaustivity: Printer = noPrinter
val simplify: Printer = noPrinter
}
26 changes: 26 additions & 0 deletions compiler/src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,16 @@ class Definitions {
def Boolean_&& = Boolean_andR.symbol
lazy val Boolean_orR = BooleanClass.requiredMethodRef(nme.ZOR)
def Boolean_|| = Boolean_orR.symbol
lazy val Boolean_eqeqR = BooleanClass.info.member(nme.EQ).suchThat(_.info.firstParamTypes match {
case List(pt) => (pt isRef BooleanClass)
case _ => false
})
def Boolean_== = Boolean_eqeqR.symbol
lazy val Boolean_neqeqR = BooleanClass.info.member(nme.NE).suchThat(_.info.firstParamTypes match {
case List(pt) => (pt isRef BooleanClass)
case _ => false
})
def Boolean_!= = Boolean_neqeqR.symbol

lazy val ByteType: TypeRef = valueTypeRef("scala.Byte", BoxedByteType, java.lang.Byte.TYPE, ByteEnc)
def ByteClass(implicit ctx: Context) = ByteType.symbol.asClass
Expand Down Expand Up @@ -423,6 +433,13 @@ class Definitions {
lazy val Long_LSR_Int = LongType.member(nme.LSR).requiredSymbol(
x => (x is Method) && (x.info.firstParamTypes.head isRef defn.IntClass)
)
lazy val Long_plusR = LongClass.requiredMethodRef(nme.PLUS, List(LongType))
def Long_+ = Long_plusR.symbol
lazy val Long_mulR = LongClass.requiredMethodRef(nme.MUL, List(LongType))
def Long_* = Long_mulR.symbol
lazy val Long_divR = LongClass.requiredMethodRef(nme.DIV, List(LongType))
def Long_/ = Long_divR.symbol

lazy val FloatType: TypeRef = valueTypeRef("scala.Float", BoxedFloatType, java.lang.Float.TYPE, FloatEnc)
def FloatClass(implicit ctx: Context) = FloatType.symbol.asClass
lazy val DoubleType: TypeRef = valueTypeRef("scala.Double", BoxedDoubleType, java.lang.Double.TYPE, DoubleEnc)
Expand Down Expand Up @@ -483,6 +500,11 @@ class Definitions {
lazy val BoxedNumberClass = ctx.requiredClass("java.lang.Number")
lazy val ThrowableClass = ctx.requiredClass("java.lang.Throwable")
lazy val ClassCastExceptionClass = ctx.requiredClass("java.lang.ClassCastException")
lazy val ArithmeticExceptionClass = ctx.requiredClass("java.lang.ArithmeticException")
lazy val ArithmeticExceptionClass_stringConstructor = ArithmeticExceptionClass.info.member(nme.CONSTRUCTOR).suchThat(_.info.firstParamTypes match {
case List(pt) => (pt isRef StringClass)
case _ => false
}).symbol.asTerm
lazy val JavaSerializableClass = ctx.requiredClass("java.io.Serializable")
lazy val ComparableClass = ctx.requiredClass("java.lang.Comparable")

Expand Down Expand Up @@ -514,6 +536,10 @@ class Definitions {
def DynamicClass(implicit ctx: Context) = DynamicType.symbol.asClass
lazy val OptionType: TypeRef = ctx.requiredClassRef("scala.Option")
def OptionClass(implicit ctx: Context) = OptionType.symbol.asClass
lazy val SomeType: TypeRef = ctx.requiredClassRef("scala.Some")
def SomeClass(implicit ctx: Context) = SomeType.symbol.asClass
lazy val NoneModuleRef: TermRef = ctx.requiredModuleRef("scala.None")
def NoneClass(implicit ctx: Context) = NoneModuleRef.symbol.moduleClass.asClass
lazy val EnumType: TypeRef = ctx.requiredClassRef("scala.Enum")
def EnumClass(implicit ctx: Context) = EnumType.symbol.asClass
lazy val EnumValuesType: TypeRef = ctx.requiredClassRef("scala.runtime.EnumValues")
Expand Down
5 changes: 4 additions & 1 deletion compiler/src/dotty/tools/dotc/core/NameKinds.scala
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,9 @@ object NameKinds {
val PatMatCaseName = new UniqueNameKind("case")
val PatMatMatchFailName = new UniqueNameKind("matchFail")
val PatMatSelectorName = new UniqueNameKind("selector")
val LocalOptFact = new UniqueNameKind("fact")
val LocalOptSelector = new UniqueNameKind("selector")
val LocalOptFallback = new UniqueNameKind("fallback")

/** The kind of names of default argument getters */
val DefaultGetterName = new NumberedNameKind(DEFAULTGETTER, "DefaultGetter") {
Expand Down Expand Up @@ -384,4 +387,4 @@ object NameKinds {
def qualifiedNameKindOfTag : collection.Map[Int, QualifiedNameKind] = qualifiedNameKinds
def numberedNameKindOfTag : collection.Map[Int, NumberedNameKind] = numberedNameKinds
def uniqueNameKindOfSeparator: collection.Map[String, UniqueNameKind] = uniqueNameKinds
}
}
8 changes: 7 additions & 1 deletion compiler/src/dotty/tools/dotc/core/Scopes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,10 @@ object Scopes {
/** Is the scope empty? */
def isEmpty: Boolean = lastEntry eq null

def foreach[U](p: Symbol => U)(implicit ctx: Context): Unit = toList foreach p
/** Applies a function f to all Symbols of this Scope. */
def foreach[U](f: Symbol => U)(implicit ctx: Context): Unit = toList.foreach(f)

/** Selects all Symbols of this Scope which satisfy a predicate. */
def filter(p: Symbol => Boolean)(implicit ctx: Context): List[Symbol] = {
ensureComplete()
var syms: List[Symbol] = Nil
Expand All @@ -99,6 +101,10 @@ object Scopes {
syms
}

/** Tests whether a predicate holds for at least one Symbol of this Scope. */
def exists(p: Symbol => Boolean)(implicit ctx: Context): Boolean = filter(p).isEmpty

/** Finds the first Symbol of this Scope satisfying a predicate, if any. */
def find(p: Symbol => Boolean)(implicit ctx: Context): Symbol = filter(p) match {
case sym :: _ => sym
case _ => NoSymbol
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/core/StdNames.scala
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,7 @@ object StdNames {
val isArray: N = "isArray"
val isDefinedAt: N = "isDefinedAt"
val isDefinedAtImpl: N = "$isDefinedAt"
val isDefined: N = "isDefined"
val isEmpty: N = "isEmpty"
val isInstanceOf_ : N = "isInstanceOf"
val java: N = "java"
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/TypeComparer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -624,7 +624,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
*/
def compareHkApply2(tp1: Type, tp2: HKApply, tycon2: Type, args2: List[Type]): Boolean = {
val tparams = tycon2.typeParams
if (tparams.isEmpty) return false // can happen for ill-typed programs, e.g. neg/tcpoly_overloaded.scala
if (tparams.isEmpty) return tp1.isRef(NothingClass) // can happen for ill-typed programs, e.g. neg/tcpoly_overloaded.scala

/** True if `tp1` and `tp2` have compatible type constructors and their
* corresponding arguments are subtypes relative to their variance (see `isSubArgs`).
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/TypeErasure.scala
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
// but potentially re-introduced by ResolveSuper, when we add
// forwarders to mixin methods.
// See doc comment for ElimByName for speculation how we could improve this.
else MethodType(Nil, Nil, eraseResult(rt))
else MethodType(Nil, Nil, eraseResult(sym.info.finalResultType))
case tp: PolyType =>
eraseResult(tp.resultType) match {
case rt: MethodType => rt
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3080,7 +3080,7 @@ object Types {
myRepr
}

override def toString = s"Skolem($hashCode)"
override def toString = s"Skolem()"
}

// ------------ Type variables ----------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ class ClassfileParser(
if (method) Flags.Method | methodTranslation.flags(jflags)
else fieldTranslation.flags(jflags)
val name = pool.getName(in.nextChar)
if (!(sflags is Flags.Private) || name == nme.CONSTRUCTOR || ctx.settings.optimise.value) {
if (!(sflags is Flags.Private) || name == nme.CONSTRUCTOR) {
val member = ctx.newSymbol(
getOwner(jflags), name, sflags, memberCompleter, coord = start)
getScope(jflags).enter(member)
Expand Down
4 changes: 3 additions & 1 deletion compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ class PlainPrinter(_ctx: Context) extends Printer {
case AndType(tp1, tp2) =>
homogenize(tp1) & homogenize(tp2)
case OrType(tp1, tp2) =>
homogenize(tp1) | homogenize(tp2)
if (tp1.classSymbol.id > tp2.classSymbol.id)
homogenize(tp1) | homogenize(tp2)
else homogenize(tp2) | homogenize(tp1)
case tp: SkolemType =>
homogenize(tp.info)
case tp: LazyRef =>
Expand Down
5 changes: 4 additions & 1 deletion compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,10 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
toTextTuple(args.init)
("implicit " provided isImplicit) ~ argStr ~ " => " ~ argText(args.last)
}
homogenize(tp) match {
val htp = homogenize(tp)
htp match {
case x: ConstantType if homogenizedView =>
return toText(x.widen)
case AppliedType(tycon, args) =>
val cls = tycon.typeSymbol
if (tycon.isRepeatedParam) return toTextLocal(args.head) ~ "*"
Expand Down
Loading