Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
98 commits
Select commit Hold shift + click to select a range
a9261db
Filling out template with PR 5389
josh11b Apr 29, 2025
c01299c
Checkpoint progress.
josh11b Apr 30, 2025
d115853
Checkpoint progress.
josh11b Apr 30, 2025
26933f0
Checkpoint progress.
josh11b Apr 30, 2025
caee934
Checkpoint progress.
josh11b Apr 30, 2025
3e01e9c
Checkpoint progress.
josh11b Apr 30, 2025
f520e23
Checkpoint progress.
josh11b May 1, 2025
74446ec
Checkpoint progress.
josh11b May 3, 2025
cb53abe
Checkpoint progress.
josh11b May 4, 2025
01bf70f
Checkpoint progress.
josh11b May 4, 2025
a7a34d4
Checkpoint progress.
josh11b May 4, 2025
92d7afd
Checkpoint progress.
josh11b May 4, 2025
d447a7b
Checkpoint progress.
josh11b May 5, 2025
9ed273e
Checkpoint progress.
josh11b May 5, 2025
1feddd3
Checkpoint progress.
josh11b May 14, 2025
88e86b7
Checkpoint progress.
josh11b May 14, 2025
fd6c97a
Checkpoint progress.
josh11b May 19, 2025
b860b61
Checkpoint progress.
josh11b May 19, 2025
3c0c972
Checkpoint progress.
josh11b May 20, 2025
3432799
Checkpoint progress.
josh11b May 21, 2025
d4fc697
Checkpoint progress.
josh11b May 22, 2025
683fcdc
Checkpoint progress.
josh11b May 22, 2025
11de2f8
Checkpoint progress.
josh11b May 22, 2025
2ba77a9
Checkpoint progress.
josh11b May 23, 2025
94bfaa7
Checkpoint progress.
josh11b May 23, 2025
fd7f9f1
Checkpoint progress.
josh11b May 23, 2025
3cff65d
Checkpoint progress.
josh11b May 23, 2025
4e80973
Checkpoint progress.
josh11b May 23, 2025
b6ff9f8
Checkpoint progress.
josh11b May 24, 2025
318c962
Checkpoint progress.
josh11b May 24, 2025
449aab1
Checkpoint progress.
josh11b May 28, 2025
4c45b68
Checkpoint progress.
josh11b May 28, 2025
c1a85e0
Checkpoint progress.
josh11b May 28, 2025
3bec9a8
Checkpoint progress.
josh11b May 29, 2025
a645e65
Checkpoint progress.
josh11b May 29, 2025
e107a25
Checkpoint progress.
josh11b May 29, 2025
d305678
Checkpoint progress.
josh11b May 30, 2025
757cd8e
Merge remote-tracking branch 'upstream/trunk' into overload
josh11b May 30, 2025
9869692
Checkpoint progress.
josh11b May 30, 2025
c6ff6fc
Checkpoint progress.
josh11b May 31, 2025
c4a5575
Checkpoint progress.
josh11b Jun 3, 2025
45faf37
Checkpoint progress.
josh11b Jun 3, 2025
be738bc
Checkpoint progress.
josh11b Jun 4, 2025
76564d7
Big change to merge form type
josh11b Jun 5, 2025
ae65589
Checkpoint progress.
josh11b Jun 6, 2025
d5da55d
Checkpoint progress.
josh11b Jun 6, 2025
6845da1
Checkpoint progress.
josh11b Jun 6, 2025
9ecc773
Checkpoint progress.
josh11b Jun 6, 2025
c25ce83
Checkpoint progress.
josh11b Jun 9, 2025
84a6772
Checkpoint progress.
josh11b Jun 10, 2025
af2ec9b
Checkpoint progress.
josh11b Jun 11, 2025
aae935c
Checkpoint progress.
josh11b Jun 11, 2025
96ceb92
Checkpoint progress.
josh11b Jun 12, 2025
de97500
Checkpoint progress.
josh11b Jun 12, 2025
537002f
Checkpoint progress.
josh11b Jun 13, 2025
acba490
Checkpoint progress.
josh11b Jun 13, 2025
15636b1
Checkpoint progress.
josh11b Jun 13, 2025
f7cad28
Checkpoint progress.
josh11b Jun 13, 2025
f66dd5d
Checkpoint progress.
josh11b Jun 14, 2025
3644766
Checkpoint progress.
josh11b Jun 14, 2025
069b18a
Checkpoint progress.
josh11b Jun 15, 2025
d76ef26
Checkpoint progress.
josh11b Jun 17, 2025
0c85dda
Checkpoint progress.
josh11b Jun 17, 2025
a673302
Checkpoint progress.
josh11b Jun 18, 2025
c79e3c4
`val` instead of `let`
josh11b Jun 18, 2025
7fb1df5
`ref` on argument expressions control deduction
josh11b Jun 18, 2025
467dbf5
const and anchor
josh11b Jun 24, 2025
e78d443
Checkpoint progress.
josh11b Jun 25, 2025
a11ee5c
Checkpoint progress.
josh11b Jun 27, 2025
9ef902f
Rename
josh11b Jun 27, 2025
164009e
Checkpoint progress.
josh11b Jul 5, 2025
ebbd0e2
Checkpoint progress.
josh11b Jul 21, 2025
31c4dce
Checkpoint progress.
josh11b Aug 1, 2025
ab187ef
Checkpoint progress.
josh11b Aug 2, 2025
94023f0
Checkpoint progress.
josh11b Aug 2, 2025
218c958
Checkpoint progress.
josh11b Aug 2, 2025
f584d45
Checkpoint progress.
josh11b Aug 2, 2025
ab745fb
Checkpoint progress.
josh11b Aug 7, 2025
db05d19
Checkpoint progress.
josh11b Aug 7, 2025
26e0318
Checkpoint progress.
josh11b Aug 29, 2025
75ff32c
Checkpoint progress.
josh11b Aug 29, 2025
6061972
Checkpoint progress.
josh11b Sep 3, 2025
549540c
Checkpoint progress.
josh11b Sep 5, 2025
5c9836f
Merge remote-tracking branch 'upstream/trunk' into overload
josh11b Sep 5, 2025
15f63fd
Checkpoint progress.
josh11b Sep 8, 2025
1204042
Checkpoint progress.
josh11b Sep 9, 2025
ae3c9f1
Checkpoint progress.
josh11b Sep 9, 2025
66984db
Checkpoint progress.
josh11b Sep 9, 2025
f94868c
Checkpoint progress.
josh11b Sep 9, 2025
1fc99b3
Finish summary
josh11b Sep 10, 2025
eeafec4
Checkpoint progress.
josh11b Sep 10, 2025
5a178bd
Merge remote-tracking branch 'upstream/trunk' into overload
josh11b Sep 10, 2025
4a20e08
Apply suggestions from code review
josh11b Sep 15, 2025
7a75b38
Fix typo
josh11b Sep 15, 2025
361b3a9
Apply suggestions from code review
josh11b Sep 15, 2025
74f6fe4
Fix formatting
josh11b Sep 15, 2025
e387dd0
Reasons we didn't go with alternative
josh11b Sep 25, 2025
59b2648
Update docs/design/expressions/as_expressions.md
josh11b Oct 1, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
197 changes: 143 additions & 54 deletions docs/design/assignment.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,127 +173,214 @@ provided for built-in types as necessary to give the semantics described above.
### Simple assignment

