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

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: Long line. 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 registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);
Johnni Winther 2015/11/11 09:56:30 Why not 'isInvalid'? Added a comment.
3921 }
3922 kind = ConstructorAccessKind.FACTORY;
3923 break;
3924 case ConstructorResultKind.ABSTRACT:
3925 isInvalid = true;
3926 kind = ConstructorAccessKind.ABSTRACT;
3927 break;
3928 case ConstructorResultKind.INVALID_TYPE:
3929 isInvalid = true;
3930 kind = ConstructorAccessKind.UNRESOLVED_TYPE;
3931 break;
3932 case ConstructorResultKind.UNRESOLVED_CONSTRUCTOR:
3933 registry.registerNewStructure(node,
3934 new NewInvokeStructure(
3935 new ConstructorAccessSemantics(
3936 ConstructorAccessKind.UNRESOLVED_CONSTRUCTOR,
3937 constructor,
3938 type),
3939 selector));
3940 return new ResolutionResult.forElement(constructor);
sigurdm 2015/11/11 08:24:52 It is a bit confusing to have returns and breaks i
Johnni Winther 2015/11/11 09:56:29 Ack. Added a TODO.
3941 case ConstructorResultKind.NON_CONSTANT:
3942 registry.registerNewStructure(node,
3943 new NewInvokeStructure(
3944 new ConstructorAccessSemantics(
3945 ConstructorAccessKind.NON_CONSTANT_CONSTRUCTOR,
3946 constructor,
3947 type),
3948 selector));
3949 return new ResolutionResult.forElement(constructor);
3894 } 3950 }
3895 3951
3896 // [constructor] might be the implementation element 3952 if (!isInvalid) {
3897 // and only declaration elements may be registered. 3953 // [constructor] might be the implementation element
3898 registry.registerStaticUse( 3954 // and only declaration elements may be registered.
3899 new StaticUse.constructorInvoke( 3955 registry.registerStaticUse(
3900 constructor.declaration, callSelector.callStructure)); 3956 new StaticUse.constructorInvoke(
3901 ClassElement cls = constructor.enclosingClass; 3957 constructor.declaration, callStructure));
3902 if (cls.isEnumClass && currentClass != cls) { 3958 // TODO(johniwinther): Avoid registration of `type` in face of redirecting
3903 reporter.reportErrorMessage( 3959 // factory constructors.
3904 node, 3960 registry.registerTypeUse(new TypeUse.instantiation(type));
3905 MessageKind.CANNOT_INSTANTIATE_ENUM,
3906 {'enumName': cls.name});
3907 isValidAsConstant = false;
3908 } 3961 }
3909 3962
3910 InterfaceType type = registry.getType(node); 3963 if (node.isConst) {
3911 if (node.isConst && type.containsTypeVariables) { 3964 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 3965
3924 if (isSymbolConstructor) { 3966 if (constructor == compiler.symbolConstructor) {
3925 if (node.isConst) {
3926 Node argumentNode = node.send.arguments.head; 3967 Node argumentNode = node.send.arguments.head;
3927 ConstantExpression constant = 3968 ConstantExpression constant =
3928 compiler.resolver.constantCompiler.compileNode( 3969 compiler.resolver.constantCompiler.compileNode(
3929 argumentNode, registry.mapping); 3970 argumentNode, registry.mapping);
3930 ConstantValue name = compiler.constants.getConstantValue(constant); 3971 ConstantValue name = compiler.constants.getConstantValue(constant);
3931 if (!name.isString) { 3972 if (!name.isString) {
3932 DartType type = name.getType(coreTypes); 3973 DartType type = name.getType(coreTypes);
3933 reporter.reportErrorMessage( 3974 reporter.reportErrorMessage(
3934 argumentNode, 3975 argumentNode,
3935 MessageKind.STRING_EXPECTED, 3976 MessageKind.STRING_EXPECTED,
3936 {'type': type}); 3977 {'type': type});
3937 } else { 3978 } else {
3938 StringConstantValue stringConstant = name; 3979 StringConstantValue stringConstant = name;
3939 String nameString = stringConstant.toDartString().slowToString(); 3980 String nameString = stringConstant.toDartString().slowToString();
3940 if (validateSymbol(argumentNode, nameString)) { 3981 if (validateSymbol(argumentNode, nameString)) {
3941 registry.registerConstSymbol(nameString); 3982 registry.registerConstSymbol(nameString);
3942 } 3983 }
3943 } 3984 }
3944 } else { 3985 } else if (constructor == compiler.mirrorsUsedConstructor) {
3945 if (!compiler.mirrorUsageAnalyzerTask.hasMirrorUsage( 3986 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 } 3987 }
3952 } else if (isMirrorsUsedConstant) { 3988
3953 compiler.mirrorUsageAnalyzerTask.validate(node, registry.mapping);
3954 }
3955 if (node.isConst) {
3956 analyzeConstantDeferred(node); 3989 analyzeConstantDeferred(node);
3957 3990
3958 // TODO(johnniwinther): Compute this in the [ConstructorResolver]. 3991 if (type.containsTypeVariables) {
3959 // Check that the constructor is not deferred. 3992 reporter.reportErrorMessage(
3960 Send send = node.send.selector.asSend(); 3993 node.send.selector,
3961 if (send != null) { 3994 MessageKind.TYPE_VARIABLE_IN_CONSTANT);
3962 // Of the form `const a.b(...)`. 3995 isValidAsConstant = false;
3963 if (compiler.deferredLoadTask.deferredPrefixElement( 3996 isInvalid = true;
3964 send, registry.mapping) != null) { 3997 }
3965 // `a` is a deferred prefix. 3998
3966 isValidAsConstant = false; 3999 if (result.prefix != null && result.prefix.isDeferred) {
sigurdm 2015/11/11 08:24:52 I think you can use `result.isDeferred` here.
Johnni Winther 2015/11/11 09:56:30 Done.
3967 // TODO(johnniwinther): Create an [ErroneousConstantExpression] here 4000 isValidAsConstant = false;
3968 // when constants are only created during resolution.
3969 }
3970 } 4001 }
3971 4002
3972 if (isValidAsConstant && 4003 if (isValidAsConstant &&
3973 constructor.isConst && 4004 argumentsResult.isValidAsConstant &&
3974 argumentsResult.isValidAsConstant) { 4005 // TODO(johnniwinther): Remove this when all constants are computed
4006 // in resolution.
4007 !constructor.isFromEnvironmentConstructor) {
3975 CallStructure callStructure = argumentsResult.callStructure; 4008 CallStructure callStructure = argumentsResult.callStructure;
3976 List<ConstantExpression> arguments = argumentsResult.constantArguments; 4009 List<ConstantExpression> arguments = argumentsResult.constantArguments;
4010
3977 ConstructedConstantExpression constant = 4011 ConstructedConstantExpression constant =
3978 new ConstructedConstantExpression( 4012 new ConstructedConstantExpression(
3979 type, 4013 type,
3980 constructor, 4014 constructor,
3981 callStructure, 4015 callStructure,
3982 arguments); 4016 arguments);
4017 registry.registerNewStructure(node,
4018 new ConstInvokeStructure(ConstantInvokeKind.CONSTRUCTED, constant));
3983 return new ConstantResult(node, constant); 4019 return new ConstantResult(node, constant);
4020 } else if (isInvalid) {
4021 // Known to be non-constant.
4022 kind == ConstructorAccessKind.NON_CONSTANT_CONSTRUCTOR;
4023 registry.registerNewStructure(node,
4024 new NewInvokeStructure(
4025 new ConstructorAccessSemantics(kind, constructor, type),
4026 selector));
4027 } else {
4028 // Might be valid but we don't know for sure.
sigurdm 2015/11/11 08:24:52 Write where/when this is resolved.
Johnni Winther 2015/11/11 09:56:29 Done.
4029 registry.registerNewStructure(node,
4030 new LateConstInvokeStructure(registry.mapping));
3984 } 4031 }
4032
4033 } else {
4034 // Not constant.
4035 if (constructor == compiler.symbolConstructor &&
4036 !compiler.mirrorUsageAnalyzerTask.hasMirrorUsage(enclosingElement)) {
4037 reporter.reportHintMessage(
4038 node.newToken, MessageKind.NON_CONST_BLOAT,
4039 {'name': coreClasses.symbolClass.name});
4040 }
4041 registry.registerNewStructure(node,
4042 new NewInvokeStructure(
4043 new ConstructorAccessSemantics(kind, constructor, type),
4044 selector));
3985 } 4045 }
3986 4046
3987 return const NoneResult(); 4047 return const NoneResult();
3988 } 4048 }
3989 4049
3990 void checkConstMapKeysDontOverrideEquals(Spannable spannable, 4050 void checkConstMapKeysDontOverrideEquals(Spannable spannable,
3991 MapConstantValue map) { 4051 MapConstantValue map) {
3992 for (ConstantValue key in map.keys) { 4052 for (ConstantValue key in map.keys) {
3993 if (!key.isObject) continue; 4053 if (!key.isObject) continue;
3994 ObjectConstantValue objectConstant = key; 4054 ObjectConstantValue objectConstant = key;
(...skipping 765 matching lines...) Expand 10 before | Expand all | Expand 10 after
4760 } 4820 }
4761 return const NoneResult(); 4821 return const NoneResult();
4762 } 4822 }
4763 } 4823 }
4764 4824
4765 /// Looks up [name] in [scope] and unwraps the result. 4825 /// Looks up [name] in [scope] and unwraps the result.
4766 Element lookupInScope(DiagnosticReporter reporter, Node node, 4826 Element lookupInScope(DiagnosticReporter reporter, Node node,
4767 Scope scope, String name) { 4827 Scope scope, String name) {
4768 return Elements.unwrap(scope.lookup(name), reporter, node); 4828 return Elements.unwrap(scope.lookup(name), reporter, node);
4769 } 4829 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698