@@ -795,19 +795,26 @@ class ParameterTypeInformation extends ElementTypeInformation {
795
795
final Local _parameter;
796
796
final AbstractValue _type;
797
797
final FunctionEntity _method;
798
+
799
+ /// The input type is calculated directly from the union of this node's
800
+ /// inputs (i.e. the actual arguments for this parameter). When this
801
+ /// parameter's static type is not trusted, an implicit check will be added
802
+ /// based on this type. [type] on the other hand is the type of this parameter
803
+ /// within the function body so it is narrowed using the static type.
804
+ AbstractValue _inputType;
798
805
bool get _isInstanceMemberParameter =>
799
806
_hasFlag (_Flag .isInstanceMemberParameter);
800
807
bool get _isClosureParameter => _hasFlag (_Flag .isClosureParameter);
801
808
bool get _isInitializingFormal => _hasFlag (_Flag .isInitializingFormal);
802
809
bool _isTearOffClosureParameter = false ;
803
- TypeInformation ? get concreteParameterType =>
804
- _hasFlag (_Flag .isVirtual) ? users.first : null ;
810
+ bool get _isVirtual => _hasFlag (_Flag .isVirtual);
805
811
806
812
ParameterTypeInformation .localFunction (super .abstractValueDomain,
807
813
super .context, this ._parameter, DartType type, this ._method)
808
814
: _type = abstractValueDomain
809
815
.createFromStaticType (type, nullable: true )
810
816
.abstractValue,
817
+ _inputType = abstractValueDomain.uncomputedType,
811
818
super ._internal () {
812
819
_setFlag (_Flag .isClosureParameter);
813
820
}
@@ -822,6 +829,7 @@ class ParameterTypeInformation extends ElementTypeInformation {
822
829
: _type = abstractValueDomain
823
830
.createFromStaticType (type, nullable: true )
824
831
.abstractValue,
832
+ _inputType = abstractValueDomain.uncomputedType,
825
833
super ._internal () {
826
834
_setFlagTo (_Flag .isInitializingFormal, isInitializingFormal);
827
835
}
@@ -831,6 +839,7 @@ class ParameterTypeInformation extends ElementTypeInformation {
831
839
{required bool isVirtual})
832
840
: _type =
833
841
_createInstanceMemberStaticType (abstractValueDomain, type, _method),
842
+ _inputType = abstractValueDomain.uncomputedType,
834
843
super ._withInputs () {
835
844
_setFlag (_Flag .isInstanceMemberParameter);
836
845
_setFlagTo (_Flag .isVirtual, isVirtual);
@@ -916,53 +925,61 @@ class ParameterTypeInformation extends ElementTypeInformation {
916
925
917
926
AbstractValue potentiallyNarrowType (
918
927
AbstractValue mask, InferrerEngine inferrer) {
919
- if (inferrer.closedWorld.annotationsData
920
- .getParameterCheckPolicy (method)
921
- .isTrusted) {
922
- // In checked or strong mode we don't trust the types of the arguments
923
- // passed to a parameter. The means that the checking of a parameter is
924
- // based on the actual arguments.
925
- //
926
- // With --trust-type-annotations or --omit-implicit-checks we _do_ trust
927
- // the arguments passed to a parameter - and we never check them.
928
- //
929
- // In all these cases we _do_ trust the static type of a parameter within
930
- // the method itself. For instance:
931
- //
932
- // method(int i) => i;
933
- // main() {
934
- // dynamic f = method;
935
- // f(0); // valid call
936
- // f(''); // invalid call
937
- // }
938
- //
939
- // Here, in all cases, we infer the returned value of `method` to be an
940
- // `int`. In checked and strong mode we infer the parameter of `method` to
941
- // be either `int` or `String` and therefore insert a check at the entry
942
- // of 'method'. With --trust-type-annotations or --omit-implicit-checks we
943
- // (unsoundly) infer the parameter to be `int` and leave the parameter
944
- // unchecked, and `method` will at runtime actually return a `String` from
945
- // the second invocation.
946
- //
947
- // The trusting of the parameter types within the body of the method is
948
- // is done through `LocalsHandler.update` called in
949
- // `KernelTypeGraphBuilder.handleParameter`.
950
- return _narrowType (inferrer.abstractValueDomain, mask, _type);
951
- }
952
- return mask;
928
+ return _narrowType (inferrer.abstractValueDomain, mask, _type);
929
+ }
930
+
931
+ AbstractValue checkedType (InferrerEngine inferrer) {
932
+ // By default we don't trust the types of the arguments passed to a
933
+ // parameter. This means that the checking of a parameter is based on the
934
+ // actual arguments.
935
+ //
936
+ // With --omit-implicit-checks we _do_ trust the arguments passed to a
937
+ // parameter - and we never check them.
938
+ //
939
+ // In all these cases we _do_ trust the static type of a parameter within
940
+ // the method itself. For instance:
941
+ //
942
+ // method(int i) => i;
943
+ // main() {
944
+ // dynamic f = method;
945
+ // f(0); // valid call
946
+ // f(''); // invalid call
947
+ // }
948
+ //
949
+ // Here, in all cases, we infer the returned value of `method` to be an
950
+ // `int`. By default we infer the parameter of `method` to be either
951
+ // `int` or `String` and therefore insert a check at the entry of 'method'.
952
+ // With --omit-implicit-checks we (unsoundly) infer the parameter to be
953
+ // `int` and leave the parameter unchecked, and `method` will at runtime
954
+ // actually return a `String` from the second invocation.
955
+ //
956
+ // The trusting of the parameter types within the body of the method is
957
+ // handled by `potentiallyNarrowType` on each call to `computeType`.
958
+ return inferrer.closedWorld.annotationsData
959
+ .getParameterCheckPolicy (method)
960
+ .isTrusted
961
+ ? type
962
+ : _inputType;
953
963
}
954
964
955
965
@override
956
966
AbstractValue computeType (InferrerEngine inferrer) {
957
967
final special = handleSpecialCases (inferrer);
958
968
if (special != null ) return special;
959
- return potentiallyNarrowType (
960
- inferrer.types.computeTypeMask (inputs), inferrer);
969
+ final inputType = _inputType = inferrer.types.computeTypeMask (inputs);
970
+ // Virtual parameters are only inputs to other parameters (virtual or
971
+ // concrete) and not function bodies. The user parameters need to know the
972
+ // full set of inputs passed to the virtual parameter.
973
+ return _isVirtual ? inputType : potentiallyNarrowType (inputType, inferrer);
961
974
}
962
975
963
976
@override
964
977
AbstractValue safeType (InferrerEngine inferrer) {
965
- return potentiallyNarrowType (super .safeType (inferrer), inferrer);
978
+ final inputType = _inputType = super .safeType (inferrer);
979
+ // Virtual parameters are only inputs to other parameters (virtual or
980
+ // concrete) and not function bodies. The user parameters need to know the
981
+ // full set of inputs passed to the virtual parameter.
982
+ return _isVirtual ? inputType : potentiallyNarrowType (inputType, inferrer);
966
983
}
967
984
968
985
@override
0 commit comments