Soooooo it's fuzzy, but I rather like the idea of not having to do this:
const VecU32 = Vec(|U32|) let mut x = VecU32.new() VecU32.extend(x, [1,2,3])
but rather just doing:
let mut x = Vec[U32].new() Vec.extend(x, [1,2,3])
In principle, it's totally possible to infer a type for
Vec.extend()
because we already know the type forx
, and then it's possible to instantiate an instance of the moduleVec
with that type. As long as we have only one instance ofVec[U32]
(which is the usual case) then it's unambiguous and as long as creatingVec[U32]
is pure then there shouldn't be any coherence issues. If I'm understanding correctly. Or, to lean less on sugar and inference, as Vi said you could haveVec
be a separate module that takes some type parameter and attempts to dispatch off to another module chosen by modular implicits??? Or include one module inside the other (which is not implemented in Garnet yet and which I haven't had much need for yet, since it smacks of subtyping.)~plecra is this vaguely accurate as to what you were thinking?
What would that look like with modular implicits, actually? Let's try it out:
const thingy = Vec(|U32|) -- We need another module `Vec`, separate from `Vec[T]`, that takes an implicit impl of `Vec[T]` and just calls out to it let mut x = Vec.new(|U32|) -- actually calls `Vec.new(|U32| thingy)` Vec.extend(x, [1,2,3]) -- actually calls `Vec.new(thingy, x, [1,2,3])`
Hmmm. It works? I think? (I could be totally wrong, it's been a long day.) But it doesn't actually solve the explicit-instantiation problem, and in general feels a bit like taking the long way around.
Ok, MPL 2.0 miiiiiight actually do what we want. I'd be interested in your take on it ~plecra , if you ever want to dig into it.
Its main structural difference from the LGPL seems to be it explicitly licenses one file at a time, and explicitly allows derivative works to combine those files with works under other licenses. It explicitly allows you to "upgrade" portions of the Covered Work to GPL versions; idk what the GPL thinks of that.
Licensing one file at a time is kinda painful but maybe it actually very nicely dodges the whole "what is a derivative work" debate by forcing you to explicitly state it. Basically solving ambiguity via micromanagement, and the micromanagement can be automated via a tool to handle SPDX headers.
What I worry about with the per-file model is someone just plopping
proprietary_extensions.rs
into an otherwise-libre project, compiling it, and shipping it without having to make their extensions public. The exact wording in the MPL is a little obtuse, it defines "Modifications" as (among other things) "any file in Source Code Form that results from an addition to, deletion from, or modification of the contents of Covered Software". So if you have to adduse crate::proprietary_extensions;
to the MPL-covered portion of the program thenproprietary_extensions.rs
has to be MPL, but... by my reading, if you already haveuse crate::*;
in it, adding a new file that gets included by that wildcard does not mean that file has to be MPL. You haven't added to, removed from or modified the Covered Software, in the most technical sense of the meaning. Making that impossible involves removing wildcard imports from the programming language, and I rather want wildcard imports and will not alter the programming language design for motherfucking legal reasons. So here the license's explicitness and micromanagement is a weakness.Sooooooo MPL-2.0 looks appealing in general but I'm not convinced it sufficiently protects against people adding non-libre extensions to the existing code. Modifying/extending the license is also kinda hard, though not impossible. There might be a way to contort it into doing what I want, but the fact that I have to contort it in the first place is somewhat distasteful.
Comment by ~plecra on ~icefox/garnet
Side note - glibc is positioned very differently from garnet libraries. LGPL suits libraries that will be present on the target system and dynamically linked (1). I'm guessing garnet will want to use the rusty static linking model instead, and we can't use glibc as precedent for that.
(1): There're caveats to this of course, but its a very important detail of glibc's situation
Comment by ~plecra on ~icefox/garnet
Unlike Plecra I don't think that locked mutexes are a particularly unique case, more like they're a very general symptom of a very gnarly problem
What are other examples of this problem? Ime poisoning is a highly specific solution to the problem of having a
&mut T
to something that will be visible after a panic (other cases have eg aBox<T>
on the stack that gets immediately deallocated). I've never needed another construct like it, and keep locking to a minimum anyway.
Comment by ~plecra on ~icefox/garnet
Someone wants to port garnetc and its libraries to their game console, proprietary hardware, or some other system designed to let them control and price-gouge the hell out of everyone possible?
I wholeheartedly agree that this is great, and I prefer most of my FOSS work to fall under these kinds of terms. Here's the specific situation I'm concerned about:
- I've written some code in garnet and built a useful foss tool that I now want to commercialize with a few B2B features
- I've used some of the contrib libraries fairly pervasively, as they're blessed by the language and kept in good condition
- I now want to rewrite (as in, completely rewrite them from scratch) a few of those contrib libraries so that I can use them in my closed source distribution.
However I can't because the API of the GPL'd libraries is under license! Even if I replace the implementation of the library, I still have a bunch of calls to the library API in the source code I've already written, and that's a bunch of GPL'd IP scattered across my whole project. The best I can do is now rewrite the whole project to use my new API, and the open source version suffers for it too.
To me, this makes any development on top of GPL'd libraries a massive hazard. I can never decide to use my own code in unshared projects without risking major rewrites (nor can anyone I might want to share my code with).
(edit: The default of MIT + Apache2 in rust's ecosystem is too permissive, I agree on that 😁 Using a license that ensures projects can stay public is a good idea)
Comment by ~plecra on ~icefox/garnet
A lispy system for item definitions lets the user redefine
defn
- with that, it's possible to add some extra effects that're implicitly included in every function signature as long as you're using the overriddendefn
macro. I really love this, it makes it practical to track very low level effects without making it the user's problem. TheDebug
effect, for example, can be part of the signature of every instruction and allow breakpoints to be typesafe. It can be really valuable for writing embedded applications - it isn't necessarily safe to insert breakpoints in interrupt contexts etc.
Comment by ~plecra on ~icefox/garnet
https://www.libsdl.org/license.php afaict SDL has been zlib for over a decade btw. I'm personally pretty anti-(L)GPL in FOSS. It seems sensible to leave licensing options up to maintainers of contrib libraries though - requring a license at least as permissive as LGPL, but publishing as zlib is also ok.
I do think that
contrib
should have a requirement that your API itself must be licensed zlib/BSD/public domain/MIT - to ensure users are allowed to replace libraries with their own code and use their own license
Comment by ~plecra on ~icefox/garnet
For a different point of view on Linear vs Affine: Splat considers linearity as the inability to
mem::forget
the value (Rather,trait Affine { fn forget(self); }
). Resources like vulkan resource handles are perfectly safe to forget, so they're Affine. Whenever values go out of scope, the language callsDrop::drop(that_value)
, and naturally complains if the trait isn't implemented for a type.T: Drop
is unrelated to linearity - linear types can implement Drop, and normal types dont have to.Linearity is only used for types that require it in the strictest sense:
OutPointer<T>
has made a type-level guarantee that the pointer will be written to, and its required for soundness, butforget
would break that guarantee: It's linear.