-
Notifications
You must be signed in to change notification settings - Fork 356
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
Support for general assertion frameworks #1497
Comments
Guava doesn't call |
In our code base (worked on by 100+ developers) Guava's Since I already prepared example code before finding this ticket, I'll leave it here as a(nother) motivating example. Consider this code:
These two methods are functionally equivalent, but the $ javac \
-J--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED \
-processorpath ~/.m2/repository/org/checkerframework/checker/3.8.0/checker-3.8.0.jar \
-cp $HOME/.m2/repository/com/google/guava/guava/30.0-j
re/guava-30.0-jre.jar:$HOME/.m2/repository/org/checkerframework/checker-qual/3.8.0/checker-qual-3.8.0.jar \
-processor org.checkerframework.checker.regex.RegexChecker \
Dummy.java
Dummy.java:9: error: [argument.type.incompatible] incompatible argument for parameter regex of compile.
return Pattern.compile(input);
^
found : String
required: @Regex String
1 error
shell returned 1 |
Stephan, thank you for our first confirmation that these methods are used in the wild. I appreciate it, and that enables us to increase the priority of this issue. For people not familiar with these Guava interfaces, all three behave the same, but they are intended to be called in different circumstances.
In your example, could you rewrite method Pattern compile1(@Regex String input) {
checkArgument(RegexUtil.isRegex(input), "Pattern '%s' is not a valid regex", input);
return Pattern.compile(input);
} That puts the method specification where it belongs (on the formal parameter type), while still providing run-time checks, and while suffering no false positives. I realize that doesn't handle |
@mernst thanks for the quick response. While in general a good idea, in my specific case adding |
From your description, it sounds like issuing a warning at the call site is the right thing, since the warning is a true positive. I suspect I'm missing something. Do you want your routine to take any input, and to throw an exception if the input is not a regular expression? It would be helpful if you could expand your example to a use case where writing |
In the absence of the
That's correct: I can't prevent the user from making a mistake, so the next best thing is to throw a helpful exception when they do. As a result
Hmm, I wonder whether we have different expectations about when Put another way: as a user I'd expect there to be "some" way to take arbitrary-but-well-formed user input and pass it to |
Thank you for the explanation. That is very helpful. I believe I now understand where our perspectives differ. When I write a program, I consider any user-visible exception to be a bug in the program. Your perspective is different: You don't want the Checker Framework to prevent all exceptions caused by illegal regular expressions. Rather, you want to guarantee that such exceptions only occur at certain source-code constructs (namely, A few more notes about my perspective, where I think we agree:
I'd like to find a way to make the Checker Framework support your use case. I have a few questions first. Question 1. Did I accurately characterize your point of view and the contract of the Question 2. If you are OK with throwing an exception, could you use the This code: return Pattern.compile(RegexUtil.asRegex(input)); is even shorter and simpler than your version: checkArgument(RegexUtil.isRegex(input), "Pattern '%s' is not a valid regex", input);
return Pattern.compile(input); and you mentioned that concision was your reason for preferring Question 3. Can you suppress the warning? That is the recommended approach when there are just a few potential exceptions that you don't want the Checker Framework to warn you about. Your Maybe these suggestions don't handle all your uses of |
Hi @mernst. Apologies for my slow response; it's been a busy week. Going over your questions:
Thanks a lot for all the help; while I feel that |
There are several frameworks that provide methods that take a boolean and throw an exception if the boolean is false. Instead of:
one might write:
Using Google Guava as an example: https://github.com/google/guava/blob/master/guava/src/com/google/common/base/Verify.java#L98
Methods like
Verify.verifyNotNull
https://github.com/google/guava/blob/master/guava/src/com/google/common/base/Verify.java#L137 can be annotated to require a non-null argument. (This was done in commit typetools/guava@eda5f9c .)Methods that take an arbitrary boolean should similarly be annotatable somehow.
One possibility
or maybe as a generalization of the existing https://github.com/typetools/checker-framework/blob/master/dataflow/src/org/checkerframework/dataflow/qual/TerminatesExecution.java
For
assert
we provide command-line flags to select whether they should be assumed enabled or disabled and require a special marker message"@AssumeAssertion(nullness)"
.This flexibility doesn't seem necessary for such libraries.
Implementing the logic for these new specifications should be easily generalizable from the existing handling of
assert
.The text was updated successfully, but these errors were encountered: