|
1 | 1 | use crate::traits;
|
| 2 | +use crate::traits::error_reporting::InferCtxtExt as _; |
| 3 | +use crate::traits::TraitEngineExt as _; |
2 | 4 | use rustc_data_structures::fx::FxHashMap;
|
3 | 5 | use rustc_hir::def_id::DefId;
|
| 6 | +use rustc_hir::OpaqueTyOrigin; |
4 | 7 | use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic;
|
5 |
| -use rustc_infer::infer::InferCtxt; |
| 8 | +use rustc_infer::infer::{InferCtxt, TyCtxtInferExt as _}; |
| 9 | +use rustc_infer::traits::{Obligation, ObligationCause, TraitEngine}; |
6 | 10 | use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
|
7 | 11 | use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts};
|
8 |
| -use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt}; |
| 12 | +use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, ToPredicate, Ty, TyCtxt}; |
9 | 13 | use rustc_span::Span;
|
10 | 14 |
|
11 | 15 | pub trait InferCtxtExt<'tcx> {
|
12 | 16 | fn infer_opaque_definition_from_instantiation(
|
13 | 17 | &self,
|
14 | 18 | opaque_type_key: OpaqueTypeKey<'tcx>,
|
15 | 19 | instantiated_ty: OpaqueHiddenType<'tcx>,
|
| 20 | + origin: OpaqueTyOrigin, |
16 | 21 | ) -> Ty<'tcx>;
|
17 | 22 | }
|
18 | 23 |
|
@@ -45,6 +50,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
45 | 50 | &self,
|
46 | 51 | opaque_type_key: OpaqueTypeKey<'tcx>,
|
47 | 52 | instantiated_ty: OpaqueHiddenType<'tcx>,
|
| 53 | + origin: OpaqueTyOrigin, |
48 | 54 | ) -> Ty<'tcx> {
|
49 | 55 | if self.is_tainted_by_errors() {
|
50 | 56 | return self.tcx.ty_error();
|
@@ -76,7 +82,69 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
76 | 82 | ));
|
77 | 83 | debug!(?definition_ty);
|
78 | 84 |
|
79 |
| - definition_ty |
| 85 | + // Only check this for TAIT. RPIT already supports `src/test/ui/impl-trait/nested-return-type2.rs` |
| 86 | + // on stable and we'd break that. |
| 87 | + if let OpaqueTyOrigin::TyAlias = origin { |
| 88 | + // This logic duplicates most of `check_opaque_meets_bounds`. |
| 89 | + // FIXME(oli-obk): Also do region checks here and then consider removing `check_opaque_meets_bounds` entirely. |
| 90 | + let param_env = self.tcx.param_env(def_id); |
| 91 | + let body_id = self.tcx.local_def_id_to_hir_id(def_id.as_local().unwrap()); |
| 92 | + self.tcx.infer_ctxt().enter(move |infcx| { |
| 93 | + // Require the hidden type to be well-formed with only the generics of the opaque type. |
| 94 | + // Defining use functions may have more bounds than the opaque type, which is ok, as long as the |
| 95 | + // hidden type is well formed even without those bounds. |
| 96 | + let predicate = |
| 97 | + ty::Binder::dummy(ty::PredicateKind::WellFormed(definition_ty.into())) |
| 98 | + .to_predicate(infcx.tcx); |
| 99 | + let mut fulfillment_cx = <dyn TraitEngine<'tcx>>::new(infcx.tcx); |
| 100 | + |
| 101 | + // Require that the hidden type actually fulfills all the bounds of the opaque type, even without |
| 102 | + // the bounds that the function supplies. |
| 103 | + match infcx.register_hidden_type( |
| 104 | + OpaqueTypeKey { def_id, substs: id_substs }, |
| 105 | + ObligationCause::misc(instantiated_ty.span, body_id), |
| 106 | + param_env, |
| 107 | + definition_ty, |
| 108 | + origin, |
| 109 | + ) { |
| 110 | + Ok(infer_ok) => { |
| 111 | + for obligation in infer_ok.obligations { |
| 112 | + fulfillment_cx.register_predicate_obligation(&infcx, obligation); |
| 113 | + } |
| 114 | + } |
| 115 | + Err(err) => { |
| 116 | + infcx |
| 117 | + .report_mismatched_types( |
| 118 | + &ObligationCause::misc(instantiated_ty.span, body_id), |
| 119 | + self.tcx.mk_opaque(def_id, id_substs), |
| 120 | + definition_ty, |
| 121 | + err, |
| 122 | + ) |
| 123 | + .emit(); |
| 124 | + } |
| 125 | + } |
| 126 | + |
| 127 | + fulfillment_cx.register_predicate_obligation( |
| 128 | + &infcx, |
| 129 | + Obligation::misc(instantiated_ty.span, body_id, param_env, predicate), |
| 130 | + ); |
| 131 | + |
| 132 | + // Check that all obligations are satisfied by the implementation's |
| 133 | + // version. |
| 134 | + let errors = fulfillment_cx.select_all_or_error(&infcx); |
| 135 | + |
| 136 | + let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types(); |
| 137 | + |
| 138 | + if errors.is_empty() { |
| 139 | + definition_ty |
| 140 | + } else { |
| 141 | + infcx.report_fulfillment_errors(&errors, None, false); |
| 142 | + self.tcx.ty_error() |
| 143 | + } |
| 144 | + }) |
| 145 | + } else { |
| 146 | + definition_ty |
| 147 | + } |
80 | 148 | }
|
81 | 149 | }
|
82 | 150 |
|
|
0 commit comments