Differentiate between unresolved class and constructor.

BUG=
R=asgerf@google.com

Review URL: https://codereview.chromium.org//1130773002

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@45591 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
johnniwinther@google.com 2015-05-07 13:02:49 +00:00
parent 568a551386
commit 065b2163e3
6 changed files with 236 additions and 122 deletions

View file

@ -388,17 +388,32 @@ enum ConstructorAccessKind {
///
ABSTRACT,
/// An invocation of an unresolved constructor or an unresolved type.
/// An invocation of a constructor on an unresolved type.
///
/// For instance
/// m() => new Unresolved();
///
UNRESOLVED_TYPE,
/// An invocation of an unresolved constructor.
///
/// For instance
/// class C {
/// C();
/// }
/// m1() => new C.unresolved();
/// m2() => new Unresolved();
/// m() => new C.unresolved();
///
// TODO(johnniwinther): Differentiate between error types.
ERRONEOUS,
UNRESOLVED_CONSTRUCTOR,
/// An const invocation of an non-constant constructor.
///
/// For instance
/// class C {
/// C();
/// }
/// m() => const C();
///
NON_CONSTANT_CONSTRUCTOR,
/// An invocation of an ill-defined redirecting factory constructor.
///
@ -431,7 +446,9 @@ class ConstructorAccessSemantics {
/// `true` if this invocation is erroneous.
bool get isErroneous {
return kind == ConstructorAccessKind.ABSTRACT ||
kind == ConstructorAccessKind.ERRONEOUS ||
kind == ConstructorAccessKind.UNRESOLVED_TYPE ||
kind == ConstructorAccessKind.UNRESOLVED_CONSTRUCTOR ||
kind == ConstructorAccessKind.NON_CONSTANT_CONSTRUCTOR ||
kind == ConstructorAccessKind.ERRONEOUS_REDIRECTING_FACTORY;
}
}

View file

@ -5,7 +5,7 @@
library dart2js.semantics_visitor;
import '../constants/expressions.dart';
import '../dart2jslib.dart' show invariant;
import '../dart2jslib.dart' show invariant, MessageKind;
import '../dart_types.dart';
import '../elements/elements.dart';
import '../helpers/helpers.dart';
@ -3028,9 +3028,9 @@ abstract class SemanticSendVisitor<R, A> {
///
/// where [type] is `C<int>`.
///
// TODO(johnniwinther): Update [type] to be [InterfaceType] when this is no
// longer a catch-all clause for the erroneous constructor invocations.
R errorUnresolvedConstructorInvoke(
// TODO(johnniwinther): Change [type] to [InterfaceType] when is it not
// `dynamic`.
R visitUnresolvedConstructorInvoke(
NewExpression node,
Element constructor,
DartType type,
@ -3045,7 +3045,9 @@ abstract class SemanticSendVisitor<R, A> {
///
/// where [type] is the malformed type `Unresolved`.
///
R errorUnresolvedClassConstructorInvoke(
// TODO(johnniwinther): Change [type] to [MalformedType] when is it not
// `dynamic`.
R visitUnresolvedClassConstructorInvoke(
NewExpression node,
Element element,
MalformedType type,
@ -3053,6 +3055,22 @@ abstract class SemanticSendVisitor<R, A> {
Selector selector,
A arg);
/// Constant invocation of a non-constant constructor.
///
/// For instance
/// class C {
/// C(a, b);
/// }
/// m() => const C(true, 42);
///
R errorNonConstantConstructorInvoke(
NewExpression node,
Element element,
InterfaceType type,
NodeList arguments,
CallStructure callStructure,
A arg);
/// Invocation of a constructor on an abstract [type] with [arguments].
///
/// For instance
@ -3060,7 +3078,7 @@ abstract class SemanticSendVisitor<R, A> {
///
/// where [type] is the malformed type `Unresolved`.
///
R errorAbstractClassConstructorInvoke(
R visitAbstractClassConstructorInvoke(
NewExpression node,
ConstructorElement element,
InterfaceType type,
@ -3080,12 +3098,12 @@ abstract class SemanticSendVisitor<R, A> {
/// m1() => new C(true, 42);
/// m2() => new C.a(true, 42);
///
R errorUnresolvedRedirectingFactoryConstructorInvoke(
R visitUnresolvedRedirectingFactoryConstructorInvoke(
NewExpression node,
ConstructorElement constructor,
InterfaceType type,
NodeList arguments,
Selector selector,
CallStructure callStructure,
A arg);
}

View file

@ -32,17 +32,6 @@ abstract class ErrorBulkMixin<R, A>
return bulkHandleError(node, arg);
}
@override
R errorAbstractClassConstructorInvoke(
NewExpression node,
ConstructorElement element,
InterfaceType type,
NodeList arguments,
CallStructure callStructure,
A arg) {
return bulkHandleError(node, arg);
}
@override
R errorClassTypeLiteralCompound(
Send node,
@ -250,6 +239,17 @@ abstract class ErrorBulkMixin<R, A>
return bulkHandleError(node, arg);
}
@override
R errorNonConstantConstructorInvoke(
NewExpression node,
Element element,
InterfaceType type,
NodeList arguments,
CallStructure callStructure,
A arg) {
return bulkHandleError(node, arg);
}
@override
R errorStaticFunctionSet(
Send node,
@ -442,28 +442,6 @@ abstract class ErrorBulkMixin<R, A>
return bulkHandleError(node, arg);
}
@override
R errorUnresolvedClassConstructorInvoke(
NewExpression node,
Element element,
MalformedType type,
NodeList arguments,
Selector selector,
A arg) {
return bulkHandleError(node, arg);
}
@override
R errorUnresolvedConstructorInvoke(
NewExpression node,
Element constructor,
DartType type,
NodeList arguments,
Selector selector,
A arg) {
return bulkHandleError(node, arg);
}
@override
R errorUnresolvedPostfix(
Send node,
@ -482,17 +460,6 @@ abstract class ErrorBulkMixin<R, A>
return bulkHandleError(node, arg);
}
@override
R errorUnresolvedRedirectingFactoryConstructorInvoke(
NewExpression node,
ConstructorElement constructor,
InterfaceType type,
NodeList arguments,
Selector selector,
A arg) {
return bulkHandleError(node, arg);
}
@override
R errorUnresolvedSet(
Send node,
@ -2341,6 +2308,17 @@ abstract class NewBulkMixin<R, A>
node, "Constructor invocation `#` unhandled.", arg);
}
@override
R visitAbstractClassConstructorInvoke(
NewExpression node,
ConstructorElement element,
InterfaceType type,
NodeList arguments,
CallStructure callStructure,
A arg) {
return bulkHandleNew(node, arg);
}
@override
R visitConstConstructorInvoke(
NewExpression node,
@ -2390,6 +2368,39 @@ abstract class NewBulkMixin<R, A>
A arg) {
return bulkHandleNew(node, arg);
}
@override
R visitUnresolvedClassConstructorInvoke(
NewExpression node,
Element element,
DartType type,
NodeList arguments,
Selector selector,
A arg) {
return bulkHandleNew(node, arg);
}
@override
R visitUnresolvedConstructorInvoke(
NewExpression node,
Element constructor,
DartType type,
NodeList arguments,
Selector selector,
A arg) {
return bulkHandleNew(node, arg);
}
@override
R visitUnresolvedRedirectingFactoryConstructorInvoke(
NewExpression node,
ConstructorElement constructor,
InterfaceType type,
NodeList arguments,
CallStructure callStructure,
A arg) {
return bulkHandleNew(node, arg);
}
}
/// Visitor that implements [SemanticSendVisitor] by the use of `BulkX` mixins.
@ -4798,10 +4809,10 @@ class TraversalSendMixin<R, A> implements SemanticSendVisitor<R, A> {
}
@override
R errorUnresolvedClassConstructorInvoke(
R visitUnresolvedClassConstructorInvoke(
NewExpression node,
Element constructor,
MalformedType type,
DartType type,
NodeList arguments,
Selector selector,
A arg) {
@ -4810,7 +4821,7 @@ class TraversalSendMixin<R, A> implements SemanticSendVisitor<R, A> {
}
@override
R errorUnresolvedConstructorInvoke(
R visitUnresolvedConstructorInvoke(
NewExpression node,
Element constructor,
DartType type,
@ -4872,7 +4883,7 @@ class TraversalSendMixin<R, A> implements SemanticSendVisitor<R, A> {
}
@override
R errorAbstractClassConstructorInvoke(
R visitAbstractClassConstructorInvoke(
NewExpression node,
ConstructorElement element,
InterfaceType type,
@ -4884,12 +4895,24 @@ class TraversalSendMixin<R, A> implements SemanticSendVisitor<R, A> {
}
@override
R errorUnresolvedRedirectingFactoryConstructorInvoke(
R visitUnresolvedRedirectingFactoryConstructorInvoke(
NewExpression node,
ConstructorElement constructor,
InterfaceType type,
NodeList arguments,
Selector selector,
CallStructure callStructure,
A arg) {
apply(arguments, arg);
return null;
}
@override
R errorNonConstantConstructorInvoke(
NewExpression node,
Element element,
InterfaceType type,
NodeList arguments,
CallStructure callStructure,
A arg) {
apply(arguments, arg);
return null;
@ -6596,4 +6619,47 @@ abstract class BaseImplementationOfNewMixin<R, A>
return handleConstructorInvoke(
node, constructor, type, arguments, callStructure, arg);
}
R visitUnresolvedConstructorInvoke(
NewExpression node,
Element constructor,
DartType type,
NodeList arguments,
Selector selector,
A arg) {
return handleConstructorInvoke(
node, constructor, type, arguments, selector.callStructure, arg);
}
R visitUnresolvedClassConstructorInvoke(
NewExpression node,
Element element,
DartType type,
NodeList arguments,
Selector selector,
A arg) {
return handleConstructorInvoke(
node, element, type, arguments, selector.callStructure, arg);
}
R visitAbstractClassConstructorInvoke(
NewExpression node,
ConstructorElement constructor,
InterfaceType type,
NodeList arguments,
CallStructure callStructure,
A arg) {
return handleConstructorInvoke(
node, constructor, type, arguments, callStructure, arg);
}
R visitUnresolvedRedirectingFactoryConstructorInvoke(
NewExpression node,
ConstructorElement constructor,
InterfaceType type,
NodeList arguments,
CallStructure callStructure,
A arg) {
return handleConstructorInvoke(
node, constructor, type, arguments, callStructure, arg);
}
}

View file

@ -419,8 +419,15 @@ abstract class SendResolverMixin {
ConstructorElement constructor,
DartType type) {
if (constructor.isErroneous) {
if (constructor is ErroneousElement) {
ErroneousElement error = constructor;
if (error.messageKind == MessageKind.CANNOT_FIND_CONSTRUCTOR) {
return new ConstructorAccessSemantics(
ConstructorAccessKind.UNRESOLVED_CONSTRUCTOR, constructor, type);
}
}
return new ConstructorAccessSemantics(
ConstructorAccessKind.ERRONEOUS, constructor, type);
ConstructorAccessKind.UNRESOLVED_TYPE, constructor, type);
} else if (constructor.isRedirectingFactory) {
ConstructorElement effectiveTarget = constructor.effectiveTarget;
if (effectiveTarget == constructor ||
@ -482,7 +489,7 @@ abstract class SendResolverMixin {
// This is a non-constant constant constructor invocation, like
// `const Const(method())`.
constructorAccessSemantics = new ConstructorAccessSemantics(
ConstructorAccessKind.ERRONEOUS, element, type);
ConstructorAccessKind.NON_CONSTANT_CONSTRUCTOR, element, type);
} else {
constructorAccessSemantics =
computeConstructorAccessSemantics(element, type);

View file

@ -1937,17 +1937,25 @@ class NewInvokeStructure<R, A> extends NewStructure<R, A> {
semantics.effectiveTargetSemantics.type,
node.send.argumentsNode, callStructure, arg);
case ConstructorAccessKind.ABSTRACT:
return visitor.errorAbstractClassConstructorInvoke(
return visitor.visitAbstractClassConstructorInvoke(
node, semantics.element, semantics.type,
node.send.argumentsNode, callStructure, arg);
case ConstructorAccessKind.ERRONEOUS:
return visitor.errorUnresolvedConstructorInvoke(
case ConstructorAccessKind.UNRESOLVED_CONSTRUCTOR:
return visitor.visitUnresolvedConstructorInvoke(
node, semantics.element, semantics.type,
node.send.argumentsNode, selector, arg);
case ConstructorAccessKind.UNRESOLVED_TYPE:
return visitor.visitUnresolvedClassConstructorInvoke(
node, semantics.element, semantics.type,
node.send.argumentsNode, selector, arg);
case ConstructorAccessKind.NON_CONSTANT_CONSTRUCTOR:
return visitor.errorNonConstantConstructorInvoke(
node, semantics.element, semantics.type,
node.send.argumentsNode, callStructure, arg);
case ConstructorAccessKind.ERRONEOUS_REDIRECTING_FACTORY:
return visitor.errorUnresolvedRedirectingFactoryConstructorInvoke(
return visitor.visitUnresolvedRedirectingFactoryConstructorInvoke(
node, semantics.element, semantics.type,
node.send.argumentsNode, selector, arg);
node.send.argumentsNode, callStructure, arg);
}
throw new SpannableAssertionFailure(node,
"Unhandled constructor invocation kind: ${semantics.kind}");

View file

@ -2268,16 +2268,14 @@ const Map<String, List<Test>> SEND_TESTS = const {
m() => new Class.unresolved(true, 42);
''',
const Visit(
VisitKind.ERROR_UNRESOLVED_CONSTRUCTOR_INVOKE,
VisitKind.VISIT_UNRESOLVED_CONSTRUCTOR_INVOKE,
arguments: '(true,42)')),
const Test(
'''
m() => new Unresolved(true, 42);
''',
const Visit(
// TODO(johnniwinther): Update this to
// `VisitKind.ERROR_UNRESOLVED_CLASS_CONSTRUCTOR_INVOKE`.
VisitKind.ERROR_UNRESOLVED_CONSTRUCTOR_INVOKE,
VisitKind.VISIT_UNRESOLVED_CLASS_CONSTRUCTOR_INVOKE,
arguments: '(true,42)')),
const Test(
'''
@ -2285,7 +2283,7 @@ const Map<String, List<Test>> SEND_TESTS = const {
m() => new AbstractClass();
''',
const Visit(
VisitKind.ERROR_ABSTRACT_CLASS_CONSTRUCTOR_INVOKE,
VisitKind.VISIT_ABSTRACT_CLASS_CONSTRUCTOR_INVOKE,
element: 'generative_constructor(AbstractClass#)',
type: 'AbstractClass',
arguments: '()',
@ -2298,11 +2296,11 @@ const Map<String, List<Test>> SEND_TESTS = const {
m() => new Class(true, 42);
''',
const Visit(
VisitKind.ERROR_UNRESOLVED_REDIRECTING_FACTORY_CONSTRUCTOR_INVOKE,
VisitKind.VISIT_UNRESOLVED_REDIRECTING_FACTORY_CONSTRUCTOR_INVOKE,
element: 'function(Class#)',
arguments: '(true,42)',
type: 'Class',
selector: 'Selector(call, , arity=2)')),
selector: 'CallStructure(arity=2)')),
const Test(
'''
class Class {
@ -2311,11 +2309,11 @@ const Map<String, List<Test>> SEND_TESTS = const {
m() => new Class(true, 42);
''',
const Visit(
VisitKind.ERROR_UNRESOLVED_REDIRECTING_FACTORY_CONSTRUCTOR_INVOKE,
VisitKind.VISIT_UNRESOLVED_REDIRECTING_FACTORY_CONSTRUCTOR_INVOKE,
element: 'function(Class#)',
arguments: '(true,42)',
type: 'Class',
selector: 'Selector(call, , arity=2)')),
selector: 'CallStructure(arity=2)')),
const Test(
'''
class Class {
@ -2325,11 +2323,11 @@ const Map<String, List<Test>> SEND_TESTS = const {
m() => new Class(true, 42);
''',
const Visit(
VisitKind.ERROR_UNRESOLVED_REDIRECTING_FACTORY_CONSTRUCTOR_INVOKE,
VisitKind.VISIT_UNRESOLVED_REDIRECTING_FACTORY_CONSTRUCTOR_INVOKE,
element: 'function(Class#)',
arguments: '(true,42)',
type: 'Class',
selector: 'Selector(call, , arity=2)')),
selector: 'CallStructure(arity=2)')),
const Test(
'''
abstract class AbstractClass {
@ -2341,11 +2339,11 @@ const Map<String, List<Test>> SEND_TESTS = const {
m() => new Class(true, 42);
''',
const Visit(
VisitKind.ERROR_UNRESOLVED_REDIRECTING_FACTORY_CONSTRUCTOR_INVOKE,
VisitKind.VISIT_UNRESOLVED_REDIRECTING_FACTORY_CONSTRUCTOR_INVOKE,
element: 'function(Class#)',
arguments: '(true,42)',
type: 'Class',
selector: 'Selector(call, , arity=2)')),
selector: 'CallStructure(arity=2)')),
],
};
@ -5279,31 +5277,31 @@ class SemanticSendTestVisitor extends SemanticTestVisitor {
}
@override
errorUnresolvedClassConstructorInvoke(
NewExpression node,
Element constructor,
MalformedType type,
NodeList arguments,
Selector selector,
arg) {
// TODO(johnniwinther): Test [type] and [selector].
visits.add(new Visit(
VisitKind.ERROR_UNRESOLVED_CLASS_CONSTRUCTOR_INVOKE,
arguments: arguments));
apply(arguments, arg);
}
@override
errorUnresolvedConstructorInvoke(
visitUnresolvedClassConstructorInvoke(
NewExpression node,
Element constructor,
DartType type,
NodeList arguments,
Selector selector,
arg) {
// TODO(johnniwinther): Test [type] and [selector].
// TODO(johnniwinther): Test [type] when it is not `dynamic`.
visits.add(new Visit(
VisitKind.ERROR_UNRESOLVED_CONSTRUCTOR_INVOKE,
VisitKind.VISIT_UNRESOLVED_CLASS_CONSTRUCTOR_INVOKE,
arguments: arguments));
apply(arguments, arg);
}
@override
visitUnresolvedConstructorInvoke(
NewExpression node,
Element constructor,
DartType type,
NodeList arguments,
Selector selector,
arg) {
// TODO(johnniwinther): Test [type] when it is not `dynamic`.
visits.add(new Visit(
VisitKind.VISIT_UNRESOLVED_CONSTRUCTOR_INVOKE,
arguments: arguments));
apply(arguments, arg);
}
@ -5390,7 +5388,7 @@ class SemanticSendTestVisitor extends SemanticTestVisitor {
}
@override
errorAbstractClassConstructorInvoke(
visitAbstractClassConstructorInvoke(
NewExpression node,
ConstructorElement constructor,
InterfaceType type,
@ -5398,7 +5396,7 @@ class SemanticSendTestVisitor extends SemanticTestVisitor {
CallStructure callStructure,
arg) {
visits.add(new Visit(
VisitKind.ERROR_ABSTRACT_CLASS_CONSTRUCTOR_INVOKE,
VisitKind.VISIT_ABSTRACT_CLASS_CONSTRUCTOR_INVOKE,
element: constructor,
type: type,
arguments: arguments,
@ -5407,19 +5405,19 @@ class SemanticSendTestVisitor extends SemanticTestVisitor {
}
@override
errorUnresolvedRedirectingFactoryConstructorInvoke(
visitUnresolvedRedirectingFactoryConstructorInvoke(
NewExpression node,
ConstructorElement constructor,
InterfaceType type,
NodeList arguments,
Selector selector,
CallStructure callStructure,
arg) {
visits.add(new Visit(
VisitKind.ERROR_UNRESOLVED_REDIRECTING_FACTORY_CONSTRUCTOR_INVOKE,
VisitKind.VISIT_UNRESOLVED_REDIRECTING_FACTORY_CONSTRUCTOR_INVOKE,
element: constructor,
type: type,
arguments: arguments,
selector: selector));
selector: callStructure));
apply(arguments, arg);
}
}
@ -5902,7 +5900,7 @@ class SemanticDeclarationTestVisitor extends SemanticTestVisitor {
}
@override
errorUnresolvedClassConstructorInvoke(
visitUnresolvedClassConstructorInvoke(
NewExpression node,
Element constructor,
MalformedType type,
@ -5911,13 +5909,13 @@ class SemanticDeclarationTestVisitor extends SemanticTestVisitor {
arg) {
// TODO(johnniwinther): Test [type] and [selector].
visits.add(new Visit(
VisitKind.ERROR_UNRESOLVED_CLASS_CONSTRUCTOR_INVOKE,
VisitKind.VISIT_UNRESOLVED_CLASS_CONSTRUCTOR_INVOKE,
arguments: arguments));
apply(arguments, arg);
}
@override
errorUnresolvedConstructorInvoke(
visitUnresolvedConstructorInvoke(
NewExpression node,
Element constructor,
DartType type,
@ -5926,7 +5924,7 @@ class SemanticDeclarationTestVisitor extends SemanticTestVisitor {
arg) {
// TODO(johnniwinther): Test [type] and [selector].
visits.add(new Visit(
VisitKind.ERROR_UNRESOLVED_CONSTRUCTOR_INVOKE,
VisitKind.VISIT_UNRESOLVED_CONSTRUCTOR_INVOKE,
arguments: arguments));
apply(arguments, arg);
}
@ -6013,7 +6011,7 @@ class SemanticDeclarationTestVisitor extends SemanticTestVisitor {
}
@override
errorAbstractClassConstructorInvoke(
visitAbstractClassConstructorInvoke(
NewExpression node,
ConstructorElement constructor,
InterfaceType type,
@ -6021,7 +6019,7 @@ class SemanticDeclarationTestVisitor extends SemanticTestVisitor {
CallStructure callStructure,
arg) {
visits.add(new Visit(
VisitKind.ERROR_ABSTRACT_CLASS_CONSTRUCTOR_INVOKE,
VisitKind.VISIT_ABSTRACT_CLASS_CONSTRUCTOR_INVOKE,
element: constructor,
type: type,
arguments: arguments,
@ -6030,19 +6028,19 @@ class SemanticDeclarationTestVisitor extends SemanticTestVisitor {
}
@override
errorUnresolvedRedirectingFactoryConstructorInvoke(
visitUnresolvedRedirectingFactoryConstructorInvoke(
NewExpression node,
ConstructorElement constructor,
InterfaceType type,
NodeList arguments,
Selector selector,
CallStructure callStructure,
arg) {
visits.add(new Visit(
VisitKind.ERROR_UNRESOLVED_REDIRECTING_FACTORY_CONSTRUCTOR_INVOKE,
VisitKind.VISIT_UNRESOLVED_REDIRECTING_FACTORY_CONSTRUCTOR_INVOKE,
element: constructor,
type: type,
arguments: arguments,
selector: selector));
selector: callStructure));
apply(arguments, arg);
}
}
@ -6239,10 +6237,10 @@ enum VisitKind {
VISIT_THIS_CONSTRUCTOR_INVOKE,
VISIT_FIELD_INITIALIZER,
ERROR_UNRESOLVED_CLASS_CONSTRUCTOR_INVOKE,
ERROR_UNRESOLVED_CONSTRUCTOR_INVOKE,
ERROR_ABSTRACT_CLASS_CONSTRUCTOR_INVOKE,
ERROR_UNRESOLVED_REDIRECTING_FACTORY_CONSTRUCTOR_INVOKE,
VISIT_UNRESOLVED_CLASS_CONSTRUCTOR_INVOKE,
VISIT_UNRESOLVED_CONSTRUCTOR_INVOKE,
VISIT_ABSTRACT_CLASS_CONSTRUCTOR_INVOKE,
VISIT_UNRESOLVED_REDIRECTING_FACTORY_CONSTRUCTOR_INVOKE,
VISIT_INSTANCE_GETTER_DECL,
VISIT_INSTANCE_SETTER_DECL,