Rollup merge of #95609 - compiler-errors:borrow-unsized-to-dyn, r=nagisa
Suggest borrowing when trying to coerce unsized type into `dyn Trait` A helpful error in response to #95598, since we can't coerce e.g. `&str` into `&dyn Display`, but we can coerce `&&str` into `&dyn Display` :) Not sure if the suggestion message needs some help. Let me know, and I can refine this PR.
This commit is contained in:
commit
0c5f879203
5 changed files with 71 additions and 0 deletions
|
@ -474,6 +474,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||
err.span_label(span, explanation);
|
||||
}
|
||||
|
||||
if let ObligationCauseCode::ObjectCastObligation(obj_ty) = obligation.cause.code().peel_derives() &&
|
||||
let Some(self_ty) = trait_predicate.self_ty().no_bound_vars() &&
|
||||
Some(trait_ref.def_id()) == self.tcx.lang_items().sized_trait() {
|
||||
self.suggest_borrowing_for_object_cast(&mut err, &obligation, self_ty, *obj_ty);
|
||||
}
|
||||
|
||||
if trait_predicate.is_const_if_const() && obligation.param_env.is_const() {
|
||||
let non_const_predicate = trait_ref.without_const();
|
||||
let non_const_obligation = Obligation {
|
||||
|
|
|
@ -77,6 +77,14 @@ pub trait InferCtxtExt<'tcx> {
|
|||
has_custom_message: bool,
|
||||
) -> bool;
|
||||
|
||||
fn suggest_borrowing_for_object_cast(
|
||||
&self,
|
||||
err: &mut Diagnostic,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
self_ty: Ty<'tcx>,
|
||||
object_ty: Ty<'tcx>,
|
||||
);
|
||||
|
||||
fn suggest_remove_reference(
|
||||
&self,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
|
@ -801,6 +809,35 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
// Suggest borrowing the type
|
||||
fn suggest_borrowing_for_object_cast(
|
||||
&self,
|
||||
err: &mut Diagnostic,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
self_ty: Ty<'tcx>,
|
||||
object_ty: Ty<'tcx>,
|
||||
) {
|
||||
let ty::Dynamic(predicates, _) = object_ty.kind() else { return; };
|
||||
let self_ref_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, self_ty);
|
||||
|
||||
for predicate in predicates.iter() {
|
||||
if !self.predicate_must_hold_modulo_regions(
|
||||
&obligation.with(predicate.with_self_ty(self.tcx, self_ref_ty)),
|
||||
) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
err.span_suggestion(
|
||||
obligation.cause.span.shrink_to_lo(),
|
||||
&format!(
|
||||
"consider borrowing the value, since `&{self_ty}` can be coerced into `{object_ty}`"
|
||||
),
|
||||
"&".to_string(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
|
||||
/// Whenever references are used by mistake, like `for (i, e) in &vec.iter().enumerate()`,
|
||||
/// suggest removing these references until we reach a type that implements the trait.
|
||||
fn suggest_remove_reference(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue