diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionStatelessCallbacksImpl.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionStatelessCallbacksImpl.kt index 74207c411d7..789203ef1e7 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionStatelessCallbacksImpl.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionStatelessCallbacksImpl.kt @@ -80,6 +80,7 @@ class KotlinResolutionStatelessCallbacksImpl( kotlinCallArgument.psiCallArgument.psiExpression, (resolutionCallbacks as? KotlinResolutionCallbacksImpl)?.trace?.bindingContext, isSuperCall = false, + fromImportingScope = false ) override fun isSuperExpression(receiver: SimpleKotlinCallArgument?): Boolean = diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecation/DeprecationResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecation/DeprecationResolver.kt index dd98403aaa4..f059ee3b150 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecation/DeprecationResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecation/DeprecationResolver.kt @@ -64,15 +64,17 @@ class DeprecationResolver( descriptor: DeclarationDescriptor, call: Call? = null, bindingContext: BindingContext? = null, - isSuperCall: Boolean = false + isSuperCall: Boolean = false, + fromImportingScope: Boolean = false ): Boolean = - isHiddenInResolution(descriptor, call?.callElement, bindingContext, isSuperCall) + isHiddenInResolution(descriptor, call?.callElement, bindingContext, isSuperCall, fromImportingScope) fun isHiddenInResolution( descriptor: DeclarationDescriptor, callElement: KtElement?, bindingContext: BindingContext?, - isSuperCall: Boolean + isSuperCall: Boolean, + fromImportingScope: Boolean ): Boolean { if (descriptor is FunctionDescriptor) { if (descriptor.isHiddenToOvercomeSignatureClash) return true @@ -83,14 +85,17 @@ class DeprecationResolver( if (sinceKotlinAccessibility is SinceKotlinAccessibility.NotAccessible) return true if (sinceKotlinAccessibility is SinceKotlinAccessibility.NotAccessibleButWasExperimental) { - if (callElement != null && bindingContext != null) { - return with(ExperimentalUsageChecker) { + return if (callElement != null && bindingContext != null) { + with(ExperimentalUsageChecker) { sinceKotlinAccessibility.markerClasses.any { classDescriptor -> !callElement.isExperimentalityAccepted(classDescriptor.fqNameSafe, languageVersionSettings, bindingContext) } } + } else { + // We need a softer check for descriptors from importing scope as there is no access to PSI elements + // It's fine to return false here as there will be additional checks for accessibility later + !fromImportingScope } - return true } return isDeprecatedHidden(descriptor) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyImportScope.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyImportScope.kt index dca24ef31d7..5f555673dc6 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyImportScope.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyImportScope.kt @@ -235,7 +235,8 @@ class LazyImportScope( private fun LazyImportResolver<*>.isClassifierVisible(descriptor: ClassifierDescriptor): Boolean { if (filteringKind == FilteringKind.ALL) return true - if (components.deprecationResolver.isHiddenInResolution(descriptor)) return false + // TODO: do not perform this check here because for correct work it requires corresponding PSI element + if (components.deprecationResolver.isHiddenInResolution(descriptor, fromImportingScope = true)) return false val visibility = (descriptor as DeclarationDescriptorWithVisibility).visibility val includeVisible = filteringKind == FilteringKind.VISIBLE_CLASSES diff --git a/compiler/testData/cli/jvm/useDeclarationThatWasExperimentalWithoutExplicitImport.args b/compiler/testData/cli/jvm/useDeclarationThatWasExperimentalWithoutExplicitImport.args new file mode 100644 index 00000000000..7bcf29e12b2 --- /dev/null +++ b/compiler/testData/cli/jvm/useDeclarationThatWasExperimentalWithoutExplicitImport.args @@ -0,0 +1,5 @@ +$TESTDATA_DIR$/useDeclarationThatWasExperimentalWithoutExplicitImport.kt +-d +$TEMP_DIR$ +-language-version +1.3 \ No newline at end of file diff --git a/compiler/testData/cli/jvm/useDeclarationThatWasExperimentalWithoutExplicitImport.kt b/compiler/testData/cli/jvm/useDeclarationThatWasExperimentalWithoutExplicitImport.kt new file mode 100644 index 00000000000..ff2e15a4ace --- /dev/null +++ b/compiler/testData/cli/jvm/useDeclarationThatWasExperimentalWithoutExplicitImport.kt @@ -0,0 +1,7 @@ +@ExperimentalStdlibApi +fun test(s: ArrayDeque): ArrayDeque? { + ArrayDeque(42) + + val x: ArrayDeque? = null + return x ?: s +} diff --git a/compiler/testData/cli/jvm/useDeclarationThatWasExperimentalWithoutExplicitImport.out b/compiler/testData/cli/jvm/useDeclarationThatWasExperimentalWithoutExplicitImport.out new file mode 100644 index 00000000000..d86bac9de59 --- /dev/null +++ b/compiler/testData/cli/jvm/useDeclarationThatWasExperimentalWithoutExplicitImport.out @@ -0,0 +1 @@ +OK diff --git a/compiler/testData/cli/jvm/useDeclarationThatWasExperimentalWithoutExplicitImportCommandLine.args b/compiler/testData/cli/jvm/useDeclarationThatWasExperimentalWithoutExplicitImportCommandLine.args new file mode 100644 index 00000000000..809eab58e9b --- /dev/null +++ b/compiler/testData/cli/jvm/useDeclarationThatWasExperimentalWithoutExplicitImportCommandLine.args @@ -0,0 +1,6 @@ +$TESTDATA_DIR$/useDeclarationThatWasExperimentalWithoutMarker.kt +-d +$TEMP_DIR$ +-language-version +1.3 +-Xopt-in=kotlin.ExperimentalStdlibApi \ No newline at end of file diff --git a/compiler/testData/cli/jvm/useDeclarationThatWasExperimentalWithoutExplicitImportCommandLine.out b/compiler/testData/cli/jvm/useDeclarationThatWasExperimentalWithoutExplicitImportCommandLine.out new file mode 100644 index 00000000000..d86bac9de59 --- /dev/null +++ b/compiler/testData/cli/jvm/useDeclarationThatWasExperimentalWithoutExplicitImportCommandLine.out @@ -0,0 +1 @@ +OK diff --git a/compiler/testData/cli/jvm/useDeclarationThatWasExperimentalWithoutMarker.args b/compiler/testData/cli/jvm/useDeclarationThatWasExperimentalWithoutMarker.args new file mode 100644 index 00000000000..da552d471db --- /dev/null +++ b/compiler/testData/cli/jvm/useDeclarationThatWasExperimentalWithoutMarker.args @@ -0,0 +1,5 @@ +$TESTDATA_DIR$/useDeclarationThatWasExperimentalWithoutMarker.kt +-d +$TEMP_DIR$ +-language-version +1.3 \ No newline at end of file diff --git a/compiler/testData/cli/jvm/useDeclarationThatWasExperimentalWithoutMarker.kt b/compiler/testData/cli/jvm/useDeclarationThatWasExperimentalWithoutMarker.kt new file mode 100644 index 00000000000..e8ef03407d0 --- /dev/null +++ b/compiler/testData/cli/jvm/useDeclarationThatWasExperimentalWithoutMarker.kt @@ -0,0 +1,6 @@ +fun test(s: ArrayDeque): ArrayDeque? { + ArrayDeque(42) + + val x: ArrayDeque? = null + return x ?: s +} diff --git a/compiler/testData/cli/jvm/useDeclarationThatWasExperimentalWithoutMarker.out b/compiler/testData/cli/jvm/useDeclarationThatWasExperimentalWithoutMarker.out new file mode 100644 index 00000000000..05f0afb2c5d --- /dev/null +++ b/compiler/testData/cli/jvm/useDeclarationThatWasExperimentalWithoutMarker.out @@ -0,0 +1,13 @@ +compiler/testData/cli/jvm/useDeclarationThatWasExperimentalWithoutMarker.kt:1:13: error: this declaration is experimental and its usage must be marked with '@kotlin.ExperimentalStdlibApi' or '@OptIn(kotlin.ExperimentalStdlibApi::class)' +fun test(s: ArrayDeque): ArrayDeque? { + ^ +compiler/testData/cli/jvm/useDeclarationThatWasExperimentalWithoutMarker.kt:1:31: error: this declaration is experimental and its usage must be marked with '@kotlin.ExperimentalStdlibApi' or '@OptIn(kotlin.ExperimentalStdlibApi::class)' +fun test(s: ArrayDeque): ArrayDeque? { + ^ +compiler/testData/cli/jvm/useDeclarationThatWasExperimentalWithoutMarker.kt:2:5: error: unresolved reference: ArrayDeque + ArrayDeque(42) + ^ +compiler/testData/cli/jvm/useDeclarationThatWasExperimentalWithoutMarker.kt:4:12: error: this declaration is experimental and its usage must be marked with '@kotlin.ExperimentalStdlibApi' or '@OptIn(kotlin.ExperimentalStdlibApi::class)' + val x: ArrayDeque? = null + ^ +COMPILATION_ERROR diff --git a/compiler/tests/org/jetbrains/kotlin/cli/CliTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/cli/CliTestGenerated.java index 31461c65ea9..1c3cc5be89b 100644 --- a/compiler/tests/org/jetbrains/kotlin/cli/CliTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/cli/CliTestGenerated.java @@ -720,6 +720,21 @@ public class CliTestGenerated extends AbstractCliTest { runTest("compiler/testData/cli/jvm/unknownExtraFlags.args"); } + @TestMetadata("useDeclarationThatWasExperimentalWithoutExplicitImport.args") + public void testUseDeclarationThatWasExperimentalWithoutExplicitImport() throws Exception { + runTest("compiler/testData/cli/jvm/useDeclarationThatWasExperimentalWithoutExplicitImport.args"); + } + + @TestMetadata("useDeclarationThatWasExperimentalWithoutExplicitImportCommandLine.args") + public void testUseDeclarationThatWasExperimentalWithoutExplicitImportCommandLine() throws Exception { + runTest("compiler/testData/cli/jvm/useDeclarationThatWasExperimentalWithoutExplicitImportCommandLine.args"); + } + + @TestMetadata("useDeclarationThatWasExperimentalWithoutMarker.args") + public void testUseDeclarationThatWasExperimentalWithoutMarker() throws Exception { + runTest("compiler/testData/cli/jvm/useDeclarationThatWasExperimentalWithoutMarker.args"); + } + @TestMetadata("useMixedNamedArgumentsFlag.args") public void testUseMixedNamedArgumentsFlag() throws Exception { runTest("compiler/testData/cli/jvm/useMixedNamedArgumentsFlag.args");