Skip to content

Commit 9fc3180

Browse files
Provide an InferCtxt to TyLoweringContext
So that it can create infer vars, instead of inserting them after the fact. We gain: - Accurate spans for the vars. - Being able to distinguish between valid infer vars the user wrote (or implied) and infer vars caused by errors, which should use dummy spans to prevent false diagnostics. See the removed FIXME in incorrect_generics_len.rs. - No need to try and match the infer var to the `TypeRefId` for `type_of_type_placeholder`, which can fail. Instead we just register them when we create the var. Of course, not every context lowering types has an `InferCtxt`, so it's optional.
1 parent d712cb7 commit 9fc3180

13 files changed

Lines changed: 310 additions & 205 deletions

File tree

crates/hir-ty/src/infer.rs

Lines changed: 65 additions & 75 deletions
Large diffs are not rendered by default.

crates/hir-ty/src/infer/diagnostics.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use crate::{
1818
db::{AnonConstId, HirDatabase},
1919
generics::Generics,
2020
lower::{
21-
ForbidParamsAfterReason, LifetimeElisionKind, TyLoweringContext,
21+
ForbidParamsAfterReason, LifetimeElisionKind, TyLoweringContext, TyLoweringInferVarsCtx,
2222
path::{PathDiagnosticCallback, PathLoweringContext},
2323
},
2424
};
@@ -75,6 +75,7 @@ impl<'db, 'a> InferenceTyLoweringContext<'db, 'a> {
7575
generics: &'a OnceCell<Generics<'db>>,
7676
lifetime_elision: LifetimeElisionKind<'db>,
7777
allow_using_generic_params: bool,
78+
infer_vars: Option<TyLoweringInferVarsCtx<'a, 'db>>,
7879
defined_anon_consts: &'a RefCell<ThinVec<AnonConstId>>,
7980
) -> Self {
8081
let mut ctx = TyLoweringContext::new(
@@ -85,7 +86,8 @@ impl<'db, 'a> InferenceTyLoweringContext<'db, 'a> {
8586
generic_def,
8687
generics,
8788
lifetime_elision,
88-
);
89+
)
90+
.with_infer_vars_behavior(infer_vars);
8991
if !allow_using_generic_params {
9092
ctx.forbid_params_after(0, ForbidParamsAfterReason::AnonConst);
9193
}

crates/hir-ty/src/infer/path.rs

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use stdx::never;
1313
use crate::{
1414
InferenceDiagnostic, Span, ValueTyDefId,
1515
infer::diagnostics::InferenceTyLoweringContext as TyLoweringContext,
16-
lower::{GenericPredicates, LifetimeElisionKind},
16+
lower::{GenericPredicates, LifetimeElisionKind, TyLoweringInferVarsCtx},
1717
method_resolution::{self, CandidateId, MethodError},
1818
next_solver::{
1919
GenericArg, GenericArgs, TraitRef, Ty, Unnormalized, infer::traits::ObligationCause,
@@ -38,7 +38,7 @@ impl<'db> InferenceContext<'_, 'db> {
3838
}
3939
ValuePathResolution::NonGeneric(ty) => return Some((value, ty)),
4040
};
41-
let args = self.insert_type_vars(substs, id.into());
41+
let args = self.insert_type_vars(substs);
4242

4343
self.add_required_obligations_for_value_path(id, generic_def, args);
4444

@@ -117,7 +117,7 @@ impl<'db> InferenceContext<'_, 'db> {
117117
if let Some(last_segment) = last_segment {
118118
path_ctx.set_current_segment(last_segment)
119119
}
120-
path_ctx.substs_from_path(value_def, true, false)
120+
path_ctx.substs_from_path(value_def, true, false, id.into())
121121
})
122122
};
123123

