@@ -170,7 +170,10 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
170
170
171
171
val res =
172
172
if (paramFailed || (paramTp.isErroneous && {paramFailed = true ; true })) SearchFailure
173
- else inferImplicitFor(paramTp, fun, context, reportAmbiguous = context.reportErrors)
173
+ else {
174
+ inferImplicitFor(paramTp, fun, context, reportAmbiguous = context.reportErrors)
175
+ }
176
+
174
177
argResultsBuff += res
175
178
176
179
if (res.isSuccess) {
@@ -590,7 +593,6 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
590
593
* 4. Give getClass calls a more precise type based on the type of the target of the call.
591
594
*/
592
595
protected def stabilize (tree : Tree , pre : Type , mode : Mode , pt : Type ): Tree = {
593
-
594
596
// Side effect time! Don't be an idiot like me and think you
595
597
// can move "val sym = tree.symbol" before this line, because
596
598
// inferExprAlternative side-effects the tree's symbol.
@@ -828,7 +830,6 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
828
830
protected def adapt (tree : Tree , mode : Mode , pt : Type , original : Tree = EmptyTree ): Tree = {
829
831
def hasUndets = context.undetparams.nonEmpty
830
832
def hasUndetsInMonoMode = hasUndets && ! mode.inPolyMode
831
-
832
833
def adaptToImplicitMethod (mt : MethodType ): Tree = {
833
834
if (hasUndets) { // (9) -- should revisit dropped condition `hasUndetsInMonoMode`
834
835
// dropped so that type args of implicit method are inferred even if polymorphic expressions are allowed
@@ -965,20 +966,51 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
965
966
case _ => pt == WildcardType
966
967
}
967
968
969
+ // should be recursive for checking kind of all subtypes
970
+ def kpBadKindArityMatches (tparams : List [Symbol ], targs : List [Type ]): List [(Symbol , Type )] = {
971
+ tparams.zip(targs).flatMap { case (tparam, targ) =>
972
+ if (isAnyKind(tparam.tpe)) List ()
973
+ else if (! sameLength(targ.typeParams, tparam.typeParams)) List (tparam -> targ)
974
+ else kpBadKindArityMatches(tparam.typeParams, targ.typeParams.map(_.tpe))
975
+ }
976
+ }
977
+
968
978
// todo. It would make sense when mode.inFunMode to instead use
969
979
// tree setType tree.tpe.normalize
970
980
// when typechecking, say, TypeApply(Ident(`some abstract type symbol`), List(...))
971
981
// because otherwise Ident will have its tpe set to a TypeRef, not to a PolyType, and `typedTypeApply` will fail
972
982
// but this needs additional investigation, because it crashes t5228, gadts1 and maybe something else
973
983
if (mode.inFunMode)
974
984
tree
975
- else if (properTypeRequired && tree.symbol.typeParams.nonEmpty) // (7)
985
+ else if (properTypeRequired && tree.symbol.typeParams.nonEmpty) // (7)
976
986
MissingTypeParametersError (tree)
977
- else if (kindArityMismatch && ! kindArityMismatchOk) // (7.1) @M: check kind-arity
987
+ else if (kindArityMismatch && ! kindArityMismatchOk) // (7.1) @M: check kind-arity
978
988
KindArityMismatchError (tree, pt)
979
989
else tree match { // (6)
980
990
case TypeTree () => tree
981
- case _ => TypeTree (tree.tpe) setOriginal tree
991
+ case _ =>
992
+ if (settings.YkindPolymorphism ) {
993
+ // we exclude RefinedClasses because in kind-polymorphic cases, it can happen
994
+ // type Kinder.Aux[H, M, HL0] = Kinder[H]{type M = M; type Args = HL0} gives
995
+ // isRefinementClass:true tree.tpe.typeSymbol:<refinement of Test.Kinder[H]>
996
+ // tree.tpe.typeSymbol.typeParams:List()
997
+ // tree.tpe.typeArgs:List(H, M, HL0)
998
+ //
999
+ if (! tree.tpe.typeSymbol.isRefinementClass && tree.tpe.typeSymbol.typeParams.length == 0 && tree.tpe.typeArgs.length > 0 ) {
1000
+ KindPolymorphicKindArityMismatchError (original, tree.tpe, tree.tpe.typeArgs, List (), tree.tpe.typeSymbol.tpe)
1001
+ }
1002
+ else if (tree.tpe.typeSymbol.typeParams.length > tree.tpe.typeArgs.length && tree.tpe.typeArgs.length > 0 ) {
1003
+ // List() to have a nicer error msg
1004
+ KindPolymorphicKindArityMismatchError (original, tree.tpe, tree.tpe.typeArgs, List (), tree.tpe.typeSymbol.tpe)
1005
+ }
1006
+ else {
1007
+ val badKinds = kpBadKindArityMatches(tree.tpe.typeSymbol.typeParams, tree.tpe.typeArgs)
1008
+ if (badKinds.nonEmpty) {
1009
+ KindPolymorphicKindArityMismatchError (original, tree.tpe, tree.tpe.typeArgs, badKinds, tree.tpe.typeSymbol.tpe)
1010
+ } else TypeTree (tree.tpe) setOriginal tree
1011
+ }
1012
+ }
1013
+ else TypeTree (tree.tpe) setOriginal tree
982
1014
}
983
1015
}
984
1016
@@ -1103,11 +1135,13 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
1103
1135
// all in one fell swoop at the end of typedFunction?
1104
1136
val samAttach = inferSamType(tree, pt, mode)
1105
1137
1138
+
1106
1139
if (samAttach.samTp ne NoType ) tree.setType(samAttach.samTp).updateAttachment(samAttach)
1107
1140
else { // (15) implicit view application
1108
1141
val coercion =
1109
1142
if (context.implicitsEnabled) inferView(tree, tree.tpe, pt)
1110
1143
else EmptyTree
1144
+
1111
1145
if (coercion ne EmptyTree ) {
1112
1146
def msg = s " inferred view from ${tree.tpe} to $pt via $coercion: ${coercion.tpe}"
1113
1147
if (settings.logImplicitConv) context.echo(tree.pos, msg)
@@ -2270,6 +2304,11 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
2270
2304
val tpt1 = checkNoEscaping.privates(meth, typedType(ddef.tpt))
2271
2305
checkNonCyclic(ddef, tpt1)
2272
2306
ddef.tpt.setType(tpt1.tpe)
2307
+
2308
+ // AnyKind shouldn't be usable as a real type
2309
+ if (ddef.tpt.tpe eq definitions.AnyKindClass .tpe) {
2310
+ AnyKindTypeError (ddef.tpt)
2311
+ }
2273
2312
val typedMods = typedModifiers(ddef.mods)
2274
2313
var rhs1 =
2275
2314
if (ddef.name == nme.CONSTRUCTOR && ! ddef.symbol.hasStaticFlag) { // need this to make it possible to generate static ctors
@@ -4054,6 +4093,12 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
4054
4093
checkCheckable(tree, targs.head, scrutineeType, inPattern = false )
4055
4094
}
4056
4095
val resultpe = restpe.instantiateTypeParams(tparams, targs)
4096
+
4097
+ // when using YkindPolymorphism, in case resulType has been inferred to a Type Contructor or AnyKind,
4098
+ // let's inform with a nice error
4099
+ if (settings.YkindPolymorphism && (resultpe.resultType.typeParams.nonEmpty || (resultpe.resultType eq definitions.AnyKindClass ))) {
4100
+ InferredReturnTypeError (fun, resultpe)
4101
+ } else
4057
4102
// @M substitution in instantiateParams needs to be careful!
4058
4103
// @M example: class Foo[a] { def foo[m[x]]: m[a] = error("") } (new Foo[Int]).foo[List] : List[Int]
4059
4104
// @M --> first, m[a] gets changed to m[Int], then m gets substituted for List,
@@ -5106,17 +5151,24 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
5106
5151
if (sameLength(tparams, args)) {
5107
5152
// @M: kind-arity checking is done here and in adapt, full kind-checking is in checkKindBounds (in Infer)
5108
5153
val args1 = map2Conserve(args, tparams) { (arg, tparam) =>
5109
- def ptParams = Kind .FromParams (tparam.typeParams)
5110
-
5111
- // if symbol hasn't been fully loaded, can't check kind-arity except when we're in a pattern,
5112
- // where we can (we can't take part in F-Bounds) and must (SI-8023)
5113
- val pt = if (mode.typingPatternOrTypePat) {
5114
- tparam.initialize; ptParams
5154
+ // if in KindPolymorphism, let's check type is complete, that it is AnyKind and use the inTypeConstructorAllowed mode
5155
+ // in order to avoid ProperTypeRequired and let inference happen later
5156
+ if (settings.YkindPolymorphism && tparam.rawInfo.isComplete && isAnyKind(tparam.tpe)) {
5157
+ typedHigherKindedType(arg, mode)
5115
5158
}
5116
- else if (isComplete) ptParams
5117
- else Kind .Wildcard
5159
+ else {
5160
+ def ptParams = Kind .FromParams (tparam.typeParams)
5161
+
5162
+ // if symbol hasn't been fully loaded, can't check kind-arity except when we're in a pattern,
5163
+ // where we can (we can't take part in F-Bounds) and must (SI-8023)
5164
+ val pt = if (mode.typingPatternOrTypePat) {
5165
+ tparam.initialize; ptParams
5166
+ }
5167
+ else if (isComplete) ptParams
5168
+ else Kind .Wildcard
5118
5169
5119
- typedHigherKindedType(arg, mode, pt)
5170
+ typedHigherKindedType(arg, mode, pt)
5171
+ }
5120
5172
}
5121
5173
val argtypes = mapList(args1)(treeTpe)
5122
5174
@@ -5297,7 +5349,13 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
5297
5349
5298
5350
// @M maybe the well-kindedness check should be done when checking the type arguments conform to the type parameters' bounds?
5299
5351
val args1 = if (sameLength(args, tparams)) map2Conserve(args, tparams) {
5300
- (arg, tparam) => typedHigherKindedType(arg, mode, Kind .FromParams (tparam.typeParams))
5352
+ (arg, tparam) =>
5353
+ // if in KindPolymorphism, let's check type is complete, that it is AnyKind and use the inTypeConstructorAllowed mode
5354
+ // in order to avoid ProperTypeRequired and let inference happen later
5355
+ if (settings.YkindPolymorphism && tparam.rawInfo.isComplete && isAnyKind(tparam.tpe)) {
5356
+ typedHigherKindedType(arg, mode)
5357
+ }
5358
+ else typedHigherKindedType(arg, mode, Kind .FromParams (tparam.typeParams))
5301
5359
}
5302
5360
else {
5303
5361
// @M this branch is correctly hit for an overloaded polymorphic type. It also has to handle erroneous cases.
0 commit comments