]> git.lizzy.rs Git - rust.git/commitdiff
Make coherence more tolerant of error types.
authorNiko Matsakis <niko@alum.mit.edu>
Sat, 2 Jan 2016 09:57:55 +0000 (04:57 -0500)
committerNiko Matsakis <niko@alum.mit.edu>
Sat, 9 Jan 2016 01:20:01 +0000 (20:20 -0500)
Fixes #29857.
Fixes #30589.

src/librustc/middle/traits/coherence.rs
src/librustc_typeck/coherence/mod.rs
src/test/compile-fail/coherence-projection-conflict-orphan.rs [new file with mode: 0644]
src/test/compile-fail/coherence-projection-conflict.rs [new file with mode: 0644]
src/test/compile-fail/coherence-projection-ok-orphan.rs [new file with mode: 0644]
src/test/compile-fail/coherence-projection-ok.rs [new file with mode: 0644]
src/test/compile-fail/issue-29857.rs [new file with mode: 0644]
src/test/compile-fail/issue-30589.rs [new file with mode: 0644]

index cb166fbff05859a00e6a9bdaaddb475c81f17401..62a769fbff824193aa5798d7565c3d13cef876a8 100644 (file)
@@ -330,8 +330,11 @@ fn ty_is_local_constructor<'tcx>(tcx: &ty::ctxt<'tcx>,
             tt.principal_def_id().is_local()
         }
 
-        ty::TyClosure(..) |
         ty::TyError => {
+            true
+        }
+
+        ty::TyClosure(..) => {
             tcx.sess.bug(
                 &format!("ty_is_local invoked on unexpected type: {:?}",
                         ty))
index 2c8fedb46a7b7b52e770f9194875b1c8854a2be9..7465ff526b6de1398b569cbd55f74ef67e78e663 100644 (file)
@@ -149,11 +149,23 @@ fn check_implementation(&self, item: &Item) {
                    trait_ref,
                    item.name);
 
+            // Skip impls where one of the self type is an error type.
+            // This occurs with e.g. resolve failures (#30589).
+            if trait_ref.references_error() {
+                return;
+            }
+
             enforce_trait_manually_implementable(self.crate_context.tcx,
                                                  item.span,
                                                  trait_ref.def_id);
             self.add_trait_impl(trait_ref, impl_did);
         } else {
+            // Skip inherent impls where the self type is an error
+            // type. This occurs with e.g. resolve failures (#30589).
+            if self_type.ty.references_error() {
+                return;
+            }
+
             // Add the implementation to the mapping from implementation to base
             // type def ID, if there is a base type for this implementation and
             // the implementation does not have any associated traits.
diff --git a/src/test/compile-fail/coherence-projection-conflict-orphan.rs b/src/test/compile-fail/coherence-projection-conflict-orphan.rs
new file mode 100644 (file)
index 0000000..3de7945
--- /dev/null
@@ -0,0 +1,28 @@
+// Copyright 2016 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.
+
+#![feature(rustc_attrs)]
+
+// Here we expect a coherence conflict because, even though `i32` does
+// not implement `Iterator`, we cannot rely on that negative reasoning
+// due to the orphan rules. Therefore, `A::Item` may yet turn out to
+// be `i32`.
+
+pub trait Foo<P> {}
+
+pub trait Bar {
+    type Output: 'static;
+}
+
+impl Foo<i32> for i32 { } //~ ERROR E0119
+
+impl<A:Iterator> Foo<A::Item> for A { }
+
+fn main() {}
diff --git a/src/test/compile-fail/coherence-projection-conflict.rs b/src/test/compile-fail/coherence-projection-conflict.rs
new file mode 100644 (file)
index 0000000..2236e71
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2016 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.
+
+use std::marker::PhantomData;
+
+pub trait Foo<P> {}
+
+pub trait Bar {
+    type Output: 'static;
+}
+
+impl Foo<i32> for i32 { } //~ ERROR E0119
+
+impl<A:Bar> Foo<A::Output> for A { }
+
+impl Bar for i32 {
+    type Output = i32;
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/coherence-projection-ok-orphan.rs b/src/test/compile-fail/coherence-projection-ok-orphan.rs
new file mode 100644 (file)
index 0000000..a52af08
--- /dev/null
@@ -0,0 +1,29 @@
+// Copyright 2016 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.
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+// Here we do not get a coherence conflict because `Baz: Iterator`
+// does not hold and (due to the orphan rules), we can rely on that.
+
+pub trait Foo<P> {}
+
+pub trait Bar {
+    type Output: 'static;
+}
+
+struct Baz;
+impl Foo<i32> for Baz { }
+
+impl<A:Iterator> Foo<A::Item> for A { }
+
+#[rustc_error]
+fn main() {} //~ ERROR compilation successful
diff --git a/src/test/compile-fail/coherence-projection-ok.rs b/src/test/compile-fail/coherence-projection-ok.rs
new file mode 100644 (file)
index 0000000..af88f37
--- /dev/null
@@ -0,0 +1,28 @@
+// Copyright 2016 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.
+
+#![feature(rustc_attrs)]
+
+pub trait Foo<P> {}
+
+pub trait Bar {
+    type Output: 'static;
+}
+
+impl Foo<i32> for i32 { }
+
+impl<A:Bar> Foo<A::Output> for A { }
+
+impl Bar for i32 {
+    type Output = u32;
+}
+
+#[rustc_error]
+fn main() {} //~ ERROR compilation successful
diff --git a/src/test/compile-fail/issue-29857.rs b/src/test/compile-fail/issue-29857.rs
new file mode 100644 (file)
index 0000000..b46246c
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2016 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.
+
+use std::marker::PhantomData;
+
+pub trait Foo<P> {}
+
+impl <P, T: Foo<P>> Foo<P> for Option<T> {} //~ ERROR E0119
+
+pub struct Qux<T> (PhantomData<*mut T>);
+
+impl<T> Foo<*mut T> for Option<Qux<T>> {}
+
+pub trait Bar {
+    type Output: 'static;
+}
+
+impl<T: 'static, W: Bar<Output = T>> Foo<*mut T> for W {}
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-30589.rs b/src/test/compile-fail/issue-30589.rs
new file mode 100644 (file)
index 0000000..32765d5
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2016 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.
+
+use std::fmt;
+
+impl fmt::Display for DecoderError { //~ ERROR E0412
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "Missing data: {}", self.0)
+    }
+}
+fn main() {
+}