@@ -5,13 +5,14 @@ use rustc_abi::FieldIdx;
55use rustc_data_structures:: unord:: { UnordMap , UnordSet } ;
66use rustc_errors:: MultiSpan ;
77use rustc_errors:: codes:: * ;
8- use rustc_hir:: Node ;
98use rustc_hir:: def:: { CtorKind , DefKind } ;
9+ use rustc_hir:: { Node , intravisit} ;
1010use rustc_infer:: infer:: { RegionVariableOrigin , TyCtxtInferExt } ;
1111use rustc_infer:: traits:: Obligation ;
1212use rustc_lint_defs:: builtin:: {
1313 REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS , UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS ,
1414} ;
15+ use rustc_middle:: hir:: nested_filter;
1516use rustc_middle:: middle:: resolve_bound_vars:: ResolvedArg ;
1617use rustc_middle:: middle:: stability:: EvalResult ;
1718use rustc_middle:: span_bug;
@@ -190,7 +191,7 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) {
190191/// Checks that an opaque type does not contain cycles and does not use `Self` or `T::Foo`
191192/// projections that would result in "inheriting lifetimes".
192193fn 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) ;
194195
195196 // HACK(jynelson): trying to infer the type of `impl trait` breaks documenting
196197 // `async-std` (and `pub async fn` in general).
@@ -200,23 +201,20 @@ fn check_opaque(tcx: TyCtxt<'_>, def_id: LocalDefId) {
200201 return ;
201202 }
202203
203- let span = tcx. def_span ( def_id) ;
204-
205204 if tcx. type_of ( def_id) . instantiate_identity ( ) . references_error ( ) {
206205 return ;
207206 }
208- if check_opaque_for_cycles ( tcx, def_id, span ) . is_err ( ) {
207+ if check_opaque_for_cycles ( tcx, def_id) . is_err ( ) {
209208 return ;
210209 }
211210
212- let _ = check_opaque_meets_bounds ( tcx, def_id, span , origin) ;
211+ let _ = check_opaque_meets_bounds ( tcx, def_id, origin) ;
213212}
214213
215214/// Checks that an opaque type does not contain cycles.
216215pub ( super ) fn check_opaque_for_cycles < ' tcx > (
217216 tcx : TyCtxt < ' tcx > ,
218217 def_id : LocalDefId ,
219- span : Span ,
220218) -> Result < ( ) , ErrorGuaranteed > {
221219 let args = GenericArgs :: identity_for_item ( tcx, def_id) ;
222220
@@ -233,7 +231,7 @@ pub(super) fn check_opaque_for_cycles<'tcx>(
233231 . try_expand_impl_trait_type ( def_id. to_def_id ( ) , args, InspectCoroutineFields :: No )
234232 . is_err ( )
235233 {
236- let reported = opaque_type_cycle_error ( tcx, def_id, span ) ;
234+ let reported = opaque_type_cycle_error ( tcx, def_id) ;
237235 return Err ( reported) ;
238236 }
239237
@@ -267,10 +265,11 @@ pub(super) fn check_opaque_for_cycles<'tcx>(
267265fn check_opaque_meets_bounds < ' tcx > (
268266 tcx : TyCtxt < ' tcx > ,
269267 def_id : LocalDefId ,
270- span : Span ,
271- origin : & hir:: OpaqueTyOrigin < LocalDefId > ,
268+ origin : hir:: OpaqueTyOrigin < LocalDefId > ,
272269) -> 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 {
274273 hir:: OpaqueTyOrigin :: FnReturn { parent, .. }
275274 | hir:: OpaqueTyOrigin :: AsyncFn { parent, .. }
276275 | hir:: OpaqueTyOrigin :: TyAlias { parent, .. } => parent,
@@ -281,7 +280,7 @@ fn check_opaque_meets_bounds<'tcx>(
281280 let infcx = tcx. infer_ctxt ( ) . build ( TypingMode :: analysis_in_body ( tcx, defining_use_anchor) ) ;
282281 let ocx = ObligationCtxt :: new_with_diagnostics ( & infcx) ;
283282
284- let args = match * origin {
283+ let args = match origin {
285284 hir:: OpaqueTyOrigin :: FnReturn { parent, .. }
286285 | hir:: OpaqueTyOrigin :: AsyncFn { parent, .. }
287286 | hir:: OpaqueTyOrigin :: TyAlias { parent, .. } => GenericArgs :: identity_for_item (
@@ -308,6 +307,7 @@ fn check_opaque_meets_bounds<'tcx>(
308307
309308 let misc_cause = traits:: ObligationCause :: misc ( span, def_id) ;
310309
310+ // FIXME: We should just register the item bounds here, rather than equating.
311311 match ocx. eq ( & misc_cause, param_env, opaque_ty, hidden_ty) {
312312 Ok ( ( ) ) => { }
313313 Err ( ty_err) => {
@@ -364,6 +364,97 @@ fn check_opaque_meets_bounds<'tcx>(
364364 }
365365}
366366
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+
367458fn sanity_check_found_hidden_type < ' tcx > (
368459 tcx : TyCtxt < ' tcx > ,
369460 key : ty:: OpaqueTypeKey < ' tcx > ,
@@ -1535,11 +1626,8 @@ fn check_type_alias_type_params_are_used<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalD
15351626///
15361627/// If all the return expressions evaluate to `!`, then we explain that the error will go away
15371628/// 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) ;
15431631 let mut err = struct_span_code_err ! ( tcx. dcx( ) , span, E0720 , "cannot resolve opaque type" ) ;
15441632
15451633 let mut label = false ;
0 commit comments