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.
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.
11 use hir
::def_id
::DefId
;
12 use infer
::type_variable
;
13 use ty
::{self, BoundRegion, Region, Ty, TyCtxt}
;
17 use syntax
::ast
::{self, Name}
;
18 use errors
::DiagnosticBuilder
;
23 #[derive(Clone, Copy, Debug)]
24 pub struct ExpectedFound
<T
> {
29 // Data structures used in type unification
30 #[derive(Clone, Debug)]
31 pub enum TypeError
<'tcx
> {
33 UnsafetyMismatch(ExpectedFound
<hir
::Unsafety
>),
34 AbiMismatch(ExpectedFound
<abi
::Abi
>),
36 TupleSize(ExpectedFound
<usize>),
37 FixedArraySize(ExpectedFound
<usize>),
39 RegionsDoesNotOutlive(&'tcx Region
, &'tcx Region
),
40 RegionsNotSame(&'tcx Region
, &'tcx Region
),
41 RegionsNoOverlap(&'tcx Region
, &'tcx Region
),
42 RegionsInsufficientlyPolymorphic(BoundRegion
, &'tcx Region
),
43 RegionsOverlyPolymorphic(BoundRegion
, &'tcx Region
),
44 Sorts(ExpectedFound
<Ty
<'tcx
>>),
45 IntMismatch(ExpectedFound
<ty
::IntVarValue
>),
46 FloatMismatch(ExpectedFound
<ast
::FloatTy
>),
47 Traits(ExpectedFound
<DefId
>),
48 BuiltinBoundsMismatch(ExpectedFound
<ty
::BuiltinBounds
>),
49 VariadicMismatch(ExpectedFound
<bool
>),
51 ProjectionNameMismatched(ExpectedFound
<Name
>),
52 ProjectionBoundsLength(ExpectedFound
<usize>),
53 TyParamDefaultMismatch(ExpectedFound
<type_variable
::Default
<'tcx
>>)
56 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)]
57 pub enum UnconstrainedNumeric
{
63 /// Explains the source of a type err in a short, human readable way. This is meant to be placed
64 /// in parentheses after some larger message. You should also invoke `note_and_explain_type_err()`
65 /// afterwards to present additional details, particularly when it comes to lifetime-related
67 impl<'tcx
> fmt
::Display
for TypeError
<'tcx
> {
68 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
69 use self::TypeError
::*;
70 fn report_maybe_different(f
: &mut fmt
::Formatter
,
71 expected
: String
, found
: String
) -> fmt
::Result
{
72 // A naive approach to making sure that we're not reporting silly errors such as:
73 // (expected closure, found closure).
74 if expected
== found
{
75 write
!(f
, "expected {}, found a different {}", expected
, found
)
77 write
!(f
, "expected {}, found {}", expected
, found
)
82 CyclicTy
=> write
!(f
, "cyclic type of infinite size"),
83 Mismatch
=> write
!(f
, "types differ"),
84 UnsafetyMismatch(values
) => {
85 write
!(f
, "expected {} fn, found {} fn",
89 AbiMismatch(values
) => {
90 write
!(f
, "expected {} fn, found {} fn",
94 Mutability
=> write
!(f
, "types differ in mutability"),
95 FixedArraySize(values
) => {
96 write
!(f
, "expected an array with a fixed size of {} elements, \
97 found one with {} elements",
101 TupleSize(values
) => {
102 write
!(f
, "expected a tuple with {} elements, \
103 found one with {} elements",
108 write
!(f
, "incorrect number of function parameters")
110 RegionsDoesNotOutlive(..) => {
111 write
!(f
, "lifetime mismatch")
113 RegionsNotSame(..) => {
114 write
!(f
, "lifetimes are not the same")
116 RegionsNoOverlap(..) => {
117 write
!(f
, "lifetimes do not intersect")
119 RegionsInsufficientlyPolymorphic(br
, _
) => {
120 write
!(f
, "expected bound lifetime parameter {}, \
121 found concrete lifetime", br
)
123 RegionsOverlyPolymorphic(br
, _
) => {
124 write
!(f
, "expected concrete lifetime, \
125 found bound lifetime parameter {}", br
)
127 Sorts(values
) => ty
::tls
::with(|tcx
| {
128 report_maybe_different(f
, values
.expected
.sort_string(tcx
),
129 values
.found
.sort_string(tcx
))
131 Traits(values
) => ty
::tls
::with(|tcx
| {
132 report_maybe_different(f
,
133 format
!("trait `{}`",
134 tcx
.item_path_str(values
.expected
)),
135 format
!("trait `{}`",
136 tcx
.item_path_str(values
.found
)))
138 BuiltinBoundsMismatch(values
) => {
139 if values
.expected
.is_empty() {
140 write
!(f
, "expected no bounds, found `{}`",
142 } else if values
.found
.is_empty() {
143 write
!(f
, "expected bounds `{}`, found no bounds",
146 write
!(f
, "expected bounds `{}`, found bounds `{}`",
151 IntMismatch(ref values
) => {
152 write
!(f
, "expected `{:?}`, found `{:?}`",
156 FloatMismatch(ref values
) => {
157 write
!(f
, "expected `{:?}`, found `{:?}`",
161 VariadicMismatch(ref values
) => {
162 write
!(f
, "expected {} fn, found {} function",
163 if values
.expected { "variadic" }
else { "non-variadic" }
,
164 if values
.found { "variadic" }
else { "non-variadic" }
)
166 ProjectionNameMismatched(ref values
) => {
167 write
!(f
, "expected {}, found {}",
171 ProjectionBoundsLength(ref values
) => {
172 write
!(f
, "expected {} associated type bindings, found {}",
176 TyParamDefaultMismatch(ref values
) => {
177 write
!(f
, "conflicting type parameter defaults `{}` and `{}`",
185 impl<'a
, 'gcx
, 'lcx
, 'tcx
> ty
::TyS
<'tcx
> {
186 pub fn sort_string(&self, tcx
: TyCtxt
<'a
, 'gcx
, 'lcx
>) -> String
{
188 ty
::TyBool
| ty
::TyChar
| ty
::TyInt(_
) |
189 ty
::TyUint(_
) | ty
::TyFloat(_
) | ty
::TyStr
| ty
::TyNever
=> self.to_string(),
190 ty
::TyTuple(ref tys
) if tys
.is_empty() => self.to_string(),
192 ty
::TyAdt(def
, _
) => format
!("{} `{}`", def
.descr(), tcx
.item_path_str(def
.did
)),
193 ty
::TyBox(_
) => "box".to_string(),
194 ty
::TyArray(_
, n
) => format
!("array of {} elements", n
),
195 ty
::TySlice(_
) => "slice".to_string(),
196 ty
::TyRawPtr(_
) => "*-ptr".to_string(),
197 ty
::TyRef(region
, tymut
) => {
198 let tymut_string
= tymut
.to_string();
199 if tymut_string
== "_" || //unknown type name,
200 tymut_string
.len() > 10 || //name longer than saying "reference",
201 region
.to_string() != "" //... or a complex type
204 ty
::TypeAndMut{mutbl, ..}
=> {
205 format
!("{}reference", match mutbl
{
206 hir
::Mutability
::MutMutable
=> "mutable ",
212 format
!("&{}", tymut_string
)
215 ty
::TyFnDef(..) => format
!("fn item"),
216 ty
::TyFnPtr(_
) => "fn pointer".to_string(),
217 ty
::TyTrait(ref inner
) => {
218 format
!("trait {}", tcx
.item_path_str(inner
.principal
.def_id()))
220 ty
::TyClosure(..) => "closure".to_string(),
221 ty
::TyTuple(_
) => "tuple".to_string(),
222 ty
::TyInfer(ty
::TyVar(_
)) => "inferred type".to_string(),
223 ty
::TyInfer(ty
::IntVar(_
)) => "integral variable".to_string(),
224 ty
::TyInfer(ty
::FloatVar(_
)) => "floating-point variable".to_string(),
225 ty
::TyInfer(ty
::FreshTy(_
)) => "skolemized type".to_string(),
226 ty
::TyInfer(ty
::FreshIntTy(_
)) => "skolemized integral type".to_string(),
227 ty
::TyInfer(ty
::FreshFloatTy(_
)) => "skolemized floating-point type".to_string(),
228 ty
::TyProjection(_
) => "associated type".to_string(),
229 ty
::TyParam(ref p
) => {
233 "type parameter".to_string()
236 ty
::TyAnon(..) => "anonymized type".to_string(),
237 ty
::TyError
=> "type error".to_string(),
242 impl<'a
, 'gcx
, 'tcx
> TyCtxt
<'a
, 'gcx
, 'tcx
> {
243 pub fn note_and_explain_type_err(self,
244 db
: &mut DiagnosticBuilder
,
245 err
: &TypeError
<'tcx
>,
247 use self::TypeError
::*;
250 RegionsDoesNotOutlive(subregion
, superregion
) => {
251 self.note_and_explain_region(db
, "", subregion
, "...");
252 self.note_and_explain_region(db
, "...does not necessarily outlive ",
255 RegionsNotSame(region1
, region2
) => {
256 self.note_and_explain_region(db
, "", region1
, "...");
257 self.note_and_explain_region(db
, "...is not the same lifetime as ",
260 RegionsNoOverlap(region1
, region2
) => {
261 self.note_and_explain_region(db
, "", region1
, "...");
262 self.note_and_explain_region(db
, "...does not overlap ",
265 RegionsInsufficientlyPolymorphic(_
, conc_region
) => {
266 self.note_and_explain_region(db
, "concrete lifetime that was found is ",
269 RegionsOverlyPolymorphic(_
, &ty
::ReVar(_
)) => {
270 // don't bother to print out the message below for
271 // inference variables, it's not very illuminating.
273 RegionsOverlyPolymorphic(_
, conc_region
) => {
274 self.note_and_explain_region(db
, "expected concrete lifetime is ",
278 let expected_str
= values
.expected
.sort_string(self);
279 let found_str
= values
.found
.sort_string(self);
280 if expected_str
== found_str
&& expected_str
== "closure" {
282 "no two closures, even if identical, have the same type");
284 "consider boxing your closure and/or using it as a trait object");
287 TyParamDefaultMismatch(values
) => {
288 let expected
= values
.expected
;
289 let found
= values
.found
;
290 db
.span_note(sp
, &format
!("conflicting type parameter defaults `{}` and `{}`",
295 self.map
.as_local_node_id(expected
.def_id
)
296 .and_then(|node_id
| self.map
.opt_span(node_id
))
299 db
.span_note(span
, "a default was defined here...");
302 db
.note(&format
!("a default is defined on `{}`",
303 self.item_path_str(expected
.def_id
)));
308 expected
.origin_span
,
309 "...that was applied to an unconstrained type variable here");
312 self.map
.as_local_node_id(found
.def_id
)
313 .and_then(|node_id
| self.map
.opt_span(node_id
))
316 db
.span_note(span
, "a second default was defined here...");
319 db
.note(&format
!("a second default is defined on `{}`",
320 self.item_path_str(found
.def_id
)));
324 db
.span_note(found
.origin_span
,
325 "...that also applies to the same type variable here");