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

Improve cast warnings/errors logic #1049

Open
wants to merge 66 commits into
base: master
Choose a base branch
from

Conversation

Ao-senXiong
Copy link
Member

@Ao-senXiong Ao-senXiong commented Jan 5, 2025

Cherry-pick #337
Merge with eisop/guava#10

@wmdietl wmdietl changed the title Improve type cast Improve cast warnings/errors logic Jan 5, 2025
@Ao-senXiong Ao-senXiong requested a review from wmdietl January 6, 2025 02:06
@Ao-senXiong Ao-senXiong assigned wmdietl and unassigned Ao-senXiong Jan 6, 2025
Copy link
Member

@wmdietl wmdietl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for picking up this PR!

@@ -5,7 +5,7 @@ public class CastInit {

public CastInit() {
@UnknownInitialization CastInit t1 = (@UnknownInitialization CastInit) this;
// :: warning: (cast.unsafe)
// :: error: (cast.incomparable)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this change make sense to you? @UnknownInitialization is the top of this hierarchy and @Initialized is a subtype. So why isn't this still cast.unsafe?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this error message is for @Initialized CastInit t2 = (@Initialized CastInit) this; and as this is in the constructor, so this is @UnderInitialization and is casting to @Initialized, so the cast is incomparable.

@@ -13,7 +13,9 @@ void StringIsGBnothing(
@GuardSatisfied Object o3,
@GuardedByBottom Object o4) {
String s1 = (String) o1;
// :: error: (cast.incomparable)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is incompatible with the comment on line 9 - there should be no errors in this method.

@Signed Integer x = s.bar(local);
}

class Inner<T extends @UnknownSignedness Object> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you rename the type parameter T to make the code easier to read.

"cast.unsafe",
exprType.toString(true),
castType.toString(true));
} else if (castResult == TypecastKind.ERROR) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this only handle WARNING and ERROR and not also at least NOT_UPCAST?
It seems a bit odd to have the TypecastKind with five values if isTypeCastSafe only returns three of the options.
Can you think of cleaning up the logic and the enum to make this easier to follow? Maybe there should be two separate enums, one for isTypeCastSafe and one for isUpcast?

AnnotatedDeclaredType castDeclared = (AnnotatedDeclaredType) castType;
AnnotationMirrorSet bounds =
atypeFactory.getTypeDeclarationBounds(castDeclared.getUnderlyingType());
protected TypecastKind isTypeCastSafe(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A method that starts with is should usually return a boolean. Can you think of a more appropriate name?
We are already breaking all existing clients, so we might as well pick a better name.

@@ -168,9 +168,9 @@ public void intCastTest(@IntVal({0, 1}) int input) {
@IntVal({0, 1}) int c = (int) input;
@IntVal({0, 1}) int ac = (@IntVal({0, 1}) int) input;
@IntVal({0, 1, 2}) int sc = (@IntVal({0, 1, 2}) int) input;
// :: warning: (cast.unsafe)
// :: error: (cast.incomparable)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this a cast from "0 or 1" to "definitely 1", so a downcast? Why is this incomparable now?

@@ -12,7 +12,7 @@ public class Issue2367 {

// Without the `(byte)` cast, all of these produce the following javac error:
// error: incompatible types: possible lossy conversion from int to byte
// The Value Checker's `cast.unsafe` error is analogous and is desirable.
// The Value Checker's `cast.incomparable` error is analogous and is desirable.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also doesn't seem like this should be incomparable...

* @return whether the arguments are the same type variables
*/
public static boolean areSameTypeVariables(TypeVariable v1, TypeVariable v2) {
return v1.asElement().getSimpleName() == v2.asElement().getSimpleName();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems really undesirable. Two different type variable that have the same simple name "T" are not the same. Can you think of better logic for the single use of this function?

@wmdietl wmdietl assigned Ao-senXiong and unassigned wmdietl Jan 6, 2025
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.

3 participants