<commit_before>/*
 * Use of this source code is governed by the MIT license that can be
 * found in the LICENSE file.
 */

package org.rust.lang.core.types.ty

import com.intellij.openapi.project.Project
import org.rust.lang.core.psi.RsTraitItem
import org.rust.lang.core.psi.RsTypeParameter
import org.rust.lang.core.psi.ext.bounds
import org.rust.lang.core.psi.ext.flattenHierarchy
import org.rust.lang.core.psi.ext.resolveToBoundTrait
import org.rust.lang.core.resolve.asFunctionType
import org.rust.lang.core.resolve.isAnyFnTrait
import org.rust.lang.core.types.BoundElement

class TyTypeParameter private constructor(
    private val parameter: TypeParameter,
    private val name: String?,
    private val bounds: Collection<BoundElement<RsTraitItem>>
) : Ty {

    constructor(parameter: RsTypeParameter) : this(Named(parameter), parameter.name, bounds(parameter))
    constructor(trait: RsTraitItem) : this(Self(trait), "Self", listOf(BoundElement(trait)))
    constructor(trait: RsTraitItem, target: String) : this(
        AssociatedType(trait, target),
        "${trait.name}::target",
        emptyList()
    )

    override fun equals(other: Any?): Boolean = other is TyTypeParameter && other.parameter == parameter
    override fun hashCode(): Int = parameter.hashCode()

    fun getTraitBoundsTransitively(): Collection<BoundElement<RsTraitItem>> =
        bounds.flatMap { it.flattenHierarchy }

    override fun canUnifyWith(other: Ty, project: Project, mapping: TypeMapping?): Boolean {
        if (mapping == null) return true

        if (other is TyFunction) {
            for (bound in bounds) {
                if (bound.element.isAnyFnTrait) {
                    val fnType = bound.asFunctionType
                    if (fnType != null && fnType.retType is TyTypeParameter) {
                        fnType.retType.canUnifyWith(other.retType, project, mapping)
                    }
                }
            }
        } else {
            val traits = findImplsAndTraits(project, other)
            for (bound in bounds) {
                val trait = traits.find { it.element.implementedTrait?.element == bound.element }
                if (trait != null) {
                    mapping.merge(bound.subst.reverse().substituteInValues(trait.subst))
                }<commit_msg>Fixed associated type name<commit_after>/*
 * Use of this source code is governed by the MIT license that can be
 * found in the LICENSE file.
 */

package org.rust.lang.core.types.ty

import com.intellij.openapi.project.Project
import org.rust.lang.core.psi.RsTraitItem
import org.rust.lang.core.psi.RsTypeParameter
import org.rust.lang.core.psi.ext.bounds
import org.rust.lang.core.psi.ext.flattenHierarchy
import org.rust.lang.core.psi.ext.resolveToBoundTrait
import org.rust.lang.core.resolve.asFunctionType
import org.rust.lang.core.resolve.isAnyFnTrait
import org.rust.lang.core.types.BoundElement

class TyTypeParameter private constructor(
    private val parameter: TypeParameter,
    private val name: String?,
    private val bounds: Collection<BoundElement<RsTraitItem>>
) : Ty {

    constructor(parameter: RsTypeParameter) : this(Named(parameter), parameter.name, bounds(parameter))
    constructor(trait: RsTraitItem) : this(Self(trait), "Self", listOf(BoundElement(trait)))
    constructor(trait: RsTraitItem, target: String) : this(
        AssociatedType(trait, target),
        "${trait.name}::$target",
        emptyList()
    )

    override fun equals(other: Any?): Boolean = other is TyTypeParameter && other.parameter == parameter
    override fun hashCode(): Int = parameter.hashCode()

    fun getTraitBoundsTransitively(): Collection<BoundElement<RsTraitItem>> =
        bounds.flatMap { it.flattenHierarchy }

    override fun canUnifyWith(other: Ty, project: Project, mapping: TypeMapping?): Boolean {
        if (mapping == null) return true

        if (other is TyFunction) {
            for (bound in bounds) {
                if (bound.element.isAnyFnTrait) {
                    val fnType = bound.asFunctionType
                    if (fnType != null && fnType.retType is TyTypeParameter) {
                        fnType.retType.canUnifyWith(other.retType, project, mapping)
                    }
                }
            }
        } else {
            val traits = findImplsAndTraits(project, other)
            for (bound in bounds) {
                val trait = traits.find { it.element.implementedTrait?.element == bound.element }
                if (trait != null) {
                    mapping.merge(bound.subst.reverse().substituteInValues(trait.subst))
                }
{'fraction_non_alphanumeric': 0.10397751837440554, 'fraction_numerical': 0.0, 'mean_word_length': 2.7802287581699345, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4263202', 'n_tokens_mistral': 1316, 'n_tokens_neox': 1291, 'n_words': 303}