mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-27 01:04:03 +00:00
Remove one dependence on typeck from const_eval.
This commit is contained in:
parent
00ca861f9d
commit
55470abe72
@ -59,6 +59,7 @@ pub mod back {
|
||||
}
|
||||
|
||||
pub mod middle {
|
||||
pub mod astconv_util;
|
||||
pub mod astencode;
|
||||
pub mod borrowck;
|
||||
pub mod cfg;
|
||||
|
89
src/librustc/middle/astconv_util.rs
Normal file
89
src/librustc/middle/astconv_util.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<Ty<'tcx>> {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
@ -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<const_val, St
|
||||
// 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 = ty::expr_ty_opt(tcx, e)
|
||||
.or_else(|| astconv::ast_ty_to_prim_ty(tcx, &**target_ty))
|
||||
.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")
|
||||
|
@ -46,6 +46,8 @@
|
||||
//! Note that the self region for the `foo` defaulted to `&` in the first
|
||||
//! case but `&a` in the second. Basically, defaults that appear inside
|
||||
//! an rptr (`&r.T`) use the region `r` that appears in the rptr.
|
||||
|
||||
use middle::astconv_util::{ast_ty_to_prim_ty, check_path_args, NO_TPS, NO_REGIONS};
|
||||
use middle::const_eval;
|
||||
use middle::def;
|
||||
use middle::resolve_lifetime as rl;
|
||||
@ -553,74 +555,6 @@ pub fn ast_path_to_ty_relaxed<'tcx,AC,RS>(
|
||||
}
|
||||
}
|
||||
|
||||
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<Ty<'tcx>> {
|
||||
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>(
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user