-
Notifications
You must be signed in to change notification settings - Fork 9
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
Safe oneOf
#94
Safe oneOf
#94
Conversation
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.
Copilot reviewed 1 out of 1 changed files in this pull request and generated no comments.
This is fun. This compiles: {"oneOf": [{"enum": [1,2,"foo"]}, {"enum": [2,3,"bar"]}], "type": "string"} This does not: {"oneOf": [{"enum": [1,2,"foo"]}, {"enum": [2,3,"bar"]}]} |
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.
Looks great!
}), | ||
_ => { | ||
// Except for in the cases above, it should suffice to check that the types are different | ||
mem::discriminant(self) != mem::discriminant(other) |
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.
Ha! I didn't know this existed!
Actually, on that note, maybe in future, Schema::Boolean should have value: Optional and we could drop LiteralBool? The same way numbers and strings are treated.
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.
Oh, duh. That's a good idea. 😂
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.
@mmoskal I think we really need to implement refs here (could be in the next PR), but we'll definitely have to be careful about ref cycles causing infinite loops. Maybe setting a max ref depth on this method would be an ok solution
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.
P.s. matching on RegexAst::Literal can replace the const_string check in your const_compile PR.
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 think we don't need to match on const anything - we just always compile strings as regexes and or them together with other options in AnyOf
Adds a method to check for "verifiable" schema disjointness (returns false if we're not really sure) and uses it to coerce oneOf to anyOf whenever it is provably safe to do so. This includes cases where objects have required properties that are themselves provably disjoint, covering discriminated unions.
We could probably take this one step farther and actually compute the difference between some schemas (e.g.
Schema::Boolean.subtract(Schema::LiteralBoolean{ true }) => Schema::LiteralBoolean{ false }
), but simply checking for disjointness covers some important cases.Closes (or at least contributes significant progress towards) #77