Skip to content

Commit 1733d2e

Browse files
biboudislahodajmcimadamoreGavin BiermanBrian Goetz
committed
8303374: Implement JEP 455: Primitive Types in Patterns, instanceof, and switch (Preview)
Co-authored-by: Jan Lahoda <[email protected]> Co-authored-by: Maurizio Cimadamore <[email protected]> Co-authored-by: Gavin Bierman <[email protected]> Co-authored-by: Brian Goetz <[email protected]> Co-authored-by: Raffaello Giulietti <[email protected]> Co-authored-by: Aggelos Biboudis <[email protected]> Reviewed-by: vromero, jlahoda
1 parent 6697160 commit 1733d2e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+3558
-385
lines changed
Lines changed: 296 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,296 @@
1+
/*
2+
* Copyright (c) 2024, 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. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package java.lang.runtime;
26+
27+
/**
28+
* A testing conversion of a value is exact if it yields a result without loss
29+
* of information or throwing an exception. Otherwise, it is inexact. Some
30+
* conversions are always exact regardless of the value. These conversions are
31+
* said to be unconditionally exact.
32+
* <p>
33+
* For example, a conversion from {@code int} to {@code byte} for the value 10
34+
* is exact because the result, 10, is the same as the original value. In
35+
* contrast, if the {@code int} variable {@code i} stores the value 1000 then a
36+
* narrowing primitive conversion to {@code byte} will yield the result -24.
37+
* Loss of information has occurred: both the magnitude and the sign of the
38+
* result are different than those of the original value. As such, a conversion
39+
* from {@code int} to {@code byte} for the value 1000 is inexact. Finally a
40+
* widening primitive conversion from {@code byte} to {@code int} is
41+
* unconditionally exact because it will always succeed with no loss of
42+
* information about the magnitude of the numeric value.
43+
* <p>
44+
* The methods in this class provide the run-time support for the exactness
45+
* checks of testing conversions from a primitive type to primitive type. These
46+
* methods may be used, for example, by Java compiler implementations to
47+
* implement checks for {@code instanceof} and pattern matching runtime
48+
* implementations. Unconditionally exact testing conversions do not require a
49+
* corresponding action at run time and, for this reason, methods corresponding
50+
* to these exactness checks are omitted here.
51+
* <p>
52+
* The run time conversion checks examine whether loss of information would
53+
* occur if a testing conversion would be to be applied. In those cases where a
54+
* floating-point primitive type is involved, and the value of the testing
55+
* conversion is either signed zero, signed infinity or {@code NaN}, these
56+
* methods comply with the following:
57+
*
58+
* <ul>
59+
* <li>Converting a floating-point negative zero to an integer type is considered
60+
* inexact.</li>
61+
* <li>Converting a floating-point {@code NaN} or infinity to an integer type is
62+
* considered inexact.</li>
63+
* <li>Converting a floating-point {@code NaN} or infinity or signed zero to another
64+
* floating-point type is considered exact.</li>
65+
* </ul>
66+
*
67+
* @jls 5.7.1 Exact Testing Conversions
68+
* @jls 5.7.2 Unconditionally Exact Testing Conversions
69+
* @jls 15.20.2 The instanceof Operator
70+
*
71+
* @implNote Some exactness checks describe a test which can be redirected
72+
* safely through one of the existing methods. Those are omitted too (i.e.,
73+
* {@code byte} to {@code char} can be redirected to
74+
* {@link ExactConversionsSupport#isIntToCharExact(int)}, {@code short} to
75+
* {@code byte} can be redirected to
76+
* {@link ExactConversionsSupport#isIntToByteExact(int)} and similarly for
77+
* {@code short} to {@code char}, {@code char} to {@code byte} and {@code char}
78+
* to {@code short} to the corresponding methods that take an {@code int}).
79+
*
80+
* @since 23
81+
*/
82+
public final class ExactConversionsSupport {
83+
84+
private ExactConversionsSupport() { }
85+
86+
/**
87+
* Exactness method from int to byte
88+
* @param n value
89+
* @return true if and only if the passed value can be converted exactly to the target type
90+
*/
91+
public static boolean isIntToByteExact(int n) {return n == (int)(byte)n;}
92+
93+
/**
94+
* Exactness method from int to short
95+
* @param n value
96+
* @return true if and only if the passed value can be converted exactly to the target type
97+
*/
98+
public static boolean isIntToShortExact(int n) {return n == (int)(short)n;}
99+
100+
/**
101+
* Exactness method from int to char
102+
* @param n value
103+
* @return true if and only if the passed value can be converted exactly to the target type
104+
*/
105+
public static boolean isIntToCharExact(int n) {return n == (int)(char)n;}
106+
107+
/**
108+
* Exactness method from int to float
109+
* @param n value
110+
* @return true if and only if the passed value can be converted exactly to the target type
111+
*
112+
* @implSpec relies on the notion of representation equivalence defined in the
113+
* specification of the {@linkplain Double} class.
114+
*/
115+
public static boolean isIntToFloatExact(int n) {
116+
return n == (int)(float)n && n != Integer.MAX_VALUE;
117+
}
118+
/**
119+
* Exactness method from long to byte
120+
* @param n value
121+
* @return true if and only if the passed value can be converted exactly to the target type
122+
*/
123+
public static boolean isLongToByteExact(long n) {return n == (long)(byte)n;}
124+
125+
/**
126+
* Exactness method from long to short
127+
* @param n value
128+
* @return true if and only if the passed value can be converted exactly to the target type
129+
*/
130+
public static boolean isLongToShortExact(long n) {return n == (long)(short)n;}
131+
132+
/**
133+
* Exactness method from long to char
134+
* @param n value
135+
* @return true if and only if the passed value can be converted exactly to the target type
136+
*/
137+
public static boolean isLongToCharExact(long n) {return n == (long)(char)n;}
138+
139+
/**
140+
* Exactness method from long to int
141+
* @param n value
142+
* @return true if and only if the passed value can be converted exactly to the target type
143+
*/
144+
public static boolean isLongToIntExact(long n) {return n == (long)(int)n;}
145+
146+
/**
147+
* Exactness method from long to float
148+
* @param n value
149+
* @return true if and only if the passed value can be converted exactly to the target type
150+
* @implSpec relies on the notion of representation equivalence defined in the
151+
* specification of the {@linkplain Double} class.
152+
*/
153+
public static boolean isLongToFloatExact(long n) {
154+
return n == (long)(float)n && n != Long.MAX_VALUE;
155+
}
156+
157+
/**
158+
* Exactness method from long to double
159+
* @param n value
160+
* @return true if and only if the passed value can be converted exactly to the target type
161+
* @implSpec relies on the notion of representation equivalence defined in the
162+
* specification of the {@linkplain Double} class.
163+
*/
164+
public static boolean isLongToDoubleExact(long n) {
165+
return n == (long)(double)n && n != Long.MAX_VALUE;
166+
}
167+
168+
/**
169+
* Exactness method from float to byte
170+
* @param n value
171+
* @return true if and only if the passed value can be converted exactly to the target type
172+
* @implSpec relies on the notion of representation equivalence defined in the
173+
* specification of the {@linkplain Double} class.
174+
*/
175+
public static boolean isFloatToByteExact(float n) {
176+
return n == (float)(byte)n && !isNegativeZero(n);
177+
}
178+
179+
/**
180+
* Exactness method from float to short
181+
* @param n value
182+
* @return true if and only if the passed value can be converted exactly to the target type
183+
* @implSpec relies on the notion of representation equivalence defined in the
184+
* specification of the {@linkplain Double} class.
185+
*/
186+
public static boolean isFloatToShortExact(float n) {
187+
return n == (float)(short)n && !isNegativeZero(n);
188+
}
189+
190+
/**
191+
* Exactness method from float to char
192+
* @param n value
193+
* @return true if and only if the passed value can be converted exactly to the target type
194+
* @implSpec relies on the notion of representation equivalence defined in the
195+
* specification of the {@linkplain Double} class.
196+
*/
197+
public static boolean isFloatToCharExact(float n) {
198+
return n == (float)(char)n && !isNegativeZero(n);
199+
}
200+
201+
/**
202+
* Exactness method from float to int
203+
* @param n value
204+
* @return true if and only if the passed value can be converted exactly to the target type
205+
* @implSpec relies on the notion of representation equivalence defined in the
206+
* specification of the {@linkplain Double} class.
207+
*/
208+
public static boolean isFloatToIntExact(float n) {
209+
return n == (float)(int)n && n != 0x1p31f && !isNegativeZero(n);
210+
}
211+
212+
/**
213+
* Exactness method from float to long
214+
* @param n value
215+
* @return true if and only if the passed value can be converted exactly to the target type
216+
* @implSpec relies on the notion of representation equivalence defined in the
217+
* specification of the {@linkplain Double} class.
218+
*/
219+
public static boolean isFloatToLongExact(float n) {
220+
return n == (float)(long)n && n != 0x1p63f && !isNegativeZero(n);
221+
}
222+
223+
/**
224+
* Exactness method from double to byte
225+
* @param n value
226+
* @return true if and only if the passed value can be converted exactly to the target type
227+
* @implSpec relies on the notion of representation equivalence defined in the
228+
* specification of the {@linkplain Double} class.
229+
*/
230+
public static boolean isDoubleToByteExact(double n) {
231+
return n == (double)(byte)n && !isNegativeZero(n);
232+
}
233+
234+
/**
235+
* Exactness method from double to short
236+
* @param n value
237+
* @return true if and only if the passed value can be converted exactly to the target type
238+
* @implSpec relies on the notion of representation equivalence defined in the
239+
* specification of the {@linkplain Double} class.
240+
*/
241+
public static boolean isDoubleToShortExact(double n){
242+
return n == (double)(short)n && !isNegativeZero(n);
243+
}
244+
245+
/**
246+
* Exactness method from double to char
247+
* @param n value
248+
* @return true if and only if the passed value can be converted exactly to the target type
249+
* @implSpec relies on the notion of representation equivalence defined in the
250+
* specification of the {@linkplain Double} class.
251+
*/
252+
public static boolean isDoubleToCharExact(double n) {
253+
return n == (double)(char)n && !isNegativeZero(n);
254+
}
255+
256+
/**
257+
* Exactness method from double to int
258+
* @param n value
259+
* @return true if and only if the passed value can be converted exactly to the target type
260+
* @implSpec relies on the notion of representation equivalence defined in the
261+
* specification of the {@linkplain Double} class.
262+
*/
263+
public static boolean isDoubleToIntExact(double n) {
264+
return n == (double)(int)n && !isNegativeZero(n);
265+
}
266+
267+
/**
268+
* Exactness method from double to long
269+
* @param n value
270+
* @return true if and only if the passed value can be converted exactly to the target type
271+
* @implSpec relies on the notion of representation equivalence defined in the
272+
* specification of the {@linkplain Double} class.
273+
*/
274+
public static boolean isDoubleToLongExact(double n) {
275+
return n == (double)(long)n && n != 0x1p63 && !isNegativeZero(n);
276+
}
277+
278+
/**
279+
* Exactness method from double to float
280+
* @param n value
281+
* @return true if and only if the passed value can be converted exactly to the target type
282+
* @implSpec relies on the notion of representation equivalence defined in the
283+
* specification of the {@linkplain Double} class.
284+
*/
285+
public static boolean isDoubleToFloatExact(double n) {
286+
return n == (double)(float)n || n != n;
287+
}
288+
289+
private static boolean isNegativeZero(float n) {
290+
return Float.floatToRawIntBits(n) == Integer.MIN_VALUE;
291+
}
292+
293+
private static boolean isNegativeZero(double n) {
294+
return Double.doubleToRawLongBits(n) == Long.MIN_VALUE;
295+
}
296+
}

0 commit comments

Comments
 (0)