# Leveraging the i32 default to type parameters

**URL:** <https://internals.rust-lang.org/t/leveraging-the-i32-default-to-type-parameters/17935>\
**Category:** language design\
**Created:** [December 8, 2022, 11:40am UTC](https://internals.rust-lang.org/t/leveraging-the-i32-default-to-type-parameters/17935 "2022-12-08T11:40:08Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![nakacristo](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nakacristo/32/10249_2.png) [@nakacristo](https://internals.rust-lang.org/u/nakacristo)\
**Post date:** [December 8, 2022, 11:40am UTC](https://internals.rust-lang.org/t/leveraging-the-i32-default-to-type-parameters/17935/1 "2022-12-08T11:40:08Z")

</div>

I have been thinking again on the [defaults affect inference](https://faultlore.com/blah/defaults-affect-inference/) issue, and I see that the compiler can already perform this inferences, with just the help of some annotations. More concretely, the existence of i32 as default integer can be leveraged to set defaults in other types.

Take as example `HashMap<K,V,S=RandomState>`, where the third parameter `S` would seem that it would inferred to be `RandomState` but it does not actually happens. For the sake of the example, we get way crazy and want to set also defaults `K=String` and `V=f32`. We can do the following.

```rust
trait Inference<T> {
	// A NOP to be introduced everywhere to help inference.
	fn inference_nop(&self,_:T) {}
}
impl Inference<i32> for HashMap<String,f32,RandomState> {}
impl<K,V,S> Inference<u32> for HashMap<K,V,S> {}
fn main() {
	let map = HashMap::default();
	map.inference_nop(0);//<--- magic here!
}

```

These `inference_nop`s should preferably be hidden and put into everything. I suppose this would currently require a procedural macro. This works because if `map` is constrained to some type other than the default then there is only the `Inference<u32>` implementation and 0 is unified to 0u32. If `map` is not fully constrained then it has also both `Inference<u32>` and `Inference<i32>`. Consecuently, the compiler disambiguates 0 into 0i32, which forces to use the `Inference<i32>` impl and in turn the stated `HashMap<String,f32,RandomState>` default. I made several examples in [this playground](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=b2171ecb823a73ac0e3f947facc65dbf).

The previous approach is all-or-nothing inference. If we prefer to have each parameter independently inferred, we may use a different trait for each default. See [this playground](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=0456fcdbbd21b22cb69b67dda48a45f3) for examples.

```rust
trait Inference1<T>{ fn inference1_nop(&self,_:T) {}}
trait Inference2<T>{ fn inference2_nop(&self,_:T) {}}
trait Inference3<T>{ fn inference3_nop(&self,_:T) {}}

impl<V,S> Inference1<i32> for HashMap<String,V,S> {}
impl<K,V,S> Inference1<u32> for HashMap<K,V,S> {}
impl<K,S> Inference2<i32> for HashMap<K,f32,S> {}
impl<K,V,S> Inference2<u32> for HashMap<K,V,S> {}
impl<K,V> Inference3<i32> for HashMap<K,V,RandomState> {}
impl<K,V,S> Inference3<u32> for HashMap<K,V,S> {}

```

There remain some issues when some of the parameters go against literal defaults. In the example we have `V=f32`, but if there is some floating literal like `3.0` it would conflict into using the language default of f64 and the impl default of f32. Thefore, this is an error, which coincides with an [old consensus](https://internals.rust-lang.org/t/interaction-of-user-defined-and-integral-fallbacks-with-inference/2496/40).

The purpose of presenting this idea is not to implement defaults this way, since it is clearly hacky. But to show that we may consider, in most aspects, adding defaults as if we would add a trait implementation. With no need to modify the actual inference engine. With any luck it will show some light into the issue.

(I also have made myself an icon after so many years here. So I am no longer a green 'N'.)

---

<div class="post-metadata">

**Author:** ![Kixunil](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kixunil/32/4110_2.png) [@Kixunil](https://internals.rust-lang.org/u/Kixunil)\
**Post date:** [December 8, 2022, 12:46pm UTC](https://internals.rust-lang.org/t/leveraging-the-i32-default-to-type-parameters/17935/2 "2022-12-08T12:46:37Z")

</div>

This reminds me of a somewhat similar problem I had. I had a function returning `impl Iterator` and I needed to store it in `Option` and access the option in a loop where it's checked first and set later. So inference didn't work. Thankfully I could pass noop value to the function without affecting performance:

```rust
static STUPID_HACK: Option<Vec<String>> = None;
#[allow(unused_assignments)]
let mut previous = Some(compute_structure("", &STUPID_HACK));
previous = None;

```

Though now I think I could've also used some `FnOnce` trick instead.

---

<div class="post-metadata">

**Author:** ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)\
**Post date:** [December 8, 2022, 7:03pm UTC](https://internals.rust-lang.org/t/leveraging-the-i32-default-to-type-parameters/17935/3 "2022-12-08T19:03:48Z")

</div>

There's long been a desire to have smarter inference in a whole bunch of cases, like being able to index arrays by more types without affecting inference, being able to do mixed comparisons without affecting inference, etc.

I don't think there are any easy fixes. But the [GitHub - rust-lang/types-team: Home of the "types team", affiliated with the compiler and lang teams.](https://github.com/rust-lang/types-team) is chartered with improving this kind of thing -- probably starting with finishing the new inference engine -- so if you're interesting in working on this stuff, you might want to join in with them.

> [@Kixunil](#):
>
> Though now I think I could've also used some `FnOnce` trick instead.

You can always put code in `if false` if you want it to affect inference and not run -- I use that in [Pre-pre-RFC: syntactic sugar for `Default::default()` - #7 by scottmcm](https://internals.rust-lang.org/t/pre-pre-rfc-syntactic-sugar-for-default-default/13234/7) , for example.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [March 8, 2023, 7:03pm UTC](https://internals.rust-lang.org/t/leveraging-the-i32-default-to-type-parameters/17935/4 "2023-03-08T19:03:52Z")

</div>

Closed on March 8, 2023, 7:03pm UTC

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
