Skip to content

Commit 01dfdae

Browse files
authored
Rollup merge of rust-lang#131979 - compiler-errors:compare-pred-entail, r=fmease
Minor tweaks to `compare_impl_item.rs` 1. Stop using the `InstantiatedPredicates` struct for `hybrid_preds` in `compare_impl_item.rs`, since we never actually push anything into the `spans` part of it. 2. Remove redundant impl args and don't do useless identity substitution, prefer calling `instantiate_identity`.
2 parents 304de2e + 21d95fb commit 01dfdae

File tree

3 files changed

+109
-94
lines changed

3 files changed

+109
-94
lines changed

compiler/rustc_hir_analysis/src/check/compare_impl_item.rs

+66-91
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,13 @@ mod refine;
4343
/// - `impl_m`: type of the method we are checking
4444
/// - `trait_m`: the method in the trait
4545
/// - `impl_trait_ref`: the TraitRef corresponding to the trait implementation
46+
#[instrument(level = "debug", skip(tcx))]
4647
pub(super) fn compare_impl_method<'tcx>(
4748
tcx: TyCtxt<'tcx>,
4849
impl_m: ty::AssocItem,
4950
trait_m: ty::AssocItem,
5051
impl_trait_ref: ty::TraitRef<'tcx>,
5152
) {
52-
debug!("compare_impl_method(impl_trait_ref={:?})", impl_trait_ref);
53-
5453
let _: Result<_, ErrorGuaranteed> = try {
5554
check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, false)?;
5655
compare_method_predicate_entailment(tcx, impl_m, trait_m, impl_trait_ref)?;
@@ -167,8 +166,6 @@ fn compare_method_predicate_entailment<'tcx>(
167166
trait_m: ty::AssocItem,
168167
impl_trait_ref: ty::TraitRef<'tcx>,
169168
) -> Result<(), ErrorGuaranteed> {
170-
let trait_to_impl_args = impl_trait_ref.args;
171-
172169
// This node-id should be used for the `body_id` field on each
173170
// `ObligationCause` (and the `FnCtxt`).
174171
//
@@ -183,53 +180,43 @@ fn compare_method_predicate_entailment<'tcx>(
183180
kind: impl_m.kind,
184181
});
185182

186-
// Create mapping from impl to placeholder.
187-
let impl_to_placeholder_args = GenericArgs::identity_for_item(tcx, impl_m.def_id);
188-
189-
// Create mapping from trait to placeholder.
190-
let trait_to_placeholder_args =
191-
impl_to_placeholder_args.rebase_onto(tcx, impl_m.container_id(tcx), trait_to_impl_args);
192-
debug!("compare_impl_method: trait_to_placeholder_args={:?}", trait_to_placeholder_args);
183+
// Create mapping from trait method to impl method.
184+
let trait_to_impl_args = GenericArgs::identity_for_item(tcx, impl_m.def_id).rebase_onto(
185+
tcx,
186+
impl_m.container_id(tcx),
187+
impl_trait_ref.args,
188+
);
189+
debug!(?trait_to_impl_args);
193190

194191
let impl_m_predicates = tcx.predicates_of(impl_m.def_id);
195192
let trait_m_predicates = tcx.predicates_of(trait_m.def_id);
196193

197-
// Create obligations for each predicate declared by the impl
198-
// definition in the context of the trait's parameter
199-
// environment. We can't just use `impl_env.caller_bounds`,
200-
// however, because we want to replace all late-bound regions with
201-
// region variables.
202-
let impl_predicates = tcx.predicates_of(impl_m_predicates.parent.unwrap());
203-
let mut hybrid_preds = impl_predicates.instantiate_identity(tcx);
204-
205-
debug!("compare_impl_method: impl_bounds={:?}", hybrid_preds);
206-
207194
// This is the only tricky bit of the new way we check implementation methods
208195
// We need to build a set of predicates where only the method-level bounds
209196
// are from the trait and we assume all other bounds from the implementation
210197
// to be previously satisfied.
211198
//
212199
// We then register the obligations from the impl_m and check to see
213200
// if all constraints hold.
214-
hybrid_preds.predicates.extend(
215-
trait_m_predicates
216-
.instantiate_own(tcx, trait_to_placeholder_args)
217-
.map(|(predicate, _)| predicate),
201+
let impl_predicates = tcx.predicates_of(impl_m_predicates.parent.unwrap());
202+
let mut hybrid_preds = impl_predicates.instantiate_identity(tcx).predicates;
203+
hybrid_preds.extend(
204+
trait_m_predicates.instantiate_own(tcx, trait_to_impl_args).map(|(predicate, _)| predicate),
218205
);
219206

220-
// Construct trait parameter environment and then shift it into the placeholder viewpoint.
221-
// The key step here is to update the caller_bounds's predicates to be
222-
// the new hybrid bounds we computed.
223207
let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_def_id);
224-
let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds.predicates), Reveal::UserFacing);
208+
let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds), Reveal::UserFacing);
225209
let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
210+
debug!(caller_bounds=?param_env.caller_bounds());
226211

