Skip to content

Commit 22051f0

Browse files
authored
Make Whitespace a proper trait rather than function to avoid unwanted implicit conversions (#272)
Fixes #261, which is caused by the whitespace `P[_] => P[Unit]` implicits firing as implicit conversions rather than the implicit parameters they were originally intended to be. Since whitespace is meant to ignore failures, this caused failures caused by the `Fail.! : P[String]` to be ignored when implicitly converted to `P[Unit]` The fix is to create a proper `Whitespace` trait to inherit from. Note that this is a binary incompatible change. It's stacked on top of #271 for convenience, but should probably land separately after. The relevant changes are in this commit d87ab6d if anyone wants to look. Note that I moved the custom whitespace tests to a `scala2.12+` folder to skip them on 2.11. 2.11 does not support SAM conversion, which makes defining custom whitespaces a lot more boilerplatey. Can still be done, but no need to burden everyone with boilerplatey examples just to cater for the 2.11 folks in the test suite. Things are unlikely to break just for 2.11 anyway
1 parent ac05071 commit 22051f0

File tree

15 files changed

+241
-194
lines changed

15 files changed

+241
-194
lines changed

build.sc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,11 @@ trait CommonCrossModule extends CrossScalaModule with PublishModule {
205205
def platformSegment: String
206206
def millSourcePath = super.millSourcePath / os.up
207207
def sources = T.sources {
208-
super.sources().flatMap{p => Seq(p, PathRef(p.path / os.up / s"${p.path.last}-$platformSegment")) }
208+
super.sources()
209+
.flatMap{p => Seq(p, PathRef(p.path / os.up / s"${p.path.last}-$platformSegment")) } ++
210+
(if (scalaVersion() != scala211) {
211+
Seq(PathRef(millSourcePath / "src-2.12+"))
212+
} else Seq())
209213
}
210214
}
211215
trait CommonTestModule extends ScalaModule with TestModule.Utest{

fastparse/src-2/fastparse/internal/MacroImpls.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ object MacroImpls {
196196
def flatMapMacro[T: c.WeakTypeTag, V: c.WeakTypeTag]
197197
(c: Context)
198198
(f: c.Expr[T => ParsingRun[V]])
199-
(whitespace: c.Expr[ParsingRun[Any] => ParsingRun[Unit]]): c.Expr[ParsingRun[V]] = {
199+
(whitespace: c.Expr[fastparse.Whitespace]): c.Expr[ParsingRun[V]] = {
200200
import c.universe._
201201

202202
val lhs0 = c.prefix.asInstanceOf[c.Expr[EagerOps[T]]]
@@ -439,7 +439,7 @@ object MacroImpls {
439439
(c: Context)
440440
(rhs: c.Expr[ParsingRun[V]], cut: Boolean)
441441
(s: c.Expr[Implicits.Sequencer[T, V, R]],
442-
whitespace: Option[c.Expr[ParsingRun[Any] => ParsingRun[Unit]]],
442+
whitespace: Option[c.Expr[fastparse.Whitespace]],
443443
ctx: c.Expr[ParsingRun[_]]): c.Expr[ParsingRun[R]] = {
444444
import c.universe._
445445

@@ -708,7 +708,7 @@ object MacroImpls {
708708
(c: Context)
709709
(other: c.Expr[ParsingRun[V]])
710710
(s: c.Expr[Implicits.Sequencer[T, V, R]],
711-
whitespace: c.Expr[ParsingRun[Any] => ParsingRun[Unit]],
711+
whitespace: c.Expr[fastparse.Whitespace],
712712
ctx: c.Expr[ParsingRun[_]]): c.Expr[ParsingRun[R]] = {
713713
MacroImpls.parsedSequence0[T, V, R](c)(other, false)(s, Some(whitespace), ctx)
714714
}
@@ -717,7 +717,7 @@ object MacroImpls {
717717
(c: Context)
718718
(other: c.Expr[ParsingRun[V]])
719719
(s: c.Expr[Implicits.Sequencer[T, V, R]],
720-
whitespace: c.Expr[ParsingRun[Any] => ParsingRun[Unit]],
720+
whitespace: c.Expr[fastparse.Whitespace],
721721
ctx: c.Expr[ParsingRun[_]]): c.Expr[ParsingRun[R]] = {
722722
MacroImpls.parsedSequence0[T, V, R](c)(other, true)(s, Some(whitespace), ctx)
723723
}

fastparse/src-2/fastparse/package.scala

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ package object fastparse extends fastparse.SharedPackageDefs {
2121

2222
val P = ParsingRun
2323

24+
implicit def DiscardParserValue(p: P[_]): P[Unit] = {
25+
p.successValue = ()
26+
p.asInstanceOf[P[Unit]]
27+
}
28+
2429
/**
2530
* Parses an exact string value.
2631
*/
@@ -50,7 +55,7 @@ package object fastparse extends fastparse.SharedPackageDefs {
5055
*/
5156
def ~/[V, R](other: P[V])
5257
(implicit s: Implicits.Sequencer[T, V, R],
53-
whitespace: P[Any] => P[Unit],
58+
whitespace: Whitespace,
5459
ctx: P[_]): P[R] = macro MacroImpls.parsedSequenceCut[T, V, R]
5560

5661
/**
@@ -60,7 +65,7 @@ package object fastparse extends fastparse.SharedPackageDefs {
6065
*/
6166
def ~[V, R](other: P[V])
6267
(implicit s: Implicits.Sequencer[T, V, R],
63-
whitespace: P[Any] => P[Unit],
68+
whitespace: Whitespace,
6469
ctx: P[_]): P[R] = macro MacroImpls.parsedSequence[T, V, R]
6570

6671
/**
@@ -113,7 +118,7 @@ package object fastparse extends fastparse.SharedPackageDefs {
113118
* you next want to parse an array, dictionary or string.
114119
*/
115120
def flatMap[V](f: T => P[V])
116-
(implicit whitespace: P[Any] => P[Unit]): P[V] = macro MacroImpls.flatMapMacro[T, V]
121+
(implicit whitespace: Whitespace): P[V] = macro MacroImpls.flatMapMacro[T, V]
117122
/**
118123
* Transforms the result of this parser using the given function into a
119124
* new parser which is applied (without consuming whitespace). Useful for
@@ -163,7 +168,7 @@ package object fastparse extends fastparse.SharedPackageDefs {
163168
* index of the last run.
164169
*/
165170
def rep[V](implicit repeater: Implicits.Repeater[T, V],
166-
whitespace: P[_] => P[Unit],
171+
whitespace: Whitespace,
167172
ctx: P[Any]): P[V] = macro MacroRepImpls.repXMacro1ws[T, V]
168173
/**
169174
* Repeat operator; runs the LHS parser at least `min` to at most `max`
@@ -179,7 +184,7 @@ package object fastparse extends fastparse.SharedPackageDefs {
179184
max: Int = Int.MaxValue,
180185
exactly: Int = -1)
181186
(implicit repeater: Implicits.Repeater[T, V],
182-
whitespace: P[_] => P[Unit],
187+
whitespace: Whitespace,
183188
ctx: P[Any]): P[V] =
184189
new RepImpls[T](parse0).rep[V](min, sep, max, exactly)
185190

@@ -192,7 +197,7 @@ package object fastparse extends fastparse.SharedPackageDefs {
192197
def rep[V](min: Int,
193198
sep: => P[_])
194199
(implicit repeater: Implicits.Repeater[T, V],
195-
whitespace: P[_] => P[Unit],
200+
whitespace: Whitespace,
196201
ctx: P[Any]): P[V] =
197202
new RepImpls[T](parse0).rep[V](min, sep)
198203

@@ -204,7 +209,7 @@ package object fastparse extends fastparse.SharedPackageDefs {
204209
*/
205210
def rep[V](min: Int)
206211
(implicit repeater: Implicits.Repeater[T, V],
207-
whitespace: P[_] => P[Unit],
212+
whitespace: Whitespace,
208213
ctx: P[Any]): P[V] =
209214
macro MacroRepImpls.repXMacro2ws[T, V]
210215

fastparse/src-3/fastparse/internal/MacroInlineImpls.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ object MacroInlineImpls {
135135

136136
def parsedSequence0[T: Type, V: Type, R: Type](lhs: Expr[ParsingRun[T]], rhs: Expr[ParsingRun[V]], cut: Boolean)(
137137
s: Expr[Implicits.Sequencer[T, V, R]],
138-
whitespace: Null | Expr[ParsingRun[Any] => ParsingRun[Unit]],
138+
whitespace: Null | Expr[fastparse.Whitespace],
139139
ctx: Expr[ParsingRun[_]]
140140
)(using quotes: Quotes): Expr[ParsingRun[R]] = {
141141
import quotes.reflect.*
@@ -283,7 +283,7 @@ object MacroInlineImpls {
283283

284284
inline def flatMapInline[T, V](
285285
lhs: ParsingRun[T]
286-
)(inline f: T => ParsingRun[V])(ws: ParsingRun[Any] => ParsingRun[Unit]): ParsingRun[V] = {
286+
)(inline f: T => ParsingRun[V])(ws: fastparse.Whitespace): ParsingRun[V] = {
287287
if (!lhs.isSuccess) lhs.asInstanceOf[ParsingRun[V]]
288288
else {
289289
val oldCapturing = lhs.noDropBuffer

fastparse/src-3/fastparse/internal/MacroRepImpls.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import scala.quoted.*
1818
object MacroRepImpls {
1919
def repXMacro0[T: Type, V: Type](
2020
lhs: Expr[ParsingRun[T]],
21-
whitespace: Null | Expr[ParsingRun[_] => ParsingRun[Unit]],
21+
whitespace: Null | Expr[fastparse.Whitespace],
2222
min: Null | Expr[Int],
2323
)(repeater: Expr[Implicits.Repeater[T, V]], ctx: Expr[ParsingRun[_]])(using quotes: Quotes): Expr[ParsingRun[V]] = {
2424
import quotes.reflect.*

fastparse/src-3/fastparse/package.scala

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ package object fastparse extends fastparse.SharedPackageDefs {
1414

1515
val P = ParsingRun
1616

17+
implicit def DiscardParserValue(p: P[_]): P[Unit] = {
18+
p.successValue = ()
19+
p.asInstanceOf[P[Unit]]
20+
}
21+
1722
/** Delimits a named parser. This name will appear in the parser failure
1823
* messages and stack traces, and by default is taken from the name of the
1924
* enclosing method.
@@ -78,7 +83,7 @@ package object fastparse extends fastparse.SharedPackageDefs {
7883
* character to see if it's a `[`, `{`, or `"`, and then deciding whether
7984
* you next want to parse an array, dictionary or string.
8085
*/
81-
inline def flatMap[V](f: T => P[V])(using whitespace: P[Any] => P[Unit]): P[V] =
86+
inline def flatMap[V](f: T => P[V])(using whitespace: Whitespace): P[V] =
8287
MacroInlineImpls.flatMapInline[T, V](parse0)(f)(whitespace)
8388

8489
/** Capture operator; makes the parser return the span of input it parsed
@@ -94,7 +99,7 @@ package object fastparse extends fastparse.SharedPackageDefs {
9499
*/
95100
inline def ~/[V, R](inline other: P[V])(using
96101
s: Implicits.Sequencer[T, V, R],
97-
whitespace: P[Any] => P[Unit],
102+
whitespace: Whitespace,
98103
ctx: P[_]
99104
): P[R] = ${ MacroInlineImpls.parsedSequence0[T, V, R]('parse0, 'other, true)('s, 'whitespace, 'ctx) }
100105

@@ -104,7 +109,7 @@ package object fastparse extends fastparse.SharedPackageDefs {
104109
*/
105110
inline def ~[V, R](inline other: P[V])(using
106111
s: Implicits.Sequencer[T, V, R],
107-
whitespace: P[Any] => P[Unit],
112+
whitespace: Whitespace,
108113
ctx: P[_]
109114
): P[R] =
110115
${ MacroInlineImpls.parsedSequence0[T, V, R]('parse0, 'other, false)('s, 'whitespace, 'ctx) }
@@ -129,7 +134,7 @@ package object fastparse extends fastparse.SharedPackageDefs {
129134
* a `Seq[T]` of the parsed values. On failure, backtracks to the starting
130135
* index of the last run.
131136
*/
132-
inline def rep[V](using repeater: Implicits.Repeater[T, V], whitespace: P[_] => P[Unit], ctx: P[Any]): P[V] =
137+
inline def rep[V](using repeater: Implicits.Repeater[T, V], whitespace: Whitespace, ctx: P[Any]): P[V] =
133138
${ MacroRepImpls.repXMacro0[T, V]('parse0, 'whitespace, null)('repeater, 'ctx) }
134139

135140
/** Raw repeat operator; runs the LHS parser 0 or more times *without*
@@ -145,7 +150,7 @@ package object fastparse extends fastparse.SharedPackageDefs {
145150
// * and returns a `Seq[T]` of the parsed values. On
146151
// * failure, backtracks to the starting index of the last run.
147152
// */
148-
// inline def rep[V](inline min: Int)(using repeater: Implicits.Repeater[T, V], whitespace: P[_] => P[Unit], ctx: P[Any]): P[V] =
153+
// inline def rep[V](inline min: Int)(using repeater: Implicits.Repeater[T, V], whitespace: Whitespace, ctx: P[Any]): P[V] =
149154
// ${ MacroRepImpls.repXMacro0[T, V]('parse0, 'whitespace, 'min)('repeater, 'ctx) }
150155

151156
/// ** Raw repeat operator; runs the LHS parser at least `min`
@@ -175,7 +180,7 @@ package object fastparse extends fastparse.SharedPackageDefs {
175180
exactly: Int = -1
176181
)(using
177182
repeater: Implicits.Repeater[T, V],
178-
whitespace: P[_] => P[Unit],
183+
whitespace: Whitespace,
179184
ctx: P[Any]
180185
): P[V] =
181186
if max == Int.MaxValue && exactly == -1

0 commit comments

Comments
 (0)