blob: dd941e20ef3980e8e3c0b761712d2f107762c9be (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
public aspect CallOverriding {
void foo() {
// make some calls!
Generic<Number> gn = new Generic<Number>();
SubGeneric<Double> sgd = new SubGeneric<Double>();
SubParameterized sp = new SubParameterized();
gn.foo(new Integer(5));
sgd.foo(new Double(5));
sp.foo("hi");
}
// if a type overrides a generic method from a supertype, changing the
// signature in the process (for example, is a generic subtype with a
// narrowed type variable, or extends a parameterized super class, or
// implements a parameterized interface), then a type pattern of
// OriginalDeclaringType.erasureOfOriginalSignature matches, and a
// type pattern of *.erasureOfOriginalSignature matches, but
// a type pattern OverridingType.erasureOfOriginalSignature DOES NOT
// MATCH.
declare warning : call(void *.foo(Object))
: "wildcard declaring type match on erasure";
declare warning : call(void Generic.foo(Object))
: "base declaring type match on erasure";
declare warning : call(void SubGeneric.foo(Object))
: "not expecting any matches";
declare warning : call(void SubGeneric.foo(Number))
: "sub type match on erasure";
declare warning : call(void SubParameterized.foo(Object))
: "not expecting any matches";
declare warning : call(void SubParameterized.foo(String))
: "parameterized match on erasure";
}
class Generic<T> {
int x = 0;
// call (void Generic.foo(Object))
// call (void *.foo(Object))
public void foo(T someObject) {
x = 1;
}
}
class SubGeneric<N extends Number> extends Generic<N> {
int y = 0;
// call(void Generic.foo(Object))
// call( void *.foo(Object))
// call(void SubGeneric.foo(Number))
// !call(void SubGeneric.foo(Object))
public void foo(N someObject) {
y = 1;
}
}
class SubParameterized extends Generic<String> {
int y = 0;
// call(void Generic.foo(Object))
// call( void *.foo(Object))
// call(void SubParameterized.foo(String))
// !call(void SubGeneric.foo(Object))
public void foo(String someObject) {
y = 1;
}
}
interface I<E> {
void bar(E anElement);
}
class ParameterizedI implements I<Double> {
int x;
void foo() {
ParameterizedI pi = new ParameterizedI();
pi.bar(5.0d);
}
// call(void I.bar(Object))
// call(void *.bar(Object))
// call(void ParameterizedI.bar(Double))
// !call(void ParameterizedI.bar(Object))
public void bar(Double d) {
x = 1;
}
static aspect ParameterizedChecker {
declare warning : call(void I.bar(Object)) : "erasure match on base interface";
declare warning : call(void *.bar(Object)) : "wildcard match on erasure";
declare warning : call(void ParameterizedI.bar(Double)) : "parameterized match";
declare warning : call(void ParameterizedI.bar(Object)) : "no match expected";
}
}
|