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.
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 //! Orphan checker: every impl either implements a trait defined in this
12 //! crate or pertains to a type defined in this crate.
14 use middle::cstore::LOCAL_CRATE;
15 use hir::def_id::DefId;
17 use rustc::ty::{self, TyCtxt};
20 use rustc::dep_graph::DepNode;
21 use rustc::hir::intravisit;
24 pub fn check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
25 let mut orphan = OrphanChecker { tcx: tcx };
26 tcx.visit_all_items_in_krate(DepNode::CoherenceOrphanCheck, &mut orphan);
29 struct OrphanChecker<'cx, 'tcx:'cx> {
30 tcx: TyCtxt<'cx, 'tcx, 'tcx>
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 struct_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")
39 .span_label(item.span, &format!("impl for type defined outside of crate."))
40 .span_note(item.span, &format!("define and implement a trait or new type instead"))
45 fn check_primitive_impl(&self,
47 lang_def_id: Option<DefId>,
52 Some(lang_def_id) if lang_def_id == impl_def_id => { /* OK */ },
54 struct_span_err!(self.tcx.sess, span, E0390,
55 "only a single inherent implementation marked with `#[lang = \"{}\"]` \
56 is allowed for the `{}` primitive", lang, ty)
57 .span_help(span, "consider using a trait to implement these methods")
63 /// Checks exactly one impl for orphan rules and other such
64 /// restrictions. In this fn, it can happen that multiple errors
65 /// apply to a specific impl, so just return after reporting one
66 /// to prevent inundating the user with a bunch of similar error
68 fn check_item(&self, item: &hir::Item) {
69 let def_id = self.tcx.map.local_def_id(item.id);
71 hir::ItemImpl(_, _, _, None, ref ty, _) => {
72 // For inherent impls, self type must be a nominal type
73 // defined in this crate.
74 debug!("coherence2::orphan check: inherent impl {}",
75 self.tcx.map.node_to_string(item.id));
76 let self_ty = self.tcx.lookup_item_type(def_id).ty;
79 ty::TyStruct(def, _) => {
80 self.check_def_id(item, def.did);
82 ty::TyTrait(ref data) => {
83 self.check_def_id(item, data.principal.def_id());
86 match self.tcx.lang_items.require_owned_box() {
87 Ok(trait_id) => self.check_def_id(item, trait_id),
88 Err(msg) => self.tcx.sess.span_fatal(item.span, &msg),
92 self.check_primitive_impl(def_id,
93 self.tcx.lang_items.char_impl(),
99 self.check_primitive_impl(def_id,
100 self.tcx.lang_items.str_impl(),
106 self.check_primitive_impl(def_id,
107 self.tcx.lang_items.slice_impl(),
112 ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => {
113 self.check_primitive_impl(def_id,
114 self.tcx.lang_items.const_ptr_impl(),
119 ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => {
120 self.check_primitive_impl(def_id,
121 self.tcx.lang_items.mut_ptr_impl(),
126 ty::TyInt(ast::IntTy::I8) => {
127 self.check_primitive_impl(def_id,
128 self.tcx.lang_items.i8_impl(),
133 ty::TyInt(ast::IntTy::I16) => {
134 self.check_primitive_impl(def_id,
135 self.tcx.lang_items.i16_impl(),
140 ty::TyInt(ast::IntTy::I32) => {
141 self.check_primitive_impl(def_id,
142 self.tcx.lang_items.i32_impl(),
147 ty::TyInt(ast::IntTy::I64) => {
148 self.check_primitive_impl(def_id,
149 self.tcx.lang_items.i64_impl(),
154 ty::TyInt(ast::IntTy::Is) => {
155 self.check_primitive_impl(def_id,
156 self.tcx.lang_items.isize_impl(),
161 ty::TyUint(ast::UintTy::U8) => {
162 self.check_primitive_impl(def_id,
163 self.tcx.lang_items.u8_impl(),
168 ty::TyUint(ast::UintTy::U16) => {
169 self.check_primitive_impl(def_id,
170 self.tcx.lang_items.u16_impl(),
175 ty::TyUint(ast::UintTy::U32) => {
176 self.check_primitive_impl(def_id,
177 self.tcx.lang_items.u32_impl(),
182 ty::TyUint(ast::UintTy::U64) => {
183 self.check_primitive_impl(def_id,
184 self.tcx.lang_items.u64_impl(),
189 ty::TyUint(ast::UintTy::Us) => {
190 self.check_primitive_impl(def_id,
191 self.tcx.lang_items.usize_impl(),
196 ty::TyFloat(ast::FloatTy::F32) => {
197 self.check_primitive_impl(def_id,
198 self.tcx.lang_items.f32_impl(),
203 ty::TyFloat(ast::FloatTy::F64) => {
204 self.check_primitive_impl(def_id,
205 self.tcx.lang_items.f64_impl(),
214 struct_span_err!(self.tcx.sess, ty.span, E0118,
215 "no base type found for inherent implementation")
216 .span_label(ty.span, &format!("impl requires a base type"))
217 .note(&format!("either implement a trait on it or create a newtype \
218 to wrap it instead"))
224 hir::ItemImpl(_, _, _, Some(_), _, _) => {
226 debug!("coherence2::orphan check: trait impl {}",
227 self.tcx.map.node_to_string(item.id));
228 let trait_ref = self.tcx.impl_trait_ref(def_id).unwrap();
229 let trait_def_id = trait_ref.def_id;
230 match traits::orphan_check(self.tcx, def_id) {
232 Err(traits::OrphanCheckErr::NoLocalInputType) => {
234 self.tcx.sess, item.span, E0117,
235 "only traits defined in the current crate can be \
236 implemented for arbitrary types")
237 .span_label(item.span, &format!("impl doesn't use types inside crate"))
238 .note(&format!("the impl does not reference any \
239 types defined in this crate"))
243 Err(traits::OrphanCheckErr::UncoveredTy(param_ty)) => {
244 span_err!(self.tcx.sess, item.span, E0210,
245 "type parameter `{}` must be used as the type parameter for \
246 some local type (e.g. `MyStruct<T>`); only traits defined in \
247 the current crate can be implemented for a type parameter",
253 // In addition to the above rules, we restrict impls of defaulted traits
254 // so that they can only be implemented on structs/enums. To see why this
255 // restriction exists, consider the following example (#22978). Imagine
256 // that crate A defines a defaulted trait `Foo` and a fn that operates
257 // on pairs of types:
262 // impl Foo for .. { }
263 // fn two_foos<A:Foo,B:Foo>(..) {
264 // one_foo::<(A,B)>(..)
266 // fn one_foo<T:Foo>(..) { .. }
269 // This type-checks fine; in particular the fn
270 // `two_foos` is able to conclude that `(A,B):Foo`
271 // because `A:Foo` and `B:Foo`.
273 // Now imagine that crate B comes along and does the following:
278 // impl Foo for A { }
279 // impl Foo for B { }
280 // impl !Send for (A, B) { }
283 // This final impl is legal according to the orpan
284 // rules, but it invalidates the reasoning from
286 debug!("trait_ref={:?} trait_def_id={:?} trait_has_default_impl={}",
289 self.tcx.trait_has_default_impl(trait_def_id));
291 self.tcx.trait_has_default_impl(trait_def_id) &&
292 trait_def_id.krate != LOCAL_CRATE
294 let self_ty = trait_ref.self_ty();
295 let opt_self_def_id = match self_ty.sty {
296 ty::TyStruct(self_def, _) | ty::TyEnum(self_def, _) =>
299 self.tcx.lang_items.owned_box(),
304 let msg = match opt_self_def_id {
305 // We only want to permit structs/enums, but not *all* structs/enums.
306 // They must be local to the current crate, so that people
307 // can't do `unsafe impl Send for Rc<SomethingLocal>` or
308 // `impl !Send for Box<SomethingLocalAndSend>`.
309 Some(self_def_id) => {
310 if self_def_id.is_local() {
314 "cross-crate traits with a default impl, like `{}`, \
315 can only be implemented for a struct/enum type \
316 defined in the current crate",
317 self.tcx.item_path_str(trait_def_id)))
322 "cross-crate traits with a default impl, like `{}`, \
323 can only be implemented for a struct/enum type, \
325 self.tcx.item_path_str(trait_def_id),
330 if let Some(msg) = msg {
331 span_err!(self.tcx.sess, item.span, E0321, "{}", msg);
336 // Disallow *all* explicit impls of `Sized` and `Unsize` for now.
337 if Some(trait_def_id) == self.tcx.lang_items.sized_trait() {
338 struct_span_err!(self.tcx.sess, item.span, E0322,
339 "explicit impls for the `Sized` trait are not permitted")
340 .span_label(item.span, &format!("impl of 'Sized' not allowed"))
344 if Some(trait_def_id) == self.tcx.lang_items.unsize_trait() {
345 span_err!(self.tcx.sess, item.span, E0328,
346 "explicit impls for the `Unsize` trait are not permitted");
350 hir::ItemDefaultImpl(..) => {
352 debug!("coherence2::orphan check: default trait impl {}",
353 self.tcx.map.node_to_string(item.id));
354 let trait_ref = self.tcx.impl_trait_ref(def_id).unwrap();
355 if trait_ref.def_id.krate != LOCAL_CRATE {
356 span_err!(self.tcx.sess, item.span, E0318,
357 "cannot create default implementations for traits outside the \
358 crate they're defined in; define a new trait instead");
369 impl<'cx, 'tcx,'v> intravisit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
370 fn visit_item(&mut self, item: &hir::Item) {
371 self.check_item(item);