diff options
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Namers.scala | 10 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 4 | ||||
-rw-r--r-- | test/files/run/t10261/Companion_1.scala | 4 | ||||
-rw-r--r-- | test/files/run/t10261/Test_2.scala | 14 |
4 files changed, 31 insertions, 1 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index bbb9d33140..f69d1d5254 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -664,7 +664,17 @@ trait Namers extends MethodSynthesis { if (suppress) { sym setInfo ErrorType + + // There are two ways in which we exclude the symbol from being added in typedStats::addSynthetics, + // because we don't know when the completer runs with respect to this loop in addSynthetics + // for (sym <- scope) + // for (tree <- context.unit.synthetics.get(sym) if shouldAdd(sym)) { + // if (!sym.initialize.hasFlag(IS_ERROR)) + // newStats += typedStat(tree) + // If we're already in the loop, set the IS_ERROR flag and trigger the condition `sym.initialize.hasFlag(IS_ERROR)` sym setFlag IS_ERROR + // Or, if we are not yet in the addSynthetics loop, we can just retract our symbol from the synthetics for this unit. + companionContext.unit.synthetics -= sym // Don't unlink in an error situation to generate less confusing error messages. // Ideally, our error reporting would distinguish overloaded from recursive user-defined apply methods without signature, diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index cd4a883a33..69bf5fdef7 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -3168,7 +3168,9 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper for (sym <- scope) // OPT: shouldAdd is usually true. Call it here, rather than in the outer loop for (tree <- context.unit.synthetics.get(sym) if shouldAdd(sym)) { - newStats += typedStat(tree) // might add even more synthetics to the scope + // if the completer set the IS_ERROR flag, retract the stat (currently only used by applyUnapplyMethodCompleter) + if (!sym.initialize.hasFlag(IS_ERROR)) + newStats += typedStat(tree) // might add even more synthetics to the scope context.unit.synthetics -= sym } // the type completer of a synthetic might add more synthetics. example: if the diff --git a/test/files/run/t10261/Companion_1.scala b/test/files/run/t10261/Companion_1.scala new file mode 100644 index 0000000000..9b8e2c73b2 --- /dev/null +++ b/test/files/run/t10261/Companion_1.scala @@ -0,0 +1,4 @@ +trait Companion[T] { + def parse(value: String): Option[T] + def apply(value: String): T = parse(value).get +} diff --git a/test/files/run/t10261/Test_2.scala b/test/files/run/t10261/Test_2.scala new file mode 100644 index 0000000000..d7d9fe9a0e --- /dev/null +++ b/test/files/run/t10261/Test_2.scala @@ -0,0 +1,14 @@ +import scala.util.Try + +object C extends Companion[C] { + def parse(v: String) = if (v.nonEmpty) Some(new C(v)) else None +} + +case class C(value: String) + +object Test { + def main(args: Array[String]): Unit = { + assert(Try{C("")}.isFailure, "Empty value should fail to parse") // check that parse is used to validate input + assert(C("a").value == "a", "Unexpected value") + } +} |