Skip to content

Commit 0243834

Browse files
committed
Auto merge of #120463 - lcnr:eager-inference-replacement, r=compiler-errors
some trait system cleanups Always eagerly replace projections with infer vars if normalization is ambig. Unsure why we previously didn't do so, wasn't able to find an explanation in #90887. This adds some complexity to the trait system and is afaict unnecessary. The second commit simplifies `pred_known_to_hold_modulo_regions`, afaict the optional `fulfill` isn't necessary anymore. r? types cc `@jackh726`
2 parents e29a153 + 0c7672a commit 0243834

File tree

12 files changed

+814
-917
lines changed

12 files changed

+814
-917
lines changed

compiler/rustc_hir_analysis/src/astconv/mod.rs

+10-11
Original file line numberDiff line numberDiff line change
@@ -1425,17 +1425,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
14251425
vec![]
14261426
};
14271427

1428-
let (impl_, (assoc_item, def_scope)) =
1429-
crate::traits::project::with_replaced_escaping_bound_vars(
1430-
infcx,
1431-
&mut universes,
1432-
self_ty,
1433-
|self_ty| {
1434-
self.select_inherent_assoc_type_candidates(
1435-
infcx, name, span, self_ty, param_env, candidates,
1436-
)
1437-
},
1438-
)?;
1428+
let (impl_, (assoc_item, def_scope)) = crate::traits::with_replaced_escaping_bound_vars(
1429+
infcx,
1430+
&mut universes,
1431+
self_ty,
1432+
|self_ty| {
1433+
self.select_inherent_assoc_type_candidates(
1434+
infcx, name, span, self_ty, param_env, candidates,
1435+
)
1436+
},
1437+
)?;
14391438

14401439
self.check_assoc_ty(assoc_item, name, def_scope, block, span);
14411440

compiler/rustc_trait_selection/src/solve/normalize.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::traits::error_reporting::TypeErrCtxtExt;
22
use crate::traits::query::evaluate_obligation::InferCtxtExt;
3-
use crate::traits::{needs_normalization, BoundVarReplacer, PlaceholderReplacer};
3+
use crate::traits::{BoundVarReplacer, PlaceholderReplacer};
44
use rustc_data_structures::stack::ensure_sufficient_stack;
55
use rustc_infer::infer::at::At;
66
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -205,10 +205,9 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for NormalizationFolder<'_, 'tcx> {
205205
}
206206

