Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 99aca75

Browse files
committed
middle: split caller_bounds into multiple fields
Instead of filtering on `caller_bounds` at every use, instead filter them once when creating the `ParamEnv`. This will avoid unnecessary iteration over irrelevant bounds and improve performance.
1 parent 5a320ea commit 99aca75

File tree

11 files changed

+149
-57
lines changed

11 files changed

+149
-57
lines changed

compiler/rustc_hir_analysis/src/check/compare_impl_item.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ fn compare_method_predicate_entailment<'tcx>(
233233
}
234234

235235
let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_def_id);
236-
let param_env = ty::ParamEnv::new(tcx, tcx.mk_clauses(&hybrid_preds));
236+
let param_env = ty::ParamEnv::from_iter(tcx, hybrid_preds.iter().copied());
237237
let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
238238
debug!(?param_env);
239239

@@ -523,7 +523,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
523523
.into_iter()
524524
.chain(tcx.predicates_of(trait_m.def_id).instantiate_own(tcx, trait_to_impl_args))
525525
.map(|(clause, _)| clause);
526-
let param_env = ty::ParamEnv::new(tcx, tcx.mk_clauses_from_iter(hybrid_preds));
526+
let param_env = ty::ParamEnv::from_iter(tcx, hybrid_preds);
527527
let param_env = traits::normalize_param_env_or_error(
528528
tcx,
529529
param_env,
@@ -1837,7 +1837,7 @@ fn compare_const_predicate_entailment<'tcx>(
18371837
.map(|(predicate, _)| predicate),
18381838
);
18391839

1840-
let param_env = ty::ParamEnv::new(tcx, tcx.mk_clauses(&hybrid_preds));
1840+
let param_env = ty::ParamEnv::from_iter(tcx, hybrid_preds.iter().copied());
18411841
let param_env = traits::normalize_param_env_or_error(
18421842
tcx,
18431843
param_env,
@@ -1988,7 +1988,7 @@ fn compare_type_predicate_entailment<'tcx>(
19881988
);
19891989
}
19901990

1991-
let param_env = ty::ParamEnv::new(tcx, tcx.mk_clauses(&hybrid_preds));
1991+
let param_env = ty::ParamEnv::from_iter(tcx, hybrid_preds.iter().copied());
19921992
let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
19931993
debug!(?param_env);
19941994

@@ -2336,7 +2336,7 @@ fn param_env_with_gat_bounds<'tcx>(
23362336
};
23372337
}
23382338

2339-
ty::ParamEnv::new(tcx, tcx.mk_clauses(&predicates))
2339+
ty::ParamEnv::from_iter(tcx, predicates.iter().copied())
23402340
}
23412341

23422342
/// Manually check here that `async fn foo()` wasn't matched against `fn foo()`,

compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ pub(crate) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
132132
.into_iter()
133133
.chain(tcx.predicates_of(trait_m.def_id).instantiate_own(tcx, trait_m_to_impl_m_args))
134134
.map(|(clause, _)| clause);
135-
let param_env = ty::ParamEnv::new(tcx, tcx.mk_clauses_from_iter(hybrid_preds));
135+
let param_env = ty::ParamEnv::from_iter(tcx, hybrid_preds);
136136
let param_env = normalize_param_env_or_error(tcx, param_env, ObligationCause::dummy());
137137

138138
let ref infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());

compiler/rustc_hir_analysis/src/check/wfcheck.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -586,11 +586,9 @@ fn augment_param_env<'tcx>(
586586
return param_env;
587587
}
588588

589-
let bounds =
590-
tcx.mk_clauses_from_iter(param_env.all_clauses().chain(new_predicates.iter().cloned()));
591589
// FIXME(compiler-errors): Perhaps there is a case where we need to normalize this
592590
// i.e. traits::normalize_param_env_or_error
593-
ty::ParamEnv::new(tcx, bounds)
591+
ty::ParamEnv::from_iter(tcx, param_env.all_clauses().chain(new_predicates.iter().cloned()))
594592
}
595593

