1
+ //! This module contains methods that assist in checking that impls are general
2
+ //! enough, i.e. that they always apply to every valid instantaiton of the ADT
3
+ //! they're implemented for.
4
+ //!
5
+ //! This is necessary for `Drop` and negative impls to be well-formed.
6
+
1
7
use rustc_data_structures:: fx:: FxHashSet ;
2
8
use rustc_errors:: codes:: * ;
3
9
use rustc_errors:: { ErrorGuaranteed , struct_span_code_err} ;
4
10
use rustc_infer:: infer:: { RegionResolutionError , TyCtxtInferExt } ;
5
11
use rustc_infer:: traits:: { ObligationCause , ObligationCauseCode } ;
12
+ use rustc_middle:: span_bug;
6
13
use rustc_middle:: ty:: util:: CheckRegions ;
7
14
use rustc_middle:: ty:: { self , GenericArgsRef , Ty , TyCtxt , TypingMode } ;
8
15
use rustc_trait_selection:: regions:: InferCtxtRegionExt ;
@@ -27,11 +34,12 @@ use crate::hir::def_id::{DefId, LocalDefId};
27
34
/// 3. Any bounds on the generic parameters must be reflected in the
28
35
/// struct/enum definition for the nominal type itself (i.e.
29
36
/// cannot do `struct S<T>; impl<T:Clone> Drop for S<T> { ... }`).
30
- ///
31
37
pub ( crate ) fn check_drop_impl (
32
38
tcx : TyCtxt < ' _ > ,
33
39
drop_impl_did : DefId ,
34
40
) -> Result < ( ) , ErrorGuaranteed > {
41
+ let drop_impl_did = drop_impl_did. expect_local ( ) ;
42
+
35
43
match tcx. impl_polarity ( drop_impl_did) {
36
44
ty:: ImplPolarity :: Positive => { }
37
45
ty:: ImplPolarity :: Negative => {
@@ -45,55 +53,107 @@ pub(crate) fn check_drop_impl(
45
53
} ) ) ;
46
54
}
47
55
}
48
- let dtor_self_type = tcx. type_of ( drop_impl_did) . instantiate_identity ( ) ;
49
- match dtor_self_type. kind ( ) {
56
+
57
+ tcx. ensure_ok ( ) . orphan_check_impl ( drop_impl_did) ?;
58
+
59
+ let dtor_impl_trait_ref = tcx. impl_trait_ref ( drop_impl_did) . unwrap ( ) . instantiate_identity ( ) ;
60
+
61
+ match dtor_impl_trait_ref. self_ty ( ) . kind ( ) {
50
62
ty:: Adt ( adt_def, adt_to_impl_args) => {
51
- ensure_drop_params_and_item_params_correspond (
63
+ ensure_impl_params_and_item_params_correspond (
52
64
tcx,
53
- drop_impl_did. expect_local ( ) ,
65
+ drop_impl_did,
54
66
adt_def. did ( ) ,
55
67
adt_to_impl_args,
56
68
) ?;
57
69
58
- ensure_drop_predicates_are_implied_by_item_defn (
70
+ ensure_impl_predicates_are_implied_by_item_defn (
59
71
tcx,
60
- drop_impl_did. expect_local ( ) ,
61
- adt_def. did ( ) . expect_local ( ) ,
72
+ drop_impl_did,
73
+ adt_def. did ( ) ,
62
74
adt_to_impl_args,
63
75
)
64
76
}
65
77
_ => {
66
- // Destructors only work on nominal types. This was
67
- // already checked by coherence, but compilation may
68
- // not have been terminated.
69
- let span = tcx. def_span ( drop_impl_did) ;
70
- let reported = tcx. dcx ( ) . span_delayed_bug (
71
- span,
72
- format ! ( "should have been rejected by coherence check: {dtor_self_type}" ) ,
73
- ) ;
74
- Err ( reported)
78
+ span_bug ! ( tcx. def_span( drop_impl_did) , "incoherent impl of Drop" ) ;
75
79
}
76
80
}
77
81
}
78
82
79
- fn ensure_drop_params_and_item_params_correspond < ' tcx > (
83
+ pub ( crate ) fn check_negative_auto_trait_impl < ' tcx > (
80
84
tcx : TyCtxt < ' tcx > ,
81
- drop_impl_did : LocalDefId ,
82
- self_type_did : DefId ,
85
+ impl_def_id : LocalDefId ,
86
+ impl_trait_ref : ty:: TraitRef < ' tcx > ,
87
+ polarity : ty:: ImplPolarity ,
88
+ ) -> Result < ( ) , ErrorGuaranteed > {
89
+ let ty:: ImplPolarity :: Negative = polarity else {
90
+ return Ok ( ( ) ) ;
91
+ } ;
92
+
93
+ if !tcx. trait_is_auto ( impl_trait_ref. def_id ) {
94
+ return Ok ( ( ) ) ;
95
+ }
96
+
97
+ if tcx. defaultness ( impl_def_id) . is_default ( ) {
98
+ tcx. dcx ( ) . span_delayed_bug ( tcx. def_span ( impl_def_id) , "default impl cannot be negative" ) ;
99
+ }
100
+
101
+ tcx. ensure_ok ( ) . orphan_check_impl ( impl_def_id) ?;
102
+
103
+ match impl_trait_ref. self_ty ( ) . kind ( ) {
104
+ ty:: Adt ( adt_def, adt_to_impl_args) => {
105
+ ensure_impl_params_and_item_params_correspond (
106
+ tcx,
107
+ impl_def_id,
108
+ adt_def. did ( ) ,
109
+ adt_to_impl_args,
110
+ ) ?;
111
+
112
+ ensure_impl_predicates_are_implied_by_item_defn (
113
+ tcx,
114
+ impl_def_id,
115
+ adt_def. did ( ) ,
116
+ adt_to_impl_args,
117
+ )
118
+ }
119
+ _ => {
120
+ if tcx. features ( ) . auto_traits ( ) {
121
+ // NOTE: We ignore the applicability check for negative auto impls
122
+ // defined in libcore. In the (almost impossible) future where we
123
+ // stabilize auto impls, then the proper applicability check MUST
124
+ // be implemented here to handle non-ADT rigid types.
125
+ Ok ( ( ) )
126
+ } else {
127
+ span_bug ! ( tcx. def_span( impl_def_id) , "incoherent impl of negative auto trait" ) ;
128
+ }
129
+ }
130
+ }
131
+ }
132
+
133
+ fn ensure_impl_params_and_item_params_correspond < ' tcx > (
134
+ tcx : TyCtxt < ' tcx > ,
135
+ impl_def_id : LocalDefId ,
136
+ adt_def_id : DefId ,
83
137
adt_to_impl_args : GenericArgsRef < ' tcx > ,
84
138
) -> Result < ( ) , ErrorGuaranteed > {
85
139
let Err ( arg) = tcx. uses_unique_generic_params ( adt_to_impl_args, CheckRegions :: OnlyParam ) else {
86
140
return Ok ( ( ) ) ;
87
141
} ;
88
142
89
- let drop_impl_span = tcx. def_span ( drop_impl_did) ;
90
- let item_span = tcx. def_span ( self_type_did) ;
91
- let self_descr = tcx. def_descr ( self_type_did) ;
143
+ let impl_span = tcx. def_span ( impl_def_id) ;
144
+ let item_span = tcx. def_span ( adt_def_id) ;
145
+ let self_descr = tcx. def_descr ( adt_def_id) ;
146
+ let polarity = match tcx. impl_polarity ( impl_def_id) {
147
+ ty:: ImplPolarity :: Positive | ty:: ImplPolarity :: Reservation => "" ,
148
+ ty:: ImplPolarity :: Negative => "!" ,
149
+ } ;
150
+ let trait_name = tcx
151
+ . item_name ( tcx. trait_id_of_impl ( impl_def_id. to_def_id ( ) ) . expect ( "expected impl of trait" ) ) ;
92
152
let mut err = struct_span_code_err ! (
93
153
tcx. dcx( ) ,
94
- drop_impl_span ,
154
+ impl_span ,
95
155
E0366 ,
96
- "`Drop ` impls cannot be specialized"
156
+ "`{polarity}{trait_name} ` impls cannot be specialized" ,
97
157
) ;
98
158
match arg {
99
159
ty:: util:: NotUniqueParam :: DuplicateParam ( arg) => {
@@ -116,17 +176,22 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
116
176
/// Confirms that all predicates defined on the `Drop` impl (`drop_impl_def_id`) are able to be
117
177
/// proven from within `adt_def_id`'s environment. I.e. all the predicates on the impl are
118
178
/// implied by the ADT being well formed.
119
- fn ensure_drop_predicates_are_implied_by_item_defn < ' tcx > (
179
+ fn ensure_impl_predicates_are_implied_by_item_defn < ' tcx > (
120
180
tcx : TyCtxt < ' tcx > ,
121
- drop_impl_def_id : LocalDefId ,
122
- adt_def_id : LocalDefId ,
181
+ impl_def_id : LocalDefId ,
182
+ adt_def_id : DefId ,
123
183
adt_to_impl_args : GenericArgsRef < ' tcx > ,
124
184
) -> Result < ( ) , ErrorGuaranteed > {
125
185
let infcx = tcx. infer_ctxt ( ) . build ( TypingMode :: non_body_analysis ( ) ) ;
126
186
let ocx = ObligationCtxt :: new_with_diagnostics ( & infcx) ;
127
187
128
- let impl_span = tcx. def_span ( drop_impl_def_id. to_def_id ( ) ) ;
129
-
188
+ let impl_span = tcx. def_span ( impl_def_id. to_def_id ( ) ) ;
189
+ let trait_name = tcx
190
+ . item_name ( tcx. trait_id_of_impl ( impl_def_id. to_def_id ( ) ) . expect ( "expected impl of trait" ) ) ;
191
+ let polarity = match tcx. impl_polarity ( impl_def_id) {
192
+ ty:: ImplPolarity :: Positive | ty:: ImplPolarity :: Reservation => "" ,
193
+ ty:: ImplPolarity :: Negative => "!" ,
194
+ } ;
130
195
// Take the param-env of the adt and instantiate the args that show up in
131
196
// the implementation's self type. This gives us the assumptions that the
132
197
// self ty of the implementation is allowed to know just from it being a
@@ -145,17 +210,21 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
145
210
let adt_env =
146
211
ty:: EarlyBinder :: bind ( tcx. param_env ( adt_def_id) ) . instantiate ( tcx, adt_to_impl_args) ;
147
212
148
- let fresh_impl_args = infcx. fresh_args_for_item ( impl_span, drop_impl_def_id . to_def_id ( ) ) ;
213
+ let fresh_impl_args = infcx. fresh_args_for_item ( impl_span, impl_def_id . to_def_id ( ) ) ;
149
214
let fresh_adt_ty =
150
- tcx. impl_trait_ref ( drop_impl_def_id ) . unwrap ( ) . instantiate ( tcx, fresh_impl_args) . self_ty ( ) ;
215
+ tcx. impl_trait_ref ( impl_def_id ) . unwrap ( ) . instantiate ( tcx, fresh_impl_args) . self_ty ( ) ;
151
216
152
217
ocx. eq ( & ObligationCause :: dummy_with_span ( impl_span) , adt_env, fresh_adt_ty, impl_adt_ty)
153
- . unwrap ( ) ;
218
+ . expect ( "equating fully generic trait ref should never fail" ) ;
154
219
155
- for ( clause, span) in tcx. predicates_of ( drop_impl_def_id ) . instantiate ( tcx, fresh_impl_args) {
156
- let normalize_cause = traits:: ObligationCause :: misc ( span, adt_def_id ) ;
220
+ for ( clause, span) in tcx. predicates_of ( impl_def_id ) . instantiate ( tcx, fresh_impl_args) {
221
+ let normalize_cause = traits:: ObligationCause :: misc ( span, impl_def_id ) ;
157
222
let pred = ocx. normalize ( & normalize_cause, adt_env, clause) ;
158
- let cause = traits:: ObligationCause :: new ( span, adt_def_id, ObligationCauseCode :: DropImpl ) ;
223
+ let cause = traits:: ObligationCause :: new (
224
+ span,
225
+ impl_def_id,
226
+ ObligationCauseCode :: AlwaysApplicableImpl ,
227
+ ) ;
159
228
ocx. register_obligation ( traits:: Obligation :: new ( tcx, cause, adt_env, pred) ) ;
160
229
}
161
230
@@ -173,13 +242,13 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
173
242
let root_predicate = error. root_obligation . predicate ;
174
243
if root_predicates. insert ( root_predicate) {
175
244
let item_span = tcx. def_span ( adt_def_id) ;
176
- let self_descr = tcx. def_descr ( adt_def_id. to_def_id ( ) ) ;
245
+ let self_descr = tcx. def_descr ( adt_def_id) ;
177
246
guar = Some (
178
247
struct_span_code_err ! (
179
248
tcx. dcx( ) ,
180
249
error. root_obligation. cause. span,
181
250
E0367 ,
182
- "`Drop ` impl requires `{root_predicate}` \
251
+ "`{polarity}{trait_name} ` impl requires `{root_predicate}` \
183
252
but the {self_descr} it is implemented for does not",
184
253
)
185
254
. with_span_note ( item_span, "the implementor must specify the same requirement" )
@@ -190,12 +259,12 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
190
259
return Err ( guar. unwrap ( ) ) ;
191
260
}
192
261
193
- let errors = ocx. infcx . resolve_regions ( adt_def_id , adt_env, [ ] ) ;
262
+ let errors = ocx. infcx . resolve_regions ( impl_def_id , adt_env, [ ] ) ;
194
263
if !errors. is_empty ( ) {
195
264
let mut guar = None ;
196
265
for error in errors {
197
266
let item_span = tcx. def_span ( adt_def_id) ;
198
- let self_descr = tcx. def_descr ( adt_def_id. to_def_id ( ) ) ;
267
+ let self_descr = tcx. def_descr ( adt_def_id) ;
199
268
let outlives = match error {
200
269
RegionResolutionError :: ConcreteFailure ( _, a, b) => format ! ( "{b}: {a}" ) ,
201
270
RegionResolutionError :: GenericBoundFailure ( _, generic, r) => {
@@ -212,7 +281,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
212
281
tcx. dcx( ) ,
213
282
error. origin( ) . span( ) ,
214
283
E0367 ,
215
- "`Drop ` impl requires `{outlives}` \
284
+ "`{polarity}{trait_name} ` impl requires `{outlives}` \
216
285
but the {self_descr} it is implemented for does not",
217
286
)
218
287
. with_span_note ( item_span, "the implementor must specify the same requirement" )
0 commit comments