@@ -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(-Ztrait-solver=next): Not needed when the hack below is removed.
@@ -334,7 +325,8 @@ fn compare_method_predicate_entailment<'tcx>(
334
325
// region outlives obligations.
335
326
//
336
327
// FIXME(-Ztrait-solver=next): Try removing this hack again once
337
- // the new solver is stable.
328
+ // the new 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. hir ( ) . 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. hir ( ) . 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
- . delay_span_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,53 +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
- lint
578
- } ,
579
- ) ;
580
- }
581
-
582
- #[ derive( Debug , PartialEq , Eq ) ]
583
- enum CheckImpliedWfMode {
584
- /// Checks implied well-formedness of the impl method. If it fails, we will
585
- /// re-check with `Skip`, and emit a lint if it succeeds.
586
- Check ,
587
- /// Skips checking implied well-formedness of the impl method, but will emit
588
- /// a lint if the `compare_method_predicate_entailment` succeeded. This means that
589
- /// the reason that we had failed earlier during `Check` was due to the impl
590
- /// having stronger requirements than the trait.
591
- Skip ,
592
- }
593
-
594
416
fn compare_asyncness < ' tcx > (
595
417
tcx : TyCtxt < ' tcx > ,
596
418
impl_m : ty:: AssocItem ,
0 commit comments