Change:
(imported from improperly closed bug ) As suggested by Until is done, we really should lint for this scenario.
triage: P-low
oops. triage: P-high (but nonetheless not 1.0)
I feel like this should be stronger than a medium-priority lint. I feel like rustc should reject programs that attempt to on a struct, for as long as that changes the size of that struct. In particular, not fixing this by 1.0 would foreclose the ability to change the drop flag after 1.0, since that would change the size / ABI of structs, right? Or is ABI stability not a guarantee of ?
Yeah this label got auto renamed. I'm up'ing the priority
triage: P-high I'll assign to self too
( I'm pretty confident we could fix this post 1.0, e.g. adding new warnings is allowed, and the representation issue would be "just a bug to be fixed." Nonetheless I I do I do want I do want to fix.)

Discussion:
} } } <ins> /// Lints for attempts to impl Drop on types that have `#[repr(C)]` /// attribute (see issue #24585). #[derive(Copy, Clone)] pub struct DropWithReprExtern; declare_lint! { DROP_WITH_REPR_EXTERN, Warn, "use of #[repr(C)] on a type that implements Drop" } impl LintPass for DropWithReprExtern { fn get_lints(&self) -> LintArray { lint_array!(DROP_WITH_REPR_EXTERN) } fn check_crate(&mut self, ctx: &Context, _: &ast::Crate) { for dtor_did in ctx.tcx.destructors.borrow().iter() { let (drop_impl_did, dtor_self_type) = if dtor_did.krate == ast::LOCAL_CRATE { let impl_did = ctx.tcx.map.get_parent_did(dtor_did.node); let ty = ty::lookup_item_type(ctx.tcx, impl_did).ty; (impl_did, ty) } else { continue; }; match dtor_self_type.sty { ty::ty_enum(self_type_did, _) | ty::ty_struct(self_type_did, _) | ty::ty_closure(self_type_did, _) => { let hints = ty::lookup_repr_hints(ctx.tcx, self_type_did); if hints.iter().any(|attr| *attr == attr::ReprExtern) && ty::ty_dtor(ctx.tcx, self_type_did).has_drop_flag() { let drop_impl_span = ctx.tcx.map.def_id_span(drop_impl_did, codemap::DUMMY_SP); let self_defn_span = ctx.tcx.map.def_id_span(self_type_did, codemap::DUMMY_SP); ctx.span_lint(DROP_WITH_REPR_EXTERN, drop_impl_span, "implementing Drop adds hidden state to types,  possibly conflicting with `#[repr(C)]`"); // FIXME #19668: could be span_lint_note instead of manual guard. if ctx.current_level(DROP_WITH_REPR_EXTERN) != Level::Allow { ctx.sess().span_note(self_defn_span, "the `#[repr(C)]` attribute is attached here"); } } } _ => {} } } } } </ins>

UnconditionalRecursion, InvalidNoMangleItems, PluginAsLibrary, <ins> DropWithReprExtern, </ins> ); add_builtin_with_new!(sess,

<ins> // Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. // Check we reject structs that mix a `Drop` impl with `#[repr(C)]`. // // As a special case, also check that we do not warn on such structs // if they also are declared with `#[unsafe_no_drop_flag]` #![feature(unsafe_no_drop_flag)] #![deny(drop_with_repr_extern)] #[repr(C)] struct As { x: Box<i8> } #[repr(C)] enum Ae { Ae(Box<i8>), _None } struct Bs { x: Box<i8> } enum Be { Be(Box<i8>), _None } #[repr(C)] struct Cs { x: Box<i8> } //~^ NOTE the `#[repr(C)]` attribute is attached here impl Drop for Cs { fn drop(&mut self) { } } //~^ ERROR implementing Drop adds hidden state to types, possibly conflicting with `#[repr(C)]` #[repr(C)] enum Ce { Ce(Box<i8>), _None } //~^ NOTE the `#[repr(C)]` attribute is attached here impl Drop for Ce { fn drop(&mut self) { } } //~^ ERROR implementing Drop adds hidden state to types, possibly conflicting with `#[repr(C)]` #[unsafe_no_drop_flag] #[repr(C)] struct Ds { x: Box<i8> } impl Drop for Ds { fn drop(&mut self) { } } #[unsafe_no_drop_flag] #[repr(C)] enum De { De(Box<i8>), _None } impl Drop for De { fn drop(&mut self) { } } fn main() { let a = As { x: Box::new(3) }; let b = Bs { x: Box::new(3) }; let c = Cs { x: Box::new(3) }; let d = Ds { x: Box::new(3) }; println!("{:?}", (*a.x, *b.x, *c.x, *d.x)); let _a = Ae::Ae(Box::new(3)); let _b = Be::Be(Box::new(3)); let _c = Ce::Ce(Box::new(3)); let _d = De::De(Box::new(3)); } </ins>