diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala index 55021bf50ace..77e3387c5ce0 100644 --- a/compiler/src/dotty/tools/dotc/ast/tpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala @@ -1137,6 +1137,10 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { /** Replace Ident nodes references to the underlying tree that defined them */ def underlying(using Context): Tree = MapToUnderlying().transform(tree) + /** Collect all the TypeSymbol's of the type Bind nodes in the tree. */ + def bindTypeSymbols(using Context): List[TypeSymbol] = + tree.collectSubTrees { case b: Bind if b.isType => b.symbol.asType } + // --- Higher order traversal methods ------------------------------- /** Apply `f` to each subtree of this tree */ diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 95c3b025b3ce..c5937074f4bc 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -4633,6 +4633,7 @@ object Types extends TypeUtils { */ def isUnreducibleWild(using Context): Boolean = tycon.isLambdaSub && hasWildcardArg && !isMatchAlias + && !(args.sizeIs == 1 && defn.isCompiletime_S(tycon.typeSymbol)) // S is a pseudo Match Alias def tryCompiletimeConstantFold(using Context): Type = if myEvalRunId == ctx.runId then myEvalued diff --git a/compiler/src/dotty/tools/dotc/inlines/InlineReducer.scala b/compiler/src/dotty/tools/dotc/inlines/InlineReducer.scala index 26fd52fb7138..0c321570bad5 100644 --- a/compiler/src/dotty/tools/dotc/inlines/InlineReducer.scala +++ b/compiler/src/dotty/tools/dotc/inlines/InlineReducer.scala @@ -216,31 +216,21 @@ class InlineReducer(inliner: Inliner)(using Context): type TypeBindsMap = SimpleIdentityMap[TypeSymbol, java.lang.Boolean] def getTypeBindsMap(pat: Tree, tpt: Tree): TypeBindsMap = { - val getBinds = new TreeAccumulator[Set[TypeSymbol]] { - def apply(syms: Set[TypeSymbol], t: Tree)(using Context): Set[TypeSymbol] = { - val syms1 = t match { - case t: Bind if t.symbol.isType => - syms + t.symbol.asType - case _ => syms - } - foldOver(syms1, t) - } - } - // Extractors can contain Bind nodes in type parameter lists, // for that case tree looks like this: // UnApply[t @ t](pats)(implicits): T[t] // Test case is pos/inline-caseclass.scala. + // // Alternatively, for explicitly specified type binds in type annotations like in // case A(B): A[t] // the tree will look like this: // Unapply[t](pats)(implicits) : T[t @ t] // and the binds will be found in the type tree instead // Test case is pos-macros/i15971 - val tptBinds = getBinds(Set.empty[TypeSymbol], tpt) + val tptBinds = tpt.bindTypeSymbols.toSet val binds: Set[TypeSymbol] = pat match { case UnApply(TypeApply(_, tpts), _, _) => - getBinds(Set.empty[TypeSymbol], tpts) ++ tptBinds + tpts.flatMap(_.bindTypeSymbols).toSet ++ tptBinds case _ => tptBinds } diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala index 8751bd7dc9bb..6ce0f5f2517c 100644 --- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -429,13 +429,7 @@ trait TypeAssigner { def assignType(tree: untpd.CaseDef, pat: Tree, body: Tree)(using Context): CaseDef = { val ownType = if (body.isType) { - val getParams = new TreeAccumulator[mutable.ListBuffer[TypeSymbol]] { - def apply(ps: mutable.ListBuffer[TypeSymbol], t: Tree)(using Context) = t match { - case t: Bind if t.symbol.isType => foldOver(ps += t.symbol.asType, t) - case _ => foldOver(ps, t) - } - } - val params1 = getParams(new mutable.ListBuffer[TypeSymbol](), pat).toList + val params1 = pat.bindTypeSymbols val params2 = pat.tpe match case AppliedType(tycon, args) => val tparams = tycon.typeParamSymbols diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 6bb5d1ee70ff..3434fa9f48fc 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -2649,7 +2649,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer val lub = cases1.foldLeft(defn.NothingType: Type): (acc, case1) => if !acc.exists then NoType else if case1.body.tpe.isProvisional then NoType - else acc | case1.body.tpe + else acc | TypeOps.avoid(case1.body.tpe, case1.pat.bindTypeSymbols) if lub.exists then if !lub.isAny then val msg = em"Match type upper bound inferred as $lub, where previously it was defaulted to Any" diff --git a/compiler/test/dotc/pos-test-pickling.blacklist b/compiler/test/dotc/pos-test-pickling.blacklist index ebdd414ea7f2..f35d527edf62 100644 --- a/compiler/test/dotc/pos-test-pickling.blacklist +++ b/compiler/test/dotc/pos-test-pickling.blacklist @@ -19,6 +19,7 @@ i12299a.scala i13871.scala i15181.scala i15922.scala +i15926.scala t5031_2.scala i16997.scala i7414.scala diff --git a/tests/pos/i21256.scala b/tests/pos/i21256.scala new file mode 100644 index 000000000000..e51484c73ef7 --- /dev/null +++ b/tests/pos/i21256.scala @@ -0,0 +1,5 @@ +object Test { + type MTWithBind[X] = X match { + case List[t] => t + } +}