```
package Core;

// Simple `=`.
interface AssignWith(U:! type) {
fn Op[addr self: Self*](other: U);
interface AssignWithPrimitive
(implicit_into U:! NoRefForm) {
fn Op[ref self: Self](other:? U);
}
constraint AssignWith(U:! type) {
extend require impls
AssignWithPrimitive(form(val U));
}
constraint Assign {
extend require impls AssignWith(Self);
}
constraint Assign { extend AssignWith(Self); }
```

Given `var x: T` and `y: U`:

- The statement `x = y;` is rewritten to `x.(AssignWith(U).Op)(y);`.
The statement `x = y;` is rewritten to
`x.(AssignWithPrimitive(formof(y)).Op)(y);`.

### Arithmetic

```
// Compound `+=`.
interface AddAssignWith(U:! type) {
fn Op[addr self: Self*](other: U);
interface AddAssignWithPrimitive
(implicit_into U:! NoRefForm) {
fn Op[ref self: Self](other:? U);
}
constraint AddAssignWith(U:! type) {
extend require impls
AddAssignWithPrimitive(form(val U));
}
constraint AddAssign {
extend require impls AddAssignWith(Self);
}
constraint AddAssign { extend AddAssignWith(Self); }
```

```
// Compound `-=`.
interface SubAssignWith(U:! type) {
fn Op[addr self: Self*](other: U);
interface SubAssignWithPrimitive
(implicit_into U:! NoRefForm) {
fn Op[ref self: Self](other:? U);
}
constraint SubAssignWith(U:! type) {
extend require impls
SubAssignWithPrimitive(form(val U));
}
constraint SubAssign {
extend require impls SubAssignWith(Self);
}
constraint SubAssign { extend SubAssignWith(Self); }
```

