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

change hir::ExprLit to take a ConstVal instead of an ast::Lit #32793

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion mk/crates.mk
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ DEPS_rustc_driver := arena flate getopts graphviz libc rustc rustc_back rustc_bo
rustc_typeck rustc_mir rustc_resolve log syntax serialize rustc_llvm \
rustc_trans rustc_privacy rustc_lint rustc_plugin \
rustc_metadata syntax_ext rustc_passes rustc_save_analysis rustc_const_eval
DEPS_rustc_lint := rustc log syntax rustc_const_eval
DEPS_rustc_lint := rustc log syntax rustc_const_eval rustc_const_math
DEPS_rustc_llvm := native:rustllvm libc std rustc_bitflags
DEPS_rustc_metadata := rustc syntax rbml rustc_const_math
DEPS_rustc_passes := syntax rustc core rustc_const_eval
Expand Down
131 changes: 130 additions & 1 deletion src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ use syntax::parse::token;
use syntax::std_inject;
use syntax::visit::{self, Visitor};

use rustc_const_math::{ConstVal, ConstInt, ConstIsize, ConstUsize};

use std::cell::{Cell, RefCell};

pub struct LoweringContext<'a> {
Expand Down Expand Up @@ -1142,12 +1144,24 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
let rhs = lower_expr(lctx, rhs);
hir::ExprBinary(binop, lhs, rhs)
}
ExprKind::Unary(UnOp::Neg, ref inner) => {
let (new, mut attrs) = lower_un_neg(lctx, inner);
attrs.update(|a| {
a.prepend(e.attrs.clone())
});
return P(hir::Expr {
id: e.id,
span: e.span,
attrs: attrs,
node: new,
});
},
ExprKind::Unary(op, ref ohs) => {
let op = lower_unop(lctx, op);
let ohs = lower_expr(lctx, ohs);
hir::ExprUnary(op, ohs)
}
ExprKind::Lit(ref l) => hir::ExprLit(P((**l).clone())),
ExprKind::Lit(ref l) => hir::ExprLit(lower_lit(lctx, &l.node, l.span)),
ExprKind::Cast(ref expr, ref ty) => {
let expr = lower_expr(lctx, expr);
hir::ExprCast(expr, lower_ty(lctx, ty))
Expand Down Expand Up @@ -1674,6 +1688,121 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
})
}

fn negate_lit(lctx: &LoweringContext, n: u64, ty: LitIntType) -> ConstVal {
use syntax::ast::LitIntType::*;
use syntax::ast::IntTy::*;
use std::{i8, i16, i32, i64};
use rustc_const_math::ConstVal::Integral;
const I8_OVERFLOW: u64 = i8::MAX as u64 + 1;
const I16_OVERFLOW: u64 = i16::MAX as u64 + 1;
const I32_OVERFLOW: u64 = i32::MAX as u64 + 1;
const I64_OVERFLOW: u64 = i64::MAX as u64 + 1;
match (n, ty, lctx.id_assigner.target_bitwidth()) {
(I8_OVERFLOW, Signed(I8), _) => Integral(ConstInt::I8(i8::MIN)),
(I16_OVERFLOW, Signed(I16), _) => Integral(ConstInt::I16(i16::MIN)),
(I32_OVERFLOW, Signed(I32), _) => Integral(ConstInt::I32(i32::MIN)),
(I64_OVERFLOW, Signed(I64), _) => Integral(ConstInt::I64(i64::MIN)),
(I64_OVERFLOW, Signed(Is), 64) => Integral(ConstInt::Isize(ConstIsize::Is64(i64::MIN))),
(I32_OVERFLOW, Signed(Is), 32) => Integral(ConstInt::Isize(ConstIsize::Is32(i32::MIN))),
(I64_OVERFLOW, Unsuffixed, _) => Integral(ConstInt::InferSigned(i64::MIN)),
(n, Signed(I8), _) => Integral(ConstInt::I8(-(n as i64 as i8))),
(n, Signed(I16), _) => Integral(ConstInt::I16(-(n as i64 as i16))),
(n, Signed(I32), _) => Integral(ConstInt::I32(-(n as i64 as i32))),
(n, Signed(I64), _) => Integral(ConstInt::I64(-(n as i64))),
(n, Signed(Is), 64) => Integral(ConstInt::Isize(ConstIsize::Is64(-(n as i64)))),
(n, Signed(Is), 32) => Integral(ConstInt::Isize(ConstIsize::Is32(-(n as i64 as i32)))),
(_, Signed(Is), _) => unreachable!(),
// unary negation of unsigned has already been reported by EarlyTypeLimits
(_, Unsigned(_), _) => ConstVal::Dummy,
(n, Unsuffixed, _) => Integral(ConstInt::InferSigned(-(n as i64))),
}
}

