Skip to content

Commit 2b04cce

Browse files
committed
[NFC] AST: Rename IdentTypeReprDeclRefTypeRepr
1 parent 6688873 commit 2b04cce

23 files changed

+139
-134
lines changed

docs/Generics/generics.tex

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ \section{Protocols}
458458
\item Conformance lookup: Section~\ref{conformance lookup}
459459
\end{MoreDetails}
460460

461-
\index{identifier type representation}
461+
\index{declaration reference type representation}
462462
\index{associated type}
463463
\paragraph{Associated types} Perhaps the simplest example of a protocol with an associated type is the \texttt{Iterator} protocol in the standard library. This protocol abstracts over an iterator which produces elements of a type that depends on the conformance:
464464
\begin{Verbatim}
@@ -473,7 +473,7 @@ \section{Protocols}
473473
return iter.next()!
474474
}
475475
\end{Verbatim}
476-
The return type of our function is the \emph{identifier type representation} \texttt{I.Element} with two components, ``\texttt{I}'' and ``\texttt{Element}''. Type resolution resolves this type representation to a type by performing a qualified lookup of \texttt{Element} on the base type \texttt{I}. The generic parameter type \texttt{I} is subject to a conformance requirement, and qualified lookup finds the associated type declaration \texttt{Element}.
476+
The return type of our function is the \emph{declaration reference type representation} \texttt{I.Element} with two components, ``\texttt{I}'' and ``\texttt{Element}''. Type resolution resolves this type representation to a type by performing a qualified lookup of \texttt{Element} on the base type \texttt{I}. The generic parameter type \texttt{I} is subject to a conformance requirement, and qualified lookup finds the associated type declaration \texttt{Element}.
477477

478478
\index{dependent member type}
479479
The resolved type is a \emph{dependent member type} composed from the generic parameter type \texttt{I} and associated type declaration \texttt{Element}. We will denote this dependent member type as \verb|I.[IteratorProtocol]Element| to make explicit the fact that a name lookup has resolved the identifier \texttt{Element} to an associated type.
@@ -487,7 +487,7 @@ \section{Protocols}
487487
\end{quote}
488488

489489
\begin{MoreDetails}
490-
\item Identifier type representations: Section \ref{identtyperepr}
490+
\item Declaration reference type representations: Section \ref{declreftyperepr}
491491
\end{MoreDetails}
492492

493493
\index{type parameter}
@@ -1393,7 +1393,7 @@ \chapter{Types}\label{types}
13931393

13941394
A type representation has a tree structure, so when we talk about the type representation \texttt{Array<Int>}, we really mean this:
13951395
\begin{quote}
1396-
``An identifier type representation with a single component, storing the identifier \texttt{Array} together with a single generic argument. The generic argument is another identifier type representation, again with a single component, storing the identifier \texttt{Int}.''
1396+
``A declaration reference type representation with a single component, storing the identifier \texttt{Array} together with a single generic argument. The generic argument is another declaration reference type representation, again with a single component, storing the identifier \texttt{Int}.''
13971397
\end{quote}
13981398
Types also have a tree structure, so when we talk about the type \texttt{Array<Int>}, what we really mean is:
13991399
\begin{quote}
@@ -1671,7 +1671,7 @@ \section{Abstract Types}
16711671
This concept comes from Objective-C, where it is called \texttt{instancetype}. The dynamic Self type in many ways behaves like a generic parameter, but it is not represented as one; the type checker and SILGen implement support for it directly.
16721672
\begin{example} Listing~\ref{dynamic self example} demonstrates some of the behaviors of the dynamic Self type. Two invalid cases are shown; \texttt{invalid1()} is rejected because the type checker cannot prove that the return type is always an instance of the dynamic type of \texttt{self}, and \texttt{invalid2()} is rejected because \texttt{Self} appears in contravariant position.
16731673

1674-
Note that \texttt{Self} has a different interpretation inside a non-class type declaration. In a protocol declaration, \texttt{Self} is the implicit generic parameter (Section~\ref{protocols}). In a struct or enum declaration, \texttt{Self} is the declared interface type (Section~\ref{identtyperepr}).
1674+
Note that \texttt{Self} has a different interpretation inside a non-class type declaration. In a protocol declaration, \texttt{Self} is the implicit generic parameter (Section~\ref{protocols}). In a struct or enum declaration, \texttt{Self} is the declared interface type (Section~\ref{declreftyperepr}).
16751675
\end{example}
16761676

16771677
\section{Sugared Types}\label{sugared types}
@@ -1682,7 +1682,7 @@ \section{Sugared Types}\label{sugared types}
16821682
\index{type alias type}
16831683
\paragraph{Type alias types} A type alias type represents a reference to a type alias declaration. It contains an optional parent type, a substitution map, and the substituted underlying type. The canonical type of a type alias type is the substituted underlying type.
16841684

