Skip to content

Commit

Permalink
StarlarkTypeRepr::Canonical
Browse files Browse the repository at this point in the history
Summary:
If `A` and `B` represent the same starlark type, `A::Canonical == B::Canonical`. For example `String::Canonical == <&str>::Canonical`.

This is useful with `ValueOfUnchecked::cast` in D59380757.

This diff unfortunately makes starlark API harder to use.

It would be better if we had [`associated_type_defaults`](rust-lang/rust#29661), but that won't happen soon.

Reviewed By: JakobDegen

Differential Revision: D59380699

fbshipit-source-id: 8b658203c2d46cd03ac722170ba3858d19eee001
  • Loading branch information
stepancheg authored and facebook-github-bot committed Jul 6, 2024
1 parent dd0e519 commit 42c2174
Show file tree
Hide file tree
Showing 44 changed files with 179 additions and 7 deletions.
4 changes: 4 additions & 0 deletions starlark/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ macro_rules! starlark_complex_value {
}

impl<'v> $crate::values::type_repr::StarlarkTypeRepr for &'v $x<'v> {
type Canonical = $x<'v>;

#[inline]
fn starlark_type_repr() -> $crate::typing::Ty {
<$x as $crate::values::StarlarkValue>::get_type_starlark_repr()
Expand Down Expand Up @@ -197,6 +199,8 @@ macro_rules! starlark_simple_value {
}

impl<'v> $crate::values::type_repr::StarlarkTypeRepr for &'v $x {
type Canonical = $x;

fn starlark_type_repr() -> $crate::typing::Ty {
<$x as $crate::values::StarlarkValue>::get_type_starlark_repr()
}
Expand Down
12 changes: 12 additions & 0 deletions starlark/src/stdlib/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,16 @@ use crate::values::Heap;
use crate::values::Value;

impl StarlarkTypeRepr for serde_json::Number {
type Canonical = Either<i32, f64>;

fn starlark_type_repr() -> Ty {
Either::<i32, f64>::starlark_type_repr()
}
}

impl<'a> StarlarkTypeRepr for &'a serde_json::Number {
type Canonical = serde_json::Number;

fn starlark_type_repr() -> Ty {
serde_json::Number::starlark_type_repr()
}
Expand Down Expand Up @@ -99,12 +103,16 @@ impl AllocFrozenValue for serde_json::Number {
}

impl<'a, K: StarlarkTypeRepr, V: StarlarkTypeRepr> StarlarkTypeRepr for &'a serde_json::Map<K, V> {
type Canonical = <serde_json::Map<K, V> as StarlarkTypeRepr>::Canonical;

fn starlark_type_repr() -> Ty {
AllocDict::<SmallMap<K, V>>::starlark_type_repr()
}
}

impl<K: StarlarkTypeRepr, V: StarlarkTypeRepr> StarlarkTypeRepr for serde_json::Map<K, V> {
type Canonical = <SmallMap<K, V> as StarlarkTypeRepr>::Canonical;

fn starlark_type_repr() -> Ty {
AllocDict::<SmallMap<K, V>>::starlark_type_repr()
}
Expand Down Expand Up @@ -141,13 +149,17 @@ impl AllocFrozenValue for serde_json::Map<String, serde_json::Value> {
}

impl<'a> StarlarkTypeRepr for &'a serde_json::Value {
type Canonical = <serde_json::Value as StarlarkTypeRepr>::Canonical;

fn starlark_type_repr() -> Ty {
// Any.
Value::starlark_type_repr()
}
}

impl StarlarkTypeRepr for serde_json::Value {
type Canonical = <FrozenValue as StarlarkTypeRepr>::Canonical;

fn starlark_type_repr() -> Ty {
// Any.
Value::starlark_type_repr()
Expand Down
2 changes: 2 additions & 0 deletions starlark/src/values/layout/complex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ where
T: ComplexValue<'v>,
T::Frozen: StarlarkValue<'static>,
{
type Canonical = <T as StarlarkTypeRepr>::Canonical;

fn starlark_type_repr() -> Ty {
T::starlark_type_repr()
}
Expand Down
4 changes: 4 additions & 0 deletions starlark/src/values/layout/typed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,8 @@ impl<'v, T: StarlarkValue<'v>> Deref for ValueTyped<'v, T> {
}

impl<'v, T: StarlarkValue<'v>> StarlarkTypeRepr for ValueTyped<'v, T> {
type Canonical = <T as StarlarkTypeRepr>::Canonical;

fn starlark_type_repr() -> Ty {
T::starlark_type_repr()
}
Expand Down Expand Up @@ -377,6 +379,8 @@ impl<'v> AllocStringValue<'v> for StringValue<'v> {
}

impl<'v, T: StarlarkValue<'v>> StarlarkTypeRepr for FrozenValueTyped<'v, T> {
type Canonical = <T as StarlarkTypeRepr>::Canonical;

fn starlark_type_repr() -> Ty {
T::starlark_type_repr()
}
Expand Down
4 changes: 4 additions & 0 deletions starlark/src/values/layout/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1137,12 +1137,16 @@ impl Serialize for FrozenValue {
}

impl<'v> StarlarkTypeRepr for Value<'v> {
type Canonical = <FrozenValue as StarlarkTypeRepr>::Canonical;

fn starlark_type_repr() -> Ty {
FrozenValue::starlark_type_repr()
}
}

impl StarlarkTypeRepr for FrozenValue {
type Canonical = Self;

fn starlark_type_repr() -> Ty {
Ty::any()
}
Expand Down
2 changes: 2 additions & 0 deletions starlark/src/values/owned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ impl Display for OwnedFrozenValue {
}

impl StarlarkTypeRepr for OwnedFrozenValue {
type Canonical = <FrozenValue as StarlarkTypeRepr>::Canonical;

fn starlark_type_repr() -> Ty {
FrozenValue::starlark_type_repr()
}
Expand Down
25 changes: 25 additions & 0 deletions starlark/src/values/type_repr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,17 @@ use crate::values::Value;
///
/// This derive is useful in combination with derive of [`UnpackValue`](crate::values::UnpackValue).
pub trait StarlarkTypeRepr {
/// Different Rust type representing the same Starlark Type.
///
/// For example, `bool` and `StarlarkBool` Rust types represent the same Starlark type `bool`.
///
/// Formal requirement: `Self::starlark_type_repr() == Self::Canonical::starlark_type_repr()`.
///
/// If unsure, it is safe to put `= Self` here.
/// When [`associated_type_defaults`](https://github.com/rust-lang/rust/issues/29661)
/// is stabilized, this will be the default.
type Canonical: StarlarkTypeRepr;

/// The representation of a type that a user would use verbatim in starlark type annotations
fn starlark_type_repr() -> Ty;
}
Expand All @@ -64,42 +75,56 @@ pub struct DictType<K: StarlarkTypeRepr, V: StarlarkTypeRepr> {
}

impl<K: StarlarkTypeRepr, V: StarlarkTypeRepr> StarlarkTypeRepr for DictType<K, V> {
type Canonical = DictType<K::Canonical, V::Canonical>;

fn starlark_type_repr() -> Ty {
Ty::dict(K::starlark_type_repr(), V::starlark_type_repr())
}
}

impl<'v, T: StarlarkValue<'v> + ?Sized> StarlarkTypeRepr for T {
type Canonical = Self;

fn starlark_type_repr() -> Ty {
Self::get_type_starlark_repr()
}
}

impl StarlarkTypeRepr for String {
type Canonical = StarlarkStr;

fn starlark_type_repr() -> Ty {
StarlarkStr::starlark_type_repr()
}
}

impl StarlarkTypeRepr for &str {
type Canonical = StarlarkStr;

fn starlark_type_repr() -> Ty {
StarlarkStr::starlark_type_repr()
}
}

impl<T: StarlarkTypeRepr> StarlarkTypeRepr for Option<T> {
type Canonical = <Either<NoneType, T> as StarlarkTypeRepr>::Canonical;

fn starlark_type_repr() -> Ty {
Either::<NoneType, T>::starlark_type_repr()
}
}

impl<T: StarlarkTypeRepr> StarlarkTypeRepr for Vec<T> {
type Canonical = Vec<T::Canonical>;

fn starlark_type_repr() -> Ty {
Ty::list(T::starlark_type_repr())
}
}

impl<TLeft: StarlarkTypeRepr, TRight: StarlarkTypeRepr> StarlarkTypeRepr for Either<TLeft, TRight> {
type Canonical = Either<TLeft::Canonical, TRight::Canonical>;

fn starlark_type_repr() -> Ty {
Ty::union2(TLeft::starlark_type_repr(), TRight::starlark_type_repr())
}
Expand Down
12 changes: 12 additions & 0 deletions starlark/src/values/types/bigint/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ use crate::values::UnpackValue;
use crate::values::Value;

impl StarlarkTypeRepr for u32 {
type Canonical = <i32 as StarlarkTypeRepr>::Canonical;

fn starlark_type_repr() -> Ty {
i32::starlark_type_repr()
}
Expand All @@ -50,6 +52,8 @@ impl AllocFrozenValue for u32 {
}

impl StarlarkTypeRepr for u64 {
type Canonical = <i32 as StarlarkTypeRepr>::Canonical;

fn starlark_type_repr() -> Ty {
i32::starlark_type_repr()
}
Expand All @@ -70,6 +74,8 @@ impl AllocFrozenValue for u64 {
}

impl StarlarkTypeRepr for i64 {
type Canonical = <i32 as StarlarkTypeRepr>::Canonical;

fn starlark_type_repr() -> Ty {
i32::starlark_type_repr()
}
Expand All @@ -90,6 +96,8 @@ impl AllocFrozenValue for i64 {
}

impl StarlarkTypeRepr for usize {
type Canonical = <i32 as StarlarkTypeRepr>::Canonical;

fn starlark_type_repr() -> Ty {
i32::starlark_type_repr()
}
Expand All @@ -110,6 +118,8 @@ impl AllocFrozenValue for usize {
}

impl StarlarkTypeRepr for isize {
type Canonical = <i32 as StarlarkTypeRepr>::Canonical;

fn starlark_type_repr() -> Ty {
i32::starlark_type_repr()
}
Expand All @@ -130,6 +140,8 @@ impl AllocFrozenValue for isize {
}

impl StarlarkTypeRepr for BigInt {
type Canonical = <i32 as StarlarkTypeRepr>::Canonical;

fn starlark_type_repr() -> Ty {
i32::starlark_type_repr()
}
Expand Down
6 changes: 4 additions & 2 deletions starlark/src/values/types/bool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ use crate::values::ValueError;
/// The result of calling `type()` on booleans.
pub const BOOL_TYPE: &str = "bool";

// We have to alias bool so we can have a Display that uses True/False.
/// `bool` value.
#[derive(ProvidesStaticType, Debug, Serialize, StarlarkDocs, Allocative)]
#[starlark_docs(builtin = "standard")]
#[serde(transparent)]
pub(crate) struct StarlarkBool(pub(crate) bool);
pub struct StarlarkBool(pub(crate) bool);

impl Display for StarlarkBool {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Expand Down Expand Up @@ -88,6 +88,8 @@ impl AllocFrozenValue for bool {
}

impl StarlarkTypeRepr for bool {
type Canonical = <StarlarkBool as StarlarkTypeRepr>::Canonical;

fn starlark_type_repr() -> Ty {
StarlarkBool::get_type_starlark_repr()
}
Expand Down
2 changes: 2 additions & 0 deletions starlark/src/values/types/dict/alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ where
K: StarlarkTypeRepr,
V: StarlarkTypeRepr,
{
type Canonical = DictType<K::Canonical, V::Canonical>;

fn starlark_type_repr() -> Ty {
DictType::<K, V>::starlark_type_repr()
}
Expand Down
2 changes: 2 additions & 0 deletions starlark/src/values/types/dict/of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ impl<'v, K: UnpackValue<'v> + Hash + Eq, V: UnpackValue<'v>> DictOf<'v, K, V> {
}

impl<'v, K: UnpackValue<'v>, V: UnpackValue<'v>> StarlarkTypeRepr for DictOf<'v, K, V> {
type Canonical = <DictType<K, V> as StarlarkTypeRepr>::Canonical;

fn starlark_type_repr() -> Ty {
DictType::<K, V>::starlark_type_repr()
}
Expand Down
5 changes: 4 additions & 1 deletion starlark/src/values/types/dict/refs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use crate::typing::Ty;
use crate::values::dict::value::DictGen;
use crate::values::dict::value::FrozenDictData;
use crate::values::dict::Dict;
use crate::values::type_repr::DictType;
use crate::values::type_repr::StarlarkTypeRepr;
use crate::values::FrozenValue;
use crate::values::UnpackValue;
Expand Down Expand Up @@ -153,8 +154,10 @@ impl<'v> DerefMut for DictMut<'v> {
}

impl<'v> StarlarkTypeRepr for DictRef<'v> {
type Canonical = <DictType<FrozenValue, FrozenValue> as StarlarkTypeRepr>::Canonical;

fn starlark_type_repr() -> Ty {
Dict::<'v>::starlark_type_repr()
DictType::<FrozenValue, FrozenValue>::starlark_type_repr()
}
}

Expand Down
8 changes: 8 additions & 0 deletions starlark/src/values/types/dict/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,16 @@ where
}

impl<'a, K: StarlarkTypeRepr, V: StarlarkTypeRepr> StarlarkTypeRepr for &'a SmallMap<K, V> {
type Canonical = <SmallMap<K, V> as StarlarkTypeRepr>::Canonical;

fn starlark_type_repr() -> Ty {
DictType::<K, V>::starlark_type_repr()
}
}

impl<K: StarlarkTypeRepr, V: StarlarkTypeRepr> StarlarkTypeRepr for SmallMap<K, V> {
type Canonical = <DictType<K, V> as StarlarkTypeRepr>::Canonical;

fn starlark_type_repr() -> Ty {
DictType::<K, V>::starlark_type_repr()
}
Expand Down Expand Up @@ -131,12 +135,16 @@ where
}

impl<'a, K: StarlarkTypeRepr, V: StarlarkTypeRepr> StarlarkTypeRepr for &'a BTreeMap<K, V> {
type Canonical = <BTreeMap<K, V> as StarlarkTypeRepr>::Canonical;

fn starlark_type_repr() -> Ty {
DictType::<K, V>::starlark_type_repr()
}
}

impl<K: StarlarkTypeRepr, V: StarlarkTypeRepr> StarlarkTypeRepr for BTreeMap<K, V> {
type Canonical = <DictType<K, V> as StarlarkTypeRepr>::Canonical;

fn starlark_type_repr() -> Ty {
DictType::<K, V>::starlark_type_repr()
}
Expand Down
5 changes: 5 additions & 0 deletions starlark/src/values/types/dict/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ use crate::values::layout::avalue::AValueImpl;
use crate::values::layout::avalue::AValueSimple;
use crate::values::layout::heap::repr::AValueRepr;
use crate::values::string::str_type::hash_string_value;
use crate::values::type_repr::DictType;
use crate::values::type_repr::StarlarkTypeRepr;
use crate::values::AllocFrozenValue;
use crate::values::AllocValue;
Expand Down Expand Up @@ -103,6 +104,8 @@ pub struct Dict<'v> {
}

impl<'v> StarlarkTypeRepr for Dict<'v> {
type Canonical = <DictType<FrozenValue, FrozenValue> as StarlarkTypeRepr>::Canonical;

fn starlark_type_repr() -> Ty {
DictOf::<Value<'v>, Value<'v>>::starlark_type_repr()
}
Expand Down Expand Up @@ -135,6 +138,8 @@ impl<'v> AllocValue<'v> for Dict<'v> {
}

impl StarlarkTypeRepr for FrozenDictData {
type Canonical = <DictType<FrozenValue, FrozenValue> as StarlarkTypeRepr>::Canonical;

fn starlark_type_repr() -> Ty {
Ty::dict(Ty::any(), Ty::any())
}
Expand Down
2 changes: 2 additions & 0 deletions starlark/src/values/types/float.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,8 @@ impl StarlarkFloat {
}

impl StarlarkTypeRepr for f64 {
type Canonical = <StarlarkFloat as StarlarkTypeRepr>::Canonical;

fn starlark_type_repr() -> Ty {
StarlarkFloat::starlark_type_repr()
}
Expand Down
2 changes: 2 additions & 0 deletions starlark/src/values/types/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ pub const FUNCTION_TYPE: &str = "function";
pub(crate) enum StarlarkFunction {}

impl StarlarkTypeRepr for StarlarkFunction {
type Canonical = Self;

fn starlark_type_repr() -> Ty {
Ty::any_callable()
}
Expand Down
Loading

0 comments on commit 42c2174

Please sign in to comment.