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))]
26 pub(super) fn handle_opaque_type_uses_next(&mut self) {
27 let mut opaque_types: Vec<_> = self.infcx.clone_opaque_types();
30 let num_entries = self.inner.borrow_mut().opaque_types().num_entries();
31 let prev = self.checked_opaque_types_storage_entries.replace(Some(num_entries));
32 debug_assert_eq!(prev, None);
33 for entry in &mut opaque_types {
34 *entry = self.resolve_vars_if_possible(*entry);
35 }
36 debug!(?opaque_types);
37
38 self.compute_concrete_opaque_types(&opaque_types);
39 self.apply_computed_concrete_opaque_types(&opaque_types);
40 }
41}
42
43enum UsageKind<'tcx> {
44 None,
45 NonDefiningUse(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>),
46 UnconstrainedHiddenType(OpaqueHiddenType<'tcx>),
47 HasDefiningUse,
48}
49
50impl<'tcx> UsageKind<'tcx> {
51 fn merge(&mut self, other: UsageKind<'tcx>) {
52 match (&*self, &other) {
53 (UsageKind::HasDefiningUse, _) | (_, UsageKind::None) => unreachable!(),
54 (UsageKind::None, _) => *self = other,
55 (
58 UsageKind::NonDefiningUse(..) | UsageKind::UnconstrainedHiddenType(..),
59 UsageKind::NonDefiningUse(..),
60 ) => {}
61 (
66 UsageKind::NonDefiningUse(..) | UsageKind::UnconstrainedHiddenType(..),
67 UsageKind::UnconstrainedHiddenType(..) | UsageKind::HasDefiningUse,
68 ) => *self = other,
69 }
70 }
71}
72
73impl<'tcx> FnCtxt<'_, 'tcx> {
74 fn compute_concrete_opaque_types(
75 &mut self,
76 opaque_types: &[(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)],
77 ) {
78 let tcx = self.tcx;
79 let TypingMode::Analysis { defining_opaque_types_and_generators } = self.typing_mode()
80 else {
81 unreachable!();
82 };
83
84 for def_id in defining_opaque_types_and_generators {
85 match tcx.def_kind(def_id) {
86 DefKind::OpaqueTy => {}
87 DefKind::Closure => continue,
88 _ => unreachable!("not opaque or generator: {def_id:?}"),
89 }
90
91 let mut usage_kind = UsageKind::None;
92 for &(opaque_type_key, hidden_type) in opaque_types {
93 if opaque_type_key.def_id != def_id {
94 continue;
95 }
96
97 usage_kind.merge(self.consider_opaque_type_use(opaque_type_key, hidden_type));
98 if let UsageKind::HasDefiningUse = usage_kind {
99 break;
100 }
101 }
102
103 let guar = match usage_kind {
104 UsageKind::None => {
105 if let Some(guar) = self.tainted_by_errors() {
106 guar
107 } else {
108 report_item_does_not_constrain_error(self.tcx, self.body_id, def_id, None)
109 }
110 }
111 UsageKind::NonDefiningUse(opaque_type_key, hidden_type) => {
112 report_item_does_not_constrain_error(
113 self.tcx,
114 self.body_id,
115 def_id,
116 Some((opaque_type_key, hidden_type.span)),
117 )
118 }
119 UsageKind::UnconstrainedHiddenType(hidden_type) => {
120 let infer_var = hidden_type
121 .ty
122 .walk()
123 .filter_map(ty::GenericArg::as_term)
124 .find(|term| term.is_infer())
125 .unwrap_or_else(|| hidden_type.ty.into());
126 self.err_ctxt()
127 .emit_inference_failure_err(
128 self.body_id,
129 hidden_type.span,
130 infer_var,
131 TypeAnnotationNeeded::E0282,
132 false,
133 )
134 .emit()
135 }
136 UsageKind::HasDefiningUse => continue,
137 };
138
139 self.typeck_results
140 .borrow_mut()
141 .concrete_opaque_types
142 .insert(def_id, OpaqueHiddenType::new_error(tcx, guar));
143 self.set_tainted_by_errors(guar);
144 }
145 }
146
147 fn consider_opaque_type_use(
148 &mut self,
149 opaque_type_key: OpaqueTypeKey<'tcx>,
150 hidden_type: OpaqueHiddenType<'tcx>,
151 ) -> UsageKind<'tcx> {
152 if let Err(err) = opaque_type_has_defining_use_args(
153 &self,
154 opaque_type_key,
155 hidden_type.span,
156 DefiningScopeKind::HirTypeck,
157 ) {
158 match err {
159 NonDefiningUseReason::Tainted(guar) => {
160 self.typeck_results.borrow_mut().concrete_opaque_types.insert(
161 opaque_type_key.def_id,
162 OpaqueHiddenType::new_error(self.tcx, guar),
163 );
164 return UsageKind::HasDefiningUse;
165 }
166 _ => return UsageKind::NonDefiningUse(opaque_type_key, hidden_type),
167 };
168 }
169
170 if hidden_type.ty.has_non_region_infer() {
175 return UsageKind::UnconstrainedHiddenType(hidden_type);
176 }
177
178 let cause = ObligationCause::misc(hidden_type.span, self.body_id);
179 let at = self.at(&cause, self.param_env);
180 let hidden_type = match solve::deeply_normalize(at, hidden_type) {
181 Ok(hidden_type) => hidden_type,
182 Err(errors) => {
183 let guar = self.err_ctxt().report_fulfillment_errors(errors);
184 OpaqueHiddenType::new_error(self.tcx, guar)
185 }
186 };
187 let hidden_type = hidden_type.remap_generic_params_to_declaration_params(
188 opaque_type_key,
189 self.tcx,
190 DefiningScopeKind::HirTypeck,
191 );
192
193 let prev = self
194 .typeck_results
195 .borrow_mut()
196 .concrete_opaque_types
197 .insert(opaque_type_key.def_id, hidden_type);
198 assert!(prev.is_none());
199 UsageKind::HasDefiningUse
200 }
201
202 fn apply_computed_concrete_opaque_types(
203 &mut self,
204 opaque_types: &[(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)],
205 ) {
206 let tcx = self.tcx;
207 for &(key, hidden_type) in opaque_types {
208 let expected =
209 *self.typeck_results.borrow_mut().concrete_opaque_types.get(&key.def_id).unwrap();
210
211 let expected = EarlyBinder::bind(expected.ty).instantiate(tcx, key.args);
212 self.demand_eqtype(hidden_type.span, expected, hidden_type.ty);
213 }
214 }
215
216 pub(super) fn detect_opaque_types_added_during_writeback(&self) {
229 let num_entries = self.checked_opaque_types_storage_entries.take().unwrap();
230 for (key, hidden_type) in
231 self.inner.borrow_mut().opaque_types().opaque_types_added_since(num_entries)
232 {
233 let opaque_type_string = self.tcx.def_path_str(key.def_id);
234 let msg = format!("unexpected cyclic definition of `{opaque_type_string}`");
235 self.dcx().span_delayed_bug(hidden_type.span, msg);
236 }
237 let _ = self.take_opaque_types();
238 }
239}