Clearing Up Common Misconceptions About Rust Lifetimes

{“payload”:{“allShortcutsEnabled”:false,”fileTree”:{“posts”:{“items”:[{“name”:”translations”,”path”:”posts/translations”,”contentType”:”directory”},{“name”:”common-rust-lifetime-misconceptions.md”,”path”:”posts/common-rust-lifetime-misconceptions.md”,”contentType”:”file”},{“name”:”learning-rust-in-2020.md”,”path”:”posts/learning-rust-in-2020.md”,”contentType”:”file”},{“name”:”restful-api-in-sync-and-async-rust.md”,”path”:”posts/restful-api-in-sync-and-async-rust.md”,”contentType”:”file”},{“name”:”sizedness-in-rust.md”,”path”:”posts/sizedness-in-rust.md”,”contentType”:”file”},{“name”:”too-many-brainfuck-compilers.md”,”path”:”posts/too-many-brainfuck-compilers.md”,”contentType”:”file”},{“name”:”tour-of-rusts-standard-library-traits.md”,”path”:”posts/tour-of-rusts-standard-library-traits.md”,”contentType”:”file”},{“name”:”why-blog.md”,”path”:”posts/why-blog.md”,”contentType”:”file”}],”totalCount”:8},””:{“items”:[{“name”:”assets”,”path”:”assets”,”contentType”:”directory”},{“name”:”posts”,”path”:”posts”,”contentType”:”directory”},{“name”:”.gitignore”,”path”:”.gitignore”,”contentType”:”file”},{“name”:”license-apache”,”path”:”license-apache”,”contentType”:”file”},{“name”:”license-mit”,”path”:”license-mit”,”contentType”:”file”},{“name”:”readme.md”,”path”:”readme.md”,”contentType”:”file”}],”totalCount”:6}},”fileTreeProcessingTime”:5.0203560000000005,”foldersToFetch”:[],”reducedMotionEnabled”:null,”repo”:{“id”:260733299,”defaultBranch”:”master”,”name”:”rust-blog”,”ownerLogin”:”pretzelhammer”,”currentUserCanPush”:false,”isFork”:false,”isEmpty”:false,”createdAt”:”2020-05-02T16:55:52.000Z”,”ownerAvatar”:”https://avatars.githubusercontent.com/u/7769424?v=4″,”public”:true,”private”:false,”isOrgOwned”:false},”symbolsExpanded”:false,”treeExpanded”:true,”refInfo”:{“name”:”master”,”listCacheKey”:”v0:1622891219.1341991″,”canEdit”:false,”refType”:”branch”,”currentOid”:”aa3706b503c0eba13f81ac23aceb19b0a49f1417″},”path”:”posts/common-rust-lifetime-misconceptions.md”,”currentUser”:null,”blob”:{“rawLines”:null,”stylingDirectives”:null,”csv”:null,”csvError”:null,”dependabotInfo”:{“showConfigurationBanner”:false,”configFilePath”:null,”networkDependabotPath”:”/pretzelhammer/rust-blog/network/updates”,”dismissConfigurationNoticePath”:”/settings/dismiss-notice/dependabot_configuration_notice”,”configurationNoticeDismissed”:null,”repoAlertsPath”:”/pretzelhammer/rust-blog/security/dependabot”,”repoSecurityAndAnalysisPath”:”/pretzelhammer/rust-blog/settings/security_analysis”,”repoOwnerIsOrg”:false,”currentUserCanAdminRepo”:false},”displayName”:”common-rust-lifetime-misconceptions.md”,”displayUrl”:”https://github.com/pretzelhammer/rust-blog/blob/master/posts/common-rust-lifetime-misconceptions.md?raw=true”,”headerInfo”:{“blobSize”:”40.4 KB”,”deleteInfo”:{“deleteTooltip”:”You must be signed in to make or propose changes”},”editInfo”:{“editTooltip”:”You must be signed in to make or propose changes”},”ghDesktopPath”:”https://desktop.github.com”,”gitLfsPath”:null,”onBranch”:true,”shortPath”:”7ed6b28″,”siteNavLoginPath”:”/login?return_to=https%3A%2F%2Fgithub.com%2Fpretzelhammer%2Frust-blog%2Fblob%2Fmaster%2Fposts%2Fcommon-rust-lifetime-misconceptions.md”,”isCSV”:false,”isRichtext”:true,”toc”:[{“level”:1,”text”:”Common Rust Lifetime Misconceptions”,”anchor”:”common-rust-lifetime-misconceptions”,”htmlText”:”Common Rust Lifetime Misconceptions”},{“level”:2,”text”:”Intro”,”anchor”:”intro”,”htmlText”:”Intro”},{“level”:2,”text”:”The Misconceptions”,”anchor”:”the-misconceptions”,”htmlText”:”The Misconceptions”},{“level”:3,”text”:”1) T only contains owned types”,”anchor”:”1-t-only-contains-owned-types”,”htmlText”:”1) T only contains owned types”},{“level”:3,”text”:”2) if T: ‘static then T must be valid for the entire program”,”anchor”:”2-if-t-static-then-t-must-be-valid-for-the-entire-program”,”htmlText”:”2) if T: ‘static then T must be valid for the entire program”},{“level”:3,”text”:”3) &’a T and T: ‘a are the same thing”,”anchor”:”3-a-t-and-t-a-are-the-same-thing”,”htmlText”:”3) &’a T and T: ‘a are the same thing”},{“level”:3,”text”:”4) my code isn’t generic and doesn’t have lifetimes”,”anchor”:”4-my-code-isnt-generic-and-doesnt-have-lifetimes”,”htmlText”:”4) my code isn’t generic and doesn’t have lifetimes”},{“level”:3,”text”:”5) if it compiles then my lifetime annotations are correct”,”anchor”:”5-if-it-compiles-then-my-lifetime-annotations-are-correct”,”htmlText”:”5) if it compiles then my lifetime annotations are correct”},{“level”:3,”text”:”6) boxed trait objects don’t have lifetimes”,”anchor”:”6-boxed-trait-objects-dont-have-lifetimes”,”htmlText”:”6) boxed trait objects don’t have lifetimes”},{“level”:3,”text”:”7) compiler error messages will tell me how to fix my program”,”anchor”:”7-compiler-error-messages-will-tell-me-how-to-fix-my-program”,”htmlText”:”7) compiler error messages will tell me how to fix my program”},{“level”:3,”text”:”8) lifetimes can grow and shrink at run-time”,”anchor”:”8-lifetimes-can-grow-and-shrink-at-run-time”,”htmlText”:”8) lifetimes can grow and shrink at run-time”},{“level”:3,”text”:”9) downgrading mut refs to shared refs is safe”,”anchor”:”9-downgrading-mut-refs-to-shared-refs-is-safe”,”htmlText”:”9) downgrading mut refs to shared refs is safe”},{“level”:3,”text”:”10) closures follow the same lifetime elision rules as functions”,”anchor”:”10-closures-follow-the-same-lifetime-elision-rules-as-functions”,”htmlText”:”10) closures follow the same lifetime elision rules as functions”},{“level”:2,”text”:”Conclusion”,”anchor”:”conclusion”,”htmlText”:”Conclusion”},{“level”:2,”text”:”Discuss”,”anchor”:”discuss”,”htmlText”:”Discuss”},{“level”:2,”text”:”Notifications”,”anchor”:”notifications”,”htmlText”:”Notifications”},{“level”:2,”text”:”Further Reading”,”anchor”:”further-reading”,”htmlText”:”Further Reading”}],”lineInfo”:{“truncatedLoc”:”1133″,”truncatedSloc”:”857″},”mode”:”file”},”image”:false,”isCodeownersFile”:null,”isPlain”:false,”isValidLegacyIssueTemplate”:false,”issueTemplateHelpUrl”:”https://docs.github.com/articles/about-issue-and-pull-request-templates”,”issueTemplate”:null,”discussionTemplate”:null,”language”:”Markdown”,”languageID”:222,”large”:false,”loggedIn”:false,”newDiscussionPath”:”/pretzelhammer/rust-blog/discussions/new”,”newIssuePath”:”/pretzelhammer/rust-blog/issues/new”,”planSupportInfo”:{“repoIsFork”:null,”repoOwnedByCurrentUser”:null,”requestFullPath”:”/pretzelhammer/rust-blog/blob/master/posts/common-rust-lifetime-misconceptions.md”,”showFreeOrgGatedFeatureMessage”:null,”showPlanSupportBanner”:null,”upgradeDataAttributes”:null,”upgradePath”:null},”publishBannersInfo”:{“dismissActionNoticePath”:”/settings/dismiss-notice/publish_action_from_dockerfile”,”dismissStackNoticePath”:”/settings/dismiss-notice/publish_stack_from_file”,”releasePath”:”/pretzelhammer/rust-blog/releases/new?marketplace=true”,”showPublishActionBanner”:false,”showPublishStackBanner”:false},”rawBlobUrl”:”https://github.com/pretzelhammer/rust-blog/raw/master/posts/common-rust-lifetime-misconceptions.md”,”renderImageOrRaw”:false,”richText”:”n

19 May 2020 · #rust · #lifetimes

n

Table of Contents

nnIntron

I’ve held all of these misconceptions at some point and I see many beginners struggle with these misconceptions today. Some of my terminology might be non-standard, so here’s a table of shorthand phrases I use and what I intend for them to mean.

nnnnPhrasenShorthand fornnnnnTn1) a set containing all possible types or
2) some type within that setnnnowned typensome non-reference type, e.g. i32, String, Vec, etcnnn1) borrowed type or
2) ref typensome reference type regardless of mutability, e.g. &i32, &mut i32, etcnnn1) mut ref or
2) exclusive refnexclusive mutable reference, i.e. &mut Tnnn1) immut ref or
2) shared refnshared immutable reference, i.e. &TnnnnThe Misconceptionsn

In a nutshell: A variable’s lifetime is how long the data it points to can be statically verified by the compiler to be valid at its current memory address. I’ll now spend the next ~6500 words going into more detail about where people commonly get confused.

n1) T only contains owned typesn

This misconception is more about generics than lifetimes but generics and lifetimes are tightly intertwined in Rust so it’s not possible to talk about one without also talking about the other. Anyway:

n

When I first started learning Rust I understood that i32, &i32, and &mut i32 are different types. I also understood that some generic type variable T represents a set which contains all possible types. However, despite understanding both of these things separately, I wasn’t able to understand them together. In my newbie Rust mind this is how I thought generics worked:

nnnnnnnnnnnnType VariablenTn&Tn&mut TnnnExamplesni32n&i32n&mut i32nnnn

T contains all owned types. &T contains all immutably borrowed types.

 » …
Read More rnrn

Latest articles

Related articles