2014-09-12 10:54:08 -04:00
|
|
|
// 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.
|
|
|
|
|
2015-02-18 19:34:55 -08:00
|
|
|
//! See `README.md` for high-level documentation
|
2014-09-12 10:54:08 -04:00
|
|
|
|
2015-12-30 13:47:23 -08:00
|
|
|
use super::{SelectionContext, Obligation, ObligationCause};
|
2014-09-12 10:54:08 -04:00
|
|
|
|
2016-08-31 14:00:29 +03:00
|
|
|
use hir::def_id::{DefId, LOCAL_CRATE};
|
2016-03-22 17:30:57 +02:00
|
|
|
use ty::{self, Ty, TyCtxt};
|
2016-10-04 02:19:40 +03:00
|
|
|
use infer::{InferCtxt, InferOk, TypeOrigin};
|
2016-06-21 18:08:13 -04:00
|
|
|
use syntax_pos::DUMMY_SP;
|
2014-09-12 10:54:08 -04:00
|
|
|
|
2015-04-01 18:44:53 -07:00
|
|
|
#[derive(Copy, Clone)]
|
2015-04-09 15:56:07 -04:00
|
|
|
struct InferIsLocal(bool);
|
2015-03-30 17:46:34 -04:00
|
|
|
|
2015-12-22 10:20:47 -08:00
|
|
|
/// If there are types that satisfy both impls, returns a suitably-freshened
|
|
|
|
/// `ImplHeader` with those types substituted
|
2016-05-11 04:14:41 +03:00
|
|
|
pub fn overlapping_impls<'cx, 'gcx, 'tcx>(infcx: &InferCtxt<'cx, 'gcx, 'tcx>,
|
|
|
|
impl1_def_id: DefId,
|
|
|
|
impl2_def_id: DefId)
|
|
|
|
-> Option<ty::ImplHeader<'tcx>>
|
2014-09-12 10:54:08 -04:00
|
|
|
{
|
2014-10-09 17:19:50 -04:00
|
|
|
debug!("impl_can_satisfy(\
|
2015-06-18 20:25:05 +03:00
|
|
|
impl1_def_id={:?}, \
|
|
|
|
impl2_def_id={:?})",
|
|
|
|
impl1_def_id,
|
|
|
|
impl2_def_id);
|
2014-10-09 17:19:50 -04:00
|
|
|
|
2016-02-23 12:47:09 -08:00
|
|
|
let selcx = &mut SelectionContext::intercrate(infcx);
|
2015-12-01 11:26:47 -08:00
|
|
|
overlap(selcx, impl1_def_id, impl2_def_id)
|
2015-02-12 12:42:02 -05:00
|
|
|
}
|
|
|
|
|
2015-12-01 11:26:47 -08:00
|
|
|
/// Can both impl `a` and impl `b` be satisfied by a common type (including
|
2016-02-26 10:51:10 -08:00
|
|
|
/// `where` clauses)? If so, returns an `ImplHeader` that unifies the two impls.
|
2016-05-11 04:14:41 +03:00
|
|
|
fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>,
|
|
|
|
a_def_id: DefId,
|
|
|
|
b_def_id: DefId)
|
|
|
|
-> Option<ty::ImplHeader<'tcx>>
|
2015-02-12 12:42:02 -05:00
|
|
|
{
|
2015-06-18 20:25:05 +03:00
|
|
|
debug!("overlap(a_def_id={:?}, b_def_id={:?})",
|
|
|
|
a_def_id,
|
|
|
|
b_def_id);
|
2015-02-23 13:02:31 -05:00
|
|
|
|
2016-02-26 10:51:10 -08:00
|
|
|
let a_impl_header = ty::ImplHeader::with_fresh_ty_vars(selcx, a_def_id);
|
|
|
|
let b_impl_header = ty::ImplHeader::with_fresh_ty_vars(selcx, b_def_id);
|
2015-03-30 17:46:34 -04:00
|
|
|
|
2016-02-26 10:51:10 -08:00
|
|
|
debug!("overlap: a_impl_header={:?}", a_impl_header);
|
|
|
|
debug!("overlap: b_impl_header={:?}", b_impl_header);
|
2015-02-23 13:02:31 -05:00
|
|
|
|
2015-11-20 09:34:33 -08:00
|
|
|
// Do `a` and `b` unify? If not, no overlap.
|
2016-10-04 02:19:40 +03:00
|
|
|
match selcx.infcx().eq_impl_headers(true, TypeOrigin::Misc(DUMMY_SP), &a_impl_header,
|
|
|
|
&b_impl_header) {
|
|
|
|
Ok(InferOk { obligations, .. }) => {
|
|
|
|
// FIXME(#32730) propagate obligations
|
|
|
|
assert!(obligations.is_empty());
|
|
|
|
}
|
|
|
|
Err(_) => return None
|
2015-02-12 12:42:02 -05:00
|
|
|
}
|
|
|
|
|
2015-11-20 09:34:33 -08:00
|
|
|
debug!("overlap: unification check succeeded");
|
2015-02-23 13:02:31 -05:00
|
|
|
|
2015-02-12 12:42:02 -05:00
|
|
|
// Are any of the obligations unsatisfiable? If so, no overlap.
|
2015-03-30 17:46:34 -04:00
|
|
|
let infcx = selcx.infcx();
|
2015-02-23 13:02:31 -05:00
|
|
|
let opt_failing_obligation =
|
2016-02-26 13:21:44 -08:00
|
|
|
a_impl_header.predicates
|
2016-02-26 10:51:10 -08:00
|
|
|
.iter()
|
|
|
|
.chain(&b_impl_header.predicates)
|
|
|
|
.map(|p| infcx.resolve_type_vars_if_possible(p))
|
|
|
|
.map(|p| Obligation { cause: ObligationCause::dummy(),
|
|
|
|
recursion_depth: 0,
|
|
|
|
predicate: p })
|
2015-02-23 13:02:31 -05:00
|
|
|
.find(|o| !selcx.evaluate_obligation(o));
|
|
|
|
|
|
|
|
if let Some(failing_obligation) = opt_failing_obligation {
|
2015-06-18 20:25:05 +03:00
|
|
|
debug!("overlap: obligation unsatisfiable {:?}", failing_obligation);
|
2015-12-01 11:26:47 -08:00
|
|
|
return None
|
2015-02-23 13:02:31 -05:00
|
|
|
}
|
|
|
|
|
2015-12-28 15:38:26 -08:00
|
|
|
Some(selcx.infcx().resolve_type_vars_if_possible(&a_impl_header))
|
2015-02-12 12:42:02 -05:00
|
|
|
}
|
|
|
|
|
2016-04-29 06:00:23 +03:00
|
|
|
pub fn trait_ref_is_knowable<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
|
|
|
trait_ref: &ty::TraitRef<'tcx>) -> bool
|
2015-03-30 17:46:34 -04:00
|
|
|
{
|
2015-06-18 20:25:05 +03:00
|
|
|
debug!("trait_ref_is_knowable(trait_ref={:?})", trait_ref);
|
2015-03-30 17:46:34 -04:00
|
|
|
|
|
|
|
// if the orphan rules pass, that means that no ancestor crate can
|
|
|
|
// impl this, so it's up to us.
|
2015-04-09 15:56:07 -04:00
|
|
|
if orphan_check_trait_ref(tcx, trait_ref, InferIsLocal(false)).is_ok() {
|
2015-03-30 17:46:34 -04:00
|
|
|
debug!("trait_ref_is_knowable: orphan check passed");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// if the trait is not marked fundamental, then it's always possible that
|
|
|
|
// an ancestor crate will impl this in the future, if they haven't
|
|
|
|
// already
|
|
|
|
if
|
2015-08-16 06:32:28 -04:00
|
|
|
trait_ref.def_id.krate != LOCAL_CRATE &&
|
2015-06-25 23:42:17 +03:00
|
|
|
!tcx.has_attr(trait_ref.def_id, "fundamental")
|
2015-03-30 17:46:34 -04:00
|
|
|
{
|
|
|
|
debug!("trait_ref_is_knowable: trait is neither local nor fundamental");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// find out when some downstream (or cousin) crate could impl this
|
|
|
|
// trait-ref, presuming that all the parameters were instantiated
|
|
|
|
// with downstream types. If not, then it could only be
|
|
|
|
// implemented by an upstream crate, which means that the impl
|
|
|
|
// must be visible to us, and -- since the trait is fundamental
|
|
|
|
// -- we can test.
|
2015-04-09 15:56:07 -04:00
|
|
|
orphan_check_trait_ref(tcx, trait_ref, InferIsLocal(true)).is_err()
|
2015-03-30 17:46:34 -04:00
|
|
|
}
|
|
|
|
|
Implement new orphan rule that requires that impls of remote traits meet the following two criteria:
- the self type includes some local type; and,
- type parameters in the self type must be constrained by a local type.
A type parameter is called *constrained* if it appears in some type-parameter of a local type.
Here are some examples that are accepted. In all of these examples, I
assume that `Foo` is a trait defined in another crate. If `Foo` were
defined in the local crate, then all the examples would be legal.
- `impl Foo for LocalType`
- `impl<T> Foo<T> for LocalType` -- T does not appear in Self, so it is OK
- `impl<T> Foo<T> for LocalType<T>` -- T here is constrained by LocalType
- `impl<T> Foo<T> for (LocalType<T>, T)` -- T here is constrained by LocalType
Here are some illegal examples (again, these examples assume that
`Foo` is not local to the current crate):
- `impl Foo for int` -- the Self type is not local
- `impl<T> Foo for T` -- T appears in Self unconstrained by a local type
- `impl<T> Foo for (LocalType, T)` -- T appears in Self unconstrained by a local type
This is a [breaking-change]. For the time being, you can opt out of
the new rules by placing `#[old_orphan_check]` on the trait (and
enabling the feature gate where the trait is defined). Longer term,
you should restructure your traits to avoid the problem. Usually this
means changing the order of parameters so that the "central" type
parameter is in the `Self` position.
As an example of that refactoring, consider the `BorrowFrom` trait:
```rust
pub trait BorrowFrom<Sized? Owned> for Sized? {
fn borrow_from(owned: &Owned) -> &Self;
}
```
As defined, this trait is commonly implemented for custom pointer
types, such as `Arc`. Those impls follow the pattern:
```rust
impl<T> BorrowFrom<Arc<T>> for T {...}
```
Unfortunately, this impl is illegal because the self type `T` is not
local to the current crate. Therefore, we are going to change the order of the parameters,
so that `BorrowFrom` becomes `Borrow`:
```rust
pub trait Borrow<Sized? Borrowed> for Sized? {
fn borrow_from(owned: &Self) -> &Borrowed;
}
```
Now the `Arc` impl is written:
```rust
impl<T> Borrow<T> for Arc<T> { ... }
```
This impl is legal because the self type (`Arc<T>`) is local.
2015-01-04 20:35:06 -05:00
|
|
|
pub enum OrphanCheckErr<'tcx> {
|
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.
2014-12-26 03:30:51 -05:00
|
|
|
NoLocalInputType,
|
Implement new orphan rule that requires that impls of remote traits meet the following two criteria:
- the self type includes some local type; and,
- type parameters in the self type must be constrained by a local type.
A type parameter is called *constrained* if it appears in some type-parameter of a local type.
Here are some examples that are accepted. In all of these examples, I
assume that `Foo` is a trait defined in another crate. If `Foo` were
defined in the local crate, then all the examples would be legal.
- `impl Foo for LocalType`
- `impl<T> Foo<T> for LocalType` -- T does not appear in Self, so it is OK
- `impl<T> Foo<T> for LocalType<T>` -- T here is constrained by LocalType
- `impl<T> Foo<T> for (LocalType<T>, T)` -- T here is constrained by LocalType
Here are some illegal examples (again, these examples assume that
`Foo` is not local to the current crate):
- `impl Foo for int` -- the Self type is not local
- `impl<T> Foo for T` -- T appears in Self unconstrained by a local type
- `impl<T> Foo for (LocalType, T)` -- T appears in Self unconstrained by a local type
This is a [breaking-change]. For the time being, you can opt out of
the new rules by placing `#[old_orphan_check]` on the trait (and
enabling the feature gate where the trait is defined). Longer term,
you should restructure your traits to avoid the problem. Usually this
means changing the order of parameters so that the "central" type
parameter is in the `Self` position.
As an example of that refactoring, consider the `BorrowFrom` trait:
```rust
pub trait BorrowFrom<Sized? Owned> for Sized? {
fn borrow_from(owned: &Owned) -> &Self;
}
```
As defined, this trait is commonly implemented for custom pointer
types, such as `Arc`. Those impls follow the pattern:
```rust
impl<T> BorrowFrom<Arc<T>> for T {...}
```
Unfortunately, this impl is illegal because the self type `T` is not
local to the current crate. Therefore, we are going to change the order of the parameters,
so that `BorrowFrom` becomes `Borrow`:
```rust
pub trait Borrow<Sized? Borrowed> for Sized? {
fn borrow_from(owned: &Self) -> &Borrowed;
}
```
Now the `Arc` impl is written:
```rust
impl<T> Borrow<T> for Arc<T> { ... }
```
This impl is legal because the self type (`Arc<T>`) is local.
2015-01-04 20:35:06 -05:00
|
|
|
UncoveredTy(Ty<'tcx>),
|
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.
2014-12-26 03:30:51 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// 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:
|
|
|
|
///
|
Implement new orphan rule that requires that impls of remote traits meet the following two criteria:
- the self type includes some local type; and,
- type parameters in the self type must be constrained by a local type.
A type parameter is called *constrained* if it appears in some type-parameter of a local type.
Here are some examples that are accepted. In all of these examples, I
assume that `Foo` is a trait defined in another crate. If `Foo` were
defined in the local crate, then all the examples would be legal.
- `impl Foo for LocalType`
- `impl<T> Foo<T> for LocalType` -- T does not appear in Self, so it is OK
- `impl<T> Foo<T> for LocalType<T>` -- T here is constrained by LocalType
- `impl<T> Foo<T> for (LocalType<T>, T)` -- T here is constrained by LocalType
Here are some illegal examples (again, these examples assume that
`Foo` is not local to the current crate):
- `impl Foo for int` -- the Self type is not local
- `impl<T> Foo for T` -- T appears in Self unconstrained by a local type
- `impl<T> Foo for (LocalType, T)` -- T appears in Self unconstrained by a local type
This is a [breaking-change]. For the time being, you can opt out of
the new rules by placing `#[old_orphan_check]` on the trait (and
enabling the feature gate where the trait is defined). Longer term,
you should restructure your traits to avoid the problem. Usually this
means changing the order of parameters so that the "central" type
parameter is in the `Self` position.
As an example of that refactoring, consider the `BorrowFrom` trait:
```rust
pub trait BorrowFrom<Sized? Owned> for Sized? {
fn borrow_from(owned: &Owned) -> &Self;
}
```
As defined, this trait is commonly implemented for custom pointer
types, such as `Arc`. Those impls follow the pattern:
```rust
impl<T> BorrowFrom<Arc<T>> for T {...}
```
Unfortunately, this impl is illegal because the self type `T` is not
local to the current crate. Therefore, we are going to change the order of the parameters,
so that `BorrowFrom` becomes `Borrow`:
```rust
pub trait Borrow<Sized? Borrowed> for Sized? {
fn borrow_from(owned: &Self) -> &Borrowed;
}
```
Now the `Arc` impl is written:
```rust
impl<T> Borrow<T> for Arc<T> { ... }
```
This impl is legal because the self type (`Arc<T>`) is local.
2015-01-04 20:35:06 -05:00
|
|
|
/// 1. All type parameters in `Self` must be "covered" by some local type constructor.
|
|
|
|
/// 2. Some local type must appear in `Self`.
|
2016-04-29 06:00:23 +03:00
|
|
|
pub fn orphan_check<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
|
|
|
impl_def_id: DefId)
|
|
|
|
-> Result<(), OrphanCheckErr<'tcx>>
|
2014-09-12 10:54:08 -04:00
|
|
|
{
|
2015-06-18 20:25:05 +03:00
|
|
|
debug!("orphan_check({:?})", impl_def_id);
|
2014-09-12 10:54:08 -04:00
|
|
|
|
|
|
|
// We only except this routine to be invoked on implementations
|
|
|
|
// of a trait, not inherent implementations.
|
2015-06-25 23:42:17 +03:00
|
|
|
let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
|
2015-06-18 20:25:05 +03:00
|
|
|
debug!("orphan_check: trait_ref={:?}", trait_ref);
|
2014-09-12 10:54:08 -04:00
|
|
|
|
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.
2014-12-26 03:30:51 -05:00
|
|
|
// If the *trait* is local to the crate, ok.
|
2015-08-16 09:06:23 -04:00
|
|
|
if trait_ref.def_id.is_local() {
|
2015-06-18 20:25:05 +03:00
|
|
|
debug!("trait {:?} is local to current crate",
|
|
|
|
trait_ref.def_id);
|
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.
2014-12-26 03:30:51 -05:00
|
|
|
return Ok(());
|
2014-09-12 10:54:08 -04:00
|
|
|
}
|
|
|
|
|
2015-04-09 15:56:07 -04:00
|
|
|
orphan_check_trait_ref(tcx, &trait_ref, InferIsLocal(false))
|
2015-03-30 17:46:34 -04:00
|
|
|
}
|
|
|
|
|
2016-04-29 06:00:23 +03:00
|
|
|
fn orphan_check_trait_ref<'tcx>(tcx: TyCtxt,
|
|
|
|
trait_ref: &ty::TraitRef<'tcx>,
|
|
|
|
infer_is_local: InferIsLocal)
|
|
|
|
-> Result<(), OrphanCheckErr<'tcx>>
|
2015-03-30 17:46:34 -04:00
|
|
|
{
|
2015-06-18 20:25:05 +03:00
|
|
|
debug!("orphan_check_trait_ref(trait_ref={:?}, infer_is_local={})",
|
|
|
|
trait_ref, infer_is_local.0);
|
2015-03-30 17:46:34 -04:00
|
|
|
|
2015-01-30 18:46:53 -05:00
|
|
|
// First, create an ordered iterator over all the type parameters to the trait, with the self
|
|
|
|
// type appearing first.
|
|
|
|
// Find the first input type that either references a type parameter OR
|
|
|
|
// some local type.
|
2016-08-15 01:07:09 +03:00
|
|
|
for input_ty in trait_ref.input_types() {
|
2015-04-09 15:56:07 -04:00
|
|
|
if ty_is_local(tcx, input_ty, infer_is_local) {
|
2015-06-18 20:25:05 +03:00
|
|
|
debug!("orphan_check_trait_ref: ty_is_local `{:?}`", input_ty);
|
2015-03-30 17:46:34 -04:00
|
|
|
|
|
|
|
// First local input type. Check that there are no
|
|
|
|
// uncovered type parameters.
|
2015-04-09 15:56:07 -04:00
|
|
|
let uncovered_tys = uncovered_tys(tcx, input_ty, infer_is_local);
|
2015-03-30 17:46:34 -04:00
|
|
|
for uncovered_ty in uncovered_tys {
|
|
|
|
if let Some(param) = uncovered_ty.walk().find(|t| is_type_parameter(t)) {
|
2015-06-18 20:25:05 +03:00
|
|
|
debug!("orphan_check_trait_ref: uncovered type `{:?}`", param);
|
2015-03-30 17:46:34 -04:00
|
|
|
return Err(OrphanCheckErr::UncoveredTy(param));
|
|
|
|
}
|
2015-01-30 18:46:53 -05:00
|
|
|
}
|
2015-03-30 17:46:34 -04:00
|
|
|
|
|
|
|
// OK, found local type, all prior types upheld invariant.
|
|
|
|
return Ok(());
|
2015-01-30 18:46:53 -05:00
|
|
|
}
|
2015-03-30 17:46:34 -04:00
|
|
|
|
|
|
|
// Otherwise, enforce invariant that there are no type
|
|
|
|
// parameters reachable.
|
2015-04-09 15:56:07 -04:00
|
|
|
if !infer_is_local.0 {
|
2015-03-30 17:46:34 -04:00
|
|
|
if let Some(param) = input_ty.walk().find(|t| is_type_parameter(t)) {
|
2015-06-18 20:25:05 +03:00
|
|
|
debug!("orphan_check_trait_ref: uncovered type `{:?}`", param);
|
2015-03-30 17:46:34 -04:00
|
|
|
return Err(OrphanCheckErr::UncoveredTy(param));
|
|
|
|
}
|
2015-01-30 18:46:53 -05:00
|
|
|
}
|
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.
2014-12-26 03:30:51 -05:00
|
|
|
}
|
|
|
|
|
2015-03-30 17:46:34 -04:00
|
|
|
// If we exit above loop, never found a local type.
|
|
|
|
debug!("orphan_check_trait_ref: no local type");
|
|
|
|
return Err(OrphanCheckErr::NoLocalInputType);
|
|
|
|
}
|
|
|
|
|
2016-04-29 06:00:23 +03:00
|
|
|
fn uncovered_tys<'tcx>(tcx: TyCtxt, ty: Ty<'tcx>, infer_is_local: InferIsLocal)
|
|
|
|
-> Vec<Ty<'tcx>> {
|
2015-04-09 15:56:07 -04:00
|
|
|
if ty_is_local_constructor(tcx, ty, infer_is_local) {
|
2015-03-30 17:46:34 -04:00
|
|
|
vec![]
|
|
|
|
} else if fundamental_ty(tcx, ty) {
|
|
|
|
ty.walk_shallow()
|
2015-06-10 17:22:20 +01:00
|
|
|
.flat_map(|t| uncovered_tys(tcx, t, infer_is_local))
|
2015-03-30 17:46:34 -04:00
|
|
|
.collect()
|
|
|
|
} else {
|
|
|
|
vec![ty]
|
|
|
|
}
|
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.
2014-12-26 03:30:51 -05:00
|
|
|
}
|
|
|
|
|
2016-04-29 06:00:23 +03:00
|
|
|
fn is_type_parameter(ty: Ty) -> bool {
|
2015-03-30 17:46:34 -04:00
|
|
|
match ty.sty {
|
|
|
|
// FIXME(#20590) straighten story about projection types
|
2015-06-11 16:21:46 -07:00
|
|
|
ty::TyProjection(..) | ty::TyParam(..) => true,
|
2015-03-30 17:46:34 -04:00
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-29 06:00:23 +03:00
|
|
|
fn ty_is_local(tcx: TyCtxt, ty: Ty, infer_is_local: InferIsLocal) -> bool {
|
2015-04-09 15:56:07 -04:00
|
|
|
ty_is_local_constructor(tcx, ty, infer_is_local) ||
|
|
|
|
fundamental_ty(tcx, ty) && ty.walk_shallow().any(|t| ty_is_local(tcx, t, infer_is_local))
|
2015-03-30 17:46:34 -04:00
|
|
|
}
|
|
|
|
|
2016-04-29 06:00:23 +03:00
|
|
|
fn fundamental_ty(tcx: TyCtxt, ty: Ty) -> bool {
|
2015-03-30 17:46:34 -04:00
|
|
|
match ty.sty {
|
2015-06-11 16:21:46 -07:00
|
|
|
ty::TyBox(..) | ty::TyRef(..) =>
|
2015-03-30 17:46:34 -04:00
|
|
|
true,
|
2016-09-06 01:26:02 +03:00
|
|
|
ty::TyAdt(def, _) =>
|
2015-08-07 14:41:33 +03:00
|
|
|
def.is_fundamental(),
|
2015-06-11 16:21:46 -07:00
|
|
|
ty::TyTrait(ref data) =>
|
2016-08-04 15:52:57 +03:00
|
|
|
tcx.has_attr(data.principal.def_id(), "fundamental"),
|
2015-03-30 17:46:34 -04:00
|
|
|
_ =>
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-29 06:00:23 +03:00
|
|
|
fn ty_is_local_constructor(tcx: TyCtxt, ty: Ty, infer_is_local: InferIsLocal)-> bool {
|
2015-06-18 20:25:05 +03:00
|
|
|
debug!("ty_is_local_constructor({:?})", ty);
|
2014-09-12 10:54:08 -04:00
|
|
|
|
2014-10-31 10:51:16 +02:00
|
|
|
match ty.sty {
|
2015-06-11 16:21:46 -07:00
|
|
|
ty::TyBool |
|
|
|
|
ty::TyChar |
|
|
|
|
ty::TyInt(..) |
|
|
|
|
ty::TyUint(..) |
|
|
|
|
ty::TyFloat(..) |
|
2015-10-26 21:10:41 +03:00
|
|
|
ty::TyStr |
|
2015-06-13 13:15:03 -07:00
|
|
|
ty::TyFnDef(..) |
|
|
|
|
ty::TyFnPtr(_) |
|
2015-06-11 16:21:46 -07:00
|
|
|
ty::TyArray(..) |
|
2015-06-12 16:50:13 -07:00
|
|
|
ty::TySlice(..) |
|
2015-06-11 16:21:46 -07:00
|
|
|
ty::TyRawPtr(..) |
|
|
|
|
ty::TyRef(..) |
|
2016-08-02 15:56:20 +08:00
|
|
|
ty::TyNever |
|
2015-06-11 16:21:46 -07:00
|
|
|
ty::TyTuple(..) |
|
|
|
|
ty::TyParam(..) |
|
|
|
|
ty::TyProjection(..) => {
|
2014-09-12 10:54:08 -04:00
|
|
|
false
|
|
|
|
}
|
|
|
|
|
2015-06-11 16:21:46 -07:00
|
|
|
ty::TyInfer(..) => {
|
2015-04-09 15:56:07 -04:00
|
|
|
infer_is_local.0
|
2015-03-30 17:46:34 -04:00
|
|
|
}
|
|
|
|
|
2016-09-06 01:26:02 +03:00
|
|
|
ty::TyAdt(def, _) => {
|
2015-08-16 09:06:23 -04:00
|
|
|
def.did.is_local()
|
2014-09-12 10:54:08 -04:00
|
|
|
}
|
|
|
|
|
2015-06-11 16:21:46 -07:00
|
|
|
ty::TyBox(_) => { // Box<T>
|
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.
2014-12-26 03:30:51 -05:00
|
|
|
let krate = tcx.lang_items.owned_box().map(|d| d.krate);
|
2015-08-16 06:32:28 -04:00
|
|
|
krate == Some(LOCAL_CRATE)
|
2014-09-12 10:54:08 -04:00
|
|
|
}
|
|
|
|
|
2015-06-11 16:21:46 -07:00
|
|
|
ty::TyTrait(ref tt) => {
|
2016-08-04 15:52:57 +03:00
|
|
|
tt.principal.def_id().is_local()
|
2014-09-12 10:54:08 -04:00
|
|
|
}
|
|
|
|
|
2015-06-11 16:21:46 -07:00
|
|
|
ty::TyError => {
|
2016-01-02 04:57:55 -05:00
|
|
|
true
|
|
|
|
}
|
|
|
|
|
2016-07-22 18:56:22 +03:00
|
|
|
ty::TyClosure(..) | ty::TyAnon(..) => {
|
2016-03-25 01:14:29 +01:00
|
|
|
bug!("ty_is_local invoked on unexpected type: {:?}", ty)
|
2014-09-12 10:54:08 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|