Skip to content

Commit 05e6067

Browse files
committed
Deduplicate some logic
1 parent 6b4c0ce commit 05e6067

File tree

3 files changed

+161
-181
lines changed

3 files changed

+161
-181
lines changed

compiler/rustc_borrowck/src/diagnostics/mod.rs

+51-110
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rustc_hir::def::{CtorKind, Namespace};
1111
use rustc_hir::CoroutineKind;
1212
use rustc_index::IndexSlice;
1313
use rustc_infer::infer::BoundRegionConversionTime;
14-
use rustc_infer::traits::{FulfillmentErrorCode, SelectionError, TraitEngine, TraitEngineExt};
14+
use rustc_infer::traits::{FulfillmentErrorCode, SelectionError};
1515
use rustc_middle::mir::tcx::PlaceTy;
1616
use rustc_middle::mir::{
1717
AggregateKind, CallSource, ConstOperand, FakeReadCause, Local, LocalInfo, LocalKind, Location,
@@ -25,11 +25,9 @@ use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult};
2525
use rustc_span::def_id::LocalDefId;
2626
use rustc_span::{symbol::sym, Span, Symbol, DUMMY_SP};
2727
use rustc_target::abi::{FieldIdx, VariantIdx};
28-
use rustc_trait_selection::solve::FulfillmentCtxt;
28+
use rustc_trait_selection::infer::InferCtxtExt;
2929
use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt as _;
30-
use rustc_trait_selection::traits::{
31-
type_known_to_meet_bound_modulo_regions, Obligation, ObligationCause,
32-
};
30+
use rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions;
3331

