Skip to content

Commit 070527e

Browse files
committed
Merge branch 'master' of https://github.com/lampepfl/dotty
2 parents ac22316 + 7c589a3 commit 070527e

File tree

38 files changed

+286
-127
lines changed

38 files changed

+286
-127
lines changed

compiler/src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2207,7 +2207,9 @@ object SymDenotations {
22072207
if !myCompanion.exists then
22082208
ensureCompleted()
22092209
myCompanion
2210-
override def registeredCompanion_=(c: Symbol) = { myCompanion = c }
2210+
2211+
override def registeredCompanion_=(c: Symbol) =
2212+
myCompanion = c
22112213

22122214
private var myNestingLevel = -1
22132215

@@ -2458,6 +2460,7 @@ object SymDenotations {
24582460
|| owner.isRefinementClass
24592461
|| owner.is(Scala2x)
24602462
|| owner.unforcedDecls.contains(denot.name, denot.symbol)
2463+
|| (denot.is(Synthetic) && denot.is(ModuleClass) && stillValidInOwner(denot.companionClass))
24612464
|| denot.isSelfSym
24622465
|| denot.isLocalDummy)
24632466
catch case ex: StaleSymbol => false

compiler/src/dotty/tools/dotc/core/Types.scala

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5343,14 +5343,11 @@ object Types {
53435343
def isExpandingBounds: Boolean = expandingBounds
53445344

53455345
protected def expandBounds(tp: TypeBounds): Type =
5346-
if expandingBounds then tp
5347-
else {
5348-
val saved = expandingBounds
5349-
expandingBounds = true
5350-
val res = range(atVariance(-variance)(reapply(tp.lo)), reapply(tp.hi))
5351-
expandingBounds = saved
5352-
res
5353-
}
5346+
val saved = expandingBounds
5347+
expandingBounds = true
5348+
val res = range(atVariance(-variance)(reapply(tp.lo)), reapply(tp.hi))
5349+
expandingBounds = saved
5350+
res
53545351

53555352
/** Try to widen a named type to its info relative to given prefix `pre`, where possible.
53565353
* The possible cases are listed inline in the code.

compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -349,13 +349,19 @@ class ClassfileParser(
349349
val tag = sig(index); index += 1
350350
(tag: @switch) match {
351351
case 'L' =>
352-
def processInner(tp: Type): Type = tp match {
353-
case tp: TypeRef if !tp.symbol.owner.is(Flags.ModuleClass) =>
354-
TypeRef(processInner(tp.prefix.widen), tp.symbol.asType)
355-
case _ =>
356-
tp
357-
}
358-
def processClassType(tp: Type): Type = tp match {
352+
/** A type representation where inner classes become `A#B` instead of `A.this.B` (like with `typeRef`)
353+
*
354+
* Note: the symbol must not be nested in a generic class.
355+
*/
356+
def innerType(symbol: Symbol): Type =
357+
if symbol.is(Flags.Package) then
358+
symbol.thisType
359+
else if symbol.isType then
360+
TypeRef(innerType(symbol.owner), symbol)
361+
else
362+
throw new RuntimeException("unexpected term symbol " + symbol)
363+
364+
def processTypeArgs(tp: Type): Type = tp match {
359365
case tp: TypeRef =>
360366
if (sig(index) == '<') {
361367
accept('<')
@@ -388,13 +394,13 @@ class ClassfileParser(
388394
}
389395

390396
val classSym = classNameToSymbol(subName(c => c == ';' || c == '<'))
391-
val classTpe = if (classSym eq defn.ObjectClass) defn.FromJavaObjectType else classSym.typeRef
392-
var tpe = processClassType(processInner(classTpe))
397+
val classTpe = if (classSym eq defn.ObjectClass) defn.FromJavaObjectType else innerType(classSym)
398+
var tpe = processTypeArgs(classTpe)
393399
while (sig(index) == '.') {
394400
accept('.')
395401
val name = subName(c => c == ';' || c == '<' || c == '.').toTypeName
396-
val clazz = tpe.member(name).symbol
397-
tpe = processClassType(processInner(TypeRef(tpe, clazz)))
402+
val tp = tpe.select(name)
403+
tpe = processTypeArgs(tp)
398404
}
399405
accept(';')
400406
tpe
@@ -432,15 +438,15 @@ class ClassfileParser(
432438
paramtypes += {
433439
if isRepeatedParam(index) then
434440
index += 1
435-
val elemType = sig2type(tparams, skiptvs)
441+
val elemType = sig2type(tparams, skiptvs = false)
436442
// `ElimRepeated` is responsible for correctly erasing this.
437443
defn.RepeatedParamType.appliedTo(elemType)
438444
else
439-
sig2type(tparams, skiptvs)
445+
sig2type(tparams, skiptvs = false)
440446
}
441447

442448
index += 1
443-
val restype = sig2type(tparams, skiptvs)
449+
val restype = sig2type(tparams, skiptvs = false)
444450
JavaMethodType(paramnames.toList, paramtypes.toList, restype)
445451
case 'T' =>
446452
val n = subName(';'.==).toTypeName

compiler/src/dotty/tools/dotc/transform/Erasure.scala

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import typer.{NoChecking, LiftErased}
2121
import typer.Inliner
2222
import typer.ProtoTypes._
2323
import typer.ErrorReporting.errorTree
24+
import typer.Checking.checkValue
2425
import core.TypeErasure._
2526
import core.Decorators._
2627
import dotty.tools.dotc.ast.{tpd, untpd}
@@ -569,18 +570,6 @@ object Erasure {
569570

570571
/** Check that Java statics and packages can only be used in selections.
571572
*/
572-
private def checkValue(tree: Tree, proto: Type)(using Context): tree.type =
573-
if (!proto.isInstanceOf[SelectionProto] && !proto.isInstanceOf[ApplyingProto]) then
574-
checkValue(tree)
575-
tree
576-
577-
private def checkValue(tree: Tree)(using Context): Unit =
578-
val sym = tree.tpe.termSymbol
579-
if (sym is Flags.Package)
580-
|| (sym.isAllOf(Flags.JavaModule) && !ctx.isJava)
581-
then
582-
report.error(JavaSymbolIsNotAValue(sym), tree.srcPos)
583-
584573
private def checkNotErased(tree: Tree)(using Context): tree.type = {
585574
if (!ctx.mode.is(Mode.Type)) {
586575
if (isErased(tree))
@@ -644,7 +633,7 @@ object Erasure {
644633
super.typedLiteral(tree)
645634

646635
override def typedIdent(tree: untpd.Ident, pt: Type)(using Context): Tree =
647-
checkValue(checkNotErased(super.typedIdent(tree, pt)), pt)
636+
checkNotErased(super.typedIdent(tree, pt))
648637

649638
/** Type check select nodes, applying the following rewritings exhaustively
650639
* on selections `e.m`, where `OT` is the type of the owner of `m` and `ET`
@@ -772,7 +761,7 @@ object Erasure {
772761
}
773762
}
774763

775-
checkValue(checkNotErased(recur(qual1)), pt)
764+
checkNotErased(recur(qual1))
776765
}
777766

778767
override def typedThis(tree: untpd.This)(using Context): Tree =

compiler/src/dotty/tools/dotc/transform/Mixin.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ class Mixin extends MiniPhase with SymTransformer { thisPhase =>
258258
&& !wasOneOf(getter, Deferred)
259259
&& !getter.isConstExprFinalVal
260260
yield
261-
if (isCurrent(getter) || getter.name.is(ExpandedName)) {
261+
if (isInImplementingClass(getter) || getter.name.is(ExpandedName)) {
262262
val rhs =
263263
if (wasOneOf(getter, ParamAccessor))
264264
nextArgument()
@@ -271,6 +271,9 @@ class Mixin extends MiniPhase with SymTransformer { thisPhase =>
271271
// transformFollowing call is needed to make memoize & lazy vals run
272272
transformFollowing(DefDef(mkForwarderSym(getter.asTerm), rhs))
273273
}
274+
else if wasOneOf(getter, ParamAccessor) then
275+
// mixin parameter field is defined by an override; evaluate the argument and throw it away
276+
nextArgument()
274277
else EmptyTree
275278
}
276279

compiler/src/dotty/tools/dotc/transform/MixinOps.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class MixinOps(cls: ClassSymbol, thisPhase: DenotTransformer)(using Context) {
4242
/** Is `sym` a member of implementing class `cls`?
4343
* The test is performed at phase `thisPhase`.
4444
*/
45-
def isCurrent(sym: Symbol): Boolean =
45+
def isInImplementingClass(sym: Symbol): Boolean =
4646
atPhase(thisPhase) {
4747
cls.info.nonPrivateMember(sym.name).hasAltWith(_.symbol == sym)
4848
}
@@ -71,7 +71,7 @@ class MixinOps(cls: ClassSymbol, thisPhase: DenotTransformer)(using Context) {
7171
meth.is(Method, butNot = PrivateOrAccessorOrDeferred) &&
7272
(ctx.settings.mixinForwarderChoices.isTruthy || meth.owner.is(Scala2x) || needsDisambiguation || hasNonInterfaceDefinition ||
7373
generateJUnitForwarder || generateSerializationForwarder) &&
74-
isCurrent(meth)
74+
isInImplementingClass(meth)
7575
}
7676

7777
final val PrivateOrAccessor: FlagSet = Private | Accessor

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

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -509,14 +509,22 @@ trait Applications extends Compatibility {
509509
if (success) formals match {
510510
case formal :: formals1 =>
511511

512+
def checkNoVarArg(arg: Arg) =
513+
if !ctx.isAfterTyper && isVarArg(arg) then
514+
val addendum =
515+
if formal.isRepeatedParam then
516+
i"it is not the only argument to be passed to the corresponding repeated parameter $formal"
517+
else
518+
i"the corresponding parameter has type $formal which is not a repeated parameter type"
519+
fail(em"Sequence argument type annotation `*` cannot be used here:\n$addendum", arg)
520+
512521
/** Add result of typing argument `arg` against parameter type `formal`.
513522
* @return The remaining formal parameter types. If the method is parameter-dependent
514523
* this means substituting the actual argument type for the current formal parameter
515524
* in the remaining formal parameters.
516525
*/
517-
def addTyped(arg: Arg, formal: Type): List[Type] =
518-
if !ctx.isAfterTyper && isVarArg(arg) && !formal.isRepeatedParam then
519-
fail(i"Sequence argument type annotation `: _*` cannot be used here: the corresponding parameter has type $formal which is not a repeated parameter type", arg)
526+
def addTyped(arg: Arg): List[Type] =
527+
if !formal.isRepeatedParam then checkNoVarArg(arg)
520528
addArg(typedArg(arg, formal), formal)
521529
if methodType.isParamDependent && typeOfArg(arg).exists then
522530
// `typeOfArg(arg)` could be missing because the evaluation of `arg` produced type errors
@@ -553,31 +561,36 @@ trait Applications extends Compatibility {
553561
def implicitArg = implicitArgTree(formal, appPos.span)
554562

555563
if !defaultArg.isEmpty then
556-
matchArgs(args1, addTyped(treeToArg(defaultArg), formal), n + 1)
564+
matchArgs(args1, addTyped(treeToArg(defaultArg)), n + 1)
557565
else if methodType.isContextualMethod && ctx.mode.is(Mode.ImplicitsEnabled) then
558-
matchArgs(args1, addTyped(treeToArg(implicitArg), formal), n + 1)
566+
matchArgs(args1, addTyped(treeToArg(implicitArg)), n + 1)
559567
else
560568
missingArg(n)
561569
}
562570

563571
if (formal.isRepeatedParam)
564572
args match {
565573
case arg :: Nil if isVarArg(arg) =>
566-
addTyped(arg, formal)
574+
addTyped(arg)
567575
case (arg @ Typed(Literal(Constant(null)), _)) :: Nil if ctx.isAfterTyper =>
568-
addTyped(arg, formal)
576+
addTyped(arg)
569577
case _ =>
570578
val elemFormal = formal.widenExpr.argTypesLo.head
571579
val typedArgs =
572-
harmonic(harmonizeArgs, elemFormal)(args.map(typedArg(_, elemFormal)))
580+
harmonic(harmonizeArgs, elemFormal) {
581+
args.map { arg =>
582+
checkNoVarArg(arg)
583+
typedArg(arg, elemFormal)
584+
}
585+
}
573586
typedArgs.foreach(addArg(_, elemFormal))
574587
makeVarArg(args.length, elemFormal)
575588
}
576589
else args match {
577590
case EmptyTree :: args1 =>
578591
tryDefault(n, args1)
579592
case arg :: args1 =>
580-
matchArgs(args1, addTyped(arg, formal), n + 1)
593+
matchArgs(args1, addTyped(arg), n + 1)
581594
case nil =>
582595
tryDefault(n, args)
583596
}

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,21 @@ object Checking {
653653
|| to.isRef(defn.ObjectClass, skipRefined = false)
654654
then
655655
report.error(em"the result of an implicit conversion must be more specific than $to", pos)
656+
657+
def checkValue(tree: Tree)(using Context): Unit =
658+
val sym = tree.tpe.termSymbol
659+
if sym.is(Flags.Package) || sym.isAllOf(Flags.JavaModule) && !ctx.isJava then
660+
report.error(JavaSymbolIsNotAValue(sym), tree.srcPos)
661+
662+
def checkValue(tree: Tree, proto: Type)(using Context): tree.type =
663+
tree match
664+
case tree: RefTree
665+
if tree.name.isTermName
666+
&& !proto.isInstanceOf[SelectionProto]
667+
&& !proto.isInstanceOf[FunOrPolyProto] =>
668+
checkValue(tree)
669+
case _ =>
670+
tree
656671
}
657672

658673
trait Checking {

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

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,8 @@ class Typer extends Namer
158158
*/
159159
def qualifies(denot: Denotation): Boolean =
160160
reallyExists(denot)
161-
&& !(pt.isInstanceOf[UnapplySelectionProto] && denot.symbol.is(Method, butNot = Accessor))
161+
&& (!pt.isInstanceOf[UnapplySelectionProto]
162+
|| denot.hasAltWith(sd => !sd.symbol.is(Method, butNot = Accessor)))
162163
&& !denot.symbol.is(PackageClass)
163164

164165
/** Find the denotation of enclosing `name` in given context `ctx`.
@@ -499,7 +500,7 @@ class Typer extends Namer
499500
case _ =>
500501
tree.withType(ownType)
501502
val tree2 = toNotNullTermRef(tree1, pt)
502-
checkStableIdentPattern(tree2, pt)
503+
checkLegalValue(tree2, pt)
503504
tree2
504505

505506
def isLocalExtensionMethodRef: Boolean = rawType match
@@ -537,9 +538,12 @@ class Typer extends Namer
537538
errorTree(tree, MissingIdent(tree, kind, name))
538539
end typedIdent
539540

540-
/** Check that a stable identifier pattern is indeed stable (SLS 8.1.5)
541+
/** (1) If this reference is neither applied nor selected, check that it does
542+
* not refer to a package or Java companion object.
543+
* (2) Check that a stable identifier pattern is indeed stable (SLS 8.1.5)
541544
*/
542-
private def checkStableIdentPattern(tree: Tree, pt: Type)(using Context): Unit =
545+
private def checkLegalValue(tree: Tree, pt: Type)(using Context): Unit =
546+
checkValue(tree, pt)
543547
if ctx.mode.is(Mode.Pattern)
544548
&& !tree.isType
545549
&& !pt.isInstanceOf[ApplyingProto]
@@ -557,7 +561,7 @@ class Typer extends Namer
557561
if checkedType.exists then
558562
val select = toNotNullTermRef(assignType(tree, checkedType), pt)
559563
if selName.isTypeName then checkStable(qual.tpe, qual.srcPos, "type prefix")
560-
checkStableIdentPattern(select, pt)
564+
checkLegalValue(select, pt)
561565
ConstFold(select)
562566
else if couldInstantiateTypeVar(qual.tpe.widen) then
563567
// try again with more defined qualifier type
@@ -2343,7 +2347,7 @@ class Typer extends Namer
23432347
assert(imp.selectors.length == 1, imp)
23442348
val from = imp.selectors.head.imported
23452349
val sel = tryAlternatively
2346-
(typedIdent(from, WildcardType))
2350+
(typedIdent(from, AnySelectionProto))
23472351
(typedIdent(cpy.Ident(from)(from.name.toTypeName), WildcardType))
23482352

23492353
sel.tpe match
@@ -3696,8 +3700,12 @@ class Typer extends Namer
36963700
val Select(qual, nme.apply) = tree; @unchecked
36973701
val tycon = tree.tpe.widen.finalResultType.underlyingClassRef(refinementOK = false)
36983702
val tpt = qual match
3699-
case Ident(name) => cpy.Ident(qual)(name.toTypeName)
3700-
case Select(pre, name) => cpy.Select(qual)(pre, name.toTypeName)
3703+
case Ident(name) =>
3704+
cpy.Ident(qual)(name.toTypeName)
3705+
case Select(pre, name) =>
3706+
cpy.Select(qual)(pre, name.toTypeName)
3707+
case qual: This if qual.symbol.is(ModuleClass) =>
3708+
cpy.Ident(qual)(qual.symbol.name.sourceModuleName.toTypeName)
37013709
typed(
37023710
untpd.Select(
37033711
untpd.New(untpd.TypedSplice(tpt.withType(tycon))),

compiler/test/dotty/tools/AnnotationsTests.scala

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,20 @@ class AnnotationsTest:
2929
val arrayOfString = defn.ArrayType.appliedTo(List(defn.StringType))
3030

3131
atPhase(erasurePhase.next) {
32-
val annot = cls.getAnnotation(annotCls)
3332
// Even though we're forcing the annotation after erasure,
3433
// the typed trees should be unerased, so the type of
3534
// the annotation argument should be `arrayOfString` and
3635
// not a `JavaArrayType`.
36+
val annot = cls.getAnnotation(annotCls)
3737
val arg = annot.get.argument(0).get
38-
assert(arg.tpe.isInstanceOf[AppliedType] && arg.tpe =:= arrayOfString,
38+
39+
// If we run the type check after erasure, we will have
40+
// `Array[String] =:= Array[String]` being false.
41+
// The reason is that in `TypeComparer.compareAppliedType2` we have
42+
// `tycon2.typeParams == Nil` after erasure, thus always get false.
43+
val res = atPhase(typerPhase) { arrayOfString =:= arg.tpe }
44+
45+
assert(arg.tpe.isInstanceOf[AppliedType] && res,
3946
s"Argument $arg had type:\n${arg.tpe}\nbut expected type:\n$arrayOfString")
4047
}
4148
}

compiler/test/dotty/tools/dotc/BootstrappedOnlyCompilationTests.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class BootstrappedOnlyCompilationTests {
2828
compileFilesInDir("tests/pos-macros", defaultOptions),
2929
compileFilesInDir("tests/pos-custom-args/semanticdb", defaultOptions.and("-Xsemanticdb")),
3030
compileDir("tests/pos-special/i7592", defaultOptions.and("-Yretain-trees")),
31+
compileDir("tests/pos-special/i11331.1", defaultOptions),
3132
).checkCompile()
3233
}
3334

0 commit comments

Comments
 (0)