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}