summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_trait_selection/src/traits/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_trait_selection/src/traits/mod.rs')
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs65
1 files changed, 36 insertions, 29 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 8a203dec8..f265230ff 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -17,6 +17,7 @@ pub mod query;
mod select;
mod specialize;
mod structural_match;
+mod structural_normalize;
mod util;
mod vtable;
pub mod wf;
@@ -26,6 +27,7 @@ use crate::infer::{InferCtxt, TyCtxtInferExt};
use crate::traits::error_reporting::TypeErrCtxtExt as _;
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
use rustc_errors::ErrorGuaranteed;
+use rustc_middle::query::Providers;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeSuperVisitable};
@@ -49,20 +51,24 @@ pub use self::object_safety::astconv_object_safety_violations;
pub use self::object_safety::is_vtable_safe_method;
pub use self::object_safety::MethodViolationCode;
pub use self::object_safety::ObjectSafetyViolation;
-pub use self::project::{normalize_projection_type, NormalizeExt};
+pub use self::project::NormalizeExt;
+pub use self::project::{normalize_inherent_projection, normalize_projection_type};
pub use self::select::{EvaluationCache, SelectionCache, SelectionContext};
pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError};
pub use self::specialize::specialization_graph::FutureCompatOverlapError;
pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind;
-pub use self::specialize::{specialization_graph, translate_substs, OverlapError};
+pub use self::specialize::{
+ specialization_graph, translate_substs, translate_substs_with_cause, OverlapError,
+};
pub use self::structural_match::{
search_for_adt_const_param_violation, search_for_structural_match_violation,
};
+pub use self::structural_normalize::StructurallyNormalizeExt;
pub use self::util::elaborate;
pub use self::util::{expand_trait_aliases, TraitAliasExpander};
pub use self::util::{get_vtable_index_of_object_method, impl_item_is_final, upcast_choices};
pub use self::util::{
- supertrait_def_ids, supertraits, transitive_bounds, transitive_bounds_that_define_assoc_type,
+ supertrait_def_ids, supertraits, transitive_bounds, transitive_bounds_that_define_assoc_item,
SupertraitDefIds,
};
@@ -127,7 +133,7 @@ pub fn type_known_to_meet_bound_modulo_regions<'tcx>(
ty: Ty<'tcx>,
def_id: DefId,
) -> bool {
- let trait_ref = ty::Binder::dummy(infcx.tcx.mk_trait_ref(def_id, [ty]));
+ let trait_ref = ty::TraitRef::new(infcx.tcx, def_id, [ty]);
pred_known_to_hold_modulo_regions(infcx, param_env, trait_ref.without_const())
}
@@ -139,35 +145,36 @@ pub fn type_known_to_meet_bound_modulo_regions<'tcx>(
fn pred_known_to_hold_modulo_regions<'tcx>(
infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
- pred: impl ToPredicate<'tcx> + TypeVisitable<TyCtxt<'tcx>>,
+ pred: impl ToPredicate<'tcx>,
) -> bool {
- let has_non_region_infer = pred.has_non_region_infer();
let obligation = Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, pred);
let result = infcx.evaluate_obligation_no_overflow(&obligation);
debug!(?result);
- if result.must_apply_modulo_regions() && !has_non_region_infer {
+ if result.must_apply_modulo_regions() {
true
} else if result.may_apply() {
- // Because of inference "guessing", selection can sometimes claim
- // to succeed while the success requires a guess. To ensure
- // this function's result remains infallible, we must confirm
- // that guess. While imperfect, I believe this is sound.
-
- // The handling of regions in this area of the code is terrible,
- // see issue #29149. We should be able to improve on this with
- // NLL.
- let ocx = ObligationCtxt::new(infcx);
- ocx.register_obligation(obligation);
- let errors = ocx.select_all_or_error();
- match errors.as_slice() {
- [] => true,
- errors => {
- debug!(?errors);
- false
+ // Sometimes obligations are ambiguous because the recursive evaluator
+ // is not smart enough, so we fall back to fulfillment when we're not certain
+ // that an obligation holds or not. Even still, we must make sure that
+ // the we do no inference in the process of checking this obligation.
+ let goal = infcx.resolve_vars_if_possible((obligation.predicate, obligation.param_env));
+ infcx.probe(|_| {
+ let ocx = ObligationCtxt::new_in_snapshot(infcx);
+ ocx.register_obligation(obligation);
+
+ let errors = ocx.select_all_or_error();
+ match errors.as_slice() {
+ // Only known to hold if we did no inference.
+ [] => infcx.shallow_resolve(goal) == goal,
+
+ errors => {
+ debug!(?errors);
+ false
+ }
}
- }
+ })
} else {
false
}
@@ -203,7 +210,7 @@ fn do_normalize_predicates<'tcx>(
}
};
- debug!("do_normalize_predictes: normalized predicates = {:?}", predicates);
+ debug!("do_normalize_predicates: normalized predicates = {:?}", predicates);
// We can use the `elaborated_env` here; the region code only
// cares about declarations like `'a: 'b`.
@@ -414,7 +421,7 @@ fn subst_and_check_impossible_predicates<'tcx>(
predicates.push(ty::Binder::dummy(trait_ref).to_predicate(tcx));
}
- predicates.retain(|predicate| !predicate.needs_subst());
+ predicates.retain(|predicate| !predicate.has_param());
let result = impossible_predicates(tcx, predicates);
debug!("subst_and_check_impossible_predicates(key={:?}) = {:?}", key, result);
@@ -450,7 +457,7 @@ fn is_impossible_method(tcx: TyCtxt<'_>, (impl_def_id, trait_item_def_id): (DefI
{
return ControlFlow::Break(());
}
- r.super_visit_with(self)
+ ControlFlow::Continue(())
}
fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
if let ty::ConstKind::Param(param) = ct.kind()
@@ -495,10 +502,10 @@ fn is_impossible_method(tcx: TyCtxt<'_>, (impl_def_id, trait_item_def_id): (DefI
false
}
-pub fn provide(providers: &mut ty::query::Providers) {
+pub fn provide(providers: &mut Providers) {
object_safety::provide(providers);
vtable::provide(providers);
- *providers = ty::query::Providers {
+ *providers = Providers {
specialization_graph_of: specialize::specialization_graph_provider,
specializes: specialize::specializes,
subst_and_check_impossible_predicates,