diff --git a/internal/compiler-bridge/src/main/scala-2.11/xsbt/Compat.scala b/internal/compiler-bridge/src/main/scala-2.11/xsbt/Compat.scala index bd44abf44..dfc1836e6 100644 --- a/internal/compiler-bridge/src/main/scala-2.11/xsbt/Compat.scala +++ b/internal/compiler-bridge/src/main/scala-2.11/xsbt/Compat.scala @@ -21,6 +21,9 @@ abstract class Compat { import global._ protected def processOriginalTreeAttachment(in: Tree)(func: Tree => Unit): Unit = () + + protected def processSAMAttachment(f: Function)(addDependency: Symbol => Unit): Unit = + () } object Compat { // IR is renamed to Results diff --git a/internal/compiler-bridge/src/main/scala-2.12/xsbt/Compat.scala b/internal/compiler-bridge/src/main/scala-2.12/xsbt/Compat.scala index e570bae42..7564d17c8 100644 --- a/internal/compiler-bridge/src/main/scala-2.12/xsbt/Compat.scala +++ b/internal/compiler-bridge/src/main/scala-2.12/xsbt/Compat.scala @@ -24,6 +24,12 @@ abstract class Compat { protected def processOriginalTreeAttachment(in: Tree)(func: Tree => Unit): Unit = { Compat.OriginalTreeTraverser.Instance.traverseOriginal(in)(func) } + + protected def processSAMAttachment(f: Function)(addDependency: Symbol => Unit): Unit = { + f.attachments.get[SAMFunction].foreach(sam => { + addDependency(sam.samTp.typeSymbol) + }) + } } object Compat { // IR is renamed to Results diff --git a/internal/compiler-bridge/src/main/scala/xsbt/Dependency.scala b/internal/compiler-bridge/src/main/scala/xsbt/Dependency.scala index 4f22a72eb..c643105d4 100644 --- a/internal/compiler-bridge/src/main/scala/xsbt/Dependency.scala +++ b/internal/compiler-bridge/src/main/scala/xsbt/Dependency.scala @@ -475,6 +475,16 @@ final class Dependency(val global: CallbackGlobal) extends LocateClassFile with val sym = if (tree.symbol.isModule) tree.symbol.moduleClass else tree.symbol localToNonLocalClass.resolveNonLocal(sym) super.traverse(tree) + + case f: Function => + processSAMAttachment(f)(symbol => { + addDependency(symbol) + // Not using addInheritanceDependency as it would incorrectly classify dependency as non-local + // ref: https://github.com/scala/scala/pull/10617/files#r1415226169 + val from = resolveDependencySource + addClassDependency(_localInheritanceCache, processor.localInheritance, from, symbol) + }) + super.traverse(tree) case other => super.traverse(other) } } diff --git a/internal/compiler-bridge/src/main/scala_2.10/xsbt/Compat.scala b/internal/compiler-bridge/src/main/scala_2.10/xsbt/Compat.scala index 7ae6cc923..83093eb7a 100644 --- a/internal/compiler-bridge/src/main/scala_2.10/xsbt/Compat.scala +++ b/internal/compiler-bridge/src/main/scala_2.10/xsbt/Compat.scala @@ -147,6 +147,8 @@ abstract class Compat { } protected def processOriginalTreeAttachment(in: Tree)(func: Tree => Unit): Unit = () + protected def processSAMAttachment(f: Function)(addDependency: Symbol => Unit): Unit = + () } /** Defines compatibility utils for [[ZincCompiler]]. */ diff --git a/internal/compiler-bridge/src/main/scala_2.13/xsbt/Compat.scala b/internal/compiler-bridge/src/main/scala_2.13/xsbt/Compat.scala index 34c216dbf..81fdaaa2e 100644 --- a/internal/compiler-bridge/src/main/scala_2.13/xsbt/Compat.scala +++ b/internal/compiler-bridge/src/main/scala_2.13/xsbt/Compat.scala @@ -28,6 +28,12 @@ abstract class Compat { func(a.original) } } + + protected def processSAMAttachment(f: Function)(addDependency: Symbol => Unit): Unit = { + f.attachments.get[SAMFunction].foreach(sam => { + addDependency(sam.samTp.typeSymbol) + }) + } } object Compat { // IR is renamed to Results diff --git a/zinc/src/sbt-test/source-dependencies/sam-local-inheritance/A.scala b/zinc/src/sbt-test/source-dependencies/sam-local-inheritance/A.scala new file mode 100644 index 000000000..e50a0c5ee --- /dev/null +++ b/zinc/src/sbt-test/source-dependencies/sam-local-inheritance/A.scala @@ -0,0 +1,4 @@ + +trait A { + def foo(): Int +} \ No newline at end of file diff --git a/zinc/src/sbt-test/source-dependencies/sam-local-inheritance/B.scala b/zinc/src/sbt-test/source-dependencies/sam-local-inheritance/B.scala new file mode 100644 index 000000000..7d3d72b64 --- /dev/null +++ b/zinc/src/sbt-test/source-dependencies/sam-local-inheritance/B.scala @@ -0,0 +1,3 @@ +class B { + val f: A = () => 1 +} \ No newline at end of file diff --git a/zinc/src/sbt-test/source-dependencies/sam-local-inheritance/C.scala b/zinc/src/sbt-test/source-dependencies/sam-local-inheritance/C.scala new file mode 100644 index 000000000..51596c853 --- /dev/null +++ b/zinc/src/sbt-test/source-dependencies/sam-local-inheritance/C.scala @@ -0,0 +1 @@ +class C extends B \ No newline at end of file diff --git a/zinc/src/sbt-test/source-dependencies/sam-local-inheritance/changes/A.scala b/zinc/src/sbt-test/source-dependencies/sam-local-inheritance/changes/A.scala new file mode 100644 index 000000000..3efa750ed --- /dev/null +++ b/zinc/src/sbt-test/source-dependencies/sam-local-inheritance/changes/A.scala @@ -0,0 +1,3 @@ +trait A { + def foo(): AnyVal +} \ No newline at end of file diff --git a/zinc/src/sbt-test/source-dependencies/sam-local-inheritance/test b/zinc/src/sbt-test/source-dependencies/sam-local-inheritance/test new file mode 100644 index 000000000..f95948456 --- /dev/null +++ b/zinc/src/sbt-test/source-dependencies/sam-local-inheritance/test @@ -0,0 +1,13 @@ +> compile + +> checkRecompilations 0 A B C + +# change the SAM type +$ copy-file changes/A.scala A.scala + +> compile + +> checkIterations 3 +> checkRecompilations 1 A +# SAM type change does not affect C, hence C should not be recompiled +> checkRecompilations 2 B \ No newline at end of file diff --git a/zinc/src/sbt-test/source-dependencies/sam/A.scala b/zinc/src/sbt-test/source-dependencies/sam/A.scala new file mode 100644 index 000000000..e50a0c5ee --- /dev/null +++ b/zinc/src/sbt-test/source-dependencies/sam/A.scala @@ -0,0 +1,4 @@ + +trait A { + def foo(): Int +} \ No newline at end of file diff --git a/zinc/src/sbt-test/source-dependencies/sam/B.scala b/zinc/src/sbt-test/source-dependencies/sam/B.scala new file mode 100644 index 000000000..7d3d72b64 --- /dev/null +++ b/zinc/src/sbt-test/source-dependencies/sam/B.scala @@ -0,0 +1,3 @@ +class B { + val f: A = () => 1 +} \ No newline at end of file diff --git a/zinc/src/sbt-test/source-dependencies/sam/changes/A.scala b/zinc/src/sbt-test/source-dependencies/sam/changes/A.scala new file mode 100644 index 000000000..5cd6cb81e --- /dev/null +++ b/zinc/src/sbt-test/source-dependencies/sam/changes/A.scala @@ -0,0 +1,3 @@ +trait A { + def foo(): String +} \ No newline at end of file diff --git a/zinc/src/sbt-test/source-dependencies/sam/test b/zinc/src/sbt-test/source-dependencies/sam/test new file mode 100644 index 000000000..096cc9122 --- /dev/null +++ b/zinc/src/sbt-test/source-dependencies/sam/test @@ -0,0 +1,7 @@ +> compile + +# change the SAM type +$ copy-file changes/A.scala A.scala + +# Both A.scala and B.scala should be recompiled, producing a compile error +-> compile \ No newline at end of file