]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
New upstream version 1.67.1+dfsg1
[rustc.git] / compiler / rustc_borrowck / src / diagnostics / bound_region_errors.rs
CommitLineData
487cf647
FG
1#![deny(rustc::untranslatable_diagnostic)]
2#![deny(rustc::diagnostic_outside_of_impl)]
3
5e7ed085 4use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed};
94222f64
XL
5use rustc_infer::infer::canonical::Canonical;
6use rustc_infer::infer::error_reporting::nice_region_error::NiceRegionError;
7use rustc_infer::infer::region_constraints::Constraint;
5e7ed085
FG
8use rustc_infer::infer::region_constraints::RegionConstraintData;
9use rustc_infer::infer::RegionVariableOrigin;
94222f64 10use rustc_infer::infer::{InferCtxt, RegionResolutionError, SubregionOrigin, TyCtxtInferExt as _};
487cf647 11use rustc_infer::traits::ObligationCause;
94222f64 12use rustc_middle::ty::error::TypeError;
5e7ed085
FG
13use rustc_middle::ty::RegionVid;
14use rustc_middle::ty::UniverseIndex;
94222f64
XL
15use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
16use rustc_span::Span;
17use rustc_trait_selection::traits::query::type_op;
487cf647 18use rustc_trait_selection::traits::ObligationCtxt;
c295e0f8 19use rustc_traits::{type_op_ascribe_user_type_with_span, type_op_prove_predicate_with_cause};
94222f64
XL
20
21use std::fmt;
22use std::rc::Rc;
23
c295e0f8 24use crate::region_infer::values::RegionElement;
064997fb
FG
25use crate::session_diagnostics::HigherRankedErrorCause;
26use crate::session_diagnostics::HigherRankedLifetimeError;
27use crate::session_diagnostics::HigherRankedSubtypeError;
c295e0f8 28use crate::MirBorrowckCtxt;
94222f64
XL
29
30#[derive(Clone)]
923072b8 31pub(crate) struct UniverseInfo<'tcx>(UniverseInfoInner<'tcx>);
94222f64
XL
32
33/// What operation a universe was created for.
34#[derive(Clone)]
35enum UniverseInfoInner<'tcx> {
36 /// Relating two types which have binders.
37 RelateTys { expected: Ty<'tcx>, found: Ty<'tcx> },
38 /// Created from performing a `TypeOp`.
39 TypeOp(Rc<dyn TypeOpInfo<'tcx> + 'tcx>),
40 /// Any other reason.
41 Other,
42}
43
a2a8927a 44impl<'tcx> UniverseInfo<'tcx> {
923072b8 45 pub(crate) fn other() -> UniverseInfo<'tcx> {
94222f64
XL
46 UniverseInfo(UniverseInfoInner::Other)
47 }
48
923072b8 49 pub(crate) fn relate(expected: Ty<'tcx>, found: Ty<'tcx>) -> UniverseInfo<'tcx> {
94222f64
XL
50 UniverseInfo(UniverseInfoInner::RelateTys { expected, found })
51 }
52
923072b8 53 pub(crate) fn report_error(
94222f64
XL
54 &self,
55 mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
56 placeholder: ty::PlaceholderRegion,
57 error_element: RegionElement,
c295e0f8 58 cause: ObligationCause<'tcx>,
94222f64
XL
59 ) {
60 match self.0 {
61 UniverseInfoInner::RelateTys { expected, found } => {
2b03887a 62 let err = mbcx.infcx.err_ctxt().report_mismatched_types(
c295e0f8 63 &cause,
94222f64
XL
64 expected,
65 found,
66 TypeError::RegionsPlaceholderMismatch,
67 );
5099ac24 68 mbcx.buffer_error(err);
94222f64
XL
69 }
70 UniverseInfoInner::TypeOp(ref type_op_info) => {
c295e0f8 71 type_op_info.report_error(mbcx, placeholder, error_element, cause);
94222f64
XL
72 }
73 UniverseInfoInner::Other => {
74 // FIXME: This error message isn't great, but it doesn't show
75 // up in the existing UI tests. Consider investigating this
76 // some more.
5099ac24 77 mbcx.buffer_error(
064997fb 78 mbcx.infcx.tcx.sess.create_err(HigherRankedSubtypeError { span: cause.span }),
5099ac24 79 );
94222f64
XL
80 }
81 }
82 }
83}
84
923072b8 85pub(crate) trait ToUniverseInfo<'tcx> {
94222f64
XL
86 fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx>;
87}
88
5e7ed085
FG
89impl<'tcx> ToUniverseInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> {
90 fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
91 UniverseInfo(UniverseInfoInner::TypeOp(Rc::new(crate::type_check::InstantiateOpaqueType {
92 base_universe: Some(base_universe),
93 ..self
94 })))
95 }
96}
97
94222f64
XL
98impl<'tcx> ToUniverseInfo<'tcx>
99 for Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::prove_predicate::ProvePredicate<'tcx>>>
100{
101 fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
102 UniverseInfo(UniverseInfoInner::TypeOp(Rc::new(PredicateQuery {
103 canonical_query: self,
104 base_universe,
105 })))
106 }
107}
108
109impl<'tcx, T: Copy + fmt::Display + TypeFoldable<'tcx> + 'tcx> ToUniverseInfo<'tcx>
110 for Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>
111{
112 fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
113 UniverseInfo(UniverseInfoInner::TypeOp(Rc::new(NormalizeQuery {
114 canonical_query: self,
115 base_universe,
116 })))
117 }
118}
119
120impl<'tcx> ToUniverseInfo<'tcx>
121 for Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::AscribeUserType<'tcx>>>
122{
123 fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
124 UniverseInfo(UniverseInfoInner::TypeOp(Rc::new(AscribeUserTypeQuery {
125 canonical_query: self,
126 base_universe,
127 })))
128 }
129}
130
131impl<'tcx, F, G> ToUniverseInfo<'tcx> for Canonical<'tcx, type_op::custom::CustomTypeOp<F, G>> {
132 fn to_universe_info(self, _base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
133 // We can't rerun custom type ops.
134 UniverseInfo::other()
135 }
136}
137
5e7ed085
FG
138impl<'tcx> ToUniverseInfo<'tcx> for ! {
139 fn to_universe_info(self, _base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
140 self
141 }
142}
143
94222f64
XL
144#[allow(unused_lifetimes)]
145trait TypeOpInfo<'tcx> {
146 /// Returns an error to be reported if rerunning the type op fails to
147 /// recover the error's cause.
5e7ed085
FG
148 fn fallback_error(
149 &self,
150 tcx: TyCtxt<'tcx>,
151 span: Span,
152 ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
94222f64
XL
153
154 fn base_universe(&self) -> ty::UniverseIndex;
155
156 fn nice_error(
157 &self,
5e7ed085 158 mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
c295e0f8 159 cause: ObligationCause<'tcx>,
94222f64
XL
160 placeholder_region: ty::Region<'tcx>,
161 error_region: Option<ty::Region<'tcx>>,
5e7ed085 162 ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>>;
94222f64 163
487cf647 164 #[instrument(level = "debug", skip(self, mbcx))]
94222f64
XL
165 fn report_error(
166 &self,
167 mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
168 placeholder: ty::PlaceholderRegion,
169 error_element: RegionElement,
c295e0f8 170 cause: ObligationCause<'tcx>,
94222f64
XL
171 ) {
172 let tcx = mbcx.infcx.tcx;
173 let base_universe = self.base_universe();
487cf647 174 debug!(?base_universe);
94222f64 175
5099ac24 176 let Some(adjusted_universe) =
94222f64 177 placeholder.universe.as_u32().checked_sub(base_universe.as_u32())
5099ac24
FG
178 else {
179 mbcx.buffer_error(self.fallback_error(tcx, cause.span));
94222f64
XL
180 return;
181 };
182
183 let placeholder_region = tcx.mk_region(ty::RePlaceholder(ty::Placeholder {
184 name: placeholder.name,
185 universe: adjusted_universe.into(),
186 }));
187
188 let error_region =
189 if let RegionElement::PlaceholderRegion(error_placeholder) = error_element {
190 let adjusted_universe =
191 error_placeholder.universe.as_u32().checked_sub(base_universe.as_u32());
192 adjusted_universe.map(|adjusted| {
193 tcx.mk_region(ty::RePlaceholder(ty::Placeholder {
194 name: error_placeholder.name,
195 universe: adjusted.into(),
196 }))
197 })
198 } else {
199 None
200 };
201
202 debug!(?placeholder_region);
203
c295e0f8 204 let span = cause.span;
5e7ed085 205 let nice_error = self.nice_error(mbcx, cause, placeholder_region, error_region);
94222f64
XL
206
207 if let Some(nice_error) = nice_error {
5099ac24 208 mbcx.buffer_error(nice_error);
94222f64 209 } else {
5099ac24 210 mbcx.buffer_error(self.fallback_error(tcx, span));
94222f64
XL
211 }
212 }
213}
214
215struct PredicateQuery<'tcx> {
216 canonical_query:
217 Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::prove_predicate::ProvePredicate<'tcx>>>,
218 base_universe: ty::UniverseIndex,
219}
220
a2a8927a 221impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> {
5e7ed085
FG
222 fn fallback_error(
223 &self,
224 tcx: TyCtxt<'tcx>,
225 span: Span,
226 ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
064997fb
FG
227 tcx.sess.create_err(HigherRankedLifetimeError {
228 cause: Some(HigherRankedErrorCause::CouldNotProve {
229 predicate: self.canonical_query.value.value.predicate.to_string(),
230 }),
231 span,
232 })
94222f64
XL
233 }
234
235 fn base_universe(&self) -> ty::UniverseIndex {
236 self.base_universe
237 }
238
239 fn nice_error(
240 &self,
5e7ed085 241 mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
c295e0f8 242 cause: ObligationCause<'tcx>,
94222f64
XL
243 placeholder_region: ty::Region<'tcx>,
244 error_region: Option<ty::Region<'tcx>>,
5e7ed085 245 ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
487cf647 246 let (infcx, key, _) =
2b03887a 247 mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
487cf647
FG
248 let ocx = ObligationCtxt::new(&infcx);
249 type_op_prove_predicate_with_cause(&ocx, key, cause);
250 try_extract_error_from_fulfill_cx(&ocx, placeholder_region, error_region)
94222f64
XL
251 }
252}
253
254struct NormalizeQuery<'tcx, T> {
255 canonical_query: Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>,
256 base_universe: ty::UniverseIndex,
257}
258
a2a8927a 259impl<'tcx, T> TypeOpInfo<'tcx> for NormalizeQuery<'tcx, T>
94222f64
XL
260where
261 T: Copy + fmt::Display + TypeFoldable<'tcx> + 'tcx,
262{
5e7ed085
FG
263 fn fallback_error(
264 &self,
265 tcx: TyCtxt<'tcx>,
266 span: Span,
267 ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
064997fb
FG
268 tcx.sess.create_err(HigherRankedLifetimeError {
269 cause: Some(HigherRankedErrorCause::CouldNotNormalize {
270 value: self.canonical_query.value.value.value.to_string(),
271 }),
272 span,
273 })
94222f64
XL
274 }
275
276 fn base_universe(&self) -> ty::UniverseIndex {
277 self.base_universe
278 }
279
280 fn nice_error(
281 &self,
5e7ed085 282 mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
c295e0f8 283 cause: ObligationCause<'tcx>,
94222f64
XL
284 placeholder_region: ty::Region<'tcx>,
285 error_region: Option<ty::Region<'tcx>>,
5e7ed085 286 ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
487cf647 287 let (infcx, key, _) =
2b03887a 288 mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
487cf647 289 let ocx = ObligationCtxt::new(&infcx);
2b03887a
FG
290
291 // FIXME(lqd): Unify and de-duplicate the following with the actual
292 // `rustc_traits::type_op::type_op_normalize` query to allow the span we need in the
293 // `ObligationCause`. The normalization results are currently different between
487cf647
FG
294 // `QueryNormalizeExt::query_normalize` used in the query and `normalize` called below:
295 // the former fails to normalize the `nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs` test.
296 // Check after #85499 lands to see if its fixes have erased this difference.
2b03887a 297 let (param_env, value) = key.into_parts();
487cf647 298 let _ = ocx.normalize(&cause, param_env, value.value);
2b03887a 299
487cf647 300 try_extract_error_from_fulfill_cx(&ocx, placeholder_region, error_region)
94222f64
XL
301 }
302}
303
304struct AscribeUserTypeQuery<'tcx> {
305 canonical_query: Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::AscribeUserType<'tcx>>>,
306 base_universe: ty::UniverseIndex,
307}
308
a2a8927a 309impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> {
5e7ed085
FG
310 fn fallback_error(
311 &self,
312 tcx: TyCtxt<'tcx>,
313 span: Span,
314 ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
94222f64
XL
315 // FIXME: This error message isn't great, but it doesn't show up in the existing UI tests,
316 // and is only the fallback when the nice error fails. Consider improving this some more.
064997fb 317 tcx.sess.create_err(HigherRankedLifetimeError { cause: None, span })
94222f64
XL
318 }
319
320 fn base_universe(&self) -> ty::UniverseIndex {
321 self.base_universe
322 }
323
324 fn nice_error(
325 &self,
5e7ed085 326 mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
c295e0f8 327 cause: ObligationCause<'tcx>,
94222f64
XL
328 placeholder_region: ty::Region<'tcx>,
329 error_region: Option<ty::Region<'tcx>>,
5e7ed085 330 ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
487cf647 331 let (infcx, key, _) =
2b03887a 332 mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
487cf647
FG
333 let ocx = ObligationCtxt::new(&infcx);
334 type_op_ascribe_user_type_with_span(&ocx, key, Some(cause.span)).ok()?;
335 try_extract_error_from_fulfill_cx(&ocx, placeholder_region, error_region)
94222f64
XL
336 }
337}
338
5e7ed085
FG
339impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> {
340 fn fallback_error(
341 &self,
342 tcx: TyCtxt<'tcx>,
343 span: Span,
344 ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
345 // FIXME: This error message isn't great, but it doesn't show up in the existing UI tests,
346 // and is only the fallback when the nice error fails. Consider improving this some more.
064997fb 347 tcx.sess.create_err(HigherRankedLifetimeError { cause: None, span })
5e7ed085
FG
348 }
349
350 fn base_universe(&self) -> ty::UniverseIndex {
351 self.base_universe.unwrap()
352 }
353
354 fn nice_error(
355 &self,
356 mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
357 _cause: ObligationCause<'tcx>,
358 placeholder_region: ty::Region<'tcx>,
359 error_region: Option<ty::Region<'tcx>>,
360 ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
361 try_extract_error_from_region_constraints(
362 mbcx.infcx,
363 placeholder_region,
364 error_region,
365 self.region_constraints.as_ref().unwrap(),
366 // We're using the original `InferCtxt` that we
367 // started MIR borrowchecking with, so the region
368 // constraints have already been taken. Use the data from
369 // our `mbcx` instead.
370 |vid| mbcx.regioncx.var_infos[vid].origin,
371 |vid| mbcx.regioncx.var_infos[vid].universe,
372 )
373 }
374}
375
487cf647 376#[instrument(skip(ocx), level = "debug")]
94222f64 377fn try_extract_error_from_fulfill_cx<'tcx>(
487cf647 378 ocx: &ObligationCtxt<'_, 'tcx>,
94222f64
XL
379 placeholder_region: ty::Region<'tcx>,
380 error_region: Option<ty::Region<'tcx>>,
5e7ed085 381) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
94222f64
XL
382 // We generally shouldn't have errors here because the query was
383 // already run, but there's no point using `delay_span_bug`
384 // when we're going to emit an error here anyway.
487cf647
FG
385 let _errors = ocx.select_all_or_error();
386 let region_constraints = ocx.infcx.with_region_constraints(|r| r.clone());
5e7ed085 387 try_extract_error_from_region_constraints(
487cf647 388 ocx.infcx,
5e7ed085
FG
389 placeholder_region,
390 error_region,
391 &region_constraints,
487cf647
FG
392 |vid| ocx.infcx.region_var_origin(vid),
393 |vid| ocx.infcx.universe_of_region(ocx.infcx.tcx.mk_region(ty::ReVar(vid))),
5e7ed085
FG
394 )
395}
94222f64 396
487cf647 397#[instrument(level = "debug", skip(infcx, region_var_origin, universe_of_region))]
5e7ed085 398fn try_extract_error_from_region_constraints<'tcx>(
2b03887a 399 infcx: &InferCtxt<'tcx>,
5e7ed085
FG
400 placeholder_region: ty::Region<'tcx>,
401 error_region: Option<ty::Region<'tcx>>,
402 region_constraints: &RegionConstraintData<'tcx>,
403 mut region_var_origin: impl FnMut(RegionVid) -> RegionVariableOrigin,
404 mut universe_of_region: impl FnMut(RegionVid) -> UniverseIndex,
405) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
406 let (sub_region, cause) =
94222f64
XL
407 region_constraints.constraints.iter().find_map(|(constraint, cause)| {
408 match *constraint {
409 Constraint::RegSubReg(sub, sup) if sup == placeholder_region && sup != sub => {
410 Some((sub, cause.clone()))
411 }
412 // FIXME: Should this check the universe of the var?
413 Constraint::VarSubReg(vid, sup) if sup == placeholder_region => {
5e7ed085 414 Some((infcx.tcx.mk_region(ty::ReVar(vid)), cause.clone()))
94222f64
XL
415 }
416 _ => None,
417 }
5e7ed085 418 })?;
94222f64 419
c295e0f8 420 debug!(?sub_region, "cause = {:#?}", cause);
2b03887a
FG
421 let error = match (error_region, *sub_region) {
422 (Some(error_region), ty::ReVar(vid)) => RegionResolutionError::SubSupConflict(
423 vid,
424 region_var_origin(vid),
425 cause.clone(),
426 error_region,
427 cause.clone(),
428 placeholder_region,
429 vec![],
94222f64 430 ),
2b03887a
FG
431 (Some(error_region), _) => {
432 RegionResolutionError::ConcreteFailure(cause.clone(), error_region, placeholder_region)
433 }
94222f64 434 // Note universe here is wrong...
2b03887a
FG
435 (None, ty::ReVar(vid)) => RegionResolutionError::UpperBoundUniverseConflict(
436 vid,
437 region_var_origin(vid),
438 universe_of_region(vid),
439 cause.clone(),
440 placeholder_region,
94222f64 441 ),
2b03887a
FG
442 (None, _) => {
443 RegionResolutionError::ConcreteFailure(cause.clone(), sub_region, placeholder_region)
444 }
94222f64 445 };
2b03887a 446 NiceRegionError::new(&infcx.err_ctxt(), error).try_report_from_nll().or_else(|| {
94222f64 447 if let SubregionOrigin::Subtype(trace) = cause {
2b03887a
FG
448 Some(
449 infcx
450 .err_ctxt()
451 .report_and_explain_type_error(*trace, TypeError::RegionsPlaceholderMismatch),
452 )
94222f64
XL
453 } else {
454 None
455 }
456 })
457}