RustViz is a tool that generates interactive visualizations from simple Rust programs to assist users in better understanding the Rust Lifetime and Borrowing mechanism.

Overview

RustViz

Build Status

RustViz is a tool that generates interactive visualizations from simple Rust programs to assist users in better understanding the Rust Lifetime and Borrowing mechanism.

RustViz is a project of the Future of Programming Lab at the University of Michigan.

What does it look like?

RustViz generates SVG files with graphical indicators that integrate with mdbook to render interactive visualizations of ownership and borrowing related events in a Rust program. Here's a sample view of what a visualization can look like:

alt tag

You can read more about it in our draft paper. Note that the section on generating visualizations is out of date, see below.

Usage

RustViz is capable of generating visualizations for simple Rust programs (albeit with certain limitations) that have been annotated by the user. We are not currently attempting to generate visualizations automatically. In this section, we'll showcase how to generate SVG renderings of examples provided by us.

RustViz requires Rust, Cargo and mdbook to be installed. Once you have installed all the above prerequisites, direct into /rustviz_mdbook and run the script:

~/rustviz/rustviz_mdbook$ ./view_examples.sh

You may have an output similar to this:

Generating visualizations for the following examples:
building copy...
building hatra1...
building hatra2...
building func_take_ownership...
building func_take_return_ownership...
2021-01-19 12:36:13 [INFO] (mdbook::book): Book building has started
2021-01-19 12:36:13 [INFO] (mdbook::book): Running the html backend
Serving HTTP on :: port 8000 (http://[::]:8000/) ...

If you observed this output, then you have successfully generated the Rust visualization examples! Now open your browser and navigate to http://localhost:8000/. You should be able to view the examples individually by selecting them from the left side bar. To view the visualization, click the toggle button on the top right corner of the code block.

Great, this is how you can generate and view visualizations created using RustViz. Now let's create one from scratch!

Step-By-Step Guide

In this section, we'll dive into creating an example, string_from_move_print. First, take note of the file structure we'll need to run the example:

string_from_move_print
├── input
│   └── annotated_source.rs
└── source.rs

source.rs contains the untouched source code we wish to render into an image:

fn main() {
    let x = String::from("hello");
    let y = x;
    println!("{}", y);
}

In this example, String::from() moves a string ("hello") to x, then x's resource is moved to y. Subsequently, println!() outputs a message to io::stdout without moving the resource.

Next, let's familiarize ourselves with the syntax used in main.rs. The RustViz tool defines all possible owners, references or input of any memory resource as a ResourceAccessPoint. In this case, we consider the function String::from() and two variables, x and y, as Resource Access Points (RAPs). Each of String::from() and x/y corresponds to RAPs ResourceAccessPoint::Function and ResourceAccessPoint::Owner, respectively.

In main.rs, we define these RAPs between the BEGIN and END comments on lines 1 and 2:

/*--- BEGIN Variable Definitions ---
Owner x; Owner y;
Function String::from();
--- END Variable Definitions ---*/

The definition header now can be automatically generated by running the view_examples.sh once. If any incorrect information appeared at the generated header, you could manully edit it by refering to the following documentation.

The format for each ResourceAccessPoint enum is shown below, where fields preceded by ':' denote an optional field:

ResourceAccessPoint Usage --
    Owner <:mut> <name>
    MutRef <:mut> <name>
    StaticRef <:mut> <name>
    Struct <:mut> <name>{<:mut> <member_1>, <:mut> <member_2>, ... }
    Function <name>

Alternatively, some code let mut a = 5; and let b = &a; would correspond to Owner mut a and StaticRef b, respectively. An immutable instance of some struct with member variables x and mut y, on the other hand, may be annotated as Struct a{x, mut y}.

It is important to note:

  1. all definitions must lie between BEGIN and END
  2. all definitions must be defined in the same order by which they were declared in the source code
  3. all definitions must be separated by a singular semicolon
  4. each field within a RAP definition must be separated by a whitespace

After running the view_examples.sh once we should have the following file structure:

string_from_move_print
├── input
│   └── annotated_source.rs
├── main.rs
└── source.rs

Next, we annotate the code with the use of ExternalEvents that describe move, borrow, and drop semantics of Rust. In string_from_move_print, we have four such events:

  1. Move of resource from String::from() to x
  2. Move of resource from y to x
  3. Drop of resource binded to x
  4. Drop of resource binded to y

We can specify Events in structured comments like so:

x) } let y = x; // !{ Move(x->y) } println!("{}", y); // print to stdout! } /* !{ GoOutOfScope(x), GoOutOfScope(y) } */ ">
/* --- BEGIN Variable Definitions ---
Owner x; Owner y;
Function String::from();
 --- END Variable Definitions --- */
