mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 07:21:04 +01:00
This is already allowed as a builtin conversion, but the impl allows the generics system to know about it, so that conversions like `Optional(T*)` to `Optional(const T*)` are allowed. This in turn allows a C++ `T*` to be implicitly converted to a C++ `const T*` in Carbon code.
65 lines
2.0 KiB
Plaintext
65 lines
2.0 KiB
Plaintext
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
|
// Exceptions. See /LICENSE for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
package Core library "prelude/operators/as";
|
|
|
|
import library "prelude/copy";
|
|
|
|
interface UnsafeAs(Dest:! type) {
|
|
fn Convert[self: Self]() -> Dest;
|
|
}
|
|
|
|
interface As(Dest:! type) {
|
|
// TODO: extend UnsafeAs(Dest);
|
|
fn Convert[self: Self]() -> Dest;
|
|
}
|
|
|
|
interface ImplicitAs(Dest:! type) {
|
|
// TODO: extend As(Dest);
|
|
fn Convert[self: Self]() -> Dest;
|
|
}
|
|
|
|
// Workaround: ImplicitAs extends As.
|
|
impl forall [U:! type, T:! ImplicitAs(U)] T as As(U) {
|
|
fn Convert[self: Self]() -> U { return self.Convert(); }
|
|
}
|
|
|
|
// Workaround: As extends UnsafeAs.
|
|
impl forall [U:! type, T:! As(U)] T as UnsafeAs(U) {
|
|
fn Convert[self: Self]() -> U { return self.Convert(); }
|
|
}
|
|
|
|
// Copyable types have an identity conversion that performs a copy.
|
|
impl forall [T:! Copy] T as ImplicitAs(T) {
|
|
fn Convert[self: Self]() -> Self { return self.(Copy.Op)(); }
|
|
}
|
|
|
|
// `const` can be added and removed when converting a value.
|
|
impl forall [T:! type, U:! ImplicitAs(T)] U as ImplicitAs(const T) {
|
|
fn Convert[self: U]() -> const T { return self.Convert(); }
|
|
}
|
|
|
|
impl forall [T:! type, U:! ImplicitAs(T)] const U as ImplicitAs(T) {
|
|
fn Convert[self: const U]() -> T { return (self as U).Convert(); }
|
|
}
|
|
|
|
// `const` can be added to a pointer.
|
|
// TODO: This is also provided as a builtin conversion. We provide it here so
|
|
// that Optional(T*) can implicitly convert to Optional(const T*). See #5750.
|
|
impl forall [T:! type] T* as ImplicitAs(const T*) {
|
|
fn Convert[self: T*]() -> const T* = "pointer.unsafe_convert";
|
|
}
|
|
|
|
impl forall [T:! type] T* as As(const T*) {
|
|
fn Convert[self: T*]() -> const T* = "pointer.unsafe_convert";
|
|
}
|
|
|
|
// Pointer types can be unsafely cast to other pointer types.
|
|
// TODO: Should `unsafe as` be able to remove `const`?
|
|
impl forall [T:! type, U:! type] T* as UnsafeAs(U*) {
|
|
fn Convert[self: T*]() -> U* = "pointer.unsafe_convert";
|
|
}
|
|
|
|
interface IntFitsIn(Dest:! type) {}
|