about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-10-27 16:46:52 +0100
committerGitHub <noreply@github.com>2019-10-27 16:46:52 +0100
commit53568f3fb34b20563ede4ffd792ea4564c08f3b8 (patch)
tree0842ad60d35c510ad710141a9b8f7f56ed044d88
parenta466f014b50a49fc380e5c9d8878c937732b0fb2 (diff)
parent8f988bd92cf7d6d3e9be5310c18e472ba297e247 (diff)
downloadrust-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
-rw-r--r--src/librustc/traits/coherence.rs14
-rw-r--r--src/test/ui/coherence/impl-foreign-for-locally-defined-fundamental.rs16
-rw-r--r--src/test/ui/coherence/impl-foreign-for-locally-defined-fundamental[foreign].rs16
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() {}