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+
17use rustc_data_structures:: fx:: FxHashSet ;
28use rustc_errors:: codes:: * ;
39use rustc_errors:: { ErrorGuaranteed , struct_span_code_err} ;
410use rustc_infer:: infer:: { RegionResolutionError , TyCtxtInferExt } ;
511use rustc_infer:: traits:: { ObligationCause , ObligationCauseCode } ;
12+ use rustc_middle:: span_bug;
613use rustc_middle:: ty:: util:: CheckRegions ;
714use rustc_middle:: ty:: { self , GenericArgsRef , Ty , TyCtxt , TypingMode } ;
815use rustc_trait_selection:: regions:: InferCtxtRegionExt ;
@@ -27,11 +34,12 @@ use crate::hir::def_id::{DefId, LocalDefId};
2734/// 3. Any bounds on the generic parameters must be reflected in the
2835/// struct/enum definition for the nominal type itself (i.e.
2936/// cannot do `struct S<T>; impl<T:Clone> Drop for S<T> { ... }`).
30- ///
3137pub ( crate ) fn check_drop_impl (
3238 tcx : TyCtxt < ' _ > ,
3339 drop_impl_did : DefId ,
3440) -> Result < ( ) , ErrorGuaranteed > {
41+ let drop_impl_did = drop_impl_did. expect_local ( ) ;
42+
3543 match tcx. impl_polarity ( drop_impl_did) {
3644 ty:: ImplPolarity :: Positive => { }
3745 ty:: ImplPolarity :: Negative => {
@@ -45,55 +53,107 @@ pub(crate) fn check_drop_impl(
4553 } ) ) ;
4654 }
4755 }
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 ( ) {
5062 ty:: Adt ( adt_def, adt_to_impl_args) => {
51- ensure_drop_params_and_item_params_correspond (
63+ ensure_impl_params_and_item_params_correspond (
5264 tcx,
53- drop_impl_did. expect_local ( ) ,
65+ drop_impl_did,
5466 adt_def. did ( ) ,
5567 adt_to_impl_args,
5668 ) ?;
5769
58- ensure_drop_predicates_are_implied_by_item_defn (
70+ ensure_impl_predicates_are_implied_by_item_defn (
5971 tcx,
60- drop_impl_did. expect_local ( ) ,
61- adt_def. did ( ) . expect_local ( ) ,
72+ drop_impl_did,
73+ adt_def. did ( ) ,
6274 adt_to_impl_args,
6375 )
6476 }
6577 _ => {
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" ) ;
7579 }
7680 }
7781}
7882
79- fn ensure_drop_params_and_item_params_correspond < ' tcx > (
83+ pub ( crate ) fn check_negative_auto_trait_impl < ' tcx > (
8084 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 ,
83137 adt_to_impl_args : GenericArgsRef < ' tcx > ,
84138) -> Result < ( ) , ErrorGuaranteed > {
85139 let Err ( arg) = tcx. uses_unique_generic_params ( adt_to_impl_args, CheckRegions :: OnlyParam ) else {
86140 return Ok ( ( ) ) ;
87141 } ;
88142
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 drop_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" ) ) ;
92152 let mut err = struct_span_code_err ! (
93153 tcx. dcx( ) ,
94154 drop_impl_span,
95155 E0366 ,
96- "`Drop ` impls cannot be specialized"
156+ "`{polarity}{trait_name} ` impls cannot be specialized" ,
97157 ) ;
98158 match arg {
99159 ty:: util:: NotUniqueParam :: DuplicateParam ( arg) => {
@@ -116,17 +176,22 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
116176/// Confirms that all predicates defined on the `Drop` impl (`drop_impl_def_id`) are able to be
117177/// proven from within `adt_def_id`'s environment. I.e. all the predicates on the impl are
118178/// 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 > (
120180 tcx : TyCtxt < ' tcx > ,
121- drop_impl_def_id : LocalDefId ,
122- adt_def_id : LocalDefId ,
181+ impl_def_id : LocalDefId ,
182+ adt_def_id : DefId ,
123183 adt_to_impl_args : GenericArgsRef < ' tcx > ,
124184) -> Result < ( ) , ErrorGuaranteed > {
125185 let infcx = tcx. infer_ctxt ( ) . build ( TypingMode :: non_body_analysis ( ) ) ;
126186 let ocx = ObligationCtxt :: new_with_diagnostics ( & infcx) ;
127187
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+ } ;
130195 // Take the param-env of the adt and instantiate the args that show up in
131196 // the implementation's self type. This gives us the assumptions that the
132197 // 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>(
145210 let adt_env =
146211 ty:: EarlyBinder :: bind ( tcx. param_env ( adt_def_id) ) . instantiate ( tcx, adt_to_impl_args) ;
147212
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 ( ) ) ;
149214 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 ( ) ;
151216
152217 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" ) ;
154219
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 ) ;
157222 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+ ) ;
159228 ocx. register_obligation ( traits:: Obligation :: new ( tcx, cause, adt_env, pred) ) ;
160229 }
161230
@@ -173,13 +242,13 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
173242 let root_predicate = error. root_obligation . predicate ;
174243 if root_predicates. insert ( root_predicate) {
175244 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) ;
177246 guar = Some (
178247 struct_span_code_err ! (
179248 tcx. dcx( ) ,
180249 error. root_obligation. cause. span,
181250 E0367 ,
182- "`Drop ` impl requires `{root_predicate}` \
251+ "`{polarity}{trait_name} ` impl requires `{root_predicate}` \
183252 but the {self_descr} it is implemented for does not",
184253 )
185254 . 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>(
190259 return Err ( guar. unwrap ( ) ) ;
191260 }
192261
193- let errors = ocx. infcx . resolve_regions ( adt_def_id , adt_env, [ ] ) ;
262+ let errors = ocx. infcx . resolve_regions ( impl_def_id , adt_env, [ ] ) ;
194263 if !errors. is_empty ( ) {
195264 let mut guar = None ;
196265 for error in errors {
197266 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) ;
199268 let outlives = match error {
200269 RegionResolutionError :: ConcreteFailure ( _, a, b) => format ! ( "{b}: {a}" ) ,
201270 RegionResolutionError :: GenericBoundFailure ( _, generic, r) => {
@@ -212,7 +281,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
212281 tcx. dcx( ) ,
213282 error. origin( ) . span( ) ,
214283 E0367 ,
215- "`Drop ` impl requires `{outlives}` \
284+ "`{polarity}{trait_name} ` impl requires `{outlives}` \
216285 but the {self_descr} it is implemented for does not",
217286 )
218287 . with_span_note ( item_span, "the implementor must specify the same requirement" )
0 commit comments