From 40d7506df2825dd2d1b608114e82faba8fb780f3 Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Wed, 17 Feb 2021 20:46:23 +0900 Subject: [PATCH 01/13] Move rule 1 logic to `canDirectlyPromote` --- .../tools/dotc/transform/init/Checking.scala | 36 ++++++++++++------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/init/Checking.scala b/compiler/src/dotty/tools/dotc/transform/init/Checking.scala index cc8f95b20e8c..c1d6a5d544c1 100644 --- a/compiler/src/dotty/tools/dotc/transform/init/Checking.scala +++ b/compiler/src/dotty/tools/dotc/transform/init/Checking.scala @@ -264,34 +264,44 @@ object Checking { val Summary(pots, effs) = expand(pot) val effs2 = pots.map(FieldAccess(_, field)(eff.source)) (effs2 ++ effs).toList.flatMap(check(_)) - } + /// Check if we can just directly promote a potential. + /// A potential can be (currently) directly promoted if and only if: + /// - `pot == this` and all fields of this are initialized, or + /// - `pot == Warm(C, outer)` where `outer` can be directly promoted. + private def canDirectlyPromote(pot: Potential)(using state: State): Boolean = + if (state.safePromoted.contains(pot)) true + else pot match { + case pot: ThisRef => + // If we have all fields initialized, then we can promote This to hot. + val classRef = state.thisClass.info.asInstanceOf[ClassInfo].appliedRef + classRef.fields.forall { denot => + val sym = denot.symbol + sym.isOneOf(Flags.Lazy | Flags.Deferred) || state.fieldsInited.contains(sym) + } + case Warm(cls, outer) => + canDirectlyPromote(outer) + case _ => false + } private def checkPromote(eff: Promote)(using state: State): Errors = if (state.safePromoted.contains(eff.potential)) Errors.empty else { val pot = eff.potential val errs = pot match { + case pot if canDirectlyPromote(pot) => + Errors.empty + case pot: ThisRef => - // If we have all fields initialized, then we can promote This to hot. - val classRef = state.thisClass.info.asInstanceOf[ClassInfo].appliedRef - val allFieldsInited = classRef.fields.forall { denot => - val sym = denot.symbol - sym.isOneOf(Flags.Lazy | Flags.Deferred) || state.fieldsInited.contains(sym) - } - if (allFieldsInited) - Errors.empty - else PromoteThis(pot, eff.source, state.path).toErrors case _: Cold => PromoteCold(eff.source, state.path).toErrors case pot @ Warm(cls, outer) => - val errors = state.test { checkPromote(Promote(outer)(eff.source)) } - if (errors.isEmpty) Errors.empty - else PromoteWarm(pot, eff.source, state.path).toErrors + // TODO: Implement Rule 2 + PromoteWarm(pot, eff.source, state.path).toErrors case Fun(pots, effs) => val errs1 = state.test { From 5af41fe8463cc901132be21846b762248a244b22 Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Wed, 17 Feb 2021 21:54:49 +0900 Subject: [PATCH 02/13] WIP: Rule 2 implementation --- .../tools/dotc/transform/init/Checking.scala | 37 ++++++++++++++++++- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/init/Checking.scala b/compiler/src/dotty/tools/dotc/transform/init/Checking.scala index c1d6a5d544c1..172b86af7a31 100644 --- a/compiler/src/dotty/tools/dotc/transform/init/Checking.scala +++ b/compiler/src/dotty/tools/dotc/transform/init/Checking.scala @@ -285,6 +285,40 @@ object Checking { case _ => false } + /// Check the Promotion of a Warm object, according to "Rule 2": + // + // Rule 2: Promote(pot) + // + // for all concrete methods `m` of D + // pot.m!, Promote(pot.m) + // + // for all concrete fields `f` of D + // Promote(pot.f) + // + // for all inner classes `F` of D + // Warm[F, pot].init!, Promote(Warm[F, pot]) + private def checkPromoteWarm(warm: Warm, eff: Effect)(using state: State): Errors = + val Warm(cls, outer) = warm + // Errors.empty + val classRef = cls.info.asInstanceOf[ClassInfo].appliedRef + // All members of class must be promotable. + val memberErrs = classRef.allMembers.flatMap { denot => + val sym = denot.symbol + val summary = warm.toPots.select(sym, warm.source, true) + (summary.effs ++ summary.pots.map(Promote(_)(warm.source)).toList) + }.flatMap(check(_)) + + // All inner classes of classRef must be promotable. + // TODO: Implement this + val innerClassesErrs = Errors.empty + + val errs = memberErrs ++ innerClassesErrs + if errs.isEmpty then { + Errors.empty + } else { + UnsafePromotion(warm, eff.source, state.path, errs.toList).toErrors + } + private def checkPromote(eff: Promote)(using state: State): Errors = if (state.safePromoted.contains(eff.potential)) Errors.empty else { @@ -300,8 +334,7 @@ object Checking { PromoteCold(eff.source, state.path).toErrors case pot @ Warm(cls, outer) => - // TODO: Implement Rule 2 - PromoteWarm(pot, eff.source, state.path).toErrors + checkPromoteWarm(pot, eff) case Fun(pots, effs) => val errs1 = state.test { From 35b796b17fc0bb3c4c3981b8acbb26149e6d5896 Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Thu, 25 Feb 2021 16:07:39 +0900 Subject: [PATCH 03/13] Add checks for member classes --- .../tools/dotc/transform/init/Checking.scala | 34 ++++++++++++++----- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/init/Checking.scala b/compiler/src/dotty/tools/dotc/transform/init/Checking.scala index 172b86af7a31..00b4166a4234 100644 --- a/compiler/src/dotty/tools/dotc/transform/init/Checking.scala +++ b/compiler/src/dotty/tools/dotc/transform/init/Checking.scala @@ -299,20 +299,36 @@ object Checking { // Warm[F, pot].init!, Promote(Warm[F, pot]) private def checkPromoteWarm(warm: Warm, eff: Effect)(using state: State): Errors = val Warm(cls, outer) = warm + val source = eff.source // Errors.empty val classRef = cls.info.asInstanceOf[ClassInfo].appliedRef // All members of class must be promotable. - val memberErrs = classRef.allMembers.flatMap { denot => - val sym = denot.symbol - val summary = warm.toPots.select(sym, warm.source, true) - (summary.effs ++ summary.pots.map(Promote(_)(warm.source)).toList) - }.flatMap(check(_)) + val buffer = new mutable.ArrayBuffer[Effect] + val excludedFlags = Flags.Deferred | Flags.Private | Flags.Protected + + classRef.fields.foreach { denot => + val f = denot.symbol + if !f.isOneOf(excludedFlags) && f.hasSource then + buffer += Promote(FieldReturn(warm, f)(source))(source) + buffer += FieldAccess(warm, f)(source) + } + + classRef.membersBasedOnFlags(Flags.Method, Flags.Deferred).foreach { denot => + val m = denot.symbol + if !m.isConstructor && m.hasSource && !theEnv.canIgnoreMethod(m) then + buffer += MethodCall(warm, m)(source) + buffer += Promote(MethodReturn(warm, m)(source))(source) + } - // All inner classes of classRef must be promotable. - // TODO: Implement this - val innerClassesErrs = Errors.empty + classRef.memberClasses.foreach { denot => + val cls = denot.symbol.asClass + if cls.hasSource then + val potInner = Potentials.asSeenFrom(Warm(cls, ThisRef()(source))(source), warm) + buffer += MethodCall(potInner, cls.primaryConstructor)(source) + buffer += Promote(potInner)(source) + } - val errs = memberErrs ++ innerClassesErrs + val errs = buffer.toList.flatMap(eff => check(eff)) if errs.isEmpty then { Errors.empty } else { From 1874233286b681fdbeded6b4ecedbbb9a971736f Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Thu, 25 Feb 2021 16:55:17 +0900 Subject: [PATCH 04/13] Add expand logic to canDirectlyPromote --- .../src/dotty/tools/dotc/transform/init/Checking.scala | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/init/Checking.scala b/compiler/src/dotty/tools/dotc/transform/init/Checking.scala index 00b4166a4234..e383a4c839e9 100644 --- a/compiler/src/dotty/tools/dotc/transform/init/Checking.scala +++ b/compiler/src/dotty/tools/dotc/transform/init/Checking.scala @@ -270,7 +270,7 @@ object Checking { /// A potential can be (currently) directly promoted if and only if: /// - `pot == this` and all fields of this are initialized, or /// - `pot == Warm(C, outer)` where `outer` can be directly promoted. - private def canDirectlyPromote(pot: Potential)(using state: State): Boolean = + private def canDirectlyPromote(pot: Potential)(using state: State): Boolean = trace("checking direct promotion of " + pot.show, init) { if (state.safePromoted.contains(pot)) true else pot match { case pot: ThisRef => @@ -282,8 +282,13 @@ object Checking { } case Warm(cls, outer) => canDirectlyPromote(outer) - case _ => false + case _ => + val summary = expand(pot) + if (!summary.effs.isEmpty) + false // max depth of expansion reached + else summary.pots.forall(canDirectlyPromote) } + } /// Check the Promotion of a Warm object, according to "Rule 2": // From dffcc6e8d96aecc98be0f2feb6dfab7b3130ec12 Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Thu, 25 Feb 2021 16:56:08 +0900 Subject: [PATCH 05/13] Add more tests --- tests/init/pos/early-promote.scala | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 tests/init/pos/early-promote.scala diff --git a/tests/init/pos/early-promote.scala b/tests/init/pos/early-promote.scala new file mode 100644 index 000000000000..fe4d73bff16e --- /dev/null +++ b/tests/init/pos/early-promote.scala @@ -0,0 +1,29 @@ +class Y { + class X { + class B { + def g = f + def g2 = n + } + val f = 42 + val b = new B // warm(B, X.this) + } + + val n = 10 + val x = new X + List(x.b) // unsafe promotion + +} + +class A { // checking A + class B { + def bf = 42 + class C { + def x = bf // uses outer[C], but never outer[B] + } + List((new C).x) + def c = new C + } + val b = new B() + List(b) // Direct promotion works here + val af = 42 +} From e2b758e817fb9a9420a5665521ba675ceaeda0dc Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Tue, 9 Mar 2021 16:07:57 +0900 Subject: [PATCH 06/13] Mitigate infinite recursion on canDirectlyPromote --- .../src/dotty/tools/dotc/transform/init/Checking.scala | 6 ++++-- tests/init/pos/early-promote.scala | 9 +++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/init/Checking.scala b/compiler/src/dotty/tools/dotc/transform/init/Checking.scala index e383a4c839e9..f5996595d341 100644 --- a/compiler/src/dotty/tools/dotc/transform/init/Checking.scala +++ b/compiler/src/dotty/tools/dotc/transform/init/Checking.scala @@ -270,8 +270,10 @@ object Checking { /// A potential can be (currently) directly promoted if and only if: /// - `pot == this` and all fields of this are initialized, or /// - `pot == Warm(C, outer)` where `outer` can be directly promoted. - private def canDirectlyPromote(pot: Potential)(using state: State): Boolean = trace("checking direct promotion of " + pot.show, init) { + private def canDirectlyPromote(pot: Potential, visited: Set[Potential] = Set.empty)(using state: State): Boolean = trace("checking direct promotion of " + pot.show, init) { if (state.safePromoted.contains(pot)) true + // If this potential's promotion depends on itself, we cannot directly promote it. + else if (visited.contains(pot)) false else pot match { case pot: ThisRef => // If we have all fields initialized, then we can promote This to hot. @@ -286,7 +288,7 @@ object Checking { val summary = expand(pot) if (!summary.effs.isEmpty) false // max depth of expansion reached - else summary.pots.forall(canDirectlyPromote) + else summary.pots.forall(canDirectlyPromote(_, visited + pot)) } } diff --git a/tests/init/pos/early-promote.scala b/tests/init/pos/early-promote.scala index fe4d73bff16e..02b85c3f4e8d 100644 --- a/tests/init/pos/early-promote.scala +++ b/tests/init/pos/early-promote.scala @@ -27,3 +27,12 @@ class A { // checking A List(b) // Direct promotion works here val af = 42 } + +class RecursiveF { + val a = f + def f: RecursiveF = f + class B(x: Int) + + println(new a.B(5)) + val n = 10 +} From fb48e37bae02ca0e8ed056705f38372c22bd6713 Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Tue, 9 Mar 2021 16:11:16 +0900 Subject: [PATCH 07/13] Fix comment style --- .../tools/dotc/transform/init/Checking.scala | 36 ++++++++++--------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/init/Checking.scala b/compiler/src/dotty/tools/dotc/transform/init/Checking.scala index f5996595d341..e36fb0e2bc08 100644 --- a/compiler/src/dotty/tools/dotc/transform/init/Checking.scala +++ b/compiler/src/dotty/tools/dotc/transform/init/Checking.scala @@ -266,10 +266,12 @@ object Checking { (effs2 ++ effs).toList.flatMap(check(_)) } - /// Check if we can just directly promote a potential. - /// A potential can be (currently) directly promoted if and only if: - /// - `pot == this` and all fields of this are initialized, or - /// - `pot == Warm(C, outer)` where `outer` can be directly promoted. + /** + * Check if we can just directly promote a potential. + * A potential can be (currently) directly promoted if and only if: + * - `pot == this` and all fields of this are initialized, or + * - `pot == Warm(C, outer)` where `outer` can be directly promoted. + */ private def canDirectlyPromote(pot: Potential, visited: Set[Potential] = Set.empty)(using state: State): Boolean = trace("checking direct promotion of " + pot.show, init) { if (state.safePromoted.contains(pot)) true // If this potential's promotion depends on itself, we cannot directly promote it. @@ -292,18 +294,20 @@ object Checking { } } - /// Check the Promotion of a Warm object, according to "Rule 2": - // - // Rule 2: Promote(pot) - // - // for all concrete methods `m` of D - // pot.m!, Promote(pot.m) - // - // for all concrete fields `f` of D - // Promote(pot.f) - // - // for all inner classes `F` of D - // Warm[F, pot].init!, Promote(Warm[F, pot]) + /** + * Check the Promotion of a Warm object, according to "Rule 2": + * + * Rule 2: Promote(pot) + * + * for all concrete methods `m` of D + * pot.m!, Promote(pot.m) + * + * for all concrete fields `f` of D + * Promote(pot.f) + * + * for all inner classes `F` of D + * Warm[F, pot].init!, Promote(Warm[F, pot]) + */ private def checkPromoteWarm(warm: Warm, eff: Effect)(using state: State): Errors = val Warm(cls, outer) = warm val source = eff.source From ccbd3eb345a9a3cb69552c52fb34b63443d3b9a0 Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Tue, 9 Mar 2021 16:13:20 +0900 Subject: [PATCH 08/13] Match Scala 3 style --- compiler/src/dotty/tools/dotc/transform/init/Checking.scala | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/init/Checking.scala b/compiler/src/dotty/tools/dotc/transform/init/Checking.scala index e36fb0e2bc08..f8d085ce6213 100644 --- a/compiler/src/dotty/tools/dotc/transform/init/Checking.scala +++ b/compiler/src/dotty/tools/dotc/transform/init/Checking.scala @@ -340,11 +340,10 @@ object Checking { } val errs = buffer.toList.flatMap(eff => check(eff)) - if errs.isEmpty then { + if errs.isEmpty then Errors.empty - } else { + else UnsafePromotion(warm, eff.source, state.path, errs.toList).toErrors - } private def checkPromote(eff: Promote)(using state: State): Errors = if (state.safePromoted.contains(eff.potential)) Errors.empty From e7e6e7cabe00600c69ab46940b49015830f5f05c Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Thu, 11 Mar 2021 16:48:37 +0900 Subject: [PATCH 09/13] Fix nit on comment indentation --- .../tools/dotc/transform/init/Checking.scala | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/init/Checking.scala b/compiler/src/dotty/tools/dotc/transform/init/Checking.scala index f8d085ce6213..c3efd8a0ad58 100644 --- a/compiler/src/dotty/tools/dotc/transform/init/Checking.scala +++ b/compiler/src/dotty/tools/dotc/transform/init/Checking.scala @@ -267,11 +267,11 @@ object Checking { } /** - * Check if we can just directly promote a potential. - * A potential can be (currently) directly promoted if and only if: - * - `pot == this` and all fields of this are initialized, or - * - `pot == Warm(C, outer)` where `outer` can be directly promoted. - */ + * Check if we can just directly promote a potential. + * A potential can be (currently) directly promoted if and only if: + * - `pot == this` and all fields of this are initialized, or + * - `pot == Warm(C, outer)` where `outer` can be directly promoted. + */ private def canDirectlyPromote(pot: Potential, visited: Set[Potential] = Set.empty)(using state: State): Boolean = trace("checking direct promotion of " + pot.show, init) { if (state.safePromoted.contains(pot)) true // If this potential's promotion depends on itself, we cannot directly promote it. @@ -295,19 +295,19 @@ object Checking { } /** - * Check the Promotion of a Warm object, according to "Rule 2": - * - * Rule 2: Promote(pot) - * - * for all concrete methods `m` of D - * pot.m!, Promote(pot.m) - * - * for all concrete fields `f` of D - * Promote(pot.f) - * - * for all inner classes `F` of D - * Warm[F, pot].init!, Promote(Warm[F, pot]) - */ + * Check the Promotion of a Warm object, according to "Rule 2": + * + * Rule 2: Promote(pot) + * + * for all concrete methods `m` of D + * pot.m!, Promote(pot.m) + * + * for all concrete fields `f` of D + * Promote(pot.f) + * + * for all inner classes `F` of D + * Warm[F, pot].init!, Promote(Warm[F, pot]) + */ private def checkPromoteWarm(warm: Warm, eff: Effect)(using state: State): Errors = val Warm(cls, outer) = warm val source = eff.source From 270a8865011744b27c0602eb6345828ba59516a0 Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Thu, 18 Mar 2021 17:41:24 +0900 Subject: [PATCH 10/13] Move directlyPromote check up --- .../tools/dotc/transform/init/Checking.scala | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/init/Checking.scala b/compiler/src/dotty/tools/dotc/transform/init/Checking.scala index c3efd8a0ad58..70189899a452 100644 --- a/compiler/src/dotty/tools/dotc/transform/init/Checking.scala +++ b/compiler/src/dotty/tools/dotc/transform/init/Checking.scala @@ -349,39 +349,39 @@ object Checking { if (state.safePromoted.contains(eff.potential)) Errors.empty else { val pot = eff.potential - val errs = pot match { - case pot if canDirectlyPromote(pot) => + val errs = + if canDirectlyPromote(pot) then Errors.empty + else pot match { + case pot: ThisRef => + PromoteThis(pot, eff.source, state.path).toErrors - case pot: ThisRef => - PromoteThis(pot, eff.source, state.path).toErrors - - case _: Cold => - PromoteCold(eff.source, state.path).toErrors + case _: Cold => + PromoteCold(eff.source, state.path).toErrors - case pot @ Warm(cls, outer) => - checkPromoteWarm(pot, eff) + case pot @ Warm(cls, outer) => + checkPromoteWarm(pot, eff) - case Fun(pots, effs) => - val errs1 = state.test { - effs.toList.flatMap(check(_)) - } - val errs2 = state.test { - pots.toList.flatMap { pot => - checkPromote(Promote(pot)(eff.source)) + case Fun(pots, effs) => + val errs1 = state.test { + effs.toList.flatMap(check(_)) + } + val errs2 = state.test { + pots.toList.flatMap { pot => + checkPromote(Promote(pot)(eff.source)) + } } - } - if (errs1.nonEmpty || errs2.nonEmpty) - UnsafePromotion(pot, eff.source, state.path, errs1 ++ errs2).toErrors - else - Errors.empty + if (errs1.nonEmpty || errs2.nonEmpty) + UnsafePromotion(pot, eff.source, state.path, errs1 ++ errs2).toErrors + else + Errors.empty - case pot => - val Summary(pots, effs) = expand(pot) - val effs2 = pots.map(Promote(_)(eff.source)) - (effs2 ++ effs).toList.flatMap(check(_)) - } + case pot => + val Summary(pots, effs) = expand(pot) + val effs2 = pots.map(Promote(_)(eff.source)) + (effs2 ++ effs).toList.flatMap(check(_)) + } // If we can safely promote, then we don't need to check again if (errs.isEmpty) state.safePromoted += pot From 259a2ab15ca7a800ab9acbf881996d541414d4bf Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Thu, 18 Mar 2021 19:15:47 +0900 Subject: [PATCH 11/13] Fix init tests --- tests/init/neg/inner1.scala | 2 +- tests/init/neg/inner17.scala | 2 +- tests/init/neg/inner19.scala | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/init/neg/inner1.scala b/tests/init/neg/inner1.scala index bef2fd2d159e..d39c3ba2ac77 100644 --- a/tests/init/neg/inner1.scala +++ b/tests/init/neg/inner1.scala @@ -4,7 +4,7 @@ class Foo { val list = List(1, 2, 3) // error, as Inner access `this.list` val inner: Inner = new this.Inner // ok, `list` is instantiated - lib.escape(inner) // error + lib.escape(inner) // ok, can promote inner early val name = "good" diff --git a/tests/init/neg/inner17.scala b/tests/init/neg/inner17.scala index 441ed02767b3..756278cd5130 100644 --- a/tests/init/neg/inner17.scala +++ b/tests/init/neg/inner17.scala @@ -5,7 +5,7 @@ class A { val a = f } - println(new B) // error + println(new B) // OK, can promote B early } class C extends A { diff --git a/tests/init/neg/inner19.scala b/tests/init/neg/inner19.scala index 2089f777dc52..2e502eddc24c 100644 --- a/tests/init/neg/inner19.scala +++ b/tests/init/neg/inner19.scala @@ -14,6 +14,6 @@ class A { class B extends A { println((new O.B).f) - O.C(4) // error - override val n = 50 // error + O.C(4) + override val n = 50 // error because line 16 } \ No newline at end of file From 363f8b6dc3cb7190083ecf145875b6af3bfabb1c Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Thu, 29 Apr 2021 20:24:08 +0900 Subject: [PATCH 12/13] Short circuit if we find a problematic promotion --- .../dotty/tools/dotc/transform/init/Checking.scala | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/init/Checking.scala b/compiler/src/dotty/tools/dotc/transform/init/Checking.scala index 70189899a452..380a7265d646 100644 --- a/compiler/src/dotty/tools/dotc/transform/init/Checking.scala +++ b/compiler/src/dotty/tools/dotc/transform/init/Checking.scala @@ -339,11 +339,12 @@ object Checking { buffer += Promote(potInner)(source) } - val errs = buffer.toList.flatMap(eff => check(eff)) - if errs.isEmpty then - Errors.empty - else - UnsafePromotion(warm, eff.source, state.path, errs.toList).toErrors + for (eff <- buffer.toList) { + val err = check(eff) + if !errs.isEmpty then + return UnsafePromotion(warm, eff.source, state.path, errs.toList).toErrors + } + Errors.empty private def checkPromote(eff: Promote)(using state: State): Errors = if (state.safePromoted.contains(eff.potential)) Errors.empty From 1d2688eeef67b0f6a8aeb532ad0ce0dedc1d41a9 Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Thu, 29 Apr 2021 20:47:28 +0900 Subject: [PATCH 13/13] Update Checking.scala --- compiler/src/dotty/tools/dotc/transform/init/Checking.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/transform/init/Checking.scala b/compiler/src/dotty/tools/dotc/transform/init/Checking.scala index 380a7265d646..1e4090f841ed 100644 --- a/compiler/src/dotty/tools/dotc/transform/init/Checking.scala +++ b/compiler/src/dotty/tools/dotc/transform/init/Checking.scala @@ -340,7 +340,7 @@ object Checking { } for (eff <- buffer.toList) { - val err = check(eff) + val errs = check(eff) if !errs.isEmpty then return UnsafePromotion(warm, eff.source, state.path, errs.toList).toErrors }