Skip to content

Fix #18763: Run type inference before implicit search #23020

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 27 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
c1f2338
Run type inference before implicit search
Alex1005a Apr 20, 2025
ad5ab27
new typer state when infer types before search implicit
Alex1005a Apr 20, 2025
9be384b
not infer if type not simplified before implicit search
Alex1005a Apr 22, 2025
4fe718b
return constrainResult after AmbiguousImplicits
Alex1005a Apr 24, 2025
9f3c727
run constrainResult before implicit search when search type not ground
Alex1005a Apr 25, 2025
5ec51bc
Approximate result type before constrain
Alex1005a Apr 27, 2025
116fdfc
not subst dummyArg if tree is TypedSlice
Alex1005a Apr 27, 2025
1a8afbc
not constrainResult if type contains Wildcard Types
Alex1005a Apr 28, 2025
77a83c6
move constrain to function
Alex1005a Apr 29, 2025
58993a0
return isGround check
Alex1005a Apr 29, 2025
76d8913
return resultAlreadyConstrained check
Alex1005a Apr 29, 2025
d03d8bd
return simplified check
Alex1005a Apr 29, 2025
23cc07f
fix
Alex1005a Apr 29, 2025
b91ad9b
no need in constrain type, if it already constrained
Alex1005a Apr 29, 2025
480cb8d
subtype check instead constrainResult
Alex1005a May 24, 2025
24b2dc7
remove resultAlreadyConstrained check
Alex1005a May 25, 2025
368095d
Merge branch 'main' into fix-18763
Alex1005a Jul 19, 2025
d94a22f
change isGround
Alex1005a Jul 19, 2025
e8c4c10
use wildApprox instead isGround
Alex1005a Jul 19, 2025
e5b2e76
not constrain if formal contains constrained type vars
Alex1005a Jul 20, 2025
e41045e
not constrain if formal contains instantiated type vars
Alex1005a Jul 20, 2025
3a4aabd
not constrain if formal contains instantiated type vars
Alex1005a Jul 20, 2025
fe2a943
type fully defined then typevar instantiated to other typevar
Alex1005a Jul 26, 2025
33d98ad
revert
Alex1005a Jul 26, 2025
899c5e6
wildApprox before constrain result
Alex1005a Jul 27, 2025
53563a7
use isFullyDefined
Alex1005a Jul 27, 2025
01c8620
use new ctx in isFullyDefined
Alex1005a Jul 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions compiler/src/dotty/tools/dotc/typer/Inferencing.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ object Inferencing {
* but only if the overall result of `isFullyDefined` is `true`.
* Variables that are successfully minimized do not count as uninstantiated.
*/
def isFullyDefined(tp: Type, force: ForceDegree.Value)(using Context): Boolean =
withFreshTyperState(new IsFullyDefinedAccumulator(force).process(tp), x => x)
def isFullyDefined(tp: Type, force: ForceDegree.Value, ifProto: Boolean = false)(using Context): Boolean =
withFreshTyperState(new IsFullyDefinedAccumulator(force, ifProto = ifProto).process(tp), x => x)

/** Try to fully define `tp`. Return whether constraint has changed.
* Any changed constraint is kept.
Expand Down Expand Up @@ -161,7 +161,7 @@ object Inferencing {
* Instance types can be improved by replacing covariant occurrences of Nothing
* with fresh type variables, if `force` allows this in its `canImprove` implementation.
*/
private class IsFullyDefinedAccumulator(force: ForceDegree.Value, minimizeSelected: Boolean = false)
private class IsFullyDefinedAccumulator(force: ForceDegree.Value, minimizeSelected: Boolean = false, ifProto: Boolean = false)
(using Context) extends TypeAccumulator[Boolean] {

/** Replace toplevel-covariant occurrences (i.e. covariant without double flips)
Expand Down Expand Up @@ -233,8 +233,10 @@ object Inferencing {
val tpd = tp.dealias
if tpd ne tp then apply(x, tpd)
else tp match
case _: WildcardType | _: ProtoType =>
case _: WildcardType =>
false
case tp: ProtoType =>
ifProto && foldOver(x, tp)
case tvar: TypeVar if !tvar.isInstantiated =>
force.appliesTo(tvar)
&& ctx.typerState.constraint.contains(tvar)
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ object ProtoTypes {
args: List[untpd.Tree] = this.args,
resultType: Type = this.resultType,
typer: Typer = this.typer,
constrainResultDeep: Boolean = this.constrainResultDeep): FunProto =
constrainResultDeep: Boolean = this.constrainResultDeep)(using Context): FunProto =
if (args eq this.args)
&& (resultType eq this.resultType)
&& (typer eq this.typer)
Expand Down
23 changes: 22 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import transform.CheckUnused.OriginalName
import scala.annotation.{unchecked as _, *}
import dotty.tools.dotc.util.chaining.*
import dotty.tools.dotc.ast.untpd.Mod
import dotty.tools.dotc.reporting.Reporter.NoReporter

object Typer {

Expand Down Expand Up @@ -4357,6 +4358,27 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
else formals1
implicitArgs(formals2, argIndex + 1, pt)


def doesntContainsWildcards = {
val newCtx = ctx.fresh.setNewScope.setReporter(new reporting.ThrowingReporter(NoReporter))
val pt1 = pt.deepenProtoTrans(using newCtx)
try {
isFullyDefined(pt1, ForceDegree.none, ifProto = true)(using newCtx)
} catch {
case _: UnhandledError => false
}
}
val pt1 = pt.deepenProtoTrans
if (pt1 `ne` pt)
&& (pt1 ne sharpenedPt)
&& formal.typeSymbol != defn.ClassTagClass
&& !isFullyDefined(formal, ForceDegree.none)
&& !formal.existsPart(ty => {
val dty = ty.dealias
(dty ne ty) && ty.isInstanceOf[TypeVar] && dty.isInstanceOf[TypeVar]
}, StopAt.Static, forceLazy = false)
&& doesntContainsWildcards then
constrainResult(tree.symbol, wtp, wildApprox(pt1))
val arg = inferImplicitArg(formal, tree.span.endPos)

def canProfitFromMoreConstraints =
Expand All @@ -4367,7 +4389,6 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer

arg.tpe match
case failed: SearchFailureType if canProfitFromMoreConstraints =>
val pt1 = pt.deepenProtoTrans
if (pt1 `ne` pt) && (pt1 ne sharpenedPt) && constrainResult(tree.symbol, wtp, pt1)
then return implicitArgs(formals, argIndex, pt1)
case _ =>
Expand Down
Loading