Skip to content

Commit b4038a9

Browse files
committed
dropck: do not add types with escaped-regions into the breadcrumbs set.
In particular, when we traverse a type like: `(for <'r> Fn(&'r u8), for <'r> Fn(&'r u8))` we should not add the first type `Fn(&'r u8)` to the bread-crumbs set, because that type ends up being structurally equivalent to the *second* `Fn(&'r u8)` type, even though they each should be considered distinct since they occur under distinct `for <'r>` binders. Fix rust-lang#25750.
1 parent 9090420 commit b4038a9

File tree

1 file changed

+27
-2
lines changed

1 file changed

+27
-2
lines changed

src/librustc_typeck/check/dropck.rs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use check::regionck::{self, Rcx};
1313
use middle::infer;
1414
use middle::region;
1515
use middle::subst::{self, Subst};
16-
use middle::ty::{self, Ty};
16+
use middle::ty::{self, Ty, RegionEscape};
1717

1818
use syntax::ast;
1919
use syntax::codemap::{self, Span};
@@ -358,7 +358,32 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
358358
if breadcrumbs.contains(&typ) {
359359
continue;
360360
}
361-
breadcrumbs.push(typ);
361+
362+
// Okay, it looks like we have not seen `typ`, so add it to
363+
// the breadcrumbs set so that we will not recurse on it again
364+
// in the future.
365+
//
366+
// Issues #25750, #27138: on a type `B` within `for <'r> B`,
367+
// occurrences of `'r` within `B` are not globally meaningful.
368+
// Nonetheless they might accidentally be considered equal to
369+
// other occurrences outside of the `for <'r> B`, since they
370+
// will be structurally the same.
371+
//
372+
// This comes up for example in the type:
373+
//
374+
// (for <'r> Fn(&'r u8), for <'r> Fn(&'r u8))
375+
//
376+
// We deal with this by detecting if we are looking at such a
377+
// `B`, and if so, we don't add it to breadcrumbs set.
378+
//
379+
// (A more robust/disciplined way of dealing with this would
380+
// be to add such types *temporarily* to the breadcrumbs set,
381+
// *solely* during the extent of the time that we are
382+
// underneath the `for <'r> ...`; I may look into doing that
383+
// later, but for now I think this simpler measure will suffice.)
384+
if !typ.has_escaping_regions() {
385+
breadcrumbs.push(typ);
386+
}
362387

363388
// If we encounter `PhantomData<T>`, then we should replace it
364389
// with `T`, the type it represents as owned by the

0 commit comments

Comments
 (0)