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