The Tag implementation does not care about T - it is only interested at the non-generic tag field. And yet it needs to specify the generic parameter with all it's complex trait bounds.
I don't suggest removing the trait bounds entirely from impl Trait blocks (I'm pretty sure this was already suggested multiple times in the past), but when we don't need to refer or acknowledge the generic type, it'd be nice if we can just white-hole it:
impl Tag for MyTaggedData<_> {
fn tag(&self) -> &str {
&self.tag
}
}
The general name for similar functionality is "implied bounds" but I don't know the status of anything in that space.
More specifically, it's generally considered more idiomatic to only put bounds which are structurally required on the struct itself, i.e. those which are required to name the (projected) types of the component data.
A type is considered well-formed (WF) if it meets some simple correctness criteria. For builtin types like &'a T or [T], these criteria are built into the language. For user-defined types like a struct or an enum, the criteria are declared in the form of where clauses. In general, all types that appear in the source and elsewhere should be well-formed.
By putting the bounds on the declaration, you're communicating to the compiler that the type is not valid unless the bounds are met. Then the compiler has to enforce this at some point. To me your OP sounds like you want less things enforced, or you want the point where things are enforced to change (with or without implied bounds).
I don't think these bounds will be unenforced in any suggestion, because:
They are defined on the type declaration which means that the compiler is always aware of them (even the RPC you've linked does not suggest to not enforce them - only to infer them)
impl blocks are not actually instantiating the types, so the enforcement was not happening there either way - all that was happening there is that the user was forced to re-state the bounds.
My suggestion is actually weaker than RFC 2089. If we modify my suggestion's syntax to just not require the bounds (and have my original suggestion of allowing white-hole type inference as sugar on top of it), then with my suggestion this will compile - unless you uncomment the commented out line:
With RFC 2089 it'd compile even with the commented out line, because Bar's generic parameter T is bound to implement Foo in the declaration, and thus all impl blocks can automatically infer it. In my softer suggestion, we won't have to tell the impl block that T: Foo and the impl block won't yell at us that Bar<T> can only work if T: Foo (which I assume is what you mean by "not enforcing", but I don't consider it as such), but unlike RFC 2089 we won't be able to utilize the fact that T: Foo inside the impl block.
I'll even go farther: under my suggestion this will not compile:
Under my suggestion, this will complain that the Bar<T> returned from bar is illegal because it does not know that T: Foo like Bar's trait bounds require. Even though we are inside a Bar<T>impl block, it won't do that deduction. Of course, returning Self will be just fine, because then it won't have to deduce that T: Foo.
Another interesting case for _ as an inferred type hole generic that just came to mind â allocator generic collections are so annoying due to needing to propagate around the A: Allocator parameter everywhere (and the concept of splitting String/str for the alloc-free subset not always working cleanly).
If routines that need to work with collections could just change <T> to <T, _>, that would decrease the burden significantly. Although, in full fairness, <T, impl Allocator> also isn't that much of a burden either, and doesn't block turbofish of the other generic parameters anymore[1].
Although, unfortunately, it is still an inference breaking signature relaxation, as a fully turbofished name isn't sufficient to uniquely identify a function instantiation anymore. âŠī¸
I wish allocator support stabilization could just be punted on Rust getting effects or contexts or capabilities or whatever type of DI that would permit some sort of implicit diffusion of allocators down the call stack without ceremony.