]> git.lizzy.rs Git - rust.git/commitdiff
permit negative impls for non-auto traits
authorNiko Matsakis <niko@alum.mit.edu>
Wed, 8 Jan 2020 11:39:38 +0000 (06:39 -0500)
committerNiko Matsakis <niko@alum.mit.edu>
Thu, 26 Mar 2020 10:27:45 +0000 (06:27 -0400)
39 files changed:
src/libcore/clone.rs
src/libcore/ops/deref.rs
src/librustc_error_codes/error_codes.rs
src/librustc_error_codes/error_codes/E0749.md [new file with mode: 0644]
src/librustc_error_codes/error_codes/E0750.md [new file with mode: 0644]
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/wfcheck.rs
src/test/ui/error-codes/E0192.rs [deleted file]
src/test/ui/error-codes/E0192.stderr [deleted file]
src/test/ui/specialization/defaultimpl/validation.rs
src/test/ui/specialization/defaultimpl/validation.stderr
src/test/ui/syntax-trait-polarity.rs
src/test/ui/syntax-trait-polarity.stderr
src/test/ui/traits/negative-impls/auxiliary/foreign_trait.rs [new file with mode: 0644]
src/test/ui/traits/negative-impls/negated-auto-traits-error.rs [new file with mode: 0644]
src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr [new file with mode: 0644]
src/test/ui/traits/negative-impls/negated-auto-traits-rpass.rs [new file with mode: 0644]
src/test/ui/traits/negative-impls/negative-default-impls.rs [new file with mode: 0644]
src/test/ui/traits/negative-impls/negative-default-impls.stderr [new file with mode: 0644]
src/test/ui/traits/negative-impls/negative-specializes-positive-item.rs [new file with mode: 0644]
src/test/ui/traits/negative-impls/negative-specializes-positive-item.stderr [new file with mode: 0644]
src/test/ui/traits/negative-impls/negative-specializes-positive.rs [new file with mode: 0644]
src/test/ui/traits/negative-impls/negative-specializes-positive.stderr [new file with mode: 0644]
src/test/ui/traits/negative-impls/no-items.rs [new file with mode: 0644]
src/test/ui/traits/negative-impls/no-items.stderr [new file with mode: 0644]
src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs [new file with mode: 0644]
src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr [new file with mode: 0644]
src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs [new file with mode: 0644]
src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr [new file with mode: 0644]
src/test/ui/traits/negative-impls/positive-specializes-negative.rs [new file with mode: 0644]
src/test/ui/traits/negative-impls/positive-specializes-negative.stderr [new file with mode: 0644]
src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs [new file with mode: 0644]
src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.stderr [new file with mode: 0644]
src/test/ui/traits/negative-impls/typeck-negative-impls-builtin.rs [new file with mode: 0644]
src/test/ui/traits/traits-negative-impls-rpass.rs [deleted file]
src/test/ui/traits/traits-negative-impls.rs [deleted file]
src/test/ui/traits/traits-negative-impls.stderr [deleted file]
src/test/ui/typeck/typeck-negative-impls-builtin.rs [deleted file]
src/test/ui/typeck/typeck-negative-impls-builtin.stderr [deleted file]

index 9a412e57294277452e900c180e245d4121548913..629c197e37691d06b06d066658479ba1af9a0459 100644 (file)
@@ -227,4 +227,9 @@ fn clone(&self) -> Self {
             *self
         }
     }
+
+    // Shared references can be cloned, but mutable references *cannot*!
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[cfg(not(bootstrap))]
+    impl<T: ?Sized> !Clone for &mut T {}
 }
index 68244fdb38114dc1e8e04f106a2974a4da742f0e..e2deeb556610cf63a34948c8075505eb64645cc2 100644 (file)
@@ -81,6 +81,10 @@ fn deref(&self) -> &T {
     }
 }
 
+#[cfg(not(bootstrap))]
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: ?Sized> !DerefMut for &T {}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> Deref for &mut T {
     type Target = T;
index 86da425060efabfc5984ff5340a83b514b6a15d1..bff20c2a62cef4961447bcef26cf81246c64cda7 100644 (file)
@@ -97,7 +97,6 @@
 E0185: include_str!("./error_codes/E0185.md"),
 E0186: include_str!("./error_codes/E0186.md"),
 E0191: include_str!("./error_codes/E0191.md"),
-E0192: include_str!("./error_codes/E0192.md"),
 E0193: include_str!("./error_codes/E0193.md"),
 E0195: include_str!("./error_codes/E0195.md"),
 E0197: include_str!("./error_codes/E0197.md"),
 E0746: include_str!("./error_codes/E0746.md"),
 E0747: include_str!("./error_codes/E0747.md"),
 E0748: include_str!("./error_codes/E0748.md"),
+E0749: include_str!("./error_codes/E0749.md"),
+E0750: include_str!("./error_codes/E0750.md"),
 ;
 //  E0006, // merged with E0005
 //  E0008, // cannot bind by-move into a pattern guard
 //  E0188, // can not cast an immutable reference to a mutable pointer
 //  E0189, // deprecated: can only cast a boxed pointer to a boxed object
 //  E0190, // deprecated: can only cast a &-pointer to an &-object
+//  E0192, // negative impl only applicable to auto traits
 //  E0194, // merged into E0403
 //  E0196, // cannot determine a type for this closure
     E0208,
diff --git a/src/librustc_error_codes/error_codes/E0749.md b/src/librustc_error_codes/error_codes/E0749.md
new file mode 100644 (file)
index 0000000..9eb8ee4
--- /dev/null
@@ -0,0 +1,4 @@
+Negative impls are not allowed to have any items. Negative impls
+declare that a trait is **not** implemented (and never will be) and
+hence there is no need to specify the values for trait methods or
+other items.
diff --git a/src/librustc_error_codes/error_codes/E0750.md b/src/librustc_error_codes/error_codes/E0750.md
new file mode 100644 (file)
index 0000000..e0cf56f
--- /dev/null
@@ -0,0 +1,4 @@
+Negative impls cannot be default impls. A default impl supplies
+default values for the items within to be used by other impls, whereas
+a negative impl declares that there are no other impls. These don't
+make sense to combine.
index e7ba00ac245076f8245b58c75dfdb6ba0e9e93ea..98ff5ccc82f694b9fa5fbd8f3dae6c4746248f36 100644 (file)
@@ -1659,11 +1659,14 @@ fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
             _ => unreachable!(),
         };
 