pub fn lower_un_neg(lctx: &LoweringContext, inner: &Expr) -> (hir::Expr_, ThinAttributes) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is all of this necessary? Can't we just keep the negation expression?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works better in patterns

match inner.node {
ExprKind::Paren(ref ex) => {
let (new, mut attrs) = lower_un_neg(lctx, ex);
attrs.update(|attrs| attrs.prepend(ex.attrs.clone()));
return (new, attrs);
}
ExprKind::Lit(ref lit) => {
if let LitKind::Int(n, ty) = lit.node {
return (hir::ExprLit(negate_lit(lctx, n, ty)), None);
}
},
ExprKind::Unary(UnOp::Neg, ref double_inner) => {
if let ExprKind::Lit(ref lit) = double_inner.node {
// skip double negation where applicable
if let LitKind::Int(..) = lit.node {
return (
hir::ExprLit(lower_lit(lctx, &lit.node, inner.span)),
double_inner.attrs.clone(),
);
}
}
},
_ => {},
}
(hir::ExprUnary(hir::UnNeg, lower_expr(lctx, inner)), None)
}

pub fn lower_lit(lctx: &LoweringContext, lit: &LitKind, span: Span) -> ConstVal {
use syntax::ast::LitIntType::*;
use syntax::ast::LitKind::*;
use syntax::ast::IntTy::*;
use syntax::ast::UintTy::*;
match *lit {
Str(ref s, _) => ConstVal::Str((*s).clone()),
ByteStr(ref data) => ConstVal::ByteStr(data.clone()),
Byte(n) => ConstVal::Integral(ConstInt::U8(n)),
Int(n, Signed(I8)) => ConstVal::Integral(ConstInt::I8(n as i64 as i8)),
Int(n, Signed(I16)) => ConstVal::Integral(ConstInt::I16(n as i64 as i16)),
Int(n, Signed(I32)) => ConstVal::Integral(ConstInt::I32(n as i64 as i32)),
Int(n, Signed(I64)) => ConstVal::Integral(ConstInt::I64(n as i64)),
Int(n, Signed(Is)) => {
ConstVal::Integral(match lctx.id_assigner.target_bitwidth() {
32 => ConstInt::Isize(ConstIsize::Is32(n as i64 as i32)),
64 => ConstInt::Isize(ConstIsize::Is64(n as i64)),
_ => unimplemented!(),
})
},
Int(n, Unsigned(U8)) => ConstVal::Integral(ConstInt::U8(n as u8)),
Int(n, Unsigned(U16)) => ConstVal::Integral(ConstInt::U16(n as u16)),
Int(n, Unsigned(U32)) => ConstVal::Integral(ConstInt::U32(n as u32)),
Int(n, Unsigned(U64)) => ConstVal::Integral(ConstInt::U64(n)),
Int(n, Unsigned(Us)) => {
ConstVal::Integral(match lctx.id_assigner.target_bitwidth() {
32 => ConstInt::Usize(ConstUsize::Us32(n as u32)),
64 => ConstInt::Usize(ConstUsize::Us64(n)),
_ => unimplemented!(),
})
},
Int(n, Unsuffixed) => ConstVal::Integral(ConstInt::Infer(n)),
Float(ref f, fty) => {
if let Ok(x) = f.parse::<f64>() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

double rounding

ConstVal::Float(x, Some(fty))
} else {
// FIXME(#31407) this is only necessary because float parsing is buggy
lctx.id_assigner
.diagnostic()
.span_bug(span, "could not evaluate float literal (see issue #31407)");
}
},
FloatUnsuffixed(ref f) => {
if let Ok(x) = f.parse::<f64>() {
ConstVal::Float(x, None)
} else {
// FIXME(#31407) this is only necessary because float parsing is buggy
lctx.id_assigner
.diagnostic()
.span_bug(span, "could not evaluate float literal (see issue #31407)");
}
},
Bool(b) => ConstVal::Bool(b),
Char(c) => ConstVal::Char(c),
}
}

