Use adapted bounds for method type arguments#1850
Conversation
There was a problem hiding this comment.
Pull request overview
This PR updates the Checker Framework’s method-invocation type argument checking to use viewpoint-adapted bounds for method type parameters, and adds a viewpoint test to exercise both explicit and inferred method type arguments against those adapted bounds.
Changes:
- Add
AnnotatedTypeFactory.methodTypeVariablesFromUse(...)to compute method type-parameter bounds in the invocation’s viewpoint. - Use the new adapted-bounds helper from
BaseTypeVisitor.visitMethodInvocation(...)when validating method type arguments. - Add a new viewpoint test covering explicit and inferred method type arguments with receiver-dependent bounds.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| framework/tests/viewpointtest/MethodTypeVariableBounds.java | New test cases for receiver-dependent method type parameter bounds under different receiver viewpoints. |
| framework/src/main/java/org/checkerframework/framework/type/AnnotatedTypeFactory.java | Introduces a helper to compute invocation-viewpoint-adapted method type parameter bounds. |
| framework/src/main/java/org/checkerframework/common/basetype/BaseTypeVisitor.java | Switches method invocation type-argument checking to use adapted bounds from the factory helper. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
AnnotatedTypeCopierWithReplacement skips executable type parameters, so adapted method/constructor type-variable bounds were discarded and inference still saw unadapted declaration bounds. Install the adapted declarations, drop the redundant post-check re-adaptation helper, and add constructor coverage.
| * Returns the receiver type used to viewpoint-adapt a method invocation. | ||
| * | ||
| * @param tree a method invocation tree | ||
| * @return the receiver type, or null if the invocation has no receiver |
There was a problem hiding this comment.
Cross-reference getReceiverType and explain differences!
| AnnotatedTypeMirror tv = combineTypeWithType(receiverType, typeVariable); | ||
| mappings.put(typeVariable, tv); | ||
| // Adapt type-variable declarations separately. AnnotatedTypeCopierWithReplacement does not | ||
| // replace executable type parameters (see its visitTypeVariable), so install the adapted |
There was a problem hiding this comment.
Shouldn't the AnnotatedTypeCopierWithReplacement do this? Do you understand the reasoning given there?
| for (AnnotatedTypeVariable typeVariable : typeVariables) { | ||
| AnnotatedTypeVariable adapted = | ||
| (AnnotatedTypeVariable) combineTypeWithType(receiverType, typeVariable); | ||
| mappings.put(typeVariable, adapted); |
There was a problem hiding this comment.
Do we still need to add it to the mapping? Why add it to the mapping if AnnotatedTypeCopierWithReplacement doesn't do anything with the method type variables?
Split from #1173.
Use viewpoint-adapted method type parameter bounds when checking method invocation type arguments.
Adds a viewpoint test covering explicit and inferred type arguments.