-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Do not suggest "using a local generic parameter" for constants #115720
Comments
It's should be This code can compile successfully: fn main() { }
trait Trait {
const X: u32;
}
impl Trait for () {
const X: u32 = 0;
}
impl<T: Trait> Trait for [T] {
const X: u32 = {
let tmp: u32 = T::X + 1;
tmp
};
} This should also be ok: const X: u32 = {
const TEMP: u32 = T::X + 1;
TEMP
}; emm, this error seems need to be fixed: 11 | impl<T: Trait> Trait for [T] {
| - type parameter from outer function
12 | const X: u32 = {
13 | const TEMP: u32 = T::X + 1;
| - ^^^^ use of generic parameter from outer function
| |
| help: try using a local generic parameter instead: `<T>` |
Yes, I updated the code. |
It should be worth mentioning that this suggestion only occurs on beta and nightly but not on stable. |
No, inner items (like constants, functions, static items, impl items) are not allowed to reference the generics of their parent item since inner items are just like top-level items, they are compiled separately. The exception being associated items which may reference the generics of their parent. |
Is this a current limitation or a design decision? Is there any discussion on this topic? For context I was trying to implement a trait that (statically) describes Rust types with DBus type signatures. The idea fell apart on arrays: impl<T: Type> Type for [T] {
const SIGNATURE: &'static str = const_format::concatcp!("a", T::SIGNATURE);
} which fails with a very similar error message as in my example. |
That's unfortunate. At first glance, I don't see a good way to fix I haven't been around for long enough but I'd wager it was an intentional decision for ease of use (no accidental size explosions due to quadratic / polynomial monomorphization?) and implementation.
|
Hm, okay. I didn't even know about "generic const items". Using them sort of fixes the error in this case: impl<T: Trait> Trait for [T] {
const X: u32 = {
const TEMP<T: Trait>: u32 = T::X + 1;
TEMP::<T>
};
} I too don't see a way to use them to concatenate strings... Still, the error message can be improved at least because it refers to some |
Yeah, I meant that I used For sure, the diagnostic should definitely be improved, I'm gonna fix that. |
But I found a way to prepend bytes in my specific case. I'm not really sure if this is the intended way to use generic const items. #![feature(generic_const_items, generic_const_exprs)]
#![allow(incomplete_features)]
fn main() {
dbg!(<[i32]>::SIGNATURE);
dbg!(<[u32]>::SIGNATURE);
dbg!(<[&[u32]]>::SIGNATURE);
}
trait Type {
const SIGNATURE: &'static str;
}
impl Type for i32 {
const SIGNATURE: &'static str = "i";
}
impl Type for u32 {
const SIGNATURE: &'static str = "u";
}
impl<T: Type + ?Sized> Type for &T {
const SIGNATURE: &'static str = T::SIGNATURE;
}
impl<T: Type> Type for [T]
where
[(); T::SIGNATURE.len() + 1]:,
{
const SIGNATURE: &'static str = unsafe { std::str::from_utf8_unchecked(CONST_PREPEND_BYTE::<b'a', T>) };
}
const CONST_PREPEND_BYTE<const B: u8, T: Type>: &[u8; T::SIGNATURE.len() + 1] = {
let mut arr = [0u8; T::SIGNATURE.len() + 1];
let mut i = 0;
arr[0] = B;
while i < T::SIGNATURE.len() {
arr[i + 1] = T::SIGNATURE.as_bytes()[i];
i += 1;
}
& { arr } // This works but just `&arr` doesn't???
} where [(); T::SIGNATURE.len() + 1]:;
Awesome :) |
Improve diagnostic for generic params from outer items (E0401) Generalize the wording of E0401 to talk about *outer items* instead of *outer functions* since the current phrasing is outdated. The outer item can be a function, constant, trait, ADT or impl block (see the new UI test for the more exotic examples). Further, don't suggest introducing generic parameters to constant items unless the feature `generic_const_items` is enabled. Lastly, make E0401 translatable while we're at it. Fixes rust-lang#115720.
Improve diagnostic for generic params from outer items (E0401) Generalize the wording of E0401 to talk about *outer items* instead of *outer functions* since the current phrasing is outdated. The outer item can be a function, constant, trait, ADT or impl block (see the new UI test for the more exotic examples). Further, don't suggest introducing generic parameters to constant items unless the feature `generic_const_items` is enabled. Lastly, make E0401 translatable while we're at it. Fixes rust-lang#115720.
Rollup merge of rust-lang#115744 - fmease:fix-e0401, r=compiler-errors Improve diagnostic for generic params from outer items (E0401) Generalize the wording of E0401 to talk about *outer items* instead of *outer functions* since the current phrasing is outdated. The outer item can be a function, constant, trait, ADT or impl block (see the new UI test for the more exotic examples). Further, don't suggest introducing generic parameters to constant items unless the feature `generic_const_items` is enabled. Lastly, make E0401 translatable while we're at it. Fixes rust-lang#115720.
Code
Current output
Desired output
I'm not sure what the output should be (I'm not even sure why this does not compile), but using a local generic parameter does not make sense for me. It seems like the error message thinks this code is inside a function.
The text was updated successfully, but these errors were encountered: