Skip to content

Commit

Permalink
Fix #18649: Use loBound of param types when materializing a context f…
Browse files Browse the repository at this point in the history
…unction.

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.
  • Loading branch information
sjrd committed Oct 12, 2023
1 parent 1d0bc79 commit 242e68f
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 1 deletion.
8 changes: 8 additions & 0 deletions compiler/src/dotty/tools/dotc/transform/TreeChecker.scala
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,14 @@ object TreeChecker {
super.typedClassDef(cdef, cls)
}

override def typedValDef(vdef: untpd.ValDef, sym: Symbol)(using Context): Tree =
val tpdTree = super.typedValDef(vdef, sym)
vdef.tpt.tpe match
case _: ValueType => () // ok
case _: ExprType if sym.isOneOf(TermParamOrAccessor) => () // ok
case _ => assert(false, i"wrong type, expected a value type for ${sym.fullName}, but found: ${sym.info}")
tpdTree

override def typedDefDef(ddef: untpd.DefDef, sym: Symbol)(using Context): Tree =
def defParamss = ddef.paramss.filter(!_.isEmpty).nestedMap(_.symbol)
def layout(symss: List[List[Symbol]]): String =
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3242,7 +3242,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
val paramTypes = {
val hasWildcard = formals.exists(_.existsPart(_.isInstanceOf[WildcardType], StopAt.Static))
if hasWildcard then formals.map(_ => untpd.TypeTree())
else formals.map(untpd.TypeTree)
else formals.map(formal => untpd.TypeTree(formal.loBound)) // about loBound, see tests/pos/i18649.scala
}

val erasedParams = pt match {
Expand Down
7 changes: 7 additions & 0 deletions tests/pos/i18649.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
object Test:
// always inferred Nothing for `x`
def contextFunctionWildcardExplicit: ? ?=> String = x ?=> "foo"

// used to infer TYPEBOUNDS for the type of the argument
def contextFunctionWildcardInserted: ? ?=> String = "foo"
end Test

0 comments on commit 242e68f

Please sign in to comment.