tamer: ld::xmle::sections: Remove generic object type
xmle sections will only ever contain an object of one type, so there is no use in making this generic. I think the original plan was to have this represent, generically, sections of some object file (like ELF), but doing so would require a significant redesign anyway, so it makes no sense. This is easier to reason about. DEV-10859main
parent
31144d0c9a
commit
08d92ca663
|
@ -212,7 +212,7 @@ fn get_ident<'a>(
|
|||
|
||||
fn output_xmle<'a>(
|
||||
depgraph: &'a LinkerAsg,
|
||||
sorted: &mut Sections<'a, IdentObject>,
|
||||
sorted: &mut Sections<'a>,
|
||||
name: SymbolId,
|
||||
relroot: SymbolId,
|
||||
output: &str,
|
||||
|
|
|
@ -24,8 +24,8 @@
|
|||
use super::Sections;
|
||||
use crate::{
|
||||
ir::asg::{
|
||||
Asg, BaseAsg, IdentKind, IdentObjectData, IdentObjectState, IndexType,
|
||||
ObjectRef, UnresolvedError,
|
||||
Asg, BaseAsg, IdentKind, IdentObject, IdentObjectData,
|
||||
IdentObjectState, IndexType, ObjectRef, UnresolvedError,
|
||||
},
|
||||
sym::GlobalSymbolResolve,
|
||||
};
|
||||
|
@ -39,13 +39,12 @@ pub type SortResult<T, Ix> = Result<T, SortError<Ix>>;
|
|||
/// This performs the equivalent of a topological sort,
|
||||
/// although function cycles are permitted.
|
||||
/// The actual operation performed is a post-order depth-first traversal.
|
||||
pub fn sort<'a, O, Ix>(
|
||||
asg: &'a BaseAsg<O, Ix>,
|
||||
pub fn sort<'a, Ix>(
|
||||
asg: &'a BaseAsg<IdentObject, Ix>,
|
||||
roots: &[ObjectRef<Ix>],
|
||||
) -> SortResult<Sections<'a, O>, Ix>
|
||||
) -> SortResult<Sections<'a>, Ix>
|
||||
where
|
||||
Ix: IndexType,
|
||||
O: IdentObjectData + IdentObjectState<O>,
|
||||
{
|
||||
let mut deps = Sections::new();
|
||||
|
||||
|
@ -101,10 +100,9 @@ where
|
|||
///
|
||||
/// We loop through all SCCs and check that they are not all functions. If
|
||||
/// they are, we ignore the cycle, otherwise we will return an error.
|
||||
fn check_cycles<O, Ix>(asg: &BaseAsg<O, Ix>) -> SortResult<(), Ix>
|
||||
fn check_cycles<Ix>(asg: &BaseAsg<IdentObject, Ix>) -> SortResult<(), Ix>
|
||||
where
|
||||
Ix: IndexType,
|
||||
O: IdentObjectData + IdentObjectState<O>,
|
||||
{
|
||||
// While `tarjan_scc` does do a topological sort, it does not suit our
|
||||
// needs because we need to filter out some allowed cycles. It would
|
||||
|
@ -209,95 +207,16 @@ impl<Ix: IndexType> std::error::Error for SortError<Ix> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::cell::RefCell;
|
||||
|
||||
use super::*;
|
||||
use crate::{
|
||||
ir::{
|
||||
asg::{
|
||||
DataType, Dim, FragmentText, IdentObject, Source,
|
||||
TransitionResult,
|
||||
},
|
||||
asg::{DataType, Dim, FragmentText, IdentObject, Source},
|
||||
legacyir::SymDtype,
|
||||
},
|
||||
sym::{GlobalSymbolIntern, SymbolId},
|
||||
sym::GlobalSymbolIntern,
|
||||
};
|
||||
|
||||
#[derive(Debug, Default, PartialEq)]
|
||||
struct StubIdentObject {
|
||||
given_declare: Option<SymbolId>,
|
||||
given_extern: Option<(IdentKind, Source)>,
|
||||
given_resolve: Option<(IdentKind, Source)>,
|
||||
given_set_fragment: Option<FragmentText>,
|
||||
fail_resolved: RefCell<Option<UnresolvedError>>,
|
||||
}
|
||||
|
||||
impl<'i> IdentObjectData for StubIdentObject {
|
||||
fn name(&self) -> Option<SymbolId> {
|
||||
self.given_declare
|
||||
}
|
||||
|
||||
fn kind(&self) -> Option<&IdentKind> {
|
||||
self.given_resolve.as_ref().map(|args| &args.0)
|
||||
}
|
||||
|
||||
fn src(&self) -> Option<&Source> {
|
||||
None
|
||||
}
|
||||
|
||||
fn fragment(&self) -> Option<&FragmentText> {
|
||||
None
|
||||
}
|
||||
|
||||
fn as_ident(&self) -> Option<&IdentObject> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<'i> IdentObjectState<StubIdentObject> for StubIdentObject {
|
||||
fn declare(ident: SymbolId) -> Self {
|
||||
Self {
|
||||
given_declare: Some(ident),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve(
|
||||
mut self,
|
||||
kind: IdentKind,
|
||||
src: Source,
|
||||
) -> TransitionResult<StubIdentObject> {
|
||||
self.given_resolve = Some((kind, src));
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
fn resolved(&self) -> Result<&StubIdentObject, UnresolvedError> {
|
||||
if self.fail_resolved.borrow().is_some() {
|
||||
return Err(self.fail_resolved.replace(None).unwrap());
|
||||
}
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
fn extern_(
|
||||
mut self,
|
||||
kind: IdentKind,
|
||||
src: Source,
|
||||
) -> TransitionResult<StubIdentObject> {
|
||||
self.given_extern = Some((kind, src));
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
fn set_fragment(
|
||||
mut self,
|
||||
text: FragmentText,
|
||||
) -> TransitionResult<StubIdentObject> {
|
||||
self.given_set_fragment.replace(text);
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
type Sut = BaseAsg<StubIdentObject, u16>;
|
||||
type Sut = BaseAsg<IdentObject, u16>;
|
||||
|
||||
macro_rules! assert_section_sym {
|
||||
( $iterable:expr, $s:ident ) => {{
|
||||
|
@ -397,9 +316,9 @@ mod test {
|
|||
|
||||
match sort(&sut, &vec![sym_node]) {
|
||||
Ok(_) => panic!("Unexpected success - dependency is not in graph"),
|
||||
Err(SortError::MissingObjectKind(_)) => (),
|
||||
_ => {
|
||||
panic!("Incorrect error result when dependency is not in graph")
|
||||
Err(SortError::UnresolvedObject(_)) => (),
|
||||
bad => {
|
||||
panic!("Incorrect error result when dependency is not in graph: {:?}", bad)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -969,33 +888,4 @@ mod test {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// A graph containing unresolved objects cannot be sorted.
|
||||
#[test]
|
||||
fn graph_sort_fail_unresolved() -> SortResult<(), u16> {
|
||||
let mut sut = Sut::new();
|
||||
|
||||
let sym = "unresolved".intern();
|
||||
let node = sut
|
||||
.declare(sym, IdentKind::Meta, Default::default())
|
||||
.unwrap();
|
||||
let ident = sut.get(node).unwrap();
|
||||
|
||||
let expected = UnresolvedError::Missing { name: sym };
|
||||
|
||||
// Cause resolved() to fail.
|
||||
ident.fail_resolved.replace(Some(expected.clone()));
|
||||
|
||||
let result = sort(&sut, &vec![node])
|
||||
.expect_err("expected sort failure due to unresolved identifier");
|
||||
|
||||
match result {
|
||||
SortError::UnresolvedObject(err) => {
|
||||
assert_eq!(expected, err);
|
||||
}
|
||||
_ => panic!("expected SortError::Unresolved: {:?}", result),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
//! which places the relocatable object code fragments in the order
|
||||
//! necessary for execution.
|
||||
|
||||
use crate::ir::asg::IdentObjectData;
|
||||
use crate::ir::asg::{IdentObject, IdentObjectData};
|
||||
use crate::sym::SymbolId;
|
||||
use fxhash::FxHashSet;
|
||||
use std::collections::hash_set;
|
||||
|
@ -37,13 +37,13 @@ use std::slice::Iter;
|
|||
/// information. Rather than dealing with those differently, each `Section`
|
||||
/// will have a `head` and `tail` that are empty by default.
|
||||
#[derive(Clone, Debug, Default, PartialEq)]
|
||||
pub struct Section<'a, T> {
|
||||
head: Option<&'a T>,
|
||||
body: Vec<&'a T>,
|
||||
tail: Option<&'a T>,
|
||||
pub struct Section<'a> {
|
||||
head: Option<&'a IdentObject>,
|
||||
body: Vec<&'a IdentObject>,
|
||||
tail: Option<&'a IdentObject>,
|
||||
}
|
||||
|
||||
impl<'a, T> Section<'a, T> {
|
||||
impl<'a> Section<'a> {
|
||||
/// New empty section.
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
|
@ -61,26 +61,26 @@ impl<'a, T> Section<'a, T> {
|
|||
|
||||
/// Push an `IdentObject` into a `Section`'s head
|
||||
#[inline]
|
||||
pub fn set_head(&mut self, obj: &'a T) {
|
||||
pub fn set_head(&mut self, obj: &'a IdentObject) {
|
||||
self.head.replace(obj);
|
||||
}
|
||||
|
||||
/// Push an `IdentObject` into a `Section`'s body
|
||||
#[inline]
|
||||
pub fn push_body(&mut self, obj: &'a T) {
|
||||
pub fn push_body(&mut self, obj: &'a IdentObject) {
|
||||
self.body.push(obj)
|
||||
}
|
||||
|
||||
/// Push an `IdentObject` into a `Section`'s tail
|
||||
#[inline]
|
||||
pub fn set_tail(&mut self, obj: &'a T) {
|
||||
pub fn set_tail(&mut self, obj: &'a IdentObject) {
|
||||
self.tail.replace(obj);
|
||||
}
|
||||
|
||||
/// Construct a new iterator visiting each head, body, and tail object
|
||||
/// in order.
|
||||
#[inline]
|
||||
pub fn iter(&self) -> SectionIter<T> {
|
||||
pub fn iter(&self) -> SectionIter {
|
||||
SectionIter(
|
||||
self.head
|
||||
.iter()
|
||||
|
@ -95,15 +95,15 @@ impl<'a, T> Section<'a, T> {
|
|||
/// This iterator should be created with [`Section::iter`].
|
||||
///
|
||||
/// This hides the complex iterator type from callers.
|
||||
pub struct SectionIter<'a, T>(
|
||||
pub struct SectionIter<'a>(
|
||||
Chain<
|
||||
Chain<option::Iter<'a, &'a T>, Iter<'a, &'a T>>,
|
||||
option::Iter<'a, &'a T>,
|
||||
Chain<option::Iter<'a, &'a IdentObject>, Iter<'a, &'a IdentObject>>,
|
||||
option::Iter<'a, &'a IdentObject>,
|
||||
>,
|
||||
);
|
||||
|
||||
impl<'a, T> Iterator for SectionIter<'a, T> {
|
||||
type Item = &'a T;
|
||||
impl<'a> Iterator for SectionIter<'a> {
|
||||
type Item = &'a IdentObject;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
|
@ -122,14 +122,14 @@ impl<'a, T> Iterator for SectionIter<'a, T> {
|
|||
/// [object file](crate::obj).
|
||||
// TODO: Remove pub
|
||||
#[derive(Debug, Default, PartialEq)]
|
||||
pub struct Sections<'a, T> {
|
||||
pub map: Section<'a, T>,
|
||||
pub retmap: Section<'a, T>,
|
||||
pub st: Section<'a, T>,
|
||||
pub rater: Section<'a, T>,
|
||||
pub struct Sections<'a> {
|
||||
pub map: Section<'a>,
|
||||
pub retmap: Section<'a>,
|
||||
pub st: Section<'a>,
|
||||
pub rater: Section<'a>,
|
||||
}
|
||||
|
||||
impl<'a, T: IdentObjectData> Sections<'a, T> {
|
||||
impl<'a> Sections<'a> {
|
||||
/// New collection of empty sections.
|
||||
#[inline]
|
||||
pub fn new() -> Self {
|
||||
|
@ -152,7 +152,7 @@ impl<'a, T: IdentObjectData> Sections<'a, T> {
|
|||
/// they are chained in the same order in which they are defined
|
||||
/// on the [`Sections`] struct.
|
||||
#[inline]
|
||||
pub fn iter_all(&self) -> SectionsIter<T> {
|
||||
pub fn iter_all(&self) -> SectionsIter {
|
||||
SectionsIter(SectionsIterType::All(
|
||||
self.map
|
||||
.iter()
|
||||
|
@ -173,13 +173,13 @@ impl<'a, T: IdentObjectData> Sections<'a, T> {
|
|||
/// appear in;
|
||||
/// they may change or be combined in the future.
|
||||
#[inline]
|
||||
pub fn iter_static(&self) -> SectionsIter<T> {
|
||||
pub fn iter_static(&self) -> SectionsIter {
|
||||
SectionsIter(SectionsIterType::Single(self.st.iter()))
|
||||
}
|
||||
|
||||
/// Construct an iterator over the map section.
|
||||
#[inline]
|
||||
pub fn iter_map(&self) -> SectionsIter<T> {
|
||||
pub fn iter_map(&self) -> SectionsIter {
|
||||
SectionsIter(SectionsIterType::Single(self.map.iter()))
|
||||
}
|
||||
|
||||
|
@ -199,13 +199,13 @@ impl<'a, T: IdentObjectData> Sections<'a, T> {
|
|||
|
||||
/// Construct an iterator over the return map section.
|
||||
#[inline]
|
||||
pub fn iter_retmap(&self) -> SectionsIter<T> {
|
||||
pub fn iter_retmap(&self) -> SectionsIter {
|
||||
SectionsIter(SectionsIterType::Single(self.retmap.iter()))
|
||||
}
|
||||
|
||||
/// Construct an iterator over the executable `rater` section.
|
||||
#[inline]
|
||||
pub fn iter_exec(&self) -> SectionsIter<T> {
|
||||
pub fn iter_exec(&self) -> SectionsIter {
|
||||
SectionsIter(SectionsIterType::Single(self.rater.iter()))
|
||||
}
|
||||
}
|
||||
|
@ -213,15 +213,15 @@ impl<'a, T: IdentObjectData> Sections<'a, T> {
|
|||
// Compose the chained iterator type for [`SectionsIter`].
|
||||
// This could be further abstracted away,
|
||||
// but it's likely that `Sections` will be simplified in the future.
|
||||
type SIter<'a, T> = SectionIter<'a, T>;
|
||||
type CSIter1<'a, T, L> = Chain<L, SIter<'a, T>>;
|
||||
type CSIter2<'a, T, L> = CSIter1<'a, T, CSIter1<'a, T, L>>;
|
||||
type SIter4<'a, T> = CSIter2<'a, T, CSIter1<'a, T, SIter<'a, T>>>;
|
||||
type SIter<'a> = SectionIter<'a>;
|
||||
type CSIter1<'a, L> = Chain<L, SIter<'a>>;
|
||||
type CSIter2<'a, L> = CSIter1<'a, CSIter1<'a, L>>;
|
||||
type SIter4<'a> = CSIter2<'a, CSIter1<'a, SIter<'a>>>;
|
||||
|
||||
/// Types of iterators encapsulated by [`SectionsIter`].
|
||||
enum SectionsIterType<'a, T> {
|
||||
All(SIter4<'a, T>),
|
||||
Single(SIter<'a, T>),
|
||||
enum SectionsIterType<'a> {
|
||||
All(SIter4<'a>),
|
||||
Single(SIter<'a>),
|
||||
}
|
||||
|
||||
/// Iterator over each of the sections.
|
||||
|
@ -229,10 +229,10 @@ enum SectionsIterType<'a, T> {
|
|||
/// This iterator should be created with [`Sections::iter_all`].
|
||||
///
|
||||
/// This hides the complex iterator type from callers.
|
||||
pub struct SectionsIter<'a, T>(SectionsIterType<'a, T>);
|
||||
pub struct SectionsIter<'a>(SectionsIterType<'a>);
|
||||
|
||||
impl<'a, T> Iterator for SectionsIter<'a, T> {
|
||||
type Item = &'a T;
|
||||
impl<'a> Iterator for SectionsIter<'a> {
|
||||
type Item = &'a IdentObject;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
|
@ -257,7 +257,7 @@ mod test {
|
|||
use crate::ir::asg::{IdentKind, IdentObject, Source};
|
||||
use crate::sym::GlobalSymbolIntern;
|
||||
|
||||
type Sut<'a> = Section<'a, IdentObject>;
|
||||
type Sut<'a> = Section<'a>;
|
||||
|
||||
#[test]
|
||||
fn section_empty() {
|
||||
|
|
|
@ -29,16 +29,15 @@
|
|||
//! which can then use [`XmlWriter`](crate::ir::xir::writer::XmlWriter)
|
||||
//! for writing.
|
||||
|
||||
use super::{Sections, SectionsIter};
|
||||
use super::{super::LSPAN, Sections, SectionsIter};
|
||||
use crate::{
|
||||
ir::{
|
||||
asg::{IdentKind, IdentObject, IdentObjectData},
|
||||
asg::{IdentKind, IdentObject},
|
||||
xir::{
|
||||
iter::{elem_wrap, ElemWrapIter},
|
||||
AttrValue, QName, Text, Token,
|
||||
},
|
||||
},
|
||||
ld::LSPAN,
|
||||
sym::{st::*, SymbolId},
|
||||
};
|
||||
use arrayvec::ArrayVec;
|
||||
|
@ -117,18 +116,18 @@ const DEP_TOK_SIZE: usize = DEP_MAX_ATTRS_KEY_VAL + DEP_CLOSE;
|
|||
/// another object is requested and the buffer populated with the
|
||||
/// appropriate token stream.
|
||||
/// This repeats until no more section object data is available.
|
||||
struct DepListIter<'a, T: IdentObjectData> {
|
||||
struct DepListIter<'a> {
|
||||
/// Source data to lower into `l:deps`.
|
||||
iter: SectionsIter<'a, T>,
|
||||
iter: SectionsIter<'a>,
|
||||
/// Constant-size [`Token`] buffer used as a stack.
|
||||
toks: ArrayVec<Token, DEP_TOK_SIZE>,
|
||||
/// Relative path to project root.
|
||||
relroot: AttrValue,
|
||||
}
|
||||
|
||||
impl<'a, T: IdentObjectData> DepListIter<'a, T> {
|
||||
impl<'a> DepListIter<'a> {
|
||||
#[inline]
|
||||
fn new(sections: &'a Sections<T>, relroot: SymbolId) -> Self {
|
||||
fn new(sections: &'a Sections, relroot: SymbolId) -> Self {
|
||||
Self {
|
||||
iter: sections.iter_all(),
|
||||
toks: ArrayVec::new(),
|
||||
|
@ -151,14 +150,12 @@ impl<'a, T: IdentObjectData> DepListIter<'a, T> {
|
|||
// that we can diff the two;
|
||||
// TODO: re-order sensibly once we're done.
|
||||
self.iter.next().map(|obj| {
|
||||
let ident = obj.as_ident().expect("unexpected non-identifier object");
|
||||
|
||||
match ident {
|
||||
match obj {
|
||||
IdentObject::Ident(sym, kind, src)
|
||||
| IdentObject::IdentFragment(sym, kind, src, _) => (*sym, kind, src),
|
||||
_ => unreachable!(
|
||||
"identifier should have been filtered out during sorting: {:?}",
|
||||
ident,
|
||||
obj,
|
||||
),
|
||||
}
|
||||
}).and_then(|(sym, kind, src)| {
|
||||
|
@ -241,7 +238,7 @@ impl<'a, T: IdentObjectData> DepListIter<'a, T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, T: IdentObjectData> Iterator for DepListIter<'a, T> {
|
||||
impl<'a> Iterator for DepListIter<'a> {
|
||||
type Item = Token;
|
||||
|
||||
#[inline]
|
||||
|
@ -265,7 +262,7 @@ struct MapFromsIter {
|
|||
|
||||
impl MapFromsIter {
|
||||
#[inline]
|
||||
fn new<'a, T: IdentObjectData>(sections: &'a Sections<T>) -> Self {
|
||||
fn new<'a>(sections: &'a Sections) -> Self {
|
||||
let iter = Self {
|
||||
iter: sections.iter_map_froms_uniq(),
|
||||
// Most of the time we have a single `from` (4 tokens).
|
||||
|
@ -301,18 +298,18 @@ impl Iterator for MapFromsIter {
|
|||
/// Produce text fragments associated with objects.
|
||||
///
|
||||
/// Here, "text" refers to the compiled program text.
|
||||
struct FragmentIter<'a, T> {
|
||||
iter: SectionsIter<'a, T>,
|
||||
struct FragmentIter<'a> {
|
||||
iter: SectionsIter<'a>,
|
||||
}
|
||||
|
||||
impl<'a, T: IdentObjectData> FragmentIter<'a, T> {
|
||||
impl<'a> FragmentIter<'a> {
|
||||
#[inline]
|
||||
fn new(iter: SectionsIter<'a, T>) -> Self {
|
||||
fn new(iter: SectionsIter<'a>) -> Self {
|
||||
Self { iter }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: IdentObjectData> Iterator for FragmentIter<'a, T> {
|
||||
impl<'a> Iterator for FragmentIter<'a> {
|
||||
type Item = Token;
|
||||
|
||||
#[inline]
|
||||
|
@ -320,8 +317,7 @@ impl<'a, T: IdentObjectData> Iterator for FragmentIter<'a, T> {
|
|||
self.iter
|
||||
.by_ref()
|
||||
.filter_map(|obj| {
|
||||
match obj.as_ident().expect("encountered non-identifier object")
|
||||
{
|
||||
match obj {
|
||||
IdentObject::IdentFragment(_, _, _, frag) => Some(*frag),
|
||||
|
||||
// These will never have fragments.
|
||||
|
@ -345,28 +341,28 @@ impl<'a, T: IdentObjectData> Iterator for FragmentIter<'a, T> {
|
|||
/// having to resort to dynamic dispatch,
|
||||
/// since this iterator will receive over a million calls on larger
|
||||
/// programs (and hundreds of thousands on smaller).
|
||||
pub struct LowerIter<'a, T: IdentObjectData>(
|
||||
pub struct LowerIter<'a>(
|
||||
ElemWrapIter<
|
||||
Chain<
|
||||
Chain<
|
||||
Chain<
|
||||
Chain<
|
||||
Chain<
|
||||
Chain<HeaderIter, ElemWrapIter<DepListIter<'a, T>>>,
|
||||
Chain<HeaderIter, ElemWrapIter<DepListIter<'a>>>,
|
||||
ElemWrapIter<MapFromsIter>,
|
||||
>,
|
||||
ElemWrapIter<FragmentIter<'a, T>>,
|
||||
ElemWrapIter<FragmentIter<'a>>,
|
||||
>,
|
||||
ElemWrapIter<FragmentIter<'a, T>>,
|
||||
ElemWrapIter<FragmentIter<'a>>,
|
||||
>,
|
||||
ElemWrapIter<FragmentIter<'a, T>>,
|
||||
ElemWrapIter<FragmentIter<'a>>,
|
||||
>,
|
||||
ElemWrapIter<FragmentIter<'a, T>>,
|
||||
ElemWrapIter<FragmentIter<'a>>,
|
||||
>,
|
||||
>,
|
||||
);
|
||||
|
||||
impl<'a, T: IdentObjectData> Iterator for LowerIter<'a, T> {
|
||||
impl<'a> Iterator for LowerIter<'a> {
|
||||
type Item = Token;
|
||||
|
||||
/// Produce the next XIR [`Token`] representing the lowering of
|
||||
|
@ -388,11 +384,11 @@ impl<'a, T: IdentObjectData> Iterator for LowerIter<'a, T> {
|
|||
/// which can be written using
|
||||
/// [`XmlWriter`](crate::ir::xir::writer::XmlWriter).
|
||||
#[inline]
|
||||
pub fn lower_iter<'a, T: IdentObjectData>(
|
||||
sections: &'a Sections<T>,
|
||||
pub fn lower_iter<'a>(
|
||||
sections: &'a Sections,
|
||||
pkg_name: SymbolId,
|
||||
relroot: SymbolId,
|
||||
) -> LowerIter<'a, T> {
|
||||
) -> LowerIter<'a> {
|
||||
LowerIter(elem_wrap(
|
||||
QN_PACKAGE,
|
||||
LSPAN,
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
use super::*;
|
||||
use crate::convert::ExpectInto;
|
||||
use crate::ir::asg::IdentObjectData;
|
||||
use crate::ir::legacyir::SymDtype;
|
||||
use crate::ir::{
|
||||
asg::{Dim, IdentKind, Source},
|
||||
|
@ -44,7 +45,7 @@ macro_rules! assert_attr{
|
|||
|
||||
#[test]
|
||||
fn test_produces_header() -> TestResult {
|
||||
let empty = Sections::<IdentObject>::new();
|
||||
let empty = Sections::new();
|
||||
let name = "test-pkg".intern();
|
||||
let relroot = "rel/root/".intern();
|
||||
|
||||
|
@ -63,7 +64,7 @@ fn test_produces_header() -> TestResult {
|
|||
|
||||
#[test]
|
||||
fn test_closes_package() -> TestResult {
|
||||
let empty = Sections::<IdentObject>::new();
|
||||
let empty = Sections::new();
|
||||
|
||||
let result = lower_iter(&empty, "foo".intern(), "relroot".intern()).last();
|
||||
|
||||
|
@ -212,7 +213,7 @@ fn test_writes_deps() -> TestResult {
|
|||
});
|
||||
|
||||
p_syms.enumerate().for_each(|(i, ele)| {
|
||||
let ident = objs[i].as_ident().unwrap();
|
||||
let ident = &objs[i];
|
||||
let attrs = ele.attrs();
|
||||
|
||||
assert_eq!(
|
||||
|
|
Loading…
Reference in New Issue