split compare_predicate_entailment and collect_trait_impl_trait_tys out · rust-lang/rust@bec079d (original) (raw)
`@@ -15,7 +15,7 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError};
`
15
15
`use rustc_middle::ty::subst::{InternalSubsts, Subst};
`
16
16
`use rustc_middle::ty::util::ExplicitSelf;
`
17
17
`use rustc_middle::ty::{
`
18
``
`-
self, DefIdTree, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable,
`
``
18
`+
self, AssocItem, DefIdTree, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable,
`
19
19
`};
`
20
20
`use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt};
`
21
21
`use rustc_span::Span;
`
`@@ -68,7 +68,10 @@ pub(crate) fn compare_impl_method<'tcx>(
`
68
68
`return;
`
69
69
`}
`
70
70
``
71
``
`-
tcx.ensure().compare_predicates_and_trait_impl_trait_tys(impl_m.def_id);
`
``
71
`+
if let Err(_) = compare_predicate_entailment(tcx, impl_m, impl_m_span, trait_m, impl_trait_ref)
`
``
72
`+
{
`
``
73
`+
return;
`
``
74
`+
}
`
72
75
`}
`
73
76
``
74
77
`/// This function is best explained by example. Consider a trait:
`
`@@ -137,15 +140,13 @@ pub(crate) fn compare_impl_method<'tcx>(
`
137
140
`///
`
138
141
`/// Finally we register each of these predicates as an obligation and check that
`
139
142
`/// they hold.
`
140
``
`-
pub(super) fn compare_predicates_and_trait_impl_trait_tys<'tcx>(
`
``
143
`+
fn compare_predicate_entailment<'tcx>(
`
141
144
`tcx: TyCtxt<'tcx>,
`
142
``
`-
def_id: DefId,
`
143
``
`-
) -> Result<&'tcx FxHashMap<DefId, Ty<'tcx>>, ErrorGuaranteed> {
`
144
``
`-
let impl_m = tcx.opt_associated_item(def_id).unwrap();
`
145
``
`-
let impl_m_span = tcx.def_span(def_id);
`
146
``
`-
let trait_m = tcx.opt_associated_item(impl_m.trait_item_def_id.unwrap()).unwrap();
`
147
``
`-
let impl_trait_ref = tcx.impl_trait_ref(impl_m.impl_container(tcx).unwrap()).unwrap();
`
148
``
-
``
145
`+
impl_m: &AssocItem,
`
``
146
`+
impl_m_span: Span,
`
``
147
`+
trait_m: &AssocItem,
`
``
148
`+
impl_trait_ref: ty::TraitRef<'tcx>,
`
``
149
`+
) -> Result<(), ErrorGuaranteed> {
`
149
150
`let trait_to_impl_substs = impl_trait_ref.substs;
`
150
151
``
151
152
`` // This node-id should be used for the body_id
field on each
``
`@@ -164,7 +165,6 @@ pub(super) fn compare_predicates_and_trait_impl_trait_tys<'tcx>(
`
164
165
`kind: impl_m.kind,
`
165
166
`},
`
166
167
`);
`
167
``
`-
let return_span = tcx.hir().fn_decl_by_hir_id(impl_m_hir_id).unwrap().output.span();
`
168
168
``
169
169
`// Create mapping from impl to placeholder.
`
170
170
`let impl_to_placeholder_substs = InternalSubsts::identity_for_item(tcx, impl_m.def_id);
`
`@@ -270,12 +270,6 @@ pub(super) fn compare_predicates_and_trait_impl_trait_tys<'tcx>(
`
270
270
``
271
271
`let trait_sig = tcx.bound_fn_sig(trait_m.def_id).subst(tcx, trait_to_placeholder_substs);
`
272
272
`let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, trait_sig);
`
273
``
`-
let mut collector =
`
274
``
`-
ImplTraitInTraitCollector::new(&ocx, return_span, param_env, impl_m_hir_id);
`
275
``
`-
// FIXME(RPITIT): This should only be needed on the output type, but
`
276
``
`-
// RPITIT placeholders shouldn't show up anywhere except for there,
`
277
``
`-
// so I think this is fine.
`
278
``
`-
let trait_sig = trait_sig.fold_with(&mut collector);
`
279
273
``
280
274
`// Next, add all inputs and output as well-formed tys. Importantly,
`
281
275
`// we have to do this before normalization, since the normalized ty may
`
`@@ -422,6 +416,121 @@ pub(super) fn compare_predicates_and_trait_impl_trait_tys<'tcx>(
`
422
416
`&outlives_environment,
`
423
417
`);
`
424
418
``
``
419
`+
Ok(())
`
``
420
`+
})
`
``
421
`+
}
`
``
422
+
``
423
`+
pub fn collect_trait_impl_trait_tys<'tcx>(
`
``
424
`+
tcx: TyCtxt<'tcx>,
`
``
425
`+
def_id: DefId,
`
``
426
`+
) -> Result<&'tcx FxHashMap<DefId, Ty<'tcx>>, ErrorGuaranteed> {
`
``
427
`+
let impl_m = tcx.opt_associated_item(def_id).unwrap();
`
``
428
`+
let trait_m = tcx.opt_associated_item(impl_m.trait_item_def_id.unwrap()).unwrap();
`
``
429
`+
let impl_trait_ref = tcx.impl_trait_ref(impl_m.impl_container(tcx).unwrap()).unwrap();
`
``
430
`+
let param_env = tcx.param_env(def_id);
`
``
431
+
``
432
`+
let trait_to_impl_substs = impl_trait_ref.substs;
`
``
433
+
``
434
`+
let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local());
`
``
435
`+
let return_span = tcx.hir().fn_decl_by_hir_id(impl_m_hir_id).unwrap().output.span();
`
``
436
`+
let cause = ObligationCause::new(
`
``
437
`+
return_span,
`
``
438
`+
impl_m_hir_id,
`
``
439
`+
ObligationCauseCode::CompareImplItemObligation {
`
``
440
`+
impl_item_def_id: impl_m.def_id.expect_local(),
`
``
441
`+
trait_item_def_id: trait_m.def_id,
`
``
442
`+
kind: impl_m.kind,
`
``
443
`+
},
`
``
444
`+
);
`
``
445
+
``
446
`+
// Create mapping from impl to placeholder.
`
``
447
`+
let impl_to_placeholder_substs = InternalSubsts::identity_for_item(tcx, impl_m.def_id);
`
``
448
+
``
449
`+
// Create mapping from trait to placeholder.
`
``
450
`+
let trait_to_placeholder_substs =
`
``
451
`+
impl_to_placeholder_substs.rebase_onto(tcx, impl_m.container_id(tcx), trait_to_impl_substs);
`
``
452
+
``
453
`+
tcx.infer_ctxt().enter(|ref infcx| {
`
``
454
`+
let ocx = ObligationCtxt::new(infcx);
`
``
455
+
``
456
`+
let norm_cause = ObligationCause::misc(return_span, impl_m_hir_id);
`
``
457
`+
let impl_return_ty = ocx.normalize(
`
``
458
`+
norm_cause.clone(),
`
``
459
`+
param_env,
`
``
460
`+
infcx
`
``
461
`+
.replace_bound_vars_with_fresh_vars(
`
``
462
`+
return_span,
`
``
463
`+
infer::HigherRankedType,
`
``
464
`+
tcx.fn_sig(impl_m.def_id),
`
``
465
`+
)
`
``
466
`+
.output(),
`
``
467
`+
);
`
``
468
+
``
469
`+
let mut collector =
`
``
470
`+
ImplTraitInTraitCollector::new(&ocx, return_span, param_env, impl_m_hir_id);
`
``
471
`+
let unnormalized_trait_return_ty = tcx
`
``
472
`+
.liberate_late_bound_regions(
`
``
473
`+
impl_m.def_id,
`
``
474
`+
tcx.bound_fn_sig(trait_m.def_id).subst(tcx, trait_to_placeholder_substs),
`
``
475
`+
)
`
``
476
`+
.output()
`
``
477
`+
.fold_with(&mut collector);
`
``
478
`+
let trait_return_ty =
`
``
479
`+
ocx.normalize(norm_cause.clone(), param_env, unnormalized_trait_return_ty);
`
``
480
+
``
481
`+
let wf_tys = FxHashSet::from_iter([unnormalized_trait_return_ty, trait_return_ty]);
`
``
482
+
``
483
`+
match infcx.at(&cause, param_env).eq(trait_return_ty, impl_return_ty) {
`
``
484
`+
Ok(infer::InferOk { value: (), obligations }) => {
`
``
485
`+
ocx.register_obligations(obligations);
`
``
486
`+
}
`
``
487
`+
Err(terr) => {
`
``
488
`+
let mut diag = struct_span_err!(
`
``
489
`+
tcx.sess,
`
``
490
`+
cause.span(),
`
``
491
`+
E0053,
`
``
492
`` +
"method {}
has an incompatible return type for trait",
``
``
493
`+
trait_m.name
`
``
494
`+
);
`
``
495
`+
let hir = tcx.hir();
`
``
496
`+
infcx.note_type_err(
`
``
497
`+
&mut diag,
`
``
498
`+
&cause,
`
``
499
`+
hir.get_if_local(impl_m.def_id)
`
``
500
`+
.and_then(|node| node.fn_decl())
`
``
501
`+
.map(|decl| (decl.output.span(), "return type in trait".to_owned())),
`
``
502
`+
Some(infer::ValuePairs::Terms(ExpectedFound {
`
``
503
`+
expected: trait_return_ty.into(),
`
``
504
`+
found: impl_return_ty.into(),
`
``
505
`+
})),
`
``
506
`+
terr,
`
``
507
`+
false,
`
``
508
`+
false,
`
``
509
`+
);
`
``
510
`+
return Err(diag.emit());
`
``
511
`+
}
`
``
512
`+
}
`
``
513
+
``
514
`+
// Check that all obligations are satisfied by the implementation's
`
``
515
`+
// RPITs.
`
``
516
`+
let errors = ocx.select_all_or_error();
`
``
517
`+
if !errors.is_empty() {
`
``
518
`+
let reported = infcx.report_fulfillment_errors(&errors, None, false);
`
``
519
`+
return Err(reported);
`
``
520
`+
}
`
``
521
+
``
522
`+
// Finally, resolve all regions. This catches wily misuses of
`
``
523
`+
// lifetime parameters.
`
``
524
`+
let outlives_environment = OutlivesEnvironment::with_bounds(
`
``
525
`+
param_env,
`
``
526
`+
Some(infcx),
`
``
527
`+
infcx.implied_bounds_tys(param_env, impl_m_hir_id, wf_tys),
`
``
528
`+
);
`
``
529
`+
infcx.check_region_obligations_and_report_errors(
`
``
530
`+
impl_m.def_id.expect_local(),
`
``
531
`+
&outlives_environment,
`
``
532
`+
);
`
``
533
+
425
534
`let mut collected_tys = FxHashMap::default();
`
426
535
`for (def_id, (ty, substs)) in collector.types {
`
427
536
`match infcx.fully_resolve(ty) {
`
`@@ -1307,7 +1416,7 @@ pub(crate) fn compare_ty_impl<'tcx>(
`
1307
1416
`})();
`
1308
1417
`}
`
1309
1418
``
1310
``
`-
/// The equivalent of [compare_predicates_and_trait_impl_trait_tys], but for associated types
`
``
1419
`+
/// The equivalent of [compare_predicate_entailment], but for associated types
`
1311
1420
`/// instead of associated functions.
`
1312
1421
`fn compare_type_predicate_entailment<'tcx>(
`
1313
1422
`tcx: TyCtxt<'tcx>,
`