3432
use super::borrow_set::BorrowData;
3533
use super::MirBorrowckCtxt;
@@ -1175,113 +1173,56 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
11751173
} else {
11761174
vec![(move_span.shrink_to_hi(), ".clone()".to_string())]
11771175
};
1178-
self.infcx.probe(|_snapshot| {
1179-
if let ty::Adt(def, args) = ty.kind()
1180-
&& !has_sugg
1181-
&& let Some((def_id, _imp)) = tcx
1182-
.all_impls(clone_trait)
1183-
.filter_map(|def_id| {
1184-
tcx.impl_trait_ref(def_id).map(|r| (def_id, r))
1185-
})
1186-
.map(|(def_id, imp)| (def_id, imp.skip_binder()))
1187-
.filter(|(_, imp)| match imp.self_ty().peel_refs().kind() {
1188-
ty::Adt(i_def, _) if i_def.did() == def.did() => true,
1189-
_ => false,
1190-
})
1191-
.next()
1192-
{
1193-
let mut fulfill_cx = FulfillmentCtxt::new(self.infcx);
1194-
// We get all obligations from the impl to talk about specific
1195-
// trait bounds.
1196-
let obligations = tcx
1197-
.predicates_of(def_id)
1198-
.instantiate(tcx, args)
1199-
.into_iter()
1200-
.map(|(clause, span)| {
1201-
Obligation::new(
1202-
tcx,
1203-
ObligationCause::misc(
1204-
span,
1205-
self.body.source.def_id().expect_local(),
1206-
),
1207-
self.param_env,
1208-
clause,
1209-
)
1210-
})
1211-
.collect::<Vec<_>>();
1212-
fulfill_cx
1213-
.register_predicate_obligations(self.infcx, obligations);
1214-
// We also register the parent obligation for the type at hand
1215-
// implementing `Clone`, to account for bounds that also need
1216-
// to be evaluated, like ensuring that `Self: Clone`.
1217-
let trait_ref = ty::TraitRef::new(tcx, clone_trait, [ty]);
1218-
let obligation = Obligation::new(
1219-
tcx,
1220-
ObligationCause::dummy(),
1221-
self.param_env,
1222-
trait_ref,
1223-
);
1224-
fulfill_cx
1225-
.register_predicate_obligation(self.infcx, obligation);
1226-
let errors = fulfill_cx.select_all_or_error(self.infcx);
1227-
// We remove the last predicate failure, which corresponds to
1228-
// the top-level obligation, because most of the type we only
1229-
// care about the other ones, *except* when it is the only one.
1230-
// This seems to only be relevant for arbitrary self-types.
1231-
// Look at `tests/ui/moves/move-fn-self-receiver.rs`.
1232-
let errors = match &errors[..] {
1233-
errors @ [] | errors @ [_] | [errors @ .., _] => errors,
1234-
};
1235-
let msg = match &errors[..] {
1236-
[] => "you can `clone` the value and consume it, but this \
1237-
might not be your desired behavior"
1238-
.to_string(),
1239-
[error] => {
1240-
format!(
1241-
"you could `clone` the value and consume it, if \
1242-
the `{}` trait bound could be satisfied",
1243-
error.obligation.predicate,
1244-
)
1245-
}
1246-
[errors @ .., last] => {
1247-
format!(
1248-
"you could `clone` the value and consume it, if \
1249-
the following trait bounds could be satisfied: {} \
1250-
and `{}`",
1251-
errors
1252-
.iter()
1253-
.map(|e| format!(
1254-
"`{}`",
1255-
e.obligation.predicate
1256-
))
1257-
.collect::<Vec<_>>()
1258-
.join(", "),
1259-
last.obligation.predicate,
1260-
)
1261-
}
1262-
};
1263-
err.multipart_suggestion_verbose(
1264-
msg,
1265-
sugg.clone(),
1266-
Applicability::MaybeIncorrect,
1267-
);
1268-
for error in errors {
1269-
if let FulfillmentErrorCode::CodeSelectionError(
1270-
SelectionError::Unimplemented,
1271-
) = error.code
1272-
&& let ty::PredicateKind::Clause(ty::ClauseKind::Trait(
1273-
pred,
1274-
)) = error.obligation.predicate.kind().skip_binder()
1275-
{
1276-
self.infcx.err_ctxt().suggest_derive(
1277-
&error.obligation,
1278-
err,
1279-
error.obligation.predicate.kind().rebind(pred),
1280-
);
1281-
}
1176+
if let Some(errors) =
1177+
self.infcx.could_impl_trait(clone_trait, ty, self.param_env)
1178+
&& !has_sugg
1179+
{
1180+
let msg = match &errors[..] {
1181+
[] => "you can `clone` the value and consume it, but this \
1182+
might not be your desired behavior"
1183+
.to_string(),
1184+
[error] => {
1185+
format!(
1186+
"you could `clone` the value and consume it, if \
1187+
the `{}` trait bound could be satisfied",
1188+
error.obligation.predicate,
1189+
)
1190+
}
1191+
[errors @ .., last] => {
1192+
format!(
1193+
"you could `clone` the value and consume it, if \
1194+
the following trait bounds could be satisfied: {} \
1195+
and `{}`",
1196+
errors
1197+
.iter()
1198+
.map(|e| format!("`{}`", e.obligation.predicate))
1199+
.collect::<Vec<_>>()
1200+
.join(", "),
1201+
last.obligation.predicate,
1202+
)
1203+
}
1204+
};
1205+
err.multipart_suggestion_verbose(
1206+
msg,
1207+
sugg.clone(),
1208+
Applicability::MaybeIncorrect,
1209+
);
1210+
for error in errors {
1211+
if let FulfillmentErrorCode::CodeSelectionError(
1212+
SelectionError::Unimplemented,
1213+
) = error.code
1214+
&& let ty::PredicateKind::Clause(ty::ClauseKind::Trait(
1215+
pred,
1216+
)) = error.obligation.predicate.kind().skip_binder()
1217+
{
1218+
self.infcx.err_ctxt().suggest_derive(
1219+
&error.obligation,
1220+
err,
1221+
error.obligation.predicate.kind().rebind(pred),
1222+
);
12821223
}
12831224
}
1284-
});
1225+
}
12851226
}
12861227
}
12871228
}

compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs

