@@ -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 } ;
11- use rustc_infer:: traits:: Obligation ;
11+ use rustc_infer:: traits:: { Obligation , ObligationCauseCode } ;
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,16 @@ 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, definition_def_id) =
271+ if let Some ( ( span, def_id) ) = best_definition_site_of_opaque ( tcx, def_id, origin) {
272+ ( span, Some ( def_id) )
273+ } else {
274+ ( tcx. def_span ( def_id) , None )
275+ } ;
276+
277+ let defining_use_anchor = match origin {
274278 hir:: OpaqueTyOrigin :: FnReturn { parent, .. }
275279 | hir:: OpaqueTyOrigin :: AsyncFn { parent, .. }
276280 | hir:: OpaqueTyOrigin :: TyAlias { parent, .. } => parent,
@@ -281,7 +285,7 @@ fn check_opaque_meets_bounds<'tcx>(
281285 let infcx = tcx. infer_ctxt ( ) . build ( TypingMode :: analysis_in_body ( tcx, defining_use_anchor) ) ;
282286 let ocx = ObligationCtxt :: new_with_diagnostics ( & infcx) ;
283287
284- let args = match * origin {
288+ let args = match origin {
285289 hir:: OpaqueTyOrigin :: FnReturn { parent, .. }
286290 | hir:: OpaqueTyOrigin :: AsyncFn { parent, .. }
287291 | hir:: OpaqueTyOrigin :: TyAlias { parent, .. } => GenericArgs :: identity_for_item (
@@ -306,8 +310,33 @@ fn check_opaque_meets_bounds<'tcx>(
306310 _ => re,
307311 } ) ;
308312
309- let misc_cause = traits:: ObligationCause :: misc ( span, def_id) ;
313+ // HACK: We eagerly instantiate some bounds to report better errors for them...
314+ // This isn't necessary for correctness, since we register these bounds when
315+ // equating the opaque below, but we should clean this up in the new solver.
316+ for ( predicate, pred_span) in
317+ tcx. explicit_item_bounds ( def_id) . iter_instantiated_copied ( tcx, args)
318+ {
319+ let predicate = predicate. fold_with ( & mut BottomUpFolder {
320+ tcx,
321+ ty_op : |ty| if ty == opaque_ty { hidden_ty } else { ty } ,
322+ lt_op : |lt| lt,
323+ ct_op : |ct| ct,
324+ } ) ;
325+
326+ ocx. register_obligation ( Obligation :: new (
327+ tcx,
328+ ObligationCause :: new (
329+ span,
330+ def_id,
331+ ObligationCauseCode :: OpaqueTypeBound ( pred_span, definition_def_id) ,
332+ ) ,
333+ param_env,
334+ predicate,
335+ ) ) ;
336+ }
310337
338+ let misc_cause = ObligationCause :: misc ( span, def_id) ;
339+ // FIXME: We should just register the item bounds here, rather than equating.
311340 match ocx. eq ( & misc_cause, param_env, opaque_ty, hidden_ty) {
312341 Ok ( ( ) ) => { }
313342 Err ( ty_err) => {
@@ -364,6 +393,97 @@ fn check_opaque_meets_bounds<'tcx>(
364393 }
365394}
366395
396+ fn best_definition_site_of_opaque < ' tcx > (
397+ tcx : TyCtxt < ' tcx > ,
398+ opaque_def_id : LocalDefId ,
399+ origin : hir:: OpaqueTyOrigin < LocalDefId > ,
400+ ) -> Option < ( Span , LocalDefId ) > {
401+ struct TaitConstraintLocator < ' tcx > {
402+ opaque_def_id : LocalDefId ,
403+ tcx : TyCtxt < ' tcx > ,
404+ }
405+ impl < ' tcx > TaitConstraintLocator < ' tcx > {
406+ fn check ( & self , item_def_id : LocalDefId ) -> ControlFlow < ( Span , LocalDefId ) > {
407+ if !self . tcx . has_typeck_results ( item_def_id) {
408+ return ControlFlow :: Continue ( ( ) ) ;
409+ }
410+
411+ if let Some ( hidden_ty) =
412+ self . tcx . mir_borrowck ( item_def_id) . concrete_opaque_types . get ( & self . opaque_def_id )
413+ {
414+ ControlFlow :: Break ( ( hidden_ty. span , item_def_id) )
415+ } else {
416+ ControlFlow :: Continue ( ( ) )
417+ }
418+ }
419+ }
420+ impl < ' tcx > intravisit:: Visitor < ' tcx > for TaitConstraintLocator < ' tcx > {
421+ type NestedFilter = nested_filter:: All ;
422+ type Result = ControlFlow < ( Span , LocalDefId ) > ;
423+ fn nested_visit_map ( & mut self ) -> Self :: Map {
424+ self . tcx . hir ( )
425+ }
426+ fn visit_expr ( & mut self , ex : & ' tcx hir:: Expr < ' tcx > ) -> Self :: Result {
427+ if let hir:: ExprKind :: Closure ( closure) = ex. kind {
428+ self . check ( closure. def_id ) ?;
429+ }
430+ intravisit:: walk_expr ( self , ex)
431+ }
432+ fn visit_item ( & mut self , it : & ' tcx hir:: Item < ' tcx > ) -> Self :: Result {
433+ self . check ( it. owner_id . def_id ) ?;
434+ intravisit:: walk_item ( self , it)
435+ }
436+ fn visit_impl_item ( & mut self , it : & ' tcx hir:: ImplItem < ' tcx > ) -> Self :: Result {
437+ self . check ( it. owner_id . def_id ) ?;
438+ intravisit:: walk_impl_item ( self , it)
439+ }
440+ fn visit_trait_item ( & mut self , it : & ' tcx hir:: TraitItem < ' tcx > ) -> Self :: Result {
441+ self . check ( it. owner_id . def_id ) ?;
442+ intravisit:: walk_trait_item ( self , it)
443+ }
444+ fn visit_foreign_item ( & mut self , it : & ' tcx hir:: ForeignItem < ' tcx > ) -> Self :: Result {
445+ intravisit:: walk_foreign_item ( self , it)
446+ }
447+ }
448+
449+ let mut locator = TaitConstraintLocator { tcx, opaque_def_id } ;
450+ match origin {
451+ hir:: OpaqueTyOrigin :: FnReturn { parent, .. }
452+ | hir:: OpaqueTyOrigin :: AsyncFn { parent, .. } => locator. check ( parent) . break_value ( ) ,
453+ hir:: OpaqueTyOrigin :: TyAlias { parent, in_assoc_ty : true } => {
454+ let impl_def_id = tcx. local_parent ( parent) ;
455+ for assoc in tcx. associated_items ( impl_def_id) . in_definition_order ( ) {
456+ match assoc. kind {
457+ ty:: AssocKind :: Const | ty:: AssocKind :: Fn => {
458+ if let ControlFlow :: Break ( span) = locator. check ( assoc. def_id . expect_local ( ) )
459+ {
460+ return Some ( span) ;
461+ }
462+ }
463+ ty:: AssocKind :: Type => { }
464+ }
465+ }
466+
467+ None
468+ }
469+ hir:: OpaqueTyOrigin :: TyAlias { in_assoc_ty : false , .. } => {
470+ let scope = tcx. hir ( ) . get_defining_scope ( tcx. local_def_id_to_hir_id ( opaque_def_id) ) ;
471+ let found = if scope == hir:: CRATE_HIR_ID {
472+ tcx. hir ( ) . walk_toplevel_module ( & mut locator)
473+ } else {
474+ match tcx. hir_node ( scope) {
475+ Node :: Item ( it) => locator. visit_item ( it) ,
476+ Node :: ImplItem ( it) => locator. visit_impl_item ( it) ,
477+ Node :: TraitItem ( it) => locator. visit_trait_item ( it) ,
478+ Node :: ForeignItem ( it) => locator. visit_foreign_item ( it) ,
479+ other => bug ! ( "{:?} is not a valid scope for an opaque type item" , other) ,
480+ }
481+ } ;
482+ found. break_value ( )
483+ }
484+ }
485+ }
486+
367487fn sanity_check_found_hidden_type < ' tcx > (
368488 tcx : TyCtxt < ' tcx > ,
369489 key : ty:: OpaqueTypeKey < ' tcx > ,
@@ -1535,11 +1655,8 @@ fn check_type_alias_type_params_are_used<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalD
15351655///
15361656/// If all the return expressions evaluate to `!`, then we explain that the error will go away
15371657/// 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 {
1658+ fn opaque_type_cycle_error ( tcx : TyCtxt < ' _ > , opaque_def_id : LocalDefId ) -> ErrorGuaranteed {
1659+ let span = tcx. def_span ( opaque_def_id) ;
15431660 let mut err = struct_span_code_err ! ( tcx. dcx( ) , span, E0720 , "cannot resolve opaque type" ) ;
15441661
15451662 let mut label = false ;
0 commit comments