Skip to content

Commit 0b15a66

Browse files
committed
account for the pick-constraint edges when reporting errors
Also, thread through better span info to improve the error message to something tolerable.
1 parent 3e01c74 commit 0b15a66

File tree

10 files changed

+195
-18
lines changed

10 files changed

+195
-18
lines changed

src/librustc/infer/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -910,13 +910,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
910910
pub fn pick_constraint(
911911
&self,
912912
opaque_type_def_id: DefId,
913+
definition_span: Span,
913914
hidden_ty: Ty<'tcx>,
914915
region: ty::Region<'tcx>,
915916
in_regions: &Rc<Vec<ty::Region<'tcx>>>,
916917
) {
917918
debug!("sub_regions({:?} <: {:?})", region, in_regions);
918919
self.borrow_region_constraints()
919-
.pick_constraint(opaque_type_def_id, hidden_ty, region, in_regions);
920+
.pick_constraint(opaque_type_def_id, definition_span, hidden_ty, region, in_regions);
920921
}
921922

922923
pub fn subtype_predicate(

src/librustc/infer/opaque_types/mod.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use crate::util::nodemap::DefIdMap;
1212
use errors::DiagnosticBuilder;
1313
use rustc_data_structures::fx::FxHashMap;
1414
use std::rc::Rc;
15+
use syntax_pos::Span;
1516

1617
pub type OpaqueTypeMap<'tcx> = DefIdMap<OpaqueTypeDecl<'tcx>>;
1718

@@ -33,6 +34,20 @@ pub struct OpaqueTypeDecl<'tcx> {
3334
/// then `substs` would be `['a, T]`.
3435
pub substs: SubstsRef<'tcx>,
3536

37+
/// The span of this particular definition of the opaque type. So
38+
/// for example:
39+
///
40+
/// ```
41+
/// existential type Foo;
42+
/// fn bar() -> Foo {
43+
/// ^^^ this is the span we are looking for!
44+
/// ```
45+
///
46+
/// In cases where the fn returns `(impl Trait, impl Trait)` or
47+
/// other such combinations, the result is currently
48+
/// over-approximated, but better than nothing.
49+
pub definition_span: Span,
50+
3651
/// The type variable that represents the value of the abstract type
3752
/// that we require. In other words, after we compile this function,
3853
/// we will be created a constraint like:
@@ -99,12 +114,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
99114
/// - `param_env` -- the in-scope parameter environment to be used for
100115
/// obligations
101116
/// - `value` -- the value within which we are instantiating opaque types
117+
/// - `value_span` -- the span where the value came from, used in error reporting
102118
pub fn instantiate_opaque_types<T: TypeFoldable<'tcx>>(
103119
&self,
104120
parent_def_id: DefId,
105121
body_id: hir::HirId,
106122
param_env: ty::ParamEnv<'tcx>,
107123
value: &T,
124+
value_span: Span,
108125
) -> InferOk<'tcx, (T, OpaqueTypeMap<'tcx>)> {
109126
debug!(
110127
"instantiate_opaque_types(value={:?}, parent_def_id={:?}, body_id={:?}, \
@@ -116,6 +133,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
116133
parent_def_id,
117134
body_id,
118135
param_env,
136+
value_span,
119137
opaque_types: Default::default(),
120138
obligations: vec![],
121139
};
@@ -427,6 +445,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
427445
tcx: self.tcx,
428446
op: |r| self.pick_constraint(
429447
opaque_type_def_id,
448+
opaque_defn.definition_span,
430449
concrete_ty,
431450
r,
432451
&option_regions,
@@ -807,6 +826,7 @@ struct Instantiator<'a, 'tcx> {
807826
parent_def_id: DefId,
808827
body_id: hir::HirId,
809828
param_env: ty::ParamEnv<'tcx>,
829+
value_span: Span,
810830
opaque_types: OpaqueTypeMap<'tcx>,
811831
obligations: Vec<PredicateObligation<'tcx>>,
812832
}
@@ -954,10 +974,18 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
954974
debug!("instantiate_opaque_types: param_env={:#?}", self.param_env,);
955975
debug!("instantiate_opaque_types: generics={:#?}", tcx.generics_of(def_id),);
956976

977+
// Ideally, we'd get the span where *this specific `ty` came
978+
// from*, but right now we just use the span from the overall
979+
// value being folded. In simple cases like `-> impl Foo`,
980+
// these are the same span, but not in cases like `-> (impl
981+
// Foo, impl Bar)`.
982+
let definition_span = self.value_span;
983+
957984
self.opaque_types.insert(
958985
def_id,
959986
OpaqueTypeDecl {
960987
substs,
988+
definition_span,
961989
concrete_ty: ty_var,
962990
has_required_region_bounds: !required_region_bounds.is_empty(),
963991
origin,

src/librustc/infer/region_constraints/mod.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use crate::ty::ReStatic;
1414
use crate::ty::{self, Ty, TyCtxt};
1515
use crate::ty::{ReLateBound, ReVar};
1616
use crate::ty::{Region, RegionVid};
17+
use syntax_pos::Span;
1718

1819
use std::collections::BTreeMap;
1920
use std::{cmp, fmt, mem};
@@ -155,6 +156,9 @@ pub struct PickConstraint<'tcx> {
155156
/// the def-id of the opaque type causing this constraint: used for error reporting
156157
pub opaque_type_def_id: DefId,
157158

159+
/// the span where the hidden type was instantiated
160+
pub definition_span: Span,
161+
158162
/// the hidden type in which `pick_region` appears: used for error reporting
159163
pub hidden_ty: Ty<'tcx>,
160164

@@ -167,14 +171,14 @@ pub struct PickConstraint<'tcx> {
167171

168172
BraceStructTypeFoldableImpl! {
169173
impl<'tcx> TypeFoldable<'tcx> for PickConstraint<'tcx> {
170-
opaque_type_def_id, hidden_ty, pick_region, option_regions
174+
opaque_type_def_id, definition_span, hidden_ty, pick_region, option_regions
171175
}
172176
}
173177

174178
BraceStructLiftImpl! {
175179
impl<'a, 'tcx> Lift<'tcx> for PickConstraint<'a> {
176180
type Lifted = PickConstraint<'tcx>;
177-
opaque_type_def_id, hidden_ty, pick_region, option_regions
181+
opaque_type_def_id, definition_span, hidden_ty, pick_region, option_regions
178182
}
179183
}
180184

@@ -687,6 +691,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
687691
pub fn pick_constraint(
688692
&mut self,
689693
opaque_type_def_id: DefId,
694+
definition_span: Span,
690695
hidden_ty: Ty<'tcx>,
691696
pick_region: ty::Region<'tcx>,
692697
option_regions: &Rc<Vec<ty::Region<'tcx>>>,
@@ -699,6 +704,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
699704

700705
self.data.pick_constraints.push(PickConstraint {
701706
opaque_type_def_id,
707+
definition_span,
702708
hidden_ty,
703709
pick_region,
704710
option_regions: option_regions.clone()

src/librustc_mir/borrow_check/nll/pick_constraints.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use rustc_data_structures::fx::FxHashMap;
55
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
66
use std::hash::Hash;
77
use std::ops::Index;
8+
use syntax_pos::Span;
89

910
/// Compactly stores a set of `pick R0 in [R1...Rn]` constraints,
1011
/// indexed by the region R0.
@@ -34,6 +35,9 @@ crate struct NllPickConstraint<'tcx> {
3435
/// The opaque type whose hidden type is being inferred. (Used in error reporting.)
3536
crate opaque_type_def_id: DefId,
3637

38+
/// The span where the hidden type was instantiated.
39+
crate definition_span: Span,
40+
3741
/// The hidden type in which R0 appears. (Used in error reporting.)
3842
crate hidden_ty: Ty<'tcx>,
3943

@@ -79,6 +83,7 @@ impl<'tcx> PickConstraintSet<'tcx, ty::RegionVid> {
7983
next_constraint,
8084
pick_region_vid,
8185
opaque_type_def_id: p_c.opaque_type_def_id,
86+
definition_span: p_c.definition_span,
8287
hidden_ty: p_c.hidden_ty,
8388
start_index,
8489
end_index,

src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::borrow_check::nll::constraints::OutlivesConstraint;
2+
use crate::borrow_check::nll::region_infer::AppliedPickConstraint;
23
use crate::borrow_check::nll::region_infer::RegionInferenceContext;
34
use crate::borrow_check::nll::type_check::Locations;
45
use crate::borrow_check::nll::universal_regions::DefiningTy;
@@ -195,6 +196,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
195196
Trace::NotVisited => {
196197
bug!("found unvisited region {:?} on path to {:?}", p, r)
197198
}
199+
198200
Trace::FromOutlivesConstraint(c) => {
199201
result.push(c);
200202
p = c.sup;
@@ -211,10 +213,30 @@ impl<'tcx> RegionInferenceContext<'tcx> {
211213
// Otherwise, walk over the outgoing constraints and
212214
// enqueue any regions we find, keeping track of how we
213215
// reached them.
216+
217+
// A constraint like `'r: 'x` can come from our constraint
218+
// graph.
214219
let fr_static = self.universal_regions.fr_static;
215-
for constraint in self.constraint_graph
216-
.outgoing_edges(r, &self.constraints, fr_static)
217-
{
220+
let outgoing_edges_from_graph = self.constraint_graph
221+
.outgoing_edges(r, &self.constraints, fr_static);
222+
223+
224+
// But pick-constraints can also give rise to `'r: 'x`
225+
// edges that were not part of the graph initially, so
226+
// watch out for those.
227+
let outgoing_edges_from_picks = self.applied_pick_constraints(r)
228+
.iter()
229+
.map(|&AppliedPickConstraint { best_option, pick_constraint_index, .. }| {
230+
let p_c = &self.pick_constraints[pick_constraint_index];
231+
OutlivesConstraint {
232+
sup: r,
233+
sub: best_option,
234+
locations: Locations::All(p_c.definition_span),
235+
category: ConstraintCategory::OpaqueType,
236+
}
237+
});
238+
239+
for constraint in outgoing_edges_from_graph.chain(outgoing_edges_from_picks) {
218240
debug_assert_eq!(constraint.sup, r);
219241
let sub_region = constraint.sub;
220242
if let Trace::NotVisited = context[sub_region] {
@@ -687,7 +709,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
687709

688710
// Finds some region R such that `fr1: R` and `R` is live at
689711
// `elem`.
690-
crate fn find_sub_region_live_at(&self, fr1: RegionVid, elem: Location) -> RegionVid {
712+
crate fn find_sub_region_live_at(
713+
&self,
714+
fr1: RegionVid,
715+
elem: Location,
716+
) -> RegionVid {
691717
debug!("find_sub_region_live_at(fr1={:?}, elem={:?})", fr1, elem);
692718
self.find_constraint_paths_between_regions(fr1, |r| {
693719
// First look for some `r` such that `fr1: r` and `r` is live at `elem`
@@ -729,8 +755,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
729755
fr1: RegionVid,
730756
fr2: RegionVid,
731757
) -> (ConstraintCategory, Span) {
732-
let (category, _, span) =
733-
self.best_blame_constraint(body, fr1, |r| self.provides_universal_region(r, fr1, fr2));
758+
let (category, _, span) = self.best_blame_constraint(
759+
body,
760+
fr1,
761+
|r| self.provides_universal_region(r, fr1, fr2),
762+
);
734763
(category, span)
735764
}
736765

0 commit comments

Comments
 (0)