diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index f6991120f3479..1906a9b2875b6 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -1,6 +1,5 @@ use crate::check::regionck::RegionCtxt; use crate::hir; -use crate::hir::def_id::{DefId, LocalDefId}; use rustc_errors::{struct_span_err, ErrorReported}; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{InferOk, RegionckMode, TyCtxtInferExt}; @@ -9,6 +8,7 @@ use rustc_middle::ty::error::TypeError; use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; use rustc_middle::ty::subst::{Subst, SubstsRef}; use rustc_middle::ty::{self, Predicate, Ty, TyCtxt}; +use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::Span; use rustc_trait_selection::traits::error_reporting::InferCtxtExt; use rustc_trait_selection::traits::query::dropck_outlives::AtExt; @@ -32,9 +32,30 @@ use rustc_trait_selection::traits::{ObligationCause, TraitEngine, TraitEngineExt /// cannot do `struct S; impl Drop for S { ... }`). /// pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), ErrorReported> { + check_restricted_impl(tcx, drop_impl_did) +} + +pub fn check_restricted_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), ErrorReported> { let dtor_self_type = tcx.type_of(drop_impl_did); let dtor_predicates = tcx.predicates_of(drop_impl_did); - match dtor_self_type.kind { + + let check_empty_where_bounds = |s| { + if dtor_predicates.predicates.is_empty() { + Ok(()) + } else { + // FIXME(negative_impls): Improve the diagnostics for `T: Sized` here. + // + // In this case the problem is not that there are unexpected where bounds, + // but instead, that a parameter is missing `T: ?Sized`. + tcx.sess.span_err( + tcx.def_span(drop_impl_did), + &format!("negative impls on {} must not contain where bounds", s), + ); + Err(ErrorReported) + } + }; + + let kind_str = match dtor_self_type.kind { ty::Adt(adt_def, self_to_impl_substs) => { ensure_drop_params_and_item_params_correspond( tcx, @@ -43,25 +64,82 @@ pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), Erro adt_def.did, )?; - ensure_drop_predicates_are_implied_by_item_defn( + return ensure_drop_predicates_are_implied_by_item_defn( tcx, + drop_impl_did.expect_local(), dtor_predicates, - adt_def.did.expect_local(), + adt_def.did, self_to_impl_substs, - ) + ); } - _ => { - // Destructors only work on nominal types. This was + _ if tcx.lang_items().drop_trait() + == Some(tcx.impl_trait_ref(drop_impl_did).unwrap().def_id) => + { + // Destructors only work on nominal types. This was // already checked by coherence, but compilation may // not have been terminated. - let span = tcx.def_span(drop_impl_did); tcx.sess.delay_span_bug( - span, + tcx.def_span(drop_impl_did), &format!("should have been rejected by coherence check: {}", dtor_self_type), ); - Err(ErrorReported) + return Err(ErrorReported); } - } + ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => { + return check_empty_where_bounds("primitive types"); + } + ty::Foreign(_) => { + return check_empty_where_bounds("foreign types"); + } + ty::Array(..) => { + // FIXME: Support negative impls for `[T; N]` where `T: Sized` is the only predicate. + "arrays" + } + ty::Slice(..) => { + // FIXME: Support negative impls for `[T]` where `T: Sized` is the only predicate. + "slices" + } + ty::RawPtr(..) => { + return check_empty_where_bounds("raw pointers"); + } + ty::Ref(..) => { + return check_empty_where_bounds("references"); + } + ty::FnPtr(..) => { + // In case we ever get variadic functions allowing this would mean that we have + // specialized negative impls on stable. + "function pointers" + } + ty::Dynamic(..) => { + return check_empty_where_bounds("trait objects"); + } + ty::Never => { + return check_empty_where_bounds("`!`"); + } + ty::Tuple(..) => { + // In case we ever get variadic tuples allowing this would mean that we have + // specialized negative impls on stable. + "tuples" + } + ty::Projection(..) => "projections", + ty::Opaque(..) => "opaque types", + ty::Param(..) => { + return check_empty_where_bounds("type parameters"); + } + ty::Error(..) => return Ok(()), + ty::FnDef(..) + | ty::Closure(..) + | ty::Generator(..) + | ty::GeneratorWitness(..) + | ty::Bound(..) + | ty::Placeholder(..) + | ty::Infer(..) => bug!("unexpected impl self ty: {:?}", dtor_self_type), + }; + + tcx.sess.span_err( + tcx.def_span(drop_impl_did), + &format!("negative impls are not allowed for {}", kind_str), + ); + Err(ErrorReported) } fn ensure_drop_params_and_item_params_correspond<'tcx>( @@ -94,11 +172,13 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>( Err(_) => { let item_span = tcx.def_span(self_type_did); let self_descr = tcx.def_kind(self_type_did).descr(self_type_did); + let trait_ref = tcx.impl_trait_ref(drop_impl_did).unwrap(); struct_span_err!( tcx.sess, drop_impl_span, E0366, - "`Drop` impls cannot be specialized" + "`{}` impls cannot be specialized", + trait_ref.print_only_trait_path() ) .span_note( item_span, @@ -142,8 +222,9 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>( /// implied by assuming the predicates attached to self_type_did. fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( tcx: TyCtxt<'tcx>, + drop_impl_did: LocalDefId, dtor_predicates: ty::GenericPredicates<'tcx>, - self_type_did: LocalDefId, + self_type_did: DefId, self_to_impl_substs: SubstsRef<'tcx>, ) -> Result<(), ErrorReported> { let mut result = Ok(()); @@ -183,8 +264,6 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( // absent. So we report an error that the Drop impl injected a // predicate that is not present on the struct definition. - let self_type_hir_id = tcx.hir().as_local_hir_id(self_type_did); - // We can assume the predicates attached to struct/enum definition // hold. let generic_assumptions = tcx.predicates_of(self_type_did); @@ -238,13 +317,15 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( }; if !assumptions_in_impl_context.iter().copied().any(predicate_matches_closure) { - let item_span = tcx.hir().span(self_type_hir_id); - let self_descr = tcx.def_kind(self_type_did).descr(self_type_did.to_def_id()); + let item_span = tcx.def_span(self_type_did); + let self_descr = tcx.def_kind(self_type_did).descr(self_type_did); + let trait_ref = tcx.impl_trait_ref(drop_impl_did).unwrap(); struct_span_err!( tcx.sess, predicate_sp, E0367, - "`Drop` impl requires `{}` but the {} it is implemented for does not", + "`{}` impl requires `{}` but the {} it is implemented for does not", + trait_ref.print_only_trait_path(), predicate, self_descr, ) diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index dabae6cbc4137..20ffdf7ebe457 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -1,9 +1,9 @@ -use crate::check::{FnCtxt, Inherited}; +use crate::check::{dropck::check_restricted_impl, FnCtxt, Inherited}; use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter}; use rustc_ast::ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; +use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::itemlikevisit::ParItemLikeVisitor; @@ -123,7 +123,10 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) { check_impl(tcx, item, self_ty, of_trait); } (ty::ImplPolarity::Negative, ast::ImplPolarity::Negative(span)) => { - // FIXME(#27579): what amount of WF checking do we need for neg impls? + if let Err(ErrorReported) = check_restricted_impl(tcx, def_id.to_def_id()) { + return; + } + if let hir::Defaultness::Default { .. } = defaultness { let mut spans = vec![span]; spans.extend(defaultness_span); diff --git a/src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types.rs b/src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types.rs index 6483b9213dc53..1ec5d20ad6f49 100644 --- a/src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types.rs +++ b/src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types.rs @@ -3,7 +3,7 @@ auto trait MyTrait {} -impl !MyTrait for *mut T {} +impl !MyTrait for *mut T {} struct MyS; diff --git a/src/test/ui/issues/issue-17959.rs b/src/test/ui/issues/issue-17959.rs index 01416a0d79e5f..0d4ede6d653ff 100644 --- a/src/test/ui/issues/issue-17959.rs +++ b/src/test/ui/issues/issue-17959.rs @@ -9,7 +9,7 @@ struct G { } impl Drop for G { -//~^ ERROR `Drop` impl requires `T: std::marker::Sized` +//~^ ERROR `std::ops::Drop` impl requires `T: std::marker::Sized` fn drop(&mut self) { if !self._ptr.is_null() { } diff --git a/src/test/ui/issues/issue-17959.stderr b/src/test/ui/issues/issue-17959.stderr index 29d32c1f3cec6..bd31dcadd3c4b 100644 --- a/src/test/ui/issues/issue-17959.stderr +++ b/src/test/ui/issues/issue-17959.stderr @@ -1,4 +1,4 @@ -error[E0367]: `Drop` impl requires `T: std::marker::Sized` but the struct it is implemented for does not +error[E0367]: `std::ops::Drop` impl requires `T: std::marker::Sized` but the struct it is implemented for does not --> $DIR/issue-17959.rs:11:6 | LL | impl Drop for G { diff --git a/src/test/ui/issues/issue-29516.rs b/src/test/ui/issues/issue-29516.rs index 035f904b15bb3..966bd21341b00 100644 --- a/src/test/ui/issues/issue-29516.rs +++ b/src/test/ui/issues/issue-29516.rs @@ -1,10 +1,9 @@ -// check-pass #![feature(optin_builtin_traits)] #![feature(negative_impls)] auto trait NotSame {} -impl !NotSame for (A, A) {} +impl !NotSame for (A, A) {} //~ ERROR negative impls are not allowed for tuples trait OneOfEach {} diff --git a/src/test/ui/issues/issue-29516.stderr b/src/test/ui/issues/issue-29516.stderr new file mode 100644 index 0000000000000..affa34b438e0c --- /dev/null +++ b/src/test/ui/issues/issue-29516.stderr @@ -0,0 +1,8 @@ +error: negative impls are not allowed for tuples + --> $DIR/issue-29516.rs:6:1 + | +LL | impl !NotSame for (A, A) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/issues/issue-38868.stderr b/src/test/ui/issues/issue-38868.stderr index 10d1e7c4e66dc..5443893721487 100644 --- a/src/test/ui/issues/issue-38868.stderr +++ b/src/test/ui/issues/issue-38868.stderr @@ -1,4 +1,4 @@ -error[E0366]: `Drop` impls cannot be specialized +error[E0366]: `std::ops::Drop` impls cannot be specialized --> $DIR/issue-38868.rs:5:1 | LL | / impl Drop for List { diff --git a/src/test/ui/issues/issue-41974.rs b/src/test/ui/issues/issue-41974.rs index 7875b432d7be4..7a082bb08176a 100644 --- a/src/test/ui/issues/issue-41974.rs +++ b/src/test/ui/issues/issue-41974.rs @@ -1,14 +1,13 @@ #[derive(Copy, Clone)] struct Flags; -trait A { -} +trait A {} -impl Drop for T where T: A { //~ ERROR E0119 - //~^ ERROR E0120 - //~| ERROR E0210 - fn drop(&mut self) { - } +impl Drop for T where T: A { + //~^ ERROR E0119 + //~| ERROR E0120 + //~| ERROR E0210 + fn drop(&mut self) {} } fn main() {} diff --git a/src/test/ui/issues/issue-41974.stderr b/src/test/ui/issues/issue-41974.stderr index d082e0a6b5dc4..accaaf1c2281f 100644 --- a/src/test/ui/issues/issue-41974.stderr +++ b/src/test/ui/issues/issue-41974.stderr @@ -1,7 +1,7 @@ error[E0119]: conflicting implementations of trait `std::ops::Drop` for type `std::boxed::Box<_>`: - --> $DIR/issue-41974.rs:7:1 + --> $DIR/issue-41974.rs:6:1 | -LL | impl Drop for T where T: A { +LL | impl Drop for T where T: A { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: conflicting implementation in crate `alloc`: @@ -10,15 +10,15 @@ LL | impl Drop for T where T: A { = note: downstream crates may implement trait `A` for type `std::boxed::Box<_>` error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions - --> $DIR/issue-41974.rs:7:18 + --> $DIR/issue-41974.rs:6:18 | -LL | impl Drop for T where T: A { +LL | impl Drop for T where T: A { | ^ must be a struct, enum, or union error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) - --> $DIR/issue-41974.rs:7:6 + --> $DIR/issue-41974.rs:6:6 | -LL | impl Drop for T where T: A { +LL | impl Drop for T where T: A { | ^ type parameter `T` must be used as the type parameter for some local type | = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local diff --git a/src/test/ui/reject-specialized-drops-8142.rs b/src/test/ui/reject-specialized-drops-8142.rs index c4671736d79ec..a751f4bff9a5d 100644 --- a/src/test/ui/reject-specialized-drops-8142.rs +++ b/src/test/ui/reject-specialized-drops-8142.rs @@ -21,11 +21,11 @@ struct TupleStruct(T); union Union { f: T } impl<'al,'adds_bnd:'al> Drop for K<'al,'adds_bnd> { // REJECT - //~^ ERROR `Drop` impl requires `'adds_bnd: 'al` + //~^ ERROR `std::ops::Drop` impl requires `'adds_bnd: 'al` fn drop(&mut self) { } } impl<'al,'adds_bnd> Drop for L<'al,'adds_bnd> where 'adds_bnd:'al { // REJECT - //~^ ERROR `Drop` impl requires `'adds_bnd: 'al` + //~^ ERROR `std::ops::Drop` impl requires `'adds_bnd: 'al` fn drop(&mut self) { } } impl<'ml> Drop for M<'ml> { fn drop(&mut self) { } } // ACCEPT @@ -38,13 +38,13 @@ impl Drop for N<'static> { fn drop(&mut self) { } } // RE impl Drop for O { fn drop(&mut self) { } } // ACCEPT impl Drop for P { fn drop(&mut self) { } } // REJECT -//~^ ERROR `Drop` impls cannot be specialized +//~^ ERROR `std::ops::Drop` impls cannot be specialized impl Drop for Q { fn drop(&mut self) { } } // REJECT -//~^ ERROR `Drop` impl requires `AddsBnd: Bound` +//~^ ERROR `std::ops::Drop` impl requires `AddsBnd: Bound` impl<'rbnd,AddsRBnd:'rbnd> Drop for R { fn drop(&mut self) { } } // REJECT -//~^ ERROR `Drop` impl requires `AddsRBnd: 'rbnd` +//~^ ERROR `std::ops::Drop` impl requires `AddsRBnd: 'rbnd` impl Drop for S { fn drop(&mut self) { } } // ACCEPT @@ -53,18 +53,18 @@ impl<'t,Bt:'t> Drop for T<'t,Bt> { fn drop(&mut self) { } } // ACCEPT impl Drop for U { fn drop(&mut self) { } } // ACCEPT impl Drop for V { fn drop(&mut self) { } } // REJECT -//~^ ERROR `Drop` impls cannot be specialized +//~^ ERROR `std::ops::Drop` impls cannot be specialized impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT //~^ ERROR cannot infer an appropriate lifetime for lifetime parameter `'lw` impl Drop for Enum { fn drop(&mut self) { } } // REJECT -//~^ ERROR `Drop` impl requires `AddsBnd: Bound` +//~^ ERROR `std::ops::Drop` impl requires `AddsBnd: Bound` impl Drop for TupleStruct { fn drop(&mut self) { } } // REJECT -//~^ ERROR `Drop` impl requires `AddsBnd: Bound` +//~^ ERROR `std::ops::Drop` impl requires `AddsBnd: Bound` impl Drop for Union { fn drop(&mut self) { } } // REJECT -//~^ ERROR `Drop` impl requires `AddsBnd: Bound` +//~^ ERROR `std::ops::Drop` impl requires `AddsBnd: Bound` pub fn main() { } diff --git a/src/test/ui/reject-specialized-drops-8142.stderr b/src/test/ui/reject-specialized-drops-8142.stderr index f819faa278995..7191a06b99e75 100644 --- a/src/test/ui/reject-specialized-drops-8142.stderr +++ b/src/test/ui/reject-specialized-drops-8142.stderr @@ -1,4 +1,4 @@ -error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the union it is implemented for does not +error[E0367]: `std::ops::Drop` impl requires `AddsBnd: Bound` but the union it is implemented for does not --> $DIR/reject-specialized-drops-8142.rs:67:21 | LL | impl Drop for Union { fn drop(&mut self) { } } // REJECT @@ -10,7 +10,7 @@ note: the implementor must specify the same requirement LL | union Union { f: T } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0367]: `Drop` impl requires `'adds_bnd: 'al` but the struct it is implemented for does not +error[E0367]: `std::ops::Drop` impl requires `'adds_bnd: 'al` but the struct it is implemented for does not --> $DIR/reject-specialized-drops-8142.rs:23:20 | LL | impl<'al,'adds_bnd:'al> Drop for K<'al,'adds_bnd> { // REJECT @@ -22,7 +22,7 @@ note: the implementor must specify the same requirement LL | struct K<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0367]: `Drop` impl requires `'adds_bnd: 'al` but the struct it is implemented for does not +error[E0367]: `std::ops::Drop` impl requires `'adds_bnd: 'al` but the struct it is implemented for does not --> $DIR/reject-specialized-drops-8142.rs:27:67 | LL | impl<'al,'adds_bnd> Drop for L<'al,'adds_bnd> where 'adds_bnd:'al { // REJECT @@ -49,7 +49,7 @@ LL | struct N<'n> { x: &'n i8 } | ^^ = note: ...does not necessarily outlive the static lifetime -error[E0366]: `Drop` impls cannot be specialized +error[E0366]: `std::ops::Drop` impls cannot be specialized --> $DIR/reject-specialized-drops-8142.rs:40:1 | LL | impl Drop for P { fn drop(&mut self) { } } // REJECT @@ -61,7 +61,7 @@ note: use the same sequence of generic type, lifetime and const parameters as th LL | struct P { x: *const Tp } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the struct it is implemented for does not +error[E0367]: `std::ops::Drop` impl requires `AddsBnd: Bound` but the struct it is implemented for does not --> $DIR/reject-specialized-drops-8142.rs:43:14 | LL | impl Drop for Q { fn drop(&mut self) { } } // REJECT @@ -73,7 +73,7 @@ note: the implementor must specify the same requirement LL | struct Q { x: *const Tq } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0367]: `Drop` impl requires `AddsRBnd: 'rbnd` but the struct it is implemented for does not +error[E0367]: `std::ops::Drop` impl requires `AddsRBnd: 'rbnd` but the struct it is implemented for does not --> $DIR/reject-specialized-drops-8142.rs:46:21 | LL | impl<'rbnd,AddsRBnd:'rbnd> Drop for R { fn drop(&mut self) { } } // REJECT @@ -85,7 +85,7 @@ note: the implementor must specify the same requirement LL | struct R { x: *const Tr } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0366]: `Drop` impls cannot be specialized +error[E0366]: `std::ops::Drop` impls cannot be specialized --> $DIR/reject-specialized-drops-8142.rs:55:1 | LL | impl Drop for V { fn drop(&mut self) { } } // REJECT @@ -121,7 +121,7 @@ LL | impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJ = note: expected `W<'l1, 'l2>` found `W<'_, '_>` -error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the enum it is implemented for does not +error[E0367]: `std::ops::Drop` impl requires `AddsBnd: Bound` but the enum it is implemented for does not --> $DIR/reject-specialized-drops-8142.rs:61:14 | LL | impl Drop for Enum { fn drop(&mut self) { } } // REJECT @@ -133,7 +133,7 @@ note: the implementor must specify the same requirement LL | enum Enum { Variant(T) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the struct it is implemented for does not +error[E0367]: `std::ops::Drop` impl requires `AddsBnd: Bound` but the struct it is implemented for does not --> $DIR/reject-specialized-drops-8142.rs:64:14 | LL | impl Drop for TupleStruct { fn drop(&mut self) { } } // REJECT diff --git a/src/test/ui/specialization/defaultimpl/validation.rs b/src/test/ui/specialization/defaultimpl/validation.rs index 8558a1efb82f3..3b65caa7b4878 100644 --- a/src/test/ui/specialization/defaultimpl/validation.rs +++ b/src/test/ui/specialization/defaultimpl/validation.rs @@ -7,10 +7,10 @@ struct Z; default impl S {} //~ ERROR inherent impls cannot be `default` 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 +default impl !Send for Z {} //~ ERROR `std::marker::Send` impl requires `Z: std::marker::Send` but + //~^ ERROR impls of auto traits cannot be default trait Tr {} -default impl !Tr for S {} //~ ERROR negative impls cannot be default impls +default impl !Tr for S {} //~ ERROR `Tr` impl requires `S: Tr` but fn main() {} diff --git a/src/test/ui/specialization/defaultimpl/validation.stderr b/src/test/ui/specialization/defaultimpl/validation.stderr index 2449849725f38..372660696a36e 100644 --- a/src/test/ui/specialization/defaultimpl/validation.stderr +++ b/src/test/ui/specialization/defaultimpl/validation.stderr @@ -33,18 +33,30 @@ LL | default impl !Send for Z {} | | | default because of this -error[E0750]: negative impls cannot be default impls +error[E0367]: `std::marker::Send` impl requires `Z: std::marker::Send` but the struct it is implemented for does not --> $DIR/validation.rs:10:1 | LL | default impl !Send for Z {} - | ^^^^^^^ ^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the implementor must specify the same requirement + --> $DIR/validation.rs:5:1 + | +LL | struct Z; + | ^^^^^^^^^ -error[E0750]: negative impls cannot be default impls +error[E0367]: `Tr` impl requires `S: Tr` but the struct it is implemented for does not --> $DIR/validation.rs:14:1 | LL | default impl !Tr for S {} - | ^^^^^^^ ^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the implementor must specify the same requirement + --> $DIR/validation.rs:4:1 + | +LL | struct S; + | ^^^^^^^^^ error: aborting due to 5 previous errors; 1 warning emitted -For more information about this error, try `rustc --explain E0750`. +For more information about this error, try `rustc --explain E0367`. diff --git a/src/test/ui/traits/negative-impls/issue-74629.rs b/src/test/ui/traits/negative-impls/issue-74629.rs new file mode 100644 index 0000000000000..979cfb714cc70 --- /dev/null +++ b/src/test/ui/traits/negative-impls/issue-74629.rs @@ -0,0 +1,30 @@ +#![feature(negative_impls)] +#![feature(optin_builtin_traits)] +struct Nil; +struct Cons(H); +struct Test; + +trait Fold {} + +impl Fold for Cons // 0 +where + T: Fold, +{} + +impl Fold for Cons // 1 +where + T: Fold, + private::Is: private::NotNil, +{} + +impl Fold for Test {} // 2 + +mod private { + use crate::Nil; + + pub struct Is(T); + pub auto trait NotNil {} + impl !NotNil for Is {} //~ ERROR `private::NotNil` impls cannot +} + +fn main() {} diff --git a/src/test/ui/traits/negative-impls/issue-74629.stderr b/src/test/ui/traits/negative-impls/issue-74629.stderr new file mode 100644 index 0000000000000..622e1e2efb49c --- /dev/null +++ b/src/test/ui/traits/negative-impls/issue-74629.stderr @@ -0,0 +1,15 @@ +error[E0366]: `private::NotNil` impls cannot be specialized + --> $DIR/issue-74629.rs:27:5 + | +LL | impl !NotNil for Is {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: use the same sequence of generic type, lifetime and const parameters as the struct definition + --> $DIR/issue-74629.rs:25:5 + | +LL | pub struct Is(T); + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0366`. diff --git a/src/test/ui/traits/negative-impls/negative-default-impls.rs b/src/test/ui/traits/negative-impls/negative-default-impls.rs index c68bca432fa86..7c389a49bc6b7 100644 --- a/src/test/ui/traits/negative-impls/negative-default-impls.rs +++ b/src/test/ui/traits/negative-impls/negative-default-impls.rs @@ -6,6 +6,7 @@ trait MyTrait { type Foo; } -default impl !MyTrait for u32 {} //~ ERROR negative impls cannot be default impls +default impl !MyTrait for u32 {} +//~^ ERROR negative impls on primitive types must not contain where bounds 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 index 50e74373b53bb..178c2bae31f69 100644 --- a/src/test/ui/traits/negative-impls/negative-default-impls.stderr +++ b/src/test/ui/traits/negative-impls/negative-default-impls.stderr @@ -7,12 +7,11 @@ LL | #![feature(specialization)] = note: `#[warn(incomplete_features)]` on by default = note: see issue #31844 for more information -error[E0750]: negative impls cannot be default impls +error: negative impls on primitive types must not contain where bounds --> $DIR/negative-default-impls.rs:9:1 | LL | default impl !MyTrait for u32 {} - | ^^^^^^^ ^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error; 1 warning emitted -For more information about this error, try `rustc --explain E0750`. diff --git a/src/test/ui/traits/negative-impls/negative-impl-sized.rs b/src/test/ui/traits/negative-impls/negative-impl-sized.rs new file mode 100644 index 0000000000000..caa2477ec26be --- /dev/null +++ b/src/test/ui/traits/negative-impls/negative-impl-sized.rs @@ -0,0 +1,10 @@ +#![feature(negative_impls)] + +// Test that negative impls for a trait requires `T: ?Sized`. + +trait MyTrait {} + +impl !MyTrait for T {} +//~^ ERROR negative impls on type parameters must not contain where bounds + +fn main() {} diff --git a/src/test/ui/traits/negative-impls/negative-impl-sized.stderr b/src/test/ui/traits/negative-impls/negative-impl-sized.stderr new file mode 100644 index 0000000000000..f412bbff116d2 --- /dev/null +++ b/src/test/ui/traits/negative-impls/negative-impl-sized.stderr @@ -0,0 +1,8 @@ +error: negative impls on type parameters must not contain where bounds + --> $DIR/negative-impl-sized.rs:7:1 + | +LL | impl !MyTrait for T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/traits/negative-impls/negative-specializes-negative.rs b/src/test/ui/traits/negative-impls/negative-specializes-negative.rs index 35297ab124ed0..a26b1496e1331 100644 --- a/src/test/ui/traits/negative-impls/negative-specializes-negative.rs +++ b/src/test/ui/traits/negative-impls/negative-specializes-negative.rs @@ -7,7 +7,7 @@ trait MyTrait {} -impl !MyTrait for T {} +impl !MyTrait for T {} impl !MyTrait for u32 {} fn main() {}