You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/ty-module/param-ty-const-regions.md
+18-9Lines changed: 18 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,7 +1,7 @@
1
1
# Parameter `Ty`/`Const`/`Region`s
2
2
3
-
When inside of generic items, types can be written that use in scope generic parameters, for example `fn foo<'a, T>(_: &'a Vec<T>)`. In this specific case
4
-
the `&'a Vec<T>` type would be represented internally as:
3
+
When inside of generic items, types can be written that use in scope generic parameters, for example `fn foo<'a, T>(_: &'a Vec<T>)`.
4
+
In this specific case the `&'a Vec<T>` type would be represented internally as:
The `Vec<T>` type is represented as `TyKind::Adt(Vec, &[GenericArgKind::Type(Param("T", 0))])`.
31
31
32
-
The name is somewhat self explanatory, it's the name of the type parameter. The index of the type parameter is an integer indicating
33
-
its order in the list of generic parameters in scope (note: this includes parameters defined on items on outer scopes than the item the parameter is defined on). Consider the following examples:
32
+
The name is somewhat self explanatory, it's the name of the type parameter.
33
+
The index of the type parameter is an integer indicating
34
+
its order in the list of generic parameters in scope (note: this includes parameters defined on items on outer scopes than the item the parameter is defined on).
35
+
Consider the following examples:
34
36
35
37
```rust,ignore
36
38
struct Foo<A, B> {
@@ -49,25 +51,32 @@ impl<X, Y> Foo<X, Y> {
49
51
}
50
52
```
51
53
52
-
Concretely given the `ty::Generics` for the item the parameter is defined on, if the index is `2` then starting from the root `parent`, it will be the third parameter to be introduced. For example in the above example, `Z` has index `2` and is the third generic parameter to be introduced, starting from the `impl` block.
54
+
Concretely given the `ty::Generics` for the item the parameter is defined on, if the index is `2` then starting from the root `parent`, it will be the third parameter to be introduced.
55
+
For example in the above example, `Z` has index `2` and is the third generic parameter to be introduced, starting from the `impl` block.
53
56
54
57
The index fully defines the `Ty` and is the only part of `TyKind::Param` that matters for reasoning about the code we are compiling.
55
58
56
-
Generally we do not care what the name is and only use the index. The name is included for diagnostics and debug logs as otherwise it would be
59
+
Generally we do not care what the name is and only use the index.
60
+
The name is included for diagnostics and debug logs as otherwise it would be
57
61
incredibly difficult to understand the output, i.e. `Vec<Param(0)>: Sized` vs `Vec<T>: Sized`. In debug output, parameter types are
58
62
often printed out as `{name}/#{index}`, for example in the function `foo` if we were to debug print `Vec<T>` it would be written as `Vec<T/#0>`.
59
63
60
-
An alternative representation would be to only have the name, however using an index is more efficient as it means we can index into `GenericArgs` when instantiating generic parameters with some arguments. We would otherwise have to store `GenericArgs` as a `HashMap<Symbol, GenericArg>` and do a hashmap lookup everytime we used a generic item.
64
+
An alternative representation would be to only have the name, however using an index is more efficient as it means we can index into `GenericArgs` when instantiating generic parameters with some arguments.
65
+
We would otherwise have to store `GenericArgs` as a `HashMap<Symbol, GenericArg>` and do a hashmap lookup everytime we used a generic item.
61
66
62
67
In theory an index would also allow for having multiple distinct parameters that use the same name, e.g.
63
68
`impl<A> Foo<A> { fn bar<A>() { .. } }`.
64
69
The rules against shadowing make this difficult but those language rules could change in the future.
65
70
66
71
### Lifetime parameters
67
72
68
-
In contrast to `Ty`/`Const`'s `Param` singular `Param` variant, lifetimes have two variants for representing region parameters: [`RegionKind::EarlyParam`] and [`RegionKind::LateParam`]. The reason for this is due to function's distinguishing between [early and late bound parameters][ch_early_late_bound] which is discussed in an earlier chapter (see link).
73
+
In contrast to `Ty`/`Const`'s `Param` singular `Param` variant, lifetimes have two variants for representing region parameters: [`RegionKind::EarlyParam`] and [`RegionKind::LateParam`].
74
+
The reason for this is due to function's distinguishing between [early and late bound parameters][ch_early_late_bound] which is discussed in an earlier chapter (see link).
69
75
70
-
`RegionKind::EarlyParam` is structured identically to `Ty/Const`'s `Param` variant, it is simply a `u32` index and a `Symbol`. For lifetime parameters defined on non-function items we always use `ReEarlyParam`. For functions we use `ReEarlyParam` for any early bound parameters and `ReLateParam` for any late bound parameters. Note that just like `Ty` and `Const` params we often debug format them as `'SYMBOL/#INDEX`, see for example:
76
+
`RegionKind::EarlyParam` is structured identically to `Ty/Const`'s `Param` variant, it is simply a `u32` index and a `Symbol`.
77
+
For lifetime parameters defined on non-function items we always use `ReEarlyParam`.
78
+
For functions we use `ReEarlyParam` for any early bound parameters and `ReLateParam` for any late bound parameters.
79
+
Note that just like `Ty` and `Const` params we often debug format them as `'SYMBOL/#INDEX`, see for example:
71
80
72
81
```rust,ignore
73
82
// This function would have its signature represented as:
0 commit comments