]> git.proxmox.com Git - rustc.git/blame - src/librustc/middle/const_val.rs
New upstream version 1.25.0+dfsg1
[rustc.git] / src / librustc / middle / const_val.rs
CommitLineData
54a0048b
SL
1// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
cc61c64b
XL
11pub use rustc_const_math::ConstInt;
12
54a0048b 13use hir::def_id::DefId;
3b2f2976 14use ty::{self, TyCtxt, layout};
8bb4bdeb 15use ty::subst::Substs;
54a0048b 16use rustc_const_math::*;
8bb4bdeb 17
cc61c64b
XL
18use graphviz::IntoCow;
19use errors::DiagnosticBuilder;
ea8adc8c 20use serialize::{self, Encodable, Encoder, Decodable, Decoder};
cc61c64b
XL
21use syntax::symbol::InternedString;
22use syntax::ast;
23use syntax_pos::Span;
54a0048b 24
cc61c64b 25use std::borrow::Cow;
cc61c64b 26
ea8adc8c 27pub type EvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ConstEvalErr<'tcx>>;
32a655c1 28
ea8adc8c 29#[derive(Copy, Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq)]
8bb4bdeb 30pub enum ConstVal<'tcx> {
54a0048b 31 Integral(ConstInt),
ea8adc8c 32 Float(ConstFloat),
54a0048b 33 Str(InternedString),
ea8adc8c 34 ByteStr(ByteArray<'tcx>),
54a0048b 35 Bool(bool),
cc61c64b
XL
36 Char(char),
37 Variant(DefId),
8bb4bdeb 38 Function(DefId, &'tcx Substs<'tcx>),
ea8adc8c
XL
39 Aggregate(ConstAggregate<'tcx>),
40 Unevaluated(DefId, &'tcx Substs<'tcx>),
54a0048b
SL
41}
42
ea8adc8c
XL
43#[derive(Copy, Clone, Debug, Hash, RustcEncodable, Eq, PartialEq)]
44pub struct ByteArray<'tcx> {
45 pub data: &'tcx [u8],
46}
47
48impl<'tcx> serialize::UseSpecializedDecodable for ByteArray<'tcx> {}
49
50#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
51pub enum ConstAggregate<'tcx> {
52 Struct(&'tcx [(ast::Name, &'tcx ty::Const<'tcx>)]),
53 Tuple(&'tcx [&'tcx ty::Const<'tcx>]),
54 Array(&'tcx [&'tcx ty::Const<'tcx>]),
55 Repeat(&'tcx ty::Const<'tcx>, u64),
56}
57
58impl<'tcx> Encodable for ConstAggregate<'tcx> {
59 fn encode<S: Encoder>(&self, _: &mut S) -> Result<(), S::Error> {
60 bug!("should never encode ConstAggregate::{:?}", self)
61 }
62}
63
64impl<'tcx> Decodable for ConstAggregate<'tcx> {
65 fn decode<D: Decoder>(_: &mut D) -> Result<Self, D::Error> {
66 bug!("should never decode ConstAggregate")
54a0048b 67 }
ea8adc8c 68}
8bb4bdeb 69
ea8adc8c 70impl<'tcx> ConstVal<'tcx> {
8bb4bdeb
XL
71 pub fn to_const_int(&self) -> Option<ConstInt> {
72 match *self {
73 ConstVal::Integral(i) => Some(i),
74 ConstVal::Bool(b) => Some(ConstInt::U8(b as u8)),
75 ConstVal::Char(ch) => Some(ConstInt::U32(ch as u32)),
76 _ => None
77 }
78 }
54a0048b 79}
cc61c64b
XL
80
81#[derive(Clone, Debug)]
82pub struct ConstEvalErr<'tcx> {
83 pub span: Span,
84 pub kind: ErrKind<'tcx>,
85}
86
87#[derive(Clone, Debug)]
88pub enum ErrKind<'tcx> {
89 CannotCast,
90 MissingStructField,
cc61c64b
XL
91
92 NonConstPath,
93 UnimplementedConstVal(&'static str),
94 ExpectedConstTuple,
95 ExpectedConstStruct,
96 IndexedNonVec,
97 IndexNotUsize,
98 IndexOutOfBounds { len: u64, index: u64 },
99
100 MiscBinaryOp,
101 MiscCatchAll,
102
103 IndexOpFeatureGated,
104 Math(ConstMathErr),
3b2f2976 105 LayoutError(layout::LayoutError<'tcx>),
cc61c64b
XL
106
107 ErroneousReferencedConstant(Box<ConstEvalErr<'tcx>>),
108
ff7c6d11
XL
109 TypeckError,
110 CheckMatchError,
cc61c64b
XL
111}
112
113impl<'tcx> From<ConstMathErr> for ErrKind<'tcx> {
114 fn from(err: ConstMathErr) -> ErrKind<'tcx> {
115 match err {
116 ConstMathErr::UnsignedNegation => ErrKind::TypeckError,
117 _ => ErrKind::Math(err)
118 }
119 }
120}
121
122#[derive(Clone, Debug)]
123pub enum ConstEvalErrDescription<'a> {
124 Simple(Cow<'a, str>),
125}
126
127impl<'a> ConstEvalErrDescription<'a> {
128 /// Return a one-line description of the error, for lints and such
129 pub fn into_oneline(self) -> Cow<'a, str> {
130 match self {
131 ConstEvalErrDescription::Simple(simple) => simple,
132 }
133 }
134}
135
136impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
137 pub fn description(&self) -> ConstEvalErrDescription {
138 use self::ErrKind::*;
139 use self::ConstEvalErrDescription::*;
140
141 macro_rules! simple {
142 ($msg:expr) => ({ Simple($msg.into_cow()) });
143 ($fmt:expr, $($arg:tt)+) => ({
144 Simple(format!($fmt, $($arg)+).into_cow())
145 })
146 }
147
148 match self.kind {
149 CannotCast => simple!("can't cast this type"),
cc61c64b
XL
150 MissingStructField => simple!("nonexistent struct field"),
151 NonConstPath => simple!("non-constant path in constant expression"),
152 UnimplementedConstVal(what) =>
153 simple!("unimplemented constant expression: {}", what),
154 ExpectedConstTuple => simple!("expected constant tuple"),
155 ExpectedConstStruct => simple!("expected constant struct"),
156 IndexedNonVec => simple!("indexing is only supported for arrays"),
157 IndexNotUsize => simple!("indices must be of type `usize`"),
158 IndexOutOfBounds { len, index } => {
159 simple!("index out of bounds: the len is {} but the index is {}",
160 len, index)
161 }
162
163 MiscBinaryOp => simple!("bad operands for binary"),
164 MiscCatchAll => simple!("unsupported constant expr"),
165 IndexOpFeatureGated => simple!("the index operation on const values is unstable"),
166 Math(ref err) => Simple(err.description().into_cow()),
3b2f2976 167 LayoutError(ref err) => Simple(err.to_string().into_cow()),
cc61c64b
XL
168
169 ErroneousReferencedConstant(_) => simple!("could not evaluate referenced constant"),
170
171 TypeckError => simple!("type-checking failed"),
ff7c6d11 172 CheckMatchError => simple!("match-checking failed"),
cc61c64b
XL
173 }
174 }
175
176 pub fn struct_error(&self,
177 tcx: TyCtxt<'a, 'gcx, 'tcx>,
178 primary_span: Span,
179 primary_kind: &str)
180 -> DiagnosticBuilder<'gcx>
181 {
182 let mut err = self;
183 while let &ConstEvalErr {
184 kind: ErrKind::ErroneousReferencedConstant(box ref i_err), ..
185 } = err {
186 err = i_err;
187 }
188
189 let mut diag = struct_span_err!(tcx.sess, err.span, E0080, "constant evaluation error");
190 err.note(tcx, primary_span, primary_kind, &mut diag);
191 diag
192 }
193
194 pub fn note(&self,
195 _tcx: TyCtxt<'a, 'gcx, 'tcx>,
196 primary_span: Span,
197 primary_kind: &str,
198 diag: &mut DiagnosticBuilder)
199 {
200 match self.description() {
201 ConstEvalErrDescription::Simple(message) => {
7cac9316 202 diag.span_label(self.span, message);
cc61c64b
XL
203 }
204 }
205
206 if !primary_span.contains(self.span) {
207 diag.span_note(primary_span,
208 &format!("for {} here", primary_kind));
209 }
210 }
211
212 pub fn report(&self,
213 tcx: TyCtxt<'a, 'gcx, 'tcx>,
214 primary_span: Span,
215 primary_kind: &str)
216 {
ff7c6d11
XL
217 match self.kind {
218 ErrKind::TypeckError | ErrKind::CheckMatchError => return,
219 _ => {}
cc61c64b
XL
220 }
221 self.struct_error(tcx, primary_span, primary_kind).emit();
222 }
223}