@@ -1087,62 +1087,89 @@ object desugar {
1087
1087
* If the original pattern variable carries a type annotation, so does the corresponding
1088
1088
* ValDef or DefDef.
1089
1089
*/
1090
- def makePatDef (original : Tree , mods : Modifiers , pat : Tree , rhs : Tree )(using Context ): Tree = pat match {
1091
- case IdPattern (named, tpt) =>
1092
- derivedValDef(original, named, tpt, rhs, mods)
1093
- case _ =>
1094
- def isTuplePattern (arity : Int ): Boolean = pat match {
1095
- case Tuple (pats) if pats.size == arity =>
1096
- pats.forall(isVarPattern)
1097
- case _ => false
1098
- }
1099
- val isMatchingTuple : Tree => Boolean = {
1100
- case Tuple (es) => isTuplePattern(es.length)
1101
- case _ => false
1102
- }
1090
+ def makePatDef (original : Tree , mods : Modifiers , pat : Tree , rhs : Tree )(using Context ): Tree =
1103
1091
1104
- // We can only optimize `val pat = if (...) e1 else e2` if:
1105
- // - `e1` and `e2` are both tuples of arity N
1106
- // - `pat` is a tuple of N variables or wildcard patterns like `(x1, x2, ..., xN)`
1107
- val tupleOptimizable = forallResults(rhs, isMatchingTuple)
1092
+ def singleGivenPattern (named : Bind ) =
1093
+ val Bind (_, Typed (_, tpt)) = named : @ unchecked
1094
+ report.error(
1095
+ em """ please use an alias given, such as
1096
+ | ${hl(" given" )} ${tpt} = $rhs""" .stripMargin, original)
1097
+ derivedValDef(original, Ident (named.name).withSpan(pat.span), tpt, rhs, mods | Given | Lazy | Final )
1098
+
1099
+ pat match {
1100
+ case IdPattern (named, tpt) =>
1101
+ derivedValDef(original, named, tpt, rhs, mods)
1102
+ case Parens (named : Bind ) if named.mods.is(Given ) =>
1103
+ singleGivenPattern(named)
1104
+ case named : Bind if named.mods.is(Given ) =>
1105
+ singleGivenPattern(named)
1106
+ case _ =>
1107
+ def isTuplePattern (arity : Int ): Boolean = pat match {
1108
+ case Tuple (pats) if pats.size == arity =>
1109
+ pats.forall(pat => isVarPattern(pat) || isGivenPattern(pat))
1110
+ case _ => false
1111
+ }
1112
+ val isMatchingTuple : Tree => Boolean = {
1113
+ case Tuple (es) => isTuplePattern(es.length)
1114
+ case _ => false
1115
+ }
1108
1116
1109
- val vars =
1110
- if (tupleOptimizable) // include `_`
1111
- pat match {
1112
- case Tuple (pats) =>
1113
- pats.map { case id : Ident => id -> TypeTree () }
1117
+ // We can only optimize `val pat = if (...) e1 else e2` if:
1118
+ // - `e1` and `e2` are both tuples of arity N
1119
+ // - `pat` is a tuple of N variables or wildcard patterns like `(x1, x2, ..., xN)`
1120
+ val tupleOptimizable = forallResults(rhs, isMatchingTuple)
1121
+
1122
+ val vars =
1123
+ if (tupleOptimizable) // include `_`
1124
+ pat match {
1125
+ case Tuple (pats) =>
1126
+ pats.map {
1127
+ case id : Ident => id -> TypeTree ()
1128
+ case bind @ Bind (_, Typed (_, tpt)) => bind -> tpt
1129
+ }
1130
+ }
1131
+ else
1132
+ getVariables(pat) // no `_`
1133
+
1134
+ val ids = for ((named, _) <- vars) yield Ident (named.name)
1135
+ val caseDef = CaseDef (pat, EmptyTree , makeTuple(ids))
1136
+ val matchExpr =
1137
+ if (tupleOptimizable) rhs
1138
+ else Match (makeSelector(rhs, MatchCheck .IrrefutablePatDef ), caseDef :: Nil )
1139
+
1140
+ def defMods (named : NameTree , mods : Modifiers ) =
1141
+ named match {
1142
+ case named : Bind if named.mods.is(Given ) => mods | Given
1143
+ case _ => mods
1114
1144
}
1115
- else getVariables(pat) // no `_`
1116
-
1117
- val ids = for ((named, _) <- vars) yield Ident (named.name)
1118
- val caseDef = CaseDef (pat, EmptyTree , makeTuple(ids))
1119
- val matchExpr =
1120
- if (tupleOptimizable) rhs
1121
- else Match (makeSelector(rhs, MatchCheck .IrrefutablePatDef ), caseDef :: Nil )
1122
- vars match {
1123
- case Nil if ! mods.is(Lazy ) =>
1124
- matchExpr
1125
- case (named, tpt) :: Nil =>
1126
- derivedValDef(original, named, tpt, matchExpr, mods)
1127
- case _ =>
1128
- val tmpName = UniqueName .fresh()
1129
- val patMods =
1130
- mods & Lazy | Synthetic | (if (ctx.owner.isClass) PrivateLocal else EmptyFlags )
1131
- val firstDef =
1132
- ValDef (tmpName, TypeTree (), matchExpr)
1133
- .withSpan(pat.span.union(rhs.span)).withMods(patMods)
1134
- val useSelectors = vars.length <= 22
1135
- def selector (n : Int ) =
1136
- if useSelectors then Select (Ident (tmpName), nme.selectorName(n))
1137
- else Apply (Select (Ident (tmpName), nme.apply), Literal (Constant (n)) :: Nil )
1138
- val restDefs =
1139
- for (((named, tpt), n) <- vars.zipWithIndex if named.name != nme.WILDCARD )
1140
- yield
1141
- if (mods.is(Lazy )) derivedDefDef(original, named, tpt, selector(n), mods &~ Lazy )
1142
- else derivedValDef(original, named, tpt, selector(n), mods)
1143
- flatTree(firstDef :: restDefs)
1144
- }
1145
- }
1145
+
1146
+ vars match {
1147
+ case Nil if ! mods.is(Lazy ) =>
1148
+ matchExpr
1149
+ case (named, tpt) :: Nil =>
1150
+ derivedValDef(original, named, tpt, matchExpr, defMods(named, mods))
1151
+ case _ =>
1152
+ val tmpName = UniqueName .fresh()
1153
+ val patMods =
1154
+ mods & Lazy | Synthetic | (if (ctx.owner.isClass) PrivateLocal else EmptyFlags )
1155
+ val firstDef =
1156
+ ValDef (tmpName, TypeTree (), matchExpr)
1157
+ .withSpan(pat.span.union(rhs.span)).withMods(patMods)
1158
+ val useSelectors = vars.length <= 22
1159
+ def selector (n : Int ) =
1160
+ if useSelectors then Select (Ident (tmpName), nme.selectorName(n))
1161
+ else Apply (Select (Ident (tmpName), nme.apply), Literal (Constant (n)) :: Nil )
1162
+ val restDefs =
1163
+ for (((named, tpt), n) <- vars.zipWithIndex if named.name != nme.WILDCARD )
1164
+ yield
1165
+ val mods1 = defMods(named, mods)
1166
+ if (mods1.is(Lazy )) derivedDefDef(original, named, tpt, selector(n), mods1 &~ Lazy )
1167
+ else derivedValDef(original, named, tpt, selector(n), mods1)
1168
+ flatTree(firstDef :: restDefs)
1169
+ }
1170
+ }
1171
+
1172
+ end makePatDef
1146
1173
1147
1174
/** Expand variable identifier x to x @ _ */
1148
1175
def patternVar (tree : Tree )(using Context ): Bind = {
0 commit comments