Skip to content

Commit 291492f

Browse files
committed
Make sure constrainResult does not change context when false
constrainResult should behave like isSubType in this respect. This fixes #2672. The assertion in Applications.scala is no longer needed because it is now obviously true by design.
1 parent beff5cb commit 291492f

File tree

4 files changed

+50
-16
lines changed

4 files changed

+50
-16
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,11 +217,11 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
217217
// apply the result type constraint, unless method type is dependent
218218
val resultApprox = resultTypeApprox(methType)
219219
val savedConstraint = ctx.typerState.constraint
220-
if (!constrainResult(resultApprox, resultType))
220+
if (!constrainResult(resultApprox, resultType)
221221
if (ctx.typerState.isCommittable)
222222
// defer the problem until after the application;
223223
// it might be healed by an implicit conversion
224-
assert(ctx.typerState.constraint eq savedConstraint)
224+
()
225225
else
226226
fail(err.typeMismatchMsg(methType.resultType, resultType))
227227
// 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)