[HN Gopher] Rust 1.63
___________________________________________________________________
Rust 1.63
Author : todsacerdoti
Score : 270 points
Date : 2022-08-11 15:03 UTC (7 hours ago)
(HTM) web link (blog.rust-lang.org)
(TXT) w3m dump (blog.rust-lang.org)
| baby wrote:
| so const Mutex means you can do this IIUC:
| const THING: Mutex<u64> = Mutex::new(4);
|
| without using the once_cell crate. This is pretty cool! Also I
| realize that the Rust playground is still using 1.62.0
|
| https://play.rust-lang.org/?version=beta&mode=debug&edition=...
| shepmaster wrote:
| Wouldn't you want to use static instead of const, otherwise you
| might get a new unique mutex at each usage? I think there's a
| Clippy lint for that.
|
| The playground rebuilds overnight (roughly after the nightly is
| released); releases don't have as fixed timing so I tend to
| trigger a rebuild when I notice. This HN post was delivered
| before the git tag was published even, so I've started it.
|
| Playground is updated now.
| tialaramex wrote:
| Yes. If I say FOUR is a const Mutex with a 4 in it, whenever
| I talk about FOUR I get a completely new unlocked Mutex with
| a 4 in it, unrelated to any other Mutex regardless of whether
| it was made the same way.
|
| This might be what you want if you, for some reason, need to
| make different Mutexes with a 4 in them all the time. But, if
| you actually meant one Mutex, which intially has a 4 in it,
| then that's a static variable not a constant.
|
| https://play.rust-
| lang.org/?version=beta&mode=debug&edition=...
|
| Change FOUR to be static instead of const, and now when we
| print y each time it's gone up by ten because we're using the
| same Mutex which is what we presumably intended.
| baby wrote:
| What's the difference between CONST and STATIC
| fundamentally?
| CryZe wrote:
| If those terms mean anything to you: const is an rvalue,
| static is an lvalue.
| notpopcorn wrote:
| A const is like a `#define` in C or C++, while a static
| is a global variable.
| aendruk wrote:
| It's a small thing, but array::from_fn makes me happy.
| brundolf wrote:
| Something I can't figure out is how it infers the length in
| this example: let array =
| core::array::from_fn(|i| i); assert_eq!(array, [0, 1, 2,
| 3, 4]);
|
| Is it because of the assert_eq? Can it use the length of the
| second argument to infer the length all the way back up in the
| from_fn call?
| aendruk wrote:
| Yep, you could change the asserted length and it would
| succeed: assert_eq!(array, [0, 1, 2]);
|
| If you tried both-- assert_eq!(array, [0, 1,
| 2]); assert_eq!(array, [0, 1, 2, 3, 4]);
|
| --the assertions would never run because it wouldn't even
| compile: error[E0277]: can't compare `[usize;
| 3]` with `[{integer}; 5]`
| dymk wrote:
| Yes, it's inferring that `array` must be an `[i32; 5]`
| because there exists an impl of `PartialEq` for `[T; N]`
| against another `[T; N]`, so `N` in `::from_fn` must be 5.
| sophacles wrote:
| nit: wouldn't it be usize since the only way to get T is
| from the bare numbers which default to usize?
| [deleted]
| steveklabnik wrote:
| "bare numbers" don't default to usize; integers default
| to i32 and floats to f64.
| orlp wrote:
| In this case the "bare numbers" do get inferred to be
| usize due to the signature of from_fn.
| steveklabnik wrote:
| Yes, I realize that I may have read these words slightly
| differently than the parent meant them! I just said the
| same thing in a reply to your sibling.
| aendruk wrote:
| It does seem to be choosing [usize; 5] in this case
| though.
|
| https://rust.godbolt.org/z/qasxnrTf9
| steveklabnik wrote:
| Yes, that is true. If you use a literal array, you get
| i32 for the element type.
|
| I _believe_ this is because of the signature:
| pub fn from_fn<T, const N: usize, F>(cb: F) -> [T; N]
| where F: FnMut(usize) -> T,
|
| While T is unconstrained, N is a usize, which is used in
| the closure, which we then re-use as the element.
| sophacles wrote:
| OK this is just kinda funny - I was right, but only by
| accident. For some reason I thought that the literal
| defaulted to usize not i32. The fact that this path makes
| my assertion of usize correct is pretty cool though.
| Thanks for diving into it!
| orlp wrote:
| Sorry but the typing part is incorrect. Look at the
| signature of from_fn: pub fn from_fn<T,
| const N: usize, F>(cb: F) -> [T; N] where
| F: FnMut(usize) -> T,
|
| It takes a function with signature f(usize) -> T. So |i| i
| gets inferred to be a function taking a usize, and
| returning a usize (since we just give the argument straight
| back). So it infers [usize; 5] in the end.
|
| For example core::array::from_fn(|i| i) == [0i32] wouldn't
| even compile.
| wongarsu wrote:
| You are right. The parameter given to the closure is the
| array index, which is usize. Since that's returned
| straight back the returned value is also of type usize,
| and the integers in the array in the assert are inferred
| to also be usize.
|
| Which is in a way an even stronger showcase of Rust's
| type inference: the length of the variable is inferred
| from the constant array, but the type of the content of
| the constant array is inferred by the type of the content
| of the variable, which is inferred from the type of the
| closure.
| dymk wrote:
| Good catch. The parent comment is interested in how the
| array length is inferred though, so I'm going to consider
| the explanation close enough (that it's an i32 or usize
| isn't particularly relevant).
| zerr wrote:
| What's a sane/legit use case of such inferring in general?
| game-of-throws wrote:
| let numbers = [0, 1, 2]; let doubled =
| numbers.map(|x| x * 2);
|
| You wouldn't want to have to explicitly type out the
| length of the second array.
| tomjakubowski wrote:
| That isn't really inferring the size of the array though.
| [T; N]::map(impl FnMut(T) -> U) defines its return type
| as [U; N]. N is fixed at the original array literal.
|
| https://doc.rust-lang.org/std/primitive.array.html
| brundolf wrote:
| It's inferring it from the array literal in the first
| place, but it is a different kind of inference from the
| original one. But I think that's what the question was
| asking for:
|
| > What's a sane/legit use case of such inferring in
| general?
|
| Depends how you interpret "such inferring"
| dymk wrote:
| It's inferring the size of `doubled`
| [deleted]
| PoignardAzur wrote:
| A few use cases: let foobar =
| Default::default(); do_something_with(foobar); //
| where do_something_with takes a FooBar param
|
| One I often use in unit tests: fn
| generate_ids<const N: usize>() -> [Id; N] { ... }
| let [id_button, id_label, id_thing, id_other_thing] =
| generate_ids();
|
| (before const generics were stabilized, the above code
| instead had multiple utility functions, eg
| generate_2_ids, generate_3_ids, etc)
| brundolf wrote:
| I think the one here is legit (perhaps more realistic
| would be where you're passing the new array to an actual
| function that requires a certain array length).
|
| People always complain about Rust's type system being
| verbose- well, this makes it less verbose. It knows what
| you need from the function call, so it doesn't make you
| say it. And as an added benefit, if the required type
| ever changes in a way that can still be generated by the
| provided code (eg. the function you're passing to needs a
| different length), you won't need to update any explicit
| type annotations at the call-site.
|
| If that's ever undesirable - you want to be very precise
| about your code - well, then you can do that too by
| specifying the generic parameters explicitly.
| kibwen wrote:
| It's not anything specific to arrays, it's just how type
| inference works. Here's another example:
| let mut x = HashMap::new(); x.insert(1, 2);
|
| Note that nowhere did we need to specify the concrete
| type of the HashMap; the compiler sees that you
| eventually insert numbers into the map so it uses that
| information to fill in the generic type parameters for
| the key and value.
| Ar-Curunir wrote:
| You general type inference, or inferring the array
| length? The latter follows from the former, so it would
| be kind of a weird hole in the language if type inference
| worked everywhere except array lengths.
| zerr wrote:
| "Scattered through multiple lines" inference :) Such code
| makes another programmer analyze multiple lines to deduce
| types in the head.
| brundolf wrote:
| In practice, type inference works best when paired with
| editor integration. Most languages/editors will give you
| hover-overs with inferred types, but some like rust-
| analyzer have started going further (the greyed-out text
| here is all inlaid by the editor): https://user-
| images.githubusercontent.com/3971413/96668192-1...
| dymk wrote:
| The tooling ecosystem, for instance rust-analyzer, make
| this not an issue if you're reading the code in an
| environment that supports it. I have rust-analyzer to
| display inferred types when I hold `control+command`.
|
| In other languages, this can be a brittle/expensive
| operation due to meh tooling. But with Rust, it tends to
| "just work".
|
| Online viewers of source e.g. Github and such don't have
| all this information exposed yet, but they're
| incrementally getting there. For instance, "go to
| definition" works for Rust code in Github.
|
| One could imagine a generic file format included as an
| artifact in source control, that online viewers could
| consume, to annotate spans of source code. Go to
| definition, show expanded type, etc.
| brundolf wrote:
| That rocks
| svnpenn wrote:
| Why does it arbitrarily choose length 5?
|
| https://doc.rust-lang.org/core/array/fn.from_fn.html
| aendruk wrote:
| In that example N is inferred from the assertion; observing
| the output has affected it.
| svnpenn wrote:
| Wow that is stupid. That is way too much assumption.
| sophacles wrote:
| Exactly 0 assumptions are made - how is that too much?
| surewe wrote:
| Sure, it's a lot of assumption, but the type system would
| prevent an invalid assumption from compiling (arrays are
| typed [T; N] where T is the type they hold and N is the
| number of elements), and you can always override it with
| a turbofish.
| dymk wrote:
| https://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type
| _sy...
|
| It's a dream once you understand it. You don't need to
| understand the math, just the general concept of type
| unification, and that type inference can flow in "both
| directions", as opposed to in e.g. C++ where `auto`
| inference only works in one direction.
|
| Rust is not exactly HM type inference, but it's something
| close to it. http://smallcultfollowing.com/babysteps/blog
| /2014/07/09/an-e...
| chrismorgan wrote:
| No, it's just the right amount, and makes perfect sense.
| This is the whole point of type inference: where there
| are multiple possibilities, determine types based on how
| you use them, and if you still have ambiguity after that,
| complain.
|
| If you tried comparing it to something that wasn't an
| array, or if you tried comparing it to multiple
| different-sized arrays, it would complain.
| shepmaster wrote:
| Is likely based on what you compare it to. For example, this
| passes as well let array =
| core::array::from_fn(|i| i); assert_eq!(array, [0, 1,
| 2, 3, 4, 5]);
|
| The magic of type inference
| ydnaclementine wrote:
| What is everyone building in rust, and how do the killer rust
| features (mentioned in other comments) help you?
|
| I'm not anti rust in any way, it's more of having limited time
| and so many languages problem. But I'm interested in the types of
| problems rust is good for, so I could consider it if/when I
| encounter them
| pjmlp wrote:
| Only hobby coding.
|
| Java, .NET languages and C++ are what pay the bills for me.
| gattr wrote:
| I wrote a video acquisition tool for astrophotography [1] (and
| I dogfood it). Uses GTK3 for GUI.
|
| [1] https://github.com/GreatAttractor/vidoxide
| ostenning wrote:
| I'm building commercial hardware products using embedded Rust,
| I love it. I cant really imagine going back to C. I haven't dug
| too deep into the offerings with this update, but none of the
| standard library stuff is relevant for me
| dymk wrote:
| I've written no code professionally in Rust, but a fair amount
| of personal project code. I've written C++ both professionally
| and as a hobby. At least for hobby use, comparing the two, Rust
| is wonderful.
|
| - It's easy to set up cross compilation.
|
| - Cargo makes dependencies easy.
|
| - Building is almost always just `cargo build` except for very
| exceptional projects, same with `cargo test`.
|
| - `cargo fmt` makes formatting easy and built in.
|
| - Clippy gives actually useful lints and can automate most
| refactorings.
|
| - Rust-analyzer is fast to index decently large projects, works
| with almost all language features (even complex ones like proc
| macros), and has some real time-saver automation built in.
|
| Working with the borrow checker can feel like a pain, but in
| many cases, feels like a fun puzzle (writing hobby code, I'm
| not under time pressure, so it's 'solve a puzzle' and not 'oh
| fuck deadline coming up').
|
| But really, the tooling of the language is where it shines.
| CJefferson wrote:
| Personally, I use Rust as a "better C++".
|
| Ways in which it is better:
|
| * A decent package manager
|
| * "Safe by default" (you have to use 'unsafe' to turn off the
| safety features), unlike C++ which is "unsafe by default" (v[i]
| is undefined behaviour if i is out of bounds, for all of C
| arrays, std::arrays and std::vectors).
|
| * Really easy to do multithreading -- I had reached the point
| with C and C++ where I was of the opinion it is "almost
| impossible" to write large thread-safe programs, and all
| communication should be between processes with pipes, wherever
| reasonable. In Rust I again feel I can safely and productively
| write multi-threaded code.
|
| The things Rust doesn't let you do (throw pointers around
| everywhere) can get a little annoying, but I find the extra
| safety increases my productivity enough that it's worth the
| tradeoff.
| tialaramex wrote:
| You didn't say otherwise, but this is such a frequent
| misunderstanding from people who don't write Rust, or write
| only safe Rust (which is fine) that it's worth pointing out
| the unsafe keyword and Rust's choice to be "safe by default"
| are not directly related. Culturally obviously they come from
| the same place, but for example:
|
| v[i] is bounds checked in Rust _even in unsafe_. The unsafe
| "super powers" don't include "magically now indexing has no
| bounds checks" but because Rust's get function
| v.get_unchecked(i) is marked unsafe++ you would need to mark
| code unsafe to use that function and _that_ function doesn 't
| have bounds checks.
|
| If you write: unsafe {
| println!("{}", v[i]); }
|
| The compiler will point out that unsafe isn't doing anything
| for you here, v[i] is safe, marking it unsafe is just a waste
| of everybody's time.
|
| C++ doesn't have bounds checked array access for its
| abandoned built-in arrays, but it does (these days) have
| bounds checked access for std::array and std::vector as a
| separate member function, however because they aren't the
| default few C++ programmers use them even where they
| undoubtedly should. This is an ergonomics issue, it's just
| easier to write needlessly unsafe C++.
|
| ++ This said just get() before I edited it, but Steve
| corrected me, see below.
| steveklabnik wrote:
| Teeeny tiny note
|
| > because Rust's get function v.get(i) is marked unsafe
|
| You mean get_unchecked. get is safe, and returns an Option,
| so that None can be returned if something is out of bounds.
| tialaramex wrote:
| Doh! I even had the "get_unchecked()" function in front
| of me on the screen and wrote get() anyway. Thanks Steve.
| steveklabnik wrote:
| No problem. Thanks for explaining what unsafe does and
| doesn't do; you're 100% right that this is a common
| misconception that comes up often.
| CJefferson wrote:
| You are right, I did know this but it's worth clarifying.
| Thanks.
| dralley wrote:
| >(you have to use 'unsafe' to turn off the safety features)
|
| "unsafe" doesn't turn off any safety features, it just allows
| you to do additional things which the base language does not,
| like:
|
| * use raw pointers
|
| * use mutable static globals
|
| * access fields of unions
|
| https://doc.rust-lang.org/book/ch19-01-unsafe-
| rust.html#unsa...
|
| All the rules of safe Rust still apply inside of unsafe
| blocks. The borrow checker still works, etc.
| shpongled wrote:
| I'm building scientific software in Rust.
|
| Phenomenal performance, drop-in concurrency support (`iter()`
| -> `par_iter()` with Rayon), and a great ML-based type system
| that makes writing correct code easy.
|
| It also has some of the best developer UX/tooling out of any
| language I've used.
| nynx wrote:
| I've written a bunch of embedded software in rust.
| pornel wrote:
| Cloudflare is using Rust for network stacks, proxies, caches,
| compression, and image processing. Basically everything that
| you would use C or C++ for, but where security is also
| incredibly important.
| kibwen wrote:
| I work on a project that's basically a mini-OS designed to host
| WebAssembly applications.
|
| The OS parts need to run on bare metal and do all sorts of
| cursed shenanigans, where Rust's separation of safe and unsafe
| code lets us better focus on proving to ourselves that the
| unsafe bits are working as intended (we also test our unsafe
| code under Rust's Miri interpreter/sanitizer for extra
| confidence). IOW, the killer feature is low-level control plus
| a reasonable expectation of safety.
|
| The actual WebAssembly interpreter is also written in Rust,
| which is a good fit because inefficiency in an interpreter
| leads to inefficiency in anything running in the interpreter.
| The killer feature here is performance plus safety.
|
| The overall package is bundled up into a CLI app that lets you
| deploy an instance of our OS with your application running
| within. Rust has a fairly nice wealth of libraries that make
| this pleasant, from CLI argument parsers to cryptography to
| OIDC and beyond. And it all gets packaged up into a single
| binary for easy distribution (even the OS and interpreter
| parts, which get embedded directly in the binary via
| `include_bytes!`). The killer feature here is great platform
| support (including cross-compilation) and small binaries
| (though you may reasonably disagree on "small"; altogether the
| binary (again, including the OS and interpreter) comes out to
| 25 MB).
|
| Finally, Rust's lack of a pervasive runtime and great
| WebAssembly tooling means that it's easy to compile Rust
| applications to run on top of all this as well.
| cultureulterior wrote:
| This OS seems interesting! Link?
| kibwen wrote:
| Keep in mind that I'm using "OS" here loosely; it's a bare-
| metal program that exposes a subset of Linux syscalls so
| that the interpreter (which itself is compiled for Linux)
| can run in the extremely specific context that we target.
| It's still early days so I won't spend too much time
| shilling it, but all the code is open source and lives
| under the umbrella of the Linux Foundation:
| https://enarx.dev/
| cliffcrosland wrote:
| We are using Rust to build a fast log event database. The
| workload includes a lot of asynchronous networking I/O and
| parallelized CPU-intensive work, like indexing and SIMD-
| accelerated string search. There are great libraries for what
| we need. The performance and low memory footprint are quite
| useful.
| Hamuko wrote:
| I've written a small automatic file organiser in Rust that I
| run in a Docker container on my NAS. Docker reports that the
| container is using 1.5 MiB of memory, so that's pretty nice.
| Pretty sure I wouldn't have achieved that if I wrote it in
| Python like I normally do.
| jackmott42 wrote:
| I've done some hobby projects in Rust. One was a SIMD
| abstraction library, where you could write code that looks more
| or less like SIMD intrinsics, but it would either at compile
| time or runtime select the SIMD instruction set for the target
| cpu.
|
| The traits/generics/macro system made that feasible, though
| messy. You can do similar things with templates in C++
| ekidd wrote:
| I've built a fair amount of production software in Rust. The
| best features are:
|
| - Rust is naturally pretty fast, on the rough order of C++ in
| many cases. Even unoptimized programs tend to be very snappy
| (as long as you remember to compile in release mode and buffer
| I/O).
|
| - Rust tends to warn me if I make a dumb mistake, rather than
| having my program mysteriously corrupt memory at run-time.
|
| - Rust has very nice support for portable CLI applications,
| both in the standard library and in third-party libraries.
|
| - With a bit of extra work, I can usually deliver a single,
| statically-linked Linux binary. Go is even better at this, but
| Rust does it well.
|
| - It turns out the "algebraic data types", what Rust calls
| "enum" and "match", are just a really nice way to write down
| every possible "case" or "state" of some value. If a piece of
| software involves hundreds of special cases, Rust allows me to
| think about them clearly.
|
| - Rust has surprisingly good third-party libraries for many
| things. (Not everything.)
|
| - Multithreaded Rust apps are a dream.
|
| Cons:
|
| - Rust forces me to keep track of whether things live on the
| heap or the stack, whether I'm passing them by value or
| reference, and so on. This is good when I want performance, but
| for other kinds of code, it's just a "cognitive tax."
|
| - Rust's learning curve is higher than Go, but arguably lower
| than C++. This is especially true if you've either never worked
| with stack/heap/pointers before.
|
| - Rust tends to favor "mostly functional" architectures over
| "mutable objet soup" architectures. This pushes you to use
| less-familiar designs for games and GUI libraries, for example.
| wiseowise wrote:
| > Rust tends to favor "mostly functional" architectures over
| "mutable objet soup" architectures. This pushes you to use
| less-familiar designs for games and GUI libraries, for
| example.
|
| How is that a con?
| ikawe wrote:
| One example would be the lack of pragmatic rust native GUI
| libraries. There are wrappers for GTK and Qt, which are
| probably your best option.
|
| The most popular pure rust ones are based on somewhat
| esoteric patterns and seem prone to being abandoned.
|
| Within that there are some interesting options, like for
| functionally reactive programming and immediate mode guis,
| but these paradigms aren't all encompassing and in fact
| cover a pretty minority use case based on what GUIs are
| being created today.
|
| Maybe one day we'll all only ever create purely functional
| GUIs and speak Esperanto, but until then, we're a little
| hamstrung in rust.
| game-of-throws wrote:
| I think that's more a function of the newness of the
| language than anything else. Golang is (I say this as a
| Rust developer) more popular, has been around longer, yet
| still has the same dearth of GUI libs.
| oconnor663 wrote:
| It's a big piece of the learning curve, and one that
| usually only shows up when you try to write larger
| programs. Plus there's very little the compiler can do to
| point you in the right direction when your object soup
| needs major refactoring. From what I've seen, a lot of
| folks either give up on Rust or start writing blatantly
| unsound unsafe code when they hit this.
|
| On the upside, a lot of C++ game programming uses an ECS-
| style architecture, which does work well in Rust.
| iopq wrote:
| When I tried to be more functional, it was really awkward in
| Rust
|
| I wanted to write some helper functions that applied an
| argument to a closure and I got this code
| fn apply<A, B, C, G>(mut f: impl FnMut(B) -> G, a: A) -> impl
| FnMut(&B) -> C // must still be `for<'r> impl
| FnMut(&'r B) -> C`, because that's what filter requires
| where G: FnMut(A) -> C, B: Copy, // for
| dereferencing A: Clone, { move
| |b| f(*b)(a.clone()) // this must do any bridging necessary
| to satisfy the requirements }
|
| needless to say, Rust doesn't do automatic currying or any
| advanced functional language tricks so it's just painful to
| write the same type of code
| teknopurge wrote:
| security. I dabble with system programs and it's nice to get
| the speed/portability of native optimized code and know most
| memory issues won't occur.
| di4na wrote:
| NIFs for particular casting of numbers to other binary formats
| in erlang. NIFS for embedded database and data format in
| erlang.
|
| Main reason ? It works. The compiler has real error messages
| that are helpful making the onboarding of anyone having to fix
| problems a far far better situation than any of the
| competitors. It has a proper modern toolchain.
|
| All of these would be killer features. All together ? No
| competition.
|
| I also write cli tool and all kind of parsers for embedded
| language. The libraries here, in particular if you want good
| error messages and UX, are simply the best in all other
| environment i know of.
| allisdust wrote:
| I use it to write backend web services. Some how it doesn't
| appear to be any less productive than typescript +nodejs
| combination. Library support used to be a mess but now a lot of
| good libraries exist to get the job done.
| bsnnkv wrote:
| I've built the most popular[1] actively maintained tiling
| window manager for Windows that is available today.[2]
|
| It would have been impossible for me to build this in any other
| language. I knew absolutely 0 about developing for Windows when
| I started this, but I quickly realized that the Win32 API is a
| very old beast with a lot of footguns that Rust saves me from
| on a daily basis.
|
| On top of that, with parking_lot I can quickly and easily
| detect incredibly rare instances of deadlocks, and in general
| have to worry very little about concurrency. All of this allows
| me to stop worrying about the noise and focus on the real work
| of how the window manager should behave.
|
| 1. Based on Github Stars
|
| 2. https://github.com/LGUG2Z/komorebi
| Macha wrote:
| Rust has replaced Python for me in my personal CLI tools where
| I expect to use them as an ongoing basis. At this stage I am
| almost as fast writing Rust as Python, find the Rust projects
| much easier in terms of environment setup than the whole
| pipenv/poetry/pyenv world, and enjoy the instant response of
| not having to wait for a python interpreter startup.
|
| I also have some side projects like a gameboy emulator, where
| it's nice to have what is effectively a lower level language
| with the safety and features of higher level language.
|
| My day job is mostly Java/Javascript though, rewriting the
| world isn't yet worth it, but there's certainly one or two of
| our systems where if a rewrite in another language was on the
| table I'd make the case for Rust
| Scarbutt wrote:
| _At this stage I am almost as fast writing Rust as Python_
|
| By generously use of copying?
| oconnor663 wrote:
| The "One Simple Trick" that lets you port most Python code
| straight to Rust is to take all the aliasing "object soup"
| references that Rust doesn't like, shove those objects in a
| Vec or a HashMap, and use indexes/keys instead of Rust
| references. This does require plumbing the Vec/HashMap
| around through different functions, but if you do it this
| way from the beginning it's not much extra work.
| kylebarron wrote:
| I'm building WebAssembly bindings to existing Rust libraries
| [0] and lower-dependency geospatial tools [1]. Rust makes it
| very easy to bind rust code to both WebAssembly and Python. And
| by avoiding some large C geospatial dependencies we can get
| reliable performance in both wasm and Python using the exact
| same codebase.
|
| [0]: https://github.com/kylebarron/parquet-wasm
|
| [1]: https://github.com/kylebarron/geopolars
| theptip wrote:
| Oh, that's really cool. Rust noob here, and I hadn't seen the
| tooling for building Python bindings. That looks like it
| could be a very powerful way to speed up your Python programs
| (much easier than the "just replace the slow bits in C"
| advice that was standard.)
|
| The mappings in
| https://github.com/kylebarron/geopolars/blob/master/py-
| geopo... for example look very easy to follow.
| solar-ice wrote:
| I write video streaming software in Rust. Rust helps us make
| sure we've got concurrency correct, has a very solid type
| system to help us make sure we've got general application
| properties correct, and seriously reduces the space where we
| have to go looking for segfaults and suchlike (primarily third-
| party C libraries and bindings to them).
| __david__ wrote:
| For me the killer feature of Rust is its nice broad scope. I've
| done:
|
| - embedded programs on avr hardware, which is impressive that
| something like rust can compile down to an 8 bit micro. Doing
| some sort of crazy map/iterator filter closures and finding the
| resulting assembly being nice and tight makes me super happy.
|
| - web servers and clients (a scraper that collects scores from
| a web page and serves its own page of aggregated scores to my
| family).
|
| - a low level opengl tmux/terminal client (Rust's Enums were a
| killer feature here)
|
| - a windows GUI program for installing a PC game mod (99%
| developed on a mac and cross-compiled)
|
| - a cli app to "compile" svgs down to png sprites for a web
| based game
|
| - a launcher for Emacs that uses native cocoa apis to display a
| dialog on error
|
| Each of these cases ended up pushing different parts of Rust
| for me. I would say the killer feature that spans all of those
| is Cargo and the crates.io registry. There are a ton of very
| good libraries out there--it feels like the heyday of CPAN or
| RubyGems to me.
|
| I also quite enjoy how many programming errors Rust finds at
| compile time. With Rust code I spend _way_ more time fixing
| compiler errors, but when it compiles I typically don 't find a
| ton of major logic errors. I personally find it extremely
| rewarding when I get something to compile and then it just
| works. This happens more in Rust than in other languages I've
| heavily used.
| emadda wrote:
| https://table.dog (a CLI to download Stripe to SQLite).
|
| I considered Node.js, C#.
|
| I went with Rust for a few reasons:
|
| - Easy to build small portable binaries (as a primary language
| feature).
|
| - The type checker ensures type consistency when writing out to
| SQL tables (SQLite is loosely typed). Code that reads from the
| SQLite database implicitly benefits from Rusts strong type
| checks.
|
| - Macros to convert structs to SQL insert/updates.
|
| - Reduce the chance of errors at runtime.
|
| - Leverage as much as SQLite's write throughput as possible.
|
| - When converting Stripes Open API JSON spec into Rust code
| (using another Node.js program), the Rust type checker ensures
| I have a well formed HTTP client - the strict compiler makes it
| a good target for generated programs. Read more about this idea
| at (https://willcrichton.net/notes/rust-the-new-llvm/).
| huyage wrote:
| I'm building an HTTP CRUD app on top of PostgreSQL. I have
| previously used Go for various CRUD apps. The experience is
| better except for compile time. My favorites:
|
| 1. Much more expressive type system: no more `interface{}`.
|
| 2. Algebraic data type with `enum`. Exhaustive check.
|
| 3. `serde` crate is lightyears ahead of Go's `json:"wtf"`.
|
| 4. Compile-time checks against DB with `sqlx` crate.
|
| 5. Logging is a breeze with `tracing::instrument`.
|
| 6. Using macros to reduce boilerplate has better UX than Go
| codegen.
|
| What these give me is more confidence in
| development/refactoring because the compiler can guide me most
| of the way.
|
| Low lights:
|
| 1. Build time.
|
| 2. Async is still clunky. e.g. Try to implement an `actix-web`
| extractor or middleware.
|
| 3. Please just stablize nightly rustfmt features already.
| mjb8086 wrote:
| I'm looking to do a bit of CRUD on top of PostgreSQL as well.
| Currently mid-way through learning the language.
|
| Would you mind sharing some of your experiences? Do you find
| the 'stubbornness' of the compiler frustrating at all? How do
| you find the tooling?
|
| Also, I've considered Diesel for ORM, so was wondering if
| you've been using that too.
| huyage wrote:
| > Do you find the 'stubbornness' of the compiler
| frustrating at all?
|
| I actually love it. The more work I can offload to compiler
| the better. One simple example that frustrated me in Go was
| adding a field to a struct. You add the field the the whole
| thing still compiles even though the zero-initialized value
| probably broke your app logic. In Rust if I add a field to
| a struct, the compiler warns me about all the places that I
| need to double check.
|
| > Would you mind sharing some of your experiences?
|
| I highly recommend zero2prod book which is well-written,
| practical, but still teaches the essential principles
| (https://www.zero2prod.com/). You basically deploy a CRUD
| app to DigitalOcean from scratch. The best way to ramp up
| IMHO.
|
| > How do you find the tooling?
|
| Cargo is sweet. rust-analyzer is all I need. I need less
| extraneous tooling to be effective. For example, in Go I
| might use a task runner to watch the repo and run tests
| when I change a file. But in Rust I can just follow the
| rust-analyzer highlights and manually compile less-
| frequently.
|
| > Also, I've considered Diesel for ORM, so was wondering if
| you've been using that too.
|
| I was not happy with GORM (https://gorm.io/index.html) and
| never had a satisfactory experience with any ORM. I'm a fan
| of writing plain SQL, even in Go. It's just that with Rust
| sqlx I can get compile-time checks against the schema. It's
| not anything new (see Haskell), but it tightens the
| feedback loop and I have full control of the performance.
| orthecreedence wrote:
| I do a lot of cryptography stuff in rust that is ported to
| various platforms and embedded in larger apps so I don't have
| to write the same logic over and over (desktop/mobile mainly).
|
| Also, lately working on some identity/p2p stuff.
| api wrote:
| ZeroTier version 2 is being built in Rust, with the main
| reasons being safety (it's a network protocol!), easier cross
| platform compilation, easier dependency management, and an all
| around better language than C++. It should help us greatly
| boost developer velocity while also be much safer from a
| security point of view.
| mwcampbell wrote:
| That will also make it more attractive to other developers
| using Rust who want to embed the SDK. Speaking of which, I've
| emailed ZeroTier a couple of times now about licensing the
| SDK (the first email was last week), and haven't yet heard
| back.
| marcosdumay wrote:
| I am currently writing a kinda complex GUI application intended
| to run on a browser. So it's in webassembly.
|
| Compared to Javascript, Rust safety features allow me to
| iterate quickly and improves my productivity from "I won't be
| able to complete this project" to "it's trivial, just some
| work". Compared to Typescript, Rust gives me some performance
| and types that actually represent the data I use, but I am not
| sure if I lost a bit of productivity (the TS tooling is
| horrible, so programing a bit slower isn't the entire story).
|
| I don't consider this a problem Rust is good for, but one that
| all the more suitable languages still don't support.
| rvcdbn wrote:
| How come the first example isn't a race on a since it's accessed
| from two threads?
| jcranmer wrote:
| Both threads are only reading the array. For it to be a race,
| at least one of the accesses must be a write.
| theptip wrote:
| The second usage is a mut borrow and I think would be
| incompatible with a read only borrow if they were run in
| parallel.
|
| As the comment eludes to, each spawned thread is implicitly
| joined if you drop the join handle returned by s::spawn().
|
| So in this case the spawned threads run serially.
| DenseComet wrote:
| Nope, the threads run in parallel. The variable x is
| mutably borrowed only once by the second thread. The
| variable a is immutably borrowed twice, so there is no
| issue.
| theptip wrote:
| Are you certain?
|
| From the docs on https://doc.rust-
| lang.org/stable/std/thread/struct.Scope.htm...,
|
| > If the join handle is dropped, the spawned thread will
| implicitly joined at the end of the scope.
|
| Plus the comment says
|
| > // We can even mutably borrow `x` here, // because no
| other threads are using it.
|
| Which doesn't line up with another thread having a read-
| only borrow on it.
|
| Anyway not at my machine to test right now, I could be
| wrong.
| theptip wrote:
| Oh never mind, I'm completely misreading. Thanks for the
| pointer.
| [deleted]
| tomjakubowski wrote:
| The second use is a mutable borrow of x, not the array. x
| is borrowed read-only later, after the scoped threads are
| joined.
| rvcdbn wrote:
| ah, that makes sense thanks
| nextaccountic wrote:
| If one thread tries to mutate the variable a instead of just
| reading from it, the compiler will output a compile-time error
| saying you can't do that. (But, if you wrap a into a mutex and
| add the required methods to lock the mutex, you suddenly can)
| Lvl999Noob wrote:
| Awesome update! It's good to see scoped threads here. Btw, can
| someone explain how these are safe when the initial
| implementation wasn't? The problem was that someone could put a
| reference to a local variable inside an `Rc` or `Arc` and leak it
| with reference cycles, right? How is that case prevented now?
| duckerude wrote:
| The original implementation gave out a handle that waited for
| all the threads to end when it was dropped (i.e. went out of
| scope). That would prevent premature cleanup. But it was
| possible to leak the handle so that it would never be dropped
| even at the end of the block, and then it wouldn't wait for the
| threads.
|
| The new implementation calls a closure and waits for the
| threads when that closure returns. Unlike the destructor here's
| no way to stop that code from running when it should.
| [deleted]
| game-of-throws wrote:
| Side note: since memory leaks were deemed safe, there are
| easier ways to deliberately leak than using reference cycles.
| The most straightforward are `mem::forget` and `Box::leak`.
| [deleted]
| kam wrote:
| `std::thread::scope` takes a closure, and joins the threads
| after the call to the closure returns, rather than relying on
| `Drop`.
| chmod600 wrote:
| With the "try_reserve" stabilizations, does that mean the
| "allocator_api" is closer to stabilization?
| kibwen wrote:
| I think that is less about the general allocator API than it is
| about the fallible allocation for collections RFC (
| https://github.com/rust-lang/rust/issues/48043 ), which is
| something that the Rust-in-Linux folks have been pushing for
| recently.
| brundolf wrote:
| Wow this is a juicy one
| joshsyn wrote:
| GolDDranks wrote:
| Scoped threads are something that really showcases Rust's
| features around thread-safety, lifetimes, sharing and mutability.
| I'm glad it's finally back in the standard library!
| davidatbu wrote:
| I would be very interested in hearing from experienced folks
| about how important this is/what useful patterns it unlocks.
|
| I ask because I remember when trying to learn Kotlin, the docs
| made a big deal of structured concurrency[0], and golang of
| course is known for its concurrency story.
|
| [0] https://kotlinlang.org/docs/coroutines-
| basics.html#structure...
| klabb3 wrote:
| Sadly, this is only lexical scoping which means you can only
| borrow from the outer scope and not ad-hoc the normal way
| borrowing works in Rust.
|
| In short, this means that thread pools and async runtimes
| cannot use this feature to provide borrowing across tasks.
| We're still stuck with Arc-ing everything that crosses task
| boundaries.
|
| Prior to 1.0, there were "true" scoped threads (with a
| lifetime 'a on the join handle), which let you borrow from
| the parent thread. (This could have extended to tasks as
| well, had they been around.) unfortunately it wasn't safe
| together with the much more popular Arc/Rc, which wasn't
| 'static restricted, despite it's ability to cause cycles and
| leak. So those powerful scoped threads were removed and
| "destructors are not guaranteed to run in safe Rust" was
| formalized instead.
|
| Seeing how popular async became, I wonder if this was the
| only and right way to move forward. I'm not against Arcs,
| they have their place. But if you can use normal RAII it's
| much preferable.
| oconnor663 wrote:
| > async runtimes cannot use this feature to provide
| borrowing across tasks
|
| They can't use this function, but with some duplicated
| unsafe code they can still provide similar APIs for their
| callers, right? Things like this:
| https://github.com/jaboatman/tokio-scoped
| klabb3 wrote:
| I just checked quickly so may be wrong, but it looks like
| they're pulling the same trick as with the new scoped
| threads, ie only lexical scoping. Note also that the
| scope function is blocking and called from within an
| async fn, which is normally not great for composability
| with other async code.
|
| That said, taking a step back it has crossed my mind that
| bringing back true scoping with unsafe in the impl might
| be an acceptable way forward, despite how upsetting this
| is to a lot of rustaceans. I _think_ that the failure
| modes (ie triggering UB) for this case can be simply
| enumerated in a short list of "DON'Ts" (such as putting
| a scoped join handle in an Arc).
|
| OTOH, since leaking was formalized and explicitly allowed
| (heck, even borderline encouraged through mem::forget),
| god knows if people have exploited that for other cases
| in true Hyrum's law fashion, that breaks the
| abovementioned idea. They certainly had the right to.
| thramp wrote:
| the problem with this approaches like these that it
| requires blocking the runtime:
| https://github.com/jaboatman/tokio-
| scoped/blob/master/src/li....
| masklinn wrote:
| > I would be very interested in hearing from experienced
| folks about how important this is/what useful patterns it
| unlocks.
|
| For Rust it allows thread to play better with lifetimes,
| which means there are scenarios where you don't need the
| overhead of a lock (and usually the Arc that does with it,
| unless you go with a global) or queue, you can just work with
| on-stack "unsynchronised" borrows and it's thread safe.
|
| That means lower syntactic _and_ runtime overhead in the
| cases where it's an option.
|
| It was already available in crossbeam so it's not _novel_
| novel, but not needing a dependency for it is useful still.
| davidatbu wrote:
| Thanks! I didn't know that it was already available in
| crossbeam, that helps a lot in understanding the
| significance of this feature.
| csomar wrote:
| This is a huge update! At least, for me, I can see several things
| on my code base that could be changed because of this. (The first
| one is the lazy initialization of sync primitives; and the second
| one is BorrowedFd/OwnedFd.
| ActorNightly wrote:
| I wish they would stop adding features and just to lock down the
| language, and focus on more maintainability and use. Adding
| features is nice but its one of the biggest issues that slows
| down adoption. More people care about learning a language and
| being able to read code without trying to figure out what some
| latest feature does rather than some syntactical sugar.
| funklute wrote:
| Rust is a pretty young language though.... if now is not the
| time to add features, then when is?
| oxff wrote:
| I wish they'd break their current backwards compat. promises to
| fix some accidental complexity that has been introduced. Let
| legacy langs provide this kind of maintainability
| brundolf wrote:
| They have the Editions mechanism for unavoidable breaking
| changes, but their target market is people who care a whole
| lot about stability and maintainability, so it wouldn't make
| any sense for them to jettison that design goal.
| tialaramex wrote:
| It's not worth it.
|
| For example, it seems as though
| "Word".contains(char::is_ascii_lowercase) should work,
| because after all "Word".contains(char::is_lowercase) works
| and char::is_ascii_lowercase exists and does what you expect,
| the same but for ASCII only.
|
| However, for compatibility reasons char::is_lowercase takes a
| char, while char::is_ascii_lowercase takes a _reference_ to a
| char, and so you can 't just pass it to contains() and will
| need to write a closure to pass to contains to do ASCII
| instead.
|
| Writing the closure is ugly, but it's nowhere close to how
| awful a compatibility break would be so even a million things
| like this (and so far maybe I can think of a dozen) aren't
| worth it.
| cercatrova wrote:
| It's a systems language so they're not gonna break BC.
| Although if there's a really great feature that comes out
| that requires BC breaking, then they should do so.
| game-of-throws wrote:
| Literally every single thing in the post is generalizing a
| feature that already exists. Don't you think removing these
| special cases makes the language simpler and easier to use?
|
| You might have a point though in a few releases when GATs are
| stabilized. I'll keep an eye out for your username complaining
| about that release ;)
| Macha wrote:
| There's no new syntax here?
|
| The first is a new library function that takes a closure as the
| parameter. This function has existed for as long as Rust has
| been 1.0 in the crossbeam library, it's just now also in std.
|
| The second change is a new api type.
|
| The third change is a library change to increase flexibility of
| that library.
|
| The fourth is arguably a bugfix, where existing syntax could
| not be used in an edge case.
|
| The fifth is unifying the compiler implementations so that some
| types of patterns now work in code using the oldest
| compatibility mode that previously only worked in more current
| modes.
| pas wrote:
| there are a lot of work-in-progress features that are important
| so we can write more maintainable code, like GAT.
|
| but it's also true that there are quite a few threads that are
| conceptually simpler than GAT and are just left unfinished.
|
| and there is a very serious push (or pushback with regards to
| GAT) to keep those promises.
|
| https://github.com/rust-lang/rust/pull/96709#issuecomment-11...
| ekidd wrote:
| Almost everything in Rust 1.63.0 appears to be an improvement
| in the standard library. Scoped threads no longer require a
| third-party library, some types support "const" better, and a
| bunch of existing types got some useful new methods. The only
| real language change here is the "impl / turbofish" one, which
| allows something that _should_ work, but which wasn 't allowed
| before.
|
| I'm not sure it would be realistic to totally stop adding
| features to the standard library, or to stop making existing
| syntax work the way a Rust user would expect. I would hope that
| any actively maintained language does things like these.
| brundolf wrote:
| Most of the features here (and in Rust updates in general these
| days) are just the loosening of constraints on what you could
| already do. If anything, these types of changes make the
| language conceptually simpler.
|
| This gets pointed out by somebody in the comment section under
| every Rust update. The trope that Rust is getting harder to use
| is tired, and not really based in reality.
| ActorNightly wrote:
| Different syntax = different ways of doing things = codebases
| that diverge in implementation. It doesn't matter if the new
| way doing things is conceptually simpler, you are now
| creating 2 ways to do things based on what version of the
| compiler you use, which people will have to know, therefore
| increasing complexity, not reducing it. I don't understand
| how people don't get this by now. Saying "oh just learn and
| use the latest version" is completely unrealistic guidance.
|
| And while its fine for high level scripting languages like
| Python, because the whole idea is to abstract a lot of the
| functionality into the syntax, the issue with Rust is that
| its trying to be the next C and be applicable for writing
| critically important pieces of software like parts of the
| linux kernel. You absolutely must have a locked down language
| set for this. The reason C is still used for the kernel isn't
| because of circumstances, its specifically because there is
| very few ambiguities in the core language.
| brundolf wrote:
| > you are now creating 2 ways to do things based on what
| version of the compiler you use
|
| Which of the features in Rust 1.63 adds a divergent way of
| doing something you could already do?
|
| > The reason C is still used for the kernel isn't because
| of circumstances, its specifically because there is very
| few ambiguities in the core language
|
| What are some ambiguities in the core Rust language?
| game-of-throws wrote:
| C was used because it existed 30 years ago, and is full of
| ambiguities (undefined behavior), and Rust curtails UB
| quite a bit by defining many semantics that are left
| unspecified in C.
|
| You don't need a "locked down" language to build an OS. In
| fact Linux just upgraded the version of C they use to C11.
| Time always marches forward, my friend.
| sophacles wrote:
| And C is about to get C23 with additionaly syntax and
| features.
| mbrubeck wrote:
| Which "different syntax" are you talking about? I don't see
| any changes in this release that add new syntax to the
| language.
| superkuh wrote:
| dboreham wrote:
| It's a fine line. Python world spent 10 years not using Python
| 3 features.
| throwaway894345 wrote:
| Python is interpreted--you have to write code that works on
| all of your target platforms. Rust is compiled. You don't
| have to care (much) about what is installed on your target
| platforms.
| hojjat12000 wrote:
| Except for Libc. I compiled a rust program on Ubuntu 20.04
| and tried to run it on Ubuntu 18.04, and bam.... a piano
| fell on my head! Consequences.
| sophacles wrote:
| How is this any different from C?
| throwaway894345 wrote:
| Yeah, that was the "(much)" in my comment. Pretty sure
| you can statically link some libc or another though.
| nazgulsenpai wrote:
| This sounds more like an argument against the package manager
| maintainer for a Linux distribution rather than a Rust problem.
| cies wrote:
| > Bash developers
|
| Yeah those always seem to crowd my views on conferences, hordes
| of Bash developers /s
|
| Nitpick: Bash is interpreted, Rust is compiled. The executable
| rustc produces may well run on a machine that was not updated
| in the last 15 years.
| oxff wrote:
| Maybe the package managers for Linux distributions need to
| rethink their package distribution model :)
| mcronce wrote:
| There's nothing stopping you from installing using rustup.
| There are also _tons_ of projects that have much older MSRVs
| than simply "latest stable".
| jeroenhd wrote:
| Ask your OS package maintainers to update their packages if you
| want a more modern toolkit. Or stick to the one your package
| maintainers decided on if you can live without those features.
|
| I don't think a tool that receives regular updates should
| necessarily come from standard OS repos, they should be stable.
| Perhaps the Rust people could host their own repositories but
| the fact they don't do it suggests that it's not worth the
| hassle. This stuff is handed out for free, take it or leave it.
|
| As Rust is open source software, you're free to grab each Rust
| release, package it up, and offer it as a package on your own
| repository, or you could probably pay someone to do it for you
| if you find the right people. I'd much prefer a repository as
| well, but I accept that the Rust devs don't work for me and I
| don't pay for any services that would entitle me to such
| requests.
| msbarnett wrote:
| My distro gets updated software when it's available; sounds
| like your beef is with your distro insisting that the entire
| world should work on its timelines instead of vice-versa.
| kbd wrote:
| > This contrasts with say, Bash developers [who] will write for
| what is actually available on the OSes people are running.
|
| This is obvious, right? Rust is compiled with what you have on
| _your_ machine, while Bash is interpreted and so depends on the
| capabilities on the _target_ machine.
| nu11ptr wrote:
| Not true for most of the big hitter crates. MSRV is a big thing
| and I never understood why, but it was recently explained to me
| it was so the old tool chains in distros could keep compiling,
| so the big crates tend to bump MSRV very slowly. Obviously,
| each project owner decides this on their own, so it isn't
| universally true, but is common practice.
| epage wrote:
| Theres also talk of improving the situation, including
|
| - Depencency MSRV errors explaining how to downgrade (merged)
|
| - The dependency resolver skipping versions that need newer
| Rust. To have reasonable errors, this will require the new
| pubgrub resolver. The main question is opt-in vs opt-out
|
| - Warnings when using functions newer than your MSRV
|
| Among other ideas
| [deleted]
| orthecreedence wrote:
| And why haven't the rust developers backported the latest
| versions of rust to Slackware 3.3??
| bilkow wrote:
| > Want to use your system repo rust toolchain instead?
|
| If you want to use your system toolchain, just install your
| software from there, it will be compatible with the available
| toolchains, if it's a library, you don't even need the
| toolchain if its an application. The software is obviously also
| gonna be "outdated", because that's the point of Debian, stable
| software that has been well tested with the system.
|
| > This is because Rust devs, for now, are the type that will
| immediately beginning putting the new code features
|
| There is the concept of MSRV (Minimum Supported Rust Version)
| that a great fraction of the community follows. You just
| specify publicly the minimum version that your library supports
| and enforce it with CI. This is not as good as having an
| official standard (say, in Cargo.toml), but a lot better than
| just implicitly depending on what you think is currently
| available in bash for most users.
|
| > without consideration that it's not available in any OS
| repository toolchains
|
| Arch's package has been available on the same day in the last
| Rust's release. We'll probably have 1.63.0 available today or
| tomorrow.
| shepmaster wrote:
| > This is not as good as having an official standard (say, in
| Cargo.toml)
|
| It's present now: https://doc.rust-
| lang.org/cargo/reference/manifest.html#the-...
| bilkow wrote:
| Oh, incredible! How have I missed that, thought it was
| still just a proposal...
| pavon wrote:
| Yeah, I was very excited when that was added. I prefer to
| use use the system Rust as well, and my primary complaint
| was the hassle of having to manually resolve dependency
| versions (for packages not in the OS package manager)
| because Cargo hasn't had great support for restricting
| packages to ones compatible with your version of Rust.
|
| There will always be some issues with package maintainers
| using new features without realizing it, and/or forgetting
| to bump the minimum version. But now that there is a
| standard for how it should be done, I can submit patches to
| these projects to fix the problems when I encounter them.
| [deleted]
| dietr1ch wrote:
| Using nix I ended up realizing that I want my system to be
| almost empty, providing not much more than a shell to any
| project I'm working on. Anything that's comes from my system is
| something that might bite anyone else or myself when using the
| project, and allow the classical "works on my machine"
| scenarios, luckily here at least the issue is that it won't
| build.
| loeg wrote:
| For those missing the context; this guy wants new Rust software
| on Debian stable's old Rust toolchain. And complains about it
| in every Rust thread on HN.
|
| A similar problem afflicts other software in Debian stable;
| Rust is not unique. The reasonable solution is to stop using
| Debian stable if you want updates.
| pavon wrote:
| To clarify, without weighing in on the merits of his
| complaint, what he is saying is that he _wants_ to use Debian
| Stable 's toolchain and is complaining that the ecosystem
| (crates on cargo.io) move to use the latest features so
| quickly, and don't have stable backport releases, which makes
| this difficult to do.
|
| Edit: Reworded to remove disagreement.
| loeg wrote:
| I think you're agreeing with me, but framing it as
| disagreement.
|
| > the ecosystem (crates on cargo.io) move to use the latest
| features so quickly
|
| They use the new features in new software -- implying he
| wants to use that new software. If he uses the old versions
| that predate the new features, this wouldn't be a problem
| for him.
| pavon wrote:
| Yes, I did misread your post, sorry. Reworded mine to be
| a clarification rather than a contradiction.
| Macha wrote:
| I'm not saying now that's opposed.
|
| If you want Debian to curate your compiler version, then
| use the Debian curated versions of your Rust software for
| compatibility.
| baby wrote:
| Wait can't you just use rustup?
| krastanov wrote:
| `rustup` is awesome for me as a developer. It is not
| convenient if I am a sysadmin that wants everything to be
| stable and consistent: I can not afford to use special
| version/package manager for every single language. It is
| fair to complain that rust (or python, or julia, or any
| other language with built-in environment/package/version
| manager) do not play nice with OS package managers. OS
| package managers are starting to take "vendoring" a bit
| more seriously because of this.
| rascul wrote:
| The OS package managers seem to be figuring it out,
| though. I've noticed that both opensuse and debian have a
| number of rust programs in their repos.
| pornel wrote:
| Debian does it the hard way, by making a Debian package
| for every crates-io dependency used and patching Rust
| programs to use Debian's forked deps instead. It's seems
| like a massive pain for them, and has zero value for Rust
| end users, since normal Cargo won't use any of this.
|
| Rust often carries its own bugfixes to its LLVM version
| (before they're accepted upstream). Debian unbundles LLVM
| from Rust and makes Rust use Debian's LLVM, which creates
| a risk of undoing Rust's bugfixes and causing
| miscompilations.
|
| I don't think anyone should be using Debian-packaged
| Rust. Debian's and Rust's policies are fundamentally
| incompatible. This results in Debian having a hopelessly
| outdated inferior package that is a pain for both Debian
| users and the rest of the Rust ecosystem.
| troutwine wrote:
| At the most recent RustConf William Brown spoke about how
| OpenSUSE deals with Rust[1]. If I remember correctly from
| his talk they started doing something very similar to
| Debian and then eventually settled on "just use rustup".
| I wish I had taken better notes because there was more
| nuance to the history there but I think they'll release
| the videos of the talks soon.
|
| [1]: https://rustconf.com/schedule#how-we-ship-rust-in-
| opensuse
| pas wrote:
| you want stability (aka reproducibility across a fleet of
| workstations/servers), but also security updates too,
| right? but what do you mean by consistency?
|
| and you don't want to create & distribute a new OS image
| for every security update, right?
|
| ... anyway, the whole problem is that only upstream can
| provide these kind of security updates. it's a big (and
| very very convenient) lie what stable distros are doing,
| but many times packages have to work their asses off to
| maintain this illusion. (when they have to
| patch/backport/hack packages.)
|
| Rust as language and compiler provides the tools for this
| (stability guarantee, editions, etc), but the various
| devs that provide Rust crates might not.
|
| sure, if Rust would artificially hold back new features
| that would definitely provide this "stability", but it's
| no wonder devs adopt new features fast. because they want
| them, it makes their life easier, and it usually makes
| users happier too.
|
| what the Rust ecosystem is doing (and NodeJS and
| TypeScript and quite a few high-velocity newish ones) is
| providing updates to users faster.
|
| of course there are some users that might not care about
| this, hence debian oldstable, and so on.
| baby wrote:
| I could understand any other languages, but rustup is
| kind of flawless from my point of view, so I'm still
| wondering what doesn't work exactly : o
| malkia wrote:
| or find ways to override and install latest, for example
| latest LLVM that would work on debian stable -
| https://apt.llvm.org/ (maybe similar for rust?). I've
| switched to this on my debian stable so that I can compile
| carbonlang (it needs llvm12, debian stable had only llvm11) -
| with above I've actually got llvm15, and then week ago
| switched to llvm16 (I can adjust that back to say llvm14 if I
| want).
| lvass wrote:
| I assume the issue here is not getting the Rust toolchain
| on a developer system, but Rust packages in APT.
| baby wrote:
| Use nix instead then?
| superkuh wrote:
| The Debian example you're referring to was back from the
| release of 11. It's rustc was only 3 months old and already
| couldn't compile. That's not a "Debian is old" problem and it
| was only one instance. I've run into the same problem on
| other OSes as well. No OS hosted repo can keep up with rust
| and it's particular selection of bleeding edge types.
|
| And it's hardly every Rust thread. There are far too many
| rust threads to even count, let alone comment on.
| pas wrote:
| > No OS hosted repo can keep up with rust and it's
| particular selection of bleeding edge types.
|
| what? why? someone has to click the approve on the
| update+build+publish pipeline.. and that's in most repos
| anyway.
| fweimer wrote:
| Debian packages rustc-mozilla for building Firefox. Firefox
| ESR 102 will need Rust 1.59.0, and that version has already
| been uploaded to stable-proposed-updates. 1.59 is not _that_
| old (it 's from February 2022), and this actually builds
| after installing rustc-mozilla (with cargo even):
| use std::arch::asm; fn main() {
| unsafe { asm!( "syscall",
| in("eax") 60, in("edi") 0,
| out("rcx") _, out("r11") _, }
| }
|
| I guess for the same reason, there's now an LLVM and Clang 13
| build in Debian stable, too.
|
| I'm not entirely happy how Mozilla forced Debian's hand here.
| But it means that there is a relatively current, Debian-
| blessed Rust compiler, and you can use it for your own builds
| if you are willing to upgrade from time to time.
| game-of-throws wrote:
| Why are you here flaming the Rust devs for having the audacity
| to dare release a new version of their software, instead of
| talking to the packagers that distribute years-old versions?
| matthews2 wrote:
| Gentoo got Rust 1.62.1 (the previous release) only three days
| after it was announced on rust-lang.org.
| kibwen wrote:
| Having the new borrow checker finally on in all cases is nifty.
| For valid programs the behavior is the same as the previous
| version, but in the event of a compiler error, previous versions
| would still show you the output of the old borrow checker. I've
| already had one case where someone came asking about a confusing
| borrow checker error message and I just had to suggest that they
| try compiling with 1.63 and the new error message was clear
| enough that it answered their question immediately.
|
| Now we just need to do it all over again once Polonius finally
| arrives. :P
| brundolf wrote:
| Migrations aren't ideal, but I'm excited to see continued
| innovation in borrow-checking. This is a major area where Rust
| is exploring truly new territory as a language, so growing
| pains are to be expected, and it's encouraging to me that
| Rust's semantics allow borrow checking to keep getting better
| without breaking changes
| cwzwarich wrote:
| > it's encouraging to me that Rust's semantics allow borrow
| checking to keep getting better without breaking changes
|
| Just to be clear, these are breaking changes. If the new
| borrow checker didn't break existing code, they would have
| removed the old one long ago. They've just decided that the
| observable effects of the breaking change in the ecosystem
| are small enough (especially after warning about them for
| years) that they are okay making the breaking change without
| a semver-incrementing Rust 2.0.
|
| To be fair, the reason for the breaking changes is generally
| to fix soundness issues (of course, not every example of code
| now banned will exhibit unsoundness), but that doesn't cover
| all of them. There were some completely sound (albeit
| useless) examples of partial initialization that broke with
| NLL:
|
| https://github.com/rust-
| lang/rust/issues/21232#issuecomment-...
|
| https://github.com/rust-lang/rust/issues/54987
|
| Strict adherence to semver would require still accepting this
| code.
| brundolf wrote:
| Sure, I guess all I meant was that the fundamental
| semantics of borrowing and lifetimes that were chosen at
| the beginning have continued to scale up to a better and
| better borrow-checker experience. They haven't found deep
| limitations of the language that prevented innovation
| without going back to the drawing board.
| pavon wrote:
| I'm probably mixing different things up, but I thought the non-
| lexical lifetime changes made the borrow checker more
| permissive in the sense that some code that the compiler would
| reject using the lexical borrow checker, would be allowed using
| the non-lexical borrow checker.
|
| If this is so, how are they maintaining edition compatibility?
| It seems like you could write code for the 2015 edition that
| would build with the new compiler, but not an older (2015
| edition compliant) compiler.
| [deleted]
| kibwen wrote:
| The new borrow checker both allows more to compile (by being
| more precise about tracking control flow, allowing it to
| prove more advanced things about lifetime usage) and also
| less code to compile (again, by being more precise about
| tracking control flow, allowing bugs in the old borrow
| checker to be fixed (see https://github.com/rust-
| lang/rust/issues?q=is%3Aissue+label%... for examples)).
|
| The edition compatibility story here is interesting. When the
| 2018 edition came out, the new borrow checker was only turned
| on for code on the 2018 edition. Meanwhile, in the 2015
| edition, it would run both borrow checkers and yield a
| warning if your code passed the old borrow checker but not
| the new one. After a migration period, the new borrow checker
| was eventually made the default on the 2015 edition as well.
| Because of the aforementioned soundness bugs fixed by the new
| borrow checker, this was seen as acceptable (soundness fixes
| are explicitly allowed by the stability policy, although the
| Rust developers still try to provide migration periods to
| make them less painful).
| kam wrote:
| Editions only guarantee that old code builds with new
| compilers, not vice versa. New features are added to all
| editions unless they require e.g. new keywords that are
| available only in new editions.
| pavon wrote:
| Ah, that is right. I apologize, I think I've learned that
| three times now, but for some reason my brain refuses to
| accept it.
|
| I like that previous editions get new features when
| possible, unlike say C++, but I wish they'd gone with
| semantic versioning for the language version, like python
| did when both 2 and 3 were active. Oh well, I just need to
| remember that the edition is like the major version, and
| compiler version is sort of like minor version, and both
| are needed to specify forwards compatibility.
| game-of-throws wrote:
| It might make more sense to think of editions as optional
| changes to the surface syntax, and nothing more. They are
| not nearly as important as the name makes them sound.
| brundolf wrote:
| They are often small, but it's a mistake to say they're
| surface-level. Changes to syntax or semantics only get
| made when absolutely necessary to allow for essential
| features or fixes.
| brundolf wrote:
| I'm not sure semver would really do it here, because then
| you could have say: 2.17 1.17
|
| What would you call the compiler binary that could
| compile both language v1 and language v2, with (shared)
| minor-version .17?
|
| The issue is that semantic versions are a hierarchy,
| whereas Rust edition x compiler version are a matrix
| game-of-throws wrote:
| Editions are orthogonal to compiler versions. It is perfectly
| fine if code builds with a new compiler but not an old one.
| Another example of this: you can write code in a 2015 edition
| crate that calls the new `std::thread::scope` function.
| Macha wrote:
| Editions promise old code works with new compilers.
|
| They do not promise new code works with old compilers
| jmartin2683 wrote:
| Rust is the greatest. It's my go-to for virtually anything that
| it could reasonably be used for (a lot). After using it
| exclusively for a while and getting comfortable and fast with it,
| I can't see any good reason to use anything else for most
| purposes.
| pjmlp wrote:
| GUI programming at the same level as MAUI, SwiftUI, Jetpack
| Compose, Qt, WPF,...
| sebzim4500 wrote:
| Yeah GUI is really the biggest missing part of the ecosystem.
| To be fair it is an extremely difficult problem; there is a
| reason there are so many electron apps out there.
| pjmlp wrote:
| Not really, the reason is laziness and seeing nails
| everywhere, instead of picking the right tool.
|
| Coding GUI/TUIs since MS-DOS and Amiga 500 days, and Web
| since 1996.
| pas wrote:
| A lot of times a cross platform non-native GUI is the
| right tool. Same UX on every platform. What's not to
| like? Allows faster iteration for small teams, you can
| use TS and doesn't even have to think about
| Swift/ObjC/Java/Kotlin/C++, and you can use whatever you
| like for the backend.
| pjmlp wrote:
| PWA then.
| debug-desperado wrote:
| Probably a lost cause at this point since most GUI toolsets
| are too object-oriented to comfortably wrap and call with
| Rust. Do a web view with Tauri instead.
| pjmlp wrote:
| Or chose a better tool for the job, picking languages based
| on platforms, not picking an hammer and then trying to find
| a nail that fits.
| felipellrocha wrote:
| I am on the same boat. It's just too good. There are flaws, for
| sure, but it seems like the language itself is going on an
| incredibly good direction.
| monkmartinez wrote:
| I have some serious FOMO with Rust... I have been using JS and
| Python for everything the last few years. Will you please
| recommend some Primers/Resources/Tutorials for Rust for someone
| like me? That is, basically a script basher that glues
| everything together with Python.
| lawn wrote:
| The Rust Programming Language book is usually the first thing
| people recommend.
|
| https://doc.rust-lang.org/book/
| mkaic wrote:
| I'm a junior programmer who never went to college and writes
| Python for a living (ML researcher). I've been itching to learn
| another programming language, ideally something fast and low-
| level, and have had my eye on Rust now for some time. But in my
| brief experiments trying some of the docs' hello-world projects,
| I'm already finding myself a little out of my depth.
|
| I'm realizing I don't know anything about compilers and very
| little about how languages work on a technical level -- stuff
| like "strong" vs. "weak" typing, memory management, stacks and
| heaps and garbage collection -- I've _seen_ all those terms
| before but have no intuition for what they mean. I never have to
| think about these concepts because Python is such a high-level
| "it just works" scripting language.
|
| Could anyone recommend some online resources for learning about
| the computer science of programming for someone with little prior
| experience? I'm not quite sure where to even start, but I'm eager
| to learn because at the moment I don't really feel like a "real
| programmer", more like a script kiddie. Heck, I only learned to
| use Git properly like 6 months ago!
| whb07 wrote:
| CS50X is a great starting point as they talk about the intro
| into bits/heap/stack etc. In the first half they have the work
| using C which will show you how to think about all this.
|
| I'd suggest doing the C parts and stopping at the python side.
| Once you stop, step into Rust and you'll see how much easier it
| is to perform all the things you were doing in C.
| Scarbutt wrote:
| 'The C programming language' and then 'Operating Systems: Three
| Easy Pieces'
___________________________________________________________________
(page generated 2022-08-11 23:01 UTC)