@@ -950,6 +950,29 @@ public void rawClass() {
950950 .doTest ();
951951 }
952952
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+
953976 @ Ignore ("b/26797524 - add tests for generic arguments" )
954977 @ Test
955978 public void mutableTypeParam () {
@@ -1001,6 +1024,78 @@ public void knownThreadSafeFlag() {
10011024 .doTest ();
10021025 }
10031026
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+
10041099 @ Test
10051100 public void annotatedClassType () {
10061101 compilationHelper
@@ -1015,10 +1110,65 @@ public void annotatedClassType() {
10151110 .doTest ();
10161111 }
10171112
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+
10181127 // 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+ }
10191148
10201149 // javac does not instantiate type variables when they are not used for target typing, so we
10211150 // 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+ }
10221172
10231173 @ Test
10241174 public void threadSafeUpperBound () {
0 commit comments