@@ -11,8 +11,9 @@ import Constants.*
11
11
import util .{Stats , SimpleIdentityMap , SimpleIdentitySet }
12
12
import Decorators .*
13
13
import Uniques .*
14
- import Flags .Method
14
+ import Flags .{ Method , Transparent }
15
15
import inlines .Inlines
16
+ import config .{Feature , SourceVersion }
16
17
import config .Printers .typr
17
18
import Inferencing .*
18
19
import ErrorReporting .*
@@ -108,7 +109,7 @@ object ProtoTypes {
108
109
res
109
110
110
111
/** 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,
112
113
* we should always succeed and not constrain type parameters in the expected type,
113
114
* because the actual return type can be a subtype of the currently known return type.
114
115
* However, we should constrain parameters of the declared return type. This distinction is
@@ -128,11 +129,30 @@ object ProtoTypes {
128
129
case _ =>
129
130
false
130
131
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
+
136
156
end constrainResult
137
157
end Compatibility
138
158
0 commit comments