Skip to content

Commit cf8a11e

Browse files
committed
rollup merge of #20594: nikomatsakis/orphan-ordered
Conflicts: src/libsyntax/feature_gate.rs
2 parents f3ad232 + 6e68fd0 commit cf8a11e

18 files changed

+80
-53
lines changed

src/libcore/borrow.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,14 @@ use option::Option;
5353
use self::Cow::*;
5454

5555
/// A trait for borrowing data.
56+
#[old_orphan_check]
5657
pub trait BorrowFrom<Sized? Owned> for Sized? {
5758
/// Immutably borrow from an owned value.
5859
fn borrow_from(owned: &Owned) -> &Self;
5960
}
6061

6162
/// A trait for mutably borrowing data.
63+
#[old_orphan_check]
6264
pub trait BorrowFromMut<Sized? Owned> for Sized? : BorrowFrom<Owned> {
6365
/// Mutably borrow from an owned value.
6466
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> {
9193
}
9294

9395
/// Trait for moving into a `Cow`
96+
#[old_orphan_check]
9497
pub trait IntoCow<'a, T, Sized? B> {
9598
/// Moves `self` into `Cow`
9699
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> {
103106
}
104107

105108
/// A generalization of Clone to borrowed data.
109+
#[old_orphan_check]
106110
pub trait ToOwned<Owned> for Sized?: BorrowFrom<Owned> {
107111
/// Create owned data from borrowed data, usually by copying.
108112
fn to_owned(&self) -> Owned;

src/libcore/cmp.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ use option::Option::{self, Some, None};
6969
/// only if `a != b`.
7070
#[lang="eq"]
7171
#[stable]
72+
#[old_orphan_check]
7273
pub trait PartialEq<Sized? Rhs = Self> for Sized? {
7374
/// This method tests for `self` and `other` values to be equal, and is used by `==`.
7475
#[stable]

src/librustc/lint/builtin.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,9 @@ impl LintPass for UnusedAttributes {
666666
"must_use",
667667
"stable",
668668
"unstable",
669+
670+
// FIXME: #19470 this shouldn't be needed forever
671+
"old_orphan_check",
669672
];
670673

671674
static CRATE_ATTRS: &'static [&'static str] = &[

src/librustc/middle/traits/coherence.rs

Lines changed: 23 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use super::SelectionContext;
1414
use super::{Obligation, ObligationCause};
1515
use super::util;
1616

17-
use middle::subst::Subst;
17+
use middle::subst::{Subst};
1818
use middle::ty::{self, Ty};
1919
use middle::infer::InferCtxt;
2020
use std::collections::HashSet;
@@ -53,20 +53,20 @@ pub fn impl_can_satisfy(infcx: &InferCtxt,
5353
}
5454

5555
#[allow(missing_copy_implementations)]
56-
pub enum OrphanCheckErr {
56+
pub enum OrphanCheckErr<'tcx> {
5757
NoLocalInputType,
58-
UncoveredTypeParameter(ty::ParamTy),
58+
UncoveredTy(Ty<'tcx>),
5959
}
6060

6161
/// Checks the coherence orphan rules. `impl_def_id` should be the
6262
/// def-id of a trait impl. To pass, either the trait must be local, or else
6363
/// two conditions must be satisfied:
6464
///
65-
/// 1. At least one of the input types must involve a local type.
66-
/// 2. All type parameters must be covered by a local type.
67-
pub fn orphan_check(tcx: &ty::ctxt,
68-
impl_def_id: ast::DefId)
69-
-> Result<(), OrphanCheckErr>
65+
/// 1. All type parameters in `Self` must be "covered" by some local type constructor.
66+
/// 2. Some local type must appear in `Self`.
67+
pub fn orphan_check<'tcx>(tcx: &ty::ctxt<'tcx>,
68+
impl_def_id: ast::DefId)
69+
-> Result<(), OrphanCheckErr<'tcx>>
7070
{
7171
debug!("impl_is_local({})", impl_def_id.repr(tcx));
7272

@@ -82,31 +82,21 @@ pub fn orphan_check(tcx: &ty::ctxt,
8282
return Ok(());
8383
}
8484

85-
// Check condition 1: at least one type must be local.
86-
if !trait_ref.input_types().iter().any(|&t| ty_reaches_local(tcx, t)) {
87-
return Err(OrphanCheckErr::NoLocalInputType);
85+
// Otherwise, check that (1) all type parameters are covered.
86+
let covered_params = type_parameters_covered_by_ty(tcx, trait_ref.self_ty());
87+
let all_params = type_parameters_reachable_from_ty(trait_ref.self_ty());
88+
for &param in all_params.difference(&covered_params) {
89+
return Err(OrphanCheckErr::UncoveredTy(param));
8890
}
8991

90-
// Check condition 2: type parameters must be "covered" by a local type.
91-
let covered_params: HashSet<_> =
92-
trait_ref.input_types().iter()
93-
.flat_map(|&t| type_parameters_covered_by_ty(tcx, t).into_iter())
94-
.collect();
95-
let all_params: HashSet<_> =
96-
trait_ref.input_types().iter()
97-
.flat_map(|&t| type_parameters_reachable_from_ty(t).into_iter())
98-
.collect();
99-
for &param in all_params.difference(&covered_params) {
100-
return Err(OrphanCheckErr::UncoveredTypeParameter(param));
92+
// And (2) some local type appears.
93+
if !trait_ref.self_ty().walk().any(|t| ty_is_local_constructor(tcx, t)) {
94+
return Err(OrphanCheckErr::NoLocalInputType);
10195
}
10296

10397
return Ok(());
10498
}
10599

106-
fn ty_reaches_local<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
107-
ty.walk().any(|t| ty_is_local_constructor(tcx, t))
108-
}
109-
110100
fn ty_is_local_constructor<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
111101
debug!("ty_is_local_constructor({})", ty.repr(tcx));
112102

@@ -153,8 +143,8 @@ fn ty_is_local_constructor<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
153143
}
154144

155145
fn type_parameters_covered_by_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
156-
ty: Ty<'tcx>)
157-
-> HashSet<ty::ParamTy>
146+
ty: Ty<'tcx>)
147+
-> HashSet<Ty<'tcx>>
158148
{
159149
if ty_is_local_constructor(tcx, ty) {
160150
type_parameters_reachable_from_ty(ty)
@@ -164,14 +154,14 @@ fn type_parameters_covered_by_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
164154
}
165155

166156
/// All type parameters reachable from `ty`
167-
fn type_parameters_reachable_from_ty<'tcx>(ty: Ty<'tcx>) -> HashSet<ty::ParamTy> {
157+
fn type_parameters_reachable_from_ty<'tcx>(ty: Ty<'tcx>) -> HashSet<Ty<'tcx>> {
168158
ty.walk()
169-
.filter_map(|t| {
159+
.filter(|&t| {
170160
match t.sty {
171-
ty::ty_param(ref param_ty) => Some(param_ty.clone()),
172-
_ => None,
161+
// FIXME(#20590) straighten story about projection types
162+
ty::ty_projection(..) | ty::ty_param(..) => true,
163+
_ => false,
173164
}
174165
})
175166
.collect()
176167
}
177-

src/librustc_typeck/check/callee.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use super::TupleArgumentsFlag;
2222
use super::write_call;
2323

2424
use middle::infer;
25-
use middle::ty::{mod, Ty};
25+
use middle::ty::{self, Ty};
2626
use syntax::ast;
2727
use syntax::codemap::Span;
2828
use syntax::parse::token;

src/librustc_typeck/coherence/orphan.rs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,20 +72,30 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
7272
ast::ItemImpl(_, _, _, Some(_), _, _) => {
7373
// "Trait" impl
7474
debug!("coherence2::orphan check: trait impl {}", item.repr(self.tcx));
75+
let trait_def_id = ty::impl_trait_ref(self.tcx, def_id).unwrap().def_id;
7576
match traits::orphan_check(self.tcx, def_id) {
7677
Ok(()) => { }
7778
Err(traits::OrphanCheckErr::NoLocalInputType) => {
78-
span_err!(self.tcx.sess, item.span, E0117,
79-
"cannot provide an extension implementation \
80-
where both trait and type are not defined in this crate");
79+
if !ty::has_attr(self.tcx, trait_def_id, "old_orphan_check") {
80+
let self_ty = ty::lookup_item_type(self.tcx, def_id).ty;
81+
span_err!(
82+
self.tcx.sess, item.span, E0117,
83+
"the type `{}` does not reference any \
84+
types defined in this crate; \
85+
only traits defined in the current crate can be \
86+
implemented for arbitrary types",
87+
self_ty.user_string(self.tcx));
88+
}
8189
}
82-
Err(traits::OrphanCheckErr::UncoveredTypeParameter(param_ty)) => {
83-
if !self.tcx.sess.features.borrow().old_orphan_check {
90+
Err(traits::OrphanCheckErr::UncoveredTy(param_ty)) => {
91+
if !ty::has_attr(self.tcx, trait_def_id, "old_orphan_check") {
8492
self.tcx.sess.span_err(
8593
item.span,
86-
format!("type parameter `{}` must also appear as a type parameter \
87-
of some type defined within this crate",
88-
param_ty.user_string(self.tcx)).as_slice());
94+
format!(
95+
"type parameter `{}` is not constrained by any local type; \
96+
only traits defined in the current crate can be implemented \
97+
for a type parameter",
98+
param_ty.user_string(self.tcx)).as_slice());
8999
self.tcx.sess.span_note(
90100
item.span,
91101
format!("for a limited time, you can add \

src/libsyntax/feature_gate.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,26 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
305305
many unsafe patterns and may be \
306306
removed in the future");
307307
}
308+
309+
if attr::contains_name(i.attrs[],
310+
"old_orphan_check") {
311+
self.gate_feature(
312+
"old_orphan_check",
313+
i.span,
314+
"the new orphan check rules will eventually be strictly enforced");
315+
}
316+
317+
for item in items.iter() {
318+
match *item {
319+
ast::MethodImplItem(_) => {}
320+
ast::TypeImplItem(ref typedef) => {
321+
self.gate_feature("associated_types",
322+
typedef.span,
323+
"associated types are \
324+
experimental")
325+
}
326+
}
327+
}
308328
}
309329

310330
_ => {}

src/test/compile-fail/coherence-all-remote.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ extern crate "coherence-lib" as lib;
1414
use lib::Remote;
1515

1616
impl<T> Remote for int { }
17-
//~^ ERROR cannot provide an extension implementation
17+
//~^ ERROR E0117
1818

1919
fn main() { }

src/test/run-pass/coherence-bigint-int.rs renamed to src/test/compile-fail/coherence-bigint-int.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@ use lib::Remote1;
1515

1616
pub struct BigInt;
1717

18-
impl Remote1<BigInt> for int { }
18+
impl Remote1<BigInt> for int { } //~ ERROR E0117
1919

2020
fn main() { }

src/test/compile-fail/coherence-bigint-param.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@ use lib::Remote1;
1616
pub struct BigInt;
1717

1818
impl<T> Remote1<BigInt> for T { }
19-
//~^ ERROR type parameter `T` must also appear
19+
//~^ ERROR type parameter `T` is not constrained
2020

2121
fn main() { }

src/test/run-pass/coherence-bigint-vecint.rs renamed to src/test/compile-fail/coherence-bigint-vecint.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@ use lib::Remote1;
1515

1616
pub struct BigInt;
1717

18-
impl Remote1<BigInt> for Vec<int> { }
18+
impl Remote1<BigInt> for Vec<int> { } //~ ERROR E0117
1919

2020
fn main() { }

src/test/compile-fail/coherence-cross-crate-conflict.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ extern crate trait_impl_conflict;
1616
use trait_impl_conflict::Foo;
1717

1818
impl<A> Foo for A {
19-
//~^ ERROR E0117
19+
//~^ ERROR type parameter `A` is not constrained
2020
//~^^ ERROR E0119
2121
}
2222

src/test/compile-fail/coherence-lone-type-parameter.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,6 @@
1313
extern crate "coherence-lib" as lib;
1414
use lib::Remote;
1515

16-
impl<T> Remote for T { } //~ ERROR E0117
16+
impl<T> Remote for T { } //~ ERROR type parameter `T` is not constrained
1717

1818
fn main() { }

src/test/compile-fail/coherence-orphan.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ struct TheType;
1818

1919
impl TheTrait<uint> for int { } //~ ERROR E0117
2020

21-
impl TheTrait<TheType> for int { }
21+
impl TheTrait<TheType> for int { } //~ ERROR E0117
2222

2323
impl TheTrait<int> for TheType { }
2424

src/test/compile-fail/coherence-overlapping-pairs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@ use lib::Remote;
1616
struct Foo;
1717

1818
impl<T> Remote for lib::Pair<T,Foo> { }
19-
//~^ ERROR type parameter `T` must also appear
19+
//~^ ERROR type parameter `T` is not constrained
2020

2121
fn main() { }

src/test/compile-fail/coherence-pair-covered-uncovered.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@ use lib::{Remote, Pair};
1616
struct Local<T>(T);
1717

1818
impl<T,U> Remote for Pair<T,Local<U>> { }
19-
//~^ ERROR type parameter `T` must also appear
19+
//~^ ERROR type parameter `T` is not constrained
2020

2121
fn main() { }

src/test/compile-fail/drop-on-non-struct.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
impl Drop for int {
1212
//~^ ERROR the Drop trait may only be implemented on structures
13-
//~^^ ERROR cannot provide an extension implementation
13+
//~^^ ERROR E0117
1414
fn drop(&mut self) {
1515
println!("kaboom");
1616
}

src/test/compile-fail/coherence-iterator-vec-any-elem.rs renamed to src/test/run-pass/coherence-iterator-vec-any-elem.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,5 @@ use lib::Remote1;
1616
struct Foo<T>(T);
1717

1818
impl<T,U> Remote1<U> for Foo<T> { }
19-
//~^ ERROR type parameter `U` must also appear
2019

2120
fn main() { }

0 commit comments

Comments
 (0)