Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
#2976. Add semantics tests #2998
#2976. Add semantics tests #2998
Changes from 4 commits
25d91e1
ad85162
8a234de
1203145
3597dba
8623da3
6041c65
5d90609
5de5a77
891475b
138bdcf
File filter
Filter by extension
Conversations
Jump to
There are no files selected for viewing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is really hard to test! ;-)
The point could be that a type alias can be non-generic and still denote a parameterized type (
typedef X = SomeType<With, Args>;
), and this allows for the constructor invocations to have the actual type arguments, and it also allows for a static method invocation to ignore the same type arguments (because that's how we treat type aliases when used to access static members).Apart from this, there would be no distinction between this description and a shorter one that simply says "the semantics of
.id
isT.id
, whereT
is the greatest closure of the context type.However, that works for invocations of static methods, but it is not the actual semantics of constructor invocations: For them we strip off the actual type arguments (so the greatest closure operation is ignored ... for both static member invocations and constructor invocations!), and then type inference is performed as if no actual type arguments were passed.
This means that it isn't hugely meaningful to test "as if prefixed by a type alias" at all.
What we need to test is that it works to call a static method even in the case where the context type has actual type arguments (where those actual type arguments must be ignored).
Next, we should test that it works to invoke a constructor in a case where the context type has actual type arguments (e.g.,
List<num>
as context type should make.filled(10, 10)
meanList<num>.filled(10, 10)
, and the type argument should not beint
, as it would be if the context type were_
).Finally, it should work to invoke a constructor with a context type schema (say,
List<Iterable<_>>
), and we should then see that the actual arguments to the constructor invocation plays a role:In this case we'd get
int
from the context type andString
from the actual argument['Hello']
, and the result would then be aMap<int, String>
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And the spec also doesn't use the "like a type alias" phrasing any more. Since yesterday.
What's important to test is that it:
so
.filled
with context typeList<int>
denotes (the constructor)List.filled
. Even ifList
is not in scope.The current spec also doesn't use "the greatest closure of the context type" any more. An occurrence of
_
doesn't matter, it's either in a position where it's irrelevant, or the scheme is_
in which case it doesn't denote a static namespace.To find the static namespace, it just looks at the context type scheme, and if it's of the form
S?
orFutureOr<S>
, it recurses on theS
, and otherwise it only recognizes types of the formC
/C<typeArgs>
whereC
is a type introduced by aclass
,mixin
,enum
orextension type
declaration.(It's written declaratively, "a type scheme denotes a static namespace N if and only if either the type scheme is a type introduced by a type declaration and N is the static namespace of that declaration, or the type scheme is either
S?
orFutureOr<S>
and S denotes the static namespace N.".)So if the context type scheme is a non-generic type or instantiated generic type scheme whose type is introduced by the declaration D, then
.id
denotes the static member namedid
or constructor with base nameid
in D.And if it's a constructor, then it's a raw reference to that constructor, where type arguments to the class can be inferred from arguments or actual context type (not shorthand context, in the cases where those differ.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How can we have a context type
List<int>
ifList
is not in scope or shadowed? It's just a compile-time error.Please, clarify.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can declare a function like
void foo<X>(List<X> xs) {}
in another library 'lib.dart', and then callfoo
from a library that imports 'lib.dart' and imports 'dart:core' with a prefix such thatList
isn't in scope without the prefix.foo(.filled(1, 1))
should then work.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you!