|
9 | 9 | //! which creates a new `TypeckResults` which doesn't contain any inference variables.
|
10 | 10 |
|
11 | 11 | use std::mem;
|
| 12 | +use std::ops::ControlFlow; |
12 | 13 |
|
| 14 | +use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; |
13 | 15 | use rustc_data_structures::unord::ExtendUnord;
|
14 |
| -use rustc_errors::ErrorGuaranteed; |
| 16 | +use rustc_errors::{E0720, ErrorGuaranteed}; |
| 17 | +use rustc_hir::def_id::LocalDefId; |
15 | 18 | use rustc_hir::intravisit::{self, InferKind, Visitor};
|
16 | 19 | use rustc_hir::{self as hir, AmbigArg, HirId};
|
17 | 20 | use rustc_infer::traits::solve::Goal;
|
18 | 21 | use rustc_middle::traits::ObligationCause;
|
19 | 22 | use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion};
|
20 | 23 | use rustc_middle::ty::{
|
21 |
| - self, DefiningScopeKind, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, |
22 |
| - TypeVisitableExt, fold_regions, |
| 24 | + self, DefiningScopeKind, OpaqueHiddenType, Ty, TyCtxt, TypeFoldable, TypeFolder, |
| 25 | + TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, |
| 26 | + fold_regions, |
23 | 27 | };
|
24 | 28 | use rustc_span::{Span, sym};
|
25 | 29 | use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded;
|
@@ -595,6 +599,35 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
595 | 599 | entry.span = prev.span.substitute_dummy(hidden_type.span);
|
596 | 600 | }
|
597 | 601 | }
|
| 602 | + |
| 603 | + let recursive_opaques: Vec<_> = self |
| 604 | + .typeck_results |
| 605 | + .concrete_opaque_types |
| 606 | + .iter() |
| 607 | + .filter(|&(&def_id, hidden_ty)| { |
| 608 | + hidden_ty |
| 609 | + .ty |
| 610 | + .visit_with(&mut HasRecursiveOpaque { |
| 611 | + def_id, |
| 612 | + seen: Default::default(), |
| 613 | + opaques: &self.typeck_results.concrete_opaque_types, |
| 614 | + tcx, |
| 615 | + }) |
| 616 | + .is_break() |
| 617 | + }) |
| 618 | + .map(|(def_id, hidden_ty)| (*def_id, hidden_ty.span)) |
| 619 | + .collect(); |
| 620 | + for (def_id, span) in recursive_opaques { |
| 621 | + let guar = self |
| 622 | + .fcx |
| 623 | + .dcx() |
| 624 | + .struct_span_err(span, "cannot resolve opaque type") |
| 625 | + .with_code(E0720) |
| 626 | + .emit(); |
| 627 | + self.typeck_results |
| 628 | + .concrete_opaque_types |
| 629 | + .insert(def_id, OpaqueHiddenType { span, ty: Ty::new_error(tcx, guar) }); |
| 630 | + } |
598 | 631 | }
|
599 | 632 |
|
600 | 633 | fn visit_field_id(&mut self, hir_id: HirId) {
|
@@ -959,3 +992,34 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EagerlyNormalizeConsts<'tcx> {
|
959 | 992 | self.tcx.try_normalize_erasing_regions(self.typing_env, ct).unwrap_or(ct)
|
960 | 993 | }
|
961 | 994 | }
|
| 995 | + |
| 996 | +struct HasRecursiveOpaque<'a, 'tcx> { |
| 997 | + def_id: LocalDefId, |
| 998 | + seen: FxHashSet<LocalDefId>, |
| 999 | + opaques: &'a FxIndexMap<LocalDefId, ty::OpaqueHiddenType<'tcx>>, |
| 1000 | + tcx: TyCtxt<'tcx>, |
| 1001 | +} |
| 1002 | + |
| 1003 | +impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasRecursiveOpaque<'_, 'tcx> { |
| 1004 | + type Result = ControlFlow<()>; |
| 1005 | + |
| 1006 | + fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { |
| 1007 | + if let ty::Alias(ty::Opaque, alias_ty) = *t.kind() |
| 1008 | + && let Some(def_id) = alias_ty.def_id.as_local() |
| 1009 | + { |
| 1010 | + if self.def_id == def_id { |
| 1011 | + return ControlFlow::Break(()); |
| 1012 | + } |
| 1013 | + |
| 1014 | + if self.seen.insert(def_id) |
| 1015 | + && let Some(hidden_ty) = self.opaques.get(&def_id) |
| 1016 | + { |
| 1017 | + ty::EarlyBinder::bind(hidden_ty.ty) |
| 1018 | + .instantiate(self.tcx, alias_ty.args) |
| 1019 | + .visit_with(self)?; |
| 1020 | + } |
| 1021 | + } |
| 1022 | + |
| 1023 | + t.super_visit_with(self) |
| 1024 | + } |
| 1025 | +} |
0 commit comments