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

@ -3,6 +3,7 @@
use crate::arena::Arena;
use crate::dep_graph::DepGraph;
use crate::hir::exports::ExportMap;
use crate::hir::place::Place as HirPlace;
use crate::ich::{NodeIdHashingMode, StableHashingContext};
use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos};
use crate::lint::{struct_lint_level, LintDiagnosticBuilder, LintLevelSource};
@ -379,7 +380,7 @@ pub struct TypeckResults<'tcx> {
/// Records the reasons that we picked the kind of each closure;
/// not all closures are present in the map.
closure_kind_origins: ItemLocalMap<(Span, Symbol)>,
closure_kind_origins: ItemLocalMap<(Span, HirPlace<'tcx>)>,
/// For each fn, records the "liberated" types of its arguments
/// and return type. Liberated means that all bound regions
@ -642,11 +643,13 @@ impl<'tcx> TypeckResults<'tcx> {
self.upvar_capture_map[&upvar_id]
}
pub fn closure_kind_origins(&self) -> LocalTableInContext<'_, (Span, Symbol)> {
pub fn closure_kind_origins(&self) -> LocalTableInContext<'_, (Span, HirPlace<'tcx>)> {
LocalTableInContext { hir_owner: self.hir_owner, data: &self.closure_kind_origins }
}
pub fn closure_kind_origins_mut(&mut self) -> LocalTableInContextMut<'_, (Span, Symbol)> {
pub fn closure_kind_origins_mut(
&mut self,
) -> LocalTableInContextMut<'_, (Span, HirPlace<'tcx>)> {
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.closure_kind_origins }
}

View file

@ -17,7 +17,9 @@ pub use self::IntVarValue::*;
pub use self::Variance::*;
use crate::hir::exports::ExportMap;
use crate::hir::place::Place as HirPlace;
use crate::hir::place::{
Place as HirPlace, PlaceBase as HirPlaceBase, ProjectionKind as HirProjectionKind,
};
use crate::ich::StableHashingContext;
use crate::middle::cstore::CrateStoreDyn;
use crate::middle::resolve_lifetime::ObjectLifetimeDefault;
@ -734,6 +736,43 @@ pub struct CapturedPlace<'tcx> {
pub info: CaptureInfo<'tcx>,
}
pub fn place_to_string_for_capture(tcx: TyCtxt<'tcx>, place: &HirPlace<'tcx>) -> String {
let name = match place.base {
HirPlaceBase::Upvar(upvar_id) => tcx.hir().name(upvar_id.var_path.hir_id).to_string(),
_ => bug!("Capture_information should only contain upvars"),
};
let mut curr_string = name;
for (i, proj) in place.projections.iter().enumerate() {
match proj.kind {
HirProjectionKind::Deref => {
curr_string = format!("*{}", curr_string);
}
HirProjectionKind::Field(idx, variant) => match place.ty_before_projection(i).kind() {
ty::Adt(def, ..) => {
curr_string = format!(
"{}.{}",
curr_string,
def.variants[variant].fields[idx as usize].ident.name.as_str()
);
}
ty::Tuple(_) => {
curr_string = format!("{}.{}", curr_string, idx);
}
_ => {
bug!(
"Field projection applied to a type other than Adt or Tuple: {:?}.",
place.ty_before_projection(i).kind()
)
}
},
proj => bug!("{:?} unexpected because it isn't captured", proj),
}
}
curr_string.to_string()
}
/// Part of `MinCaptureInformationMap`; describes the capture kind (&, &mut, move)
/// for a particular capture as well as identifying the part of the source code
/// that triggered this capture to occur.