Skip to content

Commit c886894

Browse files
committed
Treat associated types the same as type parameters when it comes to region bounding. Fixes rust-lang#20303.
Strictly speaking, this is a [breaking-change] (if you are using associated types). You are no longer free to wantonly violate the type system rules by closing associated types into objects without any form of region bound. Instead you should add region bounds like `T::X : 'a`, just as you would with a normal type parameter.
1 parent 8e83af6 commit c886894

File tree

7 files changed

+275
-104
lines changed

7 files changed

+275
-104
lines changed

src/librustc/middle/infer/error_reporting.rs

+31-28
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ use super::region_inference::RegionResolutionError;
6666
use super::region_inference::ConcreteFailure;
6767
use super::region_inference::SubSupConflict;
6868
use super::region_inference::SupSupConflict;
69-
use super::region_inference::ParamBoundFailure;
69+
use super::region_inference::GenericBoundFailure;
70+
use super::region_inference::GenericKind;
7071
use super::region_inference::ProcessedErrors;
7172
use super::region_inference::SameRegions;
7273

@@ -120,11 +121,11 @@ pub trait ErrorReporting<'tcx> {
120121
sub: Region,
121122
sup: Region);
122123

123-
fn report_param_bound_failure(&self,
124-
origin: SubregionOrigin<'tcx>,
125-
param_ty: ty::ParamTy,
126-
sub: Region,
127-
sups: Vec<Region>);
124+
fn report_generic_bound_failure(&self,
125+
origin: SubregionOrigin<'tcx>,
126+
kind: GenericKind<'tcx>,
127+
sub: Region,
128+
sups: Vec<Region>);
128129

129130
fn report_sub_sup_conflict(&self,
130131
var_origin: RegionVariableOrigin,
@@ -175,8 +176,8 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
175176
self.report_concrete_failure(origin, sub, sup);
176177
}
177178

178-
ParamBoundFailure(origin, param_ty, sub, sups) => {
179-
self.report_param_bound_failure(origin, param_ty, sub, sups);
179+
GenericBoundFailure(kind, param_ty, sub, sups) => {
180+
self.report_generic_bound_failure(kind, param_ty, sub, sups);
180181
}
181182

182183
SubSupConflict(var_origin,
@@ -421,63 +422,65 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
421422
found.user_string(self.tcx)))
422423
}
423424

424-
fn report_param_bound_failure(&self,
425-
origin: SubregionOrigin<'tcx>,
426-
param_ty: ty::ParamTy,
427-
sub: Region,
428-
_sups: Vec<Region>) {
429-
425+
fn report_generic_bound_failure(&self,
426+
origin: SubregionOrigin<'tcx>,
427+
bound_kind: GenericKind<'tcx>,
428+
sub: Region,
429+
_sups: Vec<Region>)
430+
{
430431
// FIXME: it would be better to report the first error message
431432
// with the span of the parameter itself, rather than the span
432433
// where the error was detected. But that span is not readily
433434
// accessible.
434435

436+
let labeled_user_string = match bound_kind {
437+
GenericKind::Param(ref p) =>
438+
format!("the parameter type `{}`", p.user_string(self.tcx)),
439+
GenericKind::Projection(ref p) =>
440+
format!("the associated type `{}`", p.user_string(self.tcx)),
441+
};
442+
435443
match sub {
436444
ty::ReFree(ty::FreeRegion {bound_region: ty::BrNamed(..), ..}) => {
437445
// Does the required lifetime have a nice name we can print?
438446
self.tcx.sess.span_err(
439447
origin.span(),
440-
format!(
441-
"the parameter type `{}` may not live long enough",
442-
param_ty.user_string(self.tcx))[]);
448+
format!("{} may not live long enough", labeled_user_string)[]);
443449
self.tcx.sess.span_help(
444450
origin.span(),
445451
format!(
446452
"consider adding an explicit lifetime bound `{}: {}`...",
447-
param_ty.user_string(self.tcx),
453+
bound_kind.user_string(self.tcx),
448454
sub.user_string(self.tcx))[]);
449455
}
450456

451457
ty::ReStatic => {
452458
// Does the required lifetime have a nice name we can print?
453459
self.tcx.sess.span_err(
454460
origin.span(),
455-
format!(
456-
"the parameter type `{}` may not live long enough",
457-
param_ty.user_string(self.tcx))[]);
461+
format!("{} may not live long enough", labeled_user_string)[]);
458462
self.tcx.sess.span_help(
459463
origin.span(),
460464
format!(
461465
"consider adding an explicit lifetime bound `{}: 'static`...",
462-
param_ty.user_string(self.tcx))[]);
466+
bound_kind.user_string(self.tcx))[]);
463467
}
464468

