summaryrefslogtreecommitdiff
path: root/src/model
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2022-11-22 20:12:37 +0100
committerLaurenz <laurmaedje@gmail.com>2022-11-22 20:12:37 +0100
commit5992f11b4c33d82fa245205980094accb57a8c76 (patch)
treeb0043ba4b4cabab2fa8f63ec80f37c9d247e134a /src/model
parentb476de87b7cea1405bf3c051ff8e0ac7c473dbae (diff)
Reorganize content type
Diffstat (limited to 'src/model')
-rw-r--r--src/model/content.rs366
-rw-r--r--src/model/eval.rs11
-rw-r--r--src/model/styles.rs50
3 files changed, 215 insertions, 212 deletions
diff --git a/src/model/content.rs b/src/model/content.rs
index d72e4e19..9d78020c 100644
--- a/src/model/content.rs
+++ b/src/model/content.rs
@@ -9,19 +9,22 @@ use comemo::Tracked;
use siphasher::sip128::{Hasher128, SipHasher};
use typst_macros::node;
-use super::{Args, Key, Property, Recipe, RecipeId, Style, StyleMap, Value, Vm};
+use super::{
+ Args, Key, Property, Recipe, RecipeId, Style, StyleMap, Unlabellable, Value, Vm,
+};
use crate::diag::{SourceResult, StrResult};
use crate::syntax::Span;
use crate::util::{EcoString, ReadableTypeId};
use crate::World;
/// Composable representation of styled content.
-///
-/// This results from:
-/// - anything written between square brackets in Typst
-/// - any constructor function
#[derive(Clone, Hash)]
-pub struct Content(Arc<dyn Bounds>, Vec<RecipeId>, Option<Span>, Option<EcoString>);
+pub struct Content {
+ obj: Arc<dyn Bounds>,
+ guards: Vec<RecipeId>,
+ span: Option<Span>,
+ label: Option<EcoString>,
+}
impl Content {
/// Create empty content.
@@ -37,99 +40,38 @@ impl Content {
}
}
- /// Whether the content is empty.
- pub fn is_empty(&self) -> bool {
- self.downcast::<SequenceNode>().map_or(false, |seq| seq.0.is_empty())
- }
-
- /// The node's human-readable name.
- pub fn name(&self) -> &'static str {
- (*self.0).name()
- }
-
- /// The id of the contained node.
- pub fn id(&self) -> NodeId {
- (*self.0).id()
- }
-
- /// Whether the contained node is of type `T`.
- pub fn is<T: 'static>(&self) -> bool {
- (*self.0).as_any().is::<T>()
- }
-
- /// Cast to `T` if the contained node is of type `T`.
- pub fn downcast<T: 'static>(&self) -> Option<&T> {
- (*self.0).as_any().downcast_ref::<T>()
- }
-
- /// Try to cast to a mutable instance of `T`.
- fn try_downcast_mut<T: 'static>(&mut self) -> Option<&mut T> {
- Arc::get_mut(&mut self.0)?.as_any_mut().downcast_mut::<T>()
- }
-
- /// Access a field on this content.
- pub fn field(&self, name: &str) -> Option<Value> {
- if name == "label" {
- return Some(match &self.3 {
- Some(label) => Value::Str(label.clone().into()),
- None => Value::None,
- });
+ /// Attach a span to the content.
+ pub fn spanned(mut self, span: Span) -> Self {
+ if let Some(styled) = self.to_mut::<StyledNode>() {
+ styled.sub.span = Some(span);
+ } else if let Some(styled) = self.to::<StyledNode>() {
+ self = StyledNode {
+ sub: styled.sub.clone().spanned(span),
+ map: styled.map.clone(),
+ }
+ .pack();
}
-
- self.0.field(name)
- }
-
- /// Whether this content has the given capability.
- pub fn has<C>(&self) -> bool
- where
- C: Capability + ?Sized,
- {
- self.0.vtable(TypeId::of::<C>()).is_some()
- }
-
- /// Cast to a trait object if this content has the given capability.
- pub fn to<C>(&self) -> Option<&C>
- where
- C: Capability + ?Sized,
- {
- let node: &dyn Bounds = &*self.0;
- let vtable = node.vtable(TypeId::of::<C>())?;
- let data = node as *const dyn Bounds as *const ();
- Some(unsafe { &*crate::util::fat::from_raw_parts(data, vtable) })
+ self.span = Some(span);
+ self
}
- /// Repeat this content `n` times.
- pub fn repeat(&self, n: i64) -> StrResult<Self> {
- let count = usize::try_from(n)
- .map_err(|_| format!("cannot repeat this content {} times", n))?;
-
- Ok(Self::sequence(vec![self.clone(); count]))
+ /// Attach a label to the content.
+ pub fn labelled(mut self, label: EcoString) -> Self {
+ self.label = Some(label);
+ self
}
/// Style this content with a single style property.
- pub fn styled<'k, K: Key<'k>>(self, key: K, value: K::Value) -> Self {
+ pub fn styled<K: Key>(self, key: K, value: K::Value) -> Self {
self.styled_with_entry(Style::Property(Property::new(key, value)))
}
- /// Style this content with a recipe, eagerly applying it if possible.
- pub fn styled_with_recipe(
- self,
- world: Tracked<dyn World>,
- recipe: Recipe,
- ) -> SourceResult<Self> {
- if recipe.selector.is_none() {
- recipe.transform.apply(world, recipe.span, self)
- } else {
- Ok(self.styled_with_entry(Style::Recipe(recipe)))
- }
- }
-
/// Style this content with a style entry.
pub fn styled_with_entry(mut self, style: Style) -> Self {
- if let Some(styled) = self.try_downcast_mut::<StyledNode>() {
+ if let Some(styled) = self.to_mut::<StyledNode>() {
styled.map.apply(style);
self
- } else if let Some(styled) = self.downcast::<StyledNode>() {
+ } else if let Some(styled) = self.to::<StyledNode>() {
let mut map = styled.map.clone();
map.apply(style);
StyledNode { sub: styled.sub.clone(), map }.pack()
@@ -144,7 +86,7 @@ impl Content {
return self;
}
- if let Some(styled) = self.try_downcast_mut::<StyledNode>() {
+ if let Some(styled) = self.to_mut::<StyledNode>() {
styled.map.apply_map(&styles);
return self;
}
@@ -152,86 +94,140 @@ impl Content {
StyledNode { sub: self, map: styles }.pack()
}
- /// Disable a show rule recipe.
- pub fn guard(mut self, id: RecipeId) -> Self {
- self.1.push(id);
- self
+ /// Style this content with a recipe, eagerly applying it if possible.
+ pub fn styled_with_recipe(
+ self,
+ world: Tracked<dyn World>,
+ recipe: Recipe,
+ ) -> SourceResult<Self> {
+ if recipe.selector.is_none() {
+ recipe.transform.apply(world, recipe.span, self)
+ } else {
+ Ok(self.styled_with_entry(Style::Recipe(recipe)))
+ }
}
- /// Whether no show rule was executed for this node so far.
- pub fn pristine(&self) -> bool {
- self.1.is_empty()
+ /// Repeat this content `n` times.
+ pub fn repeat(&self, n: i64) -> StrResult<Self> {
+ let count = usize::try_from(n)
+ .map_err(|_| format!("cannot repeat this content {} times", n))?;
+
+ Ok(Self::sequence(vec![self.clone(); count]))
}
+}
- /// Check whether a show rule recipe is disabled.
- pub fn guarded(&self, id: RecipeId) -> bool {
- self.1.contains(&id)
+impl Content {
+ /// The id of the contained node.
+ pub fn id(&self) -> NodeId {
+ (*self.obj).id()
+ }
+
+ /// The node's human-readable name.
+ pub fn name(&self) -> &'static str {
+ (*self.obj).name()
}
/// The node's span.
pub fn span(&self) -> Option<Span> {
- self.2
+ self.span
}
- /// Set the content's span.
- pub fn set_span(&mut self, span: Span) {
- if let Some(styled) = self.try_downcast_mut::<StyledNode>() {
- styled.sub.2 = Some(span);
- } else if let Some(styled) = self.downcast::<StyledNode>() {
- *self = StyledNode {
- sub: styled.sub.clone().spanned(span),
- map: styled.map.clone(),
- }
- .pack();
+ /// The content's label.
+ pub fn label(&self) -> Option<&EcoString> {
+ self.label.as_ref()
+ }
+
+ /// Access a field on this content.
+ pub fn field(&self, name: &str) -> Option<Value> {
+ if name == "label" {
+ return Some(match &self.label {
+ Some(label) => Value::Str(label.clone().into()),
+ None => Value::None,
+ });
}
- self.2 = Some(span);
+
+ self.obj.field(name)
}
- /// Attach a span to the content.
- pub fn spanned(mut self, span: Span) -> Self {
- self.set_span(span);
- self
+ /// Whether the contained node is of type `T`.
+ pub fn is<T: 'static>(&self) -> bool {
+ (*self.obj).as_any().is::<T>()
}
- /// The content's label.
- pub fn label(&self) -> Option<&EcoString> {
- self.3.as_ref()
+ /// Cast to `T` if the contained node is of type `T`.
+ pub fn to<T: 'static>(&self) -> Option<&T> {
+ (*self.obj).as_any().downcast_ref::<T>()
}
- /// Set the content's label.
- pub fn set_label(&mut self, label: EcoString) {
- self.3 = Some(label);
+ /// Whether this content has the given capability.
+ pub fn has<C>(&self) -> bool
+ where
+ C: Capability + ?Sized,
+ {
+ self.obj.vtable(TypeId::of::<C>()).is_some()
}
- /// Attacha label to the content.
- pub fn labelled(mut self, label: EcoString) -> Self {
- self.set_label(label);
+ /// Cast to a trait object if this content has the given capability.
+ pub fn with<C>(&self) -> Option<&C>
+ where
+ C: Capability + ?Sized,
+ {
+ let node: &dyn Bounds = &*self.obj;
+ let vtable = node.vtable(TypeId::of::<C>())?;
+ let data = node as *const dyn Bounds as *const ();
+ Some(unsafe { &*crate::util::fat::from_raw_parts(data, vtable) })
+ }
+
+ /// Try to cast to a mutable instance of `T`.
+ fn to_mut<T: 'static>(&mut self) -> Option<&mut T> {
+ Arc::get_mut(&mut self.obj)?.as_any_mut().downcast_mut::<T>()
+ }
+
+ /// Disable a show rule recipe.
+ #[doc(hidden)]
+ pub fn guarded(mut self, id: RecipeId) -> Self {
+ self.guards.push(id);
self
}
- /// Copy the metadata from other content.
- pub fn copy_meta(&mut self, from: &Content) {
- self.1 = from.1.clone();
- self.2 = from.2;
- self.3 = from.3.clone();
+ /// Whether a label can be attached to the content.
+ pub(super) fn labellable(&self) -> bool {
+ !self.has::<dyn Unlabellable>()
}
-}
-impl Default for Content {
- fn default() -> Self {
- Self::empty()
+ /// Whether no show rule was executed for this node so far.
+ pub(super) fn is_pristine(&self) -> bool {
+ self.guards.is_empty()
+ }
+
+ /// Check whether a show rule recipe is disabled.
+ pub(super) fn is_guarded(&self, id: RecipeId) -> bool {
+ self.guards.contains(&id)
+ }
+
+ /// Copy the metadata from other content.
+ pub(super) fn copy_meta(&mut self, from: &Content) {
+ self.guards = from.guards.clone();
+ self.span = from.span;
+ self.label = from.label.clone();
}
}
impl Debug for Content {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- self.0.fmt(f)
+ self.obj.fmt(f)
+ }
+}
+
+impl Default for Content {
+ fn default() -> Self {
+ Self::empty()
}
}
impl PartialEq for Content {
fn eq(&self, other: &Self) -> bool {
- (*self.0).hash128() == (*other.0).hash128()
+ (*self.obj).hash128() == (*other.obj).hash128()
}
}
@@ -240,10 +236,10 @@ impl Add for Content {
fn add(self, mut rhs: Self) -> Self::Output {
let mut lhs = self;
- if let Some(lhs_mut) = lhs.try_downcast_mut::<SequenceNode>() {
- if let Some(rhs_mut) = rhs.try_downcast_mut::<SequenceNode>() {
+ if let Some(lhs_mut) = lhs.to_mut::<SequenceNode>() {
+ if let Some(rhs_mut) = rhs.to_mut::<SequenceNode>() {
lhs_mut.0.append(&mut rhs_mut.0);
- } else if let Some(rhs) = rhs.downcast::<SequenceNode>() {
+ } else if let Some(rhs) = rhs.to::<SequenceNode>() {
lhs_mut.0.extend(rhs.0.iter().cloned());
} else {
lhs_mut.0.push(rhs);
@@ -251,7 +247,7 @@ impl Add for Content {
return lhs;
}
- let seq = match (lhs.downcast::<SequenceNode>(), rhs.downcast::<SequenceNode>()) {
+ let seq = match (lhs.to::<SequenceNode>(), rhs.to::<SequenceNode>()) {
(Some(lhs), Some(rhs)) => lhs.0.iter().chain(&rhs.0).cloned().collect(),
(Some(lhs), None) => lhs.0.iter().cloned().chain(iter::once(rhs)).collect(),
(None, Some(rhs)) => iter::once(lhs).chain(rhs.0.iter().cloned()).collect(),
@@ -306,14 +302,54 @@ impl Hash for dyn Bounds {
}
}
+/// A node with applied styles.
+#[derive(Clone, Hash)]
+pub struct StyledNode {
+ /// The styled content.
+ pub sub: Content,
+ /// The styles.
+ pub map: StyleMap,
+}
+
+#[node]
+impl StyledNode {}
+
+impl Debug for StyledNode {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ self.map.fmt(f)?;
+ self.sub.fmt(f)
+ }
+}
+
+/// A sequence of nodes.
+///
+/// Combines other arbitrary content. So, when you write `[Hi] + [you]` in
+/// Typst, the two text nodes are combined into a single sequence node.
+#[derive(Clone, Hash)]
+pub struct SequenceNode(pub Vec<Content>);
+
+#[node]
+impl SequenceNode {}
+
+impl Debug for SequenceNode {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ f.debug_list().entries(self.0.iter()).finish()
+ }
+}
+
/// A constructable, stylable content node.
-pub trait Node: 'static {
- /// Pack into type-erased content.
+pub trait Node: 'static + Capable {
+ /// Pack a node into type-erased content.
fn pack(self) -> Content
where
- Self: Debug + Hash + Sync + Send + Sized + 'static,
+ Self: Node + Debug + Hash + Sync + Send + Sized + 'static,
{
- Content(Arc::new(self), vec![], None, None)
+ Content {
+ obj: Arc::new(self),
+ guards: vec![],
+ span: None,
+ label: None,
+ }
}
/// A unique identifier of the node type.
@@ -340,17 +376,8 @@ pub trait Node: 'static {
/// Access a field on this node.
fn field(&self, name: &str) -> Option<Value>;
-
- /// Extract the pointer of the vtable of the trait object with the
- /// given type `id` if this node implements that trait.
- fn vtable(&self, id: TypeId) -> Option<*const ()>;
}
-/// A capability a node can have.
-///
-/// This is implemented by trait objects.
-pub trait Capability: 'static + Send + Sync {}
-
/// A unique identifier for a node.
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
pub struct NodeId(ReadableTypeId);
@@ -368,37 +395,14 @@ impl Debug for NodeId {
}
}
-/// A node with applied styles.
-#[derive(Clone, Hash)]
-pub struct StyledNode {
- /// The styled content.
- pub sub: Content,
- /// The styles.
- pub map: StyleMap,
-}
-
-#[node]
-impl StyledNode {}
-
-impl Debug for StyledNode {
- fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- self.map.fmt(f)?;
- self.sub.fmt(f)
- }
-}
-
-/// A sequence of nodes.
+/// A capability a node can have.
///
-/// Combines other arbitrary content. So, when you write `[Hi] + [you]` in
-/// Typst, the two text nodes are combined into a single sequence node.
-#[derive(Clone, Hash)]
-pub struct SequenceNode(pub Vec<Content>);
-
-#[node]
-impl SequenceNode {}
+/// This is implemented by trait objects.
+pub trait Capability: 'static {}
-impl Debug for SequenceNode {
- fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- f.debug_list().entries(self.0.iter()).finish()
- }
+/// Dynamically access a trait implementation at runtime.
+pub unsafe trait Capable {
+ /// Return the vtable pointer of the trait object with given type `id`
+ /// if `self` implements the trait.
+ fn vtable(&self, of: TypeId) -> Option<*const ()>;
}
diff --git a/src/model/eval.rs b/src/model/eval.rs
index 8078c87f..7c0cffb5 100644
--- a/src/model/eval.rs
+++ b/src/model/eval.rs
@@ -1,13 +1,14 @@
//! Evaluation of markup into modules.
use std::collections::BTreeMap;
+use std::mem;
use comemo::{Track, Tracked};
use unicode_segmentation::UnicodeSegmentation;
use super::{
methods, ops, Arg, Args, Array, CapturesVisitor, Closure, Content, Dict, Flow, Func,
- Recipe, Scope, Scopes, Selector, StyleMap, Transform, Unlabellable, Value, Vm,
+ Recipe, Scope, Scopes, Selector, StyleMap, Transform, Value, Vm,
};
use crate::diag::{bail, error, At, SourceResult, StrResult, Trace, Tracepoint};
use crate::geom::{Abs, Angle, Em, Fr, Ratio};
@@ -137,10 +138,8 @@ fn eval_markup(
seq.push(tail.styled_with_recipe(vm.world, recipe)?)
}
ast::MarkupNode::Label(label) => {
- if let Some(node) =
- seq.iter_mut().rev().find(|node| !node.has::<dyn Unlabellable>())
- {
- node.set_label(label.get().clone());
+ if let Some(node) = seq.iter_mut().rev().find(|node| node.labellable()) {
+ *node = mem::take(node).labelled(label.get().clone());
}
}
_ => seq.push(node.eval(vm)?),
@@ -1080,7 +1079,7 @@ impl Eval for ast::FuncReturn {
}
/// Access an expression mutably.
-pub trait Access {
+trait Access {
/// Access the value.
fn access<'a>(&self, vm: &'a mut Vm) -> SourceResult<&'a mut Value>;
}
diff --git a/src/model/styles.rs b/src/model/styles.rs
index 30db00bd..96eb0ab4 100644
--- a/src/model/styles.rs
+++ b/src/model/styles.rs
@@ -36,19 +36,19 @@ impl StyleMap {
/// If the property needs folding and the value is already contained in the
/// style map, `self` contributes the outer values and `value` is the inner
/// one.
- pub fn set<'a, K: Key<'a>>(&mut self, key: K, value: K::Value) {
+ pub fn set<K: Key>(&mut self, key: K, value: K::Value) {
self.0.push(Style::Property(Property::new(key, value)));
}
/// Set an inner value for a style property if it is `Some(_)`.
- pub fn set_opt<'a, K: Key<'a>>(&mut self, key: K, value: Option<K::Value>) {
+ pub fn set_opt<K: Key>(&mut self, key: K, value: Option<K::Value>) {
if let Some(value) = value {
self.set(key, value);
}
}
/// Whether the map contains a style property for the given key.
- pub fn contains<'a, K: Key<'a>>(&self, _: K) -> bool {
+ pub fn contains<K: Key>(&self, _: K) -> bool {
self.0
.iter()
.filter_map(|entry| entry.property())
@@ -188,13 +188,13 @@ impl Debug for Style {
///
/// This trait is not intended to be implemented manually, but rather through
/// the `#[node]` proc-macro.
-pub trait Key<'a>: Copy + 'static {
+pub trait Key: Copy + 'static {
/// The unfolded type which this property is stored as in a style map.
type Value: Debug + Clone + Hash + Sync + Send + 'static;
/// The folded type of value that is returned when reading this property
/// from a style chain.
- type Output;
+ type Output<'a>;
/// The name of the property, used for debug printing.
const NAME: &'static str;
@@ -204,10 +204,10 @@ pub trait Key<'a>: Copy + 'static {
/// Compute an output value from a sequence of values belonging to this key,
/// folding if necessary.
- fn get(
+ fn get<'a>(
chain: StyleChain<'a>,
values: impl Iterator<Item = &'a Self::Value>,
- ) -> Self::Output;
+ ) -> Self::Output<'a>;
}
/// A style property originating from a set rule or constructor.
@@ -229,7 +229,7 @@ pub struct Property {
impl Property {
/// Create a new property from a key-value pair.
- pub fn new<'a, K: Key<'a>>(_: K, value: K::Value) -> Self {
+ pub fn new<K: Key>(_: K, value: K::Value) -> Self {
Self {
key: KeyId::of::<K>(),
node: K::node(),
@@ -241,7 +241,7 @@ impl Property {
}
/// Whether this property has the given key.
- pub fn is<'a, K: Key<'a>>(&self) -> bool {
+ pub fn is<K: Key>(&self) -> bool {
self.key == KeyId::of::<K>()
}
@@ -251,7 +251,7 @@ impl Property {
}
/// Access the property's value if it is of the given key.
- pub fn downcast<'a, K: Key<'a>>(&'a self) -> Option<&'a K::Value> {
+ pub fn downcast<K: Key>(&self) -> Option<&K::Value> {
if self.key == KeyId::of::<K>() {
(**self.value).as_any().downcast_ref()
} else {
@@ -314,7 +314,7 @@ struct KeyId(ReadableTypeId);
impl KeyId {
/// The id of the given key.
- pub fn of<'a, T: Key<'a>>() -> Self {
+ pub fn of<T: Key>() -> Self {
Self(ReadableTypeId::of::<T>())
}
}
@@ -327,7 +327,7 @@ impl Debug for KeyId {
/// A built-in show rule for a node.
#[capability]
-pub trait Show: 'static + Sync + Send {
+pub trait Show {
/// Execute the base recipe for this node.
fn show(
&self,
@@ -338,7 +338,7 @@ pub trait Show: 'static + Sync + Send {
/// Post-process a node after it was realized.
#[capability]
-pub trait Finalize: 'static + Sync + Send {
+pub trait Finalize {
/// Finalize the fully realized form of the node. Use this for effects that
/// should work even in the face of a user-defined show rule, for example
/// the linking behaviour of a link node.
@@ -352,7 +352,7 @@ pub trait Finalize: 'static + Sync + Send {
/// Indicates that a node cannot be labelled.
#[capability]
-pub trait Unlabellable: 'static + Sync + Send {}
+pub trait Unlabellable {}
/// A show rule recipe.
#[derive(Clone, PartialEq, Hash)]
@@ -386,7 +386,7 @@ impl Recipe {
return Ok(None);
}
- self.transform.apply(world, self.span, target.clone().guard(sel))?
+ self.transform.apply(world, self.span, target.clone().guarded(sel))?
}
Some(Selector::Regex(regex)) => {
@@ -412,7 +412,7 @@ impl Recipe {
let transformed = self.transform.apply(
world,
self.span,
- make(m.as_str().into()).guard(sel),
+ make(m.as_str().into()).guarded(sel),
)?;
result.push(transformed);
@@ -559,7 +559,7 @@ impl<'a> StyleChain<'a> {
/// Returns the property's default value if no map in the chain contains an
/// entry for it. Also takes care of resolving and folding and returns
/// references where applicable.
- pub fn get<K: Key<'a>>(self, key: K) -> K::Output {
+ pub fn get<K: Key>(self, key: K) -> K::Output<'a> {
K::get(self, self.values(key))
}
@@ -576,7 +576,7 @@ impl<'a> StyleChain<'a> {
let mut realized = None;
for recipe in self.entries().filter_map(Style::recipe) {
let sel = RecipeId::Nth(n);
- if recipe.applicable(target) && !target.guarded(sel) {
+ if recipe.applicable(target) && !target.is_guarded(sel) {
if let Some(content) = recipe.apply(world, sel, target)? {
realized = Some(content);
break;
@@ -587,15 +587,15 @@ impl<'a> StyleChain<'a> {
// Realize if there was no matching recipe.
let base = RecipeId::Base(target.id());
- if realized.is_none() && !target.guarded(base) {
- if let Some(showable) = target.to::<dyn Show>() {
+ if realized.is_none() && !target.is_guarded(base) {
+ if let Some(showable) = target.with::<dyn Show>() {
realized = Some(showable.show(world, self)?);
}
}
// Finalize only if this is the first application for this node.
- if let Some(node) = target.to::<dyn Finalize>() {
- if target.pristine() {
+ if let Some(node) = target.with::<dyn Finalize>() {
+ if target.is_pristine() {
if let Some(content) = realized {
realized = Some(node.finalize(world, self, content)?);
}
@@ -612,7 +612,7 @@ impl<'a> StyleChain<'a> {
// Find out whether any recipe matches and is unguarded.
for recipe in self.entries().filter_map(Style::recipe) {
- if recipe.applicable(target) && !target.guarded(RecipeId::Nth(n)) {
+ if recipe.applicable(target) && !target.is_guarded(RecipeId::Nth(n)) {
return true;
}
n -= 1;
@@ -638,7 +638,7 @@ impl<'a> StyleChain<'a> {
}
/// Iterate over all values for the given property in the chain.
- fn values<K: Key<'a>>(self, _: K) -> Values<'a, K> {
+ fn values<K: Key>(self, _: K) -> Values<'a, K> {
Values {
entries: self.entries(),
key: PhantomData,
@@ -682,7 +682,7 @@ struct Values<'a, K> {
barriers: usize,
}
-impl<'a, K: Key<'a>> Iterator for Values<'a, K> {
+impl<'a, K: Key> Iterator for Values<'a, K> {
type Item = &'a K::Value;
fn next(&mut self) -> Option<Self::Item> {