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