Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ public Error disabledError(JavaFileObject classfile, int majorVersion) {
* @return true iff sym has been declared using a preview language feature
*/
public boolean declaredUsingPreviewFeature(Symbol sym) {
return false;
return sym.isValueClass();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this include records too given how its semantics are changed? Maybe in another RFE?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not completely certain, but I think this should not include records.

My understanding is that for records, only the implementation of the record's constructor changes, and that this is transparent(?) for the users of the record. I.e. the change not in the declaration/signatures, but in the implementation. If a class, e.g. PM, uses a preview feature inside an implementation only (i.e. not in a declaration), we don't taint another class, e.g. Use, that only uses PM.

For example:

$ cat PM.java 
public class PM {
    private boolean test(Object o) {
        return o instanceof byte b;
    }
}
$ cat Use.java 
public class Use {
    PM pm;
}
$ javac --enable-preview --source 28 -Xlint:preview PM.java Use.java
PM.java:3: warning: [preview] primitive patterns are a preview feature and may be removed in a future release.
        return o instanceof byte b;
                            ^
1 warning

There's no warning for the use of PM in Use, and Use.class is not marked a preview classfile.

Even though PM uses a preview feature (primitive patterns), it only does so inside an implementation, and so the use of the preview feature is invisible to the use site, leading to no warning.

My understanding (possibly wrong) is that the change in record constructors is similar to the use of pattern matching in the implementation of PM.

}

public void checkSourceLevel(DiagnosticPosition pos, Feature feature) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1002,9 +1002,6 @@ void writeField(VarSymbol v) {
Type fldType = v.erasure(types);
if (fldType.requiresLoadableDescriptors(v.owner)) {
poolWriter.enterLoadableDescriptorsClass(fldType.tsym);
if (preview.isPreview(Source.Feature.VALUE_CLASSES)) {
preview.markUsesPreview(null);
}
}
int acountIdx = beginAttrs();
int acount = 0;
Expand Down Expand Up @@ -1035,17 +1032,11 @@ void writeMethod(MethodSymbol m) {
for (Type t : mtype.getParameterTypes()) {
if (t.requiresLoadableDescriptors(m.owner)) {
poolWriter.enterLoadableDescriptorsClass(t.tsym);
if (preview.isPreview(Source.Feature.VALUE_CLASSES)) {
preview.markUsesPreview(null);
}
}
}
Type returnType = mtype.getReturnType();
if (returnType.requiresLoadableDescriptors(m.owner)) {
poolWriter.enterLoadableDescriptorsClass(returnType.tsym);
if (preview.isPreview(Source.Feature.VALUE_CLASSES)) {
preview.markUsesPreview(null);
}
}
int acountIdx = beginAttrs();
int acount = 0;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -41,9 +41,11 @@
import java.lang.classfile.ClassFile;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

import com.sun.tools.javac.util.Assert;

import toolbox.Task.OutputKind;
import toolbox.TestRunner;
import toolbox.ToolBox;

Expand Down Expand Up @@ -81,24 +83,53 @@ class Ident {
Path classes = base.resolve("classes");
tb.createDirectories(classes);

new toolbox.JavacTask(tb)
.options("--enable-preview", "-source", Integer.toString(Runtime.version().feature()))
List<String> log;
List<String> expected;

expected = List.of(
"Ident.java:2:5: compiler.warn.declared.using.preview: kindname.class, Val",
"Val.java:1:1: compiler.warn.preview.feature.use.plural: (compiler.misc.feature.value.classes)",
"2 warnings"
);

log = new toolbox.JavacTask(tb)
.options("--enable-preview",
"-source", Integer.toString(Runtime.version().feature()),
"-XDrawDiagnostics",
"-Xlint:preview")
.outdir(classes)
.files(findJavaFiles(src))
.run()
.writeAll();
.writeAll()
.getOutputLines(OutputKind.DIRECT);

tb.checkEqual(log, expected);

Path classFilePath = classes.resolve("Ident.class");
var classFile = ClassFile.of().parse(classFilePath);
Assert.check(classFile.minorVersion() == 65535);
Assert.check(classFile.findAttribute(Attributes.loadableDescriptors()).isPresent());

expected = List.of(
"- compiler.warn.preview.feature.use.classfile: Val.class, 28",
"Ident.java:2:5: compiler.warn.declared.using.preview: kindname.class, Val",
"2 warnings"
);

// now with the value class in the classpath
new toolbox.JavacTask(tb)
.options("--enable-preview", "-source", Integer.toString(Runtime.version().feature()), "-cp", classes.toString())
log = new toolbox.JavacTask(tb)
.options("--enable-preview",
"-source", Integer.toString(Runtime.version().feature()),
"-cp", classes.toString(),
"-XDrawDiagnostics",
"-Xlint:preview")
.outdir(classes)
.files(src.resolve("Ident.java"))
.run()
.writeAll();
.writeAll()
.getOutputLines(OutputKind.DIRECT);

tb.checkEqual(log, expected);

classFilePath = classes.resolve("Ident.class");
classFile = ClassFile.of().parse(classFilePath);
Expand All @@ -121,24 +152,53 @@ void m(Val val) {}
Path classes = base.resolve("classes");
tb.createDirectories(classes);

new toolbox.JavacTask(tb)
.options("--enable-preview", "-source", Integer.toString(Runtime.version().feature()))
List<String> log;
List<String> expected;

expected = List.of(
"Ident.java:2:12: compiler.warn.declared.using.preview: kindname.class, Val",
"Val.java:1:1: compiler.warn.preview.feature.use.plural: (compiler.misc.feature.value.classes)",
"2 warnings"
);

log = new toolbox.JavacTask(tb)
.options("--enable-preview",
"-source", Integer.toString(Runtime.version().feature()),
"-XDrawDiagnostics",
"-Xlint:preview")
.outdir(classes)
.files(findJavaFiles(src))
.run()
.writeAll();
.writeAll()
.getOutputLines(OutputKind.DIRECT);

tb.checkEqual(log, expected);

Path classFilePath = classes.resolve("Ident.class");
var classFile = ClassFile.of().parse(classFilePath);
Assert.check(classFile.minorVersion() == 65535);
Assert.check(classFile.findAttribute(Attributes.loadableDescriptors()).isPresent());

expected = List.of(
"- compiler.warn.preview.feature.use.classfile: Val.class, 28",
"Ident.java:2:12: compiler.warn.declared.using.preview: kindname.class, Val",
"2 warnings"
);

// now with the value class in the classpath
new toolbox.JavacTask(tb)
.options("--enable-preview", "-source", Integer.toString(Runtime.version().feature()), "-cp", classes.toString())
log = new toolbox.JavacTask(tb)
.options("--enable-preview",
"-source", Integer.toString(Runtime.version().feature()),
"-cp", classes.toString(),
"-XDrawDiagnostics",
"-Xlint:preview")
.outdir(classes)
.files(src.resolve("Ident.java"))
.run()
.writeAll();
.writeAll()
.getOutputLines(OutputKind.DIRECT);

tb.checkEqual(log, expected);

classFilePath = classes.resolve("Ident.class");
classFile = ClassFile.of().parse(classFilePath);
Expand All @@ -164,25 +224,52 @@ Val m() {
Path classes = base.resolve("classes");
tb.createDirectories(classes);

new toolbox.JavacTask(tb)
.options("--enable-preview", "-source", Integer.toString(Runtime.version().feature()))
List<String> log;
List<String> expected;

expected = List.of(
"Ident.java:2:5: compiler.warn.declared.using.preview: kindname.class, Val",
"Val.java:1:1: compiler.warn.preview.feature.use.plural: (compiler.misc.feature.value.classes)",
"2 warnings"
);

log = new toolbox.JavacTask(tb)
.options("--enable-preview",
"-source", Integer.toString(Runtime.version().feature()),
"-XDrawDiagnostics",
"-Xlint:preview")
.outdir(classes)
.files(findJavaFiles(src))
.run()
.writeAll();
.writeAll()
.getOutputLines(OutputKind.DIRECT);

tb.checkEqual(log, expected);

Path classFilePath = classes.resolve("Ident.class");
var classFile = ClassFile.of().parse(classFilePath);
Assert.check(classFile.minorVersion() == 65535);
Assert.check(classFile.findAttribute(Attributes.loadableDescriptors()).isPresent());

expected = List.of(
"Ident.java:2:5: compiler.warn.declared.using.preview: kindname.class, Val",
"Val.java:1:1: compiler.warn.preview.feature.use.plural: (compiler.misc.feature.value.classes)",
"2 warnings"
);

// now with the value class in the classpath
new toolbox.JavacTask(tb)
.options("--enable-preview", "-source", Integer.toString(Runtime.version().feature()), "-cp", classes.toString())
.options("--enable-preview",
"-source", Integer.toString(Runtime.version().feature()), "-cp", classes.toString(),
"-XDrawDiagnostics",
"-Xlint:preview")
.outdir(classes)
.files(src.resolve("Ident.java"))
.run()
.writeAll();
.writeAll()
.getOutputLines(OutputKind.DIRECT);

tb.checkEqual(log, expected);

classFilePath = classes.resolve("Ident.class");
classFile = ClassFile.of().parse(classFilePath);
Expand Down