+38-71
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use rustc_hir::{
2121
StmtKind, TyKind, WherePredicate,
2222
};
2323
use rustc_hir_analysis::astconv::AstConv;
24-
use rustc_infer::traits::{self, StatementAsExpression, TraitEngineExt};
24+
use rustc_infer::traits::{self, StatementAsExpression};
2525
use rustc_middle::lint::in_external_macro;
2626
use rustc_middle::middle::stability::EvalResult;
2727
use rustc_middle::ty::print::with_no_trimmed_paths;
@@ -34,7 +34,6 @@ use rustc_span::source_map::Spanned;
3434
use rustc_span::symbol::{sym, Ident};
3535
use rustc_span::{Span, Symbol};
3636
use rustc_trait_selection::infer::InferCtxtExt;
37-
use rustc_trait_selection::solve::FulfillmentCtxt;
3837
use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt;
3938
use rustc_trait_selection::traits::error_reporting::DefIdOrName;
4039
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
@@ -1604,78 +1603,46 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16041603
None,
16051604
);
16061605
} else {
1607-
self.infcx.probe(|_snapshot| {
1608-
if let ty::Adt(def, args) = expected_ty.kind()
1609-
&& let Some((def_id, _imp)) = self
1610-
.tcx
1611-
.all_impls(clone_trait_did)
1612-
.filter_map(|def_id| {
1613-
self.tcx.impl_trait_ref(def_id).map(|r| (def_id, r))
1614-
})
1615-
.map(|(def_id, imp)| (def_id, imp.skip_binder()))
1616-
.filter(|(_, imp)| match imp.self_ty().peel_refs().kind() {
1617-
ty::Adt(i_def, _) if i_def.did() == def.did() => true,
1618-
_ => false,
1619-
})
1620-
.next()
1621-
{
1622-
let mut fulfill_cx = FulfillmentCtxt::new(&self.infcx);
1623-
// We get all obligations from the impl to talk about specific
1624-
// trait bounds.
1625-
let obligations = self
1626-
.tcx
1627-
.predicates_of(def_id)
1628-
.instantiate(self.tcx, args)
1629-
.into_iter()
1630-
.map(|(clause, span)| {
1631-
traits::Obligation::new(
1632-
self.tcx,
1633-
traits::ObligationCause::misc(span, self.body_id),
1634-
self.param_env,
1635-
clause,
1636-
)
1637-
})
1638-
.collect::<Vec<_>>();
1639-
fulfill_cx.register_predicate_obligations(&self.infcx, obligations);
1640-
let errors = fulfill_cx.select_all_or_error(&self.infcx);
1641-
match &errors[..] {
1642-
[] => {}
1643-
[error] => {
1644-
diag.help(format!(
1645-
"`Clone` is not implemented because the trait bound `{}` is \
1646-
not satisfied",
1647-
error.obligation.predicate,
1648-
));
1649-
}
1650-
[errors @ .., last] => {
1651-
diag.help(format!(
1652-
"`Clone` is not implemented because the following trait bounds \
1653-
could not be satisfied: {} and `{}`",
1654-
errors
1655-
.iter()
1656-
.map(|e| format!("`{}`", e.obligation.predicate))
1657-
.collect::<Vec<_>>()
1658-
.join(", "),
1659-
last.obligation.predicate,
1660-
));
1661-
}
1606+
if let Some(errors) =
1607+
self.could_impl_trait(clone_trait_did, expected_ty, self.param_env)
1608+
{
1609+
match &errors[..] {
1610+
[] => {}
1611+
[error] => {
1612+
diag.help(format!(
1613+
"`Clone` is not implemented because the trait bound `{}` is \
1614+
not satisfied",
1615+
error.obligation.predicate,
1616+
));
16621617
}
1663-
for error in errors {
1664-
if let traits::FulfillmentErrorCode::CodeSelectionError(
1665-
traits::SelectionError::Unimplemented,
1666-
) = error.code
1667-
&& let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) =
1668-
error.obligation.predicate.kind().skip_binder()
1669-
{
1670-
self.infcx.err_ctxt().suggest_derive(
1671-
&error.obligation,
1672-
diag,
1673-
error.obligation.predicate.kind().rebind(pred),
1674-
);
1675-
}
1618+
[errors @ .., last] => {
1619+
diag.help(format!(
1620+
"`Clone` is not implemented because the following trait bounds \
1621+
could not be satisfied: {} and `{}`",
1622+
errors
1623+
.iter()
1624+
.map(|e| format!("`{}`", e.obligation.predicate))
1625+
.collect::<Vec<_>>()
1626+
.join(", "),
1627+
last.obligation.predicate,
1628+
));
16761629
}
16771630
}
1678-
});
1631+
for error in errors {
1632+
if let traits::FulfillmentErrorCode::CodeSelectionError(
1633+
traits::SelectionError::Unimplemented,
1634+
) = error.code
1635+
&& let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) =
1636+
error.obligation.predicate.kind().skip_binder()
1637+
{
1638+
self.infcx.err_ctxt().suggest_derive(
1639+
&error.obligation,
1640+
diag,
1641+
error.obligation.predicate.kind().rebind(pred),
1642+
);
1643+
}
1644+
}
1645+
}
16791646
self.suggest_derive(diag, &[(trait_ref.to_predicate(self.tcx), None, None)]);
16801647
}
16811648
}

0 commit comments

Comments
 (0)