···77- New Gleam packages are now generated requiring `>= 1.0.0` of `gleam_stdlib`.
88 ([Surya Rose](https://github.com/GearsDatapacks))
991010+### Bug fixes
1111+1212+- Fixed a bug where certain invalid programs would type check if they contained
1313+ many mutually recursive functions.
1414+ ([Surya Rose](https://github.com/GearsDatapacks))
1515+1016## v1.16.0-rc2 - 2026-04-14
11171218### Bug fixes
···1414 type_::Error,
1515};
1616use itertools::Itertools;
1717-use petgraph::stable_graph::NodeIndex;
1818-use petgraph::{Directed, stable_graph::StableGraph};
1717+use petgraph::{Directed, stable_graph::NodeIndex, stable_graph::StableGraph};
19182019#[derive(Debug, Default)]
2120struct CallGraphBuilder<'a> {
···462461 module: Some(_), ..
463462 } => (),
464463465465- Constant::List { elements, .. } | Constant::Tuple { elements, .. } => {
464464+ Constant::List { elements, tail, .. } => {
465465+ for element in elements {
466466+ self.constant(element);
467467+ }
468468+ if let Some(tail) = tail {
469469+ self.constant(tail);
470470+ }
471471+ }
472472+473473+ Constant::Tuple { elements, .. } => {
466474 for element in elements {
467475 self.constant(element);
468476 }
···536544537545 // Determine the order in which the functions should be compiled by looking
538546 // at which other functions they depend on.
539539- let indices = crate::graph::into_dependency_order(graph);
547547+ let indices = petgraph::algo::tarjan_scc(&graph);
540548541549 // We got node indices back, so we need to map them back to the functions
542550 // they represent.
···11-//! General functions for working with graphs.
22-33-use petgraph::{Direction, prelude::NodeIndex, stable_graph::StableGraph};
44-55-/// Sort a graph into a sequence from the leaves to the roots.
66-///
77-/// Nodes are returned in their smallest possible groups, which is either a leaf
88-/// or a cycle.
99-///
1010-/// This function is implemented using `pop_leaf_or_cycle`.
1111-///
1212-pub fn into_dependency_order<N, E>(mut graph: StableGraph<N, E>) -> Vec<Vec<NodeIndex>> {
1313- let mut items = vec![];
1414-1515- // Remove all self-edges from the graph.
1616- graph.retain_edges(|graph, edge| match graph.edge_endpoints(edge) {
1717- Some((a, b)) => a != b,
1818- None => false,
1919- });
2020-2121- loop {
2222- let current = pop_leaf_or_cycle(&mut graph);
2323- if current.is_empty() {
2424- return items;
2525- } else {
2626- items.push(current);
2727- }
2828- }
2929-}
3030-3131-/// The same as `leaf_or_cycle` but removes the nodes from the graph.
3232-/// See the docs there for more details.
3333-///
3434-/// # Panics
3535-///
3636-/// Panics if the graph contains a self-edge.
3737-///
3838-fn pop_leaf_or_cycle<N, E>(graph: &mut StableGraph<N, E>) -> Vec<NodeIndex> {
3939- let nodes = leaf_or_cycle(graph);
4040- for node in &nodes {
4141- _ = graph.remove_node(*node);
4242- }
4343- nodes
4444-}
4545-4646-/// Return a leaf from the graph. If there are no leaves then the largest cycle
4747-/// is returned instead.
4848-///
4949-/// If there are no leaves or cycles then an empty vector is returned.
5050-///
5151-/// The nodes returned are not removed from the graph.
5252-///
5353-/// # Panics
5454-///
5555-/// Panics if the graph contains a self-edge.
5656-///
5757-fn leaf_or_cycle<N, E>(graph: &StableGraph<N, E>) -> Vec<NodeIndex> {
5858- if graph.node_count() == 0 {
5959- return vec![];
6060- }
6161-6262- // Find a leaf, returning one if found.
6363- for node in graph.node_indices() {
6464- let mut outgoing = graph.neighbors_directed(node, Direction::Outgoing);
6565- let referenced = outgoing.next();
6666-6767- if referenced == Some(node) {
6868- panic!("Self edge found in graph");
6969- }
7070-7171- // This is a leaf.
7272- if referenced.is_none() {
7373- return vec![node];
7474- }
7575- }
7676-7777- // No leaves were found, so find a cycle.
7878- // We use a toposort to find the start of the cycle.
7979- let start = petgraph::algo::toposort(&graph, None)
8080- .expect_err("Non-empty graph has no leaves or cycles")
8181- .node_id();
8282-8383- // Then traverse the graph to find nodes in the cycle.
8484- // This traverses all possible paths to find a cycle, this can likely be
8585- // optimised. There's not a large number of functions in a module however so
8686- // this is tolerable in this specific instance.
8787- #[derive(Debug)]
8888- enum Step {
8989- Backtrack,
9090- Next(NodeIndex),
9191- }
9292- let mut path = vec![];
9393- let mut stack = vec![Step::Next(start)];
9494- let mut cycles = vec![];
9595-9696- while let Some(step) = stack.pop() {
9797- let node = match step {
9898- // We have processed all the nodes in the branch so backtrack,
9999- // popping the node off the path.
100100- Step::Backtrack => {
101101- _ = path.pop();
102102- continue;
103103- }
104104- Step::Next(node) => node,
105105- };
106106-107107- if path.contains(&node) {
108108- continue;
109109- }
110110-111111- // Add this node to the path and record the point at which we need to
112112- // backtrack in order to go back up the tree.
113113- stack.push(Step::Backtrack);
114114- path.push(node);
115115-116116- // Check each child & add them to the stack if they are not the target.
117117- for node in graph.neighbors_directed(node, Direction::Outgoing) {
118118- if node == start {
119119- cycles.push(path.clone());
120120- } else {
121121- stack.push(Step::Next(node));
122122- }
123123- }
124124- }
125125-126126- cycles
127127- .into_iter()
128128- .max_by_key(|x| x.len())
129129- .expect("Could not find cycle for toposort returned start node")
130130-}
131131-132132-#[cfg(test)]
133133-mod tests {
134134- use super::*;
135135-136136- #[test]
137137- fn leaf_or_cycle_empty() {
138138- let mut graph: StableGraph<(), ()> = StableGraph::new();
139139- assert!(pop_leaf_or_cycle(&mut graph).is_empty());
140140- }
141141-142142- #[test]
143143- fn leaf_or_cycle_1() {
144144- let mut graph: StableGraph<(), ()> = StableGraph::new();
145145- let a = graph.add_node(());
146146- assert_eq!(into_dependency_order(graph), vec![vec![a]]);
147147- }
148148-149149- #[test]
150150- fn leaf_or_cycle_2() {
151151- let mut graph: StableGraph<(), ()> = StableGraph::new();
152152- let a = graph.add_node(());
153153- let b = graph.add_node(());
154154-155155- assert_eq!(into_dependency_order(graph), vec![vec![a], vec![b]]);
156156- }
157157-158158- #[test]
159159- fn leaf_or_cycle_3() {
160160- let mut graph: StableGraph<(), ()> = StableGraph::new();
161161- // Here a depends on b so b must come before a
162162- let a = graph.add_node(());
163163- let b = graph.add_node(());
164164- let c = graph.add_node(());
165165- _ = graph.add_edge(a, b, ());
166166-167167- assert_eq!(
168168- into_dependency_order(graph),
169169- vec![vec![b], vec![a], vec![c]]
170170- );
171171- }
172172-173173- #[test]
174174- fn leaf_or_cycle_4() {
175175- let mut graph: StableGraph<(), ()> = StableGraph::new();
176176- let a = graph.add_node(());
177177- let b = graph.add_node(());
178178- let c = graph.add_node(());
179179- _ = graph.add_edge(a, b, ());
180180- _ = graph.add_edge(a, c, ());
181181-182182- assert_eq!(
183183- into_dependency_order(graph),
184184- vec![vec![b], vec![c], vec![a]]
185185- );
186186- }
187187-188188- #[test]
189189- fn leaf_or_cycle_5() {
190190- let mut graph: StableGraph<(), ()> = StableGraph::new();
191191- let a = graph.add_node(());
192192- let b = graph.add_node(());
193193- let c = graph.add_node(());
194194- _ = graph.add_edge(a, b, ());
195195- _ = graph.add_edge(b, a, ());
196196-197197- assert_eq!(into_dependency_order(graph), vec![vec![c], vec![b, a]]);
198198- }
199199-200200- #[test]
201201- fn leaf_or_cycle_6() {
202202- let mut graph: StableGraph<(), ()> = StableGraph::new();
203203- let a = graph.add_node(());
204204- let b = graph.add_node(());
205205- let c = graph.add_node(());
206206- let d = graph.add_node(());
207207- _ = graph.add_edge(a, b, ());
208208- _ = graph.add_edge(b, c, ());
209209- _ = graph.add_edge(c, a, ());
210210- _ = graph.add_edge(d, a, ());
211211-212212- assert_eq!(into_dependency_order(graph), vec![vec![c, a, b], vec![d]]);
213213- }
214214-215215- #[test]
216216- fn leaf_or_cycle_7() {
217217- let mut graph: StableGraph<(), ()> = StableGraph::new();
218218- let a = graph.add_node(());
219219- let b = graph.add_node(());
220220- _ = graph.add_edge(a, a, ());
221221- _ = graph.add_edge(a, b, ());
222222- _ = graph.add_edge(b, b, ());
223223-224224- // Here there are no true leafs, only cycles. However, b is in a loop
225225- // with itself so counts as a leaf as far as we are concerned.
226226-227227- assert_eq!(into_dependency_order(graph), vec![vec![b], vec![a]]);
228228- }
229229-230230- #[test]
231231- fn leaf_or_cycle_8() {
232232- let mut graph: StableGraph<(), ()> = StableGraph::new();
233233- let a = graph.add_node(());
234234- let b = graph.add_node(());
235235- _ = graph.add_edge(a, a, ());
236236- _ = graph.add_edge(a, b, ());
237237- _ = graph.add_edge(b, b, ());
238238- _ = graph.add_edge(b, b, ());
239239- _ = graph.add_edge(b, b, ());
240240-241241- // Here there are no true leafs, only cycles. However, b is in a loop
242242- // with itself so counts as a leaf as far as we are concerned.
243243- // This is different from the previous test as there are multiple self
244244- // references for node b.
245245-246246- assert_eq!(into_dependency_order(graph), vec![vec![b], vec![a]]);
247247- }
248248-249249- #[test]
250250- fn leaf_or_cycle_9() {
251251- let mut graph: StableGraph<(), ()> = StableGraph::new();
252252- let a = graph.add_node(());
253253- let b = graph.add_node(());
254254- let c = graph.add_node(());
255255-256256- _ = graph.add_edge(a, a, ());
257257- _ = graph.add_edge(a, b, ());
258258-259259- _ = graph.add_edge(b, b, ());
260260- _ = graph.add_edge(b, c, ());
261261-262262- _ = graph.add_edge(c, b, ());
263263- _ = graph.add_edge(c, c, ());
264264-265265- // Here there are no true leafs, only cycles. However, b is in a loop
266266- // with itself so counts as a leaf as far as we are concerned.
267267- // This is different from the previous test as there are multiple self
268268- // references for node b.
269269-270270- assert_eq!(into_dependency_order(graph), vec![vec![c, b], vec![a]]);
271271- }
272272-}
···2525 UtfCodepoint as $UtfCodepoint,
2626} from "../gleam.mjs";
27272828-function wibble(n, m) {
2929- return n + m;
3030-}
3131-3228function message() {
3329 return "Hello!";
3030+}
3131+3232+function wibble(n, m) {
3333+ return n + m;
3434}
35353636export function main() {
···9595mod dep_tree;
9696pub(crate) mod derivation_tree;
9797pub mod exhaustiveness;
9898-pub(crate) mod graph;
9998pub(crate) mod inline;
10099pub mod reference;
101100