From 93da7c96aa1ac8a0b17e73742885f1f6658774d5 Mon Sep 17 00:00:00 2001 From: odersky Date: Wed, 8 Jun 2022 11:16:58 +0200 Subject: [PATCH 1/2] Recover from stackoverflows in AvoidMap --- .../src/dotty/tools/dotc/core/TypeOps.scala | 66 ++++++++++--------- tests/neg/i15365.scala | 17 +++++ 2 files changed, 52 insertions(+), 31 deletions(-) create mode 100644 tests/neg/i15365.scala diff --git a/compiler/src/dotty/tools/dotc/core/TypeOps.scala b/compiler/src/dotty/tools/dotc/core/TypeOps.scala index 01ad6fdb0724..fc18c9758947 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeOps.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeOps.scala @@ -423,38 +423,42 @@ object TypeOps: sym.is(Package) || sym.isStatic && isStaticPrefix(pre.prefix) case _ => true - override def apply(tp: Type): Type = tp match - case tp: TermRef - if toAvoid(tp) => - tp.info.widenExpr.dealias match { - case info: SingletonType => apply(info) - case info => range(defn.NothingType, apply(info)) - } - case tp: TypeRef if toAvoid(tp) => - tp.info match { - case info: AliasingBounds => - apply(info.alias) - case TypeBounds(lo, hi) => - range(atVariance(-variance)(apply(lo)), apply(hi)) - case info: ClassInfo => - range(defn.NothingType, apply(classBound(info))) + override def apply(tp: Type): Type = + try + tp match + case tp: TermRef + if toAvoid(tp) => + tp.info.widenExpr.dealias match { + case info: SingletonType => apply(info) + case info => range(defn.NothingType, apply(info)) + } + case tp: TypeRef if toAvoid(tp) => + tp.info match { + case info: AliasingBounds => + apply(info.alias) + case TypeBounds(lo, hi) => + range(atVariance(-variance)(apply(lo)), apply(hi)) + case info: ClassInfo => + range(defn.NothingType, apply(classBound(info))) + case _ => + emptyRange // should happen only in error cases + } + case tp: ThisType => + // ThisType is only used inside a class. + // Therefore, either they don't appear in the type to be avoided, or + // it must be a class that encloses the block whose type is to be avoided. + tp + case tp: LazyRef => + if localParamRefs.contains(tp.ref) then tp + else if isExpandingBounds then emptyRange + else mapOver(tp) + case tl: HKTypeLambda => + localParamRefs ++= tl.paramRefs + mapOver(tl) case _ => - emptyRange // should happen only in error cases - } - case tp: ThisType => - // ThisType is only used inside a class. - // Therefore, either they don't appear in the type to be avoided, or - // it must be a class that encloses the block whose type is to be avoided. - tp - case tp: LazyRef => - if localParamRefs.contains(tp.ref) then tp - else if isExpandingBounds then emptyRange - else mapOver(tp) - case tl: HKTypeLambda => - localParamRefs ++= tl.paramRefs - mapOver(tl) - case _ => - super.apply(tp) + super.apply(tp) + catch case ex: Throwable => + handleRecursive("traversing for avoiding local references", s"${tp.show}" , ex) end apply /** Three deviations from standard derivedSelect: diff --git a/tests/neg/i15365.scala b/tests/neg/i15365.scala new file mode 100644 index 000000000000..f7d368b5223a --- /dev/null +++ b/tests/neg/i15365.scala @@ -0,0 +1,17 @@ +trait Tagged[U] +type WithTag[+TT, UU] = TT & Tagged[UU] + +trait FromInput[Val] +implicit def coercedScalaInput[Tc1]: FromInput[WithTag[Tc1, Int]] = ??? +implicit def optionInput[To](implicit ev: FromInput[To]): FromInput[Option[To]] = ??? + +trait WithoutInputTypeTags[TW] +implicit def coercedOptArgTpe[Tc]: WithoutInputTypeTags[Option[WithTag[Tc, Int]]] = ??? + +trait InputType[+TI] +class OptionInputType[TO](ofType: InputType[TO]) extends InputType[Option[TO]] + +type Argument[TA] +def argument[Ta](argumentType: InputType[Ta])(implicit fromInput: FromInput[Ta], res: WithoutInputTypeTags[Ta]): Argument[Option[Ta]] = ??? + +def test = argument(OptionInputType(??? : InputType[WithTag[Boolean, Int]])) :: Nil // error From ac0100d5c5e31289179ec1c288cb27bffe448d18 Mon Sep 17 00:00:00 2001 From: odersky Date: Wed, 8 Jun 2022 12:58:36 +0200 Subject: [PATCH 2/2] Reclassify test to allow deep subtypes --- tests/{neg => neg-custom-args/allow-deep-subtypes}/i15365.scala | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/{neg => neg-custom-args/allow-deep-subtypes}/i15365.scala (100%) diff --git a/tests/neg/i15365.scala b/tests/neg-custom-args/allow-deep-subtypes/i15365.scala similarity index 100% rename from tests/neg/i15365.scala rename to tests/neg-custom-args/allow-deep-subtypes/i15365.scala