File tree 3 files changed +41
-3
lines changed
compiler/src/dotty/tools/dotc/typer
3 files changed +41
-3
lines changed Original file line number Diff line number Diff line change @@ -28,13 +28,25 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
28
28
private type SpecialHandlers = List [(ClassSymbol , SpecialHandler )]
29
29
30
30
val synthesizedClassTag : SpecialHandler = (formal, span) =>
31
+ def instArg (tp : Type ): Type = tp.stripTypeVar match
32
+ // Special case to avoid instantiating `Int & S` to `Int & Nothing` in
33
+ // i16328.scala. The intersection comes from an earlier instantiation
34
+ // to an upper bound.
35
+ // The dual situation with unions is harder to trigger because lower
36
+ // bounds are usually widened during instantiation.
37
+ case tp : AndOrType if tp.tp1 =:= tp.tp2 =>
38
+ instArg(tp.tp1)
39
+ case _ =>
40
+ if isFullyDefined(tp, ForceDegree .all) then tp
41
+ else NoType // this happens in tests/neg/i15372.scala
42
+
31
43
val tag = formal.argInfos match
32
- case arg :: Nil if isFullyDefined(arg, ForceDegree .all) =>
33
- arg match
44
+ case arg :: Nil =>
45
+ instArg( arg) match
34
46
case defn.ArrayOf (elemTp) =>
35
47
val etag = typer.inferImplicitArg(defn.ClassTagClass .typeRef.appliedTo(elemTp), span)
36
48
if etag.tpe.isError then EmptyTree else etag.select(nme.wrap)
37
- case tp if hasStableErasure(tp) && ! defn.isBottomClassAfterErasure( tp.typeSymbol) =>
49
+ case tp if hasStableErasure(tp) && ! tp.isBottomTypeAfterErasure =>
38
50
val sym = tp.typeSymbol
39
51
val classTagModul = ref(defn.ClassTagModule )
40
52
if defn.SpecialClassTagClasses .contains(sym) then
Original file line number Diff line number Diff line change
1
+ import scala .reflect .ClassTag
2
+
3
+ @ main def Test =
4
+ val x : Array [? <: String ] = Array [Int & Nothing ]() // error: No ClassTag available for Int & Nothing
5
+ // (was: ClassCastException: [I cannot be cast to [Ljava.lang.String)
6
+ val y : Array [? <: Int ] = Array [String & Nothing ]() // error: No ClassTag available for String & Nothing
7
+ // (was: ClassCastException: [Lscala.runtime.Nothing$; cannot be cast to [I)
Original file line number Diff line number Diff line change
1
+ import scala .reflect .ClassTag
2
+
3
+ object Test {
4
+ def getParamType [T : ClassTag ](x : T => Int ): T = ???
5
+
6
+ def id [S ](x : S ): S = x
7
+
8
+ def main (args : Array [String ]) = {
9
+ // worked before
10
+ val a1 = getParamType((x : Int ) => x)
11
+ val a2 : Int = a1 // ensure that we actually got a ClassTag for the right type
12
+
13
+ // broken before
14
+ val b1 = id(getParamType((x : Int ) => x)) // was error
15
+ val b2 : Int = b1
16
+ val c1 = id(id(getParamType((x : Int ) => x))) // was error
17
+ val c2 : Int = c1
18
+ }
19
+ }
You can’t perform that action at this time.
0 commit comments