@@ -348,24 +348,6 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
348
348
}
349
349
}
350
350
351
- def checkParamsConvertible (tree : Tree , tpe0 : Type ): Unit = {
352
- def checkParamsConvertible0 (tpe : Type ) =
353
- tpe match {
354
- case MethodType (formals, restpe) =>
355
- /*
356
- if (formals.exists(_.typeSymbol == ByNameParamClass) && formals.length != 1)
357
- error(pos, "methods with `=>`-parameter can be converted to function values only if they take no other parameters")
358
- if (formals exists (isRepeatedParamType(_)))
359
- error(pos, "methods with `*`-parameters cannot be converted to function values");
360
- */
361
- if (tpe.isDependentMethodType)
362
- DependentMethodTpeConversionToFunctionError (tree, tpe)
363
- checkParamsConvertible(tree, restpe)
364
- case _ =>
365
- }
366
- checkParamsConvertible0(tpe0)
367
- }
368
-
369
351
/** Check that type of given tree does not contain local or private
370
352
* components.
371
353
*/
@@ -803,10 +785,10 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
803
785
* unless followed by explicit type application.
804
786
* (4) Do the following to unapplied methods used as values:
805
787
* (4.1) If the method has only implicit parameters pass implicit arguments
806
- * (4.2) otherwise, if `pt` is a function type and method is not a constructor,
807
- * convert to function by eta-expansion,
808
- * (4.3) otherwise, if the method is nullary with a result type compatible to `pt`
788
+ * (4.2) otherwise, if the method is nullary with a result type compatible to `pt`
809
789
* and it is not a constructor, apply it to ()
790
+ * (4.3) otherwise, if `pt` is a function type and method is not a constructor,
791
+ * convert to function by eta-expansion,
810
792
* otherwise issue an error
811
793
* (5) Convert constructors in a pattern as follows:
812
794
* (5.1) If constructor refers to a case class factory, set tree's type to the unique
@@ -900,62 +882,42 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
900
882
def instantiateToMethodType (mt : MethodType ): Tree = {
901
883
val meth = tree match {
902
884
// a partial named application is a block (see comment in EtaExpansion)
885
+ //
886
+ // TODO: document why we need to peel off one layer to begin with, and, if we do, why we don't need to recurse??
887
+ // (and why we don't need to look at the stats to make sure it's the block created by eta-expansion)
888
+ // I don't see how we call etaExpand on a constructor..
889
+ //
890
+ // I guess we don't need to recurse because the outer block and a nested block will refer to the same method
891
+ // after eta-expansion (if that's what generated these blocks), so we can just look at the outer one.
892
+ //
893
+ // How about user-written blocks? Can they ever have a MethodType?
903
894
case Block (_, tree1) => tree1.symbol
904
895
case _ => tree.symbol
905
896
}
906
897
907
898
def cantAdapt =
908
- if (context.implicitsEnabled) MissingArgsForMethodTpeError (tree, meth)
909
- else UnstableTreeError (tree)
910
-
911
- def emptyApplication : Tree = adapt(typed(Apply (tree, Nil ) setPos tree.pos), mode, pt, original)
899
+ if (context.implicitsEnabled) MissingArgsForMethodTpeError (tree, meth) else UnstableTreeError (tree)
912
900
913
901
// constructors do not eta-expand
914
902
if (meth.isConstructor) cantAdapt
915
- // (4.2) eta-expand method value when function or sam type is expected
916
- else if (isFunctionType(pt) || (! mt.params.isEmpty && samOf(pt).exists)) {
917
- // scala/bug#9536 `!mt.params.isEmpty &&`: for backwards compatibility with 2.11,
918
- // we don't adapt a zero-arg method value to a SAM
919
- // In 2.13, we won't do any eta-expansion for zero-arg methods, but we should deprecate first
920
-
921
- debuglog(s " eta-expanding $tree: ${tree.tpe} to $pt" )
922
- checkParamsConvertible(tree, tree.tpe)
923
-
924
- // method values (`m _`) are always eta-expanded (this syntax will disappear once we eta-expand regardless of expected type, at least for arity > 0)
925
- // a "naked" method reference (`m`) may or not be eta expanded -- currently, this depends on the expected type and the arity (the conditions for this are in flux)
926
- def isMethodValue = tree.getAndRemoveAttachment[MethodValueAttachment .type ].isDefined
927
- val nakedZeroAryMethod = mt.params.isEmpty && ! isMethodValue
928
-
929
- // scala/bug#7187 eta-expansion of zero-arg method value is deprecated
930
- // 2.13 will switch order of (4.3) and (4.2), always inserting () before attempting eta expansion
931
- // (This effectively disables implicit eta-expansion of 0-ary methods.)
932
- // See mind-bending stuff like scala/bug#9178
933
- if (nakedZeroAryMethod && settings.isScala213) emptyApplication
934
- else {
935
- // eventually, we will deprecate insertion of `()` (except for java-defined methods) -- this is already the case in dotty
936
- // Once that's done, we can more aggressively eta-expand method references, even if they are 0-arity
937
- // 2.13 will already eta-expand non-zero-arity methods regardless of expected type (whereas 2.12 requires a function-equivalent type)
938
- if (nakedZeroAryMethod && settings.isScala212) {
939
- currentRun.reporting.deprecationWarning(tree.pos, NoSymbol ,
940
- s " Eta-expansion of zero-argument methods is deprecated. To avoid this warning, write ${Function (Nil , Apply (tree, Nil ))}. " , " 2.12.0" )
941
- }
942
-
943
- val tree0 = etaExpand(context.unit, tree, this )
903
+ // (4.2) apply to empty argument list
904
+ else if (mt.params.isEmpty && (settings.isScala213 || ! isFunctionType(pt))) {
905
+ // Starting with 2.13, always insert `()`, regardless of expected type.
906
+ // On older versions, expected type must not be a FunctionN (can be a SAM)
907
+ //
908
+ // scala/bug#7187 deprecates eta-expansion of zero-arg method values (since 2.12; was never introduced for SAM types: scala/bug#9536).
909
+ // The next step is to also deprecate insertion of `()` (except for java-defined methods), as dotty already requires explicitly writing them.
910
+ // Once explicit application to () is required, we can more aggressively eta-expand method references, even if they are 0-arity
911
+ adapt(typed(Apply (tree, Nil ) setPos tree.pos), mode, pt, original)
912
+ }
913
+ // (4.3) eta-expand method value when function or sam type is expected (for experimentation, always eta-expand under 2.14 source level)
914
+ else if (isFunctionType(pt) || samOf(pt).exists || settings.isScala214) { // TODO: decide on `settings.isScala214`
915
+ if (settings.isScala212 && mt.params.isEmpty) // implies isFunctionType(pt)
916
+ currentRun.reporting.deprecationWarning(tree.pos, NoSymbol , " Eta-expansion of zero-argument methods is deprecated. " +
917
+ s " To avoid this warning, write ${Function (Nil , Apply (tree, Nil ))}. " , " 2.12.0" )
944
918
945
- // #2624: need to infer type arguments for eta expansion of a polymorphic method
946
- // context.undetparams contains clones of meth.typeParams (fresh ones were generated in etaExpand)
947
- // need to run typer on tree0, since etaExpansion sets the tpe's of its subtrees to null
948
- // can't type with the expected type, as we can't recreate the setup in (3) without calling typed
949
- // (note that (3) does not call typed to do the polymorphic type instantiation --
950
- // it is called after the tree has been typed with a polymorphic expected result type)
951
- if (hasUndets)
952
- instantiate(typed(tree0, mode), mode, pt)
953
- else
954
- typed(tree0, mode, pt)
955
- }
919
+ typedEtaExpansion(tree, mode, pt)
956
920
}
957
- // (4.3) apply to empty argument list
958
- else if (mt.params.isEmpty) emptyApplication
959
921
else cantAdapt
960
922
}
961
923
@@ -1645,7 +1607,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
1645
1607
map2(preSuperStats, preSuperVals)((ldef, gdef) => gdef.tpt setType ldef.symbol.tpe)
1646
1608
1647
1609
if (superCall1 == cunit) EmptyTree
1648
- else cbody2 match {
1610
+ else cbody2 match { // ???
1649
1611
case Block (_, expr) => expr
1650
1612
case tree => tree
1651
1613
}
@@ -3003,7 +2965,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
3003
2965
// This tree is the result from one of:
3004
2966
// - manual eta-expansion with named arguments (x => f(x));
3005
2967
// - wildcard-style eta expansion (`m(_, _,)`);
3006
- // - instantiateToMethodType adapting a tree of method type to a function type using etaExpand.
2968
+ // - (I don't think it can result from etaExpand, because we know the argument types there.)
3007
2969
//
3008
2970
// Note that method values are a separate thing (`m _`): they have the idiosyncratic shape
3009
2971
// of `Typed(expr, Function(Nil, EmptyTree))`
@@ -3082,6 +3044,23 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
3082
3044
}
3083
3045
}
3084
3046
3047
+ // #2624: need to infer type arguments for eta expansion of a polymorphic method
3048
+ // context.undetparams contains clones of meth.typeParams (fresh ones were generated in etaExpand)
3049
+ // need to run typer on tree0, since etaExpansion sets the tpe's of its subtrees to null
3050
+ // can't type with the expected type, as we can't recreate the setup in (3) without calling typed
3051
+ // (note that (3) does not call typed to do the polymorphic type instantiation --
3052
+ // it is called after the tree has been typed with a polymorphic expected result type)
3053
+ def typedEtaExpansion (tree : Tree , mode : Mode , pt : Type ): Tree = {
3054
+ debuglog(s " eta-expanding $tree: ${tree.tpe} to $pt" )
3055
+
3056
+ if (tree.tpe.isDependentMethodType) DependentMethodTpeConversionToFunctionError (tree, tree.tpe) // TODO: support this
3057
+ else {
3058
+ val expansion = etaExpand(context.unit, tree, this )
3059
+ if (context.undetparams.isEmpty) typed(expansion, mode, pt)
3060
+ else instantiate(typed(expansion, mode), mode, pt)
3061
+ }
3062
+ }
3063
+
3085
3064
def typedRefinement (templ : Template ): Unit = {
3086
3065
val stats = templ.body
3087
3066
namer.enterSyms(stats)
@@ -4613,14 +4592,6 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
4613
4592
treeCopy.New (tree, tpt1).setType(tp)
4614
4593
}
4615
4594
4616
- def functionTypeWildcard (arity : Int ): Type =
4617
- functionType(List .fill(arity)(WildcardType ), WildcardType )
4618
-
4619
- def checkArity (tree : Tree )(tp : Type ): tp.type = tp match {
4620
- case NoType => MaxFunctionArityError (tree); tp
4621
- case _ => tp
4622
- }
4623
-
4624
4595
4625
4596
/** Eta expand an expression like `m _`, where `m` denotes a method or a by-name argument
4626
4597
*
@@ -4633,9 +4604,12 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
4633
4604
*/
4634
4605
def typedEta (methodValue : Tree ): Tree = methodValue.tpe match {
4635
4606
case tp@ (MethodType (_, _) | PolyType (_, MethodType (_, _))) => // (1)
4636
- val formals = tp.params
4637
- if (isFunctionType(pt) || samMatchesFunctionBasedOnArity(samOf(pt), formals)) methodValue
4638
- else adapt(methodValue, mode, checkArity(methodValue)(functionTypeWildcard(formals.length)))
4607
+ val etaPt =
4608
+ if (pt ne WildcardType ) pt
4609
+ else functionType(tp.params.map(_ => WildcardType ), WildcardType ) orElse WildcardType // arity overflow --> NoType
4610
+
4611
+ // We know syntactically methodValue can't refer to a constructor because you can't write `this _` for that (right???)
4612
+ typedEtaExpansion(methodValue, mode, etaPt)
4639
4613
4640
4614
case TypeRef (_, ByNameParamClass , _) | NullaryMethodType (_) => // (2)
4641
4615
val pos = methodValue.pos
@@ -5420,14 +5394,19 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
5420
5394
// that typecheck must not trigger macro expansions, so we explicitly prohibit them
5421
5395
// however we cannot do `context.withMacrosDisabled`
5422
5396
// because `expr` might contain nested macro calls (see scala/bug#6673).
5423
- // Otherwise, eta-expand, passing the original tree, which is required in adapt
5424
- // for trees of the form `f() _`: if the method type takes implicits, the fallback
5425
- // strategy will use `f()`; else if not, original is used to distinguish an explicit
5426
- // method value from eta-expansion driven by an expected function type.
5397
+ // Otherwise, (check for dead code, and) eta-expand.
5427
5398
case MethodValue (expr) =>
5428
- typed1(suppressMacroExpansion(expr), mode, pt) match {
5399
+ // Need to type in FUNmode so that we accept a method type (which also means we can't use our pt),
5400
+ // this does mean no overloading is performed. The main reason to ignore pt and move to FUNmode is that
5401
+ // the `m` in `m _` could involve an implicit conversion, which will go through adapt after converting,
5402
+ // which will run afoul of the restriction that a method-typed tree is only allowed when a function type is expected.
5403
+ // We peeled off the `_` marker for the typed1 call, so we don't know that the user has requested eta-expansion.
5404
+ // See scala/bug#8299.
5405
+ val funTyped = typed1(suppressMacroExpansion(expr), mode | FUNmode , WildcardType )
5406
+ if (funTyped.tpe.isInstanceOf [OverloadedType ]) inferExprAlternative(funTyped, pt)
5407
+ funTyped match {
5429
5408
case macroDef if treeInfo.isMacroApplication(macroDef) => MacroEtaError (macroDef)
5430
- case methodValue => typedEta(checkDead(methodValue).updateAttachment( MethodValueAttachment ) )
5409
+ case methodValue => typedEta(checkDead(methodValue))
5431
5410
}
5432
5411
case Typed (expr, tpt) =>
5433
5412
val tpt1 = typedType(tpt, mode) // type the ascribed type first
0 commit comments