465469
_ => {
466470
// If not, be less specific.
467471
self.tcx.sess.span_err(
468472
origin.span(),
469473
format!(
470-
"the parameter type `{}` may not live long enough",
471-
param_ty.user_string(self.tcx))[]);
474+
"{} may not live long enough",
475+
labeled_user_string)[]);
472476
self.tcx.sess.span_help(
473477
origin.span(),
474478
format!(
475-
"consider adding an explicit lifetime bound to `{}`",
476-
param_ty.user_string(self.tcx))[]);
479+
"consider adding an explicit lifetime bound for `{}`",
480+
bound_kind.user_string(self.tcx))[]);
477481
note_and_explain_region(
478482
self.tcx,
479-
format!("the parameter type `{}` must be valid for ",
480-
param_ty.user_string(self.tcx))[],
483+
format!("{} must be valid for ", labeled_user_string)[],
481484
sub,
482485
"...");
483486
}

src/librustc/middle/infer/mod.rs

+15-13
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ pub use self::ValuePairs::*;
2020
pub use self::fixup_err::*;
2121
pub use middle::ty::IntVarValue;
2222
pub use self::freshen::TypeFreshener;
23+
pub use self::region_inference::GenericKind;
2324

2425
use middle::subst;
2526
use middle::subst::Substs;
@@ -382,19 +383,6 @@ pub fn mk_subr<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
382383
cx.region_vars.commit(snapshot);
383384
}
384385

385-
pub fn verify_param_bound<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
386-
origin: SubregionOrigin<'tcx>,
387-
param_ty: ty::ParamTy,
388-
a: ty::Region,
389-
bs: Vec<ty::Region>) {
390-
debug!("verify_param_bound({}, {} <: {})",
391-
param_ty.repr(cx.tcx),
392-
a.repr(cx.tcx),
393-
bs.repr(cx.tcx));
394-
395-
cx.region_vars.verify_param_bound(origin, param_ty, a, bs);
396-
}
397-
398386
pub fn mk_eqty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
399387
a_is_expected: bool,
400388
origin: TypeOrigin,
@@ -1070,6 +1058,20 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
10701058
value,
10711059
|br, _| self.next_region_var(LateBoundRegion(span, br, lbrct)))
10721060
}
1061+
1062+
/// See `verify_generic_bound` method in `region_inference`
1063+
pub fn verify_generic_bound(&self,
1064+
origin: SubregionOrigin<'tcx>,
1065+
kind: GenericKind<'tcx>,
1066+
a: ty::Region,
1067+
bs: Vec<ty::Region>) {
1068+
debug!("verify_generic_bound({}, {} <: {})",
1069+
kind.repr(self.tcx),
1070+
a.repr(self.tcx),
1071+
bs.repr(self.tcx));
1072+
1073+
self.region_vars.verify_generic_bound(origin, kind, a, bs);
1074+
}
10731075
}
10741076

