Skip to content

Commit 80f6a9b

Browse files
oderskyWojciechMazur
authored andcommitted
Refine isMatched of IgnoredProtos
Fixes the Open CB counter example. [Cherry-picked 0436529]
1 parent e46d751 commit 80f6a9b

File tree

2 files changed

+40
-4
lines changed

2 files changed

+40
-4
lines changed

compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,13 +162,15 @@ object ProtoTypes {
162162
override def viewExists(tp: Type, pt: Type)(using Context): Boolean = false
163163
}
164164

165-
/** A trait for prototypes that match all types */
166-
trait MatchAlways extends ProtoType {
167-
def isMatchedBy(tp1: Type, keepConstraint: Boolean)(using Context): Boolean = true
165+
/** A trait for prototypes that map to themselves */
166+
trait FixedProto extends ProtoType:
168167
def map(tm: TypeMap)(using Context): ProtoType = this
169168
def fold[T](x: T, ta: TypeAccumulator[T])(using Context): T = x
170169
override def toString: String = getClass.toString
171-
}
170+
171+
/** A trait for prototypes that match all types */
172+
trait MatchAlways extends FixedProto:
173+
def isMatchedBy(tp1: Type, keepConstraint: Boolean)(using Context): Boolean = true
172174

173175
/** A class marking ignored prototypes that can be revealed by `deepenProto` */
174176
abstract case class IgnoredProto(ignored: Type) extends CachedGroundType with MatchAlways:
@@ -179,6 +181,21 @@ object ProtoTypes {
179181
ignored
180182
override def deepenProtoTrans(using Context): Type = ignored.deepenProtoTrans
181183

184+
override def isMatchedBy(tp1: Type, keepConstraint: Boolean)(using Context): Boolean =
185+
def takesParams(tp: Type): Boolean = tp match
186+
case tp: PolyType => takesParams(tp.resType)
187+
case MethodType(pnames) => pnames.nonEmpty && !tp.isImplicitMethod
188+
case _ => false
189+
ignored match
190+
case ignored: SelectionProto if ignored.name != nme.apply =>
191+
// Non-implicit methods that take at least one parameter don't match ignored
192+
// selection protos unless the selection is via `apply`. This is because a
193+
// match of a different selection would require an eta expansion _and_ an
194+
// implicit conversion, which is not allowed. So the prototype would not
195+
// match even if implicit conversions were present. Test case: i23773a.scala.
196+
!takesParams(tp1.widen)
197+
case _ => true
198+
182199
/** Did someone look inside via deepenProto? Used for error deagniostics
183200
* to give a more extensive expected type.
184201
*/

tests/pos/i23773a.scala

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
trait NumericDate
2+
trait JWSDecoded[H]
3+
4+
trait StandardHeaderWrite[H]:
5+
def setAlgorithm(header: H, algorithm: Algorithm): H
6+
7+
object StandardHeaderWrite:
8+
def apply[H](using sh: StandardHeaderWrite[H]): StandardHeaderWrite[H] = ???
9+
// unused - required to reproduce
10+
def apply[H](setAlg: (H, Algorithm) => H): StandardHeaderWrite[H] = ???
11+
12+
final case class JWK(algorithm: Option[Algorithm])
13+
sealed trait Algorithm
14+
15+
def Test[F[_], H](key: JWK, header: H)(using StandardHeaderWrite[H]) = {
16+
key.algorithm
17+
.map(StandardHeaderWrite[H].setAlgorithm(header, _))
18+
.getOrElse(header)
19+
}

0 commit comments

Comments
 (0)