Skip to content

Commit

Permalink
Fix scala#18649: Use loBound of param types when materializing a cont…
Browse files Browse the repository at this point in the history
…ext 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.
  • Loading branch information
sjrd committed Oct 5, 2023
1 parent 1d0bc79 commit 3ba4ce1
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(Param | ParamAccessor) => () // 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 3ba4ce1

Please sign in to comment.