From 4920a3371f5c02e61d3a0f5722ff7034a99938ff Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 25 Mar 2020 08:46:58 +0100 Subject: [PATCH 01/22] better explain GLOBAL_KIND choice --- src/librustc_mir/const_eval/machine.rs | 2 +- src/librustc_mir/transform/const_prop.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/const_eval/machine.rs b/src/librustc_mir/const_eval/machine.rs index 8f4501cc3fb69..3f657089251e4 100644 --- a/src/librustc_mir/const_eval/machine.rs +++ b/src/librustc_mir/const_eval/machine.rs @@ -178,7 +178,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter { type MemoryMap = FxHashMap, Allocation)>; - const GLOBAL_KIND: Option = None; // no copying of globals allowed + const GLOBAL_KIND: Option = None; // no copying of globals from `tcx` to machine memory // We do not check for alignment to avoid having to carry an `Align` // in `ConstValue::ByRef`. diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index cbb79637076bc..232d33a35313e 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -172,7 +172,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { type MemoryMap = FxHashMap, Allocation)>; - const GLOBAL_KIND: Option = None; + const GLOBAL_KIND: Option = None; // no copying of globals from `tcx` to machine memory const CHECK_ALIGN: bool = false; From b5343d6baa6daeca974931f4148638393e80e216 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 25 Mar 2020 08:47:59 +0100 Subject: [PATCH 02/22] rename def_id -> static_def_id --- src/librustc_mir/const_eval/machine.rs | 6 +++--- src/librustc_mir/interpret/machine.rs | 2 +- src/librustc_mir/transform/const_prop.rs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/librustc_mir/const_eval/machine.rs b/src/librustc_mir/const_eval/machine.rs index 3f657089251e4..0970e09791999 100644 --- a/src/librustc_mir/const_eval/machine.rs +++ b/src/librustc_mir/const_eval/machine.rs @@ -350,15 +350,15 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter { memory_extra: &MemoryExtra, alloc_id: AllocId, allocation: &Allocation, - def_id: Option, + static_def_id: Option, is_write: bool, ) -> InterpResult<'tcx> { if is_write && allocation.mutability == Mutability::Not { Err(err_ub!(WriteToReadOnly(alloc_id)).into()) } else if is_write { Err(ConstEvalErrKind::ModifiedGlobal.into()) - } else if memory_extra.can_access_statics || def_id.is_none() { - // `def_id.is_none()` indicates this is not a static, but a const or so. + } else if memory_extra.can_access_statics || static_def_id.is_none() { + // `static_def_id.is_none()` indicates this is not a static, but a const or so. Ok(()) } else { Err(ConstEvalErrKind::ConstAccessesStatic.into()) diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index cc87c2916862b..74933bed8f89e 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -215,7 +215,7 @@ pub trait Machine<'mir, 'tcx>: Sized { _memory_extra: &Self::MemoryExtra, _alloc_id: AllocId, _allocation: &Allocation, - _def_id: Option, + _static_def_id: Option, _is_write: bool, ) -> InterpResult<'tcx> { Ok(()) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 232d33a35313e..3b2a41e5c0cfc 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -274,7 +274,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { _memory_extra: &(), _alloc_id: AllocId, allocation: &Allocation, - def_id: Option, + static_def_id: Option, is_write: bool, ) -> InterpResult<'tcx> { if is_write { @@ -285,7 +285,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { if allocation.mutability == Mutability::Mut { throw_machine_stop_str!("can't eval mutable globals in ConstProp"); } - if def_id.is_some() && allocation.relocations().len() > 0 { + if static_def_id.is_some() && allocation.relocations().len() > 0 { throw_machine_stop_str!("can't eval statics with pointers in ConstProp"); } From 4d77d010962dc91e225437cbd508e1b10a9192cf Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Wed, 25 Mar 2020 22:42:13 +0100 Subject: [PATCH 03/22] Fix for #62691: use the largest niche across all fields fixes #62691 --- src/librustc/ty/layout.rs | 25 +++++++++++-------------- src/test/ui/type-sizes.rs | 7 +++++++ 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index c54360e03933e..e63a9eac0e643 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -282,8 +282,6 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let mut align = if pack.is_some() { dl.i8_align } else { dl.aggregate_align }; - let mut sized = true; - let mut offsets = vec![Size::ZERO; fields.len()]; let mut inverse_memory_index: Vec = (0..fields.len() as u32).collect(); let mut optimize = !repr.inhibit_struct_field_reordering_opt(); @@ -320,6 +318,8 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // At the bottom of this function, we invert `inverse_memory_index` to // produce `memory_index` (see `invert_mapping`). + let mut sized = true; + let mut offsets = vec![Size::ZERO; fields.len()]; let mut offset = Size::ZERO; let mut largest_niche = None; let mut largest_niche_available = 0; @@ -907,18 +907,15 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let count = (niche_variants.end().as_u32() - niche_variants.start().as_u32() + 1) as u128; - // FIXME(#62691) use the largest niche across all fields, - // not just the first one. - for (field_index, &field) in variants[i].iter().enumerate() { - let niche = match &field.largest_niche { - Some(niche) => niche, - _ => continue, - }; - let (niche_start, niche_scalar) = match niche.reserve(self, count) { - Some(pair) => pair, - None => continue, - }; - + if let Some((field_index, niche, (niche_start, niche_scalar))) = variants[i] + .iter() + .enumerate() + .filter_map(|(i, &field)| { + let niche = field.largest_niche.as_ref()?; + Some((i, niche, niche.reserve(self, count)?)) + }) + .max_by_key(|(_, niche, _)| niche.available(dl)) + { let mut align = dl.aggregate_align; let st = variants .iter_enumerated() diff --git a/src/test/ui/type-sizes.rs b/src/test/ui/type-sizes.rs index 27433fd770b05..1d332cc3bf7ba 100644 --- a/src/test/ui/type-sizes.rs +++ b/src/test/ui/type-sizes.rs @@ -74,6 +74,11 @@ enum NicheFilledEnumWithAbsentVariant { C, } +enum Option2 { + Some(A, B), + None +} + pub fn main() { assert_eq!(size_of::(), 1 as usize); assert_eq!(size_of::(), 4 as usize); @@ -113,4 +118,6 @@ pub fn main() { assert_eq!(size_of::>>(), size_of::<(bool, &())>()); assert_eq!(size_of::>>(), size_of::<(bool, &())>()); + assert_eq!(size_of::>>(), size_of::<(bool, &())>()); + assert_eq!(size_of::>>(), size_of::<(bool, &())>()); } From 81006f644da0963aa24aa86d1df9a69a859efcef Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Wed, 25 Mar 2020 23:05:47 +0100 Subject: [PATCH 04/22] Optimize slightly by avoiding to call Niche::reserve when not needed --- src/librustc/ty/layout.rs | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index e63a9eac0e643..e8c0ec89cc443 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -907,14 +907,25 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let count = (niche_variants.end().as_u32() - niche_variants.start().as_u32() + 1) as u128; - if let Some((field_index, niche, (niche_start, niche_scalar))) = variants[i] - .iter() - .enumerate() - .filter_map(|(i, &field)| { - let niche = field.largest_niche.as_ref()?; - Some((i, niche, niche.reserve(self, count)?)) + let mut niche_size = 0; + if let Some((field_index, niche, niche_start, niche_scalar)) = + variants[i].iter().enumerate().fold(None, |acc, (j, &field)| { + let niche = match &field.largest_niche { + Some(niche) => niche, + _ => return acc, + }; + let ns = niche.available(dl); + if ns <= niche_size { + return acc; + } + match niche.reserve(self, count) { + Some(pair) => { + niche_size = ns; + Some((j, niche, pair.0, pair.1)) + } + None => acc, + } }) - .max_by_key(|(_, niche, _)| niche.available(dl)) { let mut align = dl.aggregate_align; let st = variants From bb3e513a2cfdc01a35c5226c24b15200d635135e Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Thu, 26 Mar 2020 00:10:14 +0100 Subject: [PATCH 05/22] Revert previous commit and make the optimisation in a nicer way --- src/librustc/ty/layout.rs | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index e8c0ec89cc443..91d39334acb78 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -907,25 +907,12 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let count = (niche_variants.end().as_u32() - niche_variants.start().as_u32() + 1) as u128; - let mut niche_size = 0; - if let Some((field_index, niche, niche_start, niche_scalar)) = - variants[i].iter().enumerate().fold(None, |acc, (j, &field)| { - let niche = match &field.largest_niche { - Some(niche) => niche, - _ => return acc, - }; - let ns = niche.available(dl); - if ns <= niche_size { - return acc; - } - match niche.reserve(self, count) { - Some(pair) => { - niche_size = ns; - Some((j, niche, pair.0, pair.1)) - } - None => acc, - } - }) + if let Some((field_index, niche, (niche_start, niche_scalar))) = variants[i] + .iter() + .enumerate() + .filter_map(|(i, &field)| Some((i, field.largest_niche.as_ref()?))) + .max_by_key(|(_, niche)| niche.available(dl)) + .and_then(|(i, niche)| Some((i, niche, niche.reserve(self, count)?))) { let mut align = dl.aggregate_align; let st = variants From 73c82030e893ab259081bf38b4259e05156c32d0 Mon Sep 17 00:00:00 2001 From: Rakshith Ravi Date: Thu, 26 Mar 2020 10:36:52 +0530 Subject: [PATCH 06/22] Throw error when encountering `...` instead of `..` while destructing a pattern Added tests and stderr output --- src/librustc_parse/parser/pat.rs | 21 ++++++++++++++ .../issue-70388-recover-dotdotdot-rest-pat.rs | 7 +++++ ...ue-70388-recover-dotdotdot-rest-pat.stderr | 29 +++++++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 src/test/ui/parser/issue-70388-recover-dotdotdot-rest-pat.rs create mode 100644 src/test/ui/parser/issue-70388-recover-dotdotdot-rest-pat.stderr diff --git a/src/librustc_parse/parser/pat.rs b/src/librustc_parse/parser/pat.rs index f7f7ac89a1864..983aa43916fa8 100644 --- a/src/librustc_parse/parser/pat.rs +++ b/src/librustc_parse/parser/pat.rs @@ -295,6 +295,8 @@ impl<'a> Parser<'a> { // A rest pattern `..`. self.bump(); // `..` PatKind::Rest + } else if self.check(&token::DotDotDot) && !self.is_pat_range_end_start(1) { + self.recover_dotdotdot_rest_pat(lo) } else if let Some(form) = self.parse_range_end() { self.parse_pat_range_to(form)? // `..=X`, `...X`, or `..X`. } else if self.eat_keyword(kw::Underscore) { @@ -362,6 +364,25 @@ impl<'a> Parser<'a> { Ok(pat) } + /// Recover from a typoed `...` pattern that was encountered + /// Ref: Issue #70388 + fn recover_dotdotdot_rest_pat(&mut self, lo: Span) -> PatKind { + // A typoed rest pattern `...`. + self.bump(); // `...` + + // The user probably mistook `...` for a rest pattern `..`. + self.struct_span_err(lo, "unexpected `...`") + .span_label(lo, "not a valid pattern") + .span_suggestion_short( + lo, + "for a rest pattern, use `..` instead of `...`", + "..".to_owned(), + Applicability::MachineApplicable, + ) + .emit(); + PatKind::Rest + } + /// Try to recover the more general form `intersect ::= $pat_lhs @ $pat_rhs`. /// /// Allowed binding patterns generated by `binding ::= ref? mut? $ident @ $pat_rhs` diff --git a/src/test/ui/parser/issue-70388-recover-dotdotdot-rest-pat.rs b/src/test/ui/parser/issue-70388-recover-dotdotdot-rest-pat.rs new file mode 100644 index 0000000000000..ca8abd78c47ac --- /dev/null +++ b/src/test/ui/parser/issue-70388-recover-dotdotdot-rest-pat.rs @@ -0,0 +1,7 @@ +struct Foo(i32); + +fn main() { + let Foo(...) = Foo(0); //~ ERROR unexpected `...` + let [_, ..., _] = [0, 1]; //~ ERROR unexpected `...` + let _recovery_witness: () = 0; //~ ERROR mismatched types +} diff --git a/src/test/ui/parser/issue-70388-recover-dotdotdot-rest-pat.stderr b/src/test/ui/parser/issue-70388-recover-dotdotdot-rest-pat.stderr new file mode 100644 index 0000000000000..4961e8fc0492d --- /dev/null +++ b/src/test/ui/parser/issue-70388-recover-dotdotdot-rest-pat.stderr @@ -0,0 +1,29 @@ +error: unexpected `...` + --> $DIR/issue-70388-recover-dotdotdot-rest-pat.rs:4:13 + | +LL | let Foo(...) = Foo(0); + | ^^^ + | | + | not a valid pattern + | help: for a rest pattern, use `..` instead of `...` + +error: unexpected `...` + --> $DIR/issue-70388-recover-dotdotdot-rest-pat.rs:5:13 + | +LL | let [_, ..., _] = [0, 1]; + | ^^^ + | | + | not a valid pattern + | help: for a rest pattern, use `..` instead of `...` + +error[E0308]: mismatched types + --> $DIR/issue-70388-recover-dotdotdot-rest-pat.rs:6:33 + | +LL | let _recovery_witness: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. From c21e25c2622c2a7294189ddc545a0cb9c621631a Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Thu, 26 Mar 2020 10:52:52 +0100 Subject: [PATCH 07/22] simplify match stmt --- src/librustc_ast_passes/ast_validation.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index c03c44fc634ce..d6d1153f2790f 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -289,11 +289,7 @@ impl<'a> AstValidator<'a> { match expr.kind { ExprKind::Lit(..) | ExprKind::Err => {} ExprKind::Path(..) if allow_paths => {} - ExprKind::Unary(UnOp::Neg, ref inner) - if match inner.kind { - ExprKind::Lit(_) => true, - _ => false, - } => {} + ExprKind::Unary(UnOp::Neg, ref inner) if matches!(inner.kind, ExprKind::Lit(_)) => {} _ => self.err_handler().span_err( expr.span, "arbitrary expressions aren't allowed \ From e8a05e201ee6cea12fe05e4271e91fd40c2fb235 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 8 Jan 2020 06:39:38 -0500 Subject: [PATCH 08/22] permit negative impls for non-auto traits --- src/libcore/clone.rs | 5 +++ src/libcore/ops/deref.rs | 4 ++ src/librustc_error_codes/error_codes.rs | 4 +- src/librustc_error_codes/error_codes/E0749.md | 4 ++ src/librustc_error_codes/error_codes/E0750.md | 4 ++ src/librustc_typeck/check/mod.rs | 44 ++++++++++++++----- src/librustc_typeck/check/wfcheck.rs | 30 ++++++------- src/test/ui/error-codes/E0192.rs | 12 ----- src/test/ui/error-codes/E0192.stderr | 11 ----- .../specialization/defaultimpl/validation.rs | 3 +- .../defaultimpl/validation.stderr | 18 +++++--- src/test/ui/syntax-trait-polarity.rs | 2 - src/test/ui/syntax-trait-polarity.stderr | 25 ++--------- .../negative-impls/auxiliary/foreign_trait.rs | 6 +++ .../negated-auto-traits-error.rs} | 0 .../negated-auto-traits-error.stderr} | 14 +++--- .../negated-auto-traits-rpass.rs} | 0 .../negative-impls/negative-default-impls.rs | 10 +++++ .../negative-default-impls.stderr | 9 ++++ .../negative-specializes-positive-item.rs | 13 ++++++ .../negative-specializes-positive-item.stderr | 12 +++++ .../negative-specializes-positive.rs | 14 ++++++ .../negative-specializes-positive.stderr | 11 +++++ src/test/ui/traits/negative-impls/no-items.rs | 11 +++++ .../ui/traits/negative-impls/no-items.stderr | 9 ++++ .../pin-unsound-issue-66544-clone.rs | 26 +++++++++++ .../pin-unsound-issue-66544-clone.stderr | 13 ++++++ .../pin-unsound-issue-66544-derefmut.rs | 33 ++++++++++++++ .../pin-unsound-issue-66544-derefmut.stderr | 13 ++++++ .../positive-specializes-negative.rs | 9 ++++ .../positive-specializes-negative.stderr | 11 +++++ .../rely-on-negative-impl-in-coherence.rs | 21 +++++++++ .../rely-on-negative-impl-in-coherence.stderr | 11 +++++ .../typeck-negative-impls-builtin.rs | 6 ++- .../typeck-negative-impls-builtin.stderr | 11 ----- 35 files changed, 328 insertions(+), 101 deletions(-) create mode 100644 src/librustc_error_codes/error_codes/E0749.md create mode 100644 src/librustc_error_codes/error_codes/E0750.md delete mode 100644 src/test/ui/error-codes/E0192.rs delete mode 100644 src/test/ui/error-codes/E0192.stderr create mode 100644 src/test/ui/traits/negative-impls/auxiliary/foreign_trait.rs rename src/test/ui/traits/{traits-negative-impls.rs => negative-impls/negated-auto-traits-error.rs} (100%) rename src/test/ui/traits/{traits-negative-impls.stderr => negative-impls/negated-auto-traits-error.stderr} (92%) rename src/test/ui/traits/{traits-negative-impls-rpass.rs => negative-impls/negated-auto-traits-rpass.rs} (100%) create mode 100644 src/test/ui/traits/negative-impls/negative-default-impls.rs create mode 100644 src/test/ui/traits/negative-impls/negative-default-impls.stderr create mode 100644 src/test/ui/traits/negative-impls/negative-specializes-positive-item.rs create mode 100644 src/test/ui/traits/negative-impls/negative-specializes-positive-item.stderr create mode 100644 src/test/ui/traits/negative-impls/negative-specializes-positive.rs create mode 100644 src/test/ui/traits/negative-impls/negative-specializes-positive.stderr create mode 100644 src/test/ui/traits/negative-impls/no-items.rs create mode 100644 src/test/ui/traits/negative-impls/no-items.stderr create mode 100644 src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs create mode 100644 src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr create mode 100644 src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs create mode 100644 src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr create mode 100644 src/test/ui/traits/negative-impls/positive-specializes-negative.rs create mode 100644 src/test/ui/traits/negative-impls/positive-specializes-negative.stderr create mode 100644 src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs create mode 100644 src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.stderr rename src/test/ui/{typeck => traits/negative-impls}/typeck-negative-impls-builtin.rs (67%) delete mode 100644 src/test/ui/typeck/typeck-negative-impls-builtin.stderr diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index 9a412e5729427..629c197e37691 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -227,4 +227,9 @@ mod impls { *self } } + + // Shared references can be cloned, but mutable references *cannot*! + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg(not(bootstrap))] + impl !Clone for &mut T {} } diff --git a/src/libcore/ops/deref.rs b/src/libcore/ops/deref.rs index 68244fdb38114..e2deeb556610c 100644 --- a/src/libcore/ops/deref.rs +++ b/src/libcore/ops/deref.rs @@ -81,6 +81,10 @@ impl Deref for &T { } } +#[cfg(not(bootstrap))] +#[stable(feature = "rust1", since = "1.0.0")] +impl !DerefMut for &T {} + #[stable(feature = "rust1", since = "1.0.0")] impl Deref for &mut T { type Target = T; diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs index 86da425060efa..bff20c2a62cef 100644 --- a/src/librustc_error_codes/error_codes.rs +++ b/src/librustc_error_codes/error_codes.rs @@ -97,7 +97,6 @@ E0184: include_str!("./error_codes/E0184.md"), 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"), @@ -426,6 +425,8 @@ E0745: include_str!("./error_codes/E0745.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 @@ -460,6 +461,7 @@ E0748: include_str!("./error_codes/E0748.md"), // 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 index 0000000000000..9eb8ee4e3fdf7 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0749.md @@ -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 index 0000000000000..e0cf56f716f9d --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0750.md @@ -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. diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index e7ba00ac24507..98ff5ccc82f69 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1659,11 +1659,14 @@ fn check_opaque_for_inheriting_lifetimes(tcx: TyCtxt<'tcx>, def_id: DefId, span: _ => 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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { 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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_label( fn_span, "implicitly returns `()` as its body has no tail or `return` \ - expression", + expression", ); } }, @@ -5577,11 +5598,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { 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 {}", diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 27be0faade82f..c89c4b028b4ea 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -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 index c52977e49b457..0000000000000 --- a/src/test/ui/error-codes/E0192.rs +++ /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 index da706dea167f6..0000000000000 --- a/src/test/ui/error-codes/E0192.stderr +++ /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`. diff --git a/src/test/ui/specialization/defaultimpl/validation.rs b/src/test/ui/specialization/defaultimpl/validation.rs index 5b8a72104e31a..ac8742c70c878 100644 --- a/src/test/ui/specialization/defaultimpl/validation.rs +++ b/src/test/ui/specialization/defaultimpl/validation.rs @@ -8,8 +8,9 @@ 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 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() {} diff --git a/src/test/ui/specialization/defaultimpl/validation.stderr b/src/test/ui/specialization/defaultimpl/validation.stderr index e03153f343b8e..9bf59bd4f636a 100644 --- a/src/test/ui/specialization/defaultimpl/validation.stderr +++ b/src/test/ui/specialization/defaultimpl/validation.stderr @@ -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`. diff --git a/src/test/ui/syntax-trait-polarity.rs b/src/test/ui/syntax-trait-polarity.rs index bfbe6394c1694..739a3c12dfb41 100644 --- a/src/test/ui/syntax-trait-polarity.rs +++ b/src/test/ui/syntax-trait-polarity.rs @@ -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); @@ -22,6 +21,5 @@ impl !TestType2 {} unsafe impl !Send for TestType2 {} //~^ ERROR negative impls cannot be unsafe impl !TestTrait for TestType2 {} -//~^ ERROR invalid negative impl fn main() {} diff --git a/src/test/ui/syntax-trait-polarity.stderr b/src/test/ui/syntax-trait-polarity.stderr index f70d67ec7dc98..1fd40fb66570d 100644 --- a/src/test/ui/syntax-trait-polarity.stderr +++ b/src/test/ui/syntax-trait-polarity.stderr @@ -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 !TestType2 {} | -^^^^^^^^^^^^ inherent impl for this type @@ -24,7 +24,7 @@ LL | impl !TestType2 {} | 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 !Send for TestType2 {} | ------ -^^^^ @@ -32,23 +32,6 @@ LL | unsafe impl !Send for TestType2 {} | | 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 !TestTrait for TestType2 {} - | ^^^^^^^^^^ - | - = 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 index 0000000000000..1790b24be3384 --- /dev/null +++ b/src/test/ui/traits/negative-impls/auxiliary/foreign_trait.rs @@ -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/traits-negative-impls.rs b/src/test/ui/traits/negative-impls/negated-auto-traits-error.rs similarity index 100% rename from src/test/ui/traits/traits-negative-impls.rs rename to src/test/ui/traits/negative-impls/negated-auto-traits-error.rs diff --git a/src/test/ui/traits/traits-negative-impls.stderr b/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr similarity index 92% rename from src/test/ui/traits/traits-negative-impls.stderr rename to src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr index 599bbfe222546..69a91b09e3ee0 100644 --- a/src/test/ui/traits/traits-negative-impls.stderr +++ b/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr @@ -1,5 +1,5 @@ error[E0277]: `dummy::TestType` cannot be sent between threads safely - --> $DIR/traits-negative-impls.rs:23:11 + --> $DIR/negated-auto-traits-error.rs:23:11 | LL | struct Outer(T); | ------------------------- required by `Outer` @@ -10,7 +10,7 @@ LL | Outer(TestType); = 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 + --> $DIR/negated-auto-traits-error.rs:23:5 | LL | struct Outer(T); | ------------------------- required by `Outer` @@ -21,7 +21,7 @@ LL | Outer(TestType); = 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 + --> $DIR/negated-auto-traits-error.rs:32:13 | LL | fn is_send(_: T) {} | ------- ---- required by this bound in `is_send` @@ -32,7 +32,7 @@ LL | is_send(TestType); = 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 + --> $DIR/negated-auto-traits-error.rs:40:13 | LL | fn is_send(_: T) {} | ------- ---- required by this bound in `is_send` @@ -44,7 +44,7 @@ LL | is_send((8, 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 + --> $DIR/negated-auto-traits-error.rs:48:13 | LL | fn is_send(_: T) {} | ------- ---- required by this bound in `is_send` @@ -60,7 +60,7 @@ LL | is_send(Box::new(TestType)); = note: required because it appears within the type `std::boxed::Box` error[E0277]: `dummy3::TestType` cannot be sent between threads safely - --> $DIR/traits-negative-impls.rs:56:13 + --> $DIR/negated-auto-traits-error.rs:56:13 | LL | fn is_send(_: T) {} | ------- ---- required by this bound in `is_send` @@ -74,7 +74,7 @@ LL | is_send(Box::new(Outer2(TestType))); = note: required because it appears within the type `std::boxed::Box>` error[E0277]: `main::TestType` cannot be sent between threads safely - --> $DIR/traits-negative-impls.rs:66:13 + --> $DIR/negated-auto-traits-error.rs:66:13 | LL | fn is_sync(_: T) {} | ------- ---- required by this bound in `is_sync` diff --git a/src/test/ui/traits/traits-negative-impls-rpass.rs b/src/test/ui/traits/negative-impls/negated-auto-traits-rpass.rs similarity index 100% rename from src/test/ui/traits/traits-negative-impls-rpass.rs rename to src/test/ui/traits/negative-impls/negated-auto-traits-rpass.rs 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 index 0000000000000..b23ac87f89986 --- /dev/null +++ b/src/test/ui/traits/negative-impls/negative-default-impls.rs @@ -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 index 0000000000000..d2423d01a9afa --- /dev/null +++ b/src/test/ui/traits/negative-impls/negative-default-impls.stderr @@ -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 index 0000000000000..2ebf0bdcbe9be --- /dev/null +++ b/src/test/ui/traits/negative-impls/negative-specializes-positive-item.rs @@ -0,0 +1,13 @@ +#![feature(specialization)] +#![feature(optin_builtin_traits)] + +// Negative impl for u32 cannot "specialize" the base impl. +trait MyTrait { + fn foo(); +} +impl 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 index 0000000000000..83421b4d7a14a --- /dev/null +++ b/src/test/ui/traits/negative-impls/negative-specializes-positive-item.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `MyTrait` for type `u32`: + --> $DIR/negative-specializes-positive-item.rs:11:1 + | +LL | impl 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 index 0000000000000..7ab0161229572 --- /dev/null +++ b/src/test/ui/traits/negative-impls/negative-specializes-positive.rs @@ -0,0 +1,14 @@ +#![feature(specialization)] +#![feature(optin_builtin_traits)] + +// Negative impl for u32 cannot "specialize" the base impl. +trait MyTrait { } +impl MyTrait for T { } +impl !MyTrait for u32 { } //~ ERROR conflicting implementations + +// The second impl specializes the first, no error. +trait MyTrait2 { } +impl 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 index 0000000000000..a542e88673efa --- /dev/null +++ b/src/test/ui/traits/negative-impls/negative-specializes-positive.stderr @@ -0,0 +1,11 @@ +error[E0119]: conflicting implementations of trait `MyTrait` for type `u32`: + --> $DIR/negative-specializes-positive.rs:7:1 + | +LL | impl 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 index 0000000000000..5bfbf9653ab11 --- /dev/null +++ b/src/test/ui/traits/negative-impls/no-items.rs @@ -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 index 0000000000000..67b94bba12143 --- /dev/null +++ b/src/test/ui/traits/negative-impls/no-items.stderr @@ -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 index 0000000000000..5c3e7fe3d010c --- /dev/null +++ b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs @@ -0,0 +1,26 @@ +use std::cell::Cell; +use std::marker::PhantomPinned; +use std::pin::Pin; + +struct MyType<'a>(Cell>>, 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 index 0000000000000..1655d806fb438 --- /dev/null +++ b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr @@ -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 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 index 0000000000000..a34b8d635ab0e --- /dev/null +++ b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs @@ -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>>, 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 index 0000000000000..80c9682a0102f --- /dev/null +++ b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr @@ -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 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 index 0000000000000..20267cf3aba7f --- /dev/null +++ b/src/test/ui/traits/negative-impls/positive-specializes-negative.rs @@ -0,0 +1,9 @@ +#![feature(specialization)] +#![feature(optin_builtin_traits)] + +trait MyTrait { } + +impl !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 index 0000000000000..6e41759d2a227 --- /dev/null +++ b/src/test/ui/traits/negative-impls/positive-specializes-negative.stderr @@ -0,0 +1,11 @@ +error[E0119]: conflicting implementations of trait `MyTrait` for type `u32`: + --> $DIR/positive-specializes-negative.rs:7:1 + | +LL | impl !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 index 0000000000000..b823c0f78649f --- /dev/null +++ b/src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs @@ -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 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 index 0000000000000..7cce45d2c8f8f --- /dev/null +++ b/src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.stderr @@ -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 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/typeck/typeck-negative-impls-builtin.rs b/src/test/ui/traits/negative-impls/typeck-negative-impls-builtin.rs similarity index 67% rename from src/test/ui/typeck/typeck-negative-impls-builtin.rs rename to src/test/ui/traits/negative-impls/typeck-negative-impls-builtin.rs index fef98977cc435..6a2e99f8147a7 100644 --- a/src/test/ui/typeck/typeck-negative-impls-builtin.rs +++ b/src/test/ui/traits/negative-impls/typeck-negative-impls-builtin.rs @@ -1,12 +1,14 @@ +// run-pass + #![feature(optin_builtin_traits)] +#![allow(dead_code)] struct TestType; trait TestTrait { - fn dummy(&self) { } + 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 index c90655086acda..0000000000000 --- a/src/test/ui/typeck/typeck-negative-impls-builtin.stderr +++ /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`. From 65071708f8fe72dd2103c6eace0eb6802a6acf03 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 8 Jan 2020 14:10:59 -0500 Subject: [PATCH 09/22] make a custom error for overlap with negative impls --- src/librustc_error_codes/error_codes.rs | 1 + src/librustc_error_codes/error_codes/E0751.md | 12 + .../traits/specialize/mod.rs | 245 ++++++++++++------ ...herence-conflicting-negative-trait-impl.rs | 8 +- ...nce-conflicting-negative-trait-impl.stderr | 21 +- .../ui/issues/issue-33140-hack-boundaries.rs | 28 +- .../issues/issue-33140-hack-boundaries.stderr | 25 +- .../specialization-overlap-negative.rs | 2 +- .../specialization-overlap-negative.stderr | 8 +- .../specialization/specialization-polarity.rs | 4 +- .../specialization-polarity.stderr | 14 +- .../negative-specializes-positive-item.rs | 6 +- .../negative-specializes-positive-item.stderr | 10 +- .../negative-specializes-positive.rs | 14 +- .../negative-specializes-positive.stderr | 12 +- .../pin-unsound-issue-66544-clone.rs | 4 +- .../pin-unsound-issue-66544-clone.stderr | 10 +- .../pin-unsound-issue-66544-derefmut.rs | 4 +- .../pin-unsound-issue-66544-derefmut.stderr | 10 +- .../positive-specializes-negative.rs | 8 +- .../positive-specializes-negative.stderr | 12 +- 21 files changed, 271 insertions(+), 187 deletions(-) create mode 100644 src/librustc_error_codes/error_codes/E0751.md diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs index bff20c2a62cef..fdcf3d639574b 100644 --- a/src/librustc_error_codes/error_codes.rs +++ b/src/librustc_error_codes/error_codes.rs @@ -427,6 +427,7 @@ 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"), +E0751: include_str!("./error_codes/E0751.md"), ; // E0006, // merged with E0005 // E0008, // cannot bind by-move into a pattern guard diff --git a/src/librustc_error_codes/error_codes/E0751.md b/src/librustc_error_codes/error_codes/E0751.md new file mode 100644 index 0000000000000..a440f82e4b6b3 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0751.md @@ -0,0 +1,12 @@ +There are both a positive and negative trait implementation for the same type. + +Erroneous code example: + +```compile_fail,E0748 +trait MyTrait {} +impl MyTrait for i32 { } +impl !MyTrait for i32 { } +``` + +Negative implementations are a promise that the trait will never be +implemented for the given types. diff --git a/src/librustc_trait_selection/traits/specialize/mod.rs b/src/librustc_trait_selection/traits/specialize/mod.rs index 0cc5032d74e8e..732716ef86577 100644 --- a/src/librustc_trait_selection/traits/specialize/mod.rs +++ b/src/librustc_trait_selection/traits/specialize/mod.rs @@ -324,86 +324,7 @@ pub(super) fn specialization_graph_provider( }; if let Some(overlap) = overlap { - let impl_span = - tcx.sess.source_map().guess_head_span(tcx.span_of_impl(impl_def_id).unwrap()); - - // Work to be done after we've built the DiagnosticBuilder. We have to define it - // now because the struct_lint methods don't return back the DiagnosticBuilder - // that's passed in. - let decorate = |err: LintDiagnosticBuilder<'_>| { - let msg = format!( - "conflicting implementations of trait `{}`{}:{}", - overlap.trait_desc, - overlap - .self_desc - .clone() - .map_or(String::new(), |ty| { format!(" for type `{}`", ty) }), - match used_to_be_allowed { - Some(FutureCompatOverlapErrorKind::Issue33140) => " (E0119)", - _ => "", - } - ); - let mut err = err.build(&msg); - match tcx.span_of_impl(overlap.with_impl) { - Ok(span) => { - err.span_label( - tcx.sess.source_map().guess_head_span(span), - "first implementation here".to_string(), - ); - - err.span_label( - impl_span, - format!( - "conflicting implementation{}", - overlap - .self_desc - .map_or(String::new(), |ty| format!(" for `{}`", ty)) - ), - ); - } - Err(cname) => { - let msg = match to_pretty_impl_header(tcx, overlap.with_impl) { - Some(s) => format!( - "conflicting implementation in crate `{}`:\n- {}", - cname, s - ), - None => format!("conflicting implementation in crate `{}`", cname), - }; - err.note(&msg); - } - } - - for cause in &overlap.intercrate_ambiguity_causes { - cause.add_intercrate_ambiguity_hint(&mut err); - } - - if overlap.involves_placeholder { - coherence::add_placeholder_note(&mut err); - } - err.emit() - }; - - match used_to_be_allowed { - None => { - sg.has_errored = true; - let err = struct_span_err!(tcx.sess, impl_span, E0119, ""); - decorate(LintDiagnosticBuilder::new(err)); - } - Some(kind) => { - let lint = match kind { - FutureCompatOverlapErrorKind::Issue33140 => { - ORDER_DEPENDENT_TRAIT_OBJECTS - } - FutureCompatOverlapErrorKind::LeakCheck => COHERENCE_LEAK_CHECK, - }; - tcx.struct_span_lint_hir( - lint, - tcx.hir().as_local_hir_id(impl_def_id).unwrap(), - impl_span, - decorate, - ) - } - }; + report_overlap_conflict(tcx, overlap, impl_def_id, used_to_be_allowed, &mut sg); } } else { let parent = tcx.impl_parent(impl_def_id).unwrap_or(trait_id); @@ -414,6 +335,170 @@ pub(super) fn specialization_graph_provider( tcx.arena.alloc(sg) } +fn report_overlap_conflict( + tcx: TyCtxt<'_>, + overlap: OverlapError, + impl_def_id: DefId, + used_to_be_allowed: Option, + sg: &mut specialization_graph::Graph, +) { + let impl_polarity = tcx.impl_polarity(impl_def_id); + let other_polarity = tcx.impl_polarity(overlap.with_impl); + match (impl_polarity, other_polarity) { + (ty::ImplPolarity::Negative, ty::ImplPolarity::Positive) => { + report_negative_positive_conflict( + tcx, + &overlap, + impl_def_id, + impl_def_id, + overlap.with_impl, + sg, + ); + } + + (ty::ImplPolarity::Positive, ty::ImplPolarity::Negative) => { + report_negative_positive_conflict( + tcx, + &overlap, + impl_def_id, + overlap.with_impl, + impl_def_id, + sg, + ); + } + + _ => { + report_conflicting_impls(tcx, overlap, impl_def_id, used_to_be_allowed, sg); + } + } +} + +fn report_negative_positive_conflict( + tcx: TyCtxt<'_>, + overlap: &OverlapError, + local_impl_def_id: DefId, + negative_impl_def_id: DefId, + positive_impl_def_id: DefId, + sg: &mut specialization_graph::Graph, +) { + let impl_span = + tcx.sess.source_map().guess_head_span(tcx.span_of_impl(local_impl_def_id).unwrap()); + + let mut err = struct_span_err!( + tcx.sess, + impl_span, + E0748, + "found both positive and negative implementation of trait `{}`{}:", + overlap.trait_desc, + overlap.self_desc.clone().map_or(String::new(), |ty| format!(" for type `{}`", ty)) + ); + + match tcx.span_of_impl(negative_impl_def_id) { + Ok(span) => { + err.span_label( + tcx.sess.source_map().guess_head_span(span), + "negative implementation here".to_string(), + ); + } + Err(cname) => { + err.note(&format!("negative implementation in crate `{}`", cname)); + } + } + + match tcx.span_of_impl(positive_impl_def_id) { + Ok(span) => { + err.span_label( + tcx.sess.source_map().guess_head_span(span), + "positive implementation here".to_string(), + ); + } + Err(cname) => { + err.note(&format!("positive implementation in crate `{}`", cname)); + } + } + + sg.has_errored = true; + err.emit(); +} + +fn report_conflicting_impls( + tcx: TyCtxt<'_>, + overlap: OverlapError, + impl_def_id: DefId, + used_to_be_allowed: Option, + sg: &mut specialization_graph::Graph, +) { + let impl_span = tcx.sess.source_map().guess_head_span(tcx.span_of_impl(impl_def_id).unwrap()); + + // Work to be done after we've built the DiagnosticBuilder. We have to define it + // now because the struct_lint methods don't return back the DiagnosticBuilder + // that's passed in. + let decorate = |err: LintDiagnosticBuilder<'_>| { + let msg = format!( + "conflicting implementations of trait `{}`{}:{}", + overlap.trait_desc, + overlap.self_desc.clone().map_or(String::new(), |ty| { format!(" for type `{}`", ty) }), + match used_to_be_allowed { + Some(FutureCompatOverlapErrorKind::Issue33140) => " (E0119)", + _ => "", + } + ); + let mut err = err.build(&msg); + match tcx.span_of_impl(overlap.with_impl) { + Ok(span) => { + err.span_label( + tcx.sess.source_map().guess_head_span(span), + "first implementation here".to_string(), + ); + + err.span_label( + impl_span, + format!( + "conflicting implementation{}", + overlap.self_desc.map_or(String::new(), |ty| format!(" for `{}`", ty)) + ), + ); + } + Err(cname) => { + let msg = match to_pretty_impl_header(tcx, overlap.with_impl) { + Some(s) => format!("conflicting implementation in crate `{}`:\n- {}", cname, s), + None => format!("conflicting implementation in crate `{}`", cname), + }; + err.note(&msg); + } + } + + for cause in &overlap.intercrate_ambiguity_causes { + cause.add_intercrate_ambiguity_hint(&mut err); + } + + if overlap.involves_placeholder { + coherence::add_placeholder_note(&mut err); + } + err.emit() + }; + + match used_to_be_allowed { + None => { + sg.has_errored = true; + let err = struct_span_err!(tcx.sess, impl_span, E0119, ""); + decorate(LintDiagnosticBuilder::new(err)); + } + Some(kind) => { + let lint = match kind { + FutureCompatOverlapErrorKind::Issue33140 => ORDER_DEPENDENT_TRAIT_OBJECTS, + FutureCompatOverlapErrorKind::LeakCheck => COHERENCE_LEAK_CHECK, + }; + tcx.struct_span_lint_hir( + lint, + tcx.hir().as_local_hir_id(impl_def_id).unwrap(), + impl_span, + decorate, + ) + } + }; +} + /// Recovers the "impl X for Y" signature from `impl_def_id` and returns it as a /// string. fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Option { diff --git a/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.rs b/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.rs index b4f5f9ef56bb1..0fabb5ec91d31 100644 --- a/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.rs +++ b/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.rs @@ -6,13 +6,11 @@ trait MyTrait {} struct TestType(::std::marker::PhantomData); -unsafe impl Send for TestType {} +unsafe impl Send for TestType {} -impl !Send for TestType {} -//~^ ERROR conflicting implementations +impl !Send for TestType {} //~ ERROR found both positive and negative implementation -unsafe impl Send for TestType {} -//~^ ERROR conflicting implementations +unsafe impl Send for TestType {} //~ ERROR conflicting implementations impl !Send for TestType {} diff --git a/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.stderr b/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.stderr index 25d3d3ee997a5..5081536b70245 100644 --- a/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.stderr +++ b/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.stderr @@ -1,21 +1,22 @@ -error[E0119]: conflicting implementations of trait `std::marker::Send` for type `TestType<_>`: +error[E0748]: found both positive and negative implementation of trait `std::marker::Send` for type `TestType<_>`: --> $DIR/coherence-conflicting-negative-trait-impl.rs:11:1 | -LL | unsafe impl Send for TestType {} - | ---------------------------------------------------- first implementation here +LL | unsafe impl Send for TestType {} + | ------------------------------------------------------ positive implementation here LL | LL | impl !Send for TestType {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `TestType<_>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ negative implementation here error[E0119]: conflicting implementations of trait `std::marker::Send` for type `TestType<_>`: - --> $DIR/coherence-conflicting-negative-trait-impl.rs:14:1 + --> $DIR/coherence-conflicting-negative-trait-impl.rs:13:1 | -LL | unsafe impl Send for TestType {} - | ---------------------------------------------------- first implementation here +LL | unsafe impl Send for TestType {} + | ------------------------------------------------------ first implementation here ... -LL | unsafe impl Send for TestType {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `TestType<_>` +LL | unsafe impl Send for TestType {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `TestType<_>` error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0119`. +Some errors have detailed explanations: E0119, E0748. +For more information about an error, try `rustc --explain E0119`. diff --git a/src/test/ui/issues/issue-33140-hack-boundaries.rs b/src/test/ui/issues/issue-33140-hack-boundaries.rs index fbdef51c13255..5aba886273f7b 100644 --- a/src/test/ui/issues/issue-33140-hack-boundaries.rs +++ b/src/test/ui/issues/issue-33140-hack-boundaries.rs @@ -4,8 +4,7 @@ // Check that the issue #33140 hack does not allow unintended things. // OK -trait Trait0 { -} +trait Trait0 {} impl Trait0 for dyn Send {} impl Trait0 for dyn Send {} @@ -20,58 +19,49 @@ impl Trait1 for dyn Send {} //~^ ERROR E0119 // Problem 2: negative impl -trait Trait2 { -} +trait Trait2 {} impl Trait2 for dyn Send {} impl !Trait2 for dyn Send {} -//~^ ERROR E0119 - +//~^ ERROR E0748 // Problem 3: type parameter -trait Trait3 { -} +trait Trait3 {} impl Trait3 for dyn Send {} impl Trait3 for dyn Send {} //~^ ERROR E0119 // Problem 4a: not a trait object - generic -trait Trait4a { -} +trait Trait4a {} impl Trait4a for T {} impl Trait4a for dyn Send {} //~^ ERROR E0119 // Problem 4b: not a trait object - misc -trait Trait4b { -} +trait Trait4b {} impl Trait4b for () {} impl Trait4b for () {} //~^ ERROR E0119 // Problem 4c: not a principal-less trait object -trait Trait4c { -} +trait Trait4c {} impl Trait4c for dyn Trait1 + Send {} impl Trait4c for dyn Trait1 + Send {} //~^ ERROR E0119 // Problem 4d: lifetimes -trait Trait4d { -} +trait Trait4d {} impl<'a> Trait4d for dyn Send + 'a {} impl<'a> Trait4d for dyn Send + 'a {} //~^ ERROR E0119 - // Problem 5: where-clauses -trait Trait5 { -} +trait Trait5 {} impl Trait5 for dyn Send {} impl Trait5 for dyn Send where u32: Copy {} diff --git a/src/test/ui/issues/issue-33140-hack-boundaries.stderr b/src/test/ui/issues/issue-33140-hack-boundaries.stderr index 95aaa55ba7c67..b3bf34a2a9031 100644 --- a/src/test/ui/issues/issue-33140-hack-boundaries.stderr +++ b/src/test/ui/issues/issue-33140-hack-boundaries.stderr @@ -1,21 +1,21 @@ error[E0119]: conflicting implementations of trait `Trait1` for type `(dyn std::marker::Send + 'static)`: - --> $DIR/issue-33140-hack-boundaries.rs:19:1 + --> $DIR/issue-33140-hack-boundaries.rs:18:1 | LL | impl Trait1 for dyn Send {} | ------------------------ first implementation here LL | impl Trait1 for dyn Send {} | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)` -error[E0119]: conflicting implementations of trait `Trait2` for type `(dyn std::marker::Send + 'static)`: - --> $DIR/issue-33140-hack-boundaries.rs:27:1 +error[E0748]: found both positive and negative implementation of trait `Trait2` for type `(dyn std::marker::Send + 'static)`: + --> $DIR/issue-33140-hack-boundaries.rs:25:1 | LL | impl Trait2 for dyn Send {} - | ------------------------ first implementation here + | ------------------------ positive implementation here LL | impl !Trait2 for dyn Send {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ negative implementation here error[E0119]: conflicting implementations of trait `Trait3<(dyn std::marker::Sync + 'static)>` for type `(dyn std::marker::Send + 'static)`: - --> $DIR/issue-33140-hack-boundaries.rs:36:1 + --> $DIR/issue-33140-hack-boundaries.rs:32:1 | LL | impl Trait3 for dyn Send {} | ---------------------------------- first implementation here @@ -23,7 +23,7 @@ LL | impl Trait3 for dyn Send {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)` error[E0119]: conflicting implementations of trait `Trait4a` for type `(dyn std::marker::Send + 'static)`: - --> $DIR/issue-33140-hack-boundaries.rs:44:1 + --> $DIR/issue-33140-hack-boundaries.rs:39:1 | LL | impl Trait4a for T {} | ----------------------------- first implementation here @@ -31,7 +31,7 @@ LL | impl Trait4a for dyn Send {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)` error[E0119]: conflicting implementations of trait `Trait4b` for type `()`: - --> $DIR/issue-33140-hack-boundaries.rs:52:1 + --> $DIR/issue-33140-hack-boundaries.rs:46:1 | LL | impl Trait4b for () {} | ------------------- first implementation here @@ -39,7 +39,7 @@ LL | impl Trait4b for () {} | ^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` error[E0119]: conflicting implementations of trait `Trait4c` for type `(dyn Trait1 + std::marker::Send + 'static)`: - --> $DIR/issue-33140-hack-boundaries.rs:60:1 + --> $DIR/issue-33140-hack-boundaries.rs:53:1 | LL | impl Trait4c for dyn Trait1 + Send {} | ---------------------------------- first implementation here @@ -47,7 +47,7 @@ LL | impl Trait4c for dyn Trait1 + Send {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Trait1 + std::marker::Send + 'static)` error[E0119]: conflicting implementations of trait `Trait4d` for type `dyn std::marker::Send`: - --> $DIR/issue-33140-hack-boundaries.rs:68:1 + --> $DIR/issue-33140-hack-boundaries.rs:60:1 | LL | impl<'a> Trait4d for dyn Send + 'a {} | ---------------------------------- first implementation here @@ -55,7 +55,7 @@ LL | impl<'a> Trait4d for dyn Send + 'a {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `dyn std::marker::Send` error[E0119]: conflicting implementations of trait `Trait5` for type `(dyn std::marker::Send + 'static)`: - --> $DIR/issue-33140-hack-boundaries.rs:77:1 + --> $DIR/issue-33140-hack-boundaries.rs:67:1 | LL | impl Trait5 for dyn Send {} | ------------------------ first implementation here @@ -64,4 +64,5 @@ LL | impl Trait5 for dyn Send where u32: Copy {} error: aborting due to 8 previous errors -For more information about this error, try `rustc --explain E0119`. +Some errors have detailed explanations: E0119, E0748. +For more information about an error, try `rustc --explain E0119`. diff --git a/src/test/ui/specialization/specialization-overlap-negative.rs b/src/test/ui/specialization/specialization-overlap-negative.rs index af80d6686e3a1..4f5f65dafaa2e 100644 --- a/src/test/ui/specialization/specialization-overlap-negative.rs +++ b/src/test/ui/specialization/specialization-overlap-negative.rs @@ -6,6 +6,6 @@ trait MyTrait {} struct TestType(::std::marker::PhantomData); unsafe impl Send for TestType {} -impl !Send for TestType {} //~ ERROR E0119 +impl !Send for TestType {} //~ ERROR E0748 fn main() {} diff --git a/src/test/ui/specialization/specialization-overlap-negative.stderr b/src/test/ui/specialization/specialization-overlap-negative.stderr index 947aad824ea88..cbc7271b199a6 100644 --- a/src/test/ui/specialization/specialization-overlap-negative.stderr +++ b/src/test/ui/specialization/specialization-overlap-negative.stderr @@ -1,11 +1,11 @@ -error[E0119]: conflicting implementations of trait `std::marker::Send` for type `TestType<_>`: +error[E0748]: found both positive and negative implementation of trait `std::marker::Send` for type `TestType<_>`: --> $DIR/specialization-overlap-negative.rs:9:1 | LL | unsafe impl Send for TestType {} - | ------------------------------------------ first implementation here + | ------------------------------------------ positive implementation here LL | impl !Send for TestType {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `TestType<_>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ negative implementation here error: aborting due to previous error -For more information about this error, try `rustc --explain E0119`. +For more information about this error, try `rustc --explain E0748`. diff --git a/src/test/ui/specialization/specialization-polarity.rs b/src/test/ui/specialization/specialization-polarity.rs index d574480674571..fd0671ad09e32 100644 --- a/src/test/ui/specialization/specialization-polarity.rs +++ b/src/test/ui/specialization/specialization-polarity.rs @@ -6,11 +6,11 @@ auto trait Foo {} impl Foo for T {} -impl !Foo for u8 {} //~ ERROR E0119 +impl !Foo for u8 {} //~ ERROR E0748 auto trait Bar {} impl !Bar for T {} -impl Bar for u8 {} //~ ERROR E0119 +impl Bar for u8 {} //~ ERROR E0748 fn main() {} diff --git a/src/test/ui/specialization/specialization-polarity.stderr b/src/test/ui/specialization/specialization-polarity.stderr index bc1b2aeb70fc7..c6e7f193d0132 100644 --- a/src/test/ui/specialization/specialization-polarity.stderr +++ b/src/test/ui/specialization/specialization-polarity.stderr @@ -1,19 +1,19 @@ -error[E0119]: conflicting implementations of trait `Foo` for type `u8`: +error[E0748]: found both positive and negative implementation of trait `Foo` for type `u8`: --> $DIR/specialization-polarity.rs:9:1 | LL | impl Foo for T {} - | ----------------- first implementation here + | ----------------- positive implementation here LL | impl !Foo for u8 {} - | ^^^^^^^^^^^^^^^^ conflicting implementation for `u8` + | ^^^^^^^^^^^^^^^^ negative implementation here -error[E0119]: conflicting implementations of trait `Bar` for type `u8`: +error[E0748]: found both positive and negative implementation of trait `Bar` for type `u8`: --> $DIR/specialization-polarity.rs:14:1 | LL | impl !Bar for T {} - | ------------------ first implementation here + | ------------------ negative implementation here LL | impl Bar for u8 {} - | ^^^^^^^^^^^^^^^ conflicting implementation for `u8` + | ^^^^^^^^^^^^^^^ positive implementation here error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0119`. +For more information about this error, try `rustc --explain E0748`. 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 index 2ebf0bdcbe9be..c7009430eae99 100644 --- a/src/test/ui/traits/negative-impls/negative-specializes-positive-item.rs +++ b/src/test/ui/traits/negative-impls/negative-specializes-positive-item.rs @@ -6,8 +6,8 @@ trait MyTrait { fn foo(); } impl MyTrait for T { - default fn foo() { } + default fn foo() {} } -impl !MyTrait for u32 { } //~ ERROR conflicting implementations +impl !MyTrait for u32 {} //~ ERROR E0748 -fn main() { } +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 index 83421b4d7a14a..21fd08251d474 100644 --- a/src/test/ui/traits/negative-impls/negative-specializes-positive-item.stderr +++ b/src/test/ui/traits/negative-impls/negative-specializes-positive-item.stderr @@ -1,12 +1,12 @@ -error[E0119]: conflicting implementations of trait `MyTrait` for type `u32`: +error[E0748]: found both positive and negative implementation of trait `MyTrait` for type `u32`: --> $DIR/negative-specializes-positive-item.rs:11:1 | LL | impl MyTrait for T { - | --------------------- first implementation here + | --------------------- positive implementation here ... -LL | impl !MyTrait for u32 { } - | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32` +LL | impl !MyTrait for u32 {} + | ^^^^^^^^^^^^^^^^^^^^^ negative implementation here error: aborting due to previous error -For more information about this error, try `rustc --explain E0119`. +For more information about this error, try `rustc --explain E0748`. diff --git a/src/test/ui/traits/negative-impls/negative-specializes-positive.rs b/src/test/ui/traits/negative-impls/negative-specializes-positive.rs index 7ab0161229572..25301c696e13f 100644 --- a/src/test/ui/traits/negative-impls/negative-specializes-positive.rs +++ b/src/test/ui/traits/negative-impls/negative-specializes-positive.rs @@ -2,13 +2,13 @@ #![feature(optin_builtin_traits)] // Negative impl for u32 cannot "specialize" the base impl. -trait MyTrait { } -impl MyTrait for T { } -impl !MyTrait for u32 { } //~ ERROR conflicting implementations +trait MyTrait {} +impl MyTrait for T {} +impl !MyTrait for u32 {} //~ ERROR E0748 // The second impl specializes the first, no error. -trait MyTrait2 { } -impl MyTrait2 for T { } -impl MyTrait2 for u32 { } +trait MyTrait2 {} +impl MyTrait2 for T {} +impl MyTrait2 for u32 {} -fn main() { } +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 index a542e88673efa..0e7426c826028 100644 --- a/src/test/ui/traits/negative-impls/negative-specializes-positive.stderr +++ b/src/test/ui/traits/negative-impls/negative-specializes-positive.stderr @@ -1,11 +1,11 @@ -error[E0119]: conflicting implementations of trait `MyTrait` for type `u32`: +error[E0748]: found both positive and negative implementation of trait `MyTrait` for type `u32`: --> $DIR/negative-specializes-positive.rs:7:1 | -LL | impl MyTrait for T { } - | --------------------- first implementation here -LL | impl !MyTrait for u32 { } - | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32` +LL | impl MyTrait for T {} + | --------------------- positive implementation here +LL | impl !MyTrait for u32 {} + | ^^^^^^^^^^^^^^^^^^^^^ negative implementation here error: aborting due to previous error -For more information about this error, try `rustc --explain E0119`. +For more information about this error, try `rustc --explain E0748`. 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 index 5c3e7fe3d010c..d9c498fca6645 100644 --- 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 @@ -4,13 +4,13 @@ use std::pin::Pin; struct MyType<'a>(Cell>>, PhantomPinned); -impl<'a> Clone for &'a mut MyType<'a> { //~ ERROR conflicting implementations +impl<'a> Clone for &'a mut MyType<'a> { + //~^ ERROR E0748 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; 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 index 1655d806fb438..f3305722cf2d3 100644 --- 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 @@ -1,13 +1,11 @@ -error[E0119]: conflicting implementations of trait `std::clone::Clone` for type `&mut MyType<'_>`: +error[E0748]: found both positive and negative implementation 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> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ positive implementation here | - = note: conflicting implementation in crate `core`: - - impl std::clone::Clone for &mut T - where T: ?Sized; + = note: negative implementation in crate `core` error: aborting due to previous error -For more information about this error, try `rustc --explain E0119`. +For more information about this error, try `rustc --explain E0748`. 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 index a34b8d635ab0e..cc27c301ffa9d 100644 --- 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 @@ -9,13 +9,13 @@ use std::pin::Pin; struct MyType<'a>(Cell>>, PhantomPinned); -impl<'a> DerefMut for &'a MyType<'a> { //~ ERROR conflicting implementations +impl<'a> DerefMut for &'a MyType<'a> { + //~^ ERROR E0748 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; 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 index 80c9682a0102f..4e71c2468246b 100644 --- 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 @@ -1,13 +1,11 @@ -error[E0119]: conflicting implementations of trait `std::ops::DerefMut` for type `&MyType<'_>`: +error[E0748]: found both positive and negative implementation 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> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ positive implementation here | - = note: conflicting implementation in crate `core`: - - impl std::ops::DerefMut for &T - where T: ?Sized; + = note: negative implementation in crate `core` error: aborting due to previous error -For more information about this error, try `rustc --explain E0119`. +For more information about this error, try `rustc --explain E0748`. diff --git a/src/test/ui/traits/negative-impls/positive-specializes-negative.rs b/src/test/ui/traits/negative-impls/positive-specializes-negative.rs index 20267cf3aba7f..8a8ee70370fea 100644 --- a/src/test/ui/traits/negative-impls/positive-specializes-negative.rs +++ b/src/test/ui/traits/negative-impls/positive-specializes-negative.rs @@ -1,9 +1,9 @@ #![feature(specialization)] #![feature(optin_builtin_traits)] -trait MyTrait { } +trait MyTrait {} -impl !MyTrait for T { } -impl MyTrait for u32 { } //~ ERROR conflicting implementations +impl !MyTrait for T {} +impl MyTrait for u32 {} //~ ERROR E0748 -fn main() { } +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 index 6e41759d2a227..ab371945a7eab 100644 --- a/src/test/ui/traits/negative-impls/positive-specializes-negative.stderr +++ b/src/test/ui/traits/negative-impls/positive-specializes-negative.stderr @@ -1,11 +1,11 @@ -error[E0119]: conflicting implementations of trait `MyTrait` for type `u32`: +error[E0748]: found both positive and negative implementation of trait `MyTrait` for type `u32`: --> $DIR/positive-specializes-negative.rs:7:1 | -LL | impl !MyTrait for T { } - | ---------------------- first implementation here -LL | impl MyTrait for u32 { } - | ^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32` +LL | impl !MyTrait for T {} + | ---------------------- negative implementation here +LL | impl MyTrait for u32 {} + | ^^^^^^^^^^^^^^^^^^^^ positive implementation here error: aborting due to previous error -For more information about this error, try `rustc --explain E0119`. +For more information about this error, try `rustc --explain E0748`. From fda3378e3fcf279a19409ef368ce9bd5b57bfd62 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 9 Jan 2020 05:56:38 -0500 Subject: [PATCH 10/22] introduce `negative_impls` feature gate and document They used to be covered by `optin_builtin_traits` but negative impls are now applicable to all traits, not just auto traits. This also adds docs in the unstable book for the current state of auto traits. --- .../src/language-features/negative-impls.md | 57 +++++++++++++++++ .../language-features/optin-builtin-traits.md | 64 ++++++++++++++++++- src/liballoc/lib.rs | 1 + src/libcore/lib.rs | 1 + src/libproc_macro/lib.rs | 1 + src/librustc_ast_passes/feature_gate.rs | 10 +-- src/librustc_errors/lib.rs | 4 +- src/librustc_feature/active.rs | 3 + src/librustc_span/lib.rs | 43 +++++++++++-- src/librustc_span/symbol.rs | 1 + src/libstd/lib.rs | 1 + src/test/pretty/trait-polarity.rs | 2 +- src/test/rustdoc/empty-section.rs | 2 +- src/test/rustdoc/impl-parts-crosscrate.rs | 2 +- src/test/rustdoc/impl-parts.rs | 1 + src/test/rustdoc/issue-55321.rs | 2 +- src/test/rustdoc/negative-impl-sidebar.rs | 2 +- src/test/rustdoc/negative-impl.rs | 2 +- src/test/ui/async-await/issue-64130-1-sync.rs | 2 +- src/test/ui/async-await/issue-64130-2-send.rs | 2 +- .../ui/async-await/issue-64130-3-other.rs | 1 + .../ui/async-await/issue-64130-3-other.stderr | 4 +- src/test/ui/codemap_tests/empty_span.rs | 2 +- ...herence-conflicting-negative-trait-impl.rs | 2 +- .../coherence/coherence-default-trait-impl.rs | 1 + .../coherence-default-trait-impl.stderr | 4 +- ...ce-impl-trait-for-marker-trait-negative.rs | 1 + ...mpl-trait-for-marker-trait-negative.stderr | 10 +-- ...ce-impl-trait-for-marker-trait-positive.rs | 1 + ...mpl-trait-for-marker-trait-positive.stderr | 10 +-- src/test/ui/coherence/coherence-impls-copy.rs | 2 +- src/test/ui/coherence/coherence-impls-send.rs | 7 +- .../ui/coherence/coherence-impls-sized.rs | 2 +- .../coherence-negative-impls-safe-rpass.rs | 2 +- .../coherence-negative-impls-safe.rs | 2 +- src/test/ui/coherence/coherence-orphan.rs | 2 +- src/test/ui/error-codes/E0198.rs | 2 +- src/test/ui/error-codes/E0199.rs | 2 +- src/test/ui/feature-gate-negative_impls.rs | 3 + .../ui/feature-gate-negative_impls.stderr | 12 ++++ .../feature-gate-optin-builtin-traits.stderr | 2 +- .../generator/auto-trait-regions.nll.stderr | 8 +-- src/test/ui/generator/auto-trait-regions.rs | 1 + .../ui/generator/auto-trait-regions.stderr | 8 +-- src/test/ui/issues/issue-17718-static-sync.rs | 2 +- src/test/ui/issues/issue-23080-2.rs | 1 + src/test/ui/issues/issue-23080-2.stderr | 2 +- src/test/ui/issues/issue-23080.rs | 1 + src/test/ui/issues/issue-23080.stderr | 2 +- src/test/ui/issues/issue-29516.rs | 1 + .../ui/issues/issue-33140-hack-boundaries.rs | 2 +- src/test/ui/mut/mutable-enum-indirect.rs | 2 +- src/test/ui/never_type/auto-traits.rs | 1 + src/test/ui/no_send-enum.rs | 2 +- src/test/ui/no_send-struct.rs | 2 +- src/test/ui/no_share-enum.rs | 2 +- src/test/ui/no_share-struct.rs | 2 +- src/test/ui/parser/trait-object-bad-parens.rs | 1 + .../ui/parser/trait-object-bad-parens.stderr | 8 +-- src/test/ui/privacy/privacy-sanity.rs | 2 +- .../private-in-public-non-principal-2.rs | 1 + .../private-in-public-non-principal-2.stderr | 2 +- .../private-in-public-non-principal.rs | 1 + .../private-in-public-non-principal.stderr | 4 +- .../specialization/defaultimpl/validation.rs | 2 +- .../specialization-overlap-negative.rs | 2 +- .../specialization/specialization-polarity.rs | 1 + .../specialization-polarity.stderr | 4 +- .../syntax-trait-polarity-feature-gate.stderr | 2 +- src/test/ui/syntax-trait-polarity.rs | 2 +- src/test/ui/traits/auto-traits.rs | 1 + .../negative-impls/auxiliary/foreign_trait.rs | 6 +- .../negated-auto-traits-error.rs | 2 +- .../negated-auto-traits-rpass.rs | 2 +- .../negative-impls/negative-default-impls.rs | 2 +- .../negative-specializes-positive-item.rs | 2 +- .../negative-specializes-positive.rs | 2 +- src/test/ui/traits/negative-impls/no-items.rs | 2 +- .../positive-specializes-negative.rs | 2 +- .../rely-on-negative-impl-in-coherence.rs | 2 +- .../typeck-negative-impls-builtin.rs | 2 +- ...overlap-not-permitted-for-builtin-trait.rs | 5 +- .../overlap-permitted-for-marker-traits.rs | 28 ++++++++ src/test/ui/traits/syntax-trait-polarity.rs | 2 +- ...its-inductive-overflow-supertrait-oibit.rs | 1 + ...inductive-overflow-supertrait-oibit.stderr | 4 +- .../typeck-auto-trait-no-supertraits-2.rs | 1 + .../typeck-auto-trait-no-supertraits-2.stderr | 2 +- .../typeck-auto-trait-no-supertraits.rs | 1 + .../typeck-auto-trait-no-supertraits.stderr | 2 +- ...-default-trait-impl-constituent-types-2.rs | 1 + ...ault-trait-impl-constituent-types-2.stderr | 2 +- ...ck-default-trait-impl-constituent-types.rs | 1 + ...efault-trait-impl-constituent-types.stderr | 2 +- ...efault-trait-impl-cross-crate-coherence.rs | 2 +- ...typeck-default-trait-impl-negation-send.rs | 2 +- ...typeck-default-trait-impl-negation-sync.rs | 2 +- .../typeck-default-trait-impl-negation.rs | 1 + .../typeck-default-trait-impl-negation.stderr | 4 +- .../typeck-default-trait-impl-precedence.rs | 1 + ...ypeck-default-trait-impl-precedence.stderr | 2 +- .../ui/typeck/typeck-unsafe-always-share.rs | 2 +- 102 files changed, 330 insertions(+), 111 deletions(-) create mode 100644 src/doc/unstable-book/src/language-features/negative-impls.md create mode 100644 src/test/ui/feature-gate-negative_impls.rs create mode 100644 src/test/ui/feature-gate-negative_impls.stderr create mode 100644 src/test/ui/traits/overlap-permitted-for-marker-traits.rs diff --git a/src/doc/unstable-book/src/language-features/negative-impls.md b/src/doc/unstable-book/src/language-features/negative-impls.md new file mode 100644 index 0000000000000..3cf9351b6304b --- /dev/null +++ b/src/doc/unstable-book/src/language-features/negative-impls.md @@ -0,0 +1,57 @@ +# `negative_impls` + +The tracking issue for this feature is [#13231] + +[#13231]: https://github.com/rust-lang/rust/issues/13231 + +---- + +With the feature gate `negative_impls`, you can write negative impls as well as positive ones: + +```rust +#![feature(negative_impls)] +trait DerefMut { } +impl !DerefMut for &T { } +``` + +Negative impls indicate a semver guarantee that the given trait will not be implemented for the given types. Negative impls play an additional purpose for auto traits, described below. + +Negative impls have the following characteristics: + +* They do not have any items. +* They must obey the orphan rules as if they were a positive impl. +* They cannot "overlap" with any positive impls. + +## Semver interaction + +It is a breaking change to remove a negative impl. Negative impls are a commitment not to implement the given trait for the named types. + +## Orphan and overlap rules + +Negative impls must obey the same orphan rules as a positive impl. This implies you cannot add a negative impl for types defined in upstream crates and so forth. + +Similarly, negative impls cannot overlap with positive impls, again using the same "overlap" check that we ordinarily use to determine if two impls overlap. (Note that positive impls typically cannot overlap with one another either, except as permitted by specialization.) + +## Interaction with auto traits + +Declaring a negative impl `impl !SomeAutoTrait for SomeType` for an +auto-trait serves two purposes: + +* as with any trait, it declares that `SomeType` will never implement `SomeAutoTrait`; +* it disables the automatic `SomeType: SomeAutoTrait` impl that would otherwise have been generated. + +Note that, at present, there is no way to indicate that a given type +does not implement an auto trait *but that it may do so in the +future*. For ordinary types, this is done by simply not declaring any +impl at all, but that is not an option for auto traits. A workaround +is that one could embed a marker type as one of the fields, where the +marker type is `!AutoTrait`. + +## Immediate uses + +Negative impls are used to declare that `&T: !DerefMut` and `&mut T: !Clone`, as required to fix the soundness of `Pin` described in [#66544](https://github.com/rust-lang/rust/issues/66544). + +This serves two purposes: + +* For proving the correctness of unsafe code, we can use that impl as evidence that no `DerefMut` or `Clone` impl exists. +* It prevents downstream crates from creating such impls. diff --git a/src/doc/unstable-book/src/language-features/optin-builtin-traits.md b/src/doc/unstable-book/src/language-features/optin-builtin-traits.md index 1ec8b8bf8ddbd..6f0f0cfd33e4d 100644 --- a/src/doc/unstable-book/src/language-features/optin-builtin-traits.md +++ b/src/doc/unstable-book/src/language-features/optin-builtin-traits.md @@ -10,7 +10,8 @@ The `optin_builtin_traits` feature gate allows you to define auto traits. Auto traits, like [`Send`] or [`Sync`] in the standard library, are marker traits that are automatically implemented for every type, unless the type, or a type it contains, -has explicitly opted out via a negative impl. +has explicitly opted out via a negative impl. (Negative impls are separately controlled +by the `negative_impls` feature.) [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html @@ -22,6 +23,7 @@ impl !Trait for Type Example: ```rust +#![feature(negative_impls)] #![feature(optin_builtin_traits)] auto trait Valid {} @@ -43,3 +45,63 @@ fn main() { // must_be_valid( MaybeValid(False) ); } ``` + +## Automatic trait implementations + +When a type is declared as an `auto trait`, we will automatically +create impls for every struct/enum/union, unless an explicit impl is +provided. These automatic impls contain a where clause for each field +of the form `T: AutoTrait`, where `T` is the type of the field and +`AutoTrait` is the auto trait in question. As an example, consider the +struct `List` and the auto trait `Send`: + +```rust +struct List { + data: T, + next: Option>>, +} +``` + +Presuming that there is no explicit impl of `Send` for `List`, the +compiler will supply an automatic impl of the form: + +```rust +struct List { + data: T, + next: Option>>, +} + +unsafe impl Send for List +where + T: Send, // from the field `data` + Option>>: Send, // from the field `next` +{ } +``` + +Explicit impls may be either positive or negative. They take the form: + +```rust,ignore +impl<...> AutoTrait for StructName<..> { } +impl<...> !AutoTrait for StructName<..> { } +``` + +## Coinduction: Auto traits permit cyclic matching + +Unlike ordinary trait matching, auto traits are **coinductive**. This +means, in short, that cycles which occur in trait matching are +considered ok. As an example, consider the recursive struct `List` +introduced in the previous section. In attempting to determine whether +`List: Send`, we would wind up in a cycle: to apply the impl, we must +show that `Option>: Send`, which will in turn require +`Box: Send` and then finally `List: Send` again. Under ordinary +trait matching, this cycle would be an error, but for an auto trait it +is considered a successful match. + +## Items + +Auto traits cannot have any trait items, such as methods or associated types. This ensures that we can generate default implementations. + +## Supertraits + +Auto traits cannot have supertraits. This is for soundness reasons, as the interaction of coinduction with implied bounds is difficult to reconcile. + diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index d55a1a3b63584..5857b79d5eeeb 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -99,6 +99,7 @@ #![feature(internal_uninit_const)] #![feature(lang_items)] #![feature(libc)] +#![cfg_attr(not(bootstrap), feature(negative_impls))] #![feature(nll)] #![feature(optin_builtin_traits)] #![feature(pattern)] diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 94fc2fd357a06..0bee16f98bd5e 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -98,6 +98,7 @@ #![feature(is_sorted)] #![feature(lang_items)] #![feature(link_llvm_intrinsics)] +#![cfg_attr(not(bootstrap), feature(negative_impls))] #![feature(never_type)] #![feature(nll)] #![feature(exhaustive_patterns)] diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index 8f16e3c08ec5b..a975ce93bb1a3 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -24,6 +24,7 @@ #![feature(decl_macro)] #![feature(extern_types)] #![feature(in_band_lifetimes)] +#![cfg_attr(not(bootstrap), feature(negative_impls))] #![feature(optin_builtin_traits)] #![feature(rustc_attrs)] #![cfg_attr(bootstrap, feature(specialization))] diff --git a/src/librustc_ast_passes/feature_gate.rs b/src/librustc_ast_passes/feature_gate.rs index 5cd7b58e14e3a..a0d7b064d0ccf 100644 --- a/src/librustc_ast_passes/feature_gate.rs +++ b/src/librustc_ast_passes/feature_gate.rs @@ -286,8 +286,8 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { start, i.span, "`#[start]` functions are experimental \ - and their signature may change \ - over time" + and their signature may change \ + over time" ); } if attr::contains_name(&i.attrs[..], sym::main) { @@ -296,8 +296,8 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { main, i.span, "declaration of a non-standard `#[main]` \ - function may change over time, for now \ - a top-level `fn main()` is required" + function may change over time, for now \ + a top-level `fn main()` is required" ); } } @@ -341,7 +341,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { if let ast::ImplPolarity::Negative(span) = polarity { gate_feature_post!( &self, - optin_builtin_traits, + negative_impls, span.to(of_trait.as_ref().map(|t| t.path.span).unwrap_or(span)), "negative trait bounds are not yet fully implemented; \ use marker types for now" diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index a21314afb1e3b..6157c46f80cf9 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -802,13 +802,13 @@ impl HandlerInner { )); self.failure(&format!( "For more information about an error, try \ - `rustc --explain {}`.", + `rustc --explain {}`.", &error_codes[0] )); } else { self.failure(&format!( "For more information about this error, try \ - `rustc --explain {}`.", + `rustc --explain {}`.", &error_codes[0] )); } diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs index 9f1fee8fc09d8..293f86d459749 100644 --- a/src/librustc_feature/active.rs +++ b/src/librustc_feature/active.rs @@ -152,6 +152,9 @@ declare_features! ( /// Allows features specific to OIBIT (auto traits). (active, optin_builtin_traits, "1.0.0", Some(13231), None), + /// Allow negative trait implementations. + (active, negative_impls, "1.0.0", Some(13231), None), + /// Allows using `box` in patterns (RFC 469). (active, box_patterns, "1.0.0", Some(29641), None), diff --git a/src/librustc_span/lib.rs b/src/librustc_span/lib.rs index 3ebcef947bc37..7a1aea15753b3 100644 --- a/src/librustc_span/lib.rs +++ b/src/librustc_span/lib.rs @@ -9,6 +9,7 @@ #![feature(const_if_match)] #![feature(const_fn)] #![feature(const_panic)] +#![cfg_attr(not(bootstrap), feature(negative_impls))] #![feature(nll)] #![feature(optin_builtin_traits)] #![feature(specialization)] @@ -305,7 +306,11 @@ impl Span { /// Returns `self` if `self` is not the dummy span, and `other` otherwise. pub fn substitute_dummy(self, other: Span) -> Span { - if self.is_dummy() { other } else { self } + if self.is_dummy() { + other + } else { + self + } } /// Returns `true` if `self` fully encloses `other`. @@ -336,21 +341,33 @@ impl Span { pub fn trim_start(self, other: Span) -> Option { let span = self.data(); let other = other.data(); - if span.hi > other.hi { Some(span.with_lo(cmp::max(span.lo, other.hi))) } else { None } + if span.hi > other.hi { + Some(span.with_lo(cmp::max(span.lo, other.hi))) + } else { + None + } } /// Returns the source span -- this is either the supplied span, or the span for /// the macro callsite that expanded to it. pub fn source_callsite(self) -> Span { let expn_data = self.ctxt().outer_expn_data(); - if !expn_data.is_root() { expn_data.call_site.source_callsite() } else { self } + if !expn_data.is_root() { + expn_data.call_site.source_callsite() + } else { + self + } } /// The `Span` for the tokens in the previous macro expansion from which `self` was generated, /// if any. pub fn parent(self) -> Option { let expn_data = self.ctxt().outer_expn_data(); - if !expn_data.is_root() { Some(expn_data.call_site) } else { None } + if !expn_data.is_root() { + Some(expn_data.call_site) + } else { + None + } } /// Edition of the crate from which this span came. @@ -376,10 +393,18 @@ impl Span { pub fn source_callee(self) -> Option { fn source_callee(expn_data: ExpnData) -> ExpnData { let next_expn_data = expn_data.call_site.ctxt().outer_expn_data(); - if !next_expn_data.is_root() { source_callee(next_expn_data) } else { expn_data } + if !next_expn_data.is_root() { + source_callee(next_expn_data) + } else { + expn_data + } } let expn_data = self.ctxt().outer_expn_data(); - if !expn_data.is_root() { Some(source_callee(expn_data)) } else { None } + if !expn_data.is_root() { + Some(source_callee(expn_data)) + } else { + None + } } /// Checks if a span is "internal" to a macro in which `#[unstable]` @@ -1199,7 +1224,11 @@ impl SourceFile { let line_index = lookup_line(&self.lines[..], pos); assert!(line_index < self.lines.len() as isize); - if line_index >= 0 { Some(line_index as usize) } else { None } + if line_index >= 0 { + Some(line_index as usize) + } else { + None + } } pub fn line_bounds(&self, line_index: usize) -> (BytePos, BytePos) { diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index dcb4e849a75e8..bb41629ef094d 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -473,6 +473,7 @@ symbols! { needs_drop, needs_panic_runtime, negate_unsigned, + negative_impls, never, never_type, never_type_fallback, diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index e5dad307a209a..d41105270549e 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -278,6 +278,7 @@ #![feature(maybe_uninit_ref)] #![feature(maybe_uninit_slice)] #![feature(needs_panic_runtime)] +#![cfg_attr(not(bootstrap), feature(negative_impls))] #![feature(never_type)] #![feature(nll)] #![feature(optin_builtin_traits)] diff --git a/src/test/pretty/trait-polarity.rs b/src/test/pretty/trait-polarity.rs index 3aab99bf6a0ae..df1a7946afb11 100644 --- a/src/test/pretty/trait-polarity.rs +++ b/src/test/pretty/trait-polarity.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] // pp-exact diff --git a/src/test/rustdoc/empty-section.rs b/src/test/rustdoc/empty-section.rs index d95f3a80365cd..665aa38b11eba 100644 --- a/src/test/rustdoc/empty-section.rs +++ b/src/test/rustdoc/empty-section.rs @@ -1,6 +1,6 @@ #![crate_name = "foo"] -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] pub struct Foo; diff --git a/src/test/rustdoc/impl-parts-crosscrate.rs b/src/test/rustdoc/impl-parts-crosscrate.rs index f9583d1a72296..a68db9c70ad2d 100644 --- a/src/test/rustdoc/impl-parts-crosscrate.rs +++ b/src/test/rustdoc/impl-parts-crosscrate.rs @@ -1,7 +1,7 @@ // aux-build:rustdoc-impl-parts-crosscrate.rs // ignore-cross-compile -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] extern crate rustdoc_impl_parts_crosscrate; diff --git a/src/test/rustdoc/impl-parts.rs b/src/test/rustdoc/impl-parts.rs index fbb4e725481c0..68baca9a04e9a 100644 --- a/src/test/rustdoc/impl-parts.rs +++ b/src/test/rustdoc/impl-parts.rs @@ -1,3 +1,4 @@ +#![feature(negative_impls)] #![feature(optin_builtin_traits)] pub auto trait AnOibit {} diff --git a/src/test/rustdoc/issue-55321.rs b/src/test/rustdoc/issue-55321.rs index 257cb32c65c25..8c001db06c5bf 100644 --- a/src/test/rustdoc/issue-55321.rs +++ b/src/test/rustdoc/issue-55321.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] // @has issue_55321/struct.A.html // @has - '//*[@id="implementations-list"]/*[@class="impl"]//code' "impl !Send for A" diff --git a/src/test/rustdoc/negative-impl-sidebar.rs b/src/test/rustdoc/negative-impl-sidebar.rs index 838ca0402e48a..cb46d1778d924 100644 --- a/src/test/rustdoc/negative-impl-sidebar.rs +++ b/src/test/rustdoc/negative-impl-sidebar.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] #![crate_name = "foo"] pub struct Foo; diff --git a/src/test/rustdoc/negative-impl.rs b/src/test/rustdoc/negative-impl.rs index 8ac87f4f0cb97..d76aac6906c46 100644 --- a/src/test/rustdoc/negative-impl.rs +++ b/src/test/rustdoc/negative-impl.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] // @matches negative_impl/struct.Alpha.html '//pre' "pub struct Alpha" pub struct Alpha; diff --git a/src/test/ui/async-await/issue-64130-1-sync.rs b/src/test/ui/async-await/issue-64130-1-sync.rs index cc5ca89f03af0..af83f14bbda5d 100644 --- a/src/test/ui/async-await/issue-64130-1-sync.rs +++ b/src/test/ui/async-await/issue-64130-1-sync.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] // edition:2018 // This tests the the specialized async-await-specific error when futures don't implement an diff --git a/src/test/ui/async-await/issue-64130-2-send.rs b/src/test/ui/async-await/issue-64130-2-send.rs index 1efe2ab3f85e2..2362831d8b8f6 100644 --- a/src/test/ui/async-await/issue-64130-2-send.rs +++ b/src/test/ui/async-await/issue-64130-2-send.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] // edition:2018 // This tests the the specialized async-await-specific error when futures don't implement an diff --git a/src/test/ui/async-await/issue-64130-3-other.rs b/src/test/ui/async-await/issue-64130-3-other.rs index 901544edba18a..b819970d59d50 100644 --- a/src/test/ui/async-await/issue-64130-3-other.rs +++ b/src/test/ui/async-await/issue-64130-3-other.rs @@ -1,4 +1,5 @@ #![feature(optin_builtin_traits)] +#![feature(negative_impls)] // edition:2018 // This tests the the unspecialized async-await-specific error when futures don't implement an diff --git a/src/test/ui/async-await/issue-64130-3-other.stderr b/src/test/ui/async-await/issue-64130-3-other.stderr index d6828172928dd..6456e7abd745d 100644 --- a/src/test/ui/async-await/issue-64130-3-other.stderr +++ b/src/test/ui/async-await/issue-64130-3-other.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `Foo: Qux` is not satisfied in `impl std::future::Future` - --> $DIR/issue-64130-3-other.rs:23:5 + --> $DIR/issue-64130-3-other.rs:24:5 | LL | fn is_qux(t: T) { } | ------ --- required by this bound in `is_qux` @@ -13,7 +13,7 @@ LL | is_qux(bar()); = help: the following implementations were found: note: future does not implement `Qux` as this value is used across an await - --> $DIR/issue-64130-3-other.rs:17:5 + --> $DIR/issue-64130-3-other.rs:18:5 | LL | let x = Foo; | - has type `Foo` diff --git a/src/test/ui/codemap_tests/empty_span.rs b/src/test/ui/codemap_tests/empty_span.rs index 4d52b391280a7..7753e2eceb543 100644 --- a/src/test/ui/codemap_tests/empty_span.rs +++ b/src/test/ui/codemap_tests/empty_span.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] fn main() { struct Foo; diff --git a/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.rs b/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.rs index 0fabb5ec91d31..24b878927530c 100644 --- a/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.rs +++ b/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] #![feature(marker_trait_attr)] #[marker] diff --git a/src/test/ui/coherence/coherence-default-trait-impl.rs b/src/test/ui/coherence/coherence-default-trait-impl.rs index db24662e2d5ad..4115ba34e17b2 100644 --- a/src/test/ui/coherence/coherence-default-trait-impl.rs +++ b/src/test/ui/coherence/coherence-default-trait-impl.rs @@ -1,4 +1,5 @@ #![feature(optin_builtin_traits)] +#![feature(negative_impls)] auto trait MySafeTrait {} diff --git a/src/test/ui/coherence/coherence-default-trait-impl.stderr b/src/test/ui/coherence/coherence-default-trait-impl.stderr index f6a163268a14a..b08ccb087d91c 100644 --- a/src/test/ui/coherence/coherence-default-trait-impl.stderr +++ b/src/test/ui/coherence/coherence-default-trait-impl.stderr @@ -1,11 +1,11 @@ error[E0199]: implementing the trait `MySafeTrait` is not unsafe - --> $DIR/coherence-default-trait-impl.rs:7:1 + --> $DIR/coherence-default-trait-impl.rs:8:1 | LL | unsafe impl MySafeTrait for Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0200]: the trait `MyUnsafeTrait` requires an `unsafe impl` declaration - --> $DIR/coherence-default-trait-impl.rs:12:1 + --> $DIR/coherence-default-trait-impl.rs:13:1 | LL | impl MyUnsafeTrait for Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.rs b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.rs index 5ea69190951e1..a9c8d20a79d75 100644 --- a/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.rs +++ b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.rs @@ -1,4 +1,5 @@ #![feature(optin_builtin_traits)] +#![feature(negative_impls)] // Test for issue #56934 - that it is impossible to redundantly // implement an auto-trait for a trait object type that contains it. diff --git a/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr index b8137b36948cd..23db5328a728b 100644 --- a/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr +++ b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr @@ -1,17 +1,17 @@ error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1` - --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:14:1 + --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1 | LL | impl !Marker1 for dyn Object + Marker2 { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1` error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2` - --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:16:1 + --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:17:1 | LL | impl !Marker2 for dyn Object + Marker2 { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2` error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:22:1 + --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:23:1 | LL | impl !Send for dyn Marker2 {} | ^^^^^^^^^^^^^^^----------- @@ -22,13 +22,13 @@ LL | impl !Send for dyn Marker2 {} = note: define and implement a trait or new type instead error[E0321]: cross-crate traits with a default impl, like `std::marker::Send`, can only be implemented for a struct/enum type, not `(dyn Object + 'static)` - --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:26:1 + --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:27:1 | LL | impl !Send for dyn Object {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type error[E0321]: cross-crate traits with a default impl, like `std::marker::Send`, can only be implemented for a struct/enum type, not `(dyn Object + Marker2 + 'static)` - --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:27:1 + --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:28:1 | LL | impl !Send for dyn Object + Marker2 {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type diff --git a/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.rs b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.rs index 6b5689e8260f0..c565f9c83e89e 100644 --- a/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.rs +++ b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.rs @@ -1,4 +1,5 @@ #![feature(optin_builtin_traits)] +#![feature(negative_impls)] // Test for issue #56934 - that it is impossible to redundantly // implement an auto-trait for a trait object type that contains it. diff --git a/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr index d68337bed0066..141ab7771f325 100644 --- a/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr +++ b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr @@ -1,17 +1,17 @@ error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1` - --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:14:1 + --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:15:1 | LL | impl Marker1 for dyn Object + Marker2 { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1` error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2` - --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:16:1 + --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:17:1 | LL | impl Marker2 for dyn Object + Marker2 { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2` error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:22:1 + --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:23:1 | LL | unsafe impl Send for dyn Marker2 {} | ^^^^^^^^^^^^^^^^^^^^^----------- @@ -22,13 +22,13 @@ LL | unsafe impl Send for dyn Marker2 {} = note: define and implement a trait or new type instead error[E0321]: cross-crate traits with a default impl, like `std::marker::Send`, can only be implemented for a struct/enum type, not `(dyn Object + 'static)` - --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:26:1 + --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:27:1 | LL | unsafe impl Send for dyn Object {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type error[E0321]: cross-crate traits with a default impl, like `std::marker::Send`, can only be implemented for a struct/enum type, not `(dyn Object + Marker2 + 'static)` - --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:27:1 + --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:28:1 | LL | unsafe impl Send for dyn Object + Marker2 {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type diff --git a/src/test/ui/coherence/coherence-impls-copy.rs b/src/test/ui/coherence/coherence-impls-copy.rs index dec40f9dd40aa..a86ca0e5eacdc 100644 --- a/src/test/ui/coherence/coherence-impls-copy.rs +++ b/src/test/ui/coherence/coherence-impls-copy.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] use std::marker::Copy; diff --git a/src/test/ui/coherence/coherence-impls-send.rs b/src/test/ui/coherence/coherence-impls-send.rs index 7898dc9831da2..e00cb9a7c5b51 100644 --- a/src/test/ui/coherence/coherence-impls-send.rs +++ b/src/test/ui/coherence/coherence-impls-send.rs @@ -1,9 +1,9 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] use std::marker::Copy; enum TestE { - A + A, } struct MyType; @@ -26,5 +26,4 @@ unsafe impl Send for &'static [NotSync] {} //~^ ERROR conflicting implementations of trait //~| ERROR only traits defined in the current crate -fn main() { -} +fn main() {} diff --git a/src/test/ui/coherence/coherence-impls-sized.rs b/src/test/ui/coherence/coherence-impls-sized.rs index 19e7349c507ef..231b96ad42efb 100644 --- a/src/test/ui/coherence/coherence-impls-sized.rs +++ b/src/test/ui/coherence/coherence-impls-sized.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] use std::marker::Copy; diff --git a/src/test/ui/coherence/coherence-negative-impls-safe-rpass.rs b/src/test/ui/coherence/coherence-negative-impls-safe-rpass.rs index 695a71cbd2d7c..b87e162aca096 100644 --- a/src/test/ui/coherence/coherence-negative-impls-safe-rpass.rs +++ b/src/test/ui/coherence/coherence-negative-impls-safe-rpass.rs @@ -2,7 +2,7 @@ #![allow(dead_code)] // pretty-expanded FIXME #23616 -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] use std::marker::Send; diff --git a/src/test/ui/coherence/coherence-negative-impls-safe.rs b/src/test/ui/coherence/coherence-negative-impls-safe.rs index 45c478ecc0362..4821aa6b5ad3d 100644 --- a/src/test/ui/coherence/coherence-negative-impls-safe.rs +++ b/src/test/ui/coherence/coherence-negative-impls-safe.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] use std::marker::Send; diff --git a/src/test/ui/coherence/coherence-orphan.rs b/src/test/ui/coherence/coherence-orphan.rs index a7b48825d7c02..3beac04c7e829 100644 --- a/src/test/ui/coherence/coherence-orphan.rs +++ b/src/test/ui/coherence/coherence-orphan.rs @@ -1,5 +1,5 @@ // aux-build:coherence_orphan_lib.rs -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] extern crate coherence_orphan_lib as lib; diff --git a/src/test/ui/error-codes/E0198.rs b/src/test/ui/error-codes/E0198.rs index 00ab0c3562378..041bbe8fdcf69 100644 --- a/src/test/ui/error-codes/E0198.rs +++ b/src/test/ui/error-codes/E0198.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] struct Foo; diff --git a/src/test/ui/error-codes/E0199.rs b/src/test/ui/error-codes/E0199.rs index c95afa3f97d4a..2421bf0a55f65 100644 --- a/src/test/ui/error-codes/E0199.rs +++ b/src/test/ui/error-codes/E0199.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] struct Foo; diff --git a/src/test/ui/feature-gate-negative_impls.rs b/src/test/ui/feature-gate-negative_impls.rs new file mode 100644 index 0000000000000..683fd6db6f29d --- /dev/null +++ b/src/test/ui/feature-gate-negative_impls.rs @@ -0,0 +1,3 @@ +trait MyTrait {} +impl !MyTrait for u32 {} //~ ERROR negative trait bounds are not yet fully implemented +fn main() {} diff --git a/src/test/ui/feature-gate-negative_impls.stderr b/src/test/ui/feature-gate-negative_impls.stderr new file mode 100644 index 0000000000000..922048996bd10 --- /dev/null +++ b/src/test/ui/feature-gate-negative_impls.stderr @@ -0,0 +1,12 @@ +error[E0658]: negative trait bounds are not yet fully implemented; use marker types for now + --> $DIR/feature-gate-negative_impls.rs:2:6 + | +LL | impl !MyTrait for u32 {} + | ^^^^^^^^ + | + = note: see issue #13231 for more information + = help: add `#![feature(negative_impls)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-optin-builtin-traits.stderr b/src/test/ui/feature-gates/feature-gate-optin-builtin-traits.stderr index 490d29ad8a35f..e9090b78c78a1 100644 --- a/src/test/ui/feature-gates/feature-gate-optin-builtin-traits.stderr +++ b/src/test/ui/feature-gates/feature-gate-optin-builtin-traits.stderr @@ -14,7 +14,7 @@ LL | impl !AutoDummyTrait for DummyStruct {} | ^^^^^^^^^^^^^^^ | = note: see issue #13231 for more information - = help: add `#![feature(optin_builtin_traits)]` to the crate attributes to enable + = help: add `#![feature(negative_impls)]` to the crate attributes to enable error: aborting due to 2 previous errors diff --git a/src/test/ui/generator/auto-trait-regions.nll.stderr b/src/test/ui/generator/auto-trait-regions.nll.stderr index bf87aea0d4c1a..794369a8dc02b 100644 --- a/src/test/ui/generator/auto-trait-regions.nll.stderr +++ b/src/test/ui/generator/auto-trait-regions.nll.stderr @@ -1,5 +1,5 @@ error[E0716]: temporary value dropped while borrowed - --> $DIR/auto-trait-regions.rs:45:24 + --> $DIR/auto-trait-regions.rs:46:24 | LL | let a = A(&mut true, &mut true, No); | ^^^^ - temporary value is freed at the end of this statement @@ -12,7 +12,7 @@ LL | assert_foo(a); = note: consider using a `let` binding to create a longer lived value error[E0716]: temporary value dropped while borrowed - --> $DIR/auto-trait-regions.rs:45:35 + --> $DIR/auto-trait-regions.rs:46:35 | LL | let a = A(&mut true, &mut true, No); | ^^^^ - temporary value is freed at the end of this statement @@ -25,13 +25,13 @@ LL | assert_foo(a); = note: consider using a `let` binding to create a longer lived value error: higher-ranked subtype error - --> $DIR/auto-trait-regions.rs:30:5 + --> $DIR/auto-trait-regions.rs:31:5 | LL | assert_foo(gen); | ^^^^^^^^^^^^^^^ error: higher-ranked subtype error - --> $DIR/auto-trait-regions.rs:49:5 + --> $DIR/auto-trait-regions.rs:50:5 | LL | assert_foo(gen); | ^^^^^^^^^^^^^^^ diff --git a/src/test/ui/generator/auto-trait-regions.rs b/src/test/ui/generator/auto-trait-regions.rs index dbd8965dcf0d0..1e77d8058a72b 100644 --- a/src/test/ui/generator/auto-trait-regions.rs +++ b/src/test/ui/generator/auto-trait-regions.rs @@ -1,5 +1,6 @@ #![feature(generators)] #![feature(optin_builtin_traits)] +#![feature(negative_impls)] auto trait Foo {} diff --git a/src/test/ui/generator/auto-trait-regions.stderr b/src/test/ui/generator/auto-trait-regions.stderr index 29a3907d93c84..5ec462e10465f 100644 --- a/src/test/ui/generator/auto-trait-regions.stderr +++ b/src/test/ui/generator/auto-trait-regions.stderr @@ -1,5 +1,5 @@ error: implementation of `Foo` is not general enough - --> $DIR/auto-trait-regions.rs:30:5 + --> $DIR/auto-trait-regions.rs:31:5 | LL | auto trait Foo {} | ----------------- trait `Foo` defined here @@ -11,7 +11,7 @@ LL | assert_foo(gen); = note: ...but `Foo` is actually implemented for the type `&'1 OnlyFooIfStaticRef`, for some specific lifetime `'1` error: implementation of `Foo` is not general enough - --> $DIR/auto-trait-regions.rs:30:5 + --> $DIR/auto-trait-regions.rs:31:5 | LL | auto trait Foo {} | ----------------- trait `Foo` defined here @@ -23,7 +23,7 @@ LL | assert_foo(gen); = note: ...but `Foo` is actually implemented for the type `&'1 OnlyFooIfStaticRef`, for some specific lifetime `'1` error: implementation of `Foo` is not general enough - --> $DIR/auto-trait-regions.rs:49:5 + --> $DIR/auto-trait-regions.rs:50:5 | LL | auto trait Foo {} | ----------------- trait `Foo` defined here @@ -35,7 +35,7 @@ LL | assert_foo(gen); = note: ...but `Foo` is actually implemented for the type `A<'_, '2>`, for some specific lifetime `'2` error: implementation of `Foo` is not general enough - --> $DIR/auto-trait-regions.rs:49:5 + --> $DIR/auto-trait-regions.rs:50:5 | LL | auto trait Foo {} | ----------------- trait `Foo` defined here diff --git a/src/test/ui/issues/issue-17718-static-sync.rs b/src/test/ui/issues/issue-17718-static-sync.rs index dccbde6a3c532..6f278d76bb18b 100644 --- a/src/test/ui/issues/issue-17718-static-sync.rs +++ b/src/test/ui/issues/issue-17718-static-sync.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] use std::marker::Sync; diff --git a/src/test/ui/issues/issue-23080-2.rs b/src/test/ui/issues/issue-23080-2.rs index d20bb4bd90726..7f6b9e3fba79f 100644 --- a/src/test/ui/issues/issue-23080-2.rs +++ b/src/test/ui/issues/issue-23080-2.rs @@ -1,6 +1,7 @@ //~ ERROR #![feature(optin_builtin_traits)] +#![feature(negative_impls)] unsafe auto trait Trait { type Output; //~ ERROR E0380 diff --git a/src/test/ui/issues/issue-23080-2.stderr b/src/test/ui/issues/issue-23080-2.stderr index fcd1ecfa98288..48ce09aaa34da 100644 --- a/src/test/ui/issues/issue-23080-2.stderr +++ b/src/test/ui/issues/issue-23080-2.stderr @@ -1,5 +1,5 @@ error[E0380]: auto traits cannot have methods or associated items - --> $DIR/issue-23080-2.rs:6:10 + --> $DIR/issue-23080-2.rs:7:10 | LL | unsafe auto trait Trait { | ----- auto trait cannot have items diff --git a/src/test/ui/issues/issue-23080.rs b/src/test/ui/issues/issue-23080.rs index fa5c35316bc28..035db82ba5de0 100644 --- a/src/test/ui/issues/issue-23080.rs +++ b/src/test/ui/issues/issue-23080.rs @@ -1,4 +1,5 @@ #![feature(optin_builtin_traits)] +#![feature(negative_impls)] unsafe auto trait Trait { fn method(&self) { //~ ERROR E0380 diff --git a/src/test/ui/issues/issue-23080.stderr b/src/test/ui/issues/issue-23080.stderr index dbb9861b5784a..73ecb1c362e17 100644 --- a/src/test/ui/issues/issue-23080.stderr +++ b/src/test/ui/issues/issue-23080.stderr @@ -1,5 +1,5 @@ error[E0380]: auto traits cannot have methods or associated items - --> $DIR/issue-23080.rs:4:8 + --> $DIR/issue-23080.rs:5:8 | LL | unsafe auto trait Trait { | ----- auto trait cannot have items diff --git a/src/test/ui/issues/issue-29516.rs b/src/test/ui/issues/issue-29516.rs index d43367e34529b..035f904b15bb3 100644 --- a/src/test/ui/issues/issue-29516.rs +++ b/src/test/ui/issues/issue-29516.rs @@ -1,5 +1,6 @@ // check-pass #![feature(optin_builtin_traits)] +#![feature(negative_impls)] auto trait NotSame {} diff --git a/src/test/ui/issues/issue-33140-hack-boundaries.rs b/src/test/ui/issues/issue-33140-hack-boundaries.rs index 5aba886273f7b..5984a256a3086 100644 --- a/src/test/ui/issues/issue-33140-hack-boundaries.rs +++ b/src/test/ui/issues/issue-33140-hack-boundaries.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] #![allow(order_dependent_trait_objects)] // Check that the issue #33140 hack does not allow unintended things. diff --git a/src/test/ui/mut/mutable-enum-indirect.rs b/src/test/ui/mut/mutable-enum-indirect.rs index 611ff0d66a24e..502859c041353 100644 --- a/src/test/ui/mut/mutable-enum-indirect.rs +++ b/src/test/ui/mut/mutable-enum-indirect.rs @@ -1,7 +1,7 @@ // Tests that an `&` pointer to something inherently mutable is itself // to be considered mutable. -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] use std::marker::Sync; diff --git a/src/test/ui/never_type/auto-traits.rs b/src/test/ui/never_type/auto-traits.rs index 2d9689888cb30..84c8db4053e4f 100644 --- a/src/test/ui/never_type/auto-traits.rs +++ b/src/test/ui/never_type/auto-traits.rs @@ -1,6 +1,7 @@ // check-pass #![feature(optin_builtin_traits)] +#![feature(negative_impls)] #![feature(never_type)] fn main() { diff --git a/src/test/ui/no_send-enum.rs b/src/test/ui/no_send-enum.rs index 4b4d06f1e32cd..bd560649b990e 100644 --- a/src/test/ui/no_send-enum.rs +++ b/src/test/ui/no_send-enum.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] use std::marker::Send; diff --git a/src/test/ui/no_send-struct.rs b/src/test/ui/no_send-struct.rs index 67816bfee5d02..75a363f9f7639 100644 --- a/src/test/ui/no_send-struct.rs +++ b/src/test/ui/no_send-struct.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] use std::marker::Send; diff --git a/src/test/ui/no_share-enum.rs b/src/test/ui/no_share-enum.rs index f5edb63cf86e9..44bf1913e7aac 100644 --- a/src/test/ui/no_share-enum.rs +++ b/src/test/ui/no_share-enum.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] use std::marker::Sync; diff --git a/src/test/ui/no_share-struct.rs b/src/test/ui/no_share-struct.rs index 35867d0f2166d..7d8a36a76f274 100644 --- a/src/test/ui/no_share-struct.rs +++ b/src/test/ui/no_share-struct.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] use std::marker::Sync; diff --git a/src/test/ui/parser/trait-object-bad-parens.rs b/src/test/ui/parser/trait-object-bad-parens.rs index 048e028be1ca1..0a2836d691f5f 100644 --- a/src/test/ui/parser/trait-object-bad-parens.rs +++ b/src/test/ui/parser/trait-object-bad-parens.rs @@ -1,4 +1,5 @@ #![feature(optin_builtin_traits)] +#![feature(negative_impls)] #![allow(bare_trait_objects)] auto trait Auto {} diff --git a/src/test/ui/parser/trait-object-bad-parens.stderr b/src/test/ui/parser/trait-object-bad-parens.stderr index f53afdff5e7c2..74e484eebee1f 100644 --- a/src/test/ui/parser/trait-object-bad-parens.stderr +++ b/src/test/ui/parser/trait-object-bad-parens.stderr @@ -1,23 +1,23 @@ error[E0178]: expected a path on the left-hand side of `+`, not `((Auto))` - --> $DIR/trait-object-bad-parens.rs:7:16 + --> $DIR/trait-object-bad-parens.rs:8:16 | LL | let _: Box<((Auto)) + Auto>; | ^^^^^^^^^^^^^^^ expected a path error[E0178]: expected a path on the left-hand side of `+`, not `(Auto + Auto)` - --> $DIR/trait-object-bad-parens.rs:9:16 + --> $DIR/trait-object-bad-parens.rs:10:16 | LL | let _: Box<(Auto + Auto) + Auto>; | ^^^^^^^^^^^^^^^^^^^^ expected a path error[E0178]: expected a path on the left-hand side of `+`, not `(Auto)` - --> $DIR/trait-object-bad-parens.rs:11:16 + --> $DIR/trait-object-bad-parens.rs:12:16 | LL | let _: Box<(Auto +) + Auto>; | ^^^^^^^^^^^^^^^ expected a path error[E0178]: expected a path on the left-hand side of `+`, not `(dyn Auto)` - --> $DIR/trait-object-bad-parens.rs:13:16 + --> $DIR/trait-object-bad-parens.rs:14:16 | LL | let _: Box<(dyn Auto) + Auto>; | ^^^^^^^^^^^^^^^^^ expected a path diff --git a/src/test/ui/privacy/privacy-sanity.rs b/src/test/ui/privacy/privacy-sanity.rs index f83b24c49a10a..8bbf1ab5d1f30 100644 --- a/src/test/ui/privacy/privacy-sanity.rs +++ b/src/test/ui/privacy/privacy-sanity.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] pub trait Tr { fn f(); diff --git a/src/test/ui/privacy/private-in-public-non-principal-2.rs b/src/test/ui/privacy/private-in-public-non-principal-2.rs index 8a59073fa6c7e..cd3d609ca3ea6 100644 --- a/src/test/ui/privacy/private-in-public-non-principal-2.rs +++ b/src/test/ui/privacy/private-in-public-non-principal-2.rs @@ -1,4 +1,5 @@ #![feature(optin_builtin_traits)] +#![feature(negative_impls)] #[allow(private_in_public)] mod m { diff --git a/src/test/ui/privacy/private-in-public-non-principal-2.stderr b/src/test/ui/privacy/private-in-public-non-principal-2.stderr index 1b6d143b93217..7850694aab207 100644 --- a/src/test/ui/privacy/private-in-public-non-principal-2.stderr +++ b/src/test/ui/privacy/private-in-public-non-principal-2.stderr @@ -1,5 +1,5 @@ error: trait `m::PrivNonPrincipal` is private - --> $DIR/private-in-public-non-principal-2.rs:11:5 + --> $DIR/private-in-public-non-principal-2.rs:12:5 | LL | m::leak_dyn_nonprincipal(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ private trait diff --git a/src/test/ui/privacy/private-in-public-non-principal.rs b/src/test/ui/privacy/private-in-public-non-principal.rs index b306849ac8e5e..aa946f5c0ac05 100644 --- a/src/test/ui/privacy/private-in-public-non-principal.rs +++ b/src/test/ui/privacy/private-in-public-non-principal.rs @@ -1,4 +1,5 @@ #![feature(optin_builtin_traits)] +#![feature(negative_impls)] pub trait PubPrincipal {} auto trait PrivNonPrincipal {} diff --git a/src/test/ui/privacy/private-in-public-non-principal.stderr b/src/test/ui/privacy/private-in-public-non-principal.stderr index 778c98671ad4d..05131135d490f 100644 --- a/src/test/ui/privacy/private-in-public-non-principal.stderr +++ b/src/test/ui/privacy/private-in-public-non-principal.stderr @@ -1,5 +1,5 @@ warning: private trait `PrivNonPrincipal` in public interface (error E0445) - --> $DIR/private-in-public-non-principal.rs:6:1 + --> $DIR/private-in-public-non-principal.rs:7:1 | LL | pub fn leak_dyn_nonprincipal() -> Box { loop {} } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,7 +15,7 @@ LL | pub fn check_doc_lint() {} | ^^^^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/private-in-public-non-principal.rs:10:8 + --> $DIR/private-in-public-non-principal.rs:11:8 | LL | #[deny(missing_docs)] | ^^^^^^^^^^^^ diff --git a/src/test/ui/specialization/defaultimpl/validation.rs b/src/test/ui/specialization/defaultimpl/validation.rs index ac8742c70c878..8134333c58f73 100644 --- a/src/test/ui/specialization/defaultimpl/validation.rs +++ b/src/test/ui/specialization/defaultimpl/validation.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] #![feature(specialization)] struct S; diff --git a/src/test/ui/specialization/specialization-overlap-negative.rs b/src/test/ui/specialization/specialization-overlap-negative.rs index 4f5f65dafaa2e..dff2b28bf003c 100644 --- a/src/test/ui/specialization/specialization-overlap-negative.rs +++ b/src/test/ui/specialization/specialization-overlap-negative.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] #![feature(specialization)] trait MyTrait {} diff --git a/src/test/ui/specialization/specialization-polarity.rs b/src/test/ui/specialization/specialization-polarity.rs index fd0671ad09e32..4a733fb3c497e 100644 --- a/src/test/ui/specialization/specialization-polarity.rs +++ b/src/test/ui/specialization/specialization-polarity.rs @@ -1,6 +1,7 @@ // Make sure specialization cannot change impl polarity #![feature(optin_builtin_traits)] +#![feature(negative_impls)] #![feature(specialization)] auto trait Foo {} diff --git a/src/test/ui/specialization/specialization-polarity.stderr b/src/test/ui/specialization/specialization-polarity.stderr index c6e7f193d0132..30655d87d5500 100644 --- a/src/test/ui/specialization/specialization-polarity.stderr +++ b/src/test/ui/specialization/specialization-polarity.stderr @@ -1,5 +1,5 @@ error[E0748]: found both positive and negative implementation of trait `Foo` for type `u8`: - --> $DIR/specialization-polarity.rs:9:1 + --> $DIR/specialization-polarity.rs:10:1 | LL | impl Foo for T {} | ----------------- positive implementation here @@ -7,7 +7,7 @@ LL | impl !Foo for u8 {} | ^^^^^^^^^^^^^^^^ negative implementation here error[E0748]: found both positive and negative implementation of trait `Bar` for type `u8`: - --> $DIR/specialization-polarity.rs:14:1 + --> $DIR/specialization-polarity.rs:15:1 | LL | impl !Bar for T {} | ------------------ negative implementation here diff --git a/src/test/ui/syntax-trait-polarity-feature-gate.stderr b/src/test/ui/syntax-trait-polarity-feature-gate.stderr index 5d4c1b354f700..1c37106f13db0 100644 --- a/src/test/ui/syntax-trait-polarity-feature-gate.stderr +++ b/src/test/ui/syntax-trait-polarity-feature-gate.stderr @@ -5,7 +5,7 @@ LL | impl !Send for TestType {} | ^^^^^ | = note: see issue #13231 for more information - = help: add `#![feature(optin_builtin_traits)]` to the crate attributes to enable + = help: add `#![feature(negative_impls)]` to the crate attributes to enable error: aborting due to previous error diff --git a/src/test/ui/syntax-trait-polarity.rs b/src/test/ui/syntax-trait-polarity.rs index 739a3c12dfb41..ed2947493b02c 100644 --- a/src/test/ui/syntax-trait-polarity.rs +++ b/src/test/ui/syntax-trait-polarity.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] use std::marker::Send; diff --git a/src/test/ui/traits/auto-traits.rs b/src/test/ui/traits/auto-traits.rs index c495b97b25bfe..15fdddc5f3f5c 100644 --- a/src/test/ui/traits/auto-traits.rs +++ b/src/test/ui/traits/auto-traits.rs @@ -1,6 +1,7 @@ // run-pass #![allow(unused_doc_comments)] #![feature(optin_builtin_traits)] +#![feature(negative_impls)] auto trait Auto {} unsafe auto trait AutoUnsafe {} diff --git a/src/test/ui/traits/negative-impls/auxiliary/foreign_trait.rs b/src/test/ui/traits/negative-impls/auxiliary/foreign_trait.rs index 1790b24be3384..681f26438e695 100644 --- a/src/test/ui/traits/negative-impls/auxiliary/foreign_trait.rs +++ b/src/test/ui/traits/negative-impls/auxiliary/foreign_trait.rs @@ -1,6 +1,6 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] -pub trait ForeignTrait { } +pub trait ForeignTrait {} -impl ForeignTrait for u32 { } +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 index fb9a3a99748d0..4bdad5dc591c5 100644 --- a/src/test/ui/traits/negative-impls/negated-auto-traits-error.rs +++ b/src/test/ui/traits/negative-impls/negated-auto-traits-error.rs @@ -3,7 +3,7 @@ // 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)] +#![feature(negative_impls)] use std::marker::Send; 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 index 8664b6a6a6e36..010dbf2466403 100644 --- a/src/test/ui/traits/negative-impls/negated-auto-traits-rpass.rs +++ b/src/test/ui/traits/negative-impls/negated-auto-traits-rpass.rs @@ -1,6 +1,6 @@ // run-pass #![allow(unused_variables)] -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] use std::marker::Send; 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 b23ac87f89986..2d50bc83ec304 100644 --- a/src/test/ui/traits/negative-impls/negative-default-impls.rs +++ b/src/test/ui/traits/negative-impls/negative-default-impls.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] #![feature(specialization)] trait MyTrait { 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 index c7009430eae99..043273e624189 100644 --- a/src/test/ui/traits/negative-impls/negative-specializes-positive-item.rs +++ b/src/test/ui/traits/negative-impls/negative-specializes-positive-item.rs @@ -1,5 +1,5 @@ #![feature(specialization)] -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] // Negative impl for u32 cannot "specialize" the base impl. trait MyTrait { diff --git a/src/test/ui/traits/negative-impls/negative-specializes-positive.rs b/src/test/ui/traits/negative-impls/negative-specializes-positive.rs index 25301c696e13f..ac0fac10eef50 100644 --- a/src/test/ui/traits/negative-impls/negative-specializes-positive.rs +++ b/src/test/ui/traits/negative-impls/negative-specializes-positive.rs @@ -1,5 +1,5 @@ #![feature(specialization)] -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] // Negative impl for u32 cannot "specialize" the base impl. trait MyTrait {} diff --git a/src/test/ui/traits/negative-impls/no-items.rs b/src/test/ui/traits/negative-impls/no-items.rs index 5bfbf9653ab11..5fc6be9b30007 100644 --- a/src/test/ui/traits/negative-impls/no-items.rs +++ b/src/test/ui/traits/negative-impls/no-items.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] trait MyTrait { type Foo; diff --git a/src/test/ui/traits/negative-impls/positive-specializes-negative.rs b/src/test/ui/traits/negative-impls/positive-specializes-negative.rs index 8a8ee70370fea..eac4c24d5d3d0 100644 --- a/src/test/ui/traits/negative-impls/positive-specializes-negative.rs +++ b/src/test/ui/traits/negative-impls/positive-specializes-negative.rs @@ -1,5 +1,5 @@ #![feature(specialization)] -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] trait MyTrait {} 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 index b823c0f78649f..db72aaf18034f 100644 --- 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 @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] // aux-build: foreign_trait.rs 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 index 6a2e99f8147a7..e326d3ab3f3cb 100644 --- a/src/test/ui/traits/negative-impls/typeck-negative-impls-builtin.rs +++ b/src/test/ui/traits/negative-impls/typeck-negative-impls-builtin.rs @@ -1,6 +1,6 @@ // run-pass -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] #![allow(dead_code)] struct TestType; diff --git a/src/test/ui/traits/overlap-not-permitted-for-builtin-trait.rs b/src/test/ui/traits/overlap-not-permitted-for-builtin-trait.rs index 86029473b513b..4106f56d64ac6 100644 --- a/src/test/ui/traits/overlap-not-permitted-for-builtin-trait.rs +++ b/src/test/ui/traits/overlap-not-permitted-for-builtin-trait.rs @@ -1,5 +1,5 @@ #![allow(dead_code)] -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] // Overlapping negative impls for `MyStruct` are not permitted: struct MyStruct; @@ -7,5 +7,4 @@ impl !Send for MyStruct {} impl !Send for MyStruct {} //~^ ERROR conflicting implementations of trait -fn main() { -} +fn main() {} diff --git a/src/test/ui/traits/overlap-permitted-for-marker-traits.rs b/src/test/ui/traits/overlap-permitted-for-marker-traits.rs new file mode 100644 index 0000000000000..00823d13b3696 --- /dev/null +++ b/src/test/ui/traits/overlap-permitted-for-marker-traits.rs @@ -0,0 +1,28 @@ +// run-pass +// Tests for RFC 1268: we allow overlapping impls of marker traits, +// that is, traits without items. In this case, a type `T` is +// `MyMarker` if it is either `Debug` or `Display`. + +#![feature(marker_trait_attr)] +#![feature(negative_impls)] + +use std::fmt::{Debug, Display}; + +#[marker] +trait MyMarker {} + +impl MyMarker for T {} +impl MyMarker for T {} + +fn foo(t: T) -> T { + t +} + +fn main() { + // Debug && Display: + assert_eq!(1, foo(1)); + assert_eq!(2.0, foo(2.0)); + + // Debug && !Display: + assert_eq!(vec![1], foo(vec![1])); +} diff --git a/src/test/ui/traits/syntax-trait-polarity.rs b/src/test/ui/traits/syntax-trait-polarity.rs index c6524f5c8e782..c809f9e89f934 100644 --- a/src/test/ui/traits/syntax-trait-polarity.rs +++ b/src/test/ui/traits/syntax-trait-polarity.rs @@ -2,7 +2,7 @@ #![allow(dead_code)] // pretty-expanded FIXME #23616 -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] struct TestType; diff --git a/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.rs b/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.rs index c65242b1bb1c3..571f934fc5bc7 100644 --- a/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.rs +++ b/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.rs @@ -3,6 +3,7 @@ // to be synthesized. #![feature(optin_builtin_traits)] +#![feature(negative_impls)] auto trait Magic: Copy {} //~ ERROR E0568 diff --git a/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr b/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr index a83ff3701511d..f44986da0e230 100644 --- a/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr +++ b/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr @@ -1,5 +1,5 @@ error[E0568]: auto traits cannot have super traits - --> $DIR/traits-inductive-overflow-supertrait-oibit.rs:7:19 + --> $DIR/traits-inductive-overflow-supertrait-oibit.rs:8:19 | LL | auto trait Magic: Copy {} | ----- ^^^^ help: remove the super traits @@ -7,7 +7,7 @@ LL | auto trait Magic: Copy {} | auto trait cannot have super traits error[E0277]: the trait bound `NoClone: std::marker::Copy` is not satisfied - --> $DIR/traits-inductive-overflow-supertrait-oibit.rs:15:23 + --> $DIR/traits-inductive-overflow-supertrait-oibit.rs:16:23 | LL | fn copy(x: T) -> (T, T) { (x, x) } | ---- ----- required by this bound in `copy` diff --git a/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.rs b/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.rs index 92d8ba887270e..8824a6d2767f7 100644 --- a/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.rs +++ b/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.rs @@ -1,4 +1,5 @@ #![feature(optin_builtin_traits)] +#![feature(negative_impls)] auto trait Magic : Sized where Option : Magic {} //~ ERROR E0568 impl Magic for T {} diff --git a/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr b/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr index e397629327754..63b3300f6dbf4 100644 --- a/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr +++ b/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr @@ -1,5 +1,5 @@ error[E0568]: auto traits cannot have super traits - --> $DIR/typeck-auto-trait-no-supertraits-2.rs:3:20 + --> $DIR/typeck-auto-trait-no-supertraits-2.rs:4:20 | LL | auto trait Magic : Sized where Option : Magic {} | ----- ^^^^^ help: remove the super traits diff --git a/src/test/ui/typeck/typeck-auto-trait-no-supertraits.rs b/src/test/ui/typeck/typeck-auto-trait-no-supertraits.rs index e48017acfc718..edbca91512486 100644 --- a/src/test/ui/typeck/typeck-auto-trait-no-supertraits.rs +++ b/src/test/ui/typeck/typeck-auto-trait-no-supertraits.rs @@ -23,6 +23,7 @@ // } #![feature(optin_builtin_traits)] +#![feature(negative_impls)] auto trait Magic: Copy {} //~ ERROR E0568 impl Magic for T {} diff --git a/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr b/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr index b1602e3642ecb..796638fc54dce 100644 --- a/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr +++ b/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr @@ -1,5 +1,5 @@ error[E0568]: auto traits cannot have super traits - --> $DIR/typeck-auto-trait-no-supertraits.rs:27:19 + --> $DIR/typeck-auto-trait-no-supertraits.rs:28:19 | LL | auto trait Magic: Copy {} | ----- ^^^^ help: remove the super traits diff --git a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.rs b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.rs index 6c170fb5bae7d..71ac2b466c10a 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.rs +++ b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.rs @@ -1,4 +1,5 @@ #![feature(optin_builtin_traits)] +#![feature(negative_impls)] auto trait MyTrait {} diff --git a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.stderr b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.stderr index f060afea24e7f..23401ca308676 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.stderr +++ b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `MyS2: MyTrait` is not satisfied in `(MyS2, MyS)` - --> $DIR/typeck-default-trait-impl-constituent-types-2.rs:16:5 + --> $DIR/typeck-default-trait-impl-constituent-types-2.rs:17:5 | LL | fn is_mytrait() {} | ---------- ------- required by this bound in `is_mytrait` diff --git a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.rs b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.rs index d72f676121875..6483b9213dc53 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.rs +++ b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.rs @@ -1,4 +1,5 @@ #![feature(optin_builtin_traits)] +#![feature(negative_impls)] auto trait MyTrait {} diff --git a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.stderr b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.stderr index 22a2cb3e0ecb8..a30b29a3893cc 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.stderr +++ b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `MyS2: MyTrait` is not satisfied - --> $DIR/typeck-default-trait-impl-constituent-types.rs:20:18 + --> $DIR/typeck-default-trait-impl-constituent-types.rs:21:18 | LL | fn is_mytrait() {} | ---------- ------- required by this bound in `is_mytrait` diff --git a/src/test/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.rs b/src/test/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.rs index 212e165151d81..772ac322032ec 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.rs +++ b/src/test/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.rs @@ -3,7 +3,7 @@ // Test that we do not consider associated types to be sendable without // some applicable trait bound (and we don't ICE). -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] extern crate tdticc_coherence_lib as lib; diff --git a/src/test/ui/typeck/typeck-default-trait-impl-negation-send.rs b/src/test/ui/typeck/typeck-default-trait-impl-negation-send.rs index 617d0f3b565a8..3a2fc39d409d9 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-negation-send.rs +++ b/src/test/ui/typeck/typeck-default-trait-impl-negation-send.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] struct MySendable { t: *mut u8 diff --git a/src/test/ui/typeck/typeck-default-trait-impl-negation-sync.rs b/src/test/ui/typeck/typeck-default-trait-impl-negation-sync.rs index e4487fb110cf1..2734b761e61b7 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-negation-sync.rs +++ b/src/test/ui/typeck/typeck-default-trait-impl-negation-sync.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] struct Managed; impl !Send for Managed {} diff --git a/src/test/ui/typeck/typeck-default-trait-impl-negation.rs b/src/test/ui/typeck/typeck-default-trait-impl-negation.rs index 0b6e13be6e108..47cab60625dce 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-negation.rs +++ b/src/test/ui/typeck/typeck-default-trait-impl-negation.rs @@ -1,4 +1,5 @@ #![feature(optin_builtin_traits)] +#![feature(negative_impls)] auto trait MyTrait {} diff --git a/src/test/ui/typeck/typeck-default-trait-impl-negation.stderr b/src/test/ui/typeck/typeck-default-trait-impl-negation.stderr index 4b13fcc885a0d..e31bb81074469 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-negation.stderr +++ b/src/test/ui/typeck/typeck-default-trait-impl-negation.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `ThisImplsUnsafeTrait: MyTrait` is not satisfied - --> $DIR/typeck-default-trait-impl-negation.rs:21:19 + --> $DIR/typeck-default-trait-impl-negation.rs:22:19 | LL | fn is_my_trait() {} | ----------- ------- required by this bound in `is_my_trait` @@ -11,7 +11,7 @@ LL | is_my_trait::(); error[E0277]: the trait bound `ThisImplsTrait: MyUnsafeTrait` is not satisfied - --> $DIR/typeck-default-trait-impl-negation.rs:24:26 + --> $DIR/typeck-default-trait-impl-negation.rs:25:26 | LL | fn is_my_unsafe_trait() {} | ------------------ ------------- required by this bound in `is_my_unsafe_trait` diff --git a/src/test/ui/typeck/typeck-default-trait-impl-precedence.rs b/src/test/ui/typeck/typeck-default-trait-impl-precedence.rs index 9b228f706465b..614a5ff55b1ed 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-precedence.rs +++ b/src/test/ui/typeck/typeck-default-trait-impl-precedence.rs @@ -4,6 +4,7 @@ // impls whose types unify. #![feature(optin_builtin_traits)] +#![feature(negative_impls)] auto trait Defaulted { } impl<'a,T:Signed> Defaulted for &'a T { } diff --git a/src/test/ui/typeck/typeck-default-trait-impl-precedence.stderr b/src/test/ui/typeck/typeck-default-trait-impl-precedence.stderr index 1587730441820..0d256094c60e0 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-precedence.stderr +++ b/src/test/ui/typeck/typeck-default-trait-impl-precedence.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `u32: Signed` is not satisfied - --> $DIR/typeck-default-trait-impl-precedence.rs:18:5 + --> $DIR/typeck-default-trait-impl-precedence.rs:19:5 | LL | fn is_defaulted() { } | ------------ --------- required by this bound in `is_defaulted` diff --git a/src/test/ui/typeck/typeck-unsafe-always-share.rs b/src/test/ui/typeck/typeck-unsafe-always-share.rs index 7d1ff732983fe..dc5ddf5156302 100644 --- a/src/test/ui/typeck/typeck-unsafe-always-share.rs +++ b/src/test/ui/typeck/typeck-unsafe-always-share.rs @@ -1,6 +1,6 @@ // Verify that UnsafeCell is *always* !Sync regardless if `T` is sync. -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] use std::cell::UnsafeCell; use std::marker::Sync; From cc0d6d03f61d19e6d6d7b5137be314d27f7f1d70 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 17 Jan 2020 14:34:25 -0500 Subject: [PATCH 11/22] create a tracking issue and link to it --- .../unstable-book/src/language-features/negative-impls.md | 4 ++-- src/librustc_feature/active.rs | 6 +++--- src/test/ui/feature-gate-negative_impls.stderr | 2 +- .../feature-gates/feature-gate-optin-builtin-traits.stderr | 2 +- src/test/ui/syntax-trait-polarity-feature-gate.stderr | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/doc/unstable-book/src/language-features/negative-impls.md b/src/doc/unstable-book/src/language-features/negative-impls.md index 3cf9351b6304b..151520f0e4abc 100644 --- a/src/doc/unstable-book/src/language-features/negative-impls.md +++ b/src/doc/unstable-book/src/language-features/negative-impls.md @@ -1,8 +1,8 @@ # `negative_impls` -The tracking issue for this feature is [#13231] +The tracking issue for this feature is [#68318]. -[#13231]: https://github.com/rust-lang/rust/issues/13231 +[#68318]: https://github.com/rust-lang/rust/issues/68318 ---- diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs index 293f86d459749..825323f55bd18 100644 --- a/src/librustc_feature/active.rs +++ b/src/librustc_feature/active.rs @@ -152,9 +152,6 @@ declare_features! ( /// Allows features specific to OIBIT (auto traits). (active, optin_builtin_traits, "1.0.0", Some(13231), None), - /// Allow negative trait implementations. - (active, negative_impls, "1.0.0", Some(13231), None), - /// Allows using `box` in patterns (RFC 469). (active, box_patterns, "1.0.0", Some(29641), None), @@ -557,6 +554,9 @@ declare_features! ( // Allows limiting the evaluation steps of const expressions (active, const_eval_limit, "1.43.0", Some(67217), None), + /// Allow negative trait implementations. + (active, negative_impls, "1.43.0", Some(68318), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- diff --git a/src/test/ui/feature-gate-negative_impls.stderr b/src/test/ui/feature-gate-negative_impls.stderr index 922048996bd10..b253fbd0da7f9 100644 --- a/src/test/ui/feature-gate-negative_impls.stderr +++ b/src/test/ui/feature-gate-negative_impls.stderr @@ -4,7 +4,7 @@ error[E0658]: negative trait bounds are not yet fully implemented; use marker ty LL | impl !MyTrait for u32 {} | ^^^^^^^^ | - = note: see issue #13231 for more information + = note: see issue #68318 for more information = help: add `#![feature(negative_impls)]` to the crate attributes to enable error: aborting due to previous error diff --git a/src/test/ui/feature-gates/feature-gate-optin-builtin-traits.stderr b/src/test/ui/feature-gates/feature-gate-optin-builtin-traits.stderr index e9090b78c78a1..1553d0531dc09 100644 --- a/src/test/ui/feature-gates/feature-gate-optin-builtin-traits.stderr +++ b/src/test/ui/feature-gates/feature-gate-optin-builtin-traits.stderr @@ -13,7 +13,7 @@ error[E0658]: negative trait bounds are not yet fully implemented; use marker ty LL | impl !AutoDummyTrait for DummyStruct {} | ^^^^^^^^^^^^^^^ | - = note: see issue #13231 for more information + = note: see issue #68318 for more information = help: add `#![feature(negative_impls)]` to the crate attributes to enable error: aborting due to 2 previous errors diff --git a/src/test/ui/syntax-trait-polarity-feature-gate.stderr b/src/test/ui/syntax-trait-polarity-feature-gate.stderr index 1c37106f13db0..3562deecbd522 100644 --- a/src/test/ui/syntax-trait-polarity-feature-gate.stderr +++ b/src/test/ui/syntax-trait-polarity-feature-gate.stderr @@ -4,7 +4,7 @@ error[E0658]: negative trait bounds are not yet fully implemented; use marker ty LL | impl !Send for TestType {} | ^^^^^ | - = note: see issue #13231 for more information + = note: see issue #68318 for more information = help: add `#![feature(negative_impls)]` to the crate attributes to enable error: aborting due to previous error From 68aa798436e7aefb13edb61698f1ac5c7fef14fe Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 13 Mar 2020 14:32:48 -0400 Subject: [PATCH 12/22] bump negative impls version to 1.44.0 --- src/librustc_feature/active.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs index 825323f55bd18..4dfa309540cad 100644 --- a/src/librustc_feature/active.rs +++ b/src/librustc_feature/active.rs @@ -555,7 +555,7 @@ declare_features! ( (active, const_eval_limit, "1.43.0", Some(67217), None), /// Allow negative trait implementations. - (active, negative_impls, "1.43.0", Some(68318), None), + (active, negative_impls, "1.44.0", Some(68318), None), // ------------------------------------------------------------------------- // feature-group-end: actual feature gates From 73a55009acf3783262f4201717a0290ff7bc35be Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 13 Mar 2020 14:33:37 -0400 Subject: [PATCH 13/22] convert to doc comments --- src/libcore/clone.rs | 4 ++-- src/libcore/marker.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index 629c197e37691..eb101fc72fd9e 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -219,7 +219,7 @@ mod impls { } } - // Shared references can be cloned, but mutable references *cannot*! + /// Shared references can be cloned, but mutable references *cannot*! #[stable(feature = "rust1", since = "1.0.0")] impl Clone for &T { #[inline] @@ -228,7 +228,7 @@ mod impls { } } - // Shared references can be cloned, but mutable references *cannot*! + /// Shared references can be cloned, but mutable references *cannot*! #[stable(feature = "rust1", since = "1.0.0")] #[cfg(not(bootstrap))] impl !Clone for &mut T {} diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 2b908f07af8da..549f80de36aa5 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -87,7 +87,7 @@ impl !Send for *mut T {} message = "the size for values of type `{Self}` cannot be known at compilation time", label = "doesn't have a size known at compile-time", note = "to learn more, visit " + ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>" )] #[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable #[cfg_attr(not(bootstrap), rustc_specialization_trait)] @@ -790,7 +790,7 @@ mod copy_impls { #[stable(feature = "rust1", since = "1.0.0")] impl Copy for *mut T {} - // Shared references can be copied, but mutable references *cannot*! + /// Shared references can be copied, but mutable references *cannot*! #[stable(feature = "rust1", since = "1.0.0")] impl Copy for &T {} } From f66284778a3ec9127b50179e917e3b07cbeaa6be Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 13 Mar 2020 14:34:58 -0400 Subject: [PATCH 14/22] move feature-gate-negative-impls test to traits/negative-impls --- .../ui/{ => traits/negative-impls}/feature-gate-negative_impls.rs | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/test/ui/{ => traits/negative-impls}/feature-gate-negative_impls.rs (100%) diff --git a/src/test/ui/feature-gate-negative_impls.rs b/src/test/ui/traits/negative-impls/feature-gate-negative_impls.rs similarity index 100% rename from src/test/ui/feature-gate-negative_impls.rs rename to src/test/ui/traits/negative-impls/feature-gate-negative_impls.rs From 7107f6e606ae1d935c2981842554758c4abf100a Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 13 Mar 2020 14:40:29 -0400 Subject: [PATCH 15/22] comment the `typeck-negative-impls-builtin` test --- .../ui/traits/negative-impls/typeck-negative-impls-builtin.rs | 3 +++ 1 file changed, 3 insertions(+) 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 index e326d3ab3f3cb..474e0381799bd 100644 --- a/src/test/ui/traits/negative-impls/typeck-negative-impls-builtin.rs +++ b/src/test/ui/traits/negative-impls/typeck-negative-impls-builtin.rs @@ -1,3 +1,6 @@ +// A simple test that we are able to create negative impls, when the +// feature gate is given. +// // run-pass #![feature(negative_impls)] From 644b9a0a94764fb0e30911bb66519c29430bbfad Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 13 Mar 2020 14:41:43 -0400 Subject: [PATCH 16/22] give the negative-impls-builtin test a more sensible name --- .../{typeck-negative-impls-builtin.rs => negative-impls-basic.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/test/ui/traits/negative-impls/{typeck-negative-impls-builtin.rs => negative-impls-basic.rs} (100%) diff --git a/src/test/ui/traits/negative-impls/typeck-negative-impls-builtin.rs b/src/test/ui/traits/negative-impls/negative-impls-basic.rs similarity index 100% rename from src/test/ui/traits/negative-impls/typeck-negative-impls-builtin.rs rename to src/test/ui/traits/negative-impls/negative-impls-basic.rs From f5c09ed344c97825561553f50a3ece17d97ed101 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 13 Mar 2020 14:43:23 -0400 Subject: [PATCH 17/22] move stderr file too --- .../negative-impls}/feature-gate-negative_impls.stderr | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/test/ui/{ => traits/negative-impls}/feature-gate-negative_impls.stderr (100%) diff --git a/src/test/ui/feature-gate-negative_impls.stderr b/src/test/ui/traits/negative-impls/feature-gate-negative_impls.stderr similarity index 100% rename from src/test/ui/feature-gate-negative_impls.stderr rename to src/test/ui/traits/negative-impls/feature-gate-negative_impls.stderr From b9e09d8f65b9750ecb2f8e7860a1df9633735865 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 13 Mar 2020 14:43:34 -0400 Subject: [PATCH 18/22] add test for negative specializes negative --- .../negative-impls/negative-specializes-negative.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/test/ui/traits/negative-impls/negative-specializes-negative.rs diff --git a/src/test/ui/traits/negative-impls/negative-specializes-negative.rs b/src/test/ui/traits/negative-impls/negative-specializes-negative.rs new file mode 100644 index 0000000000000..877c3e8af4f1a --- /dev/null +++ b/src/test/ui/traits/negative-impls/negative-specializes-negative.rs @@ -0,0 +1,13 @@ +#![feature(specialization)] +#![feature(negative_impls)] + +// Test a negative impl that "specializes" another negative impl. +// +// run-pass + +trait MyTrait {} + +impl !MyTrait for T {} +impl !MyTrait for u32 {} + +fn main() {} From c35801e160ed521b62348cfe6557ef7b56130282 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 19 Mar 2020 13:51:00 -0400 Subject: [PATCH 19/22] use slice pattern instead of calling `is_empty()` and `[0]` --- src/librustc_typeck/check/mod.rs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 98ff5ccc82f69..b282c7333d617 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -305,7 +305,11 @@ impl<'a, 'tcx> Expectation<'tcx> { match *self { ExpectHasType(ety) => { let ety = fcx.shallow_resolve(ety); - if !ety.is_ty_var() { ExpectHasType(ety) } else { NoExpectation } + if !ety.is_ty_var() { + ExpectHasType(ety) + } else { + NoExpectation + } } ExpectRvalueLikeUnsized(ety) => ExpectRvalueLikeUnsized(ety), _ => NoExpectation, @@ -1618,7 +1622,11 @@ fn check_opaque_for_inheriting_lifetimes(tcx: TyCtxt<'tcx>, def_id: DefId, span: impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueVisitor<'tcx> { fn visit_ty(&mut self, t: Ty<'tcx>) -> bool { debug!("check_opaque_for_inheriting_lifetimes: (visit_ty) t={:?}", t); - if t == self.opaque_identity_ty { false } else { t.super_visit_with(self) } + if t == self.opaque_identity_ty { + false + } else { + t.super_visit_with(self) + } } fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool { @@ -1978,8 +1986,8 @@ fn check_impl_items_against_trait<'tcx>( 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; + if let [first_item_ref, ..] = impl_item_refs { + let first_item_span = tcx.hir().impl_item(first_item_ref.id).span; struct_span_err!( tcx.sess, first_item_span, @@ -3767,8 +3775,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &'b self, self_ty: ty::TyVid, ) -> impl Iterator, traits::PredicateObligation<'tcx>)> - + Captures<'tcx> - + 'b { + + Captures<'tcx> + + 'b { // FIXME: consider using `sub_root_var` here so we // can see through subtyping. let ty_var_root = self.root_var(self_ty); From 011215b2c7fcd9df884de1012a5c67d8e96adc69 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 19 Mar 2020 13:55:46 -0400 Subject: [PATCH 20/22] pacify the merciless x.py fmt --- src/librustc_span/lib.rs | 42 ++++++-------------------------- src/librustc_typeck/check/mod.rs | 16 +++--------- 2 files changed, 11 insertions(+), 47 deletions(-) diff --git a/src/librustc_span/lib.rs b/src/librustc_span/lib.rs index 7a1aea15753b3..a0c4c90722d25 100644 --- a/src/librustc_span/lib.rs +++ b/src/librustc_span/lib.rs @@ -306,11 +306,7 @@ impl Span { /// Returns `self` if `self` is not the dummy span, and `other` otherwise. pub fn substitute_dummy(self, other: Span) -> Span { - if self.is_dummy() { - other - } else { - self - } + if self.is_dummy() { other } else { self } } /// Returns `true` if `self` fully encloses `other`. @@ -341,33 +337,21 @@ impl Span { pub fn trim_start(self, other: Span) -> Option { let span = self.data(); let other = other.data(); - if span.hi > other.hi { - Some(span.with_lo(cmp::max(span.lo, other.hi))) - } else { - None - } + if span.hi > other.hi { Some(span.with_lo(cmp::max(span.lo, other.hi))) } else { None } } /// Returns the source span -- this is either the supplied span, or the span for /// the macro callsite that expanded to it. pub fn source_callsite(self) -> Span { let expn_data = self.ctxt().outer_expn_data(); - if !expn_data.is_root() { - expn_data.call_site.source_callsite() - } else { - self - } + if !expn_data.is_root() { expn_data.call_site.source_callsite() } else { self } } /// The `Span` for the tokens in the previous macro expansion from which `self` was generated, /// if any. pub fn parent(self) -> Option { let expn_data = self.ctxt().outer_expn_data(); - if !expn_data.is_root() { - Some(expn_data.call_site) - } else { - None - } + if !expn_data.is_root() { Some(expn_data.call_site) } else { None } } /// Edition of the crate from which this span came. @@ -393,18 +377,10 @@ impl Span { pub fn source_callee(self) -> Option { fn source_callee(expn_data: ExpnData) -> ExpnData { let next_expn_data = expn_data.call_site.ctxt().outer_expn_data(); - if !next_expn_data.is_root() { - source_callee(next_expn_data) - } else { - expn_data - } + if !next_expn_data.is_root() { source_callee(next_expn_data) } else { expn_data } } let expn_data = self.ctxt().outer_expn_data(); - if !expn_data.is_root() { - Some(source_callee(expn_data)) - } else { - None - } + if !expn_data.is_root() { Some(source_callee(expn_data)) } else { None } } /// Checks if a span is "internal" to a macro in which `#[unstable]` @@ -1224,11 +1200,7 @@ impl SourceFile { let line_index = lookup_line(&self.lines[..], pos); assert!(line_index < self.lines.len() as isize); - if line_index >= 0 { - Some(line_index as usize) - } else { - None - } + if line_index >= 0 { Some(line_index as usize) } else { None } } pub fn line_bounds(&self, line_index: usize) -> (BytePos, BytePos) { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index b282c7333d617..91ab94bc684e2 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -305,11 +305,7 @@ impl<'a, 'tcx> Expectation<'tcx> { match *self { ExpectHasType(ety) => { let ety = fcx.shallow_resolve(ety); - if !ety.is_ty_var() { - ExpectHasType(ety) - } else { - NoExpectation - } + if !ety.is_ty_var() { ExpectHasType(ety) } else { NoExpectation } } ExpectRvalueLikeUnsized(ety) => ExpectRvalueLikeUnsized(ety), _ => NoExpectation, @@ -1622,11 +1618,7 @@ fn check_opaque_for_inheriting_lifetimes(tcx: TyCtxt<'tcx>, def_id: DefId, span: impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueVisitor<'tcx> { fn visit_ty(&mut self, t: Ty<'tcx>) -> bool { debug!("check_opaque_for_inheriting_lifetimes: (visit_ty) t={:?}", t); - if t == self.opaque_identity_ty { - false - } else { - t.super_visit_with(self) - } + if t == self.opaque_identity_ty { false } else { t.super_visit_with(self) } } fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool { @@ -3775,8 +3767,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &'b self, self_ty: ty::TyVid, ) -> impl Iterator, traits::PredicateObligation<'tcx>)> - + Captures<'tcx> - + 'b { + + Captures<'tcx> + + 'b { // FIXME: consider using `sub_root_var` here so we // can see through subtyping. let ty_var_root = self.root_var(self_ty); From 0d0702623fd0df96dfb6311b4a23bd0122d49b08 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 26 Mar 2020 07:41:26 -0400 Subject: [PATCH 21/22] wip pacify the merciless ui tests --- src/test/ui/privacy/private-in-public-non-principal.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/privacy/private-in-public-non-principal.stderr b/src/test/ui/privacy/private-in-public-non-principal.stderr index 05131135d490f..f7f8d71bdb5f2 100644 --- a/src/test/ui/privacy/private-in-public-non-principal.stderr +++ b/src/test/ui/privacy/private-in-public-non-principal.stderr @@ -9,7 +9,7 @@ LL | pub fn leak_dyn_nonprincipal() -> Box = note: for more information, see issue #34537 error: missing documentation for an associated function - --> $DIR/private-in-public-non-principal.rs:13:9 + --> $DIR/private-in-public-non-principal.rs:14:9 | LL | pub fn check_doc_lint() {} | ^^^^^^^^^^^^^^^^^^^^^^^ From 0b00c20465c2cacf34b4d3d1a5f4d0427f384cb2 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Thu, 26 Mar 2020 13:14:25 +0100 Subject: [PATCH 22/22] Reorganize a bit the code and add a comment --- src/librustc/ty/layout.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 91d39334acb78..dc34f07665475 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -907,12 +907,18 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let count = (niche_variants.end().as_u32() - niche_variants.start().as_u32() + 1) as u128; - if let Some((field_index, niche, (niche_start, niche_scalar))) = variants[i] + + // Find the field with the largest niche + let niche_candidate = variants[i] .iter() .enumerate() - .filter_map(|(i, &field)| Some((i, field.largest_niche.as_ref()?))) - .max_by_key(|(_, niche)| niche.available(dl)) - .and_then(|(i, niche)| Some((i, niche, niche.reserve(self, count)?))) + .filter_map(|(j, &field)| Some((j, field.largest_niche.as_ref()?))) + .max_by_key(|(_, niche)| niche.available(dl)); + + if let Some((field_index, niche, (niche_start, niche_scalar))) = + niche_candidate.and_then(|(field_index, niche)| { + Some((field_index, niche, niche.reserve(self, count)?)) + }) { let mut align = dl.aggregate_align; let st = variants