mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +01:00
Implements proposal #7016: `self` moves from the deduced implicit list (`fn F[self: Self]()`) to the front of the explicit list. Its type may be written explicitly (`fn F(self: Self)`) or omitted, in which case it defaults to `Self` (`fn F(self)`, `fn F(ref self)`); `self` in the implicit list is rejected. Throughout checking, `self` is modeled as the first explicit parameter. Because a method is just a function whose first parameter is `self`, it can also be called as an ordinary function with the receiver passed explicitly (`Type.M(obj, ...)`), not only as `obj.M(...)`. A new `SemIR::CallArgParamPatterns` helper chooses the parameters matched against the explicit arguments, excluding a leading `self` only when it is supplied as a method-call receiver; arity checking, conversion, and generic deduction use it. The resulting SemIR and lowering are unchanged: `self` is still `call_param0`, and witnesses, thunks, and vtables are unaffected. An omitted `self` type is parsed as a `SelfBindingPattern` node with no type expression; checking synthesizes the `Self` type so it behaves exactly like `self: Self`. However, the exact spelling used must match between a forward declaration and a definition, following #3763's rules around declaration matching. Generated functions, thunks, and C++ interop import/export build `self` as the first explicit parameter, and the `self`-type override (e.g. Derived->Base for a virtual override) applies to the explicit `self`. Placement is validated by new diagnostics: `SelfInImplicitParamList`, `SelfNotFirstParam`, and `SelfOutsideParamList`. The benchmark source generator and the documentation adopt the `(self)` shorthand; the prelude, the examples, and the test data are migrated in the following commits. Assisted-by: Claude Code with Claude Opus 4.7 --------- Co-authored-by: josh11b <15258583+josh11b@users.noreply.github.com>
This commit is contained in:
co-authored by
josh11b
parent
fb05da761f
commit
7871237c15
+5
-5
@@ -15,23 +15,23 @@ export import library "prelude/parts/destroy";
|
||||
export import library "prelude/parts/form";
|
||||
|
||||
interface UnsafeAs(Dest:! type) {
|
||||
fn Convert[self: Self]() -> Dest;
|
||||
fn Convert(self) -> Dest;
|
||||
}
|
||||
|
||||
interface As(Dest:! type) {
|
||||
// TODO: extend UnsafeAs(Dest);
|
||||
fn Convert[self: Self]() -> Dest;
|
||||
fn Convert(self) -> Dest;
|
||||
}
|
||||
|
||||
interface ImplicitAs(Dest:! type) {
|
||||
// TODO: extend As(Dest);
|
||||
fn Convert[self: Self]() -> Dest;
|
||||
fn Convert(self) -> Dest;
|
||||
}
|
||||
|
||||
interface BitAndWith(Other:! type) {
|
||||
fn Op[self: Self](other: Other) -> Self;
|
||||
fn Op(self, other: Other) -> Self;
|
||||
}
|
||||
|
||||
impl type as BitAndWith(type) {
|
||||
fn Op[self: Self](other: Self) -> Self = "type.and";
|
||||
fn Op(self, other: Self) -> Self = "type.and";
|
||||
}
|
||||
|
||||
@@ -18,5 +18,5 @@ class Char {
|
||||
}
|
||||
|
||||
impl CharLiteral as ImplicitAs(Char) {
|
||||
fn Convert[self: Self]() -> Char = "char.convert_checked";
|
||||
fn Convert(self) -> Char = "char.convert_checked";
|
||||
}
|
||||
|
||||
+11
-11
@@ -9,7 +9,7 @@ package Core library "prelude/parts/copy";
|
||||
// Copying an object, which is a conversion from a value representation to an
|
||||
// initializing representation.
|
||||
interface Copy {
|
||||
fn Op[self: Self]() -> Self;
|
||||
fn Op(self) -> Self;
|
||||
}
|
||||
|
||||
private fn MakeBool() -> type = "bool.make_type";
|
||||
@@ -22,45 +22,45 @@ private fn MakeIntLiteral() -> type = "int_literal.make_type";
|
||||
private alias IntLiteral = MakeIntLiteral();
|
||||
|
||||
impl forall [T:! Copy] const T as Copy {
|
||||
fn Op[self: Self]() -> Self { return (self as T).(Copy.Op)() as const T; }
|
||||
fn Op(self) -> Self { return (self as T).(Copy.Op)() as const T; }
|
||||
}
|
||||
|
||||
impl Bool as Copy {
|
||||
fn Op[self: Self]() -> Self = "primitive_copy";
|
||||
fn Op(self) -> Self = "primitive_copy";
|
||||
}
|
||||
|
||||
impl CharLiteral as Copy {
|
||||
fn Op[self: Self]() -> Self = "primitive_copy";
|
||||
fn Op(self) -> Self = "primitive_copy";
|
||||
}
|
||||
|
||||
impl FloatLiteral as Copy {
|
||||
fn Op[self: Self]() -> Self = "primitive_copy";
|
||||
fn Op(self) -> Self = "primitive_copy";
|
||||
}
|
||||
|
||||
impl IntLiteral as Copy {
|
||||
fn Op[self: Self]() -> Self = "primitive_copy";
|
||||
fn Op(self) -> Self = "primitive_copy";
|
||||
}
|
||||
|
||||
impl forall [T:! type] T* as Copy {
|
||||
fn Op[self: Self]() -> Self = "primitive_copy";
|
||||
fn Op(self) -> Self = "primitive_copy";
|
||||
}
|
||||
|
||||
impl type as Copy {
|
||||
fn Op[self: Self]() -> Self = "primitive_copy";
|
||||
fn Op(self) -> Self = "primitive_copy";
|
||||
}
|
||||
|
||||
impl () as Copy {
|
||||
fn Op[self: Self]() -> Self = "no_op";
|
||||
fn Op(self) -> Self = "no_op";
|
||||
}
|
||||
|
||||
impl forall [T:! Copy, U:! Copy] (T, U) as Copy {
|
||||
fn Op[self: Self]() -> Self {
|
||||
fn Op(self) -> Self {
|
||||
return (self.0.Op(), self.1.Op());
|
||||
}
|
||||
}
|
||||
|
||||
impl forall [T:! Copy, U:! Copy, V:! Copy] (T, U, V) as Copy {
|
||||
fn Op[self: Self]() -> Self {
|
||||
fn Op(self) -> Self {
|
||||
return (self.0.Op(), self.1.Op(), self.2.Op());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,12 +8,12 @@ package Core library "prelude/parts/destroy";
|
||||
|
||||
// TODO: Add `Destructor`, as in:
|
||||
// interface Destructor {
|
||||
// private fn Op[ref self: Self]();
|
||||
// private fn Op(ref self);
|
||||
// }
|
||||
|
||||
// Destroys objects. This will invoke `Destructor` impls recursively on members;
|
||||
// it does not deallocate memory.
|
||||
interface Destroy {
|
||||
// TODO: This should be `final fn Op[ref self: Self]() = "type.destroy"`.
|
||||
fn Op[ref self: Self]();
|
||||
// TODO: This should be `final fn Op(ref self) = "type.destroy"`.
|
||||
fn Op(ref self);
|
||||
}
|
||||
|
||||
@@ -23,14 +23,14 @@ class Float(N:! IntLiteral) {
|
||||
}
|
||||
|
||||
impl forall [N:! IntLiteral] Float(N) as Copy {
|
||||
fn Op[self: Self]() -> Self = "primitive_copy";
|
||||
fn Op(self) -> Self = "primitive_copy";
|
||||
}
|
||||
|
||||
impl forall [To:! IntLiteral] FloatLiteral as ImplicitAs(Float(To)) {
|
||||
fn Convert[self: Self]() -> Float(To) = "float.convert_checked";
|
||||
fn Convert(self) -> Float(To) = "float.convert_checked";
|
||||
}
|
||||
|
||||
// TODO: Remove this once ImplicitAs extends As.
|
||||
impl forall [To:! IntLiteral] FloatLiteral as As(Float(To)) {
|
||||
fn Convert[self: Self]() -> Float(To) = "float.convert_checked";
|
||||
fn Convert(self) -> Float(To) = "float.convert_checked";
|
||||
}
|
||||
|
||||
+6
-6
@@ -23,31 +23,31 @@ class Int(N:! IntLiteral) {
|
||||
// Copy.
|
||||
|
||||
impl forall [N:! IntLiteral] Int(N) as Copy {
|
||||
fn Op[self: Self]() -> Self = "primitive_copy";
|
||||
fn Op(self) -> Self = "primitive_copy";
|
||||
}
|
||||
|
||||
// Conversions.
|
||||
|
||||
impl forall [To:! IntLiteral] IntLiteral as ImplicitAs(Int(To)) {
|
||||
fn Convert[self: Self]() -> Int(To) = "int.convert_checked";
|
||||
fn Convert(self) -> Int(To) = "int.convert_checked";
|
||||
}
|
||||
|
||||
final impl forall [From:! IntLiteral] Int(From) as ImplicitAs(IntLiteral) {
|
||||
fn Convert[self: Self]() -> IntLiteral = "int.convert_checked";
|
||||
fn Convert(self) -> IntLiteral = "int.convert_checked";
|
||||
}
|
||||
|
||||
// TODO: Remove these once ImplicitAs extends As.
|
||||
impl forall [To:! IntLiteral] IntLiteral as As(Int(To)) {
|
||||
fn Convert[self: Self]() -> Int(To) = "int.convert_checked";
|
||||
fn Convert(self) -> Int(To) = "int.convert_checked";
|
||||
}
|
||||
|
||||
final impl forall [From:! IntLiteral] Int(From) as As(IntLiteral) {
|
||||
fn Convert[self: Self]() -> IntLiteral = "int.convert_checked";
|
||||
fn Convert(self) -> IntLiteral = "int.convert_checked";
|
||||
}
|
||||
|
||||
// Negate.
|
||||
|
||||
final impl forall [N:! IntLiteral]
|
||||
Int(N) as Negate where .Result = Self {
|
||||
fn Op[self: Self]() -> Self = "int.snegate";
|
||||
fn Op(self) -> Self = "int.snegate";
|
||||
}
|
||||
|
||||
@@ -13,9 +13,9 @@ alias IntLiteral = MakeIntLiteral();
|
||||
|
||||
interface Negate {
|
||||
let Result:! type;
|
||||
fn Op[self: Self]() -> Result;
|
||||
fn Op(self) -> Result;
|
||||
}
|
||||
|
||||
impl IntLiteral as Negate where .Result = Self {
|
||||
fn Op[self: Self]() -> Self = "int.snegate";
|
||||
fn Op(self) -> Self = "int.snegate";
|
||||
}
|
||||
|
||||
@@ -15,6 +15,6 @@ import library "prelude/parts/optional";
|
||||
interface Iterate {
|
||||
let ElementType:! Copy;
|
||||
let CursorType:! type;
|
||||
fn NewCursor[self: Self]() -> CursorType;
|
||||
fn Next[self: Self](cursor: CursorType*) -> Optional(ElementType);
|
||||
fn NewCursor(self) -> CursorType;
|
||||
fn Next(self, cursor: CursorType*) -> Optional(ElementType);
|
||||
}
|
||||
|
||||
@@ -27,8 +27,8 @@ class Optional(T:! Copy) {
|
||||
return {.has_value = true, .value = value};
|
||||
}
|
||||
|
||||
fn HasValue[self: Self]() -> bool { return self.has_value; }
|
||||
fn Get[self: Self]() -> T { return self.value; }
|
||||
fn HasValue(self) -> bool { return self.has_value; }
|
||||
fn Get(self) -> T { return self.value; }
|
||||
|
||||
var has_value: bool;
|
||||
var value: T;
|
||||
|
||||
@@ -23,31 +23,31 @@ class UInt(N:! IntLiteral) {
|
||||
// Copy.
|
||||
|
||||
impl forall [N:! IntLiteral] UInt(N) as Copy {
|
||||
fn Op[self: Self]() -> Self = "primitive_copy";
|
||||
fn Op(self) -> Self = "primitive_copy";
|
||||
}
|
||||
|
||||
// Conversions.
|
||||
|
||||
impl forall [To:! IntLiteral] IntLiteral as ImplicitAs(UInt(To)) {
|
||||
fn Convert[self: Self]() -> UInt(To) = "int.convert_checked";
|
||||
fn Convert(self) -> UInt(To) = "int.convert_checked";
|
||||
}
|
||||
|
||||
final impl forall [From:! IntLiteral] UInt(From) as ImplicitAs(IntLiteral) {
|
||||
fn Convert[self: Self]() -> IntLiteral = "int.convert_checked";
|
||||
fn Convert(self) -> IntLiteral = "int.convert_checked";
|
||||
}
|
||||
|
||||
// TODO: Remove these once ImplicitAs extends As.
|
||||
impl forall [To:! IntLiteral] IntLiteral as As(UInt(To)) {
|
||||
fn Convert[self: Self]() -> UInt(To) = "int.convert_checked";
|
||||
fn Convert(self) -> UInt(To) = "int.convert_checked";
|
||||
}
|
||||
|
||||
final impl forall [From:! IntLiteral] UInt(From) as As(IntLiteral) {
|
||||
fn Convert[self: Self]() -> IntLiteral = "int.convert_checked";
|
||||
fn Convert(self) -> IntLiteral = "int.convert_checked";
|
||||
}
|
||||
|
||||
// Negate.
|
||||
|
||||
final impl forall [N:! IntLiteral]
|
||||
UInt(N) as Negate where .Result = Self {
|
||||
fn Op[self: Self]() -> Self = "int.unegate";
|
||||
fn Op(self) -> Self = "int.unegate";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user