From ad96b032a3d8d3e7e228f4b99b65ffa28bb64c83 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 3 Jan 2018 19:06:13 +0100 Subject: [PATCH 1/4] Fix #3736: Search all imports for language features --- .../src/dotty/tools/dotc/core/TypeOps.scala | 18 +++++++++--------- tests/pos/i3736.scala | 3 +++ 2 files changed, 12 insertions(+), 9 deletions(-) create mode 100644 tests/pos/i3736.scala diff --git a/compiler/src/dotty/tools/dotc/core/TypeOps.scala b/compiler/src/dotty/tools/dotc/core/TypeOps.scala index c940a0ec45fb..047a07b3fb82 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeOps.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeOps.scala @@ -292,16 +292,16 @@ trait TypeOps { this: Context => // TODO: Make standalone object. if (!sym.exists || (sym eq defn.LanguageModuleClass)) "" else toPrefix(sym.owner) + sym.name + "." def featureName = toPrefix(owner) + feature - def hasImport(implicit ctx: Context): Boolean = { - if (ctx.importInfo == null || (ctx.importInfo.site.widen.typeSymbol ne owner)) false - else if (ctx.importInfo.excluded.contains(feature)) false - else if (ctx.importInfo.originals.contains(feature)) true - else { - var c = ctx.outer - while (c.importInfo eq ctx.importInfo) c = c.outer - hasImport(c) + def hasImport(implicit ctx: Context): Boolean = + ctx.importInfo != null && { + ctx.importInfo.site.widen.typeSymbol == owner && + !ctx.importInfo.excluded.contains(feature) && + ctx.importInfo.originals.contains(feature) || { + var c = ctx.outer + while (c.importInfo eq ctx.importInfo) c = c.outer + hasImport(c) + } } - } def hasOption = ctx.base.settings.language.value exists (s => s == featureName || s == "_") hasImport(ctx.withPhase(ctx.typerPhase)) || hasOption } diff --git a/tests/pos/i3736.scala b/tests/pos/i3736.scala new file mode 100644 index 000000000000..3f859c29dc28 --- /dev/null +++ b/tests/pos/i3736.scala @@ -0,0 +1,3 @@ +import scala.language.dynamics +import scala.Nil +class Foo() extends Dynamic From 51498d27352b3c75a1563e65ee1bc302c3674a00 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Wed, 3 Jan 2018 11:29:58 +0100 Subject: [PATCH 2/4] Fix #3736: Fix owner checking logic --- compiler/src/dotty/tools/dotc/core/TypeOps.scala | 13 ++++++++----- tests/neg/i3736b.scala | 7 +++++++ 2 files changed, 15 insertions(+), 5 deletions(-) create mode 100644 tests/neg/i3736b.scala diff --git a/compiler/src/dotty/tools/dotc/core/TypeOps.scala b/compiler/src/dotty/tools/dotc/core/TypeOps.scala index 047a07b3fb82..cab35c6a096c 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeOps.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeOps.scala @@ -292,16 +292,19 @@ trait TypeOps { this: Context => // TODO: Make standalone object. if (!sym.exists || (sym eq defn.LanguageModuleClass)) "" else toPrefix(sym.owner) + sym.name + "." def featureName = toPrefix(owner) + feature - def hasImport(implicit ctx: Context): Boolean = - ctx.importInfo != null && { - ctx.importInfo.site.widen.typeSymbol == owner && - !ctx.importInfo.excluded.contains(feature) && - ctx.importInfo.originals.contains(feature) || { + def hasImport(implicit ctx: Context): Boolean = { + if (ctx.importInfo eq null) false + else { + val isImportOwner = ctx.importInfo.site.widen.typeSymbol eq owner + if (isImportOwner && ctx.importInfo.excluded.contains(feature)) false + else if (isImportOwner && ctx.importInfo.originals.contains(feature)) true + else { var c = ctx.outer while (c.importInfo eq ctx.importInfo) c = c.outer hasImport(c) } } + } def hasOption = ctx.base.settings.language.value exists (s => s == featureName || s == "_") hasImport(ctx.withPhase(ctx.typerPhase)) || hasOption } diff --git a/tests/neg/i3736b.scala b/tests/neg/i3736b.scala new file mode 100644 index 000000000000..adb3ce49bb88 --- /dev/null +++ b/tests/neg/i3736b.scala @@ -0,0 +1,7 @@ +import foo.dynamics + +class Foo() extends Dynamic // error: extension of type scala.Dynamic needs to be enabled + +package foo { + class dynamic +} From 895a47c278d6bbfc214068e81c6fb958e34b0bc3 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 4 Jan 2018 11:44:27 +0100 Subject: [PATCH 3/4] Fix logic and comment for hasImport --- compiler/src/dotty/tools/dotc/core/TypeOps.scala | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/TypeOps.scala b/compiler/src/dotty/tools/dotc/core/TypeOps.scala index cab35c6a096c..b0df2d7feec0 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeOps.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeOps.scala @@ -277,8 +277,11 @@ trait TypeOps { this: Context => // TODO: Make standalone object. * * import owner.feature * - * (the feature may be bunched with others, or renamed, but wildcard imports - * don't count). + * and there is no visible nested import that excludes the feature, as in + * + * import owner.{ feature => _ } + * + * The feature may be bunched with others, or renamed, but wildcard imports don't count. * * 2. The feature is enabled by a compiler option * @@ -296,8 +299,8 @@ trait TypeOps { this: Context => // TODO: Make standalone object. if (ctx.importInfo eq null) false else { val isImportOwner = ctx.importInfo.site.widen.typeSymbol eq owner - if (isImportOwner && ctx.importInfo.excluded.contains(feature)) false - else if (isImportOwner && ctx.importInfo.originals.contains(feature)) true + if (isImportOwner && ctx.importInfo.originals.contains(feature)) true + else if (isImportOwner && ctx.importInfo.excluded.contains(feature)) false else { var c = ctx.outer while (c.importInfo eq ctx.importInfo) c = c.outer From acc16caa9d545a976baa4b1e081b2f0ac4b5b85d Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 4 Jan 2018 11:51:49 +0100 Subject: [PATCH 4/4] Add test for renaming in hasImport --- tests/neg/dynamicNoImport.scala | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/neg/dynamicNoImport.scala b/tests/neg/dynamicNoImport.scala index c009d91a43d0..ca12706735fa 100644 --- a/tests/neg/dynamicNoImport.scala +++ b/tests/neg/dynamicNoImport.scala @@ -9,5 +9,10 @@ package A { class Foo extends scala.Dynamic // error trait Bar extends scala.Dynamic // error object Baz extends scala.Dynamic // error + + package C { + import scala.language.{ dynamics => d } + class Foo extends scala.Dynamic // OK + } } }