diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala index 04c4c2e9d4bc..6144f015ebd7 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala @@ -163,7 +163,7 @@ Standard-Section: "ASTs" TopLevelStat* BYNAMEtype underlying_Type PARAMtype Length binder_ASTref paramNum_Nat POLYtype Length result_Type NamesTypes - METHODtype Length result_Type NamesTypes // needed for refinements + methodType(_, _) Length result_Type NamesTypes // needed for refinements TYPELAMBDAtype Length result_Type NamesTypes // variance encoded in front of name: +/-/(nothing) SHAREDtype type_ASTRef NamesTypes = NameType* @@ -226,7 +226,7 @@ Standard Section: "Positions" Assoc* object TastyFormat { final val header = Array(0x5C, 0xA1, 0xAB, 0x1F) - val MajorVersion = 4 + val MajorVersion = 5 val MinorVersion = 0 /** Tags used to serialize names */ @@ -392,14 +392,28 @@ object TastyFormat { final val ANDtpt = 165 final val ORtype = 166 final val ORtpt = 167 - final val METHODtype = 168 - final val POLYtype = 169 - final val TYPELAMBDAtype = 170 - final val LAMBDAtpt = 171 - final val PARAMtype = 172 - final val ANNOTATION = 173 - final val TERMREFin = 174 - final val TYPEREFin = 175 + final val POLYtype = 168 + final val TYPELAMBDAtype = 169 + final val LAMBDAtpt = 170 + final val PARAMtype = 171 + final val ANNOTATION = 172 + final val TERMREFin = 173 + final val TYPEREFin = 174 + + // In binary: 101100EI + // I = implicit method type + // E = erased method type + final val METHODtype = 176 + final val IMPLICITMETHODtype = 177 + final val ERASEDMETHODtype = 178 + final val ERASEDIMPLICITMETHODtype = 179 + + def methodType(isImplicit: Boolean = false, isErased: Boolean = false) = { + val implicitOffset = if (isImplicit) 1 else 0 + val erasedOffset = if (isErased) 2 else 0 + METHODtype + implicitOffset + erasedOffset + } + final val HOLE = 255 final val firstSimpleTreeTag = UNITconst @@ -588,6 +602,9 @@ object TastyFormat { case BYNAMEtpt => "BYNAMEtpt" case POLYtype => "POLYtype" case METHODtype => "METHODtype" + case IMPLICITMETHODtype => "IMPLICITMETHODtype" + case ERASEDMETHODtype => "ERASEDMETHODtype" + case ERASEDIMPLICITMETHODtype => "ERASEDIMPLICITMETHODtype" case TYPELAMBDAtype => "TYPELAMBDAtype" case LAMBDAtpt => "LAMBDAtpt" case PARAMtype => "PARAMtype" diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala index 1d0ab3ac40e9..dbf563e7b2ac 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala @@ -84,7 +84,7 @@ class TastyPrinter(bytes: Array[Byte])(implicit ctx: Context) { } else if (tag >= firstNatASTTreeTag) { tag match { - case IDENT | IDENTtpt | SELECT | TERMREF | TYPEREF | SELFDEF => printName() + case IDENT | IDENTtpt | SELECT | SELECTtpt | TERMREF | TYPEREF | SELFDEF => printName() case _ => printNat() } printTree() diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index f9652f19a4d8..618130db3017 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -251,7 +251,7 @@ class TreePickler(pickler: TastyPickler) { case tpe: PolyType if richTypes => pickleMethodic(POLYtype, tpe) case tpe: MethodType if richTypes => - pickleMethodic(METHODtype, tpe) + pickleMethodic(methodType(isImplicit = tpe.isImplicitMethod, isErased = tpe.isErasedMethod), tpe) case tpe: ParamRef => assert(pickleParamRef(tpe), s"orphan parameter reference: $tpe") case tpe: LazyRef => diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 6046a162fd7e..981c53f667aa 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -287,6 +287,12 @@ class TreeUnpickler(reader: TastyReader, readMethodic(PolyType, _.toTypeName) case METHODtype => readMethodic(MethodType, _.toTermName) + case IMPLICITMETHODtype => + readMethodic(ImplicitMethodType, _.toTermName) + case ERASEDMETHODtype => + readMethodic(ErasedMethodType, _.toTermName) + case ERASEDIMPLICITMETHODtype => + readMethodic(ErasedImplicitMethodType, _.toTermName) case TYPELAMBDAtype => readMethodic(HKTypeLambda, _.toTypeName) case PARAMtype => diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 7e4d94dc1f93..3e1d661d2599 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -759,8 +759,8 @@ object Parsers { case Ident(name) if name != tpnme.WILDCARD && in.token == COLON => isValParamList = true funArgTypesRest( - typedFunParam(paramStart, name.toTermName), - () => typedFunParam(in.offset, ident())) + typedFunParam(paramStart, name.toTermName, imods), + () => typedFunParam(in.offset, ident(), imods)) case t => funArgTypesRest(t, funArgType) } @@ -800,9 +800,9 @@ object Parsers { } /** TypedFunParam ::= id ':' Type */ - def typedFunParam(start: Offset, name: TermName): Tree = atPos(start) { + def typedFunParam(start: Offset, name: TermName, mods: Modifiers = EmptyModifiers): Tree = atPos(start) { accept(COLON) - makeParameter(name, typ(), Modifiers(Param)) + makeParameter(name, typ(), mods | Param) } /** InfixType ::= RefinedType {id [nl] refinedType} diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 438b3ef9b279..eab055cb1fa4 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -777,7 +777,7 @@ class Typer extends Namer completeParams(params) val params1 = params.map(typedExpr(_).asInstanceOf[ValDef]) val resultTpt = typed(body) - val companion = if (isImplicit) ImplicitMethodType else MethodType + val companion = MethodType.maker(isImplicit = isImplicit, isErased = isErased) val mt = companion.fromSymbols(params1.map(_.symbol), resultTpt.tpe) if (mt.isParamDependent) ctx.error(i"$mt is an illegal function type because it has inter-parameter dependencies", tree.pos) diff --git a/compiler/test/dotty/tools/dotc/FromTastyTests.scala b/compiler/test/dotty/tools/dotc/FromTastyTests.scala index 0e0aa9d0edd2..1e4a1c2e25bb 100644 --- a/compiler/test/dotty/tools/dotc/FromTastyTests.scala +++ b/compiler/test/dotty/tools/dotc/FromTastyTests.scala @@ -46,6 +46,9 @@ class FromTastyTests extends ParallelTesting { // Type miss match after unpickling "hklub0.scala", + // Closure type miss match + "i4125.scala", + // Missing position "t1203a.scala", "t2260.scala", diff --git a/tests/pos/i4125.scala b/tests/pos/i4125.scala new file mode 100644 index 000000000000..9ef034ba27b8 --- /dev/null +++ b/tests/pos/i4125.scala @@ -0,0 +1,4 @@ +object Test { + def foo: (erased (x: Int, y: Int) => Int) = erased (x, y) => 1 + def bar: (erased implicit (x: Int, y: Int) => Int) = erased implicit (x, y) => 1 +} diff --git a/tests/pos/implicit-dep.scala b/tests/pos/implicit-dep.scala new file mode 100644 index 000000000000..778048f7acee --- /dev/null +++ b/tests/pos/implicit-dep.scala @@ -0,0 +1,9 @@ +trait HasT { + type T +} + +object Test { + + + def foo: implicit Int => implicit (g: HasT) => g.T = ??? +}