From 8e4886dd55266aca41943f7ce48863f61bcd250e Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Thu, 2 Jan 2020 20:28:21 -0500 Subject: [PATCH 1/7] Revert `const_err` lint checking of casts Reverts part of #67676 --- src/librustc_mir/transform/const_prop.rs | 70 ++----------------- .../ui/consts/const-prop-overflowing-casts.rs | 16 +++-- .../const-prop-overflowing-casts.stderr | 22 ------ .../ui/simd/simd-intrinsic-generic-cast.rs | 1 - 4 files changed, 18 insertions(+), 91 deletions(-) delete mode 100644 src/test/ui/consts/const-prop-overflowing-casts.stderr diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 3895cdf71a6..958239b76e4 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -12,10 +12,10 @@ use rustc::mir::visit::{ MutVisitor, MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor, }; use rustc::mir::{ - read_only, AggregateKind, BasicBlock, BinOp, Body, BodyAndCache, CastKind, ClearCrossCrate, - Constant, Local, LocalDecl, LocalKind, Location, Operand, Place, PlaceBase, - ReadOnlyBodyAndCache, Rvalue, SourceInfo, SourceScope, SourceScopeData, Statement, - StatementKind, Terminator, TerminatorKind, UnOp, RETURN_PLACE, + read_only, AggregateKind, BasicBlock, BinOp, Body, BodyAndCache, ClearCrossCrate, Constant, + Local, LocalDecl, LocalKind, Location, Operand, Place, PlaceBase, ReadOnlyBodyAndCache, Rvalue, + SourceInfo, SourceScope, SourceScopeData, Statement, StatementKind, Terminator, TerminatorKind, + UnOp, RETURN_PLACE, }; use rustc::ty::layout::{ HasDataLayout, HasTyCtxt, LayoutError, LayoutOf, Size, TargetDataLayout, TyLayout, @@ -29,9 +29,9 @@ use syntax::ast::Mutability; use crate::const_eval::error_to_const_error; use crate::interpret::{ - self, intern_const_alloc_recursive, truncate, AllocId, Allocation, Frame, ImmTy, Immediate, - InterpCx, LocalState, LocalValue, Memory, MemoryKind, OpTy, Operand as InterpOperand, PlaceTy, - Pointer, ScalarMaybeUndef, StackPopCleanup, + self, intern_const_alloc_recursive, AllocId, Allocation, Frame, ImmTy, Immediate, InterpCx, + LocalState, LocalValue, Memory, MemoryKind, OpTy, Operand as InterpOperand, PlaceTy, Pointer, + ScalarMaybeUndef, StackPopCleanup, }; use crate::rustc::ty::subst::Subst; use crate::transform::{MirPass, MirSource}; @@ -539,57 +539,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { Some(()) } - fn check_cast( - &mut self, - op: &Operand<'tcx>, - ty: Ty<'tcx>, - source_info: SourceInfo, - place_layout: TyLayout<'tcx>, - ) -> Option<()> { - if !ty.is_integral() || !op.ty(&self.local_decls, self.tcx).is_integral() { - return Some(()); - } - - let value = self.use_ecx(source_info, |this| { - this.ecx.read_immediate(this.ecx.eval_operand(op, None)?) - })?; - - // Do not try to read bits for ZSTs. This can occur when casting an enum with one variant - // to an integer. Such enums are represented as ZSTs but still have a discriminant value - // which can be casted. - if value.layout.is_zst() { - return Some(()); - } - - let value_size = value.layout.size; - let value_bits = value.to_scalar().and_then(|r| r.to_bits(value_size)); - if let Ok(value_bits) = value_bits { - let truncated = truncate(value_bits, place_layout.size); - if truncated != value_bits { - let scope = source_info.scope; - let lint_root = match &self.source_scopes[scope].local_data { - ClearCrossCrate::Set(data) => data.lint_root, - ClearCrossCrate::Clear => return None, - }; - self.tcx.lint_hir( - ::rustc::lint::builtin::CONST_ERR, - lint_root, - source_info.span, - &format!( - "truncating cast: the value {} requires {} bits but the target type is \ - only {} bits", - value_bits, - value_size.bits(), - place_layout.size.bits() - ), - ); - return None; - } - } - - Some(()) - } - fn const_prop( &mut self, rvalue: &Rvalue<'tcx>, @@ -651,11 +600,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } } - Rvalue::Cast(CastKind::Misc, op, ty) => { - trace!("checking Cast(Misc, {:?}, {:?})", op, ty); - self.check_cast(op, ty, source_info, place_layout)?; - } - _ => {} } diff --git a/src/test/ui/consts/const-prop-overflowing-casts.rs b/src/test/ui/consts/const-prop-overflowing-casts.rs index 11a04611487..8cc5b98250b 100644 --- a/src/test/ui/consts/const-prop-overflowing-casts.rs +++ b/src/test/ui/consts/const-prop-overflowing-casts.rs @@ -1,9 +1,15 @@ -// build-fail -// ignore-tidy-linelength +// check-pass + +enum Foo { + Bar = -42, + Baz = 42, +} fn main() { let _ = 0u8 as u32; - let _ = (1u32 << 31) as u16; //~ ERROR truncating cast: the value 2147483648 requires 32 bits but the target type is only 16 bits - let _ = (1u16 << 15) as u8; //~ ERROR truncating cast: the value 32768 requires 16 bits but the target type is only 8 bits - let _ = (!0u16) as u8; //~ ERROR truncating cast: the value 65535 requires 16 bits but the target type is only 8 bits + let _ = (1u32 << 31) as u16; + let _ = (1u16 << 15) as u8; + let _ = (!0u16) as u8; + let _ = (-1i16) as i8; + let _ = (Foo::Bar) as i8; } diff --git a/src/test/ui/consts/const-prop-overflowing-casts.stderr b/src/test/ui/consts/const-prop-overflowing-casts.stderr deleted file mode 100644 index af4e2c7005a..00000000000 --- a/src/test/ui/consts/const-prop-overflowing-casts.stderr +++ /dev/null @@ -1,22 +0,0 @@ -error: truncating cast: the value 2147483648 requires 32 bits but the target type is only 16 bits - --> $DIR/const-prop-overflowing-casts.rs:6:13 - | -LL | let _ = (1u32 << 31) as u16; - | ^^^^^^^^^^^^^^^^^^^ - | - = note: `#[deny(const_err)]` on by default - -error: truncating cast: the value 32768 requires 16 bits but the target type is only 8 bits - --> $DIR/const-prop-overflowing-casts.rs:7:13 - | -LL | let _ = (1u16 << 15) as u8; - | ^^^^^^^^^^^^^^^^^^ - -error: truncating cast: the value 65535 requires 16 bits but the target type is only 8 bits - --> $DIR/const-prop-overflowing-casts.rs:8:13 - | -LL | let _ = (!0u16) as u8; - | ^^^^^^^^^^^^^ - -error: aborting due to 3 previous errors - diff --git a/src/test/ui/simd/simd-intrinsic-generic-cast.rs b/src/test/ui/simd/simd-intrinsic-generic-cast.rs index b81a76851d3..15f232e2c0f 100644 --- a/src/test/ui/simd/simd-intrinsic-generic-cast.rs +++ b/src/test/ui/simd/simd-intrinsic-generic-cast.rs @@ -4,7 +4,6 @@ #![feature(repr_simd, platform_intrinsics, concat_idents, test)] #![allow(non_camel_case_types)] -#![allow(const_err)] // the test macro casts i32s to i8 and u8 which causes lots of warnings extern crate test; From e589358210862cdbb34c124bcc95a67afe09135c Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Thu, 2 Jan 2020 19:02:06 -0500 Subject: [PATCH 2/7] improve generic `Drop` error messages - Use the span of the predicate - Use the def's description instead of "struct/enum" (notably incorrect for unions) - Align formatting with other error messages --- src/librustc_typeck/check/dropck.rs | 34 +++---- src/test/ui/issues/issue-17959.rs | 2 +- src/test/ui/issues/issue-17959.stderr | 16 +--- src/test/ui/issues/issue-38868.stderr | 4 +- src/test/ui/reject-specialized-drops-8142.rs | 27 ++++-- .../ui/reject-specialized-drops-8142.stderr | 96 ++++++++++++------- 6 files changed, 110 insertions(+), 69 deletions(-) diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 6f2d529bc34..004fce7e35b 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -47,7 +47,6 @@ pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), Erro ensure_drop_predicates_are_implied_by_item_defn( tcx, - drop_impl_did, dtor_predicates, adt_def.did, self_to_impl_substs, @@ -95,16 +94,23 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>( } Err(_) => { let item_span = tcx.def_span(self_type_did); + let self_descr = tcx + .def_kind(self_type_did) + .map(|kind| kind.descr(self_type_did)) + .unwrap_or("type"); struct_span_err!( tcx.sess, drop_impl_span, E0366, - "Implementations of Drop cannot be specialized" + "`Drop` impls cannot be specialized" ) .span_note( item_span, - "Use same sequence of generic type and region \ - parameters that is on the struct/enum definition", + &format!( + "use the same sequence of generic type, lifetime and const parameters \ + as the {} definition", + self_descr, + ), ) .emit(); return Err(ErrorReported); @@ -143,7 +149,6 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>( /// implied by assuming the predicates attached to self_type_did. fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( tcx: TyCtxt<'tcx>, - drop_impl_did: DefId, dtor_predicates: ty::GenericPredicates<'tcx>, self_type_did: DefId, self_to_impl_substs: SubstsRef<'tcx>, @@ -187,8 +192,6 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( let self_type_hir_id = tcx.hir().as_local_hir_id(self_type_did).unwrap(); - let drop_impl_span = tcx.def_span(drop_impl_did); - // We can assume the predicates attached to struct/enum definition // hold. let generic_assumptions = tcx.predicates_of(self_type_did); @@ -205,7 +208,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( // just to look for all the predicates directly. assert_eq!(dtor_predicates.parent, None); - for (predicate, _) in dtor_predicates.predicates { + for (predicate, predicate_sp) in dtor_predicates.predicates { // (We do not need to worry about deep analysis of type // expressions etc because the Drop impls are already forced // to take on a structure that is roughly an alpha-renaming of @@ -241,18 +244,17 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( if !assumptions_in_impl_context.iter().any(predicate_matches_closure) { let item_span = tcx.hir().span(self_type_hir_id); + let self_descr = + tcx.def_kind(self_type_did).map(|kind| kind.descr(self_type_did)).unwrap_or("type"); struct_span_err!( tcx.sess, - drop_impl_span, + *predicate_sp, E0367, - "The requirement `{}` is added only by the Drop impl.", - predicate - ) - .span_note( - item_span, - "The same requirement must be part of \ - the struct/enum definition", + "`Drop` impl requires `{}` but the {} it is implemented for does not", + predicate, + self_descr, ) + .span_note(item_span, "the implementor must specify the same requirement") .emit(); result = Err(ErrorReported); } diff --git a/src/test/ui/issues/issue-17959.rs b/src/test/ui/issues/issue-17959.rs index 73865ae2d2e..01416a0d79e 100644 --- a/src/test/ui/issues/issue-17959.rs +++ b/src/test/ui/issues/issue-17959.rs @@ -9,7 +9,7 @@ struct G { } impl Drop for G { -//~^ ERROR: The requirement `T: std::marker::Sized` is added only by the Drop impl. [E0367] +//~^ ERROR `Drop` impl requires `T: std::marker::Sized` fn drop(&mut self) { if !self._ptr.is_null() { } diff --git a/src/test/ui/issues/issue-17959.stderr b/src/test/ui/issues/issue-17959.stderr index de742e48aea..29d32c1f3ce 100644 --- a/src/test/ui/issues/issue-17959.stderr +++ b/src/test/ui/issues/issue-17959.stderr @@ -1,16 +1,10 @@ -error[E0367]: The requirement `T: std::marker::Sized` is added only by the Drop impl. - --> $DIR/issue-17959.rs:11:1 +error[E0367]: `Drop` impl requires `T: std::marker::Sized` but the struct it is implemented for does not + --> $DIR/issue-17959.rs:11:6 | -LL | / impl Drop for G { -LL | | -LL | | fn drop(&mut self) { -LL | | if !self._ptr.is_null() { -LL | | } -LL | | } -LL | | } - | |_^ +LL | impl Drop for G { + | ^ | -note: The same requirement must be part of the struct/enum definition +note: the implementor must specify the same requirement --> $DIR/issue-17959.rs:7:1 | LL | / struct G { diff --git a/src/test/ui/issues/issue-38868.stderr b/src/test/ui/issues/issue-38868.stderr index fe932c744bf..10d1e7c4e66 100644 --- a/src/test/ui/issues/issue-38868.stderr +++ b/src/test/ui/issues/issue-38868.stderr @@ -1,4 +1,4 @@ -error[E0366]: Implementations of Drop cannot be specialized +error[E0366]: `Drop` impls cannot be specialized --> $DIR/issue-38868.rs:5:1 | LL | / impl Drop for List { @@ -8,7 +8,7 @@ LL | | } LL | | } | |_^ | -note: Use same sequence of generic type and region parameters that is on the struct/enum definition +note: use the same sequence of generic type, lifetime and const parameters as the struct definition --> $DIR/issue-38868.rs:1:1 | LL | / pub struct List { diff --git a/src/test/ui/reject-specialized-drops-8142.rs b/src/test/ui/reject-specialized-drops-8142.rs index 655b42f5f8f..d7fec8802f0 100644 --- a/src/test/ui/reject-specialized-drops-8142.rs +++ b/src/test/ui/reject-specialized-drops-8142.rs @@ -1,5 +1,5 @@ // Issue 8142: Test that Drop impls cannot be specialized beyond the -// predicates attached to the struct/enum definition itself. +// predicates attached to the type definition itself. trait Bound { fn foo(&self) { } } struct K<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 } @@ -16,12 +16,16 @@ struct U; struct V { x: *const Tva, y: *const Tvb } struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 } +enum Enum { Variant(T) } +struct TupleStruct(T); +union Union { f: T } + impl<'al,'adds_bnd:'al> Drop for K<'al,'adds_bnd> { // REJECT - //~^ ERROR The requirement `'adds_bnd : 'al` is added only by the Drop impl. + //~^ ERROR `Drop` impl requires `'adds_bnd : 'al` fn drop(&mut self) { } } impl<'al,'adds_bnd> Drop for L<'al,'adds_bnd> where 'adds_bnd:'al { // REJECT - //~^ ERROR The requirement `'adds_bnd : 'al` is added only by the Drop impl. + //~^ ERROR `Drop` impl requires `'adds_bnd : 'al` fn drop(&mut self) { } } impl<'ml> Drop for M<'ml> { fn drop(&mut self) { } } // ACCEPT @@ -34,13 +38,13 @@ impl Drop for N<'static> { fn drop(&mut self) { } } // RE impl Drop for O { fn drop(&mut self) { } } // ACCEPT impl Drop for P { fn drop(&mut self) { } } // REJECT -//~^ ERROR Implementations of Drop cannot be specialized +//~^ ERROR `Drop` impls cannot be specialized impl Drop for Q { fn drop(&mut self) { } } // REJECT -//~^ ERROR The requirement `AddsBnd: Bound` is added only by the Drop impl. +//~^ ERROR `Drop` impl requires `AddsBnd: Bound` impl<'rbnd,AddsRBnd:'rbnd> Drop for R { fn drop(&mut self) { } } // REJECT -//~^ ERROR The requirement `AddsRBnd : 'rbnd` is added only by the Drop impl. +//~^ ERROR `Drop` impl requires `AddsRBnd : 'rbnd` impl Drop for S { fn drop(&mut self) { } } // ACCEPT @@ -49,9 +53,18 @@ impl<'t,Bt:'t> Drop for T<'t,Bt> { fn drop(&mut self) { } } // ACCEPT impl Drop for U { fn drop(&mut self) { } } // ACCEPT impl Drop for V { fn drop(&mut self) { } } // REJECT -//~^ ERROR Implementations of Drop cannot be specialized +//~^ ERROR `Drop` impls cannot be specialized impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT //~^ ERROR cannot infer an appropriate lifetime for lifetime parameter `'lw` +impl Drop for Enum { fn drop(&mut self) { } } // REJECT +//~^ ERROR `Drop` impl requires `AddsBnd: Bound` + +impl Drop for TupleStruct { fn drop(&mut self) { } } // REJECT +//~^ ERROR `Drop` impl requires `AddsBnd: Bound` + +impl Drop for Union { fn drop(&mut self) { } } // REJECT +//~^ ERROR `Drop` impl requires `AddsBnd: Bound` + pub fn main() { } diff --git a/src/test/ui/reject-specialized-drops-8142.stderr b/src/test/ui/reject-specialized-drops-8142.stderr index 527babb0120..14618df90cb 100644 --- a/src/test/ui/reject-specialized-drops-8142.stderr +++ b/src/test/ui/reject-specialized-drops-8142.stderr @@ -1,33 +1,41 @@ -error[E0367]: The requirement `'adds_bnd : 'al` is added only by the Drop impl. - --> $DIR/reject-specialized-drops-8142.rs:19:1 +error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the union it is implemented for does not + --> $DIR/reject-specialized-drops-8142.rs:67:21 | -LL | / impl<'al,'adds_bnd:'al> Drop for K<'al,'adds_bnd> { // REJECT -LL | | -LL | | fn drop(&mut self) { } } - | |____________________________^ +LL | impl Drop for Union { fn drop(&mut self) { } } // REJECT + | ^^^^^ | -note: The same requirement must be part of the struct/enum definition +note: the implementor must specify the same requirement + --> $DIR/reject-specialized-drops-8142.rs:21:1 + | +LL | union Union { f: T } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0367]: `Drop` impl requires `'adds_bnd : 'al` but the struct it is implemented for does not + --> $DIR/reject-specialized-drops-8142.rs:23:20 + | +LL | impl<'al,'adds_bnd:'al> Drop for K<'al,'adds_bnd> { // REJECT + | ^^^ + | +note: the implementor must specify the same requirement --> $DIR/reject-specialized-drops-8142.rs:5:1 | LL | struct K<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0367]: The requirement `'adds_bnd : 'al` is added only by the Drop impl. - --> $DIR/reject-specialized-drops-8142.rs:23:1 +error[E0367]: `Drop` impl requires `'adds_bnd : 'al` but the struct it is implemented for does not + --> $DIR/reject-specialized-drops-8142.rs:27:67 | -LL | / impl<'al,'adds_bnd> Drop for L<'al,'adds_bnd> where 'adds_bnd:'al { // REJECT -LL | | -LL | | fn drop(&mut self) { } } - | |____________________________^ +LL | impl<'al,'adds_bnd> Drop for L<'al,'adds_bnd> where 'adds_bnd:'al { // REJECT + | ^^^ | -note: The same requirement must be part of the struct/enum definition +note: the implementor must specify the same requirement --> $DIR/reject-specialized-drops-8142.rs:6:1 | LL | struct L<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0308]: mismatched types - --> $DIR/reject-specialized-drops-8142.rs:29:1 + --> $DIR/reject-specialized-drops-8142.rs:33:1 | LL | impl Drop for N<'static> { fn drop(&mut self) { } } // REJECT | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch @@ -41,56 +49,56 @@ LL | struct N<'n> { x: &'n i8 } | ^^ = note: ...does not necessarily outlive the static lifetime -error[E0366]: Implementations of Drop cannot be specialized - --> $DIR/reject-specialized-drops-8142.rs:36:1 +error[E0366]: `Drop` impls cannot be specialized + --> $DIR/reject-specialized-drops-8142.rs:40:1 | LL | impl Drop for P { fn drop(&mut self) { } } // REJECT | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: Use same sequence of generic type and region parameters that is on the struct/enum definition +note: use the same sequence of generic type, lifetime and const parameters as the struct definition --> $DIR/reject-specialized-drops-8142.rs:10:1 | LL | struct P { x: *const Tp } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0367]: The requirement `AddsBnd: Bound` is added only by the Drop impl. - --> $DIR/reject-specialized-drops-8142.rs:39:1 +error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the struct it is implemented for does not + --> $DIR/reject-specialized-drops-8142.rs:43:14 | LL | impl Drop for Q { fn drop(&mut self) { } } // REJECT - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^ | -note: The same requirement must be part of the struct/enum definition +note: the implementor must specify the same requirement --> $DIR/reject-specialized-drops-8142.rs:11:1 | LL | struct Q { x: *const Tq } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0367]: The requirement `AddsRBnd : 'rbnd` is added only by the Drop impl. - --> $DIR/reject-specialized-drops-8142.rs:42:1 +error[E0367]: `Drop` impl requires `AddsRBnd : 'rbnd` but the struct it is implemented for does not + --> $DIR/reject-specialized-drops-8142.rs:46:21 | LL | impl<'rbnd,AddsRBnd:'rbnd> Drop for R { fn drop(&mut self) { } } // REJECT - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^ | -note: The same requirement must be part of the struct/enum definition +note: the implementor must specify the same requirement --> $DIR/reject-specialized-drops-8142.rs:12:1 | LL | struct R { x: *const Tr } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0366]: Implementations of Drop cannot be specialized - --> $DIR/reject-specialized-drops-8142.rs:51:1 +error[E0366]: `Drop` impls cannot be specialized + --> $DIR/reject-specialized-drops-8142.rs:55:1 | LL | impl Drop for V { fn drop(&mut self) { } } // REJECT | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: Use same sequence of generic type and region parameters that is on the struct/enum definition +note: use the same sequence of generic type, lifetime and const parameters as the struct definition --> $DIR/reject-specialized-drops-8142.rs:16:1 | LL | struct V { x: *const Tva, y: *const Tvb } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'lw` due to conflicting requirements - --> $DIR/reject-specialized-drops-8142.rs:54:1 + --> $DIR/reject-specialized-drops-8142.rs:58:1 | LL | impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -106,14 +114,38 @@ note: ...but the lifetime must also be valid for the lifetime `'l2` as defined o LL | struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 } | ^^^ note: ...so that the types are compatible - --> $DIR/reject-specialized-drops-8142.rs:54:1 + --> $DIR/reject-specialized-drops-8142.rs:58:1 | LL | impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: expected `W<'l1, 'l2>` found `W<'_, '_>` -error: aborting due to 8 previous errors +error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the enum it is implemented for does not + --> $DIR/reject-specialized-drops-8142.rs:61:14 + | +LL | impl Drop for Enum { fn drop(&mut self) { } } // REJECT + | ^^^^^ + | +note: the implementor must specify the same requirement + --> $DIR/reject-specialized-drops-8142.rs:19:1 + | +LL | enum Enum { Variant(T) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the struct it is implemented for does not + --> $DIR/reject-specialized-drops-8142.rs:64:14 + | +LL | impl Drop for TupleStruct { fn drop(&mut self) { } } // REJECT + | ^^^^^ + | +note: the implementor must specify the same requirement + --> $DIR/reject-specialized-drops-8142.rs:20:1 + | +LL | struct TupleStruct(T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 11 previous errors Some errors have detailed explanations: E0308, E0366, E0367, E0495. For more information about an error, try `rustc --explain E0308`. From e9990bc65f8e44fd2843478ac685bb79c0a50ed0 Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Thu, 2 Jan 2020 22:24:21 -0500 Subject: [PATCH 3/7] clarify that `Drop` can be implemented for enums and unions too --- src/librustc_typeck/coherence/builtin.rs | 47 ++++++++------------ src/test/ui/dropck/drop-on-non-struct.rs | 7 ++- src/test/ui/dropck/drop-on-non-struct.stderr | 14 ++++-- src/test/ui/error-codes/E0117.rs | 3 +- src/test/ui/error-codes/E0117.stderr | 4 +- src/test/ui/error-codes/E0120.stderr | 4 +- src/test/ui/issues/issue-41974.stderr | 4 +- 7 files changed, 41 insertions(+), 42 deletions(-) diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index 7f7e21838d2..7e016cf7e9a 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -13,7 +13,6 @@ use rustc::ty::util::CopyImplementationError; use rustc::ty::TypeFoldable; use rustc::ty::{self, Ty, TyCtxt}; -use hir::Node; use rustc::hir::def_id::DefId; use rustc::hir::{self, ItemKind}; @@ -51,35 +50,25 @@ impl<'tcx> Checker<'tcx> { } fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: DefId) { - if let ty::Adt(..) = tcx.type_of(impl_did).kind { - /* do nothing */ - } else { - // Destructors only work on nominal types. - if let Some(impl_hir_id) = tcx.hir().as_local_hir_id(impl_did) { - if let Some(Node::Item(item)) = tcx.hir().find(impl_hir_id) { - let span = match item.kind { - ItemKind::Impl(.., ref ty, _) => ty.span, - _ => item.span, - }; - struct_span_err!( - tcx.sess, - span, - E0120, - "the Drop trait may only be implemented on \ - structures" - ) - .span_label(span, "implementing Drop requires a struct") - .emit(); - } else { - bug!("didn't find impl in ast map"); - } - } else { - bug!( - "found external impl of Drop trait on \ - something other than a struct" - ); - } + // Destructors only work on nominal types. + if let ty::Adt(..) | ty::Error = tcx.type_of(impl_did).kind { + return; } + + let impl_hir_id = tcx.hir().as_local_hir_id(impl_did).expect("foreign Drop impl on non-ADT"); + let sp = match tcx.hir().expect_item(impl_hir_id).kind { + ItemKind::Impl(.., ty, _) => ty.span, + _ => bug!("expected Drop impl item"), + }; + + struct_span_err!( + tcx.sess, + sp, + E0120, + "the `Drop` trait may only be implemented for structs, enums, and unions", + ) + .span_label(sp, "must be a struct, enum, or union") + .emit(); } fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: DefId) { diff --git a/src/test/ui/dropck/drop-on-non-struct.rs b/src/test/ui/dropck/drop-on-non-struct.rs index 259cdf40ae5..ef5e18126dc 100644 --- a/src/test/ui/dropck/drop-on-non-struct.rs +++ b/src/test/ui/dropck/drop-on-non-struct.rs @@ -1,10 +1,15 @@ impl<'a> Drop for &'a mut isize { - //~^ ERROR the Drop trait may only be implemented on structures + //~^ ERROR the `Drop` trait may only be implemented for structs, enums, and unions //~^^ ERROR E0117 fn drop(&mut self) { println!("kaboom"); } } +impl Drop for Nonexistent { + //~^ ERROR cannot find type `Nonexistent` + fn drop(&mut self) { } +} + fn main() { } diff --git a/src/test/ui/dropck/drop-on-non-struct.stderr b/src/test/ui/dropck/drop-on-non-struct.stderr index a374b0d2636..3991c44f2ed 100644 --- a/src/test/ui/dropck/drop-on-non-struct.stderr +++ b/src/test/ui/dropck/drop-on-non-struct.stderr @@ -1,8 +1,14 @@ -error[E0120]: the Drop trait may only be implemented on structures +error[E0412]: cannot find type `Nonexistent` in this scope + --> $DIR/drop-on-non-struct.rs:9:15 + | +LL | impl Drop for Nonexistent { + | ^^^^^^^^^^^ not found in this scope + +error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions --> $DIR/drop-on-non-struct.rs:1:19 | LL | impl<'a> Drop for &'a mut isize { - | ^^^^^^^^^^^^^ implementing Drop requires a struct + | ^^^^^^^^^^^^^ must be a struct, enum, or union error[E0117]: only traits defined in the current crate can be implemented for arbitrary types --> $DIR/drop-on-non-struct.rs:1:1 @@ -15,7 +21,7 @@ LL | impl<'a> Drop for &'a mut isize { | = note: define and implement a trait or new type instead -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0117, E0120. +Some errors have detailed explanations: E0117, E0120, E0412. For more information about an error, try `rustc --explain E0117`. diff --git a/src/test/ui/error-codes/E0117.rs b/src/test/ui/error-codes/E0117.rs index 18dd809f3ff..dbbac514801 100644 --- a/src/test/ui/error-codes/E0117.rs +++ b/src/test/ui/error-codes/E0117.rs @@ -1,6 +1,5 @@ impl Drop for u32 {} //~ ERROR E0117 -//~| ERROR the Drop trait may only be implemented on structures -//~| implementing Drop requires a struct +//~| ERROR the `Drop` trait may only be implemented for structs, enums, and unions fn main() { } diff --git a/src/test/ui/error-codes/E0117.stderr b/src/test/ui/error-codes/E0117.stderr index f0cfc8a2533..b48a1d8e50d 100644 --- a/src/test/ui/error-codes/E0117.stderr +++ b/src/test/ui/error-codes/E0117.stderr @@ -1,8 +1,8 @@ -error[E0120]: the Drop trait may only be implemented on structures +error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions --> $DIR/E0117.rs:1:15 | LL | impl Drop for u32 {} - | ^^^ implementing Drop requires a struct + | ^^^ must be a struct, enum, or union error[E0117]: only traits defined in the current crate can be implemented for arbitrary types --> $DIR/E0117.rs:1:1 diff --git a/src/test/ui/error-codes/E0120.stderr b/src/test/ui/error-codes/E0120.stderr index 68ca7d800d5..6c306455e42 100644 --- a/src/test/ui/error-codes/E0120.stderr +++ b/src/test/ui/error-codes/E0120.stderr @@ -1,8 +1,8 @@ -error[E0120]: the Drop trait may only be implemented on structures +error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions --> $DIR/E0120.rs:3:15 | LL | impl Drop for dyn MyTrait { - | ^^^^^^^^^^^ implementing Drop requires a struct + | ^^^^^^^^^^^ must be a struct, enum, or union error: aborting due to previous error diff --git a/src/test/ui/issues/issue-41974.stderr b/src/test/ui/issues/issue-41974.stderr index 9f164822dea..d082e0a6b5d 100644 --- a/src/test/ui/issues/issue-41974.stderr +++ b/src/test/ui/issues/issue-41974.stderr @@ -9,11 +9,11 @@ LL | impl Drop for T where T: A { where T: ?Sized; = note: downstream crates may implement trait `A` for type `std::boxed::Box<_>` -error[E0120]: the Drop trait may only be implemented on structures +error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions --> $DIR/issue-41974.rs:7:18 | LL | impl Drop for T where T: A { - | ^ implementing Drop requires a struct + | ^ must be a struct, enum, or union error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) --> $DIR/issue-41974.rs:7:6 From ec64bbbe07df8e502b64e449be86c1613717c0c7 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 3 Jan 2020 17:42:44 +0100 Subject: [PATCH 4/7] Small error explanations cleanup --- src/librustc_error_codes/error_codes/E0136.md | 7 +++++-- src/librustc_error_codes/error_codes/E0161.md | 3 +-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0136.md b/src/librustc_error_codes/error_codes/E0136.md index c0e8c7e061c..b91b52c074c 100644 --- a/src/librustc_error_codes/error_codes/E0136.md +++ b/src/librustc_error_codes/error_codes/E0136.md @@ -1,5 +1,4 @@ -A binary can only have one entry point, and by default that entry point is the -function `main()`. If there are multiple such functions, please rename one. +More than one `main` function was found. Erroneous code example: @@ -14,3 +13,7 @@ fn main() { // error! // ... } ``` + +A binary can only have one entry point, and by default that entry point is the +`main()` function. If there are multiple instances of this function, please +rename one of them. diff --git a/src/librustc_error_codes/error_codes/E0161.md b/src/librustc_error_codes/error_codes/E0161.md index 26269db2327..c2e2f0240f4 100644 --- a/src/librustc_error_codes/error_codes/E0161.md +++ b/src/librustc_error_codes/error_codes/E0161.md @@ -1,5 +1,4 @@ -A value was moved. However, its size was not known at compile time, and only -values of a known size can be moved. +A value was moved whose size was not known at compile time. Erroneous code example: From aab4276477e84545641b1cf69b43612efa6bf702 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 3 Jan 2020 17:42:56 +0100 Subject: [PATCH 5/7] Clean up E0164 explanation --- src/librustc_error_codes/error_codes/E0164.md | 38 ++++++++++++++----- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0164.md b/src/librustc_error_codes/error_codes/E0164.md index b41ce6fad8e..8eb5ace4fe4 100644 --- a/src/librustc_error_codes/error_codes/E0164.md +++ b/src/librustc_error_codes/error_codes/E0164.md @@ -1,24 +1,44 @@ -This error means that an attempt was made to match a struct type enum -variant as a non-struct type: +Something which is neither a tuple struct nor a tuple variant was used as a +pattern. + +Erroneous code example: ```compile_fail,E0164 -enum Foo { B { i: u32 } } +enum A { + B, + C, +} -fn bar(foo: Foo) -> u32 { +impl A { + fn new() {} +} + +fn bar(foo: A) { match foo { - Foo::B(i) => i, // error E0164 + A::new() => (), // error! + _ => {} } } ``` -Try using `{}` instead: +This error means that an attempt was made to match something which is neither a +tuple struct nor a tuple variant. Only these two elements are allowed as +pattern: ``` -enum Foo { B { i: u32 } } +enum A { + B, + C, +} -fn bar(foo: Foo) -> u32 { +impl A { + fn new() {} +} + +fn bar(foo: A) { match foo { - Foo::B{i} => i, + A::B => (), // ok! + _ => {} } } ``` From 83333fe85b25c77f35b79bf06cde69b889558dca Mon Sep 17 00:00:00 2001 From: Oliver Middleton Date: Fri, 3 Jan 2020 23:41:11 +0000 Subject: [PATCH 6/7] Remove unused `#[link_name = "m"]` attributes These were perhaps supposed to be `#[link(name = "m")]` but linking libm should be handled by the libc crate anyway. --- src/libstd/sys/unix/cmath.rs | 1 - src/libstd/sys/vxworks/cmath.rs | 1 - src/libstd/sys/windows/cmath.rs | 1 - 3 files changed, 3 deletions(-) diff --git a/src/libstd/sys/unix/cmath.rs b/src/libstd/sys/unix/cmath.rs index 2916ebe4440..f327b69fc75 100644 --- a/src/libstd/sys/unix/cmath.rs +++ b/src/libstd/sys/unix/cmath.rs @@ -2,7 +2,6 @@ use libc::{c_double, c_float}; -#[link_name = "m"] extern "C" { pub fn acos(n: c_double) -> c_double; pub fn acosf(n: c_float) -> c_float; diff --git a/src/libstd/sys/vxworks/cmath.rs b/src/libstd/sys/vxworks/cmath.rs index 2916ebe4440..f327b69fc75 100644 --- a/src/libstd/sys/vxworks/cmath.rs +++ b/src/libstd/sys/vxworks/cmath.rs @@ -2,7 +2,6 @@ use libc::{c_double, c_float}; -#[link_name = "m"] extern "C" { pub fn acos(n: c_double) -> c_double; pub fn acosf(n: c_float) -> c_float; diff --git a/src/libstd/sys/windows/cmath.rs b/src/libstd/sys/windows/cmath.rs index 7c5bfa1bd06..6f5d40b494f 100644 --- a/src/libstd/sys/windows/cmath.rs +++ b/src/libstd/sys/windows/cmath.rs @@ -2,7 +2,6 @@ use libc::{c_double, c_float}; -#[link_name = "m"] extern "C" { pub fn acos(n: c_double) -> c_double; pub fn asin(n: c_double) -> c_double; From 062cd789588dfc493ef8c69378379024d3670f75 Mon Sep 17 00:00:00 2001 From: Dylan DPC Date: Sat, 4 Jan 2020 11:41:35 +0530 Subject: [PATCH 7/7] Update E0164.md --- src/librustc_error_codes/error_codes/E0164.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_error_codes/error_codes/E0164.md b/src/librustc_error_codes/error_codes/E0164.md index 8eb5ace4fe4..48bb6f4b382 100644 --- a/src/librustc_error_codes/error_codes/E0164.md +++ b/src/librustc_error_codes/error_codes/E0164.md @@ -22,7 +22,7 @@ fn bar(foo: A) { ``` This error means that an attempt was made to match something which is neither a -tuple struct nor a tuple variant. Only these two elements are allowed as +tuple struct nor a tuple variant. Only these two elements are allowed as a pattern: ```