-        tcx.sess.span_err(span, &format!(
+        tcx.sess.span_err(
+            span,
+            &format!(
             "`{}` return type cannot contain a projection or `Self` that references lifetimes from \
              a parent scope",
             if is_async { "async fn" } else { "impl Trait" },
-        ));
+        ),
+        );
     }
 }
 
@@ -1841,8 +1844,8 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: DefId, span: Span)
         Ok(ConstValue::ByRef { alloc, .. }) => {
             if alloc.relocations().len() != 0 {
                 let msg = "statics with a custom `#[link_section]` must be a \
-                       simple list of bytes on the wasm target with no \
-                       extra levels of indirection such as references";
+                           simple list of bytes on the wasm target with no \
+                           extra levels of indirection such as references";
                 tcx.sess.span_err(span, msg);
             }
         }
@@ -1971,6 +1974,24 @@ fn check_impl_items_against_trait<'tcx>(
         return;
     }
 
+    // Negative impls are not expected to have any items
+    match tcx.impl_polarity(impl_id) {
+        ty::ImplPolarity::Reservation | ty::ImplPolarity::Positive => {}
+        ty::ImplPolarity::Negative => {
+            if !impl_item_refs.is_empty() {
+                let first_item_span = tcx.hir().impl_item(impl_item_refs[0].id).span;
+                struct_span_err!(
+                    tcx.sess,
+                    first_item_span,
+                    E0749,
+                    "negative impls cannot have any items"
+                )
+                .emit();
+            }
+            return;
+        }
+    }
+
     // Locate trait definition and items
     let trait_def = tcx.trait_def(impl_trait_ref.def_id);
 
@@ -2010,7 +2031,7 @@ fn check_impl_items_against_trait<'tcx>(
                             impl_item.span,
                             E0323,
                             "item `{}` is an associated const, \
-                              which doesn't match its trait `{}`",
+                             which doesn't match its trait `{}`",
                             ty_impl_item.ident,
                             impl_trait_ref.print_only_trait_path()
                         );
@@ -3554,7 +3575,7 @@ fn try_index_step(
         let adjusted_ty = autoderef.unambiguous_final_ty(self);
         debug!(
             "try_index_step(expr={:?}, base_expr={:?}, adjusted_ty={:?}, \
-                               index_ty={:?})",
+             index_ty={:?})",
             expr, base_expr, adjusted_ty, index_ty
         );
 
@@ -4705,7 +4726,7 @@ fn check_block_with_expected(
                                 err.span_label(
                                     fn_span,
                                     "implicitly returns `()` as its body has no tail or `return` \
-                                 expression",
+                                     expression",
                                 );
                             }
                         },
@@ -5577,11 +5598,14 @@ pub fn instantiate_value_path(
             match self.at(&self.misc(span), self.param_env).sup(impl_ty, self_ty) {
                 Ok(ok) => self.register_infer_ok_obligations(ok),
                 Err(_) => {
-                    self.tcx.sess.delay_span_bug(span, &format!(
+                    self.tcx.sess.delay_span_bug(
+                        span,
+                        &format!(
                         "instantiate_value_path: (UFCS) {:?} was a subtype of {:?} but now is not?",
                         self_ty,
                         impl_ty,
-                    ));
+                    ),
+                    );
                 }
             }
         }
