1
Fork 0

Note base types of coercion

This commit is contained in:
Michael Goulet 2023-05-11 02:10:56 +00:00
parent 2a8221dbdf
commit 14bf909e71
65 changed files with 142 additions and 225 deletions

View file

@ -797,9 +797,17 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
err.span_label(span, explanation);
}
if let ObligationCauseCode::ObjectCastObligation(concrete_ty, obj_ty) = obligation.cause.code().peel_derives() &&
Some(trait_ref.def_id()) == self.tcx.lang_items().sized_trait() {
self.suggest_borrowing_for_object_cast(&mut err, &root_obligation, *concrete_ty, *obj_ty);
if let ObligationCauseCode::Coercion { source, target } =
*obligation.cause.code().peel_derives()
{
if Some(trait_ref.def_id()) == self.tcx.lang_items().sized_trait() {
self.suggest_borrowing_for_object_cast(
&mut err,
&root_obligation,
source,
target,
);
}
}
let UnsatisfiedConst(unsatisfied_const) = self
@ -1510,7 +1518,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
| ObligationCauseCode::BindingObligation(_, _)
| ObligationCauseCode::ExprItemObligation(..)
| ObligationCauseCode::ExprBindingObligation(..)
| ObligationCauseCode::ObjectCastObligation(..)
| ObligationCauseCode::Coercion { .. }
| ObligationCauseCode::OpaqueType
);

View file

@ -1442,8 +1442,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
err: &mut Diagnostic,
obligation: &PredicateObligation<'tcx>,
self_ty: Ty<'tcx>,
object_ty: Ty<'tcx>,
target_ty: Ty<'tcx>,
) {
let ty::Ref(_, object_ty, hir::Mutability::Not) = target_ty.kind() else { return; };
let ty::Dynamic(predicates, _, ty::Dyn) = object_ty.kind() else { return; };
let self_ref_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, self_ty);
@ -1458,7 +1459,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
err.span_suggestion(
obligation.cause.span.shrink_to_lo(),
format!(
"consider borrowing the value, since `&{self_ty}` can be coerced into `{object_ty}`"
"consider borrowing the value, since `&{self_ty}` can be coerced into `{target_ty}`"
),
"&",
Applicability::MaybeIncorrect,
@ -2851,30 +2852,27 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
err.span_note(tcx.def_span(item_def_id), descr);
}
}
ObligationCauseCode::ObjectCastObligation(concrete_ty, object_ty) => {
let (concrete_ty, concrete_file) =
self.tcx.short_ty_string(self.resolve_vars_if_possible(concrete_ty));
let (object_ty, object_file) =
self.tcx.short_ty_string(self.resolve_vars_if_possible(object_ty));
ObligationCauseCode::Coercion { source, target } => {
let (source, source_file) =
self.tcx.short_ty_string(self.resolve_vars_if_possible(source));
let (target, target_file) =
self.tcx.short_ty_string(self.resolve_vars_if_possible(target));
err.note(with_forced_trimmed_paths!(format!(
"required for the cast from `{concrete_ty}` to the object type `{object_ty}`",
"required for the cast from `{source}` to `{target}`",
)));
if let Some(file) = concrete_file {
if let Some(file) = source_file {
err.note(format!(
"the full name for the casted type has been written to '{}'",
"the full name for the source type has been written to '{}'",
file.display(),
));
}
if let Some(file) = object_file {
if let Some(file) = target_file {
err.note(format!(
"the full name for the object type has been written to '{}'",
"the full name for the target type has been written to '{}'",
file.display(),
));
}
}
ObligationCauseCode::Coercion { source: _, target } => {
err.note(format!("required by cast to type `{}`", self.ty_to_string(target)));
}
ObligationCauseCode::RepeatElementCopy { is_const_fn } => {
err.note(
"the `Copy` trait is required because this value will be copied for each element of the array",

View file

@ -29,9 +29,9 @@ use crate::traits::{
ImplSourceAutoImplData, ImplSourceBuiltinData, ImplSourceClosureData,
ImplSourceConstDestructData, ImplSourceFnPointerData, ImplSourceFutureData,
ImplSourceGeneratorData, ImplSourceObjectData, ImplSourceTraitAliasData,
ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, Normalized, ObjectCastObligation,
Obligation, ObligationCause, OutputTypeParameterMismatch, PredicateObligation, Selection,
SelectionError, TraitNotObjectSafe, TraitObligation, Unimplemented,
ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, Normalized, Obligation,
ObligationCause, OutputTypeParameterMismatch, PredicateObligation, Selection, SelectionError,
TraitNotObjectSafe, TraitObligation, Unimplemented,
};
use super::BuiltinImplConditions;
@ -905,16 +905,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.map_err(|_| Unimplemented)?;
nested.extend(obligations);
// Register one obligation for 'a: 'b.
let cause = ObligationCause::new(
obligation.cause.span,
obligation.cause.body_id,
ObjectCastObligation(source, target),
);
let outlives = ty::OutlivesPredicate(r_a, r_b);
nested.push(Obligation::with_depth(
tcx,
cause,
obligation.cause.clone(),
obligation.recursion_depth + 1,
obligation.param_env,
obligation.predicate.rebind(outlives),
@ -1005,15 +999,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
nested.extend(obligations);
// Register one obligation for 'a: 'b.
let cause = ObligationCause::new(
obligation.cause.span,
obligation.cause.body_id,
ObjectCastObligation(source, target),
);
let outlives = ty::OutlivesPredicate(r_a, r_b);
nested.push(Obligation::with_depth(
tcx,
cause,
obligation.cause.clone(),
obligation.recursion_depth + 1,
obligation.param_env,
obligation.predicate.rebind(outlives),
@ -1027,16 +1016,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
return Err(TraitNotObjectSafe(did));
}
let cause = ObligationCause::new(
obligation.cause.span,
obligation.cause.body_id,
ObjectCastObligation(source, target),
);
let predicate_to_obligation = |predicate| {
Obligation::with_depth(
tcx,
cause.clone(),
obligation.cause.clone(),
obligation.recursion_depth + 1,
obligation.param_env,
predicate,
@ -1056,7 +1039,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
);
// We can only make objects from sized types.
let tr = ty::TraitRef::from_lang_item(tcx, LangItem::Sized, cause.span, [source]);
let tr = ty::TraitRef::from_lang_item(
tcx,
LangItem::Sized,
obligation.cause.span,
[source],
);
nested.push(predicate_to_obligation(tr.without_const().to_predicate(tcx)));
// If the type is `Foo + 'a`, ensure that the type

View file

@ -2647,14 +2647,19 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
let predicates = predicates.instantiate_own(tcx, substs);
let mut obligations = Vec::with_capacity(predicates.len());
for (index, (predicate, span)) in predicates.into_iter().enumerate() {
let cause = cause.clone().derived_cause(parent_trait_pred, |derived| {
ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
derived,
impl_or_alias_def_id: def_id,
impl_def_predicate_index: Some(index),
span,
}))
});
let cause =
if Some(parent_trait_pred.def_id()) == tcx.lang_items().coerce_unsized_trait() {
cause.clone()
} else {
cause.clone().derived_cause(parent_trait_pred, |derived| {
ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
derived,
impl_or_alias_def_id: def_id,
impl_def_predicate_index: Some(index),
span,
}))
})
};
let predicate = normalize_with_depth_to(
self,
param_env,