Borrowing allows functions to temporarily access a value without taking ownership of its resources. &T provides shared access, &mut T provides exclusive access; references must also point to valid, aligned data that satisfies type requirements during their usage. Access permissions, lifetimes, and address conditions are all indispensable.
The "multiple readers or one writer" model is the intuitive model for ordinary data. Interior mutability allows modification under a different protocol with shared references, and exclusive references can be temporarily reborrowed, so the rules cannot be understood as "all syntactic reference variables can never coexist."
Why Borrowing Vec Elements Prevents push
push requires exclusive access to the Vec, and when capacity is insufficient, it may reallocate, invalidating the addresses of old elements. Even if capacity has been reserved, the standard push interface still requires &mut Vec, so you cannot bypass borrowing rules when you still need to use element references afterward.
fnmain(){letmut values =vec![1,2,3];let first =&values[0];assert_eq!(*first,1);
values.push(4);assert_eq!(values,[1,2,3,4]);}
Moving assert_eq!(*first, 1) after push causes the borrow of first to span the modification, resulting in a compilation error. Simply writing a reference binding that is not used afterward does not mean that subsequent modifications are necessarily illegal.
NLL (Non-Lexical Lifetimes) infers the regions required for borrows based on control flow and usage constraints, rather than conservatively extending them to the end of the lexical block. It is not simply the "last line" of text scanning; branches, returned references, and destructor constraints can all affect the result. Borrow Checker Overview
Move a use across a mutation
Keep the data and push API fixed, changing only where first is used. Orange marks exclusive mutation; teal marks where later use still requires the element borrow. An overlap calls for changing use order or the interface, not merely reserving capacity.
Preparing the visual
Move a use across a mutation
In this straight-line example, reading the element reference after push conflicts even with spare capacity.
{"id":"rust-borrow-region","title":"Move a use across a mutation","summary":"In this straight-line example, reading the element reference after push conflicts even with spare capacity.","height":1000,"html":"<h2 data-i18n=\"heading\"></h2><p class=\"intro\" data-i18n=\"intro\"></p><div class=\"control\"><label for=\"use\" data-i18n=\"use\"></label><output for=\"use\" id=\"use-value\"></output><input id=\"use\" type=\"range\" min=\"2\" max=\"6\" value=\"3\" step=\"1\"></div><label class=\"check\"><input type=\"checkbox\" id=\"capacity\"><span data-i18n=\"capacity\"></span></label><div id=\"regions\" class=\"intervals\"></div><pre id=\"code\" class=\"source\"></pre><div class=\"copy\"><p id=\"explanation\" role=\"status\"></p><p class=\"reserve\" aria-hidden=\"true\" data-i18n=\"ok\"></p><p class=\"reserve\" aria-hidden=\"true\" data-i18n=\"bad\"></p></div><details class=\"scope\"><summary data-i18n=\"scopeLabel\"></summary><p data-i18n=\"scope\"></p></details>","css":".intro{margin:8px 0 18px;color:var(--muted);font-size:14px}.caption,.hint{font-size:12px;color:var(--muted);margin-top:12px}.control{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:6px 12px;align-items:center;margin:14px 0;font-size:13px}.control label{font-size:13px}.control output{color:var(--accent);min-width:5em;text-align:right;font-variant-numeric:tabular-nums}.control input{grid-column:1/-1;width:100%;margin:0}.presets{display:flex;gap:4px;align-items:stretch}.presets button{flex:1 1 0;min-width:0;overflow-wrap:anywhere;font-size:13px}.actions{display:flex;gap:8px;flex-wrap:wrap;margin:14px 0}.actions button{flex:1;min-width:0;font-size:13px;min-height:42px}.copy{display:grid;font-size:14px;margin:16px 0}.copy>*{grid-area:1/1;margin:0}.reserve{visibility:hidden}.scope{margin-top:14px;color:var(--muted);font-size:12px}.scope summary{padding:8px 0;cursor:pointer}.scope p{margin-top:10px}.two{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin:16px 0}.card{border:1px solid var(--rule);border-radius:9px;padding:14px;min-width:0}.card header{font-size:14px;font-weight:600;margin-bottom:10px}.card button{font-size:12px;width:100%;min-width:0}.card small{display:block;font-size:12px;color:var(--muted)}.card code{font-size:12px;overflow-wrap:anywhere}.metrics{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin:16px 0}.metrics>div{border-left:2px solid var(--accent);padding-left:10px;min-width:0}.metrics span{display:block;min-height:3.2em;color:var(--muted);font-size:12px}.metrics strong{font-size:23px;display:block;font-weight:550;overflow-wrap:anywhere;font-variant-numeric:tabular-nums}.formula{border-top:1px solid var(--rule);padding-top:12px;margin-top:14px;font-size:13px;font-variant-numeric:tabular-nums;overflow-wrap:anywhere}.value{font:550 20px ui-monospace,monospace}.legend{display:flex;flex-wrap:wrap;gap:6px 14px;font-size:12px;color:var(--muted);margin:12px 0}.legend span:before{content:'';display:inline-block;width:8px;height:8px;border-radius:2px;background:var(--accent);margin-right:6px}.legend .second:before{background:var(--second)}.check{display:flex;align-items:center;gap:8px;font-size:13px;margin:12px 0}.check input{width:16px;height:16px;flex-shrink:0;accent-color:var(--accent)}select,input[type=text],input[type=number]{background:var(--paper);color:var(--ink);font:inherit;font-size:13px;padding:10px;border:1px solid var(--rule);border-radius:7px;max-width:100%;min-width:0}select{width:100%;min-height:42px}.band{height:20px;display:flex;background:var(--surface);border-radius:4px;overflow:hidden}.band i{height:100%;display:block;background:var(--accent);transition:width .25s}.band i.second{background:var(--second)}button:disabled{cursor:default}.status{font-size:13px;min-height:4.8em}.mono{font-family:ui-monospace,monospace;font-variant-numeric:tabular-nums}.muted{color:var(--muted)}\n@media(max-width:480px){.two{gap:8px}.card{padding:12px 9px}.actions button,.presets button{font-size:12px}.metrics strong{font-size:20px}.metrics{gap:8px}}\n@media(prefers-reduced-motion:reduce){*,*::before,*::after{transition:none!important;animation:none!important}}\n.track-row{margin:16px 0}.track-row>span{display:block;font-size:12px;color:var(--muted);margin-bottom:7px}.track{display:flex;gap:5px;min-width:0}.cell{flex:1;min-width:0;min-height:48px;border:1px solid var(--rule);border-radius:5px;background:var(--surface);display:flex;align-items:center;justify-content:center;text-align:center;padding:5px 3px;font-size:12px;overflow-wrap:anywhere;font-variant-numeric:tabular-nums}.cell.on{background:var(--accent-soft);border-color:var(--accent)}.cell.gold{background:var(--second-soft);border-color:var(--second)}.cell.empty{border-style:dashed;color:var(--muted)}.cell.error{border-color:var(--second);text-decoration:line-through}.choices{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px;margin:14px 0}.choices button{min-width:0;padding:10px 4px;font-size:12px;overflow-wrap:anywhere}.choices button[aria-current=true]{border-color:var(--accent);background:var(--accent-soft)}.relation{display:grid;grid-template-columns:minmax(0,1fr) 28px minmax(0,1fr);align-items:center;gap:6px;margin:12px 0}.relation .cell{min-height:72px}.relation>i{text-align:center;font-style:normal;color:var(--accent)}.readout{font-size:13px;white-space:pre-line;min-height:6.4em;overflow-wrap:anywhere}.plot{position:relative;border-left:1px solid var(--rule);border-bottom:1px solid var(--rule);padding:8px 0;margin:18px 0}.plot-row{height:28px;position:relative;margin:4px 0;background:var(--surface)}.plot-row i{position:absolute;inset-block:5px;background:var(--accent);min-width:2px;transition:width .2s,left .2s}.plot-row b{position:relative;padding:4px 6px;font:11px/28px ui-monospace,monospace;background:var(--paper);border-radius:3px}.axis{display:flex;justify-content:space-between;font-size:11px;color:var(--muted)}\n\n/* Action labels must remain readable across locales and narrow embeds. */\n.actions{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}\n.actions button{overflow-wrap:anywhere;white-space:normal;min-height:58px;padding:8px}\nbutton{overflow-wrap:anywhere}\n@media(min-width:640px){.actions{grid-template-columns:repeat(3,minmax(0,1fr))}}\n\n.metrics span{overflow-wrap:anywhere}\n.panel{border:1px solid var(--rule);border-radius:9px;padding:12px;margin:14px 0;min-width:0}.panel h3{font-size:13px;margin:0 0 10px;color:var(--muted)}.source{font:13px/1.8 ui-monospace,monospace;white-space:pre-wrap;overflow-wrap:anywhere;margin:12px 0}.source mark{background:var(--accent-soft);color:var(--ink);border-bottom:2px solid var(--accent)}.source .fault{background:var(--second-soft);border-color:var(--second)}.diagram{display:block;width:100%;height:auto;max-height:320px;margin:14px 0;overflow:visible}.diagram text{fill:var(--ink);font:12px ui-monospace,monospace}.diagram .edge{stroke:var(--muted);stroke-width:1.5;fill:none}.diagram .edge.on{stroke:var(--accent);stroke-width:3}.diagram .node{fill:var(--surface);stroke:var(--rule);stroke-width:1.5}.diagram .node.on{fill:var(--accent-soft);stroke:var(--accent)}.diagram .node.gold{fill:var(--second-soft);stroke:var(--second)}.log{font:12px/1.8 ui-monospace,monospace;white-space:pre-line;overflow-wrap:anywhere;min-height:7.2em}.table{display:grid;gap:5px;margin:14px 0}.table .tr{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:5px}.table .tr>*{padding:8px 5px;background:var(--surface);border-radius:4px;min-width:0;overflow-wrap:anywhere;font-size:12px}.table .tr .on{background:var(--accent-soft)}.table .tr .gold{background:var(--second-soft)}.choices button{min-height:44px}.metrics strong{min-height:1.6em}.code-line{display:block}.code-line.on{background:var(--accent-soft);border-left:2px solid var(--accent);padding-left:6px}.status-badge{font-size:12px;color:var(--accent)}.tile-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px}.tile-grid .cell{min-height:40px}.actions button{min-height:48px}.form-field{display:grid;gap:8px;margin:14px 0;font-size:13px}.form-field input{width:100%;font-family:ui-monospace,monospace}.metrics.three{grid-template-columns:repeat(3,minmax(0,1fr))}.formula{min-height:3.2em}.presets{flex-wrap:wrap}.presets button{flex-basis:25%;min-height:44px}\n\n.budget{display:flex;height:28px;margin:16px 0;background:var(--surface);border-radius:5px;overflow:hidden}.budget i{display:block;background:var(--accent);transition:width .2s}.budget i.gold{background:var(--second)}.intervals{margin:16px 0}.interval{position:relative;height:36px;background:var(--surface);margin:6px 0;border-radius:4px;overflow:hidden}.interval i{position:absolute;height:100%;background:var(--accent-soft);border-left:2px solid var(--accent)}.interval i.gold{background:var(--second-soft);border-color:var(--second)}.interval span{position:relative;z-index:1;font:12px/36px ui-monospace,monospace;padding-left:7px}.table .tr>*{min-height:4.8em}.formula{white-space:pre-line;min-height:7.2em}.actions:has(>button:only-child){grid-template-columns:1fr}.metrics strong{min-height:3.2em}.rangegrid{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:3px;margin:14px 0}.rangegrid .cell{min-height:30px;padding:3px 1px;font-size:10px}.message{min-height:7.2em;white-space:pre-line;font:13px/1.8 ui-monospace,monospace;overflow-wrap:anywhere}\n/* Allow CJK hanging punctuation without overflowing a metric's border box. */\n.metrics>div{padding-right:4px}.metrics span{line-break:anywhere}\n\n.chart-wrap{margin:18px 0}.chart-label{font-size:12px;color:var(--muted);min-height:3.2em}.curve{display:block;width:100%;height:auto;max-height:320px;overflow:visible}.curve text{font:11px ui-monospace,monospace;fill:var(--muted)}.gridline{stroke:var(--rule);stroke-width:1}.metrics strong{font-size:20px;min-height:3.2em}.formula{font:12px/1.8 ui-monospace,monospace;min-height:9em}.readout{min-height:8em}.presets button{flex-basis:30%}.scope p{overflow-wrap:anywhere} .unit-note{font-size:12px;color:var(--muted);margin:10px 0}\n\n.metrics span{word-break:break-all;line-break:strict}.metrics>div{padding-right:6px}\n\n.cell{min-height:72px}.metrics strong{min-height:3.6em}\n\n.source{min-height:13em}","js":"const $=s=>document.querySelector(s);const set=(id,v)=>$('#'+id).textContent=v;const t=k=>viz.t(k);function cells(id,values){$('#'+id).replaceChildren(...values.map(v=>{const e=document.createElement('div');e.className='cell '+(v.cls||'');e.textContent=v.text;e.title=v.title||v.text;return e;}));}function pressed(mode){document.querySelectorAll('[data-mode]').forEach(e=>e.setAttribute('aria-pressed',String(e.dataset.mode===mode)));}const esc=s=>String(s).replace(/[&<>\"']/g,c=>({'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[c]));const fmt=s=>'{'+[...s].sort().join(', ')+'}';function graph(id,nodes,edges){const el=$('#'+id);el.setAttribute('viewBox','0 0 360 200');el.innerHTML='<defs><marker id=\"arrow-'+id+'\" viewBox=\"0 0 10 10\" refX=\"8\" refY=\"5\" markerWidth=\"5\" markerHeight=\"5\" orient=\"auto-start-reverse\"><path d=\"M 0 0 L 10 5 L 0 10 z\" fill=\"var(--muted)\"/></marker></defs>'+edges.map(e=>{const a=nodes[e[0]],b=nodes[e[1]],dx=b.x-a.x,dy=b.y-a.y,d=Math.hypot(dx,dy)||1;if(edges.some(r=>r[0]===e[1]&&r[1]===e[0])){const nx=-dy/d,ny=dx/d;return '<path class=\"edge '+(e[2]?'on':'')+'\" d=\"M '+(a.x+dx/d*22+nx*12)+' '+(a.y+dy/d*22+ny*12)+' Q '+((a.x+b.x)/2+nx*38)+' '+((a.y+b.y)/2+ny*38)+' '+(b.x-dx/d*25+nx*12)+' '+(b.y-dy/d*25+ny*12)+'\" marker-end=\"url(#arrow-'+id+')\"/>';}return '<line class=\"edge '+(e[2]?'on':'')+'\" x1=\"'+(a.x+dx/d*25)+'\" y1=\"'+(a.y+dy/d*25)+'\" x2=\"'+(b.x-dx/d*28)+'\" y2=\"'+(b.y-dy/d*28)+'\" marker-end=\"url(#arrow-'+id+')\"/>';}).join('')+nodes.map(n=>'<g><circle class=\"node '+(n.cls||'')+'\" cx=\"'+n.x+'\" cy=\"'+n.y+'\" r=\"25\"/><text x=\"'+n.x+'\" y=\"'+(n.y+4)+'\" text-anchor=\"middle\">'+esc(n.name)+'</text>'+(n.sub?'<text x=\"'+n.x+'\" y=\"'+(n.y+43)+'\" text-anchor=\"middle\">'+esc(n.sub)+'</text>':'')+'</g>').join('');}function table(id,rows){$('#'+id).classList.add('table');$('#'+id).replaceChildren(...rows.map(r=>{const row=document.createElement('div');row.className='tr';row.style.gridTemplateColumns='repeat('+r.length+',minmax(0,1fr))';r.forEach(x=>{const c=document.createElement('div');if(typeof x==='object'){c.textContent=x.text;c.className=x.cls||'';}else c.textContent=x;row.append(c)});return row;}));}function band(id,parts,total){$('#'+id).replaceChildren(...parts.map((p,i)=>{const e=document.createElement('i');e.style.width=(100*p.value/total)+'%';e.className=i%2?'gold':'on';e.title=p.name+': '+p.value;return e}));}function intervals(id,items,total){$('#'+id).replaceChildren(...items.map(p=>{const row=document.createElement('div');row.className='interval';const bar=document.createElement('i');bar.style.left=(100*p.start/total)+'%';bar.style.width=(100*(p.end-p.start)/total)+'%';bar.className=p.cls||'';const label=document.createElement('span');label.textContent=p.label;row.append(bar,label);return row;}));}function plot(id,series,xr,yr,opts={}){const e=$('#'+id),X=x=>42+(x-xr[0])/(xr[1]-xr[0])*298,Y=y=>175-(y-yr[0])/(yr[1]-yr[0])*148;let out='<defs><clipPath id=\"clip-'+id+'\"><rect x=\"42\" y=\"27\" width=\"298\" height=\"148\"/></clipPath></defs>';for(let i=0;i<3;i++){let x=xr[0]+i*(xr[1]-xr[0])/2,y=yr[0]+i*(yr[1]-yr[0])/2;out+='<path class=\"gridline\" d=\"M '+X(x)+' 27V175M42 '+Y(y)+'H340\"/><text x=\"'+X(x)+'\" y=\"194\" text-anchor=\"middle\">'+esc(opts.xfmt?opts.xfmt(x):Number(x.toFixed(2)))+'</text><text x=\"36\" y=\"'+(Y(y)+4)+'\" text-anchor=\"end\">'+esc(opts.yfmt?opts.yfmt(y):Number(y.toFixed(2)))+'</text>';}out+='<g clip-path=\"url(#clip-'+id+')\">';for(const s of series){out+='<path fill=\"none\" stroke=\"'+(s.color||'var(--accent)')+'\" stroke-width=\"2.5\" '+(s.dash?'stroke-dasharray=\"5 4\"':'')+' d=\"'+s.pts.map((p,i)=>(i?'L':'M')+X(p[0]).toFixed(2)+','+Y(p[1]).toFixed(2)).join(' ')+'\"/>';}for(const p of opts.points||[])out+='<circle cx=\"'+X(p[0])+'\" cy=\"'+Y(p[1])+'\" r=\"4\" fill=\"var(--second)\" stroke=\"var(--paper)\" stroke-width=\"1.5\"/>';if(opts.cursor!==undefined)out+='<path d=\"M'+X(opts.cursor)+' 27V175\" stroke=\"var(--muted)\" stroke-dasharray=\"3 3\"/>';e.innerHTML=out+'</g>';e.dataset.curves=JSON.stringify(series.map(s=>s.pts));}const curve=(fn,lo,hi,n=120)=>Array.from({length:n+1},(_,i)=>{const x=lo+(hi-lo)*i/n;return[x,fn(x)]});function inputs(draw){document.querySelectorAll('input,select').forEach(e=>{e.addEventListener('input',draw);e.addEventListener('change',draw)});draw()}const n=id=>+$('#'+id).value;const show=(id,v,d=3)=>set(id,Number(v.toFixed(d)));function draw(){let u=n('use');set('use-value',u);intervals('regions',[{start:1,end:u,label:t('borrow')},{start:4,end:4.4,label:t('change'),cls:'gold'}],7);let lines=['let mut v = vec![1, 2, 3];','let first = &v[0];',...Array(5).fill('// …')];lines[4]='v.push(4);';lines[u]+=' use_value(*first);';$('#code').innerHTML=lines.map((s,i)=>'<span class=\"code-line '+(i===u||i===4?'on':'')+'\">'+i+' '+esc(s)+'</span>').join('');set('explanation',t(u>=4?'bad':'ok'));document.body.dataset.allowed=String(u<4);}inputs(draw);","audio":false,"strings":{"bad":"Rejected: push requires exclusive access while first is needed afterward. Spare capacity does not narrow its signature.","borrow":"Shared element borrow","capacity":"Enough capacity reserved","change":"push needs &mut Vec","heading":"Move a use across a mutation","intro":"Move the last reference use and inspect whether it overlaps push.","ok":"Allowed: the last use precedes push, so the element borrow is no longer needed.","reset":"Reset","scope":"Models the shown ordinary Vec::push call in straight-line control flow; NLL also analyzes branches, loops and destructors.","scopeLabel":"Model scope and assumptions","use":"Last use of first"}}
Reborrowing: Deriving a Shorter Permission Temporarily from an Existing One
parent is the existing &mut Vec, and child is the reborrow of its target. During the time child is used, conflicting accesses cannot be made through parent; after child's borrow ends, parent can continue to be used. Ownership of the original Vec was never transferred, so this is not "ownership restored after the function returns."
Calls with known parameter types of &mut T can often be implicitly reborrowed, without needing to explicitly write &mut *parent every time. Ordinary assignment or generic consumption by value should not be universally assumed to involve reborrowing; &mut T itself is not Copy.
Explicit Reborrowing and Moving Reference Variables
fnconsume<T>(_: T){}fnmain(){letmut number =1;let parent =&mut number;consume(&mut*parent);// What is passed is a newly created short borrow
*parent +=1;assert_eq!(*parent,2);}
If consume(&mut *parent) is changed to consume(parent), the generic parameter T will be inferred as &mut i32, and the reference value itself is moved, making parent unusable afterward. Neither version moves the ownership of number; the difference is "which reference value is consumed." When fixing this, the interface should accept the actual required &mut T, or explicitly create a short borrow, rather than looking for a Clone for an exclusive reference.
Exclusive Borrows Can Be Split into Disjoint Parts
It is safe for two &mut slices to exist simultaneously because the element ranges do not overlap. The compiler can also recognize independent borrows of some struct fields; for general dynamic indexing, however, you often need proven interfaces like split_at_mut rather than expecting it to deduce arbitrary arithmetic inequality conditions.
Dynamically Selecting Two Elements by First Turning Disjointness into Slice Boundaries
When i < j, split at j; i is definitely in the left half, and j corresponds to the zeroth item in the right half; when reversed, swap the return order so that the caller always gets i first and then j. This preserves input order while expressing mutually exclusive ranges through safe slice APIs. If the business logic only wants to swap two positions, using slice::swap directly is simpler and does not require obtaining two references first. Borrow Splitting
Method Signatures That Are Too Broad Can Also Create Unnecessary Conflicts
Here, title and rows are different fields, so it is safe to share-read one and exclusive-modify the other simultaneously. If changed to a method accepting &mut Report, the call boundary declares that it might exclusively own the entire object, and the caller cannot narrow this requirement based solely on the fact that the method currently only modifies rows internally. Prioritizing narrowing auxiliary function parameters is often a more accurate expression of responsibility than adding RefCell or copying title.
Reference Variables Do Not Need mut; The Target May Still Be Modified
For let reference = &mut value;, the reference binding does not need mut, but the target can still be modified through it. let mut reference additionally allows re-binding this variable to another reference. Distinguishing between "pointer variable can be changed" and "has exclusive access to the target" helps understand signatures.
The end of a borrow does not mean the guard has been destroyed. RefCell's Ref, MutexGuard, etc., hold runtime state and usually need to exit the appropriate scope or be explicitly dropped to release the corresponding protocol state; you cannot directly apply the NLL intuition of ordinary references.
Returning References and Elision Rules
fnfirst_word(text:&str)->&str{&text[..text.find('').unwrap_or(text.len())]}fnmain(){let text =String::from("中文 rust");assert_eq!(first_word(&text),"中文");}
The function returns a substring of the input, not a borrow of a newly created local String. find locates the byte position of the space, which happens to be on a UTF-8 boundary; you cannot arbitrarily treat character indices as byte offsets.
Here there is only one input reference lifetime, and the output is associated with it by the rules, so no explicit annotation is needed. Only when multiple inputs exist ambiguity do you need to express clearer relationships; see Lifetimes.
Borrowed Return Values Bring Constraints Back to the Caller
fnfirst_word(text:&str)->&str{&text[..text.find('').unwrap_or(text.len())]}fnmain(){letmut text =String::from("中文 rust");let word =first_word(&text);assert_eq!(word,"中文");
text.push('!');// word is no longer used
let owned =first_word(&text).to_owned();
text.clear();assert_eq!(owned,"中文");}
The &str version associates the result with the source, suitable for short-term reading; the String version explicitly separates storage, suitable for usage that crosses source modifications or deallocation. The latter is not "extending the lifetime of a reference," but creating another owner responsible for the text.
Check Sequentially When Encountering Borrow Errors
Issue
Corresponding Handling
Is the reference still used after modification?
Move read-only consumption before modification, or change the result representation
Do the two operations actually target different fields/ranges?
Narrow function parameters, use splitting interfaces
Did you move the &mut reference itself?
Use explicit parameter types or explicit reborrowing
Do you need to save independent data long-term?
Return owned values, explicitly cloning or sharing costs
Is it actually a guard holding a runtime lock?
Limit guard scope or explicitly drop
These handling methods change access timing, access scope, or ownership relationships respectively. Using unsafe to bypass errors does not automatically make the relationships valid, and adding clone does not guarantee resource independence; you must first determine the actual contract required.
Scope of Guarantees Provided by Compile-Time Checks
The ordinary borrow checker does not track reference counts at runtime, nor does it provide business locks for arbitrary resources. &[T] and &dyn Trait also contain corresponding metadata, so it is not accurate to say that all references are fixed at 8 bytes. After entering unsafe, FFI, or interior mutability wrappers, additional contracts are maintained by the implementer; safe callers relying on these wrappers are sound.