596594
/// We use the following trait as an example throughout this function.

compiler/rustc_middle/src/ty/codec.rs

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,14 @@ impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for CtfeProvenance {
209209

210210
impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::ParamEnvInner<'tcx> {
211211
fn encode(&self, e: &mut E) {
212-
self.caller_bounds.encode(e);
212+
self.trait_clauses.encode(e);
213+
self.region_outlives_clauses.encode(e);
214+
self.type_outlives_clauses.encode(e);
215+
self.projection_clauses.encode(e);
216+
self.const_arg_has_type_clauses.encode(e);
217+
self.well_formed_clauses.encode(e);
218+
self.const_evaluatable_clauses.encode(e);
219+
self.host_effect_clauses.encode(e);
213220
}
214221
}
215222

@@ -340,8 +347,24 @@ impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::SymbolName<'tcx> {
340347

341348
impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::ParamEnvInner<'tcx> {
342349
fn decode(d: &mut D) -> Self {
343-
let caller_bounds = Decodable::decode(d);
344-
ty::ParamEnvInner { caller_bounds }
350+
let trait_clauses = Decodable::decode(d);
351+
let region_outlives_clauses = Decodable::decode(d);
352+
let type_outlives_clauses = Decodable::decode(d);
353+
let projection_clauses = Decodable::decode(d);
354+
let const_arg_has_type_clauses = Decodable::decode(d);
355+
let well_formed_clauses = Decodable::decode(d);
356+
let const_evaluatable_clauses = Decodable::decode(d);
357+
let host_effect_clauses = Decodable::decode(d);
358+
ty::ParamEnvInner {
359+
trait_clauses,
360+
region_outlives_clauses,
361+
type_outlives_clauses,
362+
projection_clauses,
363+
const_arg_has_type_clauses,
364+
well_formed_clauses,
365+
const_evaluatable_clauses,
366+
host_effect_clauses,
367+
}
345368
}
346369
}
347370

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 104 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -971,18 +971,39 @@ impl<'tcx> rustc_type_ir::Flags for Clauses<'tcx> {
971971
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
972972
#[derive(HashStable, TypeVisitable, TypeFoldable)]
973973
pub struct ParamEnvInner<'tcx> {
974-
/// Caller bounds are `Obligation`s that the caller must satisfy. This is
975-
/// basically the set of bounds on the in-scope type parameters, translated
976-
/// into `Obligation`s, and elaborated and normalized.
977-
///
978-
/// Use the `caller_bounds()` method to access.
979-
caller_bounds: Clauses<'tcx>,
980-
}
981-
982-
/// When interacting with the type system we must provide information about the
983-
/// environment. `ParamEnv` is the type that represents this information. See the
974+
/// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be
975+
/// the `Self` type of the trait reference and `A`, `B`, and `C`
976+
/// would be the type parameters.
977+
trait_clauses: Clauses<'tcx>,
978+
/// `where 'a: 'r`
979+
region_outlives_clauses: Clauses<'tcx>,
980+
/// `where T: 'r`
981+
type_outlives_clauses: Clauses<'tcx>,
982+
/// `where <T as TraitRef>::Name == X`, approximately.
983+
/// See the `ProjectionPredicate` struct for details.
984+
projection_clauses: Clauses<'tcx>,
985+
/// Ensures that a const generic argument to a parameter `const N: u8`
986+
/// is of type `u8`.
987+
const_arg_has_type_clauses: Clauses<'tcx>,
988+
/// No syntax: `T` well-formed.
989+
well_formed_clauses: Clauses<'tcx>,
990+
/// Constant initializer must evaluate successfully.
991+
const_evaluatable_clauses: Clauses<'tcx>,
992+
/// Enforces the constness of the predicate we're calling. Like a projection
993+
/// goal from a where clause, it's always going to be paired with a
994+
/// corresponding trait clause; this just enforces the *constness* of that
995+
/// implementation.
996+
host_effect_clauses: Clauses<'tcx>,
997+
}
998+
999+
/// When interacting with the type system we must provide information about the environment.
1000+
/// `ParamEnv` is the type that represents this information. See the
9841001
/// [dev guide chapter][param_env_guide] for more information.
9851002
///
1003+
/// Contains various kinds of caller bounds - `Obligation`s that the caller must satisfy. This is
1004+
/// basically the set of bounds on the in-scope type parameters, translated into `Obligation`s,
1005+
/// and elaborated and normalized.
1006+
///
9861007
/// [param_env_guide]: https://rustc-dev-guide.rust-lang.org/typing_parameter_envs.html
9871008
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
9881009
#[derive(HashStable)]
@@ -997,64 +1018,117 @@ impl<'tcx> ParamEnv<'tcx> {
9971018
/// [param_env_guide]: https://rustc-dev-guide.rust-lang.org/typing_parameter_envs.html
9981019
#[inline]
9991020
pub fn empty(tcx: TyCtxt<'tcx>) -> Self {
1000-
tcx.mk_param_env(ParamEnvInner { caller_bounds: ListWithCachedTypeInfo::empty() })
1021+
tcx.mk_param_env(ParamEnvInner {
1022+
trait_clauses: ListWithCachedTypeInfo::empty(),
1023+
region_outlives_clauses: ListWithCachedTypeInfo::empty(),
1024+
type_outlives_clauses: ListWithCachedTypeInfo::empty(),
1025+
projection_clauses: ListWithCachedTypeInfo::empty(),
1026+
const_arg_has_type_clauses: ListWithCachedTypeInfo::empty(),
1027+
well_formed_clauses: ListWithCachedTypeInfo::empty(),
1028+
const_evaluatable_clauses: ListWithCachedTypeInfo::empty(),
1029+
host_effect_clauses: ListWithCachedTypeInfo::empty(),
1030+
})
10011031
}
10021032

10031033
#[inline]
10041034
pub fn all_clauses(self) -> impl Iterator<Item = Clause<'tcx>> {
1005-
self.0.0.caller_bounds.iter()
1035+
let trait_clauses = self.0.0.trait_clauses.iter();
1036+
let region_outlives_clauses = self.0.0.region_outlives_clauses.iter();
1037+
let type_outlives_clauses = self.0.0.type_outlives_clauses.iter();
1038+
let projection_clauses = self.0.0.projection_clauses.iter();
1039+
let const_arg_has_type_clauses = self.0.0.const_arg_has_type_clauses.iter();
1040+
let well_formed_clauses = self.0.0.well_formed_clauses.iter();
1041+
let const_evaluatable_clauses = self.0.0.const_evaluatable_clauses.iter();
1042+
let host_effect_clauses = self.0.0.host_effect_clauses.iter();
1043+
1044+
trait_clauses.chain(region_outlives_clauses.chain(type_outlives_clauses.chain(
1045+
projection_clauses.chain(const_arg_has_type_clauses.chain(
1046+
well_formed_clauses.chain(const_evaluatable_clauses.chain(host_effect_clauses)),
1047+
)),
1048+
)))
10061049
}
10071050

