- 
          
 - 
                Notifications
    
You must be signed in to change notification settings  - Fork 198
 
          ✨ Add circular option to fc.letrec
          #6040
        
          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
base: main
Are you sure you want to change the base?
Conversation
          
 | 
    
          
@fast-check/ava
 @fast-check/expect-type
 fast-check
 @fast-check/jest
 @fast-check/packaged
 @fast-check/poisoning
 @fast-check/vitest
 @fast-check/worker
 commit:   | 
    
          Codecov Report❌ Patch coverage is  
 Additional details and impacted files@@            Coverage Diff             @@
##             main    #6040      +/-   ##
==========================================
- Coverage   95.98%   95.95%   -0.04%     
==========================================
  Files         212      212              
  Lines       10194    10299     +105     
  Branches     2765     2798      +33     
==========================================
+ Hits         9785     9882      +97     
- Misses        409      417       +8     
 Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
  | 
    
| 
           @dubzzz would you also be able to take a look at my "open questions" in my PR description, and give your thoughts? #6040 (comment)  | 
    
| 
           I'm not forgetting this PR. I just have a very very limited bandwidth at the moment. I promise I'll try to review and if needed provide you with feedback as soon as I find the time for it 🤗  | 
    
| 
           In the meantime, you can install it via: npm i https://pkg.pr.new/fast-check@6040 | 
    
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome work! Thanks a lot for the time you spent on this PR. I'd have a few requests before merging it:
- Drop any unmap code for now
 
Currently you provided an unmap code via poolsArb.map but none for nat().map, so it won't be enough. Let do it in a second time, it would probably help focusing the PR on the core feature.
- 
Move
derefPoolsinto a dedicated file and put a small test on it - 
Factorizing
letrecWithCyclesandletrecWithoutCycleswould be nice 
I have the feeling that "without" one could stop at return strictArbs; while the "with" would have to add its pools.
        
          
                packages/fast-check/test/unit/arbitrary/__test-helpers__/ArbitraryAssertions.ts
              
                Outdated
          
            Show resolved
            Hide resolved
        
      | for (const key in strictArbs) { | ||
| if (!safeHasOwnProperty(strictArbs, key)) { | ||
| // Prevents accidental iteration over properties inherited from an object’s prototype | ||
| continue; | ||
| } | ||
| const lazyAtKey: LazyArbitrary<unknown> | undefined = lazyArbs[key]; | ||
| const lazyArb = lazyAtKey !== undefined ? lazyAtKey : new LazyArbitrary(key); | ||
| lazyArb.underlying = noShrink(nat().map((index) => ({ [placeholderSymbol]: { key, index } }))); | ||
| lazyArbs[key] = lazyArb; | ||
| // eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
| poolArbs[key] = array(strictArbs[key]!, poolConstraints); | ||
| } | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personal note: Close to the non-cycle one. The difference is that non-cycle one was doing lazyArb.underlying = strictArbs[key]. Plus the pool.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I fell that up to this loop we could have the two codes being the same. The "with cycles" one could just be a follow up code not returning immediately but doing the extra stuff with pools and cie.
| 
           @dubzzz I think I've addressed things now (sorry, was busy for a while) The one thing we might want to think about is catching the scenario where we we accidentally don't replace some   | 
    
| 
           @gruhn since you seem to be around, curious if you have any thoughts on my comment above? I got a bit stuck on this point  | 
    
Description
Closes #6039
Checklist — Don't delete this checklist and make sure you do the following before opening the PR
pnpm run bumpand flag the impacts properlyAdvanced
Open questions:
circular: trueoption tofc.letrec#6039)// TODO: Do we need to clone here?in the PR code. If I do need to clone, then what should I be using to do that? Answer: I think we don't need cloning here as long as we implement shrinking correctlyplaceholderSymbol. I tried tracking them in a local set fromnat().map(...)and then deleting them later when we replace, and asserting we have zero after, but this was causing problems, so I'm probably missing something. This seems like a critical feature in order to ship thisassertProduceValuesShrinkableWithoutContextnorassertShrinkProducesSameValueWithoutInitialContextpass forcircular: true. Does that make sense? Should they pass? If so, then what am I doing wrong?