about summary refs log tree commit diff
path: root/compiler/rustc_hir_analysis/src
diff options
context:
space:
mode:
authorLeón Orell Valerian Liehr <me@fmease.dev>2023-02-17 18:42:08 +0100
committerLeón Orell Valerian Liehr <me@fmease.dev>2023-02-19 18:35:34 +0100
commitcc65ebd0d29a79a2a1d3fd77e679c763837b33c4 (patch)
treefdfb71b3c2aeb3e2949c2ee6e4a18c5ba2513832 /compiler/rustc_hir_analysis/src
parentaa7edf70739528746d55915b96c63bd3ec43f3a7 (diff)
downloadrust-cc65ebd0d29a79a2a1d3fd77e679c763837b33c4.tar.gz
rust-cc65ebd0d29a79a2a1d3fd77e679c763837b33c4.zip
Make use of ObligationCtxt
Diffstat (limited to 'compiler/rustc_hir_analysis/src')
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/errors.rs14
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs73
2 files changed, 33 insertions, 54 deletions
diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs
index 191f4f0f910..0e9f5fb3dae 100644
--- a/compiler/rustc_hir_analysis/src/astconv/errors.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs
@@ -4,6 +4,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{pluralize, struct_span_err, Applicability, Diagnostic, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
+use rustc_infer::traits::FulfillmentError;
 use rustc_middle::ty::{self, Ty};
 use rustc_session::parse::feature_err;
 use rustc_span::lev_distance::find_best_match_for_name;
@@ -226,8 +227,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         &self,
         name: Ident,
         self_ty: Ty<'tcx>,
-        candidates: &[DefId],
-        unsatisfied_predicates: Vec<ty::Predicate<'tcx>>,
+        candidates: Vec<(DefId, (DefId, DefId))>,
+        fulfillment_errors: Vec<FulfillmentError<'tcx>>,
         span: Span,
     ) -> ErrorGuaranteed {
         let tcx = self.tcx();
@@ -245,16 +246,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             }
         };
 