10081051
#[inline]
10091052
pub fn trait_clauses(self) -> impl Iterator<Item = PolyTraitPredicate<'tcx>> {
1010-
self.0.0.caller_bounds.iter().filter_map(|c| c.as_trait_clause())
1053+
self.0.0.trait_clauses.iter().filter_map(|c| c.as_trait_clause())
10111054
}
10121055

10131056
#[inline]
10141057
pub fn region_outlives_clauses(
10151058
self,
10161059
) -> impl Iterator<Item = PolyRegionOutlivesPredicate<'tcx>> {
1017-
self.0.0.caller_bounds.iter().filter_map(|c| c.as_region_outlives_clause())
1060+
self.0.0.region_outlives_clauses.iter().filter_map(|c| c.as_region_outlives_clause())
10181061
}
10191062

10201063
#[inline]
10211064
pub fn type_outlives_clauses(self) -> impl Iterator<Item = PolyTypeOutlivesPredicate<'tcx>> {
1022-
self.0.0.caller_bounds.iter().filter_map(|c| c.as_type_outlives_clause())
1065+
self.0.0.type_outlives_clauses.iter().filter_map(|c| c.as_type_outlives_clause())
10231066
}
10241067

10251068
#[inline]
10261069
pub fn projection_clauses(self) -> impl Iterator<Item = PolyProjectionPredicate<'tcx>> {
1027-
self.0.0.caller_bounds.iter().filter_map(|c| c.as_projection_clause())
1070+
self.0.0.projection_clauses.iter().filter_map(|c| c.as_projection_clause())
10281071
}
10291072

