// Path: src/com/redhat/ceylon/model/typechecker/model/Type.java
// static void checkDepth() {
//     if (depth.get()>100) {
//         throw new DecidabilityException();
//     }
// }
// 
// Path: src/com/redhat/ceylon/model/typechecker/model/Type.java
// static void decDepth() {
//     depth.set(depth.get()-1);
// }
// 
// Path: src/com/redhat/ceylon/model/typechecker/model/Type.java
// static void incDepth() {
//     depth.set(depth.get()+1);
// }
// 
// Path: src/com/redhat/ceylon/model/typechecker/model/ModelUtil.java
// static final Map<TypeParameter, Type> EMPTY_TYPE_ARG_MAP = 
//         Collections.<TypeParameter,Type>emptyMap();
// 
// Path: src/com/redhat/ceylon/model/typechecker/model/ModelUtil.java
// static final Map<TypeParameter, SiteVariance> EMPTY_VARIANCE_MAP = 
//         emptyMap();
// 
// Path: src/com/redhat/ceylon/model/typechecker/model/ModelUtil.java
// public static boolean isAbstraction(Declaration d) {
//     return d!=null && d.isAbstraction();
// }
// 
// Path: src/com/redhat/ceylon/model/typechecker/model/ModelUtil.java
// public static Type appliedType(
//         TypeDeclaration declaration, 
//         Type typeArgument) {
//     if (declaration==null) return null;
//     return declaration.appliedType(null, 
//             singletonList(typeArgument));
// }


import static com.redhat.ceylon.model.typechecker.model.Type.checkDepth;
import static com.redhat.ceylon.model.typechecker.model.Type.decDepth;
import static com.redhat.ceylon.model.typechecker.model.Type.incDepth;
import static com.redhat.ceylon.model.typechecker.model.ModelUtil.EMPTY_TYPE_ARG_MAP;
import static com.redhat.ceylon.model.typechecker.model.ModelUtil.EMPTY_VARIANCE_MAP;
import static com.redhat.ceylon.model.typechecker.model.ModelUtil.isAbstraction;
import static com.redhat.ceylon.model.typechecker.model.ModelUtil.appliedType;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.redhat.ceylon.model.typechecker.context.TypeCache;
        this.qualifyingType = qualifyingType;
    }
    
    public abstract Declaration getDeclaration();

    public Map<TypeParameter, Type> getTypeArguments() {
        Declaration declaration = getDeclaration();
        if (declaration instanceof Generic) {
            if (TypeCache.isEnabled()) {
                if (typeArgumentsWithDefaults==null) {
                    typeArgumentsWithDefaults = 
                            getTypeArgumentsInternal(declaration);
                }
                return typeArgumentsWithDefaults;
            }
            else {
                return getTypeArgumentsInternal(declaration);
            }
        }
        else {
            return typeArguments;
        }
    }

    private Map<TypeParameter, Type> 
    getTypeArgumentsInternal(Declaration declaration) {
        checkDepth();
        incDepth();
        try {
            return fillInDefaultTypeArguments(
// Path: src/com/redhat/ceylon/model/typechecker/model/Type.java
// static void checkDepth() {
//     if (depth.get()>100) {
//         throw new DecidabilityException();
//     }
// }
// 
// Path: src/com/redhat/ceylon/model/typechecker/model/Type.java
// static void decDepth() {
//     depth.set(depth.get()-1);
// }
// 
// Path: src/com/redhat/ceylon/model/typechecker/model/Type.java
// static void incDepth() {
//     depth.set(depth.get()+1);
// }
// 
// Path: src/com/redhat/ceylon/model/typechecker/model/ModelUtil.java
// static final Map<TypeParameter, Type> EMPTY_TYPE_ARG_MAP = 
//         Collections.<TypeParameter,Type>emptyMap();
// 
// Path: src/com/redhat/ceylon/model/typechecker/model/ModelUtil.java
// static final Map<TypeParameter, SiteVariance> EMPTY_VARIANCE_MAP = 
//         emptyMap();
// 
// Path: src/com/redhat/ceylon/model/typechecker/model/ModelUtil.java
// public static boolean isAbstraction(Declaration d) {
//     return d!=null && d.isAbstraction();
// }
// 
// Path: src/com/redhat/ceylon/model/typechecker/model/ModelUtil.java
// public static Type appliedType(
//         TypeDeclaration declaration, 
//         Type typeArgument) {
//     if (declaration==null) return null;
//     return declaration.appliedType(null, 
//             singletonList(typeArgument));
// }


// Path: src/com/redhat/ceylon/model/typechecker/model/Reference.java
import static com.redhat.ceylon.model.typechecker.model.Type.checkDepth;
import static com.redhat.ceylon.model.typechecker.model.Type.decDepth;
import static com.redhat.ceylon.model.typechecker.model.Type.incDepth;
import static com.redhat.ceylon.model.typechecker.model.ModelUtil.EMPTY_TYPE_ARG_MAP;
import static com.redhat.ceylon.model.typechecker.model.ModelUtil.EMPTY_VARIANCE_MAP;
import static com.redhat.ceylon.model.typechecker.model.ModelUtil.isAbstraction;
import static com.redhat.ceylon.model.typechecker.model.ModelUtil.appliedType;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.redhat.ceylon.model.typechecker.context.TypeCache;

        this.qualifyingType = qualifyingType;
    }
    
    public abstract Declaration getDeclaration();

    public Map<TypeParameter, Type> getTypeArguments() {
        Declaration declaration = getDeclaration();
        if (declaration instanceof Generic) {
            if (TypeCache.isEnabled()) {
                if (typeArgumentsWithDefaults==null) {
                    typeArgumentsWithDefaults = 
                            getTypeArgumentsInternal(declaration);
                }
                return typeArgumentsWithDefaults;
            }
            else {
                return getTypeArgumentsInternal(declaration);
            }
        }
        else {
            return typeArguments;
        }
    }

    private Map<TypeParameter, Type> 
    getTypeArgumentsInternal(Declaration declaration) {
        checkDepth();
        incDepth();
        try {
            return fillInDefaultTypeArguments(
                    declaration,