Add stricter orphan rules for cross-crate impls of default traits.
This commit is contained in:
parent
dbec033e29
commit
2e216896e4
3 changed files with 87 additions and 1 deletions
|
@ -69,7 +69,8 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
|
||||||
ast::ItemImpl(_, _, _, Some(_), _, _) => {
|
ast::ItemImpl(_, _, _, Some(_), _, _) => {
|
||||||
// "Trait" impl
|
// "Trait" impl
|
||||||
debug!("coherence2::orphan check: trait impl {}", item.repr(self.tcx));
|
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) {
|
match traits::orphan_check(self.tcx, def_id) {
|
||||||
Ok(()) => { }
|
Ok(()) => { }
|
||||||
Err(traits::OrphanCheckErr::NoLocalInputType) => {
|
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<SomethingLocal>`, 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(..) => {
|
ast::ItemDefaultImpl(..) => {
|
||||||
// "Trait" impl
|
// "Trait" impl
|
||||||
|
|
|
@ -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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 .. { }
|
|
@ -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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<C> { }
|
||||||
|
//~^ ERROR can only be implemented for a struct or enum type
|
||||||
|
|
||||||
|
fn main() { }
|
Loading…
Add table
Add a link
Reference in a new issue