fn main() {
    let x = String::from("hello"); // !{ Move(String::from()->x) }
    let y = x; // !{ Move(x->y) }
    println!("{}", y); // print to stdout!
} /* !{
    GoOutOfScope(x),
    GoOutOfScope(y)
} */

Each Event is defined on the line where it occurs and within delimiters !{ and }.

Events can be annotated within block comments; however, the block must start on the line in which the events occur. Additionally, all Events within a !{} delimitation must be separated by a singular comma and must each follow the format:

ExternalEvents Usage:
    Format: <event_name>(<from>-><to>)
        e.g.: // !{ PassByMutableReference(a->Some_Function()), ... }
    Note: GoOutOfScope and InitializeParam require only the <from> parameter
        e.g.: // !{ GoOutOfScope(x) }

Refer to the Appendix for a list of usable ExternalEvent's.

Phew! All that's left is running the program. Simply navigate into src and run:

cargo run string_from_move_print

Now your folder should look like this:

string_from_move_print
├── input
│   └── annotated_source.rs
├── main.rs
├── source.rs
├── vis_code.svg
└── vis_timeline.svg

Congratulations! You have successfully generated your first visualization! As a last step, add the name of your example to targetExamples under view_examples.sh and run the script from rustviz_mdbook to see it in your browser.

Appendix

ExternalEvent Usage:

Event Usage
Bind(a->b) Let binding or assignment.
e.g.: let a = 1;
Copy(a->b) Copies the resource of a to variable b. Here, a implements the Copy trait.
Move(a->b) Moves the resource of a to variable b. Here, a implements the Move trait.
Note: Moving to None (i.e.: Move(a->None)) is used to express a move to the caller function.
StaticBorrow(a->b) Assigns an immutable reference of a to b.
e.g.: let b = &a;
MutableBorrow(a->b) Assigns a mutable reference of a to b.
e.g.: let b = &mut a;
StaticReturn(a->b) Ends the non-lexical lifetime of the reference variable a and returns the resource back to its owner b.
MutableReturn(a->b) Ends the non-lexical lifetime of the reference variable a and returns the resource back to its owner b.
PassByStaticReference(a->b) Passes an immutable reference of variable a to function b. Not to be confused with StaticBorrow.
PassByMutableReference(a->b) Passes a mutable reference of variable a to function b. Not to be confused with MutableBorrow.
StructBox(a->a.b) Creates a struct instance a whose last member variable is b.
Notes:
(1) This event should be specified on the same line the struct instance, a, goes out of lexical scope.
(2) A struct's member variables should always be defined in the same order they are declared in.
GoOutOfScope(a) Ends the lexical lifetime of variable a.
InitializeParam(a) Initializes the parameter a of some function.
e.g.: some_fn(a: String) {..}

