Pārlūkot izejas kodu

Switch generics to using compound/simple member access terminology (#1138)

This is following #1119 .

* Updates terminology.md, overview.md, details.md
josh11b 4 gadi atpakaļ
vecāks
revīzija
f0d6e3122a

+ 39 - 32
docs/design/generics/details.md

@@ -15,7 +15,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 -   [Implementing interfaces](#implementing-interfaces)
 -   [Implementing interfaces](#implementing-interfaces)
     -   [Implementing multiple interfaces](#implementing-multiple-interfaces)
     -   [Implementing multiple interfaces](#implementing-multiple-interfaces)
     -   [External impl](#external-impl)
     -   [External impl](#external-impl)
-    -   [Qualified member names](#qualified-member-names)
+    -   [Qualified member names and compound member access](#qualified-member-names-and-compound-member-access)
     -   [Access](#access)
     -   [Access](#access)
 -   [Generics](#generics)
 -   [Generics](#generics)
     -   [Return type](#return-type)
     -   [Return type](#return-type)
@@ -188,9 +188,9 @@ This includes members of `ConvertibleToString` that are not explicitly named in
 the `impl` definition but have defaults. Whether the implementation is defined
 the `impl` definition but have defaults. Whether the implementation is defined
 as [internal](terminology.md#internal-impl) or
 as [internal](terminology.md#internal-impl) or
 [external](terminology.md#external-impl), you may access the `ToString` function
 [external](terminology.md#external-impl), you may access the `ToString` function
-for a `Song` value `s` by writing a
-[qualified](terminology.md#qualified-and-unqualified-member-names) function
-call, like `s.(ConvertibleToString.ToString)()`.
+for a `Song` value `s` by a writing function call
+[using the compound member access syntax with the qualified name](terminology.md#compound-member-access-using-qualified-names),
+like `s.(ConvertibleToString.ToString)()`.
 
 
 If `Song` doesn't implement an interface or we would like to use a different
 If `Song` doesn't implement an interface or we would like to use a different
 implementation of that interface, we can define another type that also has the
 implementation of that interface, we can define another type that also has the
@@ -405,8 +405,9 @@ Carbon requires `impl`s defined in a different library to be `external` so that
 the API of `Point3` doesn't change based on what is imported. It would be
 the API of `Point3` doesn't change based on what is imported. It would be
 particularly bad if two different libraries implemented interfaces with
 particularly bad if two different libraries implemented interfaces with
 conflicting names that both affected the API of a single type. As a consequence
 conflicting names that both affected the API of a single type. As a consequence
-of this restriction, you can find all the names of direct (unqualified) members
-of a type in the definition of that type. The only thing that may be in another
+of this restriction, you can find all the names of direct members (those
+available by [simple member access](terminology.md#simple-member-access)) of a
+type in the definition of that type. The only thing that may be in another
 library is an `impl` of an interface.
 library is an `impl` of an interface.
 
 
 You might also use `external impl` to implement an interface for a type to avoid
 You might also use `external impl` to implement an interface for a type to avoid
@@ -476,8 +477,10 @@ same library as the class?
 different files based on explicit configuration in that file. For example, we
 different files based on explicit configuration in that file. For example, we
 could support a declaration that a given interface or a given method of an
 could support a declaration that a given interface or a given method of an
 interface is "in scope" for a particular type in this file. With that
 interface is "in scope" for a particular type in this file. With that
-declaration, the method could be called unqualified. This avoids most concerns
-arising from name collisions between interfaces. It has a few downsides though:
+declaration, the method could be called using
+[simple member access](terminology.md#simple-member-access). This avoids most
+concerns arising from name collisions between interfaces. It has a few downsides
+though:
 
 
 -   It increases variability between files, since the same type will have
 -   It increases variability between files, since the same type will have
     different APIs depending on these declarations. This makes it harder to
     different APIs depending on these declarations. This makes it harder to
@@ -495,12 +498,14 @@ Swift and Rust, we don't allow a type's API to be modified outside its
 definition. So in Carbon a type's API is consistent no matter what is imported,
 definition. So in Carbon a type's API is consistent no matter what is imported,
 unlike Swift and Rust.
 unlike Swift and Rust.
 
 
-### Qualified member names
+### Qualified member names and compound member access
 
 
 Given a value of type `Point3` and an interface `Vector` implemented for that
 Given a value of type `Point3` and an interface `Vector` implemented for that
 type, you can access the methods from that interface using the member's
 type, you can access the methods from that interface using the member's
-_qualified name_, whether or not the implementation is done externally with an
-`external impl` declaration:
+_qualified name_ using
+[the compound member access syntax](terminology.md#simple-member-access),
+whether or not the implementation is done externally with an `external impl`
+declaration:
 
 
 ```
 ```
 var p1: Point3 = {.x = 1.0, .y = 2.0};
 var p1: Point3 = {.x = 1.0, .y = 2.0};
@@ -581,7 +586,9 @@ present in the signature of the function to type check the body of
 
 
 Names are looked up in the body of `AddAndScaleGeneric` for values of type `T`
 Names are looked up in the body of `AddAndScaleGeneric` for values of type `T`
 in `Vector`. This means that `AddAndScaleGeneric` is interpreted as equivalent
 in `Vector`. This means that `AddAndScaleGeneric` is interpreted as equivalent
-to adding a `Vector` qualification to all unqualified member accesses of `T`:
+to adding a `Vector`
+[qualification](#qualified-member-names-and-compound-member-access) to replace
+all simple member accesses of `T`:
 
 
 ```
 ```
 fn AddAndScaleGeneric[T:! Vector](a: T, b: T, s: Double) -> T {
 fn AddAndScaleGeneric[T:! Vector](a: T, b: T, s: Double) -> T {
@@ -785,7 +792,8 @@ signatures. Implementing `Vector` would not imply an implementation of
 An interface's name may be used in a few different contexts:
 An interface's name may be used in a few different contexts:
 
 
 -   to define [an `impl` for a type](#implementing-interfaces),
 -   to define [an `impl` for a type](#implementing-interfaces),
--   as a namespace name in [a qualified name](#qualified-member-names), and
+-   as a namespace name in
+    [a qualified name](#qualified-member-names-and-compound-member-access), and
 -   as a [type-of-type](terminology.md#type-of-type) for
 -   as a [type-of-type](terminology.md#type-of-type) for
     [a generic type parameter](#generics).
     [a generic type parameter](#generics).
 
 
@@ -806,7 +814,8 @@ aliases for the corresponding qualified names inside `Vector` as a namespace.
 
 
 The requirements determine which types are values of a given type-of-type. The
 The requirements determine which types are values of a given type-of-type. The
 set of names in a type-of-type determines the API of a generic type value and
 set of names in a type-of-type determines the API of a generic type value and
-define the result of qualified member name lookup.
+define the result of [member access](/docs/design/expressions/member_access.md)
+into the type-of-type.
 
 
 This general structure of type-of-types holds not just for interfaces, but
 This general structure of type-of-types holds not just for interfaces, but
 others described in the rest of this document.
 others described in the rest of this document.
@@ -875,9 +884,8 @@ members of those interfaces.
 To declare a named constraint that includes other declarations for use with
 To declare a named constraint that includes other declarations for use with
 template parameters, use the `template` keyword before `constraint`. Method,
 template parameters, use the `template` keyword before `constraint`. Method,
 associated type, and associated function requirements may only be declared
 associated type, and associated function requirements may only be declared
-inside a `template constraint`. Note that a generic constraint ignores the
-unqualified member names defined for a type, but a template constraint can
-depend on them.
+inside a `template constraint`. Note that a generic constraint ignores the names
+of members defined for a type, but a template constraint can depend on them.
 
 
 There is an analogy between declarations used in a `constraint` and in an
 There is an analogy between declarations used in a `constraint` and in an
 `interface` definition. If an `interface` `I` has (non-`alias`) declarations
 `interface` definition. If an `interface` `I` has (non-`alias`) declarations
@@ -1036,8 +1044,8 @@ constraint {
 ```
 ```
 
 
 Conflicts can be resolved at the call site using
 Conflicts can be resolved at the call site using
-[the qualified name syntax](#qualified-member-names), or by defining a named
-constraint explicitly and renaming the methods:
+[the compound member access syntax using qualified names](#qualified-member-names-and-compound-member-access),
+or by defining a named constraint explicitly and renaming the methods:
 
 
 ```
 ```
 constraint RenderableAndEndOfGame {
 constraint RenderableAndEndOfGame {
@@ -1561,7 +1569,7 @@ adapter SongByTitle for Song {
 }
 }
 ```
 ```
 
 
-or using qualified names:
+or using qualified names with the compound member access syntax:
 
 
 ```
 ```
 adapter SongByTitle for Song {
 adapter SongByTitle for Song {
@@ -1852,8 +1860,8 @@ external impl Window as DrawingContext { ... }
 An adapter can make that much more convenient by making a compatible type where
 An adapter can make that much more convenient by making a compatible type where
 the interface is [implemented internally](terminology.md#internal-impl). This
 the interface is [implemented internally](terminology.md#internal-impl). This
 avoids having to
 avoids having to
-[qualify](terminology.md#qualified-and-unqualified-member-names) each call to
-methods in the interface.
+[qualify](terminology.md#compound-member-access-using-qualified-names) each call
+to methods in the interface.
 
 
 ```
 ```
 adapter DrawInWindow for Window {
 adapter DrawInWindow for Window {
@@ -2580,14 +2588,13 @@ fn Contains
 the `where` constraint means `CT.ElementType` must satisfy `Comparable` as well.
 the `where` constraint means `CT.ElementType` must satisfy `Comparable` as well.
 However, inside the body of `Contains`, `CT.ElementType` will only act like the
 However, inside the body of `Contains`, `CT.ElementType` will only act like the
 implementation of `Comparable` is [external](#external-impl). That is, items
 implementation of `Comparable` is [external](#external-impl). That is, items
-from the `needles` container won't have an unqualified `Compare` method member,
-but can still be implicitly converted to `Comparable` and can still call
-`Compare` using the qualified member syntax, `needle.(Comparable.Compare)(elt)`.
-The rule is that an `==` `where` constraint between two type variables does not
-modify the set of unqualified member names of either type. (If you write
+from the `needles` container won't directly have a `Compare` method member, but
+can still be implicitly converted to `Comparable` and can still call `Compare`
+using the compound member access syntax, `needle.(Comparable.Compare)(elt)`. The
+rule is that an `==` `where` constraint between two type variables does not
+modify the set of member names of either type. (If you write
 `where .ElementType = String` with a `=` and a concrete type, then
 `where .ElementType = String` with a `=` and a concrete type, then
-`.ElementType` is actually set to `String` including the complete unqualified
-`String` API.)
+`.ElementType` is actually set to `String` including the complete `String` API.)
 
 
 Note that `==` constraints are symmetric, so the previous declaration of
 Note that `==` constraints are symmetric, so the previous declaration of
 `Contains` is equivalent to an alternative declaration where `CT` is declared
 `Contains` is equivalent to an alternative declaration where `CT` is declared
@@ -2876,9 +2883,9 @@ This implied constraint is equivalent to the explicit constraint that each
 parameter and return type [is legal](#must-be-legal-type-argument-constraints).
 parameter and return type [is legal](#must-be-legal-type-argument-constraints).
 
 
 **Note:** These implied constraints affect the _requirements_ of a generic type
 **Note:** These implied constraints affect the _requirements_ of a generic type
-parameter, but not its _unqualified member names_. This way you can always look
-at the declaration to see how name resolution works, without having to look up
-the definitions of everything it is used as an argument to.
+parameter, but not its _member names_. This way you can always look at the
+declaration to see how name resolution works, without having to look up the
+definitions of everything it is used as an argument to.
 
 
 **Limitation:** To limit readability concerns and ambiguity, this feature is
 **Limitation:** To limit readability concerns and ambiguity, this feature is
 limited to a single signature. Consider this interface declaration:
 limited to a single signature. Consider this interface declaration:

+ 22 - 19
docs/design/generics/overview.md

@@ -20,7 +20,7 @@ pointers to other design documents that dive deeper into individual topics.
         -   [Defining interfaces](#defining-interfaces)
         -   [Defining interfaces](#defining-interfaces)
         -   [Contrast with templates](#contrast-with-templates)
         -   [Contrast with templates](#contrast-with-templates)
     -   [Implementing interfaces](#implementing-interfaces)
     -   [Implementing interfaces](#implementing-interfaces)
-        -   [Qualified and unqualified access](#qualified-and-unqualified-access)
+        -   [Accessing members of interfaces](#accessing-members-of-interfaces)
     -   [Type-of-types](#type-of-types)
     -   [Type-of-types](#type-of-types)
     -   [Generic functions](#generic-functions)
     -   [Generic functions](#generic-functions)
         -   [Deduced parameters](#deduced-parameters)
         -   [Deduced parameters](#deduced-parameters)
@@ -90,8 +90,9 @@ Summary of how Carbon generics work:
     ["named constraints"](terminology.md#named-constraints). Named constraints
     ["named constraints"](terminology.md#named-constraints). Named constraints
     can express requirements that multiple interfaces be implemented, and give
     can express requirements that multiple interfaces be implemented, and give
     you control over how name conflicts are handled.
     you control over how name conflicts are handled.
--   Alternatively, you may resolve name conflicts by using a qualified syntax to
-    directly call a function from a specific interface.
+-   Alternatively, you may resolve name conflicts by using the compound member
+    access syntax to directly call a function from a specific interface using a
+    qualified name.
 
 
 ## What are generics?
 ## What are generics?
 
 
@@ -216,16 +217,17 @@ external impl Song as Comparable {
 
 
 Implementations may be defined within the class definition itself or
 Implementations may be defined within the class definition itself or
 out-of-line. Implementations may optionally be start with the `external` keyword
 out-of-line. Implementations may optionally be start with the `external` keyword
-to say the members of the interface are not unqualified members of the class.
-Out-of-line implementations must be external. External implementations may be
-defined in the library defining either the class or the interface.
+to say the members of the interface are not members of the class. Out-of-line
+implementations must be external. External implementations may be defined in the
+library defining either the class or the interface.
 
 
-#### Qualified and unqualified access
+#### Accessing members of interfaces
 
 
 The methods of an interface implemented internally within the class definition
 The methods of an interface implemented internally within the class definition
-may be called with the ordinary unqualified member syntax. Methods of all
-implemented interfaces may be called with the
-[qualified member syntax](terminology.md#qualified-and-unqualified-member-names),
+may be called with the
+[simple member access syntax](terminology.md#simple-member-access). Methods of
+all implemented interfaces may be called with the
+[compound member access syntax using qualified names](terminology.md#compound-member-access-using-qualified-names),
 whether they are defined internally or externally.
 whether they are defined internally or externally.
 
 
 ```
 ```
@@ -235,7 +237,8 @@ song.Print();
 // `Less` is defined in `Comparable`, which is implemented
 // `Less` is defined in `Comparable`, which is implemented
 // externally for `Song`
 // externally for `Song`
 song.(Comparable.Less)(song);
 song.(Comparable.Less)(song);
-// Can also call `Print` using the qualified syntax:
+// Can also call `Print` using the compound access syntax,
+// using the qualified name `Printable.Print`:
 song.(Printable.Print)();
 song.(Printable.Print)();
 ```
 ```
 
 
@@ -257,9 +260,8 @@ type is that it must implement the interface `Comparable`.
 
 
 A type-of-type also defines a set of names and a mapping to corresponding
 A type-of-type also defines a set of names and a mapping to corresponding
 qualified names. Those names are used for
 qualified names. Those names are used for
-[unqualfied member lookup](terminology.md#qualified-and-unqualified-member-names)
-in scopes where the value of the type is not known, such as when the type is a
-generic parameter.
+[simple member lookup](terminology.md#simple-member-access) in scopes where the
+value of the type is not known, such as when the type is a generic parameter.
 
 
 You may combine interfaces into new type-of-types using
 You may combine interfaces into new type-of-types using
 [the `&` operator](#combining-interfaces) or
 [the `&` operator](#combining-interfaces) or
@@ -325,8 +327,9 @@ differently because they are defined as generic, as long as you only refer to
 the names defined by [type-of-type](#type-of-types) for the type parameter.
 the names defined by [type-of-type](#type-of-types) for the type parameter.
 
 
 You may also refer to any of the methods of interfaces required by the
 You may also refer to any of the methods of interfaces required by the
-type-of-type using the [qualified syntax](#qualified-and-unqualified-access), as
-shown in the following sections.
+type-of-type using the
+[compound member access syntax with the qualified member name](#accessing-members-of-interfaces),
+as shown in the following sections.
 
 
 A function can have a mix of generic, template, and regular parameters.
 A function can have a mix of generic, template, and regular parameters.
 Likewise, it's allowed to pass a template or generic value to a generic or
 Likewise, it's allowed to pass a template or generic value to a generic or
@@ -409,7 +412,7 @@ fn F[T:! Renderable & EndOfGame](game_state: T*) -> (i32, i32) {
 ```
 ```
 
 
 Names with conflicts can be accessed using the
 Names with conflicts can be accessed using the
-[qualified syntax](#qualified-and-unqualified-access).
+[compound member access syntax](#accessing-members-of-interfaces).
 
 
 ```
 ```
 fn BothDraws[T:! Renderable & EndOfGame](game_state: T*) {
 fn BothDraws[T:! Renderable & EndOfGame](game_state: T*) {
@@ -442,8 +445,8 @@ fn CallItAll[T:! Combined](game_state: T*, int winner) {
     game_state->Draw_EndOfGame();
     game_state->Draw_EndOfGame();
   }
   }
   game_state->Draw_Renderable();
   game_state->Draw_Renderable();
-  // Can still use qualified syntax for names
-  // not defined in the named constraint
+  // Can still use compound member access syntax for
+  // names not defined in the named constraint
   return game_state->(Renderable.Center)();
   return game_state->(Renderable.Center)();
 }
 }
 ```
 ```

+ 38 - 13
docs/design/generics/terminology.md

@@ -30,7 +30,9 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 -   [Impls: Implementations of interfaces](#impls-implementations-of-interfaces)
 -   [Impls: Implementations of interfaces](#impls-implementations-of-interfaces)
     -   [Internal impl](#internal-impl)
     -   [Internal impl](#internal-impl)
     -   [External impl](#external-impl)
     -   [External impl](#external-impl)
--   [Qualified and unqualified member names](#qualified-and-unqualified-member-names)
+-   [Member access](#member-access)
+    -   [Simple member access](#simple-member-access)
+    -   [Compound member access using qualified names](#compound-member-access-using-qualified-names)
 -   [Compatible types](#compatible-types)
 -   [Compatible types](#compatible-types)
 -   [Subtyping and casting](#subtyping-and-casting)
 -   [Subtyping and casting](#subtyping-and-casting)
 -   [Coherence](#coherence)
 -   [Coherence](#coherence)
@@ -357,28 +359,51 @@ constraint as a way to implement all of the interfaces it requires.
 
 
 A type that implements an interface _internally_ has all the named members of
 A type that implements an interface _internally_ has all the named members of
 the interface as named members of the type. This means that the members of the
 the interface as named members of the type. This means that the members of the
-interface may be accessed as either
-[unqualified or qualified members](#qualified-and-unqualified-member-names).
+interface are available by way of both
+[simple member access and compound member access using qualified names](#member-access).
 
 
 ### External impl
 ### External impl
 
 
 In contrast, a type that implements an interface _externally_ does not include
 In contrast, a type that implements an interface _externally_ does not include
 the named members of the interface in the type. The members of the interface are
 the named members of the interface in the type. The members of the interface are
-still implemented by the type, though, and so may be accessed using the
-[qualified names](#qualified-and-unqualified-member-names) of those members.
+still implemented by the type, though, and so may be accessed using
+[compound member access using the qualified names](#compound-member-access-using-qualified-names)
+of those members.
 
 
-## Qualified and unqualified member names
+## Member access
 
 
-A qualified member includes both the name of the interface defining the member
-and the name of the member. So if `String` implements `Comparable` which has a
-`Less` method, and `s1` and `s2` are variables of type `String`, then the `Less`
+There are two different kinds of member access: _simple_ and _compound_. There
+is a [member access design document](/docs/design/expressions/member_access.md)
+with the details, but a summary of how they apply to generics is given here.
+
+### Simple member access
+
+Simple member access has the from `object.member`, where `member` is a word
+naming a member of `object`. This form may be used to access members of
+interfaces [implemented internally](#internal-impl) by the type of `object`.
+
+If `String` implements `Printable` internally, then `s1.Print()` calls the
+`Print` method of `Printable` using simple member access. In this case, the name
+`Print` is used without qualifying it with the name of the interface it is a
+member of since it is recognized as a member of the type itself as well.
+
+### Compound member access using qualified names
+
+Compound member access has the form `object.(expression)`, where `expression` is
+resolved in the containing scope. This expression may be the _qualified member
+name_ of an interface member, that consists of the name of the interface,
+possibly qualified with a package or namespace name, a dot `.` and the name of
+the member.
+
+For example, if the `Comparable` interface has a `Less` member method, then the
+qualified name of that member is `Comparable.Less`. So if `String` implements
+`Comparable`, and `s1` and `s2` are variables of type `String`, then the `Less`
 method may be called using the qualified member name by writing
 method may be called using the qualified member name by writing
 `s1.(Comparable.Less)(s2)`.
 `s1.(Comparable.Less)(s2)`.
 
 
-If the interface is implemented internally, then the method can be called using
-the unqualified syntax as well. If `String` implements `Printable` internally,
-then `s1.Print()` calls the `Print` method of `Printable` as an unqualified
-member.
+This form may be used to access any member of an interface implemented for a
+type, whether it is implemented [internally](#internal-impl) or
+[externally](#external-impl).
 
 
 ## Compatible types
 ## Compatible types