Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/infer/unify.rs')
-rw-r--r--crates/hir-ty/src/infer/unify.rs74
1 files changed, 41 insertions, 33 deletions
diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs
index 4342375621..6a34c5b8e5 100644
--- a/crates/hir-ty/src/infer/unify.rs
+++ b/crates/hir-ty/src/infer/unify.rs
@@ -11,9 +11,10 @@ use rustc_type_ir::{
solve::Certainty,
};
use smallvec::SmallVec;
+use thin_vec::ThinVec;
use crate::{
- Span,
+ InferenceDiagnostic, Span,
db::HirDatabase,
next_solver::{
Canonical, ClauseKind, Const, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs,
@@ -29,6 +30,7 @@ use crate::{
inspect::{InspectConfig, InspectGoal, ProofTreeVisitor},
obligation_ctxt::ObligationCtxt,
},
+ solver_errors::SolverDiagnostic,
traits::ParamEnvAndCrate,
};
@@ -65,7 +67,7 @@ impl<'a, 'db> ProofTreeVisitor<'db> for NestedObligationsForSelfTy<'a, 'db> {
if self.ctx.predicate_has_self_ty(goal.predicate, self.self_ty) {
self.obligations_for_self_ty.push(Obligation::new(
db,
- self.root_cause.clone(),
+ *self.root_cause,
goal.param_env,
goal.predicate,
));
@@ -133,6 +135,7 @@ pub(crate) struct InferenceTable<'db> {
pub(crate) infer_ctxt: InferCtxt<'db>,
pub(super) fulfillment_cx: FulfillmentCtxt<'db>,
pub(super) diverging_type_vars: FxHashSet<Ty<'db>>,
+ trait_errors: Vec<NextSolverError<'db>>,
}
impl<'db> InferenceTable<'db> {
@@ -153,6 +156,7 @@ impl<'db> InferenceTable<'db> {
fulfillment_cx: FulfillmentCtxt::new(&infer_ctxt),
infer_ctxt,
diverging_type_vars: FxHashSet::default(),
+ trait_errors: Vec::new(),
}
}
@@ -320,15 +324,18 @@ impl<'db> InferenceTable<'db> {
/// In case there is still ambiguity, the returned type may be an inference
/// variable. This is different from `structurally_resolve_type` which errors
/// in this case.
- pub(crate) fn try_structurally_resolve_type(&mut self, ty: Ty<'db>) -> Ty<'db> {
+ pub(crate) fn try_structurally_resolve_type(&mut self, span: Span, ty: Ty<'db>) -> Ty<'db> {
if let TyKind::Alias(..) = ty.kind() {
let result = self
.infer_ctxt
- .at(&ObligationCause::misc(), self.param_env)
+ .at(&ObligationCause::new(span), self.param_env)
.structurally_normalize_ty(ty, &mut self.fulfillment_cx);
match result {
Ok(normalized_ty) => normalized_ty,
- Err(_errors) => Ty::new_error(self.interner(), ErrorGuaranteed),
+ Err(errors) => {
+ self.trait_errors.extend(errors);
+ Ty::new_error(self.interner(), ErrorGuaranteed)
+ }
}
} else {
self.resolve_vars_with_obligations(ty)
@@ -376,7 +383,8 @@ impl<'db> InferenceTable<'db> {
}
pub(crate) fn select_obligations_where_possible(&mut self) {
- self.fulfillment_cx.try_evaluate_obligations(&self.infer_ctxt);
+ let errors = self.fulfillment_cx.try_evaluate_obligations(&self.infer_ctxt);
+ self.trait_errors.extend(errors);
}
pub(super) fn register_predicate(&mut self, obligation: PredicateObligation<'db>) {
@@ -396,22 +404,18 @@ impl<'db> InferenceTable<'db> {
/// checking later, during regionck, that `arg` is well-formed.
pub(crate) fn register_wf_obligation(&mut self, term: Term<'db>, cause: ObligationCause) {
- let _ = (term, cause);
- // FIXME: We don't currently register an obligation here because we don't implement
- // wf checking anyway and this function is currently often passed dummy spans, which could
- // prevent reporting "type annotation needed" errors.
- // self.register_predicate(Obligation::new(
- // self.interner(),
- // cause,
- // self.param_env,
- // ClauseKind::WellFormed(term),
- // ));
+ self.register_predicate(Obligation::new(
+ self.interner(),
+ cause,
+ self.param_env,
+ ClauseKind::WellFormed(term),
+ ));
}
/// Registers obligations that all `args` are well-formed.
- pub(crate) fn add_wf_bounds(&mut self, args: GenericArgs<'db>) {
+ pub(crate) fn add_wf_bounds(&mut self, span: Span, args: GenericArgs<'db>) {
for term in args.iter().filter_map(|it| it.as_term()) {
- self.register_wf_obligation(term, ObligationCause::new());
+ self.register_wf_obligation(term, ObligationCause::new(span));
}
}
@@ -425,7 +429,7 @@ impl<'db> InferenceTable<'db> {
/// Whenever you lower a user-written type, you should call this.
pub(crate) fn process_user_written_ty(&mut self, span: Span, ty: Ty<'db>) -> Ty<'db> {
let ty = self.insert_type_vars(ty, span);
- self.try_structurally_resolve_type(ty)
+ self.try_structurally_resolve_type(span, ty)
}
/// The difference of this method from `process_user_written_ty()` is that this method doesn't register a well-formed obligation,
@@ -435,8 +439,17 @@ impl<'db> InferenceTable<'db> {
// See https://github.com/rust-lang/rust/blob/cdb45c87e2cd43495379f7e867e3cc15dcee9f93/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs#L487-L495:
// Even though the new solver only lazily normalizes usually, here we eagerly normalize so that not everything needs
// to normalize before inspecting the `TyKind`.
- // FIXME(next-solver): We should not deeply normalize here, only shallowly.
- self.try_structurally_resolve_type(ty)
+ self.try_structurally_resolve_type(Span::Dummy, ty)
+ }
+
+ fn emit_trait_errors(&mut self, diagnostics: &mut ThinVec<InferenceDiagnostic>) {
+ diagnostics.extend(std::mem::take(&mut self.trait_errors).into_iter().filter_map(
+ |error| {
+ let error = error.into_fulfillment_error(&self.infer_ctxt);
+ SolverDiagnostic::from_fulfillment_error(&error)
+ .map(InferenceDiagnostic::SolverDiagnostic)
+ },
+ ));
}
}
@@ -460,7 +473,7 @@ pub(super) mod resolve_completely {
use crate::{
InferenceDiagnostic, Span,
- infer::{TypeMismatch, unify::InferenceTable},
+ infer::unify::InferenceTable,
next_solver::{
Const, ConstKind, DbInterner, DefaultAny, GenericArg, Goal, Predicate, Region, Term,
TermKind, Ty, TyKind,
@@ -510,14 +523,6 @@ pub(super) mod resolve_completely {
}
}
- pub(crate) fn resolve_type_mismatch(&mut self, value_ref: &mut TypeMismatch) {
- // Ignore diagnostics from type mismatches, which are diagnostics themselves.
- // FIXME: We should make type mismatches just regular diagnostics.
- let prev_diagnostics_len = self.diagnostics.len();
- self.resolve_completely(value_ref);
- self.diagnostics.truncate(prev_diagnostics_len);
- }
-
pub(crate) fn resolve_completely<T>(&mut self, value_ref: &mut T)
where
T: TypeFoldable<DbInterner<'db>>,
@@ -543,6 +548,8 @@ pub(super) mod resolve_completely {
pub(crate) fn resolve_diagnostics(mut self) -> (ThinVec<InferenceDiagnostic>, bool) {
let has_errors = self.has_errors;
+ self.table.emit_trait_errors(&mut self.diagnostics);
+
// Ignore diagnostics made from resolving diagnostics.
let mut diagnostics = std::mem::take(&mut self.diagnostics);
diagnostics.retain_mut(|diagnostic| {
@@ -700,7 +707,8 @@ pub(super) mod resolve_completely {
T: Into<Term<'db>> + TypeSuperFoldable<DbInterner<'db>> + Copy,
{
let value = if self.should_normalize {
- let cause = ObligationCause::new();
+ // FIXME: This should not use a dummy span.
+ let cause = ObligationCause::new(Span::Dummy);
let at = self.ctx.table.at(&cause);
let universes = vec![None; outer_exclusive_binder(value).as_usize()];
match deeply_normalize_with_skipped_universes_and_ambiguous_coroutine_goals(
@@ -710,8 +718,8 @@ pub(super) mod resolve_completely {
self.nested_goals.extend(goals);
value
}
- Err(_errors) => {
- // FIXME: Report the error.
+ Err(errors) => {
+ self.ctx.table.trait_errors.extend(errors);
value
}
}