rustc_const_eval: always demand typeck_tables for evaluating constants.
This commit is contained in:
parent
c832e6f327
commit
e7a48821c0
60 changed files with 706 additions and 1222 deletions
|
|
@ -390,44 +390,6 @@ RFC. It is, however, [currently unimplemented][iss15872].
|
|||
[iss15872]: https://github.com/rust-lang/rust/issues/15872
|
||||
"##,
|
||||
|
||||
E0109: r##"
|
||||
You tried to give a type parameter to a type which doesn't need it. Erroneous
|
||||
code example:
|
||||
|
||||
```compile_fail,E0109
|
||||
type X = u32<i32>; // error: type parameters are not allowed on this type
|
||||
```
|
||||
|
||||
Please check that you used the correct type and recheck its definition. Perhaps
|
||||
it doesn't need the type parameter.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
type X = u32; // this compiles
|
||||
```
|
||||
|
||||
Note that type parameters for enum-variant constructors go after the variant,
|
||||
not after the enum (Option::None::<u32>, not Option::<u32>::None).
|
||||
"##,
|
||||
|
||||
E0110: r##"
|
||||
You tried to give a lifetime parameter to a type which doesn't need it.
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0110
|
||||
type X = u32<'static>; // error: lifetime parameters are not allowed on
|
||||
// this type
|
||||
```
|
||||
|
||||
Please check that the correct type was used and recheck its definition; perhaps
|
||||
it doesn't need the lifetime parameter. Example:
|
||||
|
||||
```
|
||||
type X = u32; // ok!
|
||||
```
|
||||
"##,
|
||||
|
||||
E0133: r##"
|
||||
Unsafe code was used outside of an unsafe function or block.
|
||||
|
||||
|
|
@ -627,41 +589,6 @@ attributes:
|
|||
See also https://doc.rust-lang.org/book/no-stdlib.html
|
||||
"##,
|
||||
|
||||
E0229: r##"
|
||||
An associated type binding was done outside of the type parameter declaration
|
||||
and `where` clause. Erroneous code example:
|
||||
|
||||
```compile_fail,E0229
|
||||
pub trait Foo {
|
||||
type A;
|
||||
fn boo(&self) -> <Self as Foo>::A;
|
||||
}
|
||||
|
||||
struct Bar;
|
||||
|
||||
impl Foo for isize {
|
||||
type A = usize;
|
||||
fn boo(&self) -> usize { 42 }
|
||||
}
|
||||
|
||||
fn baz<I>(x: &<I as Foo<A=Bar>>::A) {}
|
||||
// error: associated type bindings are not allowed here
|
||||
```
|
||||
|
||||
To solve this error, please move the type bindings in the type parameter
|
||||
declaration:
|
||||
|
||||
```ignore
|
||||
fn baz<I: Foo<A=Bar>>(x: &<I as Foo>::A) {} // ok!
|
||||
```
|
||||
|
||||
Or in the `where` clause:
|
||||
|
||||
```ignore
|
||||
fn baz<I>(x: &<I as Foo>::A) where I: Foo<A=Bar> {}
|
||||
```
|
||||
"##,
|
||||
|
||||
E0261: r##"
|
||||
When using a lifetime like `'a` in a type, it must be declared before being
|
||||
used.
|
||||
|
|
|
|||
|
|
@ -76,7 +76,6 @@ pub mod infer;
|
|||
pub mod lint;
|
||||
|
||||
pub mod middle {
|
||||
pub mod astconv_util;
|
||||
pub mod expr_use_visitor;
|
||||
pub mod const_val;
|
||||
pub mod cstore;
|
||||
|
|
|
|||
|
|
@ -1,83 +0,0 @@
|
|||
// 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 hir;
|
||||
use hir::def::Def;
|
||||
use ty::{Ty, TyCtxt};
|
||||
|
||||
use syntax_pos::Span;
|
||||
|
||||
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
pub fn prohibit_type_params(self, segments: &[hir::PathSegment]) {
|
||||
for segment in segments {
|
||||
for typ in segment.parameters.types() {
|
||||
struct_span_err!(self.sess, typ.span, E0109,
|
||||
"type parameters are not allowed on this type")
|
||||
.span_label(typ.span, &format!("type parameter not allowed"))
|
||||
.emit();
|
||||
break;
|
||||
}
|
||||
for lifetime in segment.parameters.lifetimes() {
|
||||
struct_span_err!(self.sess, lifetime.span, E0110,
|
||||
"lifetime parameters are not allowed on this type")
|
||||
.span_label(lifetime.span,
|
||||
&format!("lifetime parameter not allowed on this type"))
|
||||
.emit();
|
||||
break;
|
||||
}
|
||||
for binding in segment.parameters.bindings() {
|
||||
self.prohibit_projection(binding.span);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn prohibit_projection(self, span: Span)
|
||||
{
|
||||
let mut err = struct_span_err!(self.sess, span, E0229,
|
||||
"associated type bindings are not allowed here");
|
||||
err.span_label(span, &format!("associate type not allowed here")).emit();
|
||||
}
|
||||
|
||||
pub fn prim_ty_to_ty(self,
|
||||
segments: &[hir::PathSegment],
|
||||
nty: hir::PrimTy)
|
||||
-> Ty<'tcx> {
|
||||
self.prohibit_type_params(segments);
|
||||
match nty {
|
||||
hir::TyBool => self.types.bool,
|
||||
hir::TyChar => self.types.char,
|
||||
hir::TyInt(it) => self.mk_mach_int(it),
|
||||
hir::TyUint(uit) => self.mk_mach_uint(uit),
|
||||
hir::TyFloat(ft) => self.mk_mach_float(ft),
|
||||
hir::TyStr => self.mk_str()
|
||||
}
|
||||
}
|
||||
|
||||
/// If a type in the AST is a primitive type, return the ty::Ty corresponding
|
||||
/// to it.
|
||||
pub fn ast_ty_to_prim_ty(self, ast_ty: &hir::Ty) -> Option<Ty<'tcx>> {
|
||||
if let hir::TyPath(hir::QPath::Resolved(None, ref path)) = ast_ty.node {
|
||||
if let Def::PrimTy(nty) = path.def {
|
||||
Some(self.prim_ty_to_ty(&path.segments, nty))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -12,28 +12,30 @@ use syntax::symbol::InternedString;
|
|||
use syntax::ast;
|
||||
use std::rc::Rc;
|
||||
use hir::def_id::DefId;
|
||||
use ty::subst::Substs;
|
||||
use rustc_const_math::*;
|
||||
|
||||
use self::ConstVal::*;
|
||||
pub use rustc_const_math::ConstInt;
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
#[derive(Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq)]
|
||||
pub enum ConstVal {
|
||||
pub enum ConstVal<'tcx> {
|
||||
Float(ConstFloat),
|
||||
Integral(ConstInt),
|
||||
Str(InternedString),
|
||||
ByteStr(Rc<Vec<u8>>),
|
||||
Bool(bool),
|
||||
Function(DefId),
|
||||
Struct(BTreeMap<ast::Name, ConstVal>),
|
||||
Tuple(Vec<ConstVal>),
|
||||
Array(Vec<ConstVal>),
|
||||
Repeat(Box<ConstVal>, u64),
|
||||
Function(DefId, &'tcx Substs<'tcx>),
|
||||
Struct(BTreeMap<ast::Name, ConstVal<'tcx>>),
|
||||
Tuple(Vec<ConstVal<'tcx>>),
|
||||
Array(Vec<ConstVal<'tcx>>),
|
||||
Repeat(Box<ConstVal<'tcx>>, u64),
|
||||
Char(char),
|
||||
}
|
||||
|
||||
impl ConstVal {
|
||||
impl<'tcx> ConstVal<'tcx> {
|
||||
pub fn description(&self) -> &'static str {
|
||||
match *self {
|
||||
Float(f) => f.description(),
|
||||
|
|
@ -43,7 +45,7 @@ impl ConstVal {
|
|||
Bool(_) => "boolean",
|
||||
Struct(_) => "struct",
|
||||
Tuple(_) => "tuple",
|
||||
Function(_) => "function definition",
|
||||
Function(..) => "function definition",
|
||||
Array(..) => "array",
|
||||
Repeat(..) => "repeat",
|
||||
Char(..) => "char",
|
||||
|
|
@ -53,8 +55,7 @@ impl ConstVal {
|
|||
pub fn to_const_int(&self) -> Option<ConstInt> {
|
||||
match *self {
|
||||
ConstVal::Integral(i) => Some(i),
|
||||
ConstVal::Bool(true) => Some(ConstInt::Infer(1)),
|
||||
ConstVal::Bool(false) => Some(ConstInt::Infer(0)),
|
||||
ConstVal::Bool(b) => Some(ConstInt::U8(b as u8)),
|
||||
ConstVal::Char(ch) => Some(ConstInt::U32(ch as u32)),
|
||||
_ => None
|
||||
}
|
||||
|
|
|
|||
|
|
@ -542,7 +542,7 @@ impl<'tcx> Terminator<'tcx> {
|
|||
impl<'tcx> TerminatorKind<'tcx> {
|
||||
pub fn if_<'a, 'gcx>(tcx: ty::TyCtxt<'a, 'gcx, 'tcx>, cond: Operand<'tcx>,
|
||||
t: BasicBlock, f: BasicBlock) -> TerminatorKind<'tcx> {
|
||||
static BOOL_SWITCH_FALSE: &'static [ConstInt] = &[ConstInt::Infer(0)];
|
||||
static BOOL_SWITCH_FALSE: &'static [ConstInt] = &[ConstInt::U8(0)];
|
||||
TerminatorKind::SwitchInt {
|
||||
discr: cond,
|
||||
switch_ty: tcx.types.bool,
|
||||
|
|
@ -1224,7 +1224,7 @@ pub enum Literal<'tcx> {
|
|||
substs: &'tcx Substs<'tcx>,
|
||||
},
|
||||
Value {
|
||||
value: ConstVal,
|
||||
value: ConstVal<'tcx>,
|
||||
},
|
||||
Promoted {
|
||||
// Index into the `promoted` vector of `Mir`.
|
||||
|
|
@ -1271,7 +1271,7 @@ 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(def_id, _) => write!(fmt, "{}", item_path_str(def_id)),
|
||||
Struct(_) | Tuple(_) | Array(_) | Repeat(..) =>
|
||||
bug!("ConstVal `{:?}` should not be in MIR", const_val),
|
||||
Char(c) => write!(fmt, "{:?}", c),
|
||||
|
|
|
|||
|
|
@ -244,6 +244,10 @@ pub struct TypeckTables<'tcx> {
|
|||
/// Set of trait imports actually used in the method resolution.
|
||||
/// This is used for warning unused imports.
|
||||
pub used_trait_imports: DefIdSet,
|
||||
|
||||
/// If any errors occurred while type-checking this body,
|
||||
/// this field will be set to `true`.
|
||||
pub tainted_by_errors: bool,
|
||||
}
|
||||
|
||||
impl<'tcx> TypeckTables<'tcx> {
|
||||
|
|
@ -262,6 +266,7 @@ impl<'tcx> TypeckTables<'tcx> {
|
|||
cast_kinds: NodeMap(),
|
||||
lints: lint::LintTable::new(),
|
||||
used_trait_imports: DefIdSet(),
|
||||
tainted_by_errors: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ use ty::{self, Ty, TyCtxt, TypeFoldable, ReprOptions};
|
|||
use syntax::ast::{FloatTy, IntTy, UintTy};
|
||||
use syntax::attr;
|
||||
use syntax_pos::DUMMY_SP;
|
||||
use rustc_const_math::ConstInt;
|
||||
|
||||
use std::cmp;
|
||||
use std::fmt;
|
||||
|
|
@ -1183,11 +1182,7 @@ impl<'a, 'gcx, 'tcx> Layout {
|
|||
i64::min_value(),
|
||||
true);
|
||||
for discr in def.discriminants(tcx) {
|
||||
let x = match discr.erase_type() {
|
||||
ConstInt::InferSigned(i) => i as i64,
|
||||
ConstInt::Infer(i) => i as u64 as i64,
|
||||
_ => bug!()
|
||||
};
|
||||
let x = discr.to_u128_unchecked() as i64;
|
||||
if x == 0 { non_zero = false; }
|
||||
if x < min { min = x; }
|
||||
if x > max { max = x; }
|
||||
|
|
|
|||
|
|
@ -381,7 +381,7 @@ define_maps! { <'tcx>
|
|||
|
||||
/// Results of evaluating monomorphic constants embedded in
|
||||
/// other items, such as enum variant explicit discriminants.
|
||||
pub monomorphic_const_eval: MonomorphicConstEval(DefId) -> Result<ConstVal, ()>
|
||||
pub monomorphic_const_eval: MonomorphicConstEval(DefId) -> Result<ConstVal<'tcx>, ()>
|
||||
}
|
||||
|
||||
fn coherent_trait_dep_node((_, def_id): (CrateNum, DefId)) -> DepNode<DefId> {
|
||||
|
|
|
|||
|
|
@ -47,6 +47,35 @@ type Disr = ConstInt;
|
|||
}
|
||||
|
||||
|
||||
macro_rules! typed_literal {
|
||||
($tcx:expr, $ty:expr, $lit:expr) => {
|
||||
match $ty {
|
||||
SignedInt(ast::IntTy::I8) => ConstInt::I8($lit),
|
||||
SignedInt(ast::IntTy::I16) => ConstInt::I16($lit),
|
||||
SignedInt(ast::IntTy::I32) => ConstInt::I32($lit),
|
||||
SignedInt(ast::IntTy::I64) => ConstInt::I64($lit),
|
||||
SignedInt(ast::IntTy::I128) => ConstInt::I128($lit),
|
||||
SignedInt(ast::IntTy::Is) => match $tcx.sess.target.int_type {
|
||||
ast::IntTy::I16 => ConstInt::Isize(ConstIsize::Is16($lit)),
|
||||
ast::IntTy::I32 => ConstInt::Isize(ConstIsize::Is32($lit)),
|
||||
ast::IntTy::I64 => ConstInt::Isize(ConstIsize::Is64($lit)),
|
||||
_ => bug!(),
|
||||
},
|
||||
UnsignedInt(ast::UintTy::U8) => ConstInt::U8($lit),
|
||||
UnsignedInt(ast::UintTy::U16) => ConstInt::U16($lit),
|
||||
UnsignedInt(ast::UintTy::U32) => ConstInt::U32($lit),
|
||||
UnsignedInt(ast::UintTy::U64) => ConstInt::U64($lit),
|
||||
UnsignedInt(ast::UintTy::U128) => ConstInt::U128($lit),
|
||||
UnsignedInt(ast::UintTy::Us) => match $tcx.sess.target.uint_type {
|
||||
ast::UintTy::U16 => ConstInt::Usize(ConstUsize::Us16($lit)),
|
||||
ast::UintTy::U32 => ConstInt::Usize(ConstUsize::Us32($lit)),
|
||||
ast::UintTy::U64 => ConstInt::Usize(ConstUsize::Us64($lit)),
|
||||
_ => bug!(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl IntTypeExt for attr::IntType {
|
||||
fn to_ty<'a, 'gcx, 'tcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
|
||||
match *self {
|
||||
|
|
@ -66,30 +95,7 @@ impl IntTypeExt for attr::IntType {
|
|||
}
|
||||
|
||||
fn initial_discriminant<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Disr {
|
||||
match *self {
|
||||
SignedInt(ast::IntTy::I8) => ConstInt::I8(0),
|
||||
SignedInt(ast::IntTy::I16) => ConstInt::I16(0),
|
||||
SignedInt(ast::IntTy::I32) => ConstInt::I32(0),
|
||||
SignedInt(ast::IntTy::I64) => ConstInt::I64(0),
|
||||
SignedInt(ast::IntTy::I128) => ConstInt::I128(0),
|
||||
SignedInt(ast::IntTy::Is) => match tcx.sess.target.int_type {
|
||||
ast::IntTy::I16 => ConstInt::Isize(ConstIsize::Is16(0)),
|
||||
ast::IntTy::I32 => ConstInt::Isize(ConstIsize::Is32(0)),
|
||||
ast::IntTy::I64 => ConstInt::Isize(ConstIsize::Is64(0)),
|
||||
_ => bug!(),
|
||||
},
|
||||
UnsignedInt(ast::UintTy::U8) => ConstInt::U8(0),
|
||||
UnsignedInt(ast::UintTy::U16) => ConstInt::U16(0),
|
||||
UnsignedInt(ast::UintTy::U32) => ConstInt::U32(0),
|
||||
UnsignedInt(ast::UintTy::U64) => ConstInt::U64(0),
|
||||
UnsignedInt(ast::UintTy::U128) => ConstInt::U128(0),
|
||||
UnsignedInt(ast::UintTy::Us) => match tcx.sess.target.uint_type {
|
||||
ast::UintTy::U16 => ConstInt::Usize(ConstUsize::Us16(0)),
|
||||
ast::UintTy::U32 => ConstInt::Usize(ConstUsize::Us32(0)),
|
||||
ast::UintTy::U64 => ConstInt::Usize(ConstUsize::Us64(0)),
|
||||
_ => bug!(),
|
||||
},
|
||||
}
|
||||
typed_literal!(tcx, *self, 0)
|
||||
}
|
||||
|
||||
fn assert_ty_matches(&self, val: Disr) {
|
||||
|
|
@ -114,7 +120,7 @@ impl IntTypeExt for attr::IntType {
|
|||
-> Option<Disr> {
|
||||
if let Some(val) = val {
|
||||
self.assert_ty_matches(val);
|
||||
(val + ConstInt::Infer(1)).ok()
|
||||
(val + typed_literal!(tcx, *self, 1)).ok()
|
||||
} else {
|
||||
Some(self.initial_discriminant(tcx))
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue