class ResolvedTypeVariable implements ResolvedType {

    private ResolvedTypeParameterDeclaration typeParameter;

    public ResolvedTypeVariable(ResolvedTypeParameterDeclaration typeParameter) {
        this.typeParameter = typeParameter;
    }

    @Override
    public String toString() {
        return "TypeVariable {" + typeParameter.toString() + "}";
    }

    public String qualifiedName() {
        return this.typeParameter.getQualifiedName();
    }

    @Override
    public boolean equals(Object o) {<FILL_FUNCTION_BODY>}

    @Override
    public int hashCode() {
        return typeParameter.hashCode();
    }

    @Override
    public boolean isArray() {
        return false;
    }

    @Override
    public ResolvedType replaceTypeVariables(ResolvedTypeParameterDeclaration tpToBeReplaced, ResolvedType replaced, Map<ResolvedTypeParameterDeclaration, ResolvedType> inferredTypes) {
        if (tpToBeReplaced.getName().equals(this.typeParameter.getName())) {
            inferredTypes.put(this.asTypeParameter(), replaced);
            return replaced;
        }
        return this;
    }

    @Override
    public boolean isReferenceType() {
        return false;
    }

    @Override
    public String describe() {
        return typeParameter.getName();
    }

    @Override
    public ResolvedTypeParameterDeclaration asTypeParameter() {
        return typeParameter;
    }

    @Override
    public ResolvedTypeVariable asTypeVariable() {
        return this;
    }

    @Override
    public boolean isTypeVariable() {
        return true;
    }

    @Override
    public boolean isAssignableBy(ResolvedType other) {
        if (other.isTypeVariable()) {
            return describe().equals(other.describe());
        }
        return true;
    }

    @Override
    public boolean mention(List<ResolvedTypeParameterDeclaration> typeParameters) {
        return typeParameters.contains(typeParameter);
    }

    // /
    // / Erasure
    // /
    // The erasure of a type variable (§4.4) is the erasure of its leftmost bound.
    // If no bound is declared for a type variable, Object is assumed.
    //
    @Override
    public ResolvedType erasure() {
        if (typeParameter.isBounded()) {
            return typeParameter.getBounds().get(0).getType();
        }
        return typeParameter.object();
    }

    /*
     * Returns the resolved type for a type variable.
     */
    @Override
    public ResolvedType solveGenericTypes(Context context) {
    	return context.solveGenericType(describe()).orElse(this);
    }

    @Override
    public String toDescriptor() {
        return String.format("L%s;", qualifiedName());
    }
}

        if (this == o)
            return true;
        if (o == null || getClass() != o.getClass())
            return false;
        ResolvedTypeVariable that = (ResolvedTypeVariable) o;
        if (!typeParameter.getName().equals(that.typeParameter.getName()))
            return false;
        if (typeParameter.declaredOnType() != that.typeParameter.declaredOnType())
            return false;
        if (typeParameter.declaredOnMethod() != that.typeParameter.declaredOnMethod())
            return false;
        return true;
    
<no_super_class>