FIR: fix a bunch of issues after DiagnosticsReporter refactoring related to reporting diagnostic on null source

This commit is contained in:
Kirill Rakhman
2023-01-05 15:00:30 +01:00
committed by Space Team
parent a7edf5b83e
commit 69f2e8826a
27 changed files with 74 additions and 42 deletions
@@ -20,7 +20,7 @@ fun foo(a: () -> Unit, b: () -> Unit, c: () -> Unit, d: () -> Unit) {
}
override fun run() {
<!LEAKED_IN_PLACE_LAMBDA!>c()<!>
<!LEAKED_IN_PLACE_LAMBDA!>c<!>()
}
}
@@ -17,7 +17,7 @@ fun foo(a: () -> Unit, b: () -> Unit, c: () -> Unit, d: () -> Unit, e: () -> Uni
val leaked: Any
constructor() {
<!LEAKED_IN_PLACE_LAMBDA!>b()<!>
<!LEAKED_IN_PLACE_LAMBDA!>b<!>()
}
init {
@@ -25,7 +25,7 @@ fun foo(a: () -> Unit, b: () -> Unit, c: () -> Unit, d: () -> Unit, e: () -> Uni
}
fun run() {
<!LEAKED_IN_PLACE_LAMBDA!>d()<!>
<!LEAKED_IN_PLACE_LAMBDA!>d<!>()
}
}
@@ -9,7 +9,7 @@ fun foo(a: () -> Unit, b: () -> Unit) {
fun localFun() {
<!LEAKED_IN_PLACE_LAMBDA!>a<!>.invoke()
<!LEAKED_IN_PLACE_LAMBDA!>a()<!>
<!LEAKED_IN_PLACE_LAMBDA!>a<!>()
}
localFun()
@@ -220,6 +220,12 @@ object FirJsExternalChecker : FirBasicDeclarationChecker() {
else -> null
}
// we shouldn't check such things as the
// copy() function of a data class
if (source?.kind !is KtRealSourceElementKind) {
return
}
val isWrong = body !is FirSingleExpressionBlock && !hasValidExternalBody()
|| initializer != null && !initializer.isDefinedExternallyExpression()
@@ -229,12 +235,6 @@ object FirJsExternalChecker : FirBasicDeclarationChecker() {
reporter.reportOn(initializer.source, FirJsErrors.WRONG_INITIALIZER_OF_EXTERNAL_DECLARATION, context)
}
// we shouldn't check such things as the
// copy() function of a data class
if (source?.kind !is KtRealSourceElementKind) {
return
}
if (this is FirFunction) {
for (defaultValue in valueParameters.mapNotNull { it.defaultValue }) {
if (!defaultValue.isDefinedExternallyExpression()) {
@@ -24,11 +24,9 @@ object FirJvmInlineApplicabilityChecker : FirRegularClassChecker() {
if (annotation != null && !declaration.isInline) {
reporter.reportOn(annotation.source, FirJvmErrors.JVM_INLINE_WITHOUT_VALUE_CLASS, context)
} else if (annotation == null && declaration.isInline && !declaration.isExpect) {
reporter.reportOn(
declaration.getModifier(KtTokens.VALUE_KEYWORD)?.source,
FirJvmErrors.VALUE_CLASS_WITHOUT_JVM_INLINE_ANNOTATION,
context
)
// only report if value keyword exists, this ignores the deprecated inline class syntax
val keyword = declaration.getModifier(KtTokens.VALUE_KEYWORD)?.source ?: return
reporter.reportOn(keyword, FirJvmErrors.VALUE_CLASS_WITHOUT_JVM_INLINE_ANNOTATION, context)
}
}
}
@@ -91,10 +91,10 @@ object FirNativeThrowsChecker : FirBasicDeclarationChecker() {
val (overriddenMember, overriddenThrows) = inherited.firstOrNull()
?: return true // Should not happen though.
if (decodeThrowsFilter(throwsAnnotation, context.session) != overriddenThrows) {
if (throwsAnnotation?.source != null && decodeThrowsFilter(throwsAnnotation, context.session) != overriddenThrows) {
val containingClassSymbol = overriddenMember.containingClassLookupTag()?.toFirRegularClassSymbol(context.session)
if (containingClassSymbol != null) {
reporter.reportOn(throwsAnnotation?.source, FirNativeErrors.INCOMPATIBLE_THROWS_OVERRIDE, containingClassSymbol, context)
reporter.reportOn(throwsAnnotation.source, FirNativeErrors.INCOMPATIBLE_THROWS_OVERRIDE, containingClassSymbol, context)
}
return false
}
@@ -47,7 +47,7 @@ object FirReturnsImpliesAnalyzer : FirControlFlowChecker() {
}
val function = graph.declaration as? FirFunction ?: return
if (function !is FirContractDescriptionOwner) return
if (function !is FirContractDescriptionOwner || function.contractDescription.source == null) return
val effects = function.contractDescription.effects ?: return
val dataFlowInfo = function.controlFlowGraphReference?.dataFlowInfo ?: return
for (firEffect in effects) {
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.KtRealSourceElementKind
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
@@ -18,8 +17,8 @@ import org.jetbrains.kotlin.fir.types.coneTypeSafe
object FirDynamicUnsupportedChecker : FirTypeRefChecker() {
override fun check(typeRef: FirTypeRef, context: CheckerContext, reporter: DiagnosticReporter) {
// It's assumed this checker is only called
// by within the platform that disallows dynamics
if (typeRef.coneTypeSafe<ConeDynamicType>() != null) {
// by a platform that disallows dynamics
if (typeRef.source != null && typeRef.coneTypeSafe<ConeDynamicType>() != null) {
reporter.reportOn(typeRef.source, FirErrors.UNSUPPORTED, "dynamic type", context)
}
}
@@ -5,13 +5,17 @@
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.findNonInterfaceSupertype
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.utils.isEnumClass
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.types.classId
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.name.StandardClassIds
object FirEnumClassSimpleChecker : FirRegularClassChecker() {
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
@@ -19,9 +23,12 @@ object FirEnumClassSimpleChecker : FirRegularClassChecker() {
return
}
declaration.findNonInterfaceSupertype(context)?.let {
reporter.reportOn(it.source, FirErrors.CLASS_IN_SUPERTYPE_FOR_ENUM, context)
}
declaration.findNonInterfaceSupertype(context)
// Ignore Enum itself
// If it's explicit, CLASS_CANNOT_BE_EXTENDED_DIRECTLY will be reported instead.
// If it's implicit, it's fine.
?.takeUnless { it.coneType.fullyExpandedType(context.session).classId == StandardClassIds.Enum }
?.let { reporter.reportOn(it.source, FirErrors.CLASS_IN_SUPERTYPE_FOR_ENUM, context) }
if (declaration.typeParameters.isNotEmpty()) {
reporter.reportOn(declaration.typeParameters.firstOrNull()?.source, FirErrors.TYPE_PARAMETERS_IN_ENUM, context)
@@ -96,11 +96,7 @@ object FirFunctionParameterChecker : FirFunctionChecker() {
if (referredParameterIndex < 0) return
if (index <= referredParameterIndex) {
reporter.reportOn(
qualifiedAccessExpression.source, FirErrors.UNINITIALIZED_PARAMETER,
referredParameter,
context
)
reporter.reportOn(qualifiedAccessExpression.source, FirErrors.UNINITIALIZED_PARAMETER, referredParameter, context)
}
}
@@ -78,7 +78,7 @@ object FirPrimaryConstructorSuperTypeChecker : FirClassChecker() {
}
val delegatedCallSource = delegatedConstructorCall.source ?: return
if (delegatedCallSource.kind !is KtFakeSourceElementKind) return
if (superClassSymbol.classId == StandardClassIds.Enum) return
if (superClassSymbol.classId == StandardClassIds.Enum || superClassSymbol.classId == StandardClassIds.Java.Record) return
if (delegatedCallSource.elementType != KtNodeTypes.SUPER_TYPE_CALL_ENTRY) {
reporter.reportOn(constructedTypeRef.source, FirErrors.SUPERTYPE_NOT_INITIALIZED, context)
}
@@ -33,6 +33,10 @@ object FirPropertyAccessorsTypesChecker : FirPropertyChecker() {
val propertyType = property.returnTypeRef.coneType
checkAccessorForDelegatedProperty(property, getter, context, reporter)
if (getter.isImplicitDelegateAccessor()) {
return
}
if (getter.visibility != property.visibility) {
reporter.reportOn(getter.source, FirErrors.GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY, context)
}
@@ -63,6 +67,10 @@ object FirPropertyAccessorsTypesChecker : FirPropertyChecker() {
reporter.reportOn(setter.source, FirErrors.VAL_WITH_SETTER, context)
}
checkAccessorForDelegatedProperty(property, setter, context, reporter)
if (setter.isImplicitDelegateAccessor()) {
return
}
val visibilityCompareResult = setter.visibility.compareTo(property.visibility)
if (visibilityCompareResult == null || visibilityCompareResult > 0) {
reporter.reportOn(setter.source, FirErrors.SETTER_VISIBILITY_INCONSISTENT_WITH_PROPERTY_VISIBILITY, context)
@@ -115,6 +123,9 @@ object FirPropertyAccessorsTypesChecker : FirPropertyChecker() {
}
}
private fun FirPropertyAccessor.isImplicitDelegateAccessor(): Boolean =
source?.kind == KtFakeSourceElementKind.DelegatedPropertyAccessor
private fun isLegallyAbstract(property: FirProperty, context: CheckerContext): Boolean {
return property.isAbstract && context.findClosestClassOrObject().let { it is FirRegularClass && it.canHaveAbstractDeclaration }
}
@@ -41,6 +41,9 @@ object FirSupertypesChecker : FirClassChecker() {
var classAppeared = false
val superClassSymbols = hashSetOf<FirRegularClassSymbol>()
for (superTypeRef in declaration.superTypeRefs) {
// skip implicit super types like Enum or Any
if (superTypeRef.source == null) continue
val coneType = superTypeRef.coneType
if (!nullableSupertypeReported && coneType.nullability == ConeNullability.NULLABLE) {
reporter.reportOn(superTypeRef.source, FirErrors.NULLABLE_SUPERTYPE, context)
@@ -23,7 +23,9 @@ object FirThrowableSubclassChecker : FirClassChecker() {
return
if (declaration.typeParameters.isNotEmpty()) {
reporter.reportOn(declaration.typeParameters.firstOrNull()?.source, FirErrors.GENERIC_THROWABLE_SUBCLASS, context)
declaration.typeParameters.firstOrNull()?.source?.let {
reporter.reportOn(it, FirErrors.GENERIC_THROWABLE_SUBCLASS, context)
}
val shouldReport = when (declaration) {
is FirRegularClass -> declaration.isInner || declaration.isLocal
@@ -20,13 +20,13 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol
import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol
import org.jetbrains.kotlin.fir.resolve.defaultType
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.isEquals
import org.jetbrains.kotlin.fir.resolve.lookupSuperTypes
import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.FirImplicitAnyTypeRef
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
@@ -56,7 +56,7 @@ object FirValueClassDeclarationChecker : FirRegularClassChecker() {
// TODO check absence of context receivers when FIR infrastructure is ready
for (supertypeEntry in declaration.superTypeRefs) {
if (supertypeEntry.toRegularClassSymbol(context.session)?.isInterface != true) {
if (supertypeEntry !is FirImplicitAnyTypeRef && supertypeEntry.toRegularClassSymbol(context.session)?.isInterface != true) {
reporter.reportOn(supertypeEntry.source, FirErrors.VALUE_CLASS_CANNOT_EXTEND_CLASSES, context)
}
}
@@ -53,7 +53,10 @@ object FirReturnSyntaxAndLabelChecker : FirReturnExpressionChecker() {
}
val containingDeclaration = context.containingDeclarations.last()
if (containingDeclaration is FirFunction && containingDeclaration.body is FirSingleExpressionBlock) {
if (containingDeclaration is FirFunction &&
containingDeclaration.body is FirSingleExpressionBlock &&
containingDeclaration.source?.kind != KtFakeSourceElementKind.DelegatedPropertyAccessor
) {
reporter.reportOn(source, FirErrors.RETURN_IN_FUNCTION_WITH_EXPRESSION_BODY, context)
}
}
@@ -17,7 +17,7 @@ import org.jetbrains.kotlin.fir.types.classId
object PlatformClassMappedToKotlinTypeRefChecker : FirTypeRefChecker() {
override fun check(typeRef: FirTypeRef, context: CheckerContext, reporter: DiagnosticReporter) {
if (typeRef is FirResolvedTypeRef) {
if (typeRef is FirResolvedTypeRef && typeRef.source != null) {
val kotlinClass = context.session.platformClassMapper.getCorrespondingKotlinClass(typeRef.type.classId)
if (kotlinClass != null) {
reporter.reportOn(typeRef.source, FirErrors.PLATFORM_CLASS_MAPPED_TO_KOTLIN, kotlinClass.asSingleFqName(), context)
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.types.ConstantValueKind
object RedundantExplicitTypeChecker : FirPropertyChecker() {
override fun check(declaration: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) {
if (!declaration.isLocal) return
if (declaration.returnTypeRef.source == null) return
val initializer = declaration.initializer ?: return
val typeReference = declaration.returnTypeRef.takeUnless { it is FirErrorTypeRef } ?: return
@@ -23,6 +23,8 @@ object FirTypeAnnotationChecker : FirTypeRefChecker() {
if (typeRef !is FirResolvedTypeRef) return
for (annotation in typeRef.annotations) {
if (annotation.source == null) continue
val annotationTargets = annotation.getAllowedAnnotationTargets(context.session)
if (KotlinTarget.TYPE !in annotationTargets) {
val useSiteTarget = annotation.useSiteTarget
@@ -393,6 +393,7 @@ fun <T> FirPropertyBuilder.generateAccessorsByDelegate(
}
argumentList = buildBinaryArgumentList(thisRef(forDispatchReceiver = true), propertyRef())
origin = FirFunctionCallOrigin.Operator
source = fakeSource
}
delegate = delegateBuilder.build()
if (getter == null || getter is FirDefaultPropertyAccessor) {
@@ -5,7 +5,10 @@
package org.jetbrains.kotlin.fir.resolve.calls.tower
import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.fakeElement
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
import org.jetbrains.kotlin.fir.expressions.builder.FirPropertyAccessExpressionBuilder
@@ -318,6 +321,7 @@ private fun BodyResolveComponents.createExplicitReceiverForInvokeByCallable(
if (candidate.currentApplicability == CandidateApplicability.K2_PROPERTY_AS_OPERATOR) {
nonFatalDiagnostics.add(ConePropertyAsOperator(candidate.symbol as FirPropertySymbol))
}
source = (info.callSite as? FirFunctionCall)?.calleeReference?.source?.fakeElement(KtFakeSourceElementKind.ImplicitInvokeCall)
}.build().let {
transformQualifiedAccessUsingSmartcastInfo(it)
}
@@ -1,6 +1,8 @@
// IGNORE_BACKEND: JS, JS_IR, NATIVE, WASM
// IGNORE_BACKEND: JS_IR_ES6
// IGNORE_BACKEND_K2: JVM_IR
// WASM_MUTE_REASON: IGNORED_IN_JS
// FIR status: don't support legacy feature. UNINITIALIZED_PARAMETER y. See KT-49800
fun f(
f1: () -> String = { f2() },
@@ -14,7 +14,7 @@ fun test_2(
) {}
fun test_3(
x: () -> Any = { y() to <!UNINITIALIZED_PARAMETER!>y<!>.invoke() }, // Error
x: () -> Any = { <!UNINITIALIZED_PARAMETER!>y<!>() to <!UNINITIALIZED_PARAMETER!>y<!>.invoke() }, // Error
y: () -> String = { "OK" }
) {}
@@ -14,7 +14,7 @@ fun test_2(
) {}
fun test_3(
x: () -> Any = { y() to <!UNINITIALIZED_PARAMETER!>y<!>.invoke() }, // Error
x: () -> Any = { <!UNINITIALIZED_PARAMETER!>y<!>() to <!UNINITIALIZED_PARAMETER!>y<!>.invoke() }, // Error
y: () -> String = { "OK" }
) {}
@@ -85,7 +85,7 @@ object O {
operator fun provideDelegate(x: Any?, y: Any?): C = C()
}
val x: String by <!OPT_IN_USAGE_ERROR!>O<!>
val x: String by <!OPT_IN_USAGE_ERROR, OPT_IN_USAGE_ERROR!>O<!>
@Marker
class OperatorContainer : Comparable<OperatorContainer> {
@@ -122,4 +122,4 @@ fun operatorContainerUsage(s: String, a: AnotherContainer) {
val res2 = <!OPT_IN_USAGE_ERROR!>s<!>()
val res3 = <!OPT_IN_USAGE_ERROR!>res1<!> <!OPT_IN_USAGE_ERROR!>><!> <!OPT_IN_USAGE_ERROR!>res2<!>
<!OPT_IN_USAGE_ERROR, OPT_IN_USAGE_ERROR, OPT_IN_USAGE_ERROR, OPT_IN_USAGE_ERROR, OPT_IN_USAGE_ERROR!>for (c in a) {}<!>
}
}
@@ -85,7 +85,7 @@ object O {
operator fun provideDelegate(x: Any?, y: Any?): C = C()
}
val x: String by <!OPT_IN_USAGE_ERROR!>O<!>
val x: String by <!OPT_IN_USAGE_ERROR, OPT_IN_USAGE_ERROR!>O<!>
@Marker
class OperatorContainer : Comparable<OperatorContainer> {
@@ -1,3 +1,6 @@
// IGNORE_BACKEND_K2: ANY
// accessing uninitialized parameter is illegal in FIR
fun f(
f1: () -> String = { f2() },
f2: () -> String = { "FAIL" }