Skip to content

Commit bc4404c

Browse files
committed
improve handling for subtype
Still not great, but good enough to land this PR.
1 parent a24e04d commit bc4404c

37 files changed

+233
-379
lines changed

src/librustc/infer/error_reporting/mod.rs

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -132,12 +132,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
132132

133133
ty::ReEmpty => ("the empty lifetime".to_owned(), None),
134134

135+
ty::RePlaceholder(_) => (format!("any other region"), None),
136+
135137
// FIXME(#13998) RePlaceholder should probably print like
136138
// ReFree rather than dumping Debug output on the user.
137139
//
138140
// We shouldn't really be having unification failures with ReVar
139141
// and ReLateBound though.
140-
ty::RePlaceholder(..) | ty::ReVar(_) | ty::ReLateBound(..) | ty::ReErased => {
142+
ty::ReVar(_) | ty::ReLateBound(..) | ty::ReErased => {
141143
(format!("lifetime {:?}", region), None)
142144
}
143145

@@ -324,8 +326,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
324326
// the error. If all of these fails, we fall back to a rather
325327
// general bit of code that displays the error information
326328
RegionResolutionError::ConcreteFailure(origin, sub, sup) => {
327-
self.report_concrete_failure(region_scope_tree, origin, sub, sup)
328-
.emit();
329+
if sub.is_placeholder() || sup.is_placeholder() {
330+
self.report_placeholder_failure(region_scope_tree, origin, sub, sup)
331+
.emit();
332+
} else {
333+
self.report_concrete_failure(region_scope_tree, origin, sub, sup)
334+
.emit();
335+
}
329336
}
330337

331338
RegionResolutionError::GenericBoundFailure(origin, param_ty, sub) => {
@@ -346,14 +353,32 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
346353
sup_origin,
347354
sup_r,
348355
) => {
349-
self.report_sub_sup_conflict(
350-
region_scope_tree,
351-
var_origin,
352-
sub_origin,
353-
sub_r,
354-
sup_origin,
355-
sup_r,
356-
);
356+
if sub_r.is_placeholder() {
357+
self.report_placeholder_failure(
358+
region_scope_tree,
359+
sub_origin,
360+
sub_r,
361+
sup_r,
362+
)
363+
.emit();
364+
} else if sup_r.is_placeholder() {
365+
self.report_placeholder_failure(
366+
region_scope_tree,
367+
sup_origin,
368+
sub_r,
369+
sup_r,
370+
)
371+
.emit();
372+
} else {
373+
self.report_sub_sup_conflict(
374+
region_scope_tree,
375+
var_origin,
376+
sub_origin,
377+
sub_r,
378+
sup_origin,
379+
sup_r,
380+
);
381+
}
357382
}
358383
}
359384
}

src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs

Lines changed: 64 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,16 @@ impl NiceRegionError<'me, 'gcx, 'tcx> {
1414
/// When given a `ConcreteFailure` for a function with arguments containing a named region and
1515
/// an anonymous region, emit an descriptive diagnostic error.
1616
pub(super) fn try_report_placeholder_conflict(&self) -> Option<ErrorReported> {
17-
// Check for the first case: relating two trait-refs, and we
18-
// find a conflict between two placeholders.
1917
match &self.error {
18+
///////////////////////////////////////////////////////////////////////////
19+
// NB. The ordering of cases in this match is very
20+
// sensitive, because we are often matching against
21+
// specific cases and then using an `_` to match all
22+
// others.
23+
24+
///////////////////////////////////////////////////////////////////////////
25+
// Check for errors from comparing trait failures -- first
26+
// with two placeholders, then with one.
2027
Some(RegionResolutionError::SubSupConflict(
2128
vid,
2229
_,
@@ -27,19 +34,19 @@ impl NiceRegionError<'me, 'gcx, 'tcx> {
2734
sub_placeholder @ ty::RePlaceholder(_),
2835
_,
2936
sup_placeholder @ ty::RePlaceholder(_),
30-
)) => if expected.def_id == found.def_id {
31-
return Some(self.try_report_placeholders_trait(
37+
))
38+
if expected.def_id == found.def_id =>
39+
{
40+
Some(self.try_report_placeholders_trait(
3241
Some(self.tcx.mk_region(ty::ReVar(*vid))),
3342
cause,
3443
Some(sub_placeholder),
3544
Some(sup_placeholder),
3645
expected.def_id,
3746
expected.substs,
3847
found.substs,
39-
));
40-
} else {
41-
// I actually can't see why this would be the case ever.
42-
},
48+
))
49+
}
4350

