Learning Rust, like with any new programming language, requires learning the language of compiler error messages, which is partly about the Rust language itself and partly how Rust programmers talk about the language. One of the first error messages that tripped me up was when I was attempting to return a Result.

I wrote a function that had a syntax error like this one:

fn get_num() -> Result<i32, &'static str> {
  let result = 4;
  OK(result);
}

Which generates this error:

   |
11 | fn get_num() -> Result<i32, &'static str> {
   |    -------      ^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found ()
   |    |
   |    implicitly returns `()` as its body has no tail or `return` expression
12 |   let result = 4;
13 |   OK(result);
   |             - help: consider removing this semicolon
   |
   = note: expected type `std::result::Result<i32, &'static str>`
              found type `()`

So, of course, I remove the semicolon, which leads to this error:

error[E0425]: cannot find function `OK` in this scope
  --> examples/tuple.rs:13:3
   |
13 |   OK(result)
   |   ^^ help: a tuple variant with a similar name exists: `Ok`

The compiler doesn’t know what I’m attempting to do, so it gives me two possibilities:
1. cannot find function OK
2. a tuple variant with a similar name exists: Ok

When I first saw this error, I thought the second part was simply pointing out the location of the error and giving me more detail. I spent a few hours trying to figure out where I had created a conflicting tuple variant… and what the heck was a tuple variant? I copy/pasted seemingly identical code and somehow the problem went away but I didn’t know what I had fixed. When I hit this error a second time, I isolated a small test case, wrote a StackOverflow post and some helpful person pointed out that Ok in Rust has a lower-case k.

For some reason my fingers really want to type OK and my eyes really want to see that as a correct formation of the syntax, so I get this error now and then. “Hello, tuple variant my old friend!” says the voice in my head that anthropomorphizes my code. Then as my fingers automatically fix the typo and recompile, I reflect on Rust tuples and wonder about tuple variants.

So, what’s a tuple?

A tuple is a “finite heterogeneous sequence,” and one of Rust’s primitive type (see doc).

The enum keyword allows us to express a type which has multiple variants which from context must be tuple variants, though I was never able to find a reference to this in the docs.

Update:
discussion on twitter
– bug filed with suggestions from twitter thread: https://github.com/rust-lang/rust/issues/65386
– there are some very awesome people developing the Rust language (and surrounding ecosystem of tools and docs)

Getting started with Rust and the petgraph crate, I made a little program to write a graph in “dot” file format. Below is the rust and some command-line code to turn it into a png.

visual graph representation with circles and arrows

use petgraph::Graph;
use petgraph::dot::{Dot, Config};
use std::fs::File;
use std::io::Write;

fn main() {
    println!("hello graph!");
    let mut graph = Graph::<_, i32>::new();
    graph.add_node("A");
    graph.add_node("B");
    graph.add_node("C");
    graph.add_node("D");
    graph.extend_with_edges(&[
        (0, 1), (0, 2), (0, 3),
        (1, 2), (1, 3),
        (2, 3),
    ]);

    println!("{:?}", Dot::with_config(&graph, &[Config::EdgeNoLabel]));
    let mut f = File::create("example.dot").unwrap();
    let output = format!("{}", Dot::with_config(&graph, &[Config::EdgeNoLabel]));
    f.write_all(&output.as_bytes()).expect("could not write file");
}

output of cargo run:

hello graph!
digraph {
    0 [label="\"A\""]
    1 [label="\"B\""]
    2 [label="\"C\""]
    3 [label="\"D\""]
    0 -> 1
    0 -> 2
    0 -> 3
    1 -> 2
    1 -> 3
    2 -> 3
}

Generate PNG from DOT file

The dot command is part of graphviz, which I installed with brew install graphviz.

The following command creates a PNG file from the .dot file generated by Rust code above

dot -T png -O example.dot

The resulting PNG is displayed at the top-right of this post (next to the Rust code).


Special thanks to:
* mcarton’s help on stackoverflow for enlightening me on a bit of Rust nuance as I experimented with petgraph.
* rudifa’s post graphviz-on-the-mac

I’m debugging an issue where my app uses a library that requires me to dynamically link with an openssl library. What’s more I’m debugging it on an old linux version. Sigh.

gdb to the rescue!

After figuring out how to build openssl from source, I stumbled upon a gdb trick… suppose you are using a fairly standard open source library (like openssl) and you want to debug something that uses it (some other library that doesn’t work over ssl), gdb will let you know if there’s an easy way to download the symbols! Just type gdb + library name.

Here’s an example

gdb openssl
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-92.el6)
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /usr/bin/openssl...(no debugging symbols found)...done.
Missing separate debuginfos, use: debuginfo-install openssl-1.0.1e-57.el6.x86_64
(gdb) quit

Now I can use this command to install the debug symbols for the specific version of openssl that is installed on this system:

debuginfo-install openssl-1.0.1e-57.el6.x86_64

then I can debug my app looking at how it calls openssl. In the gdb session below, I first set a breakpoint in main, and run to that point…

(gdb) b main
(gdb) run
Starting program: /home/builder/src/app 
warning: no loadable sections found in added symbol-file system-supplied DSO at 0x7ffff7ffa000
[Thread debugging using libthread_db enabled]

Breakpoint 1, main (argc=4, argv=0x7fffffffe698) at sample.cpp:226
226         LOG("Here I am in main!")

now the openssl library is loaded and I can set a breakpoint in it:

(gdb) b SSL_CTX_set_verify
Breakpoint 2 at 0x7ffff7734bb0: file ssl_lib.c, line 2040.
(gdb) c
Continuing.
Creating connection object
[New Thread 0x7ffff4bd6700 (LWP 53)]
Connecting to server/app URL: rtmps://live-api-s.facebook.com/rtmp/

Breakpoint 2, SSL_CTX_set_verify (ctx=0x62efe0, mode=1, cb=0x7ffff7acb6c0 <SecuredConnectionIO::VerifyCallback(int, x509_store_ctx_st*)>)
    at ssl_lib.c:2040
2040        ctx->verify_mode=mode;

I can look at variables or all of the function arguments:

(gdb) p mode
$1 = 1
(gdb) info args
ctx = 0x62efe0
mode = 1
cb = 0x7ffff7acb6c0 <SecuredConnectionIO::VerifyCallback(int, x509_store_ctx_st*)>

How cool is that?