Skip to content

Commit ce3331c

Browse files
committed
Merge pull request #25313 from pnkfelix/backport-25212-to-beta
Backport #25212 to beta
2 parents 1d78408 + c25ab82 commit ce3331c

File tree

8 files changed

+381
-103
lines changed

8 files changed

+381
-103
lines changed

src/librustc_typeck/check/dropck.rs

+141-94
Original file line numberDiff line numberDiff line change
@@ -396,19 +396,24 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
396396
}
397397
};
398398

399-
let opt_type_did = match typ.sty {
400-
ty::ty_struct(struct_did, _) => Some(struct_did),
401-
ty::ty_enum(enum_did, _) => Some(enum_did),
402-
_ => None,
399+
let dtor_kind = match typ.sty {
400+
ty::ty_enum(def_id, _) |
401+
ty::ty_struct(def_id, _) => {
402+
match destructor_for_type.get(&def_id) {
403+
Some(def_id) => DtorKind::KnownDropMethod(*def_id),
404+
None => DtorKind::PureRecur,
405+
}
406+
}
407+
ty::ty_trait(ref ty_trait) => {
408+
DtorKind::Unknown(ty_trait.bounds.clone())
409+
}
410+
_ => DtorKind::PureRecur,
403411
};
404412

405-
let opt_dtor =
406-
opt_type_did.and_then(|did| destructor_for_type.get(&did));
407-
408413
debug!("iterate_over_potentially_unsafe_regions_in_type \
409-
{}typ: {} scope: {:?} opt_dtor: {:?} xref: {}",
414+
{}typ: {} scope: {:?} xref: {}",
410415
(0..depth).map(|_| ' ').collect::<String>(),
411-
typ.repr(rcx.tcx()), scope, opt_dtor, xref_depth);
416+
typ.repr(rcx.tcx()), scope, xref_depth);
412417

413418
// If `typ` has a destructor, then we must ensure that all
414419
// borrowed data reachable via `typ` must outlive the parent
@@ -439,90 +444,7 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
439444
// simply skip the `type_must_outlive` call entirely (but
440445
// resume the recursive checking of the type-substructure).
441446

