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:
committed by
commit-bot@chromium.org
parent
a971aa8472
commit
2305d7aea1
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user