Fix bug in resolution caused by unresolved fields in annotations

Fixes #31803

Change-Id: Id50713281934bf51f8684c3acf5936edd48e33e4
Reviewed-on: https://dart-review.googlesource.com/35464
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Emily Fortuna <efortuna@google.com>
Commit-Queue: Harry Terkelsen <het@google.com>
This commit is contained in:
Harry Terkelsen
2018-01-19 23:24:47 +00:00
committed by commit-bot@chromium.org
parent a971aa8472
commit 2305d7aea1
3 changed files with 60 additions and 12 deletions
+4 -1
View File
@@ -462,7 +462,10 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
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);
+22 -11
View File
@@ -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<ClassElement> pendingClassesToBeResolved = new Queue<ClassElement>();
/// Classes to be post-processed after the type declaration is resolved.
Queue<ClassElement> pendingClassesToBePostProcessed =
new Queue<ClassElement>();
/// 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);
@@ -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);
}