10301073
#[inline]
10311074
pub fn const_arg_has_type_clauses(
10321075
self,
10331076
) -> impl Iterator<Item = PolyConstArgHasTypePredicate<'tcx>> {
1034-
self.0.0.caller_bounds.iter().filter_map(|c| c.as_const_arg_has_type_clause())
1077+
self.0.0.const_arg_has_type_clauses.iter().filter_map(|c| c.as_const_arg_has_type_clause())
10351078
}
10361079

10371080
#[inline]
10381081
pub fn well_formed_clauses(self) -> impl Iterator<Item = PolyWellFormedPredicate<'tcx>> {
1039-
self.0.0.caller_bounds.iter().filter_map(|c| c.as_well_formed_clause())
1082+
self.0.0.well_formed_clauses.iter().filter_map(|c| c.as_well_formed_clause())
10401083
}
10411084

10421085
#[inline]
10431086
pub fn const_evaluatable_clauses(
10441087
self,
10451088
) -> impl Iterator<Item = PolyConstEvaluatablePredicate<'tcx>> {
1046-
self.0.0.caller_bounds.iter().filter_map(|c| c.as_const_evaluatable_clause())
1089+
self.0.0.const_evaluatable_clauses.iter().filter_map(|c| c.as_const_evaluatable_clause())
10471090
}
10481091

10491092
#[inline]
10501093
pub fn host_effect_clauses(self) -> impl Iterator<Item = PolyHostEffectPredicate<'tcx>> {
1051-
self.0.0.caller_bounds.iter().filter_map(|c| c.as_host_effect_clause())
1094+
self.0.0.host_effect_clauses.iter().filter_map(|c| c.as_host_effect_clause())
10521095
}
10531096

