001    /*
002     * Copyright 2010-2013 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.jet.lang.resolve;
018    
019    import com.intellij.psi.PsiElement;
020    import com.intellij.psi.PsiNameIdentifierOwner;
021    import org.jetbrains.annotations.NotNull;
022    import org.jetbrains.annotations.Nullable;
023    import org.jetbrains.jet.lang.descriptors.*;
024    import org.jetbrains.jet.lang.descriptors.impl.ConstructorDescriptorImpl;
025    import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor;
026    import org.jetbrains.jet.lang.descriptors.impl.MutablePackageFragmentDescriptor;
027    import org.jetbrains.jet.lang.descriptors.impl.PackageLikeBuilder;
028    import org.jetbrains.jet.lang.psi.*;
029    import org.jetbrains.jet.lang.resolve.name.Name;
030    import org.jetbrains.jet.lang.resolve.name.SpecialNames;
031    import org.jetbrains.jet.lang.resolve.scopes.ChainedScope;
032    import org.jetbrains.jet.lang.resolve.scopes.JetScope;
033    import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
034    import org.jetbrains.jet.lang.resolve.scopes.WriteThroughScope;
035    import org.jetbrains.jet.lang.types.JetType;
036    import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
037    import org.jetbrains.jet.utils.DFS;
038    
039    import javax.inject.Inject;
040    import java.util.*;
041    
042    import static org.jetbrains.jet.lang.diagnostics.Errors.*;
043    import static org.jetbrains.jet.lang.resolve.BindingContext.FQNAME_TO_CLASS_DESCRIPTOR;
044    import static org.jetbrains.jet.lang.resolve.BindingContext.TYPE;
045    import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isEnumEntry;
046    import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isObject;
047    import static org.jetbrains.jet.lang.resolve.ModifiersChecker.getDefaultClassVisibility;
048    import static org.jetbrains.jet.lang.resolve.ModifiersChecker.resolveVisibilityFromModifiers;
049    import static org.jetbrains.jet.lang.resolve.name.SpecialNames.getClassObjectName;
050    
051    public class TypeHierarchyResolver {
052        private static final DFS.Neighbors<ClassDescriptor> CLASS_INHERITANCE_EDGES = new DFS.Neighbors<ClassDescriptor>() {
053            @NotNull
054            @Override
055            public Iterable<ClassDescriptor> getNeighbors(ClassDescriptor current) {
056                List<ClassDescriptor> result = new ArrayList<ClassDescriptor>();
057                for (JetType supertype : current.getDefaultType().getConstructor().getSupertypes()) {
058                    DeclarationDescriptor descriptor = supertype.getConstructor().getDeclarationDescriptor();
059                    if (descriptor instanceof ClassDescriptor) {
060                        result.add((ClassDescriptor) descriptor);
061                    }
062                }
063                DeclarationDescriptor container = current.getContainingDeclaration();
064                if (container instanceof ClassDescriptor) {
065                    result.add((ClassDescriptor) container);
066                }
067                return result;
068            }
069        };
070    
071        @NotNull
072        private ImportsResolver importsResolver;
073        @NotNull
074        private DescriptorResolver descriptorResolver;
075        @NotNull
076        private ScriptHeaderResolver scriptHeaderResolver;
077        @NotNull
078        private MutablePackageFragmentProvider packageFragmentProvider;
079        @NotNull
080        private BindingTrace trace;
081    
082        @Inject
083        public void setImportsResolver(@NotNull ImportsResolver importsResolver) {
084            this.importsResolver = importsResolver;
085        }
086    
087        @Inject
088        public void setDescriptorResolver(@NotNull DescriptorResolver descriptorResolver) {
089            this.descriptorResolver = descriptorResolver;
090        }
091    
092        // SCRIPT: inject script header resolver
093        @Inject
094        public void setScriptHeaderResolver(@NotNull ScriptHeaderResolver scriptHeaderResolver) {
095            this.scriptHeaderResolver = scriptHeaderResolver;
096        }
097    
098        @Inject
099        public void setPackageFragmentProvider(@NotNull MutablePackageFragmentProvider packageFragmentProvider) {
100            this.packageFragmentProvider = packageFragmentProvider;
101        }
102    
103        @Inject
104        public void setTrace(@NotNull BindingTrace trace) {
105            this.trace = trace;
106        }
107    
108        public void process(
109                @NotNull TopDownAnalysisContext c,
110                @NotNull JetScope outerScope,
111                @NotNull PackageLikeBuilder owner,
112                @NotNull Collection<? extends PsiElement> declarations
113        ) {
114    
115            {
116                // TODO: Very temp code - main goal is to remove recursion from collectPackageFragmentsAndClassifiers
117                Queue<JetDeclarationContainer> forDeferredResolve = new LinkedList<JetDeclarationContainer>();
118                forDeferredResolve.addAll(collectPackageFragmentsAndClassifiers(c, outerScope, owner, declarations));
119    
120                while (!forDeferredResolve.isEmpty()) {
121                    JetDeclarationContainer declarationContainer = forDeferredResolve.poll();
122                    assert declarationContainer != null;
123    
124                    DeclarationDescriptor descriptorForDeferredResolve = c.forDeferredResolver.get(declarationContainer);
125                    JetScope scope = c.normalScope.get(declarationContainer);
126    
127                    // Even more temp code
128                    if (descriptorForDeferredResolve instanceof MutableClassDescriptor) {
129                        forDeferredResolve.addAll(
130                                collectPackageFragmentsAndClassifiers(
131                                        c,
132                                        scope,
133                                        ((MutableClassDescriptor) descriptorForDeferredResolve).getBuilder(),
134                                        declarationContainer.getDeclarations()));
135                    }
136                    else if (descriptorForDeferredResolve instanceof MutablePackageFragmentDescriptor) {
137                        forDeferredResolve.addAll(
138                                collectPackageFragmentsAndClassifiers(
139                                        c,
140                                        scope,
141                                        ((MutablePackageFragmentDescriptor) descriptorForDeferredResolve).getBuilder(),
142                                        declarationContainer.getDeclarations()));
143                    }
144                    else {
145                        assert false;
146                    }
147                }
148            }
149    
150            importsResolver.processTypeImports(c);
151    
152            createTypeConstructors(c); // create type constructors for classes and generic parameters, supertypes are not filled in
153            resolveTypesInClassHeaders(c); // Generic bounds and types in supertype lists (no expressions or constructor resolution)
154    
155            c.setClassesTopologicalOrder(topologicallySortClassesAndObjects(c));
156    
157            // Detect and disconnect all loops in the hierarchy
158            detectAndDisconnectLoops(c);
159        }
160    
161        @NotNull
162        private Collection<JetDeclarationContainer> collectPackageFragmentsAndClassifiers(
163                @NotNull TopDownAnalysisContext c,
164                @NotNull JetScope outerScope,
165                @NotNull PackageLikeBuilder owner,
166                @NotNull Iterable<? extends PsiElement> declarations
167        ) {
168            Collection<JetDeclarationContainer> forDeferredResolve = new ArrayList<JetDeclarationContainer>();
169    
170            ClassifierCollector collector = new ClassifierCollector(c, outerScope, owner, forDeferredResolve);
171    
172            for (PsiElement declaration : declarations) {
173                declaration.accept(collector);
174            }
175    
176            return forDeferredResolve;
177        }
178    
179    
180        @NotNull
181        private static ClassKind getClassKind(@NotNull JetClass jetClass) {
182            if (jetClass.isTrait()) return ClassKind.TRAIT;
183            if (jetClass.isAnnotation()) return ClassKind.ANNOTATION_CLASS;
184            if (jetClass.isEnum()) return ClassKind.ENUM_CLASS;
185            return ClassKind.CLASS;
186        }
187    
188        private void createTypeConstructors(@NotNull TopDownAnalysisContext c) {
189            for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry : c.getDeclaredClasses().entrySet()) {
190                JetClassOrObject classOrObject = entry.getKey();
191                MutableClassDescriptor descriptor = (MutableClassDescriptor) entry.getValue();
192                if (classOrObject instanceof JetClass) {
193                    descriptorResolver.resolveMutableClassDescriptor(
194                            c.getTopDownAnalysisParameters(),
195                            (JetClass) classOrObject, descriptor, trace);
196                }
197                else if (classOrObject instanceof JetObjectDeclaration) {
198                    descriptor.setModality(Modality.FINAL);
199                    descriptor.setVisibility(resolveVisibilityFromModifiers(classOrObject, getDefaultClassVisibility(descriptor)));
200                    descriptor.setTypeParameterDescriptors(Collections.<TypeParameterDescriptor>emptyList());
201                }
202    
203                descriptor.createTypeConstructor();
204    
205                ClassKind kind = descriptor.getKind();
206                if (kind == ClassKind.ENUM_ENTRY || kind == ClassKind.OBJECT || kind == ClassKind.ENUM_CLASS) {
207                    MutableClassDescriptor classObject = descriptor.getClassObjectDescriptor();
208                    assert classObject != null : "Enum entries and named objects should have class objects: " + classOrObject.getText();
209    
210                    JetType supertype;
211                    if (kind == ClassKind.ENUM_CLASS) {
212                        supertype = KotlinBuiltIns.getInstance().getAnyType();
213                    }
214                    else {
215                        // This is a clever hack: each enum entry and object declaration (i.e. singleton) has a synthetic class object.
216                        // We make this class object inherit from the singleton here, thus allowing to use the singleton's class object where
217                        // the instance of the singleton is applicable. Effectively all members of the singleton would be present in its class
218                        // object as fake overrides, so you can access them via standard class object notation: ObjectName.memberName()
219                        supertype = descriptor.getDefaultType();
220                    }
221                    classObject.setSupertypes(Collections.singleton(supertype));
222                    classObject.createTypeConstructor();
223                }
224            }
225        }
226    
227        private void resolveTypesInClassHeaders(@NotNull TopDownAnalysisContext c) {
228            for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry : c.getDeclaredClasses().entrySet()) {
229                JetClassOrObject classOrObject = entry.getKey();
230                if (classOrObject instanceof JetClass) {
231                    ClassDescriptorWithResolutionScopes descriptor = entry.getValue();
232                    //noinspection unchecked
233                    descriptorResolver.resolveGenericBounds((JetClass) classOrObject, descriptor, descriptor.getScopeForClassHeaderResolution(),
234                                                            (List) descriptor.getTypeConstructor().getParameters(), trace);
235                }
236            }
237    
238            for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry : c.getDeclaredClasses().entrySet()) {
239                descriptorResolver.resolveSupertypesForMutableClassDescriptor(entry.getKey(), (MutableClassDescriptor) entry.getValue(), trace);
240            }
241        }
242    
243        @NotNull
244        @SuppressWarnings("unchecked")
245        private static List<MutableClassDescriptor> topologicallySortClassesAndObjects(@NotNull TopDownAnalysisContext c) {
246            Collection<ClassDescriptor> sourceClasses = (Collection) c.getAllClasses();
247            List<ClassDescriptor> allClassesOrdered = DFS.topologicalOrder(sourceClasses, CLASS_INHERITANCE_EDGES);
248            allClassesOrdered.retainAll(sourceClasses);
249            return (List) allClassesOrdered;
250        }
251    
252        private void detectAndDisconnectLoops(@NotNull TopDownAnalysisContext c) {
253            List<Runnable> tasks = new ArrayList<Runnable>();
254            for (final MutableClassDescriptor klass : c.getClassesTopologicalOrder()) {
255                for (final JetType supertype : klass.getSupertypes()) {
256                    ClassifierDescriptor supertypeDescriptor = supertype.getConstructor().getDeclarationDescriptor();
257                    if (supertypeDescriptor instanceof ClassDescriptor) {
258                        ClassDescriptor superclass = (ClassDescriptor) supertypeDescriptor;
259                        if (isReachable(superclass, klass, new HashSet<ClassDescriptor>())) {
260                            tasks.add(new Runnable() {
261                                @Override
262                                public void run() {
263                                    klass.getSupertypes().remove(supertype);
264                                }
265                            });
266                            reportCyclicInheritanceHierarchyError(trace, klass, superclass);
267                        }
268                    }
269                }
270            }
271    
272            for (Runnable task : tasks) {
273                task.run();
274            }
275        }
276    
277        // TODO: use DFS and copy to LazyClassTypeConstructor.isReachable
278        private static boolean isReachable(
279                @NotNull ClassDescriptor from,
280                @NotNull MutableClassDescriptor to,
281                @NotNull Set<ClassDescriptor> visited
282        ) {
283            if (!visited.add(from)) return false;
284            for (ClassDescriptor superclass : CLASS_INHERITANCE_EDGES.getNeighbors(from)) {
285                if (superclass == to || isReachable(superclass, to, visited)) return true;
286            }
287            return false;
288        }
289    
290        public static void reportCyclicInheritanceHierarchyError(
291                @NotNull BindingTrace trace,
292                @NotNull ClassDescriptor classDescriptor,
293                @NotNull ClassDescriptor superclass
294        ) {
295            PsiElement psiElement = BindingContextUtils.classDescriptorToDeclaration(trace.getBindingContext(), classDescriptor);
296    
297            PsiElement elementToMark = null;
298            if (psiElement instanceof JetClassOrObject) {
299                JetClassOrObject classOrObject = (JetClassOrObject) psiElement;
300                for (JetDelegationSpecifier delegationSpecifier : classOrObject.getDelegationSpecifiers()) {
301                    JetTypeReference typeReference = delegationSpecifier.getTypeReference();
302                    if (typeReference == null) continue;
303                    JetType supertype = trace.get(TYPE, typeReference);
304                    if (supertype != null && supertype.getConstructor() == superclass.getTypeConstructor()) {
305                        elementToMark = typeReference;
306                    }
307                }
308            }
309            if (elementToMark == null && psiElement instanceof PsiNameIdentifierOwner) {
310                PsiNameIdentifierOwner namedElement = (PsiNameIdentifierOwner) psiElement;
311                PsiElement nameIdentifier = namedElement.getNameIdentifier();
312                if (nameIdentifier != null) {
313                    elementToMark = nameIdentifier;
314                }
315            }
316            if (elementToMark != null) {
317                trace.report(CYCLIC_INHERITANCE_HIERARCHY.on(elementToMark));
318            }
319        }
320    
321        private class ClassifierCollector extends JetVisitorVoid {
322            private final TopDownAnalysisContext c;
323            private final JetScope outerScope;
324            private final PackageLikeBuilder owner;
325            private final Collection<JetDeclarationContainer> forDeferredResolve;
326    
327            public ClassifierCollector(
328                    @NotNull TopDownAnalysisContext c,
329                    @NotNull JetScope outerScope,
330                    @NotNull PackageLikeBuilder owner,
331                    @NotNull Collection<JetDeclarationContainer> forDeferredResolve
332            ) {
333                this.c = c;
334                this.outerScope = outerScope;
335                this.owner = owner;
336                this.forDeferredResolve = forDeferredResolve;
337            }
338    
339            @Override
340            public void visitJetFile(@NotNull JetFile file) {
341                MutablePackageFragmentDescriptor packageFragment = getOrCreatePackageFragmentForFile(file);
342                c.getPackageFragments().put(file, packageFragment);
343                c.addFile(file);
344    
345                PackageViewDescriptor packageView = packageFragment.getContainingDeclaration().getPackage(packageFragment.getFqName());
346                ChainedScope rootPlusPackageScope = new ChainedScope(packageView, "Root scope for " + file, packageView.getMemberScope(), outerScope);
347                WriteThroughScope packageScope = new WriteThroughScope(rootPlusPackageScope, packageFragment.getMemberScope(),
348                                                                         new TraceBasedRedeclarationHandler(trace), "package in file " + file.getName());
349                packageScope.changeLockLevel(WritableScope.LockLevel.BOTH);
350                c.getFileScopes().put(file, packageScope);
351    
352                if (file.isScript()) {
353                    // SCRIPT: process script hierarchy
354                    scriptHeaderResolver.processScriptHierarchy(c, file.getScript(), packageScope);
355                }
356    
357                prepareForDeferredCall(packageScope, packageFragment, file);
358            }
359    
360            @Override
361            public void visitClass(@NotNull JetClass klass) {
362                MutableClassDescriptor mutableClassDescriptor = createClassDescriptorForClass(klass, owner.getOwnerForChildren());
363    
364                owner.addClassifierDescriptor(mutableClassDescriptor);
365            }
366    
367            @Override
368            public void visitObjectDeclaration(@NotNull JetObjectDeclaration declaration) {
369                if (declaration.isObjectLiteral()) {
370                    createClassDescriptorForSingleton(declaration, SpecialNames.NO_NAME_PROVIDED, ClassKind.CLASS);
371                    return;
372                }
373    
374                MutableClassDescriptor descriptor =
375                        createClassDescriptorForSingleton(declaration, JetPsiUtil.safeName(declaration.getName()), ClassKind.OBJECT);
376    
377                owner.addClassifierDescriptor(descriptor);
378                trace.record(FQNAME_TO_CLASS_DESCRIPTOR, JetNamedDeclarationUtil.getUnsafeFQName(declaration), descriptor);
379    
380                descriptor.getBuilder().setClassObjectDescriptor(createSyntheticClassObject(descriptor));
381            }
382    
383            @Override
384            public void visitEnumEntry(@NotNull JetEnumEntry declaration) {
385                MutableClassDescriptor descriptor =
386                        createClassDescriptorForSingleton(declaration, JetPsiUtil.safeName(declaration.getName()), ClassKind.ENUM_ENTRY);
387    
388                owner.addClassifierDescriptor(descriptor);
389    
390                descriptor.getBuilder().setClassObjectDescriptor(createSyntheticClassObject(descriptor));
391            }
392    
393            @Override
394            public void visitTypedef(@NotNull JetTypedef typedef) {
395                trace.report(UNSUPPORTED.on(typedef, "TypeHierarchyResolver"));
396            }
397    
398            @Override
399            public void visitClassObject(@NotNull JetClassObject classObject) {
400                JetObjectDeclaration objectDeclaration = classObject.getObjectDeclaration();
401    
402                DeclarationDescriptor container = owner.getOwnerForChildren();
403    
404                MutableClassDescriptor classObjectDescriptor =
405                        createClassDescriptorForSingleton(objectDeclaration, getClassObjectName(container.getName()), ClassKind.CLASS_OBJECT);
406    
407                PackageLikeBuilder.ClassObjectStatus status =
408                        isEnumEntry(container) || isObject(container) || c.getTopDownAnalysisParameters().isDeclaredLocally() ?
409                        PackageLikeBuilder.ClassObjectStatus.NOT_ALLOWED :
410                        owner.setClassObjectDescriptor(classObjectDescriptor);
411    
412                switch (status) {
413                    case DUPLICATE:
414                        trace.report(MANY_CLASS_OBJECTS.on(classObject));
415                        break;
416                    case NOT_ALLOWED:
417                        trace.report(CLASS_OBJECT_NOT_ALLOWED.on(classObject));
418                        break;
419                    case OK:
420                        // Everything is OK so no errors to trace.
421                        break;
422                }
423            }
424    
425            @NotNull
426            private MutablePackageFragmentDescriptor getOrCreatePackageFragmentForFile(@NotNull JetFile file) {
427                JetPackageDirective packageDirective = file.getPackageDirective();
428                assert packageDirective != null : "scripts are not supported";
429    
430                MutablePackageFragmentDescriptor fragment = packageFragmentProvider.getOrCreateFragment(packageDirective.getFqName());
431    
432                ModuleDescriptor module = packageFragmentProvider.getModule();
433                DescriptorResolver.resolvePackageHeader(packageDirective, module, trace);
434                DescriptorResolver.registerFileInPackage(trace, file);
435                trace.record(BindingContext.FILE_TO_PACKAGE_FRAGMENT, file, fragment);
436    
437                return fragment;
438            }
439    
440    
441            private void createClassObjectForEnumClass(@NotNull MutableClassDescriptor mutableClassDescriptor) {
442                if (mutableClassDescriptor.getKind() == ClassKind.ENUM_CLASS) {
443                    MutableClassDescriptor classObject = createSyntheticClassObject(mutableClassDescriptor);
444                    mutableClassDescriptor.getBuilder().setClassObjectDescriptor(classObject);
445                    classObject.getBuilder().addFunctionDescriptor(DescriptorResolver.createEnumClassObjectValuesMethod(classObject, trace));
446                    classObject.getBuilder().addFunctionDescriptor(DescriptorResolver.createEnumClassObjectValueOfMethod(classObject, trace));
447                }
448            }
449    
450            @NotNull
451            private MutableClassDescriptor createSyntheticClassObject(@NotNull ClassDescriptor classDescriptor) {
452                MutableClassDescriptor classObject = new MutableClassDescriptor(classDescriptor, outerScope, ClassKind.CLASS_OBJECT, false,
453                                                                                getClassObjectName(classDescriptor.getName()));
454    
455                classObject.setModality(Modality.FINAL);
456                classObject.setVisibility(DescriptorUtils.getSyntheticClassObjectVisibility());
457                classObject.setTypeParameterDescriptors(Collections.<TypeParameterDescriptor>emptyList());
458                createPrimaryConstructorForObject(null, classObject);
459                return classObject;
460            }
461    
462            @NotNull
463            private MutableClassDescriptor createClassDescriptorForClass(
464                    @NotNull JetClass klass,
465                    @NotNull DeclarationDescriptor containingDeclaration
466            ) {
467                ClassKind kind = getClassKind(klass);
468                // Kind check is needed in order to not consider enums as inner in any case
469                // (otherwise it would be impossible to create a class object in the enum)
470                boolean isInner = kind == ClassKind.CLASS && klass.isInner();
471                MutableClassDescriptor mutableClassDescriptor = new MutableClassDescriptor(
472                        containingDeclaration, outerScope, kind, isInner, JetPsiUtil.safeName(klass.getName()));
473                c.getDeclaredClasses().put(klass, mutableClassDescriptor);
474                trace.record(FQNAME_TO_CLASS_DESCRIPTOR, JetNamedDeclarationUtil.getUnsafeFQName(klass), mutableClassDescriptor);
475    
476                createClassObjectForEnumClass(mutableClassDescriptor);
477    
478                JetScope classScope = mutableClassDescriptor.getScopeForMemberDeclarationResolution();
479    
480                prepareForDeferredCall(classScope, mutableClassDescriptor, klass);
481    
482                return mutableClassDescriptor;
483            }
484    
485            @NotNull
486            private MutableClassDescriptor createClassDescriptorForSingleton(
487                    @NotNull JetClassOrObject declaration,
488                    @NotNull Name name,
489                    @NotNull ClassKind kind
490            ) {
491                MutableClassDescriptor descriptor = new MutableClassDescriptor(owner.getOwnerForChildren(), outerScope, kind, false, name);
492    
493                prepareForDeferredCall(descriptor.getScopeForMemberDeclarationResolution(), descriptor, declaration);
494    
495                createPrimaryConstructorForObject(declaration, descriptor);
496                trace.record(BindingContext.CLASS, declaration, descriptor);
497    
498                c.getDeclaredClasses().put(declaration, descriptor);
499    
500                return descriptor;
501            }
502    
503            @NotNull
504            private ConstructorDescriptorImpl createPrimaryConstructorForObject(
505                    @Nullable PsiElement object,
506                    @NotNull MutableClassDescriptor mutableClassDescriptor
507            ) {
508                ConstructorDescriptorImpl constructorDescriptor = DescriptorResolver
509                        .createAndRecordPrimaryConstructorForObject(object, mutableClassDescriptor, trace);
510                mutableClassDescriptor.setPrimaryConstructor(constructorDescriptor);
511                return constructorDescriptor;
512            }
513    
514            private void prepareForDeferredCall(
515                    @NotNull JetScope outerScope,
516                    @NotNull DeclarationDescriptor descriptorForDeferredResolve,
517                    @NotNull JetDeclarationContainer container
518            ) {
519                forDeferredResolve.add(container);
520                c.normalScope.put(container, outerScope);
521                c.forDeferredResolver.put(container, descriptorForDeferredResolve);
522            }
523        }
524    }