rollup merge of #20594: nikomatsakis/orphan-ordered
Conflicts: src/libsyntax/feature_gate.rs
This commit is contained in:
commit
cf8a11e98b
|
@ -53,12 +53,14 @@ use option::Option;
|
|||
use self::Cow::*;
|
||||
|
||||
/// A trait for borrowing data.
|
||||
#[old_orphan_check]
|
||||
pub trait BorrowFrom<Sized? Owned> for Sized? {
|
||||
/// Immutably borrow from an owned value.
|
||||
fn borrow_from(owned: &Owned) -> &Self;
|
||||
}
|
||||
|
||||
/// A trait for mutably borrowing data.
|
||||
#[old_orphan_check]
|
||||
pub trait BorrowFromMut<Sized? Owned> for Sized? : BorrowFrom<Owned> {
|
||||
/// Mutably borrow from an owned value.
|
||||
fn borrow_from_mut(owned: &mut Owned) -> &mut Self;
|
||||
|
@ -91,6 +93,7 @@ impl<'a, T, Sized? B> BorrowFrom<Cow<'a, T, B>> for B where B: ToOwned<T> {
|
|||
}
|
||||
|
||||
/// Trait for moving into a `Cow`
|
||||
#[old_orphan_check]
|
||||
pub trait IntoCow<'a, T, Sized? B> {
|
||||
/// Moves `self` into `Cow`
|
||||
fn into_cow(self) -> Cow<'a, T, B>;
|
||||
|
@ -103,6 +106,7 @@ impl<'a, T, Sized? B> IntoCow<'a, T, B> for Cow<'a, T, B> where B: ToOwned<T> {
|
|||
}
|
||||
|
||||
/// A generalization of Clone to borrowed data.
|
||||
#[old_orphan_check]
|
||||
pub trait ToOwned<Owned> for Sized?: BorrowFrom<Owned> {
|
||||
/// Create owned data from borrowed data, usually by copying.
|
||||
fn to_owned(&self) -> Owned;
|
||||
|
|
|
@ -69,6 +69,7 @@ use option::Option::{self, Some, None};
|
|||
/// only if `a != b`.
|
||||
#[lang="eq"]
|
||||
#[stable]
|
||||
#[old_orphan_check]
|
||||
pub trait PartialEq<Sized? Rhs = Self> for Sized? {
|
||||
/// This method tests for `self` and `other` values to be equal, and is used by `==`.
|
||||
#[stable]
|
||||
|
|
|
@ -666,6 +666,9 @@ impl LintPass for UnusedAttributes {
|
|||
"must_use",
|
||||
"stable",
|
||||
"unstable",
|
||||
|
||||
// FIXME: #19470 this shouldn't be needed forever
|
||||
"old_orphan_check",
|
||||
];
|
||||
|
||||
static CRATE_ATTRS: &'static [&'static str] = &[
|
||||
|
|
|
@ -14,7 +14,7 @@ use super::SelectionContext;
|
|||
use super::{Obligation, ObligationCause};
|
||||
use super::util;
|
||||
|
||||
use middle::subst::Subst;
|
||||
use middle::subst::{Subst};
|
||||
use middle::ty::{self, Ty};
|
||||
use middle::infer::InferCtxt;
|
||||
use std::collections::HashSet;
|
||||
|
@ -53,20 +53,20 @@ pub fn impl_can_satisfy(infcx: &InferCtxt,
|
|||
}
|
||||
|
||||
#[allow(missing_copy_implementations)]
|
||||
pub enum OrphanCheckErr {
|
||||
pub enum OrphanCheckErr<'tcx> {
|
||||
NoLocalInputType,
|
||||
UncoveredTypeParameter(ty::ParamTy),
|
||||
UncoveredTy(Ty<'tcx>),
|
||||
}
|
||||
|
||||
/// Checks the coherence orphan rules. `impl_def_id` should be the
|
||||
/// def-id of a trait impl. To pass, either the trait must be local, or else
|
||||
/// two conditions must be satisfied:
|
||||
///
|
||||
/// 1. At least one of the input types must involve a local type.
|
||||
/// 2. All type parameters must be covered by a local type.
|
||||
pub fn orphan_check(tcx: &ty::ctxt,
|
||||
impl_def_id: ast::DefId)
|
||||
-> Result<(), OrphanCheckErr>
|
||||
/// 1. All type parameters in `Self` must be "covered" by some local type constructor.
|
||||
/// 2. Some local type must appear in `Self`.
|
||||
pub fn orphan_check<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
impl_def_id: ast::DefId)
|
||||
-> Result<(), OrphanCheckErr<'tcx>>
|
||||
{
|
||||
debug!("impl_is_local({})", impl_def_id.repr(tcx));
|
||||
|
||||
|
@ -82,31 +82,21 @@ pub fn orphan_check(tcx: &ty::ctxt,
|
|||
return Ok(());
|
||||
}
|
||||
|
||||
// Check condition 1: at least one type must be local.
|
||||
if !trait_ref.input_types().iter().any(|&t| ty_reaches_local(tcx, t)) {
|
||||
// Otherwise, check that (1) all type parameters are covered.
|
||||
let covered_params = type_parameters_covered_by_ty(tcx, trait_ref.self_ty());
|
||||
let all_params = type_parameters_reachable_from_ty(trait_ref.self_ty());
|
||||
for ¶m in all_params.difference(&covered_params) {
|
||||
return Err(OrphanCheckErr::UncoveredTy(param));
|
||||
}
|
||||
|
||||
// And (2) some local type appears.
|
||||
if !trait_ref.self_ty().walk().any(|t| ty_is_local_constructor(tcx, t)) {
|
||||
return Err(OrphanCheckErr::NoLocalInputType);
|
||||
}
|
||||
|
||||
// Check condition 2: type parameters must be "covered" by a local type.
|
||||
let covered_params: HashSet<_> =
|
||||
trait_ref.input_types().iter()
|
||||
.flat_map(|&t| type_parameters_covered_by_ty(tcx, t).into_iter())
|
||||
.collect();
|
||||
let all_params: HashSet<_> =
|
||||
trait_ref.input_types().iter()
|
||||
.flat_map(|&t| type_parameters_reachable_from_ty(t).into_iter())
|
||||
.collect();
|
||||
for ¶m in all_params.difference(&covered_params) {
|
||||
return Err(OrphanCheckErr::UncoveredTypeParameter(param));
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
fn ty_reaches_local<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
|
||||
ty.walk().any(|t| ty_is_local_constructor(tcx, t))
|
||||
}
|
||||
|
||||
fn ty_is_local_constructor<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
|
||||
debug!("ty_is_local_constructor({})", ty.repr(tcx));
|
||||
|
||||
|
@ -153,8 +143,8 @@ fn ty_is_local_constructor<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
|
|||
}
|
||||
|
||||
fn type_parameters_covered_by_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
ty: Ty<'tcx>)
|
||||
-> HashSet<ty::ParamTy>
|
||||
ty: Ty<'tcx>)
|
||||
-> HashSet<Ty<'tcx>>
|
||||
{
|
||||
if ty_is_local_constructor(tcx, ty) {
|
||||
type_parameters_reachable_from_ty(ty)
|
||||
|
@ -164,14 +154,14 @@ fn type_parameters_covered_by_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
|
|||
}
|
||||
|
||||
/// All type parameters reachable from `ty`
|
||||
fn type_parameters_reachable_from_ty<'tcx>(ty: Ty<'tcx>) -> HashSet<ty::ParamTy> {
|
||||
fn type_parameters_reachable_from_ty<'tcx>(ty: Ty<'tcx>) -> HashSet<Ty<'tcx>> {
|
||||
ty.walk()
|
||||
.filter_map(|t| {
|
||||
.filter(|&t| {
|
||||
match t.sty {
|
||||
ty::ty_param(ref param_ty) => Some(param_ty.clone()),
|
||||
_ => None,
|
||||
// FIXME(#20590) straighten story about projection types
|
||||
ty::ty_projection(..) | ty::ty_param(..) => true,
|
||||
_ => false,
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ use super::TupleArgumentsFlag;
|
|||
use super::write_call;
|
||||
|
||||
use middle::infer;
|
||||
use middle::ty::{mod, Ty};
|
||||
use middle::ty::{self, Ty};
|
||||
use syntax::ast;
|
||||
use syntax::codemap::Span;
|
||||
use syntax::parse::token;
|
||||
|
|
|
@ -72,20 +72,30 @@ 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;
|
||||
match traits::orphan_check(self.tcx, def_id) {
|
||||
Ok(()) => { }
|
||||
Err(traits::OrphanCheckErr::NoLocalInputType) => {
|
||||
span_err!(self.tcx.sess, item.span, E0117,
|
||||
"cannot provide an extension implementation \
|
||||
where both trait and type are not defined in this crate");
|
||||
if !ty::has_attr(self.tcx, trait_def_id, "old_orphan_check") {
|
||||
let self_ty = ty::lookup_item_type(self.tcx, def_id).ty;
|
||||
span_err!(
|
||||
self.tcx.sess, item.span, E0117,
|
||||
"the type `{}` does not reference any \
|
||||
types defined in this crate; \
|
||||
only traits defined in the current crate can be \
|
||||
implemented for arbitrary types",
|
||||
self_ty.user_string(self.tcx));
|
||||
}
|
||||
}
|
||||
Err(traits::OrphanCheckErr::UncoveredTypeParameter(param_ty)) => {
|
||||
if !self.tcx.sess.features.borrow().old_orphan_check {
|
||||
Err(traits::OrphanCheckErr::UncoveredTy(param_ty)) => {
|
||||
if !ty::has_attr(self.tcx, trait_def_id, "old_orphan_check") {
|
||||
self.tcx.sess.span_err(
|
||||
item.span,
|
||||
format!("type parameter `{}` must also appear as a type parameter \
|
||||
of some type defined within this crate",
|
||||
param_ty.user_string(self.tcx)).as_slice());
|
||||
format!(
|
||||
"type parameter `{}` is not constrained by any local type; \
|
||||
only traits defined in the current crate can be implemented \
|
||||
for a type parameter",
|
||||
param_ty.user_string(self.tcx)).as_slice());
|
||||
self.tcx.sess.span_note(
|
||||
item.span,
|
||||
format!("for a limited time, you can add \
|
||||
|
|
|
@ -305,6 +305,26 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
|
|||
many unsafe patterns and may be \
|
||||
removed in the future");
|
||||
}
|
||||
|
||||
if attr::contains_name(i.attrs[],
|
||||
"old_orphan_check") {
|
||||
self.gate_feature(
|
||||
"old_orphan_check",
|
||||
i.span,
|
||||
"the new orphan check rules will eventually be strictly enforced");
|
||||
}
|
||||
|
||||
for item in items.iter() {
|
||||
match *item {
|
||||
ast::MethodImplItem(_) => {}
|
||||
ast::TypeImplItem(ref typedef) => {
|
||||
self.gate_feature("associated_types",
|
||||
typedef.span,
|
||||
"associated types are \
|
||||
experimental")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ => {}
|
||||
|
|
|
@ -14,6 +14,6 @@ extern crate "coherence-lib" as lib;
|
|||
use lib::Remote;
|
||||
|
||||
impl<T> Remote for int { }
|
||||
//~^ ERROR cannot provide an extension implementation
|
||||
//~^ ERROR E0117
|
||||
|
||||
fn main() { }
|
||||
|
|
|
@ -15,6 +15,6 @@ use lib::Remote1;
|
|||
|
||||
pub struct BigInt;
|
||||
|
||||
impl Remote1<BigInt> for int { }
|
||||
impl Remote1<BigInt> for int { } //~ ERROR E0117
|
||||
|
||||
fn main() { }
|
|
@ -16,6 +16,6 @@ use lib::Remote1;
|
|||
pub struct BigInt;
|
||||
|
||||
impl<T> Remote1<BigInt> for T { }
|
||||
//~^ ERROR type parameter `T` must also appear
|
||||
//~^ ERROR type parameter `T` is not constrained
|
||||
|
||||
fn main() { }
|
||||
|
|
|
@ -15,6 +15,6 @@ use lib::Remote1;
|
|||
|
||||
pub struct BigInt;
|
||||
|
||||
impl Remote1<BigInt> for Vec<int> { }
|
||||
impl Remote1<BigInt> for Vec<int> { } //~ ERROR E0117
|
||||
|
||||
fn main() { }
|
|
@ -16,7 +16,7 @@ extern crate trait_impl_conflict;
|
|||
use trait_impl_conflict::Foo;
|
||||
|
||||
impl<A> Foo for A {
|
||||
//~^ ERROR E0117
|
||||
//~^ ERROR type parameter `A` is not constrained
|
||||
//~^^ ERROR E0119
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,6 @@
|
|||
extern crate "coherence-lib" as lib;
|
||||
use lib::Remote;
|
||||
|
||||
impl<T> Remote for T { } //~ ERROR E0117
|
||||
impl<T> Remote for T { } //~ ERROR type parameter `T` is not constrained
|
||||
|
||||
fn main() { }
|
||||
|
|
|
@ -18,7 +18,7 @@ struct TheType;
|
|||
|
||||
impl TheTrait<uint> for int { } //~ ERROR E0117
|
||||
|
||||
impl TheTrait<TheType> for int { }
|
||||
impl TheTrait<TheType> for int { } //~ ERROR E0117
|
||||
|
||||
impl TheTrait<int> for TheType { }
|
||||
|
||||
|
|
|
@ -16,6 +16,6 @@ use lib::Remote;
|
|||
struct Foo;
|
||||
|
||||
impl<T> Remote for lib::Pair<T,Foo> { }
|
||||
//~^ ERROR type parameter `T` must also appear
|
||||
//~^ ERROR type parameter `T` is not constrained
|
||||
|
||||
fn main() { }
|
||||
|
|
|
@ -16,6 +16,6 @@ use lib::{Remote, Pair};
|
|||
struct Local<T>(T);
|
||||
|
||||
impl<T,U> Remote for Pair<T,Local<U>> { }
|
||||
//~^ ERROR type parameter `T` must also appear
|
||||
//~^ ERROR type parameter `T` is not constrained
|
||||
|
||||
fn main() { }
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
impl Drop for int {
|
||||
//~^ ERROR the Drop trait may only be implemented on structures
|
||||
//~^^ ERROR cannot provide an extension implementation
|
||||
//~^^ ERROR E0117
|
||||
fn drop(&mut self) {
|
||||
println!("kaboom");
|
||||
}
|
||||
|
|
|
@ -16,6 +16,5 @@ use lib::Remote1;
|
|||
struct Foo<T>(T);
|
||||
|
||||
impl<T,U> Remote1<U> for Foo<T> { }
|
||||
//~^ ERROR type parameter `U` must also appear
|
||||
|
||||
fn main() { }
|
Loading…
Reference in New Issue