Skip to content

Commit 2e21689

Browse files
committed
Add stricter orphan rules for cross-crate impls of default traits.
1 parent dbec033 commit 2e21689

File tree

3 files changed

+87
-1
lines changed

3 files changed

+87
-1
lines changed

src/librustc_typeck/coherence/orphan.rs

+36-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
6969
ast::ItemImpl(_, _, _, Some(_), _, _) => {
7070
// "Trait" impl
7171
debug!("coherence2::orphan check: trait impl {}", item.repr(self.tcx));
72-
let trait_def_id = ty::impl_trait_ref(self.tcx, def_id).unwrap().def_id;
72+
let trait_ref = ty::impl_trait_ref(self.tcx, def_id).unwrap();
73+
let trait_def_id = trait_ref.def_id;
7374
match traits::orphan_check(self.tcx, def_id) {
7475
Ok(()) => { }
7576
Err(traits::OrphanCheckErr::NoLocalInputType) => {
@@ -92,6 +93,40 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
9293
}
9394
}
9495
}
96+
97+
// Impls of a defaulted trait face additional rules.
98+
debug!("trait_ref={} trait_def_id={} trait_has_default_impl={}",
99+
trait_ref.repr(self.tcx),
100+
trait_def_id.repr(self.tcx),
101+
ty::trait_has_default_impl(self.tcx, trait_def_id));
102+
if
103+
ty::trait_has_default_impl(self.tcx, trait_def_id) &&
104+
trait_def_id.krate != ast::LOCAL_CRATE
105+
{
106+
let self_ty = trait_ref.self_ty();
107+
match self_ty.sty {
108+
ty::ty_struct(self_def_id, _) | ty::ty_enum(self_def_id, _) => {
109+
// The orphan check often rules this out,
110+
// but not always. For example, the orphan
111+
// check would accept `impl Send for
112+
// Box<SomethingLocal>`, but we want to
113+
// forbid that.
114+
if self_def_id.krate != ast::LOCAL_CRATE {
115+
self.tcx.sess.span_err(
116+
item.span,
117+
"cross-crate traits with a default impl \
118+
can only be implemented for a struct/enum type \
119+
defined in the current crate");
120+
}
121+
}
122+
_ => {
123+
self.tcx.sess.span_err(
124+
item.span,
125+
"cross-crate traits with a default impl \
126+
can only be implemented for a struct or enum type");
127+
}
128+
}
129+
}
95130
}
96131
ast::ItemDefaultImpl(..) => {
97132
// "Trait" impl
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2015 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+
#![feature(optin_builtin_traits)]
12+
#![crate_type = "rlib"]
13+
14+
use std::marker::MarkerTrait;
15+
16+
pub trait DefaultedTrait : MarkerTrait { }
17+
impl DefaultedTrait for .. { }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright 2015 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+
// aux-build:typeck-default-trait-impl-cross-crate-coherence-lib.rs
12+
13+
// Test that we do not consider associated types to be sendable without
14+
// some applicable trait bound (and we don't ICE).
15+
16+
#![feature(optin_builtin_traits)]
17+
18+
extern crate "typeck-default-trait-impl-cross-crate-coherence-lib" as lib;
19+
20+
use lib::DefaultedTrait;
21+
22+
struct A;
23+
impl DefaultedTrait for (A,) { }
24+
//~^ ERROR can only be implemented for a struct or enum type
25+
26+
struct B;
27+
impl !DefaultedTrait for (B,) { }
28+
//~^ ERROR can only be implemented for a struct or enum type
29+
30+
struct C;
31+
impl DefaultedTrait for Box<C> { }
32+
//~^ ERROR can only be implemented for a struct or enum type
33+
34+
fn main() { }

0 commit comments

Comments
 (0)