diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc/middle/traits/coherence.rs | 56 | ||||
| -rw-r--r-- | src/librustc_typeck/coherence/orphan.rs | 6 | ||||
| -rw-r--r-- | src/test/compile-fail/coherence-all-remote.rs | 2 | ||||
| -rw-r--r-- | src/test/compile-fail/coherence-cow-no-cover.rs | 23 | ||||
| -rw-r--r-- | src/test/compile-fail/coherence-orphan.rs | 2 | ||||
| -rw-r--r-- | src/test/compile-fail/coherence-pair-covered-uncovered-1.rs | 24 | ||||
| -rw-r--r-- | src/test/run-pass/coherence-bigint-int.rs (renamed from src/test/compile-fail/coherence-bigint-int.rs) | 2 | ||||
| -rw-r--r-- | src/test/run-pass/coherence-bigint-vecint.rs (renamed from src/test/compile-fail/coherence-bigint-vecint.rs) | 2 | ||||
| -rw-r--r-- | src/test/run-pass/coherence-cow-1.rs | 23 | ||||
| -rw-r--r-- | src/test/run-pass/coherence-cow-2.rs | 23 |
10 files changed, 135 insertions, 28 deletions
diff --git a/src/librustc/middle/traits/coherence.rs b/src/librustc/middle/traits/coherence.rs index e3363aa8fb7..44cd17caaec 100644 --- a/src/librustc/middle/traits/coherence.rs +++ b/src/librustc/middle/traits/coherence.rs @@ -15,7 +15,7 @@ use super::{Obligation, ObligationCause}; use super::project; use super::util; -use middle::subst::{Subst}; +use middle::subst::{Subst, TypeSpace}; use middle::ty::{self, Ty}; use middle::infer::InferCtxt; use std::collections::HashSet; @@ -89,16 +89,28 @@ pub fn orphan_check<'tcx>(tcx: &ty::ctxt<'tcx>, return Ok(()); } - // 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); + // First, create an ordered iterator over all the type parameters to the trait, with the self + // type appearing first. + let input_tys = Some(trait_ref.self_ty()); + let input_tys = input_tys.iter().chain(trait_ref.substs.types.get_slice(TypeSpace).iter()); + let mut input_tys = input_tys; + + // Find the first input type that either references a type parameter OR + // some local type. + match input_tys.find(|&&input_ty| references_local_or_type_parameter(tcx, input_ty)) { + Some(&input_ty) => { + // Within this first type, check that all type parameters are covered by a local + // type constructor. Note that if there is no local type constructor, then any + // type parameter at all will be an error. + let covered_params = type_parameters_covered_by_ty(tcx, input_ty); + let all_params = type_parameters_reachable_from_ty(input_ty); + for ¶m in all_params.difference(&covered_params) { + return Err(OrphanCheckErr::UncoveredTy(param)); + } + } + None => { + return Err(OrphanCheckErr::NoLocalInputType); + } } return Ok(()); @@ -162,13 +174,17 @@ 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<'tcx>> { - ty.walk() - .filter(|&t| { - match t.sty { - // FIXME(#20590) straighten story about projection types - ty::ty_projection(..) | ty::ty_param(..) => true, - _ => false, - } - }) - .collect() + ty.walk().filter(|&t| is_type_parameter(t)).collect() +} + +fn references_local_or_type_parameter<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool { + ty.walk().any(|ty| is_type_parameter(ty) || ty_is_local_constructor(tcx, ty)) +} + +fn is_type_parameter<'tcx>(ty: Ty<'tcx>) -> bool { + match ty.sty { + // FIXME(#20590) straighten story about projection types + ty::ty_projection(..) | ty::ty_param(..) => true, + _ => false, + } } diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index 60b1fa5f4cf..5b97175ab22 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -77,14 +77,12 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> { Ok(()) => { } Err(traits::OrphanCheckErr::NoLocalInputType) => { 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 \ + "the impl 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)); + implemented for arbitrary types"); } } Err(traits::OrphanCheckErr::UncoveredTy(param_ty)) => { diff --git a/src/test/compile-fail/coherence-all-remote.rs b/src/test/compile-fail/coherence-all-remote.rs index f8ddf83c9c6..1e3b7f6dbd2 100644 --- a/src/test/compile-fail/coherence-all-remote.rs +++ b/src/test/compile-fail/coherence-all-remote.rs @@ -14,6 +14,6 @@ extern crate "coherence-lib" as lib; use lib::Remote1; impl<T> Remote1<T> for isize { } -//~^ ERROR E0117 +//~^ ERROR E0210 fn main() { } diff --git a/src/test/compile-fail/coherence-cow-no-cover.rs b/src/test/compile-fail/coherence-cow-no-cover.rs new file mode 100644 index 00000000000..8d14eb96c61 --- /dev/null +++ b/src/test/compile-fail/coherence-cow-no-cover.rs @@ -0,0 +1,23 @@ +// 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 + +// Test that it's not ok for U to appear uncovered + +extern crate "coherence-lib" as lib; +use lib::{Remote,Pair}; + +pub struct Cover<T>(T); + +impl<T,U> Remote for Pair<Cover<T>,U> { } +//~^ ERROR type parameter `U` is not constrained by any local type + +fn main() { } diff --git a/src/test/compile-fail/coherence-orphan.rs b/src/test/compile-fail/coherence-orphan.rs index f9f965e1ae3..d7cd68e73c3 100644 --- a/src/test/compile-fail/coherence-orphan.rs +++ b/src/test/compile-fail/coherence-orphan.rs @@ -21,7 +21,7 @@ struct TheType; impl TheTrait<usize> for isize { } //~ ERROR E0117 -impl TheTrait<TheType> for isize { } //~ ERROR E0117 +impl TheTrait<TheType> for isize { } impl TheTrait<isize> for TheType { } diff --git a/src/test/compile-fail/coherence-pair-covered-uncovered-1.rs b/src/test/compile-fail/coherence-pair-covered-uncovered-1.rs new file mode 100644 index 00000000000..3655bca6f1d --- /dev/null +++ b/src/test/compile-fail/coherence-pair-covered-uncovered-1.rs @@ -0,0 +1,24 @@ +// 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. + +// Test that the same coverage rules apply even if the local type appears in the +// list of type parameters, not the self type. + +// aux-build:coherence-lib.rs + +extern crate "coherence-lib" as lib; +use lib::{Remote1, Pair}; + +pub struct Local<T>(T); + +impl<T,U> Remote1<Pair<T,Local<U>>> for i32 { } +//~^ ERROR type parameter `T` is not constrained + +fn main() { } diff --git a/src/test/compile-fail/coherence-bigint-int.rs b/src/test/run-pass/coherence-bigint-int.rs index 684773098cd..baf2f57206d 100644 --- a/src/test/compile-fail/coherence-bigint-int.rs +++ b/src/test/run-pass/coherence-bigint-int.rs @@ -15,6 +15,6 @@ use lib::Remote1; pub struct BigInt; -impl Remote1<BigInt> for isize { } //~ ERROR E0117 +impl Remote1<BigInt> for isize { } fn main() { } diff --git a/src/test/compile-fail/coherence-bigint-vecint.rs b/src/test/run-pass/coherence-bigint-vecint.rs index 28747674b8b..cdc5bc11716 100644 --- a/src/test/compile-fail/coherence-bigint-vecint.rs +++ b/src/test/run-pass/coherence-bigint-vecint.rs @@ -15,6 +15,6 @@ use lib::Remote1; pub struct BigInt; -impl Remote1<BigInt> for Vec<isize> { } //~ ERROR E0117 +impl Remote1<BigInt> for Vec<isize> { } fn main() { } diff --git a/src/test/run-pass/coherence-cow-1.rs b/src/test/run-pass/coherence-cow-1.rs new file mode 100644 index 00000000000..b380372b401 --- /dev/null +++ b/src/test/run-pass/coherence-cow-1.rs @@ -0,0 +1,23 @@ +// 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 + +// Test that it's ok for T to appear first in the self-type, as long +// as it's covered somewhere. + +extern crate "coherence-lib" as lib; +use lib::{Remote,Pair}; + +pub struct Cover<T>(T); + +impl<T> Remote for Pair<T,Cover<T>> { } + +fn main() { } diff --git a/src/test/run-pass/coherence-cow-2.rs b/src/test/run-pass/coherence-cow-2.rs new file mode 100644 index 00000000000..93e507c0d63 --- /dev/null +++ b/src/test/run-pass/coherence-cow-2.rs @@ -0,0 +1,23 @@ +// 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 + +// Test that it's ok for T to appear second in the self-type, as long +// as it's covered somewhere. + +extern crate "coherence-lib" as lib; +use lib::{Remote,Pair}; + +pub struct Cover<T>(T); + +impl<T> Remote for Pair<Cover<T>,T> { } + +fn main() { } |