@@ -150,6 +150,10 @@ impl<'db> InferenceContext<'_, 'db> {
150150
&self.generics,
151151
LifetimeElisionKind::Infer,
152152
self.allow_using_generic_params,
153+
Some(TyLoweringInferVarsCtx {
154+
table: &mut self.table,
155+
type_of_placeholder: &mut self.result.type_of_type_placeholder,
156+
}),
153157
&self.defined_anon_consts,
154158
);
155159
let mut path_ctx = if no_diagnostics {
@@ -161,12 +165,12 @@ impl<'db> InferenceContext<'_, 'db> {
161165
let last = path.segments().last()?;
162166

163167
let (ty, orig_ns) = path_ctx.ty_ctx().lower_ty_ext(type_ref);
164-
let ty = self.table.process_user_written_ty(type_ref.into(), ty);
168+
let ty = path_ctx.expect_table().process_user_written_ty(ty);
165169

166170
path_ctx.ignore_last_segment();
167-
let (ty, _) = path_ctx.lower_ty_relative_path(ty, orig_ns, true);
171+
let (ty, _) = path_ctx.lower_ty_relative_path(ty, orig_ns, true, id.into());
168172
drop_ctx(ctx, no_diagnostics);
169-
let ty = self.table.process_user_written_ty(id.into(), ty);
173+
let ty = self.table.process_user_written_ty(ty);
170174
self.resolve_ty_assoc_item(ty, last.name, id).map(|(it, substs)| (it, Some(substs)))?
171175
} else {
172176
let hygiene = self.store.expr_or_pat_path_hygiene(id);
@@ -191,9 +195,13 @@ impl<'db> InferenceContext<'_, 'db> {
191195

192196
let (resolution, substs) = match (def, is_before_last) {
193197
(TypeNs::TraitId(trait_), true) => {
194-
let self_ty = self.table.next_ty_var(id.into());
195-
let trait_ref =
196-
path_ctx.lower_trait_ref_from_resolved_path(trait_, self_ty, true);
198+
let self_ty = path_ctx.expect_table().next_ty_var(id.into());
199+
let trait_ref = path_ctx.lower_trait_ref_from_resolved_path(
200+
trait_,
201+
self_ty,
202+
true,
203+
id.into(),
204+
);
197205
drop_ctx(ctx, no_diagnostics);
198206
self.resolve_trait_assoc_item(trait_ref, last_segment, id)
199207
}
@@ -203,13 +211,13 @@ impl<'db> InferenceContext<'_, 'db> {
203211
// should resolve to an associated type of that trait (e.g. `<T
204212
// as Iterator>::Item::default`)
205213
path_ctx.ignore_last_segment();
206-
let (ty, _) = path_ctx.lower_partly_resolved_path(def, true);
214+
let (ty, _) = path_ctx.lower_partly_resolved_path(def, true, id.into());
207215
drop_ctx(ctx, no_diagnostics);
208216
if ty.is_ty_error() {
209217
return None;
210218
}
211219

212-
let ty = self.process_user_written_ty(id.into(), ty);
220+
let ty = self.process_user_written_ty(ty);
213221

214222
self.resolve_ty_assoc_item(ty, last_segment.name, id)
215223
}

crates/hir-ty/src/infer/unify.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -442,23 +442,22 @@ impl<'db> InferenceTable<'db> {
442442
}
443443
}
444444

445-
pub(super) fn insert_type_vars<T>(&mut self, ty: T, span: Span) -> T
445+
pub(super) fn insert_type_vars<T>(&mut self, ty: T) -> T
446446
where
447447
T: TypeFoldable<DbInterner<'db>>,
448448
{
449-
self.infer_ctxt.insert_type_vars(ty, span)
449+
self.infer_ctxt.insert_type_vars(ty)
450450
}
451451

452452
/// Whenever you lower a user-written type, you should call this.
453-
pub(crate) fn process_user_written_ty(&mut self, span: Span, ty: Ty<'db>) -> Ty<'db> {
454-
let ty = self.insert_type_vars(ty, span);
455-
self.try_structurally_resolve_type(span, ty)
453+
pub(crate) fn process_user_written_ty(&mut self, ty: Ty<'db>) -> Ty<'db> {
454+
self.process_remote_user_written_ty(ty)
456455
}
457456

458457
/// The difference of this method from `process_user_written_ty()` is that this method doesn't register a well-formed obligation,
459458
/// while `process_user_written_ty()` should (but doesn't currently).
460459
pub(crate) fn process_remote_user_written_ty(&mut self, ty: Ty<'db>) -> Ty<'db> {
461-
let ty = self.insert_type_vars(ty, Span::Dummy);
460+
let ty = self.insert_type_vars(ty);
462461
// See https://github.com/rust-lang/rust/blob/cdb45c87e2cd43495379f7e867e3cc15dcee9f93/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs#L487-L495:
463462
// Even though the new solver only lazily normalizes usually, here we eagerly normalize so that not everything needs
464463
// to normalize before inspecting the `TyKind`.

crates/hir-ty/src/lib.rs

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -502,35 +502,6 @@ where
502502
Vec::from_iter(collector.params)
503503
}
504504

505-
struct TypeInferenceVarCollector<'db> {
506-
type_inference_vars: Vec<Ty<'db>>,
507-
}
508-
509-
impl<'db> rustc_type_ir::TypeVisitor<DbInterner<'db>> for TypeInferenceVarCollector<'db> {
510-
type Result = ();
511-
512-
fn visit_ty(&mut self, ty: Ty<'db>) -> Self::Result {
513-
use crate::rustc_type_ir::Flags;
514-
if ty.is_ty_var() {
515-
self.type_inference_vars.push(ty);
516-
} else if ty.flags().intersects(rustc_type_ir::TypeFlags::HAS_TY_INFER) {
517-
ty.super_visit_with(self);
518-
} else {
519-
// Fast path: don't visit inner types (e.g. generic arguments) when `flags` indicate
520-
// that there are no placeholders.
521-
}
522-
}
523-
}
524-
525-
pub fn collect_type_inference_vars<'db, T>(value: &T) -> Vec<Ty<'db>>
526-
where
527-
T: ?Sized + rustc_type_ir::TypeVisitable<DbInterner<'db>>,
528-
{
529-
let mut collector = TypeInferenceVarCollector { type_inference_vars: vec![] };
530-
value.visit_with(&mut collector);
531-
collector.type_inference_vars
532-
}
533-
534505
pub fn known_const_to_ast<'db>(
535506
konst: Const<'db>,
536507
db: &'db dyn HirDatabase,

0 commit comments

Comments
 (0)