Skip to content

Commit 63cf4b6

Browse files
committed
Fix #5481: Follow opaque aliases when determining prototypes of functions
If the prototype of a function value is a synthetic opaque type alias, assume the alias type. If the alias type is a function type, this allows one to infer the parameter types of the function value.
1 parent 3a3d5a3 commit 63cf4b6

File tree

3 files changed

+29
-4
lines changed

3 files changed

+29
-4
lines changed

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

+8
Original file line numberDiff line numberDiff line change
@@ -1083,6 +1083,14 @@ object Types {
10831083
/** Like `dealiasKeepAnnots`, but keeps only refining annotations */
10841084
final def dealiasKeepRefiningAnnots(implicit ctx: Context): Type = dealias1(keepIfRefining)
10851085

1086+
/** If this is a synthetic opaque type, its opaque alias, otherwise the type itself */
1087+
final def followSyntheticOpaque(implicit ctx: Context): Type = this match {
1088+
case tp: TypeProxy if tp.typeSymbol.is(SyntheticOpaque) =>
1089+
val AndType(alias, _) = tp.superType
1090+
alias
1091+
case _ => this
1092+
}
1093+
10861094
/** The result of normalization using `tryNormalize`, or the type itself if
10871095
* tryNormlize yields NoType
10881096
*/

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

+3-4
Original file line numberDiff line numberDiff line change
@@ -728,13 +728,12 @@ class Typer extends Namer
728728
case _: WildcardType => untpd.TypeTree()
729729
case _ => untpd.TypeTree(tp)
730730
}
731-
pt.stripTypeVar match {
732-
case _ if defn.isNonDepFunctionType(pt) =>
731+
pt.stripTypeVar.dealias.followSyntheticOpaque match {
732+
case pt1 if defn.isNonDepFunctionType(pt1) =>
733733
// if expected parameter type(s) are wildcards, approximate from below.
734734
// if expected result type is a wildcard, approximate from above.
735735
// this can type the greatest set of admissible closures.
736-
val funType = pt.dealias
737-
(funType.argTypesLo.init, typeTree(funType.argTypesHi.last))
736+
(pt1.argTypesLo.init, typeTree(pt1.argTypesHi.last))
738737
case SAMType(sam @ MethodTpe(_, formals, restpe)) =>
739738
(formals,
740739
if (sam.isResultDependent)

tests/pos/i5481.scala

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
object TypeAlias {
2+
3+
type Set[A] = A => Boolean
4+
5+
object Set {
6+
def singleton[A](a: A): Set[A] = _ == a // Works
7+
}
8+
}
9+
10+
object OpaqueType {
11+
12+
opaque type Set[A] = A => Boolean
13+
14+
object Set {
15+
def singleton[A](a: A): Set[A] = _ == a // Does not compile
16+
def singleton0[A](a: A): Set[A] = (_: A) == a // Works
17+
}
18+
}

0 commit comments

Comments
 (0)