001    /*
002     * Copyright 2010-2015 JetBrains s.r.o.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.jetbrains.kotlin.descriptors.impl;
018    
019    import kotlin.jvm.functions.Function0;
020    import org.jetbrains.annotations.NotNull;
021    import org.jetbrains.annotations.ReadOnly;
022    import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
023    import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
024    import org.jetbrains.kotlin.descriptors.DeclarationDescriptorVisitor;
025    import org.jetbrains.kotlin.descriptors.SourceElement;
026    import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
027    import org.jetbrains.kotlin.descriptors.annotations.Annotations;
028    import org.jetbrains.kotlin.name.Name;
029    import org.jetbrains.kotlin.resolve.scopes.JetScope;
030    import org.jetbrains.kotlin.resolve.scopes.LazyScopeAdapter;
031    import org.jetbrains.kotlin.storage.NotNullLazyValue;
032    import org.jetbrains.kotlin.storage.StorageManager;
033    import org.jetbrains.kotlin.types.*;
034    import org.jetbrains.kotlin.types.checker.JetTypeChecker;
035    
036    import java.util.Collections;
037    import java.util.Set;
038    
039    import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilPackage.getBuiltIns;
040    
041    public abstract class AbstractTypeParameterDescriptor extends DeclarationDescriptorNonRootImpl implements TypeParameterDescriptor {
042        private final Variance variance;
043        private final boolean reified;
044        private final int index;
045    
046        private final NotNullLazyValue<TypeConstructor> typeConstructor;
047        private final NotNullLazyValue<JetType> defaultType;
048        private final NotNullLazyValue<Set<JetType>> upperBounds;
049        private final NotNullLazyValue<JetType> upperBoundsAsType;
050    
051        protected AbstractTypeParameterDescriptor(
052                @NotNull final StorageManager storageManager,
053                @NotNull DeclarationDescriptor containingDeclaration,
054                @NotNull Annotations annotations,
055                @NotNull Name name,
056                @NotNull Variance variance,
057                boolean isReified,
058                int index,
059                @NotNull SourceElement source
060        ) {
061            super(containingDeclaration, annotations, name, source);
062            this.variance = variance;
063            this.reified = isReified;
064            this.index = index;
065    
066            this.typeConstructor = storageManager.createLazyValue(new Function0<TypeConstructor>() {
067                @Override
068                public TypeConstructor invoke() {
069                    return createTypeConstructor();
070                }
071            });
072            this.defaultType = storageManager.createLazyValue(new Function0<JetType>() {
073                @Override
074                public JetType invoke() {
075                    return JetTypeImpl.create(Annotations.EMPTY, getTypeConstructor(), false, Collections.<TypeProjection>emptyList(),
076                                           new LazyScopeAdapter(storageManager.createLazyValue(
077                                                   new Function0<JetScope>() {
078                                                       @Override
079                                                       public JetScope invoke() {
080                                                           return getUpperBoundsAsType().getMemberScope();
081                                                       }
082                                                   }
083                                           )));
084                }
085            });
086            this.upperBounds = storageManager.createRecursionTolerantLazyValue(new Function0<Set<JetType>>() {
087                @Override
088                public Set<JetType> invoke() {
089                    return resolveUpperBounds();
090                }
091            }, Collections.singleton(ErrorUtils.createErrorType("Recursion while calculating upper bounds")));
092            this.upperBoundsAsType = storageManager.createLazyValue(new Function0<JetType>() {
093                @Override
094                public JetType invoke() {
095                    return computeUpperBoundsAsType();
096                }
097            });
098        }
099    
100        @NotNull
101        @ReadOnly
102        protected abstract Set<JetType> resolveUpperBounds();
103    
104        @NotNull
105        protected abstract TypeConstructor createTypeConstructor();
106    
107        @NotNull
108        @Override
109        public Variance getVariance() {
110            return variance;
111        }
112    
113        @Override
114        public boolean isReified() {
115            return reified;
116        }
117    
118        @Override
119        public int getIndex() {
120            return index;
121        }
122    
123        @NotNull
124        @Override
125        public Set<JetType> getUpperBounds() {
126            return upperBounds.invoke();
127        }
128    
129        @NotNull
130        @Override
131        public JetType getUpperBoundsAsType() {
132            return upperBoundsAsType.invoke();
133        }
134    
135        @NotNull
136        private JetType computeUpperBoundsAsType() {
137            Set<JetType> upperBounds = getUpperBounds();
138            assert !upperBounds.isEmpty() : "Upper bound list is empty in " + getName();
139            KotlinBuiltIns builtIns = getBuiltIns(this);
140            JetType upperBoundsAsType = TypeIntersector.intersectTypes(builtIns, JetTypeChecker.DEFAULT, upperBounds);
141            return upperBoundsAsType != null ? upperBoundsAsType : builtIns.getNothingType();
142        }
143    
144        @NotNull
145        @Override
146        public TypeConstructor getTypeConstructor() {
147            return typeConstructor.invoke();
148        }
149    
150        @NotNull
151        @Override
152        public JetType getDefaultType() {
153            return defaultType.invoke();
154        }
155    
156        @NotNull
157        @Override
158        public Set<JetType> getLowerBounds() {
159            return Collections.singleton(getBuiltIns(this).getNothingType());
160        }
161    
162        @NotNull
163        @Override
164        @Deprecated
165        public TypeParameterDescriptor substitute(@NotNull TypeSubstitutor substitutor) {
166            throw new UnsupportedOperationException("Don't call substitute() on type parameters");
167        }
168    
169        @Override
170        public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
171            return visitor.visitTypeParameterDescriptor(this, data);
172        }
173    }