Skip to content

Commit

Permalink
Fix #269: Traverse original trees in Dependency
Browse files Browse the repository at this point in the history
Original type trees have to be traversed if present to correctly handle
dependencies specified in explicit, user-defined types that are expanded
by the compiler, in cases such as type projections.

The example `fuzzy-types` is undercompiling because the prefix
`FactoryProvider` is totally lost at `Usage` after typer. This is one of
these cases where Scalac is expanding types and not leaving any trace to
keep track of the original dependency.

`FactoryProvider.type#MyFactory#Product` becomes `foo.B with
foo.Nil#Product`, and therefore the type dependency traverser doesn't
see `FactoryProvider`. Traversing original type trees fixes the issue.
  • Loading branch information
jvican committed Mar 19, 2017
1 parent 7163446 commit 662e602
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 6 deletions.
10 changes: 9 additions & 1 deletion internal/compiler-bridge/src/main/scala/xsbt/Dependency.scala
Original file line number Diff line number Diff line change
Expand Up @@ -376,8 +376,16 @@ final class Dependency(val global: CallbackGlobal) extends LocateClassFile with

traverseTrees(body)

// In some cases (eg. macro annotations), `typeTree.tpe` may be null. See sbt/sbt#1593 and sbt/sbt#1655.
/* Original type trees have to be traversed because typer is very
* aggressive when expanding explicit user-defined types. For instance,
* `Foo#B` will be expanded to `C` and the dependency on `Foo` will be
* lost. This makes sure that we traverse all the original prefixes. */
case typeTree: TypeTree if !ignoredType(typeTree.tpe) =>
val original = typeTree.original
if (original != null && !inspectedOriginalTrees.contains(original)) {
traverse(original)
inspectedOriginalTrees.add(original)
}
addTypeDependencies(typeTree.tpe)
case m @ MacroExpansionOf(original) if inspectedOriginalTrees.add(original) =>
traverse(original)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,11 +188,10 @@ class ExtractUsedNames[GlobalType <: CallbackGlobal](val global: GlobalType) ext
usedNameInImportSelector(selector.name)
usedNameInImportSelector(selector.rename)
}
// TODO: figure out whether we should process the original tree or walk the type
// the argument for processing the original tree: we process what user wrote
// the argument for processing the type: we catch all transformations that typer applies
// to types but that might be a bad thing because it might expand aliases eagerly which
// not what we need
/* Original type trees have to be traversed because typer is very
* aggressive when expanding explicit user-defined types. For instance,
* `Foo#B` will be expanded to `C` and the dependency on `Foo` will be
* lost. This makes sure that we traverse all the original prefixes. */
case t: TypeTree if t.original != null =>
val original = t.original
if (!inspectedTypeTrees.contains(original)) {
Expand Down

0 comments on commit 662e602

Please sign in to comment.