Skip to content

Commit 7be315b

Browse files
authored
refactor: mark functions to create borrowed tables as unsafe (#724)
1 parent 93792db commit 7be315b

File tree

9 files changed

+104
-28
lines changed

9 files changed

+104
-28
lines changed

src/edge_table.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,14 @@ impl EdgeTable {
197197
Ok(Self { table_ })
198198
}
199199

200-
pub(crate) fn new_from_table(
200+
// # Safety
201+
//
202+
// * this fn must NEVER by part of the public API
203+
// * all returned values must only be visible to the public API
204+
// by REFERENCE (& or &mut)
205+
// * the input ptr must not be NULL
206+
// * the input ptr must point to an initialized table
207+
pub(crate) unsafe fn new_from_table(
201208
edges: *mut ll_bindings::tsk_edge_table_t,
202209
) -> Result<Self, TskitError> {
203210
let ptr = std::ptr::NonNull::new(edges).unwrap();

src/individual_table.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,14 @@ impl Iterator for IndividualTableIterator {
183183
}
184184

185185
impl IndividualTable {
186-
pub(crate) fn new_from_table(
186+
// # Safety
187+
//
188+
// * this fn must NEVER by part of the public API
189+
// * all returned values must only be visible to the public API
190+
// by REFERENCE (& or &mut)
191+
// * the input ptr must not be NULL
192+
// * the input ptr must point to an initialized table
193+
pub(crate) unsafe fn new_from_table(
187194
individuals: *mut ll_bindings::tsk_individual_table_t,
188195
) -> Result<Self, TskitError> {
189196
let ptr = std::ptr::NonNull::new(individuals).unwrap();

src/migration_table.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,14 @@ pub struct MigrationTable {
211211
}
212212

213213
impl MigrationTable {
214-
pub(crate) fn new_from_table(
214+
// # Safety
215+
//
216+
// * this fn must NEVER by part of the public API
217+
// * all returned values must only be visible to the public API
218+
// by REFERENCE (& or &mut)
219+
// * the input ptr must not be NULL
220+
// * the input ptr must point to an initialized table
221+
pub(crate) unsafe fn new_from_table(
215222
migrations: *mut ll_bindings::tsk_migration_table_t,
216223
) -> Result<Self, TskitError> {
217224
let ptr = std::ptr::NonNull::new(migrations).unwrap();

src/mutation_table.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,14 @@ pub struct MutationTable {
207207
}
208208

209209
impl MutationTable {
210-
pub(crate) fn new_from_table(
210+
// # Safety
211+
//
212+
// * this fn must NEVER by part of the public API
213+
// * all returned values must only be visible to the public API
214+
// by REFERENCE (& or &mut)
215+
// * the input ptr must not be NULL
216+
// * the input ptr must point to an initialized table
217+
pub(crate) unsafe fn new_from_table(
211218
mutations: *mut ll_bindings::tsk_mutation_table_t,
212219
) -> Result<Self, TskitError> {
213220
let ptr = std::ptr::NonNull::new(mutations).unwrap();

src/node_table.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,14 @@ impl NodeTable {
439439
Ok(Self { table_ })
440440
}
441441

442-
pub(crate) fn new_from_table(
442+
// # Safety
443+
//
444+
// * this fn must NEVER by part of the public API
445+
// * all returned values must only be visible to the public API
446+
// by REFERENCE (& or &mut)
447+
// * the input ptr must not be NULL
448+
// * the input ptr must point to an initialized table
449+
pub(crate) unsafe fn new_from_table(
443450
nodes: *mut ll_bindings::tsk_node_table_t,
444451
) -> Result<Self, TskitError> {
445452
let ptr = std::ptr::NonNull::new(nodes).unwrap();

src/population_table.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,14 @@ pub struct PopulationTable {
157157
}
158158

159159
impl PopulationTable {
160-
pub(crate) fn new_from_table(
160+
// # Safety
161+
//
162+
// * this fn must NEVER by part of the public API
163+
// * all returned values must only be visible to the public API
164+
// by REFERENCE (& or &mut)
165+
// * the input ptr must not be NULL
166+
// * the input ptr must point to an initialized table
167+
pub(crate) unsafe fn new_from_table(
161168
populations: *mut ll_bindings::tsk_population_table_t,
162169
) -> Result<Self, TskitError> {
163170
let ptr = std::ptr::NonNull::new(populations).unwrap();

src/provenance.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,14 @@ pub struct ProvenanceTable {
154154
}
155155

156156
impl ProvenanceTable {
157-
pub(crate) fn new_from_table(
157+
// # Safety
158+
//
159+
// * this fn must NEVER by part of the public API
160+
// * all returned values must only be visible to the public API
161+
// by REFERENCE (& or &mut)
162+
// * the input ptr must not be NULL
163+
// * the input ptr must point to an initialized table
164+
pub(crate) unsafe fn new_from_table(
158165
provenances: *mut ll_bindings::tsk_provenance_table_t,
159166
) -> Result<Self, crate::TskitError> {
160167
let ptr = std::ptr::NonNull::new(provenances).unwrap();

src/site_table.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,14 @@ pub struct SiteTable {
176176
}
177177

178178
impl SiteTable {
179-
pub(crate) fn new_from_table(
179+
// # Safety
180+
//
181+
// * this fn must NEVER by part of the public API
182+
// * all returned values must only be visible to the public API
183+
// by REFERENCE (& or &mut)
184+
// * the input ptr must not be NULL
185+
// * the input ptr must point to an initialized table
186+
pub(crate) unsafe fn new_from_table(
180187
sites: *mut ll_bindings::tsk_site_table_t,
181188
) -> Result<Self, TskitError> {
182189
let ptr = std::ptr::NonNull::new(sites).unwrap();

src/table_collection.rs

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -100,16 +100,24 @@ impl TableCollection {
100100
/// ```
101101
pub fn new<P: Into<Position>>(sequence_length: P) -> Result<Self, TskitError> {
102102
let mut inner = LLTableCollection::new(sequence_length.into().into())?;
103-
let edges = crate::EdgeTable::new_from_table(inner.edges_mut())?;
104-
let nodes = crate::NodeTable::new_from_table(inner.nodes_mut())?;
105-
let sites = crate::SiteTable::new_from_table(inner.sites_mut())?;
106-
let mutations = crate::MutationTable::new_from_table(inner.mutations_mut())?;
107-
let individuals = crate::IndividualTable::new_from_table(inner.individuals_mut())?;
108-
let populations = crate::PopulationTable::new_from_table(inner.populations_mut())?;
109-
let migrations = crate::MigrationTable::new_from_table(inner.migrations_mut())?;
103+
// SAFETY: all the casts to *mut Foo are coming in via an implicit
104+
// cast from &mut Foo, which means that the ptr cannot be NULL.
105+
// Further, successful creation of LLTableCollection means
106+
// that tables are initialized.
107+
// Finally, none of these variables will be pub directly other than
108+
// by reference.
109+
let edges = unsafe { crate::EdgeTable::new_from_table(inner.edges_mut())? };
110+
let nodes = unsafe { crate::NodeTable::new_from_table(inner.nodes_mut())? };
111+
let sites = unsafe { crate::SiteTable::new_from_table(inner.sites_mut())? };
112+
let mutations = unsafe { crate::MutationTable::new_from_table(inner.mutations_mut())? };
113+
let individuals =
114+
unsafe { crate::IndividualTable::new_from_table(inner.individuals_mut())? };
115+
let populations =
116+
unsafe { crate::PopulationTable::new_from_table(inner.populations_mut())? };
117+
let migrations = unsafe { crate::MigrationTable::new_from_table(inner.migrations_mut())? };
110118
#[cfg(feature = "provenance")]
111119
let provenances =
112-
crate::provenance::ProvenanceTable::new_from_table(inner.provenances_mut())?;
120+
unsafe { crate::provenance::ProvenanceTable::new_from_table(inner.provenances_mut())? };
113121
Ok(Self {
114122
inner,
115123
idmap: vec![],
@@ -127,16 +135,24 @@ impl TableCollection {
127135

128136
pub(crate) fn new_from_ll(lltables: LLTableCollection) -> Result<Self, TskitError> {
129137
let mut inner = lltables;
130-
let edges = crate::EdgeTable::new_from_table(inner.edges_mut())?;
131-
let nodes = crate::NodeTable::new_from_table(inner.nodes_mut())?;
132-
let sites = crate::SiteTable::new_from_table(inner.sites_mut())?;
133-
let mutations = crate::MutationTable::new_from_table(inner.mutations_mut())?;
134-
let individuals = crate::IndividualTable::new_from_table(inner.individuals_mut())?;
135-
let populations = crate::PopulationTable::new_from_table(inner.populations_mut())?;
136-
let migrations = crate::MigrationTable::new_from_table(inner.migrations_mut())?;
138+
// SAFETY: all the casts to *mut Foo are coming in via an implicit
139+
// cast from &mut Foo, which means that the ptr cannot be NULL.
140+
// Further, successful creation of LLTableCollection means
141+
// that tables are initialized.
142+
// Finally, none of these variables will be pub directly other than
143+
// by reference.
144+
let edges = unsafe { crate::EdgeTable::new_from_table(inner.edges_mut())? };
145+
let nodes = unsafe { crate::NodeTable::new_from_table(inner.nodes_mut())? };
146+
let sites = unsafe { crate::SiteTable::new_from_table(inner.sites_mut())? };
147+
let mutations = unsafe { crate::MutationTable::new_from_table(inner.mutations_mut())? };
148+
let individuals =
149+
unsafe { crate::IndividualTable::new_from_table(inner.individuals_mut())? };
150+
let populations =
151+
unsafe { crate::PopulationTable::new_from_table(inner.populations_mut())? };
152+
let migrations = unsafe { crate::MigrationTable::new_from_table(inner.migrations_mut())? };
137153
#[cfg(feature = "provenance")]
138154
let provenances =
139-
crate::provenance::ProvenanceTable::new_from_table(inner.provenances_mut())?;
155+
unsafe { crate::provenance::ProvenanceTable::new_from_table(inner.provenances_mut())? };
140156
Ok(Self {
141157
inner,
142158
idmap: vec![],
@@ -1740,10 +1756,14 @@ impl TableCollection {
17401756
}
17411757

17421758
// convert sys version of tables to non-sys version of tables
1743-
let new_edges = EdgeTable::new_from_table(new_edges.as_mut())?;
1744-
let new_migrations = MigrationTable::new_from_table(new_migrations.as_mut())?;
1745-
let new_mutations = MutationTable::new_from_table(new_mutations.as_mut())?;
1746-
let new_sites = SiteTable::new_from_table(new_sites.as_mut())?;
1759+
// SAFETY: all the casts to *mut Foo are coming in via an implicit
1760+
// cast from &mut Foo, which means that the ptr cannot be NULL.
1761+
// Further, all input tables are initialized.
1762+
// Finally, none of these variables will be every be pub.
1763+
let new_edges = unsafe { EdgeTable::new_from_table(new_edges.as_mut())? };
1764+
let new_migrations = unsafe { MigrationTable::new_from_table(new_migrations.as_mut())? };
1765+
let new_mutations = unsafe { MutationTable::new_from_table(new_mutations.as_mut())? };
1766+
let new_sites = unsafe { SiteTable::new_from_table(new_sites.as_mut())? };
17471767

17481768
// replace old tables with new tables
17491769
tables.set_edges(&new_edges).map(|_| ())?;

0 commit comments

Comments
 (0)