Skip to content

Commit

Permalink
Merge pull request #15376 from dotty-staging/fix-15372
Browse files Browse the repository at this point in the history
Handle unconstrained TypeVars when synthesizing ClassTags
  • Loading branch information
odersky authored Jun 12, 2022
2 parents 5015425 + 4548fab commit 5de1da3
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 16 deletions.
34 changes: 18 additions & 16 deletions compiler/src/dotty/tools/dotc/typer/Synthesizer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Types._, Flags._, Symbols._, Names._, StdNames._, Constants._
import TypeErasure.{erasure, hasStableErasure}
import Decorators._
import ProtoTypes._
import Inferencing.fullyDefinedType
import Inferencing.{fullyDefinedType, isFullyDefined}
import ast.untpd
import transform.SymUtils._
import transform.TypeUtils._
Expand All @@ -30,21 +30,23 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
val synthesizedClassTag: SpecialHandler = (formal, span) =>
formal.argInfos match
case arg :: Nil =>
fullyDefinedType(arg, "ClassTag argument", span) match
case defn.ArrayOf(elemTp) =>
val etag = typer.inferImplicitArg(defn.ClassTagClass.typeRef.appliedTo(elemTp), span)
if etag.tpe.isError then EmptyTreeNoError else withNoErrors(etag.select(nme.wrap))
case tp if hasStableErasure(tp) && !defn.isBottomClassAfterErasure(tp.typeSymbol) =>
val sym = tp.typeSymbol
val classTag = ref(defn.ClassTagModule)
val tag =
if defn.SpecialClassTagClasses.contains(sym) then
classTag.select(sym.name.toTermName)
else
val clsOfType = escapeJavaArray(erasure(tp))
classTag.select(nme.apply).appliedToType(tp).appliedTo(clsOf(clsOfType))
withNoErrors(tag.withSpan(span))
case tp => EmptyTreeNoError
if isFullyDefined(arg, ForceDegree.all) then
arg match
case defn.ArrayOf(elemTp) =>
val etag = typer.inferImplicitArg(defn.ClassTagClass.typeRef.appliedTo(elemTp), span)
if etag.tpe.isError then EmptyTreeNoError else withNoErrors(etag.select(nme.wrap))
case tp if hasStableErasure(tp) && !defn.isBottomClassAfterErasure(tp.typeSymbol) =>
val sym = tp.typeSymbol
val classTag = ref(defn.ClassTagModule)
val tag =
if defn.SpecialClassTagClasses.contains(sym) then
classTag.select(sym.name.toTermName)
else
val clsOfType = escapeJavaArray(erasure(tp))
classTag.select(nme.apply).appliedToType(tp).appliedTo(clsOf(clsOfType))
withNoErrors(tag.withSpan(span))
case tp => EmptyTreeNoError
else EmptyTreeNoError
case _ => EmptyTreeNoError
end synthesizedClassTag

Expand Down
8 changes: 8 additions & 0 deletions tests/neg/i15372.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import scala.reflect.ClassTag

class Test {
private def test[A](result: A)(implicit ct: ClassTag[A]): A = result

test(1, 2) -> Array() // error

}

0 comments on commit 5de1da3

Please sign in to comment.