tvm_ffi/extra/dispatch.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
//! Runtime type dispatch indexed by its tuple of arguments.
/// Runtime type dispatch with a complete handler outcome.
///
/// Implementations generated by `#[dispatch(prefix)]` use a borrowed receiver
/// (`&T` or `&mut T`) as `Self` and use `Ret = Option<R>`. Only the outer
/// `None` denotes no match: a matched error or inner `None` remains `Some(result)`
/// and does not try another handler. Consuming the receiver reference preserves
/// results borrowing it while ordinary method calls automatically borrow it.
/// The argument tuple and complete return type select an implementation.
#[diagnostic::on_unimplemented(
message = "this receiver does not implement Dispatcher for the requested argument tuple",
note = "use #[dispatch(prefix)] on typed handlers with compatible arguments and results"
)]
pub trait Dispatcher<Args, Ret> {
fn dispatch_tuple(self, args: Args) -> Ret;
}
use crate::{error::Result, AnyView};
// Generated alias bounds must not make recovery depend on a temporary borrow.
#[doc(hidden)]
pub trait DispatchRecovery<S> {
type Recovery;
}
impl<S, T: crate::type_traits::ContainerElement> DispatchRecovery<S> for T {
type Recovery = ();
}
impl<'source, 'value> DispatchRecovery<crate::match_any_internal::ViewSource<'source>>
for AnyView<'value>
{
type Recovery = ();
}
impl<'source, 'value, T: crate::type_traits::ContainerElement>
DispatchRecovery<crate::match_any_internal::CapabilitySource<'source>>
for crate::MutationView<'value, T>
{
type Recovery = crate::MutationView<'source>;
}
use super::structural_visit::{DefRegionKind, IntoWalker, NativeVisit, WalkResult};
// Borrowed traversal adapters forward this concrete tuple without making
// unknown-Args trait solving recurse through mutable reference layers.
impl<'receiver, 'inner, 'value, D, Ret> Dispatcher<(AnyView<'value>, DefRegionKind), Ret>
for &'receiver mut &'inner mut D
where
&'receiver mut D: Dispatcher<(AnyView<'value>, DefRegionKind), Ret>,
{
#[inline(always)]
fn dispatch_tuple(self, args: (AnyView<'value>, DefRegionKind)) -> Ret {
<&'receiver mut D as Dispatcher<(AnyView<'value>, DefRegionKind), Ret>>::dispatch_tuple(
&mut **self,
args,
)
}
}
/// Dispatch for typed `structural_walk` observer callbacks.
///
/// This private engine bridge consumes the common normalized walk signature.
/// Matching is supplied by `Dispatcher`; its outer `None` means no match.
pub(crate) trait WalkDispatch: Sized {
fn dispatch_walk(
&mut self,
value: AnyView<'_>,
def_region_kind: DefRegionKind,
) -> Option<Result<WalkResult>>;
}
impl<V> WalkDispatch for V
where
for<'receiver, 'value> &'receiver mut V:
Dispatcher<(AnyView<'value>, DefRegionKind), Option<Result<WalkResult>>>,
{
#[inline(always)]
fn dispatch_walk(
&mut self,
value: AnyView<'_>,
def_region_kind: DefRegionKind,
) -> Option<Result<WalkResult>> {
self.dispatch_tuple((value, def_region_kind))
}
}
#[doc(hidden)]
pub enum ByWalkDispatch {}
impl<'a, V: WalkDispatch> IntoWalker<ByWalkDispatch> for &'a mut V {
type Walker = DispatchWalker<&'a mut V>;
fn into_walker(self) -> Self::Walker {
DispatchWalker { walker: self }
}
}
/// Adapter from [`Dispatcher`](crate::Dispatcher) to the traversal's native callback.
#[doc(hidden)]
pub struct DispatchWalker<V> {
walker: V,
}
impl<V> super::structural_visit::NativeContext for DispatchWalker<V> {}
impl<V: WalkDispatch> NativeVisit for DispatchWalker<&mut V> {
fn visit(&mut self, value: AnyView<'_>, def_region_kind: DefRegionKind) -> Result<WalkResult> {
self.walker
.dispatch_walk(value, def_region_kind)
.unwrap_or_else(|| Ok(WalkResult::Advance))
}
}