10541097
/// Construct a trait environment with the given set of predicates.
10551098
#[inline]
1056-
pub fn new(tcx: TyCtxt<'tcx>, caller_bounds: Clauses<'tcx>) -> Self {
1057-
tcx.mk_param_env(ParamEnvInner { caller_bounds })
1099+
pub fn from_iter(tcx: TyCtxt<'tcx>, clauses: impl Iterator<Item = Clause<'tcx>>) -> Self {
1100+
let mut trait_clauses = Vec::new();
1101+
let mut region_outlives_clauses = Vec::new();
1102+
let mut type_outlives_clauses = Vec::new();
1103+
let mut projection_clauses = Vec::new();
1104+
let mut const_arg_has_type_clauses = Vec::new();
1105+
let mut well_formed_clauses = Vec::new();
1106+
let mut const_evaluatable_clauses = Vec::new();
1107+
let mut host_effect_clauses = Vec::new();
1108+
1109+
for clause in clauses {
1110+
match clause.kind().skip_binder() {
1111+
ClauseKind::Trait(..) => trait_clauses.push(clause),
1112+
ClauseKind::RegionOutlives(..) => region_outlives_clauses.push(clause),
1113+
ClauseKind::TypeOutlives(..) => type_outlives_clauses.push(clause),
1114+
ClauseKind::Projection(..) => projection_clauses.push(clause),
1115+
ClauseKind::ConstArgHasType(..) => const_arg_has_type_clauses.push(clause),
1116+
ClauseKind::WellFormed(..) => well_formed_clauses.push(clause),
1117+
ClauseKind::ConstEvaluatable(..) => const_evaluatable_clauses.push(clause),
1118+
ClauseKind::HostEffect(..) => host_effect_clauses.push(clause),
1119+
}
1120+
}
1121+
1122+
tcx.mk_param_env(ParamEnvInner {
1123+
trait_clauses: tcx.mk_clauses(&trait_clauses),
1124+
region_outlives_clauses: tcx.mk_clauses(&region_outlives_clauses),
1125+
type_outlives_clauses: tcx.mk_clauses(&type_outlives_clauses),
1126+
projection_clauses: tcx.mk_clauses(&projection_clauses),
1127+
const_arg_has_type_clauses: tcx.mk_clauses(&const_arg_has_type_clauses),
1128+
well_formed_clauses: tcx.mk_clauses(&well_formed_clauses),
1129+
const_evaluatable_clauses: tcx.mk_clauses(&const_evaluatable_clauses),
1130+
host_effect_clauses: tcx.mk_clauses(&host_effect_clauses),
1131+
})
10581132
}
10591133

10601134
/// Creates a pair of param-env and value for use in queries.
@@ -1065,35 +1139,35 @@ impl<'tcx> ParamEnv<'tcx> {
10651139

10661140
impl<'tcx> rustc_type_ir::inherent::ParamEnv<TyCtxt<'tcx>> for ParamEnv<'tcx> {
10671141
fn trait_clauses(self) -> impl Iterator<Item = Clause<'tcx>> {
1068-
self.all_clauses().filter(|c| c.as_trait_clause().is_some())
1142+
self.0.0.trait_clauses.iter()
10691143
}
10701144

10711145
fn region_outlives_clauses(self) -> impl Iterator<Item = Clause<'tcx>> {
1072-
self.all_clauses().filter(|c| c.as_region_outlives_clause().is_some())
1146+
self.0.0.region_outlives_clauses.iter()
10731147
}
10741148

10751149
fn type_outlives_clauses(self) -> impl Iterator<Item = Clause<'tcx>> {
1076-
self.all_clauses().filter(|c| c.as_type_outlives_clause().is_some())
1150+
self.0.0.type_outlives_clauses.iter()
10771151
}
10781152

10791153
fn projection_clauses(self) -> impl Iterator<Item = Clause<'tcx>> {
1080-
self.all_clauses().filter(|c| c.as_projection_clause().is_some())
1154+
self.0.0.projection_clauses.iter()
10811155
}
10821156

10831157
fn const_arg_has_type_clauses(self) -> impl Iterator<Item = Clause<'tcx>> {
1084-
self.all_clauses().filter(|c| c.as_const_arg_has_type_clause().is_some())
1158+
self.0.0.const_arg_has_type_clauses.iter()
10851159
}
10861160

10871161
fn well_formed_clauses(self) -> impl Iterator<Item = Clause<'tcx>> {
1088-
self.all_clauses().filter(|c| c.as_well_formed_clause().is_some())
1162+
self.0.0.well_formed_clauses.iter()
10891163
}
10901164

10911165
fn const_evaluatable_clauses(self) -> impl Iterator<Item = Clause<'tcx>> {
1092-
self.all_clauses().filter(|c| c.as_const_evaluatable_clause().is_some())
1166+
self.0.0.const_evaluatable_clauses.iter()
10931167
}
10941168

10951169
fn host_effect_clauses(self) -> impl Iterator<Item = Clause<'tcx>> {
1096-
self.all_clauses().filter(|c| c.as_host_effect_clause().is_some())
1170+
self.0.0.host_effect_clauses.iter()
10971171
}
10981172
}
10991173

