All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jetbrains.kotlin.types.VarianceChecker.kt Maven / Gradle / Ivy

There is a newer version: 2.0.0
Show newest version
/*
 * Copyright 2010-2016 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.types

import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.types.checker.TypeCheckingProcedure
import org.jetbrains.kotlin.types.checker.TypeCheckingProcedure.EnrichedProjectionKind
import org.jetbrains.kotlin.utils.DO_NOTHING_3

interface TypeHolder> {
    val type: KotlinType
    val arguments: List?>
    val flexibleBounds: Pair? get() = null
}

interface TypeHolderArgument> {
    val projection: TypeProjection
    val typeParameter: TypeParameterDescriptor?
    val holder: D
}

fun > D.checkTypePosition(
        position: Variance,
        reportError: (TypeParameterDescriptor, D, Variance) -> Unit = DO_NOTHING_3,
        customVariance: (TypeParameterDescriptor) -> Variance? = { null }
): Boolean {
    flexibleBounds?.let {
        return it.first.checkTypePosition(position, reportError, customVariance) and
                    it.second.checkTypePosition(position, reportError, customVariance)
    }

    val classifierDescriptor = type.constructor.declarationDescriptor
    if (classifierDescriptor is TypeParameterDescriptor) {
        val declarationVariance = customVariance(classifierDescriptor) ?: classifierDescriptor.variance
        if (!declarationVariance.allowsPosition(position)
            && !type.annotations.hasAnnotation(org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES.unsafeVariance)) {
            reportError(classifierDescriptor, this, position)
        }
        return declarationVariance.allowsPosition(position)
    }

    var noError = true
    for (argument in arguments) {
        if (argument == null || argument.typeParameter == null || argument.projection.isStarProjection) continue

        val projectionKind = TypeCheckingProcedure.getEffectiveProjectionKind(argument.typeParameter!!, argument.projection)!!
        val newPosition = when (projectionKind) {
            EnrichedProjectionKind.OUT -> position
            EnrichedProjectionKind.IN -> position.opposite()
            EnrichedProjectionKind.INV -> Variance.INVARIANT
            EnrichedProjectionKind.STAR -> null // CONFLICTING_PROJECTION error was reported
        }
        if (newPosition != null) {
            noError = noError and argument.holder.checkTypePosition(newPosition, reportError, customVariance)
        }
    }
    return noError
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy