Skip to content

Commit 46f06c2

Browse files
Fixing grammar in readme
1 parent 542b30f commit 46f06c2

File tree

2 files changed

+55
-46
lines changed

2 files changed

+55
-46
lines changed

compiler/internal/dce/README.md

Lines changed: 48 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ something alive, is also considered alive.
88

99
Once all dependencies are taken into consideration we have the set of alive
1010
declarations. Anything not considered alive is considered dead and
11-
may be safely eliminated, i.e. not outputted to the JS file(s).
11+
may be safely eliminated, i.e. not outputted to JS.
1212

1313
- [Idea](#idea)
1414
- [Package](#package)
@@ -123,7 +123,13 @@ and therefore `Foo.y()` can not be called via a `Bar.y()`.
123123

124124
We will try to reduce the false positives in alive unexported methods by using
125125
the parameter and result types of the methods. Meaning that
126-
`y()`, `y(int)`, `y() int`, etc won't match just because they are named `y`.
126+
`y()`, `y(int)`, `y() int`, etc won't match just because they are named `y`.
127+
This also helps with a generic type's unexported methods that use
128+
type parameters, e.g. `Foo.y(T)`. Since the generic type may be instantiated
129+
with `int` and `string`, the different instances of the method are `Foo.y(int)`
130+
and `Foo.y(string)`. By using the parameter and result types, it is possible
131+
to remove the unused unexported method instantiations even when some
132+
instantiations of the same method are used.
127133

128134
### Functions
129135

@@ -156,27 +162,27 @@ For functions and types with generics, the definitions are split into
156162
unique instances. For example, `type StringKeys[T any] map[string]T`
157163
could be used in code as `StringKeys[int]` and `StringKeys[*Cat]`.
158164
We don't need all possible instances, only the ones which are realized
159-
in code. Each instance depends on the realized parameter types (instance types).
160-
In the example the instance types are `int` and `*Cat`.
165+
in code. Each instance depends on the realized parameter types (type arguments).
166+
In the example the type arguments are `int` and `*Cat`.
161167

162168
The instance of the generic type also defines the code with the specific
163-
instance types (e.g. `map[string]int` and `map[string]*Cat`). When an
169+
type arguments (e.g. `map[string]int` and `map[string]*Cat`). When an
164170
instance is depended on by alive code, only that instance is alive, not the
165171
entire generic type. This means if `StringKey[*Cat]` is only used from dead
166-
code, it is also dead and can be safely eliminated.
172+
code then it is also dead and can be safely eliminated.
167173

168174
The named generic types may have methods that are also copied for an instance
169-
with the parameter types replaced by the instance types. For example,
175+
with the parameter types replaced by the type arguments. For example,
170176
`func (sk StringKeys[T]) values() []T { ... }` becomes
171-
`func (sk StringKeys[int]) values() []int { ... }` when the instance type
177+
`func (sk StringKeys[int]) values() []int { ... }` when the type argument
172178
is `int`. This method in the instance now duck-types to
173179
`interface { values() []int }` and therefore must follow the rules for
174180
unexported methods.
175181
See [Instance Duck-typing](#instance-duck-typing) example for more information.
176182

177183
Functions and named types may be generic, but methods and unnamed types
178184
may not be. This makes somethings simpler. A method with a receiver is used,
179-
only the receiver's instance types are needed. The generic type or function
185+
only the receiver's type arguments are needed. The generic type or function
180186
may not be needed since only the instances are written out.
181187

182188
This also means that inside of a generic function or named type there is only
@@ -190,12 +196,12 @@ than languages that allow a method of an object to have it's own type
190196
parameters, e.g. `class X<T> { void Y<U>() { ... } ... }`.
191197

192198
However, generics mean that the same method, receiver, type, etc names
193-
will be used with different parameters types caused by different instance
194-
types. The instance types are the type arguments being passed into those
195-
parameter types for a specific instance.
199+
will be used with different parameters types caused by different type
200+
arguments. The type arguments are being passed into those parameter types
201+
for a specific instance.
196202
When an interface is alive, the signatures for unexported methods
197203
need to be instantiated with type arguments so that we know which instances
198-
the interface is duck-typing to.
204+
the interface is duck-typing to. See [Interfaces](#interfaces) for more detail.
199205

200206
### Links
201207

@@ -227,7 +233,7 @@ simplifying the justifications down to a simple set of rules.
227233
- The `init` in every included file
228234
- Any variable initialization that has a side effect
229235
- Any linked function or variable
230-
- Anything not named
236+
- Anything not given a DCE named, e.g. packages
231237

232238
### Naming
233239

@@ -256,7 +262,7 @@ To simplify the above for GopherJS, we don't look at the receiver for
256262
an unexported method before indicating it is alive. Meaning if there is no
257263
interface, only two named objects with identical unexported methods, the use
258264
of either will indicate a use of both. This will cause slightly more unexported
259-
method to be alive while reducing the complication of type checking which object
265+
methods to be alive while reducing the complication of type checking which object
260266
or type of object is performing the call.
261267

262268
| Declaration | exported | unexported | non-generic | generic | object name | method name |
@@ -284,23 +290,25 @@ and be eliminated causing the application to not run.
284290

285291
`<package>.<var name>`, `<package>.<func name>`, `<package>.<type name>`
286292
and `<package>.<receiver name>` all have the same form. They are
287-
the package path, if there is one, followed by a `.` and the object name
288-
or receiver name. For example [`rand.Shuffle`](https://pkg.go.dev/math/rand@go1.23.1#Shuffle)
293+
the package path followed by a `.`, if there is a package path,
294+
and the object name or receiver name.
295+
For example [`rand.Shuffle`](https://pkg.go.dev/math/rand@go1.23.1#Shuffle)
289296
will be named `math/rand.Shuffle`. The builtin [`error`](https://pkg.go.dev/builtin@go1.23.1#error)
290297
will be named `error` without a package path.
291298

292299
`<package>.<func name>[<type args>]`, `<package>.<type name>[<type args>]`,
293300
and `<package>.<receiver name>[<type args>]` are the same as above
294-
except with comma separated type arguments in square brackets.
295-
The type arguments are either the instance types, or type parameters
296-
since the instance type could be a match for the type parameter on the
297-
generic. For example `type Foo[T any] struct{}; type Bar[B any] { f Foo[B] }`
301+
except with comma separated type parameters or type arguments in square brackets.
302+
The type parameter names are not used, instead the constraint types are since
303+
the names for type parameters may not match even if the constraints match.
304+
For example `type Foo[T any] struct{}; type Bar[B any] { f Foo[B] }`
298305
has `Foo[B]` used in `Bar` that is identical to `Foo[T]` even though
299-
technically `Foo[B]` is an instance of `Foo[T]` with `B` as the type argument.
306+
technically `Foo[B]` is an instance of `Foo[T]` with the `B` type parameter
307+
as the type argument.
300308

301309
Command compiles, i.e. compiles with a `main` entry point, and test builds
302-
should not have any instance types that aren't resolved to concrete types,
303-
however to handle partial compiles of packages, instance types may still
310+
should not have any type parameters that aren't resolved to concrete types,
311+
however to handle partial compiles of packages, there may still
304312
be a type parameter, including unions of approximate constraints,
305313
i.e. `~int|~string`.
306314

@@ -321,12 +329,12 @@ For the method name of unexposed methods,
321329
The rest contains the signature, `(<parameter types>)(<result types>)`.
322330
The signature is defined with only the types since
323331
`(v, u int)(ok bool, err error)` should match `(x, y int)(bool, error)`.
324-
To match both will have to be `(int, int)(bool, error)`.
332+
To match both, both will have to be `(int, int)(bool, error)`.
325333
Also the parameter types should include the veridic indicator,
326-
e.g. `sum(...int)int`, since that affects how the signature is matched.
334+
e.g. `sum(...int) int`, since that affects how the signature is matched.
327335
If there are no results then the results part is left off. Otherwise,
328336
the result types only need parenthesis if there are more than one result,
329-
e.g. `(int, int)`, `(int, int)bool`, and `(int, int)(bool, error)`.
337+
e.g. `(int, int)`, `(int, int) bool`, and `(int, int)(bool, error)`.
330338

331339
In either the object name or method name, if there is a recursive
332340
type parameter, e.g. `func Foo[T Bar[T]]()` the second usage of the
@@ -336,7 +344,7 @@ is recursive, e.g. `Foo[Bar[Bar[...]]]`.
336344

337345
### Dependencies
338346

339-
The dependencies that are specified in an expression.
347+
The dependencies are specified in an expression.
340348
For example a function that invokes another function will be dependent on
341349
that invoked function. When a dependency is added it will be added as one
342350
or more names to the declaration that depends on it. It follows the
@@ -348,7 +356,7 @@ it would automatically add all unexported signatures as dependencies via
348356
`<package path>.<method name>(<parameter type list>)(<result type list>)`.
349357
However, we do not need to do that in GopherJS because we aren't using
350358
the existence of realized methods in duck-typing. GopherJS stores full set
351-
of method information when describing the type so that even when things like
359+
of method information when describing the type so that, even when things like
352360
unexported methods in interfaces are removed, duck-typing will still work
353361
correctly. This reduces the size of the code by not keeping a potentially
354362
long method body when the signature is all that is needed.
@@ -419,7 +427,7 @@ import "point"
419427
func main() {
420428
a := point.Point{X: 10.2, Y: 45.3}
421429
b := point.Point{X: -23.0, Y: 7.7}
422-
println(`Manhatten a to b:`, a.Manhattan(b))
430+
println(`Manhattan a to b:`, a.Manhattan(b))
423431
}
424432
```
425433

@@ -476,7 +484,7 @@ func main() {
476484
### Side Effects
477485

478486
In this example unused variables are being initialized with expressions
479-
that have side effects. The `max` value is 8 by the time `main` is called
487+
that has side effects. The `max` value is 8 by the time `main` is called
480488
because each initialization calls `count()` that increments `max`.
481489
The expression doesn't have to have a function call and can be any combination
482490
of operations.
@@ -512,17 +520,17 @@ func main() {
512520

513521
In this example the type `StringKeys[T any]` is a map that stores
514522
any kind of value with string keys. There is an interface `IntProvider`
515-
that `StringKeys` will duck-type to iff the instance type is `int`,
516-
i.e. `StringKeys[int]`. This exemplifies how the instance types used
523+
that `StringKeys` will duck-type to iff the type argument is `int`,
524+
i.e. `StringKeys[int]`. This exemplifies how the type arguments used
517525
in the type arguments affect the overall signature such that in some
518526
cases a generic object may match an interface and in others it may not.
519527

520528
Also notice that the structure was typed with `T` as the parameter type's
521529
name whereas the methods use `S`. This shows that the name of the type
522530
doesn't matter in the instancing. Therefore, outputting a methods name
523-
(assuming it is unexported) should use the instance type not the parameter
524-
name, e.g. `value() []int` or `value() []any` instead of `value() []S` or
525-
`value() []T`.
531+
(assuming it is unexported) should use the type argument type,
532+
not the type parameter name, e.g. `value() []int` or `value() []any`
533+
instead of `value() []S` or `value() []T`.
526534

527535
```go
528536
package main
@@ -606,9 +614,10 @@ the higher level constructs not being used.
606614
Any variable internal to the body of a function or method that is unused or
607615
only used for computing new values for itself, are left as is.
608616
The Go compiler and linters have requirements that attempt to prevent this
609-
kind of dead-code in a function body (so long as an underscore isn't used to quite
610-
usage warnings) and prevent unreachable code. Therefore, we aren't going to
611-
worry about trying to DCE inside of function bodies or in variable initializers.
617+
kind of dead-code in a function body (unless an underscore is used to quite
618+
usage warnings, e.g. `_ = unusedVar`) and prevent unreachable code.
619+
Therefore, we aren't going to worry about trying to DCE inside of function
620+
bodies or in variable initializers.
612621

613622
GopherJS does not implicitly perform JS Tree Shaking Algorithms, as discussed in
614623
[How Modern Javascript eliminate dead code](https://blog.stackademic.com/how-modern-javascript-eliminates-dead-code-tree-shaking-algorithm-d7861e48df40)

compiler/internal/dce/filters.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ func objectName(o types.Object) string {
8282
}
8383

8484
// getTypeArgs gets the type arguments for the given type
85-
// wether they are instance types or type parameters.
85+
// wether they are type arguments or type parameters.
8686
func getTypeArgs(typ types.Type) []types.Type {
8787
switch t := typ.(type) {
8888
case *types.Pointer:
@@ -105,11 +105,11 @@ func getTypeArgs(typ types.Type) []types.Type {
105105
return nil
106106
}
107107

108-
// typeListToSlice returns the list of type arguments for the instance types.
109-
func typeListToSlice(instTypes *types.TypeList) []types.Type {
110-
tArgs := make([]types.Type, instTypes.Len())
108+
// typeListToSlice returns the list of type arguments for the type arguments.
109+
func typeListToSlice(typeArgs *types.TypeList) []types.Type {
110+
tArgs := make([]types.Type, typeArgs.Len())
111111
for i := range tArgs {
112-
tArgs[i] = instTypes.At(i)
112+
tArgs[i] = typeArgs.At(i)
113113
}
114114
return tArgs
115115
}
@@ -141,9 +141,9 @@ func (p processingGroup) is(o types.Object, tArgs []types.Type) bool {
141141
}
142142

143143
type filterGen struct {
144-
// argTypeRemap is the instance types in the same order as the
144+
// argTypeRemap is the type arguments in the same order as the
145145
// type parameters in the top level object such that the type parameters
146-
// index can be used to get the instance type.
146+
// index can be used to get the type argument.
147147
argTypeRemap []types.Type
148148
inProgress []processingGroup
149149
}

0 commit comments

Comments
 (0)