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