227212
let infcx = &tcx.infer_ctxt().build();
228213
let ocx = ObligationCtxt::new_with_diagnostics(infcx);
229214

230-
debug!("compare_impl_method: caller_bounds={:?}", param_env.caller_bounds());
231-
232-
let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_placeholder_args);
215+
// Create obligations for each predicate declared by the impl
216+
// definition in the context of the hybrid param-env. This makes
217+
// sure that the impl's method's where clauses are not more
218+
// restrictive than the trait's method (and the impl itself).
219+
let impl_m_own_bounds = impl_m_predicates.instantiate_own_identity();
233220
for (predicate, span) in impl_m_own_bounds {
234221
let normalize_cause = traits::ObligationCause::misc(span, impl_m_def_id);
235222
let predicate = ocx.normalize(&normalize_cause, param_env, predicate);
@@ -256,7 +243,6 @@ fn compare_method_predicate_entailment<'tcx>(
256243
// any associated types appearing in the fn arguments or return
257244
// type.
258245

259-
// Compute placeholder form of impl and trait method tys.
260246
let mut wf_tys = FxIndexSet::default();
261247

262248
let unnormalized_impl_sig = infcx.instantiate_binder_with_fresh_vars(
@@ -267,9 +253,9 @@ fn compare_method_predicate_entailment<'tcx>(
267253

268254
let norm_cause = ObligationCause::misc(impl_m_span, impl_m_def_id);
269255
let impl_sig = ocx.normalize(&norm_cause, param_env, unnormalized_impl_sig);
270-
debug!("compare_impl_method: impl_fty={:?}", impl_sig);
256+
debug!(?impl_sig);
271257

272-
let trait_sig = tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_to_placeholder_args);
258+
let trait_sig = tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_to_impl_args);
273259
let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, trait_sig);
274260

275261
// Next, add all inputs and output as well-formed tys. Importantly,
@@ -280,9 +266,7 @@ fn compare_method_predicate_entailment<'tcx>(
280266
// We also have to add the normalized trait signature
281267
// as we don't normalize during implied bounds computation.
282268
wf_tys.extend(trait_sig.inputs_and_output.iter());
283-
let trait_fty = Ty::new_fn_ptr(tcx, ty::Binder::dummy(trait_sig));
284-
285-
debug!("compare_impl_method: trait_fty={:?}", trait_fty);
269+
debug!(?trait_sig);
286270

287271
// FIXME: We'd want to keep more accurate spans than "the method signature" when
288272
// processing the comparison between the trait and impl fn, but we sadly lose them
@@ -455,8 +439,6 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
455439
// just so we don't ICE during instantiation later.
456440
check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, true)?;
457441

458-
let trait_to_impl_args = impl_trait_ref.args;
459-
460442
let impl_m_hir_id = tcx.local_def_id_to_hir_id(impl_m_def_id);
461443
let return_span = tcx.hir().fn_decl_by_hir_id(impl_m_hir_id).unwrap().output.span();
462444
let cause =
@@ -466,18 +448,18 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
466448
kind: impl_m.kind,
467449
});
468450

469-
// Create mapping from impl to placeholder.
470-
let impl_to_placeholder_args = GenericArgs::identity_for_item(tcx, impl_m.def_id);
471-
472-
// Create mapping from trait to placeholder.
473-
let trait_to_placeholder_args =
474-
impl_to_placeholder_args.rebase_onto(tcx, impl_m.container_id(tcx), trait_to_impl_args);
451+
// Create mapping from trait to impl (i.e. impl trait header + impl method identity args).
452+
let trait_to_impl_args = GenericArgs::identity_for_item(tcx, impl_m.def_id).rebase_onto(
453+
tcx,
454+
impl_m.container_id(tcx),
455+
impl_trait_ref.args,
456+
);
475457