compiler/rustc_trait_selection/src/traits/auto_trait.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -319,15 +319,12 @@ impl<'tcx> AutoTraitFinder<'tcx> {
319319
.map(|c| c.as_predicate())
320320
.chain(user_computed_preds.iter().cloned());
321321
let normalized_preds = elaborate(tcx, computed_preds);
322-
new_env = ty::ParamEnv::new(
323-
tcx,
324-
tcx.mk_clauses_from_iter(normalized_preds.filter_map(|p| p.as_clause())),
325-
);
322+
new_env = ty::ParamEnv::from_iter(tcx, normalized_preds.filter_map(|p| p.as_clause()));
326323
}
327324

328-
let final_user_env = ty::ParamEnv::new(
325+
let final_user_env = ty::ParamEnv::from_iter(
329326
tcx,
330-
tcx.mk_clauses_from_iter(user_computed_preds.into_iter().filter_map(|p| p.as_clause())),
327+
user_computed_preds.into_iter().filter_map(|p| p.as_clause()),
331328
);
332329
debug!(
333330
"evaluate_nested_obligations(ty={:?}, trait_did={:?}): succeeded with '{:?}' \

compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -612,7 +612,7 @@ fn receiver_is_dispatchable<'tcx>(
612612

613613
normalize_param_env_or_error(
614614
tcx,
615-
ty::ParamEnv::new(tcx, tcx.mk_clauses(&predicates)),
615+
ty::ParamEnv::from_iter(tcx, predicates.iter().copied()),
616616
ObligationCause::dummy_with_span(tcx.def_span(method.def_id)),
617617
)
618618
};

compiler/rustc_trait_selection/src/traits/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ pub fn normalize_param_env_or_error<'tcx>(
414414

415415
debug!("normalize_param_env_or_error: elaborated-predicates={:?}", predicates);
416416

417-
let elaborated_env = ty::ParamEnv::new(tcx, tcx.mk_clauses(&predicates));
417+
let elaborated_env = ty::ParamEnv::from_iter(tcx, predicates.iter().copied());
418418
if !elaborated_env.has_aliases() {
419419
return elaborated_env;
420420
}
@@ -461,7 +461,7 @@ pub fn normalize_param_env_or_error<'tcx>(
461461
// here. I believe they should not matter, because we are ignoring TypeOutlives param-env
462462
// predicates here anyway. Keeping them here anyway because it seems safer.
463463
let outlives_env = non_outlives_predicates.iter().chain(&outlives_predicates).cloned();
464-
let outlives_env = ty::ParamEnv::new(tcx, tcx.mk_clauses_from_iter(outlives_env));
464+
let outlives_env = ty::ParamEnv::from_iter(tcx, outlives_env);
465465
let Ok(outlives_predicates) =
466466
do_normalize_predicates(tcx, cause, outlives_env, outlives_predicates)
467467
else {
@@ -474,7 +474,7 @@ pub fn normalize_param_env_or_error<'tcx>(
474474
let mut predicates = non_outlives_predicates;
475475
predicates.extend(outlives_predicates);
476476
debug!("normalize_param_env_or_error: final predicates={:?}", predicates);
477-
ty::ParamEnv::new(tcx, tcx.mk_clauses(&predicates))
477+
ty::ParamEnv::from_iter(tcx, predicates.iter().copied())
478478
}
479479

480480
#[derive(Debug)]

compiler/rustc_ty_utils/src/ty.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
163163

164164
let local_did = def_id.as_local();
165165

166-
let unnormalized_env = ty::ParamEnv::new(tcx, tcx.mk_clauses(&predicates));
166+
let unnormalized_env = ty::ParamEnv::from_iter(tcx, predicates.iter().copied());
167167

168168
let body_id = local_did.unwrap_or(CRATE_DEF_ID);
169169
let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id);

0 commit comments

Comments
 (0)