Skip to content

Commit 0243834

Browse files
committed
Auto merge of rust-lang#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 rust-lang#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)