Skip to content
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

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

Closed
shepmaster opened this Issue Jan 25, 2015 · 6 comments

Comments

Projects
None yet
4 participants
@shepmaster
Copy link
Member

shepmaster commented Jan 25, 2015

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

@edwardw

This comment has been minimized.

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

Make use of a binary operator's RHS type for LHS inference
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 a
hint to infer LHS' type.

Closes rust-lang#21634

edwardw added a commit to edwardw/rust that referenced this issue Jan 31, 2015

Make use of a binary operator's RHS type for LHS inference
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

rollup merge of rust-lang#21817: edwardw/symmetric-binop
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

@bors bors closed this in #21817 Feb 3, 2015

@Byron

This comment has been minimized.

Copy link
Contributor

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

This comment has been minimized.

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

This comment has been minimized.

Copy link
Contributor

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

This comment has been minimized.

Copy link
Contributor

edwardw commented Feb 6, 2015

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

@Byron

This comment has been minimized.

Copy link
Contributor

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
You can’t perform that action at this time.