diff --git a/pkg/compiler/lib/src/resolution/members.dart b/pkg/compiler/lib/src/resolution/members.dart index f920e3c3dc7..c2d433abf07 100644 --- a/pkg/compiler/lib/src/resolution/members.dart +++ b/pkg/compiler/lib/src/resolution/members.dart @@ -462,7 +462,10 @@ class ResolverVisitor extends MappingVisitor { parameterNodes = parameterNodes.tail; }); addDeferredAction(enclosingElement, () { - functionSignature.forEachOptionalParameter((_parameter) { + // Use function.functionSignature instead of functionSignature because + // the signature may have changed. + // TODO(het): Fix this so we can use just 'functionSignature' here. + function.functionSignature.forEachOptionalParameter((_parameter) { ParameterElementX parameter = _parameter; parameter.constant = resolver.constantCompiler.compileConstant(parameter); diff --git a/pkg/compiler/lib/src/resolution/resolution.dart b/pkg/compiler/lib/src/resolution/resolution.dart index c036637a441..4762bc11744 100644 --- a/pkg/compiler/lib/src/resolution/resolution.dart +++ b/pkg/compiler/lib/src/resolution/resolution.dart @@ -582,14 +582,26 @@ class ResolverTask extends CompilerTask { // TODO(johnniwinther): Remove this queue when resolution has been split into // syntax and semantic resolution. - TypeDeclarationElement currentlyResolvedTypeDeclaration; + /// Whether or not we are currently resolving a type declaration. + /// + /// When we are resolving a type declaration, we want to avoid resolving + /// other type declarations that are encountered through type annotations + /// until after we finish resolving the current declaration. + bool isResolvingTypeDeclaration = false; + + /// Classes found in type annotations while resolving a type declaration. + /// + /// These are stored here so that they may be resolved after the original + /// type annotation. Queue pendingClassesToBeResolved = new Queue(); + + /// Classes to be post-processed after the type declaration is resolved. Queue pendingClassesToBePostProcessed = new Queue(); /// Resolve [element] using [resolveTypeDeclaration]. /// - /// This methods ensure that class declarations encountered through type + /// This method ensures that class declarations encountered through type /// annotations during the resolution of [element] are resolved after /// [element] has been resolved. // TODO(johnniwinther): Encapsulate this functionality in a @@ -598,23 +610,22 @@ class ResolverTask extends CompilerTask { TypeDeclarationElement element, resolveTypeDeclaration()) { return reporter.withCurrentElement(element, () { return measure(() { - TypeDeclarationElement previousResolvedTypeDeclaration = - currentlyResolvedTypeDeclaration; - currentlyResolvedTypeDeclaration = element; + bool previouslyResolvingTypeDeclaration = isResolvingTypeDeclaration; + isResolvingTypeDeclaration = true; var result = resolveTypeDeclaration(); - currentlyResolvedTypeDeclaration = previousResolvedTypeDeclaration; - if (currentlyResolvedTypeDeclaration == null) { + isResolvingTypeDeclaration = previouslyResolvingTypeDeclaration; + if (!isResolvingTypeDeclaration) { do { - while (!pendingClassesToBeResolved.isEmpty) { + while (pendingClassesToBeResolved.isNotEmpty) { pendingClassesToBeResolved .removeFirst() .ensureResolved(resolution); } - while (!pendingClassesToBePostProcessed.isEmpty) { + while (pendingClassesToBePostProcessed.isNotEmpty) { _postProcessClassElement( pendingClassesToBePostProcessed.removeFirst()); } - } while (!pendingClassesToBeResolved.isEmpty); + } while (pendingClassesToBeResolved.isNotEmpty); assert(pendingClassesToBeResolved.isEmpty); assert(pendingClassesToBePostProcessed.isEmpty); } @@ -645,7 +656,7 @@ class ResolverTask extends CompilerTask { } void ensureClassWillBeResolvedInternal(ClassElement element) { - if (currentlyResolvedTypeDeclaration == null) { + if (!isResolvingTypeDeclaration) { element.ensureResolved(resolution); } else { pendingClassesToBeResolved.add(element); diff --git a/tests/compiler/dart2js_extra/31803_test.dart b/tests/compiler/dart2js_extra/31803_test.dart new file mode 100644 index 00000000000..03c1f7c529a --- /dev/null +++ b/tests/compiler/dart2js_extra/31803_test.dart @@ -0,0 +1,34 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:expect/expect.dart'; + +// Tests that the compiler doesn't crash on an annotation with fields + +class Annotation { + final Object obj; + const Annotation(this.obj); +} + +class UnusedClass { + final Object x; + + const factory UnusedClass(UnusedArgumentClass x) = UnusedClass._; + + const UnusedClass._(this.x); +} + +class UnusedArgumentClass { + const UnusedArgumentClass(); +} + +@Annotation(const UnusedClass(arg)) +class A {} + +const arg = const UnusedArgumentClass(); + +main() { + var a = new A(); + Expect.isTrue(a != null); +}