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

const_eval sometimes confuses (a guess at) expected type with expression's actual type #23833

Closed
pnkfelix opened this issue Mar 29, 2015 · 5 comments
Labels
A-typesystem Area: The type system

Comments

@pnkfelix
Copy link
Member

const_eval sometimes confuses a guess at expected type with expression's actual type

Here's an example:

use std::fmt;
use std::{i8, i16, i32, i64, isize};
use std::{u8, u16, u32, u64, usize};

const A_I8_T
    : [u32; (i8::MAX as i8 - 1i8) as usize]
    = [0; (i8::MAX as usize) - 1];

fn main() {
    foo(&A_I8_T[..]);
}

fn foo<T:fmt::Debug>(x: T) {
    println!("{:?}", x);
}

playpen yields:

<anon>:6:14: 6:33 error: array length constant evaluation error: can't do this op on a usize and isize [E0250]
<anon>:6     : [u32; (i8::MAX as i8 - 1i8) as usize]
                      ^~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
playpen: application terminated with error code 101

I believe this is due to this line in const_eval.rs:

https://github.com/rust-lang/rust/blob/master/src/librustc/middle/const_eval.rs#L504
(transcribed immediately below for ease of reference:)

Namely, the logic here takes a constant expression like the one in the above count expression and feeds the expected usize type down into the computation of (i8::MAX as i8 - 1i8).

      ast::ExprCast(ref base, ref target_ty) => {
        // This tends to get called w/o the type actually having been
        // populated in the ctxt, which was causing things to blow up
        // (#5900). Fall back to doing a limited lookup to get past it.
        let ety = ety.or_else(|| ast_ty_to_prim_ty(tcx, &**target_ty))
                .unwrap_or_else(|| {
                    tcx.sess.span_fatal(target_ty.span,
                                        "target type not found for const cast")
                });
        // Prefer known type to noop, but always have a type hint.
        let base_hint = ty::expr_ty_opt(tcx, &**base).unwrap_or(ety);
        let val = try!(eval_const_expr_partial(tcx, &**base, Some(base_hint)));
        match cast_const(val, ety) {
            Ok(val) => val,
            Err(kind) => return Err(ConstEvalErr { span: e.span, kind: kind }),
        }
      }

Even though there are many many hints in (i8::MAX as i8 - 1i8) that are attempting to force the left- and right-hand sides to both be i8, the const_eval is ignoring them and trying to force the left-hand-side to be a usize.

(This causes problems for proper overflow detection in const_eval.)

@pnkfelix
Copy link
Member Author

this is related to #22531 and should be treated as a sub-bug of #22020.

@pnkfelix
Copy link
Member Author

(Not quite sure why it is so important to always have a type hint; seems like it would be more accurate to instead carry (a bottom-up determined, (update: partially-determined if necessary)) type along with the value during const-eval.)

@steveklabnik steveklabnik added the A-typesystem Area: The type system label Mar 30, 2015
@pnkfelix
Copy link
Member Author

cc #23897

@pnkfelix
Copy link
Member Author

This example, adapted from #18744 , is probably another instance of this:

fn main() {
    match 1u64 {
        0...0xFFFF_FFFF_FFFF_FFFF => { },
        _ => { },
    }
}

It currently errors with error: lower range bound must be less than upper [E0030]

(The workaround is to add explicit suffixes to at least the 0 and optionally both ends of the range.)

@nagisa
Copy link
Member

nagisa commented Aug 11, 2016

Not an issue anymore, should be closed.

@eddyb eddyb closed this as completed Aug 11, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-typesystem Area: The type system
Projects
None yet
Development

No branches or pull requests

4 participants