pub fn lower_stmt(lctx: &LoweringContext, s: &Stmt) -> hir::Stmt {
match s.node {
StmtKind::Decl(ref d, id) => {
Expand Down
6 changes: 4 additions & 2 deletions src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,14 @@ use util::nodemap::{NodeMap, FnvHashSet};
use syntax::codemap::{self, Span, Spanned, DUMMY_SP, ExpnId};
use syntax::abi::Abi;
use syntax::ast::{Name, NodeId, DUMMY_NODE_ID, TokenTree, AsmDialect};
use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, MetaItem};
use syntax::ast::{Attribute, StrStyle, FloatTy, IntTy, UintTy, MetaItem};
use syntax::attr::{ThinAttributes, ThinAttributesExt};
use syntax::parse::token::InternedString;
use syntax::ptr::P;

use std::collections::BTreeMap;
use rustc_const_math::ConstVal;

use std::fmt;
use std::hash::{Hash, Hasher};
use serialize::{Encodable, Decodable, Encoder, Decoder};
Expand Down Expand Up @@ -930,7 +932,7 @@ pub enum Expr_ {
/// A unary operation (For example: `!x`, `*x`)
ExprUnary(UnOp, P<Expr>),
/// A literal (For example: `1`, `"foo"`)
ExprLit(P<Lit>),
ExprLit(ConstVal),
/// A cast (`foo as f64`)
ExprCast(P<Expr>, P<Ty>),
ExprType(P<Expr>, P<Ty>),
Expand Down
30 changes: 28 additions & 2 deletions src/librustc/hir/print.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,13 @@ use syntax::print::pp::Breaks::{Consistent, Inconsistent};
use syntax::print::pprust::{self as ast_pp, PrintState};
use syntax::ptr::P;

use rustc_const_math::ConstVal;

use hir;
use hir::{Crate, PatKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};

use std::io::{self, Write, Read};
use std::ascii;

pub enum AnnNode<'a> {
NodeName(&'a ast::Name),
Expand Down Expand Up @@ -1303,6 +1306,29 @@ impl<'a> State<'a> {
self.print_expr_maybe_paren(expr)
}

fn print_const_val(&mut self, const_val: &ConstVal) -> io::Result<()> {
match *const_val {
ConstVal::Float(f, None) => word(&mut self.s, &format!("{}", f)),
ConstVal::Float(f, Some(t)) => {
word(&mut self.s, &format!("{}_{}", f, t.ty_to_string()))
},
ConstVal::Integral(ref i) => word(&mut self.s, &format!("{}", i)),
ConstVal::Str(ref s) => word(&mut self.s, &format!("{:?}", s)),
ConstVal::ByteStr(ref v) => {
let mut escaped: String = String::new();
for &ch in v.iter() {
escaped.extend(ascii::escape_default(ch)
.map(|c| c as char));
}
word(&mut self.s, &format!("b\"{}\"", escaped))
},
ConstVal::Bool(true) => word(&mut self.s, "true"),
ConstVal::Bool(false) => word(&mut self.s, "false"),
ConstVal::Char(c) => word(&mut self.s, &format!("{:?}", c)),
_ => unimplemented!(),
}
}

pub fn print_expr(&mut self, expr: &hir::Expr) -> io::Result<()> {
self.maybe_print_comment(expr.span.lo)?;
self.ibox(indent_unit)?;
Expand Down Expand Up @@ -1339,8 +1365,8 @@ impl<'a> State<'a> {
hir::ExprAddrOf(m, ref expr) => {
self.print_expr_addr_of(m, &expr)?;
}
hir::ExprLit(ref lit) => {
self.print_literal(&lit)?;
hir::ExprLit(ref const_val) => {
self.print_const_val(&const_val)?;
}
hir::ExprCast(ref expr, ref ty) => {
self.print_expr(&expr)?;
Expand Down
5 changes: 3 additions & 2 deletions src/librustc/hir/svh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ mod svh_visitor {
use hir::intravisit::{Visitor, FnKind};
use hir::*;
use hir;
use rustc_const_math::ConstVal;

use std::hash::{Hash, SipHasher};

Expand Down Expand Up @@ -232,7 +233,7 @@ mod svh_visitor {
SawExprTup,
SawExprBinary(hir::BinOp_),
SawExprUnary(hir::UnOp),
SawExprLit(ast::LitKind),
SawExprLit(ConstVal),
SawExprCast,
SawExprType,
SawExprIf,
Expand Down Expand Up @@ -260,7 +261,7 @@ mod svh_visitor {
ExprTup(..) => SawExprTup,
ExprBinary(op, _, _) => SawExprBinary(op.node),
ExprUnary(op, _) => SawExprUnary(op),
ExprLit(ref lit) => SawExprLit(lit.node.clone()),
ExprLit(ref lit) => SawExprLit(lit.clone()),
ExprCast(..) => SawExprCast,
ExprType(..) => SawExprType,
ExprIf(..) => SawExprIf,
Expand Down
1 change: 0 additions & 1 deletion src/librustc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ pub mod lint;
pub mod middle {
pub mod astconv_util;
pub mod expr_use_visitor; // STAGE0: increase glitch immunity
pub mod const_val;
pub mod const_qualif;
pub mod cstore;
pub mod dataflow;
Expand Down
16 changes: 10 additions & 6 deletions src/librustc/mir/repr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@
// except according to those terms.

use graphviz::IntoCow;
use middle::const_val::ConstVal;
use rustc_const_math::{ConstUsize, ConstInt};
use hir::def_id::DefId;
use rustc_const_math::{ConstUsize, ConstInt, ConstVal};
use hir::def_id::{DefId, DefIndex};
use ty::subst::Substs;
use ty::{self, AdtDef, ClosureSubsts, FnOutput, Region, Ty};
use util::ppaux;
Expand Down Expand Up @@ -999,9 +998,11 @@ impl<'tcx> Debug for Literal<'tcx> {

/// Write a `ConstVal` in a way closer to the original source code than the `Debug` output.
fn fmt_const_val<W: Write>(fmt: &mut W, const_val: &ConstVal) -> fmt::Result {
use middle::const_val::ConstVal::*;
use rustc_const_math::ConstVal::*;
match *const_val {
Float(f) => write!(fmt, "{:?}", f),
Float(f, Some(ast::FloatTy::F32)) => write!(fmt, "{}_f32", f as f32),
Float(f, Some(ast::FloatTy::F64)) => write!(fmt, "{}_f64", f),
Float(f, None) => write!(fmt, "{}", f),
Integral(n) => write!(fmt, "{}", n),
Str(ref s) => write!(fmt, "{:?}", s),
ByteStr(ref bytes) => {
Expand All @@ -1012,7 +1013,10 @@ fn fmt_const_val<W: Write>(fmt: &mut W, const_val: &ConstVal) -> fmt::Result {
write!(fmt, "b\"{}\"", escaped)
}
Bool(b) => write!(fmt, "{:?}", b),
Function(def_id) => write!(fmt, "{}", item_path_str(def_id)),
Function { krate, index } => {
let path = item_path_str(DefId { krate: krate, index: DefIndex::from_u32(index) });
write!(fmt, "{}", path)
},
Struct(node_id) | Tuple(node_id) | Array(node_id, _) | Repeat(node_id, _) =>
write!(fmt, "{}", node_to_string(node_id)),
Char(c) => write!(fmt, "{:?}", c),
Expand Down
3 changes: 1 addition & 2 deletions src/librustc/mir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use middle::const_val::ConstVal;
use hir::def_id::DefId;
use ty::subst::Substs;
use ty::{ClosureSubsts, FnOutput, Region, Ty};
use mir::repr::*;
use rustc_const_math::ConstUsize;
use rustc_const_math::{ConstUsize, ConstVal};
use rustc_data_structures::tuple_slice::TupleSlice;
use syntax::codemap::Span;

Expand Down
10 changes: 10 additions & 0 deletions src/librustc/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,16 @@ impl NodeIdAssigner for Session {
fn diagnostic(&self) -> &errors::Handler {
self.diagnostic()
}

fn target_bitwidth(&self) -> u32 {
match self.target.int_type {
ast::IntTy::Is => bug!("target int type defined as isize"),
ast::IntTy::I64 => 64,
ast::IntTy::I32 => 32,
ast::IntTy::I16 => unimplemented!(),
ast::IntTy::I8 => unimplemented!(),
}
}
}

fn split_msg_into_multilines(msg: &str) -> Option<String> {
Expand Down
12 changes: 4 additions & 8 deletions src/librustc_const_eval/check_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use self::Usefulness::*;
use self::WitnessPreference::*;

use rustc::dep_graph::DepNode;
use rustc::middle::const_val::ConstVal;
use rustc_const_math::ConstVal;
use ::{eval_const_expr, eval_const_expr_partial, compare_const_vals};
use ::{const_expr_to_pat, lookup_const_by_id};
use ::EvalHint::ExprTypeChecked;
Expand All @@ -37,7 +37,7 @@ use rustc::hir::{Pat, PatKind};
use rustc::hir::intravisit::{self, IdVisitor, IdVisitingOperation, Visitor, FnKind};
use rustc_back::slice;

use syntax::ast::{self, DUMMY_NODE_ID, NodeId};
use syntax::ast::{DUMMY_NODE_ID, NodeId};
use syntax::codemap::{Span, Spanned, DUMMY_SP};
use rustc::hir::fold::{Folder, noop_fold_pat};
use rustc::hir::print::pat_to_string;
Expand Down Expand Up @@ -275,7 +275,7 @@ fn check_for_static_nan(cx: &MatchCheckCtxt, pat: &Pat) {
pat.walk(|p| {
if let PatKind::Lit(ref expr) = p.node {
match eval_const_expr_partial(cx.tcx, &expr, ExprTypeChecked, None) {
Ok(ConstVal::Float(f)) if f.is_nan() => {
Ok(ConstVal::Float(f, _)) if f.is_nan() => {
span_warn!(cx.tcx.sess, p.span, E0003,
"unmatchable NaN in pattern, \
use the is_nan method in a guard instead");
Expand Down Expand Up @@ -423,13 +423,9 @@ fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, matrix: &Matrix, source: hir:
}

fn const_val_to_expr(value: &ConstVal) -> P<hir::Expr> {
let node = match value {
&ConstVal::Bool(b) => ast::LitKind::Bool(b),
_ => bug!()
};
P(hir::Expr {
id: 0,
node: hir::ExprLit(P(Spanned { node: node, span: DUMMY_SP })),
node: hir::ExprLit(value.clone()),
span: DUMMY_SP,
attrs: None,
})
Expand Down
Loading