1 /* 2 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @bug 8223305 8226522 27 * @summary Ensure proper errors are returned for yields. 28 * @compile/fail/ref=WrongYieldTest.out -XDrawDiagnostics -XDshould-stop.at=ATTR WrongYieldTest.java 29 */ 30 31 package t; 32 33 //ERROR - type called yield: 34 import t.WrongYieldTest.yield; 35 36 public class WrongYieldTest { 37 38 // ERROR - class called yield 39 class yield { } 40 41 // OK to have fields called yield 42 String[] yield = null; 43 44 // ERROR - field of type yield 45 yield y; 46 47 // OK to have methods called yield 48 // Nullary yield method 49 String[] yield() { 50 return null; 51 } 52 // Unary yield method 53 String[] yield(int i) { 54 return null; 55 } 56 // Binary yield method 57 String[] yield(int i, int j) { 58 return null; 59 } 60 61 // OK to declare a local called yield 62 void LocalDeclaration1() { 63 int yield; 64 } 65 // OK to declare and initialise a local called yield 66 void LocalDeclaration2() { 67 int yield = 42; 68 } 69 // ERROR can't refer to a local called yield in the initialiser 70 void LocalDeclaration3() { 71 int yield = yield + 1; 72 } 73 74 // OK yield gets interpreted as an identifier in a local declaration 75 void LocalDeclaration4(int i) { 76 int local = switch (i) { 77 default -> { 78 int yield = yield + 1; 79 yield 42; 80 } 81 }; 82 } 83 // OK - yield a local called yield 84 void LocalDeclaration5(int i) { 85 int yield = 42; 86 int temp = switch (i) { 87 default -> { 88 yield yield; 89 } 90 }; 91 } 92 93 void YieldTypedLocals(int i) { 94 // ERROR - Parsed as yield statement, and y1 is unknown 95 yield y1 = null; 96 // ..whereas.. 97 // ERROR - parsed as yield statement, which has no switch target 98 Object y1; 99 yield y1 = null; 100 101 // ERROR - Parsed as yield statement, and y2 is unknown 102 yield y2 = new yield(); 103 104 // OK - Parsed as yield statement that assigns local y 105 Object y; 106 Object o = switch (i) { 107 default : 108 yield y = null; 109 }; 110 111 // ERROR - Parsed as yield statement that assigns local y, 112 //but the initializer refers to restricted identifier: 113 Object y2; 114 Object o2 = switch (i) { 115 default : 116 yield y2 = new yield(); 117 }; 118 119 // ERROR - can not create an yield-valued local of type Object 120 Object y3 = new yield(); 121 122 // ERROR - can not create a final yield-valued local of type yield 123 final yield y4 = new yield(); 124 125 // ERROR - can create a non-final local of type yield using qualified typename 126 WrongYieldTest.yield y5 = new yield(); 127 128 } 129 130 void MethodInvocation(int i) { 131 132 // OK - can access a field called yield 133 String[] x = this.yield; 134 135 // ERROR - calling nullary yield method using simple name parsed as yield statement 136 yield(); 137 // OK - can call nullary yield method using qualified name 138 this.yield(); 139 140 // ERROR - Calling unary yield method using simple name is parsed as yield statement 141 yield(2); 142 // OK - calling unary yield method using qualified name 143 this.yield(2); 144 145 // ERROR - Calling binary yield method using simple name is parsed as yield statement 146 yield(2, 2); //error 147 // OK - calling binary yield method using qualified name 148 this.yield(2, 2); 149 150 // ERROR - nullary yield method as receiver is parsed as yield statement 151 yield().toString(); 152 // OK - nullary yield method as receiver using qualified name 153 this.yield().toString(); 154 155 // ERROR - unary yield method as receiver is parsed as yield statement 156 yield(2).toString(); 157 // OK - unary yield method as receiver using qualified name 158 this.yield(2).toString(); 159 160 // ERROR - binary yield method as receiver is parsed as yield statement 161 yield(2, 2).toString(); 162 // OK - binary yield method as receiver using qualified name 163 this.yield(2, 2).toString(); 164 165 // OK - yield method call is in an expression position 166 String str = yield(2).toString(); 167 168 169 170 //OK - yield is a variable 171 yield.toString(); 172 173 // OK - parsed as method call (with qualified local yield as receiver) 174 this.yield.toString(); 175 176 yield[0].toString(); //error 177 178 // OK - parsed as yield statement in switch expression 179 int j = switch (i) { 180 default: 181 yield(2); 182 }; 183 184 // ERROR - second yield is an unreachable statement. 185 x = switch (i) { 186 default: { 187 yield x = null; 188 yield null; 189 } 190 }; 191 } 192 193 private void yieldLocalVar1(int i) { 194 int yield = 0; 195 196 //OK - yield is a variable: 197 yield++; 198 yield--; 199 200 //ERROR - yield is a statement, but no enclosing switch expr: 201 yield ++i; 202 yield --i; 203 204 //OK - yield is a variable: 205 yield = 3; 206 207 //OK - yield is a variable: 208 for (int j = 0; j < 3; j++) 209 yield += 1; 210 211 //OK - yield is a variable and not at the beginning of the statement: 212 yieldLocalVar1(yield); 213 214 //ERROR - unqualified yield method invocation: 215 yieldLocalVar1(yield().length); 216 yieldLocalVar1(yield.class.getModifiers()); 217 } 218 219 private void yieldLocalVar2(int i) { 220 int[] yield = new int[1]; 221 222 //OK - yield is a variable: 223 yield[0] = 5; 224 } 225 226 private void lambda() { 227 SAM s = (yield y) -> {}; 228 } 229 230 interface SAM { 231 public void m(Object o); 232 } 233 }