As shown in the code, I have not applied any explicit constraints to the generic parameter T. However, the parameter's type, MyBuffer<T>, requires the structural bounds T: Default + 'static in its definition.
This code is accepted by the compiler (the function signature compiles).
But if I add the line T::default() to the function body, the code fails to compile.
My question is:
What is the specific Rust rule that governs this behavior?
Edition: Pls ignore the following detail about Default, because I messed it up when trying to find an explanation, see the real code at the 5th replying-post.
If the function's generic parameter T truly has no explicit bounds, why does the compiler accept the function signature where T appears to violate the structural constraints required by MyBuffer<T>? (i.e., Why is the Well-Formedness Predicate not immediately enforced on the signature?)
Conversely, if the compiler has successfully determined the necessary bounds for T (i.e., T: Default), why does the method call T::default() fail to compile inside the function body? (i.e., Why are the structural bounds not imported into the function body's scope for Trait resolution?)
Added at the origin posting. I can figure out maybe a function defination only cares for the code inside the body, ignoring the bounds on its parameters.
While I need a more detailed explanation to make it more clearly
For me it doesn't, with exactly the error one might expect:
error[E0277]: the trait bound `T: Default` is not satisfied
--> src/lib.rs:9:30
|
9 | ) -> Result<Pin<&'static mut MyBuffer<T>>, bool> {
| ^^^^^^^^^^^ the trait `Default` is not implemented for `T`
|
note: required by a bound in `MyBuffer`
--> src/lib.rs:4:20
|
4 | struct MyBuffer<T: Default + 'static>(PhantomData<T>);
| ^^^^^^^ required by this bound in `MyBuffer`
help: consider restricting type parameter `T` with trait `Default`
|
7 | fn alloc_clone<T: std::default::Default>(
| +++++++++++++++++++++++
Lifetime bounds on struct generics are implied elsewhere; non-lifetime bounds are not.
Making more bounds implied is not a slam-dunk as it takes away flexibility from library authors if there is not an opt-in, and introduces a SemVer hazard. Here's an article about that.
You use to always have to explicitly state lifetime bounds on the struct definition itself, even if implied by fields. RFC 2093 made it so most lifetime bounds required for the struct definition to compile are inferred.
// It use to be that this definition would error and require you to explicitly
// state that `T: 'a` in the header: `struct Foo<'a, T: 'a> { ... }`.
//
// Today, the `T: 'a` is inferred by the presence of the field. (Mostly:
// see the "n.b." below.) And, like when you have an explicit bound,
// `T: 'a` is implied elsewhere (such as when `Foo<'a, T>` is present
// in a function input argument).
struct Foo<'a, T> {
field: &'a T,
}
However, during stabilization of the RFC feature, it was decided to exclude 'static specifically, as there was a feeling that it might be confusing for 'static only... apparently.[1] Personally, I also find it more confusing that the bounds are not inferred for 'static only, since it is inconsistent.