tamer: asg::Asg::get: Narrow object type
This uses `ObjectIndex` to automatically narrow the type to what is expected. Given that `ObjectIndex` is supposed to mean that there must be an object with that index, perhaps the next step is to remove the `Option` from `get` as well. DEV-13160main
parent
6e90867212
commit
0863536149
|
@ -20,15 +20,13 @@
|
|||
//! These are tested as if they are another API directly atop of the ASG,
|
||||
//! since that is how they are used.
|
||||
|
||||
use std::assert_matches::assert_matches;
|
||||
|
||||
use super::*;
|
||||
use crate::{
|
||||
asg::{Ident, Object},
|
||||
asg::Ident,
|
||||
parse::{ParseError, Parsed},
|
||||
span::dummy::*,
|
||||
};
|
||||
|
||||
use super::*;
|
||||
use std::assert_matches::assert_matches;
|
||||
|
||||
type Sut = AirAggregate;
|
||||
|
||||
|
@ -57,7 +55,6 @@ fn ident_decl() {
|
|||
Ok(ident),
|
||||
Ident::declare(SPair(sym, S1))
|
||||
.resolve(S1, kind.clone(), src.clone())
|
||||
.map(Object::Ident)
|
||||
.as_ref(),
|
||||
);
|
||||
|
||||
|
@ -101,7 +98,6 @@ fn ident_extern_decl() {
|
|||
Ok(ident),
|
||||
Ident::declare(SPair(sym, S1))
|
||||
.extern_(S1, kind, src.clone())
|
||||
.map(Object::Ident)
|
||||
.as_ref(),
|
||||
);
|
||||
|
||||
|
@ -174,7 +170,6 @@ fn ident_fragment() {
|
|||
Ident::declare(SPair(sym, S1))
|
||||
.resolve(S1, kind.clone(), src.clone())
|
||||
.and_then(|resolved| resolved.set_fragment(frag))
|
||||
.map(Object::Ident)
|
||||
.as_ref(),
|
||||
);
|
||||
|
||||
|
@ -209,7 +204,7 @@ fn ident_root_missing() {
|
|||
|
||||
// The identifier did not previously exist,
|
||||
// and so a missing node is created as a placeholder.
|
||||
assert_eq!(&Object::Ident(Ident::Missing(SPair(sym, S1))), ident);
|
||||
assert_eq!(&Ident::Missing(SPair(sym, S1)), ident);
|
||||
|
||||
// And that missing identifier should be rooted.
|
||||
assert!(asg.is_rooted(ident_node));
|
||||
|
@ -251,7 +246,6 @@ fn ident_root_existing() {
|
|||
Ok(ident),
|
||||
Ident::declare(SPair(sym, S1))
|
||||
.resolve(S1, kind.clone(), src.clone())
|
||||
.map(Object::Ident)
|
||||
.as_ref()
|
||||
);
|
||||
|
||||
|
|
|
@ -390,10 +390,11 @@ impl Asg {
|
|||
/// between multiple graphs.
|
||||
/// It is nevertheless wrapped in an [`Option`] just in case.
|
||||
#[inline]
|
||||
pub fn get<O: ObjectKind>(&self, index: ObjectIndex<O>) -> Option<&Object> {
|
||||
pub fn get<O: ObjectKind>(&self, index: ObjectIndex<O>) -> Option<&O> {
|
||||
self.graph.node_weight(index.into()).map(|node| {
|
||||
node.as_ref()
|
||||
.expect("internal error: Asg::get missing Node data")
|
||||
.into()
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -563,7 +564,7 @@ impl Asg {
|
|||
/// [`None`] will be returned.
|
||||
#[inline]
|
||||
pub fn get_ident(&self, index: ObjectIndex<Ident>) -> Option<&Ident> {
|
||||
self.get(index).and_then(Object::as_ident_ref)
|
||||
self.get(index)
|
||||
}
|
||||
|
||||
/// Attempt to retrieve an identifier from the graph by name.
|
||||
|
@ -1016,9 +1017,6 @@ mod test {
|
|||
|
||||
// Ensure that the graph was updated with the new object from the
|
||||
// above method.
|
||||
assert_eq!(
|
||||
&Ident::Missing(id_b),
|
||||
sut.get(oi).unwrap().as_ident_ref().unwrap(),
|
||||
);
|
||||
assert_eq!(&Ident::Missing(id_b), sut.get(oi).unwrap(),);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -151,7 +151,7 @@ impl Object {
|
|||
///
|
||||
/// This is an internal method.
|
||||
/// `expected` should contain "a"/"an".
|
||||
fn narrowing_panic(self, expected: &str) -> ! {
|
||||
fn narrowing_panic(&self, expected: &str) -> ! {
|
||||
diagnostic_panic!(
|
||||
self.span()
|
||||
.internal_error(format!(
|
||||
|
@ -176,7 +176,7 @@ impl From<Expr> for Object {
|
|||
}
|
||||
|
||||
impl Into<Ident> for Object {
|
||||
/// Narrow an object into an [`Expr`],
|
||||
/// Narrow an object into an [`Ident`],
|
||||
/// panicing if the object is not of that type.
|
||||
fn into(self) -> Ident {
|
||||
match self {
|
||||
|
@ -197,6 +197,28 @@ impl Into<Expr> for Object {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> Into<&'a Ident> for &'a Object {
|
||||
/// Narrow an object into an [`Ident`],
|
||||
/// panicing if the object is not of that type.
|
||||
fn into(self) -> &'a Ident {
|
||||
match self {
|
||||
Object::Ident(ident) => ident,
|
||||
_ => self.narrowing_panic("an identifier"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Into<&'a Expr> for &'a Object {
|
||||
/// Narrow an object into an [`Expr`],
|
||||
/// panicing if the object is not of that type.
|
||||
fn into(self) -> &'a Expr {
|
||||
match self {
|
||||
Object::Expr(expr) => expr,
|
||||
_ => self.narrowing_panic("an expression"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An [`Object`]-compatbile entity.
|
||||
///
|
||||
/// See [`ObjectIndex`] for more information.
|
||||
|
@ -206,7 +228,10 @@ impl Into<Expr> for Object {
|
|||
///
|
||||
/// Note that [`Object`] is also an [`ObjectKind`],
|
||||
/// if you do not desire narrowing.
|
||||
pub trait ObjectKind = Into<Object> where Object: Into<Self>;
|
||||
pub trait ObjectKind = Into<Object>
|
||||
where
|
||||
Object: Into<Self>,
|
||||
for<'a> &'a Object: Into<&'a Self>;
|
||||
|
||||
/// Index representing an [`Object`] stored on the [`Asg`](super::Asg).
|
||||
///
|
||||
|
|
|
@ -101,7 +101,6 @@ where
|
|||
"missing internal identifier: {}",
|
||||
sym.lookup_str()
|
||||
))
|
||||
.unwrap_ident_ref()
|
||||
}
|
||||
|
||||
/// Check graph for cycles
|
||||
|
@ -520,7 +519,7 @@ mod test {
|
|||
|
||||
let expected = vec![[dep_node, sym_node]
|
||||
.into_iter()
|
||||
.map(|o| asg.get(o).unwrap().as_ident_ref().unwrap().name())
|
||||
.map(|o| asg.get(o).unwrap().name())
|
||||
.collect::<Vec<_>>()];
|
||||
|
||||
match result {
|
||||
|
@ -604,7 +603,7 @@ mod test {
|
|||
.map(|cycle| {
|
||||
cycle
|
||||
.into_iter()
|
||||
.map(|o| asg.get(o).unwrap().as_ident_ref().unwrap().name())
|
||||
.map(|o| asg.get(o).unwrap().name())
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
@ -719,7 +718,7 @@ mod test {
|
|||
|
||||
let expected = vec![[sym3_node, sym2_node, sym1_node]
|
||||
.into_iter()
|
||||
.map(|o| asg.get(o).unwrap().as_ident_ref().unwrap().name())
|
||||
.map(|o| asg.get(o).unwrap().name())
|
||||
.collect::<Vec<_>>()];
|
||||
|
||||
match result {
|
||||
|
@ -787,7 +786,7 @@ mod test {
|
|||
|
||||
let expected = vec![[sym3_node, sym2_node, sym1_node]
|
||||
.into_iter()
|
||||
.map(|o| asg.get(o).unwrap().as_ident_ref().unwrap().name())
|
||||
.map(|o| asg.get(o).unwrap().name())
|
||||
.collect::<Vec<_>>()];
|
||||
|
||||
match result {
|
||||
|
@ -854,7 +853,7 @@ mod test {
|
|||
|
||||
let expected = vec![[sym3_node, sym2_node, sym1_node]
|
||||
.into_iter()
|
||||
.map(|o| asg.get(o).unwrap().as_ident_ref().unwrap().name())
|
||||
.map(|o| asg.get(o).unwrap().name())
|
||||
.collect::<Vec<_>>()];
|
||||
|
||||
match result {
|
||||
|
@ -967,7 +966,7 @@ mod test {
|
|||
|
||||
let expected = vec![[sym3_node, sym2_node, sym1_node]
|
||||
.into_iter()
|
||||
.map(|o| asg.get(o).unwrap().as_ident_ref().unwrap().name())
|
||||
.map(|o| asg.get(o).unwrap().name())
|
||||
.collect::<Vec<_>>()];
|
||||
|
||||
match result {
|
||||
|
|
Loading…
Reference in New Issue