@@ -1386,13 +1386,10 @@ class Namer { typer: Typer =>
1386
1386
}
1387
1387
end inherited
1388
1388
1389
- /** The proto-type to be used when inferring the result type from
1390
- * the right hand side. This is `WildcardType` except if the definition
1391
- * is a default getter. In that case, the proto-type is the type of
1392
- * the corresponding parameter where bound parameters are replaced by
1393
- * Wildcards.
1389
+ /** If this is a default getter, the type of the corresponding method parameter,
1390
+ * otherwise NoType.
1394
1391
*/
1395
- def rhsProto = sym.asTerm. name collect {
1392
+ def defaultParamType = sym.name match
1396
1393
case DefaultGetterName (original, idx) =>
1397
1394
val meth : Denotation =
1398
1395
if (original.isConstructorName && (sym.owner.is(ModuleClass )))
@@ -1401,37 +1398,24 @@ class Namer { typer: Typer =>
1401
1398
ctx.defContext(sym).denotNamed(original)
1402
1399
def paramProto (paramss : List [List [Type ]], idx : Int ): Type = paramss match {
1403
1400
case params :: paramss1 =>
1404
- if (idx < params.length) wildApprox( params(idx) )
1401
+ if (idx < params.length) params(idx)
1405
1402
else paramProto(paramss1, idx - params.length)
1406
1403
case nil =>
1407
- WildcardType
1404
+ NoType
1408
1405
}
1409
1406
val defaultAlts = meth.altsWith(_.hasDefaultParams)
1410
1407
if (defaultAlts.length == 1 )
1411
1408
paramProto(defaultAlts.head.info.widen.paramInfoss, idx)
1412
1409
else
1413
- WildcardType
1414
- } getOrElse WildcardType
1410
+ NoType
1411
+ case _ =>
1412
+ NoType
1415
1413
1416
1414
// println(s"final inherited for $sym: ${inherited.toString}") !!!
1417
1415
// println(s"owner = ${sym.owner}, decls = ${sym.owner.info.decls.show}")
1418
1416
// TODO Scala 3.1: only check for inline vals (no final ones)
1419
1417
def isInlineVal = sym.isOneOf(FinalOrInline , butNot = Method | Mutable )
1420
1418
1421
- // Widen rhs type and eliminate `|' but keep ConstantTypes if
1422
- // definition is inline (i.e. final in Scala2) and keep module singleton types
1423
- // instead of widening to the underlying module class types.
1424
- // We also drop the @Repeated annotation here to avoid leaking it in method result types
1425
- // (see run/inferred-repeated-result).
1426
- def widenRhs (tp : Type ): Type =
1427
- tp.widenTermRefExpr.simplified match
1428
- case ctp : ConstantType if isInlineVal => ctp
1429
- case tp => TypeComparer .widenInferred(tp, rhsProto)
1430
-
1431
- // Replace aliases to Unit by Unit itself. If we leave the alias in
1432
- // it would be erased to BoxedUnit.
1433
- def dealiasIfUnit (tp : Type ) = if (tp.isRef(defn.UnitClass )) defn.UnitType else tp
1434
-
1435
1419
var rhsCtx = ctx.fresh.addMode(Mode .InferringReturnType )
1436
1420
if sym.isInlineMethod then rhsCtx = rhsCtx.addMode(Mode .InlineableBody )
1437
1421
if sym.is(ExtensionMethod ) then rhsCtx = rhsCtx.addMode(Mode .InExtensionMethod )
@@ -1443,8 +1427,32 @@ class Namer { typer: Typer =>
1443
1427
rhsCtx.setFreshGADTBounds
1444
1428
rhsCtx.gadt.addToConstraint(typeParams)
1445
1429
}
1446
- def rhsType = PrepareInlineable .dropInlineIfError(sym,
1447
- typedAheadExpr(mdef.rhs, (inherited orElse rhsProto).widenExpr)(using rhsCtx)).tpe
1430
+
1431
+ def typedAheadRhs (pt : Type ) =
1432
+ PrepareInlineable .dropInlineIfError(sym,
1433
+ typedAheadExpr(mdef.rhs, pt)(using rhsCtx))
1434
+
1435
+ def rhsType =
1436
+ // For default getters, we use the corresponding parameter type as an
1437
+ // expected type but we run it through `wildApprox` to allow default
1438
+ // parameters like in `def mkList[T](value: T = 1): List[T]`.
1439
+ val defaultTp = defaultParamType
1440
+ val pt = inherited.orElse(wildApprox(defaultTp)).orElse(WildcardType ).widenExpr
1441
+ val tp = typedAheadRhs(pt).tpe
1442
+ if (defaultTp eq pt) && (tp frozen_<:< defaultTp) then
1443
+ // When possible, widen to the default getter parameter type to permit a
1444
+ // larger choice of overrides (see `default-getter.scala`).
1445
+ // For justification on the use of `@uncheckedVariance`, see
1446
+ // `default-getter-variance.scala`.
1447
+ AnnotatedType (defaultTp, Annotation (defn.UncheckedVarianceAnnot ))
1448
+ else tp.widenTermRefExpr.simplified match
1449
+ case ctp : ConstantType if isInlineVal => ctp
1450
+ case tp =>
1451
+ TypeComparer .widenInferred(tp, pt)
1452
+
1453
+ // Replace aliases to Unit by Unit itself. If we leave the alias in
1454
+ // it would be erased to BoxedUnit.
1455
+ def dealiasIfUnit (tp : Type ) = if (tp.isRef(defn.UnitClass )) defn.UnitType else tp
1448
1456
1449
1457
// Approximate a type `tp` with a type that does not contain skolem types.
1450
1458
val deskolemize = new ApproximatingTypeMap {
@@ -1455,7 +1463,7 @@ class Namer { typer: Typer =>
1455
1463
}
1456
1464
}
1457
1465
1458
- def cookedRhsType = deskolemize(dealiasIfUnit(widenRhs( rhsType) ))
1466
+ def cookedRhsType = deskolemize(dealiasIfUnit(rhsType))
1459
1467
def lhsType = fullyDefinedType(cookedRhsType, " right-hand side" , mdef.span)
1460
1468
// if (sym.name.toString == "y") println(i"rhs = $rhsType, cooked = $cookedRhsType")
1461
1469
if (inherited.exists)
0 commit comments