# Can't use type-based constant in generic

**URL:** <https://users.rust-lang.org/t/cant-use-type-based-constant-in-generic/59472>\
**Category:** uncategorized\
**Created:** [May 6, 2021, 10:46pm UTC](https://users.rust-lang.org/t/cant-use-type-based-constant-in-generic/59472 "2021-05-06T22:46:47Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![John\_Nagle](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/john_nagle/32/17844_2.png) [@John\_Nagle](https://users.rust-lang.org/u/John_Nagle)\
**Post date:** [May 6, 2021, 10:46pm UTC](https://users.rust-lang.org/t/cant-use-type-based-constant-in-generic/59472/1 "2021-05-06T22:46:48Z")

</div>

> **[Rust Playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=4e1dc1beb0c02f4e0f21ebd5989ba95a)**
>
> A browser interface to the Rust compiler to experiment with the language

```rust
error[E0401]: can't use generic parameters from outer function
  --> src/main.rs:17:19
   |
16 | fn read<T>(cursor: &mut dyn Read) -> Result<T, Error> {
   | - type parameter from outer function
17 | const BYTES = T::BITS/8;
   | ^^^^^^^ use of generic parameter from outer function

```

Shouldn't that be allowed, now that we can have numeric parameters to generics? Is there a workaround? Is there a way to get the size of a type as a **const**?

It's been discussed at [Can't assign results of generic functions to `const` variables · Issue #57775 · rust-lang/rust · GitHub](https://github.com/rust-lang/rust/issues/57775)

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/steffahn/32/47569_2.png) [@steffahn](https://users.rust-lang.org/u/steffahn)\
**Post date:** [May 6, 2021, 11:04pm UTC](https://users.rust-lang.org/t/cant-use-type-based-constant-in-generic/59472/2 "2021-05-06T23:04:01Z")

</div>

The way to think about items such as `const`, `trait`, `type`, or `fn` is that while they are allowed to appear inside of a function body, they still have to be defined in such a way that they could equally well be pulled outside of that function body. That’s why `T` isn’t allowed in the `const`. Similarly:

```rust

fn foo<T>() {
    type Ty = T;
}
fn bar<T>() {
    fn f(_: T) {}
}
fn baz<T>() {
    trait Tr {
        fn f(_: T);
    }
}
fn qux<T>() {
    trait Tr {
        type Ty: AsRef<T>;
    }
}
// etc

```

doesn’t work. The way to do compile-time but type-dependent stuff is by `const fn`, or with `trait`s with associated items. By the way, I don’t know where the associated item `BITS` is supposed to come from, maybe you’re missing a trait or something in your code example?

* * *
Edit:

> The way to do compile-time but type-dependent stuff is by `const fn`, or with `trait`s with associated items.

actually, that might be wrong; maybe what you want isn’t possible on stable yet. I tried some stuff with a trait with an associated `const BITS` and I keep getting `error: generic parameters may not be used in const operations`.

---

<div class="post-metadata">

**Author:** ![John\_Nagle](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/john_nagle/32/17844_2.png) [@John\_Nagle](https://users.rust-lang.org/u/John_Nagle)\
**Post date:** [May 7, 2021, 12:01am UTC](https://users.rust-lang.org/t/cant-use-type-based-constant-in-generic/59472/3 "2021-05-07T00:01:56Z")

</div>

> [@steffahn](#):
>
> The way to think about items such as `const` , `trait` , `type` , or `fn` is that while they are allowed to appear inside of a function body, they still have to be defined in such a way that they could equally well be pulled outside of that function body. That’s why `T` isn’t allowed in the `const` .

Ref: [Rust Playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=d5493cd1e6d5624853791cefc8f31c02)

Not sure that's it. It's const-ness that's the problem, not definedness.

```
const BYTES = T::BITS/8; // NO
let bytes = T::BITS/8; // OK

```

Added the necessary trait constraints.

The [specific issue on generic type sizes](https://github.com/rust-lang/rust/issues/43408) was merged into the const generics effort, but didn't get fixed when that went in.

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/steffahn/32/47569_2.png) [@steffahn](https://users.rust-lang.org/u/steffahn)\
**Post date:** [May 7, 2021, 12:28am UTC](https://users.rust-lang.org/t/cant-use-type-based-constant-in-generic/59472/4 "2021-05-07T00:28:48Z")

</div>

Maybe some pointers to the reference might help. The word “item” is a technical term.

[Items - The Rust Reference](https://doc.rust-lang.org/stable/reference/items.html)

and it’s different from statements

[Statements - The Rust Reference](https://doc.rust-lang.org/stable/reference/statements.html)

An item is a thing that can be put at top-level in Rust, a `let … = …;` statement is not an item. On the other hand, while items can _technically_ count as statements, they’re really in essence not really part of the function or block they live in except for visibility concerns; so it’s best to think of items and statements of really different things. This means that a `const …: … = …;` is something _entirely_ different from a `let`-statement in lots of ways, it isn’t just “a `let`-statement with some ‘const-ness’ constraints” or anything like that.

More on items as statements can be read in the reference [here](https://doc.rust-lang.org/stable/reference/statements.html#item-declarations) which is a section of the “Statements” page linked above. In particular, try to understand this part and relate it to the examples I gave above:

> […] It is otherwise identical in meaning to declaring the item inside a module.
> 
> There is no implicit capture of the containing function's generic parameters, parameters, and local variables. For example, `inner` may not access `outer_var` .
> 
> ```rust
> fn outer() {
> let outer_var = true;
> 
> fn inner() { /* outer_var is not in scope here */ }
> 
> inner();
> }
> 
> ```

---

<div class="post-metadata">

**Author:** ![John\_Nagle](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/john_nagle/32/17844_2.png) [@John\_Nagle](https://users.rust-lang.org/u/John_Nagle)\
**Post date:** [May 7, 2021, 3:11am UTC](https://users.rust-lang.org/t/cant-use-type-based-constant-in-generic/59472/5 "2021-05-07T03:11:00Z")

</div>

> [@steffahn](#):
>
> `/* outer_var is not in scope here */`

That applies to a local variable, reasonably enough, because otherwise you could create a closure that way. It doesn't apply to an "item".

```
// Nesting test
pub fn outer() {
    struct St {
        pub x: f32
        }
        
    const X: f32 = 1.0;
        
    fn fn1()-> St {
        let st = St{x: X};
        st
    }
    
    let stout = fn1();
    println!("{}", stout.x)
}

```

**X** and **St** , being compile-type objects, are visible within **fn1**.

So this isn't a general scope issue, it's a special problem with generics. One that really should have been fixed when const parameters came in, since the whole point of that was to improve behavior around items whose size is determined at compile time.

---

<div class="post-metadata">

**Author:** ![system](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/system/32/51372_2.png) [@system](https://users.rust-lang.org/u/system)\
**Post date:** [August 5, 2021, 3:11am UTC](https://users.rust-lang.org/t/cant-use-type-based-constant-in-generic/59472/6 "2021-08-05T03:11:49Z")

</div>

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.
