Skip to content

Commit c7331d6

Browse files
committed
Auto merge of #87203 - jackh726:logging, r=nikomatsakis
Some perf optimizations and logging Various bits of (potential) perf optimizations and some logging additions/changes pulled out from #85499 The only not extremely straightforward change is adding `needs_normalization` in `trait::project`. This is just a perf optimization to avoid fold through a type with *only* opaque types in `UserFacing` mode (as they aren't replaced). This should be a simple PR for *anyone* to review, so I'm going to let highfive assign. But I'll go ahead and cc `@nikomatsakis` in case he has time today.
2 parents 68511b5 + fa839b1 commit c7331d6

File tree

10 files changed

+45
-18
lines changed

10 files changed

+45
-18
lines changed

compiler/rustc_data_structures/src/obligation_forest/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,7 @@ impl<O: ForestObligation> ObligationForest<O> {
418418
/// be called in a loop until `outcome.stalled` is false.
419419
///
420420
/// This _cannot_ be unrolled (presently, at least).
421+
#[inline(never)]
421422
pub fn process_obligations<P, OUT>(&mut self, processor: &mut P) -> OUT
422423
where
423424
P: ObligationProcessor<Obligation = O>,
@@ -671,6 +672,7 @@ impl<O: ForestObligation> ObligationForest<O> {
671672
self.reused_node_vec = node_rewrites;
672673
}
673674

675+
#[inline(never)]
674676
fn apply_rewrites(&mut self, node_rewrites: &[usize]) {
675677
let orig_nodes_len = node_rewrites.len();
676678

compiler/rustc_infer/src/infer/type_variable.rs

+1
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,7 @@ impl<'tcx> From<ty::TyVid> for TyVidEqKey<'tcx> {
400400

401401
impl<'tcx> ut::UnifyKey for TyVidEqKey<'tcx> {
402402
type Value = TypeVariableValue<'tcx>;
403+
#[inline(always)]
403404
fn index(&self) -> u32 {
404405
self.vid.index
405406
}

compiler/rustc_trait_selection/src/traits/fulfill.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -167,15 +167,14 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
167167
/// `SomeTrait` or a where-clause that lets us unify `$0` with
168168
/// something concrete. If this fails, we'll unify `$0` with
169169
/// `projection_ty` again.
170+
#[tracing::instrument(level = "debug", skip(self, infcx, param_env, cause))]
170171
fn normalize_projection_type(
171172
&mut self,
172173
infcx: &InferCtxt<'_, 'tcx>,
173174
param_env: ty::ParamEnv<'tcx>,
174175
projection_ty: ty::ProjectionTy<'tcx>,
175176
cause: ObligationCause<'tcx>,
176177
) -> Ty<'tcx> {
177-
debug!(?projection_ty, "normalize_projection_type");
178-
179178
debug_assert!(!projection_ty.has_escaping_bound_vars());
180179

181180
// FIXME(#20304) -- cache

compiler/rustc_trait_selection/src/traits/project.rs

+24-6
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ where
273273
Normalized { value, obligations }
274274
}
275275

276-
#[instrument(level = "debug", skip(selcx, param_env, cause, obligations))]
276+
#[instrument(level = "info", skip(selcx, param_env, cause, obligations))]
277277
pub fn normalize_with_depth_to<'a, 'b, 'tcx, T>(
278278
selcx: &'a mut SelectionContext<'b, 'tcx>,
279279
param_env: ty::ParamEnv<'tcx>,
@@ -285,13 +285,26 @@ pub fn normalize_with_depth_to<'a, 'b, 'tcx, T>(
285285
where
286286
T: TypeFoldable<'tcx>,
287287
{
288+
debug!(obligations.len = obligations.len());
288289
let mut normalizer = AssocTypeNormalizer::new(selcx, param_env, cause, depth, obligations);
289290
let result = ensure_sufficient_stack(|| normalizer.fold(value));
290291
debug!(?result, obligations.len = normalizer.obligations.len());
291292
debug!(?normalizer.obligations,);
292293
result
293294
}
294295

296+
pub(crate) fn needs_normalization<'tcx, T: TypeFoldable<'tcx>>(value: &T, reveal: Reveal) -> bool {
297+
match reveal {
298+
Reveal::UserFacing => value
299+
.has_type_flags(ty::TypeFlags::HAS_TY_PROJECTION | ty::TypeFlags::HAS_CT_PROJECTION),
300+
Reveal::All => value.has_type_flags(
301+
ty::TypeFlags::HAS_TY_PROJECTION
302+
| ty::TypeFlags::HAS_TY_OPAQUE
303+
| ty::TypeFlags::HAS_CT_PROJECTION,
304+
),
305+
}
306+
}
307+
295308
struct AssocTypeNormalizer<'a, 'b, 'tcx> {
296309
selcx: &'a mut SelectionContext<'b, 'tcx>,
297310
param_env: ty::ParamEnv<'tcx>,
@@ -314,14 +327,19 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> {
314327

315328
fn fold<T: TypeFoldable<'tcx>>(&mut self, value: T) -> T {
316329
let value = self.selcx.infcx().resolve_vars_if_possible(value);
330+
debug!(?value);
317331

318332
assert!(
319333
!value.has_escaping_bound_vars(),
320334
"Normalizing {:?} without wrapping in a `Binder`",
321335
value
322336
);
323337

324-
if !value.has_projections() { value } else { value.fold_with(self) }
338+
if !needs_normalization(&value, self.param_env.reveal()) {
339+
value
340+
} else {
341+
value.fold_with(self)
342+
}
325343
}
326344
}
327345

@@ -341,7 +359,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
341359
}
342360

343361
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
344-
if !ty.has_projections() {
362+
if !needs_normalization(&ty, self.param_env.reveal()) {
345363
return ty;
346364
}
347365
// We don't want to normalize associated types that occur inside of region
@@ -825,7 +843,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
825843

826844
let cache_result = infcx.inner.borrow_mut().projection_cache().try_start(cache_key);
827845
match cache_result {
828-
Ok(()) => {}
846+
Ok(()) => debug!("no cache"),
829847
Err(ProjectionCacheEntry::Ambiguous) => {
830848
// If we found ambiguity the last time, that means we will continue
831849
// to do so until some type in the key changes (and we know it
@@ -852,6 +870,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
852870
return Err(InProgress);
853871
}
854872
Err(ProjectionCacheEntry::Recur) => {
873+
debug!("recur cache");
855874
return Err(InProgress);
856875
}
857876
Err(ProjectionCacheEntry::NormalizedTy(ty)) => {
@@ -1058,12 +1077,11 @@ impl<'tcx> Progress<'tcx> {
10581077
///
10591078
/// IMPORTANT:
10601079
/// - `obligation` must be fully normalized
1080+
#[tracing::instrument(level = "info", skip(selcx))]
10611081
fn project_type<'cx, 'tcx>(
10621082
selcx: &mut SelectionContext<'cx, 'tcx>,
10631083
obligation: &ProjectionTyObligation<'tcx>,
10641084
) -> Result<ProjectedTy<'tcx>, ProjectionTyError<'tcx>> {
1065-
debug!(?obligation, "project_type");
1066-
10671085
if !selcx.tcx().recursion_limit().value_within_limit(obligation.recursion_depth) {
10681086
debug!("project: overflow!");
10691087
// This should really be an immediate error, but some existing code

compiler/rustc_trait_selection/src/traits/query/normalize.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::infer::at::At;
66
use crate::infer::canonical::OriginalQueryValues;
77
use crate::infer::{InferCtxt, InferOk};
88
use crate::traits::error_reporting::InferCtxtExt;
9+
use crate::traits::project::needs_normalization;
910
use crate::traits::{Obligation, ObligationCause, PredicateObligation, Reveal};
1011
use rustc_data_structures::sso::SsoHashMap;
1112
use rustc_data_structures::stack::ensure_sufficient_stack;
@@ -49,7 +50,7 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> {
4950
value,
5051
self.param_env,
5152
);
52-
if !value.has_projections() {
53+
if !needs_normalization(&value, self.param_env.reveal()) {
5354
return Ok(Normalized { value, obligations: vec![] });
5455
}
5556

@@ -65,7 +66,7 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> {
6566
};
6667

6768
let result = value.fold_with(&mut normalizer);
68-
debug!(
69+
info!(
6970
"normalize::<{}>: result={:?} with {} obligations",
7071
std::any::type_name::<T>(),
7172
result,
@@ -112,7 +113,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
112113

113114
#[instrument(level = "debug", skip(self))]
114115
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
115-
if !ty.has_projections() {
116+
if !needs_normalization(&ty, self.param_env.reveal()) {
116117
return ty;
117118
}
118119

compiler/rustc_trait_selection/src/traits/select/mod.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -1865,12 +1865,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
18651865
}
18661866
}
18671867

1868+
#[tracing::instrument(level = "debug", skip(self))]
18681869
fn match_impl(
18691870
&mut self,
18701871
impl_def_id: DefId,
18711872
obligation: &TraitObligation<'tcx>,
18721873
) -> Result<Normalized<'tcx, SubstsRef<'tcx>>, ()> {
1873-
debug!(?impl_def_id, ?obligation, "match_impl");
18741874
let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap();
18751875

18761876
// Before we create the substitutions and everything, first
@@ -1888,6 +1888,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
18881888

18891889
let impl_trait_ref = impl_trait_ref.subst(self.tcx(), impl_substs);
18901890

1891+
debug!(?impl_trait_ref);
1892+
18911893
let Normalized { value: impl_trait_ref, obligations: mut nested_obligations } =
18921894
ensure_sufficient_stack(|| {
18931895
project::normalize_with_depth(
@@ -1915,7 +1917,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
19151917
return Err(());
19161918
}
19171919

1918-
debug!(?impl_substs, "match_impl: success");
1920+
debug!(?impl_substs, ?nested_obligations, "match_impl: success");
19191921
Ok(Normalized { value: impl_substs, obligations: nested_obligations })
19201922
}
19211923

@@ -2068,6 +2070,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
20682070
/// impl or trait. The obligations are substituted and fully
20692071
/// normalized. This is used when confirming an impl or default
20702072
/// impl.
2073+
#[tracing::instrument(level = "debug", skip(self, cause, param_env))]
20712074
fn impl_or_trait_obligations(
20722075
&mut self,
20732076
cause: ObligationCause<'tcx>,
@@ -2076,7 +2079,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
20762079
def_id: DefId, // of impl or trait
20772080
substs: SubstsRef<'tcx>, // for impl or trait
20782081
) -> Vec<PredicateObligation<'tcx>> {
2079-
debug!(?def_id, "impl_or_trait_obligations");
20802082
let tcx = self.tcx();
20812083

20822084
// To allow for one-pass evaluation of the nested obligation,
@@ -2094,9 +2096,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
20942096
// `$1: Copy`, so we must ensure the obligations are emitted in
20952097
// that order.
20962098
let predicates = tcx.predicates_of(def_id);
2099+
debug!(?predicates);
20972100
assert_eq!(predicates.parent, None);
20982101
let mut obligations = Vec::with_capacity(predicates.predicates.len());
20992102
for (predicate, _) in predicates.predicates {
2103+
debug!(?predicate);
21002104
let predicate = normalize_with_depth_to(
21012105
self,
21022106
param_env,

compiler/rustc_trait_selection/src/traits/wf.rs

+1
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ pub fn trait_obligations<'a, 'tcx>(
8585
let mut wf =
8686
WfPredicates { infcx, param_env, body_id, span, out: vec![], recursion_depth: 0, item };
8787
wf.compute_trait_ref(trait_ref, Elaborate::All);
88+
debug!(obligations = ?wf.out);
8889
wf.normalize()
8990
}
9091

compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1578,6 +1578,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15781578
}
15791579

15801580
/// Add all the obligations that are required, substituting and normalized appropriately.
1581+
#[tracing::instrument(level = "debug", skip(self, span, def_id, substs))]
15811582
fn add_required_obligations(&self, span: Span, def_id: DefId, substs: &SubstsRef<'tcx>) {
15821583
let (bounds, spans) = self.instantiate_bounds(span, def_id, &substs);
15831584

compiler/rustc_typeck/src/check/inherited.rs

+1
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ impl Inherited<'a, 'tcx> {
179179
T: TypeFoldable<'tcx>,
180180
{
181181
let ok = self.partially_normalize_associated_types_in(cause, param_env, value);
182+
debug!(?ok);
182183
self.register_infer_ok_obligations(ok)
183184
}
184185
}

compiler/rustc_typeck/src/check/wfcheck.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -379,14 +379,13 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
379379
}
380380
}
381381

382+
#[tracing::instrument(level = "debug", skip(tcx, span, sig_if_method))]
382383
fn check_associated_item(
383384
tcx: TyCtxt<'_>,
384385
item_id: hir::HirId,
385386
span: Span,
386387
sig_if_method: Option<&hir::FnSig<'_>>,
387388
) {
388-
debug!("check_associated_item: {:?}", item_id);
389-
390389
let code = ObligationCauseCode::WellFormed(Some(item_id));
391390
for_id(tcx, item_id, span).with_fcx(|fcx| {
392391
let item = fcx.tcx.associated_item(fcx.tcx.hir().local_def_id(item_id));
@@ -650,14 +649,13 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: hir::HirId, ty_span: Span, allow_fo
650649
});
651650
}
652651

652+
#[tracing::instrument(level = "debug", skip(tcx, ast_self_ty, ast_trait_ref))]
653653
fn check_impl<'tcx>(
654654
tcx: TyCtxt<'tcx>,
655655
item: &'tcx hir::Item<'tcx>,
656656
ast_self_ty: &hir::Ty<'_>,
657657
ast_trait_ref: &Option<hir::TraitRef<'_>>,
658658
) {
659-
debug!("check_impl: {:?}", item);
660-
661659
for_item(tcx, item).with_fcx(|fcx| {
662660
match *ast_trait_ref {
663661
Some(ref ast_trait_ref) => {
@@ -675,6 +673,7 @@ fn check_impl<'tcx>(
675673
ast_trait_ref.path.span,
676674
Some(item),
677675
);
676+
debug!(?obligations);
678677
for obligation in obligations {
679678
fcx.register_predicate(obligation);
680679
}

0 commit comments

Comments
 (0)