diff options
| author | Dylan DPC <99973273+Dylan-DPC@users.noreply.github.com> | 2022-08-11 11:14:50 +0530 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-08-11 11:14:50 +0530 |
| commit | 23acd822537227dd53253a6f6f422ea7a49a0919 (patch) | |
| tree | e9c96f2a78972194771fde07be96f6e1a7646b39 | |
| parent | 187654481fd828e495919295369d33827f10e1c4 (diff) | |
| parent | dfb3713cdb7303a250d8b23792fe801319edf36c (diff) | |
| download | rust-23acd822537227dd53253a6f6f422ea7a49a0919.tar.gz rust-23acd822537227dd53253a6f6f422ea7a49a0919.zip | |
Rollup merge of #92744 - lambinoo:I-91161-non-exhaustive-foreign-variants, r=scottmcm
Check if enum from foreign crate has any non exhaustive variants when attempting a cast Fixes #91161 As stated in the issue, this will require a crater run as it might break other people's stuff.
| -rw-r--r-- | compiler/rustc_typeck/src/check/cast.rs | 23 | ||||
| -rw-r--r-- | src/test/ui/rfc-2008-non-exhaustive/enum-as-cast.rs | 8 | ||||
| -rw-r--r-- | src/test/ui/rfc-2008-non-exhaustive/enum-as-cast.stderr | 11 |
3 files changed, 34 insertions, 8 deletions
diff --git a/compiler/rustc_typeck/src/check/cast.rs b/compiler/rustc_typeck/src/check/cast.rs index 7aaddc2bd7a..6c7b2a2889f 100644 --- a/compiler/rustc_typeck/src/check/cast.rs +++ b/compiler/rustc_typeck/src/check/cast.rs @@ -32,6 +32,7 @@ use super::FnCtxt; use crate::hir::def_id::DefId; use crate::type_error_struct; +use hir::def_id::LOCAL_CRATE; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::lang_items::LangItem; @@ -40,7 +41,7 @@ use rustc_middle::ty::adjustment::AllowTwoPhase; use rustc_middle::ty::cast::{CastKind, CastTy}; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::subst::SubstsRef; -use rustc_middle::ty::{self, Ty, TypeAndMut, TypeVisitable}; +use rustc_middle::ty::{self, Ty, TypeAndMut, TypeVisitable, VariantDef}; use rustc_session::lint; use rustc_session::Session; use rustc_span::symbol::sym; @@ -173,6 +174,7 @@ pub enum CastError { /// or "a length". If this argument is None, then the metadata is unknown, for example, /// when we're typechecking a type parameter with a ?Sized bound. IntToFatCast(Option<&'static str>), + ForeignNonExhaustiveAdt, } impl From<ErrorGuaranteed> for CastError { @@ -591,6 +593,17 @@ impl<'a, 'tcx> CastCheck<'tcx> { } err.emit(); } + CastError::ForeignNonExhaustiveAdt => { + make_invalid_casting_error( + fcx.tcx.sess, + self.span, + self.expr_ty, + self.cast_ty, + fcx, + ) + .note("cannot cast an enum with a non-exhaustive variant when it's defined in another crate") + .emit(); + } } } @@ -789,6 +802,14 @@ impl<'a, 'tcx> CastCheck<'tcx> { _ => return Err(CastError::NonScalar), }; + if let ty::Adt(adt_def, _) = *self.expr_ty.kind() { + if adt_def.did().krate != LOCAL_CRATE { + if adt_def.variants().iter().any(VariantDef::is_field_list_non_exhaustive) { + return Err(CastError::ForeignNonExhaustiveAdt); + } + } + } + match (t_from, t_cast) { // These types have invariants! can't cast into them. (_, Int(CEnum) | FnPtr) => Err(CastError::NonScalar), diff --git a/src/test/ui/rfc-2008-non-exhaustive/enum-as-cast.rs b/src/test/ui/rfc-2008-non-exhaustive/enum-as-cast.rs index d9657bac776..5dce8180f59 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/enum-as-cast.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/enum-as-cast.rs @@ -1,5 +1,4 @@ // aux-build:enums.rs -// run-pass extern crate enums; @@ -7,11 +6,6 @@ use enums::FieldLessWithNonExhaustiveVariant; fn main() { let e = FieldLessWithNonExhaustiveVariant::default(); - // FIXME: https://github.com/rust-lang/rust/issues/91161 - // This `as` cast *should* be an error, since it would fail - // if the non-exhaustive variant got fields. But today it - // doesn't. The fix for that will update this test to - // show an error (and not be run-pass any more). - let d = e as u8; + let d = e as u8; //~ ERROR casting `FieldLessWithNonExhaustiveVariant` as `u8` is invalid [E0606] assert_eq!(d, 0); } diff --git a/src/test/ui/rfc-2008-non-exhaustive/enum-as-cast.stderr b/src/test/ui/rfc-2008-non-exhaustive/enum-as-cast.stderr new file mode 100644 index 00000000000..a61dcf8399f --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/enum-as-cast.stderr @@ -0,0 +1,11 @@ +error[E0606]: casting `FieldLessWithNonExhaustiveVariant` as `u8` is invalid + --> $DIR/enum-as-cast.rs:9:13 + | +LL | let d = e as u8; + | ^^^^^^^ + | + = note: cannot cast an enum with a non-exhaustive variant when it's defined in another crate + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0606`. |
