@@ -18,26 +18,29 @@ use rustc_span::Span;
1818use rustc_trait_selection:: traits;
1919use std:: ops:: ControlFlow ;
2020
21- pub ( super ) fn orphan_check_crate ( tcx : TyCtxt < ' _ > , ( ) : ( ) ) -> & [ LocalDefId ] {
22- let mut errors = Vec :: new ( ) ;
23- for ( & trait_def_id , impls_of_trait ) in tcx. all_local_trait_impls ( ( ) ) {
24- for & impl_of_trait in impls_of_trait {
25- match orphan_check_impl ( tcx , impl_of_trait ) {
26- Ok ( ( ) ) => { }
27- Err ( _ ) => errors . push ( impl_of_trait ) ,
28- }
29- }
21+ # [ instrument ( skip ( tcx) , level = "debug" ) ]
22+ pub ( crate ) fn orphan_check_impl (
23+ tcx : TyCtxt < ' _ > ,
24+ impl_def_id : LocalDefId ,
25+ ) -> Result < ( ) , ErrorGuaranteed > {
26+ let trait_ref = tcx . impl_trait_ref ( impl_def_id ) . unwrap ( ) ;
27+ if trait_ref . references_error ( ) {
28+ return Ok ( ( ) ) ;
29+ }
3030
31- if tcx . trait_is_auto ( trait_def_id ) {
32- lint_auto_trait_impls ( tcx, trait_def_id , impls_of_trait ) ;
33- }
31+ let ret = do_orphan_check_impl ( tcx , trait_ref , impl_def_id ) ;
32+ if tcx. trait_is_auto ( trait_ref . def_id ) {
33+ lint_auto_trait_impls ( tcx , trait_ref , impl_def_id ) ;
3434 }
35- tcx. arena . alloc_slice ( & errors)
35+
36+ ret
3637}
3738
38- #[ instrument( skip( tcx) , level = "debug" ) ]
39- fn orphan_check_impl ( tcx : TyCtxt < ' _ > , def_id : LocalDefId ) -> Result < ( ) , ErrorGuaranteed > {
40- let trait_ref = tcx. impl_trait_ref ( def_id) . unwrap ( ) ;
39+ fn do_orphan_check_impl < ' tcx > (
40+ tcx : TyCtxt < ' tcx > ,
41+ trait_ref : ty:: TraitRef < ' tcx > ,
42+ def_id : LocalDefId ,
43+ ) -> Result < ( ) , ErrorGuaranteed > {
4144 let trait_def_id = trait_ref. def_id ;
4245
4346 let item = tcx. hir ( ) . item ( hir:: ItemId { def_id } ) ;
@@ -329,89 +332,82 @@ fn emit_orphan_check_error<'tcx>(
329332
330333/// Lint impls of auto traits if they are likely to have
331334/// unsound or surprising effects on auto impls.
332- fn lint_auto_trait_impls ( tcx : TyCtxt < ' _ > , trait_def_id : DefId , impls : & [ LocalDefId ] ) {
333- let mut non_covering_impls = Vec :: new ( ) ;
334- for & impl_def_id in impls {
335- let trait_ref = tcx. impl_trait_ref ( impl_def_id) . unwrap ( ) ;
336- if trait_ref. references_error ( ) {
337- return ;
338- }
335+ fn lint_auto_trait_impls < ' tcx > (
336+ tcx : TyCtxt < ' tcx > ,
337+ trait_ref : ty:: TraitRef < ' tcx > ,
338+ impl_def_id : LocalDefId ,
339+ ) {
340+ if tcx. impl_polarity ( impl_def_id) != ImplPolarity :: Positive {
341+ return ;
342+ }
339343
340- if tcx. impl_polarity ( impl_def_id) != ImplPolarity :: Positive {
344+ assert_eq ! ( trait_ref. substs. len( ) , 1 ) ;
345+ let self_ty = trait_ref. self_ty ( ) ;
346+ let ( self_type_did, substs) = match self_ty. kind ( ) {
347+ ty:: Adt ( def, substs) => ( def. did ( ) , substs) ,
348+ _ => {
349+ // FIXME: should also lint for stuff like `&i32` but
350+ // considering that auto traits are unstable, that
351+ // isn't too important for now as this only affects
352+ // crates using `nightly`, and std.
341353 return ;
342354 }
355+ } ;
343356
344- assert_eq ! ( trait_ref. substs. len( ) , 1 ) ;
345- let self_ty = trait_ref. self_ty ( ) ;
346- let ( self_type_did, substs) = match self_ty. kind ( ) {
347- ty:: Adt ( def, substs) => ( def. did ( ) , substs) ,
348- _ => {
349- // FIXME: should also lint for stuff like `&i32` but
350- // considering that auto traits are unstable, that
351- // isn't too important for now as this only affects
352- // crates using `nightly`, and std.
353- continue ;
354- }
355- } ;
357+ // Impls which completely cover a given root type are fine as they
358+ // disable auto impls entirely. So only lint if the substs
359+ // are not a permutation of the identity substs.
360+ let Err ( arg) = tcx. uses_unique_generic_params ( substs, IgnoreRegions :: Yes ) else {
361+ // ok
362+ return ;
363+ } ;
356364
357- // Impls which completely cover a given root type are fine as they
358- // disable auto impls entirely. So only lint if the substs
359- // are not a permutation of the identity substs.
360- match tcx. uses_unique_generic_params ( substs, IgnoreRegions :: Yes ) {
361- Ok ( ( ) ) => { } // ok
362- Err ( arg) => {
363- // Ideally:
364- //
365- // - compute the requirements for the auto impl candidate
366- // - check whether these are implied by the non covering impls
367- // - if not, emit the lint
368- //
369- // What we do here is a bit simpler:
370- //
371- // - badly check if an auto impl candidate definitely does not apply
372- // for the given simplified type
373- // - if so, do not lint
374- if fast_reject_auto_impl ( tcx, trait_def_id, self_ty) {
375- // ok
376- } else {
377- non_covering_impls. push ( ( impl_def_id, self_type_did, arg) ) ;
378- }
379- }
380- }
365+ // Ideally:
366+ //
367+ // - compute the requirements for the auto impl candidate
368+ // - check whether these are implied by the non covering impls
369+ // - if not, emit the lint
370+ //
371+ // What we do here is a bit simpler:
372+ //
373+ // - badly check if an auto impl candidate definitely does not apply
374+ // for the given simplified type
375+ // - if so, do not lint
376+ if fast_reject_auto_impl ( tcx, trait_ref. def_id , self_ty) {
377+ // ok
378+ return ;
381379 }
382380
383- for & ( impl_def_id, self_type_did, arg) in & non_covering_impls {
384- tcx. struct_span_lint_hir (
385- lint:: builtin:: SUSPICIOUS_AUTO_TRAIT_IMPLS ,
386- tcx. hir ( ) . local_def_id_to_hir_id ( impl_def_id) ,
387- tcx. def_span ( impl_def_id) ,
388- |err| {
389- let item_span = tcx. def_span ( self_type_did) ;
390- let self_descr = tcx. def_kind ( self_type_did) . descr ( self_type_did) ;
391- let mut err = err. build ( & format ! (
392- "cross-crate traits with a default impl, like `{}`, \
381+ tcx. struct_span_lint_hir (
382+ lint:: builtin:: SUSPICIOUS_AUTO_TRAIT_IMPLS ,
383+ tcx. hir ( ) . local_def_id_to_hir_id ( impl_def_id) ,
384+ tcx. def_span ( impl_def_id) ,
385+ |err| {
386+ let item_span = tcx. def_span ( self_type_did) ;
387+ let self_descr = tcx. def_kind ( self_type_did) . descr ( self_type_did) ;
388+ let mut err = err. build ( & format ! (
389+ "cross-crate traits with a default impl, like `{}`, \
393390 should not be specialized",
394- tcx. def_path_str( trait_def_id) ,
395- ) ) ;
396- match arg {
397- ty:: util:: NotUniqueParam :: DuplicateParam ( arg) => {
398- err. note ( & format ! ( "`{}` is mentioned multiple times" , arg) ) ;
399- }
400- ty:: util:: NotUniqueParam :: NotParam ( arg) => {
401- err. note ( & format ! ( "`{}` is not a generic parameter" , arg) ) ;
402- }
391+ tcx. def_path_str( trait_ref. def_id) ,
392+ ) ) ;
393+ match arg {
394+ ty:: util:: NotUniqueParam :: DuplicateParam ( arg) => {
395+ err. note ( & format ! ( "`{}` is mentioned multiple times" , arg) ) ;
403396 }
404- err. span_note (
405- item_span,
406- & format ! (
407- "try using the same sequence of generic parameters as the {} definition" ,
408- self_descr,
409- ) ,
410- ) ;
411- err. emit ( ) ;
412- } ,
413- ) ;
414- }
397+ ty:: util:: NotUniqueParam :: NotParam ( arg) => {
398+ err. note ( & format ! ( "`{}` is not a generic parameter" , arg) ) ;
399+ }
400+ }
401+ err. span_note (
402+ item_span,
403+ & format ! (
404+ "try using the same sequence of generic parameters as the {} definition" ,
405+ self_descr,
406+ ) ,
407+ ) ;
408+ err. emit ( ) ;
409+ } ,
410+ ) ;
415411}
416412
417413fn fast_reject_auto_impl < ' tcx > ( tcx : TyCtxt < ' tcx > , trait_def_id : DefId , self_ty : Ty < ' tcx > ) -> bool {
0 commit comments