Fix orphan checking (cc #19470). (This is not a complete fix of #19470 because of the backwards compatibility feature gate.)
This is a [breaking-change]. The new rules require that, for an impl of a trait defined in some other crate, two conditions must hold: 1. Some type must be local. 2. Every type parameter must appear "under" some local type. Here are some examples that are legal: ```rust struct MyStruct<T> { ... } // Here `T` appears "under' `MyStruct`. impl<T> Clone for MyStruct<T> { } // Here `T` appears "under' `MyStruct` as well. Note that it also appears // elsewhere. impl<T> Iterator<T> for MyStruct<T> { } ``` Here is an illegal example: ```rust // Here `U` does not appear "under" `MyStruct` or any other local type. // We call `U` "uncovered". impl<T,U> Iterator<U> for MyStruct<T> { } ``` There are a couple of ways to rewrite this last example so that it is legal: 1. In some cases, the uncovered type parameter (here, `U`) should be converted into an associated type. This is however a non-local change that requires access to the original trait. Also, associated types are not fully baked. 2. Add `U` as a type parameter of `MyStruct`: ```rust struct MyStruct<T,U> { ... } impl<T,U> Iterator<U> for MyStruct<T,U> { } ``` 3. Create a newtype wrapper for `U` ```rust impl<T,U> Iterator<Wrapper<U>> for MyStruct<T,U> { } ``` Because associated types are not fully baked, which in the case of the `Hash` trait makes adhering to this rule impossible, you can temporarily disable this rule in your crate by using `#![feature(old_orphan_check)]`. Note that the `old_orphan_check` feature will be removed before 1.0 is released.
This commit is contained in:
parent
77723d24a8
commit
c61a0092bc
@ -64,7 +64,8 @@
|
|||||||
html_root_url = "http://doc.rust-lang.org/nightly/")]
|
html_root_url = "http://doc.rust-lang.org/nightly/")]
|
||||||
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![feature(lang_items, phase, unsafe_destructor, default_type_params)]
|
#![allow(unknown_features)]
|
||||||
|
#![feature(lang_items, phase, unsafe_destructor, default_type_params, old_orphan_check)]
|
||||||
|
|
||||||
#[phase(plugin, link)]
|
#[phase(plugin, link)]
|
||||||
extern crate core;
|
extern crate core;
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#![feature(macro_rules, default_type_params, phase, globs)]
|
#![feature(macro_rules, default_type_params, phase, globs)]
|
||||||
#![feature(unsafe_destructor, slicing_syntax)]
|
#![feature(unsafe_destructor, slicing_syntax)]
|
||||||
#![feature(unboxed_closures)]
|
#![feature(unboxed_closures)]
|
||||||
|
#![feature(old_orphan_check)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
#[phase(plugin, link)] extern crate core;
|
#[phase(plugin, link)] extern crate core;
|
||||||
|
@ -96,9 +96,9 @@ impl<'a, T: Ord> Ord for MaybeOwnedVector<'a, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
impl<'a, T: PartialEq, Sized? V: AsSlice<T>> Equiv<V> for MaybeOwnedVector<'a, T> {
|
impl<'a, T: PartialEq> Equiv<[T]> for MaybeOwnedVector<'a, T> {
|
||||||
fn equiv(&self, other: &V) -> bool {
|
fn equiv(&self, other: &[T]) -> bool {
|
||||||
self.as_slice() == other.as_slice()
|
self.as_slice() == other
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,10 +22,12 @@
|
|||||||
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
|
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
|
||||||
html_root_url = "http://doc.rust-lang.org/nightly/")]
|
html_root_url = "http://doc.rust-lang.org/nightly/")]
|
||||||
|
|
||||||
|
#![allow(unknown_features)]
|
||||||
#![feature(default_type_params, globs, macro_rules, phase, quote)]
|
#![feature(default_type_params, globs, macro_rules, phase, quote)]
|
||||||
#![feature(slicing_syntax, unsafe_destructor)]
|
#![feature(slicing_syntax, unsafe_destructor)]
|
||||||
#![feature(rustc_diagnostic_macros)]
|
#![feature(rustc_diagnostic_macros)]
|
||||||
#![feature(unboxed_closures)]
|
#![feature(unboxed_closures)]
|
||||||
|
#![feature(old_orphan_check)]
|
||||||
|
|
||||||
extern crate arena;
|
extern crate arena;
|
||||||
extern crate flate;
|
extern crate flate;
|
||||||
|
@ -14,10 +14,10 @@ use super::SelectionContext;
|
|||||||
use super::{Obligation, ObligationCause};
|
use super::{Obligation, ObligationCause};
|
||||||
use super::util;
|
use super::util;
|
||||||
|
|
||||||
use middle::subst;
|
|
||||||
use middle::subst::Subst;
|
use middle::subst::Subst;
|
||||||
use middle::ty::{mod, Ty};
|
use middle::ty::{mod, Ty};
|
||||||
use middle::infer::InferCtxt;
|
use middle::infer::InferCtxt;
|
||||||
|
use std::collections::HashSet;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::codemap::DUMMY_SP;
|
use syntax::codemap::DUMMY_SP;
|
||||||
@ -52,9 +52,21 @@ pub fn impl_can_satisfy(infcx: &InferCtxt,
|
|||||||
selcx.evaluate_impl(impl2_def_id, &obligation)
|
selcx.evaluate_impl(impl2_def_id, &obligation)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn impl_is_local(tcx: &ty::ctxt,
|
#[allow(missing_copy_implementations)]
|
||||||
impl_def_id: ast::DefId)
|
pub enum OrphanCheckErr {
|
||||||
-> bool
|
NoLocalInputType,
|
||||||
|
UncoveredTypeParameter(ty::ParamTy),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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>
|
||||||
{
|
{
|
||||||
debug!("impl_is_local({})", impl_def_id.repr(tcx));
|
debug!("impl_is_local({})", impl_def_id.repr(tcx));
|
||||||
|
|
||||||
@ -63,20 +75,40 @@ pub fn impl_is_local(tcx: &ty::ctxt,
|
|||||||
let trait_ref = ty::impl_trait_ref(tcx, impl_def_id).unwrap();
|
let trait_ref = ty::impl_trait_ref(tcx, impl_def_id).unwrap();
|
||||||
debug!("trait_ref={}", trait_ref.repr(tcx));
|
debug!("trait_ref={}", trait_ref.repr(tcx));
|
||||||
|
|
||||||
// If the trait is local to the crate, ok.
|
// If the *trait* is local to the crate, ok.
|
||||||
if trait_ref.def_id.krate == ast::LOCAL_CRATE {
|
if trait_ref.def_id.krate == ast::LOCAL_CRATE {
|
||||||
debug!("trait {} is local to current crate",
|
debug!("trait {} is local to current crate",
|
||||||
trait_ref.def_id.repr(tcx));
|
trait_ref.def_id.repr(tcx));
|
||||||
return true;
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, at least one of the input types must be local to the
|
// Check condition 1: at least one type must be local.
|
||||||
// crate.
|
if !trait_ref.input_types().iter().any(|&t| ty_reaches_local(tcx, t)) {
|
||||||
trait_ref.input_types().iter().any(|&t| ty_is_local(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(());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ty_is_local<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
|
fn ty_reaches_local<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
|
||||||
debug!("ty_is_local({})", ty.repr(tcx));
|
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));
|
||||||
|
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
ty::ty_bool |
|
ty::ty_bool |
|
||||||
@ -84,78 +116,33 @@ pub fn ty_is_local<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
|
|||||||
ty::ty_int(..) |
|
ty::ty_int(..) |
|
||||||
ty::ty_uint(..) |
|
ty::ty_uint(..) |
|
||||||
ty::ty_float(..) |
|
ty::ty_float(..) |
|
||||||
ty::ty_str(..) => {
|
ty::ty_str(..) |
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
ty::ty_unboxed_closure(..) => {
|
|
||||||
// This routine is invoked on types specified by users as
|
|
||||||
// part of an impl and hence an unboxed closure type
|
|
||||||
// cannot appear.
|
|
||||||
tcx.sess.bug("ty_is_local applied to unboxed closure type")
|
|
||||||
}
|
|
||||||
|
|
||||||
ty::ty_bare_fn(..) |
|
ty::ty_bare_fn(..) |
|
||||||
ty::ty_closure(..) => {
|
ty::ty_closure(..) |
|
||||||
|
ty::ty_vec(..) |
|
||||||
|
ty::ty_ptr(..) |
|
||||||
|
ty::ty_rptr(..) |
|
||||||
|
ty::ty_tup(..) |
|
||||||
|
ty::ty_param(..) |
|
||||||
|
ty::ty_projection(..) => {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::ty_uniq(t) => {
|
ty::ty_enum(def_id, _) |
|
||||||
|
ty::ty_struct(def_id, _) => {
|
||||||
|
def_id.krate == ast::LOCAL_CRATE
|
||||||
|
}
|
||||||
|
|
||||||
|
ty::ty_uniq(_) => { // treat ~T like Box<T>
|
||||||
let krate = tcx.lang_items.owned_box().map(|d| d.krate);
|
let krate = tcx.lang_items.owned_box().map(|d| d.krate);
|
||||||
krate == Some(ast::LOCAL_CRATE) || ty_is_local(tcx, t)
|
krate == Some(ast::LOCAL_CRATE)
|
||||||
}
|
|
||||||
|
|
||||||
ty::ty_vec(t, _) |
|
|
||||||
ty::ty_ptr(ty::mt { ty: t, .. }) |
|
|
||||||
ty::ty_rptr(_, ty::mt { ty: t, .. }) => {
|
|
||||||
ty_is_local(tcx, t)
|
|
||||||
}
|
|
||||||
|
|
||||||
ty::ty_tup(ref ts) => {
|
|
||||||
ts.iter().any(|&t| ty_is_local(tcx, t))
|
|
||||||
}
|
|
||||||
|
|
||||||
ty::ty_enum(def_id, ref substs) |
|
|
||||||
ty::ty_struct(def_id, ref substs) => {
|
|
||||||
def_id.krate == ast::LOCAL_CRATE || {
|
|
||||||
let variances = ty::item_variances(tcx, def_id);
|
|
||||||
subst::ParamSpace::all().iter().any(|&space| {
|
|
||||||
substs.types.get_slice(space).iter().enumerate().any(
|
|
||||||
|(i, &t)| {
|
|
||||||
match *variances.types.get(space, i) {
|
|
||||||
ty::Bivariant => {
|
|
||||||
// If Foo<T> is bivariant with respect to
|
|
||||||
// T, then it doesn't matter whether T is
|
|
||||||
// local or not, because `Foo<U>` for any
|
|
||||||
// U will be a subtype of T.
|
|
||||||
false
|
|
||||||
}
|
|
||||||
ty::Contravariant |
|
|
||||||
ty::Covariant |
|
|
||||||
ty::Invariant => {
|
|
||||||
ty_is_local(tcx, t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::ty_trait(ref tt) => {
|
ty::ty_trait(ref tt) => {
|
||||||
tt.principal_def_id().krate == ast::LOCAL_CRATE
|
tt.principal_def_id().krate == ast::LOCAL_CRATE
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type parameters may be bound to types that are not local to
|
ty::ty_unboxed_closure(..) |
|
||||||
// the crate.
|
|
||||||
ty::ty_param(..) => {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Associated types could be anything, I guess.
|
|
||||||
ty::ty_projection(..) => {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
ty::ty_infer(..) |
|
ty::ty_infer(..) |
|
||||||
ty::ty_open(..) |
|
ty::ty_open(..) |
|
||||||
ty::ty_err => {
|
ty::ty_err => {
|
||||||
@ -165,3 +152,27 @@ pub fn ty_is_local<'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>
|
||||||
|
{
|
||||||
|
if ty_is_local_constructor(tcx, ty) {
|
||||||
|
type_parameters_reachable_from_ty(ty)
|
||||||
|
} else {
|
||||||
|
ty.walk_children().flat_map(|t| type_parameters_covered_by_ty(tcx, t).into_iter()).collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// All type parameters reachable from `ty`
|
||||||
|
fn type_parameters_reachable_from_ty<'tcx>(ty: Ty<'tcx>) -> HashSet<ty::ParamTy> {
|
||||||
|
ty.walk()
|
||||||
|
.filter_map(|t| {
|
||||||
|
match t.sty {
|
||||||
|
ty::ty_param(ref param_ty) => Some(param_ty.clone()),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -25,6 +25,8 @@ use syntax::codemap::{Span, DUMMY_SP};
|
|||||||
use util::ppaux::Repr;
|
use util::ppaux::Repr;
|
||||||
|
|
||||||
pub use self::error_reporting::report_fulfillment_errors;
|
pub use self::error_reporting::report_fulfillment_errors;
|
||||||
|
pub use self::coherence::orphan_check;
|
||||||
|
pub use self::coherence::OrphanCheckErr;
|
||||||
pub use self::fulfill::{FulfillmentContext, RegionObligation};
|
pub use self::fulfill::{FulfillmentContext, RegionObligation};
|
||||||
pub use self::project::MismatchedProjectionTypes;
|
pub use self::project::MismatchedProjectionTypes;
|
||||||
pub use self::project::normalize;
|
pub use self::project::normalize;
|
||||||
@ -245,15 +247,6 @@ pub struct VtableBuiltinData<N> {
|
|||||||
pub nested: subst::VecPerParamSpace<N>
|
pub nested: subst::VecPerParamSpace<N>
|
||||||
}
|
}
|
||||||
|
|
||||||
/// True if neither the trait nor self type is local. Note that `impl_def_id` must refer to an impl
|
|
||||||
/// of a trait, not an inherent impl.
|
|
||||||
pub fn is_orphan_impl(tcx: &ty::ctxt,
|
|
||||||
impl_def_id: ast::DefId)
|
|
||||||
-> bool
|
|
||||||
{
|
|
||||||
!coherence::impl_is_local(tcx, impl_def_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// True if there exist types that satisfy both of the two given impls.
|
/// True if there exist types that satisfy both of the two given impls.
|
||||||
pub fn overlapping_impls(infcx: &InferCtxt,
|
pub fn overlapping_impls(infcx: &InferCtxt,
|
||||||
impl1_def_id: ast::DefId,
|
impl1_def_id: ast::DefId,
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#![allow(unknown_features)]
|
#![allow(unknown_features)]
|
||||||
#![feature(globs, phase, macro_rules, slicing_syntax)]
|
#![feature(globs, phase, macro_rules, slicing_syntax)]
|
||||||
#![feature(unboxed_closures)]
|
#![feature(unboxed_closures)]
|
||||||
|
#![feature(old_orphan_check)]
|
||||||
|
|
||||||
#[phase(plugin, link)]
|
#[phase(plugin, link)]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
@ -16,10 +16,12 @@
|
|||||||
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
|
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
|
||||||
html_root_url = "http://doc.rust-lang.org/nightly/")]
|
html_root_url = "http://doc.rust-lang.org/nightly/")]
|
||||||
|
|
||||||
|
#![allow(unknown_features)]
|
||||||
#![feature(default_type_params, globs, macro_rules, phase, quote)]
|
#![feature(default_type_params, globs, macro_rules, phase, quote)]
|
||||||
#![feature(slicing_syntax, unsafe_destructor)]
|
#![feature(slicing_syntax, unsafe_destructor)]
|
||||||
#![feature(rustc_diagnostic_macros)]
|
#![feature(rustc_diagnostic_macros)]
|
||||||
#![feature(unboxed_closures)]
|
#![feature(unboxed_closures)]
|
||||||
|
#![feature(old_orphan_check)]
|
||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
|
|
||||||
#[phase(plugin, link)] extern crate log;
|
#[phase(plugin, link)] extern crate log;
|
||||||
|
@ -22,10 +22,12 @@
|
|||||||
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
|
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
|
||||||
html_root_url = "http://doc.rust-lang.org/nightly/")]
|
html_root_url = "http://doc.rust-lang.org/nightly/")]
|
||||||
|
|
||||||
|
#![allow(unknown_features)]
|
||||||
#![feature(default_type_params, globs, macro_rules, phase, quote)]
|
#![feature(default_type_params, globs, macro_rules, phase, quote)]
|
||||||
#![feature(slicing_syntax, unsafe_destructor)]
|
#![feature(slicing_syntax, unsafe_destructor)]
|
||||||
#![feature(rustc_diagnostic_macros)]
|
#![feature(rustc_diagnostic_macros)]
|
||||||
#![feature(unboxed_closures)]
|
#![feature(unboxed_closures)]
|
||||||
|
#![feature(old_orphan_check)]
|
||||||
|
|
||||||
extern crate arena;
|
extern crate arena;
|
||||||
extern crate flate;
|
extern crate flate;
|
||||||
|
@ -18,7 +18,7 @@ use syntax::ast;
|
|||||||
use syntax::ast_util;
|
use syntax::ast_util;
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
use syntax::visit;
|
use syntax::visit;
|
||||||
use util::ppaux::Repr;
|
use util::ppaux::{Repr, UserString};
|
||||||
|
|
||||||
pub fn check(tcx: &ty::ctxt) {
|
pub fn check(tcx: &ty::ctxt) {
|
||||||
let mut orphan = OrphanChecker { tcx: tcx };
|
let mut orphan = OrphanChecker { tcx: tcx };
|
||||||
@ -67,10 +67,27 @@ 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));
|
||||||
if traits::is_orphan_impl(self.tcx, def_id) {
|
match traits::orphan_check(self.tcx, def_id) {
|
||||||
span_err!(self.tcx.sess, item.span, E0117,
|
Ok(()) => { }
|
||||||
"cannot provide an extension implementation \
|
Err(traits::OrphanCheckErr::NoLocalInputType) => {
|
||||||
where both trait and type are not defined in this crate");
|
span_err!(self.tcx.sess, item.span, E0117,
|
||||||
|
"cannot provide an extension implementation \
|
||||||
|
where both trait and type are not defined in this crate");
|
||||||
|
}
|
||||||
|
Err(traits::OrphanCheckErr::UncoveredTypeParameter(param_ty)) => {
|
||||||
|
if !self.tcx.sess.features.borrow().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());
|
||||||
|
self.tcx.sess.span_note(
|
||||||
|
item.span,
|
||||||
|
format!("for a limited time, you can add \
|
||||||
|
`#![feature(old_orphan_check)]` to your crate \
|
||||||
|
to disable this rule").as_slice());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#![allow(unknown_features)]
|
#![allow(unknown_features)]
|
||||||
#![feature(globs, macro_rules, phase, slicing_syntax)]
|
#![feature(globs, macro_rules, phase, slicing_syntax)]
|
||||||
#![feature(unboxed_closures)]
|
#![feature(unboxed_closures)]
|
||||||
|
#![feature(old_orphan_check)]
|
||||||
|
|
||||||
extern crate arena;
|
extern crate arena;
|
||||||
extern crate getopts;
|
extern crate getopts;
|
||||||
|
@ -81,7 +81,7 @@
|
|||||||
//! use serialize::json;
|
//! use serialize::json;
|
||||||
//!
|
//!
|
||||||
//! // Automatically generate `Decodable` and `Encodable` trait implementations
|
//! // Automatically generate `Decodable` and `Encodable` trait implementations
|
||||||
//! #[deriving(Decodable, Encodable)]
|
//! #[deriving(RustcDecodable, RustcEncodable)]
|
||||||
//! pub struct TestStruct {
|
//! pub struct TestStruct {
|
||||||
//! data_int: u8,
|
//! data_int: u8,
|
||||||
//! data_str: String,
|
//! data_str: String,
|
||||||
|
@ -107,6 +107,7 @@
|
|||||||
#![feature(macro_rules, globs, linkage, thread_local, asm)]
|
#![feature(macro_rules, globs, linkage, thread_local, asm)]
|
||||||
#![feature(default_type_params, phase, lang_items, unsafe_destructor)]
|
#![feature(default_type_params, phase, lang_items, unsafe_destructor)]
|
||||||
#![feature(slicing_syntax, unboxed_closures)]
|
#![feature(slicing_syntax, unboxed_closures)]
|
||||||
|
#![feature(old_orphan_check)]
|
||||||
|
|
||||||
// Don't link to std. We are std.
|
// Don't link to std. We are std.
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
@ -77,8 +77,11 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[
|
|||||||
// to bootstrap fix for #5723.
|
// to bootstrap fix for #5723.
|
||||||
("issue_5723_bootstrap", Accepted),
|
("issue_5723_bootstrap", Accepted),
|
||||||
|
|
||||||
// A way to temporary opt out of opt in copy. This will *never* be accepted.
|
// A way to temporarily opt out of opt in copy. This will *never* be accepted.
|
||||||
("opt_out_copy", Active),
|
("opt_out_copy", Deprecated),
|
||||||
|
|
||||||
|
// A way to temporarily opt out of the new orphan rules. This will *never* be accepted.
|
||||||
|
("old_orphan_check", Deprecated),
|
||||||
|
|
||||||
// These are used to test this portion of the compiler, they don't actually
|
// These are used to test this portion of the compiler, they don't actually
|
||||||
// mean anything
|
// mean anything
|
||||||
@ -91,6 +94,10 @@ enum Status {
|
|||||||
/// currently being considered for addition/removal.
|
/// currently being considered for addition/removal.
|
||||||
Active,
|
Active,
|
||||||
|
|
||||||
|
/// Represents a feature gate that is temporarily enabling deprecated behavior.
|
||||||
|
/// This gate will never be accepted.
|
||||||
|
Deprecated,
|
||||||
|
|
||||||
/// Represents a feature which has since been removed (it was once Active)
|
/// Represents a feature which has since been removed (it was once Active)
|
||||||
Removed,
|
Removed,
|
||||||
|
|
||||||
@ -108,6 +115,7 @@ pub struct Features {
|
|||||||
pub visible_private_types: bool,
|
pub visible_private_types: bool,
|
||||||
pub quote: bool,
|
pub quote: bool,
|
||||||
pub opt_out_copy: bool,
|
pub opt_out_copy: bool,
|
||||||
|
pub old_orphan_check: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Features {
|
impl Features {
|
||||||
@ -120,6 +128,7 @@ impl Features {
|
|||||||
visible_private_types: false,
|
visible_private_types: false,
|
||||||
quote: false,
|
quote: false,
|
||||||
opt_out_copy: false,
|
opt_out_copy: false,
|
||||||
|
old_orphan_check: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -442,7 +451,16 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::C
|
|||||||
};
|
};
|
||||||
match KNOWN_FEATURES.iter()
|
match KNOWN_FEATURES.iter()
|
||||||
.find(|& &(n, _)| name == n) {
|
.find(|& &(n, _)| name == n) {
|
||||||
Some(&(name, Active)) => { cx.features.push(name); }
|
Some(&(name, Active)) => {
|
||||||
|
cx.features.push(name);
|
||||||
|
}
|
||||||
|
Some(&(name, Deprecated)) => {
|
||||||
|
cx.features.push(name);
|
||||||
|
span_handler.span_warn(
|
||||||
|
mi.span,
|
||||||
|
"feature is deprecated and will only be available \
|
||||||
|
for a limited time, please rewrite code that relies on it");
|
||||||
|
}
|
||||||
Some(&(_, Removed)) => {
|
Some(&(_, Removed)) => {
|
||||||
span_handler.span_err(mi.span, "feature has been removed");
|
span_handler.span_err(mi.span, "feature has been removed");
|
||||||
}
|
}
|
||||||
@ -469,6 +487,7 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::C
|
|||||||
visible_private_types: cx.has_feature("visible_private_types"),
|
visible_private_types: cx.has_feature("visible_private_types"),
|
||||||
quote: cx.has_feature("quote"),
|
quote: cx.has_feature("quote"),
|
||||||
opt_out_copy: cx.has_feature("opt_out_copy"),
|
opt_out_copy: cx.has_feature("opt_out_copy"),
|
||||||
|
old_orphan_check: cx.has_feature("old_orphan_check"),
|
||||||
},
|
},
|
||||||
unknown_features)
|
unknown_features)
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#![feature(macro_rules, globs, default_type_params, phase, slicing_syntax)]
|
#![feature(macro_rules, globs, default_type_params, phase, slicing_syntax)]
|
||||||
#![feature(quote, unsafe_destructor)]
|
#![feature(quote, unsafe_destructor)]
|
||||||
#![feature(unboxed_closures)]
|
#![feature(unboxed_closures)]
|
||||||
|
#![feature(old_orphan_check)]
|
||||||
|
|
||||||
extern crate arena;
|
extern crate arena;
|
||||||
extern crate fmt_macros;
|
extern crate fmt_macros;
|
||||||
|
@ -31,8 +31,10 @@
|
|||||||
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
|
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
|
||||||
html_root_url = "http://doc.rust-lang.org/nightly/")]
|
html_root_url = "http://doc.rust-lang.org/nightly/")]
|
||||||
|
|
||||||
|
#![allow(unknown_features)]
|
||||||
#![feature(asm, macro_rules, phase, globs, slicing_syntax)]
|
#![feature(asm, macro_rules, phase, globs, slicing_syntax)]
|
||||||
#![feature(unboxed_closures, default_type_params)]
|
#![feature(unboxed_closures, default_type_params)]
|
||||||
|
#![feature(old_orphan_check)]
|
||||||
|
|
||||||
extern crate getopts;
|
extern crate getopts;
|
||||||
extern crate regex;
|
extern crate regex;
|
||||||
|
@ -20,7 +20,10 @@
|
|||||||
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
|
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
|
||||||
html_root_url = "http://doc.rust-lang.org/nightly/",
|
html_root_url = "http://doc.rust-lang.org/nightly/",
|
||||||
html_playground_url = "http://play.rust-lang.org/")]
|
html_playground_url = "http://play.rust-lang.org/")]
|
||||||
|
|
||||||
|
#![allow(unknown_features)]
|
||||||
#![feature(phase, globs)]
|
#![feature(phase, globs)]
|
||||||
|
#![feature(old_orphan_check)]
|
||||||
|
|
||||||
#[cfg(test)] #[phase(plugin, link)] extern crate log;
|
#[cfg(test)] #[phase(plugin, link)] extern crate log;
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
#![feature(opt_out_copy)]
|
#![feature(opt_out_copy)]
|
||||||
|
//~^ WARNING feature is deprecated
|
||||||
|
//~| WARNING feature is deprecated
|
||||||
|
|
||||||
// Test that when using the `opt-out-copy` feature we still consider
|
// Test that when using the `opt-out-copy` feature we still consider
|
||||||
// destructors to be non-movable
|
// destructors to be non-movable
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
#![feature(old_orphan_check)]
|
||||||
|
|
||||||
extern crate serialize;
|
extern crate serialize;
|
||||||
|
|
||||||
use serialize::{Encodable, Decodable};
|
use serialize::{Encodable, Decodable};
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
// This briefly tests the capability of `Cell` and `RefCell` to implement the
|
// This briefly tests the capability of `Cell` and `RefCell` to implement the
|
||||||
// `Encodable` and `Decodable` traits via `#[deriving(Encodable, Decodable)]`
|
// `Encodable` and `Decodable` traits via `#[deriving(Encodable, Decodable)]`
|
||||||
|
|
||||||
|
#![feature(old_orphan_check)]
|
||||||
|
|
||||||
extern crate serialize;
|
extern crate serialize;
|
||||||
|
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
#![feature(old_orphan_check)]
|
||||||
|
|
||||||
extern crate serialize;
|
extern crate serialize;
|
||||||
extern crate rand;
|
extern crate rand;
|
||||||
|
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
#![feature(old_orphan_check)]
|
||||||
|
|
||||||
extern crate rbml;
|
extern crate rbml;
|
||||||
extern crate serialize;
|
extern crate serialize;
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
#![feature(old_orphan_check)]
|
||||||
|
|
||||||
extern crate serialize;
|
extern crate serialize;
|
||||||
|
|
||||||
|
@ -8,6 +8,10 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
// If `Index` used an associated type for its output, this test would
|
||||||
|
// work more smoothly.
|
||||||
|
#![feature(old_orphan_check)]
|
||||||
|
|
||||||
struct Mat<T> { data: Vec<T>, cols: uint, }
|
struct Mat<T> { data: Vec<T>, cols: uint, }
|
||||||
|
|
||||||
impl<T> Mat<T> {
|
impl<T> Mat<T> {
|
||||||
|
@ -8,6 +8,10 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
// If `Mul` used an associated type for its output, this test would
|
||||||
|
// work more smoothly.
|
||||||
|
#![feature(old_orphan_check)]
|
||||||
|
|
||||||
struct Vec2 {
|
struct Vec2 {
|
||||||
x: f64,
|
x: f64,
|
||||||
y: f64
|
y: f64
|
||||||
|
@ -14,9 +14,9 @@
|
|||||||
|
|
||||||
use std::ops::Fn;
|
use std::ops::Fn;
|
||||||
|
|
||||||
struct G;
|
struct G<A>;
|
||||||
|
|
||||||
impl<'a, A: Add<int, int>> Fn<(A,), int> for G {
|
impl<'a, A: Add<int, int>> Fn<(A,), int> for G<A> {
|
||||||
extern "rust-call" fn call(&self, (arg,): (A,)) -> int {
|
extern "rust-call" fn call(&self, (arg,): (A,)) -> int {
|
||||||
arg.add(1)
|
arg.add(1)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user