diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2019-10-27 16:46:52 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-10-27 16:46:52 +0100 |
| commit | 53568f3fb34b20563ede4ffd792ea4564c08f3b8 (patch) | |
| tree | 0842ad60d35c510ad710141a9b8f7f56ed044d88 | |
| parent | a466f014b50a49fc380e5c9d8878c937732b0fb2 (diff) | |
| parent | 8f988bd92cf7d6d3e9be5310c18e472ba297e247 (diff) | |
| download | rust-53568f3fb34b20563ede4ffd792ea4564c08f3b8.tar.gz rust-53568f3fb34b20563ede4ffd792ea4564c08f3b8.zip | |
Rollup merge of #65738 - ohadravid:re-rebalance-coherence-allow-fundamental-local, r=nikomatsakis
Coherence should allow fundamental types to impl traits when they are local
After #64414, `impl<T> Remote for Box<T> { }` is disallowed, but it is also disallowed in liballoc, where `Box` is a local type!
Enabling `#![feature(re_rebalance_coherence)]` in `liballoc` results in:
```
error[E0210]: type parameter `F` must be used as the type parameter for some local type (e.g., `MyStruct<F>`)
--> src\liballoc\boxed.rs:1098:1
|
1098 | impl<F: ?Sized + Future + Unpin> Future for Box<F> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `F` must be used as the type parameter for some local type
```
This PR relaxes `uncover_fundamental_ty` to skip local fundamental types.
I didn't add a test since `liballoc` already fails to compile, but I can add one if needed.
r? @nikomatsakis
cc #63599
3 files changed, 42 insertions, 4 deletions
diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index 4696d4da58e..2734fce4ea5 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -378,15 +378,21 @@ fn orphan_check_trait_ref<'tcx>( // Let Ti be the first such type. // - No uncovered type parameters P1..=Pn may appear in T0..Ti (excluding Ti) // - fn uncover_fundamental_ty(ty: Ty<'_>) -> Vec<Ty<'_>> { - if fundamental_ty(ty) { - ty.walk_shallow().flat_map(|ty| uncover_fundamental_ty(ty)).collect() + fn uncover_fundamental_ty<'a>( + tcx: TyCtxt<'_>, + ty: Ty<'a>, + in_crate: InCrate, + ) -> Vec<Ty<'a>> { + if fundamental_ty(ty) && !ty_is_local(tcx, ty, in_crate) { + ty.walk_shallow().flat_map(|ty| uncover_fundamental_ty(tcx, ty, in_crate)).collect() } else { vec![ty] } } - for input_ty in trait_ref.input_types().flat_map(uncover_fundamental_ty) { + for input_ty in + trait_ref.input_types().flat_map(|ty| uncover_fundamental_ty(tcx, ty, in_crate)) + { debug!("orphan_check_trait_ref: check ty `{:?}`", input_ty); if ty_is_local(tcx, input_ty, in_crate) { debug!("orphan_check_trait_ref: ty_is_local `{:?}`", input_ty); diff --git a/src/test/ui/coherence/impl-foreign-for-locally-defined-fundamental.rs b/src/test/ui/coherence/impl-foreign-for-locally-defined-fundamental.rs new file mode 100644 index 00000000000..d461b5abd60 --- /dev/null +++ b/src/test/ui/coherence/impl-foreign-for-locally-defined-fundamental.rs @@ -0,0 +1,16 @@ +#![feature(fundamental)] +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; + +#[fundamental] +struct Local; + +impl Remote for Local {} + +fn main() {} diff --git a/src/test/ui/coherence/impl-foreign-for-locally-defined-fundamental[foreign].rs b/src/test/ui/coherence/impl-foreign-for-locally-defined-fundamental[foreign].rs new file mode 100644 index 00000000000..0a3d9e2e0e8 --- /dev/null +++ b/src/test/ui/coherence/impl-foreign-for-locally-defined-fundamental[foreign].rs @@ -0,0 +1,16 @@ +#![feature(fundamental)] +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; + +#[fundamental] +struct MyBox<T>(T); + +impl<T> Remote for MyBox<T> {} + +fn main() {} |
