carbon-lang
carbon-lang copied to clipboard
tracking issue: new approach for representing intrinsics in explorer
In discussion with @jonmeow, I had some concerns about how we're modeling intrinsics in explorer. Specifically, I didn't want for us to end up with a large catalogue of predeclared functions with __special_names, due to the complexity and cost associated with this approach in Clang.
As an alternative, we both seemed to like introducing intrinsics with function declarations with some kind of annotation on them. For example:
// With some kind of attribute syntax (not yet designed).
impl i32 as Add {
@Builtin("int_add")
fn Op[me: i32](rhs: i32) -> i32;
}
// With some kind of special-case syntax.
impl i32 as Add {
fn Op[me: i32](rhs: i32) -> i32 __intrinsic_body("int_add");
}
I prefer the @Builtin approach, due to its generality: we can use the same approach to mark builtin interfaces (such as AddWith) instead of matching them by name, and similarly for any other kinds of declaration that have special meaning to the implementation, such as Carbon.Int.
For the time being we agreed to use an approximation of the above approach using explorer's existing __intrinsic support:
impl i32 as Add {
fn Op[me: i32](rhs: i32) -> i32 { return __intrinsic_int_add(me, rhs); }
}
This issue tracks the progress of the new approach described above. Task list:
- [ ] Add some syntax to explorer to mark a function as a builtin.
- [ ] Switch existing intrinsics and the prelude over to the new syntax.
- [ ] Remove existing
__intrinsicmechanism in explorer. - [ ] Propose attribute syntax.
- [ ] Propose a
Builtinattribute or similar.
I worry a bit about the use of a string to identify the intrinsic as opposed to the explicit intrinsic_xxx syntax. I think it would be too easy to make a typo and have it not be caught early.
I appreciate the concern about the number of intrinsics we might end up with but perhaps there is a compromise where we use an enum as opposed to a string for the lookup? at least something that can provide some type safety.
We should be able to validate the string literal at compile time during semantic analysis, which is where we currently validate __intrinsic_xxx names, so in practice I don't think there'll be much difference. (We'll also want the compiler to look up the intrinsic and validate that the declaration of the function matches the expected one for the given kind, giving a bit more safety.)