Fix infinite loop in Mirror synthesis of unreducible match type#20133
Fix infinite loop in Mirror synthesis of unreducible match type#20133smarter merged 2 commits intoscala:mainfrom
Conversation
This regressed in f7e2e7c (present in 3.4.0).
| Right(MirrorSource.GenericTuple(types)) | ||
| case _ => reduce(tp.underlying) | ||
| case tp: MatchType => reduce(tp.normalized) | ||
| case tp: MatchType => reduce(tp.tryNormalize.orElse(tp.superType)) |
There was a problem hiding this comment.
This is actually not quite correct, if I change the definition of DoesNotReduce to:
type DoesNotReduce[T] = T match
case String => T
Then it infers an upper-bound of T and tp.superType ends up being Option[Int] and so a mirror is found when none should be found. This seems like a more general problem with superType though, so maybe something we should address after fixing this regression.
There was a problem hiding this comment.
Or perhaps we should never summon the mirror if the match type cannot be reduced? Maybe other situations where we use superType are actually fine. /cc @sjrd
There was a problem hiding this comment.
I agree using superType looks a bit suspicious given that Mirror.Of[_] isn't covariant.
But then again, it's also used in the catch all right below.
| case tp: MatchType => reduce(tp.tryNormalize.orElse(tp.superType)) | ||
| case tp: MatchType => | ||
| val n = tp.tryNormalize | ||
| if n.exists then reduce(n) else Left(i"its subpart `$tp` is an unreducible match type.") |
There was a problem hiding this comment.
I think we should return the unreduced match type instead.
An instance could have been provided manually for it.
There was a problem hiding this comment.
reduce requires that we return a class symbol it seems. Also the Synthesizer logic should only be used as a fallback if an implicit wasn't found by regular search.
There was a problem hiding this comment.
Ah good point, then an error sounds fine to me.
This regressed in f7e2e7c (present in 3.4.0).
The second commit fixes a soundness bug.