1
1
//! Orphan checker: every impl either implements a trait defined in this
2
2
//! crate or pertains to a type defined in this crate.
3
3
4
- use rustc_data_structures:: fx:: FxHashSet ;
5
- use rustc_errors:: { DelayDm , ErrorGuaranteed } ;
4
+ use rustc_errors:: ErrorGuaranteed ;
6
5
use rustc_hir as hir;
7
- use rustc_middle:: ty:: util:: CheckRegions ;
8
- use rustc_middle:: ty:: GenericArgs ;
9
- use rustc_middle:: ty:: {
10
- self , AliasKind , ImplPolarity , Ty , TyCtxt , TypeSuperVisitable , TypeVisitable , TypeVisitableExt ,
11
- TypeVisitor ,
12
- } ;
13
- use rustc_session:: lint;
14
- use rustc_span:: def_id:: { DefId , LocalDefId } ;
6
+ use rustc_middle:: ty:: { self , AliasKind , Ty , TyCtxt , TypeVisitableExt } ;
7
+ use rustc_span:: def_id:: LocalDefId ;
15
8
use rustc_span:: Span ;
16
9
use rustc_trait_selection:: traits;
17
- use std:: ops:: ControlFlow ;
18
10
19
11
use crate :: errors;
20
12
@@ -26,30 +18,17 @@ pub(crate) fn orphan_check_impl(
26
18
let trait_ref = tcx. impl_trait_ref ( impl_def_id) . unwrap ( ) . instantiate_identity ( ) ;
27
19
trait_ref. error_reported ( ) ?;
28
20
29
- let ret = do_orphan_check_impl ( tcx, trait_ref, impl_def_id) ;
30
- if tcx. trait_is_auto ( trait_ref. def_id ) {
31
- lint_auto_trait_impl ( tcx, trait_ref, impl_def_id) ;
32
- }
33
-
34
- ret
35
- }
36
-
37
- fn do_orphan_check_impl < ' tcx > (
38
- tcx : TyCtxt < ' tcx > ,
39
- trait_ref : ty:: TraitRef < ' tcx > ,
40
- def_id : LocalDefId ,
41
- ) -> Result < ( ) , ErrorGuaranteed > {
42
21
let trait_def_id = trait_ref. def_id ;
43
22
44
- match traits:: orphan_check ( tcx, def_id . to_def_id ( ) ) {
23
+ match traits:: orphan_check ( tcx, impl_def_id . to_def_id ( ) ) {
45
24
Ok ( ( ) ) => { }
46
25
Err ( err) => {
47
- let item = tcx. hir ( ) . expect_item ( def_id ) ;
26
+ let item = tcx. hir ( ) . expect_item ( impl_def_id ) ;
48
27
let hir:: ItemKind :: Impl ( impl_) = item. kind else {
49
- bug ! ( "{:?} is not an impl: {:?}" , def_id , item) ;
28
+ bug ! ( "{:?} is not an impl: {:?}" , impl_def_id , item) ;
50
29
} ;
51
30
let tr = impl_. of_trait . as_ref ( ) . unwrap ( ) ;
52
- let sp = tcx. def_span ( def_id ) ;
31
+ let sp = tcx. def_span ( impl_def_id ) ;
53
32
54
33
emit_orphan_check_error (
55
34
tcx,
@@ -193,7 +172,7 @@ fn do_orphan_check_impl<'tcx>(
193
172
// impl<T> AutoTrait for T {}
194
173
// impl<T: ?Sized> AutoTrait for T {}
195
174
ty:: Param ( ..) => (
196
- if self_ty. is_sized ( tcx, tcx. param_env ( def_id ) ) {
175
+ if self_ty. is_sized ( tcx, tcx. param_env ( impl_def_id ) ) {
197
176
LocalImpl :: Allow
198
177
} else {
199
178
LocalImpl :: Disallow { problematic_kind : "generic type" }
@@ -250,7 +229,7 @@ fn do_orphan_check_impl<'tcx>(
250
229
| ty:: Bound ( ..)
251
230
| ty:: Placeholder ( ..)
252
231
| ty:: Infer ( ..) => {
253
- let sp = tcx. def_span ( def_id ) ;
232
+ let sp = tcx. def_span ( impl_def_id ) ;
254
233
span_bug ! ( sp, "weird self type for autotrait impl" )
255
234
}
256
235
@@ -262,7 +241,7 @@ fn do_orphan_check_impl<'tcx>(
262
241
LocalImpl :: Allow => { }
263
242
LocalImpl :: Disallow { problematic_kind } => {
264
243
return Err ( tcx. dcx ( ) . emit_err ( errors:: TraitsWithDefaultImpl {
265
- span : tcx. def_span ( def_id ) ,
244
+ span : tcx. def_span ( impl_def_id ) ,
266
245
traits : tcx. def_path_str ( trait_def_id) ,
267
246
problematic_kind,
268
247
self_ty,
@@ -274,13 +253,13 @@ fn do_orphan_check_impl<'tcx>(
274
253
NonlocalImpl :: Allow => { }
275
254
NonlocalImpl :: DisallowBecauseNonlocal => {
276
255
return Err ( tcx. dcx ( ) . emit_err ( errors:: CrossCrateTraitsDefined {
277
- span : tcx. def_span ( def_id ) ,
256
+ span : tcx. def_span ( impl_def_id ) ,
278
257
traits : tcx. def_path_str ( trait_def_id) ,
279
258
} ) ) ;
280
259
}
281
260
NonlocalImpl :: DisallowOther => {
282
261
return Err ( tcx. dcx ( ) . emit_err ( errors:: CrossCrateTraits {
283
- span : tcx. def_span ( def_id ) ,
262
+ span : tcx. def_span ( impl_def_id ) ,
284
263
traits : tcx. def_path_str ( trait_def_id) ,
285
264
self_ty,
286
265
} ) ) ;
@@ -445,146 +424,3 @@ fn emit_orphan_check_error<'tcx>(
445
424
}
446
425
} )
447
426
}
448
-
449
- /// Lint impls of auto traits if they are likely to have
450
- /// unsound or surprising effects on auto impls.
451
- fn lint_auto_trait_impl < ' tcx > (
452
- tcx : TyCtxt < ' tcx > ,
453
- trait_ref : ty:: TraitRef < ' tcx > ,
454
- impl_def_id : LocalDefId ,
455
- ) {
456
- if trait_ref. args . len ( ) != 1 {
457
- tcx. dcx ( ) . span_delayed_bug (
458
- tcx. def_span ( impl_def_id) ,
459
- "auto traits cannot have generic parameters" ,
460
- ) ;
461
- return ;
462
- }
463
- let self_ty = trait_ref. self_ty ( ) ;
464
- let ( self_type_did, args) = match self_ty. kind ( ) {
465
- ty:: Adt ( def, args) => ( def. did ( ) , args) ,
466
- _ => {
467
- // FIXME: should also lint for stuff like `&i32` but
468
- // considering that auto traits are unstable, that
469
- // isn't too important for now as this only affects
470
- // crates using `nightly`, and std.
471
- return ;
472
- }
473
- } ;
474
-
475
- // Impls which completely cover a given root type are fine as they
476
- // disable auto impls entirely. So only lint if the args
477
- // are not a permutation of the identity args.
478
- let Err ( arg) = tcx. uses_unique_generic_params ( args, CheckRegions :: No ) else {
479
- // ok
480
- return ;
481
- } ;
482
-
483
- // Ideally:
484
- //
485
- // - compute the requirements for the auto impl candidate
486
- // - check whether these are implied by the non covering impls
487
- // - if not, emit the lint
488
- //
489
- // What we do here is a bit simpler:
490
- //
491
- // - badly check if an auto impl candidate definitely does not apply
492
- // for the given simplified type
493
- // - if so, do not lint
494
- if fast_reject_auto_impl ( tcx, trait_ref. def_id , self_ty) {
495
- // ok
496
- return ;
497
- }
498
-
499
- tcx. node_span_lint (
500
- lint:: builtin:: SUSPICIOUS_AUTO_TRAIT_IMPLS ,
501
- tcx. local_def_id_to_hir_id ( impl_def_id) ,
502
- tcx. def_span ( impl_def_id) ,
503
- DelayDm ( || {
504
- format ! (
505
- "cross-crate traits with a default impl, like `{}`, \
506
- should not be specialized",
507
- tcx. def_path_str( trait_ref. def_id) ,
508
- )
509
- } ) ,
510
- |lint| {
511
- let item_span = tcx. def_span ( self_type_did) ;
512
- let self_descr = tcx. def_descr ( self_type_did) ;
513
- match arg {
514
- ty:: util:: NotUniqueParam :: DuplicateParam ( arg) => {
515
- lint. note ( format ! ( "`{arg}` is mentioned multiple times" ) ) ;
516
- }
517
- ty:: util:: NotUniqueParam :: NotParam ( arg) => {
518
- lint. note ( format ! ( "`{arg}` is not a generic parameter" ) ) ;
519
- }
520
- }
521
- lint. span_note (
522
- item_span,
523
- format ! (
524
- "try using the same sequence of generic parameters as the {self_descr} definition" ,
525
- ) ,
526
- ) ;
527
- } ,
528
- ) ;
529
- }
530
-
531
- fn fast_reject_auto_impl < ' tcx > ( tcx : TyCtxt < ' tcx > , trait_def_id : DefId , self_ty : Ty < ' tcx > ) -> bool {
532
- struct DisableAutoTraitVisitor < ' tcx > {
533
- tcx : TyCtxt < ' tcx > ,
534
- trait_def_id : DefId ,
535
- self_ty_root : Ty < ' tcx > ,
536
- seen : FxHashSet < DefId > ,
537
- }
538
-
539
- impl < ' tcx > TypeVisitor < TyCtxt < ' tcx > > for DisableAutoTraitVisitor < ' tcx > {
540
- type BreakTy = ( ) ;
541
- fn visit_ty ( & mut self , ty : Ty < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
542
- let tcx = self . tcx ;
543
- if ty != self . self_ty_root {
544
- for impl_def_id in tcx. non_blanket_impls_for_ty ( self . trait_def_id , ty) {
545
- match tcx. impl_polarity ( impl_def_id) {
546
- ImplPolarity :: Negative => return ControlFlow :: Break ( ( ) ) ,
547
- ImplPolarity :: Reservation => { }
548
- // FIXME(@lcnr): That's probably not good enough, idk
549
- //
550
- // We might just want to take the rustdoc code and somehow avoid
551
- // explicit impls for `Self`.
552
- ImplPolarity :: Positive => return ControlFlow :: Continue ( ( ) ) ,
553
- }
554
- }
555
- }
556
-
557
- match ty. kind ( ) {
558
- ty:: Adt ( def, args) if def. is_phantom_data ( ) => args. visit_with ( self ) ,
559
- ty:: Adt ( def, args) => {
560
- // @lcnr: This is the only place where cycles can happen. We avoid this
561
- // by only visiting each `DefId` once.
562
- //
563
- // This will be is incorrect in subtle cases, but I don't care :)
564
- if self . seen . insert ( def. did ( ) ) {
565
- for ty in def. all_fields ( ) . map ( |field| field. ty ( tcx, args) ) {
566
- ty. visit_with ( self ) ?;
567
- }
568
- }
569
-
570
- ControlFlow :: Continue ( ( ) )
571
- }
572
- _ => ty. super_visit_with ( self ) ,
573
- }
574
- }
575
- }
576
-
577
- let self_ty_root = match self_ty. kind ( ) {
578
- ty:: Adt ( def, _) => Ty :: new_adt ( tcx, * def, GenericArgs :: identity_for_item ( tcx, def. did ( ) ) ) ,
579
- _ => unimplemented ! ( "unexpected self ty {:?}" , self_ty) ,
580
- } ;
581
-
582
- self_ty_root
583
- . visit_with ( & mut DisableAutoTraitVisitor {
584
- tcx,
585
- self_ty_root,
586
- trait_def_id,
587
- seen : FxHashSet :: default ( ) ,
588
- } )
589
- . is_break ( )
590
- }
0 commit comments