summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_hir_typeck/src/cast.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_hir_typeck/src/cast.rs')
-rw-r--r--compiler/rustc_hir_typeck/src/cast.rs52
1 files changed, 17 insertions, 35 deletions
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index d1dab0540..890a068a7 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -33,6 +33,7 @@ use super::FnCtxt;
use crate::type_error_struct;
use rustc_errors::{struct_span_err, Applicability, DelayDm, DiagnosticBuilder, ErrorGuaranteed};
use rustc_hir as hir;
+use rustc_macros::{TypeFoldable, TypeVisitable};
use rustc_middle::mir::Mutability;
use rustc_middle::ty::adjustment::AllowTwoPhase;
use rustc_middle::ty::cast::{CastKind, CastTy};
@@ -45,7 +46,6 @@ use rustc_span::def_id::{DefId, LOCAL_CRATE};
use rustc_span::symbol::sym;
use rustc_span::Span;
use rustc_trait_selection::infer::InferCtxtExt;
-use rustc_trait_selection::traits::error_reporting::report_object_safety_error;
/// Reifies a cast check to be checked once we have full type information for
/// a function context.
@@ -67,7 +67,7 @@ pub struct CastCheck<'tcx> {
/// The kind of pointer and associated metadata (thin, length or vtable) - we
/// only allow casts between fat pointers if their metadata have the same
/// kind.
-#[derive(Copy, Clone, PartialEq, Eq)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, TypeVisitable, TypeFoldable)]
enum PointerKind<'tcx> {
/// No metadata attached, ie pointer to sized type or foreign type
Thin,
@@ -76,11 +76,11 @@ enum PointerKind<'tcx> {
/// Slice
Length,
/// The unsize info of this projection
- OfProjection(&'tcx ty::ProjectionTy<'tcx>),
+ OfProjection(ty::ProjectionTy<'tcx>),
/// The unsize info of this opaque ty
OfOpaque(DefId, SubstsRef<'tcx>),
/// The unsize info of this parameter
- OfParam(&'tcx ty::ParamTy),
+ OfParam(ty::ParamTy),
}
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -94,10 +94,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
debug!("pointer_kind({:?}, {:?})", t, span);
let t = self.resolve_vars_if_possible(t);
-
- if let Some(reported) = t.error_reported() {
- return Err(reported);
- }
+ t.error_reported()?;
if self.type_is_sized_modulo_regions(self.param_env, t, span) {
return Ok(Some(PointerKind::Thin));
@@ -121,9 +118,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Pointers to foreign types are thin, despite being unsized
ty::Foreign(..) => Some(PointerKind::Thin),
// We should really try to normalize here.
- ty::Projection(ref pi) => Some(PointerKind::OfProjection(pi)),
+ ty::Projection(pi) => Some(PointerKind::OfProjection(pi)),
ty::Opaque(def_id, substs) => Some(PointerKind::OfOpaque(def_id, substs)),
- ty::Param(ref p) => Some(PointerKind::OfParam(p)),
+ ty::Param(p) => Some(PointerKind::OfParam(p)),
// Insufficient type information.
ty::Placeholder(..) | ty::Bound(..) | ty::Infer(_) => None,
@@ -222,8 +219,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
// inference is more completely known.
match cast_ty.kind() {
ty::Dynamic(_, _, ty::Dyn) | ty::Slice(..) => {
- let reported = check.report_cast_to_unsized_type(fcx);
- Err(reported)
+ Err(check.report_cast_to_unsized_type(fcx))
}
_ => Ok(check),
}
@@ -501,10 +497,9 @@ impl<'a, 'tcx> CastCheck<'tcx> {
let ty = fcx.tcx.erase_regions(ty);
let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty);
let expr_ty = fcx.tcx.erase_regions(expr_ty);
- let ty_params = fcx.tcx.mk_substs_trait(expr_ty, &[]);
if fcx
.infcx
- .type_implements_trait(from_trait, ty, ty_params, fcx.param_env)
+ .type_implements_trait(from_trait, [ty, expr_ty], fcx.param_env)
.must_apply_modulo_regions()
{
label = false;
@@ -614,10 +609,11 @@ impl<'a, 'tcx> CastCheck<'tcx> {
}
fn report_cast_to_unsized_type(&self, fcx: &FnCtxt<'a, 'tcx>) -> ErrorGuaranteed {
- if let Some(reported) =
- self.cast_ty.error_reported().or_else(|| self.expr_ty.error_reported())
- {
- return reported;
+ if let Err(err) = self.cast_ty.error_reported() {
+ return err;
+ }
+ if let Err(err) = self.expr_ty.error_reported() {
+ return err;
}
let tstr = fcx.ty_to_string(self.cast_ty);
@@ -730,9 +726,6 @@ impl<'a, 'tcx> CastCheck<'tcx> {
debug!(" -> CoercionCast");
fcx.typeck_results.borrow_mut().set_coercion_cast(self.expr.hir_id.local_id);
}
- Err(ty::error::TypeError::ObjectUnsafeCoercion(did)) => {
- self.report_object_unsafe_cast(&fcx, did);
- }
Err(_) => {
match self.do_check(fcx) {
Ok(k) => {
@@ -744,14 +737,6 @@ impl<'a, 'tcx> CastCheck<'tcx> {
};
}
}
-
- fn report_object_unsafe_cast(&self, fcx: &FnCtxt<'a, 'tcx>, did: DefId) {
- let violations = fcx.tcx.object_safety_violations(did);
- let mut err = report_object_safety_error(fcx.tcx, self.cast_span, did, violations);
- err.note(&format!("required by cast to type '{}'", fcx.ty_to_string(self.cast_ty)));
- err.emit();
- }
-
/// Checks a cast, and report an error if one exists. In some cases, this
/// can return Ok and create type errors in the fcx rather than returning
/// directly. coercion-cast is handled in check instead of here.
@@ -767,10 +752,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
match *self.expr_ty.kind() {
ty::FnDef(..) => {
// Attempt a coercion to a fn pointer type.
- let f = fcx.normalize_associated_types_in(
- self.expr_span,
- self.expr_ty.fn_sig(fcx.tcx),
- );
+ let f = fcx.normalize(self.expr_span, self.expr_ty.fn_sig(fcx.tcx));
let res = fcx.try_coerce(
self.expr,
self.expr_ty,
@@ -912,7 +894,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
}
// vtable kinds must match
- if cast_kind == expr_kind {
+ if fcx.tcx.erase_regions(cast_kind) == fcx.tcx.erase_regions(expr_kind) {
Ok(CastKind::PtrPtrCast)
} else {
Err(CastError::DifferingKinds)
@@ -954,7 +936,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
m_cast: ty::TypeAndMut<'tcx>,
) -> Result<CastKind, CastError> {
// array-ptr-cast: allow mut-to-mut, mut-to-const, const-to-const
- if m_expr.mutbl == hir::Mutability::Mut || m_cast.mutbl == hir::Mutability::Not {
+ if m_expr.mutbl >= m_cast.mutbl {
if let ty::Array(ety, _) = m_expr.ty.kind() {
// Due to the limitations of LLVM global constants,
// region pointers end up pointing at copies of