Skip to content

Type inference of floating point numbers through a comparison depends on the order of the operands #21634

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

Closed
shepmaster opened this issue Jan 25, 2015 · 6 comments · Fixed by #21817
Labels
A-type-system Area: Type system

Comments

@shepmaster
Copy link
Member

This fails:

fn main() {
    if let Some(value) = "hi".parse() {
        if value <= 0.0 { println!("1") } else { println!("2") };
    }
}

with the error:

error: the type of this value must be known in this context
         if value <= 0.0 { println!("1") } else { println!("2") };
            ^~~~~

Simply flipping the order of the comparison operands allows it to compile:

fn main() {
    if let Some(value) = "hi".parse() {
        if 0.0 >= value { println!("1") } else { println!("2") };
    }
}

Tested with rustc 1.0.0-dev (102ab57d8 2015-01-25 13:33:18 +0000) Originally from this Stack Overflow question

@kmcallister kmcallister added the A-type-system Area: Type system label Jan 28, 2015
@edwardw
Copy link
Contributor

edwardw commented Jan 31, 2015

Other operators such as value + 0.0, value += 0.0 or value == 0.0 also don't type check under the same circumstances. Interesting.

edwardw added a commit to edwardw/rust that referenced this issue Jan 31, 2015
For "symmetric" binary operators, meaning the types of two side must be
equal, if the type of LHS doesn't know yet but RHS does, use that as an
hint to infer LHS' type.

Closes rust-lang#21634
alexcrichton added a commit to alexcrichton/rust that referenced this issue Feb 2, 2015
For "symmetric" binary operators, meaning the types of two sides must be
equal, if the type of LHS doesn't know yet but RHS does, use that as an
hint to infer LHS' type.

Closes rust-lang#21634
@Byron
Copy link
Member

Byron commented Feb 3, 2015

Please note that this issue was referenced from a question on stackoverflow, implying that it would be resolved with the fix discussed here.

Today I tried it with the latest version I could pull, rustc 1.0.0-dev (7858cb432 2015-02-03 03:44:05 +0000) (which definitely includes this fix), but find my issue unresolved.

Maybe both are unrelated after all, yet I felt the need to file some sort of report in case it should be fixed.

How to reproduce my particular issue

If you replace self.mulfed(<T as Float>::one() / self.len()) with self.mulfed(Float::one() / self.len()), one will get this compile error:

src/rust/vec.rs:89:21: 89:33 error: the type of this value must be known in this context
src/rust/vec.rs:89         self.mulfed(Float::one() / self.len())
                                       ^~~~~~~~~~~~

@edwardw
Copy link
Contributor

edwardw commented Feb 5, 2015

@Byron, thanks for reporting this. I'm a bit confused though. What is self.len()? It is not in anywhere in the original question.

@Byron
Copy link
Member

Byron commented Feb 6, 2015

@edwardw Sorry for the late reply. self.len() just expands to self.dot(self).sqrt(), which is what you see in the original question. The code I linked on github is a little newer, and 'post-question', so to speak. To my mind it doesn't change the issue at all. By now I have far more code that uses the Float trait as constraint for a type parameter, and thanks to the somewhat missing type inference in this case, the code seems more bloated than it has to be (at least from my perspective of a newbie in Rust).
Especially when using the Float trait constraint, it becomes very cumbersome to program, as one cannot write something like this anymore ...

let x: T = 5.0; // where T: Float,
error: mismatched types:
 expected `T`,
    found `_`
(expected type parameter,
    found floating-point variable) [E0308]

... which forces you to use facilities of the Float trait exclusively.

let one: T = Float::one();
let x = one + one + one + one + one; // now x is 5.0T

I am just trying to share my experiences so far, maybe the 'issues' I run into are perfectly intended, even though they seem unnecessary to me.

For the issue above, my workaround is to not use a type parameter constrained to Float, but instead use a type alias. That way, type inference works as expected, while still allowing me to test the programs performance gains when using f32 or f64 respectively.

let x: MyFloat = 5.0; // type MyFloat = f32;
// Now I can easily set MyFloat to be f64 for example, which is what I originally intended with T: Float

@edwardw
Copy link
Contributor

edwardw commented Feb 6, 2015

@Byron, I just filed a bug report on your behalf: #22001.

@Byron
Copy link
Member

Byron commented Feb 8, 2015

@edwardw Does this also mean that using number literals in a generic context is not desired ? I have also posted a question which aims at this on disqus, as a closed ticket might not be the right forum for this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-type-system Area: Type system
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants