Skip to content

Commit 7ada5e5

Browse files
committed
Avoid recomputing defaults for all arguments.
1 parent be9a2a0 commit 7ada5e5

File tree

1 file changed

+47
-58
lines changed

1 file changed

+47
-58
lines changed

compiler/rustc_typeck/src/collect/object_lifetime_defaults.rs

Lines changed: 47 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ use rustc_hir::{GenericArg, GenericParamKind, LifetimeName, Node};
88
use rustc_middle::bug;
99
use rustc_middle::hir::nested_filter;
1010
use rustc_middle::middle::resolve_lifetime::*;
11-
use rustc_middle::ty::{GenericParamDefKind, TyCtxt};
12-
use rustc_span::def_id::DefId;
11+
use rustc_middle::ty::{DefIdTree, GenericParamDefKind, TyCtxt};
1312
use rustc_span::symbol::sym;
1413
use std::borrow::Cow;
1514

@@ -447,15 +446,13 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
447446
return;
448447
}
449448

449+
let tcx = self.tcx;
450+
450451
// Figure out if this is a type/trait segment,
451452
// which requires object lifetime defaults.
452-
let parent_def_id = |this: &mut Self, def_id: DefId| {
453-
let def_key = this.tcx.def_key(def_id);
454-
DefId { krate: def_id.krate, index: def_key.parent.expect("missing parent") }
455-
};
456453
let type_def_id = match res {
457-
Res::Def(DefKind::AssocTy, def_id) if depth == 1 => Some(parent_def_id(self, def_id)),
458-
Res::Def(DefKind::Variant, def_id) if depth == 0 => Some(parent_def_id(self, def_id)),
454+
Res::Def(DefKind::AssocTy, def_id) if depth == 1 => Some(tcx.parent(def_id)),
455+
Res::Def(DefKind::Variant, def_id) if depth == 0 => Some(tcx.parent(def_id)),
459456
Res::Def(
460457
DefKind::Struct
461458
| DefKind::Union
@@ -468,22 +465,24 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
468465
};
469466
debug!(?type_def_id);
470467

471-
// Compute a vector of defaults, one for each type parameter,
472-
// per the rules given in RFCs 599 and 1156. Example:
473-
//
474-
// ```rust
475-
// struct Foo<'a, T: 'a, U> { }
476-
// ```
477-
//
478-
// If you have `Foo<'x, dyn Bar, dyn Baz>`, we want to default
479-
// `dyn Bar` to `dyn Bar + 'x` (because of the `T: 'a` bound)
480-
// and `dyn Baz` to `dyn Baz + 'static` (because there is no
481-
// such bound).
482-
//
483-
// Therefore, we would compute `object_lifetime_defaults` to a
484-
// vector like `['x, 'static]`. Note that the vector only
485-
// includes type parameters.
486-
let object_lifetime_defaults = type_def_id.map_or_else(Vec::new, |def_id| {
468+
if let Some(type_def_id) = type_def_id {
469+
// Compute a vector of defaults, one for each type parameter,
470+
// per the rules given in RFCs 599 and 1156. Example:
471+
//
472+
// ```rust
473+
// struct Foo<'a, T: 'a, U> { }
474+
// ```
475+
//
476+
// If you have `Foo<'x, dyn Bar, dyn Baz>`, we want to default
477+
// `dyn Bar` to `dyn Bar + 'x` (because of the `T: 'a` bound)
478+
// and `dyn Baz` to `dyn Baz + 'static` (because there is no
479+
// such bound).
480+
//
481+
// Therefore, we would compute `object_lifetime_defaults` to a
482+
// vector like `['x, 'static]`. Note that the vector only
483+
// includes type parameters.
484+
let generics = self.tcx.generics_of(type_def_id);
485+
487486
let in_body = {
488487
let mut scope = self.scope;
489488
loop {
@@ -498,7 +497,16 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
498497
}
499498
}
500499
};
501-
let generics = self.tcx.generics_of(def_id);
500+
let object_lifetime_default = |i: usize| {
501+
let param = generics.params.get(i)?;
502+
match param.kind {
503+
GenericParamDefKind::Type { object_lifetime_default, .. } => {
504+
Some(object_lifetime_default)
505+
}
506+
GenericParamDefKind::Const { .. } => Some(ObjectLifetimeDefault::Empty),
507+
GenericParamDefKind::Lifetime => return None,
508+
}
509+
};
502510
let set_to_region = |set: ObjectLifetimeDefault| match set {
503511
ObjectLifetimeDefault::Empty => {
504512
if in_body {
@@ -509,51 +517,32 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
509517
}
510518
ObjectLifetimeDefault::Static => Some(Region::Static),
511519
ObjectLifetimeDefault::Param(def_id) => {
512-
let index = generics.param_def_id_to_index[&def_id];
520+
let index = *generics.param_def_id_to_index.get(&def_id)?;
513521
generic_args.args.get(index as usize).and_then(|arg| match arg {
514-
GenericArg::Lifetime(lt) => self.tcx.named_region(lt.hir_id),
522+
GenericArg::Lifetime(lt) => tcx.named_region(lt.hir_id),
515523
_ => None,
516524
})
517525
}
518526
ObjectLifetimeDefault::Ambiguous => None,
519527
};
520-
generics
521-
.params
522-
.iter()
523-
.filter_map(|param| match param.kind {
524-
GenericParamDefKind::Type { object_lifetime_default, .. } => {
525-
Some(object_lifetime_default)
526-
}
527-
GenericParamDefKind::Const { .. } => Some(ObjectLifetimeDefault::Empty),
528-
GenericParamDefKind::Lifetime => None,
529-
})
530-
.map(set_to_region)
531-
.collect()
532-
});
533-
debug!(?object_lifetime_defaults);
534-
535-
let mut i = 0;
536-
for arg in generic_args.args {
537-
match arg {
538-
GenericArg::Lifetime(_) => {}
539-
GenericArg::Type(ty) => {
540-
if let Some(&lt) = object_lifetime_defaults.get(i) {
541-
let scope = Scope::ObjectLifetimeDefault { lifetime: lt, s: self.scope };
528+
529+
for (i, arg) in generic_args.args.iter().enumerate() {
530+
if let GenericArg::Type(ty) = arg {
531+
if let Some(default) = object_lifetime_default(i) {
532+
let lifetime = set_to_region(default);
533+
let scope = Scope::ObjectLifetimeDefault { lifetime, s: self.scope };
542534
self.with(scope, |this| this.visit_ty(ty));
543535
} else {
544536
self.visit_ty(ty);
545537
}
546-
i += 1;
547-
}
548-
GenericArg::Const(ct) => {
549-
self.visit_anon_const(&ct.value);
550-
i += 1;
551-
}
552-
GenericArg::Infer(inf) => {
553-
self.visit_id(inf.hir_id);
554-
i += 1;
538+
} else {
539+
self.visit_generic_arg(arg);
555540
}
556541
}
542+
} else {
543+
for arg in generic_args.args {
544+
self.visit_generic_arg(arg);
545+
}
557546
}
558547

559548
// Hack: when resolving the type `XX` in binding like `dyn

0 commit comments

Comments
 (0)