Skip to content

Commit 3828660

Browse files
Deeply normalize when processing registered region obligations
1 parent f3dd4c0 commit 3828660

File tree

17 files changed

+96
-21
lines changed

17 files changed

+96
-21
lines changed

compiler/rustc_hir_analysis/src/check/compare_impl_item.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use rustc_middle::ty::{
2020
};
2121
use rustc_middle::ty::{GenericParamDefKind, TyCtxt};
2222
use rustc_span::Span;
23+
use rustc_trait_selection::regions::InferCtxtRegionExt;
2324
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
2425
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
2526
use rustc_trait_selection::traits::{
@@ -380,7 +381,7 @@ fn compare_method_predicate_entailment<'tcx>(
380381
param_env,
381382
infcx.implied_bounds_tys(param_env, impl_m_def_id, &wf_tys),
382383
);
383-
let errors = infcx.resolve_regions(&outlives_env);
384+
let errors = infcx.resolve_regions_normalizing_outlives_obligations(&outlives_env);
384385
if !errors.is_empty() {
385386
return Err(infcx
386387
.tainted_by_errors()

compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use rustc_middle::ty::{
88
self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperVisitable, TypeVisitable, TypeVisitor,
99
};
1010
use rustc_span::Span;
11+
use rustc_trait_selection::regions::InferCtxtRegionExt;
1112
use rustc_trait_selection::traits::{
1213
elaborate, normalize_param_env_or_error, outlives_bounds::InferCtxtExt, ObligationCtxt,
1314
};
@@ -160,7 +161,7 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
160161
param_env,
161162
infcx.implied_bounds_tys(param_env, impl_m.def_id.expect_local(), &implied_wf_types),
162163
);
163-
let errors = infcx.resolve_regions(&outlives_env);
164+
let errors = infcx.resolve_regions_normalizing_outlives_obligations(&outlives_env);
164165
if !errors.is_empty() {
165166
tcx.dcx().delayed_bug("encountered errors when checking RPITIT refinement (regions)");
166167
return;

compiler/rustc_hir_analysis/src/check/dropck.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
88
use rustc_middle::ty::util::CheckRegions;
99
use rustc_middle::ty::GenericArgsRef;
1010
use rustc_middle::ty::{self, TyCtxt};
11+
use rustc_trait_selection::regions::InferCtxtRegionExt;
1112
use rustc_trait_selection::traits::{self, ObligationCtxt};
1213

1314
use crate::errors;
@@ -173,7 +174,9 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
173174
return Err(guar.unwrap());
174175
}
175176

176-
let errors = ocx.infcx.resolve_regions(&OutlivesEnvironment::new(param_env));
177+
let errors = ocx
178+
.infcx
179+
.resolve_regions_normalizing_outlives_obligations(&OutlivesEnvironment::new(param_env));
177180
if !errors.is_empty() {
178181
let mut guar = None;
179182
for error in errors {
@@ -188,6 +191,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
188191
RegionResolutionError::UpperBoundUniverseConflict(a, _, _, _, b) => {
189192
format!("{b}: {a}", a = ty::Region::new_var(tcx, a))
190193
}
194+
RegionResolutionError::CannotNormalize(..) => todo!(),
191195
};
192196
guar = Some(
193197
struct_span_code_err!(

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use rustc_session::parse::feature_err;
2424
use rustc_span::symbol::{sym, Ident, Symbol};
2525
use rustc_span::{Span, DUMMY_SP};
2626
use rustc_target::spec::abi::Abi;
27+
use rustc_trait_selection::regions::InferCtxtRegionExt;
2728
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
2829
use rustc_trait_selection::traits::misc::{
2930
type_allowed_to_implement_const_param_ty, ConstParamTyImplementationError,
@@ -134,7 +135,7 @@ where
134135
infcx.implied_bounds_tys_compat(param_env, body_def_id, &assumed_wf_types, false);
135136
let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
136137

137-
let errors = infcx.resolve_regions(&outlives_env);
138+
let errors = infcx.resolve_regions_normalizing_outlives_obligations(&outlives_env);
138139
if errors.is_empty() {
139140
return Ok(());
140141
}
@@ -175,7 +176,8 @@ where
175176
let implied_bounds =
176177
infcx_compat.implied_bounds_tys_compat(param_env, body_def_id, &assumed_wf_types, true);
177178
let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
178-
let errors_compat = infcx_compat.resolve_regions(&outlives_env);
179+
let errors_compat =
180+
infcx_compat.resolve_regions_normalizing_outlives_obligations(&outlives_env);
179181
if errors_compat.is_empty() {
180182
Ok(())
181183
} else {
@@ -775,7 +777,7 @@ fn test_region_obligations<'tcx>(
775777
infcx.implied_bounds_tys(param_env, id, wf_tys),
776778
);
777779

778-
let errors = infcx.resolve_regions(&outlives_environment);
780+
let errors = infcx.resolve_regions_normalizing_outlives_obligations(&outlives_environment);
779781
debug!(?errors, "errors");
780782

781783
// If we were able to prove that the type outlives the region without

compiler/rustc_infer/src/infer/error_reporting/mod.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
518518

519519
self.report_placeholder_failure(sup_origin, sub_r, sup_r).emit();
520520
}
521+
522+
RegionResolutionError::CannotNormalize(ty, origin) => {
523+
self.tcx
524+
.dcx()
525+
.struct_span_err(origin.span(), format!("cannot normalize `{ty}`"))
526+
.emit();
527+
}
521528
}
522529
}
523530
}
@@ -559,7 +566,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
559566
RegionResolutionError::GenericBoundFailure(..) => true,
560567
RegionResolutionError::ConcreteFailure(..)
561568
| RegionResolutionError::SubSupConflict(..)
562-
| RegionResolutionError::UpperBoundUniverseConflict(..) => false,
569+
| RegionResolutionError::UpperBoundUniverseConflict(..)
570+
| RegionResolutionError::CannotNormalize(..) => false,
563571
};
564572