476458
let hybrid_preds = tcx
477459
.predicates_of(impl_m.container_id(tcx))
478460
.instantiate_identity(tcx)
479461
.into_iter()
480-
.chain(tcx.predicates_of(trait_m.def_id).instantiate_own(tcx, trait_to_placeholder_args))
462+
.chain(tcx.predicates_of(trait_m.def_id).instantiate_own(tcx, trait_to_impl_args))
481463
.map(|(clause, _)| clause);
482464
let param_env = ty::ParamEnv::new(tcx.mk_clauses_from_iter(hybrid_preds), Reveal::UserFacing);
483465
let param_env = traits::normalize_param_env_or_error(
@@ -511,7 +493,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
511493
.instantiate_binder_with_fresh_vars(
512494
return_span,
513495
infer::HigherRankedType,
514-
tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_to_placeholder_args),
496+
tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_to_impl_args),
515497
)
516498
.fold_with(&mut collector);
517499

@@ -705,7 +687,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
705687
// Also, we only need to account for a difference in trait and impl args,
706688
// since we previously enforce that the trait method and impl method have the
707689
// same generics.
708-
let num_trait_args = trait_to_impl_args.len();
690+
let num_trait_args = impl_trait_ref.args.len();
709691
let num_impl_args = tcx.generics_of(impl_m.container_id(tcx)).own_params.len();
710692
let ty = match ty.try_fold_with(&mut RemapHiddenTyRegions {
711693
tcx,
@@ -1041,12 +1023,7 @@ fn check_region_bounds_on_impl_item<'tcx>(
10411023
let trait_generics = tcx.generics_of(trait_m.def_id);
10421024
let trait_params = trait_generics.own_counts().lifetimes;
10431025

1044-
debug!(
1045-
"check_region_bounds_on_impl_item: \
1046-
trait_generics={:?} \
1047-
impl_generics={:?}",
1048-
trait_generics, impl_generics
1049-
);
1026+
debug!(?trait_generics, ?impl_generics);
10501027

10511028
// Must have same number of early-bound lifetime parameters.
10521029
// Unfortunately, if the user screws up the bounds, then this
@@ -1710,8 +1687,7 @@ pub(super) fn compare_impl_const_raw(
17101687
let trait_const_item = tcx.associated_item(trait_const_item_def);
17111688
let impl_trait_ref =
17121689
tcx.impl_trait_ref(impl_const_item.container_id(tcx)).unwrap().instantiate_identity();
1713-
1714-
debug!("compare_impl_const(impl_trait_ref={:?})", impl_trait_ref);
1690+
debug!(?impl_trait_ref);
17151691

17161692
compare_number_of_generics(tcx, impl_const_item, trait_const_item, false)?;
17171693
compare_generic_param_kinds(tcx, impl_const_item, trait_const_item, false)?;
@@ -1722,6 +1698,7 @@ pub(super) fn compare_impl_const_raw(
17221698
/// The equivalent of [compare_method_predicate_entailment], but for associated constants
17231699
/// instead of associated functions.
17241700
// FIXME(generic_const_items): If possible extract the common parts of `compare_{type,const}_predicate_entailment`.
1701+
#[instrument(level = "debug", skip(tcx))]
17251702
fn compare_const_predicate_entailment<'tcx>(
17261703
tcx: TyCtxt<'tcx>,
17271704
impl_ct: ty::AssocItem,
@@ -1736,13 +1713,14 @@ fn compare_const_predicate_entailment<'tcx>(
17361713
// because we shouldn't really have to deal with lifetimes or
17371714
// predicates. In fact some of this should probably be put into
17381715
// shared functions because of DRY violations...
1739-
let impl_args = GenericArgs::identity_for_item(tcx, impl_ct.def_id);
1740-
let trait_to_impl_args =
1741-
impl_args.rebase_onto(tcx, impl_ct.container_id(tcx), impl_trait_ref.args);
1716+
let trait_to_impl_args = GenericArgs::identity_for_item(tcx, impl_ct.def_id).rebase_onto(
1717+
tcx,
1718+
impl_ct.container_id(tcx),
1719+
impl_trait_ref.args,
1720+
);
17421721

17431722
// Create a parameter environment that represents the implementation's
1744-
// method.
1745-
// Compute placeholder form of impl and trait const tys.
1723+
// associated const.
17461724
let impl_ty = tcx.type_of(impl_ct_def_id).instantiate_identity();
17471725

17481726
let trait_ty = tcx.type_of(trait_ct.def_id).instantiate(tcx, trait_to_impl_args);
@@ -1759,14 +1737,14 @@ fn compare_const_predicate_entailment<'tcx>(
17591737
// The predicates declared by the impl definition, the trait and the
17601738
// associated const in the trait are assumed.
17611739
let impl_predicates = tcx.predicates_of(impl_ct_predicates.parent.unwrap());
1762-
let mut hybrid_preds = impl_predicates.instantiate_identity(tcx);
1763-
hybrid_preds.predicates.extend(
1740+
let mut hybrid_preds = impl_predicates.instantiate_identity(tcx).predicates;
1741+
hybrid_preds.extend(
17641742
trait_ct_predicates
17651743
.instantiate_own(tcx, trait_to_impl_args)
17661744
.map(|(predicate, _)| predicate),
17671745
);
17681746

1769-
let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds.predicates), Reveal::UserFacing);
1747+
let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds), Reveal::UserFacing);
17701748
let param_env = traits::normalize_param_env_or_error(
17711749
tcx,
17721750
param_env,
@@ -1776,7 +1754,7 @@ fn compare_const_predicate_entailment<'tcx>(
17761754
let infcx = tcx.infer_ctxt().build();
17771755
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
17781756

1779-
let impl_ct_own_bounds = impl_ct_predicates.instantiate_own(tcx, impl_args);
1757+
let impl_ct_own_bounds = impl_ct_predicates.instantiate_own_identity();
17801758
for (predicate, span) in impl_ct_own_bounds {
17811759
let cause = ObligationCause::misc(span, impl_ct_def_id);
17821760
let predicate = ocx.normalize(&cause, param_env, predicate);
@@ -1787,20 +1765,15 @@ fn compare_const_predicate_entailment<'tcx>(
17871765

17881766
// There is no "body" here, so just pass dummy id.
17891767
let impl_ty = ocx.normalize(&cause, param_env, impl_ty);
1790-
1791-
debug!("compare_const_impl: impl_ty={:?}", impl_ty);
1768+
debug!(?impl_ty);
17921769

17931770
let trait_ty = ocx.normalize(&cause, param_env, trait_ty);
1794-
1795-
debug!("compare_const_impl: trait_ty={:?}", trait_ty);
1771+
debug!(?trait_ty);
17961772

17971773
let err = ocx.sup(&cause, param_env, trait_ty, impl_ty);
17981774

17991775
if let Err(terr) = err {
1800-
debug!(
1801-
"checking associated const for compatibility: impl ty {:?}, trait ty {:?}",
1802-
impl_ty, trait_ty
1803-
);
1776+
debug!(?impl_ty, ?trait_ty);
18041777

18051778
// Locate the Span containing just the type of the offending impl
18061779
let (ty, _) = tcx.hir().expect_impl_item(impl_ct_def_id).expect_const();
@@ -1845,14 +1818,13 @@ fn compare_const_predicate_entailment<'tcx>(
18451818
ocx.resolve_regions_and_report_errors(impl_ct_def_id, &outlives_env)
18461819
}
18471820

1821+
#[instrument(level = "debug", skip(tcx))]
18481822
pub(super) fn compare_impl_ty<'tcx>(
18491823
tcx: TyCtxt<'tcx>,
18501824
impl_ty: ty::AssocItem,
18511825
trait_ty: ty::AssocItem,
18521826
impl_trait_ref: ty::TraitRef<'tcx>,
18531827
) {
1854-
debug!("compare_impl_type(impl_trait_ref={:?})", impl_trait_ref);
1855-
18561828
let _: Result<(), ErrorGuaranteed> = try {
18571829
compare_number_of_generics(tcx, impl_ty, trait_ty, false)?;
18581830
compare_generic_param_kinds(tcx, impl_ty, trait_ty, false)?;
@@ -1864,20 +1836,23 @@ pub(super) fn compare_impl_ty<'tcx>(
18641836

18651837
/// The equivalent of [compare_method_predicate_entailment], but for associated types
18661838
/// instead of associated functions.
1839+
#[instrument(level = "debug", skip(tcx))]
18671840
fn compare_type_predicate_entailment<'tcx>(
18681841
tcx: TyCtxt<'tcx>,
18691842
impl_ty: ty::AssocItem,
18701843
trait_ty: ty::AssocItem,
18711844
impl_trait_ref: ty::TraitRef<'tcx>,
18721845
) -> Result<(), ErrorGuaranteed> {
1873-
let impl_args = GenericArgs::identity_for_item(tcx, impl_ty.def_id);
1874-
let trait_to_impl_args =
1875-
impl_args.rebase_onto(tcx, impl_ty.container_id(tcx), impl_trait_ref.args);
1846+
let trait_to_impl_args = GenericArgs::identity_for_item(tcx, impl_ty.def_id).rebase_onto(
1847+
tcx,
1848+
impl_ty.container_id(tcx),
1849+
impl_trait_ref.args,
1850+
);
18761851

18771852
let impl_ty_predicates = tcx.predicates_of(impl_ty.def_id);
18781853
let trait_ty_predicates = tcx.predicates_of(trait_ty.def_id);
18791854

1880-
let impl_ty_own_bounds = impl_ty_predicates.instantiate_own(tcx, impl_args);
1855+
let impl_ty_own_bounds = impl_ty_predicates.instantiate_own_identity();
18811856
if impl_ty_own_bounds.len() == 0 {
18821857
// Nothing to check.
18831858
return Ok(());
@@ -1887,29 +1862,29 @@ fn compare_type_predicate_entailment<'tcx>(
18871862
// `ObligationCause` (and the `FnCtxt`). This is what
18881863
// `regionck_item` expects.
18891864
let impl_ty_def_id = impl_ty.def_id.expect_local();
1890-
debug!("compare_type_predicate_entailment: trait_to_impl_args={:?}", trait_to_impl_args);
1865+
debug!(?trait_to_impl_args);
18911866

18921867
// The predicates declared by the impl definition, the trait and the
18931868
// associated type in the trait are assumed.
18941869
let impl_predicates = tcx.predicates_of(impl_ty_predicates.parent.unwrap());
1895-
let mut hybrid_preds = impl_predicates.instantiate_identity(tcx);
1896-
hybrid_preds.predicates.extend(
1870+
let mut hybrid_preds = impl_predicates.instantiate_identity(tcx).predicates;
1871+
hybrid_preds.extend(
18971872
trait_ty_predicates
18981873
.instantiate_own(tcx, trait_to_impl_args)
18991874
.map(|(predicate, _)| predicate),
19001875
);
1901-
1902-
debug!("compare_type_predicate_entailment: bounds={:?}", hybrid_preds);
1876+
debug!(?hybrid_preds);
19031877

19041878
let impl_ty_span = tcx.def_span(impl_ty_def_id);
19051879
let normalize_cause = ObligationCause::misc(impl_ty_span, impl_ty_def_id);
1906-
let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds.predicates), Reveal::UserFacing);
1880+
1881+
let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds), Reveal::UserFacing);
19071882
let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
1883+
debug!(caller_bounds=?param_env.caller_bounds());
1884+
19081885
let infcx = tcx.infer_ctxt().build();
19091886
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
19101887

1911-
debug!("compare_type_predicate_entailment: caller_bounds={:?}", param_env.caller_bounds());
1912-
19131888
for (predicate, span) in impl_ty_own_bounds {
19141889
let cause = ObligationCause::misc(span, impl_ty_def_id);
19151890
let predicate = ocx.normalize(&cause, param_env, predicate);
@@ -2009,11 +1984,11 @@ pub(super) fn check_type_bounds<'tcx>(
20091984
.explicit_item_bounds(trait_ty.def_id)
20101985
.iter_instantiated_copied(tcx, rebased_args)
20111986
.map(|(concrete_ty_bound, span)| {
2012-
debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound);
1987+
debug!(?concrete_ty_bound);
20131988
traits::Obligation::new(tcx, mk_cause(span), param_env, concrete_ty_bound)
20141989
})
20151990
.collect();
2016-
debug!("check_type_bounds: item_bounds={:?}", obligations);
1991+
debug!(item_bounds=?obligations);
20171992

20181993
// Normalize predicates with the assumption that the GAT may always normalize
20191994
// to its definition type. This should be the param-env we use to *prove* the
@@ -2032,7 +2007,7 @@ pub(super) fn check_type_bounds<'tcx>(
20322007
} else {
20332008
ocx.normalize(&normalize_cause, normalize_param_env, obligation.predicate)
20342009
};
2035-
debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate);
2010+
debug!(?normalized_predicate);
20362011
obligation.predicate = normalized_predicate;
20372012

20382013
ocx.register_obligation(obligation);

compiler/rustc_middle/src/ty/generics.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,9 @@ impl<'tcx> GenericPredicates<'tcx> {
395395
EarlyBinder::bind(self.predicates).iter_instantiated_copied(tcx, args)
396396
}
397397

398-
pub fn instantiate_own_identity(self) -> impl Iterator<Item = (Clause<'tcx>, Span)> {
398+
pub fn instantiate_own_identity(
399+
self,
400+
) -> impl Iterator<Item = (Clause<'tcx>, Span)> + DoubleEndedIterator + ExactSizeIterator {
399401
EarlyBinder::bind(self.predicates).iter_identity_copied()
400402
}
401403

0 commit comments

Comments
 (0)