提交 735c308a 编写于 作者: A Alex Crichton

rollup merge of #20416: nikomatsakis/coherence

Conflicts:
	src/test/run-pass/issue-15734.rs
	src/test/run-pass/issue-3743.rs
......@@ -64,7 +64,8 @@
html_root_url = "http://doc.rust-lang.org/nightly/")]
#![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)]
extern crate core;
......
......@@ -25,6 +25,7 @@
#![feature(macro_rules, default_type_params, phase, globs)]
#![feature(unsafe_destructor, slicing_syntax)]
#![feature(unboxed_closures)]
#![feature(old_orphan_check)]
#![no_std]
#[phase(plugin, link)] extern crate core;
......
......@@ -98,9 +98,9 @@ fn cmp(&self, other: &MaybeOwnedVector<T>) -> Ordering {
}
#[allow(deprecated)]
impl<'a, T: PartialEq, Sized? V: AsSlice<T>> Equiv<V> for MaybeOwnedVector<'a, T> {
fn equiv(&self, other: &V) -> bool {
self.as_slice() == other.as_slice()
impl<'a, T: PartialEq> Equiv<[T]> for MaybeOwnedVector<'a, T> {
fn equiv(&self, other: &[T]) -> bool {
self.as_slice() == other
}
}
......
......@@ -22,10 +22,12 @@
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/nightly/")]
#![allow(unknown_features)]
#![feature(default_type_params, globs, macro_rules, phase, quote)]
#![feature(slicing_syntax, unsafe_destructor)]
#![feature(rustc_diagnostic_macros)]
#![feature(unboxed_closures)]
#![feature(old_orphan_check)]
extern crate arena;
extern crate flate;
......@@ -98,6 +100,7 @@ pub mod middle {
pub mod traits;
pub mod ty;
pub mod ty_fold;
pub mod ty_walk;
pub mod weak_lang_items;
}
......
......@@ -443,9 +443,15 @@ pub fn get_impl_trait<'tcx>(cdata: Cmd,
-> Option<Rc<ty::TraitRef<'tcx>>>
{
let item_doc = lookup_item(id, cdata.data());
reader::maybe_get_doc(item_doc, tag_item_trait_ref).map(|tp| {
doc_trait_ref(tp, tcx, cdata)
})
let fam = item_family(item_doc);
match fam {
Family::Impl => {
reader::maybe_get_doc(item_doc, tag_item_trait_ref).map(|tp| {
doc_trait_ref(tp, tcx, cdata)
})
}
_ => None
}
}
pub fn get_impl_vtables<'tcx>(cdata: Cmd,
......
......@@ -11,7 +11,8 @@
//! A pass that annotates every item and method with its stability level,
//! propagating default levels lexically from parent to children ast nodes.
use util::nodemap::{NodeMap, DefIdMap};
use middle::ty;
use metadata::csearch;
use syntax::codemap::Span;
use syntax::{attr, visit};
use syntax::ast;
......@@ -21,8 +22,8 @@
use syntax::ast_util::is_local;
use syntax::attr::Stability;
use syntax::visit::{FnKind, FkMethod, Visitor};
use middle::ty;
use metadata::csearch;
use util::nodemap::{NodeMap, DefIdMap};
use util::ppaux::Repr;
use std::mem::replace;
......@@ -154,10 +155,13 @@ pub fn build(krate: &Crate) -> Index {
/// Lookup the stability for a node, loading external crate
/// metadata as necessary.
pub fn lookup(tcx: &ty::ctxt, id: DefId) -> Option<Stability> {
debug!("lookup(id={})",
id.repr(tcx));
// is this definition the implementation of a trait method?
match ty::trait_item_of_item(tcx, id) {
Some(ty::MethodTraitItemId(trait_method_id))
if trait_method_id != id => {
Some(ty::MethodTraitItemId(trait_method_id)) if trait_method_id != id => {
debug!("lookup: trait_method_id={}", trait_method_id);
return lookup(tcx, trait_method_id)
}
_ => {}
......@@ -178,6 +182,7 @@ pub fn lookup(tcx: &ty::ctxt, id: DefId) -> Option<Stability> {
// stability of the trait to determine the stability of any
// unmarked impls for it. See FIXME above for more details.
debug!("lookup: trait_id={}", trait_id);
lookup(tcx, trait_id)
} else {
None
......
......@@ -14,10 +14,10 @@
use super::{Obligation, ObligationCause};
use super::util;
use middle::subst;
use middle::subst::Subst;
use middle::ty::{mod, Ty};
use middle::infer::InferCtxt;
use std::collections::HashSet;
use std::rc::Rc;
use syntax::ast;
use syntax::codemap::DUMMY_SP;
......@@ -52,9 +52,21 @@ pub fn impl_can_satisfy(infcx: &InferCtxt,
selcx.evaluate_impl(impl2_def_id, &obligation)
}
pub fn impl_is_local(tcx: &ty::ctxt,
impl_def_id: ast::DefId)
-> bool
#[allow(missing_copy_implementations)]
pub enum OrphanCheckErr {
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));
......@@ -63,20 +75,40 @@ pub fn impl_is_local(tcx: &ty::ctxt,
let trait_ref = ty::impl_trait_ref(tcx, impl_def_id).unwrap();
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 {
debug!("trait {} is local to current crate",
trait_ref.def_id.repr(tcx));
return true;
return Ok(());
}
// Otherwise, at least one of the input types must be local to the
// crate.
trait_ref.input_types().iter().any(|&t| ty_is_local(tcx, t))
// Check condition 1: at least one type must be local.
if !trait_ref.input_types().iter().any(|&t| ty_reaches_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 &param 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))
}
pub fn ty_is_local<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
debug!("ty_is_local({})", ty.repr(tcx));
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 {
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_uint(..) |
ty::ty_float(..) |
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_str(..) |
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
}
ty::ty_uniq(t) => {
let krate = tcx.lang_items.owned_box().map(|d| d.krate);
krate == Some(ast::LOCAL_CRATE) || ty_is_local(tcx, t)
}
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, _) |
ty::ty_struct(def_id, _) => {
def_id.krate == ast::LOCAL_CRATE
}
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_uniq(_) => { // treat ~T like Box<T>
let krate = tcx.lang_items.owned_box().map(|d| d.krate);
krate == Some(ast::LOCAL_CRATE)
}
ty::ty_trait(ref tt) => {
tt.principal_def_id().krate == ast::LOCAL_CRATE
}
// Type parameters may be bound to types that are not local to
// the crate.
ty::ty_param(..) => {
false
}
// Associated types could be anything, I guess.
ty::ty_projection(..) => {
false
}
ty::ty_unboxed_closure(..) |
ty::ty_infer(..) |
ty::ty_open(..) |
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 util::ppaux::Repr;
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::project::MismatchedProjectionTypes;
pub use self::project::normalize;
......@@ -245,15 +247,6 @@ pub struct VtableBuiltinData<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.
pub fn overlapping_impls(infcx: &InferCtxt,
impl1_def_id: ast::DefId,
......
......@@ -59,6 +59,7 @@
use middle::traits;
use middle::ty;
use middle::ty_fold::{mod, TypeFoldable, TypeFolder};
use middle::ty_walk::TypeWalker;
use util::ppaux::{note_and_explain_region, bound_region_ptr_to_string};
use util::ppaux::{trait_store_to_string, ty_to_string};
use util::ppaux::{Repr, UserString};
......@@ -2831,59 +2832,61 @@ pub fn mk_param_from_def<'tcx>(cx: &ctxt<'tcx>, def: &TypeParameterDef) -> Ty<'t
pub fn mk_open<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { mk_t(cx, ty_open(ty)) }
pub fn walk_ty<'tcx, F>(ty: Ty<'tcx>, mut f: F) where
F: FnMut(Ty<'tcx>),
impl<'tcx> TyS<'tcx> {
/// Iterator that walks `self` and any types reachable from
/// `self`, in depth-first order. Note that just walks the types
/// that appear in `self`, it does not descend into the fields of
/// structs or variants. For example:
///
/// ```notrust
/// int => { int }
/// Foo<Bar<int>> => { Foo<Bar<int>>, Bar<int>, int }
/// [int] => { [int], int }
/// ```
pub fn walk(&'tcx self) -> TypeWalker<'tcx> {
TypeWalker::new(self)
}
/// Iterator that walks types reachable from `self`, in
/// depth-first order. Note that this is a shallow walk. For
/// example:
///
/// ```notrust
/// int => { }
/// Foo<Bar<int>> => { Bar<int>, int }
/// [int] => { int }
/// ```
pub fn walk_children(&'tcx self) -> TypeWalker<'tcx> {
// Walks type reachable from `self` but not `self
let mut walker = self.walk();
let r = walker.next();
assert_eq!(r, Some(self));
walker
}
}
pub fn walk_ty<'tcx, F>(ty_root: Ty<'tcx>, mut f: F)
where F: FnMut(Ty<'tcx>),
{
maybe_walk_ty(ty, |ty| { f(ty); true });
for ty in ty_root.walk() {
f(ty);
}
}
pub fn maybe_walk_ty<'tcx, F>(ty: Ty<'tcx>, mut f: F) where F: FnMut(Ty<'tcx>) -> bool {
// FIXME(#19596) This is a workaround, but there should be a better way to do this
fn maybe_walk_ty_<'tcx, F>(ty: Ty<'tcx>, f: &mut F) where F: FnMut(Ty<'tcx>) -> bool {
if !(*f)(ty) {
return;
}
match ty.sty {
ty_bool | ty_char | ty_int(_) | ty_uint(_) | ty_float(_) |
ty_str | ty_infer(_) | ty_param(_) | ty_err => {}
ty_uniq(ty) | ty_vec(ty, _) | ty_open(ty) => maybe_walk_ty_(ty, f),
ty_ptr(ref tm) | ty_rptr(_, ref tm) => {
maybe_walk_ty_(tm.ty, f);
}
ty_trait(box TyTrait { ref principal, .. }) => {
for subty in principal.0.substs.types.iter() {
maybe_walk_ty_(*subty, f);
}
}
ty_projection(ProjectionTy { ref trait_ref, .. }) => {
for subty in trait_ref.substs.types.iter() {
maybe_walk_ty_(*subty, f);
}
}
ty_enum(_, ref substs) |
ty_struct(_, ref substs) |
ty_unboxed_closure(_, _, ref substs) => {
for subty in substs.types.iter() {
maybe_walk_ty_(*subty, f);
}
}
ty_tup(ref ts) => { for tt in ts.iter() { maybe_walk_ty_(*tt, f); } }
ty_bare_fn(_, ref ft) => {
for a in ft.sig.0.inputs.iter() { maybe_walk_ty_(*a, f); }
if let ty::FnConverging(output) = ft.sig.0.output {
maybe_walk_ty_(output, f);
}
}
ty_closure(ref ft) => {
for a in ft.sig.0.inputs.iter() { maybe_walk_ty_(*a, f); }
if let ty::FnConverging(output) = ft.sig.0.output {
maybe_walk_ty_(output, f);
}
}
/// Walks `ty` and any types appearing within `ty`, invoking the
/// callback `f` on each type. If the callback returns false, then the
/// children of the current type are ignored.
///
/// Note: prefer `ty.walk()` where possible.
pub fn maybe_walk_ty<'tcx,F>(ty_root: Ty<'tcx>, mut f: F)
where F : FnMut(Ty<'tcx>) -> bool
{
let mut walker = ty_root.walk();
while let Some(ty) = walker.next() {
if !f(ty) {
walker.skip_current_subtree();
}
}
maybe_walk_ty_(ty, &mut f);
}
// Folds types from the bottom up.
......@@ -6122,22 +6125,9 @@ pub fn populate_implementations_for_trait_if_necessary(
/// Given the def_id of an impl, return the def_id of the trait it implements.
/// If it implements no trait, return `None`.
pub fn trait_id_of_impl(tcx: &ctxt,
def_id: ast::DefId) -> Option<ast::DefId> {
let node = match tcx.map.find(def_id.node) {
Some(node) => node,
None => return None
};
match node {
ast_map::NodeItem(item) => {
match item.node {
ast::ItemImpl(_, _, Some(ref trait_ref), _, _) => {
Some(node_id_to_trait_ref(tcx, trait_ref.ref_id).def_id)
}
_ => None
}
}
_ => None
}
def_id: ast::DefId)
-> Option<ast::DefId> {
ty::impl_trait_ref(tcx, def_id).map(|tr| tr.def_id)
}
/// If the given def ID describes a method belonging to an impl, return the
......
// Copyright 2012-2014 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.
//! An iterator over the type substructure.
use middle::ty::{mod, Ty};
use std::iter::Iterator;
pub struct TypeWalker<'tcx> {
stack: Vec<Ty<'tcx>>,
last_subtree: uint,
}
impl<'tcx> TypeWalker<'tcx> {
pub fn new(ty: Ty<'tcx>) -> TypeWalker<'tcx> {
TypeWalker { stack: vec!(ty), last_subtree: 1, }
}
fn push_subtypes(&mut self, parent_ty: Ty<'tcx>) {
match parent_ty.sty {
ty::ty_bool | ty::ty_char | ty::ty_int(_) | ty::ty_uint(_) | ty::ty_float(_) |
ty::ty_str | ty::ty_infer(_) | ty::ty_param(_) | ty::ty_err => {
}
ty::ty_uniq(ty) | ty::ty_vec(ty, _) | ty::ty_open(ty) => {
self.stack.push(ty);
}
ty::ty_ptr(ref mt) | ty::ty_rptr(_, ref mt) => {
self.stack.push(mt.ty);
}
ty::ty_projection(ref data) => {
self.push_reversed(data.trait_ref.substs.types.as_slice());
}
ty::ty_trait(box ty::TyTrait { ref principal, .. }) => {
self.push_reversed(principal.substs().types.as_slice());
}
ty::ty_enum(_, ref substs) |
ty::ty_struct(_, ref substs) |
ty::ty_unboxed_closure(_, _, ref substs) => {
self.push_reversed(substs.types.as_slice());
}
ty::ty_tup(ref ts) => {
self.push_reversed(ts.as_slice());
}
ty::ty_bare_fn(_, ref ft) => {
self.push_sig_subtypes(&ft.sig);
}
ty::ty_closure(ref ft) => {
self.push_sig_subtypes(&ft.sig);
}
}
}
fn push_sig_subtypes(&mut self, sig: &ty::PolyFnSig<'tcx>) {
match sig.0.output {
ty::FnConverging(output) => { self.stack.push(output); }
ty::FnDiverging => { }
}
self.push_reversed(sig.0.inputs.as_slice());
}
fn push_reversed(&mut self, tys: &[Ty<'tcx>]) {
// We push slices on the stack in reverse order so as to
// maintain a pre-order traversal. As of the time of this
// writing, the fact that the traversal is pre-order is not
// known to be significant to any code, but it seems like the
// natural order one would expect (basically, the order of the
// types as they are written).
for &ty in tys.iter().rev() {
self.stack.push(ty);
}
}
/// Skips the subtree of types corresponding to the last type
/// returned by `next()`.
///
/// Example: Imagine you are walking `Foo<Bar<int>, uint>`.
///
/// ```rust
/// let mut iter: TypeWalker = ...;
/// iter.next(); // yields Foo
/// iter.next(); // yields Bar<int>
/// iter.skip_current_subtree(); // skips int
/// iter.next(); // yields uint
/// ```
pub fn skip_current_subtree(&mut self) {
self.stack.truncate(self.last_subtree);
}
}
impl<'tcx> Iterator<Ty<'tcx>> for TypeWalker<'tcx> {
fn next(&mut self) -> Option<Ty<'tcx>> {
debug!("next(): stack={}", self.stack);
match self.stack.pop() {
None => {
return None;
}
Some(ty) => {
self.last_subtree = self.stack.len();
self.push_subtypes(ty);
debug!("next: stack={}", self.stack);
Some(ty)
}
}
}
}
......@@ -32,6 +32,7 @@
#![allow(unknown_features)]
#![feature(globs, phase, macro_rules, slicing_syntax)]
#![feature(unboxed_closures)]
#![feature(old_orphan_check)]
#[phase(plugin, link)]
extern crate log;
......
......@@ -16,10 +16,12 @@
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/nightly/")]
#![allow(unknown_features)]
#![feature(default_type_params, globs, macro_rules, phase, quote)]
#![feature(slicing_syntax, unsafe_destructor)]
#![feature(rustc_diagnostic_macros)]
#![feature(unboxed_closures)]
#![feature(old_orphan_check)]
#![allow(non_camel_case_types)]
#[phase(plugin, link)] extern crate log;
......
......@@ -34,8 +34,6 @@
use syntax::diagnostic::{Level, RenderSpan, Bug, Fatal, Error, Warning, Note, Help};
use syntax::parse::token;
use arena::TypedArena;
struct Env<'a, 'tcx: 'a> {
infcx: &'a infer::InferCtxt<'a, 'tcx>,
}
......@@ -831,3 +829,57 @@ fn subst_region_renumber_region() {
assert_eq!(t_substituted, t_expected);
})
}
#[test]
fn walk_ty() {
test_env(EMPTY_SOURCE_STR, errors(&[]), |env| {
let tcx = env.infcx.tcx;
let int_ty = tcx.types.int;
let uint_ty = tcx.types.uint;
let tup1_ty = ty::mk_tup(tcx, vec!(int_ty, uint_ty, int_ty, uint_ty));
let tup2_ty = ty::mk_tup(tcx, vec!(tup1_ty, tup1_ty, uint_ty));
let uniq_ty = ty::mk_uniq(tcx, tup2_ty);
let walked: Vec<_> = uniq_ty.walk().collect();
assert_eq!(vec!(uniq_ty,
tup2_ty,
tup1_ty, int_ty, uint_ty, int_ty, uint_ty,
tup1_ty, int_ty, uint_ty, int_ty, uint_ty,
uint_ty),
walked);
})
}
#[test]
fn walk_ty_skip_subtree() {
test_env(EMPTY_SOURCE_STR, errors(&[]), |env| {
let tcx = env.infcx.tcx;
let int_ty = tcx.types.int;
let uint_ty = tcx.types.uint;
let tup1_ty = ty::mk_tup(tcx, vec!(int_ty, uint_ty, int_ty, uint_ty));
let tup2_ty = ty::mk_tup(tcx, vec!(tup1_ty, tup1_ty, uint_ty));
let uniq_ty = ty::mk_uniq(tcx, tup2_ty);
// types we expect to see (in order), plus a boolean saying
// whether to skip the subtree.
let mut expected = vec!((uniq_ty, false),
(tup2_ty, false),
(tup1_ty, false),
(int_ty, false),
(uint_ty, false),
(int_ty, false),
(uint_ty, false),
(tup1_ty, true), // skip the int/uint/int/uint
(uint_ty, false));
expected.reverse();
let mut walker = uniq_ty.walk();
while let Some(t) = walker.next() {
debug!("walked to {}", t);
let (expected_ty, skip) = expected.pop().unwrap();
assert_eq!(t, expected_ty);
if skip { walker.skip_current_subtree(); }
}
assert!(expected.is_empty());
})
}
......@@ -22,10 +22,12 @@
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/nightly/")]
#![allow(unknown_features)]
#![feature(default_type_params, globs, macro_rules, phase, quote)]
#![feature(slicing_syntax, unsafe_destructor)]
#![feature(rustc_diagnostic_macros)]
#![feature(unboxed_closures)]
#![feature(old_orphan_check)]
extern crate arena;
extern crate flate;
......
......@@ -18,7 +18,7 @@
use syntax::ast_util;
use syntax::codemap::Span;
use syntax::visit;
use util::ppaux::Repr;
use util::ppaux::{Repr, UserString};
pub fn check(tcx: &ty::ctxt) {
let mut orphan = OrphanChecker { tcx: tcx };
......@@ -72,10 +72,27 @@ fn visit_item(&mut self, item: &'v ast::Item) {
ast::ItemImpl(_, _, Some(_), _, _) => {
// "Trait" impl
debug!("coherence2::orphan check: trait impl {}", item.repr(self.tcx));
if traits::is_orphan_impl(self.tcx, def_id) {
span_err!(self.tcx.sess, item.span, E0117,
"cannot provide an extension implementation \
where both trait and type are not defined in this crate");
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");
}
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)]
#![feature(globs, macro_rules, phase, slicing_syntax)]
#![feature(unboxed_closures)]
#![feature(old_orphan_check)]
extern crate arena;
extern crate getopts;
......
......@@ -76,12 +76,13 @@
//! Create a struct called `TestStruct` and serialize and deserialize it to and from JSON using the
//! serialization API, using the derived serialization code.
//!
//! ```rust
//! ```notrust
//! // FIXME(#19470): this cannot be ```rust``` because it fails orphan checking at the moment
//! extern crate serialize;
//! use serialize::json;
//!
//! // Automatically generate `Decodable` and `Encodable` trait implementations
//! #[deriving(Decodable, Encodable)]
//! #[deriving(RustcDecodable, RustcEncodable)]
//! pub struct TestStruct {
//! data_int: u8,
//! data_str: String,
......@@ -110,7 +111,8 @@
//!
//! ### Simple example of `ToJson` usage
//!
//! ```rust
//! ```notrust
//! // FIXME(#19470): this cannot be ```rust``` because it fails orphan checking at the moment
//! extern crate serialize;
//! use serialize::json::{mod, ToJson, Json};
//!
......@@ -149,7 +151,8 @@
//!
//! ### Verbose example of `ToJson` usage
//!
//! ```rust
//! ```notrust
//! // FIXME(#19470): this cannot be ```rust``` because it fails orphan checking at the moment
//! extern crate serialize;
//! use std::collections::BTreeMap;
//! use serialize::json::{mod, Json, ToJson};
......
......@@ -107,6 +107,7 @@
#![feature(macro_rules, globs, linkage, thread_local, asm)]
#![feature(default_type_params, phase, lang_items, unsafe_destructor)]
#![feature(slicing_syntax, unboxed_closures)]
#![feature(old_orphan_check)]
// Don't link to std. We are std.
#![no_std]
......
......@@ -78,8 +78,11 @@
// to bootstrap fix for #5723.
("issue_5723_bootstrap", Accepted),
// A way to temporary opt out of opt in copy. This will *never* be accepted.
("opt_out_copy", Active),
// A way to temporarily opt out of opt in copy. This will *never* be accepted.
("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
// mean anything
......@@ -92,6 +95,10 @@ enum Status {
/// currently being considered for addition/removal.
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)
Removed,
......@@ -109,6 +116,7 @@ pub struct Features {
pub visible_private_types: bool,
pub quote: bool,
pub opt_out_copy: bool,
pub old_orphan_check: bool,
}
impl Features {
......@@ -121,6 +129,7 @@ pub fn new() -> Features {
visible_private_types: false,
quote: false,
opt_out_copy: false,
old_orphan_check: false,
}
}
}
......@@ -453,7 +462,16 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::C
};
match KNOWN_FEATURES.iter()
.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)) => {
span_handler.span_err(mi.span, "feature has been removed");
}
......@@ -480,6 +498,7 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::C
visible_private_types: cx.has_feature("visible_private_types"),
quote: cx.has_feature("quote"),
opt_out_copy: cx.has_feature("opt_out_copy"),
old_orphan_check: cx.has_feature("old_orphan_check"),
},
unknown_features)
}
......
......@@ -26,6 +26,7 @@
#![feature(macro_rules, globs, default_type_params, phase, slicing_syntax)]
#![feature(quote, unsafe_destructor)]
#![feature(unboxed_closures)]
#![feature(old_orphan_check)]
extern crate arena;
extern crate fmt_macros;
......
......@@ -31,8 +31,10 @@
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/nightly/")]
#![allow(unknown_features)]
#![feature(asm, macro_rules, phase, globs, slicing_syntax)]
#![feature(unboxed_closures, default_type_params)]
#![feature(old_orphan_check)]
extern crate getopts;
extern crate regex;
......
......@@ -20,7 +20,10 @@
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/nightly/",
html_playground_url = "http://play.rust-lang.org/")]
#![allow(unknown_features)]
#![feature(phase, globs)]
#![feature(old_orphan_check)]
#[cfg(test)] #[phase(plugin, link)] extern crate log;
......
// Copyright 2012 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.
#![crate_type="lib"]
pub trait Remote {
fn foo(&self) { }
}
pub trait Remote1<T> {
fn foo(&self, t: T) { }
}
pub trait Remote2<T, U> {
fn foo(&self, t: T, u: U) { }
}
pub struct Pair<T,U>(T,U);
// Copyright 2014 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:coherence-lib.rs
extern crate "coherence-lib" as lib;
use lib::Remote;
impl<T> Remote for int { }
//~^ ERROR cannot provide an extension implementation
fn main() { }
// Copyright 2014 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:coherence-lib.rs
extern crate "coherence-lib" as lib;
use lib::Remote1;
pub struct BigInt;
impl<T> Remote1<BigInt> for T { }
//~^ ERROR type parameter `T` must also appear
fn main() { }
// Copyright 2014 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:coherence-lib.rs
extern crate "coherence-lib" as lib;
use lib::Remote1;
struct Foo<T>(T);
impl<T,U> Remote1<U> for Foo<T> { }
//~^ ERROR type parameter `U` must also appear
fn main() { }
// Copyright 2014 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:coherence-lib.rs
extern crate "coherence-lib" as lib;
use lib::Remote;
impl<T> Remote for T { } //~ ERROR E0117
fn main() { }
// Copyright 2014 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:coherence-lib.rs
extern crate "coherence-lib" as lib;
use lib::Remote;
struct Foo;
impl<T> Remote for lib::Pair<T,Foo> { }
//~^ ERROR type parameter `T` must also appear
fn main() { }
// Copyright 2014 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:coherence-lib.rs
extern crate "coherence-lib" as lib;
use lib::{Remote, Pair};
struct Local<T>(T);
impl<T,U> Remote for Pair<T,Local<U>> { }
//~^ ERROR type parameter `T` must also appear
fn main() { }
......@@ -9,6 +9,8 @@
// except according to those terms.
#![feature(opt_out_copy)]
//~^ WARNING feature is deprecated
//~| WARNING feature is deprecated
// Test that when using the `opt-out-copy` feature we still consider
// destructors to be non-movable
......
// Copyright 2014 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:coherence-lib.rs
extern crate "coherence-lib" as lib;
use lib::Remote1;
pub struct BigInt;
impl Remote1<BigInt> for int { }
fn main() { }
// Copyright 2014 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:coherence-lib.rs
extern crate "coherence-lib" as lib;
use lib::Remote1;
pub struct BigInt;
impl Remote1<BigInt> for Vec<int> { }
fn main() { }
// Copyright 2014 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:coherence-lib.rs
extern crate "coherence-lib" as lib;
use lib::Remote1;
pub trait Local {
fn foo(&self) { }
}
impl<T> Local for T { }
fn main() { }
// Copyright 2014 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:coherence-lib.rs
extern crate "coherence-lib" as lib;
use lib::Remote;
struct Foo<T>(T);
impl<T> Remote for Foo<T> { }
fn main() { }
// Copyright 2014 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:coherence-lib.rs
extern crate "coherence-lib" as lib;
use lib::Remote1;
struct Foo<T>(T);
impl<T> Remote1<T> for Foo<T> { }
fn main() { }
// Copyright 2014 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:coherence-lib.rs
extern crate "coherence-lib" as lib;
use lib::Remote;
struct Local;
impl Remote for Vec<Local> { }
fn main() { }
// Copyright 2014 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:coherence-lib.rs
extern crate "coherence-lib" as lib;
use lib::Remote;
struct Local<T>(T);
impl<T> Remote for Vec<Local<T>> { }
fn main() { }
......@@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(old_orphan_check)]
extern crate serialize;
use serialize::{Encodable, Decodable};
......
......@@ -11,6 +11,8 @@
// This briefly tests the capability of `Cell` and `RefCell` to implement the
// `Encodable` and `Decodable` traits via `#[deriving(Encodable, Decodable)]`
#![feature(old_orphan_check)]
extern crate serialize;
use std::cell::{Cell, RefCell};
......
......@@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(old_orphan_check)]
extern crate serialize;
extern crate rand;
......
......@@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(old_orphan_check)]
extern crate rbml;
extern crate serialize;
......
......@@ -8,6 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(old_orphan_check)]
extern crate serialize;
......
......@@ -8,6 +8,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// If `Index` used an associated type for its output, this test would
// work more smoothly.
#![feature(old_orphan_check)]
use std::ops::Index;
struct Mat<T> { data: Vec<T>, cols: uint, }
......
......@@ -8,6 +8,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// If `Mul` used an associated type for its output, this test would
// work more smoothly.
#![feature(old_orphan_check)]
use std::ops::Mul;
struct Vec2 {
......
......@@ -15,9 +15,9 @@
use std::ops::Fn;
use std::ops::Add;
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 {
arg.add(1)
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册