rustc_hir_typeck/
opaque_types.rs1use 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 if let Some(guar) = self.tainted_by_errors() {
121 guar
122 } else {
123 let infer_var = hidden_type
124 .ty
125 .walk()
126 .filter_map(ty::GenericArg::as_term)
127 .find(|term| term.is_infer())
128 .unwrap_or_else(|| hidden_type.ty.into());
129 self.err_ctxt()
130 .emit_inference_failure_err(
131 self.body_id,
132 hidden_type.span,
133 infer_var,
134 TypeAnnotationNeeded::E0282,
135 false,
136 )
137 .emit()
138 }
139 }
140 UsageKind::HasDefiningUse => continue,
141 };
142
143 self.typeck_results
144 .borrow_mut()
145 .concrete_opaque_types
146 .insert(def_id, OpaqueHiddenType::new_error(tcx, guar));
147 self.set_tainted_by_errors(guar);
148 }
149 }
150
151 fn consider_opaque_type_use(
152 &mut self,
153 opaque_type_key: OpaqueTypeKey<'tcx>,
154 hidden_type: OpaqueHiddenType<'tcx>,
155 ) -> UsageKind<'tcx> {
156 if let Err(err) = opaque_type_has_defining_use_args(
157 &self,
158 opaque_type_key,
159 hidden_type.span,
160 DefiningScopeKind::HirTypeck,
161 ) {
162 match err {
163 NonDefiningUseReason::Tainted(guar) => {
164 self.typeck_results.borrow_mut().concrete_opaque_types.insert(
165 opaque_type_key.def_id,
166 OpaqueHiddenType::new_error(self.tcx, guar),
167 );
168 return UsageKind::HasDefiningUse;
169 }
170 _ => return UsageKind::NonDefiningUse(opaque_type_key, hidden_type),
171 };
172 }
173
174 if hidden_type.ty.has_non_region_infer() {
179 return UsageKind::UnconstrainedHiddenType(hidden_type);
180 }
181
182 let cause = ObligationCause::misc(hidden_type.span, self.body_id);
183 let at = self.at(&cause, self.param_env);
184 let hidden_type = match solve::deeply_normalize(at, hidden_type) {
185 Ok(hidden_type) => hidden_type,
186 Err(errors) => {
187 let guar = self.err_ctxt().report_fulfillment_errors(errors);
188 OpaqueHiddenType::new_error(self.tcx, guar)
189 }
190 };
191 let hidden_type = hidden_type.remap_generic_params_to_declaration_params(
192 opaque_type_key,
193 self.tcx,
194 DefiningScopeKind::HirTypeck,
195 );
196
197 let prev = self
198 .typeck_results
199 .borrow_mut()
200 .concrete_opaque_types
201 .insert(opaque_type_key.def_id, hidden_type);
202 assert!(prev.is_none());
203 UsageKind::HasDefiningUse
204 }
205
206 fn apply_computed_concrete_opaque_types(
207 &mut self,
208 opaque_types: &[(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)],
209 ) {
210 let tcx = self.tcx;
211 for &(key, hidden_type) in opaque_types {
212 let expected =
213 *self.typeck_results.borrow_mut().concrete_opaque_types.get(&key.def_id).unwrap();
214
215 let expected = EarlyBinder::bind(expected.ty).instantiate(tcx, key.args);
216 self.demand_eqtype(hidden_type.span, expected, hidden_type.ty);
217 }
218 }
219
220 pub(super) fn detect_opaque_types_added_during_writeback(&self) {
233 let num_entries = self.checked_opaque_types_storage_entries.take().unwrap();
234 for (key, hidden_type) in
235 self.inner.borrow_mut().opaque_types().opaque_types_added_since(num_entries)
236 {
237 let opaque_type_string = self.tcx.def_path_str(key.def_id);
238 let msg = format!("unexpected cyclic definition of `{opaque_type_string}`");
239 self.dcx().span_delayed_bug(hidden_type.span, msg);
240 }
241 let _ = self.take_opaque_types();
242 }
243}