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.
16 use syntax
::ast
::{Item, ItemImpl}
;
19 use syntax
::codemap
::Span
;
21 use util
::ppaux
::{Repr, UserString}
;
23 pub fn check(tcx
: &ty
::ctxt
) {
24 let mut orphan
= OrphanChecker { tcx: tcx }
;
25 visit
::walk_crate(&mut orphan
, tcx
.map
.krate());
28 struct OrphanChecker
<'cx
, 'tcx
:'cx
> {
29 tcx
: &'cx ty
::ctxt
<'tcx
>
32 impl<'cx
, 'tcx
> OrphanChecker
<'cx
, 'tcx
> {
33 fn check_def_id(&self, span
: Span
, def_id
: ast
::DefId
) {
34 if def_id
.krate
!= ast
::LOCAL_CRATE
{
35 span_err
!(self.tcx
.sess
, span
, E0116
,
36 "cannot associate methods with a type outside the \
37 crate the type is defined in; define and implement \
38 a trait or new type instead");
43 impl<'cx
, 'tcx
,'v
> visit
::Visitor
<'v
> for OrphanChecker
<'cx
, 'tcx
> {
44 fn visit_item(&mut self, item
: &'v ast
::Item
) {
45 let def_id
= ast_util
::local_def(item
.id
);
47 ast
::ItemImpl(_
, _
, _
, None
, _
, _
) => {
48 // For inherent impls, self type must be a nominal type
49 // defined in this crate.
50 debug
!("coherence2::orphan check: inherent impl {}", item
.repr(self.tcx
));
51 let self_ty
= ty
::lookup_item_type(self.tcx
, def_id
).ty
;
53 ty
::ty_enum(def_id
, _
) |
54 ty
::ty_struct(def_id
, _
) => {
55 self.check_def_id(item
.span
, def_id
);
57 ty
::ty_trait(ref data
) => {
58 self.check_def_id(item
.span
, data
.principal_def_id());
61 self.check_def_id(item
.span
,
62 self.tcx
.lang_items
.owned_box()
66 span_err
!(self.tcx
.sess
, item
.span
, E0118
,
67 "no base type found for inherent implementation; \
68 implement a trait or new type instead");
72 ast
::ItemImpl(_
, _
, _
, Some(_
), _
, _
) => {
74 debug
!("coherence2::orphan check: trait impl {}", item
.repr(self.tcx
));
75 let trait_def_id
= ty
::impl_trait_ref(self.tcx
, def_id
).unwrap().def_id
;
76 match traits
::orphan_check(self.tcx
, def_id
) {
78 Err(traits
::OrphanCheckErr
::NoLocalInputType
) => {
79 if !ty
::has_attr(self.tcx
, trait_def_id
, "old_orphan_check") {
80 let self_ty
= ty
::lookup_item_type(self.tcx
, def_id
).ty
;
82 self.tcx
.sess
, item
.span
, E0117
,
83 "the type `{}` does not reference any \
84 types defined in this crate; \
85 only traits defined in the current crate can be \
86 implemented for arbitrary types",
87 self_ty
.user_string(self.tcx
));
90 Err(traits
::OrphanCheckErr
::UncoveredTy(param_ty
)) => {
91 if !ty
::has_attr(self.tcx
, trait_def_id
, "old_orphan_check") {
92 self.tcx
.sess
.span_err(
95 "type parameter `{}` is not constrained by any local type; \
96 only traits defined in the current crate can be implemented \
97 for a type parameter",
98 param_ty
.user_string(self.tcx
)).as_slice());
99 self.tcx
.sess
.span_note(
101 format
!("for a limited time, you can add \
102 `#![feature(old_orphan_check)]` to your crate \
103 to disable this rule").as_slice());
113 visit
::walk_item(self, item
);