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 middle
::def_id
::DefId
;
13 use middle
::infer
::type_variable
;
14 use middle
::ty
::{self, BoundRegion, Region, Ty}
;
18 use syntax
::ast
::{self, Name}
;
19 use syntax
::codemap
::Span
;
20 use syntax
::errors
::DiagnosticBuilder
;
24 #[derive(Clone, Copy, Debug)]
25 pub struct ExpectedFound
<T
> {
30 // Data structures used in type unification
31 #[derive(Clone, Debug)]
32 pub enum TypeError
<'tcx
> {
34 UnsafetyMismatch(ExpectedFound
<hir
::Unsafety
>),
35 AbiMismatch(ExpectedFound
<abi
::Abi
>),
41 TupleSize(ExpectedFound
<usize>),
42 FixedArraySize(ExpectedFound
<usize>),
43 TyParamSize(ExpectedFound
<usize>),
45 RegionsDoesNotOutlive(Region
, Region
),
46 RegionsNotSame(Region
, Region
),
47 RegionsNoOverlap(Region
, Region
),
48 RegionsInsufficientlyPolymorphic(BoundRegion
, Region
),
49 RegionsOverlyPolymorphic(BoundRegion
, Region
),
50 Sorts(ExpectedFound
<Ty
<'tcx
>>),
52 IntMismatch(ExpectedFound
<ty
::IntVarValue
>),
53 FloatMismatch(ExpectedFound
<ast
::FloatTy
>),
54 Traits(ExpectedFound
<DefId
>),
55 BuiltinBoundsMismatch(ExpectedFound
<ty
::BuiltinBounds
>),
56 VariadicMismatch(ExpectedFound
<bool
>),
58 ConvergenceMismatch(ExpectedFound
<bool
>),
59 ProjectionNameMismatched(ExpectedFound
<Name
>),
60 ProjectionBoundsLength(ExpectedFound
<usize>),
61 TyParamDefaultMismatch(ExpectedFound
<type_variable
::Default
<'tcx
>>)
64 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)]
65 pub enum UnconstrainedNumeric
{
71 /// Explains the source of a type err in a short, human readable way. This is meant to be placed
72 /// in parentheses after some larger message. You should also invoke `note_and_explain_type_err()`
73 /// afterwards to present additional details, particularly when it comes to lifetime-related
75 impl<'tcx
> fmt
::Display
for TypeError
<'tcx
> {
76 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
77 use self::TypeError
::*;
78 fn report_maybe_different(f
: &mut fmt
::Formatter
,
79 expected
: String
, found
: String
) -> fmt
::Result
{
80 // A naive approach to making sure that we're not reporting silly errors such as:
81 // (expected closure, found closure).
82 if expected
== found
{
83 write
!(f
, "expected {}, found a different {}", expected
, found
)
85 write
!(f
, "expected {}, found {}", expected
, found
)
90 CyclicTy
=> write
!(f
, "cyclic type of infinite size"),
91 Mismatch
=> write
!(f
, "types differ"),
92 UnsafetyMismatch(values
) => {
93 write
!(f
, "expected {} fn, found {} fn",
97 AbiMismatch(values
) => {
98 write
!(f
, "expected {} fn, found {} fn",
102 Mutability
=> write
!(f
, "values differ in mutability"),
104 write
!(f
, "boxed values differ in mutability")
106 VecMutability
=> write
!(f
, "vectors differ in mutability"),
107 PtrMutability
=> write
!(f
, "pointers differ in mutability"),
108 RefMutability
=> write
!(f
, "references differ in mutability"),
109 TyParamSize(values
) => {
110 write
!(f
, "expected a type with {} type params, \
111 found one with {} type params",
115 FixedArraySize(values
) => {
116 write
!(f
, "expected an array with a fixed size of {} elements, \
117 found one with {} elements",
121 TupleSize(values
) => {
122 write
!(f
, "expected a tuple with {} elements, \
123 found one with {} elements",
128 write
!(f
, "incorrect number of function parameters")
130 RegionsDoesNotOutlive(..) => {
131 write
!(f
, "lifetime mismatch")
133 RegionsNotSame(..) => {
134 write
!(f
, "lifetimes are not the same")
136 RegionsNoOverlap(..) => {
137 write
!(f
, "lifetimes do not intersect")
139 RegionsInsufficientlyPolymorphic(br
, _
) => {
140 write
!(f
, "expected bound lifetime parameter {}, \
141 found concrete lifetime", br
)
143 RegionsOverlyPolymorphic(br
, _
) => {
144 write
!(f
, "expected concrete lifetime, \
145 found bound lifetime parameter {}", br
)
147 Sorts(values
) => ty
::tls
::with(|tcx
| {
148 report_maybe_different(f
, values
.expected
.sort_string(tcx
),
149 values
.found
.sort_string(tcx
))
151 Traits(values
) => ty
::tls
::with(|tcx
| {
152 report_maybe_different(f
,
153 format
!("trait `{}`",
154 tcx
.item_path_str(values
.expected
)),
155 format
!("trait `{}`",
156 tcx
.item_path_str(values
.found
)))
158 BuiltinBoundsMismatch(values
) => {
159 if values
.expected
.is_empty() {
160 write
!(f
, "expected no bounds, found `{}`",
162 } else if values
.found
.is_empty() {
163 write
!(f
, "expected bounds `{}`, found no bounds",
166 write
!(f
, "expected bounds `{}`, found bounds `{}`",
172 write
!(f
, "expected an integral type, found `char`")
174 IntMismatch(ref values
) => {
175 write
!(f
, "expected `{:?}`, found `{:?}`",
179 FloatMismatch(ref values
) => {
180 write
!(f
, "expected `{:?}`, found `{:?}`",
184 VariadicMismatch(ref values
) => {
185 write
!(f
, "expected {} fn, found {} function",
186 if values
.expected { "variadic" }
else { "non-variadic" }
,
187 if values
.found { "variadic" }
else { "non-variadic" }
)
189 ConvergenceMismatch(ref values
) => {
190 write
!(f
, "expected {} fn, found {} function",
191 if values
.expected { "converging" }
else { "diverging" }
,
192 if values
.found { "converging" }
else { "diverging" }
)
194 ProjectionNameMismatched(ref values
) => {
195 write
!(f
, "expected {}, found {}",
199 ProjectionBoundsLength(ref values
) => {
200 write
!(f
, "expected {} associated type bindings, found {}",
204 TyParamDefaultMismatch(ref values
) => {
205 write
!(f
, "conflicting type parameter defaults `{}` and `{}`",
213 impl<'tcx
> ty
::TyS
<'tcx
> {
214 fn sort_string(&self, cx
: &ty
::ctxt
) -> String
{
216 ty
::TyBool
| ty
::TyChar
| ty
::TyInt(_
) |
217 ty
::TyUint(_
) | ty
::TyFloat(_
) | ty
::TyStr
=> self.to_string(),
218 ty
::TyTuple(ref tys
) if tys
.is_empty() => self.to_string(),
220 ty
::TyEnum(def
, _
) => format
!("enum `{}`", cx
.item_path_str(def
.did
)),
221 ty
::TyBox(_
) => "box".to_string(),
222 ty
::TyArray(_
, n
) => format
!("array of {} elements", n
),
223 ty
::TySlice(_
) => "slice".to_string(),
224 ty
::TyRawPtr(_
) => "*-ptr".to_string(),
225 ty
::TyRef(_
, _
) => "&-ptr".to_string(),
226 ty
::TyBareFn(Some(_
), _
) => format
!("fn item"),
227 ty
::TyBareFn(None
, _
) => "fn pointer".to_string(),
228 ty
::TyTrait(ref inner
) => {
229 format
!("trait {}", cx
.item_path_str(inner
.principal_def_id()))
231 ty
::TyStruct(def
, _
) => {
232 format
!("struct `{}`", cx
.item_path_str(def
.did
))
234 ty
::TyClosure(..) => "closure".to_string(),
235 ty
::TyTuple(_
) => "tuple".to_string(),
236 ty
::TyInfer(ty
::TyVar(_
)) => "inferred type".to_string(),
237 ty
::TyInfer(ty
::IntVar(_
)) => "integral variable".to_string(),
238 ty
::TyInfer(ty
::FloatVar(_
)) => "floating-point variable".to_string(),
239 ty
::TyInfer(ty
::FreshTy(_
)) => "skolemized type".to_string(),
240 ty
::TyInfer(ty
::FreshIntTy(_
)) => "skolemized integral type".to_string(),
241 ty
::TyInfer(ty
::FreshFloatTy(_
)) => "skolemized floating-point type".to_string(),
242 ty
::TyProjection(_
) => "associated type".to_string(),
243 ty
::TyParam(ref p
) => {
244 if p
.space
== subst
::SelfSpace
{
247 "type parameter".to_string()
250 ty
::TyError
=> "type error".to_string(),
255 impl<'tcx
> ty
::ctxt
<'tcx
> {
256 pub fn note_and_explain_type_err(&self,
257 db
: &mut DiagnosticBuilder
,
258 err
: &TypeError
<'tcx
>,
260 use self::TypeError
::*;
263 RegionsDoesNotOutlive(subregion
, superregion
) => {
264 self.note_and_explain_region(db
, "", subregion
, "...");
265 self.note_and_explain_region(db
, "...does not necessarily outlive ",
268 RegionsNotSame(region1
, region2
) => {
269 self.note_and_explain_region(db
, "", region1
, "...");
270 self.note_and_explain_region(db
, "...is not the same lifetime as ",
273 RegionsNoOverlap(region1
, region2
) => {
274 self.note_and_explain_region(db
, "", region1
, "...");
275 self.note_and_explain_region(db
, "...does not overlap ",
278 RegionsInsufficientlyPolymorphic(_
, conc_region
) => {
279 self.note_and_explain_region(db
, "concrete lifetime that was found is ",
282 RegionsOverlyPolymorphic(_
, ty
::ReVar(_
)) => {
283 // don't bother to print out the message below for
284 // inference variables, it's not very illuminating.
286 RegionsOverlyPolymorphic(_
, conc_region
) => {
287 self.note_and_explain_region(db
, "expected concrete lifetime is ",
291 let expected_str
= values
.expected
.sort_string(self);
292 let found_str
= values
.found
.sort_string(self);
293 if expected_str
== found_str
&& expected_str
== "closure" {
295 "no two closures, even if identical, have the same type");
297 "consider boxing your closure and/or using it as a trait object");
300 TyParamDefaultMismatch(values
) => {
301 let expected
= values
.expected
;
302 let found
= values
.found
;
303 db
.span_note(sp
, &format
!("conflicting type parameter defaults `{}` and `{}`",
308 self.map
.as_local_node_id(expected
.def_id
)
309 .and_then(|node_id
| self.map
.opt_span(node_id
))
312 db
.span_note(span
, "a default was defined here...");
315 db
.note(&format
!("a default is defined on `{}`",
316 self.item_path_str(expected
.def_id
)));
321 expected
.origin_span
,
322 "...that was applied to an unconstrained type variable here");
325 self.map
.as_local_node_id(found
.def_id
)
326 .and_then(|node_id
| self.map
.opt_span(node_id
))
329 db
.span_note(span
, "a second default was defined here...");
332 db
.note(&format
!("a second default is defined on `{}`",
333 self.item_path_str(found
.def_id
)));
337 db
.span_note(found
.origin_span
,
338 "...that also applies to the same type variable here");