4451
Some(RegionResolutionError::SubSupConflict(
4552
vid,
@@ -51,19 +58,19 @@ impl NiceRegionError<'me, 'gcx, 'tcx> {
5158
sub_placeholder @ ty::RePlaceholder(_),
5259
_,
5360
_,
54-
)) => if expected.def_id == found.def_id {
55-
return Some(self.try_report_placeholders_trait(
61+
))
62+
if expected.def_id == found.def_id =>
63+
{
64+
Some(self.try_report_placeholders_trait(
5665
Some(self.tcx.mk_region(ty::ReVar(*vid))),
5766
cause,
5867
Some(sub_placeholder),
5968
None,
6069
expected.def_id,
6170
expected.substs,
6271
found.substs,
63-
));
64-
} else {
65-
// I actually can't see why this would be the case ever.
66-
},
72+
))
73+
}
6774

6875
Some(RegionResolutionError::SubSupConflict(
6976
vid,
@@ -75,48 +82,40 @@ impl NiceRegionError<'me, 'gcx, 'tcx> {
7582
_,
7683
_,
7784
sup_placeholder @ ty::RePlaceholder(_),
78-
)) => if expected.def_id == found.def_id {
79-
return Some(self.try_report_placeholders_trait(
85+
))
86+
if expected.def_id == found.def_id =>
87+
{
88+
Some(self.try_report_placeholders_trait(
8089
Some(self.tcx.mk_region(ty::ReVar(*vid))),
8190
cause,
8291
None,
8392
Some(*sup_placeholder),
8493
expected.def_id,
8594
expected.substs,
8695
found.substs,
87-
));
88-
} else {
89-
// I actually can't see why this would be the case ever.
90-
},
91-
92-
Some(RegionResolutionError::ConcreteFailure(
93-
SubregionOrigin::Subtype(TypeTrace { .. }),
94-
ty::RePlaceholder(_),
95-
ty::RePlaceholder(_),
96-
)) => {
97-
// I actually can't see why this would be the case ever.
96+
))
9897
}
9998

10099
Some(RegionResolutionError::ConcreteFailure(
101100
SubregionOrigin::Subtype(TypeTrace {
102101
cause,
103102
values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
104103
}),
105-
sub_region,
104+
sub_region @ ty::RePlaceholder(_),
106105
sup_region @ ty::RePlaceholder(_),
107-
)) => if expected.def_id == found.def_id {
108-
return Some(self.try_report_placeholders_trait(
109-
Some(sub_region),
110-
cause,
106+
))
107+
if expected.def_id == found.def_id =>
108+
{
109+
Some(self.try_report_placeholders_trait(
111110
None,
111+
cause,
112+
Some(*sub_region),
112113
Some(*sup_region),
113114
expected.def_id,
114115
expected.substs,
115116
found.substs,
116-
));
117-
} else {
118-
// I actually can't see why this would be the case ever.
119-
},
117+
))
118+
}
120119

121120
Some(RegionResolutionError::ConcreteFailure(
122121
SubregionOrigin::Subtype(TypeTrace {
@@ -125,24 +124,43 @@ impl NiceRegionError<'me, 'gcx, 'tcx> {
125124
}),
126125
sub_region @ ty::RePlaceholder(_),
127126
sup_region,
128-
)) => if expected.def_id == found.def_id {
129-
return Some(self.try_report_placeholders_trait(
127+
))
128+
if expected.def_id == found.def_id =>
129+
{
130+
Some(self.try_report_placeholders_trait(
130131
Some(sup_region),
131132
cause,
132-
None,
133133
Some(*sub_region),
134+
None,
134135
expected.def_id,
135136
expected.substs,
136137
found.substs,
137-
));
138-
} else {
139-
// I actually can't see why this would be the case ever.
140-
},
138+
))
139+
}
141140

142-
_ => {}
143-
}
141+
Some(RegionResolutionError::ConcreteFailure(
142+
SubregionOrigin::Subtype(TypeTrace {
143+
cause,
144+
values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
145+
}),
146+
sub_region,
147+
sup_region @ ty::RePlaceholder(_),
148+
))
149+
if expected.def_id == found.def_id =>
150+
{
151+
Some(self.try_report_placeholders_trait(
152+
Some(sub_region),
153+
cause,
154+
None,
155+
Some(*sup_region),
156+
expected.def_id,
157+
expected.substs,
158+
found.substs,
159+
))
160+
}
144161

145-
None
162+
_ => None,
163+
}
146164
}
147165

148166
// error[E0308]: implementation of `Foo` does not apply to enough lifetimes

src/librustc/infer/error_reporting/note.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,4 +442,24 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
442442
}
443443
}
444444
}
445+
446+
pub(super) fn report_placeholder_failure(
447+
&self,
448+
region_scope_tree: &region::ScopeTree,
449+
placeholder_origin: SubregionOrigin<'tcx>,
450+
sub: Region<'tcx>,
451+
sup: Region<'tcx>,
452+
) -> DiagnosticBuilder<'tcx> {
453+
// I can't think how to do better than this right now. -nikomatsakis
454+
match placeholder_origin {
455+
infer::Subtype(trace) => {
456+
let terr = TypeError::RegionsPlaceholderMismatch;
457+
self.report_and_explain_type_error(trace, &terr)
458+
}
459+
460+
_ => {
461+
self.report_concrete_failure(region_scope_tree, placeholder_origin, sub, sup)
462+
}
463+
}
464+
}
445465
}

