Sanitize declaration return types
On JVM, strip @EnhancedNullability annotation from inferred types for functions, properties, and local variables, so that these annotations do not "escape" from Kotlin declarations.
This commit is contained in:
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.jvm
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.annotations.FilteredAnnotations
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.DeclarationReturnTypeSanitizer
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.WrappedTypeFactory
|
||||
|
||||
object JvmDeclarationReturnTypeSanitizer : DeclarationReturnTypeSanitizer {
|
||||
override fun sanitizeReturnType(
|
||||
inferred: UnwrappedType,
|
||||
wrappedTypeFactory: WrappedTypeFactory,
|
||||
trace: BindingTrace,
|
||||
languageVersionSettings: LanguageVersionSettings
|
||||
): UnwrappedType =
|
||||
if (languageVersionSettings.supportsFeature(LanguageFeature.StrictJavaNullabilityAssertions)) {
|
||||
// NB can't check for presence of EnhancedNullability here,
|
||||
// because it will also cause recursion in declaration type resolution.
|
||||
inferred.replaceAnnotations(FilteredAnnotations(inferred.annotations) {
|
||||
it != JvmAnnotationNames.ENHANCED_NULLABILITY_ANNOTATION
|
||||
})
|
||||
}
|
||||
else inferred
|
||||
}
|
||||
+3
-1
@@ -81,7 +81,9 @@ object JvmPlatformConfigurator : PlatformConfigurator(
|
||||
|
||||
delegationFilter = JvmDelegationFilter,
|
||||
|
||||
overridesBackwardCompatibilityHelper = JvmOverridesBackwardCompatibilityHelper
|
||||
overridesBackwardCompatibilityHelper = JvmOverridesBackwardCompatibilityHelper,
|
||||
|
||||
declarationReturnTypeSanitizer = JvmDeclarationReturnTypeSanitizer
|
||||
) {
|
||||
override fun configureModuleComponents(container: StorageComponentContainer) {
|
||||
container.useImpl<JvmReflectionAPICallChecker>()
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.WrappedTypeFactory
|
||||
|
||||
interface DeclarationReturnTypeSanitizer {
|
||||
fun sanitizeReturnType(
|
||||
inferred: UnwrappedType,
|
||||
wrappedTypeFactory: WrappedTypeFactory,
|
||||
trace: BindingTrace,
|
||||
languageVersionSettings: LanguageVersionSettings
|
||||
): UnwrappedType
|
||||
|
||||
object Default : DeclarationReturnTypeSanitizer {
|
||||
override fun sanitizeReturnType(
|
||||
inferred: UnwrappedType,
|
||||
wrappedTypeFactory: WrappedTypeFactory,
|
||||
trace: BindingTrace,
|
||||
languageVersionSettings: LanguageVersionSettings
|
||||
) = inferred
|
||||
}
|
||||
}
|
||||
@@ -87,6 +87,7 @@ public class DescriptorResolver {
|
||||
private final WrappedTypeFactory wrappedTypeFactory;
|
||||
private final SyntheticResolveExtension syntheticResolveExtension;
|
||||
private final TypeApproximator typeApproximator;
|
||||
private final DeclarationReturnTypeSanitizer declarationReturnTypeSanitizer;
|
||||
|
||||
public DescriptorResolver(
|
||||
@NotNull AnnotationResolver annotationResolver,
|
||||
@@ -103,7 +104,8 @@ public class DescriptorResolver {
|
||||
@NotNull ModifiersChecker modifiersChecker,
|
||||
@NotNull WrappedTypeFactory wrappedTypeFactory,
|
||||
@NotNull Project project,
|
||||
TypeApproximator approximator
|
||||
@NotNull TypeApproximator approximator,
|
||||
@NotNull DeclarationReturnTypeSanitizer declarationReturnTypeSanitizer
|
||||
) {
|
||||
this.annotationResolver = annotationResolver;
|
||||
this.builtIns = builtIns;
|
||||
@@ -120,6 +122,7 @@ public class DescriptorResolver {
|
||||
this.wrappedTypeFactory = wrappedTypeFactory;
|
||||
this.syntheticResolveExtension = SyntheticResolveExtension.Companion.getInstance(project);
|
||||
typeApproximator = approximator;
|
||||
this.declarationReturnTypeSanitizer = declarationReturnTypeSanitizer;
|
||||
}
|
||||
|
||||
public List<KotlinType> resolveSupertypes(
|
||||
@@ -1152,12 +1155,12 @@ public class DescriptorResolver {
|
||||
) {
|
||||
return wrappedTypeFactory.createRecursionIntolerantDeferredType(trace, () -> {
|
||||
PreliminaryDeclarationVisitor.Companion.createForDeclaration(function, trace, languageVersionSettings);
|
||||
KotlinType type = expressionTypingServices.getBodyExpressionType(
|
||||
trace, scope, dataFlowInfo, function, functionDescriptor);
|
||||
KotlinType result = transformAnonymousTypeIfNeeded(functionDescriptor, function, type, trace);
|
||||
UnwrappedType approximatedType = typeApproximator.approximateDeclarationType(result, false);
|
||||
functionsTypingVisitor.checkTypesForReturnStatements(function, trace, approximatedType);
|
||||
return approximatedType;
|
||||
KotlinType type = expressionTypingServices.getBodyExpressionType(trace, scope, dataFlowInfo, function, functionDescriptor);
|
||||
KotlinType publicType = transformAnonymousTypeIfNeeded(functionDescriptor, function, type, trace);
|
||||
UnwrappedType approximatedType = typeApproximator.approximateDeclarationType(publicType, false);
|
||||
KotlinType sanitizedType = declarationReturnTypeSanitizer.sanitizeReturnType(approximatedType, wrappedTypeFactory, trace, languageVersionSettings);
|
||||
functionsTypingVisitor.checkTypesForReturnStatements(function, trace, sanitizedType);
|
||||
return sanitizedType;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@ class FunctionDescriptorResolver(
|
||||
assert(function.typeReference == null) {
|
||||
"Return type must be initialized early for function: " + function.text + ", at: " + DiagnosticUtils.atLocation(function) }
|
||||
|
||||
val returnType = when {
|
||||
val inferredReturnType = when {
|
||||
function.hasBlockBody() ->
|
||||
builtIns.unitType
|
||||
function.hasBody() ->
|
||||
@@ -142,7 +142,7 @@ class FunctionDescriptorResolver(
|
||||
else ->
|
||||
ErrorUtils.createErrorType("No type, no body")
|
||||
}
|
||||
functionDescriptor.setReturnType(returnType)
|
||||
functionDescriptor.setReturnType(inferredReturnType)
|
||||
}
|
||||
|
||||
fun initializeFunctionDescriptorAndExplicitReturnType(
|
||||
|
||||
@@ -24,7 +24,7 @@ interface IdentifierChecker {
|
||||
fun checkIdentifier(identifier: PsiElement?, diagnosticHolder: DiagnosticSink)
|
||||
fun checkDeclaration(declaration: KtDeclaration, diagnosticHolder: DiagnosticSink)
|
||||
|
||||
object DEFAULT : IdentifierChecker {
|
||||
object Default : IdentifierChecker {
|
||||
override fun checkIdentifier(identifier: PsiElement?, diagnosticHolder: DiagnosticSink) {}
|
||||
override fun checkDeclaration(declaration: KtDeclaration, diagnosticHolder: DiagnosticSink) {}
|
||||
}
|
||||
|
||||
@@ -20,11 +20,16 @@ import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.VariableDescriptorWithInitializerImpl
|
||||
import org.jetbrains.kotlin.diagnostics.Errors.*
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.KtProperty
|
||||
import org.jetbrains.kotlin.psi.KtPsiUtil
|
||||
import org.jetbrains.kotlin.psi.KtVariableDeclaration
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
|
||||
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptorNonRoot
|
||||
interface OverloadFilter {
|
||||
fun filterPackageMemberOverloads(overloads: Collection<DeclarationDescriptorNonRoot>): Collection<DeclarationDescriptorNonRoot>
|
||||
|
||||
object DEFAULT : OverloadFilter {
|
||||
object Default : OverloadFilter {
|
||||
override fun filterPackageMemberOverloads(overloads: Collection<DeclarationDescriptorNonRoot>): Collection<DeclarationDescriptorNonRoot> =
|
||||
overloads
|
||||
}
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
interface OverridesBackwardCompatibilityHelper {
|
||||
fun overrideCanBeOmitted(overridingDescriptor: CallableMemberDescriptor): Boolean
|
||||
|
||||
object DEFAULT : OverridesBackwardCompatibilityHelper {
|
||||
object Default : OverridesBackwardCompatibilityHelper {
|
||||
override fun overrideCanBeOmitted(overridingDescriptor: CallableMemberDescriptor): Boolean =
|
||||
false
|
||||
}
|
||||
|
||||
@@ -64,8 +64,9 @@ abstract class TargetPlatform(val platformName: String) {
|
||||
override val platformConfigurator =
|
||||
object : PlatformConfigurator(
|
||||
DynamicTypesSettings(), listOf(), listOf(), listOf(), listOf(), listOf(),
|
||||
IdentifierChecker.DEFAULT, OverloadFilter.DEFAULT, PlatformToKotlinClassMap.EMPTY, DelegationFilter.DEFAULT,
|
||||
OverridesBackwardCompatibilityHelper.DEFAULT
|
||||
IdentifierChecker.Default, OverloadFilter.Default, PlatformToKotlinClassMap.EMPTY, DelegationFilter.Default,
|
||||
OverridesBackwardCompatibilityHelper.Default,
|
||||
DeclarationReturnTypeSanitizer.Default
|
||||
) {
|
||||
override fun configureModuleComponents(container: StorageComponentContainer) {
|
||||
container.useInstance(SyntheticScopes.Empty)
|
||||
@@ -118,7 +119,8 @@ abstract class PlatformConfigurator(
|
||||
private val overloadFilter: OverloadFilter,
|
||||
private val platformToKotlinClassMap: PlatformToKotlinClassMap,
|
||||
private val delegationFilter: DelegationFilter,
|
||||
private val overridesBackwardCompatibilityHelper: OverridesBackwardCompatibilityHelper
|
||||
private val overridesBackwardCompatibilityHelper: OverridesBackwardCompatibilityHelper,
|
||||
private val declarationReturnTypeSanitizer: DeclarationReturnTypeSanitizer
|
||||
) {
|
||||
private val declarationCheckers: List<DeclarationChecker> = DEFAULT_DECLARATION_CHECKERS + additionalDeclarationCheckers
|
||||
private val callCheckers: List<CallChecker> = DEFAULT_CALL_CHECKERS + additionalCallCheckers
|
||||
@@ -139,6 +141,7 @@ abstract class PlatformConfigurator(
|
||||
useInstance(platformToKotlinClassMap)
|
||||
useInstance(delegationFilter)
|
||||
useInstance(overridesBackwardCompatibilityHelper)
|
||||
useInstance(declarationReturnTypeSanitizer)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+8
-2
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptorWithAccessors
|
||||
import org.jetbrains.kotlin.descriptors.impl.VariableDescriptorWithInitializerImpl
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
@@ -39,7 +40,9 @@ class VariableTypeAndInitializerResolver(
|
||||
private val constantExpressionEvaluator: ConstantExpressionEvaluator,
|
||||
private val delegatedPropertyResolver: DelegatedPropertyResolver,
|
||||
private val wrappedTypeFactory: WrappedTypeFactory,
|
||||
private val typeApproximator: TypeApproximator
|
||||
private val typeApproximator: TypeApproximator,
|
||||
private val declarationReturnTypeSanitizer: DeclarationReturnTypeSanitizer,
|
||||
private val languageVersionSettings: LanguageVersionSettings
|
||||
) {
|
||||
companion object {
|
||||
@JvmField
|
||||
@@ -92,6 +95,7 @@ class VariableTypeAndInitializerResolver(
|
||||
|
||||
else -> resolveInitializerType(scopeForInitializer, variable.initializer!!, dataFlowInfo, trace, local)
|
||||
}
|
||||
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
@@ -152,7 +156,9 @@ class VariableTypeAndInitializerResolver(
|
||||
trace: BindingTrace,
|
||||
local: Boolean
|
||||
): KotlinType {
|
||||
return approximateType(expressionTypingServices.safeGetType(scope, initializer, TypeUtils.NO_EXPECTED_TYPE, dataFlowInfo, trace), local)
|
||||
val inferredType = expressionTypingServices.safeGetType(scope, initializer, TypeUtils.NO_EXPECTED_TYPE, dataFlowInfo, trace)
|
||||
val approximatedType = approximateType(inferredType, local)
|
||||
return declarationReturnTypeSanitizer.sanitizeReturnType(approximatedType, wrappedTypeFactory, trace, languageVersionSettings)
|
||||
}
|
||||
|
||||
private fun approximateType(type: KotlinType, local: Boolean): UnwrappedType = typeApproximator.approximateDeclarationType(type, local)
|
||||
|
||||
@@ -23,7 +23,7 @@ interface DelegationFilter {
|
||||
|
||||
fun filter(interfaceMember: CallableMemberDescriptor, languageVersionSettings: LanguageVersionSettings): Boolean
|
||||
|
||||
object DEFAULT : DelegationFilter {
|
||||
object Default : DelegationFilter {
|
||||
override fun filter(interfaceMember: CallableMemberDescriptor, languageVersionSettings: LanguageVersionSettings) = true
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.container.useInstance
|
||||
import org.jetbrains.kotlin.js.naming.NameSuggestion
|
||||
import org.jetbrains.kotlin.js.resolve.diagnostics.*
|
||||
import org.jetbrains.kotlin.platform.PlatformToKotlinClassMap
|
||||
import org.jetbrains.kotlin.resolve.DeclarationReturnTypeSanitizer
|
||||
import org.jetbrains.kotlin.resolve.OverloadFilter
|
||||
import org.jetbrains.kotlin.resolve.OverridesBackwardCompatibilityHelper
|
||||
import org.jetbrains.kotlin.resolve.PlatformConfigurator
|
||||
@@ -51,10 +52,11 @@ object JsPlatformConfigurator : PlatformConfigurator(
|
||||
additionalClassifierUsageCheckers = listOf(),
|
||||
additionalAnnotationCheckers = listOf(),
|
||||
identifierChecker = JsIdentifierChecker,
|
||||
overloadFilter = OverloadFilter.DEFAULT,
|
||||
overloadFilter = OverloadFilter.Default,
|
||||
platformToKotlinClassMap = PlatformToKotlinClassMap.EMPTY,
|
||||
delegationFilter = DelegationFilter.DEFAULT,
|
||||
overridesBackwardCompatibilityHelper = OverridesBackwardCompatibilityHelper.DEFAULT
|
||||
delegationFilter = DelegationFilter.Default,
|
||||
overridesBackwardCompatibilityHelper = OverridesBackwardCompatibilityHelper.Default,
|
||||
declarationReturnTypeSanitizer = DeclarationReturnTypeSanitizer.Default
|
||||
) {
|
||||
override fun configureModuleComponents(container: StorageComponentContainer) {
|
||||
container.useInstance(NameSuggestion())
|
||||
|
||||
Reference in New Issue
Block a user