Skip to content

Commit

Permalink
Simplify class member conflict rules.
Browse files Browse the repository at this point in the history
As of patchset 5: The ruleset concerning class member conflicts
(apart from simple name clashes) has now been simplified
considerably, and it's expressed in one location, in a new section
(the locations where we previously had such rules are now
`\commentary{}` with a reference to the new section).

The old rules and the new simplified rules specify the same set
of conflicts (in that sense, patchset 4 == patchset 5).

The old description below gives details about what was changed
from the start of this CL until patchset 4.

------------------------------- OLD description:

Added conflict for constructor and setter with "the same name".

Discussed the inconsistent approach to conflicts between named
constructors and instance members with Lasse; we agreed that it
is confusing if we allow the constructor `C.n` to coexist with the
instance method/getter `n` and instance setter `n=`, except that
they must be inherited rather than declared in the enclosing class
`C`, so I adjusted the wording such that only _static_ members
conflict with named constructors.

One more reason why there is no conflict between `C.n` and an instance
member named `n` or `n=` is that the latter can _never_ be denoted
by `C.n` (but static members can be denoted by `C.n`, also in `C`).

Change-Id: I012e772ae6473fddd8f9944553d69e6a6ceeb2f9
Reviewed-on: https://dart-review.googlesource.com/56800
Reviewed-by: Leaf Petersen <leafp@google.com>
Reviewed-by: Lasse R.H. Nielsen <lrn@google.com>
  • Loading branch information
eernstg committed May 31, 2018
1 parent 377eb52 commit 08c893d
Showing 1 changed file with 49 additions and 47 deletions.
96 changes: 49 additions & 47 deletions docs/language/dartLangSpec.tex
Original file line number Diff line number Diff line change
Expand Up @@ -1272,10 +1272,12 @@ \section{Classes}
% Maybe the final field hides the setter in scope?
% I think the original rules were best.

\LMHash{}
It is a compile-time error if a class declares two members of the same name.
It is a compile-time error if a class has an instance member and a static member with the same name.
% It is a compile-time error if a generic (\ref{generics}) class declares a member with the same name as one of its type parameters.
\commentary{
It is a compile-time error if a class declares two members of the same name,
either because it declares the same name twice in the same scope (\ref{scoping}),
or because it declares a static member and an instance member with the same name
(\ref{classMemberConflicts}).
}