@@ -5767,7 +5791,7 @@ fn fatally_break_rust(sess: &Session) {
     handler.note_without_error("the compiler expectedly panicked. this is a feature.");
     handler.note_without_error(
         "we would appreciate a joke overview: \
-        https://github.com/rust-lang/rust/issues/43162#issuecomment-320764675",
+         https://github.com/rust-lang/rust/issues/43162#issuecomment-320764675",
     );
     handler.note_without_error(&format!(
         "rustc {} running on {}",
index 27be0faade82f26cd0ff5b294ac049f8e0f91b7d..c89c4b028b4ea9b4124f18bcb62c50769ef7a92a 100644 (file)
@@ -124,18 +124,16 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: DefId) {
                 }
                 (ty::ImplPolarity::Negative, ast::ImplPolarity::Negative(span)) => {
                     // FIXME(#27579): what amount of WF checking do we need for neg impls?
-                    if let (Some(of_trait), false) = (of_trait, is_auto) {
+                    if let hir::Defaultness::Default { .. } = defaultness {
+                        let mut spans = vec![span];
+                        spans.extend(defaultness_span);
                         struct_span_err!(
                             tcx.sess,
-                            span.to(of_trait.path.span),
-                            E0192,
-                            "invalid negative impl"
+                            spans,
+                            E0750,
+                            "negative impls cannot be default impls"
                         )
-                        .note(
-                            "negative impls are only allowed for auto traits, like `Send` and \
-                             `Sync`",
-                        )
-                        .emit()
+                        .emit();
                     }
                 }
                 (ty::ImplPolarity::Reservation, _) => {
@@ -902,13 +900,13 @@ fn check_opaque_types<'fcx, 'tcx>(
                                             .struct_span_err(
                                                 span,
                                                 "non-defining opaque type use \
-                                                    in defining scope",
+                                                 in defining scope",
                                             )
                                             .span_label(
                                                 param_span,
                                                 "cannot use static lifetime; use a bound lifetime \
-                                                instead or remove the lifetime parameter from the \
-                                                opaque type",
+                                                 instead or remove the lifetime parameter from the \
+                                                 opaque type",
                                             )
                                             .emit();
                                     } else {
@@ -923,13 +921,13 @@ fn check_opaque_types<'fcx, 'tcx>(
                                             .struct_span_err(
                                                 span,
                                                 "non-defining opaque type use \
-                                                in defining scope",
+                                                 in defining scope",
                                             )
                                             .span_note(
                                                 tcx.def_span(param.def_id),
                                                 &format!(
                                                     "used non-generic const {} for \
-                                                    generic parameter",
+                                                     generic parameter",
                                                     ty,
                                                 ),
                                             )
@@ -944,7 +942,7 @@ fn check_opaque_types<'fcx, 'tcx>(
                                     .struct_span_err(
                                         span,
                                         "non-defining opaque type use \
-                                            in defining scope",
+                                         in defining scope",
                                     )
                                     .span_note(spans, "lifetime used multiple times")
                                     .emit();
@@ -1030,7 +1028,7 @@ fn check_method_receiver<'fcx, 'tcx>(
                     span,
                     &format!(
                         "`{}` cannot be used as the type of `self` without \
-                            the `arbitrary_self_types` feature",
+                         the `arbitrary_self_types` feature",
                         receiver_ty,
                     ),
                 )
diff --git a/src/test/ui/error-codes/E0192.rs b/src/test/ui/error-codes/E0192.rs
deleted file mode 100644 (file)
index c52977e..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#![feature(optin_builtin_traits)]
-
-trait Trait {
-    type Bar;
-}
-
-struct Foo;
-
-impl !Trait for Foo { } //~ ERROR E0192
-
-fn main() {
-}
diff --git a/src/test/ui/error-codes/E0192.stderr b/src/test/ui/error-codes/E0192.stderr
deleted file mode 100644 (file)
index da706de..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0192]: invalid negative impl
-  --> $DIR/E0192.rs:9:6
-   |
-LL | impl !Trait for Foo { }
-   |      ^^^^^^
-   |
-   = note: negative impls are only allowed for auto traits, like `Send` and `Sync`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0192`.
index 5b8a72104e31af64fb26243f381b40949f31153b..ac8742c70c8787f97198d750bf1608a376f2ad6b 100644 (file)
@@ -8,8 +8,9 @@
 
 default unsafe impl Send for S {} //~ ERROR impls of auto traits cannot be default
 default impl !Send for Z {} //~ ERROR impls of auto traits cannot be default
+                            //~^ ERROR negative impls cannot be default impls
 
 trait Tr {}
-default impl !Tr for S {} //~ ERROR invalid negative impl
+default impl !Tr for S {} //~ ERROR negative impls cannot be default impls
 
 fn main() {}
index e03153f343b8ecfbd15790586b8938cf4aac6921..9bf59bd4f636a494c2d83aa0d857cada0dee19d6 100644 (file)
@@ -24,14 +24,18 @@ LL | default impl !Send for Z {}
    | |
    | default because of this
 
-error[E0192]: invalid negative impl
-  --> $DIR/validation.rs:13:14
+error[E0750]: negative impls cannot be default impls
+  --> $DIR/validation.rs:10:14
    |
-LL | default impl !Tr for S {}
-   |              ^^^
+LL | default impl !Send for Z {}
+   | ^^^^^^^      ^
+
+error[E0750]: negative impls cannot be default impls
+  --> $DIR/validation.rs:14:14
    |
-   = note: negative impls are only allowed for auto traits, like `Send` and `Sync`
+LL | default impl !Tr for S {}
+   | ^^^^^^^      ^
 
-error: aborting due to 4 previous errors
+error: aborting due to 5 previous errors
 
-For more information about this error, try `rustc --explain E0192`.
+For more information about this error, try `rustc --explain E0750`.
index bfbe6394c16942b9c0408b32b4715dde78eb394d..739a3c12dfb41059ec844ddfe150c4e1bfdebf2d 100644 (file)
@@ -12,7 +12,6 @@ trait TestTrait {}
 unsafe impl !Send for TestType {}
 //~^ ERROR negative impls cannot be unsafe
 impl !TestTrait for TestType {}
-//~^ ERROR invalid negative impl
 
 struct TestType2<T>(T);
 
@@ -22,6 +21,5 @@ impl<T> !TestType2<T> {}
 unsafe impl<T> !Send for TestType2<T> {}
 //~^ ERROR negative impls cannot be unsafe
 impl<T> !TestTrait for TestType2<T> {}
-//~^ ERROR invalid negative impl
 
 fn main() {}
index f70d67ec7dc98286803cab95b8e0913b1800a156..1fd40fb66570df1c093a2ee08593be2869871655 100644 (file)
@@ -16,7 +16,7 @@ LL | unsafe impl !Send for TestType {}
    | unsafe because of this
 
 error: inherent impls cannot be negative
-  --> $DIR/syntax-trait-polarity.rs:19:10
+  --> $DIR/syntax-trait-polarity.rs:18:10
    |
 LL | impl<T> !TestType2<T> {}
    |         -^^^^^^^^^^^^ inherent impl for this type
@@ -24,7 +24,7 @@ LL | impl<T> !TestType2<T> {}
    |         negative because of this
 
 error[E0198]: negative impls cannot be unsafe
-  --> $DIR/syntax-trait-polarity.rs:22:16
+  --> $DIR/syntax-trait-polarity.rs:21:16
    |
 LL | unsafe impl<T> !Send for TestType2<T> {}
    | ------         -^^^^
@@ -32,23 +32,6 @@ LL | unsafe impl<T> !Send for TestType2<T> {}
    | |              negative because of this
    | unsafe because of this
 
-error[E0192]: invalid negative impl
-  --> $DIR/syntax-trait-polarity.rs:14:6
-   |
-LL | impl !TestTrait for TestType {}
-   |      ^^^^^^^^^^
-   |
-   = note: negative impls are only allowed for auto traits, like `Send` and `Sync`
-
-error[E0192]: invalid negative impl
-  --> $DIR/syntax-trait-polarity.rs:24:9
-   |
-LL | impl<T> !TestTrait for TestType2<T> {}
-   |         ^^^^^^^^^^
-   |
-   = note: negative impls are only allowed for auto traits, like `Send` and `Sync`
-
-error: aborting due to 6 previous errors
+error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0192, E0198.
-For more information about an error, try `rustc --explain E0192`.
+For more information about this error, try `rustc --explain E0198`.
diff --git a/src/test/ui/traits/negative-impls/auxiliary/foreign_trait.rs b/src/test/ui/traits/negative-impls/auxiliary/foreign_trait.rs
new file mode 100644 (file)
index 0000000..1790b24
--- /dev/null
@@ -0,0 +1,6 @@
+#![feature(optin_builtin_traits)]
+
+pub trait ForeignTrait { }
+
+impl ForeignTrait for u32 { }
+impl !ForeignTrait for String {}
diff --git a/src/test/ui/traits/negative-impls/negated-auto-traits-error.rs b/src/test/ui/traits/negative-impls/negated-auto-traits-error.rs
new file mode 100644 (file)
index 0000000..fb9a3a9
--- /dev/null
@@ -0,0 +1,68 @@
+// The dummy functions are used to avoid adding new cfail files.
+// What happens is that the compiler attempts to squash duplicates and some
+// errors are not reported. This way, we make sure that, for each function, different
+// typeck phases are involved and all errors are reported.
+
+#![feature(optin_builtin_traits)]
+
+use std::marker::Send;
+
+struct Outer<T: Send>(T);
+
+struct Outer2<T>(T);
+
+unsafe impl<T: Send> Sync for Outer2<T> {}
+
+fn is_send<T: Send>(_: T) {}
+fn is_sync<T: Sync>(_: T) {}
+
+fn dummy() {
+    struct TestType;
+    impl !Send for TestType {}
+
+    Outer(TestType);
+    //~^ ERROR `dummy::TestType` cannot be sent between threads safely
+    //~| ERROR `dummy::TestType` cannot be sent between threads safely
+}
+
+fn dummy1b() {
+    struct TestType;
+    impl !Send for TestType {}
+
+    is_send(TestType);
+    //~^ ERROR `dummy1b::TestType` cannot be sent between threads safely
+}
+
+fn dummy1c() {
+    struct TestType;
+    impl !Send for TestType {}
+
+    is_send((8, TestType));
+    //~^ ERROR `dummy1c::TestType` cannot be sent between threads safely
+}
+
+fn dummy2() {
+    struct TestType;
+    impl !Send for TestType {}
+
+    is_send(Box::new(TestType));
+    //~^ ERROR `dummy2::TestType` cannot be sent between threads safely
+}
+
+fn dummy3() {
+    struct TestType;
+    impl !Send for TestType {}
+
+    is_send(Box::new(Outer2(TestType)));
+    //~^ ERROR `dummy3::TestType` cannot be sent between threads safely
+}
+
+fn main() {
+    struct TestType;
+    impl !Send for TestType {}
+
+    // This will complain about a missing Send impl because `Sync` is implement *just*
+    // for T that are `Send`. Look at #20366 and #19950
+    is_sync(Outer2(TestType));
+    //~^ ERROR `main::TestType` cannot be sent between threads safely
+}
diff --git a/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr b/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr
new file mode 100644 (file)
index 0000000..69a91b0
--- /dev/null
@@ -0,0 +1,93 @@
+error[E0277]: `dummy::TestType` cannot be sent between threads safely
+  --> $DIR/negated-auto-traits-error.rs:23:11
+   |
+LL | struct Outer<T: Send>(T);
+   | ------------------------- required by `Outer`
+...
+LL |     Outer(TestType);
+   |           ^^^^^^^^ `dummy::TestType` cannot be sent between threads safely
+   |
+   = help: the trait `std::marker::Send` is not implemented for `dummy::TestType`
+
+error[E0277]: `dummy::TestType` cannot be sent between threads safely
+  --> $DIR/negated-auto-traits-error.rs:23:5
+   |
+LL | struct Outer<T: Send>(T);
+   | ------------------------- required by `Outer`
+...
+LL |     Outer(TestType);
+   |     ^^^^^^^^^^^^^^^ `dummy::TestType` cannot be sent between threads safely
+   |
+   = help: the trait `std::marker::Send` is not implemented for `dummy::TestType`
+
+error[E0277]: `dummy1b::TestType` cannot be sent between threads safely
+  --> $DIR/negated-auto-traits-error.rs:32:13
+   |
+LL | fn is_send<T: Send>(_: T) {}
+   |    -------    ---- required by this bound in `is_send`
+...
+LL |     is_send(TestType);
+   |             ^^^^^^^^ `dummy1b::TestType` cannot be sent between threads safely
+   |
+   = help: the trait `std::marker::Send` is not implemented for `dummy1b::TestType`
+
+error[E0277]: `dummy1c::TestType` cannot be sent between threads safely
+  --> $DIR/negated-auto-traits-error.rs:40:13
+   |
+LL | fn is_send<T: Send>(_: T) {}
+   |    -------    ---- required by this bound in `is_send`
+...
+LL |     is_send((8, TestType));
+   |             ^^^^^^^^^^^^^ `dummy1c::TestType` cannot be sent between threads safely
+   |
+   = help: within `({integer}, dummy1c::TestType)`, the trait `std::marker::Send` is not implemented for `dummy1c::TestType`
+   = note: required because it appears within the type `({integer}, dummy1c::TestType)`
+
+error[E0277]: `dummy2::TestType` cannot be sent between threads safely
+  --> $DIR/negated-auto-traits-error.rs:48:13
+   |
+LL | fn is_send<T: Send>(_: T) {}
+   |    -------    ---- required by this bound in `is_send`
+...
+LL |     is_send(Box::new(TestType));
+   |             ^^^^^^^^^^^^^^^^^^
+   |             |
+   |             expected an implementor of trait `std::marker::Send`
+   |             help: consider borrowing here: `&Box::new(TestType)`
+   |
+   = note: the trait bound `dummy2::TestType: std::marker::Send` is not satisfied
+   = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<dummy2::TestType>`
+   = note: required because it appears within the type `std::boxed::Box<dummy2::TestType>`
+
+error[E0277]: `dummy3::TestType` cannot be sent between threads safely
+  --> $DIR/negated-auto-traits-error.rs:56:13
+   |
+LL | fn is_send<T: Send>(_: T) {}
+   |    -------    ---- required by this bound in `is_send`
+...
+LL |     is_send(Box::new(Outer2(TestType)));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ `dummy3::TestType` cannot be sent between threads safely
+   |
+   = help: within `Outer2<dummy3::TestType>`, the trait `std::marker::Send` is not implemented for `dummy3::TestType`
+   = note: required because it appears within the type `Outer2<dummy3::TestType>`
+   = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<Outer2<dummy3::TestType>>`
+   = note: required because it appears within the type `std::boxed::Box<Outer2<dummy3::TestType>>`
+
+error[E0277]: `main::TestType` cannot be sent between threads safely
+  --> $DIR/negated-auto-traits-error.rs:66:13
+   |
+LL | fn is_sync<T: Sync>(_: T) {}
+   |    -------    ---- required by this bound in `is_sync`
+...
+LL |     is_sync(Outer2(TestType));
+   |             ^^^^^^^^^^^^^^^^
+   |             |
+   |             expected an implementor of trait `std::marker::Sync`
+   |             help: consider borrowing here: `&Outer2(TestType)`
+   |
+   = note: the trait bound `main::TestType: std::marker::Sync` is not satisfied
+   = note: required because of the requirements on the impl of `std::marker::Sync` for `Outer2<main::TestType>`
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/traits/negative-impls/negated-auto-traits-rpass.rs b/src/test/ui/traits/negative-impls/negated-auto-traits-rpass.rs
new file mode 100644 (file)
index 0000000..8664b6a
--- /dev/null
@@ -0,0 +1,21 @@
+// run-pass
+#![allow(unused_variables)]
+#![feature(optin_builtin_traits)]
+
+use std::marker::Send;
+
+pub struct WaitToken;
+impl !Send for WaitToken {}
+
+pub struct Test<T>(T);
+unsafe impl<T: 'static> Send for Test<T> {}
+
+pub fn spawn<F>(_: F) -> () where F: FnOnce(), F: Send + 'static {}
+
+fn main() {
+    let wt = Test(WaitToken);
+    spawn(move || {
+        let x = wt;
+        println!("Hello, World!");
+    });
+}
diff --git a/src/test/ui/traits/negative-impls/negative-default-impls.rs b/src/test/ui/traits/negative-impls/negative-default-impls.rs
new file mode 100644 (file)
index 0000000..b23ac87
--- /dev/null
@@ -0,0 +1,10 @@
+#![feature(optin_builtin_traits)]
+#![feature(specialization)]
+
+trait MyTrait {
+    type Foo;
+}
+
+default impl !MyTrait for u32 {} //~ ERROR negative impls cannot be default impls
+
+fn main() {}
diff --git a/src/test/ui/traits/negative-impls/negative-default-impls.stderr b/src/test/ui/traits/negative-impls/negative-default-impls.stderr
new file mode 100644 (file)
index 0000000..d2423d0
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0750]: negative impls cannot be default impls
+  --> $DIR/negative-default-impls.rs:8:14
+   |
+LL | default impl !MyTrait for u32 {}
+   | ^^^^^^^      ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0750`.
diff --git a/src/test/ui/traits/negative-impls/negative-specializes-positive-item.rs b/src/test/ui/traits/negative-impls/negative-specializes-positive-item.rs
new file mode 100644 (file)
index 0000000..2ebf0bd
--- /dev/null
@@ -0,0 +1,13 @@
+#![feature(specialization)]
+#![feature(optin_builtin_traits)]
+
+// Negative impl for u32 cannot "specialize" the base impl.
+trait MyTrait {
+    fn foo();
+}
+impl<T> MyTrait for T {
+    default fn foo() { }
+}
+impl !MyTrait for u32 { } //~ ERROR conflicting implementations
+
+fn main() { }
diff --git a/src/test/ui/traits/negative-impls/negative-specializes-positive-item.stderr b/src/test/ui/traits/negative-impls/negative-specializes-positive-item.stderr
new file mode 100644 (file)
index 0000000..83421b4
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `MyTrait` for type `u32`:
+  --> $DIR/negative-specializes-positive-item.rs:11:1
+   |
+LL | impl<T> MyTrait for T {
+   | --------------------- first implementation here
+...
+LL | impl !MyTrait for u32 { }
+   | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/traits/negative-impls/negative-specializes-positive.rs b/src/test/ui/traits/negative-impls/negative-specializes-positive.rs
new file mode 100644 (file)
index 0000000..7ab0161
--- /dev/null
@@ -0,0 +1,14 @@
+#![feature(specialization)]
+#![feature(optin_builtin_traits)]
+
+// Negative impl for u32 cannot "specialize" the base impl.
+trait MyTrait { }
+impl<T> MyTrait for T { }
+impl !MyTrait for u32 { } //~ ERROR conflicting implementations
+
+// The second impl specializes the first, no error.
+trait MyTrait2 { }
+impl<T> MyTrait2 for T { }
+impl MyTrait2 for u32 { }
+
+fn main() { }
diff --git a/src/test/ui/traits/negative-impls/negative-specializes-positive.stderr b/src/test/ui/traits/negative-impls/negative-specializes-positive.stderr
new file mode 100644 (file)
index 0000000..a542e88
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0119]: conflicting implementations of trait `MyTrait` for type `u32`:
+  --> $DIR/negative-specializes-positive.rs:7:1
+   |
+LL | impl<T> MyTrait for T { }
+   | --------------------- first implementation here
+LL | impl !MyTrait for u32 { }
+   | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/traits/negative-impls/no-items.rs b/src/test/ui/traits/negative-impls/no-items.rs
new file mode 100644 (file)
index 0000000..5bfbf96
--- /dev/null
@@ -0,0 +1,11 @@
+#![feature(optin_builtin_traits)]
+
+trait MyTrait {
+    type Foo;
+}
+
+impl !MyTrait for u32 {
+    type Foo = i32; //~ ERROR negative impls cannot have any items
+}
+
+fn main() {}
diff --git a/src/test/ui/traits/negative-impls/no-items.stderr b/src/test/ui/traits/negative-impls/no-items.stderr
new file mode 100644 (file)
index 0000000..67b94bb
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0749]: negative impls cannot have any items
+  --> $DIR/no-items.rs:8:5
+   |
+LL |     type Foo = i32;
+   |     ^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0749`.
diff --git a/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs
new file mode 100644 (file)
index 0000000..5c3e7fe
--- /dev/null
@@ -0,0 +1,26 @@
+use std::cell::Cell;
+use std::marker::PhantomPinned;
+use std::pin::Pin;
+
+struct MyType<'a>(Cell<Option<&'a mut MyType<'a>>>, PhantomPinned);
+
+impl<'a> Clone for &'a mut MyType<'a> { //~ ERROR conflicting implementations
+    fn clone(&self) -> &'a mut MyType<'a> {
+        self.0.replace(None).unwrap()
+    }
+}
+
+
+fn main() {
+    let mut unpinned = MyType(Cell::new(None), PhantomPinned);
+    let bad_addr = &unpinned as *const MyType<'_> as usize;
+    let mut p = Box::pin(MyType(Cell::new(Some(&mut unpinned)), PhantomPinned));
+
+    // p_mut1 is okay: it does not point to the bad_addr
+    let p_mut1: Pin<&mut MyType<'_>> = p.as_mut();
+    assert_ne!(bad_addr, &*p_mut1 as *const _ as usize);
+
+    // but p_mut2 does point to bad_addr! this is unsound
+    let p_mut2: Pin<&mut MyType<'_>> = p_mut1.clone();
+    assert_eq!(bad_addr, &*p_mut2 as *const _ as usize);
+}
diff --git a/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr
new file mode 100644 (file)
index 0000000..1655d80
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0119]: conflicting implementations of trait `std::clone::Clone` for type `&mut MyType<'_>`:
+  --> $DIR/pin-unsound-issue-66544-clone.rs:7:1
+   |
+LL | impl<'a> Clone for &'a mut MyType<'a> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: conflicting implementation in crate `core`:
+           - impl<T> std::clone::Clone for &mut T
+             where T: ?Sized;
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs
new file mode 100644 (file)
index 0000000..a34b8d6
--- /dev/null
@@ -0,0 +1,33 @@
+// Demonstrate that "rogue" `DerefMut` impls for `&T` are not allowed.
+//
+// https://github.com/rust-lang/rust/issues/66544
+
+use std::cell::Cell;
+use std::marker::PhantomPinned;
+use std::ops::DerefMut;
+use std::pin::Pin;
+
+struct MyType<'a>(Cell<Option<&'a mut MyType<'a>>>, PhantomPinned);
+
+impl<'a> DerefMut for &'a MyType<'a> { //~ ERROR conflicting implementations
+    fn deref_mut(&mut self) -> &mut MyType<'a> {
+        self.0.replace(None).unwrap()
+    }
+}
+
+
+fn main() {
+    let mut unpinned = MyType(Cell::new(None), PhantomPinned);
+    let bad_addr = &unpinned as *const MyType<'_> as usize;
+    let p = Box::pin(MyType(Cell::new(Some(&mut unpinned)), PhantomPinned));
+
+    // p_ref is okay: it does not point to the bad_addr
+    let mut p_ref: Pin<&MyType<'_>> = p.as_ref();
+    assert_ne!(bad_addr, &*p_ref as *const _ as usize);
+
+    // but p_mut does point to bad_addr! this is unsound
+    let p_mut: Pin<&mut MyType<'_>> = p_ref.as_mut();
+    assert_eq!(bad_addr, &*p_mut as *const _ as usize);
+
+    println!("oh no!");
+}
diff --git a/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr
new file mode 100644 (file)
index 0000000..80c9682
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0119]: conflicting implementations of trait `std::ops::DerefMut` for type `&MyType<'_>`:
+  --> $DIR/pin-unsound-issue-66544-derefmut.rs:12:1
+   |
+LL | impl<'a> DerefMut for &'a MyType<'a> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: conflicting implementation in crate `core`:
+           - impl<T> std::ops::DerefMut for &T
+             where T: ?Sized;
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/traits/negative-impls/positive-specializes-negative.rs b/src/test/ui/traits/negative-impls/positive-specializes-negative.rs
new file mode 100644 (file)
index 0000000..20267cf
--- /dev/null
@@ -0,0 +1,9 @@
+#![feature(specialization)]
+#![feature(optin_builtin_traits)]
+
+trait MyTrait { }
+
+impl<T> !MyTrait for T { }
+impl MyTrait for u32 { } //~ ERROR conflicting implementations
+
+fn main() { }
diff --git a/src/test/ui/traits/negative-impls/positive-specializes-negative.stderr b/src/test/ui/traits/negative-impls/positive-specializes-negative.stderr
new file mode 100644 (file)
index 0000000..6e41759
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0119]: conflicting implementations of trait `MyTrait` for type `u32`:
+  --> $DIR/positive-specializes-negative.rs:7:1
+   |
+LL | impl<T> !MyTrait for T { }
+   | ---------------------- first implementation here
+LL | impl MyTrait for u32 { }
+   | ^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs b/src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs
new file mode 100644 (file)
index 0000000..b823c0f
--- /dev/null
@@ -0,0 +1,21 @@
+#![feature(optin_builtin_traits)]
+
+// aux-build: foreign_trait.rs
+
+// Test that we cannot implement `LocalTrait` for `String`,
+// even though there is a `String: !ForeignTrait` impl.
+//
+// This may not be the behavior we want long term, but it's the
+// current semantics that we implemented so as to land `!Foo` impls
+// quickly. See internals thread:
+//
+// https://internals.rust-lang.org/t/foo/11587/
+
+extern crate foreign_trait;
+use foreign_trait::ForeignTrait;
+
+trait LocalTrait { }
+impl<T: ForeignTrait> LocalTrait for T { }
+impl LocalTrait for String { } //~ ERROR conflicting implementations
+
+fn main() { }
diff --git a/src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.stderr b/src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.stderr
new file mode 100644 (file)
index 0000000..7cce45d
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0119]: conflicting implementations of trait `LocalTrait` for type `std::string::String`:
+  --> $DIR/rely-on-negative-impl-in-coherence.rs:19:1
+   |
+LL | impl<T: ForeignTrait> LocalTrait for T { }
+   | -------------------------------------- first implementation here
+LL | impl LocalTrait for String { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `std::string::String`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/traits/negative-impls/typeck-negative-impls-builtin.rs b/src/test/ui/traits/negative-impls/typeck-negative-impls-builtin.rs
new file mode 100644 (file)
index 0000000..6a2e99f
--- /dev/null
@@ -0,0 +1,14 @@
+// run-pass
+
+#![feature(optin_builtin_traits)]
+#![allow(dead_code)]
+
+struct TestType;
+
+trait TestTrait {
+    fn dummy(&self) {}
+}
+
+impl !TestTrait for TestType {}
+
+fn main() {}
diff --git a/src/test/ui/traits/traits-negative-impls-rpass.rs b/src/test/ui/traits/traits-negative-impls-rpass.rs
deleted file mode 100644 (file)
index 8664b6a..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// run-pass
-#![allow(unused_variables)]
-#![feature(optin_builtin_traits)]
-
-use std::marker::Send;
-
-pub struct WaitToken;
-impl !Send for WaitToken {}
-
-pub struct Test<T>(T);
-unsafe impl<T: 'static> Send for Test<T> {}
-
-pub fn spawn<F>(_: F) -> () where F: FnOnce(), F: Send + 'static {}
-
-fn main() {
-    let wt = Test(WaitToken);
-    spawn(move || {
-        let x = wt;
-        println!("Hello, World!");
-    });
-}
diff --git a/src/test/ui/traits/traits-negative-impls.rs b/src/test/ui/traits/traits-negative-impls.rs
deleted file mode 100644 (file)
index fb9a3a9..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-// The dummy functions are used to avoid adding new cfail files.
-// What happens is that the compiler attempts to squash duplicates and some
-// errors are not reported. This way, we make sure that, for each function, different
-// typeck phases are involved and all errors are reported.
-
-#![feature(optin_builtin_traits)]
-
-use std::marker::Send;
-
-struct Outer<T: Send>(T);
-
-struct Outer2<T>(T);
-
-unsafe impl<T: Send> Sync for Outer2<T> {}
-
-fn is_send<T: Send>(_: T) {}
-fn is_sync<T: Sync>(_: T) {}
-
-fn dummy() {
-    struct TestType;
-    impl !Send for TestType {}
-
-    Outer(TestType);
-    //~^ ERROR `dummy::TestType` cannot be sent between threads safely
-    //~| ERROR `dummy::TestType` cannot be sent between threads safely
-}
-
-fn dummy1b() {
-    struct TestType;
-    impl !Send for TestType {}
-
-    is_send(TestType);
-    //~^ ERROR `dummy1b::TestType` cannot be sent between threads safely
-}
-
-fn dummy1c() {
-    struct TestType;
-    impl !Send for TestType {}
-
-    is_send((8, TestType));
-    //~^ ERROR `dummy1c::TestType` cannot be sent between threads safely
-}
-
-fn dummy2() {
-    struct TestType;
-    impl !Send for TestType {}
-
-    is_send(Box::new(TestType));
-    //~^ ERROR `dummy2::TestType` cannot be sent between threads safely
-}
-
-fn dummy3() {
-    struct TestType;
-    impl !Send for TestType {}
-
-    is_send(Box::new(Outer2(TestType)));
-    //~^ ERROR `dummy3::TestType` cannot be sent between threads safely
-}
-
-fn main() {
-    struct TestType;
-    impl !Send for TestType {}
-
-    // This will complain about a missing Send impl because `Sync` is implement *just*
-    // for T that are `Send`. Look at #20366 and #19950
-    is_sync(Outer2(TestType));
-    //~^ ERROR `main::TestType` cannot be sent between threads safely
-}
diff --git a/src/test/ui/traits/traits-negative-impls.stderr b/src/test/ui/traits/traits-negative-impls.stderr
deleted file mode 100644 (file)
index 599bbfe..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-error[E0277]: `dummy::TestType` cannot be sent between threads safely
-  --> $DIR/traits-negative-impls.rs:23:11
-   |
-LL | struct Outer<T: Send>(T);
-   | ------------------------- required by `Outer`
-...
-LL |     Outer(TestType);
-   |           ^^^^^^^^ `dummy::TestType` cannot be sent between threads safely
-   |
-   = help: the trait `std::marker::Send` is not implemented for `dummy::TestType`
-
-error[E0277]: `dummy::TestType` cannot be sent between threads safely
-  --> $DIR/traits-negative-impls.rs:23:5
-   |
-LL | struct Outer<T: Send>(T);
-   | ------------------------- required by `Outer`
-...
-LL |     Outer(TestType);
-   |     ^^^^^^^^^^^^^^^ `dummy::TestType` cannot be sent between threads safely
-   |
-   = help: the trait `std::marker::Send` is not implemented for `dummy::TestType`
-
-error[E0277]: `dummy1b::TestType` cannot be sent between threads safely
-  --> $DIR/traits-negative-impls.rs:32:13
-   |
-LL | fn is_send<T: Send>(_: T) {}
-   |    -------    ---- required by this bound in `is_send`
-...
-LL |     is_send(TestType);
-   |             ^^^^^^^^ `dummy1b::TestType` cannot be sent between threads safely
-   |
-   = help: the trait `std::marker::Send` is not implemented for `dummy1b::TestType`
-
-error[E0277]: `dummy1c::TestType` cannot be sent between threads safely
-  --> $DIR/traits-negative-impls.rs:40:13
-   |
-LL | fn is_send<T: Send>(_: T) {}
-   |    -------    ---- required by this bound in `is_send`
-...
-LL |     is_send((8, TestType));
-   |             ^^^^^^^^^^^^^ `dummy1c::TestType` cannot be sent between threads safely
-   |
-   = help: within `({integer}, dummy1c::TestType)`, the trait `std::marker::Send` is not implemented for `dummy1c::TestType`
-   = note: required because it appears within the type `({integer}, dummy1c::TestType)`
-
-error[E0277]: `dummy2::TestType` cannot be sent between threads safely
-  --> $DIR/traits-negative-impls.rs:48:13
-   |
-LL | fn is_send<T: Send>(_: T) {}
-   |    -------    ---- required by this bound in `is_send`
-...
-LL |     is_send(Box::new(TestType));
-   |             ^^^^^^^^^^^^^^^^^^
-   |             |
-   |             expected an implementor of trait `std::marker::Send`
-   |             help: consider borrowing here: `&Box::new(TestType)`
-   |
-   = note: the trait bound `dummy2::TestType: std::marker::Send` is not satisfied
-   = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<dummy2::TestType>`
-   = note: required because it appears within the type `std::boxed::Box<dummy2::TestType>`
-
-error[E0277]: `dummy3::TestType` cannot be sent between threads safely
-  --> $DIR/traits-negative-impls.rs:56:13
-   |
-LL | fn is_send<T: Send>(_: T) {}
-   |    -------    ---- required by this bound in `is_send`
-...
-LL |     is_send(Box::new(Outer2(TestType)));
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ `dummy3::TestType` cannot be sent between threads safely
-   |
-   = help: within `Outer2<dummy3::TestType>`, the trait `std::marker::Send` is not implemented for `dummy3::TestType`
-   = note: required because it appears within the type `Outer2<dummy3::TestType>`
-   = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<Outer2<dummy3::TestType>>`
-   = note: required because it appears within the type `std::boxed::Box<Outer2<dummy3::TestType>>`
-
-error[E0277]: `main::TestType` cannot be sent between threads safely
-  --> $DIR/traits-negative-impls.rs:66:13
-   |
-LL | fn is_sync<T: Sync>(_: T) {}
-   |    -------    ---- required by this bound in `is_sync`
-...
-LL |     is_sync(Outer2(TestType));
-   |             ^^^^^^^^^^^^^^^^
-   |             |
-   |             expected an implementor of trait `std::marker::Sync`
-   |             help: consider borrowing here: `&Outer2(TestType)`
-   |
-   = note: the trait bound `main::TestType: std::marker::Sync` is not satisfied
-   = note: required because of the requirements on the impl of `std::marker::Sync` for `Outer2<main::TestType>`
-
-error: aborting due to 7 previous errors
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/typeck/typeck-negative-impls-builtin.rs b/src/test/ui/typeck/typeck-negative-impls-builtin.rs
deleted file mode 100644 (file)
index fef9897..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#![feature(optin_builtin_traits)]
-
-struct TestType;
-
-trait TestTrait {
-    fn dummy(&self) { }
-}
-
-impl !TestTrait for TestType {}
-//~^ ERROR invalid negative impl
-
-fn main() {}
diff --git a/src/test/ui/typeck/typeck-negative-impls-builtin.stderr b/src/test/ui/typeck/typeck-negative-impls-builtin.stderr
deleted file mode 100644 (file)
index c906550..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0192]: invalid negative impl
-  --> $DIR/typeck-negative-impls-builtin.rs:9:6
-   |
-LL | impl !TestTrait for TestType {}
-   |      ^^^^^^^^^^
-   |
-   = note: negative impls are only allowed for auto traits, like `Send` and `Sync`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0192`.