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>,

`