]> git.proxmox.com Git - rustc.git/blame - src/librustc/middle/const_val.rs
New upstream version 1.28.0~beta.14+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
54a0048b 11use hir::def_id::DefId;
94b46f34 12use ty;
8bb4bdeb 13use ty::subst::Substs;
94b46f34
XL
14use ty::query::TyCtxtAt;
15use mir::interpret::ConstValue;
0531ce1d 16use errors::DiagnosticBuilder;
8bb4bdeb 17
cc61c64b 18use graphviz::IntoCow;
cc61c64b 19use syntax_pos::Span;
94b46f34 20use syntax::ast;
54a0048b 21
cc61c64b 22use std::borrow::Cow;
0531ce1d 23use rustc_data_structures::sync::Lrc;
cc61c64b 24
ea8adc8c 25pub type EvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ConstEvalErr<'tcx>>;
32a655c1 26
94b46f34 27#[derive(Copy, Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq, Ord, PartialOrd)]
8bb4bdeb 28pub enum ConstVal<'tcx> {
ea8adc8c 29 Unevaluated(DefId, &'tcx Substs<'tcx>),
94b46f34 30 Value(ConstValue<'tcx>),
ea8adc8c 31}
8bb4bdeb 32
94b46f34 33#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
cc61c64b
XL
34pub struct ConstEvalErr<'tcx> {
35 pub span: Span,
0531ce1d 36 pub kind: Lrc<ErrKind<'tcx>>,
cc61c64b
XL
37}
38
94b46f34 39#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
cc61c64b 40pub enum ErrKind<'tcx> {
cc61c64b 41
94b46f34 42 CouldNotResolve,
ff7c6d11
XL
43 TypeckError,
44 CheckMatchError,
0531ce1d
XL
45 Miri(::mir::interpret::EvalError<'tcx>, Vec<FrameInfo>),
46}
47
94b46f34 48#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
0531ce1d
XL
49pub struct FrameInfo {
50 pub span: Span,
51 pub location: String,
94b46f34 52 pub lint_root: Option<ast::NodeId>,
cc61c64b
XL
53}
54
cc61c64b 55#[derive(Clone, Debug)]
0531ce1d 56pub enum ConstEvalErrDescription<'a, 'tcx: 'a> {
cc61c64b 57 Simple(Cow<'a, str>),
0531ce1d 58 Backtrace(&'a ::mir::interpret::EvalError<'tcx>, &'a [FrameInfo]),
cc61c64b
XL
59}
60
0531ce1d 61impl<'a, 'tcx> ConstEvalErrDescription<'a, 'tcx> {
cc61c64b
XL
62 /// Return a one-line description of the error, for lints and such
63 pub fn into_oneline(self) -> Cow<'a, str> {
64 match self {
65 ConstEvalErrDescription::Simple(simple) => simple,
0531ce1d 66 ConstEvalErrDescription::Backtrace(miri, _) => format!("{}", miri).into_cow(),
cc61c64b
XL
67 }
68 }
69}
70
71impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
0531ce1d 72 pub fn description(&'a self) -> ConstEvalErrDescription<'a, 'tcx> {
cc61c64b
XL
73 use self::ErrKind::*;
74 use self::ConstEvalErrDescription::*;
75
76 macro_rules! simple {
77 ($msg:expr) => ({ Simple($msg.into_cow()) });
78 ($fmt:expr, $($arg:tt)+) => ({
79 Simple(format!($fmt, $($arg)+).into_cow())
80 })
81 }
82
0531ce1d 83 match *self.kind {
94b46f34 84 CouldNotResolve => simple!("could not resolve"),
cc61c64b 85 TypeckError => simple!("type-checking failed"),
ff7c6d11 86 CheckMatchError => simple!("match-checking failed"),
0531ce1d 87 Miri(ref err, ref trace) => Backtrace(err, trace),
cc61c64b
XL
88 }
89 }
90
91 pub fn struct_error(&self,
94b46f34
XL
92 tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
93 message: &str)
94 -> Option<DiagnosticBuilder<'tcx>>
cc61c64b 95 {
94b46f34 96 self.struct_generic(tcx, message, None, true)
cc61c64b
XL
97 }
98
94b46f34
XL
99 pub fn report_as_error(&self,
100 tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
101 message: &str
102 ) {
103 let err = self.struct_generic(tcx, message, None, true);
104 if let Some(mut err) = err {
105 err.emit();
cc61c64b 106 }
94b46f34 107 }
cc61c64b 108
94b46f34
XL
109 pub fn report_as_lint(&self,
110 tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
111 message: &str,
112 lint_root: ast::NodeId,
113 ) {
114 let lint = self.struct_generic(
115 tcx,
116 message,
117 Some(lint_root),
118 false,
119 );
120 if let Some(mut lint) = lint {
121 lint.emit();
cc61c64b
XL
122 }
123 }
124
94b46f34
XL
125 fn struct_generic(
126 &self,
127 tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
128 message: &str,
129 lint_root: Option<ast::NodeId>,
130 as_err: bool,
131 ) -> Option<DiagnosticBuilder<'tcx>> {
132 let (msg, frames): (_, &[_]) = match *self.kind {
133 ErrKind::TypeckError | ErrKind::CheckMatchError => return None,
134 ErrKind::Miri(ref miri, ref frames) => {
0531ce1d
XL
135 match miri.kind {
136 ::mir::interpret::EvalErrorKind::TypeckError |
94b46f34
XL
137 ::mir::interpret::EvalErrorKind::Layout(_) => return None,
138 ::mir::interpret::EvalErrorKind::ReferencedConstant(ref inner) => {
139 inner.struct_generic(tcx, "referenced constant", lint_root, as_err)?.emit();
140 (miri.to_string(), frames)
141 },
142 _ => (miri.to_string(), frames),
0531ce1d
XL
143 }
144 }
94b46f34
XL
145 _ => (self.description().into_oneline().to_string(), &[]),
146 };
147 trace!("reporting const eval failure at {:?}", self.span);
148 let mut err = if as_err {
149 struct_error(tcx, message)
150 } else {
151 let node_id = frames
152 .iter()
153 .rev()
154 .filter_map(|frame| frame.lint_root)
155 .next()
156 .or(lint_root)
157 .expect("some part of a failing const eval must be local");
158 tcx.struct_span_lint_node(
159 ::rustc::lint::builtin::CONST_ERR,
160 node_id,
161 tcx.span,
162 message,
163 )
164 };
165 err.span_label(self.span, msg);
166 for FrameInfo { span, location, .. } in frames {
167 err.span_label(*span, format!("inside call to `{}`", location));
cc61c64b 168 }
94b46f34 169 Some(err)
cc61c64b
XL
170 }
171}
0531ce1d
XL
172
173pub fn struct_error<'a, 'gcx, 'tcx>(
94b46f34 174 tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
0531ce1d 175 msg: &str,
94b46f34
XL
176) -> DiagnosticBuilder<'tcx> {
177 struct_span_err!(tcx.sess, tcx.span, E0080, "{}", msg)
0531ce1d 178}