565573
let mut errors = if errors.iter().all(|e| is_bound_failure(e)) {
@@ -574,6 +582,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
574582
RegionResolutionError::GenericBoundFailure(ref sro, _, _) => sro.span(),
575583
RegionResolutionError::SubSupConflict(_, ref rvo, _, _, _, _, _) => rvo.span(),
576584
RegionResolutionError::UpperBoundUniverseConflict(_, ref rvo, _, _, _) => rvo.span(),
585+
RegionResolutionError::CannotNormalize(_, ref sro) => sro.span(),
577586
});
578587
errors
579588
}

compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ pub enum RegionResolutionError<'tcx> {
9898
SubregionOrigin<'tcx>, // cause of the constraint
9999
Region<'tcx>, // the placeholder `'b`
100100
),
101+
102+
CannotNormalize(Ty<'tcx>, SubregionOrigin<'tcx>),
101103
}
102104

103105
impl<'tcx> RegionResolutionError<'tcx> {
@@ -106,7 +108,8 @@ impl<'tcx> RegionResolutionError<'tcx> {
106108
RegionResolutionError::ConcreteFailure(origin, _, _)
107109
| RegionResolutionError::GenericBoundFailure(origin, _, _)
108110
| RegionResolutionError::SubSupConflict(_, _, origin, _, _, _, _)
109-
| RegionResolutionError::UpperBoundUniverseConflict(_, _, _, origin, _) => origin,
111+
| RegionResolutionError::UpperBoundUniverseConflict(_, _, _, origin, _)
112+
| RegionResolutionError::CannotNormalize(_, origin) => origin,
110113
}
111114
}
112115
}

compiler/rustc_infer/src/infer/outlives/mod.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use super::{InferCtxt, RegionResolutionError};
55
use crate::infer::free_regions::RegionRelations;
66
use crate::infer::lexical_region_resolve;
77
use rustc_middle::traits::query::OutlivesBound;
8-
use rustc_middle::ty;
8+
use rustc_middle::ty::{self, Ty};
99

1010
pub mod components;
1111
pub mod env;
@@ -41,12 +41,22 @@ impl<'tcx> InferCtxt<'tcx> {
4141
/// result. After this, no more unification operations should be
4242
/// done -- or the compiler will panic -- but it is legal to use
4343
/// `resolve_vars_if_possible` as well as `fully_resolve`.
44+
///
45+
/// If you are in a crate that has access to `rustc_trai_selection`,
46+
/// then it's probably better to use `resolve_regions_normalizing_outlives_obligations`,
47+
/// which knows how to normalize registered region obligations.
4448
#[must_use]
4549
pub fn resolve_regions(
4650
&self,
4751
outlives_env: &OutlivesEnvironment<'tcx>,
52+
deeply_normalize_ty: impl Fn(Ty<'tcx>) -> Result<Ty<'tcx>, Ty<'tcx>>,
4853
) -> Vec<RegionResolutionError<'tcx>> {
49-
self.process_registered_region_obligations(outlives_env);
54+
match self.process_registered_region_obligations(outlives_env, deeply_normalize_ty) {
55+
Ok(()) => {}
56+
Err((ty, origin)) => {
57+
return vec![RegionResolutionError::CannotNormalize(ty, origin)];
58+
}
59+
};
5060

5161
let (var_infos, data) = {
5262
let mut inner = self.inner.borrow_mut();

compiler/rustc_infer/src/infer/outlives/obligations.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -123,15 +123,19 @@ impl<'tcx> InferCtxt<'tcx> {
123123
/// flow of the inferencer. The key point is that it is
124124
/// invoked after all type-inference variables have been bound --
125125
/// right before lexical region resolution.
126-
#[instrument(level = "debug", skip(self, outlives_env))]
127-
pub fn process_registered_region_obligations(&self, outlives_env: &OutlivesEnvironment<'tcx>) {
126+
#[instrument(level = "debug", skip(self, outlives_env, deeply_normalize_ty))]
127+
pub fn process_registered_region_obligations<E>(
128+
&self,
129+
outlives_env: &OutlivesEnvironment<'tcx>,
130+
mut deeply_normalize_ty: impl FnMut(Ty<'tcx>) -> Result<Ty<'tcx>, E>,
131+
) -> Result<(), (E, SubregionOrigin<'tcx>)> {
128132
assert!(!self.in_snapshot(), "cannot process registered region obligations in a snapshot");
129133

130134
let my_region_obligations = self.take_registered_region_obligations();
131135

132136
for RegionObligation { sup_type, sub_region, origin } in my_region_obligations {
137+
let sup_type = deeply_normalize_ty(sup_type).map_err(|e| (e, origin.clone()))?;
133138
debug!(?sup_type, ?sub_region, ?origin);
134-
let sup_type = self.resolve_vars_if_possible(sup_type);
135139

136140
let outlives = &mut TypeOutlives::new(
137141
self,
@@ -143,6 +147,8 @@ impl<'tcx> InferCtxt<'tcx> {
143147
let category = origin.to_constraint_category();
144148
outlives.type_must_outlive(origin, sup_type, sub_region, category);
145149
}
150+
151+
Ok(())
146152
}
147153
}
148154

compiler/rustc_trait_selection/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ extern crate smallvec;
4040

4141
pub mod errors;
4242
pub mod infer;
43+
pub mod regions;
4344
pub mod solve;
4445
pub mod traits;
4546

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
2+
use rustc_infer::infer::{InferCtxt, RegionResolutionError};
3+
use rustc_middle::traits::ObligationCause;
4+
5+
pub trait InferCtxtRegionExt<'tcx> {
6+
fn resolve_regions_normalizing_outlives_obligations(
7+
&self,
8+
outlives_env: &OutlivesEnvironment<'tcx>,
9+
) -> Vec<RegionResolutionError<'tcx>>;
10+
}
11+
12+
impl<'tcx> InferCtxtRegionExt<'tcx> for InferCtxt<'tcx> {
13+
fn resolve_regions_normalizing_outlives_obligations(
14+
&self,
15+
outlives_env: &OutlivesEnvironment<'tcx>,
16+
) -> Vec<RegionResolutionError<'tcx>> {
17+
self.resolve_regions(outlives_env, |ty| {
18+
let ty = self.resolve_vars_if_possible(ty);
19+
20+
if self.next_trait_solver() {
21+
crate::solve::deeply_normalize(
22+
self.at(&ObligationCause::dummy(), outlives_env.param_env),
23+
ty,
24+
)
25+
.map_err(|_| ty)
26+
} else {
27+
Ok(ty)
28+
}
29+
})
30+
}
31+
}

compiler/rustc_trait_selection/src/traits/auto_trait.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
179179
}
180180

181181
let outlives_env = OutlivesEnvironment::new(full_env);
182-
infcx.process_registered_region_obligations(&outlives_env);
182+
let _ = infcx.process_registered_region_obligations::<!>(&outlives_env, |ty| Ok(ty));
183183

184184
let region_data =
185185
infcx.inner.borrow_mut().unwrap_region_constraints().region_constraint_data().clone();

compiler/rustc_trait_selection/src/traits/coherence.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
77
use crate::infer::outlives::env::OutlivesEnvironment;
88
use crate::infer::InferOk;
9+
use crate::regions::InferCtxtRegionExt;
910
use crate::solve::inspect::{InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor};
1011
use crate::solve::{deeply_normalize_for_diagnostics, inspect};
1112
use crate::traits::engine::TraitEngineExt;
@@ -538,7 +539,7 @@ fn try_prove_negated_where_clause<'tcx>(
538539
// the normalization ourselves since this is totally fallible...
539540
let outlives_env = OutlivesEnvironment::new(param_env);
540541

541-
let errors = infcx.resolve_regions(&outlives_env);
542+
let errors = infcx.resolve_regions_normalizing_outlives_obligations(&outlives_env);
542543
if !errors.is_empty() {
543544
return false;
544545
}

compiler/rustc_trait_selection/src/traits/engine.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::fmt::Debug;
33

44
use super::FulfillmentContext;
55
use super::TraitEngine;
6+
use crate::regions::InferCtxtRegionExt;
67
use crate::solve::FulfillmentCtxt as NextFulfillmentCtxt;
78
use crate::traits::error_reporting::TypeErrCtxtExt;
89
use crate::traits::NormalizeExt;
@@ -201,7 +202,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
201202
generic_param_scope: LocalDefId,
202203
outlives_env: &OutlivesEnvironment<'tcx>,
203204
) -> Result<(), ErrorGuaranteed> {
204-
let errors = self.infcx.resolve_regions(outlives_env);
205+
let errors = self.infcx.resolve_regions_normalizing_outlives_obligations(outlives_env);
205206
if errors.is_empty() {
206207
Ok(())
207208
} else {

compiler/rustc_trait_selection/src/traits/misc.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! Miscellaneous type-system utilities that are too small to deserve their own modules.
22
3+
use crate::regions::InferCtxtRegionExt;
34
use crate::traits::{self, ObligationCause, ObligationCtxt};
45

56
use hir::LangItem;
@@ -197,7 +198,7 @@ pub fn all_fields_implement_trait<'tcx>(
197198
&FxIndexSet::from_iter([self_type]),
198199
),
199200
);
200-
let errors = infcx.resolve_regions(&outlives_env);
201+
let errors = infcx.resolve_regions_normalizing_outlives_obligations(&outlives_env);
201202
if !errors.is_empty() {
202203
infringing.push((field, ty, InfringingFieldsReason::Regions(errors)));
203204
}

compiler/rustc_trait_selection/src/traits/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ pub mod wf;
2525

2626
use crate::infer::outlives::env::OutlivesEnvironment;
2727
use crate::infer::{InferCtxt, TyCtxtInferExt};
28+
use crate::regions::InferCtxtRegionExt;
2829
use crate::traits::error_reporting::TypeErrCtxtExt as _;
2930
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
3031
use rustc_errors::ErrorGuaranteed;
@@ -213,7 +214,7 @@ fn do_normalize_predicates<'tcx>(
213214
// FIXME: It's very weird that we ignore region obligations but apparently
214215
// still need to use `resolve_regions` as we need the resolved regions in
215216
// the normalized predicates.
216-
let errors = infcx.resolve_regions(&outlives_env);
217+
let errors = infcx.resolve_regions_normalizing_outlives_obligations(&outlives_env);
217218
if !errors.is_empty() {
218219
tcx.dcx().span_delayed_bug(
219220
span,

tests/ui/traits/next-solver/specialization-transmute.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// compile-flags: -Znext-solver
2+
//~^ ERROR cannot normalize `<T as Default>::Id`
23

34
#![feature(specialization)]
45
//~^ WARN the feature `specialization` is incomplete
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
2-
--> $DIR/specialization-transmute.rs:3:12
2+
--> $DIR/specialization-transmute.rs:4:12
33
|
44
LL | #![feature(specialization)]
55
| ^^^^^^^^^^^^^^
@@ -8,12 +8,14 @@ LL | #![feature(specialization)]
88
= help: consider using `min_specialization` instead, which is more stable and complete
99
= note: `#[warn(incomplete_features)]` on by default
1010

11+
error: cannot normalize `<T as Default>::Id`
12+
1113
error[E0282]: type annotations needed
12-
--> $DIR/specialization-transmute.rs:13:23
14+
--> $DIR/specialization-transmute.rs:14:23
1315
|
1416
LL | default type Id = T;
1517
| ^ cannot infer type for associated type `<T as Default>::Id`
1618

17-
error: aborting due to 1 previous error; 1 warning emitted
19+
error: aborting due to 2 previous errors; 1 warning emitted
1820

1921
For more information about this error, try `rustc --explain E0282`.

0 commit comments

Comments
 (0)