From 4b1f5daa63afc29d4d7f8c5959e56d2e8bc998e1 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 10 Nov 2016 15:29:01 +0100 Subject: Fix #1664: Refine isOuterRef condition We forgot the case where a hoistable method can still refer to free variables that have to be passed using outer pointers. Fixes #1664. --- src/dotty/tools/dotc/transform/ExplicitOuter.scala | 20 ++++++++++++-------- tests/pos/i1664.scala | 12 ++++++++++++ 2 files changed, 24 insertions(+), 8 deletions(-) create mode 100644 tests/pos/i1664.scala diff --git a/src/dotty/tools/dotc/transform/ExplicitOuter.scala b/src/dotty/tools/dotc/transform/ExplicitOuter.scala index 3f235dca7..3fec47e9f 100644 --- a/src/dotty/tools/dotc/transform/ExplicitOuter.scala +++ b/src/dotty/tools/dotc/transform/ExplicitOuter.scala @@ -226,14 +226,18 @@ object ExplicitOuter { case ref: TermRef => if (ref.prefix ne NoPrefix) !ref.symbol.isStatic && isOuterRef(ref.prefix) - else if (ref.symbol is Hoistable) - // ref.symbol will be placed in enclosing class scope by LambdaLift, so it might need - // an outer path then. - isOuterSym(ref.symbol.owner.enclosingClass) - else - // ref.symbol will get a proxy in immediately enclosing class. If this properly - // contains the current class, it needs an outer path. - ctx.owner.enclosingClass.owner.enclosingClass.isContainedIn(ref.symbol.owner) + else ( + (ref.symbol is Hoistable) && + // ref.symbol will be placed in enclosing class scope by LambdaLift, so it might need + // an outer path then. + isOuterSym(ref.symbol.owner.enclosingClass) + || + // If not hoistable, ref.symbol will get a proxy in immediately enclosing class. If this properly + // contains the current class, it needs an outer path. + // If the symbol is hoistable, it might have free variables for which the same + // reasoning applies. See pos/i1664.scala + ctx.owner.enclosingClass.owner.enclosingClass.isContainedIn(ref.symbol.owner) + ) case _ => false } def hasOuterPrefix(tp: Type) = tp match { diff --git a/tests/pos/i1664.scala b/tests/pos/i1664.scala new file mode 100644 index 000000000..39d8d606d --- /dev/null +++ b/tests/pos/i1664.scala @@ -0,0 +1,12 @@ +object test { + def f[a](x: a) = { + def print = x + class A { + def f() = { + class B { def h = print } + new B + } + f() + } + } +} -- cgit v1.2.3