mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 22:34:27 +02:00
8320575: generic type information lost on mandated parameters of record's compact constructors
Co-authored-by: Chen Liang <liach@openjdk.org> Reviewed-by: jlahoda
This commit is contained in:
parent
253508b03a
commit
7bf1989f59
3 changed files with 399 additions and 29 deletions
|
@ -255,12 +255,17 @@ public abstract sealed class Executable extends AccessibleObject
|
|||
* represented by this object. Returns an array of length
|
||||
* 0 if the underlying executable takes no parameters.
|
||||
* Note that the constructors of some inner classes
|
||||
* may have an implicitly declared parameter in addition to
|
||||
* explicitly declared ones.
|
||||
* may have an {@linkplain java.compiler/javax.lang.model.util.Elements.Origin#MANDATED
|
||||
* implicitly declared} parameter in addition to explicitly
|
||||
* declared ones.
|
||||
* Also note that compact constructors of a record class may have
|
||||
* {@linkplain java.compiler/javax.lang.model.util.Elements.Origin#MANDATED
|
||||
* implicitly declared} parameters.
|
||||
*
|
||||
* @return the parameter types for the executable this object
|
||||
* represents
|
||||
*/
|
||||
@SuppressWarnings("doclint:reference") // cross-module links
|
||||
public abstract Class<?>[] getParameterTypes();
|
||||
|
||||
/**
|
||||
|
@ -280,18 +285,32 @@ public abstract sealed class Executable extends AccessibleObject
|
|||
* underlying executable takes no parameters. Note that the
|
||||
* constructors of some inner classes may have an implicitly
|
||||
* declared parameter in addition to explicitly declared ones.
|
||||
* Also note that as a <a
|
||||
* href="{@docRoot}/java.base/java/lang/reflect/package-summary.html#LanguageJvmModel">modeling
|
||||
* artifact</a>, the number of returned parameters can differ
|
||||
* Compact constructors of a record class may also have
|
||||
* {@linkplain java.compiler/javax.lang.model.util.Elements.Origin#MANDATED
|
||||
* implicitly declared} parameters,
|
||||
* but they are a special case and thus considered as if they had
|
||||
* been explicitly declared in the source.
|
||||
* Finally note that as a {@link java.lang.reflect##LanguageJvmModel
|
||||
* modeling artifact}, the number of returned parameters can differ
|
||||
* depending on whether or not generic information is present. If
|
||||
* generic information is present, only parameters explicitly
|
||||
* present in the source will be returned; if generic information
|
||||
* is not present, implicit and synthetic parameters may be
|
||||
* generic information is present, parameters explicitly
|
||||
* present in the source or parameters of compact constructors
|
||||
* of a record class will be returned.
|
||||
* Note that parameters of compact constructors of a record class are a special case,
|
||||
* as they are not explicitly present in the source, and its type will be returned
|
||||
* regardless of the parameters being
|
||||
* {@linkplain java.compiler/javax.lang.model.util.Elements.Origin#MANDATED
|
||||
* implicitly declared} or not.
|
||||
* If generic information is not present, implicit and synthetic parameters may be
|
||||
* returned as well.
|
||||
*
|
||||
* <p>If a formal parameter type is a parameterized type,
|
||||
* the {@code Type} object returned for it must accurately reflect
|
||||
* the actual type arguments used in the source code.
|
||||
* the actual type arguments used in the source code. This assertion also
|
||||
* applies to the parameters of compact constructors of a record class,
|
||||
* independently of them being
|
||||
* {@linkplain java.compiler/javax.lang.model.util.Elements.Origin#MANDATED
|
||||
* implicitly declared} or not.
|
||||
*
|
||||
* <p>If a formal parameter type is a type variable or a parameterized
|
||||
* type, it is created. Otherwise, it is resolved.
|
||||
|
@ -309,6 +328,7 @@ public abstract sealed class Executable extends AccessibleObject
|
|||
* the underlying executable's parameter types refer to a parameterized
|
||||
* type that cannot be instantiated for any reason
|
||||
*/
|
||||
@SuppressWarnings("doclint:reference") // cross-module links
|
||||
public Type[] getGenericParameterTypes() {
|
||||
if (hasGenericInformation())
|
||||
return getGenericInfo().getParameterTypes();
|
||||
|
@ -335,22 +355,34 @@ public abstract sealed class Executable extends AccessibleObject
|
|||
// If we have real parameter data, then we use the
|
||||
// synthetic and mandate flags to our advantage.
|
||||
if (realParamData) {
|
||||
final Type[] out = new Type[nonGenericParamTypes.length];
|
||||
final Parameter[] params = getParameters();
|
||||
int fromidx = 0;
|
||||
for (int i = 0; i < out.length; i++) {
|
||||
final Parameter param = params[i];
|
||||
if (param.isSynthetic() || param.isImplicit()) {
|
||||
// If we hit a synthetic or mandated parameter,
|
||||
// use the non generic parameter info.
|
||||
out[i] = nonGenericParamTypes[i];
|
||||
if (getDeclaringClass().isRecord() && this instanceof Constructor) {
|
||||
/* we could be seeing a compact constructor of a record class
|
||||
* its parameters are mandated but we should be able to retrieve
|
||||
* its generic information if present
|
||||
*/
|
||||
if (genericParamTypes.length == nonGenericParamTypes.length) {
|
||||
return genericParamTypes;
|
||||
} else {
|
||||
// Otherwise, use the generic parameter info.
|
||||
out[i] = genericParamTypes[fromidx];
|
||||
fromidx++;
|
||||
return nonGenericParamTypes.clone();
|
||||
}
|
||||
} else {
|
||||
final Type[] out = new Type[nonGenericParamTypes.length];
|
||||
final Parameter[] params = getParameters();
|
||||
int fromidx = 0;
|
||||
for (int i = 0; i < out.length; i++) {
|
||||
final Parameter param = params[i];
|
||||
if (param.isSynthetic() || param.isImplicit()) {
|
||||
// If we hit a synthetic or mandated parameter,
|
||||
// use the non generic parameter info.
|
||||
out[i] = nonGenericParamTypes[i];
|
||||
} else {
|
||||
// Otherwise, use the generic parameter info.
|
||||
out[i] = genericParamTypes[fromidx];
|
||||
fromidx++;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
return out;
|
||||
} else {
|
||||
// Otherwise, use the non-generic parameter data.
|
||||
// Without method parameter reflection data, we have
|
||||
|
@ -748,13 +780,18 @@ public abstract sealed class Executable extends AccessibleObject
|
|||
* Returns an array of length 0 if the method/constructor declares no
|
||||
* parameters.
|
||||
* Note that the constructors of some inner classes
|
||||
* may have an implicitly declared parameter in addition to
|
||||
* explicitly declared ones.
|
||||
* may have an
|
||||
* {@linkplain java.compiler/javax.lang.model.util.Elements.Origin#MANDATED
|
||||
* implicitly declared} parameter in addition to explicitly declared ones.
|
||||
* Also note that compact constructors of a record class may have
|
||||
* {@linkplain java.compiler/javax.lang.model.util.Elements.Origin#MANDATED
|
||||
* implicitly declared} parameters.
|
||||
*
|
||||
* @return an array of objects representing the types of the
|
||||
* formal parameters of the method or constructor represented by this
|
||||
* {@code Executable}
|
||||
*/
|
||||
@SuppressWarnings("doclint:reference") // cross-module links
|
||||
public AnnotatedType[] getAnnotatedParameterTypes() {
|
||||
return TypeAnnotationParser.buildAnnotatedTypes(getTypeAnnotationBytes0(),
|
||||
SharedSecrets.getJavaLangAccess().
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue