1use rustc_hir::def::DefKind;
2use rustc_infer::traits::ObligationCause;
3use rustc_middle::ty::{
4 self, DefiningScopeKind, EarlyBinder, OpaqueHiddenType, OpaqueTypeKey, TypeVisitableExt,
5 TypingMode,
6};
7use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded;
8use rustc_trait_selection::opaque_types::{
9 NonDefiningUseReason, opaque_type_has_defining_use_args, report_item_does_not_constrain_error,
10};
11use rustc_trait_selection::solve;
12use tracing::{debug, instrument};
13
14use crate::FnCtxt;
15
16impl<'tcx> FnCtxt<'_, 'tcx> {
17 #[instrument(level = "debug", skip(self))]
28 pub(super) fn try_handle_opaque_type_uses_next(&mut self) {
29 let opaque_types: Vec<_> = self.infcx.clone_opaque_types();
32
33 self.compute_definition_site_hidden_types(opaque_types, false);
34 }
35
36 #[instrument(level = "debug", skip(self))]
45 pub(super) fn handle_opaque_type_uses_next(&mut self) {
46 let opaque_types: Vec<_> = self.infcx.clone_opaque_types();
49 let num_entries = self.inner.borrow_mut().opaque_types().num_entries();
50 let prev = self.checked_opaque_types_storage_entries.replace(Some(num_entries));
51 debug_assert_eq!(prev, None);
52
53 self.compute_definition_site_hidden_types(opaque_types, true);
54 }
55}
56
57#[derive(Copy, Clone, Debug)]
58enum UsageKind<'tcx> {
59 None,
60 NonDefiningUse(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>),
61 UnconstrainedHiddenType(OpaqueHiddenType<'tcx>),
62 HasDefiningUse(OpaqueHiddenType<'tcx>),
63}
64
65impl<'tcx> UsageKind<'tcx> {
66 fn merge(&mut self, other: UsageKind<'tcx>) {
67 match (&*self, &other) {
68 (UsageKind::HasDefiningUse(_), _) | (_, UsageKind::None) => unreachable!(),
69 (UsageKind::None, _) => *self = other,
70 (
73 UsageKind::NonDefiningUse(..) | UsageKind::UnconstrainedHiddenType(..),
74 UsageKind::NonDefiningUse(..),
75 ) => {}
76 (
81 UsageKind::NonDefiningUse(..) | UsageKind::UnconstrainedHiddenType(..),
82 UsageKind::UnconstrainedHiddenType(..) | UsageKind::HasDefiningUse(_),
83 ) => *self = other,
84 }
85 }
86}
87
88impl<'tcx> FnCtxt<'_, 'tcx> {
89 fn compute_definition_site_hidden_types(
90 &mut self,
91 mut opaque_types: Vec<(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)>,
92 error_on_missing_defining_use: bool,
93 ) {
94 for entry in opaque_types.iter_mut() {
95 *entry = self.resolve_vars_if_possible(*entry);
96 }
97 debug!(?opaque_types);
98
99 let tcx = self.tcx;
100 let TypingMode::Analysis { defining_opaque_types_and_generators } = self.typing_mode()
101 else {
102 unreachable!();
103 };
104
105 for def_id in defining_opaque_types_and_generators {
106 match tcx.def_kind(def_id) {
107 DefKind::OpaqueTy => {}
108 DefKind::Closure => continue,
109 _ => unreachable!("not opaque or generator: {def_id:?}"),
110 }
111
112 let mut usage_kind = UsageKind::None;
116 for &(opaque_type_key, hidden_type) in &opaque_types {
117 if opaque_type_key.def_id != def_id {
118 continue;
119 }
120
121 usage_kind.merge(self.consider_opaque_type_use(opaque_type_key, hidden_type));
122
123 if let UsageKind::HasDefiningUse(..) = usage_kind {
124 break;
125 }
126 }
127
128 if let UsageKind::HasDefiningUse(ty) = usage_kind {
129 for &(opaque_type_key, hidden_type) in &opaque_types {
130 if opaque_type_key.def_id != def_id {
131 continue;
132 }
133
134 let expected = EarlyBinder::bind(ty.ty).instantiate(tcx, opaque_type_key.args);
135 self.demand_eqtype(hidden_type.span, expected, hidden_type.ty);
136 }
137
138 let _ = self.typeck_results.borrow_mut().hidden_types.insert(def_id, ty);
143 }
144
145 if !error_on_missing_defining_use {
148 continue;
149 }
150
151 let guar = match usage_kind {
152 UsageKind::HasDefiningUse(_) => continue,
153 UsageKind::None => {
154 if let Some(guar) = self.tainted_by_errors() {
155 guar
156 } else {
157 report_item_does_not_constrain_error(self.tcx, self.body_id, def_id, None)
158 }
159 }
160 UsageKind::NonDefiningUse(opaque_type_key, hidden_type) => {
161 report_item_does_not_constrain_error(
162 self.tcx,
163 self.body_id,
164 def_id,
165 Some((opaque_type_key, hidden_type.span)),
166 )
167 }
168 UsageKind::UnconstrainedHiddenType(hidden_type) => {
169 if let Some(guar) = self.tainted_by_errors() {
170 guar
171 } else {
172 let infer_var = hidden_type
173 .ty
174 .walk()
175 .filter_map(ty::GenericArg::as_term)
176 .find(|term| term.is_infer())
177 .unwrap_or_else(|| hidden_type.ty.into());
178 self.err_ctxt()
179 .emit_inference_failure_err(
180 self.body_id,
181 hidden_type.span,
182 infer_var,
183 TypeAnnotationNeeded::E0282,
184 false,
185 )
186 .emit()
187 }
188 }
189 };
190
191 self.typeck_results
192 .borrow_mut()
193 .hidden_types
194 .insert(def_id, OpaqueHiddenType::new_error(tcx, guar));
195 self.set_tainted_by_errors(guar);
196 }
197 }
198
199 #[tracing::instrument(skip(self), ret)]
200 fn consider_opaque_type_use(
201 &self,
202 opaque_type_key: OpaqueTypeKey<'tcx>,
203 hidden_type: OpaqueHiddenType<'tcx>,
204 ) -> UsageKind<'tcx> {
205 if let Err(err) = opaque_type_has_defining_use_args(
206 &self,
207 opaque_type_key,
208 hidden_type.span,
209 DefiningScopeKind::HirTypeck,
210 ) {
211 match err {
212 NonDefiningUseReason::Tainted(guar) => {
213 return UsageKind::HasDefiningUse(OpaqueHiddenType::new_error(self.tcx, guar));
214 }
215 _ => return UsageKind::NonDefiningUse(opaque_type_key, hidden_type),
216 };
217 }
218
219 if hidden_type.ty.has_non_region_infer() {
224 return UsageKind::UnconstrainedHiddenType(hidden_type);
225 }
226
227 let cause = ObligationCause::misc(hidden_type.span, self.body_id);
228 let at = self.at(&cause, self.param_env);
229 let hidden_type = match solve::deeply_normalize(at, hidden_type) {
230 Ok(hidden_type) => hidden_type,
231 Err(errors) => {
232 let guar = self.err_ctxt().report_fulfillment_errors(errors);
233 OpaqueHiddenType::new_error(self.tcx, guar)
234 }
235 };
236 let hidden_type = hidden_type.remap_generic_params_to_declaration_params(
237 opaque_type_key,
238 self.tcx,
239 DefiningScopeKind::HirTypeck,
240 );
241 UsageKind::HasDefiningUse(hidden_type)
242 }
243
244 pub(super) fn detect_opaque_types_added_during_writeback(&self) {
257 let num_entries = self.checked_opaque_types_storage_entries.take().unwrap();
258 for (key, hidden_type) in
259 self.inner.borrow_mut().opaque_types().opaque_types_added_since(num_entries)
260 {
261 let opaque_type_string = self.tcx.def_path_str(key.def_id);
262 let msg = format!("unexpected cyclic definition of `{opaque_type_string}`");
263 self.dcx().span_delayed_bug(hidden_type.span, msg);
264 }
265 let _ = self.take_opaque_types();
266 }
267}