@@ -18,6 +18,7 @@ use rustc::traits::{self, ObligationCause, Reveal};
18
18
use rustc:: ty:: { self , Ty , TyCtxt } ;
19
19
use rustc:: ty:: ParameterEnvironment ;
20
20
use rustc:: ty:: TypeFoldable ;
21
+ use rustc:: ty:: adjustment:: CoerceUnsizedInfo ;
21
22
use rustc:: ty:: subst:: Subst ;
22
23
use rustc:: ty:: util:: CopyImplementationError ;
23
24
use rustc:: infer;
@@ -159,28 +160,41 @@ fn visit_implementation_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
159
160
}
160
161
161
162
fn visit_implementation_of_coerce_unsized < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
162
- coerce_unsized_trait : DefId ,
163
+ _ : DefId ,
163
164
impl_did : DefId ) {
164
165
debug ! ( "visit_implementation_of_coerce_unsized: impl_did={:?}" ,
165
166
impl_did) ;
166
167
168
+ // Just compute this for the side-effects, in particular reporting
169
+ // errors; other parts of the code may demand it for the info of
170
+ // course.
171
+ if impl_did. is_local ( ) {
172
+ let span = tcx. def_span ( impl_did) ;
173
+ ty:: queries:: coerce_unsized_info:: get ( tcx, span, impl_did) ;
174
+ }
175
+ }
176
+
177
+ pub fn coerce_unsized_info < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
178
+ impl_did : DefId )
179
+ -> CoerceUnsizedInfo {
180
+ debug ! ( "compute_coerce_unsized_info(impl_did={:?})" , impl_did) ;
181
+ let coerce_unsized_trait = tcx. lang_items . coerce_unsized_trait ( ) . unwrap ( ) ;
182
+
167
183
let unsize_trait = match tcx. lang_items . require ( UnsizeTraitLangItem ) {
168
184
Ok ( id) => id,
169
185
Err ( err) => {
170
186
tcx. sess . fatal ( & format ! ( "`CoerceUnsized` implementation {}" , err) ) ;
171
187
}
172
188
} ;
173
189
174
- let impl_node_id = if let Some ( n) = tcx. hir . as_local_node_id ( impl_did) {
175
- n
176
- } else {
177
- debug ! ( "visit_implementation_of_coerce_unsized(): impl not \
178
- in this crate") ;
179
- return ;
180
- } ;
190
+ // this provider should only get invoked for local def-ids
191
+ let impl_node_id = tcx. hir . as_local_node_id ( impl_did) . unwrap_or_else ( || {
192
+ bug ! ( "coerce_unsized_info: invoked for non-local def-id {:?}" , impl_did)
193
+ } ) ;
181
194
182
195
let source = tcx. item_type ( impl_did) ;
183
196
let trait_ref = tcx. impl_trait_ref ( impl_did) . unwrap ( ) ;
197
+ assert_eq ! ( trait_ref. def_id, coerce_unsized_trait) ;
184
198
let target = trait_ref. substs . type_at ( 1 ) ;
185
199
debug ! ( "visit_implementation_of_coerce_unsized: {:?} -> {:?} (bound)" ,
186
200
source,
@@ -192,6 +206,8 @@ fn visit_implementation_of_coerce_unsized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
192
206
let target = target. subst ( tcx, & param_env. free_substs ) ;
193
207
assert ! ( !source. has_escaping_regions( ) ) ;
194
208
209
+ let err_info = CoerceUnsizedInfo { custom_kind : None } ;
210
+
195
211
debug ! ( "visit_implementation_of_coerce_unsized: {:?} -> {:?} (free)" ,
196
212
source,
197
213
target) ;
@@ -234,7 +250,7 @@ fn visit_implementation_of_coerce_unsized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
234
250
definition; expected {}, found {}",
235
251
source_path,
236
252
target_path) ;
237
- return ;
253
+ return err_info ;
238
254
}
239
255
240
256
let fields = & def_a. struct_variant ( ) . fields ;
@@ -268,7 +284,7 @@ fn visit_implementation_of_coerce_unsized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
268
284
"the trait `CoerceUnsized` may only be implemented \
269
285
for a coercion between structures with one field \
270
286
being coerced, none found") ;
271
- return ;
287
+ return err_info ;
272
288
} else if diff_fields. len ( ) > 1 {
273
289
let item = tcx. hir . expect_item ( impl_node_id) ;
274
290
let span = if let ItemImpl ( .., Some ( ref t) , _, _) = item. node {
@@ -295,7 +311,7 @@ fn visit_implementation_of_coerce_unsized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
295
311
. join( ", " ) ) ) ;
296
312
err. span_label ( span, & format ! ( "requires multiple coercions" ) ) ;
297
313
err. emit ( ) ;
298
- return ;
314
+ return err_info ;
299
315
}
300
316
301
317
let ( i, a, b) = diff_fields[ 0 ] ;
@@ -309,7 +325,7 @@ fn visit_implementation_of_coerce_unsized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
309
325
E0376 ,
310
326
"the trait `CoerceUnsized` may only be implemented \
311
327
for a coercion between structures") ;
312
- return ;
328
+ return err_info ;
313
329
}
314
330
} ;
315
331
@@ -331,8 +347,8 @@ fn visit_implementation_of_coerce_unsized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
331
347
. caller_bounds ) ;
332
348
infcx. resolve_regions_and_report_errors ( & free_regions, impl_node_id) ;
333
349
334
- if let Some ( kind ) = kind {
335
- tcx . maps . custom_coerce_unsized_kind . borrow_mut ( ) . insert ( impl_did , kind) ;
350
+ CoerceUnsizedInfo {
351
+ custom_kind : kind
336
352
}
337
- } ) ;
353
+ } )
338
354
}
0 commit comments