@@ -1061,7 +1061,10 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
1061
1061
1062
1062
def typedBlock (tree : untpd.Block , pt : Type )(using Context ): Tree = {
1063
1063
val (stats1, exprCtx) = withoutMode(Mode .Pattern ) {
1064
- typedBlockStats(tree.stats)
1064
+ // in all cases except a closure block, we disable precise type enforcement
1065
+ tree.expr match
1066
+ case _ : untpd.Closure => typedBlockStats(tree.stats)
1067
+ case _ => withoutMode(Mode .Precise ){ typedBlockStats(tree.stats) }
1065
1068
}
1066
1069
var expr1 = typedExpr(tree.expr, pt.dropIfProto)(using exprCtx)
1067
1070
@@ -1913,7 +1916,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
1913
1916
}
1914
1917
1915
1918
def typedInlined (tree : untpd.Inlined , pt : Type )(using Context ): Tree = {
1916
- val (bindings1, exprCtx) = typedBlockStats(tree.bindings)
1919
+ val (bindings1, exprCtx) = withoutMode( Mode . Precise ){ typedBlockStats(tree.bindings) }
1917
1920
val expansion1 = typed(tree.expansion, pt)(using inlineContext(tree.call)(using exprCtx))
1918
1921
assignType(cpy.Inlined (tree)(tree.call, bindings1.asInstanceOf [List [MemberDef ]], expansion1),
1919
1922
bindings1, expansion1)
@@ -2686,7 +2689,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
2686
2689
pkg.moduleClass.info.decls.lookup(topLevelClassName).ensureCompleted()
2687
2690
var stats1 = typedStats(tree.stats, pkg.moduleClass)._1
2688
2691
if (! ctx.isAfterTyper)
2689
- stats1 = stats1 ++ typedBlockStats(MainProxies .proxies(stats1))._1
2692
+ stats1 = stats1 ++ withoutMode( Mode . Precise ){ typedBlockStats(MainProxies .proxies(stats1))._1 }
2690
2693
cpy.PackageDef (tree)(pid1, stats1).withType(pkg.termRef)
2691
2694
}
2692
2695
case _ =>
@@ -3047,7 +3050,48 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
3047
3050
typed(tree, pt, locked)(using ctx.withSource(tree.source))
3048
3051
else if ctx.run.nn.isCancelled then
3049
3052
tree.withType(WildcardType )
3050
- else adapt(typedUnadapted(tree, pt, locked), pt, locked)
3053
+ else
3054
+ val tu = typedUnadapted(tree, pt, locked)
3055
+ pt match
3056
+ // If we are already in precise mode, then the arguments are already typed precisely,
3057
+ // so there is no need for any additional logic.
3058
+ case pt : FunProto if ! ctx.mode.is(Mode .Precise ) =>
3059
+ extension (tpe : Type ) def getArgsPrecises : List [Boolean ] = tpe.widen match
3060
+ case mt : MethodType => mt.paramInfos.map(_.isPrecise)
3061
+ case pt : PolyType => pt.resType.getArgsPrecises
3062
+ case _ => Nil
3063
+ val argsPrecises = tu.tpe.getArgsPrecises
3064
+ // if the function arguments are known to be precise, then we update the
3065
+ // proto with this information and later propagate its state back to the
3066
+ // original proto.
3067
+ if (argsPrecises.contains(true ))
3068
+ val ptPrecises = pt.derivedFunProto(argsPrecises = argsPrecises)
3069
+ val adapted = adapt(tu, ptPrecises, locked)
3070
+ pt.resetTo(ptPrecises.snapshot)
3071
+ adapted
3072
+ // otherwise, we need to check for overloaded function, because in that
3073
+ // case we may not know if the final adapted function will be precise.
3074
+ else tu.tpe match
3075
+ // the function is overloaded, so we preserve the typer and proto state,
3076
+ // adapt the tree, and then check if the arguments should be considered as
3077
+ // precise. if so, then we need to recover the typer state and proto
3078
+ // state, and re-adapt the tree with the precise enforcement.
3079
+ case v : TermRef if v.isOverloaded =>
3080
+ val savedTyperState = ctx.typerState.snapshot()
3081
+ val savedProtoState = pt.snapshot
3082
+ val adaptedMaybePrecise = adapt(tu, pt, locked)
3083
+ val argsPrecises = adaptedMaybePrecise.tpe.getArgsPrecises
3084
+ if (argsPrecises.contains(true ))
3085
+ val ptPrecises = pt.derivedFunProto(argsPrecises = argsPrecises)
3086
+ ctx.typerState.resetTo(savedTyperState)
3087
+ pt.resetTo(savedProtoState)
3088
+ val adapted = adapt(tu, ptPrecises, locked)
3089
+ pt.resetTo(ptPrecises.snapshot)
3090
+ adapted
3091
+ else adaptedMaybePrecise
3092
+ // the function is not overloaded or has precise arguments
3093
+ case _ => adapt(tu, pt, locked)
3094
+ case _ => adapt(tu, pt, locked)
3051
3095
}
3052
3096
3053
3097
def typed (tree : untpd.Tree , pt : Type = WildcardType )(using Context ): Tree =
0 commit comments