diff options
| author | León Orell Valerian Liehr <me@fmease.dev> | 2023-02-17 18:42:08 +0100 |
|---|---|---|
| committer | León Orell Valerian Liehr <me@fmease.dev> | 2023-02-19 18:35:34 +0100 |
| commit | cc65ebd0d29a79a2a1d3fd77e679c763837b33c4 (patch) | |
| tree | fdfb71b3c2aeb3e2949c2ee6e4a18c5ba2513832 /compiler/rustc_hir_analysis/src | |
| parent | aa7edf70739528746d55915b96c63bd3ec43f3a7 (diff) | |
| download | rust-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.rs | 14 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/astconv/mod.rs | 73 |
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, )) } |