442-
let has_dtor_of_interest;
443-
444-
if let Some(&dtor_method_did) = opt_dtor {
445-
let impl_did = ty::impl_of_method(rcx.tcx(), dtor_method_did)
446-
.unwrap_or_else(|| {
447-
rcx.tcx().sess.span_bug(
448-
span, "no Drop impl found for drop method")
449-
});
450-
451-
let dtor_typescheme = ty::lookup_item_type(rcx.tcx(), impl_did);
452-
let dtor_generics = dtor_typescheme.generics;
453-
let dtor_predicates = ty::lookup_predicates(rcx.tcx(), impl_did);
454-
455-
let has_pred_of_interest = dtor_predicates.predicates.iter().any(|pred| {
456-
// In `impl<T> Drop where ...`, we automatically
457-
// assume some predicate will be meaningful and thus
458-
// represents a type through which we could reach
459-
// borrowed data. However, there can be implicit
460-
// predicates (namely for Sized), and so we still need
461-
// to walk through and filter out those cases.
462-
463-
let result = match *pred {
464-
ty::Predicate::Trait(ty::Binder(ref t_pred)) => {
465-
let def_id = t_pred.trait_ref.def_id;
466-
match rcx.tcx().lang_items.to_builtin_kind(def_id) {
467-
// Issue 24895: deliberately do not include `BoundCopy` here.
468-
Some(ty::BoundSend) |
469-
Some(ty::BoundSized) |
470-
Some(ty::BoundSync) => false,
471-
_ => true,
472-
}
473-
}
474-
ty::Predicate::Equate(..) |
475-
ty::Predicate::RegionOutlives(..) |
476-
ty::Predicate::TypeOutlives(..) |
477-
ty::Predicate::Projection(..) => {
478-
// we assume all of these where-clauses may
479-
// give the drop implementation the capabilty
480-
// to access borrowed data.
481-
true
482-
}
483-
};
484-
485-
if result {
486-
debug!("typ: {} has interesting dtor due to generic preds, e.g. {}",
487-
typ.repr(rcx.tcx()), pred.repr(rcx.tcx()));
488-
}
489-
490-
result
491-
});
492-
493-
// In `impl<'a> Drop ...`, we automatically assume
494-
// `'a` is meaningful and thus represents a bound
495-
// through which we could reach borrowed data.
496-
//
497-
// FIXME (pnkfelix): In the future it would be good to
498-
// extend the language to allow the user to express,
499-
// in the impl signature, that a lifetime is not
500-
// actually used (something like `where 'a: ?Live`).
501-
let has_region_param_of_interest =
502-
dtor_generics.has_region_params(subst::TypeSpace);
503-
504-
has_dtor_of_interest =
505-
has_region_param_of_interest ||
506-
has_pred_of_interest;
507-
508-
if has_dtor_of_interest {
509-
debug!("typ: {} has interesting dtor, due to \
510-
region params: {} or pred: {}",
511-
typ.repr(rcx.tcx()),
512-
has_region_param_of_interest,
513-
has_pred_of_interest);
514-
} else {
515-
debug!("typ: {} has dtor, but it is uninteresting",
516-
typ.repr(rcx.tcx()));
517-
}
518-
519-
} else {
520-
debug!("typ: {} has no dtor, and thus is uninteresting",
521-
typ.repr(rcx.tcx()));
522-
has_dtor_of_interest = false;
523-
}
524-
525-
if has_dtor_of_interest {
447+
if has_dtor_of_interest(rcx.tcx(), dtor_kind, typ, span) {
526448
// If `typ` has a destructor, then we must ensure that all
527449
// borrowed data reachable via `typ` must outlive the
528450
// parent of `scope`. (It does not suffice for it to
@@ -608,7 +530,7 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
608530

609531
ty::ty_rptr(..) | ty::ty_ptr(_) | ty::ty_bare_fn(..) => {
610532
// Don't recurse, since references, pointers,
611-
// boxes, and bare functions don't own instances
533+
// and bare functions don't own instances
612534
// of the types appearing within them.
613535
walker.skip_current_subtree();
614536
}
@@ -627,3 +549,128 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
627549

628550
return Ok(());
629551
}
552+
553+
enum DtorKind<'tcx> {
554+
// Type has an associated drop method with this def id
555+
KnownDropMethod(ast::DefId),
556+
557+
// Type has no destructor (or its dtor is known to be pure
558+
// with respect to lifetimes), though its *substructure*
559+
// may carry a destructor.
560+
PureRecur,
561+
562+
// Type may have impure destructor that is unknown;
563+
// e.g. `Box<Trait+'a>`
564+
Unknown(ty::ExistentialBounds<'tcx>),
565+
}
566+
567+
fn has_dtor_of_interest<'tcx>(tcx: &ty::ctxt<'tcx>,
568+
dtor_kind: DtorKind,
569+
typ: ty::Ty<'tcx>,
570+
span: Span) -> bool {
571+
let has_dtor_of_interest: bool;
572+
573+
match dtor_kind {
574+
DtorKind::PureRecur => {
575+
debug!("typ: {} has no dtor, and thus is uninteresting",
576+
typ.repr(tcx));
577+
has_dtor_of_interest = false;
578+
}
579+
DtorKind::Unknown(bounds) => {
580+
match bounds.region_bound {
581+
ty::ReStatic => {
582+
debug!("trait: {} has 'static bound, and thus is uninteresting",
583+
typ.repr(tcx));
584+
has_dtor_of_interest = false;
585+
}
586+
ty::ReEmpty => {
587+
debug!("trait: {} has empty region bound, and thus is uninteresting",
588+
typ.repr(tcx));
589+
has_dtor_of_interest = false;
590+
}
591+
r => {
592+
debug!("trait: {} has non-static bound: {}; assumed interesting",
593+
typ.repr(tcx), r.repr(tcx));
594+
has_dtor_of_interest = true;
595+
}
596+
}
597+
}
598+
DtorKind::KnownDropMethod(dtor_method_did) => {
599+
let impl_did = ty::impl_of_method(tcx, dtor_method_did)
600+
.unwrap_or_else(|| {
601+
tcx.sess.span_bug(
602+
span, "no Drop impl found for drop method")
603+
});
604+
605+
let dtor_typescheme = ty::lookup_item_type(tcx, impl_did);
606+
let dtor_generics = dtor_typescheme.generics;
607+
let dtor_predicates = ty::lookup_predicates(tcx, impl_did);
608+
609+
let has_pred_of_interest = dtor_predicates.predicates.iter().any(|pred| {
610+
// In `impl<T> Drop where ...`, we automatically
611+
// assume some predicate will be meaningful and thus
612+
// represents a type through which we could reach
613+
// borrowed data. However, there can be implicit
614+
// predicates (namely for Sized), and so we still need
615+
// to walk through and filter out those cases.
616+
617+
let result = match *pred {
618+
ty::Predicate::Trait(ty::Binder(ref t_pred)) => {
619+
let def_id = t_pred.trait_ref.def_id;
620+
match tcx.lang_items.to_builtin_kind(def_id) {
621+
// Issue 24895: deliberately do not include `BoundCopy` here.
622+
Some(ty::BoundSend) |
623+
Some(ty::BoundSized) |
624+
Some(ty::BoundSync) => false,
625+
_ => true,
626+
}
627+
}
628+
ty::Predicate::Equate(..) |
629+
ty::Predicate::RegionOutlives(..) |
630+
ty::Predicate::TypeOutlives(..) |
631+
ty::Predicate::Projection(..) => {
632+
// we assume all of these where-clauses may
633+
// give the drop implementation the capabilty
634+
// to access borrowed data.
635+
true
636+
}
637+
};
638+
639+
if result {
640+
debug!("typ: {} has interesting dtor due to generic preds, e.g. {}",
641+
typ.repr(tcx), pred.repr(tcx));
642+
}
643+
644+
result
645+
});
646+
647+
// In `impl<'a> Drop ...`, we automatically assume
648+
// `'a` is meaningful and thus represents a bound
649+
// through which we could reach borrowed data.
650+
//
651+
// FIXME (pnkfelix): In the future it would be good to
652+
// extend the language to allow the user to express,
653+
// in the impl signature, that a lifetime is not
654+
// actually used (something like `where 'a: ?Live`).
655+
let has_region_param_of_interest =
656+
dtor_generics.has_region_params(subst::TypeSpace);
657+
658+
has_dtor_of_interest =
659+
has_region_param_of_interest ||
660+
has_pred_of_interest;
661+
662+
if has_dtor_of_interest {
663+
debug!("typ: {} has interesting dtor, due to \
664+
region params: {} or pred: {}",
665+
typ.repr(tcx),
666+
has_region_param_of_interest,
667+
has_pred_of_interest);
668+
} else {
669+
debug!("typ: {} has dtor, but it is uninteresting",
670+
typ.repr(tcx));
671+
}
672+
}
673+
}
674+
675+
return has_dtor_of_interest;
676+
}