Note:

  1. GoOutOfScope and InitializeParam require a singular parameter previously defined in the Variable Definitions section. (e.g.: // !{ GoOutOfScope(x) })
  2. All other events require two parameters, a and b, which can either be defined (e.g.: Owner a) or undefined (None). The None option is generally used for scalar types or undefined variables (e.g.: let x = 1 can be annotated as Bind(None->x)). The None type can also used as the parameter (e.g.: Move(a->None)) to specify a move to the function caller.
  3. All uses of Struct fields must be preceded by its parent struct's name. (e.g.: a.b = 1; can be annotated as Move(None->a.b), where a is the parent and b is the field.)

Visualization Limitations

Some features are still being built. As of now, we are limited to:

  • No branching logic
  • No looping
  • No explicit lifetime annotation
Comments
  • Incorrect gap in timeline in hatra1 example

    Incorrect gap in timeline in hatra1 example

    Image from iOS

    There shouldn't be a gap in the timeline where circled. Figure out what is causing this.

    It wasn't there in the screenshot we used in the HATRA paper.

    bug examples 
    opened by vishnureddy17 2
  • Add new example - immutable_borrow_lifetime & Correct wrong example

    Add new example - immutable_borrow_lifetime & Correct wrong example

    This example illustrate examples below - from The Rust Programming Language Book

    fn main() {
        let string1 = String::from("abcd");
        let string2 = String::from("xyz");
    
        let result = longest(&string1, &string2);
        println!("The longest string is {}", result);
    }
    
    fn longest<'a>(x: &'a String, y: &'a String) -> &'a String {
        if x.len() > y.len() {
            x
        } else {
            y
        }
    }
    
    opened by c0wjay 1
  • Http server and Python

    Http server and Python

    In view_examples.sh I had to replace

    python3 -m http.server 8000

    with

    python -m http.server 8000

    This was on Windows. I did actually have Python 3.x installed but second command works.

    You probably should mention this has a dependency on Python too. Is Python typically pre-installed in Linux distros? I gather it is in macOS.

    opened by kevinmcfarlane 1
  • The ownership diagram of [view_examples] is not showing up when view_examples.sh gets started.

    The ownership diagram of [view_examples] is not showing up when view_examples.sh gets started.

    image image

    ./view_examples.sh Generating visualizations for the following examples: building extra_credit...done 2021-09-07 21:28:18 [INFO] (mdbook::book): Book building has started 2021-09-07 21:28:18 [INFO] (mdbook::book): Running the html backend Serving HTTP on :: port 8000 (http://[::]:8000/) ...

    rustc --version rustc 1.54.0 (a178d0322 2021-07-26)

    rustup --version rustup 1.24.3 (ce5817a94 2021-05-31)

    cargo --version cargo 1.54.0 (5ae8d74b3 2021-06-22)

    mdbook --version mdbook v0.4.12

    opened by Erik1288 1
  • Incorrect hover message on immutable_borrow example

    Incorrect hover message on immutable_borrow example

    The hover message says "can mutate the resource it refers to" even though it can't. image_from_ios

    Not sure if this is because the wrong events are used in this example or if it's because of a bug

    examples 
    opened by vishnureddy17 1
  • Figure out a way to handle overlapping Arrows without having to manually edit the SVG

    Figure out a way to handle overlapping Arrows without having to manually edit the SVG

    related: fplab/rust-resource-timeline#31

    We did say in the paper "In some cases, the SVG needs to be tweaked. Fig. 2 was adjusted to fix overlapping arrows on line 6." So if we have to skip any of the paper-related issues due to time constraint, this one would be it. But it's better to fix it if possible.

    HATRA submission 
    opened by vishnureddy17 1
  • No second line for r3 in hatra2 example

    No second line for r3 in hatra2 example

    Image from iOS

    Since r3 is a variable of reference type, it should have a second line where circled. Figure out why is is missing. This issue wasn't present in the screenshot in the HATRA paper.

    bug examples 
    opened by vishnureddy17 1
  • When a variable goes out of scope, have the hover message say whether it's resource is dropped or not

    When a variable goes out of scope, have the hover message say whether it's resource is dropped or not

    Currently, the hover message says "x goes out of scope". We want it to say "x goes out of scope. Its resource is dropped" or "x goes out of scope. It did not own a resource." so we can match what we said in the paper.

    In the past, the hover messages always said that the resource is dropped whenever a variable of non-reference type went out of scope. This was incorrect because if ownership got moved away from a variable, there won't be a drop when that variable goes out of scope.

    HATRA submission 
    opened by vishnureddy17 0
  • string_from_move_print in README

    string_from_move_print in README

    There are currently two string_from_move_print folders in the rustviz repo. The first is located under src -> examples and the second under rustviz_mdbook -> src -> assets. This might confuse a naive user using the tool for the first time.

    opened by gt-cole 0
  • [move_func_return] Add a missing return type.

    [move_func_return] Add a missing return type.

    I think there is a missing return type in move_func_return

    fn f() {
        // - help: try adding a return type: `-> String`
        let x = String::from("hello");
        // ...
        x
    }
    
    fn main() {
        let s = f();
        println!("{}", s);
    }
    

    This PR should fix it.

    opened by sjinno 0
  • Issue with immutable_borrow_method_call

    Issue with immutable_borrow_method_call

    Screenshot from 2020-11-08 15-52-30

    The len1 and len2 timelines are messed up. If I change the event from Duplicate to Move from String::len() to len1 and len2 then it looks fine. But integers have the copy trait so it shouldn't be a move.

    bug examples 
    opened by vishnureddy17 1
Owner
null
Rust crate for creating beautiful interactive Chord Diagrams

Chord PRO Released Chord PRO is the full-featured chord visualization API, producing beautiful interactive visualizations, e.g. those featured on the

Dr. Shahin Rostami 25 Sep 10, 2022
A better visualization of clang's -ftime-trace output

crofiler: Easier C++ build profiling Understanding why C++ builds get slow has become a lot easier since clang introduced their -ftime-trace build tra

Hadrien G. 7 Nov 15, 2022
A small charting/visualization tool and partial vega implementation for Rust

Gust A charting library for rust! Disclaimer This is still very much a work in progress! APIs are very unstable and subject to change. Contributions a

Samuel Resendez 128 Dec 24, 2022
KDash - A fast and simple dashboard for Kubernetes

KDash - A fast and simple dashboard for Kubernetes

null 915 Jan 4, 2023
binocle is a graphical tool to visualize binary data

a graphical tool to visualize binary data

David Peter 773 Dec 30, 2022
A color-coded visualization tool for the instructions of an anchor program

anchor-viz A color-coded visualization tool for the instructions of an anchor program. (This is a schematic of basic-2 from anchor's examples/tutorial

cavemanloverboy 5 Oct 15, 2022
A simple 2D plotting library that outputs graphs to SVG that can be styled using CSS.

Poloto graphs can be stylized using css either directly in the SVG, or from inside of html with an embedded svg. The latter allows the user to dynamically match the svg to their website's theme.

Ken Reed 119 Dec 13, 2022
A rust drawing library for high quality data plotting for both WASM and native, statically and realtimely 🦀 📈🚀

Plotters - A Rust drawing library focus on data plotting for both WASM and native applications ?? ?? ?? Plotters is drawing library designed for rende

Hao Hou 2.7k Jan 4, 2023
Swash is a pure Rust, cross-platform crate that provides font introspection, complex text shaping and glyph rendering.

Swash is a pure Rust, cross-platform crate that provides font introspection, complex text shaping and glyph rendering. Goals This crate aims to

Chad Brokaw 398 Dec 14, 2022
🌱 Easy to use, blazing-fast, and reliable Chia plot manager for your farm

?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? UNDER DEVELOPME

Daniel De Lucca 8 May 31, 2022
This is an implementation of an Iced backend for Plotters, for both native and wasm applications.

plotters-iced This is an implementation of an Iced backend for Plotters, for both native and wasm applications. This backend has been optimized as for

joylei 54 Dec 14, 2022
📝 Web-based, reactive Datalog notebooks for data analysis and visualization

?? Web-based, reactive Datalog notebooks for data analysis and visualization

Eric Zhang 486 Dec 28, 2022
Data plotting library for Rust

plotlib plotlib is a generic data visualisation and plotting library for Rust. It is currently in the very early stages of development. It can current

Matt Williams 417 Dec 31, 2022
Plotly for Rust

Plotly.rs Plotly for Rust Getting Started | Recipes | API Docs | Changelog | | | A plotting library for Rust powered by Plotly.js. Usage Add this to y

Ioannis Giagkiozis 671 Jan 8, 2023
This is a Rust implementation of a boid flocking simulation using the ggez graphics crate.

Boidflock This is a Rust implementation of a boid flocking simulation using the ggez graphics crate. The CLI for this program is built using the struc

Andrew Lee 12 Jan 4, 2023
A Rust library for drawing plots, powered by Gnuplot.

RustGnuplot A Gnuplot controller written in Rust. Documentation See here Examples A simple example: let mut fg = Figure::new(); fg.axes2d() .set_titl

null 353 Dec 26, 2022
Render farm simulator & plotting for optimisation written in Rust.

Farm Usage Simulator Given a few basic charasteristics of a render farm and render jobs this app runs a few randomized farm usage scenarios and plots

ford 2 Jul 17, 2022
A Rust API for Vega-Lite V4 to build chart with a rusty API.

Vega-Lite V4 for Rust A Rust API for Vega-Lite V4 to build chart with a rusty API. Similar to the Altair project in python, this crate build upon Vega

Procyon 18 Nov 26, 2022
Externalize easily the plotting process from Rust to gnuplot.

preexplorer Easy plotter and saver of simple data. Handy tool for development stage or small computational projects. Save data, have a quick view and

Raimundo Saona 4 Jan 7, 2022