@@ -11,8 +11,9 @@ import Constants.*
1111import util .{Stats , SimpleIdentityMap , SimpleIdentitySet }
1212import Decorators .*
1313import Uniques .*
14- import Flags .Method
14+ import Flags .{ Method , Transparent }
1515import inlines .Inlines
16+ import config .{Feature , SourceVersion }
1617import config .Printers .typr
1718import Inferencing .*
1819import ErrorReporting .*
@@ -108,7 +109,7 @@ object ProtoTypes {
108109 res
109110
110111 /** Constrain result with two special cases:
111- * 1. If `meth` is an inlineable method in an inlineable context,
112+ * 1. If `meth` is a transparent inlineable method in an inlineable context,
112113 * we should always succeed and not constrain type parameters in the expected type,
113114 * because the actual return type can be a subtype of the currently known return type.
114115 * However, we should constrain parameters of the declared return type. This distinction is
@@ -128,11 +129,30 @@ object ProtoTypes {
128129 case _ =>
129130 false
130131
131- if Inlines .isInlineable(meth) then
132- constrainResult(mt, wildApprox(pt))
133- true
134- else
135- constFoldException(pt) || constrainResult(mt, pt)
132+ constFoldException(pt) || {
133+ if Inlines .isInlineable(meth) then
134+ // Stricter behavisour in 3.4+: do not apply `wildApprox` to non-transparent inlines
135+ // unless their return type is a MatchType. In this case there's no reason
136+ // not to constrain type variables in the expected type. For transparent inlines
137+ // we do not want to constrain type variables in the expected type since the
138+ // actual return type might be smaller after instantiation. For inlines returning
139+ // MatchTypes we do not want to constrain because the MatchType might be more
140+ // specific after instantiation. TODO: Should we also use Wildcards for non-inline
141+ // methods returning MatchTypes?
142+ if Feature .sourceVersion.isAtLeast(SourceVersion .`3.4`) then
143+ if meth.is(Transparent ) || mt.resultType.isMatchAlias then
144+ constrainResult(mt, wildApprox(pt))
145+ // do not constrain the result type of transparent inline methods
146+ true
147+ else
148+ constrainResult(mt, pt)
149+ else
150+ // Best-effort to fix https://github.com/scala/scala3/issues/9685 in the 3.3.x series
151+ // while preserving source compatibility as much as possible
152+ constrainResult(mt, wildApprox(pt)) || meth.is(Transparent )
153+ else constrainResult(mt, pt)
154+ }
155+
136156 end constrainResult
137157 end Compatibility
138158
0 commit comments