From 9d715df625fe93c252a3e31732072fce8574e5f1 Mon Sep 17 00:00:00 2001 From: Leaf Petersen Date: Thu, 29 Dec 2016 17:19:40 -0800 Subject: [PATCH 1/6] Informal proposal for strong mode toplevel inference --- docs/language/informal/toplevel-inference.md | 293 +++++++++++++++++++ 1 file changed, 293 insertions(+) create mode 100644 docs/language/informal/toplevel-inference.md diff --git a/docs/language/informal/toplevel-inference.md b/docs/language/informal/toplevel-inference.md new file mode 100644 index 000000000000..5e712c5923e4 --- /dev/null +++ b/docs/language/informal/toplevel-inference.md @@ -0,0 +1,293 @@ +# Toplevel inference + +Owner: leafp@google.com + +Status: Proposal + + +## Top level inference overview + +Top level inference has two phases: +1. Method inference +2. Static variable and field inference + + +All results from the first phase are available in the second phase. + + +As a general principle, when inference fails it is an error. Tools are free to +behave in implementation specific ways to provide a graceful user experience, +but with respect to the language and its semantics, programs for which inference +fails are unspecified. + + +The intuitive idea behind this proposal is that top level inference works by +first inferring methods, and then doing inference for "field like things" +(static variables, fields, setters, and getters), where we don't allow inference +for "field like things" to depend on the results of inference for "field like +things" except in cases where the dependencies are statically visible. + + +Some broad principles for type inference that the language team has agreed to, +and which this proposal is designed to satisfy: +* Type inference should be free to fail with an error, rather than being + required to always produce some answer +* It should not be possible for a programmer to observe a declaration as having + two different types (e.g. dynamic for recursive uses, but subsequently int). + Some consistent answer (or an error) should always be produced. +* The inference for local variables, toplevel variables, and fields, should + either agree or error out. The same expression should not be inferred + differently at different syntactic positions. It’s ok for an expression to be + inferrable at one level but not at another. +* Obvious types should be inferred +* Inferred and annotated types should be treated the same +* Simple intuition for users +* Efficient to implement +* Type arguments should be mostly inferred + + +A motivating example for the current strong mode implementation (that also +serves as a demonstration of its shortcomings) is as follows: + + +```dart +class A { + var x = 3; +} +var a = new A(); +var b = a.x; +``` + + +To ensure stability with respect to cycles and different orderings, current +strong mode does inference in two passes: first on the static variables, and +secondly on fields (method override based inference is mostly irrelevant for +this discussion). The implementation ensures that inference is stable, but it +has several unfortunate consequences, most notably the following. Inference may +result in the same variable being implicitly seen at two different types. In the +example above, if all declarations are in the same library, then b will be +inferred before x has been inferred, and so b will be inferred to have type +dynamic. The same declaration in a separate library will see the type of a.x +after inference, and hence will be inferred to have type `int`. This violates +one of the principles above, and also means that changes to the library +structure that introduce a cycle may change inference results. + + +## Method inference + + +### Method inference + + +Method inference for a method m behaves as if all method inference for all of +its supertypes has already been performed. + + +If a method leaves a type off of its signature (parameter type or return type) +and it does not override or implement anything from a super type, it is an +error. + + +If a method leaves a type off of its signature (parameter type or return type) +and it does not override or implement anything from a super type, then the +omitted types are treated as dynamic. + + +Otherwise, the missing types are filled in with the type from the overridden +method. If there are multiple overridden/implemented methods and the type to be +filled in does not agree, it is an error. If there is no corresponding +parameter position in the overridden method to infer from, it is treated as +dynamic (e.g. overriding a one parameter method with a method that takes a +second optional parameter). + + +### Setter return types + + +If the return type is left off a setter, the return type is inferred to be +`void`. + + +## Static variable and field inference + + +A “candidate” for inference is any of the following: +* A top level variable definition +* A static class level variable definition +* An instance variable, getter or setter definition with the type annotation + omitted. + + +The *inference dependencies of a candidate* which is inferred via override +inference are the instance fields, setters, and getters that the candidate +overrides. + + +The *inference dependencies of a candidate* which is inferred via initializer +inference are the *inference dependencies of the initializer expression* used to +infer the type of the candidate. + + +The *inference dependencies of an expression* are as defined below +as part of initializer inference. + + +Informally, the inference dependencies of a candidate are all of the program +elements that contribute to inference for the candidate, and hence which must +have their types inferred before the candidate can have its type inferred. Note +that by design, a top level variable or static class variable never depends on +an instance field, setter, or getter. This means that top level variable and +static class variable inference can be done without reference to the results of +field inference. + + +For each candidate, inference for all of its dependencies must be performed +before inference for the candidate is performed. If this cannot be done +(because of a cycle) it is a static error. Note that it is always possible for +the programmer to break a cycle and hence eliminate the error by adding a type +annotation. + + +### Candidate inference + +#### Top level variables + +The inferred type of a top level variable is the type inferred from its +initializer. + +#### Static class variables + +The inferred type of a static class variable is the type inferred from its +initializer. + +#### Instance field, getter, and setter inference + + +The inferred type of a getter, setter, or field is as follows. Note that I say +that a setter overrides a getter if there is a getter of the same name in some +superclass or interface, and similarly for setters overriding getters, fields, +etc. + + +A getter, setter or field which overrides/implements only a getter is inferred +to have the type taken from the overridden getter result type. + + +A getter, setter or field which overrides/implements only a setter is inferred +to have the type taken from the overridden setter parameter. + + +A getter which overrides/implements both a setter and a getter is inferred to +have the type taken from the overridden getter result type. + + +A setter which overrides/implements both a setter and a getter is inferred to +have the type taken from the overridden setter parameter type. + + +A field which overrides/implements both a setter and a getter is inferred to +have the type taken from the overridden setter parameter type if this type is +the same as the return type of the overridden getter (if the types don’t match +inference fails with an error). + + +Note that overriding a field is addressed via the implicit induced getter/setter +pair (or just getter in the case of a final field). + + +A getter or setter with no annotated type that does not override anything is +treated as if it were annotated with dynamic. + + +A field with no annotated type that does not override anything has the type +inferred from its initializer. + + +### Initializer inference + + +Initializer inference works by defining a subset of the expressions in the +language for which we can predictably do inference in a way that is not +sensitive to ordering outside of the static dependencies that are syntactically +apparent in the expression. In particular, field inference cannot change the +outcome of initializer inference. + + +A meta-goal is to keep this inference relatively lightweight and efficient to +implement. + + +In all cases, if initializer inference fails, it is an error and produces no +result. Implementations are free to treat this as a result of dynamic after +emitting the error for the purposes of emitting subsequent error messages, but +the behavior of programs for which initializer inference fails is unspecified. + +#### Immediately evident expressions + +We define a set of expressions with immediately-evident types (called +immediately-evident expressions, abbreviated IE) as follows. Immediately +evident expressions have an inferred type as specified below. Any expression +which is not an IE has no inferred type. For every immediately evident +expression, we also define the set of variable dependencies upon which its +inference relies. + + +* null, boolean, numeric, string, and symbol literals have their corresponding + type. + * No inference dependencies +* A list literal or a map literal with explicit type arguments has the type + `List` or `Map` respectively, where `` or `` are the + provided type arguments. + * No inference dependencies +* A list literal with no type arguments, and for which all of the elements are + IEs, has the type `List` where `T` is the least upper bound of the + inferred types of the elements. + * If the elements do not all have an inferred type, it is an error + * The inference dependencies of the list literal are the collected + dependencies of the elements. +* A map literal with no type arguments, and for which all of the keys and + values are IEs, has the type `Map` where `K` is the least upper bound of + the inferred types of the provided keys, and `V` is the least upper bound of + the provided values. + * If the keys and values do not all have an inferred type, it is an error. + * The inference dependencies of the map literal are the collected + dependencies of the keys and values. +* A type literal has type `Type` + * No inference dependencies +* A function literal with an expression body for which all parameter types are + specified and for which the return expression is an IE and has an inferred + type, has the corresponding function type. + * If the return expression has no inferred type it is an error. + * The inference dependencies are the inference dependencies of the return + expression. +* An instance creation expression with no omitted type arguments has the + obvious type. + * No inference dependencies +* An `as` expression has the cast to type + * No inference dependencies +* A simple or qualified identifier referring to a top level function, getter, + or a static class getter or method, has the inferred type of the identifier. + * If the identifier has no inferred type it is an error. + * The inference dependency of the identifier is itself if the identifier is + a candidate for inference. Otherwise there are no inference dependencies. +* A simple identifier denoting a formal parameter has the annotated type of the + variable + * No inference dependencies. +* A function (or function expression) invocation with no omitted generic + arguments where the applicand is an IE that has an inferred type with a + return type of `T`, has type `T` (with any generic arguments substituted in). + * If the applicand has no inferred type, it is an error. + * The inference dependencies are the inference dependencies of the + applicand. +* A method invocation `o.m(...)` with no omitted type arguments where the + receiver is an IE with inferred type `T` such that `T` provides a signature + for `m` with return type `S` has type `S` (with any generic arguments + substituted in). + * If the receiver has no inferred type, it is an error. + * The inference dependencies are the inference dependencies of the receiver. +* A cascade expression `o..e` where `o` is an IE with type `T`, has inferred + type `T` + * If the cascade target has no inferred type it is an error. + * The inference dependencies are the inference dependencies of the cascade + target. + From 6407d5ded9e08951fedbbe730610608789a424a1 Mon Sep 17 00:00:00 2001 From: Leaf Petersen Date: Fri, 13 Jan 2017 22:28:29 -0800 Subject: [PATCH 2/6] Address feedback 1 --- docs/language/informal/toplevel-inference.md | 80 ++++++++++++-------- 1 file changed, 49 insertions(+), 31 deletions(-) diff --git a/docs/language/informal/toplevel-inference.md b/docs/language/informal/toplevel-inference.md index 5e712c5923e4..637a187747d7 100644 --- a/docs/language/informal/toplevel-inference.md +++ b/docs/language/informal/toplevel-inference.md @@ -8,9 +8,17 @@ Status: Proposal ## Top level inference overview Top level inference has two phases: -1. Method inference -2. Static variable and field inference +1. **Method override inference** + * If you omit a return type or parameter type from an overridden method, + inference will try to fill in the missing type using the signature of the + method you are overriding. +2. **Static variable and field inference** + * If you omit the type of a field, setter, or getter, which overrides a + corresponding member of a superclass, then inference will try to fill in the + missing type using the type of the corresponding member of the superclass. + * Otherwise, declarations of static variables and fields that omit a type + will be inferred from their initializer if present. All results from the first phase are available in the second phase. @@ -24,8 +32,8 @@ fails are unspecified. The intuitive idea behind this proposal is that top level inference works by first inferring methods, and then doing inference for "field like things" (static variables, fields, setters, and getters), where we don't allow inference -for "field like things" to depend on the results of inference for "field like -things" except in cases where the dependencies are statically visible. +for "field like things" to depend on the results of inference for other "field +like things" except in cases where the dependencies are statically predictable. Some broad principles for type inference that the language team has agreed to, @@ -33,8 +41,10 @@ and which this proposal is designed to satisfy: * Type inference should be free to fail with an error, rather than being required to always produce some answer * It should not be possible for a programmer to observe a declaration as having - two different types (e.g. dynamic for recursive uses, but subsequently int). - Some consistent answer (or an error) should always be produced. + two different types at difference points in the program (e.g. dynamic for + recursive uses, but subsequently int). Some consistent answer (or an error) + should always be produced. See the example below for an approach that + violates this principle. * The inference for local variables, toplevel variables, and fields, should either agree or error out. The same expression should not be inferred differently at different syntactic positions. It’s ok for an expression to be @@ -62,15 +72,15 @@ var b = a.x; To ensure stability with respect to cycles and different orderings, current strong mode does inference in two passes: first on the static variables, and secondly on fields (method override based inference is mostly irrelevant for -this discussion). The implementation ensures that inference is stable, but it -has several unfortunate consequences, most notably the following. Inference may -result in the same variable being implicitly seen at two different types. In the -example above, if all declarations are in the same library, then b will be -inferred before x has been inferred, and so b will be inferred to have type -dynamic. The same declaration in a separate library will see the type of a.x -after inference, and hence will be inferred to have type `int`. This violates -one of the principles above, and also means that changes to the library -structure that introduce a cycle may change inference results. +this discussion). This ensures that inference is stable, but it has several +unfortunate consequences, most notably the following. Inference may result in +the same variable being implicitly seen at two different types. In the example +above, if all declarations are in the same library, then b will be inferred +before x has been inferred, and so b will be inferred to have type dynamic. The +same declaration in a separate library will see the type of a.x after inference, +and hence will be inferred to have type `int`. This violates one of the +principles above, and also means that changes to the library structure that +introduce a cycle may change inference results. ## Method inference @@ -83,11 +93,6 @@ Method inference for a method m behaves as if all method inference for all of its supertypes has already been performed. -If a method leaves a type off of its signature (parameter type or return type) -and it does not override or implement anything from a super type, it is an -error. - - If a method leaves a type off of its signature (parameter type or return type) and it does not override or implement anything from a super type, then the omitted types are treated as dynamic. @@ -187,8 +192,8 @@ have the type taken from the overridden setter parameter type. A field which overrides/implements both a setter and a getter is inferred to have the type taken from the overridden setter parameter type if this type is -the same as the return type of the overridden getter (if the types don’t match -inference fails with an error). +the same as the return type of the overridden getter (if the types are not the +same then inference fails with an error). Note that overriding a field is addressed via the implicit induced getter/setter @@ -239,12 +244,18 @@ inference relies. `List` or `Map` respectively, where `` or `` are the provided type arguments. * No inference dependencies -* A list literal with no type arguments, and for which all of the elements are - IEs, has the type `List` where `T` is the least upper bound of the - inferred types of the elements. +* A non-empty list literal with no type arguments, and for which all of the + elements are IEs, has the type `List` where `T` is the least upper bound + of the inferred types of the elements. * If the elements do not all have an inferred type, it is an error * The inference dependencies of the list literal are the collected dependencies of the elements. +* An non-const empty list literal with no type arguments has the type + `List`. + * No inference dependencies. +* A const empty list literal with no type arguments has the type + `List`. + * No inference dependencies. * A map literal with no type arguments, and for which all of the keys and values are IEs, has the type `Map` where `K` is the least upper bound of the inferred types of the provided keys, and `V` is the least upper bound of @@ -252,11 +263,17 @@ inference relies. * If the keys and values do not all have an inferred type, it is an error. * The inference dependencies of the map literal are the collected dependencies of the keys and values. +* An non-const empty map literal with no type arguments has the type + `Map`. + * No inference dependencies. +* A const empty map literal with no type arguments has the type `Map`. + * No inference dependencies. * A type literal has type `Type` * No inference dependencies * A function literal with an expression body for which all parameter types are - specified and for which the return expression is an IE and has an inferred - type, has the corresponding function type. + type annotated and for which the return expression is an IE and has an + inferred type, has the corresponding function type. * If the return expression has no inferred type it is an error. * The inference dependencies are the inference dependencies of the return expression. @@ -265,13 +282,14 @@ inference relies. * No inference dependencies * An `as` expression has the cast to type * No inference dependencies -* A simple or qualified identifier referring to a top level function, getter, - or a static class getter or method, has the inferred type of the identifier. +* A simple or qualified identifier referring to a top level function, static + variable, field, getter; or a static class variable, static getter or method; + has the inferred type of the identifier. * If the identifier has no inferred type it is an error. * The inference dependency of the identifier is itself if the identifier is a candidate for inference. Otherwise there are no inference dependencies. -* A simple identifier denoting a formal parameter has the annotated type of the - variable +* A simple identifier denoting a formal parameter has the type with which it was + annotated. * No inference dependencies. * A function (or function expression) invocation with no omitted generic arguments where the applicand is an IE that has an inferred type with a From fde62aeac89564ba232c9a9c08bfc392e9ef6ee9 Mon Sep 17 00:00:00 2001 From: Leaf Petersen Date: Tue, 28 Feb 2017 15:51:37 -0800 Subject: [PATCH 3/6] Address more comments --- docs/language/informal/toplevel-inference.md | 85 +++++++++++++------- 1 file changed, 56 insertions(+), 29 deletions(-) diff --git a/docs/language/informal/toplevel-inference.md b/docs/language/informal/toplevel-inference.md index 637a187747d7..e961c4a5a3b6 100644 --- a/docs/language/informal/toplevel-inference.md +++ b/docs/language/informal/toplevel-inference.md @@ -70,17 +70,17 @@ var b = a.x; To ensure stability with respect to cycles and different orderings, current -strong mode does inference in two passes: first on the static variables, and -secondly on fields (method override based inference is mostly irrelevant for -this discussion). This ensures that inference is stable, but it has several -unfortunate consequences, most notably the following. Inference may result in -the same variable being implicitly seen at two different types. In the example -above, if all declarations are in the same library, then b will be inferred -before x has been inferred, and so b will be inferred to have type dynamic. The -same declaration in a separate library will see the type of a.x after inference, -and hence will be inferred to have type `int`. This violates one of the -principles above, and also means that changes to the library structure that -introduce a cycle may change inference results. +strong mode does inference in two passes: firstly on the static and top-level +variables, and secondly on fields (method override based inference is mostly +irrelevant for this discussion). This ensures that inference is stable, but it +has several unfortunate consequences, most notably the following. Inference may +result in the same variable being implicitly seen at two different types. In the +example above, if all declarations are in the same library, then b will be +inferred before x has been inferred, and so b will be inferred to have type +dynamic. The same declaration in a separate library will see the type of a.x +after inference, and hence will be inferred to have type `int`. This violates +one of the principles above, and also means that changes to the library +structure that introduce a cycle may change inference results. ## Method inference @@ -116,11 +116,11 @@ If the return type is left off a setter, the return type is inferred to be ## Static variable and field inference -A “candidate” for inference is any of the following: +A “candidate” for inference is one of any of the following kinds of definitions, +for which the type annotation has been omitted: * A top level variable definition * A static class level variable definition -* An instance variable, getter or setter definition with the type annotation - omitted. +* An instance variable, getter or setter definition. The *inference dependencies of a candidate* which is inferred via override @@ -168,10 +168,10 @@ initializer. #### Instance field, getter, and setter inference -The inferred type of a getter, setter, or field is as follows. Note that I say +The inferred type of a getter, setter, or field is as follows. Note that we say that a setter overrides a getter if there is a getter of the same name in some -superclass or interface, and similarly for setters overriding getters, fields, -etc. +superclass or interface (explicitly declared or induced by an instance variable +declaration), and similarly for setters overriding getters, fields, etc. A getter, setter or field which overrides/implements only a getter is inferred @@ -227,7 +227,7 @@ result. Implementations are free to treat this as a result of dynamic after emitting the error for the purposes of emitting subsequent error messages, but the behavior of programs for which initializer inference fails is unspecified. -#### Immediately evident expressions +#### Expressions with immediately-evident type We define a set of expressions with immediately-evident types (called immediately-evident expressions, abbreviated IE) as follows. Immediately @@ -237,9 +237,24 @@ expression, we also define the set of variable dependencies upon which its inference relies. -* null, boolean, numeric, string, and symbol literals have their corresponding - type. +* null, boolean, numeric, string, type, and symbol literals have their + corresponding type. * No inference dependencies +* An `await` of an expression has type `T` if the expression is an immediately +evident expression with type `T` or `Future`. + * Inference dependencies are the inference dependencies of the awaited + expression +* A `throw` expression has type `bottom`. + * No inference dependencies +* A parenthesized expression has the inferred type of the sub-expression + * Inference dependencies are the dependencies of the sub-expression +* A conditional expression where both values are immediately evident expressions + has type `T` where `T` is the least upper bound of the inferred type of the + two returned sub-expressions. + * Inference dependencies are the union of the inference dependencies of the + two returned sub-expressions. +* Logical boolean expressions have inferred type `boolean`. + * No inference dependencies * A list literal or a map literal with explicit type arguments has the type `List` or `Map` respectively, where `` or `` are the provided type arguments. @@ -254,7 +269,7 @@ inference relies. `List`. * No inference dependencies. * A const empty list literal with no type arguments has the type - `List`. + `List`. * No inference dependencies. * A map literal with no type arguments, and for which all of the keys and values are IEs, has the type `Map` where `K` is the least upper bound of @@ -266,29 +281,39 @@ inference relies. * An non-const empty map literal with no type arguments has the type `Map`. * No inference dependencies. -* A const empty map literal with no type arguments has the type `Map`. +* A const empty map literal with no type arguments has the type `Map`. * No inference dependencies. -* A type literal has type `Type` - * No inference dependencies * A function literal with an expression body for which all parameter types are type annotated and for which the return expression is an IE and has an inferred type, has the corresponding function type. * If the return expression has no inferred type it is an error. * The inference dependencies are the inference dependencies of the return - expression. + expression. + * If the function is marked `async`, then the return type of the function is + inferred as `Future>` where `T` is the inferred type of the + return expression and flatten is as described in the spec. +* An instance creation expression with no omitted type arguments has the + obvious type. + * No inference dependencies * An instance creation expression with no omitted type arguments has the obvious type. * No inference dependencies * An `as` expression has the cast to type * No inference dependencies +* An `is` expression has type boolean + * No inference dependencies * A simple or qualified identifier referring to a top level function, static variable, field, getter; or a static class variable, static getter or method; - has the inferred type of the identifier. - * If the identifier has no inferred type it is an error. + or an instance method; has the inferred type of the identifier. + * Otherwise, if the identifier has no inferred or annotated type then it is + an error. + * Note: specifically, references to instance fields and instance getters are + disallowed here. * The inference dependency of the identifier is itself if the identifier is a candidate for inference. Otherwise there are no inference dependencies. -* A simple identifier denoting a formal parameter has the type with which it was +* A simple identifier denoting a formal parameter which has an annotated type is + an immediately evident expression and has the type with which it was annotated. * No inference dependencies. * A function (or function expression) invocation with no omitted generic @@ -309,3 +334,5 @@ inference relies. * The inference dependencies are the inference dependencies of the cascade target. +Note: Assignment expressions are not immediately evident expressions, and +if-null expressions are not immediately evident expressions. From ade26bda8a68548f963edb44e63417e8e79c6d07 Mon Sep 17 00:00:00 2001 From: Leaf Petersen Date: Tue, 7 Mar 2017 11:26:48 -0800 Subject: [PATCH 4/6] Address comments from @scheglov --- docs/language/informal/toplevel-inference.md | 41 +++++++++++++------- pkg/dev_compiler/tool/global_compile.dart | 2 +- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/docs/language/informal/toplevel-inference.md b/docs/language/informal/toplevel-inference.md index e961c4a5a3b6..22747b29abb6 100644 --- a/docs/language/informal/toplevel-inference.md +++ b/docs/language/informal/toplevel-inference.md @@ -10,9 +10,9 @@ Status: Proposal Top level inference has two phases: 1. **Method override inference** - * If you omit a return type or parameter type from an overridden method, - inference will try to fill in the missing type using the signature of the - method you are overriding. + * If you omit a return type or parameter type from an overridden or + implemented method, inference will try to fill in the missing type using the + signature of the method you are overriding. 2. **Static variable and field inference** * If you omit the type of a field, setter, or getter, which overrides a corresponding member of a superclass, then inference will try to fill in the @@ -98,12 +98,12 @@ and it does not override or implement anything from a super type, then the omitted types are treated as dynamic. -Otherwise, the missing types are filled in with the type from the overridden -method. If there are multiple overridden/implemented methods and the type to be -filled in does not agree, it is an error. If there is no corresponding -parameter position in the overridden method to infer from, it is treated as -dynamic (e.g. overriding a one parameter method with a method that takes a -second optional parameter). +Otherwise, the missing types are filled in with the type from the overridden or +implemented method. If there are multiple overridden/implemented methods and +the type to be filled in does not agree, it is an error. If there is no +corresponding parameter position in the overridden method to infer from, it is +treated as dynamic (e.g. overriding a one parameter method with a method that +takes a second optional parameter). ### Setter return types @@ -236,6 +236,9 @@ which is not an IE has no inferred type. For every immediately evident expression, we also define the set of variable dependencies upon which its inference relies. +The intention is that toplevel inference should always return the same result as +local inference, or else produce an error. + * null, boolean, numeric, string, type, and symbol literals have their corresponding type. @@ -253,8 +256,23 @@ evident expression with type `T` or `Future`. two returned sub-expressions. * Inference dependencies are the union of the inference dependencies of the two returned sub-expressions. -* Logical boolean expressions have inferred type `boolean`. +* Logical boolean expressions and equality expressions have inferred type + `boolean`. * No inference dependencies +* Relational expressions, bitwise expressions, and shift expressions are treated +as the appropriate method call as defined in the spec. + * Inference dependencies are those of the left hand operand. +* A multiplicative binary expression is treated as a method call as defined in + the spec, with the same exceptions for when the left hand operand is of type `int`. + * Inference dependencies are those of the left hand operand. +* Applications of the prefix operator `!` have type `boolean` + * No inference dependencies +* Applications of the prefix operators `++` and `--` have the type of the operand. + * Inference dependencies are those of the operand. +* Applications of other prefix operators are treated as method calls. + * Inference dependencies are those of the operand. +* Application of a postfix operator to an expression `e` has the inferred type of `e`. + * Inference dependencies are those of the operand. * A list literal or a map literal with explicit type arguments has the type `List` or `Map` respectively, where `` or `` are the provided type arguments. @@ -296,9 +314,6 @@ evident expression with type `T` or `Future`. * An instance creation expression with no omitted type arguments has the obvious type. * No inference dependencies -* An instance creation expression with no omitted type arguments has the - obvious type. - * No inference dependencies * An `as` expression has the cast to type * No inference dependencies * An `is` expression has type boolean diff --git a/pkg/dev_compiler/tool/global_compile.dart b/pkg/dev_compiler/tool/global_compile.dart index 56f1b0a5d3f3..bdd13e0485fd 100644 --- a/pkg/dev_compiler/tool/global_compile.dart +++ b/pkg/dev_compiler/tool/global_compile.dart @@ -60,7 +60,7 @@ void main(List args) { '--modules=legacy', // TODO(vsm): Change this to use common format. '--single-out-file', '--inline-source-map', - '-p', + '--packages', packageRoot ]; if (metadata) { From 77fcf54c673a6b4be8db95d0a12e83c8b491fef4 Mon Sep 17 00:00:00 2001 From: Leaf Petersen Date: Tue, 7 Mar 2017 13:09:04 -0800 Subject: [PATCH 5/6] Additional clarifications --- docs/language/informal/toplevel-inference.md | 23 +++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/docs/language/informal/toplevel-inference.md b/docs/language/informal/toplevel-inference.md index 22747b29abb6..9b38170b0aec 100644 --- a/docs/language/informal/toplevel-inference.md +++ b/docs/language/informal/toplevel-inference.md @@ -99,11 +99,17 @@ omitted types are treated as dynamic. Otherwise, the missing types are filled in with the type from the overridden or -implemented method. If there are multiple overridden/implemented methods and -the type to be filled in does not agree, it is an error. If there is no -corresponding parameter position in the overridden method to infer from, it is -treated as dynamic (e.g. overriding a one parameter method with a method that -takes a second optional parameter). +implemented method. If there are multiple overridden/implemented methods, and +any two of them have non-equal types (declared or inferred) for a parameter +position which is being inferred for the overriding method, it is an error. If +there is no corresponding parameter position in the overridden method to infer +from and the signatures are compatible, it is treated as dynamic +(e.g. overriding a one parameter method with a method that takes a second +optional parameter). Note: if there is no corresponding parameter position in +the overriden method to infer from and the signatures are incompatible +(e.g. overriding a one parameter method with a method that takes a second +non-optional parameter), the inference result is not defined and tools are free +to either emit an error, or to defer the error to override checking. ### Setter return types @@ -327,9 +333,10 @@ as the appropriate method call as defined in the spec. disallowed here. * The inference dependency of the identifier is itself if the identifier is a candidate for inference. Otherwise there are no inference dependencies. -* A simple identifier denoting a formal parameter which has an annotated type is - an immediately evident expression and has the type with which it was - annotated. +* A simple identifier denoting a formal parameter which has an annotated type + and is not a promotion candidate is an immediately evident expression and has + the type with which it was annotated. + * Note: the treatment of promotion candidates is still under discussion. * No inference dependencies. * A function (or function expression) invocation with no omitted generic arguments where the applicand is an IE that has an inferred type with a From 8f2be46aac7705ab6a1024a795aaf977519a8be2 Mon Sep 17 00:00:00 2001 From: Leaf Petersen Date: Fri, 24 Mar 2017 16:19:29 -0700 Subject: [PATCH 6/6] Clarify final field override inference --- docs/language/informal/toplevel-inference.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/language/informal/toplevel-inference.md b/docs/language/informal/toplevel-inference.md index 9b38170b0aec..e694b7cdf562 100644 --- a/docs/language/informal/toplevel-inference.md +++ b/docs/language/informal/toplevel-inference.md @@ -188,18 +188,18 @@ A getter, setter or field which overrides/implements only a setter is inferred to have the type taken from the overridden setter parameter. -A getter which overrides/implements both a setter and a getter is inferred to -have the type taken from the overridden getter result type. +A getter or final field which overrides/implements both a setter and a getter is +inferred to have the type taken from the overridden getter result type. A setter which overrides/implements both a setter and a getter is inferred to have the type taken from the overridden setter parameter type. -A field which overrides/implements both a setter and a getter is inferred to -have the type taken from the overridden setter parameter type if this type is -the same as the return type of the overridden getter (if the types are not the -same then inference fails with an error). +A non-final field which overrides/implements both a setter and a getter is +inferred to have the type taken from the overridden setter parameter type if +this type is the same as the return type of the overridden getter (if the types +are not the same then inference fails with an error). Note that overriding a field is addressed via the implicit induced getter/setter