]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/coherence/orphan.rs
Make name resolution errors non-fatal
[rust.git] / src / librustc_typeck / coherence / orphan.rs
1 // Copyright 2014 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
11 //! Orphan checker: every impl either implements a trait defined in this
12 //! crate or pertains to a type defined in this crate.
13
14 use middle::cstore::LOCAL_CRATE;
15 use middle::def_id::DefId;
16 use middle::traits;
17 use middle::ty;
18 use syntax::ast;
19 use syntax::codemap::Span;
20 use rustc_front::intravisit;
21 use rustc_front::hir;
22 use rustc_front::hir::{Item, ItemImpl};
23
24 pub fn check(tcx: &ty::ctxt) {
25     let mut orphan = OrphanChecker { tcx: tcx };
26     tcx.map.krate().visit_all_items(&mut orphan);
27 }
28
29 struct OrphanChecker<'cx, 'tcx:'cx> {
30     tcx: &'cx ty::ctxt<'tcx>
31 }
32
33 impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
34     fn check_def_id(&self, item: &hir::Item, def_id: DefId) {
35         if def_id.krate != LOCAL_CRATE {
36             span_err!(self.tcx.sess, item.span, E0116,
37                       "cannot define inherent `impl` for a type outside of the \
38                        crate where the type is defined; define and implement \
39                        a trait or new type instead");
40         }
41     }
42
43     fn check_primitive_impl(&self,
44                             impl_def_id: DefId,
45                             lang_def_id: Option<DefId>,
46                             lang: &str,
47                             ty: &str,
48                             span: Span) {
49         match lang_def_id {
50             Some(lang_def_id) if lang_def_id == impl_def_id => { /* OK */ },
51             _ => {
52                 span_err!(self.tcx.sess, span, E0390,
53                           "only a single inherent implementation marked with `#[lang = \"{}\"]` \
54                            is allowed for the `{}` primitive", lang, ty);
55                 span_help!(self.tcx.sess, span,
56                            "consider using a trait to implement these methods");
57             }
58         }
59     }
60
61     /// Checks exactly one impl for orphan rules and other such
62     /// restrictions.  In this fn, it can happen that multiple errors
63     /// apply to a specific impl, so just return after reporting one
64     /// to prevent inundating the user with a bunch of similar error
65     /// reports.
66     fn check_item(&self, item: &hir::Item) {
67         let def_id = self.tcx.map.local_def_id(item.id);
68         match item.node {
69             hir::ItemImpl(_, _, _, None, _, _) => {
70                 // For inherent impls, self type must be a nominal type
71                 // defined in this crate.
72                 debug!("coherence2::orphan check: inherent impl {}",
73                        self.tcx.map.node_to_string(item.id));
74                 let self_ty = self.tcx.lookup_item_type(def_id).ty;
75                 match self_ty.sty {
76                     ty::TyEnum(def, _) |
77                     ty::TyStruct(def, _) => {
78                         self.check_def_id(item, def.did);
79                     }
80                     ty::TyTrait(ref data) => {
81                         self.check_def_id(item, data.principal_def_id());
82                     }
83                     ty::TyBox(..) => {
84                         match self.tcx.lang_items.require_owned_box() {
85                             Ok(trait_id) => self.check_def_id(item, trait_id),
86                             Err(msg) => self.tcx.sess.span_fatal(item.span, &msg),
87                         }
88                     }
89                     ty::TyChar => {
90                         self.check_primitive_impl(def_id,
91                                                   self.tcx.lang_items.char_impl(),
92                                                   "char",
93                                                   "char",
94                                                   item.span);
95                     }
96                     ty::TyStr => {
97                         self.check_primitive_impl(def_id,
98                                                   self.tcx.lang_items.str_impl(),
99                                                   "str",
100                                                   "str",
101                                                   item.span);
102                     }
103                     ty::TySlice(_) => {
104                         self.check_primitive_impl(def_id,
105                                                   self.tcx.lang_items.slice_impl(),
106                                                   "slice",
107                                                   "[T]",
108                                                   item.span);
109                     }
110                     ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => {
111                         self.check_primitive_impl(def_id,
112                                                   self.tcx.lang_items.const_ptr_impl(),
113                                                   "const_ptr",
114                                                   "*const T",
115                                                   item.span);
116                     }
117                     ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => {
118                         self.check_primitive_impl(def_id,
119                                                   self.tcx.lang_items.mut_ptr_impl(),
120                                                   "mut_ptr",
121                                                   "*mut T",
122                                                   item.span);
123                     }
124                     ty::TyInt(ast::TyI8) => {
125                         self.check_primitive_impl(def_id,
126                                                   self.tcx.lang_items.i8_impl(),
127                                                   "i8",
128                                                   "i8",
129                                                   item.span);
130                     }
131                     ty::TyInt(ast::TyI16) => {
132                         self.check_primitive_impl(def_id,
133                                                   self.tcx.lang_items.i16_impl(),
134                                                   "i16",
135                                                   "i16",
136                                                   item.span);
137                     }
138                     ty::TyInt(ast::TyI32) => {
139                         self.check_primitive_impl(def_id,
140                                                   self.tcx.lang_items.i32_impl(),
141                                                   "i32",
142                                                   "i32",
143                                                   item.span);
144                     }
145                     ty::TyInt(ast::TyI64) => {
146                         self.check_primitive_impl(def_id,
147                                                   self.tcx.lang_items.i64_impl(),
148                                                   "i64",
149                                                   "i64",
150                                                   item.span);
151                     }
152                     ty::TyInt(ast::TyIs) => {
153                         self.check_primitive_impl(def_id,
154                                                   self.tcx.lang_items.isize_impl(),
155                                                   "isize",
156                                                   "isize",
157                                                   item.span);
158                     }
159                     ty::TyUint(ast::TyU8) => {
160                         self.check_primitive_impl(def_id,
161                                                   self.tcx.lang_items.u8_impl(),
162                                                   "u8",
163                                                   "u8",
164                                                   item.span);
165                     }
166                     ty::TyUint(ast::TyU16) => {
167                         self.check_primitive_impl(def_id,
168                                                   self.tcx.lang_items.u16_impl(),
169                                                   "u16",
170                                                   "u16",
171                                                   item.span);
172                     }
173                     ty::TyUint(ast::TyU32) => {
174                         self.check_primitive_impl(def_id,
175                                                   self.tcx.lang_items.u32_impl(),
176                                                   "u32",
177                                                   "u32",
178                                                   item.span);
179                     }
180                     ty::TyUint(ast::TyU64) => {
181                         self.check_primitive_impl(def_id,
182                                                   self.tcx.lang_items.u64_impl(),
183                                                   "u64",
184                                                   "u64",
185                                                   item.span);
186                     }
187                     ty::TyUint(ast::TyUs) => {
188                         self.check_primitive_impl(def_id,
189                                                   self.tcx.lang_items.usize_impl(),
190                                                   "usize",
191                                                   "usize",
192                                                   item.span);
193                     }
194                     ty::TyFloat(ast::TyF32) => {
195                         self.check_primitive_impl(def_id,
196                                                   self.tcx.lang_items.f32_impl(),
197                                                   "f32",
198                                                   "f32",
199                                                   item.span);
200                     }
201                     ty::TyFloat(ast::TyF64) => {
202                         self.check_primitive_impl(def_id,
203                                                   self.tcx.lang_items.f64_impl(),
204                                                   "f64",
205                                                   "f64",
206                                                   item.span);
207                     }
208                     ty::TyError => {
209                         return;
210                     }
211                     _ => {
212                         span_err!(self.tcx.sess, item.span, E0118,
213                                   "no base type found for inherent implementation; \
214                                    implement a trait or new type instead");
215                         return;
216                     }
217                 }
218             }
219             hir::ItemImpl(_, _, _, Some(_), _, _) => {
220                 // "Trait" impl
221                 debug!("coherence2::orphan check: trait impl {}",
222                        self.tcx.map.node_to_string(item.id));
223                 let trait_ref = self.tcx.impl_trait_ref(def_id).unwrap();
224                 let trait_def_id = trait_ref.def_id;
225                 match traits::orphan_check(self.tcx, def_id) {
226                     Ok(()) => { }
227                     Err(traits::OrphanCheckErr::NoLocalInputType) => {
228                         span_err!(
229                             self.tcx.sess, item.span, E0117,
230                             "the impl does not reference any \
231                              types defined in this crate; \
232                              only traits defined in the current crate can be \
233                              implemented for arbitrary types");
234                         return;
235                     }
236                     Err(traits::OrphanCheckErr::UncoveredTy(param_ty)) => {
237                         span_err!(self.tcx.sess, item.span, E0210,
238                                 "type parameter `{}` must be used as the type parameter for \
239                                  some local type (e.g. `MyStruct<T>`); only traits defined in \
240                                  the current crate can be implemented for a type parameter",
241                                 param_ty);
242                         return;
243                     }
244                 }
245
246                 // In addition to the above rules, we restrict impls of defaulted traits
247                 // so that they can only be implemented on structs/enums. To see why this
248                 // restriction exists, consider the following example (#22978). Imagine
249                 // that crate A defines a defaulted trait `Foo` and a fn that operates
250                 // on pairs of types:
251                 //
252                 // ```
253                 // // Crate A
254                 // trait Foo { }
255                 // impl Foo for .. { }
256                 // fn two_foos<A:Foo,B:Foo>(..) {
257                 //     one_foo::<(A,B)>(..)
258                 // }
259                 // fn one_foo<T:Foo>(..) { .. }
260                 // ```
261                 //
262                 // This type-checks fine; in particular the fn
263                 // `two_foos` is able to conclude that `(A,B):Foo`
264                 // because `A:Foo` and `B:Foo`.
265                 //
266                 // Now imagine that crate B comes along and does the following:
267                 //
268                 // ```
269                 // struct A { }
270                 // struct B { }
271                 // impl Foo for A { }
272                 // impl Foo for B { }
273                 // impl !Send for (A, B) { }
274                 // ```
275                 //
276                 // This final impl is legal according to the orpan
277                 // rules, but it invalidates the reasoning from
278                 // `two_foos` above.
279                 debug!("trait_ref={:?} trait_def_id={:?} trait_has_default_impl={}",
280                        trait_ref,
281                        trait_def_id,
282                        self.tcx.trait_has_default_impl(trait_def_id));
283                 if
284                     self.tcx.trait_has_default_impl(trait_def_id) &&
285                     trait_def_id.krate != LOCAL_CRATE
286                 {
287                     let self_ty = trait_ref.self_ty();
288                     let opt_self_def_id = match self_ty.sty {
289                         ty::TyStruct(self_def, _) | ty::TyEnum(self_def, _) =>
290                             Some(self_def.did),
291                         ty::TyBox(..) =>
292                             self.tcx.lang_items.owned_box(),
293                         _ =>
294                             None
295                     };
296
297                     let msg = match opt_self_def_id {
298                         // We only want to permit structs/enums, but not *all* structs/enums.
299                         // They must be local to the current crate, so that people
300                         // can't do `unsafe impl Send for Rc<SomethingLocal>` or
301                         // `impl !Send for Box<SomethingLocalAndSend>`.
302                         Some(self_def_id) => {
303                             if self_def_id.is_local() {
304                                 None
305                             } else {
306                                 Some(format!(
307                                     "cross-crate traits with a default impl, like `{}`, \
308                                      can only be implemented for a struct/enum type \
309                                      defined in the current crate",
310                                     self.tcx.item_path_str(trait_def_id)))
311                             }
312                         }
313                         _ => {
314                             Some(format!(
315                                 "cross-crate traits with a default impl, like `{}`, \
316                                  can only be implemented for a struct/enum type, \
317                                  not `{}`",
318                                 self.tcx.item_path_str(trait_def_id),
319                                 self_ty))
320                         }
321                     };
322
323                     if let Some(msg) = msg {
324                         span_err!(self.tcx.sess, item.span, E0321, "{}", msg);
325                         return;
326                     }
327                 }
328
329                 // Disallow *all* explicit impls of `Sized` and `Unsize` for now.
330                 if Some(trait_def_id) == self.tcx.lang_items.sized_trait() {
331                     span_err!(self.tcx.sess, item.span, E0322,
332                               "explicit impls for the `Sized` trait are not permitted");
333                     return;
334                 }
335                 if Some(trait_def_id) == self.tcx.lang_items.unsize_trait() {
336                     span_err!(self.tcx.sess, item.span, E0328,
337                               "explicit impls for the `Unsize` trait are not permitted");
338                     return;
339                 }
340             }
341             hir::ItemDefaultImpl(..) => {
342                 // "Trait" impl
343                 debug!("coherence2::orphan check: default trait impl {}",
344                        self.tcx.map.node_to_string(item.id));
345                 let trait_ref = self.tcx.impl_trait_ref(def_id).unwrap();
346                 if trait_ref.def_id.krate != LOCAL_CRATE {
347                     span_err!(self.tcx.sess, item.span, E0318,
348                               "cannot create default implementations for traits outside the \
349                                crate they're defined in; define a new trait instead");
350                     return;
351                 }
352             }
353             _ => {
354                 // Not an impl
355             }
356         }
357     }
358 }
359
360 impl<'cx, 'tcx,'v> intravisit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
361     fn visit_item(&mut self, item: &hir::Item) {
362         self.check_item(item);
363     }
364 }