src/libstd/net/parser.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ impl<'a> Parser<'a> {
6161
}
6262

6363
// Return result of first successful parser
64-
fn read_or<T>(&mut self, parsers: &mut [Box<FnMut(&mut Parser) -> Option<T>>])
64+
fn read_or<T>(&mut self, parsers: &mut [Box<FnMut(&mut Parser) -> Option<T> + 'static>])
6565
-> Option<T> {
6666
for pf in parsers.iter_mut() {
6767
match self.read_atomically(|p: &mut Parser| pf(p)) {

src/libsyntax/ext/expand.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -986,9 +986,10 @@ fn expand_pat(p: P<ast::Pat>, fld: &mut MacroExpander) -> P<ast::Pat> {
986986
let fm = fresh_mark();
987987
let marked_before = mark_tts(&tts[..], fm);
988988
let mac_span = fld.cx.original_span();
989-
let expanded = match expander.expand(fld.cx,
990-
mac_span,
991-
&marked_before[..]).make_pat() {
989+
let pat = expander.expand(fld.cx,
990+
mac_span,
991+
&marked_before[..]).make_pat();
992+
let expanded = match pat {
992993
Some(e) => e,
993994
None => {
994995
fld.cx.span_err(

src/libsyntax/util/parser_testing.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,11 @@ pub fn string_to_stmt(source_str : String) -> P<ast::Stmt> {
7272
/// Parse a string, return a pat. Uses "irrefutable"... which doesn't
7373
/// (currently) affect parsing.
7474
pub fn string_to_pat(source_str: String) -> P<ast::Pat> {
75-
string_to_parser(&new_parse_sess(), source_str).parse_pat()
75+
// Binding `sess` and `parser` works around dropck-injected
76+
// region-inference issues; see #25212, #22323, #22321.
77+
let sess = new_parse_sess();
78+
let mut parser = string_to_parser(&sess, source_str);
79+
parser.parse_pat()
7680
}
7781

7882
/// Convert a vector of strings to a vector of ast::Ident's

0 commit comments

Comments
 (0)