10751077
impl<'tcx> TypeTrace<'tcx> {

src/librustc/middle/infer/region_inference/mod.rs

+59-23
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,15 @@ use super::cres;
2222
use super::{RegionVariableOrigin, SubregionOrigin, TypeTrace, MiscVariable};
2323

2424
use middle::region;
25-
use middle::ty;
25+
use middle::ty::{mod, Ty};
2626
use middle::ty::{BoundRegion, FreeRegion, Region, RegionVid};
2727
use middle::ty::{ReEmpty, ReStatic, ReInfer, ReFree, ReEarlyBound};
2828
use middle::ty::{ReLateBound, ReScope, ReVar, ReSkolemized, BrFresh};
2929
use middle::graph;
3030
use middle::graph::{Direction, NodeIndex};
3131
use util::common::indenter;
3232
use util::nodemap::{FnvHashMap, FnvHashSet};
33-
use util::ppaux::Repr;
33+
use util::ppaux::{Repr, UserString};
3434

3535
use std::cell::{Cell, RefCell};
3636
use std::cmp::Ordering::{self, Less, Greater, Equal};
@@ -61,12 +61,18 @@ pub enum Verify<'tcx> {
6161
// `b` are inference variables.
6262
VerifyRegSubReg(SubregionOrigin<'tcx>, Region, Region),
6363

64-
// VerifyParamBound(T, _, R, RS): The parameter type `T` must
65-
// outlive the region `R`. `T` is known to outlive `RS`. Therefore
66-
// verify that `R <= RS[i]` for some `i`. Inference variables may
67-
// be involved (but this verification step doesn't influence
68-
// inference).
69-
VerifyParamBound(ty::ParamTy, SubregionOrigin<'tcx>, Region, Vec<Region>),
64+
// VerifyGenericBound(T, _, R, RS): The parameter type `T` (or
65+
// associated type) must outlive the region `R`. `T` is known to
66+
// outlive `RS`. Therefore verify that `R <= RS[i]` for some
67+
// `i`. Inference variables may be involved (but this verification
68+
// step doesn't influence inference).
69+
VerifyGenericBound(GenericKind<'tcx>, SubregionOrigin<'tcx>, Region, Vec<Region>),
70+
}
71+
72+
#[deriving(Clone, Show, PartialEq, Eq)]
73+
pub enum GenericKind<'tcx> {
74+
Param(ty::ParamTy),
75+
Projection(ty::ProjectionTy<'tcx>),
7076
}
7177

7278
#[derive(Copy, PartialEq, Eq, Hash)]
@@ -98,12 +104,12 @@ pub enum RegionResolutionError<'tcx> {
98104
/// `o` requires that `a <= b`, but this does not hold
99105
ConcreteFailure(SubregionOrigin<'tcx>, Region, Region),
100106

101-
/// `ParamBoundFailure(p, s, a, bs)
107+
/// `GenericBoundFailure(p, s, a, bs)
102108
///
103-
/// The parameter type `p` must be known to outlive the lifetime
109+
/// The parameter/assocated-type `p` must be known to outlive the lifetime
104110
/// `a`, but it is only known to outlive `bs` (and none of the
105111
/// regions in `bs` outlive `a`).
106-
ParamBoundFailure(SubregionOrigin<'tcx>, ty::ParamTy, Region, Vec<Region>),
112+
GenericBoundFailure(SubregionOrigin<'tcx>, GenericKind<'tcx>, Region, Vec<Region>),
107113

108114
/// `SubSupConflict(v, sub_origin, sub_r, sup_origin, sup_r)`:
109115
///
@@ -489,12 +495,13 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
489495
}
490496
}
491497

492-
pub fn verify_param_bound(&self,
493-
origin: SubregionOrigin<'tcx>,
494-
param_ty: ty::ParamTy,
495-
sub: Region,
496-
sups: Vec<Region>) {
497-
self.add_verify(VerifyParamBound(param_ty, origin, sub, sups));
498+
/// See `Verify::VerifyGenericBound`
499+
pub fn verify_generic_bound(&self,
500+
origin: SubregionOrigin<'tcx>,
501+
kind: GenericKind<'tcx>,
502+
sub: Region,
503+
sups: Vec<Region>) {
504+
self.add_verify(VerifyGenericBound(kind, origin, sub, sups));
498505
}
499506

500507
pub fn lub_regions(&self,
@@ -660,7 +667,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
660667
&mut result_set, r,
661668
a, b);
662669
}
663-
VerifyParamBound(_, _, a, ref bs) => {
670+
VerifyGenericBound(_, _, a, ref bs) => {
664671
for &b in bs.iter() {
665672
consider_adding_bidirectional_edges(
666673
&mut result_set, r,
@@ -1211,7 +1218,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
12111218
errors.push(ConcreteFailure((*origin).clone(), sub, sup));
12121219
}
12131220

1214-
VerifyParamBound(ref param_ty, ref origin, sub, ref sups) => {
1221+
VerifyGenericBound(ref kind, ref origin, sub, ref sups) => {
12151222
let sub = normalize(values, sub);
12161223
if sups.iter()
12171224
.map(|&sup| normalize(values, sup))
@@ -1223,8 +1230,8 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
12231230
let sups = sups.iter().map(|&sup| normalize(values, sup))
12241231
.collect();
12251232
errors.push(
1226-
ParamBoundFailure(
1227-
(*origin).clone(), *param_ty, sub, sups));
1233+
GenericBoundFailure(
1234+
(*origin).clone(), kind.clone(), sub, sups));
12281235
}
12291236
}
12301237
}
@@ -1584,8 +1591,8 @@ impl<'tcx> Repr<'tcx> for Verify<'tcx> {
15841591
VerifyRegSubReg(_, ref a, ref b) => {
15851592
format!("VerifyRegSubReg({}, {})", a.repr(tcx), b.repr(tcx))
15861593
}
1587-
VerifyParamBound(_, ref p, ref a, ref bs) => {
1588-
format!("VerifyParamBound({}, {}, {})",
1594+
VerifyGenericBound(_, ref p, ref a, ref bs) => {
1595+
format!("VerifyGenericBound({}, {}, {})",
15891596
p.repr(tcx), a.repr(tcx), bs.repr(tcx))
15901597
}
15911598
}
@@ -1624,3 +1631,32 @@ impl<'tcx> Repr<'tcx> for RegionAndOrigin<'tcx> {
16241631
self.origin.repr(tcx))
16251632
}
16261633
}
1634+
1635+
impl<'tcx> Repr<'tcx> for GenericKind<'tcx> {
1636+
fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
1637+
match *self {
1638+
GenericKind::Param(ref p) => p.repr(tcx),
1639+
GenericKind::Projection(ref p) => p.repr(tcx),
1640+
}
1641+
}
1642+
}
1643+
1644+
impl<'tcx> UserString<'tcx> for GenericKind<'tcx> {
1645+
fn user_string(&self, tcx: &ty::ctxt<'tcx>) -> String {
1646+
match *self {
1647+
GenericKind::Param(ref p) => p.user_string(tcx),
1648+
GenericKind::Projection(ref p) => p.user_string(tcx),
1649+
}
1650+
}
1651+
}
1652+
1653+
impl<'tcx> GenericKind<'tcx> {
1654+
pub fn to_ty(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx> {
1655+
match *self {
1656+
GenericKind::Param(ref p) =>
1657+
p.to_ty(tcx),
1658+
GenericKind::Projection(ref p) =>
1659+
ty::mk_projection(tcx, p.trait_ref.clone(), p.item_name),
1660+
}
1661+
}
1662+
}

0 commit comments

Comments
 (0)