Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(451)

Side by Side Diff: pkg/compiler/lib/src/resolution/members.dart

Issue 1437463005: Compute NewStructure in resolution. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Updated cf. comments. Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library dart2js.resolution.members; 5 library dart2js.resolution.members;
6 6
7 import '../common.dart'; 7 import '../common.dart';
8 import '../common/names.dart' show 8 import '../common/names.dart' show
9 Selectors; 9 Selectors;
10 import '../common/resolution.dart' show 10 import '../common/resolution.dart' show
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
44 StaticUse, 44 StaticUse,
45 TypeUse; 45 TypeUse;
46 46
47 import 'access_semantics.dart'; 47 import 'access_semantics.dart';
48 import 'class_members.dart' show MembersCreator; 48 import 'class_members.dart' show MembersCreator;
49 import 'operators.dart'; 49 import 'operators.dart';
50 import 'send_structure.dart'; 50 import 'send_structure.dart';
51 51
52 import 'constructors.dart' show 52 import 'constructors.dart' show
53 ConstructorResolver, 53 ConstructorResolver,
54 ConstructorResult; 54 ConstructorResult,
55 ConstructorResultKind;
55 import 'label_scope.dart' show 56 import 'label_scope.dart' show
56 StatementScope; 57 StatementScope;
57 import 'registry.dart' show 58 import 'registry.dart' show
58 ResolutionRegistry; 59 ResolutionRegistry;
59 import 'resolution.dart' show 60 import 'resolution.dart' show
60 ResolverTask; 61 ResolverTask;
61 import 'resolution_common.dart' show 62 import 'resolution_common.dart' show
62 MappingVisitor; 63 MappingVisitor;
63 import 'resolution_result.dart'; 64 import 'resolution_result.dart';
64 import 'scope.dart' show 65 import 'scope.dart' show
(...skipping 3601 matching lines...) Expand 10 before | Expand all | Expand 10 after
3666 } 3667 }
3667 3668
3668 ResolutionResult visitYield(Yield node) { 3669 ResolutionResult visitYield(Yield node) {
3669 coreClasses.streamClass.ensureResolved(resolution); 3670 coreClasses.streamClass.ensureResolved(resolution);
3670 coreClasses.iterableClass.ensureResolved(resolution); 3671 coreClasses.iterableClass.ensureResolved(resolution);
3671 visit(node.expression); 3672 visit(node.expression);
3672 return const NoneResult(); 3673 return const NoneResult();
3673 } 3674 }
3674 3675
3675 ResolutionResult visitRedirectingFactoryBody(RedirectingFactoryBody node) { 3676 ResolutionResult visitRedirectingFactoryBody(RedirectingFactoryBody node) {
3676 final isSymbolConstructor = enclosingElement == compiler.symbolConstructor;
3677 if (!enclosingElement.isFactoryConstructor) { 3677 if (!enclosingElement.isFactoryConstructor) {
3678 reporter.reportErrorMessage( 3678 reporter.reportErrorMessage(
3679 node, MessageKind.FACTORY_REDIRECTION_IN_NON_FACTORY); 3679 node, MessageKind.FACTORY_REDIRECTION_IN_NON_FACTORY);
3680 reporter.reportHintMessage( 3680 reporter.reportHintMessage(
3681 enclosingElement, MessageKind.MISSING_FACTORY_KEYWORD); 3681 enclosingElement, MessageKind.MISSING_FACTORY_KEYWORD);
3682 } 3682 }
3683
3683 ConstructorElementX constructor = enclosingElement; 3684 ConstructorElementX constructor = enclosingElement;
3684 bool isConstConstructor = constructor.isConst; 3685 bool isConstConstructor = constructor.isConst;
3685 bool isValidAsConstant = isConstConstructor; 3686 bool isValidAsConstant = isConstConstructor;
3686 ConstructorElement redirectionTarget = resolveRedirectingFactory( 3687 ConstructorResult result = resolveRedirectingFactory(
3687 node, inConstContext: isConstConstructor).element; 3688 node, inConstContext: isConstConstructor);
3689 ConstructorElement redirectionTarget = result.element;
3688 constructor.immediateRedirectionTarget = redirectionTarget; 3690 constructor.immediateRedirectionTarget = redirectionTarget;
3689 3691
3690 Node constructorReference = node.constructorReference; 3692 Node constructorReference = node.constructorReference;
3691 if (constructorReference is Send) { 3693 if (result.isDeferred) {
3692 constructor.redirectionDeferredPrefix = 3694 constructor.redirectionDeferredPrefix = result.prefix;
3693 compiler.deferredLoadTask.deferredPrefixElement(constructorReference,
3694 registry.mapping);
3695 } 3695 }
3696 3696
3697 registry.setRedirectingTargetConstructor(node, redirectionTarget); 3697 registry.setRedirectingTargetConstructor(node, redirectionTarget);
3698 switch (result.kind) {
3699 case ConstructorResultKind.GENERATIVE:
3700 case ConstructorResultKind.FACTORY:
3701 // Register a post process to check for cycles in the redirection chain
3702 // and set the actual generative constructor at the end of the chain.
3703 addDeferredAction(constructor, () {
3704 compiler.resolver.resolveRedirectionChain(constructor, node);
3705 });
3706 break;
3707 case ConstructorResultKind.ABSTRACT:
3708 case ConstructorResultKind.INVALID_TYPE:
3709 case ConstructorResultKind.UNRESOLVED_CONSTRUCTOR:
3710 case ConstructorResultKind.NON_CONSTANT:
3711 isValidAsConstant = false;
3712 constructor.setEffectiveTarget(
3713 result.element, result.type, isMalformed: true);
3714 break;
3715 }
3698 if (Elements.isUnresolved(redirectionTarget)) { 3716 if (Elements.isUnresolved(redirectionTarget)) {
3699 registry.registerFeature(Feature.THROW_NO_SUCH_METHOD); 3717 registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);
3700 return const NoneResult(); 3718 return const NoneResult();
3701 } else { 3719 } else {
3702 if (isConstConstructor && 3720 if (isConstConstructor &&
3703 !redirectionTarget.isConst) { 3721 !redirectionTarget.isConst) {
3704 reporter.reportErrorMessage( 3722 reporter.reportErrorMessage(
3705 node, MessageKind.CONSTRUCTOR_IS_NOT_CONST); 3723 node, MessageKind.CONSTRUCTOR_IS_NOT_CONST);
3706 isValidAsConstant = false; 3724 isValidAsConstant = false;
3707 } 3725 }
(...skipping 28 matching lines...) Expand all
3736 redirectionTarget.computeType(resolution); 3754 redirectionTarget.computeType(resolution);
3737 FunctionSignature targetSignature = redirectionTarget.functionSignature; 3755 FunctionSignature targetSignature = redirectionTarget.functionSignature;
3738 constructor.computeType(resolution); 3756 constructor.computeType(resolution);
3739 FunctionSignature constructorSignature = constructor.functionSignature; 3757 FunctionSignature constructorSignature = constructor.functionSignature;
3740 if (!targetSignature.isCompatibleWith(constructorSignature)) { 3758 if (!targetSignature.isCompatibleWith(constructorSignature)) {
3741 assert(!isSubtype); 3759 assert(!isSubtype);
3742 registry.registerFeature(Feature.THROW_NO_SUCH_METHOD); 3760 registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);
3743 isValidAsConstant = false; 3761 isValidAsConstant = false;
3744 } 3762 }
3745 3763
3746 // Register a post process to check for cycles in the redirection chain and
3747 // set the actual generative constructor at the end of the chain.
3748 addDeferredAction(constructor, () {
3749 compiler.resolver.resolveRedirectionChain(constructor, node);
3750 });
3751
3752 registry.registerStaticUse( 3764 registry.registerStaticUse(
3753 new StaticUse.constructorRedirect(redirectionTarget)); 3765 new StaticUse.constructorRedirect(redirectionTarget));
3754 // TODO(johnniwinther): Register the effective target type as part of the 3766 // TODO(johnniwinther): Register the effective target type as part of the
3755 // static use instead. 3767 // static use instead.
3756 registry.registerTypeUse(new TypeUse.instantiation( 3768 registry.registerTypeUse(new TypeUse.instantiation(
3757 redirectionTarget.enclosingClass.thisType 3769 redirectionTarget.enclosingClass.thisType
3758 .subst(type.typeArguments, targetClass.typeVariables))); 3770 .subst(type.typeArguments, targetClass.typeVariables)));
3759 if (isSymbolConstructor) { 3771 if (enclosingElement == compiler.symbolConstructor) {
3760 registry.registerFeature(Feature.SYMBOL_CONSTRUCTOR); 3772 registry.registerFeature(Feature.SYMBOL_CONSTRUCTOR);
3761 } 3773 }
3762 if (isValidAsConstant) { 3774 if (isValidAsConstant) {
3763 List<String> names = <String>[]; 3775 List<String> names = <String>[];
3764 List<ConstantExpression> arguments = <ConstantExpression>[]; 3776 List<ConstantExpression> arguments = <ConstantExpression>[];
3765 int index = 0; 3777 int index = 0;
3766 constructorSignature.forEachParameter((ParameterElement parameter) { 3778 constructorSignature.forEachParameter((ParameterElement parameter) {
3767 if (parameter.isNamed) { 3779 if (parameter.isNamed) {
3768 String name = parameter.name; 3780 String name = parameter.name;
3769 names.add(name); 3781 names.add(name);
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
3864 ResolutionResult result = visit(node.expression); 3876 ResolutionResult result = visit(node.expression);
3865 allowedCategory = oldCategory; 3877 allowedCategory = oldCategory;
3866 sendIsMemberAccess = oldSendIsMemberAccess; 3878 sendIsMemberAccess = oldSendIsMemberAccess;
3867 if (result.kind == ResultKind.CONSTANT) { 3879 if (result.kind == ResultKind.CONSTANT) {
3868 return result; 3880 return result;
3869 } 3881 }
3870 return const NoneResult(); 3882 return const NoneResult();
3871 } 3883 }
3872 3884
3873 ResolutionResult visitNewExpression(NewExpression node) { 3885 ResolutionResult visitNewExpression(NewExpression node) {
3874 bool isValidAsConstant = true; 3886 ConstructorResult result = resolveConstructor(node);
3875 ConstructorElement constructor = resolveConstructor(node).element; 3887 ConstructorElement constructor = result.element;
3876 final bool isSymbolConstructor = constructor == compiler.symbolConstructor;
3877 final bool isMirrorsUsedConstant =
3878 node.isConst && (constructor == compiler.mirrorsUsedConstructor);
3879 Selector callSelector = resolveSelector(node.send, constructor);
3880 ArgumentsResult argumentsResult; 3888 ArgumentsResult argumentsResult;
3881 if (node.isConst) { 3889 if (node.isConst) {
3882 argumentsResult = 3890 argumentsResult =
3883 inConstantContext(() => resolveArguments(node.send.argumentsNode)); 3891 inConstantContext(() => resolveArguments(node.send.argumentsNode));
3884 } else { 3892 } else {
3885 argumentsResult = resolveArguments(node.send.argumentsNode); 3893 argumentsResult = resolveArguments(node.send.argumentsNode);
3886 } 3894 }
3895 // TODO(johnniwinther): Avoid the need for a [Selector].
3896 Selector selector = resolveSelector(node.send, constructor);
3897 CallStructure callStructure = selector.callStructure;
3887 registry.useElement(node.send, constructor); 3898 registry.useElement(node.send, constructor);
3888 if (Elements.isUnresolved(constructor)) { 3899
3889 return new ResolutionResult.forElement(constructor); 3900 DartType type = result.type;
3890 } 3901 ConstructorAccessKind kind;
3891 constructor.computeType(resolution); 3902 NewStructure newStructure;
3892 if (!callSelector.applies(constructor, compiler.world)) { 3903 bool isInvalid = false;
3893 registry.registerFeature(Feature.THROW_NO_SUCH_METHOD); 3904 switch (result.kind) {
3905 case ConstructorResultKind.GENERATIVE:
3906 // Ensure that the signature of [constructor] has been computed.
3907 constructor.computeType(resolution);
3908 if (!callStructure.signatureApplies(constructor.functionSignature)) {
3909 isInvalid = true;
3910 kind = ConstructorAccessKind.INCOMPATIBLE;
3911 registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);
3912 } else {
3913 kind = ConstructorAccessKind.GENERATIVE;
3914 }
3915 break;
3916 case ConstructorResultKind.FACTORY:
3917 // Ensure that the signature of [constructor] has been computed.
3918 constructor.computeType(resolution);
3919 if (!callStructure.signatureApplies(constructor.functionSignature)) {
3920 // The effective target might still be valid(!) so the is not an
3921 // invalid case in itself. For instance
3922 //
3923 // class A {
3924 // factory A() = A.a;
3925 // A.a(a);
3926 // }
3927 // m() => new A(0); // This creates a warning but works at runtime.
3928 //
3929 registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);
3930 }
3931 kind = ConstructorAccessKind.FACTORY;
3932 break;
3933 case ConstructorResultKind.ABSTRACT:
3934 isInvalid = true;
3935 kind = ConstructorAccessKind.ABSTRACT;
3936 break;
3937 case ConstructorResultKind.INVALID_TYPE:
3938 isInvalid = true;
3939 kind = ConstructorAccessKind.UNRESOLVED_TYPE;
3940 break;
3941 case ConstructorResultKind.UNRESOLVED_CONSTRUCTOR:
3942 // TODO(johnniwinther): Unify codepaths to only have one return.
3943 registry.registerNewStructure(node,
3944 new NewInvokeStructure(
3945 new ConstructorAccessSemantics(
3946 ConstructorAccessKind.UNRESOLVED_CONSTRUCTOR,
3947 constructor,
3948 type),
3949 selector));
3950 return new ResolutionResult.forElement(constructor);
3951 case ConstructorResultKind.NON_CONSTANT:
3952 registry.registerNewStructure(node,
3953 new NewInvokeStructure(
3954 new ConstructorAccessSemantics(
3955 ConstructorAccessKind.NON_CONSTANT_CONSTRUCTOR,
3956 constructor,
3957 type),
3958 selector));
3959 return new ResolutionResult.forElement(constructor);
3894 } 3960 }
3895 3961
3896 // [constructor] might be the implementation element 3962 if (!isInvalid) {
3897 // and only declaration elements may be registered. 3963 // [constructor] might be the implementation element
3898 registry.registerStaticUse( 3964 // and only declaration elements may be registered.
3899 new StaticUse.constructorInvoke( 3965 registry.registerStaticUse(
3900 constructor.declaration, callSelector.callStructure)); 3966 new StaticUse.constructorInvoke(
3901 ClassElement cls = constructor.enclosingClass; 3967 constructor.declaration, callStructure));
3902 if (cls.isEnumClass && currentClass != cls) { 3968 // TODO(johniwinther): Avoid registration of `type` in face of redirecting
3903 reporter.reportErrorMessage( 3969 // factory constructors.
3904 node, 3970 registry.registerTypeUse(new TypeUse.instantiation(type));
3905 MessageKind.CANNOT_INSTANTIATE_ENUM,
3906 {'enumName': cls.name});
3907 isValidAsConstant = false;
3908 } 3971 }
3909 3972
3910 InterfaceType type = registry.getType(node); 3973 if (node.isConst) {
3911 if (node.isConst && type.containsTypeVariables) { 3974 bool isValidAsConstant = !isInvalid && constructor.isConst;
3912 reporter.reportErrorMessage(
3913 node.send.selector,
3914 MessageKind.TYPE_VARIABLE_IN_CONSTANT);
3915 isValidAsConstant = false;
3916 }
3917 // TODO(johniwinther): Avoid registration of `type` in face of redirecting
3918 // factory constructors.
3919 registry.registerTypeUse(new TypeUse.instantiation(type));
3920 if (constructor.isGenerativeConstructor && cls.isAbstract) {
3921 isValidAsConstant = false;
3922 }
3923 3975
3924 if (isSymbolConstructor) { 3976 if (constructor == compiler.symbolConstructor) {
3925 if (node.isConst) {
3926 Node argumentNode = node.send.arguments.head; 3977 Node argumentNode = node.send.arguments.head;
3927 ConstantExpression constant = 3978 ConstantExpression constant =
3928 compiler.resolver.constantCompiler.compileNode( 3979 compiler.resolver.constantCompiler.compileNode(
3929 argumentNode, registry.mapping); 3980 argumentNode, registry.mapping);
3930 ConstantValue name = compiler.constants.getConstantValue(constant); 3981 ConstantValue name = compiler.constants.getConstantValue(constant);
3931 if (!name.isString) { 3982 if (!name.isString) {
3932 DartType type = name.getType(coreTypes); 3983 DartType type = name.getType(coreTypes);
3933 reporter.reportErrorMessage( 3984 reporter.reportErrorMessage(
3934 argumentNode, 3985 argumentNode,
3935 MessageKind.STRING_EXPECTED, 3986 MessageKind.STRING_EXPECTED,
3936 {'type': type}); 3987 {'type': type});
3937 } else { 3988 } else {
3938 StringConstantValue stringConstant = name; 3989 StringConstantValue stringConstant = name;
3939 String nameString = stringConstant.toDartString().slowToString(); 3990 String nameString = stringConstant.toDartString().slowToString();
3940 if (validateSymbol(argumentNode, nameString)) { 3991 if (validateSymbol(argumentNode, nameString)) {
3941 registry.registerConstSymbol(nameString); 3992 registry.registerConstSymbol(nameString);
3942 } 3993 }
3943 } 3994 }
3944 } else { 3995 } else if (constructor == compiler.mirrorsUsedConstructor) {
3945 if (!compiler.mirrorUsageAnalyzerTask.hasMirrorUsage( 3996 compiler.mirrorUsageAnalyzerTask.validate(node, registry.mapping);
3946 enclosingElement)) {
3947 reporter.reportHintMessage(
3948 node.newToken, MessageKind.NON_CONST_BLOAT,
3949 {'name': coreClasses.symbolClass.name});
3950 }
3951 } 3997 }
3952 } else if (isMirrorsUsedConstant) { 3998
3953 compiler.mirrorUsageAnalyzerTask.validate(node, registry.mapping);
3954 }
3955 if (node.isConst) {
3956 analyzeConstantDeferred(node); 3999 analyzeConstantDeferred(node);
3957 4000
3958 // TODO(johnniwinther): Compute this in the [ConstructorResolver]. 4001 if (type.containsTypeVariables) {
3959 // Check that the constructor is not deferred. 4002 reporter.reportErrorMessage(
3960 Send send = node.send.selector.asSend(); 4003 node.send.selector,
3961 if (send != null) { 4004 MessageKind.TYPE_VARIABLE_IN_CONSTANT);
3962 // Of the form `const a.b(...)`. 4005 isValidAsConstant = false;
3963 if (compiler.deferredLoadTask.deferredPrefixElement( 4006 isInvalid = true;
3964 send, registry.mapping) != null) { 4007 }
3965 // `a` is a deferred prefix. 4008
3966 isValidAsConstant = false; 4009 if (result.isDeferred) {
3967 // TODO(johnniwinther): Create an [ErroneousConstantExpression] here 4010 isValidAsConstant = false;
3968 // when constants are only created during resolution.
3969 }
3970 } 4011 }
3971 4012
3972 if (isValidAsConstant && 4013 if (isValidAsConstant &&
3973 constructor.isConst && 4014 argumentsResult.isValidAsConstant &&
3974 argumentsResult.isValidAsConstant) { 4015 // TODO(johnniwinther): Remove this when all constants are computed
4016 // in resolution.
4017 !constructor.isFromEnvironmentConstructor) {
3975 CallStructure callStructure = argumentsResult.callStructure; 4018 CallStructure callStructure = argumentsResult.callStructure;
3976 List<ConstantExpression> arguments = argumentsResult.constantArguments; 4019 List<ConstantExpression> arguments = argumentsResult.constantArguments;
4020
3977 ConstructedConstantExpression constant = 4021 ConstructedConstantExpression constant =
3978 new ConstructedConstantExpression( 4022 new ConstructedConstantExpression(
3979 type, 4023 type,
3980 constructor, 4024 constructor,
3981 callStructure, 4025 callStructure,
3982 arguments); 4026 arguments);
4027 registry.registerNewStructure(node,
4028 new ConstInvokeStructure(ConstantInvokeKind.CONSTRUCTED, constant));
3983 return new ConstantResult(node, constant); 4029 return new ConstantResult(node, constant);
4030 } else if (isInvalid) {
4031 // Known to be non-constant.
4032 kind == ConstructorAccessKind.NON_CONSTANT_CONSTRUCTOR;
4033 registry.registerNewStructure(node,
4034 new NewInvokeStructure(
4035 new ConstructorAccessSemantics(kind, constructor, type),
4036 selector));
4037 } else {
4038 // Might be valid but we don't know for sure. The compile-time constant
4039 // evaluator will compute the actual constant as a deferred action.
4040 registry.registerNewStructure(node,
4041 new LateConstInvokeStructure(registry.mapping));
3984 } 4042 }
4043
4044 } else {
4045 // Not constant.
4046 if (constructor == compiler.symbolConstructor &&
4047 !compiler.mirrorUsageAnalyzerTask.hasMirrorUsage(enclosingElement)) {
4048 reporter.reportHintMessage(
4049 node.newToken, MessageKind.NON_CONST_BLOAT,
4050 {'name': coreClasses.symbolClass.name});
4051 }
4052 registry.registerNewStructure(node,
4053 new NewInvokeStructure(
4054 new ConstructorAccessSemantics(kind, constructor, type),
4055 selector));
3985 } 4056 }
3986 4057
3987 return const NoneResult(); 4058 return const NoneResult();
3988 } 4059 }
3989 4060
3990 void checkConstMapKeysDontOverrideEquals(Spannable spannable, 4061 void checkConstMapKeysDontOverrideEquals(Spannable spannable,
3991 MapConstantValue map) { 4062 MapConstantValue map) {
3992 for (ConstantValue key in map.keys) { 4063 for (ConstantValue key in map.keys) {
3993 if (!key.isObject) continue; 4064 if (!key.isObject) continue;
3994 ObjectConstantValue objectConstant = key; 4065 ObjectConstantValue objectConstant = key;
(...skipping 765 matching lines...) Expand 10 before | Expand all | Expand 10 after
4760 } 4831 }
4761 return const NoneResult(); 4832 return const NoneResult();
4762 } 4833 }
4763 } 4834 }
4764 4835
4765 /// Looks up [name] in [scope] and unwraps the result. 4836 /// Looks up [name] in [scope] and unwraps the result.
4766 Element lookupInScope(DiagnosticReporter reporter, Node node, 4837 Element lookupInScope(DiagnosticReporter reporter, Node node,
4767 Scope scope, String name) { 4838 Scope scope, String name) {
4768 return Elements.unwrap(scope.lookup(name), reporter, node); 4839 return Elements.unwrap(scope.lookup(name), reporter, node);
4769 } 4840 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/resolution/constructors.dart ('k') | pkg/compiler/lib/src/resolution/registry.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698