starlark/values/
traits.rs

1/*
2 * Copyright 2018 The Starlark in Rust Authors.
3 * Copyright (c) Facebook, Inc. and its affiliates.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *     https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18//! The values module define a trait `StarlarkValue` that defines the attribute of
19//! any value in Starlark and a few macro to help implementing this trait.
20//! The `Value` struct defines the actual structure holding a StarlarkValue. It is
21//! mostly used to enable mutable and Rc behavior over a StarlarkValue.
22//! This modules also defines this traits for the basic immutable values: int,
23//! bool and NoneType. Sub-modules implement other common types of all Starlark
24//! dialect.
25//!
26//! __Note__: we use _sequence_, _iterable_ and _indexable_ according to the
27//! definition in the [Starlark specification](
28//! https://github.com/bazelbuild/starlark/blob/master/spec.md#sequence-types).
29//! We also use the term _container_ for denoting any of those type that can
30//! hold several values.
31
32use std::cmp::Ordering;
33use std::fmt::Debug;
34use std::fmt::Display;
35use std::fmt::Write;
36
37use allocative::Allocative;
38use erased_serde::Serialize;
39use starlark_derive::starlark_internal_vtable;
40use starlark_map::StarlarkHashValue;
41
42use crate::any::ProvidesStaticType;
43use crate::collections::Hashed;
44use crate::collections::StarlarkHasher;
45use crate::docs::DocItem;
46use crate::docs::DocMember;
47use crate::docs::DocProperty;
48use crate::environment::Methods;
49use crate::eval::Arguments;
50use crate::eval::Evaluator;
51use crate::private::Private;
52use crate::typing::Ty;
53use crate::typing::TyBasic;
54use crate::typing::TypingBinOp;
55use crate::values::demand::Demand;
56use crate::values::error::ControlError;
57use crate::values::function::FUNCTION_TYPE;
58use crate::values::Freeze;
59use crate::values::FrozenStringValue;
60use crate::values::FrozenValue;
61use crate::values::Heap;
62use crate::values::Trace;
63use crate::values::Value;
64use crate::values::ValueError;
65
66/// A trait for values which are more complex - because they are either mutable
67/// (e.g. using [`RefCell`](std::cell::RefCell)), or contain references to other values.
68///
69/// For values that contain nested [`Value`] types (mutable or not) there are a bunch of helpers
70/// and macros.
71///
72/// ## Types containing [`Value`]
73///
74/// A Starlark type containing values will need to exist in two states: one containing [`Value`]
75/// and one containing [`FrozenValue`](crate::values::FrozenValue). To deal with that, if we are defining the type
76/// containing a single value, let's call it `One`, we'd define `OneGen`
77/// (for the general version), and then have the
78/// [`starlark_complex_value!`](crate::starlark_complex_value!) macro
79/// generate `One` and `FrozenOne` aliases.
80///
81/// ```
82/// use allocative::Allocative;
83/// use derive_more::Display;
84/// use starlark::starlark_complex_value;
85/// use starlark::values::Coerce;
86/// use starlark::values::ComplexValue;
87/// use starlark::values::Freeze;
88/// use starlark::values::FreezeResult;
89/// use starlark::values::Freezer;
90/// use starlark::values::FrozenValue;
91/// use starlark::values::NoSerialize;
92/// use starlark::values::ProvidesStaticType;
93/// use starlark::values::StarlarkValue;
94/// use starlark::values::Trace;
95/// use starlark::values::Tracer;
96/// use starlark::values::Value;
97/// use starlark::values::ValueLike;
98/// use starlark_derive::starlark_value;
99///
100/// #[derive(
101///     Debug,
102///     Trace,
103///     Coerce,
104///     Display,
105///     ProvidesStaticType,
106///     NoSerialize,
107///     Allocative
108/// )]
109/// #[repr(C)]
110/// struct OneGen<V>(V);
111/// starlark_complex_value!(One);
112///
113/// #[starlark_value(type = "one")]
114/// impl<'v, V: ValueLike<'v>> StarlarkValue<'v> for OneGen<V>
115/// where
116///     Self: ProvidesStaticType<'v>,
117/// {
118///     // To implement methods which work for both `One` and `FrozenOne`,
119///     // use the `ValueLike` trait.
120/// }
121///
122/// impl<'v> Freeze for One<'v> {
123///     type Frozen = FrozenOne;
124///     fn freeze(self, freezer: &Freezer) -> FreezeResult<Self::Frozen> {
125///         Ok(OneGen(self.0.freeze(freezer)?))
126///     }
127/// }
128/// ```
129///
130/// The [`starlark_complex_value!`](crate::starlark_complex_value!) requires that
131/// the type have an instance for `Coerce`, then the macro defines two type aliases.
132/// ```
133/// # use crate::starlark::values::*;
134/// # #[derive(Debug, Trace)]
135/// # struct OneGen<V>(V);
136/// type One<'v> = OneGen<Value<'v>>;
137/// type FrozenOne = OneGen<FrozenValue>;
138/// ```
139///
140/// To make these aliases public (or public to the crate) pass a visibility
141/// to the macro, e.g. `starlark_complex_value!(pub One)`.
142///
143/// The macro also defines instances of [`ProvidesStaticType`] for both,
144/// [`AllocValue`](crate::values::AllocValue) for both,
145/// [`AllocFrozenValue`](crate::values::AllocFrozenValue) for the frozen one, and
146/// [`UnpackValue`](crate::values::UnpackValue) for the non-frozen one.
147/// It also defines the methods:
148/// ```
149/// # use crate::starlark::values::*;
150/// # use std::cell::RefMut;
151/// # struct OneGen<V>(V);
152/// # type One<'v> = OneGen<Value<'v>>;
153/// impl<'v> One<'v> {
154///     // Obtain a reference to `One` from a `Value`, regardless
155///     // of whether the underlying `Value` is a `One` or `FrozenOne`.
156///     pub fn from_value(x: Value<'v>) -> Option<&'v Self> {
157/// # unimplemented!(
158/// # r#"
159///         ...
160/// # "#);
161///     }
162/// }
163/// ```
164///
165/// ## Different types
166///
167/// If the types are different between the frozen and non-frozen values you can define your own
168/// type specialisations as `type One<'v> = OneGen<Value<'v>>` and `type FrozenOne = OneGen<String>`
169/// and use [`starlark_complex_values!`](crate::starlark_complex_values!) which will provide similar facilities to
170/// [`starlark_complex_value!`](crate::starlark_simple_value!).
171///
172/// ## Other types
173///
174/// The macro [`starlark_complex_value!`](crate::starlark_complex_value!) is applicable
175/// when there is a single base type, `FooGen<V>`, with specialisations
176/// `FooGen<Value<'v>>` and `FooGen<FrozenValue>`.
177/// If you have a type where the difference between frozen and non-frozen does not follow this
178/// pattern then you will have to write instances of the traits you need manually.
179/// Examples of cases where the macro doesn't work include:
180///
181/// * If your type doesn't contain any [`Value`] types, but instead implements this trait for mutability.
182/// * If the difference between frozen and non-frozen is more complex, e.g. a [`Cell`](std::cell::Cell)
183///   when non-frozen and a direct value when frozen.
184pub trait ComplexValue<'v>: StarlarkValue<'v> + Trace<'v> + Freeze
185where
186    <Self as Freeze>::Frozen: StarlarkValue<'static>,
187{
188}
189
190impl<'v, V> ComplexValue<'v> for V
191where
192    V: StarlarkValue<'v> + Trace<'v> + Freeze,
193    <V as Freeze>::Frozen: StarlarkValue<'static>,
194{
195}
196
197/// How to put a Rust values into [`Value`]s.
198///
199/// Every Rust value stored in a [`Value`] must implement this trait.
200/// You _must_ also implement [`ComplexValue`] if:
201///
202/// * A type is not [`Send`] and [`Sync`], typically because it contains
203///   interior mutability such as a [`RefCell`](std::cell::RefCell).
204/// * A type contains nested Starlark [`Value`]s.
205///
206/// There are only two required members of [`StarlarkValue`], namely
207/// [`TYPE`](StarlarkValue::TYPE)
208/// and [`get_type_value_static`](StarlarkValue::get_type_value_static).
209/// Both these should be implemented with the [`starlark_value`](crate::values::starlark_value)
210/// proc macro:
211///
212/// ```
213/// use allocative::Allocative;
214/// # use starlark::starlark_simple_value;
215/// use derive_more::Display;
216/// use starlark::values::NoSerialize;
217/// use starlark::values::ProvidesStaticType;
218/// use starlark::values::StarlarkValue;
219/// use starlark_derive::starlark_value;
220///
221/// #[derive(Debug, Display, ProvidesStaticType, NoSerialize, Allocative)]
222/// #[display("Foo")]
223/// struct Foo;
224/// # starlark_simple_value!(Foo);
225/// #[starlark_value(type = "foo")]
226/// impl<'v> StarlarkValue<'v> for Foo {}
227/// ```
228///
229/// Every additional field enables further features in Starlark. In most cases the default
230/// implementation returns an "unimplemented" [`Err`].
231///
232/// # Note To Implementors
233/// Any additional methods that are added to this trait also need to be added to the
234/// [`StarlarkValue`] implementation in `crate::values::layout::avalue::Wrapper`. Otherwise,
235/// any implementations other than the default implementation will not be run.
236#[starlark_internal_vtable]
237#[allow(non_upper_case_globals, non_snake_case)] // For generated members.
238pub trait StarlarkValue<'v>:
239    'v + ProvidesStaticType<'v> + Allocative + Debug + Display + Serialize + Sized
240{
241    /// Two implementations of `StarlarkValue` are considered to have the same type,
242    /// if `Canonical` field points to the same type.
243    ///
244    /// This field is generated by `#[starlark_value]` proc macro by default
245    /// when proc macro can infer the type, otherwise this implementation cannot serve as a type.
246    // Using qualified path here because proc macro erases the type.
247    type Canonical: StarlarkValue<'v> = Self;
248
249    /// Return a string describing the type of self, as returned by the type()
250    /// function.
251    ///
252    /// This can be only implemented by the [`#[starlark_value]`](crate::values::starlark_value)
253    /// proc macro.
254    const TYPE: &'static str = panic!("This field is implemented by #[starlark_value] proc macro");
255
256    /// Like [`TYPE`](Self::TYPE), but returns a reusable [`FrozenStringValue`]
257    /// pointer to it. This function deliberately doesn't take a heap,
258    /// as it would not be performant to allocate a new value each time.
259    ///
260    /// This can be only implemented by the [`#[starlark_value]`](crate::values::starlark_value)
261    /// proc macro.
262    fn get_type_value_static() -> FrozenStringValue {
263        panic!("This function is implemented by #[starlark_value] proc macro")
264    }
265
266    /// Return a string that is the representation of a type that a user would use in
267    /// type annotations. This often will be the same as [`Self::TYPE`], but in
268    /// some instances it might be slightly different than what is returned by `TYPE`.
269    ///
270    /// This can be only implemented by the [`#[starlark_value]`](crate::values::starlark_value)
271    /// proc macro.
272    fn get_type_starlark_repr() -> Ty {
273        Ty::starlark_value::<Self>()
274    }
275
276    /// Please do not implement this method or `get_type`,
277    /// but use [`#[starlark_value]`](crate::values::starlark_value) proc macro.
278    #[doc(hidden)]
279    #[starlark_internal_vtable(skip)]
280    fn please_use_starlark_type_macro() {
281        panic!("This function is implemented by #[starlark_value] proc macro")
282    }
283
284    /// Type is special in Starlark, it is implemented differently than user defined types.
285    /// For example, some special types like `bool` cannon be heap allocated.
286    ///
287    /// This function must not be implemented outside of starlark crate.
288    #[doc(hidden)]
289    #[starlark_internal_vtable(skip)]
290    fn is_special(_private: Private) -> bool {
291        false
292    }
293
294    /// Function is implemented for types values.
295    #[doc(hidden)]
296    fn type_matches_value(&self, _value: Value<'v>, _private: Private) -> bool {
297        unreachable!("`type_matches_value` should only be called on special types")
298    }
299
300    /// Get the members associated with this type, accessible via `this_type.x`.
301    /// These members will have `dir`/`getattr`/`hasattr` properly implemented,
302    /// so it is the preferred way to go if possible. See
303    /// [`MethodsStatic`](crate::environment::MethodsStatic) for an example of how
304    /// to define this method.
305    fn get_methods() -> Option<&'static Methods>
306    where
307        Self: Sized,
308    {
309        None
310    }
311
312    /// Return the documentation for this value.
313    ///
314    /// This should be the doc-item that is expected to be generated when this value appears as a
315    /// global in a module. In other words, for normal types this should generally return a
316    /// `DocMember::Property`. In that case there is no need to override this method.
317    fn documentation(&self) -> DocItem
318    where
319        Self: Sized,
320    {
321        let ty = self
322            .typechecker_ty()
323            .unwrap_or_else(|| Self::get_type_starlark_repr());
324        DocItem::Member(DocMember::Property(DocProperty {
325            docs: None,
326            typ: ty,
327        }))
328    }
329
330    /// Type of this instance for typechecker.
331    /// Note this can be more precise than generic type.
332    fn typechecker_ty(&self) -> Option<Ty> {
333        // TODO(nga): replace with `Self::get_type_starlark_repr()`
334        //   when it gets implemented properly.
335        None
336    }
337
338    /// Evaluate this value as a type expression. Basically, `eval_type(this)`.
339    #[doc(hidden)]
340    fn eval_type(&self) -> Option<Ty> {
341        None
342    }
343
344    /// Return a string representation of self, as returned by the `repr()` function.
345    /// Defaults to the `Display` instance - which should be fine for nearly all types.
346    /// In many cases the `repr()` representation will also be a Starlark expression
347    /// for creating the value.
348    ///
349    /// ```rust
350    /// # starlark::assert::all_true(r#"
351    /// repr("test") == '"test"'
352    /// repr([1,2,3]) == '[1, 2, 3]'
353    /// repr([1,[2,3]]) == '[1, [2, 3]]'
354    /// repr([1]) == '[1]'
355    /// repr([]) == '[]'
356    /// # "#);
357    /// ```
358    fn collect_repr(&self, collector: &mut String) {
359        // Rust won't return Err when writing to a String, so safe unwrap
360        write!(collector, "{}", self).unwrap()
361    }
362
363    /// Invoked to print `repr` when a cycle is the object stack is detected.
364    fn collect_repr_cycle(&self, collector: &mut String) {
365        write!(collector, "<{}...>", Self::TYPE).unwrap()
366    }
367
368    /// String used when printing call stack. `repr(self)` by default.
369    fn name_for_call_stack(&self, me: Value<'v>) -> String {
370        me.to_repr()
371    }
372
373    /// Convert self to a boolean, as returned by the bool() function.
374    /// The default implementation returns [`true`].
375    fn to_bool(&self) -> bool {
376        // Return `true` by default, because this is default when implementing
377        // custom types in Python: https://docs.python.org/release/2.5.2/lib/truth.html
378        true
379    }
380
381    /// Return a hash data for self to be used when self is placed as a key in a `Dict`.
382    /// Return an [`Err`] if there is no hash for this value (e.g. list).
383    /// Must be stable between frozen and non-frozen values.
384    fn write_hash(&self, hasher: &mut StarlarkHasher) -> crate::Result<()> {
385        if Self::TYPE == FUNCTION_TYPE {
386            // The Starlark spec says values of type "function" must be hashable.
387            // We could return the address of the function, but that changes
388            // with frozen/non-frozen which breaks freeze for Dict.
389            // We could create an atomic counter and use that, but it takes memory,
390            // effort, complexity etc, and we don't expect many Dict's keyed by
391            // function. Returning 0 as the hash is valid, as Eq will sort it out.
392            let _ = hasher;
393            Ok(())
394        } else {
395            Err(crate::Error::new_other(ControlError::NotHashableValue(
396                Self::TYPE.to_owned(),
397            )))
398        }
399    }
400
401    /// Get the hash value. Calls [`write_hash`](Self::write_hash) by default.
402    #[doc(hidden)]
403    fn get_hash(&self, _private: Private) -> crate::Result<StarlarkHashValue> {
404        let mut hasher = StarlarkHasher::new();
405        self.write_hash(&mut hasher)?;
406        Ok(hasher.finish_small())
407    }
408
409    /// Compare `self` with `other` for equality.
410    /// Should only return an error on excessive recursion.
411    ///
412    /// This function can only be called when it is known that self pointer
413    /// is not equal to the other pointer. Thus, an implementation may assume
414    /// that the pointers are not equal. Implementation of `equals` for some
415    /// builtin types and default implementation rely on this assumption.
416    ///
417    /// Equality must be symmetric (`a == b` implies `b == a`).
418    /// When evaluating `a == b` (or when using equality in dicts and such),
419    /// it is not specified whether `a.equals(b)` or `b.equals(a)` is called.
420    fn equals(&self, _other: Value<'v>) -> crate::Result<bool> {
421        // Type is only equal via a pointer
422        Ok(false)
423    }
424
425    /// Compare `self` with `other`.
426    /// This method returns a result of type [`Ordering`], or an [`Err`]
427    /// if the two types differ.
428    fn compare(&self, other: Value<'v>) -> crate::Result<Ordering> {
429        ValueError::unsupported_with(self, "compare", other)
430    }
431
432    /// Directly invoke a function.
433    /// The number of `named` and `names` arguments are guaranteed to be equal.
434    ///
435    /// # Parameters
436    ///
437    /// * `me` - self, but as `Value`, meaning it has unfrozen flag,
438    ///   so it can be stored in a heap.
439    fn invoke(
440        &self,
441        _me: Value<'v>,
442        _args: &Arguments<'v, '_>,
443        _eval: &mut Evaluator<'v, '_, '_>,
444    ) -> crate::Result<Value<'v>> {
445        ValueError::unsupported(self, "call()")
446    }
447
448    /// Return the result of `a[index]` if `a` is indexable.
449    fn at(&self, index: Value<'v>, _heap: &'v Heap) -> crate::Result<Value<'v>> {
450        ValueError::unsupported_with(self, "[]", index)
451    }
452
453    /// Return the result of `a[index0, index1]` if `a` is indexable by two parameters.
454    fn at2(
455        &self,
456        _index0: Value<'v>,
457        _index1: Value<'v>,
458        _heap: &'v Heap,
459        _private: Private,
460    ) -> crate::Result<Value<'v>> {
461        ValueError::unsupported(self, "[,]")
462    }
463
464    /// Extract a slice of the underlying object if the object is indexable. The
465    /// result will be object between `start` and `stop` (both of them are
466    /// added length() if negative and then clamped between 0 and length()).
467    /// `stride` indicates the direction.
468    ///
469    /// # Parameters
470    ///
471    /// * start: the start of the slice.
472    /// * stop: the end of the slice.
473    /// * stride: the direction of slice,
474    ///
475    /// # Examples
476    ///
477    /// ```rust
478    /// # starlark::assert::all_true(r#"
479    /// 'abc'[1:] == 'bc'         # Remove the first element
480    /// 'abc'[:-1] == 'ab'        # Remove the last element
481    /// 'abc'[1:-1] == 'b'        # Remove the first and the last element
482    /// 'abc'[-1:] == 'c'         # Take the last letter
483    /// 'abc'[:1] == 'a'          # Take the first letter
484    /// 'banana'[1::2] == 'aaa'   # Select one element out of 2, skipping the first
485    /// 'banana'[4::-2] == 'nnb'  # Select one element out of 2 in reverse order, starting at index 4
486    /// # "#);
487    /// ```
488    fn slice(
489        &self,
490        _start: Option<Value<'v>>,
491        _stop: Option<Value<'v>>,
492        _stride: Option<Value<'v>>,
493        _heap: &'v Heap,
494    ) -> crate::Result<Value<'v>> {
495        ValueError::unsupported(self, "[::]")
496    }
497
498    /// Implement iteration over the value of this container by providing
499    /// the values in a `Vec`.
500    #[starlark_internal_vtable(skip)]
501    fn iterate_collect(&self, _heap: &'v Heap) -> crate::Result<Vec<Value<'v>>> {
502        ValueError::unsupported(self, "(iter)")
503    }
504
505    /// Returns an iterator over the value of this container if this value holds
506    /// an iterable container.
507    ///
508    /// **This function is hard to implement correctly.**
509    /// For example, returning a list from this function is memory violation,
510    /// because the list object acting as an iterator is assumed
511    /// to have the iteration lock acquired.
512    ///
513    /// Consider implementing [`iterate_collect`](Self::iterate_collect) instead
514    /// when possible.
515    ///
516    /// This function calls [`iterate_collect`](Self::iterate_collect) by default.
517    ///
518    /// Returned iterator value must implement
519    /// [`iter_next`](Self::iter_next) and [`iter_stop`](Self::iter_stop).
520    /// Default implementations of these functions panic.
521    ///
522    /// Starlark-rust guarantees that
523    /// * `iter_next` and `iter_stop` are only called on the value returned from `iterate`
524    /// * `iter_next` is called only before `iter_stop`
525    /// * `iter_stop` is called exactly once
526    ///
527    /// So implementations of iterators may acquire mutation lock in `iterate`,
528    /// assume that it is held in `iter_next`, and release it in `iter_stop`.
529    /// Obviously, there are no such guarantees if these functions are called directly.
530    unsafe fn iterate(&self, _me: Value<'v>, heap: &'v Heap) -> crate::Result<Value<'v>> {
531        Ok(heap.alloc_tuple(&self.iterate_collect(heap)?))
532    }
533
534    /// Returns the size hint for the iterator.
535    unsafe fn iter_size_hint(&self, _index: usize) -> (usize, Option<usize>) {
536        (0, None)
537    }
538
539    /// Yield the next value from the iterator.
540    ///
541    /// This function is called on the iterator value returned by [`iterate`](Self::iterate).
542    /// This function accepts an index, which starts at 0 and is incremented by 1
543    /// for each call to `iter_next`. The index can be used to implement
544    /// cheap iteration over simple containers like lists:
545    /// list [`iterate`](Self::iterate) just returns the list itself,
546    /// and the passed index is used to access the list elements.
547    ///
548    /// Default implementation panics.
549    ///
550    /// This function is only called before [`iter_stop`](Self::iter_stop).
551    unsafe fn iter_next(&self, _index: usize, _heap: &'v Heap) -> Option<Value<'v>> {
552        panic!(
553            "iter_next called on non-iterable value of type {}",
554            Self::TYPE
555        )
556    }
557
558    /// Indicate that the iteration is finished.
559    ///
560    /// This function is typically used to release mutation lock.
561    /// The function must be implemented for iterators even if it does nothing.
562    ///
563    /// This function is called exactly once for the iterator.
564    unsafe fn iter_stop(&self) {
565        panic!(
566            "iter_stop called on non-iterable value of type {}",
567            Self::TYPE
568        )
569    }
570
571    /// Returns the length of the value, if this value is a sequence.
572    fn length(&self) -> crate::Result<i32> {
573        ValueError::unsupported(self, "len()")
574    }
575
576    /// Attribute type, for the typechecker.
577    ///
578    /// If [`get_attr`](StarlarkValue::get_attr) is implemented,
579    /// `#[starlark_value]` proc macro will generate this to return `Some(Any)`.
580    fn attr_ty(_name: &str) -> Option<Ty> {
581        Some(Ty::any())
582    }
583
584    /// Get an attribute for the current value as would be returned by dotted
585    /// expression (i.e. `a.attribute`).
586    ///
587    /// The three methods [`get_attr`](StarlarkValue::get_attr),
588    /// [`has_attr`](StarlarkValue::has_attr) and [`dir_attr`](StarlarkValue::dir_attr)
589    /// must be consistent - if you implement one, you should probably implement all three.
590    ///
591    /// This operations must have no side effects, because it can be called speculatively.
592    fn get_attr(&self, _attribute: &str, _heap: &'v Heap) -> Option<Value<'v>> {
593        None
594    }
595
596    /// A version of `get_attr` which takes `BorrowHashed<str>` instead of `&str`,
597    /// thus implementation may reuse the hash of the string if this is called
598    /// repeatedly with the same string.
599    ///
600    /// This function is optional, but if it is implemented, it must be consistent with
601    /// [`get_attr`](Self::get_attr).
602    fn get_attr_hashed(&self, attribute: Hashed<&str>, heap: &'v Heap) -> Option<Value<'v>> {
603        self.get_attr(attribute.key(), heap)
604    }
605
606    /// Return true if an attribute of name `attribute` exists for the current
607    /// value.
608    ///
609    /// The three methods [`get_attr`](StarlarkValue::get_attr),
610    /// [`has_attr`](StarlarkValue::has_attr) and [`dir_attr`](StarlarkValue::dir_attr)
611    /// must be consistent.
612    ///
613    /// Default implementation of this function delegates to [`get_attr`](Self::get_attr).
614    fn has_attr(&self, attribute: &str, heap: &'v Heap) -> bool {
615        self.get_attr(attribute, heap).is_some()
616    }
617
618    /// Return a vector of string listing all attribute of the current value.
619    ///
620    /// The three methods [`get_attr`](StarlarkValue::get_attr),
621    /// [`has_attr`](StarlarkValue::has_attr) and [`dir_attr`](StarlarkValue::dir_attr)
622    /// must be consistent - if you implement one, you should probably implement all three.
623    fn dir_attr(&self) -> Vec<String> {
624        Vec::new()
625    }
626
627    /// Tell whether `other` is in the current value, if it is a container.
628    ///
629    /// # Examples
630    ///
631    /// ```rust
632    /// # starlark::assert::all_true(r#"
633    /// ('a' in 'abc') == True
634    /// ('b' in 'abc') == True
635    /// ('z' in 'abc') == False
636    /// # "#);
637    /// ```
638    fn is_in(&self, other: Value<'v>) -> crate::Result<bool> {
639        ValueError::unsupported_owned(other.get_type(), "in", Some(Self::TYPE))
640    }
641
642    /// Apply the `+` unary operator to the current value.
643    ///
644    /// # Examples
645    ///
646    /// ```rust
647    /// # starlark::assert::all_true(r#"
648    /// +1 == 1
649    /// # "#);
650    /// ```
651    fn plus(&self, _heap: &'v Heap) -> crate::Result<Value<'v>> {
652        ValueError::unsupported(self, "+")
653    }
654
655    /// Apply the `-` unary operator to the current value.
656    ///
657    /// # Examples
658    ///
659    /// ```rust
660    /// # starlark::assert::all_true(r#"
661    /// -(1) == -1
662    /// # "#);
663    /// ```
664    fn minus(&self, _heap: &'v Heap) -> crate::Result<Value<'v>> {
665        ValueError::unsupported(self, "-")
666    }
667
668    /// Add with the arguments the other way around.
669    /// Normal `add` should return `None` in order for it to be evaluated.
670    fn radd(&self, _lhs: Value<'v>, _heap: &'v Heap) -> Option<crate::Result<Value<'v>>> {
671        None
672    }
673
674    /// Add `other` to the current value. Pass both self and
675    /// the Value form of self as original. Should return [`None`]
676    /// to fall through to `radd`.
677    ///
678    /// # Examples
679    ///
680    /// ```rust
681    /// # starlark::assert::all_true(r#"
682    /// 1 + 2 == 3
683    /// [1, 2, 3] + [2, 3] == [1, 2, 3, 2, 3]
684    /// 'abc' + 'def' == 'abcdef'
685    /// (1, 2, 3) + (2, 3) == (1, 2, 3, 2, 3)
686    /// # "#);
687    /// ```
688    fn add(&self, _rhs: Value<'v>, _heap: &'v Heap) -> Option<crate::Result<Value<'v>>> {
689        None
690    }
691
692    /// Subtract `other` from the current value.
693    ///
694    /// # Examples
695    ///
696    /// ```rust
697    /// # starlark::assert::all_true(r#"
698    /// 1 - 2 == -1
699    /// # "#);
700    /// ```
701    fn sub(&self, other: Value<'v>, _heap: &'v Heap) -> crate::Result<Value<'v>> {
702        ValueError::unsupported_with(self, "-", other)
703    }
704
705    /// Called on `rhs` of `lhs * rhs` when `lhs.mul` returns `None`.
706    fn rmul(&self, lhs: Value<'v>, heap: &'v Heap) -> Option<crate::Result<Value<'v>>> {
707        let _ignore = (lhs, heap);
708        None
709    }
710
711    /// Multiply the current value with `other`.
712    ///
713    /// When this function returns `None`, starlark-rust calls `rhs.rmul(lhs)`.
714    ///
715    /// # Examples
716    ///
717    /// ```rust
718    /// # starlark::assert::all_true(r#"
719    /// 2 * 3 == 6
720    /// [1, 2, 3] * 3 == [1, 2, 3, 1, 2, 3, 1, 2, 3]
721    /// 'abc' * 3 == 'abcabcabc'
722    /// (1, 2, 3) * 3 == (1, 2, 3, 1, 2, 3, 1, 2, 3)
723    /// # "#);
724    /// ```
725    fn mul(&self, _rhs: Value<'v>, _heap: &'v Heap) -> Option<crate::Result<Value<'v>>> {
726        None
727    }
728
729    /// Divide the current value by `other`. Always results in a float value.
730    ///
731    /// # Examples
732    ///
733    /// ```rust
734    /// # starlark::assert::all_true(r#"
735    /// 4 / 2.0 == 2.0
736    /// 7 / 2 == 3.5
737    /// # "#);
738    /// ```
739    fn div(&self, other: Value<'v>, _heap: &'v Heap) -> crate::Result<Value<'v>> {
740        ValueError::unsupported_with(self, "/", other)
741    }
742
743    /// Apply the percent operator between the current value and `other`. Usually used on
744    /// strings, as per
745    /// [the Starlark spec](https://github.com/bazelbuild/starlark/blob/master/spec.md#string-interpolation).
746    ///
747    /// # Examples
748    ///
749    /// ```rust
750    /// # starlark::assert::all_true(r#"
751    /// 5 % 3 == 2
752    /// -5 % -3 == -2
753    /// 5 % -3 == -1
754    /// -5 % 3 == 1
755    /// 5.5 % 3.0 == 2.5
756    /// -5.5 % 3.0 == 0.5
757    /// 5.5 % -3.0 == -0.5
758    /// -5.5 % -3.0 == -2.5
759    /// "a %s c" % 3 == "a 3 c"
760    /// "Hello %s, your score is %d" % ("Bob", 75) == "Hello Bob, your score is 75"
761    /// "%d %o %x" % (65, 65, 65) == "65 101 41"
762    /// "%d" % 12345678901234567890 == "12345678901234567890"
763    /// "Hello %s, welcome" % "Bob" == "Hello Bob, welcome"
764    /// "%s" % (1,) == "1"
765    /// "%s" % ((1,),) == "(1,)"
766    /// "%s" % [1] == "[1]"
767    /// "test" % () == "test"
768    /// # "#);
769    /// ```
770    fn percent(&self, other: Value<'v>, _heap: &'v Heap) -> crate::Result<Value<'v>> {
771        ValueError::unsupported_with(self, "%", other)
772    }
773
774    /// Floor division between the current value and `other`.
775    ///
776    /// # Examples
777    ///
778    /// ```rust
779    /// # starlark::assert::all_true(r#"
780    /// 7 // 2 == 3
781    /// -7 // -2 == 3
782    /// 7 // -2 == -4
783    /// -7 // 2 == -4
784    /// 7.0 // 2.0 == 3.0
785    /// -7.0 // -2.0 == 3.0
786    /// 7.0 // -2.0 == -4.0
787    /// -7.0 // 2.0 == -4.0
788    /// 3.0 // 2.0 == 1.0
789    /// # "#);
790    /// ```
791    fn floor_div(&self, other: Value<'v>, _heap: &'v Heap) -> crate::Result<Value<'v>> {
792        ValueError::unsupported_with(self, "//", other)
793    }
794
795    /// Bitwise `&` operator.
796    fn bit_and(&self, other: Value<'v>, _heap: &'v Heap) -> crate::Result<Value<'v>> {
797        ValueError::unsupported_with(self, "&", other)
798    }
799
800    /// Bitwise `|` operator.
801    ///
802    /// # Examples
803    ///
804    /// ```rust
805    /// # starlark::assert::all_true(r#"
806    /// 0xb00f | 0x0ee0 == 0xbeef
807    /// 4 | 7 == 7
808    /// {1: 2} | {3: 4} == {1: 2, 3: 4}
809    /// {1: 2} | {1: 3} == {1: 3}
810    /// # "#);
811    /// ```
812    fn bit_or(&self, other: Value<'v>, _heap: &'v Heap) -> crate::Result<Value<'v>> {
813        ValueError::unsupported_with(self, "|", other)
814    }
815
816    /// Bitwise `^` operator.
817    fn bit_xor(&self, other: Value<'v>, _heap: &'v Heap) -> crate::Result<Value<'v>> {
818        ValueError::unsupported_with(self, "^", other)
819    }
820
821    /// Bitwise `~` operator.
822    fn bit_not(&self, _heap: &'v Heap) -> crate::Result<Value<'v>> {
823        ValueError::unsupported(self, "~")
824    }
825
826    /// Bitwise `<<` operator.
827    fn left_shift(&self, other: Value<'v>, _heap: &'v Heap) -> crate::Result<Value<'v>> {
828        ValueError::unsupported_with(self, "<<", other)
829    }
830
831    /// Bitwise `>>` operator.
832    fn right_shift(&self, other: Value<'v>, _heap: &'v Heap) -> crate::Result<Value<'v>> {
833        ValueError::unsupported_with(self, ">>", other)
834    }
835
836    /// Typecheck `this op rhs`.
837    fn bin_op_ty(_op: TypingBinOp, _rhs: &TyBasic) -> Option<Ty> {
838        None
839    }
840
841    /// Typecheck `lhs op this`.
842    fn rbin_op_ty(_lhs: &TyBasic, _op: TypingBinOp) -> Option<Ty> {
843        None
844    }
845
846    /// Called when exporting a value under a specific name,
847    fn export_as(
848        &self,
849        _variable_name: &str,
850        _eval: &mut Evaluator<'v, '_, '_>,
851    ) -> crate::Result<()> {
852        // Most data types ignore how they are exported
853        // but rules/providers like to use it as a helpful hint for users
854        Ok(())
855    }
856
857    /// Set the value at `index` with the new value.
858    ///
859    /// ```rust
860    /// # starlark::assert::is_true(r#"
861    /// v = [1, 2, 3]
862    /// v[1] = 1
863    /// v[2] = [2,3]
864    /// v == [1, 1, [2, 3]]
865    /// # "#);
866    /// ```
867    fn set_at(&self, _index: Value<'v>, _new_value: Value<'v>) -> crate::Result<()> {
868        Err(crate::Error::new_other(
869            ValueError::CannotMutateImmutableValue,
870        ))
871    }
872
873    /// Set the attribute named `attribute` of the current value to
874    /// `value` (e.g. `a.attribute = value`).
875    fn set_attr(&self, attribute: &str, _new_value: Value<'v>) -> crate::Result<()> {
876        ValueError::unsupported(self, &format!(".{}=", attribute))
877    }
878
879    /// Dynamically provide values based on type.
880    ///
881    /// Value can be fetched using [`Value::request_value`].
882    ///
883    /// The API is based on
884    /// [std::any::Provider](https://doc.rust-lang.org/std/any/trait.Provider.html).
885    fn provide(&'v self, demand: &mut Demand<'_, 'v>) {
886        let _ = demand;
887    }
888
889    /// When freezing, this function is called on mutable value to return
890    /// statically allocated singleton value if possible.
891    ///
892    /// This function is used for optimization and rarely needed to be implemented.
893    fn try_freeze_static(&self) -> Option<FrozenValue> {
894        None
895    }
896}