1685-
The type alias type's substitution map is formed in type resolution, from any generic arguments applied to the type alias type declaration itself, together with the generic arguments of the base type (Section~\ref{identtyperepr}). Type resolution applies this substitution map to the underlying type of the type alias declaration to compute the substituted underlying type. The type alias type also preserves this substitution map for printing, and for requirement inference (Section~\ref{requirementinference}).
1685+
The type alias type's substitution map is formed in type resolution, from any generic arguments applied to the type alias type declaration itself, together with the generic arguments of the base type (Section~\ref{declreftyperepr}). Type resolution applies this substitution map to the underlying type of the type alias declaration to compute the substituted underlying type. The type alias type also preserves this substitution map for printing, and for requirement inference (Section~\ref{requirementinference}).
16861686

16871687
\index{optional sugared type}
16881688
\paragraph{Optional types} The optional type is written as \texttt{T?} for some object type \texttt{T}; its canonical type is \texttt{Optional<T>}.
@@ -4073,7 +4073,7 @@ \chapter{Substitution Maps}\label{substmaps}
40734073
\end{quote}
40744074
The first two original types are generic parameters, and substitution directly projects the corresponding replacement type from the substitution map; the second two original types are substituted by recursively replacing generic parameters they contain.
40754075

4076-
References to generic type alias declarations are more complex because in addition to the generic parameters of the base type, the generic type alias will have generic parameters of its own. Section~\ref{identtyperepr} describes how the substitution map is computed in this case.
4076+
References to generic type alias declarations are more complex because in addition to the generic parameters of the base type, the generic type alias will have generic parameters of its own. Section~\ref{declreftyperepr} describes how the substitution map is computed in this case.
40774077
\end{example}
40784078

40794079
\index{substitution failure}
@@ -4257,7 +4257,7 @@ \section{Context Substitution Maps}\label{contextsubstmap}
42574257
}
42584258
\]
42594259
\end{example}
4260-
In fact, the type alias \texttt{A} cannot be referenced as a member of this base type at all, because name lookup checks whether the generic requirements of a type declaration are satisfied. Checking generic requirements will be first introduced as part of type resolution (Section~\ref{identtyperepr}), and will come up elsewhere as well.
4260+
In fact, the type alias \texttt{A} cannot be referenced as a member of this base type at all, because name lookup checks whether the generic requirements of a type declaration are satisfied. Checking generic requirements will be first introduced as part of type resolution (Section~\ref{declreftyperepr}), and will come up elsewhere as well.
42614261
\index{protocol substitution map}
42624262
\index{protocol Self type}
42634263
\paragraph{Protocol substitution map}
@@ -5864,20 +5864,20 @@ \chapter{Type Resolution}\label{typeresolution}
58645864
\end{itemize}
58655865
\fi
58665866

5867-
\section{Identifier Type Representations}\label{identtyperepr}
5867+
\section{Declaration Reference Type Representations}\label{declreftyperepr}
58685868

58695869
\ifWIP
58705870

5871-
\index{identifier type representation}
5872-
Structural types, such as function types and tuples, have their own type representations parsed from special syntax, and type resolution constructs the corresponding semantic types directly. On the other hand, references to type declarations---nominal types, type aliases, generic parameters and associated types---are resolved via name lookup from a very general kind of type representation called an \emph{identifier type representation}.
5871+
\index{declaration reference type representation}
5872+
Structural types, such as function types and tuples, have their own type representations parsed from special syntax, and type resolution constructs the corresponding semantic types directly. On the other hand, references to type declarations---nominal types, type aliases, generic parameters and associated types---are resolved via name lookup from a very general kind of type representation called an \emph{declaration reference type representation}.
58735873

5874-
This kind of type representation consists of one or more \emph{components}, separated by dot in written syntax. Each component stores an identifier, together with an optional list of one or more generic arguments, where each generic argument is again recursively a type representation. The following identifier type representation has three components, two of which have generic arguments:
5874+
This kind of type representation consists of one or more \emph{components}, separated by dot in written syntax. The first, base component is an arbitrary type representation. Each subsequent component stores an identifier, together with an optional list of one or more generic arguments, where each generic argument is again recursively a type representation. The following declaration reference type representation has three components, two of which have generic arguments:
58755875
\begin{quote}
58765876
\begin{verbatim}
58775877
Foo.Bar<(Int) -> ()>.Baz<Float, String>
58785878
\end{verbatim}
58795879
\end{quote}
5880-
\paragraph{Unqualified lookup} The first component is special. An unqualified name lookup is performed to find a type declaration with the given name, starting from the innermost lexical scope, finally reaching the top level, after which all imported modules are searched.
5880+
\paragraph{Unqualified lookup} The first component is special. If it stores an identifier, an unqualified name lookup is performed to find a type declaration with the given name, starting from the innermost lexical scope, finally reaching the top level, after which all imported modules are searched.
58815881

