diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index 95dafccd866..fc49a555ad3 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -69,7 +69,8 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> { ast::ItemImpl(_, _, _, Some(_), _, _) => { // "Trait" impl debug!("coherence2::orphan check: trait impl {}", item.repr(self.tcx)); - let trait_def_id = ty::impl_trait_ref(self.tcx, def_id).unwrap().def_id; + let trait_ref = ty::impl_trait_ref(self.tcx, def_id).unwrap(); + let trait_def_id = trait_ref.def_id; match traits::orphan_check(self.tcx, def_id) { Ok(()) => { } Err(traits::OrphanCheckErr::NoLocalInputType) => { @@ -92,6 +93,40 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> { } } } + + // Impls of a defaulted trait face additional rules. + debug!("trait_ref={} trait_def_id={} trait_has_default_impl={}", + trait_ref.repr(self.tcx), + trait_def_id.repr(self.tcx), + ty::trait_has_default_impl(self.tcx, trait_def_id)); + if + ty::trait_has_default_impl(self.tcx, trait_def_id) && + trait_def_id.krate != ast::LOCAL_CRATE + { + let self_ty = trait_ref.self_ty(); + match self_ty.sty { + ty::ty_struct(self_def_id, _) | ty::ty_enum(self_def_id, _) => { + // The orphan check often rules this out, + // but not always. For example, the orphan + // check would accept `impl Send for + // Box`, but we want to + // forbid that. + if self_def_id.krate != ast::LOCAL_CRATE { + self.tcx.sess.span_err( + item.span, + "cross-crate traits with a default impl \ + can only be implemented for a struct/enum type \ + defined in the current crate"); + } + } + _ => { + self.tcx.sess.span_err( + item.span, + "cross-crate traits with a default impl \ + can only be implemented for a struct or enum type"); + } + } + } } ast::ItemDefaultImpl(..) => { // "Trait" impl diff --git a/src/test/auxiliary/typeck-default-trait-impl-cross-crate-coherence-lib.rs b/src/test/auxiliary/typeck-default-trait-impl-cross-crate-coherence-lib.rs new file mode 100644 index 00000000000..579b9b01925 --- /dev/null +++ b/src/test/auxiliary/typeck-default-trait-impl-cross-crate-coherence-lib.rs @@ -0,0 +1,17 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(optin_builtin_traits)] +#![crate_type = "rlib"] + +use std::marker::MarkerTrait; + +pub trait DefaultedTrait : MarkerTrait { } +impl DefaultedTrait for .. { } diff --git a/src/test/compile-fail/typeck-default-trait-impl-cross-crate-coherence.rs b/src/test/compile-fail/typeck-default-trait-impl-cross-crate-coherence.rs new file mode 100644 index 00000000000..bcc01d1a0a7 --- /dev/null +++ b/src/test/compile-fail/typeck-default-trait-impl-cross-crate-coherence.rs @@ -0,0 +1,34 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:typeck-default-trait-impl-cross-crate-coherence-lib.rs + +// Test that we do not consider associated types to be sendable without +// some applicable trait bound (and we don't ICE). + +#![feature(optin_builtin_traits)] + +extern crate "typeck-default-trait-impl-cross-crate-coherence-lib" as lib; + +use lib::DefaultedTrait; + +struct A; +impl DefaultedTrait for (A,) { } +//~^ ERROR can only be implemented for a struct or enum type + +struct B; +impl !DefaultedTrait for (B,) { } +//~^ ERROR can only be implemented for a struct or enum type + +struct C; +impl DefaultedTrait for Box { } +//~^ ERROR can only be implemented for a struct or enum type + +fn main() { }