Skip to content

Commit 1a4060c

Browse files
authored
Merge pull request #2892 from dotty-staging/fix-#2762-1
Fix #2762: Make sure constrainResult does not change context when false
2 parents 9b99107 + ba801d5 commit 1a4060c

File tree

4 files changed

+49
-16
lines changed

4 files changed

+49
-16
lines changed

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,12 +216,11 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
216216
case methType: MethodType =>
217217
// apply the result type constraint, unless method type is dependent
218218
val resultApprox = resultTypeApprox(methType)
219-
val savedConstraint = ctx.typerState.constraint
220219
if (!constrainResult(resultApprox, resultType))
221220
if (ctx.typerState.isCommittable)
222221
// defer the problem until after the application;
223222
// it might be healed by an implicit conversion
224-
assert(ctx.typerState.constraint eq savedConstraint)
223+
()
225224
else
226225
fail(err.typeMismatchMsg(methType.resultType, resultType))
227226
// match all arguments with corresponding formal parameters

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

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -54,20 +54,23 @@ object ProtoTypes {
5454
/** Check that the result type of the current method
5555
* fits the given expected result type.
5656
*/
57-
def constrainResult(mt: Type, pt: Type)(implicit ctx: Context): Boolean = pt match {
58-
case pt: FunProto =>
59-
mt match {
60-
case mt: MethodType =>
61-
constrainResult(resultTypeApprox(mt), pt.resultType)
62-
case _ =>
63-
true
64-
}
65-
case _: ValueTypeOrProto if !disregardProto(pt) =>
66-
isCompatible(normalize(mt, pt), pt)
67-
case pt: WildcardType if pt.optBounds.exists =>
68-
isCompatible(normalize(mt, pt), pt)
69-
case _ =>
70-
true
57+
def constrainResult(mt: Type, pt: Type)(implicit ctx: Context): Boolean = {
58+
val savedConstraint = ctx.typerState.constraint
59+
val res = pt match {
60+
case pt: FunProto =>
61+
mt match {
62+
case mt: MethodType => constrainResult(resultTypeApprox(mt), pt.resultType)
63+
case _ => true
64+
}
65+
case _: ValueTypeOrProto if !disregardProto(pt) =>
66+
isCompatible(normalize(mt, pt), pt)
67+
case pt: WildcardType if pt.optBounds.exists =>
68+
isCompatible(normalize(mt, pt), pt)
69+
case _ =>
70+
true
71+
}
72+
if (!res) ctx.typerState.constraint = savedConstraint
73+
res
7174
}
7275
}
7376

tests/neg/i2672.scala

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
class Foo[T]
2+
3+
trait Prepend {
4+
type Out
5+
}
6+
7+
object Test {
8+
def foo()(implicit ev: Prepend): Foo[ev.Out] = ???
9+
10+
def test: Unit = {
11+
foo(): Foo[Any] // error: found: Prepend => Foo[_] required: Foo[Any]
12+
13+
}
14+
15+
implicit val p: Prepend = ???
16+
}

tests/pos/i2672.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
class Foo[+T]
2+
3+
trait Prepend {
4+
type Out
5+
}
6+
7+
object Test {
8+
def foo()(implicit ev: Prepend): Foo[ev.Out] = ???
9+
10+
def test: Unit = {
11+
foo(): Foo[Any]
12+
}
13+
14+
implicit val p: Prepend = ???
15+
}

0 commit comments

Comments
 (0)