Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stack overflow regression of recursive arbOption #487

Closed
wants to merge 1 commit into from

Conversation

ashawley
Copy link
Contributor

@ashawley ashawley commented Jul 17, 2019

The change in #408 broke definitions of Arbitrary[X] where X is a class with a recursive Option value. One potential fix is to rollback #286 that was released in 1.14.0. Alternatively, we can just call-by-name the implicit Arbitrary of arbOption with Gen.delay, in case it is recursive.

@non
Copy link
Contributor

non commented Aug 6, 2019

I don't agree this is a legit test case.

Here's a very similar definition that does fine without the code as-is:

case class Recur(option: Option[Recur])

implicit def arbRecur: Arbitrary[Recur] =
  Arbitrary {
    Gen.lzy(Arbitrary.arbitrary[Option[Recur]]).map(Recur(_))
  }

An even more idiomatic version might look like this:

case class Recur(option: Option[Recur])

object Recur {
  implicit val arbRecur: Arbitrary[Recur] = {
    lazy val g: Gen[Recur] = Gen.lzy(Gen.option(g).map(Recur(_)))
    Arbitrary(g)
  }
}

I think it's reasonable to require people to use Gen.lzy when building circular generators. The fact that it happened to work previously without is something of a fluke.

@ashawley
Copy link
Contributor Author

ashawley commented Aug 6, 2019

I agree. That it worked before was a fluke. I guess the motivation was to produce a bug-fix release, and this would avoid a regression for existing test suites.

@ashawley ashawley changed the title Revert 90% weighting of Some Stack overflow regression of recursive arbOption Aug 6, 2019
@ashawley
Copy link
Contributor Author

ashawley commented Aug 6, 2019

Toying around with it further, it seems there is a way to avoid the stackoverflow regression for existing recursive definitions, but also keep the 90/10 weighting of Some/None.

@non
Copy link
Contributor

non commented Aug 6, 2019

@ashawley I'd prefer to keep the existing weighting since I think it's more likely to produce interesting data by default. OK to close this?

@ashawley
Copy link
Contributor Author

ashawley commented Aug 6, 2019

Have you looked at the new changes here? This preserves the existing weighting.

@ashawley
Copy link
Contributor Author

ashawley commented Aug 6, 2019

That, or I'm not understanding what you mean by "existing".

@non
Copy link
Contributor

non commented Aug 6, 2019

Aha, I see your update. Sorry for the confusion!

I'm still not convinced by this PR. There is a cost to using Gen.delay and I don't think every user of Arbitrary[Option[A]] should pay it so that the recursive definition in the test can avoid it.

As before, you could just rewrite your test to use delay instead:

implicit def arbRecur: Arbitrary[Recur] = Arbitrary {
  Gen.delay(Arbitrary.arbitrary[Option[Recur]])
    .map(Recur(_))
  }

My belief is that these kinds of self-referential Arbitrary instances are quite rare, and that it's fine to require this kind of rewrite. I agree that it's unfortunate that code that used to work may have to be modified, but I think it's likely to be a rare occurrence. The alternatives both seem worse to me: reverting the frequency means that most testing with options will end up being redundant, and adding this delay will slow down all tests that use arbitrary to generate options.

What do you think?

@ashawley
Copy link
Contributor Author

ashawley commented Aug 6, 2019

I'm happy to close. Again, I'm not invested in recursive Option, so I can't defend it. I'm trying to generate goodwill by avoiding a regression in bug fix release, and get ScalaCheck working again in the Community Build.

I'll reopen a new PR that captures the the idiomatic version you want to support going forward.

@ashawley ashawley closed this Aug 6, 2019
@non
Copy link
Contributor

non commented Aug 6, 2019

Perfect, thanks! I'm sorry to be so demanding, but I'm trying to step up into more of a maintainer-ish role here (to get things back on track).

@ashawley ashawley deleted the revert-option-weight branch August 31, 2019 21:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants