@@ -6,10 +6,10 @@ use rustc_data_structures::fx::FxHashSet;
6
6
use rustc_errors:: { codes:: * , struct_span_code_err, ErrorGuaranteed } ;
7
7
use rustc_infer:: infer:: outlives:: env:: OutlivesEnvironment ;
8
8
use rustc_infer:: infer:: { RegionResolutionError , TyCtxtInferExt } ;
9
- use rustc_infer:: traits:: ObligationCauseCode ;
9
+ use rustc_infer:: traits:: { ObligationCause , ObligationCauseCode } ;
10
10
use rustc_middle:: ty:: util:: CheckRegions ;
11
- use rustc_middle:: ty:: GenericArgsRef ;
12
11
use rustc_middle:: ty:: { self , TyCtxt } ;
12
+ use rustc_middle:: ty:: { GenericArgsRef , Ty } ;
13
13
use rustc_trait_selection:: regions:: InferCtxtRegionExt ;
14
14
use rustc_trait_selection:: traits:: { self , ObligationCtxt } ;
15
15
@@ -115,8 +115,9 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
115
115
Err ( err. emit ( ) )
116
116
}
117
117
118
- /// Confirms that every predicate imposed by dtor_predicates is
119
- /// implied by assuming the predicates attached to self_type_did.
118
+ /// Confirms that all predicates defined on the `Drop` impl (`drop_impl_def_id`) are able to be
119
+ /// proven from within `adt_def_id`'s environment. I.e. all the predicates on the impl are
120
+ /// implied by the ADT being well formed.
120
121
fn ensure_drop_predicates_are_implied_by_item_defn < ' tcx > (
121
122
tcx : TyCtxt < ' tcx > ,
122
123
drop_impl_def_id : LocalDefId ,
@@ -126,6 +127,8 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
126
127
let infcx = tcx. infer_ctxt ( ) . build ( ) ;
127
128
let ocx = ObligationCtxt :: new_with_diagnostics ( & infcx) ;
128
129
130
+ let impl_span = tcx. def_span ( drop_impl_def_id. to_def_id ( ) ) ;
131
+
129
132
// Take the param-env of the adt and instantiate the args that show up in
130
133
// the implementation's self type. This gives us the assumptions that the
131
134
// self ty of the implementation is allowed to know just from it being a
@@ -135,14 +138,27 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
135
138
// We don't need to normalize this param-env or anything, since we're only
136
139
// instantiating it with free params, so no additional param-env normalization
137
140
// can occur on top of what has been done in the param_env query itself.
138
- let param_env =
141
+ //
142
+ // Note: Ideally instead of instantiating the `ParamEnv` with the arguments from the impl ty we
143
+ // could instead use identity args for the adt. Unfortunately this would cause any errors to
144
+ // reference the params from the ADT instead of from the impl which is bad UX. To resolve
145
+ // this we "rename" the ADT's params to be the impl's params which should not affect behaviour.
146
+ let impl_adt_ty = Ty :: new_adt ( tcx, tcx. adt_def ( adt_def_id) , adt_to_impl_args) ;
147
+ let adt_env =
139
148
ty:: EarlyBinder :: bind ( tcx. param_env ( adt_def_id) ) . instantiate ( tcx, adt_to_impl_args) ;
140
149
141
- for ( pred, span) in tcx. predicates_of ( drop_impl_def_id) . instantiate_identity ( tcx) {
150
+ let fresh_impl_args = infcx. fresh_args_for_item ( impl_span, drop_impl_def_id. to_def_id ( ) ) ;
151
+ let fresh_adt_ty =
152
+ tcx. impl_trait_ref ( drop_impl_def_id) . unwrap ( ) . instantiate ( tcx, fresh_impl_args) . self_ty ( ) ;
153
+
154
+ ocx. eq ( & ObligationCause :: dummy_with_span ( impl_span) , adt_env, fresh_adt_ty, impl_adt_ty)
155
+ . unwrap ( ) ;
156
+
157
+ for ( clause, span) in tcx. predicates_of ( drop_impl_def_id) . instantiate ( tcx, fresh_impl_args) {
142
158
let normalize_cause = traits:: ObligationCause :: misc ( span, adt_def_id) ;
143
- let pred = ocx. normalize ( & normalize_cause, param_env , pred ) ;
159
+ let pred = ocx. normalize ( & normalize_cause, adt_env , clause ) ;
144
160
let cause = traits:: ObligationCause :: new ( span, adt_def_id, ObligationCauseCode :: DropImpl ) ;
145
- ocx. register_obligation ( traits:: Obligation :: new ( tcx, cause, param_env , pred) ) ;
161
+ ocx. register_obligation ( traits:: Obligation :: new ( tcx, cause, adt_env , pred) ) ;
146
162
}
147
163
148
164
// All of the custom error reporting logic is to preserve parity with the old
@@ -176,7 +192,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
176
192
return Err ( guar. unwrap ( ) ) ;
177
193
}
178
194
179
- let errors = ocx. infcx . resolve_regions ( & OutlivesEnvironment :: new ( param_env ) ) ;
195
+ let errors = ocx. infcx . resolve_regions ( & OutlivesEnvironment :: new ( adt_env ) ) ;
180
196
if !errors. is_empty ( ) {
181
197
let mut guar = None ;
182
198
for error in errors {
0 commit comments