op meta: propagate sub-validation errors dropped by ValidationErrors::merge_all misuse - #259
Open
thedavidmeister wants to merge 2 commits into
Open
op meta: propagate sub-validation errors dropped by ValidationErrors::merge_all misuse#259thedavidmeister wants to merge 2 commits into
thedavidmeister wants to merge 2 commits into
Conversation
ValidationErrors::merge_all only keeps a child error whose errors carry kind Struct under the merged field key, so the raw BitInteger / RainString / Operand results passed by BitIntegerRange, OperandArgRange and Output were all discarded. bits [0,16] validated Ok despite MAX_BIT_INTEGER being 15, and Output::validate was unconditionally Ok. Closes #173 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Dropping either per-end merge leaves an is_err() assertion satisfied by the other end, so the keys themselves have to be asserted. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Warning Review limit reachedNext included review available in 3 minutes. View limit detailsLimit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #173.
The defect
validator 0.16.1'sValidationErrors::merge_all(parent, field, children)keeps a child result only when that child's errors carry aValidationErrorsKind::Structunder the keyfield— it is written for children the derive has already wrapped withValidationErrors::merge(Ok(()), field, elem.validate())(seevalidator_derive'swrap_if_collection). The three hand-rolled impls incrates/cli/src/meta/types/op/v1.rspassed rawBitInteger/Operand/RainStringresults instead, whose errors sit under their own field key ("value") with kindField.err.remove("range")/err.remove("output")therefore found nothing and every child error was filtered out.On main:
BitIntegerRange(BitInteger{0}, BitInteger{16}).validate()returnedOkeven thoughMAX_BIT_INTEGER == 15. Only themin <= maxparent check was live.OpMeta::try_from(br#"{"name":"add","inputs":[{"bits":[0,16]}]}"#.to_vec())returnedOk.Output::validatewas unconditionallyOk— its parent was the literalOk(())and all children were dropped, so aComputedoutput with an out-of-bounds range and a non-ASCII computation validated.OperandArgRange's per-operand children were dropped too.The fix
Each impl now merges its children the way
mergeis meant to be used — oneValidationErrors::merge(result, key, child.validate())per child, under a key distinct from the parent's own"range"key:BitIntegerRange→"min"/"max", on top of the existing"range"order check.OperandArgRange→"exact", or"min"/"max"on top of"range".Output→"exact", or"bits"/"computation".Distinct keys are load-bearing, not cosmetic.
ValidationErrors::add_nestedpanics on a non-vacant entry, so nesting a child under the same"range"key the order check already occupies would turn an out-of-order and out-of-bounds range into a panic rather than anErr.test_bit_integer_range_ends_validatedpins that case (range(255, 16)) and asserts all three keys are present.Nothing outside these three impls changes: the derive-generated nested
#[validate]paths already merged correctly, and no op meta fixture in the repo is newly rejected.QA
test_bit_integer_range_ends_validated,test_output_computed_sub_validation_propagates,test_opmeta_input_bits_validated,test_opmeta_output_bits_validated— each fails on base. Verified by reverting only the threeimpl Validatebodies toorigin/mainin the working tree while keeping this PR's test module (confirmed byte-identical to base: the diff vsorigin/mainfor the file started at themod testshunk, line 283) and runningcargo test -p rain-metadata --lib meta::types::op::v1→FAILED. 12 passed; 4 failed. With the fix in place:ok. 16 passed; 0 failed.BitIntegerRangemerge(result, "max", self.1.validate())→result— KILLED bytest_bit_integer_range_ends_validated,test_output_computed_sub_validation_propagates,test_opmeta_input_bits_validated,test_opmeta_output_bits_validated(4 failed).BitIntegerRangemerge(result, "min", self.0.validate())→ dropped — KILLED bytest_bit_integer_range_ends_validated(1 failed). This one survives anis_err()-only suite: with the order check live,mincan only be out of bounds whenmaxis too, so themaxmerge alone still yieldsErr. It is theerrors().contains_key("min")assertion that kills it — hence the second commit.Outputmerge(Ok(()), "bits", bits.validate())→Ok(())— KILLED bytest_output_computed_sub_validation_propagates,test_opmeta_output_bits_validated(2 failed).Outputmerge(result, "computation", computation.validate())→result— KILLED by the same two (2 failed).OperandArgRangeall three per-operand merges dropped — SURVIVES, and no test claims otherwise.OperandderivesValidatewith no constraint on itsu16, soOperand::validate()is vacuouslyOkand the merges cannot be observed. This is issue BitIntegerRange/OperandArgRange/Output validation drops all sub-validation errors (ValidationErrors::merge_all misuse) #173's ownP06and it stays alive; killing it needs a constraint onOperand, which is a separate question. The merge is corrected here for the same reason the type has aValidateimpl at all.MAX_BIT_INTEGER's doc — "BitIntegers cannot range past the size of an Operand in bits, zero indexed" — gives0..=15for au16operand, sobits [0,16]must fail;REGEX_RAIN_STRING("printable ASCII characters and whitespace") makes\u{2665}an invalidComputation. The merge semantics come from readingvalidator-0.16.1/src/types.rs(merge,merge_all,add_nested) andvalidator_derive-0.16.0/src/quoting.rs(wrap_if_collection), not from this file.BitIntegerRange(P03),OperandArgRange(P06),Output(P07). All three are fixed.P03andP07are covered by the new tests above.P06is covered by the fix but not by a test, for the reason stated in the mutations list and acknowledged in the issue itself ("currently unobservable becauseOperandderivesValidatewith no constraints"). The issue's triage note asks whether out-of-bounds ends should error at this layer: taken as yes, sinceBitIntegeralready declares#[validate(range(min = MIN_BIT_INTEGER, max = MAX_BIT_INTEGER))]and the doc states the bound — the impls were plainly trying to enforce it.The three
NOTE: … see rainlanguage/rain.metadata#173comments the companion AMT PR left at these spots are removed, since the assertions they were deferring are now made.🤖 Generated with Claude Code