From 55470abe720114bd93e55bc7fa79d454186e9f02 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 26 Nov 2014 04:52:02 -0500 Subject: [PATCH] Remove one dependence on typeck from const_eval. --- src/librustc/lib.rs | 1 + src/librustc/middle/astconv_util.rs | 89 +++++++++++++++++++++++++ src/librustc/middle/const_eval.rs | 14 +--- src/librustc/middle/typeck/astconv.rs | 70 +------------------ src/librustc/middle/typeck/check/mod.rs | 44 ++++++------ 5 files changed, 119 insertions(+), 99 deletions(-) create mode 100644 src/librustc/middle/astconv_util.rs diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index d8da4df08bc..5637f5d1755 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -59,6 +59,7 @@ pub mod back { } pub mod middle { + pub mod astconv_util; pub mod astencode; pub mod borrowck; pub mod cfg; diff --git a/src/librustc/middle/astconv_util.rs b/src/librustc/middle/astconv_util.rs new file mode 100644 index 00000000000..6b90bcd60e7 --- /dev/null +++ b/src/librustc/middle/astconv_util.rs @@ -0,0 +1,89 @@ +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/*! + * This module contains a simple utility routine + * used by both `typeck` and `const_eval`. + * Almost certainly this could (and should) be refactored out of existence. + */ + +use middle::def; +use middle::ty::{mod, Ty}; +use syntax::ast; +use util::ppaux::Repr; + +pub const NO_REGIONS: uint = 1; +pub const NO_TPS: uint = 2; + +pub fn check_path_args(tcx: &ty::ctxt, + path: &ast::Path, + flags: uint) { + if (flags & NO_TPS) != 0u { + if path.segments.iter().any(|s| s.parameters.has_types()) { + span_err!(tcx.sess, path.span, E0109, + "type parameters are not allowed on this type"); + } + } + + if (flags & NO_REGIONS) != 0u { + if path.segments.iter().any(|s| s.parameters.has_lifetimes()) { + span_err!(tcx.sess, path.span, E0110, + "region parameters are not allowed on this type"); + } + } +} + +pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty) + -> Option> { + match ast_ty.node { + ast::TyPath(ref path, id) => { + let a_def = match tcx.def_map.borrow().get(&id) { + None => { + tcx.sess.span_bug(ast_ty.span, + format!("unbound path {}", + path.repr(tcx)).as_slice()) + } + Some(&d) => d + }; + match a_def { + def::DefPrimTy(nty) => { + match nty { + ast::TyBool => { + check_path_args(tcx, path, NO_TPS | NO_REGIONS); + Some(ty::mk_bool()) + } + ast::TyChar => { + check_path_args(tcx, path, NO_TPS | NO_REGIONS); + Some(ty::mk_char()) + } + ast::TyInt(it) => { + check_path_args(tcx, path, NO_TPS | NO_REGIONS); + Some(ty::mk_mach_int(it)) + } + ast::TyUint(uit) => { + check_path_args(tcx, path, NO_TPS | NO_REGIONS); + Some(ty::mk_mach_uint(uit)) + } + ast::TyFloat(ft) => { + check_path_args(tcx, path, NO_TPS | NO_REGIONS); + Some(ty::mk_mach_float(ft)) + } + ast::TyStr => { + Some(ty::mk_str(tcx)) + } + } + } + _ => None + } + } + _ => None + } +} + diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index d5a292b9f09..43726f55bb9 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -17,8 +17,8 @@ pub use self::constness::*; use metadata::csearch; use middle::{astencode, def}; use middle::pat_util::def_to_path; -use middle::ty::{mod, Ty}; -use middle::typeck::{astconv, check}; +use middle::ty::{mod}; +use middle::astconv_util::{ast_ty_to_prim_ty}; use util::nodemap::DefIdMap; use syntax::ast::{mod, Expr}; @@ -277,14 +277,6 @@ impl<'a, 'tcx> ConstEvalVisitor<'a, 'tcx> { } impl<'a, 'tcx, 'v> Visitor<'v> for ConstEvalVisitor<'a, 'tcx> { - fn visit_ty(&mut self, t: &ast::Ty) { - if let ast::TyFixedLengthVec(_, ref expr) = t.node { - check::check_const_in_type(self.tcx, &**expr, ty::mk_uint()); - } - - visit::walk_ty(self, t); - } - fn visit_expr_post(&mut self, e: &Expr) { self.classify(e); } @@ -504,7 +496,7 @@ pub fn eval_const_expr_partial(tcx: &ty::ctxt, e: &Expr) -> Result( } } -pub const NO_REGIONS: uint = 1; -pub const NO_TPS: uint = 2; - -fn check_path_args(tcx: &ty::ctxt, - path: &ast::Path, - flags: uint) { - if (flags & NO_TPS) != 0u { - if path.segments.iter().any(|s| s.parameters.has_types()) { - span_err!(tcx.sess, path.span, E0109, - "type parameters are not allowed on this type"); - } - } - - if (flags & NO_REGIONS) != 0u { - if path.segments.iter().any(|s| s.parameters.has_lifetimes()) { - span_err!(tcx.sess, path.span, E0110, - "region parameters are not allowed on this type"); - } - } -} - -pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty) - -> Option> { - match ast_ty.node { - ast::TyPath(ref path, id) => { - let a_def = match tcx.def_map.borrow().get(&id) { - None => { - tcx.sess.span_bug(ast_ty.span, - format!("unbound path {}", - path.repr(tcx)).as_slice()) - } - Some(&d) => d - }; - match a_def { - def::DefPrimTy(nty) => { - match nty { - ast::TyBool => { - check_path_args(tcx, path, NO_TPS | NO_REGIONS); - Some(ty::mk_bool()) - } - ast::TyChar => { - check_path_args(tcx, path, NO_TPS | NO_REGIONS); - Some(ty::mk_char()) - } - ast::TyInt(it) => { - check_path_args(tcx, path, NO_TPS | NO_REGIONS); - Some(ty::mk_mach_int(it)) - } - ast::TyUint(uit) => { - check_path_args(tcx, path, NO_TPS | NO_REGIONS); - Some(ty::mk_mach_uint(uit)) - } - ast::TyFloat(ft) => { - check_path_args(tcx, path, NO_TPS | NO_REGIONS); - Some(ty::mk_mach_float(ft)) - } - ast::TyStr => { - Some(ty::mk_str(tcx)) - } - } - } - _ => None - } - } - _ => None - } -} - /// Converts the given AST type to a built-in type. A "built-in type" is, at /// present, either a core numeric type, a string, or `Box`. pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 02106f25304..cacccbda53c 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -361,6 +361,17 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckItemTypesVisitor<'a, 'tcx> { check_item(self.ccx, i); visit::walk_item(self, i); } + + fn visit_ty(&mut self, t: &ast::Ty) { + match t.node { + ast::TyFixedLengthVec(_, ref expr) => { + check_const_in_type(self.ccx, &**expr, ty::mk_uint()); + } + _ => {} + } + + visit::walk_ty(self, t); + } } pub fn check_item_types(ccx: &CrateCtxt) { @@ -4672,25 +4683,18 @@ fn check_block_with_expected<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, /// Checks a constant appearing in a type. At the moment this is just the /// length expression in a fixed-length vector, but someday it might be /// extended to type-level numeric literals. -pub fn check_const_in_type<'tcx>(tcx: &ty::ctxt<'tcx>, - expr: &ast::Expr, - expected_type: Ty<'tcx>) { - // Synthesize a crate context. The trait map is not needed here (though I - // imagine it will be if we have associated statics --pcwalton), so we - // leave it blank. - let ccx = CrateCtxt { - trait_map: NodeMap::new(), - tcx: tcx, - }; - let inh = static_inherited_fields(&ccx); - let fcx = blank_fn_ctxt(&ccx, &inh, ty::FnConverging(expected_type), expr.id); +fn check_const_in_type<'a,'tcx>(ccx: &'a CrateCtxt<'a,'tcx>, + expr: &ast::Expr, + expected_type: Ty<'tcx>) { + let inh = static_inherited_fields(ccx); + let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(expected_type), expr.id); check_const_with_ty(&fcx, expr.span, expr, expected_type); } -pub fn check_const(ccx: &CrateCtxt, - sp: Span, - e: &ast::Expr, - id: ast::NodeId) { +fn check_const(ccx: &CrateCtxt, + sp: Span, + e: &ast::Expr, + id: ast::NodeId) { let inh = static_inherited_fields(ccx); let rty = ty::node_id_to_type(ccx.tcx, id); let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id); @@ -4698,10 +4702,10 @@ pub fn check_const(ccx: &CrateCtxt, check_const_with_ty(&fcx, sp, e, declty); } -pub fn check_const_with_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, - _: Span, - e: &ast::Expr, - declty: Ty<'tcx>) { +fn check_const_with_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, + _: Span, + e: &ast::Expr, + declty: Ty<'tcx>) { // Gather locals in statics (because of block expressions). // This is technically unnecessary because locals in static items are forbidden, // but prevents type checking from blowing up before const checking can properly