[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-rust-196-turns-ranges-into-safer-copies-en":3,"article-related-rust-196-turns-ranges-into-safer-copies-en":30,"series-tools-a3df178b-7492-4b4b-8ab6-1de524c2fbdd":75},{"id":4,"slug":5,"title":6,"content":7,"summary":8,"source":9,"source_url":10,"author":11,"image_url":12,"cover_image":12,"category":13,"language":14,"translated_content":11,"related_article_id":15,"keywords":16,"key_takeaways":22,"views":26,"created_at":27,"published_at":28,"topic_cluster_id":29},"a3df178b-7492-4b4b-8ab6-1de524c2fbdd","rust-196-turns-ranges-into-safer-copies-en","Rust 1.96 turns ranges into safer copies","\u003Cp data-speakable=\"summary\">\u003Ca href=\"\u002Ftag\u002Frust\">Rust\u003C\u002Fa> 1.96.0 adds Copy-friendly Range types that remove a common iterator footgun.\u003C\u002Fp>\u003Cp>I've been using Rust long enough that I stopped trusting anything that looks “obviously simple.” Ranges were one of those things. I’d reach for \u003Ccode>0..n\u003C\u002Fcode>, wire it into a helper, stash it in a struct, and then hit the same annoying wall: the type I thought was just a plain span over numbers was also acting like an iterator with state. That’s where Rust starts doing its usual thing, which is usually great until it isn’t. The old range types were convenient, but they also carried enough weirdness that I kept tripping over ownership rules in places that should have been boring. And boring is what I want from a range.\u003C\u002Fp>\u003Cp>What really bothered me was the mismatch between how I used ranges and how the library treated them. I wanted to copy them around, store them, pass them through APIs, and not think about whether I had consumed an iterator by accident. Instead, I had to remember that some range-ish types were iterator-ish in ways that made them awkward to reuse. That’s the sort of paper cut that doesn’t look dramatic in a changelog, but it infects real code. Rust 1.96.0 finally addresses that mess with new range types that behave the way most of us expected in the first place.\u003C\u002Fp>\u003Cp>The trigger for this breakdown was Paul Krill’s InfoWorld piece, \u003Ca href=\"https:\u002F\u002Fwww.infoworld.com\u002Farticle\u002F4191267\u002Frust-introduces-new-range-types.html\">\"Rust introduces new Range types\"\u003C\u002Fa>, which covers the stabilization of the new \u003Ccode>core::range\u003C\u002Fcode> types in Rust 1.96.0. The key detail is not the version number. It’s the cleanup: Rust is separating the “range as a value” idea from the “range as iterator state” idea, and that’s long overdue.\u003C\u002Fp>\u003Ch2>Rust finally stops pretending ranges are just iterators\u003C\u002Fh2>\u003Cblockquote>\"It is a footgun to implement both Iterator and Copy on the same type\"\u003C\u002Fblockquote>\u003Cp>What this actually means is that the old range types were too easy to misuse. A type that can be copied around freely should not also behave like a stateful iterator unless you really know what you’re doing. Rust’s standard library team is basically admitting that the old design mixed two different responsibilities.\u003C\u002Fp>\n\u003Cfigure class=\"my-6\">\u003Cimg src=\"https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1783190002602-30jh.png\" alt=\"Rust 1.96 turns ranges into safer copies\" class=\"rounded-xl w-full\" loading=\"lazy\" \u002F>\u003C\u002Ffigure>\n\u003Cp>The article says the new replacement range types implement \u003Ccode>IntoIterator\u003C\u002Fcode> rather than \u003Ccode>Iterator\u003C\u002Fcode>, which is the important shift. That sounds tiny, but it changes how the type behaves in everyday code. Instead of the range itself being the iterator, the range becomes a value that can produce an iterator when needed. That means the range can also be \u003Ccode>Copy\u003C\u002Fcode>, which is exactly what developers expected \u003Ca href=\"\u002Fnews\u002Fai-coding-subscriptions-predictable-value-2026-en\">when they\u003C\u002Fa> first saw something like \u003Ccode>0..10\u003C\u002Fcode>.\u003C\u002Fp>\u003Cp>I’ve run into this sort of confusion in APIs that try to be clever. They save a line of code up front and cost you an hour later when ownership gets weird. Rust usually avoids that trap, but ranges slipped through with a design that made sense historically and got awkward in practice. This update is Rust cleaning up its own mess, which I appreciate more than shiny new syntax.\u003C\u002Fp>\u003Cp>How to apply it: if you’re designing your own types, separate “this is a reusable description of work” from “this is the thing currently doing the work.” If your type is meant to be copied, don’t make the type itself carry hidden iteration state unless you absolutely need it.\u003C\u002Fp>\u003Cul>\u003Cli>Use value types for reusable descriptions.\u003C\u002Fli>\u003Cli>Use iterators for consumed state.\u003C\u002Fli>\u003Cli>When in doubt, make the conversion explicit.\u003C\u002Fli>\u003C\u002Ful>\u003Ch2>\u003Ccode>core::range\u003C\u002Fcode> is the boring API I wanted all along\u003C\u002Fh2>\u003Cp>The new stable types are \u003Ccode>core::range::Range\u003C\u002Fcode>, \u003Ccode>core::range::RangeFrom\u003C\u002Fcode>, \u003Ccode>core::range::RangeInclusive\u003C\u002Fcode>, and associated iterators. The article also says \u003Ccode>core::range::RangeFull\u003C\u002Fcode> and \u003Ccode>core::range::RangeTo\u003C\u002Fcode> will show up later as re-exports from \u003Ccode>core::ops\u003C\u002Fcode>. That’s a lot of names, but the idea is simple: Rust is moving the “good” version of ranges into a namespace that reflects their real purpose.\u003C\u002Fp>\u003Cp>What this actually means is that the standard library now has a proper home for range values that are meant to be copied, stored, and passed around. The old range syntax like \u003Ccode>0..1\u003C\u002Fcode> still produces legacy types for now, so nobody’s code explodes today. But the direction is obvious: the language wants the syntax to map to the new range family in a future edition.\u003C\u002Fp>\u003Cp>I like this because it gives library authors a cleaner target. If I’m writing code that needs to hold onto a range, I want a type that behaves like data, not a half-consumed iterator with personality problems. The new namespace also makes it easier to explain in docs and \u003Ca href=\"\u002Ftag\u002Fcode-review\">code review\u003C\u002Fa>. “Use \u003Ccode>core::range\u003C\u002Fcode> for reusable range values” is a sentence I can live with.\u003C\u002Fp>\u003Cp>How to apply it: when you introduce a new \u003Ca href=\"\u002Ftag\u002Fapi\">API\u003C\u002Fa>, name the stable concept after the thing users actually mean, not the implementation detail you happened to start with. If your public type is both data and behavior, you’re probably going to make somebody miserable later.\u003C\u002Fp>\u003Cul>\u003Cli>Prefer namespaces that reflect user intent.\u003C\u002Fli>\u003Cli>Keep legacy behavior isolated during transitions.\u003C\u002Fli>\u003Cli>Document the migration path before changing syntax.\u003C\u002Fli>\u003C\u002Ful>\u003Ch2>The real win is Copy-friendly slice accessors\u003C\u002Fh2>\u003Cp>InfoWorld notes that with these stabilizations, it’s now possible to store slice accessors in \u003Ccode>Copy\u003C\u002Fcode> types without splitting start and end. That’s the kind of sentence that looks dry until you’ve actually had to do the workaround yourself.\u003C\u002Fp>\n\u003Cfigure class=\"my-6\">\u003Cimg src=\"https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1783189998850-ou89.png\" alt=\"Rust 1.96 turns ranges into safer copies\" class=\"rounded-xl w-full\" loading=\"lazy\" \u002F>\u003C\u002Ffigure>\n\u003Cp>What this actually means is that code can carry around a range-like value without manually decomposing it into two fields just to satisfy the borrow checker. That’s a huge quality-of-life improvement for APIs that need to keep a slice window around. Instead of storing \u003Ccode>start\u003C\u002Fcode> and \u003Ccode>end\u003C\u002Fcode> separately, you can store the range itself and let the type system stop being annoying for once.\u003C\u002Fp>\u003Cp>I’ve done the split-field workaround. It works, but it’s ugly and it leaks implementation detail into your struct layout. You end up with code that says “I know this is a range, but I’m pretending it isn’t because the type system made me.” That’s not a design. That’s a surrender.\u003C\u002Fp>\u003Cp>How to apply it: if you have a range-like concept in your own code, ask whether users need the endpoints independently or whether they just need the interval as a unit. If it’s the latter, don’t force them to split it. Give them a single value they can copy.\u003C\u002Fp>\u003Cul>\u003Cli>Store ranges as ranges when possible.\u003C\u002Fli>\u003Cli>Split endpoints only when each endpoint has separate meaning.\u003C\u002Fli>\u003Cli>Prefer API shapes that match the mental model users already have.\u003C\u002Fli>\u003C\u002Ful>\u003Ch2>Public fields on \u003Ccode>RangeInclusive\u003C\u002Fcode> are a tell, not a flourish\u003C\u002Fh2>\u003Cp>The article says the new \u003Ccode>RangeInclusive\u003C\u002Fcode> type makes its fields public, unlike the legacy version that hid the exhausted iterator state. That detail matters more than it first appears. The old type had to protect internal iterator bookkeeping. The new one doesn’t, because it’s not pretending to be an iterator anymore.\u003C\u002Fp>\u003Cp>What this actually means is that the type is simpler and more honest. If a type is just representing a range, then its fields can be exposed without dragging along iterator exhaustion semantics. Rust is removing a layer of defensive weirdness that only existed because the old abstraction was doing double duty.\u003C\u002Fp>\u003Cp>I’ve always thought public fields get a bad reputation when the real issue is whether the abstraction is clean. Public fields on a messy type are a problem. Public fields on a straight-up data carrier are fine. This change says the new range types are data carriers first, iterator machinery second.\u003C\u002Fp>\u003Cp>How to apply it: when you design a type, don’t hide fields just because “encapsulation.” Hide them when there’s real invariants to protect. If the type is basically a tuple with a name, exposing fields can make the API easier to use and easier to reason about.\u003C\u002Fp>\u003Cp>For anyone maintaining libraries, this also means the migration story matters. If you’ve built helpers around legacy \u003Ccode>RangeInclusive\u003C\u002Fcode> behavior, you should expect the new types to be less forgiving about iterator-style assumptions. That’s good. Weird hidden state is how bugs breed.\u003C\u002Fp>\u003Ch2>Rust is still keeping legacy ranges around, and that’s the right call\u003C\u002Fh2>\u003Cp>The article says range syntax like \u003Ccode>0..1\u003C\u002Fcode> still produces the legacy types for now, and the team plans to move that syntax over in an upcoming edition. It also says a future version will introduce \u003Ccode>core::range::legacy::*\u003C\u002Fcode> as the new home for the current ranges. That’s a classic Rust migration move: keep the old thing working, name it honestly, and move forward without breaking everyone on Tuesday.\u003C\u002Fp>\u003Cp>What this actually means is that there’s a bridge period where both models exist. That’s not glamorous, but it’s how you avoid forcing the whole ecosystem to rewrite code just because the standard library got smarter. I respect that. Rust can be strict without being reckless.\u003C\u002Fp>\u003Cp>I ran into a similar migration pattern in a large codebase where we had to replace one internal date type with another. The worst mistake would have been a flag day. The better move was exactly what Rust is doing here: introduce the new API, keep the old one available, and make the old naming say “legacy” so nobody pretends it’s the long-term answer.\u003C\u002Fp>\u003Cp>How to apply it: if you’re shipping a breaking cleanup, give users a path. Keep the old API available long enough to migrate, but don’t let the old naming pretend it’s the future. Honest names reduce confusion.\u003C\u002Fp>\u003Ch2>The new macros are a nice side dish, not the main course\u003C\u002Fh2>\u003Cp>Rust 1.96.0 also adds \u003Ccode>assert_matches!\u003C\u002Fcode> and \u003Ccode>debug_assert_matches!\u003C\u002Fcode>, which check whether a value matches a pattern and panic with a \u003Ccode>Debug\u003C\u002Fcode> representation if it doesn’t. That’s useful, but I’d treat it as a convenience feature next to the range work.\u003C\u002Fp>\u003Cp>What this actually means is that Rust is making pattern-based assertions easier to write and easier to debug. If you’ve ever written a test that needed to confirm a value matched a specific enum shape, this saves a little ceremony and gives better failure output than a hand-rolled check.\u003C\u002Fp>\u003Cp>I like additions like this because they remove friction without changing how I think about the program. The range update changes how I model data. These macros just make my tests less annoying. Useful, yes. The headline? Not for me.\u003C\u002Fp>\u003Cp>How to apply it: use pattern assertions in tests when the shape matters more than the exact value. Keep them out of production logic unless they genuinely simplify error handling or invariant checks.\u003C\u002Fp>\u003Ch2>WebAssembly got stricter, and that’s a feature\u003C\u002Fh2>\u003Cp>The article also notes that WebAssembly targets no longer pass \u003Ccode>--allow-undefined\u003C\u002Fcode> to the linker. Undefined symbols now trigger a linker error instead of quietly becoming WebAssembly imports from the \u003Ccode>env\u003C\u002Fcode> module. That’s Rust choosing earlier failure over mystery behavior.\u003C\u002Fp>\u003Cp>What this actually means is that the toolchain will catch missing symbols before you ship a broken module or accidentally depend on a naming mistake. I’ve seen enough build systems to know that “it linked somehow” is not a compliment. It’s usually a warning sign.\u003C\u002Fp>\u003Cp>This part matters because it shows the same philosophy as the range change: remove hidden behavior that surprises people later. Whether the surprise is iterator state or undefined symbols, the fix is the same. Make the failure obvious and make the model simpler.\u003C\u002Fp>\u003Cp>How to apply it: if you maintain build tooling or cross-target code, prefer strict linking and early validation. Hidden imports and implicit fallbacks are the kind of thing that make debugging miserable three weeks later.\u003C\u002Fp>\u003Ch2>The template you can copy\u003C\u002Fh2>\u003Cpre>\u003Ccode>## What changed in Rust 1.96.0\n\nRust 1.96.0 introduces new `core::range` types that separate reusable range values from iterator state.\nThe big win is that these range types are `Copy`-friendly and avoid the old `Iterator` + `Copy` footgun.\n\n### Why this matters\n- Store ranges as values instead of splitting `start` and `end`\n- Use `IntoIterator` when a range needs to produce iteration behavior\n- Keep iterator state out of types that should be freely copied\n\n### Practical migration notes\n- Existing syntax like `0..1` still uses legacy range types for now\n- Plan for future editions to map range syntax to `core::range`\n- Treat `core::range::legacy::*` as compatibility territory, not the long-term API\n\n### Design rule I’m using\nIf a type is meant to be copied and reused, it should describe work, not perform work.\nIf it needs state, make that state explicit.\n\n### Example pattern\nrust\nuse core::range::Range;\n\n#[derive(Copy, Clone)]\nstruct Window {\n    bounds: Range\u003Cusize>,\n}\n\nimpl Window {\n    fn new(bounds: Range\u003Cusize>) -> Self {\n        Self { bounds }\n    }\n}\n\n\n### Test helper idea\nrust\nassert_matches!(value, Some(MyEnum::Ready { .. }));\n\n\n### My rule of thumb\n- Data-like range? Make it copyable.\n- Iterator-like state? Make it consumed.\n- Legacy compatibility? Keep it named honestly.\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>That template is mine, but the underlying idea comes from the Rust team’s range cleanup and Paul Krill’s InfoWorld summary of Rust 1.96.0. I’ve adapted it into something you can paste into docs, an internal memo, or a migration note without rewriting the whole explanation.\u003C\u002Fp>\u003Cp>Source: \u003Ca href=\"https:\u002F\u002Fwww.infoworld.com\u002Farticle\u002F4191267\u002Frust-introduces-new-range-types.html\">InfoWorld article\u003C\u002Fa>. For the upstream Rust side, start with the \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Frust-lang\u002Frfcs\u002Fpull\u002F3550\">RFC 3550 discussion\u003C\u002Fa> and the \u003Ca href=\"https:\u002F\u002Fblog.rust-lang.org\u002F\">Rust blog\u003C\u002Fa> for release details. The template and commentary here are my synthesis, not a verbatim rewrite.\u003C\u002Fp>","Rust 1.96.0 adds new Range* types that are Copy-friendly and fix a nasty Iterator footgun.","www.infoworld.com","https:\u002F\u002Fwww.infoworld.com\u002Farticle\u002F4191267\u002Frust-introduces-new-range-types.html",null,"https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1783190002602-30jh.png","tools","en","29e9abee-1972-4b0f-8994-ce27c006a5f3",[17,18,19,20,21],"Rust","range types","Copy","IntoIterator","standard library",[23,24,25],"Rust 1.96.0 fixes a long-standing range design problem by separating reusable values from iterator state.","The new core::range types are easier to copy, store, and use in APIs that need slice-like windows.","The migration is gradual, with legacy range syntax staying in place until a future edition changes it.",0,"2026-07-04T18:32:53.529817+00:00","2026-07-04T18:32:53.52+00:00","67ae454c-5b5e-4f58-8062-543f410e2792",{"tags":31,"relatedLang":34,"relatedPosts":38},[32],{"name":17,"slug":33},"rust",{"id":15,"slug":35,"title":36,"language":37},"rust-196-turns-ranges-into-safer-copies-zh","Rust 1.96 讓 range 變可複製","zh",[39,45,51,57,63,69],{"id":40,"slug":41,"title":42,"cover_image":43,"image_url":43,"created_at":44,"category":13},"730d012d-2979-4f5e-b881-545cfa17aa52","rustrover-2026-1-4-right-default-ide-rust-en","RustRover 2026.1.4 is the right default IDE for Rust teams","https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1783211563197-9rof.png","2026-07-05T00:32:20.046071+00:00",{"id":46,"slug":47,"title":48,"cover_image":49,"image_url":49,"created_at":50,"category":13},"fcbbb173-58d2-4218-a111-452a7238377e","claude-design-synced-prototypes-setup-en","Claude Design setup for synced prototypes","https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1783191767986-jvz3.png","2026-07-04T19:02:22.032457+00:00",{"id":52,"slug":53,"title":54,"cover_image":55,"image_url":55,"created_at":56,"category":13},"b55fbd0c-846b-4592-953e-e581e1dd4918","ai-data-operations-vs-mlops-what-each-owns-en","AI Data Operations vs MLOps: what each owns","https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1783168368731-aeq1.png","2026-07-04T12:32:19.952613+00:00",{"id":58,"slug":59,"title":60,"cover_image":61,"image_url":61,"created_at":62,"category":13},"6f72b385-bc6c-47cf-b466-8eb40fed86a7","opentag-turns-slack-threads-into-actions-en","OpenTag turns Slack threads into actions","https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1783148604415-put0.png","2026-07-04T07:02:50.733486+00:00",{"id":64,"slug":65,"title":66,"cover_image":67,"image_url":67,"created_at":68,"category":13},"fa7e59ac-8216-4826-84a1-3ae5a7fc4f57","gpu-vram-needed-llm-fine-tuning-2026-en","GPU VRAM Needed for LLM Fine-Tuning in 2026","https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1783128777001-pdg7.png","2026-07-04T01:32:34.039474+00:00",{"id":70,"slug":71,"title":72,"cover_image":73,"image_url":73,"created_at":74,"category":13},"f8c5ce9b-047c-42ee-bc74-66efa81c4177","claude-sonnet-5-shangshou-bushu-yu-pinggu-en","Claude Sonnet 5 上手部署与评估","https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1783125166441-691z.png","2026-07-04T00:32:19.725711+00:00",[76,81,86,91,96,101,106,111,116,121],{"id":77,"slug":78,"title":79,"created_at":80},"8008f1a9-7a00-4bad-88c9-3eedc9c6b4b1","surepath-ai-mcp-policy-controls-en","SurePath AI's New MCP Policy Controls Enhance AI Security","2026-03-26T01:26:52.222015+00:00",{"id":82,"slug":83,"title":84,"created_at":85},"27e39a8f-b65d-4f7b-a875-859e2b210156","mcp-standard-ai-tools-2026-en","MCP Standard in 2026: Integrating AI Tools","2026-03-26T01:27:43.127519+00:00",{"id":87,"slug":88,"title":89,"created_at":90},"165f9a19-c92d-46ba-b3f0-7125f662921d","rag-2026-transforming-enterprise-ai-en","How RAG in 2026 is Transforming Enterprise AI","2026-03-26T01:28:11.485236+00:00",{"id":92,"slug":93,"title":94,"created_at":95},"6a2a8e6e-b956-49d8-be12-cc47bdc132b2","mastering-ai-prompts-2026-guide-en","Mastering AI Prompts: A 2026 Guide for Developers","2026-03-26T01:29:07.835148+00:00",{"id":97,"slug":98,"title":99,"created_at":100},"3ab2c67e-4664-4c67-a013-687a2f605814","garry-tan-open-sources-claude-code-toolkit-en","Garry Tan Open-Sources a Claude Code Toolkit","2026-03-26T08:26:20.245934+00:00",{"id":102,"slug":103,"title":104,"created_at":105},"66a7cbf8-7e76-41d4-9bbf-eaca9761bf69","github-ai-projects-to-watch-in-2026-en","20 GitHub AI Projects to Watch in 2026","2026-03-26T08:28:09.752027+00:00",{"id":107,"slug":108,"title":109,"created_at":110},"9f332fda-eace-448a-a292-2283951eee71","practical-github-guide-learning-ml-2026-en","A Practical GitHub Guide to Learning ML in 2026","2026-03-27T01:16:50.125678+00:00",{"id":112,"slug":113,"title":114,"created_at":115},"1b1f637d-0f4d-42bd-974b-07b53829144d","aiml-2026-student-ai-ml-lab-repo-review-en","AIML-2026 Is a Bare-Bones Student Lab Repo","2026-03-27T01:21:51.661231+00:00",{"id":117,"slug":118,"title":119,"created_at":120},"6d1bf3f6-e191-4d30-b55b-8a0722fa6afe","ai-trending-github-repos-and-research-feeds-en","AI Trending Tracks Repos and Research Feeds","2026-03-27T01:31:35.709532+00:00",{"id":122,"slug":123,"title":124,"created_at":125},"010539a1-4c3a-4bd3-937a-26616422ee0d","awesome-ai-for-science-research-tools-map-en","Awesome AI for Science Is Becoming a Real Research Map","2026-03-27T01:46:50.89513+00:00"]