Understanding Lifetime in Rust – Part I

Lifetime is where the true strength of Rust lies and makes it unique from other languages with similar syntax like C++ and Java. Unfortunately, it is also the area that takes the longest to understand. The effort put in learning this is well worth it. Remember that lifetime solves two very nagging problems in programming:

  • Memory management – Rust achieves automatic memory management without the need for GC or reference counting. The compiler is able to deterministically predict lifetime of objects and inject memory free code at the correct places. Rust also eliminates common memory safety errors like double free and use after free as we shall see here.
  • Race condition – Rust enforces strict ownership rules. While multiple threads can have read-only access to an object only one thread can own it for modification. This makes concurrent code error free and in many cases you can do lock free concurrent programming.

As I learn more about lifetime I plan on rolling out more articles in this series. In Part I we will explore one of the simplest use cases of lifetime.

Continue reading

Rust Using Visual Studio Code

I am getting decent productivity using MS Visual Studio Code to code Rust. This is how I have it setup.

Use a Good Font

VS Code has built in support for Rust syntax coloring. But a good font always helps. My favorite is Source Code Pro. Download and install it from Google Fonts.

In VS Code open preferences using the menu Code > Preferences > User Settings. The right hand pane has your personal settings. Enter the font settings as follows.

// Place your settings in this file to overwrite the default settings
{
    "editor.fontFamily": "SourceCodePro-Medium",
    "editor.fontSize": 18
}

image

Save changes.

Setup Build Tasks

With this setup you will be able to compile, run and test right from VS Code.

In VS Code press Command+Shift+P to open the available menu items.

image

Type task to filter the list.

Select Tasks: Configure Task Runner.

Enter this JSON in the editor. Courtesy various posters in this Reddit post.

{
    "version": "0.1.0",
    "command": "cargo",
    "isShellCommand": true,
    "tasks": [
        {
            "taskName": "build",
            "isBuildCommand": true,
            "showOutput": "always",
            "problemMatcher": {
                "owner": "rust",
                "fileLocation": [
                    "relative",
                    "${workspaceRoot}"
                ],
                "pattern": {
                    "regexp": "^(.*):(\d+):(\d+):\s+(\d+):(\d+)\s+(warning|error):\s+(.*)$",
                    "file": 1,
                    "line": 2,
                    "column": 3,
                    "endLine": 4,
                    "endColumn": 5,
                    "severity": 6,
                    "message": 7
                }
            }
        },
        {
            "taskName": "clean",
            "showOutput": "always"
        },
        {
            "taskName": "run",
            "showOutput": "always"
        },
        {
            "taskName": "test",
            "showOutput": "always",
            "isTestCommand": true,
            "problemMatcher": [
                {
                    "owner": "rust",
                    "fileLocation": [
                        "relative",
                        "${workspaceRoot}"
                    ],
                    "pattern": {
                        "regexp": "^(.*):(\d+):(\d+):\s+(\d+):(\d+)\s+(warning|error):\s+(.*)$",
                        "file": 1,
                        "line": 2,
                        "column": 3,
                        "endLine": 4,
                        "endColumn": 5,
                        "severity": 6,
                        "message": 7
                    }
                },
                {
                    "owner": "rust",
                    "fileLocation": [
                        "relative",
                        "${workspaceRoot}"
                    ],
                    "severity": "error",
                    "pattern": {
                        "regexp": "^.*panicked\s+at\s+'(.*)',\s+(.*):(\d+)$",
                        "message": 1,
                        "file": 2,
                        "line": 3
                    }
                }
            ]
        }
    ]
}

Save changes.

Configure Keyboard

VS Code already comes with keyboard shortcut for tasks like build (Command+Shift+B) and test (Command+Shift+t). But we will now setup a keyboard shortcut to run any task from the list of available tasks.

From VS Code menu select Code > Preferences > Keyboard Shortcuts.

In the right hand side pane enter:

// Place your key bindings in this file to overwrite the defaults
[
    { "key": "shift+cmd+r", "command": "workbench.action.tasks.runTask" }
]

Save changes.

Development Workflow

The tasks we have setup above works with Cargo based projects. From VS Code menu select File > Open. Select the root folder of your Cargo based project (the folder that contains Cargo.toml).

To do a build use Command+Shift+B. Errors and warnings will be highlighted in the editor.

image

You can also move the mouse over the error squiggly line and view the error message right there.

To test the crate press Command+Shift+t.

If you are working on a binary crate and want to run it press Command+Shift+r. This will open the list of all tasks.

image

Select run from the list.

Change Background Color

I use the dark theme (View > Theme > Dark theme). But the background is semi transparent which I find hugely distracting. To change the background, locate the file native.main.css within VS Code distribution. Open the file. Change the background to full black like this:

.monaco-editor.vs-dark .zone-widget .monaco-editor {
    color: #BBB;
    background: #000000;
}

Save changes.