/// reports.
fn visit_item(&mut self, item: &hir::Item) {
let def_id = self.tcx.hir.local_def_id(item.id);
- match item.node {
- hir::ItemKind::Impl(.., Some(_), _, _) => {
- // "Trait" impl
- debug!("coherence2::orphan check: trait impl {}",
- self.tcx.hir.node_to_string(item.id));
- let trait_ref = self.tcx.impl_trait_ref(def_id).unwrap();
- let trait_def_id = trait_ref.def_id;
- let cm = self.tcx.sess.source_map();
- let sp = cm.def_span(item.span);
- match traits::orphan_check(self.tcx, def_id) {
- Ok(()) => {}
- Err(traits::OrphanCheckErr::NoLocalInputType) => {
- struct_span_err!(self.tcx.sess,
- sp,
- E0117,
- "only traits defined in the current crate can be \
- implemented for arbitrary types")
- .span_label(sp, "impl doesn't use types inside crate")
- .note("the impl does not reference any types defined in this crate")
- .note("define and implement a trait or new type instead")
- .emit();
- return;
- }
- Err(traits::OrphanCheckErr::UncoveredTy(param_ty)) => {
- struct_span_err!(self.tcx.sess,
- sp,
- E0210,
- "type parameter `{}` must be used as the type parameter \
- for some local type (e.g. `MyStruct<{}>`)",
- param_ty,
- param_ty)
- .span_label(sp,
- format!("type parameter `{}` must be used as the type \
- parameter for some local type", param_ty))
- .note("only traits defined in the current crate can be implemented \
- for a type parameter")
- .emit();
- return;
- }
+ // "Trait" impl
+ if let hir::ItemKind::Impl(.., Some(_), _, _) = item.node {
+ debug!("coherence2::orphan check: trait impl {}",
+ self.tcx.hir.node_to_string(item.id));
+ let trait_ref = self.tcx.impl_trait_ref(def_id).unwrap();
+ let trait_def_id = trait_ref.def_id;
+ let cm = self.tcx.sess.source_map();
+ let sp = cm.def_span(item.span);
+ match traits::orphan_check(self.tcx, def_id) {
+ Ok(()) => {}
+ Err(traits::OrphanCheckErr::NoLocalInputType) => {
+ struct_span_err!(self.tcx.sess,
+ sp,
+ E0117,
+ "only traits defined in the current crate can be \
+ implemented for arbitrary types")
+ .span_label(sp, "impl doesn't use types inside crate")
+ .note("the impl does not reference any types defined in this crate")
+ .note("define and implement a trait or new type instead")
+ .emit();
+ return;
+ }
+ Err(traits::OrphanCheckErr::UncoveredTy(param_ty)) => {
+ struct_span_err!(self.tcx.sess,
+ sp,
+ E0210,
+ "type parameter `{}` must be used as the type parameter \
+ for some local type (e.g. `MyStruct<{}>`)",
+ param_ty,
+ param_ty)
+ .span_label(sp,
+ format!("type parameter `{}` must be used as the type \
+ parameter for some local type", param_ty))
+ .note("only traits defined in the current crate can be implemented \
+ for a type parameter")
+ .emit();
+ return;
}
+ }
- // In addition to the above rules, we restrict impls of auto traits
- // so that they can only be implemented on nominal types, such as structs,
- // enums or foreign types. To see why this restriction exists, consider the
- // following example (#22978). Imagine that crate A defines an auto trait
- // `Foo` and a fn that operates on pairs of types:
- //
- // ```
- // // Crate A
- // auto trait Foo { }
- // fn two_foos<A:Foo,B:Foo>(..) {
- // one_foo::<(A,B)>(..)
- // }
- // fn one_foo<T:Foo>(..) { .. }
- // ```
- //
- // This type-checks fine; in particular the fn
- // `two_foos` is able to conclude that `(A,B):Foo`
- // because `A:Foo` and `B:Foo`.
- //
- // Now imagine that crate B comes along and does the following:
- //
- // ```
- // struct A { }
- // struct B { }
- // impl Foo for A { }
- // impl Foo for B { }
- // impl !Send for (A, B) { }
- // ```
- //
- // This final impl is legal according to the orpan
- // rules, but it invalidates the reasoning from
- // `two_foos` above.
- debug!("trait_ref={:?} trait_def_id={:?} trait_is_auto={}",
- trait_ref,
- trait_def_id,
- self.tcx.trait_is_auto(trait_def_id));
- if self.tcx.trait_is_auto(trait_def_id) &&
- !trait_def_id.is_local() {
- let self_ty = trait_ref.self_ty();
- let opt_self_def_id = match self_ty.sty {
- ty::Adt(self_def, _) => Some(self_def.did),
- ty::Foreign(did) => Some(did),
- _ => None,
- };
+ // In addition to the above rules, we restrict impls of auto traits
+ // so that they can only be implemented on nominal types, such as structs,
+ // enums or foreign types. To see why this restriction exists, consider the
+ // following example (#22978). Imagine that crate A defines an auto trait
+ // `Foo` and a fn that operates on pairs of types:
+ //
+ // ```
+ // // Crate A
+ // auto trait Foo { }
+ // fn two_foos<A:Foo,B:Foo>(..) {
+ // one_foo::<(A,B)>(..)
+ // }
+ // fn one_foo<T:Foo>(..) { .. }
+ // ```
+ //
+ // This type-checks fine; in particular the fn
+ // `two_foos` is able to conclude that `(A,B):Foo`
+ // because `A:Foo` and `B:Foo`.
+ //
+ // Now imagine that crate B comes along and does the following:
+ //
+ // ```
+ // struct A { }
+ // struct B { }
+ // impl Foo for A { }
+ // impl Foo for B { }
+ // impl !Send for (A, B) { }
+ // ```
+ //
+ // This final impl is legal according to the orpan
+ // rules, but it invalidates the reasoning from
+ // `two_foos` above.
+ debug!("trait_ref={:?} trait_def_id={:?} trait_is_auto={}",
+ trait_ref,
+ trait_def_id,
+ self.tcx.trait_is_auto(trait_def_id));
+ if self.tcx.trait_is_auto(trait_def_id) &&
+ !trait_def_id.is_local() {
+ let self_ty = trait_ref.self_ty();
+ let opt_self_def_id = match self_ty.sty {
+ ty::Adt(self_def, _) => Some(self_def.did),
+ ty::Foreign(did) => Some(did),
+ _ => None,
+ };
- let msg = match opt_self_def_id {
- // We only want to permit nominal types, but not *all* nominal types.
- // They must be local to the current crate, so that people
- // can't do `unsafe impl Send for Rc<SomethingLocal>` or
- // `impl !Send for Box<SomethingLocalAndSend>`.
- Some(self_def_id) => {
- if self_def_id.is_local() {
- None
- } else {
- Some((
- format!("cross-crate traits with a default impl, like `{}`, \
- can only be implemented for a struct/enum type \
- defined in the current crate",
- self.tcx.item_path_str(trait_def_id)),
- "can't implement cross-crate trait for type in another crate"
- ))
- }
- }
- _ => {
- Some((format!("cross-crate traits with a default impl, like `{}`, can \
- only be implemented for a struct/enum type, not `{}`",
- self.tcx.item_path_str(trait_def_id),
- self_ty),
- "can't implement cross-crate trait with a default impl for \
- non-struct/enum type"))
+ let msg = match opt_self_def_id {
+ // We only want to permit nominal types, but not *all* nominal types.
+ // They must be local to the current crate, so that people
+ // can't do `unsafe impl Send for Rc<SomethingLocal>` or
+ // `impl !Send for Box<SomethingLocalAndSend>`.
+ Some(self_def_id) => {
+ if self_def_id.is_local() {
+ None
+ } else {
+ Some((
+ format!("cross-crate traits with a default impl, like `{}`, \
+ can only be implemented for a struct/enum type \
+ defined in the current crate",
+ self.tcx.item_path_str(trait_def_id)),
+ "can't implement cross-crate trait for type in another crate"
+ ))
}
- };
-
- if let Some((msg, label)) = msg {
- struct_span_err!(self.tcx.sess, sp, E0321, "{}", msg)
- .span_label(sp, label)
- .emit();
- return;
}
+ _ => {
+ Some((format!("cross-crate traits with a default impl, like `{}`, can \
+ only be implemented for a struct/enum type, not `{}`",
+ self.tcx.item_path_str(trait_def_id),
+ self_ty),
+ "can't implement cross-crate trait with a default impl for \
+ non-struct/enum type"))
+ }
+ };
+
+ if let Some((msg, label)) = msg {
+ struct_span_err!(self.tcx.sess, sp, E0321, "{}", msg)
+ .span_label(sp, label)
+ .emit();
+ return;
}
}
- _ => {
- // Not an impl
- }
}
}