From 26c85649d1b94ee95fc431541798e9693765be4f Mon Sep 17 00:00:00 2001 From: Albert Chen Date: Tue, 29 Dec 2020 19:26:32 -0800 Subject: [PATCH 1/3] selectDynamic type parameters fix --- compiler/src/dotty/tools/dotc/typer/Applications.scala | 2 +- compiler/src/dotty/tools/dotc/typer/Dynamic.scala | 2 +- tests/pos/i10951.scala | 8 ++++++++ 3 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 tests/pos/i10951.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 10f770f6ce42..74d63631abfb 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -1076,7 +1076,7 @@ trait Applications extends Compatibility { case _ => } def tryDynamicTypeApply(): Tree = typedFn match { - case typedFn: Select if !pt.isInstanceOf[FunProto] => typedDynamicSelect(typedFn, typedArgs, pt) + case typedFn: Select if !pt.isInstanceOf[FunProto] => typedDynamicSelect(typedFn, tree.args, pt) case _ => tree.withType(TryDynamicCallType) } if (typedFn.tpe eq TryDynamicCallType) tryDynamicTypeApply() diff --git a/compiler/src/dotty/tools/dotc/typer/Dynamic.scala b/compiler/src/dotty/tools/dotc/typer/Dynamic.scala index 80c41bbe772f..9ee5b43f9c93 100644 --- a/compiler/src/dotty/tools/dotc/typer/Dynamic.scala +++ b/compiler/src/dotty/tools/dotc/typer/Dynamic.scala @@ -106,7 +106,7 @@ trait Dynamic { * Note: inner part of translation foo.bar(baz) = quux ~~> foo.selectDynamic(bar).update(baz, quux) is achieved * through an existing transformation of in typedAssign [foo.bar(baz) = quux ~~> foo.bar.update(baz, quux)]. */ - def typedDynamicSelect(tree: untpd.Select, targs: List[Tree], pt: Type)(using Context): Tree = + def typedDynamicSelect(tree: untpd.Select, targs: List[untpd.Tree], pt: Type)(using Context): Tree = typedApply(coreDynamic(tree.qualifier, nme.selectDynamic, tree.name, tree.span, targs), pt) /** Translate selection that does not typecheck according to the normal rules into a updateDynamic. diff --git a/tests/pos/i10951.scala b/tests/pos/i10951.scala new file mode 100644 index 000000000000..2520536a491c --- /dev/null +++ b/tests/pos/i10951.scala @@ -0,0 +1,8 @@ +import scala.language.dynamics + +object Dyn extends Dynamic: + def selectDynamic[T](name: String): Option[T] = None + +val a: Option[(Int, Int)] = Dyn.asdf[Tuple2[Int, Int]] +val b: Option[(Int, Int)] = Dyn.selectDynamic[(Int, Int)]("asdf") +val c: Option[(Int, Int)] = Dyn.asdf[(Int, Int)] From 04ea25cfe9c77f612964ba306f070ba058ee695c Mon Sep 17 00:00:00 2001 From: Albert Chen Date: Wed, 30 Dec 2020 23:46:47 -0800 Subject: [PATCH 2/3] add PreTypedTypeTree to memoize type checked trees --- compiler/src/dotty/tools/dotc/ast/untpd.scala | 6 ++++++ compiler/src/dotty/tools/dotc/typer/Applications.scala | 2 +- compiler/src/dotty/tools/dotc/typer/Typer.scala | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/ast/untpd.scala b/compiler/src/dotty/tools/dotc/ast/untpd.scala index b98d7df11221..81617fcdfb7f 100644 --- a/compiler/src/dotty/tools/dotc/ast/untpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/untpd.scala @@ -345,6 +345,12 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { def derivedTree(originalSym: Symbol)(using Context): tpd.Tree } + /** A type tree that memoizes the result of a typed tree. Used when + * typechecking selectDynamic calls to prevent typechecking type arguments + * multiple types. + */ + final class MemoizedTypeTree(val result: tpd.Tree)(implicit @constructorOnly src: SourceFile) extends TypeTree + /** Property key containing TypeTrees whose type is computed * from the symbol in this type. These type trees have marker trees * TypeRefOfSym or InfoOfSym as their originals. diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 74d63631abfb..5ff4df2b1839 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -1076,7 +1076,7 @@ trait Applications extends Compatibility { case _ => } def tryDynamicTypeApply(): Tree = typedFn match { - case typedFn: Select if !pt.isInstanceOf[FunProto] => typedDynamicSelect(typedFn, tree.args, pt) + case typedFn: Select if !pt.isInstanceOf[FunProto] => typedDynamicSelect(typedFn, typedArgs.map(untpd.MemoizedTypeTree(_)), pt) case _ => tree.withType(TryDynamicCallType) } if (typedFn.tpe eq TryDynamicCallType) tryDynamicTypeApply() diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 8b0034510bc6..ee3008edfefa 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1695,6 +1695,7 @@ class Typer extends Namer case None => errorTree(tree, "Something's wrong: missing original symbol for type tree") } + case tree: untpd.MemoizedTypeTree => tree.result case _ => tree.withType( if (isFullyDefined(pt, ForceDegree.flipBottom)) pt From 13624d5c29efcdddeb3b658cf98339b59aef74a5 Mon Sep 17 00:00:00 2001 From: Albert Chen Date: Sat, 2 Jan 2021 10:49:38 -0800 Subject: [PATCH 3/3] revert MemoizedTypeTree, use TypedSplice instead --- compiler/src/dotty/tools/dotc/ast/untpd.scala | 6 ------ compiler/src/dotty/tools/dotc/typer/Applications.scala | 2 +- compiler/src/dotty/tools/dotc/typer/Typer.scala | 1 - 3 files changed, 1 insertion(+), 8 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/untpd.scala b/compiler/src/dotty/tools/dotc/ast/untpd.scala index 81617fcdfb7f..b98d7df11221 100644 --- a/compiler/src/dotty/tools/dotc/ast/untpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/untpd.scala @@ -345,12 +345,6 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { def derivedTree(originalSym: Symbol)(using Context): tpd.Tree } - /** A type tree that memoizes the result of a typed tree. Used when - * typechecking selectDynamic calls to prevent typechecking type arguments - * multiple types. - */ - final class MemoizedTypeTree(val result: tpd.Tree)(implicit @constructorOnly src: SourceFile) extends TypeTree - /** Property key containing TypeTrees whose type is computed * from the symbol in this type. These type trees have marker trees * TypeRefOfSym or InfoOfSym as their originals. diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 5ff4df2b1839..89157ff7ee1b 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -1076,7 +1076,7 @@ trait Applications extends Compatibility { case _ => } def tryDynamicTypeApply(): Tree = typedFn match { - case typedFn: Select if !pt.isInstanceOf[FunProto] => typedDynamicSelect(typedFn, typedArgs.map(untpd.MemoizedTypeTree(_)), pt) + case typedFn: Select if !pt.isInstanceOf[FunProto] => typedDynamicSelect(typedFn, typedArgs.map(untpd.TypedSplice(_)), pt) case _ => tree.withType(TryDynamicCallType) } if (typedFn.tpe eq TryDynamicCallType) tryDynamicTypeApply() diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index ee3008edfefa..8b0034510bc6 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1695,7 +1695,6 @@ class Typer extends Namer case None => errorTree(tree, "Something's wrong: missing original symbol for type tree") } - case tree: untpd.MemoizedTypeTree => tree.result case _ => tree.withType( if (isFullyDefined(pt, ForceDegree.flipBottom)) pt