\commentary{
Here are simple examples, that illustrate the difference between ``has a member'' and ``declares a member''.
Expand Down Expand Up @@ -1324,9 +1326,11 @@ \subsection{Instance Methods}
\LMHash{}
It is a static warning if an instance method $m_1$ overrides an instance member $m_2$ and the type of $m_1$ is not a subtype of the type of $m_2$.
It is a static warning if an instance method $m_1$ overrides an instance member $m_2$, the signature of $m_2$ explicitly specifies a default value for a formal parameter $p$, and the signature of $m_1$ implies a different default value for $p$.
It is a static warning if a class $C$ declares an instance method named $n$ and has a setter named $n=$.

% Works. If the name is public, no issue. If it's private, if a subclass has a conflicting inst var, it either is in the same lib and will be flagged, or is in another and is not an issue.
\commentary{
A method declaration may conflict with other declarations
(\ref{classMemberConflicts}).
}


\subsubsection{Operators}
Expand Down Expand Up @@ -1418,35 +1422,18 @@ \subsection{Getters}
The instance getters of a class $C$ are those instance getters declared by $C$, either implicitly or explicitly, and the instance getters inherited by $C$ from its superclass.
The static getters of a class $C$ are those static getters declared by $C$.

\LMHash{}
It is a compile-time error if a class has both a getter and a method with the same name.
This restriction holds regardless of whether the getter is defined explicitly or implicitly, or whether the getter or the method are inherited or not.

\commentary{
This implies that a getter can never override a method, and a method can never override a getter or an instance variable.
A getter declaration may conflict with other declarations
(\ref{classMemberConflicts}).
In particular, a getter can never override a method,
and a method can never override a getter or an instance variable.
}

\LMHash{}
It is a static warning if the return type of a getter is \VOID.
It is a static warning if a getter $m_1$ overrides (\ref{inheritanceAndOverriding}) a getter
$m_2$ and the type of $m_1$ is not a subtype of the type of $m_2$.

\LMHash{}
It is a static warning if a class declares a static getter named $v$ and also has a non-static setter named $v=$.

% We need not consider implicit declarations: If $v$ is declared
% implicitly then there is a static variable $v$ and an induced setter
% $v=$, and then it is already a compile-time error to have an
% instance setter named $v=$ due to the name clash. Otherwise, $v$ is
% an explicitly declared static getter (and there may or may not be an
% explicitly declared static setter $v=$). If the non-static setter
% $v=$ is declared implicitly then there is an instance variable $v$
% inducing it, and it will also induce an instance getter $v$, which
% is again already a compile-time error. Hence, if any of said
% declarations are implicit then it is already a compile-time error,
% so we need not specify how to handle those cases with respect to
% this static warning.


\subsection{Setters}
\LMLabel{setters}
Expand Down Expand Up @@ -1490,22 +1477,10 @@ \subsection{Setters}
It is a static warning if a setter $m_1$ overrides (\ref{inheritanceAndOverriding}) a setter $m_2$ and the type of $m_1$ is not a subtype of the type of $m_2$.
It is a static warning if a class has a setter named $v=$ with argument type $T$ and a getter named $v$ with return type $S$, and $T$ may not be assigned to $S$.

\LMHash{}
It is a static warning if a class declares a static setter named $v=$ and has an instance getter named $v$.
It is a static warning if a class declares a setter named $v=$ and has a method named $v$.

% We need not consider implicit declarations: If $v=$ is declared
% implicitly then there is a static variable $v$, and then it is
% already a compile-time error to have an instance member named $v$,
% both when it is a method and when it is induced by an instance
% variable. Otherwise, $v=$ is an explicitly declared setter (and
% there may or may not be an explicitly declared static getter
% $v$). If the non-static member $v$ is declared implicitly then there
% is an instance variable $v$ inducing it, and it will also induce an
% instance setter $v=$, which is again already a compile-time error.
% Hence, if any of said declarations are implicit then it is already a
% compile-time error, so we need not specify how to handle those cases
% with respect to this static warning.
\commentary{
A setter declaration may conflict with other declarations
(\ref{classMemberConflicts}).
}


\subsection{Abstract Instance Members}
Expand Down Expand Up @@ -1632,9 +1607,13 @@ \subsection{Constructors}

\LMHash{}
A {\em constructor name} always begins with the name of its immediately enclosing class, and may optionally be followed by a dot and an identifier $id$.
It is a compile-time error if $id$ is the name of a member declared in the immediately enclosing class.
It is a compile-time error if the name of a constructor is not a constructor name.

\commentary{
A constructor declaration may conflict with static member declarations
(\ref{classMemberConflicts}).
}

% In what scope do constructors go? The simple names of named constructors go in the static scope of the class. Unnamed ones go nowhere, but we use the class name to refer to them; the class name could also in the static scope of the class as well to prevent weird errors, or we could ban it explicitly and avoiding duplication. Similarly, the instance scope could contain the constructor names and class name, or we could have special rules to prevent collisions between instance members and constructors or the class.

% The enclosing scope of a generative constructor is the instance scope of the class in which it is declared (but what about redirecting?)
Expand Down Expand Up @@ -2170,9 +2149,10 @@ \subsection{Static Methods}
Dart static methods may be seen as functions of the enclosing library.
}

\LMHash{}
It is a static warning if a class $C$ declares a static method named $n$ and has a setter named $n=$.
It is a static warning if a class $C$ declares a static member named $n$ and has an instance member named $n$.
\commentary{
Static method declarations may conflict with other declarations
(\ref{classMemberConflicts}).
}


\subsection{Static Variables}
Expand Down Expand Up @@ -2451,6 +2431,28 @@ \subsection{Superinterfaces}
% Should we ignore unimplemented private members?


\subsection{Class Member Conflicts}
\LMLabel{classMemberConflicts}

Some pairs of class member declarations cannot coexist,
even though they do not both introduce the same name into the same scope.
This section specifies these errors.

The {\em basename} of a getter or method named $n$ is $n$;
the basename of a setter named \code{$n$=} is $n$.

Let $C$ be a class.
It is a compile-time error if $C$ declares a
\begin{itemize}
\item constructor named \code{$C$.$n$} and a static member with basename $n$.
\item getter or a setter with basename $n$, and has a method named $n$.
\item method named $n$, and has a getter or a setter with basename $n$.
\item static member with basename $n$, and has an instance member with basename $n$.
\end{itemize}
These errors occur when the getters or setters are defined explicitly
as well as when they are induced by variable declarations.


\section{Interfaces}
\LMLabel{interfaces}

Expand Down

0 comments on commit 08c893d

Please sign in to comment.