58825882
The first component can be a module name, in which case there must be at least two components; modules can only be used as the base of a lookup, and are not first-class values which stand on their own.
58835883

@@ -5963,15 +5963,15 @@ \section{Identifier Type Representations}\label{identtyperepr}
59635963
}
59645964
\end{Verbatim}
59655965
\end{listing}
5966-
\begin{example} The return type of \texttt{f1()} in Listing~\ref{applying generic arguments} is an identifier type representation with two components:
5966+
\begin{example} The return type of \texttt{f1()} in Listing~\ref{applying generic arguments} is a declaration reference type representation with two components:
59675967
\begin{enumerate}
59685968
\item The first component is resolved by applying the substitution map $\texttt{T}:=\texttt{Int}$ to the declared interface type of \texttt{Outer}, which outputs \texttt{Outer<Int>}.
59695969
\item The second component is resolved by first building a substitution map for the generic signature of \texttt{Inner}, which is \texttt{<T,~U>}. The base type \texttt{Outer<Int>} provides the replacement $\texttt{T}:=\texttt{Int}$, and the component's single generic argument \texttt{String} provides the replacement $\texttt{U}:=\texttt{String}$. The declared interface type of the named type declaration \texttt{Inner} is \texttt{Outer<T>.Inner<U>}. Applying the combined substitution map to this type gives \texttt{Outer<Int>.Inner<String>}.
59705970
\end{enumerate}
59715971

59725972
\end{example}
59735973

5974-
The type resolution process for an identifier type representation might seem unnecessarily convoluted. When resolving a type representation like \texttt{Outer<Int>.Inner<String>}, we build the type of the first component by applying a substitution map to the declared interface type of the type declaration, \texttt{Outer<T>}. In the next step, we turn this type back into a substitution map, extend the substitution map with a replacement type for \texttt{U}, then apply it to the declared interface type of \texttt{Outer<T>.Inner<U>}. It seems like we might be able to get away with performing a chain of name lookups to find the final type declaration, then collect all of the generic arguments and apply them in one shot. Unfortunately, the next example shows why this appealing simplification does not handle the full generality of type resolution.
5974+
The type resolution process for a declaration reference type representation might seem unnecessarily convoluted. When resolving a type representation like \texttt{Outer<Int>.Inner<String>}, we build the type of the first component by applying a substitution map to the declared interface type of the type declaration, \texttt{Outer<T>}. In the next step, we turn this type back into a substitution map, extend the substitution map with a replacement type for \texttt{U}, then apply it to the declared interface type of \texttt{Outer<T>.Inner<U>}. It seems like we might be able to get away with performing a chain of name lookups to find the final type declaration, then collect all of the generic arguments and apply them in one shot. Unfortunately, the next example shows why this appealing simplification does not handle the full generality of type resolution.
59755975

59765976
\begin{listing}\captionabove{The named type declaration of a component can depend on generic arguments previously applied}\label{type resolution with dependent base}
59775977
\begin{Verbatim}
@@ -6013,7 +6013,7 @@ \section{Identifier Type Representations}\label{identtyperepr}
60136013

60146014
\end{example}
60156015

6016-
\paragraph{Bound components} A minor optimization worth understanding, because it slightly complicates the implementation. After type resolution of a component succeeds, the bound (or found, perhaps) type declaration is stored inside the component. If the identifier type representation is resolved again, any bound components will skip the name lookup and proceed to compute the final type from the bound declaration. The optimization was more profitable in the past, when type resolution actually had \emph{three} stages, with a third stage resolving interface types to archetypes. The third stage was subsumed by the \texttt{mapTypeIntoContext()} operation on generic environments. Parsing textual SIL also ``manually'' binds components to type declarations which name lookup would otherwise not find, in order to parse some of the more esoteric SIL syntax that we're not going to discuss here.
6016+
\paragraph{Bound components} A minor optimization worth understanding, because it slightly complicates the implementation. After type resolution of a component succeeds, the bound (or found, perhaps) type declaration is stored inside the component. If the declaration reference type representation is resolved again, any bound components will skip the name lookup and proceed to compute the final type from the bound declaration. The optimization was more profitable in the past, when type resolution actually had \emph{three} stages, with a third stage resolving interface types to archetypes. The third stage was subsumed by the \texttt{mapTypeIntoContext()} operation on generic environments. Parsing textual SIL also ``manually'' binds components to type declarations which name lookup would otherwise not find, in order to parse some of the more esoteric SIL syntax that we're not going to discuss here.
60176017
\fi
60186018

