@@ -2,9 +2,7 @@ use super::potentially_plural_count;
2
2
use crate::errors::LifetimesOrBoundsMismatchOnTrait;
3
3
use hir::def_id::{DefId, LocalDefId};
4
4
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
5
- use rustc_errors::{
6
- pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed, MultiSpan,
7
- };
5
+ use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed};
8
6
use rustc_hir as hir;
9
7
use rustc_hir::def::{DefKind, Res};
10
8
use rustc_hir::intravisit;
@@ -50,13 +48,7 @@ pub(super) fn compare_impl_method<'tcx>(
50
48
51
49
let _: Result<_, ErrorGuaranteed> = try {
52
50
check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, false)?;
53
- compare_method_predicate_entailment(
54
- tcx,
55
- impl_m,
56
- trait_m,
57
- impl_trait_ref,
58
- CheckImpliedWfMode::Check,
59
- )?;
51
+ compare_method_predicate_entailment(tcx, impl_m, trait_m, impl_trait_ref)?;
60
52
refine::check_refining_return_position_impl_trait_in_trait(
61
53
tcx,
62
54
impl_m,
@@ -170,7 +162,6 @@ fn compare_method_predicate_entailment<'tcx>(
170
162
impl_m: ty::AssocItem,
171
163
trait_m: ty::AssocItem,
172
164
impl_trait_ref: ty::TraitRef<'tcx>,
173
- check_implied_wf: CheckImpliedWfMode,
174
165
) -> Result<(), ErrorGuaranteed> {
175
166
let trait_to_impl_args = impl_trait_ref.args;
176
167
@@ -317,7 +308,7 @@ fn compare_method_predicate_entailment<'tcx>(
317
308
return Err(emitted);
318
309
}
319
310
320
- if check_implied_wf == CheckImpliedWfMode::Check && !(impl_sig, trait_sig).references_error() {
311
+ if !(impl_sig, trait_sig).references_error() {
321
312
// Select obligations to make progress on inference before processing
322
313
// the wf obligation below.
323
314
// FIXME(-Znext-solver): Not needed when the hack below is removed.
@@ -333,8 +324,9 @@ fn compare_method_predicate_entailment<'tcx>(
333
324
// trigger the lint. Instead, let's only consider type outlives and
334
325
// region outlives obligations.
335
326
//
336
- // FIXME(-Znext-solver): Try removing this hack again once
337
- // the new solver is stable.
327
+ // FIXME(-Znext-solver): Try removing this hack again once the new
328
+ // solver is stable. We should just be able to register a WF pred for
329
+ // the fn sig.
338
330
let mut wf_args: smallvec::SmallVec<[_; 4]> =
339
331
unnormalized_impl_sig.inputs_and_output.iter().map(|ty| ty.into()).collect();
340
332
// Annoyingly, asking for the WF predicates of an array (with an unevaluated const (only?))
@@ -357,7 +349,7 @@ fn compare_method_predicate_entailment<'tcx>(
357
349
// We need to register Projection oblgiations too, because we may end up with
358
350
// an implied `X::Item: 'a`, which gets desugared into `X::Item = ?0`, `?0: 'a`.
359
351
// If we only register the region outlives obligation, this leads to an unconstrained var.
360
- // See `implied_bounds_entailment_alias_var` test.
352
+ // See `implied_bounds_entailment_alias_var.rs ` test.
361
353
ty::PredicateKind::Clause(
362
354
ty::ClauseKind::RegionOutlives(..)
363
355
| ty::ClauseKind::TypeOutlives(..)
@@ -378,26 +370,8 @@ fn compare_method_predicate_entailment<'tcx>(
378
370
// version.
379
371
let errors = ocx.select_all_or_error();
380
372
if !errors.is_empty() {
381
- match check_implied_wf {
382
- CheckImpliedWfMode::Check => {
383
- let impl_m_hir_id = tcx.local_def_id_to_hir_id(impl_m_def_id);
384
- return compare_method_predicate_entailment(
385
- tcx,
386
- impl_m,
387
- trait_m,
388
- impl_trait_ref,
389
- CheckImpliedWfMode::Skip,
390
- )
391
- .map(|()| {
392
- // If the skip-mode was successful, emit a lint.
393
- emit_implied_wf_lint(infcx.tcx, impl_m, impl_m_hir_id, vec![]);
394
- });
395
- }
396
- CheckImpliedWfMode::Skip => {
397
- let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
398
- return Err(reported);
399
- }
400
- }
373
+ let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
374
+ return Err(reported);
401
375
}
402
376
403
377
// Finally, resolve all regions. This catches wily misuses of
@@ -408,119 +382,14 @@ fn compare_method_predicate_entailment<'tcx>(
408
382
);
409
383
let errors = infcx.resolve_regions(&outlives_env);
410
384
if !errors.is_empty() {
411
- // FIXME(compiler-errors): This can be simplified when IMPLIED_BOUNDS_ENTAILMENT
412
- // becomes a hard error (i.e. ideally we'd just call `resolve_regions_and_report_errors`
413
- let impl_m_hir_id = tcx.local_def_id_to_hir_id(impl_m_def_id);
414
- match check_implied_wf {
415
- CheckImpliedWfMode::Check => {
416
- return compare_method_predicate_entailment(
417
- tcx,
418
- impl_m,
419
- trait_m,
420
- impl_trait_ref,
421
- CheckImpliedWfMode::Skip,
422
- )
423
- .map(|()| {
424
- let bad_args = extract_bad_args_for_implies_lint(
425
- tcx,
426
- &errors,
427
- (trait_m, trait_sig),
428
- // Unnormalized impl sig corresponds to the HIR types written
429
- (impl_m, unnormalized_impl_sig),
430
- impl_m_hir_id,
431
- );
432
- // If the skip-mode was successful, emit a lint.
433
- emit_implied_wf_lint(tcx, impl_m, impl_m_hir_id, bad_args);
434
- });
435
- }
436
- CheckImpliedWfMode::Skip => {
437
- if infcx.tainted_by_errors().is_none() {
438
- infcx.err_ctxt().report_region_errors(impl_m_def_id, &errors);
439
- }
440
- return Err(tcx
441
- .sess
442
- .span_delayed_bug(rustc_span::DUMMY_SP, "error should have been emitted"));
443
- }
444
- }
385
+ return Err(infcx
386
+ .tainted_by_errors()
387
+ .unwrap_or_else(|| infcx.err_ctxt().report_region_errors(impl_m_def_id, &errors)));
445
388
}
446
389
447
390
Ok(())
448
391
}
449
392
450
- fn extract_bad_args_for_implies_lint<'tcx>(
451
- tcx: TyCtxt<'tcx>,
452
- errors: &[infer::RegionResolutionError<'tcx>],
453
- (trait_m, trait_sig): (ty::AssocItem, ty::FnSig<'tcx>),
454
- (impl_m, impl_sig): (ty::AssocItem, ty::FnSig<'tcx>),
455
- hir_id: hir::HirId,
456
- ) -> Vec<(Span, Option<String>)> {
457
- let mut blame_generics = vec![];
458
- for error in errors {
459
- // Look for the subregion origin that contains an input/output type
460
- let origin = match error {
461
- infer::RegionResolutionError::ConcreteFailure(o, ..) => o,
462
- infer::RegionResolutionError::GenericBoundFailure(o, ..) => o,
463
- infer::RegionResolutionError::SubSupConflict(_, _, o, ..) => o,
464
- infer::RegionResolutionError::UpperBoundUniverseConflict(.., o, _) => o,
465
- };
466
- // Extract (possible) input/output types from origin
467
- match origin {
468
- infer::SubregionOrigin::Subtype(trace) => {
469
- if let Some((a, b)) = trace.values.ty() {
470
- blame_generics.extend([a, b]);
471
- }
472
- }
473
- infer::SubregionOrigin::RelateParamBound(_, ty, _) => blame_generics.push(*ty),
474
- infer::SubregionOrigin::ReferenceOutlivesReferent(ty, _) => blame_generics.push(*ty),
475
- _ => {}
476
- }
477
- }
478
-
479
- let fn_decl = tcx.hir().fn_decl_by_hir_id(hir_id).unwrap();
480
- let opt_ret_ty = match fn_decl.output {
481
- hir::FnRetTy::DefaultReturn(_) => None,
482
- hir::FnRetTy::Return(ty) => Some(ty),
483
- };
484
-
485
- // Map late-bound regions from trait to impl, so the names are right.
486
- let mapping = std::iter::zip(
487
- tcx.fn_sig(trait_m.def_id).skip_binder().bound_vars(),
488
- tcx.fn_sig(impl_m.def_id).skip_binder().bound_vars(),
489
- )
490
- .filter_map(|(impl_bv, trait_bv)| {
491
- if let ty::BoundVariableKind::Region(impl_bv) = impl_bv
492
- && let ty::BoundVariableKind::Region(trait_bv) = trait_bv
493
- {
494
- Some((impl_bv, trait_bv))
495
- } else {
496
- None
497
- }
498
- })
499
- .collect();
500
-
501
- // For each arg, see if it was in the "blame" of any of the region errors.
502
- // If so, then try to produce a suggestion to replace the argument type with
503
- // one from the trait.
504
- let mut bad_args = vec![];
505
- for (idx, (ty, hir_ty)) in
506
- std::iter::zip(impl_sig.inputs_and_output, fn_decl.inputs.iter().chain(opt_ret_ty))
507
- .enumerate()
508
- {
509
- let expected_ty = trait_sig.inputs_and_output[idx]
510
- .fold_with(&mut RemapLateBound { tcx, mapping: &mapping });
511
- if blame_generics.iter().any(|blame| ty.contains(*blame)) {
512
- let expected_ty_sugg = expected_ty.to_string();
513
- bad_args.push((
514
- hir_ty.span,
515
- // Only suggest something if it actually changed.
516
- (expected_ty_sugg != ty.to_string()).then_some(expected_ty_sugg),
517
- ));
518
- }
519
- }
520
-
521
- bad_args
522
- }
523
-
524
393
struct RemapLateBound<'a, 'tcx> {
525
394
tcx: TyCtxt<'tcx>,
526
395
mapping: &'a FxHashMap<ty::BoundRegionKind, ty::BoundRegionKind>,
@@ -544,52 +413,6 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RemapLateBound<'_, 'tcx> {
544
413
}
545
414
}
546
415
547
- fn emit_implied_wf_lint<'tcx>(
548
- tcx: TyCtxt<'tcx>,
549
- impl_m: ty::AssocItem,
550
- hir_id: hir::HirId,
551
- bad_args: Vec<(Span, Option<String>)>,
552
- ) {
553
- let span: MultiSpan = if bad_args.is_empty() {
554
- tcx.def_span(impl_m.def_id).into()
555
- } else {
556
- bad_args.iter().map(|(span, _)| *span).collect::<Vec<_>>().into()
557
- };
558
- tcx.struct_span_lint_hir(
559
- rustc_session::lint::builtin::IMPLIED_BOUNDS_ENTAILMENT,
560
- hir_id,
561
- span,
562
- "impl method assumes more implied bounds than the corresponding trait method",
563
- |lint| {
564
- let bad_args: Vec<_> =
565
- bad_args.into_iter().filter_map(|(span, sugg)| Some((span, sugg?))).collect();
566
- if !bad_args.is_empty() {
567
- lint.multipart_suggestion(
568
- format!(
569
- "replace {} type{} to make the impl signature compatible",
570
- pluralize!("this", bad_args.len()),
571
- pluralize!(bad_args.len())
572
- ),
573
- bad_args,
574
- Applicability::MaybeIncorrect,
575
- );
576
- }
577
- },
578
- );
579
- }
580
-
581
- #[derive(Debug, PartialEq, Eq)]
582
- enum CheckImpliedWfMode {
583
- /// Checks implied well-formedness of the impl method. If it fails, we will
584
- /// re-check with `Skip`, and emit a lint if it succeeds.
585
- Check,
586
- /// Skips checking implied well-formedness of the impl method, but will emit
587
- /// a lint if the `compare_method_predicate_entailment` succeeded. This means that
588
- /// the reason that we had failed earlier during `Check` was due to the impl
589
- /// having stronger requirements than the trait.
590
- Skip,
591
- }
592
-
593
416
fn compare_asyncness<'tcx>(
594
417
tcx: TyCtxt<'tcx>,
595
418
impl_m: ty::AssocItem,
0 commit comments