1 use rustc_errors
::{DiagnosticBuilder, ErrorGuaranteed}
;
2 use rustc_infer
::infer
::canonical
::Canonical
;
3 use rustc_infer
::infer
::error_reporting
::nice_region_error
::NiceRegionError
;
4 use rustc_infer
::infer
::region_constraints
::Constraint
;
5 use rustc_infer
::infer
::region_constraints
::RegionConstraintData
;
6 use rustc_infer
::infer
::RegionVariableOrigin
;
7 use rustc_infer
::infer
::{InferCtxt, RegionResolutionError, SubregionOrigin, TyCtxtInferExt as _}
;
8 use rustc_infer
::traits
::{Normalized, ObligationCause, TraitEngine, TraitEngineExt}
;
9 use rustc_middle
::ty
::error
::TypeError
;
10 use rustc_middle
::ty
::RegionVid
;
11 use rustc_middle
::ty
::UniverseIndex
;
12 use rustc_middle
::ty
::{self, Ty, TyCtxt, TypeFoldable}
;
14 use rustc_trait_selection
::traits
::query
::type_op
;
15 use rustc_trait_selection
::traits
::{SelectionContext, TraitEngineExt as _}
;
16 use rustc_traits
::{type_op_ascribe_user_type_with_span, type_op_prove_predicate_with_cause}
;
21 use crate::region_infer
::values
::RegionElement
;
22 use crate::MirBorrowckCtxt
;
25 crate struct UniverseInfo
<'tcx
>(UniverseInfoInner
<'tcx
>);
27 /// What operation a universe was created for.
29 enum UniverseInfoInner
<'tcx
> {
30 /// Relating two types which have binders.
31 RelateTys { expected: Ty<'tcx>, found: Ty<'tcx> }
,
32 /// Created from performing a `TypeOp`.
33 TypeOp(Rc
<dyn TypeOpInfo
<'tcx
> + 'tcx
>),
38 impl<'tcx
> UniverseInfo
<'tcx
> {
39 crate fn other() -> UniverseInfo
<'tcx
> {
40 UniverseInfo(UniverseInfoInner
::Other
)
43 crate fn relate(expected
: Ty
<'tcx
>, found
: Ty
<'tcx
>) -> UniverseInfo
<'tcx
> {
44 UniverseInfo(UniverseInfoInner
::RelateTys { expected, found }
)
47 crate fn report_error(
49 mbcx
: &mut MirBorrowckCtxt
<'_
, 'tcx
>,
50 placeholder
: ty
::PlaceholderRegion
,
51 error_element
: RegionElement
,
52 cause
: ObligationCause
<'tcx
>,
55 UniverseInfoInner
::RelateTys { expected, found }
=> {
56 let err
= mbcx
.infcx
.report_mismatched_types(
60 TypeError
::RegionsPlaceholderMismatch
,
62 mbcx
.buffer_error(err
);
64 UniverseInfoInner
::TypeOp(ref type_op_info
) => {
65 type_op_info
.report_error(mbcx
, placeholder
, error_element
, cause
);
67 UniverseInfoInner
::Other
=> {
68 // FIXME: This error message isn't great, but it doesn't show
69 // up in the existing UI tests. Consider investigating this
72 mbcx
.infcx
.tcx
.sess
.struct_span_err(cause
.span
, "higher-ranked subtype error"),
79 crate trait ToUniverseInfo
<'tcx
> {
80 fn to_universe_info(self, base_universe
: ty
::UniverseIndex
) -> UniverseInfo
<'tcx
>;
83 impl<'tcx
> ToUniverseInfo
<'tcx
> for crate::type_check
::InstantiateOpaqueType
<'tcx
> {
84 fn to_universe_info(self, base_universe
: ty
::UniverseIndex
) -> UniverseInfo
<'tcx
> {
85 UniverseInfo(UniverseInfoInner
::TypeOp(Rc
::new(crate::type_check
::InstantiateOpaqueType
{
86 base_universe
: Some(base_universe
),
92 impl<'tcx
> ToUniverseInfo
<'tcx
>
93 for Canonical
<'tcx
, ty
::ParamEnvAnd
<'tcx
, type_op
::prove_predicate
::ProvePredicate
<'tcx
>>>
95 fn to_universe_info(self, base_universe
: ty
::UniverseIndex
) -> UniverseInfo
<'tcx
> {
96 UniverseInfo(UniverseInfoInner
::TypeOp(Rc
::new(PredicateQuery
{
97 canonical_query
: self,
103 impl<'tcx
, T
: Copy
+ fmt
::Display
+ TypeFoldable
<'tcx
> + 'tcx
> ToUniverseInfo
<'tcx
>
104 for Canonical
<'tcx
, ty
::ParamEnvAnd
<'tcx
, type_op
::Normalize
<T
>>>
106 fn to_universe_info(self, base_universe
: ty
::UniverseIndex
) -> UniverseInfo
<'tcx
> {
107 UniverseInfo(UniverseInfoInner
::TypeOp(Rc
::new(NormalizeQuery
{
108 canonical_query
: self,
114 impl<'tcx
> ToUniverseInfo
<'tcx
>
115 for Canonical
<'tcx
, ty
::ParamEnvAnd
<'tcx
, type_op
::AscribeUserType
<'tcx
>>>
117 fn to_universe_info(self, base_universe
: ty
::UniverseIndex
) -> UniverseInfo
<'tcx
> {
118 UniverseInfo(UniverseInfoInner
::TypeOp(Rc
::new(AscribeUserTypeQuery
{
119 canonical_query
: self,
125 impl<'tcx
, F
, G
> ToUniverseInfo
<'tcx
> for Canonical
<'tcx
, type_op
::custom
::CustomTypeOp
<F
, G
>> {
126 fn to_universe_info(self, _base_universe
: ty
::UniverseIndex
) -> UniverseInfo
<'tcx
> {
127 // We can't rerun custom type ops.
128 UniverseInfo
::other()
132 impl<'tcx
> ToUniverseInfo
<'tcx
> for ! {
133 fn to_universe_info(self, _base_universe
: ty
::UniverseIndex
) -> UniverseInfo
<'tcx
> {
138 #[allow(unused_lifetimes)]
139 trait TypeOpInfo
<'tcx
> {
140 /// Returns an error to be reported if rerunning the type op fails to
141 /// recover the error's cause.
146 ) -> DiagnosticBuilder
<'tcx
, ErrorGuaranteed
>;
148 fn base_universe(&self) -> ty
::UniverseIndex
;
152 mbcx
: &mut MirBorrowckCtxt
<'_
, 'tcx
>,
153 cause
: ObligationCause
<'tcx
>,
154 placeholder_region
: ty
::Region
<'tcx
>,
155 error_region
: Option
<ty
::Region
<'tcx
>>,
156 ) -> Option
<DiagnosticBuilder
<'tcx
, ErrorGuaranteed
>>;
160 mbcx
: &mut MirBorrowckCtxt
<'_
, 'tcx
>,
161 placeholder
: ty
::PlaceholderRegion
,
162 error_element
: RegionElement
,
163 cause
: ObligationCause
<'tcx
>,
165 let tcx
= mbcx
.infcx
.tcx
;
166 let base_universe
= self.base_universe();
168 let Some(adjusted_universe
) =
169 placeholder
.universe
.as_u32().checked_sub(base_universe
.as_u32())
171 mbcx
.buffer_error(self.fallback_error(tcx
, cause
.span
));
175 let placeholder_region
= tcx
.mk_region(ty
::RePlaceholder(ty
::Placeholder
{
176 name
: placeholder
.name
,
177 universe
: adjusted_universe
.into(),
181 if let RegionElement
::PlaceholderRegion(error_placeholder
) = error_element
{
182 let adjusted_universe
=
183 error_placeholder
.universe
.as_u32().checked_sub(base_universe
.as_u32());
184 adjusted_universe
.map(|adjusted
| {
185 tcx
.mk_region(ty
::RePlaceholder(ty
::Placeholder
{
186 name
: error_placeholder
.name
,
187 universe
: adjusted
.into(),
194 debug
!(?placeholder_region
);
196 let span
= cause
.span
;
197 let nice_error
= self.nice_error(mbcx
, cause
, placeholder_region
, error_region
);
199 if let Some(nice_error
) = nice_error
{
200 mbcx
.buffer_error(nice_error
);
202 mbcx
.buffer_error(self.fallback_error(tcx
, span
));
207 struct PredicateQuery
<'tcx
> {
209 Canonical
<'tcx
, ty
::ParamEnvAnd
<'tcx
, type_op
::prove_predicate
::ProvePredicate
<'tcx
>>>,
210 base_universe
: ty
::UniverseIndex
,
213 impl<'tcx
> TypeOpInfo
<'tcx
> for PredicateQuery
<'tcx
> {
218 ) -> DiagnosticBuilder
<'tcx
, ErrorGuaranteed
> {
219 let mut err
= tcx
.sess
.struct_span_err(span
, "higher-ranked lifetime error");
220 err
.note(&format
!("could not prove {}", self.canonical_query
.value
.value
.predicate
));
224 fn base_universe(&self) -> ty
::UniverseIndex
{
230 mbcx
: &mut MirBorrowckCtxt
<'_
, 'tcx
>,
231 cause
: ObligationCause
<'tcx
>,
232 placeholder_region
: ty
::Region
<'tcx
>,
233 error_region
: Option
<ty
::Region
<'tcx
>>,
234 ) -> Option
<DiagnosticBuilder
<'tcx
, ErrorGuaranteed
>> {
235 mbcx
.infcx
.tcx
.infer_ctxt().enter_with_canonical(
237 &self.canonical_query
,
238 |ref infcx
, key
, _
| {
239 let mut fulfill_cx
= <dyn TraitEngine
<'_
>>::new(infcx
.tcx
);
240 type_op_prove_predicate_with_cause(infcx
, &mut *fulfill_cx
, key
, cause
);
241 try_extract_error_from_fulfill_cx(
252 struct NormalizeQuery
<'tcx
, T
> {
253 canonical_query
: Canonical
<'tcx
, ty
::ParamEnvAnd
<'tcx
, type_op
::Normalize
<T
>>>,
254 base_universe
: ty
::UniverseIndex
,
257 impl<'tcx
, T
> TypeOpInfo
<'tcx
> for NormalizeQuery
<'tcx
, T
>
259 T
: Copy
+ fmt
::Display
+ TypeFoldable
<'tcx
> + 'tcx
,
265 ) -> DiagnosticBuilder
<'tcx
, ErrorGuaranteed
> {
266 let mut err
= tcx
.sess
.struct_span_err(span
, "higher-ranked lifetime error");
267 err
.note(&format
!("could not normalize `{}`", self.canonical_query
.value
.value
.value
));
271 fn base_universe(&self) -> ty
::UniverseIndex
{
277 mbcx
: &mut MirBorrowckCtxt
<'_
, 'tcx
>,
278 cause
: ObligationCause
<'tcx
>,
279 placeholder_region
: ty
::Region
<'tcx
>,
280 error_region
: Option
<ty
::Region
<'tcx
>>,
281 ) -> Option
<DiagnosticBuilder
<'tcx
, ErrorGuaranteed
>> {
282 mbcx
.infcx
.tcx
.infer_ctxt().enter_with_canonical(
284 &self.canonical_query
,
285 |ref infcx
, key
, _
| {
286 let mut fulfill_cx
= <dyn TraitEngine
<'_
>>::new(infcx
.tcx
);
288 let mut selcx
= SelectionContext
::new(infcx
);
290 // FIXME(lqd): Unify and de-duplicate the following with the actual
291 // `rustc_traits::type_op::type_op_normalize` query to allow the span we need in the
292 // `ObligationCause`. The normalization results are currently different between
293 // `AtExt::normalize` used in the query and `normalize` called below: the former fails
294 // to normalize the `nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs` test. Check
295 // after #85499 lands to see if its fixes have erased this difference.
296 let (param_env
, value
) = key
.into_parts();
297 let Normalized { value: _, obligations }
= rustc_trait_selection
::traits
::normalize(
303 fulfill_cx
.register_predicate_obligations(infcx
, obligations
);
305 try_extract_error_from_fulfill_cx(
316 struct AscribeUserTypeQuery
<'tcx
> {
317 canonical_query
: Canonical
<'tcx
, ty
::ParamEnvAnd
<'tcx
, type_op
::AscribeUserType
<'tcx
>>>,
318 base_universe
: ty
::UniverseIndex
,
321 impl<'tcx
> TypeOpInfo
<'tcx
> for AscribeUserTypeQuery
<'tcx
> {
326 ) -> DiagnosticBuilder
<'tcx
, ErrorGuaranteed
> {
327 // FIXME: This error message isn't great, but it doesn't show up in the existing UI tests,
328 // and is only the fallback when the nice error fails. Consider improving this some more.
329 tcx
.sess
.struct_span_err(span
, "higher-ranked lifetime error")
332 fn base_universe(&self) -> ty
::UniverseIndex
{
338 mbcx
: &mut MirBorrowckCtxt
<'_
, 'tcx
>,
339 cause
: ObligationCause
<'tcx
>,
340 placeholder_region
: ty
::Region
<'tcx
>,
341 error_region
: Option
<ty
::Region
<'tcx
>>,
342 ) -> Option
<DiagnosticBuilder
<'tcx
, ErrorGuaranteed
>> {
343 mbcx
.infcx
.tcx
.infer_ctxt().enter_with_canonical(
345 &self.canonical_query
,
346 |ref infcx
, key
, _
| {
347 let mut fulfill_cx
= <dyn TraitEngine
<'_
>>::new(infcx
.tcx
);
348 type_op_ascribe_user_type_with_span(infcx
, &mut *fulfill_cx
, key
, Some(cause
.span
))
350 try_extract_error_from_fulfill_cx(
361 impl<'tcx
> TypeOpInfo
<'tcx
> for crate::type_check
::InstantiateOpaqueType
<'tcx
> {
366 ) -> DiagnosticBuilder
<'tcx
, ErrorGuaranteed
> {
367 // FIXME: This error message isn't great, but it doesn't show up in the existing UI tests,
368 // and is only the fallback when the nice error fails. Consider improving this some more.
369 tcx
.sess
.struct_span_err(span
, "higher-ranked lifetime error for opaque type!")
372 fn base_universe(&self) -> ty
::UniverseIndex
{
373 self.base_universe
.unwrap()
378 mbcx
: &mut MirBorrowckCtxt
<'_
, 'tcx
>,
379 _cause
: ObligationCause
<'tcx
>,
380 placeholder_region
: ty
::Region
<'tcx
>,
381 error_region
: Option
<ty
::Region
<'tcx
>>,
382 ) -> Option
<DiagnosticBuilder
<'tcx
, ErrorGuaranteed
>> {
383 try_extract_error_from_region_constraints(
387 self.region_constraints
.as_ref().unwrap(),
388 // We're using the original `InferCtxt` that we
389 // started MIR borrowchecking with, so the region
390 // constraints have already been taken. Use the data from
391 // our `mbcx` instead.
392 |vid
| mbcx
.regioncx
.var_infos
[vid
].origin
,
393 |vid
| mbcx
.regioncx
.var_infos
[vid
].universe
,
398 #[instrument(skip(fulfill_cx, infcx), level = "debug")]
399 fn try_extract_error_from_fulfill_cx
<'tcx
>(
400 mut fulfill_cx
: Box
<dyn TraitEngine
<'tcx
> + 'tcx
>,
401 infcx
: &InferCtxt
<'_
, 'tcx
>,
402 placeholder_region
: ty
::Region
<'tcx
>,
403 error_region
: Option
<ty
::Region
<'tcx
>>,
404 ) -> Option
<DiagnosticBuilder
<'tcx
, ErrorGuaranteed
>> {
405 // We generally shouldn't have errors here because the query was
406 // already run, but there's no point using `delay_span_bug`
407 // when we're going to emit an error here anyway.
408 let _errors
= fulfill_cx
.select_all_or_error(infcx
);
409 let region_constraints
= infcx
.with_region_constraints(|r
| r
.clone());
410 try_extract_error_from_region_constraints(
415 |vid
| infcx
.region_var_origin(vid
),
416 |vid
| infcx
.universe_of_region(infcx
.tcx
.mk_region(ty
::ReVar(vid
))),
420 fn try_extract_error_from_region_constraints
<'tcx
>(
421 infcx
: &InferCtxt
<'_
, 'tcx
>,
422 placeholder_region
: ty
::Region
<'tcx
>,
423 error_region
: Option
<ty
::Region
<'tcx
>>,
424 region_constraints
: &RegionConstraintData
<'tcx
>,
425 mut region_var_origin
: impl FnMut(RegionVid
) -> RegionVariableOrigin
,
426 mut universe_of_region
: impl FnMut(RegionVid
) -> UniverseIndex
,
427 ) -> Option
<DiagnosticBuilder
<'tcx
, ErrorGuaranteed
>> {
428 let (sub_region
, cause
) =
429 region_constraints
.constraints
.iter().find_map(|(constraint
, cause
)| {
431 Constraint
::RegSubReg(sub
, sup
) if sup
== placeholder_region
&& sup
!= sub
=> {
432 Some((sub
, cause
.clone()))
434 // FIXME: Should this check the universe of the var?
435 Constraint
::VarSubReg(vid
, sup
) if sup
== placeholder_region
=> {
436 Some((infcx
.tcx
.mk_region(ty
::ReVar(vid
)), cause
.clone()))
442 debug
!(?sub_region
, "cause = {:#?}", cause
);
443 let nice_error
= match (error_region
, *sub_region
) {
444 (Some(error_region
), ty
::ReVar(vid
)) => NiceRegionError
::new(
446 RegionResolutionError
::SubSupConflict(
448 region_var_origin(vid
),
456 (Some(error_region
), _
) => NiceRegionError
::new(
458 RegionResolutionError
::ConcreteFailure(cause
.clone(), error_region
, placeholder_region
),
460 // Note universe here is wrong...
461 (None
, ty
::ReVar(vid
)) => NiceRegionError
::new(
463 RegionResolutionError
::UpperBoundUniverseConflict(
465 region_var_origin(vid
),
466 universe_of_region(vid
),
471 (None
, _
) => NiceRegionError
::new(
473 RegionResolutionError
::ConcreteFailure(cause
.clone(), sub_region
, placeholder_region
),
476 nice_error
.try_report_from_nll().or_else(|| {
477 if let SubregionOrigin
::Subtype(trace
) = cause
{
479 infcx
.report_and_explain_type_error(*trace
, &TypeError
::RegionsPlaceholderMismatch
),