1
Fork 0

Rollup merge of #80635 - sexxi-goose:use-place-instead-of-symbol, r=nikomatsakis`

Improve diagnostics when closure doesn't meet trait bound

Improves the diagnostics when closure doesn't meet trait bound by modifying `TypeckResuts::closure_kind_origins` such that `hir::Place` is used instead of `Symbol`. Using `hir::Place` to describe which capture influenced the decision of selecting a trait a closure satisfies to (Fn/FnMut/FnOnce, Copy) allows us to show precise path in the diagnostics when `capture_disjoint_field` feature is enabled.

Closes rust-lang/project-rfc-2229/issues/21

r? ```@nikomatsakis```
This commit is contained in:
Mara Bos 2021-01-17 12:24:44 +00:00 committed by GitHub
commit 19f97802ca
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 328 additions and 23 deletions

View file

@ -176,7 +176,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.demand_eqtype(span, inferred_kind.to_ty(self.tcx), closure_kind_ty);
// If we have an origin, store it.
if let Some(origin) = delegate.current_origin {
if let Some(origin) = delegate.current_origin.clone() {
let origin = if self.tcx.features().capture_disjoint_fields {
origin
} else {
// FIXME(project-rfc-2229#26): Once rust-lang#80092 is merged, we should restrict the
// precision of origin as well. Otherwise, this will cause issues when project-rfc-2229#26
// is fixed as we might see Index projections in the origin, which we can't print because
// we don't store enough information.
(origin.0, Place { projections: vec![], ..origin.1 })
};
self.typeck_results
.borrow_mut()
.closure_kind_origins_mut()
@ -563,7 +573,7 @@ struct InferBorrowKind<'a, 'tcx> {
// If we modified `current_closure_kind`, this field contains a `Some()` with the
// variable access that caused us to do so.
current_origin: Option<(Span, Symbol)>,
current_origin: Option<(Span, Place<'tcx>)>,
/// For each Place that is captured by the closure, we track the minimal kind of
/// access we need (ref, ref mut, move, etc) and the expression that resulted in such access.
@ -628,7 +638,7 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> {
upvar_id.closure_expr_id,
ty::ClosureKind::FnOnce,
usage_span,
var_name(tcx, upvar_id.var_path.hir_id),
place_with_id.place.clone(),
);
let capture_info = ty::CaptureInfo {
@ -720,7 +730,7 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> {
upvar_id.closure_expr_id,
ty::ClosureKind::FnMut,
tcx.hir().span(diag_expr_id),
var_name(tcx, upvar_id.var_path.hir_id),
place_with_id.place.clone(),
);
}
}
@ -765,11 +775,11 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> {
closure_id: LocalDefId,
new_kind: ty::ClosureKind,
upvar_span: Span,
var_name: Symbol,
place: Place<'tcx>,
) {
debug!(
"adjust_closure_kind(closure_id={:?}, new_kind={:?}, upvar_span={:?}, var_name={})",
closure_id, new_kind, upvar_span, var_name
"adjust_closure_kind(closure_id={:?}, new_kind={:?}, upvar_span={:?}, place={:?})",
closure_id, new_kind, upvar_span, place
);
// Is this the closure whose kind is currently being inferred?
@ -797,7 +807,7 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> {
| (ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
// new kind is stronger than the old kind
self.current_closure_kind = new_kind;
self.current_origin = Some((upvar_span, var_name));
self.current_origin = Some((upvar_span, place));
}
}
}

View file

@ -384,9 +384,11 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner);
let common_hir_owner = fcx_typeck_results.hir_owner;
for (&id, &origin) in fcx_typeck_results.closure_kind_origins().iter() {
let hir_id = hir::HirId { owner: common_hir_owner, local_id: id };
self.typeck_results.closure_kind_origins_mut().insert(hir_id, origin);
for (id, origin) in fcx_typeck_results.closure_kind_origins().iter() {
let hir_id = hir::HirId { owner: common_hir_owner, local_id: *id };
let place_span = origin.0;
let place = self.resolve(origin.1.clone(), &place_span);
self.typeck_results.closure_kind_origins_mut().insert(hir_id, (place_span, place));
}
}