60196019
\section{Checking Generic Arguments}\label{checking generic arguments}

docs/proposals/DeclarationTypeChecker.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ How do we get there?
148148

149149
The proposed architecture is significantly different from the current type checker architecture, so how do we get there from here? There are a few concrete steps we can take:
150150

151-
**Make all AST nodes phase-aware**: Introduce a trait that can ask an arbitrary AST node (``Decl``, ``TypeRepr``, ``Pattern``, etc.) its current phase. AST nodes may compute this information on-the-fly or store it, as appropriate. For example, a ``TypeRepr`` can generally determine its phase based on the existing state of the ``IdentTypeRepr`` nodes it includes.
151+
**Make all AST nodes phase-aware**: Introduce a trait that can ask an arbitrary AST node (``Decl``, ``TypeRepr``, ``Pattern``, etc.) its current phase. AST nodes may compute this information on-the-fly or store it, as appropriate. For example, a ``TypeRepr`` can generally determine its phase based on the existing state of the ``DeclRefTypeRepr`` nodes it includes.
152152

153153
**Make name lookup phase-aware**: Name lookup is currently one of the worst offenders when violating phase ordering. Parameterize name lookup based on the phase at which it's operating. For example, asking for name lookup at the "extension binding" phase might not resolve type aliases, look into superclasses, or look into protocols.
154154

include/swift/AST/CASTBridging.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ void *ProtocolTypeRepr_create(void *ctx, void *baseType, void *protoLoc);
242242
void *PackExpansionTypeRepr_create(void *ctx, void *base, void *ellipsisLoc);
243243
void *TupleTypeRepr_create(void *ctx, BridgedArrayRef elements, void *lParenLoc,
244244
void *rParenLoc);
245-
void *IdentTypeRepr_create(void *ctx, BridgedArrayRef components);
245+
void *DeclRefTypeRepr_create(void *ctx, BridgedArrayRef bridgedComponents);
246246
void *GenericIdentTypeRepr_create(void *ctx, BridgedIdentifier name,
247247
void *nameLoc, BridgedArrayRef genericArgs,
248248
void *lAngle, void *rAngle);

include/swift/AST/Expr.h

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ namespace swift {
4242
class ArchetypeType;
4343
class ASTContext;
4444
class AvailabilitySpec;
45-
class IdentTypeRepr;
45+
class DeclRefTypeRepr;
4646
class Type;
4747
class TypeRepr;
4848
class ValueDecl;
@@ -1338,18 +1338,19 @@ class TypeExpr : public Expr {
13381338
DeclNameLoc NameLoc,
13391339
TypeDecl *Decl);
13401340

1341-
/// Create a TypeExpr for a member TypeDecl of the given parent IdentTypeRepr.
1342-
static TypeExpr *createForMemberDecl(IdentTypeRepr *ParentTR,
1341+
/// Create a \c TypeExpr for a member \c TypeDecl of the given parent
1342+
/// \c DeclRefTypeRepr.
1343+
static TypeExpr *createForMemberDecl(DeclRefTypeRepr *ParentTR,
13431344
DeclNameLoc NameLoc,
13441345
TypeDecl *Decl);
13451346

1346-
/// Create a TypeExpr from an IdentTypeRepr with the given arguments applied
1347-
/// at the specified location.
1347+
/// Create a \c TypeExpr from an \c DeclRefTypeRepr with the given arguments
1348+
/// applied at the specified location.
13481349
///
13491350
/// Returns nullptr if the reference cannot be formed, which is a hack due
13501351
/// to limitations in how we model generic typealiases.
1351-
static TypeExpr *createForSpecializedDecl(IdentTypeRepr *ParentTR,
1352-
ArrayRef<TypeRepr*> Args,
1352+
static TypeExpr *createForSpecializedDecl(DeclRefTypeRepr *ParentTR,
1353+
ArrayRef<TypeRepr *> Args,
13531354
SourceRange AngleLocs,
13541355
ASTContext &C);
13551356

include/swift/AST/NameLookup.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ class ASTScopeImpl;
4343
} // namespace ast_scope
4444

4545
/// Walk the type representation recursively, collecting any
46-
/// `OpaqueReturnTypeRepr`s, `CompositionTypeRepr`s or `IdentTypeRepr`s.
46+
/// \c OpaqueReturnTypeRepr, \c CompositionTypeRepr or \c DeclRefTypeRepr
47+
/// nodes.
4748
CollectedOpaqueReprs collectOpaqueReturnTypeReprs(TypeRepr *, ASTContext &ctx, DeclContext *dc);
4849

4950
/// LookupResultEntry - One result of unqualified lookup.

0 commit comments

Comments
 (0)