```
// Compound `*=`.
interface MulAssignWith(U:! type) {
fn Op[addr self: Self*](other: U);
interface MulAssignWithPrimitive
(implicit_into U:! NoRefForm) {
fn Op[ref self: Self](other:? U);
}
constraint MulAssignWith(U:! type) {
extend require impls
MulAssignWithPrimitive(form(val U));
}
constraint MulAssign {
extend require impls MulAssignWith(Self);
}
constraint MulAssign { extend MulAssignWith(Self); }
```

```
// Compound `/=`.
interface DivAssignWith(U:! type) {
fn Op[addr self: Self*](other: U);
interface DivAssignWithPrimitive
(implicit_into U:! NoRefForm) {
fn Op[ref self: Self](other:? U);
}
constraint DivAssignWith(U:! type) {
extend require impls
DivAssignWithPrimitive(form(val U));
}
constraint DivAssign {
extend require impls DivAssignWith(Self);
}
constraint DivAssign { extend DivAssignWith(Self); }
```

```
// Compound `%=`.
interface ModAssignWith(U:! type) {
fn Op[addr self: Self*](other: U);
interface ModAssignWithPrimitive
(implicit_into U:! NoRefForm) {
fn Op[ref self: Self](other:? U);
}
constraint ModAssignWith(U:! type) {
extend require impls
ModAssignWithPrimitive(form(val U));
}
constraint ModAssign {
extend require impls ModAssignWith(Self);
}
constraint ModAssign { extend ModAssignWith(Self); }
```

```
// Increment `++`.
interface Inc { fn Op[addr self: Self*](); }
interface Inc { fn Op[ref self: Self](); }
// Decrement `++`.
interface Dec { fn Op[addr self: Self*](); }
interface Dec { fn Op[ref self: Self](); }
```

Given `var x: T` and `y: U`:
These assignment statements are rewritten as follows:

- The statement `x += y;` is rewritten to `x.(AddAssignWith(U).Op)(y);`.
- The statement `x -= y;` is rewritten to `x.(SubAssignWith(U).Op)(y);`.
- The statement `x *= y;` is rewritten to `x.(MulAssignWith(U).Op)(y);`.
- The statement `x /= y;` is rewritten to `x.(DivAssignWith(U).Op)(y);`.
- The statement `x %= y;` is rewritten to `x.(ModAssignWith(U).Op)(y);`.
- The statement `x += y;` is rewritten to
`x.(AddAssignWithPrimitive(formof(y)).Op)(y);`.
- The statement `x -= y;` is rewritten to
`x.(SubAssignWithPrimitive(formof(y)).Op)(y);`.
- The statement `x *= y;` is rewritten to
`x.(MulAssignWithPrimitive(formof(y)).Op)(y);`.
- The statement `x /= y;` is rewritten to
`x.(DivAssignWithPrimitive(formof(y)).Op)(y);`.
- The statement `x %= y;` is rewritten to
`x.(ModAssignWithPrimitive(formof(y)).Op)(y);`.
- The statement `++x;` is rewritten to `x.(Inc.Op)();`.
- The statement `--x;` is rewritten to `x.(Dec.Op)();`.

### Bitwise and bit-shift

```
// Compound `&=`.
interface BitAndAssignWith(U:! type) {
fn Op[addr self: Self*](other: U);
interface BitAndAssignWithPrimitive
(implicit_into U:! NoRefForm) {
fn Op[ref self: Self](other:? U);
}
constraint BitAndAssignWith(U:! type) {
extend require impls
BitAndAssignWithPrimitive(form(val U));
}
constraint BitAndAssign {
extend require impls BitAndAssignWith(Self);
}
constraint BitAndAssign { extend BitAndAssignWith(Self); }
```

```
// Compound `|=`.
interface BitOrAssignWith(U:! type) {
fn Op[addr self: Self*](other: U);
interface BitOrAssignWithPrimitive
(implicit_into U:! NoRefForm) {
fn Op[ref self: Self](other:? U);
}
constraint BitOrAssignWith(U:! type) {
extend require impls
BitOrAssignWithPrimitive(form(val U));
}
constraint BitOrAssign {
extend require impls BitOrAssignWith(Self);
}
constraint BitOrAssign { extend BitOrAssignWith(Self); }
```

