@@ -950,6 +950,29 @@ public void rawClass() {
950
950
.doTest ();
951
951
}
952
952
953
+ @ Ignore ("b/26797524 - add tests for generic arguments" )
954
+ @ Test
955
+ public void threadSafeTypeParam () {
956
+ compilationHelper
957
+ .addSourceLines (
958
+ "X.java" ,
959
+ "import com.google.common.collect.ImmutableList;" ,
960
+ "import com.google.errorprone.annotations.ThreadSafe;" ,
961
+ "public class X {" ,
962
+ " final ImmutableList<@ThreadSafeTypeParameter ?> unknownSafeType;" ,
963
+ " X (ImmutableList<@ThreadSafeTypeParameter ?> unknownSafeType) {" ,
964
+ " this.unknownSafeType = unknownSafeType;" ,
965
+ " }" ,
966
+ "}" )
967
+ .addSourceLines (
968
+ "Test.java" ,
969
+ "import com.google.common.collect.ImmutableList;" ,
970
+ "class Test {" ,
971
+ " final X badX = new X(ImmutableList.of(ImmutableList.<String>of()));" ,
972
+ "}" )
973
+ .doTest ();
974
+ }
975
+
953
976
@ Ignore ("b/26797524 - add tests for generic arguments" )
954
977
@ Test
955
978
public void mutableTypeParam () {
@@ -1001,6 +1024,78 @@ public void knownThreadSafeFlag() {
1001
1024
.doTest ();
1002
1025
}
1003
1026
1027
+ @ Test
1028
+ public void threadSafeTypeParameter () {
1029
+ compilationHelper
1030
+ .addSourceLines (
1031
+ "Test.java" ,
1032
+ "import com.google.errorprone.annotations.ThreadSafe;" ,
1033
+ "import com.google.errorprone.annotations.ThreadSafeTypeParameter;" ,
1034
+ "@ThreadSafe class Test<@ThreadSafeTypeParameter T> {" ,
1035
+ " final T t = null;" ,
1036
+ "}" )
1037
+ .doTest ();
1038
+ }
1039
+
1040
+ @ Test
1041
+ public void threadSafeTypeParameterInstantiation () {
1042
+ compilationHelper
1043
+ .addSourceLines (
1044
+ "A.java" ,
1045
+ "import com.google.errorprone.annotations.ThreadSafe;" ,
1046
+ "import com.google.errorprone.annotations.ThreadSafeTypeParameter;" ,
1047
+ "@ThreadSafe class A<@ThreadSafeTypeParameter T> {" ,
1048
+ "}" )
1049
+ .addSourceLines (
1050
+ "Test.java" ,
1051
+ "class Test {" ,
1052
+ " A<String> f() {" ,
1053
+ " return new A<>();" ,
1054
+ " }" ,
1055
+ " A<Object> g() {" ,
1056
+ " // BUG: Diagnostic contains: instantiation of 'T' is not "
1057
+ + "thread-safe, 'Object' is not thread-safe" ,
1058
+ " return new A<>();" ,
1059
+ " }" ,
1060
+ "}" )
1061
+ .doTest ();
1062
+ }
1063
+
1064
+ @ Test
1065
+ public void threadSafeTypeParameterUsage () {
1066
+ compilationHelper
1067
+ .addSourceLines (
1068
+ "Test.java" ,
1069
+ "import com.google.errorprone.annotations.ThreadSafeTypeParameter;" ,
1070
+ "class Test {" ,
1071
+ " static <@ThreadSafeTypeParameter T> void f() {}" ,
1072
+ "}" )
1073
+ .doTest ();
1074
+ }
1075
+
1076
+ @ Test
1077
+ public void threadSafeTypeParameterUsage_interface () {
1078
+ compilationHelper
1079
+ .addSourceLines (
1080
+ "Test.java" ,
1081
+ "import com.google.errorprone.annotations.ThreadSafe;" ,
1082
+ "import com.google.errorprone.annotations.ThreadSafeTypeParameter;" ,
1083
+ "@ThreadSafe interface Test<@ThreadSafeTypeParameter T> {" ,
1084
+ "}" )
1085
+ .doTest ();
1086
+ }
1087
+
1088
+ @ Test
1089
+ public void threadSafeTypeParameterMutableClass () {
1090
+ compilationHelper
1091
+ .addSourceLines (
1092
+ "Test.java" ,
1093
+ "import com.google.errorprone.annotations.ThreadSafeTypeParameter;" ,
1094
+ "// BUG: Diagnostic contains: @ThreadSafeTypeParameter is only supported on" ,
1095
+ "class A<@ThreadSafeTypeParameter T> {}" )
1096
+ .doTest ();
1097
+ }
1098
+
1004
1099
@ Test
1005
1100
public void annotatedClassType () {
1006
1101
compilationHelper
@@ -1015,10 +1110,65 @@ public void annotatedClassType() {
1015
1110
.doTest ();
1016
1111
}
1017
1112
1113
+ @ Test
1114
+ public void instantiationWithThreadSafeTypeParameter () {
1115
+ compilationHelper
1116
+ .addSourceLines (
1117
+ "Test.java" ,
1118
+ "import com.google.common.collect.ImmutableList;" ,
1119
+ "import com.google.errorprone.annotations.ThreadSafe;" ,
1120
+ "import com.google.errorprone.annotations.ThreadSafeTypeParameter;" ,
1121
+ "@ThreadSafe public class Test<@ThreadSafeTypeParameter T> {" ,
1122
+ " final ImmutableList<T> xs = ImmutableList.of();" ,
1123
+ "}" )
1124
+ .doTest ();
1125
+ }
1126
+
1018
1127
// Regression test for b/117937500
1128
+ @ Test
1129
+ public void notAllTypeVarsInstantiated () {
1130
+ compilationHelper
1131
+ .addSourceLines (
1132
+ "Test.java" ,
1133
+ "import com.google.errorprone.annotations.ThreadSafeTypeParameter;" ,
1134
+ "import java.util.function.Function;" ,
1135
+ "class Test {" ,
1136
+ " public final <A> void f1(A transform) {}" ,
1137
+ " public <B, @ThreadSafeTypeParameter C> C f2(Function<B, C> fn) {" ,
1138
+ " return null;" ,
1139
+ " }" ,
1140
+ " public final <D, E> void f3(Function<D, E> fn) {" ,
1141
+ " // BUG: Diagnostic contains: instantiation of 'C' is not thread-safe" ,
1142
+ " // 'E' is a non-thread-safe type variable" ,
1143
+ " f1(f2(fn));" ,
1144
+ " }" ,
1145
+ "}" )
1146
+ .doTest ();
1147
+ }
1019
1148
1020
1149
// javac does not instantiate type variables when they are not used for target typing, so we
1021
1150
// cannot check whether their instantiations are thread-safe.
1151
+ @ Ignore
1152
+ @ Test
1153
+ public void notAllTypeVarsInstantiated_shouldFail () {
1154
+ compilationHelper
1155
+ .addSourceLines (
1156
+ "Test.java" ,
1157
+ "import com.google.errorprone.annotations.ThreadSafeTypeParameter;" ,
1158
+ "import java.util.function.Function;" ,
1159
+ "class Test {" ,
1160
+ " public final <A> void f1(A transform) {}" ,
1161
+ " public <@ThreadSafeTypeParameter B, C> C f2(Function<B, C> fn) {" ,
1162
+ " return null;" ,
1163
+ " }" ,
1164
+ " public final <D, E> void f3(Function<D, E> fn) {" ,
1165
+ " // BUG: Diagnostic contains: instantiation of 'B' is not thread-safe" ,
1166
+ " // 'D' is a non-thread-safe type variable" ,
1167
+ " f1(f2(fn));" ,
1168
+ " }" ,
1169
+ "}" )
1170
+ .doTest ();
1171
+ }
1022
1172
1023
1173
@ Test
1024
1174
public void threadSafeUpperBound () {
0 commit comments