// - It's not possible to take the address of a static item with unsafe interior. This is enforced
// by borrowck::gather_loans
-use middle::cast::{CastKind};
+use middle::ty::cast::{CastKind};
use middle::const_eval;
use middle::const_eval::EvalHint::ExprTypeChecked;
use middle::def;
+use middle::def_id::DefId;
use middle::expr_use_visitor as euv;
use middle::infer;
use middle::mem_categorization as mc;
use middle::ty::{self, Ty};
use util::nodemap::NodeMap;
+use rustc_front::hir;
use syntax::ast;
use syntax::codemap::Span;
-use syntax::visit::{self, Visitor};
+use rustc_front::visit::{self, FnKind, Visitor};
use std::collections::hash_map::Entry;
use std::cmp::Ordering;
tcx: &'a ty::ctxt<'tcx>,
mode: Mode,
qualif: ConstQualif,
- rvalue_borrows: NodeMap<ast::Mutability>
+ rvalue_borrows: NodeMap<hir::Mutability>
}
impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
f(&mut euv::ExprUseVisitor::new(self, &infcx))
}
- fn global_expr(&mut self, mode: Mode, expr: &ast::Expr) -> ConstQualif {
+ fn global_expr(&mut self, mode: Mode, expr: &hir::Expr) -> ConstQualif {
assert!(mode != Mode::Var);
match self.tcx.const_qualif_map.borrow_mut().entry(expr.id) {
Entry::Occupied(entry) => return *entry.get(),
}
fn fn_like(&mut self,
- fk: visit::FnKind,
- fd: &ast::FnDecl,
- b: &ast::Block,
+ fk: FnKind,
+ fd: &hir::FnDecl,
+ b: &hir::Block,
s: Span,
fn_id: ast::NodeId)
-> ConstQualif {
}
let mode = match fk {
- visit::FkItemFn(_, _, _, ast::Constness::Const, _, _) => {
+ FnKind::ItemFn(_, _, _, hir::Constness::Const, _, _) => {
Mode::ConstFn
}
- visit::FkMethod(_, m, _) => {
- if m.constness == ast::Constness::Const {
+ FnKind::Method(_, m, _) => {
+ if m.constness == hir::Constness::Const {
Mode::ConstFn
} else {
Mode::Var
if mode == Mode::ConstFn {
for arg in &fd.inputs {
match arg.pat.node {
- ast::PatIdent(ast::BindByValue(ast::MutImmutable), _, None) => {}
+ hir::PatIdent(hir::BindByValue(hir::MutImmutable), _, None) => {}
_ => {
span_err!(self.tcx.sess, arg.pat.span, E0022,
"arguments of constant functions can only \
/// Returns true if the call is to a const fn or method.
fn handle_const_fn_call(&mut self,
- expr: &ast::Expr,
- def_id: ast::DefId,
+ expr: &hir::Expr,
+ def_id: DefId,
ret_ty: Ty<'tcx>)
-> bool {
if let Some(fn_like) = const_eval::lookup_const_fn_by_id(self.tcx, def_id) {
}
}
- fn record_borrow(&mut self, id: ast::NodeId, mutbl: ast::Mutability) {
+ fn record_borrow(&mut self, id: ast::NodeId, mutbl: hir::Mutability) {
match self.rvalue_borrows.entry(id) {
Entry::Occupied(mut entry) => {
// Merge the two borrows, taking the most demanding
// one, mutability-wise.
- if mutbl == ast::MutMutable {
+ if mutbl == hir::MutMutable {
entry.insert(mutbl);
}
}
}
}
- fn check_static_mut_type(&self, e: &ast::Expr) {
+ fn check_static_mut_type(&self, e: &hir::Expr) {
let node_ty = self.tcx.node_id_to_type(e.id);
let tcontents = node_ty.type_contents(self.tcx);
"mutable statics are not allowed to have {}", suffix);
}
- fn check_static_type(&self, e: &ast::Expr) {
+ fn check_static_type(&self, e: &hir::Expr) {
let ty = self.tcx.node_id_to_type(e.id);
let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, None, false);
let cause = traits::ObligationCause::new(e.span, e.id, traits::SharedStatic);
}
impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
- fn visit_item(&mut self, i: &ast::Item) {
+ fn visit_item(&mut self, i: &hir::Item) {
debug!("visit_item(item={})", self.tcx.map.node_to_string(i.id));
match i.node {
- ast::ItemStatic(_, ast::MutImmutable, ref expr) => {
+ hir::ItemStatic(_, hir::MutImmutable, ref expr) => {
self.check_static_type(&**expr);
self.global_expr(Mode::Static, &**expr);
}
- ast::ItemStatic(_, ast::MutMutable, ref expr) => {
+ hir::ItemStatic(_, hir::MutMutable, ref expr) => {
self.check_static_mut_type(&**expr);
self.global_expr(Mode::StaticMut, &**expr);
}
- ast::ItemConst(_, ref expr) => {
+ hir::ItemConst(_, ref expr) => {
self.global_expr(Mode::Const, &**expr);
}
- ast::ItemEnum(ref enum_definition, _) => {
+ hir::ItemEnum(ref enum_definition, _) => {
for var in &enum_definition.variants {
if let Some(ref ex) = var.node.disr_expr {
self.global_expr(Mode::Const, &**ex);
}
}
- fn visit_trait_item(&mut self, t: &'v ast::TraitItem) {
+ fn visit_trait_item(&mut self, t: &'v hir::TraitItem) {
match t.node {
- ast::ConstTraitItem(_, ref default) => {
+ hir::ConstTraitItem(_, ref default) => {
if let Some(ref expr) = *default {
self.global_expr(Mode::Const, &*expr);
} else {
}
}
- fn visit_impl_item(&mut self, i: &'v ast::ImplItem) {
+ fn visit_impl_item(&mut self, i: &'v hir::ImplItem) {
match i.node {
- ast::ConstImplItem(_, ref expr) => {
+ hir::ConstImplItem(_, ref expr) => {
self.global_expr(Mode::Const, &*expr);
}
_ => self.with_mode(Mode::Var, |v| visit::walk_impl_item(v, i)),
}
fn visit_fn(&mut self,
- fk: visit::FnKind<'v>,
- fd: &'v ast::FnDecl,
- b: &'v ast::Block,
+ fk: FnKind<'v>,
+ fd: &'v hir::FnDecl,
+ b: &'v hir::Block,
s: Span,
fn_id: ast::NodeId) {
self.fn_like(fk, fd, b, s, fn_id);
}
- fn visit_pat(&mut self, p: &ast::Pat) {
+ fn visit_pat(&mut self, p: &hir::Pat) {
match p.node {
- ast::PatLit(ref lit) => {
+ hir::PatLit(ref lit) => {
self.global_expr(Mode::Const, &**lit);
}
- ast::PatRange(ref start, ref end) => {
+ hir::PatRange(ref start, ref end) => {
self.global_expr(Mode::Const, &**start);
self.global_expr(Mode::Const, &**end);
"lower range bound must be less than or equal to upper");
}
None => {
- self.tcx.sess.span_bug(
- start.span, "literals of different types in range pat");
+ self.tcx.sess.delay_span_bug(start.span,
+ "non-constant path in constant expr");
}
}
}
}
}
- fn visit_block(&mut self, block: &ast::Block) {
+ fn visit_block(&mut self, block: &hir::Block) {
// Check all statements in the block
for stmt in &block.stmts {
let span = match stmt.node {
- ast::StmtDecl(ref decl, _) => {
+ hir::StmtDecl(ref decl, _) => {
match decl.node {
- ast::DeclLocal(_) => decl.span,
+ hir::DeclLocal(_) => decl.span,
// Item statements are allowed
- ast::DeclItem(_) => continue
+ hir::DeclItem(_) => continue
}
}
- ast::StmtExpr(ref expr, _) => expr.span,
- ast::StmtSemi(ref semi, _) => semi.span,
- ast::StmtMac(..) => {
- self.tcx.sess.span_bug(stmt.span, "unexpanded statement \
- macro in const?!")
- }
+ hir::StmtExpr(ref expr, _) => expr.span,
+ hir::StmtSemi(ref semi, _) => semi.span,
};
self.add_qualif(ConstQualif::NOT_CONST);
if self.mode != Mode::Var {
visit::walk_block(self, block);
}
- fn visit_expr(&mut self, ex: &ast::Expr) {
+ fn visit_expr(&mut self, ex: &hir::Expr) {
let mut outer = self.qualif;
self.qualif = ConstQualif::empty();
// Special-case some expressions to avoid certain flags bubbling up.
match ex.node {
- ast::ExprCall(ref callee, ref args) => {
+ hir::ExprCall(ref callee, ref args) => {
for arg in args {
self.visit_expr(&**arg)
}
let added = self.qualif - inner;
self.qualif = inner | (added - ConstQualif::NON_ZERO_SIZED);
}
- ast::ExprRepeat(ref element, _) => {
+ hir::ExprRepeat(ref element, _) => {
self.visit_expr(&**element);
// The count is checked elsewhere (typeck).
let count = match node_ty.sty {
self.qualif.remove(ConstQualif::NON_ZERO_SIZED | ConstQualif::PREFER_IN_PLACE);
}
}
- ast::ExprMatch(ref discr, ref arms, _) => {
+ hir::ExprMatch(ref discr, ref arms, _) => {
// Compute the most demanding borrow from all the arms'
// patterns and set that on the discriminator.
let mut borrow = None;
for pat in arms.iter().flat_map(|arm| &arm.pats) {
let pat_borrow = self.rvalue_borrows.remove(&pat.id);
match (borrow, pat_borrow) {
- (None, _) | (_, Some(ast::MutMutable)) => {
+ (None, _) | (_, Some(hir::MutMutable)) => {
borrow = pat_borrow;
}
_ => {}
visit::walk_expr(self, ex);
}
// Division by zero and overflow checking.
- ast::ExprBinary(op, _, _) => {
+ hir::ExprBinary(op, _, _) => {
visit::walk_expr(self, ex);
- let div_or_rem = op.node == ast::BiDiv || op.node == ast::BiRem;
+ let div_or_rem = op.node == hir::BiDiv || op.node == hir::BiRem;
match node_ty.sty {
ty::TyUint(_) | ty::TyInt(_) if div_or_rem => {
if !self.qualif.intersects(ConstQualif::NOT_CONST) {
// Handle borrows on (or inside the autorefs of) this expression.
match self.rvalue_borrows.remove(&ex.id) {
- Some(ast::MutImmutable) => {
+ Some(hir::MutImmutable) => {
// Constants cannot be borrowed if they contain interior mutability as
// it means that our "silent insertion of statics" could change
// initializer values (very bad).
self.add_qualif(ConstQualif::HAS_STATIC_BORROWS);
}
}
- Some(ast::MutMutable) => {
+ Some(hir::MutMutable) => {
// `&mut expr` means expr could be mutated, unless it's zero-sized.
if self.qualif.intersects(ConstQualif::NON_ZERO_SIZED) {
if self.mode == Mode::Var {
/// of a const/static item, it is qualified for promotion
/// instead of producing errors.
fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
- e: &ast::Expr, node_ty: Ty<'tcx>) {
+ e: &hir::Expr, node_ty: Ty<'tcx>) {
match node_ty.sty {
ty::TyStruct(def, _) |
- ty::TyEnum(def, _) if def.has_dtor(v.tcx) => {
+ ty::TyEnum(def, _) if def.has_dtor() => {
v.add_qualif(ConstQualif::NEEDS_DROP);
if v.mode != Mode::Var {
v.tcx.sess.span_err(e.span,
let method_call = ty::MethodCall::expr(e.id);
match e.node {
- ast::ExprUnary(..) |
- ast::ExprBinary(..) |
- ast::ExprIndex(..) if v.tcx.tables.borrow().method_map.contains_key(&method_call) => {
+ hir::ExprUnary(..) |
+ hir::ExprBinary(..) |
+ hir::ExprIndex(..) if v.tcx.tables.borrow().method_map.contains_key(&method_call) => {
v.add_qualif(ConstQualif::NOT_CONST);
if v.mode != Mode::Var {
span_err!(v.tcx.sess, e.span, E0011,
"user-defined operators are not allowed in {}s", v.msg());
}
}
- ast::ExprBox(..) |
- ast::ExprUnary(ast::UnUniq, _) => {
+ hir::ExprBox(..) |
+ hir::ExprUnary(hir::UnUniq, _) => {
v.add_qualif(ConstQualif::NOT_CONST);
if v.mode != Mode::Var {
span_err!(v.tcx.sess, e.span, E0010,
"allocations are not allowed in {}s", v.msg());
}
}
- ast::ExprUnary(op, ref inner) => {
+ hir::ExprUnary(op, ref inner) => {
match v.tcx.node_id_to_type(inner.id).sty {
ty::TyRawPtr(_) => {
- assert!(op == ast::UnDeref);
+ assert!(op == hir::UnDeref);
v.add_qualif(ConstQualif::NOT_CONST);
if v.mode != Mode::Var {
_ => {}
}
}
- ast::ExprBinary(op, ref lhs, _) => {
+ hir::ExprBinary(op, ref lhs, _) => {
match v.tcx.node_id_to_type(lhs.id).sty {
ty::TyRawPtr(_) => {
- assert!(op.node == ast::BiEq || op.node == ast::BiNe ||
- op.node == ast::BiLe || op.node == ast::BiLt ||
- op.node == ast::BiGe || op.node == ast::BiGt);
+ assert!(op.node == hir::BiEq || op.node == hir::BiNe ||
+ op.node == hir::BiLe || op.node == hir::BiLt ||
+ op.node == hir::BiGe || op.node == hir::BiGt);
v.add_qualif(ConstQualif::NOT_CONST);
if v.mode != Mode::Var {
_ => {}
}
}
- ast::ExprCast(ref from, _) => {
+ hir::ExprCast(ref from, _) => {
debug!("Checking const cast(id={})", from.id);
match v.tcx.cast_kinds.borrow().get(&from.id) {
None => v.tcx.sess.span_bug(e.span, "no kind for cast"),
_ => {}
}
}
- ast::ExprPath(..) => {
+ hir::ExprPath(..) => {
let def = v.tcx.def_map.borrow().get(&e.id).map(|d| d.full_def());
match def {
Some(def::DefVariant(_, _, _)) => {
}
}
}
- ast::ExprCall(ref callee, _) => {
+ hir::ExprCall(ref callee, _) => {
let mut callee = &**callee;
loop {
callee = match callee.node {
- ast::ExprParen(ref inner) => &**inner,
- ast::ExprBlock(ref block) => match block.expr {
+ hir::ExprParen(ref inner) => &**inner,
+ hir::ExprBlock(ref block) => match block.expr {
Some(ref tail) => &**tail,
None => break
},
}
}
}
- ast::ExprMethodCall(..) => {
+ hir::ExprMethodCall(..) => {
let method = v.tcx.tables.borrow().method_map[&method_call];
let is_const = match v.tcx.impl_or_trait_item(method.def_id).container() {
ty::ImplContainer(_) => v.handle_const_fn_call(e, method.def_id, node_ty),
}
}
}
- ast::ExprStruct(..) => {
+ hir::ExprStruct(..) => {
let did = v.tcx.def_map.borrow().get(&e.id).map(|def| def.def_id());
if did == v.tcx.lang_items.unsafe_cell_type() {
v.add_qualif(ConstQualif::MUTABLE_MEM);
}
}
- ast::ExprLit(_) |
- ast::ExprAddrOf(..) => {
+ hir::ExprLit(_) |
+ hir::ExprAddrOf(..) => {
v.add_qualif(ConstQualif::NON_ZERO_SIZED);
}
- ast::ExprRepeat(..) => {
+ hir::ExprRepeat(..) => {
v.add_qualif(ConstQualif::PREFER_IN_PLACE);
}
- ast::ExprClosure(..) => {
+ hir::ExprClosure(..) => {
// Paths in constant contexts cannot refer to local variables,
// as there are none, and thus closures can't have upvars there.
if v.tcx.with_freevars(e.id, |fv| !fv.is_empty()) {
}
}
- ast::ExprBlock(_) |
- ast::ExprIndex(..) |
- ast::ExprField(..) |
- ast::ExprTupField(..) |
- ast::ExprVec(_) |
- ast::ExprParen(..) |
- ast::ExprTup(..) => {}
+ hir::ExprBlock(_) |
+ hir::ExprIndex(..) |
+ hir::ExprField(..) |
+ hir::ExprTupField(..) |
+ hir::ExprVec(_) |
+ hir::ExprParen(..) |
+ hir::ExprTup(..) => {}
// Conditional control flow (possible to implement).
- ast::ExprMatch(..) |
- ast::ExprIf(..) |
- ast::ExprIfLet(..) |
+ hir::ExprMatch(..) |
+ hir::ExprIf(..) |
// Loops (not very meaningful in constants).
- ast::ExprWhile(..) |
- ast::ExprWhileLet(..) |
- ast::ExprForLoop(..) |
- ast::ExprLoop(..) |
+ hir::ExprWhile(..) |
+ hir::ExprLoop(..) |
// More control flow (also not very meaningful).
- ast::ExprBreak(_) |
- ast::ExprAgain(_) |
- ast::ExprRet(_) |
+ hir::ExprBreak(_) |
+ hir::ExprAgain(_) |
+ hir::ExprRet(_) |
// Miscellaneous expressions that could be implemented.
- ast::ExprRange(..) |
+ hir::ExprRange(..) |
// Expressions with side-effects.
- ast::ExprAssign(..) |
- ast::ExprAssignOp(..) |
- ast::ExprInlineAsm(_) |
- ast::ExprMac(_) => {
+ hir::ExprAssign(..) |
+ hir::ExprAssignOp(..) |
+ hir::ExprInlineAsm(_) => {
v.add_qualif(ConstQualif::NOT_CONST);
if v.mode != Mode::Var {
span_err!(v.tcx.sess, e.span, E0019,
}
/// Check the adjustments of an expression
-fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &ast::Expr) {
+fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr) {
match v.tcx.tables.borrow().adjustments.get(&e.id) {
- None | Some(&ty::AdjustReifyFnPointer) | Some(&ty::AdjustUnsafeFnPointer) => {}
- Some(&ty::AdjustDerefRef(ty::AutoDerefRef { autoderefs, .. })) => {
+ None |
+ Some(&ty::adjustment::AdjustReifyFnPointer) |
+ Some(&ty::adjustment::AdjustUnsafeFnPointer) => {}
+
+ Some(&ty::adjustment::AdjustDerefRef(
+ ty::adjustment::AutoDerefRef { autoderefs, .. }
+ )) => {
if (0..autoderefs as u32).any(|autoderef| {
v.tcx.is_overloaded_autoderef(e.id, autoderef)
}) {
break;
}
let mutbl = bk.to_mutbl_lossy();
- if mutbl == ast::MutMutable && self.mode == Mode::StaticMut {
+ if mutbl == hir::MutMutable && self.mode == Mode::StaticMut {
// Mutable slices are the only `&mut` allowed in
// globals, but only in `static mut`, nowhere else.
// FIXME: This exception is really weird... there isn't
_mode: euv::MutateMode) {}
fn matched_pat(&mut self,
- _: &ast::Pat,
+ _: &hir::Pat,
_: mc::cmt,
_: euv::MatchMode) {}
fn consume_pat(&mut self,
- _consume_pat: &ast::Pat,
+ _consume_pat: &hir::Pat,
_cmt: mc::cmt,
_mode: euv::ConsumeMode) {}
}