diff options
| author | Mara Bos <m-ou.se@m-ou.se> | 2021-01-17 12:24:44 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-01-17 12:24:44 +0000 |
| commit | 19f97802cacd60b68a3fdcbda198cbe3d3c6878f (patch) | |
| tree | 8627021c1234f359214c5e6efe6cf7ebad35004d /compiler/rustc_middle/src | |
| parent | 152f425dcb118f5e92a060d259d3b5236aa59333 (diff) | |
| parent | b498870d9c992e61e0f7930f2679b091b5f2ddbc (diff) | |
| download | rust-19f97802cacd60b68a3fdcbda198cbe3d3c6878f.tar.gz rust-19f97802cacd60b68a3fdcbda198cbe3d3c6878f.zip | |
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```
Diffstat (limited to 'compiler/rustc_middle/src')
| -rw-r--r-- | compiler/rustc_middle/src/ty/context.rs | 9 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/mod.rs | 41 |
2 files changed, 46 insertions, 4 deletions
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 148ac604596..1f7dc7bb79d 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -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 } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 1399fc76e02..b1769b17b42 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -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. |
