@@ -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