diff options
| author | Lamb <lamb@ltow.me> | 2022-01-10 21:01:23 +0000 |
|---|---|---|
| committer | Scott McMurray <scottmcm@users.noreply.github.com> | 2022-08-10 09:55:41 -0700 |
| commit | a3b84ad197fb209d903857df747af3ca0a1f2c25 (patch) | |
| tree | 12715823556e30f8875e801e994b09a36e0b7997 /compiler | |
| parent | 1603a70f82240ba2d27f72f964e36614d7620ad3 (diff) | |
| download | rust-a3b84ad197fb209d903857df747af3ca0a1f2c25.tar.gz rust-a3b84ad197fb209d903857df747af3ca0a1f2c25.zip | |
Check if extern crate enum has non exhaustive variant when cast
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_typeck/src/check/cast.rs | 23 |
1 files changed, 22 insertions, 1 deletions
diff --git a/compiler/rustc_typeck/src/check/cast.rs b/compiler/rustc_typeck/src/check/cast.rs index 7aaddc2bd7a..88bce06297b 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 a non-exhaustive enum 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), |