207207
fn try_fold_const(&mut self, ct: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, Self::Error> {
208-
let reveal = self.at.param_env.reveal();
209208
let infcx = self.at.infcx;
210209
debug_assert_eq!(ct, infcx.shallow_resolve(ct));
211-
if !needs_normalization(&ct, reveal) {
210+
if !ct.has_projections() {
212211
return Ok(ct);
213212
}
214213

compiler/rustc_trait_selection/src/traits/fulfill.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::infer::{InferCtxt, TyOrConstInferVar};
22
use crate::traits::error_reporting::TypeErrCtxtExt;
3+
use crate::traits::normalize::normalize_with_depth_to;
34
use rustc_data_structures::captures::Captures;
45
use rustc_data_structures::obligation_forest::ProcessResult;
56
use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome};
@@ -312,7 +313,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
312313

313314
if obligation.predicate.has_projections() {
314315
let mut obligations = Vec::new();
315-
let predicate = crate::traits::project::try_normalize_with_depth_to(
316+
let predicate = normalize_with_depth_to(
316317
&mut self.selcx,
317318
obligation.param_env,
318319
obligation.cause.clone(),

compiler/rustc_trait_selection/src/traits/mod.rs

+6-50
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ mod engine;
99
pub mod error_reporting;
1010
mod fulfill;
1111
pub mod misc;
12+
pub mod normalize;
1213
mod object_safety;
1314
pub mod outlives_bounds;
1415
pub mod project;
@@ -40,17 +41,15 @@ use rustc_span::Span;
4041
use std::fmt::Debug;
4142
use std::ops::ControlFlow;
4243

43-
pub(crate) use self::project::{needs_normalization, BoundVarReplacer, PlaceholderReplacer};
44-
4544
pub use self::coherence::{add_placeholder_note, orphan_check, overlapping_impls};
4645
pub use self::coherence::{OrphanCheckErr, OverlapResult};
4746
pub use self::engine::{ObligationCtxt, TraitEngineExt};
4847
pub use self::fulfill::{FulfillmentContext, PendingPredicateObligation};
48+
pub use self::normalize::NormalizeExt;
4949
pub use self::object_safety::astconv_object_safety_violations;
5050
pub use self::object_safety::is_vtable_safe_method;
5151
pub use self::object_safety::object_safety_violations_for_assoc_item;
5252
pub use self::object_safety::ObjectSafetyViolation;
53-
pub use self::project::NormalizeExt;
5453
pub use self::project::{normalize_inherent_projection, normalize_projection_type};
5554
pub use self::select::{EvaluationCache, SelectionCache, SelectionContext};
5655
pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError};
@@ -68,6 +67,7 @@ pub use self::util::{
6867
};
6968
pub use self::util::{expand_trait_aliases, TraitAliasExpander};
7069
pub use self::util::{get_vtable_index_of_object_method, impl_item_is_final, upcast_choices};
70+
pub use self::util::{with_replaced_escaping_bound_vars, BoundVarReplacer, PlaceholderReplacer};
7171

7272
pub use rustc_infer::traits::*;
7373

@@ -119,60 +119,16 @@ pub fn predicates_for_generics<'tcx>(
119119

120120
/// Determines whether the type `ty` is known to meet `bound` and
121121
/// returns true if so. Returns false if `ty` either does not meet
122-
/// `bound` or is not known to meet bound (note that this is
123-
/// conservative towards *no impl*, which is the opposite of the
124-
/// `evaluate` methods).
122+
/// `bound` or is not known to meet bound.
125123
pub fn type_known_to_meet_bound_modulo_regions<'tcx>(
126124
infcx: &InferCtxt<'tcx>,
127125
param_env: ty::ParamEnv<'tcx>,
128126
ty: Ty<'tcx>,
129127
def_id: DefId,
130128
) -> bool {
131129
let trait_ref = ty::TraitRef::new(infcx.tcx, def_id, [ty]);
132-
pred_known_to_hold_modulo_regions(infcx, param_env, trait_ref)
133-
}
134-
135-
/// FIXME(@lcnr): this function doesn't seem right and shouldn't exist?
136-
///
137-
/// Ping me on zulip if you want to use this method and need help with finding
138-
/// an appropriate replacement.
139-
#[instrument(level = "debug", skip(infcx, param_env, pred), ret)]
140-
fn pred_known_to_hold_modulo_regions<'tcx>(
141-
infcx: &InferCtxt<'tcx>,
142-
param_env: ty::ParamEnv<'tcx>,
143-
pred: impl ToPredicate<'tcx>,
144-
) -> bool {
145-
let obligation = Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, pred);
146-
147-
let result = infcx.evaluate_obligation_no_overflow(&obligation);
148-
debug!(?result);
149-
150-
if result.must_apply_modulo_regions() {
151-
true
152-
} else if result.may_apply() {
153-
// Sometimes obligations are ambiguous because the recursive evaluator
154-
// is not smart enough, so we fall back to fulfillment when we're not certain
155-
// that an obligation holds or not. Even still, we must make sure that
156-
// the we do no inference in the process of checking this obligation.
157-
let goal = infcx.resolve_vars_if_possible((obligation.predicate, obligation.param_env));
158-
infcx.probe(|_| {
159-
let ocx = ObligationCtxt::new(infcx);
160-
ocx.register_obligation(obligation);
161-
162-
let errors = ocx.select_all_or_error();
163-
match errors.as_slice() {
164-
// Only known to hold if we did no inference.
165-
[] => infcx.shallow_resolve(goal) == goal,
166-
167-
errors => {
168-
debug!(?errors);
169-
false
170-
}
171-
}
172-
})
173-
} else {
174-
false
175-
}
130+
let obligation = Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, trait_ref);
131+
infcx.predicate_must_hold_modulo_regions(&obligation)
176132
}
177133

178134
#[instrument(level = "debug", skip(tcx, elaborated_env))]

0 commit comments

Comments
 (0)