src/librustc/infer/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ pub struct InferCtxt<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
225225
pub type PlaceholderMap<'tcx> = BTreeMap<ty::BoundRegion, ty::Region<'tcx>>;
226226

227227
/// See `error_reporting` module for more details
228-
#[derive(Clone, Debug)]
228+
#[derive(Clone, Debug, PartialEq, Eq)]
229229
pub enum ValuePairs<'tcx> {
230230
Types(ExpectedFound<Ty<'tcx>>),
231231
Regions(ExpectedFound<ty::Region<'tcx>>),

src/librustc/ty/error.rs

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use hir::def_id::DefId;
2-
use ty::{self, BoundRegion, Region, Ty, TyCtxt};
2+
use ty::{self, Region, Ty, TyCtxt};
33
use std::borrow::Cow;
44
use std::fmt;
55
use rustc_target::spec::abi;
@@ -9,7 +9,7 @@ use syntax_pos::Span;
99

1010
use hir;
1111

12-
#[derive(Clone, Copy, Debug)]
12+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1313
pub struct ExpectedFound<T> {
1414
pub expected: T,
1515
pub found: T,
@@ -27,8 +27,7 @@ pub enum TypeError<'tcx> {
2727
ArgCount,
2828

2929
RegionsDoesNotOutlive(Region<'tcx>, Region<'tcx>),
30-
RegionsInsufficientlyPolymorphic(BoundRegion, Region<'tcx>),
31-
RegionsOverlyPolymorphic(BoundRegion, Region<'tcx>),
30+
RegionsPlaceholderMismatch,
3231

3332
Sorts(ExpectedFound<Ty<'tcx>>),
3433
IntMismatch(ExpectedFound<ty::IntVarValue>),
@@ -102,17 +101,8 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
102101
RegionsDoesNotOutlive(..) => {
103102
write!(f, "lifetime mismatch")
104103
}
105-
RegionsInsufficientlyPolymorphic(br, _) => {
106-
write!(f,
107-
"expected bound lifetime parameter{}{}, found concrete lifetime",
108-
if br.is_named() { " " } else { "" },
109-
br)
110-
}
111-
RegionsOverlyPolymorphic(br, _) => {
112-
write!(f,
113-
"expected concrete lifetime, found bound lifetime parameter{}{}",
114-
if br.is_named() { " " } else { "" },
115-
br)
104+
RegionsPlaceholderMismatch => {
105+
write!(f, "one type is more general than the other")
116106
}
117107
Sorts(values) => ty::tls::with(|tcx| {
118108
report_maybe_different(f, &values.expected.sort_string(tcx),

src/librustc/ty/structural_impls.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -434,12 +434,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> {
434434
RegionsDoesNotOutlive(a, b) => {
435435
return tcx.lift(&(a, b)).map(|(a, b)| RegionsDoesNotOutlive(a, b))
436436
}
437-
RegionsInsufficientlyPolymorphic(a, b) => {
438-
return tcx.lift(&b).map(|b| RegionsInsufficientlyPolymorphic(a, b))
439-
}
440-
RegionsOverlyPolymorphic(a, b) => {
441-
return tcx.lift(&b).map(|b| RegionsOverlyPolymorphic(a, b))
442-
}
437+
RegionsPlaceholderMismatch => RegionsPlaceholderMismatch,
443438
IntMismatch(x) => IntMismatch(x),
444439
FloatMismatch(x) => FloatMismatch(x),
445440
Traits(x) => Traits(x),
@@ -1006,8 +1001,7 @@ EnumTypeFoldableImpl! {
10061001
(ty::error::TypeError::FixedArraySize)(x),
10071002
(ty::error::TypeError::ArgCount),
10081003
(ty::error::TypeError::RegionsDoesNotOutlive)(a, b),
1009-
(ty::error::TypeError::RegionsInsufficientlyPolymorphic)(a, b),
1010-
(ty::error::TypeError::RegionsOverlyPolymorphic)(a, b),
1004+
(ty::error::TypeError::RegionsPlaceholderMismatch),
10111005
(ty::error::TypeError::IntMismatch)(x),
10121006
(ty::error::TypeError::FloatMismatch)(x),
10131007
(ty::error::TypeError::Traits)(x),

src/librustc/ty/sty.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1396,6 +1396,13 @@ impl RegionKind {
13961396
}
13971397
}
13981398

1399+
pub fn is_placeholder(&self) -> bool {
1400+
match *self {
1401+
ty::RePlaceholder(..) => true,
1402+
_ => false,
1403+
}
1404+
}
1405+
13991406
pub fn bound_at_or_above_binder(&self, index: DebruijnIndex) -> bool {
14001407
match *self {
14011408
ty::ReLateBound(debruijn, _) => debruijn >= index,

0 commit comments

Comments
 (0)