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-13160
main
Mike Gerwitz 2022-12-22 16:32:21 -05:00
parent 6e90867212
commit 0863536149
4 changed files with 42 additions and 26 deletions

View File

@ -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()
);

View File

@ -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(),);
}
}

View File

@ -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).
///

View File

@ -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 {