From a0392dff4d3b7708851d2411b472fb2f8f1abfc1 Mon Sep 17 00:00:00 2001
From: gnzlbg <gonzalobg88@gmail.com>
Date: Wed, 26 Jun 2019 12:49:33 +0200
Subject: [PATCH 01/16] Add niches to layout and expand call ABI

---
 reference/src/glossary.md | 31 +++++++++++++++++++++++++++++--
 1 file changed, 29 insertions(+), 2 deletions(-)

diff --git a/reference/src/glossary.md b/reference/src/glossary.md
index 3b9cf4f7..20456770 100644
--- a/reference/src/glossary.md
+++ b/reference/src/glossary.md
@@ -53,8 +53,13 @@ For some more information, see [this blog post](https://www.ralfj.de/blog/2018/0
 
 #### Layout
 
-The *layout* of a type defines its size and alignment as well as the offsets of its subobjects (e.g. fields of structs/unions/enum/... or elements of arrays).
-Moreover, the layout of a type records its *function call ABI* (or just *ABI* for short): how the type is passed *by value* across a function boundary.
+The *layout* of a type defines:
+
+* its size,
+* its alignment,
+* its field offsets (e.g. fields of structs, union, enums, arrays, ...)
+* its [niches][Niche],
+* its call abi.
 
 Note: Originally, *layout* and *representation* were treated as synonyms, and Rust language features like the `#[repr]` attribute reflect this. 
 In this document, *layout* and *representation* are not synonyms.
@@ -73,6 +78,28 @@ niches. For example, the "all bits uninitialized" is an invalid bit-pattern for
 `&mut T`, but this bit-pattern cannot be used by layout optimizations, and is not a
 niche.
 
+#### Call ABI
+
+The call ABI is how a type is passed *by value* across a function boundary.
+
+Note: The call ABI is not stable. Currently, it is one of:
+
+```rust,norun
+pub enum Abi {
+    Uninhabited,
+    Scalar(Scalar),
+    Vector {
+        element: Scalar,
+        count: u64
+    },
+    Aggregate {
+        // If true, the layout size of the aggregate is exact.
+        // Otherwise, the layout size of the aggregate is
+        // a lower bound.
+        sized: bool,
+    }
+}
+```
 
 ### TODO
 

From 1d198e684f5eb7febb0f94bf46ae3b533689cbe2 Mon Sep 17 00:00:00 2001
From: gnzlbg <gonzalobg88@gmail.com>
Date: Wed, 26 Jun 2019 12:52:42 +0200
Subject: [PATCH 02/16] Add note about why niches need to be part of the layout

---
 reference/src/glossary.md | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/reference/src/glossary.md b/reference/src/glossary.md
index 20456770..03645399 100644
--- a/reference/src/glossary.md
+++ b/reference/src/glossary.md
@@ -64,6 +64,7 @@ The *layout* of a type defines:
 Note: Originally, *layout* and *representation* were treated as synonyms, and Rust language features like the `#[repr]` attribute reflect this. 
 In this document, *layout* and *representation* are not synonyms.
 
+<<<<<<< HEAD
 #### Niche
 
 The *niche* of a type determines invalid bit-patterns that will be used by layout optimizations.
@@ -77,6 +78,10 @@ While all niches are invalid bit-patterns, not all invalid bit-patterns are
 niches. For example, the "all bits uninitialized" is an invalid bit-pattern for
 `&mut T`, but this bit-pattern cannot be used by layout optimizations, and is not a
 niche.
+=======
+Note: due to discriminant-elision optimizations, niches are required to compute
+the layout of, e.g., `Option<T>`, from the layout of `T`.
+>>>>>>> Add note about why niches need to be part of the layout
 
 #### Call ABI
 

From 5b6079b69295471e75cdc580858b0298b6f78fcd Mon Sep 17 00:00:00 2001
From: gnzlbg <gonzalobg88@gmail.com>
Date: Wed, 26 Jun 2019 12:56:51 +0200
Subject: [PATCH 03/16] Add call ABI example

---
 reference/src/glossary.md | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/reference/src/glossary.md b/reference/src/glossary.md
index 03645399..b86425f0 100644
--- a/reference/src/glossary.md
+++ b/reference/src/glossary.md
@@ -106,6 +106,10 @@ pub enum Abi {
 }
 ```
 
+For example, the call ABI of `i32` is `Scalar`. The call ABI of `struct
+Wrapper(i32);` is also `Scalar`. But the call ABI of `#[repr(C)] struct
+Wrapper(i32)l` is `Aggregate { sized: true }`.
+
 ### TODO
 
 * *tag*

From a05fd3ba4d3dd43fbfe5c1e32c79a1dda4c5143f Mon Sep 17 00:00:00 2001
From: gnzlbg <gnzlbg@users.noreply.github.com>
Date: Wed, 26 Jun 2019 20:17:47 +0200
Subject: [PATCH 04/16] Update reference/src/glossary.md

Co-Authored-By: Ralf Jung <post@ralfj.de>
---
 reference/src/glossary.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/reference/src/glossary.md b/reference/src/glossary.md
index b86425f0..2c753e61 100644
--- a/reference/src/glossary.md
+++ b/reference/src/glossary.md
@@ -85,7 +85,7 @@ the layout of, e.g., `Option<T>`, from the layout of `T`.
 
 #### Call ABI
 
-The call ABI is how a type is passed *by value* across a function boundary.
+The *call ABI* determines how a type is passed *by value* across a function boundary.
 
 Note: The call ABI is not stable. Currently, it is one of:
 

From afebd1cf8252992b79e7ac26e0bab8c8ed7d2387 Mon Sep 17 00:00:00 2001
From: gnzlbg <gonzalobg88@gmail.com>
Date: Wed, 26 Jun 2019 20:29:53 +0200
Subject: [PATCH 05/16] Clarify ABI and examples

---
 reference/src/glossary.md | 31 ++++++++++++++++++++++++++++---
 1 file changed, 28 insertions(+), 3 deletions(-)

diff --git a/reference/src/glossary.md b/reference/src/glossary.md
index 2c753e61..9cea80d7 100644
--- a/reference/src/glossary.md
+++ b/reference/src/glossary.md
@@ -106,9 +106,34 @@ pub enum Abi {
 }
 ```
 
-For example, the call ABI of `i32` is `Scalar`. The call ABI of `struct
-Wrapper(i32);` is also `Scalar`. But the call ABI of `#[repr(C)] struct
-Wrapper(i32)l` is `Aggregate { sized: true }`.
+where
+
+```rust,norun
+enum Integer { I8, I16, I32, I64, I128, }
+enum FloatTy { F32, F64, }
+
+enum Primitive {
+    Int(Integer, /*signedness:*/ bool),
+    Float(FloatTy),
+    Pointer
+}
+
+struct Scalar {
+    value: Primitive,
+    valid_range: RangeInclusive<u128>,
+}
+```
+
+For example, right now, the call ABI of:
+
+* `i32` is `Scalar`,
+* `struct Wrapper(i32);` (without `repr(transparent)`) is also `Scalar` (only larger `struct`s are aggregates),
+* `#[repr(C)] struct Wrapper(i32);` is `Aggregate { sized: true }` - required by `repr(C****.
+
+**NOTE**: the call ABI of `repr(Rust)` types is unspecified, so the "call ABI"
+of `repr(Rust)` types is not guaranteed and `unsafe` code shall not rely on it.
+That is, code that requires `struct Wrapper(i32);` to have the same ABI as `i32`
+needs to use `repr(transparent)`. f
 
 ### TODO
 

From bd747eeae8717328a178708544c0b56bb34236dc Mon Sep 17 00:00:00 2001
From: gnzlbg <gonzalobg88@gmail.com>
Date: Wed, 26 Jun 2019 21:17:01 +0200
Subject: [PATCH 06/16] Separate guaranteed from non guaranteed behavior in
 call ABI examples

---
 reference/src/glossary.md | 24 ++++++++++--------------
 1 file changed, 10 insertions(+), 14 deletions(-)

diff --git a/reference/src/glossary.md b/reference/src/glossary.md
index 9cea80d7..e06409a1 100644
--- a/reference/src/glossary.md
+++ b/reference/src/glossary.md
@@ -106,34 +106,30 @@ pub enum Abi {
 }
 ```
 
-where
+where:
 
 ```rust,norun
 enum Integer { I8, I16, I32, I64, I128, }
 enum FloatTy { F32, F64, }
 
-enum Primitive {
+enum Scalar {
     Int(Integer, /*signedness:*/ bool),
     Float(FloatTy),
     Pointer
 }
-
-struct Scalar {
-    value: Primitive,
-    valid_range: RangeInclusive<u128>,
-}
 ```
 
-For example, right now, the call ABI of:
+For example, the call ABI of:
 
 * `i32` is `Scalar`,
-* `struct Wrapper(i32);` (without `repr(transparent)`) is also `Scalar` (only larger `struct`s are aggregates),
-* `#[repr(C)] struct Wrapper(i32);` is `Aggregate { sized: true }` - required by `repr(C****.
+* `#[repr(C)] struct Wrapper(i32);` is `Aggregate { sized: true }`.
+* `#[repr(transparent)] struct Wrapper(i32);` is `Scalar`.
+
+The call ABI of `repr(Rust)` types is unspecified. The following is not
+guaranteed, but right now the call ABI of:
 
-**NOTE**: the call ABI of `repr(Rust)` types is unspecified, so the "call ABI"
-of `repr(Rust)` types is not guaranteed and `unsafe` code shall not rely on it.
-That is, code that requires `struct Wrapper(i32);` to have the same ABI as `i32`
-needs to use `repr(transparent)`. f
+* `/*#[repr(Rust)]*/ struct Wrapper(i32);` (without `repr(transparent)`) is also
+  `Scalar` - only larger `struct`s are aggregates.
 
 ### TODO
 

From b154cb4c553958761d0b0a7e8001721de9dbc3c0 Mon Sep 17 00:00:00 2001
From: gnzlbg <gonzalobg88@gmail.com>
Date: Wed, 26 Jun 2019 21:19:10 +0200
Subject: [PATCH 07/16] Specify which scalars in examples

---
 reference/src/glossary.md | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/reference/src/glossary.md b/reference/src/glossary.md
index e06409a1..4720a2f4 100644
--- a/reference/src/glossary.md
+++ b/reference/src/glossary.md
@@ -121,15 +121,15 @@ enum Scalar {
 
 For example, the call ABI of:
 
-* `i32` is `Scalar`,
+* `i32` is `Scalar::Int(I32,true)`,
 * `#[repr(C)] struct Wrapper(i32);` is `Aggregate { sized: true }`.
-* `#[repr(transparent)] struct Wrapper(i32);` is `Scalar`.
+* `#[repr(transparent)] struct Wrapper(i32);` is `Scalar::Int(I32,true)`.
 
 The call ABI of `repr(Rust)` types is unspecified. The following is not
 guaranteed, but right now the call ABI of:
 
 * `/*#[repr(Rust)]*/ struct Wrapper(i32);` (without `repr(transparent)`) is also
-  `Scalar` - only larger `struct`s are aggregates.
+  `Scalar::Int(I32, true)` - only larger `struct`s are aggregates.
 
 ### TODO
 

From 4861ff01ed4a3884b406b9da73dfb7952a9061b6 Mon Sep 17 00:00:00 2001
From: gnzlbg <gonzalobg88@gmail.com>
Date: Wed, 26 Jun 2019 21:23:16 +0200
Subject: [PATCH 08/16] Simplify further

---
 reference/src/glossary.md | 20 +++++---------------
 1 file changed, 5 insertions(+), 15 deletions(-)

diff --git a/reference/src/glossary.md b/reference/src/glossary.md
index 4720a2f4..c73a40c7 100644
--- a/reference/src/glossary.md
+++ b/reference/src/glossary.md
@@ -106,30 +106,20 @@ pub enum Abi {
 }
 ```
 
-where:
-
-```rust,norun
-enum Integer { I8, I16, I32, I64, I128, }
-enum FloatTy { F32, F64, }
-
-enum Scalar {
-    Int(Integer, /*signedness:*/ bool),
-    Float(FloatTy),
-    Pointer
-}
-```
+where a `Scalar` is either a primitive integer, floating point, or a pointer to
+a sized type.
 
 For example, the call ABI of:
 
-* `i32` is `Scalar::Int(I32,true)`,
+* `i32` is `Scalar(I32)`,
 * `#[repr(C)] struct Wrapper(i32);` is `Aggregate { sized: true }`.
-* `#[repr(transparent)] struct Wrapper(i32);` is `Scalar::Int(I32,true)`.
+* `#[repr(transparent)] struct Wrapper(i32);` is `Scalar(I32)`.
 
 The call ABI of `repr(Rust)` types is unspecified. The following is not
 guaranteed, but right now the call ABI of:
 
 * `/*#[repr(Rust)]*/ struct Wrapper(i32);` (without `repr(transparent)`) is also
-  `Scalar::Int(I32, true)` - only larger `struct`s are aggregates.
+  `Scalar(I32)` - only larger `struct`s are aggregates.
 
 ### TODO
 

From 6c814077ee9eedbf57297ca326c156e74fa5d8b3 Mon Sep 17 00:00:00 2001
From: gnzlbg <gonzalobg88@gmail.com>
Date: Sat, 29 Jun 2019 00:01:00 +0200
Subject: [PATCH 09/16] Ignore the Rust snippet

---
 reference/src/glossary.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/reference/src/glossary.md b/reference/src/glossary.md
index c73a40c7..2b375141 100644
--- a/reference/src/glossary.md
+++ b/reference/src/glossary.md
@@ -89,8 +89,8 @@ The *call ABI* determines how a type is passed *by value* across a function boun
 
 Note: The call ABI is not stable. Currently, it is one of:
 
-```rust,norun
-pub enum Abi {
+```rust,ignore
+enum Abi {
     Uninhabited,
     Scalar(Scalar),
     Vector {

From 624653458b6481d805d57b130f32a5f92a12e4bb Mon Sep 17 00:00:00 2001
From: gnzlbg <gnzlbg@users.noreply.github.com>
Date: Tue, 23 Jul 2019 16:15:03 +0200
Subject: [PATCH 10/16] Update reference/src/glossary.md

Co-Authored-By: Ralf Jung <post@ralfj.de>
---
 reference/src/glossary.md | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/reference/src/glossary.md b/reference/src/glossary.md
index 2b375141..869f2768 100644
--- a/reference/src/glossary.md
+++ b/reference/src/glossary.md
@@ -61,10 +61,12 @@ The *layout* of a type defines:
 * its [niches][Niche],
 * its call abi.
 
+Note: due to discriminant-elision optimizations, niches are required to compute
+the layout of, e.g., `Option<T>`, from the layout of `T`.
+
 Note: Originally, *layout* and *representation* were treated as synonyms, and Rust language features like the `#[repr]` attribute reflect this. 
 In this document, *layout* and *representation* are not synonyms.
 
-<<<<<<< HEAD
 #### Niche
 
 The *niche* of a type determines invalid bit-patterns that will be used by layout optimizations.
@@ -78,16 +80,12 @@ While all niches are invalid bit-patterns, not all invalid bit-patterns are
 niches. For example, the "all bits uninitialized" is an invalid bit-pattern for
 `&mut T`, but this bit-pattern cannot be used by layout optimizations, and is not a
 niche.
-=======
-Note: due to discriminant-elision optimizations, niches are required to compute
-the layout of, e.g., `Option<T>`, from the layout of `T`.
->>>>>>> Add note about why niches need to be part of the layout
 
 #### Call ABI
 
 The *call ABI* determines how a type is passed *by value* across a function boundary.
 
-Note: The call ABI is not stable. Currently, it is one of:
+Note: The set of possible call ABIs is not stable. Currently, it consists of:
 
 ```rust,ignore
 enum Abi {

From 875c32b20c490baa2b1ddb874bfd0fd61784aa10 Mon Sep 17 00:00:00 2001
From: gnzlbg <gonzalobg88@gmail.com>
Date: Tue, 23 Jul 2019 17:23:13 +0200
Subject: [PATCH 11/16] Properly link layout components

---
 reference/src/glossary.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/reference/src/glossary.md b/reference/src/glossary.md
index 869f2768..11e3dca7 100644
--- a/reference/src/glossary.md
+++ b/reference/src/glossary.md
@@ -58,8 +58,8 @@ The *layout* of a type defines:
 * its size,
 * its alignment,
 * its field offsets (e.g. fields of structs, union, enums, arrays, ...)
-* its [niches][Niche],
-* its call abi.
+* its [niches](glossary.html#niche),
+* its [call abi](glossary.html#call-abi).
 
 Note: due to discriminant-elision optimizations, niches are required to compute
 the layout of, e.g., `Option<T>`, from the layout of `T`.

From 6ad8df6b7e8a30d0273a7d349d287168dc7bf64a Mon Sep 17 00:00:00 2001
From: gnzlbg <gonzalobg88@gmail.com>
Date: Tue, 23 Jul 2019 17:26:45 +0200
Subject: [PATCH 12/16] Use short links

---
 reference/src/glossary.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/reference/src/glossary.md b/reference/src/glossary.md
index 11e3dca7..6a0bdde4 100644
--- a/reference/src/glossary.md
+++ b/reference/src/glossary.md
@@ -58,8 +58,8 @@ The *layout* of a type defines:
 * its size,
 * its alignment,
 * its field offsets (e.g. fields of structs, union, enums, arrays, ...)
-* its [niches](glossary.html#niche),
-* its [call abi](glossary.html#call-abi).
+* its [niches](#niche),
+* its [call abi](#call-abi).
 
 Note: due to discriminant-elision optimizations, niches are required to compute
 the layout of, e.g., `Option<T>`, from the layout of `T`.

From bd13bcdb5033651fbd813018d9506638573d4c8d Mon Sep 17 00:00:00 2001
From: gnzlbg <gonzalobg88@gmail.com>
Date: Tue, 23 Jul 2019 18:31:39 +0200
Subject: [PATCH 13/16] Update layout of arrays and slices

---
 reference/src/layout/arrays-and-slices.md | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/reference/src/layout/arrays-and-slices.md b/reference/src/layout/arrays-and-slices.md
index 375d1571..bf356fc5 100644
--- a/reference/src/layout/arrays-and-slices.md
+++ b/reference/src/layout/arrays-and-slices.md
@@ -10,8 +10,9 @@ The _offset_ of the first array element is `0`, that is, a pointer to the array
 and a pointer to its first element both point to the same memory address.
 
 The _alignment_ of array types is greater or equal to the alignment of its
-element type. If the element type is `repr(C)` the layout of the array is
-guaranteed to be the same as the layout of a C array with the same element type.
+element type. If the element type is `repr(C)` the size and alignment of the
+array is guaranteed to be the same as the size and alignment of a C array with
+the same element type.
 
 > **Note**: the type of array arguments in C function signatures, e.g., `void
 > foo(T x[N])`, decays to a pointer. That is, these functions do not take arrays

From 3d71cf6c4e5d726a742e807cb9ed6c58743c979e Mon Sep 17 00:00:00 2001
From: gnzlbg <gonzalobg88@gmail.com>
Date: Tue, 23 Jul 2019 18:31:48 +0200
Subject: [PATCH 14/16] Update layout of scalars

---
 reference/src/layout/scalars.md | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/reference/src/layout/scalars.md b/reference/src/layout/scalars.md
index 7b647cbc..8170dfa9 100644
--- a/reference/src/layout/scalars.md
+++ b/reference/src/layout/scalars.md
@@ -10,9 +10,9 @@ layout `#[repr()]` flags.
 
 ## `bool`
 
-Rust's `bool` has the same layout as C17's` _Bool`, that is, its size and
-alignment are implementation-defined. Any `bool` can be cast into an integer,
-taking on the values 1 (`true`) or 0 (`false`).
+Rust's `bool` has the same layout as C17's` _Bool` which is
+implementation-defined. Any `bool` can be cast into an integer, taking on the
+values 1 (`true`) or 0 (`false`).
 
 > **Note**: on all platforms that Rust's currently supports, its size and
 > alignment are 1, and its ABI class is `INTEGER` - see [Rust Layout and ABIs].

From 5057e1a5c7aff5fb7e7d416efbe2f10dbf6e319b Mon Sep 17 00:00:00 2001
From: gnzlbg <gonzalobg88@gmail.com>
Date: Tue, 23 Jul 2019 18:38:34 +0200
Subject: [PATCH 15/16] Update layout of pointers

---
 reference/src/layout/pointers.md | 29 ++++++++++++++++++-----------
 1 file changed, 18 insertions(+), 11 deletions(-)

diff --git a/reference/src/layout/pointers.md b/reference/src/layout/pointers.md
index 336651ef..9d965578 100644
--- a/reference/src/layout/pointers.md
+++ b/reference/src/layout/pointers.md
@@ -28,15 +28,18 @@ and are at least one word.
 
 ### Notes
 
-The layouts of `&T`, `&mut T`, `*const T` and `*mut T` are the same.
+The size, alignment, and call ABI of `&T`, `&mut T`, `*const T` and `*mut T` are
+the same.
 
-If `T` is sized, references and pointers to `T` have a size and alignment of one
-word and have therefore the same layout as C pointers.
+If `T` is sized, the size, alignment, and call ABI of references and pointers to
+`T` is the same as that of C pointers.
 
-> **warning**: while the layout of references and pointers is compatible with
-> the layout of C pointers, references come with a _validity_ invariant that
-> does not allow them to be used when they could be `NULL`, unaligned, dangling,
-> or, in the case of `&mut T`, aliasing.
+> **warning**: while the size, alignment, and call ABI of references and
+> pointers is compatible with the layout of C pointers, references come with a
+> _validity_ invariant that does not allow them to be used when they could be
+> `NULL`, unaligned, dangling, or, in the case of `&mut T`, aliasing. Since the
+> niches of references and pointers are not the same, these types are not
+> layout-compatible with each other.
 
 We do not make any guarantees about the layout of
 multi-trait objects `&(dyn Trait1 + Trait2)` or references to other dynamically sized types,
@@ -53,7 +56,7 @@ struct DynObject {
 
 > **note**: In the layout of `&dyn mut Trait` the field `data` is of the type `*mut u8`.
 
-The layout of `&[T]` is the same as that of:
+The size, alignment, and call ABI of `&[T]` and `&mut [T]` are the same as that of:
 ```rust
 #[repr(C)]
 struct Slice<T> {
@@ -62,7 +65,11 @@ struct Slice<T> {
 }
 ```
 
-> **note**: In the layout of `&mut [T]` the field `ptr` is of the type `*mut T`.
+> **note**: the field `ptr` is of the type `*mut T` for `&mut [T]`.
 
-The layout of `&str` is the same as that of `&[u8]`, and the layout of `&mut str` is
-the same as that of `&mut [u8]`.
+The size, alignment, and call ABI of `&str` is the same as that of `&[u8]`, and
+the layout of `&mut str` is the same as that of `&mut [u8]`.
+
+#### Unresolved question
+
+* Does `&str` have the same niches as `&[u8]` ?

From 288441d30787f6222225b9fccff7f4f7e5aeb5a6 Mon Sep 17 00:00:00 2001
From: gnzlbg <gonzalobg88@gmail.com>
Date: Tue, 23 Jul 2019 18:39:35 +0200
Subject: [PATCH 16/16] Update layout of function pointers

---
 reference/src/layout/function-pointers.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/reference/src/layout/function-pointers.md b/reference/src/layout/function-pointers.md
index 3188fb05..e9fe4782 100644
--- a/reference/src/layout/function-pointers.md
+++ b/reference/src/layout/function-pointers.md
@@ -25,7 +25,7 @@ or the address of a function.
 
 ### Representation
 
-The ABI and layout of `(unsafe)? (extern "ABI")? fn(Args...) -> Ret`
+The size, alignment, and call ABI of `(unsafe)? (extern "ABI")? fn(Args...) -> Ret`
 is exactly that of the corresponding C type --
 the lack of a null value does not change this. 
 On common platforms, this means that `*const ()` and `fn(Args...) -> Ret` have