-        if unsatisfied_predicates.is_empty() {
+        if fulfillment_errors.is_empty() {
             // FIXME(fmease): Copied from `rustc_hir_typeck::method::probe`. Deduplicate.
 
             let limit = if candidates.len() == 5 { 5 } else { 4 };
             let type_candidates = candidates
                 .iter()
                 .take(limit)
-                .map(|candidate| {
-                    format!("- `{}`", tcx.at(span).type_of(candidate).subst_identity())
-                })
+                .map(|&(impl_, _)| format!("- `{}`", tcx.at(span).type_of(impl_).subst_identity()))
                 .collect::<Vec<_>>()
                 .join("\n");
             let additional_types = if candidates.len() > limit {
@@ -348,8 +347,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
         // FIXME(fmease): `rustc_hir_typeck::method::suggest` uses a `skip_list` to filter out some bounds.
         // I would do the same here if it didn't mean more code duplication.
-        let mut bounds: Vec<_> = unsatisfied_predicates
+        let mut bounds: Vec<_> = fulfillment_errors
             .into_iter()
+            .map(|error| error.root_obligation.predicate)
             .filter_map(format_pred)
             .map(|(p, _)| format!("`{}`", p))
             .collect();
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index f0dd4a5d5ac..d3468f03eed 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -28,7 +28,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{walk_generics, Visitor as _};
 use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin};
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
+use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
 use rustc_infer::traits::ObligationCause;
 use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
 use rustc_middle::middle::stability::AllowUnstable;
@@ -42,13 +42,11 @@ use rustc_span::lev_distance::find_best_match_for_name;
 use rustc_span::symbol::{kw, Ident, Symbol};
 use rustc_span::{sym, Span, DUMMY_SP};
 use rustc_target::spec::abi;
-use rustc_trait_selection::traits;
 use rustc_trait_selection::traits::error_reporting::{
     report_object_safety_error, suggestions::NextTypeParamName,
 };
-use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
 use rustc_trait_selection::traits::wf::object_region_bounds;
-use rustc_trait_selection::traits::{astconv_object_safety_violations, NormalizeExt};
+use rustc_trait_selection::traits::{self, astconv_object_safety_violations, ObligationCtxt};
 
 use smallvec::{smallvec, SmallVec};
 use std::collections::BTreeSet;
@@ -1948,7 +1946,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             Res::Err
         };
 
-        // Check if we have an enum variant.
+        // Check if we have an enum variant or an inherent associated type.
         let mut variant_resolution = None;
         if let Some(adt_def) = self.probe_adt(span, qself_ty) {
             if adt_def.is_enum() {
@@ -2221,62 +2219,37 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
         let param_env = tcx.param_env(block.owner.to_def_id());
         let cause = ObligationCause::misc(span, block.owner.def_id);
-        let mut unsatisfied_predicates = Vec::new();
+        let mut fulfillment_errors = Vec::new();
 
         for &(impl_, (assoc_item, def_scope)) in &candidates {
             let infcx = tcx.infer_ctxt().ignoring_regions().build();
+            let ocx = ObligationCtxt::new(&infcx);
 
             let impl_ty = tcx.type_of(impl_);
             let impl_substs = self.fresh_item_substs(impl_, &infcx);
             let impl_ty = impl_ty.subst(tcx, impl_substs);
-
-            let InferOk { value: impl_ty, obligations } =
-                infcx.at(&cause, param_env).normalize(impl_ty);
+            let impl_ty = ocx.normalize(&cause, param_env, impl_ty);
 
             // Check that the Self-types can be related.
-            let Ok(InferOk { obligations: sub_obligations, value: () }) = infcx
-                .at(&ObligationCause::dummy(), param_env)
-                .define_opaque_types(false)
-                .sup(impl_ty, self_ty)
-            else {
+            // FIXME(fmease): Should we use `eq` here?
+            if ocx.sup(&ObligationCause::dummy(), param_env, impl_ty, self_ty).is_err() {
                 continue;
-            };
+            }
 
             // Check whether the impl imposes obligations we have to worry about.
             let impl_bounds = tcx.predicates_of(impl_);
             let impl_bounds = impl_bounds.instantiate(tcx, impl_substs);
 
-            let InferOk { value: impl_bounds, obligations: norm_obligations } =
-                infcx.at(&cause, param_env).normalize(impl_bounds);
+            let impl_bounds = ocx.normalize(&cause, param_env, impl_bounds);
 
             let impl_obligations =
                 traits::predicates_for_generics(|_, _| cause.clone(), param_env, impl_bounds);
 
-            let candidate_obligations = impl_obligations
-                .chain(norm_obligations.into_iter())
-                .chain(obligations.iter().cloned());
-
-            let mut matches = true;
-
-            // Evaluate those obligations to see if they might possibly hold.
-            for o in candidate_obligations {
-                let o = infcx.resolve_vars_if_possible(o);
-                if !infcx.predicate_may_hold(&o) {
-                    matches = false;
-                    unsatisfied_predicates.push(o.predicate);
-                }
-            }
+            ocx.register_obligations(impl_obligations);
 
-            // Evaluate those obligations to see if they might possibly hold.
-            for o in sub_obligations {
-                let o = infcx.resolve_vars_if_possible(o);
-                if !infcx.predicate_may_hold(&o) {
-                    matches = false;
-                    unsatisfied_predicates.push(o.predicate);
-                }
-            }
-
-            if !matches {
+            let errors = ocx.select_where_possible();
+            if !errors.is_empty() {
+                fulfillment_errors = errors;
                 continue;
             }
 
@@ -2286,19 +2259,25 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 bug!("unreachable: `lookup_inherent_assoc_ty` is only called on ADTs");
             };
 
-            let item_substs =
-                self.create_substs_for_associated_item(span, assoc_item, segment, adt_substs);
-            // FIXME(inherent_associated_types): Check if the obligations arising from the
-            // where-clause & the bounds on the associated type and its parameters hold.
+            let item_substs = self.create_substs_for_associated_item(
+                span, assoc_item, segment,
+                // FIXME(fmease, #107468, #105305): Don't use `adt_substs` here but `impl_substs`.
+                adt_substs,
+            );
+
+            // FIXME(fmease, #106722): Check if the bounds on the parameters of the
+            // associated type hold, if any.
             let ty = tcx.type_of(assoc_item).subst(tcx, item_substs);
+
+            // FIXME(fmease): Don't return early here! There might be multiple applicable candidates.
             return Ok(Some((ty, assoc_item)));
         }
 
         Err(self.complain_about_inherent_assoc_type_not_found(
             name,
             self_ty,
-            &candidates.into_iter().map(|(impl_, _)| impl_).collect::<Vec<_>>(),
-            unsatisfied_predicates,
+            candidates,
+            fulfillment_errors,
             span,
         ))
     }