@@ -2,9 +2,7 @@ use super::potentially_plural_count;
22use crate :: errors:: LifetimesOrBoundsMismatchOnTrait ;
33use hir:: def_id:: { DefId , LocalDefId } ;
44use 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 } ;
86use rustc_hir as hir;
97use rustc_hir:: def:: { DefKind , Res } ;
108use rustc_hir:: intravisit;
@@ -50,13 +48,7 @@ pub(super) fn compare_impl_method<'tcx>(
5048
5149 let _: Result < _ , ErrorGuaranteed > = try {
5250 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) ?;
6052 refine:: check_refining_return_position_impl_trait_in_trait (
6153 tcx,
6254 impl_m,
@@ -170,7 +162,6 @@ fn compare_method_predicate_entailment<'tcx>(
170162 impl_m : ty:: AssocItem ,
171163 trait_m : ty:: AssocItem ,
172164 impl_trait_ref : ty:: TraitRef < ' tcx > ,
173- check_implied_wf : CheckImpliedWfMode ,
174165) -> Result < ( ) , ErrorGuaranteed > {
175166 let trait_to_impl_args = impl_trait_ref. args ;
176167
@@ -317,7 +308,7 @@ fn compare_method_predicate_entailment<'tcx>(
317308 return Err ( emitted) ;
318309 }
319310
320- if check_implied_wf == CheckImpliedWfMode :: Check && !( impl_sig, trait_sig) . references_error ( ) {
311+ if !( impl_sig, trait_sig) . references_error ( ) {
321312 // Select obligations to make progress on inference before processing
322313 // the wf obligation below.
323314 // FIXME(-Znext-solver): Not needed when the hack below is removed.
@@ -333,8 +324,9 @@ fn compare_method_predicate_entailment<'tcx>(
333324 // trigger the lint. Instead, let's only consider type outlives and
334325 // region outlives obligations.
335326 //
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.
338330 let mut wf_args: smallvec:: SmallVec < [ _ ; 4 ] > =
339331 unnormalized_impl_sig. inputs_and_output . iter ( ) . map ( |ty| ty. into ( ) ) . collect ( ) ;
340332 // Annoyingly, asking for the WF predicates of an array (with an unevaluated const (only?))
@@ -357,7 +349,7 @@ fn compare_method_predicate_entailment<'tcx>(
357349 // We need to register Projection oblgiations too, because we may end up with
358350 // an implied `X::Item: 'a`, which gets desugared into `X::Item = ?0`, `?0: 'a`.
359351 // 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.
361353 ty:: PredicateKind :: Clause (
362354 ty:: ClauseKind :: RegionOutlives ( ..)
363355 | ty:: ClauseKind :: TypeOutlives ( ..)
@@ -378,26 +370,8 @@ fn compare_method_predicate_entailment<'tcx>(
378370 // version.
379371 let errors = ocx. select_all_or_error ( ) ;
380372 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) ;
401375 }
402376
403377 // Finally, resolve all regions. This catches wily misuses of
@@ -408,119 +382,14 @@ fn compare_method_predicate_entailment<'tcx>(
408382 ) ;
409383 let errors = infcx. resolve_regions ( & outlives_env) ;
410384 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) ) ) ;
445388 }
446389
447390 Ok ( ( ) )
448391}
449392
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-
524393struct RemapLateBound < ' a , ' tcx > {
525394 tcx : TyCtxt < ' tcx > ,
526395 mapping : & ' a FxHashMap < ty:: BoundRegionKind , ty:: BoundRegionKind > ,
@@ -544,52 +413,6 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RemapLateBound<'_, 'tcx> {
544413 }
545414}
546415
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-
593416fn compare_asyncness < ' tcx > (
594417 tcx : TyCtxt < ' tcx > ,
595418 impl_m : ty:: AssocItem ,
0 commit comments