Skip to content
10 changes: 9 additions & 1 deletion src/librustc/lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,13 @@ declare_lint! {
"transmute from function item type to pointer-sized type erroneously allowed"
}

declare_lint! {
pub HR_LIFETIME_IN_ASSOC_TYPE,
Warn,
"binding for associated type references higher-ranked lifetime \
that does not appear in the trait input types"
}

declare_lint! {
pub OVERLAPPING_INHERENT_IMPLS,
Warn,
Expand Down Expand Up @@ -220,7 +227,8 @@ impl LintPass for HardwiredLints {
TRANSMUTE_FROM_FN_ITEM_TYPES,
OVERLAPPING_INHERENT_IMPLS,
RENAMED_AND_REMOVED_LINTS,
SUPER_OR_SELF_IN_GLOBAL_PATH
SUPER_OR_SELF_IN_GLOBAL_PATH,
HR_LIFETIME_IN_ASSOC_TYPE
)
}
}
Expand Down
469 changes: 281 additions & 188 deletions src/librustc/traits/project.rs

Large diffs are not rendered by default.

9 changes: 7 additions & 2 deletions src/librustc/ty/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,13 @@ impl FlagComputation {

fn add_region(&mut self, r: ty::Region) {
match r {
ty::ReVar(..) |
ty::ReSkolemized(..) => { self.add_flags(TypeFlags::HAS_RE_INFER); }
ty::ReVar(..) => {
self.add_flags(TypeFlags::HAS_RE_INFER);
}
ty::ReSkolemized(..) => {
self.add_flags(TypeFlags::HAS_RE_INFER);
self.add_flags(TypeFlags::HAS_RE_SKOL);
}
ty::ReLateBound(debruijn, _) => { self.add_depth(debruijn.depth); }
ty::ReEarlyBound(..) => { self.add_flags(TypeFlags::HAS_RE_EARLY_BOUND); }
ty::ReStatic => {}
Expand Down
80 changes: 80 additions & 0 deletions src/librustc/ty/fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,35 @@ impl<'tcx> TyCtxt<'tcx> {
}
}

/// Returns a set of all late-bound regions that are constrained
/// by `value`, meaning that if we instantiate those LBR with
/// variables and equate `value` with something else, those
/// variables will also be equated.
pub fn collect_constrained_late_bound_regions<T>(&self, value: &Binder<T>)
-> FnvHashSet<ty::BoundRegion>
where T : TypeFoldable<'tcx>
{
self.collect_late_bound_regions(value, true)
}

/// Returns a set of all late-bound regions that appear in `value` anywhere.
pub fn collect_referenced_late_bound_regions<T>(&self, value: &Binder<T>)
-> FnvHashSet<ty::BoundRegion>
where T : TypeFoldable<'tcx>
{
self.collect_late_bound_regions(value, false)
}

fn collect_late_bound_regions<T>(&self, value: &Binder<T>, just_constraint: bool)
-> FnvHashSet<ty::BoundRegion>
where T : TypeFoldable<'tcx>
{
let mut collector = LateBoundRegionsCollector::new(just_constraint);
let result = value.skip_binder().visit_with(&mut collector);
assert!(!result); // should never have stopped early
collector.regions
}

/// Replace any late-bound regions bound in `value` with `'static`. Useful in trans but also
/// method lookup and a few other places where precise region relationships are not required.
pub fn erase_late_bound_regions<T>(&self, value: &Binder<T>) -> T
Expand Down Expand Up @@ -626,3 +655,54 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
false
}
}

/// Collects all the late-bound regions it finds into a hash set.
struct LateBoundRegionsCollector {
current_depth: u32,
regions: FnvHashSet<ty::BoundRegion>,
just_constrained: bool,
}

impl LateBoundRegionsCollector {
fn new(just_constrained: bool) -> Self {
LateBoundRegionsCollector {
current_depth: 1,
regions: FnvHashSet(),
just_constrained: just_constrained,
}
}
}

impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector {
fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &Binder<T>) -> bool {
self.current_depth += 1;
let r = t.super_visit_with(self);
self.current_depth -= 1;
r
}

fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
// if we are only looking for "constrained" region, we have to
// ignore the inputs to a projection, as they may not appear
// in the normalized form
if self.just_constrained {
match t.sty {
ty::TyProjection(..) => { return false; }
_ => { }
}
}

t.super_visit_with(self)
}

fn visit_region(&mut self, r: ty::Region) -> bool {
match r {
ty::ReLateBound(debruijn, br) if debruijn.depth == self.current_depth => {
self.regions.insert(br);
}
_ => { }
}
false
}
}

13 changes: 7 additions & 6 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -531,15 +531,16 @@ bitflags! {
const HAS_SELF = 1 << 1,
const HAS_TY_INFER = 1 << 2,
const HAS_RE_INFER = 1 << 3,
const HAS_RE_EARLY_BOUND = 1 << 4,
const HAS_FREE_REGIONS = 1 << 5,
const HAS_TY_ERR = 1 << 6,
const HAS_PROJECTION = 1 << 7,
const HAS_TY_CLOSURE = 1 << 8,
const HAS_RE_SKOL = 1 << 4,
const HAS_RE_EARLY_BOUND = 1 << 5,
const HAS_FREE_REGIONS = 1 << 6,
const HAS_TY_ERR = 1 << 7,
const HAS_PROJECTION = 1 << 8,
const HAS_TY_CLOSURE = 1 << 9,

// true if there are "names" of types and regions and so forth
// that are local to a particular fn
const HAS_LOCAL_NAMES = 1 << 9,
const HAS_LOCAL_NAMES = 1 << 10,

const NEEDS_SUBST = TypeFlags::HAS_PARAMS.bits |
TypeFlags::HAS_SELF.bits |
Expand Down
4 changes: 4 additions & 0 deletions src/librustc_lint/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,10 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
id: LintId::of(ILLEGAL_STRUCT_OR_ENUM_CONSTANT_PATTERN),
reference: "RFC 1445 <https://github.com/rust-lang/rfcs/pull/1445>",
},
FutureIncompatibleInfo {
id: LintId::of(HR_LIFETIME_IN_ASSOC_TYPE),
reference: "issue #32330 <https://github.com/rust-lang/rust/issues/32330>",
},
]);

// We have one lint pass defined specially
Expand Down
Loading