]> git.proxmox.com Git - rustc.git/blame - src/librustc/ty/error.rs
New upstream version 1.13.0+dfsg1
[rustc.git] / src / librustc / ty / error.rs
CommitLineData
e9174d1e
SL
1// Copyright 2012-2015 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;
54a0048b
SL
12use infer::type_variable;
13use ty::{self, BoundRegion, Region, Ty, TyCtxt};
e9174d1e
SL
14
15use std::fmt;
16use syntax::abi;
b039eaaf 17use syntax::ast::{self, Name};
3157f602
XL
18use errors::DiagnosticBuilder;
19use syntax_pos::Span;
e9174d1e 20
54a0048b 21use hir;
e9174d1e
SL
22
23#[derive(Clone, Copy, Debug)]
24pub struct ExpectedFound<T> {
25 pub expected: T,
26 pub found: T
27}
28
29// Data structures used in type unification
30#[derive(Clone, Debug)]
31pub enum TypeError<'tcx> {
32 Mismatch,
33 UnsafetyMismatch(ExpectedFound<hir::Unsafety>),
34 AbiMismatch(ExpectedFound<abi::Abi>),
35 Mutability,
36 BoxMutability,
37 PtrMutability,
38 RefMutability,
39 VecMutability,
40 TupleSize(ExpectedFound<usize>),
41 FixedArraySize(ExpectedFound<usize>),
42 TyParamSize(ExpectedFound<usize>),
43 ArgCount,
9e0c209e
SL
44 RegionsDoesNotOutlive(&'tcx Region, &'tcx Region),
45 RegionsNotSame(&'tcx Region, &'tcx Region),
46 RegionsNoOverlap(&'tcx Region, &'tcx Region),
47 RegionsInsufficientlyPolymorphic(BoundRegion, &'tcx Region),
48 RegionsOverlyPolymorphic(BoundRegion, &'tcx Region),
e9174d1e
SL
49 Sorts(ExpectedFound<Ty<'tcx>>),
50 IntegerAsChar,
51 IntMismatch(ExpectedFound<ty::IntVarValue>),
b039eaaf 52 FloatMismatch(ExpectedFound<ast::FloatTy>),
e9174d1e
SL
53 Traits(ExpectedFound<DefId>),
54 BuiltinBoundsMismatch(ExpectedFound<ty::BuiltinBounds>),
55 VariadicMismatch(ExpectedFound<bool>),
56 CyclicTy,
57 ConvergenceMismatch(ExpectedFound<bool>),
58 ProjectionNameMismatched(ExpectedFound<Name>),
59 ProjectionBoundsLength(ExpectedFound<usize>),
60 TyParamDefaultMismatch(ExpectedFound<type_variable::Default<'tcx>>)
61}
62
63#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)]
64pub enum UnconstrainedNumeric {
65 UnconstrainedFloat,
66 UnconstrainedInt,
67 Neither,
68}
69
70/// Explains the source of a type err in a short, human readable way. This is meant to be placed
71/// in parentheses after some larger message. You should also invoke `note_and_explain_type_err()`
72/// afterwards to present additional details, particularly when it comes to lifetime-related
73/// errors.
74impl<'tcx> fmt::Display for TypeError<'tcx> {
75 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
76 use self::TypeError::*;
77 fn report_maybe_different(f: &mut fmt::Formatter,
78 expected: String, found: String) -> fmt::Result {
79 // A naive approach to making sure that we're not reporting silly errors such as:
80 // (expected closure, found closure).
81 if expected == found {
82 write!(f, "expected {}, found a different {}", expected, found)
83 } else {
84 write!(f, "expected {}, found {}", expected, found)
85 }
86 }
87
88 match *self {
89 CyclicTy => write!(f, "cyclic type of infinite size"),
90 Mismatch => write!(f, "types differ"),
91 UnsafetyMismatch(values) => {
92 write!(f, "expected {} fn, found {} fn",
93 values.expected,
94 values.found)
95 }
96 AbiMismatch(values) => {
97 write!(f, "expected {} fn, found {} fn",
98 values.expected,
99 values.found)
100 }
9e0c209e 101 Mutability => write!(f, "types differ in mutability"),
e9174d1e 102 BoxMutability => {
9e0c209e 103 write!(f, "boxed types differ in mutability")
e9174d1e
SL
104 }
105 VecMutability => write!(f, "vectors differ in mutability"),
106 PtrMutability => write!(f, "pointers differ in mutability"),
107 RefMutability => write!(f, "references differ in mutability"),
108 TyParamSize(values) => {
109 write!(f, "expected a type with {} type params, \
110 found one with {} type params",
111 values.expected,
112 values.found)
113 }
114 FixedArraySize(values) => {
115 write!(f, "expected an array with a fixed size of {} elements, \
116 found one with {} elements",
117 values.expected,
118 values.found)
119 }
120 TupleSize(values) => {
121 write!(f, "expected a tuple with {} elements, \
122 found one with {} elements",
123 values.expected,
124 values.found)
125 }
126 ArgCount => {
127 write!(f, "incorrect number of function parameters")
128 }
129 RegionsDoesNotOutlive(..) => {
130 write!(f, "lifetime mismatch")
131 }
132 RegionsNotSame(..) => {
133 write!(f, "lifetimes are not the same")
134 }
135 RegionsNoOverlap(..) => {
136 write!(f, "lifetimes do not intersect")
137 }
138 RegionsInsufficientlyPolymorphic(br, _) => {
139 write!(f, "expected bound lifetime parameter {}, \
140 found concrete lifetime", br)
141 }
142 RegionsOverlyPolymorphic(br, _) => {
143 write!(f, "expected concrete lifetime, \
144 found bound lifetime parameter {}", br)
145 }
146 Sorts(values) => ty::tls::with(|tcx| {
147 report_maybe_different(f, values.expected.sort_string(tcx),
148 values.found.sort_string(tcx))
149 }),
150 Traits(values) => ty::tls::with(|tcx| {
151 report_maybe_different(f,
152 format!("trait `{}`",
153 tcx.item_path_str(values.expected)),
154 format!("trait `{}`",
155 tcx.item_path_str(values.found)))
156 }),
157 BuiltinBoundsMismatch(values) => {
158 if values.expected.is_empty() {
159 write!(f, "expected no bounds, found `{}`",
160 values.found)
161 } else if values.found.is_empty() {
162 write!(f, "expected bounds `{}`, found no bounds",
163 values.expected)
164 } else {
165 write!(f, "expected bounds `{}`, found bounds `{}`",
166 values.expected,
167 values.found)
168 }
169 }
170 IntegerAsChar => {
171 write!(f, "expected an integral type, found `char`")
172 }
173 IntMismatch(ref values) => {
174 write!(f, "expected `{:?}`, found `{:?}`",
175 values.expected,
176 values.found)
177 }
178 FloatMismatch(ref values) => {
179 write!(f, "expected `{:?}`, found `{:?}`",
180 values.expected,
181 values.found)
182 }
183 VariadicMismatch(ref values) => {
184 write!(f, "expected {} fn, found {} function",
185 if values.expected { "variadic" } else { "non-variadic" },
186 if values.found { "variadic" } else { "non-variadic" })
187 }
188 ConvergenceMismatch(ref values) => {
189 write!(f, "expected {} fn, found {} function",
190 if values.expected { "converging" } else { "diverging" },
191 if values.found { "converging" } else { "diverging" })
192 }
193 ProjectionNameMismatched(ref values) => {
194 write!(f, "expected {}, found {}",
195 values.expected,
196 values.found)
197 }
198 ProjectionBoundsLength(ref values) => {
199 write!(f, "expected {} associated type bindings, found {}",
200 values.expected,
201 values.found)
202 },
203 TyParamDefaultMismatch(ref values) => {
204 write!(f, "conflicting type parameter defaults `{}` and `{}`",
205 values.expected.ty,
206 values.found.ty)
207 }
208 }
209 }
210}
211
a7813a04 212impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> {
9e0c209e 213 pub fn sort_string(&self, tcx: TyCtxt<'a, 'gcx, 'lcx>) -> String {
e9174d1e
SL
214 match self.sty {
215 ty::TyBool | ty::TyChar | ty::TyInt(_) |
5bcae85e 216 ty::TyUint(_) | ty::TyFloat(_) | ty::TyStr | ty::TyNever => self.to_string(),
e9174d1e
SL
217 ty::TyTuple(ref tys) if tys.is_empty() => self.to_string(),
218
9e0c209e 219 ty::TyAdt(def, _) => format!("{} `{}`", def.descr(), tcx.item_path_str(def.did)),
e9174d1e
SL
220 ty::TyBox(_) => "box".to_string(),
221 ty::TyArray(_, n) => format!("array of {} elements", n),
222 ty::TySlice(_) => "slice".to_string(),
223 ty::TyRawPtr(_) => "*-ptr".to_string(),
5bcae85e
SL
224 ty::TyRef(region, tymut) => {
225 let tymut_string = tymut.to_string();
226 if tymut_string == "_" || //unknown type name,
227 tymut_string.len() > 10 || //name longer than saying "reference",
228 region.to_string() != "" //... or a complex type
229 {
230 match tymut {
231 ty::TypeAndMut{mutbl, ..} => {
232 format!("{}reference", match mutbl {
233 hir::Mutability::MutMutable => "mutable ",
234 _ => ""
235 })
236 }
237 }
238 } else {
239 format!("&{}", tymut_string)
240 }
241 }
54a0048b
SL
242 ty::TyFnDef(..) => format!("fn item"),
243 ty::TyFnPtr(_) => "fn pointer".to_string(),
e9174d1e 244 ty::TyTrait(ref inner) => {
9e0c209e 245 format!("trait {}", tcx.item_path_str(inner.principal.def_id()))
e9174d1e
SL
246 }
247 ty::TyClosure(..) => "closure".to_string(),
248 ty::TyTuple(_) => "tuple".to_string(),
249 ty::TyInfer(ty::TyVar(_)) => "inferred type".to_string(),
250 ty::TyInfer(ty::IntVar(_)) => "integral variable".to_string(),
251 ty::TyInfer(ty::FloatVar(_)) => "floating-point variable".to_string(),
252 ty::TyInfer(ty::FreshTy(_)) => "skolemized type".to_string(),
253 ty::TyInfer(ty::FreshIntTy(_)) => "skolemized integral type".to_string(),
254 ty::TyInfer(ty::FreshFloatTy(_)) => "skolemized floating-point type".to_string(),
255 ty::TyProjection(_) => "associated type".to_string(),
256 ty::TyParam(ref p) => {
9e0c209e 257 if p.is_self() {
e9174d1e
SL
258 "Self".to_string()
259 } else {
260 "type parameter".to_string()
261 }
262 }
5bcae85e 263 ty::TyAnon(..) => "anonymized type".to_string(),
e9174d1e
SL
264 ty::TyError => "type error".to_string(),
265 }
266 }
267}
268
a7813a04
XL
269impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
270 pub fn note_and_explain_type_err(self,
9cc50fc6
SL
271 db: &mut DiagnosticBuilder,
272 err: &TypeError<'tcx>,
273 sp: Span) {
e9174d1e
SL
274 use self::TypeError::*;
275
276 match err.clone() {
277 RegionsDoesNotOutlive(subregion, superregion) => {
9cc50fc6
SL
278 self.note_and_explain_region(db, "", subregion, "...");
279 self.note_and_explain_region(db, "...does not necessarily outlive ",
e9174d1e
SL
280 superregion, "");
281 }
282 RegionsNotSame(region1, region2) => {
9cc50fc6
SL
283 self.note_and_explain_region(db, "", region1, "...");
284 self.note_and_explain_region(db, "...is not the same lifetime as ",
e9174d1e
SL
285 region2, "");
286 }
287 RegionsNoOverlap(region1, region2) => {
9cc50fc6
SL
288 self.note_and_explain_region(db, "", region1, "...");
289 self.note_and_explain_region(db, "...does not overlap ",
e9174d1e
SL
290 region2, "");
291 }
292 RegionsInsufficientlyPolymorphic(_, conc_region) => {
9cc50fc6 293 self.note_and_explain_region(db, "concrete lifetime that was found is ",
e9174d1e
SL
294 conc_region, "");
295 }
9e0c209e 296 RegionsOverlyPolymorphic(_, &ty::ReVar(_)) => {
e9174d1e
SL
297 // don't bother to print out the message below for
298 // inference variables, it's not very illuminating.
299 }
300 RegionsOverlyPolymorphic(_, conc_region) => {
9cc50fc6 301 self.note_and_explain_region(db, "expected concrete lifetime is ",
e9174d1e
SL
302 conc_region, "");
303 }
304 Sorts(values) => {
305 let expected_str = values.expected.sort_string(self);
306 let found_str = values.found.sort_string(self);
307 if expected_str == found_str && expected_str == "closure" {
9cc50fc6 308 db.span_note(sp,
92a42be0 309 "no two closures, even if identical, have the same type");
9cc50fc6 310 db.span_help(sp,
92a42be0 311 "consider boxing your closure and/or using it as a trait object");
e9174d1e
SL
312 }
313 },
314 TyParamDefaultMismatch(values) => {
315 let expected = values.expected;
316 let found = values.found;
9cc50fc6
SL
317 db.span_note(sp, &format!("conflicting type parameter defaults `{}` and `{}`",
318 expected.ty,
319 found.ty));
e9174d1e 320
b039eaaf
SL
321 match
322 self.map.as_local_node_id(expected.def_id)
323 .and_then(|node_id| self.map.opt_span(node_id))
324 {
325 Some(span) => {
9cc50fc6 326 db.span_note(span, "a default was defined here...");
e9174d1e 327 }
b039eaaf 328 None => {
9cc50fc6
SL
329 db.note(&format!("a default is defined on `{}`",
330 self.item_path_str(expected.def_id)));
e9174d1e
SL
331 }
332 }
333
9cc50fc6 334 db.span_note(
e9174d1e 335 expected.origin_span,
92a42be0 336 "...that was applied to an unconstrained type variable here");
e9174d1e 337
b039eaaf
SL
338 match
339 self.map.as_local_node_id(found.def_id)
340 .and_then(|node_id| self.map.opt_span(node_id))
341 {
342 Some(span) => {
9cc50fc6 343 db.span_note(span, "a second default was defined here...");
e9174d1e 344 }
b039eaaf 345 None => {
9cc50fc6
SL
346 db.note(&format!("a second default is defined on `{}`",
347 self.item_path_str(found.def_id)));
e9174d1e
SL
348 }
349 }
350
9cc50fc6
SL
351 db.span_note(found.origin_span,
352 "...that also applies to the same type variable here");
e9174d1e
SL
353 }
354 _ => {}
355 }
356 }
357}