summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:20:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:20:39 +0000
commit1376c5a617be5c25655d0d7cb63e3beaa5a6e026 (patch)
tree3bb8d61aee02bc7a15eab3f36e3b921afc2075d0 /compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
parentReleasing progress-linux version 1.69.0+dfsg1-1~progress7.99u1. (diff)
downloadrustc-1376c5a617be5c25655d0d7cb63e3beaa5a6e026.tar.xz
rustc-1376c5a617be5c25655d0d7cb63e3beaa5a6e026.zip
Merging upstream version 1.70.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs')
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs314
1 files changed, 213 insertions, 101 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index a844a1494..1b741b730 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -24,16 +24,15 @@ use rustc_errors::{
};
use rustc_hir as hir;
use rustc_hir::def::Namespace;
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::Visitor;
-use rustc_hir::GenericParam;
-use rustc_hir::Item;
-use rustc_hir::Node;
+use rustc_hir::{GenericParam, Item, Node};
use rustc_infer::infer::error_reporting::TypeErrCtxt;
use rustc_infer::infer::{InferOk, TypeTrace};
use rustc_middle::traits::select::OverflowError;
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
+use rustc_middle::ty::fast_reject::TreatProjections;
use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
use rustc_middle::ty::print::{with_forced_trimmed_paths, FmtPrinter, Print};
use rustc_middle::ty::{
@@ -126,11 +125,9 @@ pub trait TypeErrCtxtExt<'tcx> {
+ Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
<T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug;
- fn report_fulfillment_errors(
- &self,
- errors: &[FulfillmentError<'tcx>],
- body_id: Option<hir::BodyId>,
- ) -> ErrorGuaranteed;
+ fn report_overflow_no_abort(&self, obligation: PredicateObligation<'tcx>) -> ErrorGuaranteed;
+
+ fn report_fulfillment_errors(&self, errors: &[FulfillmentError<'tcx>]) -> ErrorGuaranteed;
fn report_overflow_obligation<T>(
&self,
@@ -388,11 +385,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
}
impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
- fn report_fulfillment_errors(
- &self,
- errors: &[FulfillmentError<'tcx>],
- body_id: Option<hir::BodyId>,
- ) -> ErrorGuaranteed {
+ fn report_fulfillment_errors(&self, errors: &[FulfillmentError<'tcx>]) -> ErrorGuaranteed {
#[derive(Debug)]
struct ErrorDescriptor<'tcx> {
predicate: ty::Predicate<'tcx>,
@@ -469,7 +462,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
for from_expansion in [false, true] {
for (error, suppressed) in iter::zip(errors, &is_suppressed) {
if !suppressed && error.obligation.cause.span.from_expansion() == from_expansion {
- self.report_fulfillment_error(error, body_id);
+ self.report_fulfillment_error(error);
}
}
}
@@ -611,6 +604,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
);
}
+ fn report_overflow_no_abort(&self, obligation: PredicateObligation<'tcx>) -> ErrorGuaranteed {
+ let obligation = self.resolve_vars_if_possible(obligation);
+ let mut err = self.build_overflow_error(&obligation.predicate, obligation.cause.span, true);
+ self.note_obligation_cause(&mut err, &obligation);
+ self.point_at_returns_when_relevant(&mut err, &obligation);
+ err.emit()
+ }
+
fn report_selection_error(
&self,
mut obligation: PredicateObligation<'tcx>,
@@ -672,6 +673,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
return;
}
let trait_ref = trait_predicate.to_poly_trait_ref();
+
let (post_message, pre_message, type_def) = self
.get_parent_trait_ref(obligation.cause.code())
.map(|(t, s)| {
@@ -711,33 +713,45 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
(message, note, append_const_msg)
};
- let mut err = struct_span_err!(
- self.tcx.sess,
- span,
- E0277,
- "{}",
- message
- .and_then(|cannot_do_this| {
- match (predicate_is_const, append_const_msg) {
- // do nothing if predicate is not const
- (false, _) => Some(cannot_do_this),
- // suggested using default post message
- (true, Some(None)) => {
- Some(format!("{cannot_do_this} in const contexts"))
- }
- // overridden post message
- (true, Some(Some(post_message))) => {
- Some(format!("{cannot_do_this}{post_message}"))
- }
- // fallback to generic message
- (true, None) => None,
+ let err_msg = message
+ .and_then(|cannot_do_this| {
+ match (predicate_is_const, append_const_msg) {
+ // do nothing if predicate is not const
+ (false, _) => Some(cannot_do_this),
+ // suggested using default post message
+ (true, Some(None)) => {
+ Some(format!("{cannot_do_this} in const contexts"))
}
- })
- .unwrap_or_else(|| format!(
+ // overridden post message
+ (true, Some(Some(post_message))) => {
+ Some(format!("{cannot_do_this}{post_message}"))
+ }
+ // fallback to generic message
+ (true, None) => None,
+ }
+ })
+ .unwrap_or_else(|| {
+ format!(
"the trait bound `{}` is not satisfied{}",
trait_predicate, post_message,
- ))
- );
+ )
+ });
+
+ let (err_msg, safe_transmute_explanation) = if Some(trait_ref.def_id())
+ == self.tcx.lang_items().transmute_trait()
+ {
+ // Recompute the safe transmute reason and use that for the error reporting
+ self.get_safe_transmute_error_and_reason(
+ trait_predicate,
+ obligation.clone(),
+ trait_ref,
+ span,
+ )
+ } else {
+ (err_msg, None)
+ };
+
+ let mut err = struct_span_err!(self.tcx.sess, span, E0277, "{}", err_msg);
if is_try_conversion && let Some(ret_span) = self.return_type_span(&obligation) {
err.span_label(
@@ -827,6 +841,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// at the type param with a label to suggest constraining it.
err.help(&explanation);
}
+ } else if let Some(custom_explanation) = safe_transmute_explanation {
+ err.span_label(span, custom_explanation);
} else {
err.span_label(span, explanation);
}
@@ -955,8 +971,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
);
}
- let body_hir_id =
- self.tcx.hir().local_def_id_to_hir_id(obligation.cause.body_id);
+ let body_def_id = obligation.cause.body_id;
// Try to report a help message
if is_fn_trait
&& let Ok((implemented_kind, params)) = self.type_implements_fn_trait(
@@ -1035,9 +1050,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// Can't show anything else useful, try to find similar impls.
let impl_candidates = self.find_similar_impl_candidates(trait_predicate);
if !self.report_similar_impl_candidates(
- impl_candidates,
+ &impl_candidates,
trait_ref,
- body_hir_id,
+ body_def_id,
&mut err,
true,
) {
@@ -1071,14 +1086,21 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let impl_candidates =
self.find_similar_impl_candidates(trait_pred);
self.report_similar_impl_candidates(
- impl_candidates,
+ &impl_candidates,
trait_ref,
- body_hir_id,
+ body_def_id,
&mut err,
true,
);
}
}
+
+ self.maybe_suggest_convert_to_slice(
+ &mut err,
+ trait_ref,
+ impl_candidates.as_slice(),
+ span,
+ );
}
// Changing mutability doesn't make a difference to whether we have
@@ -1279,16 +1301,26 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
"TypeWellFormedFromEnv predicate should only exist in the environment"
),
- ty::PredicateKind::AliasEq(..) => span_bug!(
+ ty::PredicateKind::AliasRelate(..) => span_bug!(
span,
- "AliasEq predicate should never be the predicate cause of a SelectionError"
+ "AliasRelate predicate should never be the predicate cause of a SelectionError"
),
ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
- self.tcx.sess.struct_span_err(
+ let mut diag = self.tcx.sess.struct_span_err(
span,
&format!("the constant `{}` is not of type `{}`", ct, ty),
- )
+ );
+ self.note_type_err(
+ &mut diag,
+ &obligation.cause,
+ None,
+ None,
+ TypeError::Sorts(ty::error::ExpectedFound::new(true, ty, ct.ty())),
+ false,
+ false,
+ );
+ diag
}
}
}
@@ -1494,11 +1526,7 @@ trait InferCtxtPrivExt<'tcx> {
// `error` occurring implies that `cond` occurs.
fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool;
- fn report_fulfillment_error(
- &self,
- error: &FulfillmentError<'tcx>,
- body_id: Option<hir::BodyId>,
- );
+ fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>);
fn report_projection_error(
&self,
@@ -1529,9 +1557,9 @@ trait InferCtxtPrivExt<'tcx> {
fn report_similar_impl_candidates(
&self,
- impl_candidates: Vec<ImplCandidate<'tcx>>,
+ impl_candidates: &[ImplCandidate<'tcx>],
trait_ref: ty::PolyTraitRef<'tcx>,
- body_id: hir::HirId,
+ body_def_id: LocalDefId,
err: &mut Diagnostic,
other: bool,
) -> bool;
@@ -1561,11 +1589,7 @@ trait InferCtxtPrivExt<'tcx> {
trait_ref_and_ty: ty::Binder<'tcx, (ty::TraitPredicate<'tcx>, Ty<'tcx>)>,
) -> PredicateObligation<'tcx>;
- fn maybe_report_ambiguity(
- &self,
- obligation: &PredicateObligation<'tcx>,
- body_id: Option<hir::BodyId>,
- );
+ fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>);
fn predicate_can_apply(
&self,
@@ -1602,6 +1626,14 @@ trait InferCtxtPrivExt<'tcx> {
obligated_types: &mut Vec<Ty<'tcx>>,
cause_code: &ObligationCauseCode<'tcx>,
) -> bool;
+
+ fn get_safe_transmute_error_and_reason(
+ &self,
+ trait_predicate: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>,
+ obligation: Obligation<'tcx, ty::Predicate<'tcx>>,
+ trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
+ span: Span,
+ ) -> (String, Option<String>);
}
impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
@@ -1625,8 +1657,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
};
- for obligation in super::elaborate_predicates(self.tcx, std::iter::once(cond)) {
- let bound_predicate = obligation.predicate.kind();
+ for pred in super::elaborate(self.tcx, std::iter::once(cond)) {
+ let bound_predicate = pred.kind();
if let ty::PredicateKind::Clause(ty::Clause::Trait(implication)) =
bound_predicate.skip_binder()
{
@@ -1647,11 +1679,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
#[instrument(skip(self), level = "debug")]
- fn report_fulfillment_error(
- &self,
- error: &FulfillmentError<'tcx>,
- body_id: Option<hir::BodyId>,
- ) {
+ fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) {
match error.code {
FulfillmentErrorCode::CodeSelectionError(ref selection_error) => {
self.report_selection_error(
@@ -1663,8 +1691,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
FulfillmentErrorCode::CodeProjectionError(ref e) => {
self.report_projection_error(&error.obligation, e);
}
- FulfillmentErrorCode::CodeAmbiguity => {
- self.maybe_report_ambiguity(&error.obligation, body_id);
+ FulfillmentErrorCode::CodeAmbiguity { overflow: false } => {
+ self.maybe_report_ambiguity(&error.obligation);
+ }
+ FulfillmentErrorCode::CodeAmbiguity { overflow: true } => {
+ self.report_overflow_no_abort(error.obligation.clone());
}
FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => {
self.report_mismatched_types(
@@ -1768,7 +1799,10 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// constrain inference variables a bit more to nested obligations from normalize so
// we can have more helpful errors.
- ocx.select_where_possible();
+ //
+ // we intentionally drop errors from normalization here,
+ // since the normalization is just done to improve the error message.
+ let _ = ocx.select_where_possible();
if let Err(new_err) = ocx.eq_exp(
&obligation.cause,
@@ -1815,12 +1849,17 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
})
.and_then(|(trait_assoc_item, id)| {
let trait_assoc_ident = trait_assoc_item.ident(self.tcx);
- self.tcx.find_map_relevant_impl(id, proj.projection_ty.self_ty(), |did| {
- self.tcx
- .associated_items(did)
- .in_definition_order()
- .find(|assoc| assoc.ident(self.tcx) == trait_assoc_ident)
- })
+ self.tcx.find_map_relevant_impl(
+ id,
+ proj.projection_ty.self_ty(),
+ TreatProjections::ForLookup,
+ |did| {
+ self.tcx
+ .associated_items(did)
+ .in_definition_order()
+ .find(|assoc| assoc.ident(self.tcx) == trait_assoc_ident)
+ },
+ )
})
.and_then(|item| match self.tcx.hir().get_if_local(item.def_id) {
Some(
@@ -2027,9 +2066,9 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
fn report_similar_impl_candidates(
&self,
- impl_candidates: Vec<ImplCandidate<'tcx>>,
+ impl_candidates: &[ImplCandidate<'tcx>],
trait_ref: ty::PolyTraitRef<'tcx>,
- body_id: hir::HirId,
+ body_def_id: LocalDefId,
err: &mut Diagnostic,
other: bool,
) -> bool {
@@ -2120,9 +2159,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// FIXME(compiler-errors): This could be generalized, both to
// be more granular, and probably look past other `#[fundamental]`
// types, too.
- self.tcx
- .visibility(def.did())
- .is_accessible_from(body_id.owner.def_id, self.tcx)
+ self.tcx.visibility(def.did()).is_accessible_from(body_def_id, self.tcx)
} else {
true
}
@@ -2138,7 +2175,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// Prefer more similar candidates first, then sort lexicographically
// by their normalized string representation.
let mut normalized_impl_candidates_and_similarities = impl_candidates
- .into_iter()
+ .iter()
+ .copied()
.map(|ImplCandidate { trait_ref, similarity }| {
// FIXME(compiler-errors): This should be using `NormalizeExt::normalize`
let normalized = self
@@ -2193,7 +2231,12 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
trait_ref: &ty::PolyTraitRef<'tcx>,
) -> bool {
let get_trait_impl = |trait_def_id| {
- self.tcx.find_map_relevant_impl(trait_def_id, trait_ref.skip_binder().self_ty(), Some)
+ self.tcx.find_map_relevant_impl(
+ trait_def_id,
+ trait_ref.skip_binder().self_ty(),
+ TreatProjections::ForLookup,
+ Some,
+ )
};
let required_trait_path = self.tcx.def_path_str(trait_ref.def_id());
let traits_with_same_path: std::collections::BTreeSet<_> = self
@@ -2231,11 +2274,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
#[instrument(skip(self), level = "debug")]
- fn maybe_report_ambiguity(
- &self,
- obligation: &PredicateObligation<'tcx>,
- body_id: Option<hir::BodyId>,
- ) {
+ fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) {
// Unable to successfully determine, probably means
// insufficient type information, but could mean
// ambiguous impls. The latter *ought* to be a
@@ -2277,7 +2316,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
if self.tcx.lang_items().sized_trait() == Some(trait_ref.def_id()) {
if let None = self.tainted_by_errors() {
self.emit_inference_failure_err(
- body_id,
+ obligation.cause.body_id,
span,
trait_ref.self_ty().skip_binder().into(),
ErrorCode::E0282,
@@ -2304,7 +2343,13 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let subst = data.trait_ref.substs.iter().find(|s| s.has_non_region_infer());
let mut err = if let Some(subst) = subst {
- self.emit_inference_failure_err(body_id, span, subst, ErrorCode::E0283, true)
+ self.emit_inference_failure_err(
+ obligation.cause.body_id,
+ span,
+ subst,
+ ErrorCode::E0283,
+ true,
+ )
} else {
struct_span_err!(
self.tcx.sess,
@@ -2348,12 +2393,10 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
predicate.to_opt_poly_trait_pred().unwrap(),
);
if impl_candidates.len() < 10 {
- let hir =
- self.tcx.hir().local_def_id_to_hir_id(obligation.cause.body_id);
self.report_similar_impl_candidates(
- impl_candidates,
+ impl_candidates.as_slice(),
trait_ref,
- body_id.map(|id| id.hir_id).unwrap_or(hir),
+ obligation.cause.body_id,
&mut err,
false,
);
@@ -2375,8 +2418,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());
}
- if let (Some(body_id), Some(ty::subst::GenericArgKind::Type(_))) =
- (body_id, subst.map(|subst| subst.unpack()))
+ if let Some(ty::subst::GenericArgKind::Type(_)) = subst.map(|subst| subst.unpack())
+ && let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id)
{
let mut expr_finder = FindExprBySpan::new(span);
expr_finder.visit_expr(&self.tcx.hir().body(body_id).value);
@@ -2473,7 +2516,13 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
return;
}
- self.emit_inference_failure_err(body_id, span, arg, ErrorCode::E0282, false)
+ self.emit_inference_failure_err(
+ obligation.cause.body_id,
+ span,
+ arg,
+ ErrorCode::E0282,
+ false,
+ )
}
ty::PredicateKind::Subtype(data) => {
@@ -2487,7 +2536,13 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let SubtypePredicate { a_is_expected: _, a, b } = data;
// both must be type variables, or the other would've been instantiated
assert!(a.is_ty_var() && b.is_ty_var());
- self.emit_inference_failure_err(body_id, span, a.into(), ErrorCode::E0282, true)
+ self.emit_inference_failure_err(
+ obligation.cause.body_id,
+ span,
+ a.into(),
+ ErrorCode::E0282,
+ true,
+ )
}
ty::PredicateKind::Clause(ty::Clause::Projection(data)) => {
if predicate.references_error() || self.tainted_by_errors().is_some() {
@@ -2501,7 +2556,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
.find(|g| g.has_non_region_infer());
if let Some(subst) = subst {
let mut err = self.emit_inference_failure_err(
- body_id,
+ obligation.cause.body_id,
span,
subst,
ErrorCode::E0284,
@@ -2530,7 +2585,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let subst = data.walk().find(|g| g.is_non_region_infer());
if let Some(subst) = subst {
let err = self.emit_inference_failure_err(
- body_id,
+ obligation.cause.body_id,
span,
subst,
ErrorCode::E0284,
@@ -2863,6 +2918,63 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
false
}
+
+ fn get_safe_transmute_error_and_reason(
+ &self,
+ trait_predicate: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>,
+ obligation: Obligation<'tcx, ty::Predicate<'tcx>>,
+ trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
+ span: Span,
+ ) -> (String, Option<String>) {
+ let src_and_dst = trait_predicate.map_bound(|p| rustc_transmute::Types {
+ dst: p.trait_ref.substs.type_at(0),
+ src: p.trait_ref.substs.type_at(1),
+ });
+ let scope = trait_ref.skip_binder().substs.type_at(2);
+ let Some(assume) =
+ rustc_transmute::Assume::from_const(self.infcx.tcx, obligation.param_env, trait_ref.skip_binder().substs.const_at(3)) else {
+ span_bug!(span, "Unable to construct rustc_transmute::Assume where it was previously possible");
+ };
+ match rustc_transmute::TransmuteTypeEnv::new(self.infcx).is_transmutable(
+ obligation.cause,
+ src_and_dst,
+ scope,
+ assume,
+ ) {
+ rustc_transmute::Answer::No(reason) => {
+ let dst = trait_ref.skip_binder().substs.type_at(0);
+ let src = trait_ref.skip_binder().substs.type_at(1);
+ let custom_err_msg = format!("`{src}` cannot be safely transmuted into `{dst}` in the defining scope of `{scope}`").to_string();
+ let reason_msg = match reason {
+ rustc_transmute::Reason::SrcIsUnspecified => {
+ format!("`{src}` does not have a well-specified layout").to_string()
+ }
+ rustc_transmute::Reason::DstIsUnspecified => {
+ format!("`{dst}` does not have a well-specified layout").to_string()
+ }
+ rustc_transmute::Reason::DstIsBitIncompatible => {
+ format!("At least one value of `{src}` isn't a bit-valid value of `{dst}`")
+ .to_string()
+ }
+ rustc_transmute::Reason::DstIsPrivate => format!(
+ "`{dst}` is or contains a type or field that is not visible in that scope"
+ )
+ .to_string(),
+ // FIXME(bryangarza): Include the number of bytes of src and dst
+ rustc_transmute::Reason::DstIsTooBig => {
+ format!("The size of `{src}` is smaller than the size of `{dst}`")
+ }
+ };
+ (custom_err_msg, Some(reason_msg))
+ }
+ // Should never get a Yes at this point! We already ran it before, and did not get a Yes.
+ rustc_transmute::Answer::Yes => span_bug!(
+ span,
+ "Inconsistent rustc_transmute::is_transmutable(...) result, got Yes",
+ ),
+ _ => span_bug!(span, "Unsupported rustc_transmute::Reason variant"),
+ }
+ }
}
/// Crude way of getting back an `Expr` from a `Span`.