Skip to content

Commit 9553980

Browse files
committed
Further fixes
- avoid forcing denotation's info in `matches` - deal with overloaded alternatives in assignType for TypeApply
1 parent 668a637 commit 9553980

File tree

4 files changed

+63
-56
lines changed

4 files changed

+63
-56
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,9 +1073,9 @@ object Denotations {
10731073
val d = signature.matchDegree(other.signature)
10741074
(// fast path: signatures are the same and neither denotation is a PolyType
10751075
// For polytypes, signatures alone do not tell us enough to be sure about matching.
1076-
d == Signature.FullMatch && !info.isInstanceOf[PolyType] && !other.info.isInstanceOf[PolyType]
1076+
d == Signature.FullMatch &&
1077+
!infoOrCompleter.isInstanceOf[PolyType] && !other.infoOrCompleter.isInstanceOf[PolyType]
10771078
||
1078-
// slow path
10791079
d >= Signature.ParamMatch && info.matches(other.info))
10801080
}
10811081

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

Lines changed: 52 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -381,65 +381,70 @@ trait TypeAssigner {
381381
}
382382

383383
def assignType(tree: untpd.TypeApply, fn: Tree, args: List[Tree])(implicit ctx: Context): TypeApply = {
384-
val ownType = fn.tpe.widen match {
384+
def fail = tree.withType(errorType(err.takesNoParamsStr(fn, "type "), tree.pos))
385+
fn.tpe.widen match {
385386
case pt: TypeLambda =>
386-
val paramNames = pt.paramNames
387-
if (hasNamedArg(args)) {
388-
val paramBoundsByName = paramNames.zip(pt.paramInfos).toMap
389-
390-
// Type arguments which are specified by name (immutable after this first loop)
391-
val namedArgMap = new mutable.HashMap[Name, Type]
392-
for (NamedArg(name, arg) <- args)
393-
if (namedArgMap.contains(name))
394-
ctx.error(DuplicateNamedTypeParameter(name), arg.pos)
395-
else if (!paramNames.contains(name))
396-
ctx.error(UndefinedNamedTypeParameter(name, paramNames), arg.pos)
397-
else
398-
namedArgMap(name) = arg.tpe
399-
400-
// Holds indexes of non-named typed arguments in paramNames
401-
val gapBuf = new mutable.ListBuffer[Int]
402-
def nextPoly(idx: Int) = {
403-
val newIndex = gapBuf.length
404-
gapBuf += idx
405-
// Re-index unassigned type arguments that remain after transformation
406-
pt.paramRefs(newIndex)
407-
}
387+
tree.withType {
388+
val paramNames = pt.paramNames
389+
if (hasNamedArg(args)) {
390+
val paramBoundsByName = paramNames.zip(pt.paramInfos).toMap
391+
392+
// Type arguments which are specified by name (immutable after this first loop)
393+
val namedArgMap = new mutable.HashMap[Name, Type]
394+
for (NamedArg(name, arg) <- args)
395+
if (namedArgMap.contains(name))
396+
ctx.error(DuplicateNamedTypeParameter(name), arg.pos)
397+
else if (!paramNames.contains(name))
398+
ctx.error(UndefinedNamedTypeParameter(name, paramNames), arg.pos)
399+
else
400+
namedArgMap(name) = arg.tpe
401+
402+
// Holds indexes of non-named typed arguments in paramNames
403+
val gapBuf = new mutable.ListBuffer[Int]
404+
def nextPoly(idx: Int) = {
405+
val newIndex = gapBuf.length
406+
gapBuf += idx
407+
// Re-index unassigned type arguments that remain after transformation
408+
pt.paramRefs(newIndex)
409+
}
408410

409-
// Type parameters after naming assignment, conserving paramNames order
410-
val normArgs: List[Type] = paramNames.zipWithIndex.map { case (pname, idx) =>
411-
namedArgMap.getOrElse(pname, nextPoly(idx))
412-
}
411+
// Type parameters after naming assignment, conserving paramNames order
412+
val normArgs: List[Type] = paramNames.zipWithIndex.map { case (pname, idx) =>
413+
namedArgMap.getOrElse(pname, nextPoly(idx))
414+
}
413415

414-
val transform = new TypeMap {
415-
def apply(t: Type) = t match {
416-
case TypeParamRef(`pt`, idx) => normArgs(idx)
417-
case _ => mapOver(t)
416+
val transform = new TypeMap {
417+
def apply(t: Type) = t match {
418+
case TypeParamRef(`pt`, idx) => normArgs(idx)
419+
case _ => mapOver(t)
420+
}
421+
}
422+
val resultType1 = transform(pt.resultType)
423+
if (gapBuf.isEmpty) resultType1
424+
else {
425+
val gaps = gapBuf.toList
426+
pt.derivedLambdaType(
427+
gaps.map(paramNames),
428+
gaps.map(idx => transform(pt.paramInfos(idx)).bounds),
429+
resultType1)
418430
}
419431
}
420-
val resultType1 = transform(pt.resultType)
421-
if (gapBuf.isEmpty) resultType1
422432
else {
423-
val gaps = gapBuf.toList
424-
pt.derivedLambdaType(
425-
gaps.map(paramNames),
426-
gaps.map(idx => transform(pt.paramInfos(idx)).bounds),
427-
resultType1)
433+
val argTypes = args.tpes
434+
if (sameLength(argTypes, paramNames)) pt.instantiate(argTypes)
435+
else wrongNumberOfTypeArgs(fn.tpe, pt.typeParams, args, tree.pos)
428436
}
429437
}
430-
else {
431-
val argTypes = args.tpes
432-
if (sameLength(argTypes, paramNames)) pt.instantiate(argTypes)
433-
else wrongNumberOfTypeArgs(fn.tpe, pt.typeParams, args, tree.pos)
434-
}
435438
case err: ErrorType =>
436-
err
439+
tree.withType(err)
440+
case ref: TermRef if ref.isOverloaded =>
441+
val disambiguated = ref.denot.suchThat(_.info.isInstanceOf[PolyType])
442+
if (disambiguated.exists) assignType(tree, fn.withType(ref.withDenot(disambiguated)), args)
443+
else fail
437444
case _ =>
438445
//println(i"bad type: $fn: ${fn.symbol} / ${fn.symbol.isType} / ${fn.symbol.info}") // DEBUG
439-
errorType(err.takesNoParamsStr(fn, "type "), tree.pos)
446+
fail
440447
}
441-
442-
tree.withType(ownType)
443448
}
444449

445450
def assignType(tree: untpd.Typed, tpt: Tree)(implicit ctx: Context): Typed =

tests/neg/i4819.scala

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,6 @@ trait Two[Y <: Foo] {
77
}
88

99
class Foo extends One[Foo] with Two[Foo] {
10-
concat(0) // OK
11-
12-
// TODO: This does not typecheck because the polymorphic overload is masked
13-
// (we merge the denotations for both overloads into one and always prefer
14-
// MethodType to PolyType, instead we should return a MultiDenotation). See #4819.
15-
concat[Int](0) // error (that should actually not be an error)
10+
concat(0) // error: ambiguous overload
11+
concat[Int](0) // OK
1612
}

tests/pos/i4819.scala

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ trait Two[Y <: Foo] {
77
}
88

99
class Foo extends One[Foo] with Two[Foo] {
10-
concat(0) // OK
10+
concat[Int](0) // OK
1111
// See also tests/neg/i4819.scala
1212
}
13+
14+
class Bar extends One[String] with Two[Foo] {
15+
val x: String = concat(0)
16+
val y = concat[Int](0)
17+
val z: Foo = concat(0)
18+
}

0 commit comments

Comments
 (0)