```
// Compound `^=`.
interface BitXorAssignWith(U:! type) {
fn Op[addr self: Self*](other: U);
interface BitXorAssignWithPrimitive
(implicit_into U:! NoRefForm) {
fn Op[ref self: Self](other:? U);
}
constraint BitXorAssignWith(U:! type) {
extend require impls
BitXorAssignWithPrimitive(form(val U));
}
constraint BitXorAssign {
extend require impls BitXorAssignWith(Self);
}
constraint BitXorAssign { extend BitXorAssignWith(Self); }
```

```
// Compound `<<=`.
interface LeftShiftAssignWith(U:! type) {
fn Op[addr self: Self*](other: U);
interface LeftShiftAssignWithPrimitive
(implicit_into U:! NoRefForm) {
fn Op[ref self: Self](other:? U);
}
constraint LeftShiftAssignWith(U:! type) {
extend require impls
LeftShiftAssignWithPrimitive(form(val U));
}
constraint LeftShiftAssign {
extend require impls LeftShiftAssignWith(Self);
}
constraint LeftShiftAssign { extend LeftShiftAssignWith(Self); }
```

```
// Compound `>>=`.
interface RightShiftAssignWith(U:! type) {
fn Op[addr self: Self*](other: U);
interface RightShiftAssignWithPrimitive
(implicit_into U:! NoRefForm) {
fn Op[ref self: Self](other:? U);
}
constraint RightShiftAssignWith(U:! type) {
extend require impls
RightShiftAssignWithPrimitive(form(val U));
}
constraint RightShiftAssign {
extend require impls
RightShiftAssignWith(Self);
}
constraint RightShiftAssign { extend RightShiftAssignWith(Self); }
```

Given `var x: T` and `y: U`:
These assignment statements are rewritten as follows:

- The statement `x &= y;` is rewritten to `x.(BitAndAssignWith(U).Op)(y);`.
- The statement `x |= y;` is rewritten to `x.(BitOrAssignWith(U).Op)(y);`.
- The statement `x ^= y;` is rewritten to `x.(BitXorAssignWith(U).Op)(y);`.
- The statement `x &= y;` is rewritten to
`x.(BitAndAssignWithPrimitive(formof(y)).Op)(y);`.
- The statement `x |= y;` is rewritten to
`x.(BitOrAssignWithPrimitive(formof(y)).Op)(y);`.
- The statement `x ^= y;` is rewritten to
`x.(BitXorAssignWithPrimitive(formof(y)).Op)(y);`.
- The statement `x <<= y;` is rewritten to
`x.(LeftShiftAssignWith(U).Op)(y);`.
`x.(LeftShiftAssignWithPrimitive(formof(y)).Op)(y);`.
- The statement `x >>= y;` is rewritten to
`x.(RightShiftAssignWith(U).Op)(y)`;.
`x.(RightShiftAssignWithPrimitive(formof(y)).Op)(y)`;.

Implementations of these interfaces are provided for built-in types as necessary
to give the semantics described above.
Expand All @@ -310,9 +397,9 @@ This defaulting is accomplished by a parameterized implementation of
```
impl forall [U:! type, T:! OpWith(U) where .Self impls AssignWith(.Self.Result)]
T as OpAssignWith(U) {
fn Op[addr self: Self*](other: U) {
fn Op[ref self: Self](other: U) {
// Here, `$` is the operator described by `OpWith`.
*self = *self $ other;
self = self $ other;
}
}
```
Expand All @@ -321,11 +408,11 @@ If a more efficient form of compound assignment is possible for a type, a more
specific `impl` can be provided:

```
impl like MyString as AddWith(like MyString) {
impl anchor MyString as AddWith(anchor MyString) {
// Allocate new memory and perform addition.
}

impl MyString as AddAssignWith(like MyString) {
impl MyString as AddAssignWith(MyString) {
// Reuse existing storage where possible.
}
```
Expand Down Expand Up @@ -355,3 +442,5 @@ impl MyString as AddAssignWith(like MyString) {
[#1191: Bitwise and shift operators](https://github.com/carbon-language/carbon-lang/pull/1191)
- Proposal
[#2511: Assignment statements](https://github.com/carbon-language/carbon-lang/pull/2511)
- Proposal
[#5389: Generic across forms](https://github.com/carbon-language/carbon-lang/pull/5389)
Loading
Loading