| 
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