Skip to content

Commit 85d55e7

Browse files
authored
Fix #18649: Use loBound of param types when materializing a context function. (#18651)
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.
2 parents 98215d3 + 242e68f commit 85d55e7

File tree

3 files changed

+16
-1
lines changed

3 files changed

+16
-1
lines changed

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

+8
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,14 @@ object TreeChecker {
581581
super.typedClassDef(cdef, cls)
582582
}
583583

584+
override def typedValDef(vdef: untpd.ValDef, sym: Symbol)(using Context): Tree =
585+
val tpdTree = super.typedValDef(vdef, sym)
586+
vdef.tpt.tpe match
587+
case _: ValueType => () // ok
588+
case _: ExprType if sym.isOneOf(TermParamOrAccessor) => () // ok
589+
case _ => assert(false, i"wrong type, expected a value type for ${sym.fullName}, but found: ${sym.info}")
590+
tpdTree
591+
584592
override def typedDefDef(ddef: untpd.DefDef, sym: Symbol)(using Context): Tree =
585593
def defParamss = ddef.paramss.filter(!_.isEmpty).nestedMap(_.symbol)
586594
def layout(symss: List[List[Symbol]]): String =

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -3242,7 +3242,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
32423242
val paramTypes = {
32433243
val hasWildcard = formals.exists(_.existsPart(_.isInstanceOf[WildcardType], StopAt.Static))
32443244
if hasWildcard then formals.map(_ => untpd.TypeTree())
3245-
else formals.map(untpd.TypeTree)
3245+
else formals.map(formal => untpd.TypeTree(formal.loBound)) // about loBound, see tests/pos/i18649.scala
32463246
}
32473247

32483248
val erasedParams = pt match {

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)