@@ -5,13 +5,14 @@ use rustc_abi::FieldIdx;
5
5
use rustc_data_structures:: unord:: { UnordMap , UnordSet } ;
6
6
use rustc_errors:: MultiSpan ;
7
7
use rustc_errors:: codes:: * ;
8
- use rustc_hir:: Node ;
9
8
use rustc_hir:: def:: { CtorKind , DefKind } ;
9
+ use rustc_hir:: { Node , intravisit} ;
10
10
use rustc_infer:: infer:: { RegionVariableOrigin , TyCtxtInferExt } ;
11
11
use rustc_infer:: traits:: Obligation ;
12
12
use rustc_lint_defs:: builtin:: {
13
13
REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS , UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS ,
14
14
} ;
15
+ use rustc_middle:: hir:: nested_filter;
15
16
use rustc_middle:: middle:: resolve_bound_vars:: ResolvedArg ;
16
17
use rustc_middle:: middle:: stability:: EvalResult ;
17
18
use rustc_middle:: span_bug;
@@ -190,7 +191,7 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) {
190
191
/// Checks that an opaque type does not contain cycles and does not use `Self` or `T::Foo`
191
192
/// projections that would result in "inheriting lifetimes".
192
193
fn check_opaque ( tcx : TyCtxt < ' _ > , def_id : LocalDefId ) {
193
- let hir:: OpaqueTy { origin, .. } = tcx. hir ( ) . expect_opaque_ty ( def_id) ;
194
+ let hir:: OpaqueTy { origin, .. } = * tcx. hir ( ) . expect_opaque_ty ( def_id) ;
194
195
195
196
// HACK(jynelson): trying to infer the type of `impl trait` breaks documenting
196
197
// `async-std` (and `pub async fn` in general).
@@ -200,23 +201,20 @@ fn check_opaque(tcx: TyCtxt<'_>, def_id: LocalDefId) {
200
201
return ;
201
202
}
202
203
203
- let span = tcx. def_span ( def_id) ;
204
-
205
204
if tcx. type_of ( def_id) . instantiate_identity ( ) . references_error ( ) {
206
205
return ;
207
206
}
208
- if check_opaque_for_cycles ( tcx, def_id, span ) . is_err ( ) {
207
+ if check_opaque_for_cycles ( tcx, def_id) . is_err ( ) {
209
208
return ;
210
209
}
211
210
212
- let _ = check_opaque_meets_bounds ( tcx, def_id, span , origin) ;
211
+ let _ = check_opaque_meets_bounds ( tcx, def_id, origin) ;
213
212
}
214
213
215
214
/// Checks that an opaque type does not contain cycles.
216
215
pub ( super ) fn check_opaque_for_cycles < ' tcx > (
217
216
tcx : TyCtxt < ' tcx > ,
218
217
def_id : LocalDefId ,
219
- span : Span ,
220
218
) -> Result < ( ) , ErrorGuaranteed > {
221
219
let args = GenericArgs :: identity_for_item ( tcx, def_id) ;
222
220
@@ -233,7 +231,7 @@ pub(super) fn check_opaque_for_cycles<'tcx>(
233
231
. try_expand_impl_trait_type ( def_id. to_def_id ( ) , args, InspectCoroutineFields :: No )
234
232
. is_err ( )
235
233
{
236
- let reported = opaque_type_cycle_error ( tcx, def_id, span ) ;
234
+ let reported = opaque_type_cycle_error ( tcx, def_id) ;
237
235
return Err ( reported) ;
238
236
}
239
237
@@ -267,10 +265,11 @@ pub(super) fn check_opaque_for_cycles<'tcx>(
267
265
fn check_opaque_meets_bounds < ' tcx > (
268
266
tcx : TyCtxt < ' tcx > ,
269
267
def_id : LocalDefId ,
270
- span : Span ,
271
- origin : & hir:: OpaqueTyOrigin < LocalDefId > ,
268
+ origin : hir:: OpaqueTyOrigin < LocalDefId > ,
272
269
) -> Result < ( ) , ErrorGuaranteed > {
273
- let defining_use_anchor = match * origin {
270
+ let span = span_of_opaque ( tcx, def_id, origin) . unwrap_or_else ( || tcx. def_span ( def_id) ) ;
271
+
272
+ let defining_use_anchor = match origin {
274
273
hir:: OpaqueTyOrigin :: FnReturn { parent, .. }
275
274
| hir:: OpaqueTyOrigin :: AsyncFn { parent, .. }
276
275
| hir:: OpaqueTyOrigin :: TyAlias { parent, .. } => parent,
@@ -281,7 +280,7 @@ fn check_opaque_meets_bounds<'tcx>(
281
280
let infcx = tcx. infer_ctxt ( ) . build ( TypingMode :: analysis_in_body ( tcx, defining_use_anchor) ) ;
282
281
let ocx = ObligationCtxt :: new_with_diagnostics ( & infcx) ;
283
282
284
- let args = match * origin {
283
+ let args = match origin {
285
284
hir:: OpaqueTyOrigin :: FnReturn { parent, .. }
286
285
| hir:: OpaqueTyOrigin :: AsyncFn { parent, .. }
287
286
| hir:: OpaqueTyOrigin :: TyAlias { parent, .. } => GenericArgs :: identity_for_item (
@@ -308,6 +307,7 @@ fn check_opaque_meets_bounds<'tcx>(
308
307
309
308
let misc_cause = traits:: ObligationCause :: misc ( span, def_id) ;
310
309
310
+ // FIXME: We should just register the item bounds here, rather than equating.
311
311
match ocx. eq ( & misc_cause, param_env, opaque_ty, hidden_ty) {
312
312
Ok ( ( ) ) => { }
313
313
Err ( ty_err) => {
@@ -364,6 +364,97 @@ fn check_opaque_meets_bounds<'tcx>(
364
364
}
365
365
}
366
366
367
+ fn span_of_opaque < ' tcx > (
368
+ tcx : TyCtxt < ' tcx > ,
369
+ opaque_def_id : LocalDefId ,
370
+ origin : hir:: OpaqueTyOrigin < LocalDefId > ,
371
+ ) -> Option < Span > {
372
+ struct TaitConstraintLocator < ' tcx > {
373
+ opaque_def_id : LocalDefId ,
374
+ tcx : TyCtxt < ' tcx > ,
375
+ }
376
+ impl < ' tcx > TaitConstraintLocator < ' tcx > {
377
+ fn check ( & self , item_def_id : LocalDefId ) -> ControlFlow < Span > {
378
+ if !self . tcx . has_typeck_results ( item_def_id) {
379
+ return ControlFlow :: Continue ( ( ) ) ;
380
+ }
381
+
382
+ if let Some ( hidden_ty) =
383
+ self . tcx . mir_borrowck ( item_def_id) . concrete_opaque_types . get ( & self . opaque_def_id )
384
+ {
385
+ ControlFlow :: Break ( hidden_ty. span )
386
+ } else {
387
+ ControlFlow :: Continue ( ( ) )
388
+ }
389
+ }
390
+ }
391
+ impl < ' tcx > intravisit:: Visitor < ' tcx > for TaitConstraintLocator < ' tcx > {
392
+ type NestedFilter = nested_filter:: All ;
393
+ type Result = ControlFlow < Span > ;
394
+ fn nested_visit_map ( & mut self ) -> Self :: Map {
395
+ self . tcx . hir ( )
396
+ }
397
+ fn visit_expr ( & mut self , ex : & ' tcx hir:: Expr < ' tcx > ) -> Self :: Result {
398
+ if let hir:: ExprKind :: Closure ( closure) = ex. kind {
399
+ self . check ( closure. def_id ) ?;
400
+ }
401
+ intravisit:: walk_expr ( self , ex)
402
+ }
403
+ fn visit_item ( & mut self , it : & ' tcx hir:: Item < ' tcx > ) -> Self :: Result {
404
+ self . check ( it. owner_id . def_id ) ?;
405
+ intravisit:: walk_item ( self , it)
406
+ }
407
+ fn visit_impl_item ( & mut self , it : & ' tcx hir:: ImplItem < ' tcx > ) -> Self :: Result {
408
+ self . check ( it. owner_id . def_id ) ?;
409
+ intravisit:: walk_impl_item ( self , it)
410
+ }
411
+ fn visit_trait_item ( & mut self , it : & ' tcx hir:: TraitItem < ' tcx > ) -> Self :: Result {
412
+ self . check ( it. owner_id . def_id ) ?;
413
+ intravisit:: walk_trait_item ( self , it)
414
+ }
415
+ fn visit_foreign_item ( & mut self , it : & ' tcx hir:: ForeignItem < ' tcx > ) -> Self :: Result {
416
+ intravisit:: walk_foreign_item ( self , it)
417
+ }
418
+ }
419
+
420
+ let mut locator = TaitConstraintLocator { tcx, opaque_def_id } ;
421
+ match origin {
422
+ hir:: OpaqueTyOrigin :: FnReturn { parent, .. }
423
+ | hir:: OpaqueTyOrigin :: AsyncFn { parent, .. } => locator. check ( parent) . break_value ( ) ,
424
+ hir:: OpaqueTyOrigin :: TyAlias { parent, in_assoc_ty : true } => {
425
+ let impl_def_id = tcx. local_parent ( parent) ;
426
+ for assoc in tcx. associated_items ( impl_def_id) . in_definition_order ( ) {
427
+ match assoc. kind {
428
+ ty:: AssocKind :: Const | ty:: AssocKind :: Fn => {
429
+ if let ControlFlow :: Break ( span) = locator. check ( assoc. def_id . expect_local ( ) )
430
+ {
431
+ return Some ( span) ;
432
+ }
433
+ }
434
+ ty:: AssocKind :: Type => { }
435
+ }
436
+ }
437
+
438
+ None
439
+ }
440
+ hir:: OpaqueTyOrigin :: TyAlias { in_assoc_ty : false , .. } => {
441
+ let scope = tcx. hir ( ) . get_defining_scope ( tcx. local_def_id_to_hir_id ( opaque_def_id) ) ;
442
+ let found = if scope == hir:: CRATE_HIR_ID {
443
+ tcx. hir ( ) . walk_toplevel_module ( & mut locator)
444
+ } else {
445
+ match tcx. hir_node ( scope) {
446
+ Node :: Item ( it) => locator. visit_item ( it) ,
447
+ Node :: ImplItem ( it) => locator. visit_impl_item ( it) ,
448
+ Node :: TraitItem ( it) => locator. visit_trait_item ( it) ,
449
+ Node :: ForeignItem ( it) => locator. visit_foreign_item ( it) ,
450
+ other => bug ! ( "{:?} is not a valid scope for an opaque type item" , other) ,
451
+ }
452
+ } ;
453
+ found. break_value ( )
454
+ }
455
+ }
456
+ }
457
+
367
458
fn sanity_check_found_hidden_type < ' tcx > (
368
459
tcx : TyCtxt < ' tcx > ,
369
460
key : ty:: OpaqueTypeKey < ' tcx > ,
@@ -1535,11 +1626,8 @@ fn check_type_alias_type_params_are_used<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalD
1535
1626
///
1536
1627
/// If all the return expressions evaluate to `!`, then we explain that the error will go away
1537
1628
/// after changing it. This can happen when a user uses `panic!()` or similar as a placeholder.
1538
- fn opaque_type_cycle_error (
1539
- tcx : TyCtxt < ' _ > ,
1540
- opaque_def_id : LocalDefId ,
1541
- span : Span ,
1542
- ) -> ErrorGuaranteed {
1629
+ fn opaque_type_cycle_error ( tcx : TyCtxt < ' _ > , opaque_def_id : LocalDefId ) -> ErrorGuaranteed {
1630
+ let span = tcx. def_span ( opaque_def_id) ;
1543
1631
let mut err = struct_span_code_err ! ( tcx. dcx( ) , span, E0720 , "cannot resolve opaque type" ) ;
1544
1632
1545
1633
let mut label = false ;
0 commit comments