Skip to content

Commit 3d29fd1

Browse files
authored
Merge pull request #15754 from dotty-staging/backport-15679
Backport #15679: Don't ignore expected types of `New`
2 parents 8e43405 + 83f5d73 commit 3d29fd1

File tree

3 files changed

+52
-20
lines changed

3 files changed

+52
-20
lines changed

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -892,8 +892,17 @@ trait Applications extends Compatibility {
892892
def typedApply(tree: untpd.Apply, pt: Type)(using Context): Tree = {
893893

894894
def realApply(using Context): Tree = {
895+
val resultProto = tree.fun match
896+
case Select(New(_), _) if pt.isInstanceOf[ValueType] => pt
897+
// Don't ignore expected value types of `new` expressions. If we have a `new C()`
898+
// with expected type `C[T]` we want to use the type to instantiate `C`
899+
// immediately. This is necessary since `C` might _also_ have using clauses
900+
// that we want to instantiate with the best available type. See i15664.scala.
901+
case _ => IgnoredProto(pt)
902+
// Do ignore other expected result types, since there might be an implicit conversion
903+
// on the result. We could drop this if we disallow unrestricted implicit conversions.
895904
val originalProto =
896-
new FunProto(tree.args, IgnoredProto(pt))(this, tree.applyKind)(using argCtx(tree))
905+
new FunProto(tree.args, resultProto)(this, tree.applyKind)(using argCtx(tree))
897906
record("typedApply")
898907
val fun1 = typedExpr(tree.fun, originalProto)
899908

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

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3304,25 +3304,23 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
33043304
// try an implicit conversion or given extension
33053305
if ctx.mode.is(Mode.ImplicitsEnabled) && !tree.name.isConstructorName && qual.tpe.isValueType then
33063306
try
3307-
trace(i"try insert impl on qualifier $tree $pt") {
3308-
val selProto = selectionProto
3309-
inferView(qual, selProto) match
3310-
case SearchSuccess(found, _, _, isExtension) =>
3311-
if isExtension then return found
3312-
else
3313-
checkImplicitConversionUseOK(found)
3314-
return withoutMode(Mode.ImplicitsEnabled)(typedSelect(tree, pt, found))
3315-
case failure: SearchFailure =>
3316-
if failure.isAmbiguous then
3317-
return
3318-
if !inSelect // in a selection we will do the canDefineFurther afterwards
3319-
&& canDefineFurther(qual.tpe.widen)
3320-
then
3321-
tryExtensionOrConversion(tree, pt, mbrProto, qual, locked, compat, inSelect)
3322-
else
3323-
err.typeMismatch(qual, selProto, failure.reason) // TODO: report NotAMember instead, but need to be aware of failure
3324-
rememberSearchFailure(qual, failure)
3325-
}
3307+
val selProto = selectionProto
3308+
trace(i"try insert impl on qualifier $tree $pt") { inferView(qual, selProto) } match
3309+
case SearchSuccess(found, _, _, isExtension) =>
3310+
if isExtension then return found
3311+
else
3312+
checkImplicitConversionUseOK(found)
3313+
return withoutMode(Mode.ImplicitsEnabled)(typedSelect(tree, pt, found))
3314+
case failure: SearchFailure =>
3315+
if failure.isAmbiguous then
3316+
return
3317+
if !inSelect // in a selection we will do the canDefineFurther afterwards
3318+
&& canDefineFurther(qual.tpe.widen)
3319+
then
3320+
tryExtensionOrConversion(tree, pt, mbrProto, qual, locked, compat, inSelect)
3321+
else
3322+
err.typeMismatch(qual, selProto, failure.reason) // TODO: report NotAMember instead, but need to be aware of failure
3323+
rememberSearchFailure(qual, failure)
33263324
catch case ex: TypeError => nestedFailure(ex)
33273325

33283326
EmptyTree

tests/pos/i15664.scala

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
trait CpsMonad[F[_]]:
2+
type Context <: CpsMonadContext[F]
3+
type Aux[F[_], C <: CpsMonadContext[F]] = CpsMonad[F] { type Context = C }
4+
trait CpsMonadContext[F[_]]
5+
trait CpsMonadInstanceContext[F[_]] extends CpsMonad[F]:
6+
type Context = CpsMonadInstanceContextBody[F]
7+
class CpsMonadInstanceContextBody[F[_]](m: CpsMonadInstanceContext[F]) extends CpsMonadContext[F]
8+
class InferAsyncArg[F[_], C <: CpsMonadContext[F]](using val am: Aux[F, C])
9+
10+
sealed abstract class ZManaged[-R, +E, +A]
11+
type RManaged[-R, +A] = ZManaged[R, Throwable, A]
12+
13+
type ForZManaged[R, E] = [X] =>> ZManaged[R, E, X]
14+
given zManagedCpsMonad[R, E]: CpsMonadInstanceContext[ForZManaged[R, E]] = ???
15+
16+
// Usage
17+
def failing[R, E](using
18+
CpsMonad[ForZManaged[R, E]]
19+
): InferAsyncArg[ForZManaged[R, E], CpsMonadInstanceContextBody[ForZManaged[R, E]]] =
20+
new InferAsyncArg()
21+
22+
def compiling[R, E](using
23+
CpsMonad[ForZManaged[R, E]]
24+
) =
25+
new InferAsyncArg[ForZManaged[R, E], CpsMonadInstanceContextBody[ForZManaged[R, E]]]

0 commit comments

Comments
 (0)