Skip to content

Commit 70ecf1a

Browse files
sjrdWojciechMazur
authored andcommitted
Fix #18649: Use loBound of param types when materializing a context function.
Since the param types come from type arguments to `ContextFunctionN[...]`, nothing prevents them a priori from being wildcard type params, i.e., `TypeBounds`. However, that is not a valid type to give to a concrete term param. We can arbitrarily choose any type that conforms to the bounds, which realistically means one of the two bounds. Since type inference already chooses the lower bound when explicitly writing the context function, we align and choose the lower bound when materializing it. [Cherry-picked 242e68f]
1 parent 517a604 commit 70ecf1a

File tree

3 files changed

+16
-1
lines changed

3 files changed

+16
-1
lines changed

Diff for: compiler/src/dotty/tools/dotc/transform/TreeChecker.scala

+8
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,14 @@ object TreeChecker {
571571
super.typedClassDef(cdef, cls)
572572
}
573573

574+
override def typedValDef(vdef: untpd.ValDef, sym: Symbol)(using Context): Tree =
575+
val tpdTree = super.typedValDef(vdef, sym)
576+
vdef.tpt.tpe match
577+
case _: ValueType => () // ok
578+
case _: ExprType if sym.isOneOf(TermParamOrAccessor) => () // ok
579+
case _ => assert(false, i"wrong type, expected a value type for ${sym.fullName}, but found: ${sym.info}")
580+
tpdTree
581+
574582
override def typedDefDef(ddef: untpd.DefDef, sym: Symbol)(using Context): Tree =
575583
def defParamss = ddef.paramss.filter(!_.isEmpty).nestedMap(_.symbol)
576584
def layout(symss: List[List[Symbol]]): String =

Diff for: compiler/src/dotty/tools/dotc/typer/Typer.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -3160,7 +3160,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
31603160
val paramTypes = {
31613161
val hasWildcard = formals.exists(_.existsPart(_.isInstanceOf[WildcardType], StopAt.Static))
31623162
if hasWildcard then formals.map(_ => untpd.TypeTree())
3163-
else formals.map(untpd.TypeTree)
3163+
else formals.map(formal => untpd.TypeTree(formal.loBound)) // about loBound, see tests/pos/i18649.scala
31643164
}
31653165

31663166
val erasedParams = pt match {

Diff for: tests/pos/i18649.scala

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
object Test:
2+
// always inferred Nothing for `x`
3+
def contextFunctionWildcardExplicit: ? ?=> String = x ?=> "foo"
4+
5+
// used to infer TYPEBOUNDS for the type of the argument
6+
def contextFunctionWildcardInserted: ? ?=> String = "foo"
7+
end Test

0 commit comments

Comments
 (0)