Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir-ty/src/autoderef.rs4
-rw-r--r--crates/hir-ty/src/infer.rs47
-rw-r--r--crates/hir-ty/src/infer/callee.rs19
-rw-r--r--crates/hir-ty/src/infer/closure.rs66
-rw-r--r--crates/hir-ty/src/infer/coerce.rs19
-rw-r--r--crates/hir-ty/src/infer/expr.rs84
-rw-r--r--crates/hir-ty/src/infer/mutability.rs1
-rw-r--r--crates/hir-ty/src/infer/op.rs4
-rw-r--r--crates/hir-ty/src/infer/pat.rs23
-rw-r--r--crates/hir-ty/src/infer/path.rs19
-rw-r--r--crates/hir-ty/src/infer/place_op.rs27
-rw-r--r--crates/hir-ty/src/infer/unify.rs44
-rw-r--r--crates/hir-ty/src/lib.rs32
-rw-r--r--crates/hir-ty/src/method_resolution.rs26
-rw-r--r--crates/hir-ty/src/method_resolution/confirm.rs18
-rw-r--r--crates/hir-ty/src/method_resolution/probe.rs24
-rw-r--r--crates/hir-ty/src/next_solver/format_proof_tree.rs4
-rw-r--r--crates/hir-ty/src/next_solver/fulfill.rs35
-rw-r--r--crates/hir-ty/src/next_solver/infer/at.rs9
-rw-r--r--crates/hir-ty/src/next_solver/infer/canonical/instantiate.rs12
-rw-r--r--crates/hir-ty/src/next_solver/infer/canonical/mod.rs25
-rw-r--r--crates/hir-ty/src/next_solver/infer/context.rs25
-rw-r--r--crates/hir-ty/src/next_solver/infer/mod.rs176
-rw-r--r--crates/hir-ty/src/next_solver/infer/region_constraints/mod.rs30
-rw-r--r--crates/hir-ty/src/next_solver/infer/relate/generalize.rs18
-rw-r--r--crates/hir-ty/src/next_solver/infer/relate/lattice.rs29
-rw-r--r--crates/hir-ty/src/next_solver/infer/select.rs24
-rw-r--r--crates/hir-ty/src/next_solver/infer/snapshot/fudge.rs48
-rw-r--r--crates/hir-ty/src/next_solver/infer/traits.rs25
-rw-r--r--crates/hir-ty/src/next_solver/infer/type_variable.rs41
-rw-r--r--crates/hir-ty/src/next_solver/infer/unify_key.rs16
-rw-r--r--crates/hir-ty/src/next_solver/inspect.rs62
-rw-r--r--crates/hir-ty/src/next_solver/interner.rs8
-rw-r--r--crates/hir-ty/src/next_solver/normalize.rs2
-rw-r--r--crates/hir-ty/src/next_solver/solver.rs18
-rw-r--r--crates/hir-ty/src/next_solver/structural_normalize.rs2
-rw-r--r--crates/hir-ty/src/opaques.rs4
-rw-r--r--crates/hir-ty/src/specialization.rs3
-rw-r--r--crates/hir-ty/src/traits.rs3
-rw-r--r--crates/hir/src/attrs.rs2
-rw-r--r--crates/hir/src/lib.rs14
-rw-r--r--crates/hir/src/semantics.rs6
42 files changed, 612 insertions, 486 deletions
diff --git a/crates/hir-ty/src/autoderef.rs b/crates/hir-ty/src/autoderef.rs
index abab3bfb25..2c2400a14a 100644
--- a/crates/hir-ty/src/autoderef.rs
+++ b/crates/hir-ty/src/autoderef.rs
@@ -10,7 +10,7 @@ use rustc_type_ir::inherent::{IntoKind, Ty as _};
use tracing::debug;
use crate::{
- ParamEnvAndCrate,
+ ParamEnvAndCrate, Span,
db::HirDatabase,
infer::InferenceContext,
next_solver::{
@@ -39,7 +39,7 @@ pub fn autoderef<'db>(
) -> impl Iterator<Item = Ty<'db>> + use<'db> {
let interner = DbInterner::new_with(db, env.krate);
let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);
- let (ty, _) = infcx.instantiate_canonical(&ty);
+ let (ty, _) = infcx.instantiate_canonical(Span::Dummy, &ty);
let autoderef = Autoderef::new(&infcx, env.param_env, ty);
let mut v = Vec::new();
for (ty, _steps) in autoderef {
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index 8b0702c483..30b420b6d5 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -54,7 +54,7 @@ use rustc_ast_ir::Mutability;
use rustc_hash::{FxHashMap, FxHashSet};
use rustc_type_ir::{
AliasTyKind, TypeFoldable,
- inherent::{AdtDef, IntoKind, Ty as _},
+ inherent::{AdtDef, Const as _, IntoKind, Ty as _},
};
use smallvec::SmallVec;
use span::Edition;
@@ -62,7 +62,7 @@ use stdx::never;
use thin_vec::ThinVec;
use crate::{
- ImplTraitId, IncorrectGenericsLenKind, PathLoweringDiagnostic, TargetFeatures,
+ ImplTraitId, IncorrectGenericsLenKind, PathLoweringDiagnostic, Span, TargetFeatures,
closure_analysis::PlaceBase,
collect_type_inference_vars,
db::{HirDatabase, InternedOpaqueTyId},
@@ -1537,7 +1537,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
GenericArgs::for_item_with_defaults(
self.interner(),
va_list.into(),
- |_, id, _| self.table.next_var_for_param(id),
+ |_, id, _| self.table.var_for_def(id, Span::Dummy),
),
),
None => self.err_ty(),
@@ -1545,7 +1545,8 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
param_tys.push(va_list_ty);
}
- let mut param_tys = param_tys.into_iter().chain(iter::repeat(self.table.next_ty_var()));
+ let mut param_tys =
+ param_tys.into_iter().chain(iter::repeat(self.table.next_ty_var(Span::Dummy)));
if let Some(self_param) = self_param
&& let Some(ty) = param_tys.next()
{
@@ -1602,7 +1603,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
/// but if we return a new var, mark it so that no diagnostics will be issued on it.
fn insert_type_vars_shallow(&mut self, ty: Ty<'db>) -> Ty<'db> {
if ty.is_ty_error() {
- let var = self.table.next_ty_var();
+ let var = self.table.next_ty_var(Span::Dummy);
// Suppress future errors on this var. Add more things here when we add more diagnostics.
self.vars_emitted_type_must_be_known_for.insert(var);
@@ -1613,6 +1614,10 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
}
}
+ pub(super) fn insert_const_vars_shallow(&mut self, c: Const<'db>) -> Const<'db> {
+ if c.is_ct_error() { self.table.next_const_var(Span::Dummy) } else { c }
+ }
+
fn infer_body(&mut self, body_expr: ExprId) {
match self.return_coercion {
Some(_) => self.infer_return(body_expr),
@@ -1786,7 +1791,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
LifetimeElisionKind::Infer,
|ctx| ctx.lower_const(const_ref, ty),
);
- self.insert_type_vars(const_)
+ self.insert_type_vars(const_, Span::Dummy)
}
pub(crate) fn make_path_as_body_const(&mut self, path: &Path, ty: Ty<'db>) -> Const<'db> {
@@ -1796,7 +1801,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
LifetimeElisionKind::Infer,
|ctx| ctx.lower_path_as_const(path, ty),
);
- self.insert_type_vars(const_)
+ self.insert_type_vars(const_, Span::Dummy)
}
fn err_ty(&self) -> Ty<'db> {
@@ -1810,14 +1815,14 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
LifetimeElisionKind::Infer,
|ctx| ctx.lower_lifetime(lifetime_ref),
);
- self.insert_type_vars(lt)
+ self.insert_type_vars(lt, Span::Dummy)
}
- fn insert_type_vars<T>(&mut self, ty: T) -> T
+ fn insert_type_vars<T>(&mut self, ty: T, span: Span) -> T
where
T: TypeFoldable<DbInterner<'db>>,
{
- self.table.insert_type_vars(ty)
+ self.table.insert_type_vars(ty, span)
}
/// Attempts to returns the deeply last field of nested structures, but
@@ -2036,7 +2041,11 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
.associated_type_by_name(segments.first().unwrap().name)
{
// `<Self>::AssocType`
- let args = self.infcx().fill_rest_fresh_args(assoc_type.into(), trait_ref.args);
+ let args = self.infcx().fill_rest_fresh_args(
+ node.into(),
+ assoc_type.into(),
+ trait_ref.args,
+ );
let alias = Ty::new_alias(
self.interner(),
AliasTy::new_from_args(
@@ -2090,14 +2099,14 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
.db
.ty(var.lookup(self.db).parent.into())
.instantiate(interner, args);
- let ty = self.insert_type_vars(ty);
+ let ty = self.insert_type_vars(ty, Span::Dummy);
return (ty, Some(var.into()));
}
ValueNs::StructId(strukt) => {
let args = path_ctx.substs_from_path(strukt.into(), true, false);
drop(ctx);
let ty = self.db.ty(strukt.into()).instantiate(interner, args);
- let ty = self.insert_type_vars(ty);
+ let ty = self.insert_type_vars(ty, Span::Dummy);
return (ty, Some(strukt.into()));
}
ValueNs::ImplSelf(impl_id) => (TypeNs::SelfType(impl_id), None),
@@ -2119,21 +2128,21 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
let args = path_ctx.substs_from_path(strukt.into(), true, false);
drop(ctx);
let ty = self.db.ty(strukt.into()).instantiate(interner, args);
- let ty = self.insert_type_vars(ty);
+ let ty = self.insert_type_vars(ty, Span::Dummy);
forbid_unresolved_segments(self, (ty, Some(strukt.into())), unresolved)
}
TypeNs::AdtId(AdtId::UnionId(u)) => {
let args = path_ctx.substs_from_path(u.into(), true, false);
drop(ctx);
let ty = self.db.ty(u.into()).instantiate(interner, args);
- let ty = self.insert_type_vars(ty);
+ let ty = self.insert_type_vars(ty, Span::Dummy);
forbid_unresolved_segments(self, (ty, Some(u.into())), unresolved)
}
TypeNs::EnumVariantId(var) => {
let args = path_ctx.substs_from_path(var.into(), true, false);
drop(ctx);
let ty = self.db.ty(var.lookup(self.db).parent.into()).instantiate(interner, args);
- let ty = self.insert_type_vars(ty);
+ let ty = self.insert_type_vars(ty, Span::Dummy);
forbid_unresolved_segments(self, (ty, Some(var.into())), unresolved)
}
TypeNs::SelfType(impl_id) => {
@@ -2256,7 +2265,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
drop(ctx);
let interner = DbInterner::conjure();
let ty = self.db.ty(it.into()).instantiate(interner, args);
- let ty = self.insert_type_vars(ty);
+ let ty = self.insert_type_vars(ty, Span::Dummy);
self.resolve_variant_on_alias(ty, unresolved, mod_path)
}
@@ -2487,8 +2496,8 @@ impl<'db> Expectation<'db> {
}
}
- fn coercion_target_type(&self, table: &mut unify::InferenceTable<'db>) -> Ty<'db> {
- self.only_has_type(table).unwrap_or_else(|| table.next_ty_var())
+ fn coercion_target_type(&self, table: &mut unify::InferenceTable<'db>, span: Span) -> Ty<'db> {
+ self.only_has_type(table).unwrap_or_else(|| table.next_ty_var(span))
}
/// Comment copied from rustc:
diff --git a/crates/hir-ty/src/infer/callee.rs b/crates/hir-ty/src/infer/callee.rs
index a470c92124..d8639a79bd 100644
--- a/crates/hir-ty/src/infer/callee.rs
+++ b/crates/hir-ty/src/infer/callee.rs
@@ -82,7 +82,7 @@ impl<'db> InferenceContext<'_, 'db> {
}
Some(CallStep::Builtin(callee_ty)) => {
- self.confirm_builtin_call(call_expr, callee_ty, arg_exprs, expected)
+ self.confirm_builtin_call(callee_expr, call_expr, callee_ty, arg_exprs, expected)
}
Some(CallStep::DeferredClosure(_def_id, fn_sig)) => {
@@ -128,6 +128,7 @@ impl<'db> InferenceContext<'_, 'db> {
{
let closure_sig = args.as_closure().sig();
let closure_sig = autoderef.ctx().infcx().instantiate_binder_with_fresh_vars(
+ callee_expr.into(),
BoundRegionConversionTime::FnCall,
closure_sig,
);
@@ -158,15 +159,16 @@ impl<'db> InferenceContext<'_, 'db> {
let closure_args = args.as_coroutine_closure();
let coroutine_closure_sig =
autoderef.ctx().infcx().instantiate_binder_with_fresh_vars(
+ callee_expr.into(),
BoundRegionConversionTime::FnCall,
closure_args.coroutine_closure_sig(),
);
- let tupled_upvars_ty = autoderef.ctx().table.next_ty_var();
+ let tupled_upvars_ty = autoderef.ctx().table.next_ty_var(call_expr.into());
// We may actually receive a coroutine back whose kind is different
// from the closure that this dispatched from. This is because when
// we have no captures, we automatically implement `FnOnce`. This
// impl forces the closure kind to `FnOnce` i.e. `u8`.
- let kind_ty = autoderef.ctx().table.next_ty_var();
+ let kind_ty = autoderef.ctx().table.next_ty_var(call_expr.into());
let interner = autoderef.ctx().interner();
let call_sig = interner.mk_fn_sig(
[coroutine_closure_sig.tupled_inputs_ty],
@@ -297,7 +299,7 @@ impl<'db> InferenceContext<'_, 'db> {
let opt_input_type = opt_arg_exprs.map(|arg_exprs| {
Ty::new_tup_from_iter(
self.interner(),
- arg_exprs.iter().map(|_| self.table.next_ty_var()),
+ arg_exprs.iter().map(|&arg| self.table.next_ty_var(arg.into())),
)
});
@@ -388,6 +390,7 @@ impl<'db> InferenceContext<'_, 'db> {
fn confirm_builtin_call(
&mut self,
+ callee_expr: ExprId,
call_expr: ExprId,
callee_ty: Ty<'db>,
arg_exprs: &[ExprId],
@@ -411,9 +414,11 @@ impl<'db> InferenceContext<'_, 'db> {
// renormalize the associated types at this point, since they
// previously appeared within a `Binder<>` and hence would not
// have been normalized before.
- let fn_sig = self
- .infcx()
- .instantiate_binder_with_fresh_vars(BoundRegionConversionTime::FnCall, fn_sig);
+ let fn_sig = self.infcx().instantiate_binder_with_fresh_vars(
+ callee_expr.into(),
+ BoundRegionConversionTime::FnCall,
+ fn_sig,
+ );
let indices_to_skip = self.check_legacy_const_generics(def_id, arg_exprs);
self.check_call_arguments(
diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs
index a53ab7daaa..078c5c707d 100644
--- a/crates/hir-ty/src/infer/closure.rs
+++ b/crates/hir-ty/src/infer/closure.rs
@@ -65,19 +65,19 @@ impl<'db> InferenceContext<'_, 'db> {
let (expected_sig, expected_kind) = match expected.to_option(&mut self.table) {
Some(ty) => {
let ty = self.table.try_structurally_resolve_type(ty);
- self.deduce_closure_signature(ty, closure_kind)
+ self.deduce_closure_signature(closure_expr, ty, closure_kind)
}
None => (None, None),
};
let ClosureSignatures { bound_sig, mut liberated_sig } =
- self.sig_of_closure(arg_types, ret_type, expected_sig);
+ self.sig_of_closure(closure_expr, arg_types, ret_type, expected_sig);
debug!(?bound_sig, ?liberated_sig);
let parent_args = GenericArgs::identity_for_item(interner, self.generic_def.into());
- let tupled_upvars_ty = self.table.next_ty_var();
+ let tupled_upvars_ty = self.table.next_ty_var(closure_expr.into());
// FIXME: We could probably actually just unify this further --
// instead of having a `FnSig` and a `Option<CoroutineTypes>`,
@@ -103,7 +103,7 @@ impl<'db> InferenceContext<'_, 'db> {
Some(kind) => Ty::from_closure_kind(interner, kind),
// Create a type variable (for now) to represent the closure kind.
// It will be unified during the upvar inference phase (`upvar.rs`)
- None => self.table.next_ty_var(),
+ None => self.table.next_ty_var(closure_expr.into()),
};
let closure_args = ClosureArgs::new(
@@ -123,7 +123,7 @@ impl<'db> InferenceContext<'_, 'db> {
}
ClosureKind::Coroutine(_) | ClosureKind::AsyncBlock { .. } => {
let yield_ty = match closure_kind {
- ClosureKind::Coroutine(_) => self.table.next_ty_var(),
+ ClosureKind::Coroutine(_) => self.table.next_ty_var(closure_expr.into()),
ClosureKind::AsyncBlock { .. } => self.types.types.unit,
_ => unreachable!(),
};
@@ -138,7 +138,7 @@ impl<'db> InferenceContext<'_, 'db> {
// ty of `().`
let kind_ty = match closure_kind {
ClosureKind::AsyncBlock { source: CoroutineSource::Closure } => {
- self.table.next_ty_var()
+ self.table.next_ty_var(closure_expr.into())
}
_ => self.types.types.unit,
};
@@ -169,17 +169,17 @@ impl<'db> InferenceContext<'_, 'db> {
let (bound_return_ty, bound_yield_ty) =
(bound_sig.skip_binder().output(), self.types.types.unit);
// Compute all of the variables that will be used to populate the coroutine.
- let resume_ty = self.table.next_ty_var();
+ let resume_ty = self.table.next_ty_var(closure_expr.into());
let closure_kind_ty = match expected_kind {
Some(kind) => Ty::from_closure_kind(interner, kind),
// Create a type variable (for now) to represent the closure kind.
// It will be unified during the upvar inference phase (`upvar.rs`)
- None => self.table.next_ty_var(),
+ None => self.table.next_ty_var(closure_expr.into()),
};
- let coroutine_captures_by_ref_ty = self.table.next_ty_var();
+ let coroutine_captures_by_ref_ty = self.table.next_ty_var(closure_expr.into());
let closure_args = CoroutineClosureArgs::new(
interner,
@@ -214,10 +214,10 @@ impl<'db> InferenceContext<'_, 'db> {
// Create a type variable (for now) to represent the closure kind.
// It will be unified during the upvar inference phase (`upvar.rs`)
- None => self.table.next_ty_var(),
+ None => self.table.next_ty_var(closure_expr.into()),
};
- let coroutine_upvars_ty = self.table.next_ty_var();
+ let coroutine_upvars_ty = self.table.next_ty_var(closure_expr.into());
let coroutine_closure_id = InternedCoroutineClosureId::new(
self.db,
@@ -316,12 +316,14 @@ impl<'db> InferenceContext<'_, 'db> {
/// are about to type check:
fn deduce_closure_signature(
&mut self,
+ closure_expr: ExprId,
expected_ty: Ty<'db>,
closure_kind: ClosureKind,
) -> (Option<PolyFnSig<'db>>, Option<rustc_type_ir::ClosureKind>) {
match expected_ty.kind() {
TyKind::Alias(AliasTy { kind: rustc_type_ir::Opaque { def_id }, args, .. }) => self
.deduce_closure_signature_from_predicates(
+ closure_expr,
expected_ty,
closure_kind,
def_id
@@ -333,7 +335,7 @@ impl<'db> InferenceContext<'_, 'db> {
TyKind::Dynamic(object_type, ..) => {
let sig = object_type.projection_bounds().into_iter().find_map(|pb| {
let pb = pb.with_self_ty(self.interner(), Ty::new_unit(self.interner()));
- self.deduce_sig_from_projection(closure_kind, pb)
+ self.deduce_sig_from_projection(closure_expr, closure_kind, pb)
});
let kind = object_type
.principal_def_id()
@@ -342,6 +344,7 @@ impl<'db> InferenceContext<'_, 'db> {
}
TyKind::Infer(rustc_type_ir::TyVar(vid)) => self
.deduce_closure_signature_from_predicates(
+ closure_expr,
Ty::new_var(self.interner(), self.table.infer_ctxt.root_var(vid)),
closure_kind,
self.table.obligations_for_self_ty(vid).into_iter().map(|obl| obl.predicate),
@@ -361,6 +364,7 @@ impl<'db> InferenceContext<'_, 'db> {
fn deduce_closure_signature_from_predicates(
&mut self,
+ closure_expr: ExprId,
expected_ty: Ty<'db>,
closure_kind: ClosureKind,
predicates: impl DoubleEndedIterator<Item = Predicate<'db>>,
@@ -388,6 +392,7 @@ impl<'db> InferenceContext<'_, 'db> {
bound_predicate.skip_binder()
{
let inferred_sig = self.deduce_sig_from_projection(
+ closure_expr,
closure_kind,
bound_predicate.rebind(proj_predicate),
);
@@ -430,7 +435,7 @@ impl<'db> InferenceContext<'_, 'db> {
// This is a bit weird and means we may wind up discarding the goal due to it naming `expected_ty`
// even though the normalized form may not name `expected_ty`. However, this matches the existing
// behaviour of the old solver and would be technically a breaking change to fix.
- let generalized_fnptr_sig = self.table.next_ty_var();
+ let generalized_fnptr_sig = self.table.next_ty_var(closure_expr.into());
let inferred_fnptr_sig = Ty::new_fn_ptr(self.interner(), inferred_sig);
// FIXME: Report diagnostics.
_ = self
@@ -500,6 +505,7 @@ impl<'db> InferenceContext<'_, 'db> {
/// know that.
fn deduce_sig_from_projection(
&mut self,
+ closure_expr: ExprId,
closure_kind: ClosureKind,
projection: PolyProjectionPredicate<'db>,
) -> Option<PolyFnSig<'db>> {
@@ -518,7 +524,7 @@ impl<'db> InferenceContext<'_, 'db> {
// `F: FnOnce() -> Fut, Fut: Future<Output = T>` style bound. Let's still
// guide inference here, since it's beneficial for the user.
ClosureKind::AsyncClosure if Some(def_id) == self.lang_items.FnOnceOutput => {
- self.extract_sig_from_projection_and_future_bound(projection)
+ self.extract_sig_from_projection_and_future_bound(closure_expr, projection)
}
_ => None,
}
@@ -573,6 +579,7 @@ impl<'db> InferenceContext<'_, 'db> {
/// projection, and the output will be an unconstrained type variable instead.
fn extract_sig_from_projection_and_future_bound(
&mut self,
+ closure_expr: ExprId,
projection: PolyProjectionPredicate<'db>,
) -> Option<PolyFnSig<'db>> {
let projection = self.resolve_vars_if_possible(projection);
@@ -624,7 +631,7 @@ impl<'db> InferenceContext<'_, 'db> {
//
// FIXME: We probably should store this signature inference output in a way
// that does not misuse a `FnSig` type, but that can be done separately.
- let return_ty = return_ty.unwrap_or_else(|| self.table.next_ty_var());
+ let return_ty = return_ty.unwrap_or_else(|| self.table.next_ty_var(closure_expr.into()));
let sig = projection.rebind(self.interner().mk_fn_sig_safe_rust_abi(input_tys, return_ty));
@@ -633,14 +640,15 @@ impl<'db> InferenceContext<'_, 'db> {
fn sig_of_closure(
&mut self,
+ closure_expr: ExprId,
decl_inputs: &[Option<TypeRefId>],
decl_output: Option<TypeRefId>,
expected_sig: Option<PolyFnSig<'db>>,
) -> ClosureSignatures<'db> {
if let Some(e) = expected_sig {
- self.sig_of_closure_with_expectation(decl_inputs, decl_output, e)
+ self.sig_of_closure_with_expectation(closure_expr, decl_inputs, decl_output, e)
} else {
- self.sig_of_closure_no_expectation(decl_inputs, decl_output)
+ self.sig_of_closure_no_expectation(closure_expr, decl_inputs, decl_output)
}
}
@@ -648,10 +656,11 @@ impl<'db> InferenceContext<'_, 'db> {
/// types that the user gave into a signature.
fn sig_of_closure_no_expectation(
&mut self,
+ closure_expr: ExprId,
decl_inputs: &[Option<TypeRefId>],
decl_output: Option<TypeRefId>,
) -> ClosureSignatures<'db> {
- let bound_sig = self.supplied_sig_of_closure(decl_inputs, decl_output);
+ let bound_sig = self.supplied_sig_of_closure(closure_expr, decl_inputs, decl_output);
self.closure_sigs(bound_sig)
}
@@ -705,6 +714,7 @@ impl<'db> InferenceContext<'_, 'db> {
/// regions with depth 1, which are bound then by the closure.
fn sig_of_closure_with_expectation(
&mut self,
+ closure_expr: ExprId,
decl_inputs: &[Option<TypeRefId>],
decl_output: Option<TypeRefId>,
expected_sig: PolyFnSig<'db>,
@@ -713,7 +723,7 @@ impl<'db> InferenceContext<'_, 'db> {
// expectation if things don't see to match up with what we
// expect.
if expected_sig.c_variadic() {
- return self.sig_of_closure_no_expectation(decl_inputs, decl_output);
+ return self.sig_of_closure_no_expectation(closure_expr, decl_inputs, decl_output);
} else if expected_sig.skip_binder().inputs_and_output.len() != decl_inputs.len() + 1 {
return self
.sig_of_closure_with_mismatched_number_of_arguments(decl_inputs, decl_output);
@@ -745,9 +755,14 @@ impl<'db> InferenceContext<'_, 'db> {
// Along the way, it also writes out entries for types that the user
// wrote into our typeck results, which are then later used by the privacy
// check.
- match self.merge_supplied_sig_with_expectation(decl_inputs, decl_output, closure_sigs) {
+ match self.merge_supplied_sig_with_expectation(
+ closure_expr,
+ decl_inputs,
+ decl_output,
+ closure_sigs,
+ ) {
Ok(infer_ok) => self.table.register_infer_ok(infer_ok),
- Err(_) => self.sig_of_closure_no_expectation(decl_inputs, decl_output),
+ Err(_) => self.sig_of_closure_no_expectation(closure_expr, decl_inputs, decl_output),
}
}
@@ -766,6 +781,7 @@ impl<'db> InferenceContext<'_, 'db> {
/// strategy.
fn merge_supplied_sig_with_expectation(
&mut self,
+ closure_expr: ExprId,
decl_inputs: &[Option<TypeRefId>],
decl_output: Option<TypeRefId>,
mut expected_sigs: ClosureSignatures<'db>,
@@ -774,7 +790,7 @@ impl<'db> InferenceContext<'_, 'db> {
//
// (See comment on `sig_of_closure_with_expectation` for the
// meaning of these letters.)
- let supplied_sig = self.supplied_sig_of_closure(decl_inputs, decl_output);
+ let supplied_sig = self.supplied_sig_of_closure(closure_expr, decl_inputs, decl_output);
debug!(?supplied_sig);
@@ -795,6 +811,7 @@ impl<'db> InferenceContext<'_, 'db> {
self.table.commit_if_ok(|table| {
let mut all_obligations = PredicateObligations::new();
let supplied_sig = table.infer_ctxt.instantiate_binder_with_fresh_vars(
+ closure_expr.into(),
BoundRegionConversionTime::FnCall,
supplied_sig,
);
@@ -842,6 +859,7 @@ impl<'db> InferenceContext<'_, 'db> {
/// Also, record this closure signature for later.
fn supplied_sig_of_closure(
&mut self,
+ closure_expr: ExprId,
decl_inputs: &[Option<TypeRefId>],
decl_output: Option<TypeRefId>,
) -> PolyFnSig<'db> {
@@ -852,7 +870,7 @@ impl<'db> InferenceContext<'_, 'db> {
let output = self.make_body_ty(output);
self.process_user_written_ty(output)
}
- None => self.table.next_ty_var(),
+ None => self.table.next_ty_var(closure_expr.into()),
};
// First, convert the types that the user supplied (if any).
let supplied_arguments = decl_inputs.iter().map(|&input| match input {
@@ -860,7 +878,7 @@ impl<'db> InferenceContext<'_, 'db> {
let input = self.make_body_ty(input);
self.process_user_written_ty(input)
}
- None => self.table.next_ty_var(),
+ None => self.table.next_ty_var(closure_expr.into()),
});
Binder::dummy(interner.mk_fn_sig(
diff --git a/crates/hir-ty/src/infer/coerce.rs b/crates/hir-ty/src/infer/coerce.rs
index 962fc752a5..60f7b4073a 100644
--- a/crates/hir-ty/src/infer/coerce.rs
+++ b/crates/hir-ty/src/infer/coerce.rs
@@ -52,7 +52,7 @@ use smallvec::SmallVec;
use tracing::{debug, instrument};
use crate::{
- Adjust, Adjustment, AutoBorrow, ParamEnvAndCrate, PointerCast, TargetFeatures,
+ Adjust, Adjustment, AutoBorrow, ParamEnvAndCrate, PointerCast, Span, TargetFeatures,
autoderef::Autoderef,
db::{HirDatabase, InternedClosure, InternedClosureId},
infer::{
@@ -316,7 +316,8 @@ where
if b.is_infer() {
// Two unresolved type variables: create a `Coerce` predicate.
- let target_ty = if self.use_lub { self.infcx().next_ty_var() } else { b };
+ let target_ty =
+ if self.use_lub { self.infcx().next_ty_var(self.cause.span()) } else { b };
let mut obligations = PredicateObligations::with_capacity(2);
for &source_ty in &[a, b] {
@@ -463,7 +464,7 @@ where
} else {
if r_borrow_var.is_none() {
// create var lazily, at most once
- let r = self.infcx().next_region_var();
+ let r = self.infcx().next_region_var(self.cause.span());
r_borrow_var = Some(r); // [4] above
}
r_borrow_var.unwrap()
@@ -624,7 +625,7 @@ where
(TyKind::Ref(_, ty_a, mutbl_a), TyKind::Ref(_, _, mutbl_b)) => {
coerce_mutbls(mutbl_a, mutbl_b)?;
- let r_borrow = self.infcx().next_region_var();
+ let r_borrow = self.infcx().next_region_var(self.cause.span());
// We don't allow two-phase borrows here, at least for initial
// implementation. If it happens that this coercion is a function argument,
@@ -658,7 +659,7 @@ where
// the `CoerceUnsized` target type and the expected type.
// We only have the latter, so we use an inference variable
// for the former and let type inference do the rest.
- let coerce_target = self.infcx().next_ty_var();
+ let coerce_target = self.infcx().next_ty_var(self.cause.span());
let mut coercion = self.unify_and(
coerce_target,
@@ -688,6 +689,7 @@ where
errored: false,
unsize_did,
coerce_unsized_did,
+ span: self.cause.span(),
},
)
.is_break()
@@ -1451,7 +1453,7 @@ fn coerce<'db>(
) -> Result<(Vec<Adjustment>, Ty<'db>), TypeError<DbInterner<'db>>> {
let interner = DbInterner::new_with(db, env.krate);
let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);
- let ((ty1_with_vars, ty2_with_vars), vars) = infcx.instantiate_canonical(tys);
+ let ((ty1_with_vars, ty2_with_vars), vars) = infcx.instantiate_canonical(Span::Dummy, tys);
let cause = ObligationCause::new();
// FIXME: Target features.
@@ -1611,11 +1613,16 @@ struct CoerceVisitor<'a, D> {
errored: bool,
unsize_did: TraitId,
coerce_unsized_did: TraitId,
+ span: Span,
}
impl<'a, 'db, D: CoerceDelegate<'db>> ProofTreeVisitor<'db> for CoerceVisitor<'a, D> {
type Result = ControlFlow<()>;
+ fn span(&self) -> Span {
+ self.span
+ }
+
fn visit_goal(&mut self, goal: &InspectGoal<'_, 'db>) -> Self::Result {
let Some(pred) = goal.goal().predicate.as_trait_clause() else {
return ControlFlow::Continue(());
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs
index e179ca4bd3..d2d3849b2e 100644
--- a/crates/hir-ty/src/infer/expr.rs
+++ b/crates/hir-ty/src/infer/expr.rs
@@ -27,7 +27,7 @@ use syntax::ast::RangeOp;
use tracing::debug;
use crate::{
- Adjust, Adjustment, CallableDefId, Rawness, consteval,
+ Adjust, Adjustment, CallableDefId, Rawness, Span, consteval,
infer::{AllowTwoPhase, BreakableKind, coerce::CoerceMany, find_continuable, pat::PatOrigin},
lower::lower_mutability,
method_resolution::{self, CandidateId, MethodCallee, MethodError},
@@ -343,7 +343,7 @@ impl<'db> InferenceContext<'_, 'db> {
coercion_sites[1] = else_branch;
}
let mut coerce = CoerceMany::with_coercion_sites(
- expected.coercion_target_type(&mut self.table),
+ expected.coercion_target_type(&mut self.table, then_branch.into()),
&coercion_sites,
);
coerce.coerce(self, &ObligationCause::new(), then_branch, then_ty, ExprIsRead::Yes);
@@ -397,7 +397,7 @@ impl<'db> InferenceContext<'_, 'db> {
.1
}
&Expr::Loop { body, label } => {
- let ty = expected.coercion_target_type(&mut self.table);
+ let ty = expected.coercion_target_type(&mut self.table, tgt_expr.into());
let (breaks, ()) =
self.with_breakable_ctx(BreakableKind::Loop, Some(ty), label, |this| {
this.infer_expr(
@@ -466,7 +466,7 @@ impl<'db> InferenceContext<'_, 'db> {
// We don't coerce to `()` so that if the match expression is a
// statement it's branches can have any consistent type.
Expectation::HasType(ty) if *ty != self.types.types.unit => *ty,
- _ => self.table.next_ty_var(),
+ _ => self.table.next_ty_var((*expr).into()),
};
let mut coerce = CoerceMany::new(result_ty);
@@ -629,7 +629,7 @@ impl<'db> InferenceContext<'_, 'db> {
match rawness {
Rawness::RawPtr => Ty::new_ptr(self.interner(), inner_ty, mutability),
Rawness::Ref => {
- let lt = self.table.next_region_var();
+ let lt = self.table.next_region_var(tgt_expr.into());
Ty::new_ref(self.interner(), lt, inner_ty, mutability)
}
}
@@ -675,7 +675,7 @@ impl<'db> InferenceContext<'_, 'db> {
// However, rustc lowers destructuring assignments into blocks, and blocks return `!` if they have no tail
// expression and they diverge. Therefore, we have to do the same here, even though we don't lower destructuring
// assignments into blocks.
- self.table.new_maybe_never_var()
+ self.table.new_maybe_never_var(value.into())
} else {
self.types.types.unit
}
@@ -731,7 +731,7 @@ impl<'db> InferenceContext<'_, 'db> {
let idx_t = self.infer_expr_no_expect(*index, ExprIsRead::Yes);
let base_t = self.structurally_resolve_type((*base).into(), base_t);
- match self.lookup_indexing(tgt_expr, *base, base_t, idx_t) {
+ match self.lookup_indexing(tgt_expr, *base, *index, base_t, idx_t) {
Some((trait_index_ty, trait_element_ty)) => {
// two-phase not needed because index_ty is never mutable
self.demand_coerce(
@@ -755,10 +755,10 @@ impl<'db> InferenceContext<'_, 'db> {
{
Some(TyKind::Tuple(substs)) => substs
.iter()
- .chain(repeat_with(|| self.table.next_ty_var()))
+ .chain(repeat_with(|| self.table.next_ty_var(Span::Dummy)))
.take(exprs.len())
.collect::<Vec<_>>(),
- _ => (0..exprs.len()).map(|_| self.table.next_ty_var()).collect(),
+ _ => exprs.iter().map(|&expr| self.table.next_ty_var(expr.into())).collect(),
};
for (expr, ty) in exprs.iter().zip(tys.iter_mut()) {
@@ -768,7 +768,7 @@ impl<'db> InferenceContext<'_, 'db> {
Ty::new_tup(self.interner(), &tys)
}
- Expr::Array(array) => self.infer_expr_array(array, expected),
+ Expr::Array(array) => self.infer_expr_array(tgt_expr, array, expected),
Expr::Literal(lit) => match lit {
Literal::Bool(..) => self.types.types.bool,
Literal::String(..) => self.types.types.static_str_ref,
@@ -1119,7 +1119,7 @@ impl<'db> InferenceContext<'_, 'db> {
if self.features.type_changing_struct_update {
if matches!(adt_id, AdtId::StructId(_)) {
// Make some fresh generic parameters for our ADT type.
- let fresh_args = self.table.fresh_args_for_item(adt_id.into());
+ let fresh_args = self.table.fresh_args_for_item(expr.into(), adt_id.into());
// We do subtyping on the FRU fields first, so we can
// learn exactly what types we expect the base expr
// needs constrained to be compatible with the struct
@@ -1266,7 +1266,7 @@ impl<'db> InferenceContext<'_, 'db> {
// ...but otherwise we want to use any supertype of the
// scrutinee. This is sort of a workaround, see note (*) in
// `check_pat` for some details.
- let scrut_ty = self.table.next_ty_var();
+ let scrut_ty = self.table.next_ty_var(scrut.into());
self.infer_expr_coerce_never(scrut, &Expectation::HasType(scrut_ty), scrutinee_is_read);
scrut_ty
}
@@ -1328,13 +1328,19 @@ impl<'db> InferenceContext<'_, 'db> {
}
oprnd_t
}
- fn infer_expr_array(&mut self, array: &Array, expected: &Expectation<'db>) -> Ty<'db> {
+
+ fn infer_expr_array(
+ &mut self,
+ expr: ExprId,
+ array: &Array,
+ expected: &Expectation<'db>,
+ ) -> Ty<'db> {
let elem_ty = match expected
.to_option(&mut self.table)
.map(|t| self.table.try_structurally_resolve_type(t).kind())
{
Some(TyKind::Array(st, _) | TyKind::Slice(st)) => st,
- _ => self.table.next_ty_var(),
+ _ => self.table.next_ty_var(expr.into()),
};
let krate = self.resolver.krate();
@@ -1371,7 +1377,7 @@ impl<'db> InferenceContext<'_, 'db> {
let len = match self.store[repeat] {
Expr::Underscore => {
self.write_expr_ty(repeat, usize);
- self.table.next_const_var()
+ self.table.next_const_var(repeat.into())
}
_ => {
self.infer_expr(repeat, &Expectation::HasType(usize), ExprIsRead::Yes);
@@ -1383,7 +1389,7 @@ impl<'db> InferenceContext<'_, 'db> {
}
};
// Try to evaluate unevaluated constant, and insert variable if is not possible.
- let len = self.table.insert_const_vars_shallow(len);
+ let len = self.insert_const_vars_shallow(len);
Ty::new_array_with_const_len(self.interner(), elem_ty, len)
}
@@ -1477,7 +1483,7 @@ impl<'db> InferenceContext<'_, 'db> {
label: Option<LabelId>,
expected: &Expectation<'db>,
) -> Ty<'db> {
- let coerce_ty = expected.coercion_target_type(&mut self.table);
+ let coerce_ty = expected.coercion_target_type(&mut self.table, expr.into());
let g = self.resolver.update_to_inner_scope(self.db, self.owner, expr);
let (break_ty, ty) =
@@ -1488,7 +1494,7 @@ impl<'db> InferenceContext<'_, 'db> {
let decl_ty = type_ref
.as_ref()
.map(|&tr| this.make_body_ty(tr))
- .unwrap_or_else(|| this.table.next_ty_var());
+ .unwrap_or_else(|| this.table.next_ty_var((*pat).into()));
let ty = if let Some(expr) = initializer {
// If we have a subpattern that performs a read, we want to consider this
@@ -1561,7 +1567,7 @@ impl<'db> InferenceContext<'_, 'db> {
// `!`).
if this.diverges.is_always() {
// we don't even make an attempt at coercion
- this.table.new_maybe_never_var()
+ this.table.new_maybe_never_var(expr.into())
} else if let Some(t) = expected.only_has_type(&mut this.table) {
if this
.coerce(
@@ -1728,10 +1734,13 @@ impl<'db> InferenceContext<'_, 'db> {
fn instantiate_erroneous_method(&mut self, def_id: FunctionId) -> MethodCallee<'db> {
// FIXME: Using fresh infer vars for the method args isn't optimal,
// we can do better by going thorough the full probe/confirm machinery.
- let args = self.table.fresh_args_for_item(def_id.into());
+ let args = self.table.fresh_args_for_item(Span::Dummy, def_id.into());
let sig = self.db.callable_item_signature(def_id.into()).instantiate(self.interner(), args);
- let sig =
- self.infcx().instantiate_binder_with_fresh_vars(BoundRegionConversionTime::FnCall, sig);
+ let sig = self.infcx().instantiate_binder_with_fresh_vars(
+ Span::Dummy,
+ BoundRegionConversionTime::FnCall,
+ sig,
+ );
MethodCallee { def_id, args, sig }
}
@@ -1810,20 +1819,21 @@ impl<'db> InferenceContext<'_, 'db> {
None => None,
};
- let assoc_func_with_same_name = self.with_method_resolution(|ctx| {
- if !matches!(
- receiver_ty.kind(),
- TyKind::Infer(InferTy::TyVar(_)) | TyKind::Error(_)
- ) {
- ctx.probe_for_name(
- method_resolution::Mode::Path,
- method_name.clone(),
- receiver_ty,
- )
- } else {
- Err(MethodError::ErrorReported)
- }
- });
+ let assoc_func_with_same_name =
+ self.with_method_resolution(tgt_expr.into(), receiver.into(), |ctx| {
+ if !matches!(
+ receiver_ty.kind(),
+ TyKind::Infer(InferTy::TyVar(_)) | TyKind::Error(_)
+ ) {
+ ctx.probe_for_name(
+ method_resolution::Mode::Path,
+ method_name.clone(),
+ receiver_ty,
+ )
+ } else {
+ Err(MethodError::ErrorReported)
+ }
+ });
let assoc_func_with_same_name = match assoc_func_with_same_name {
Ok(method_resolution::Pick {
item: CandidateId::FunctionId(def_id), ..
@@ -1928,7 +1938,7 @@ impl<'db> InferenceContext<'_, 'db> {
let formal_input_tys: Vec<_> = formal_input_tys
.iter()
.map(|&ty| {
- let generalized_ty = self.table.next_ty_var();
+ let generalized_ty = self.table.next_ty_var(call_expr.into());
let _ = self.demand_eqtype(call_expr.into(), ty, generalized_ty);
generalized_ty
})
diff --git a/crates/hir-ty/src/infer/mutability.rs b/crates/hir-ty/src/infer/mutability.rs
index b2369f6a87..c3b532638f 100644
--- a/crates/hir-ty/src/infer/mutability.rs
+++ b/crates/hir-ty/src/infer/mutability.rs
@@ -32,6 +32,7 @@ impl<'db> InferenceContext<'_, 'db> {
};
if let Some(infer_ok) = Self::try_mutable_overloaded_place_op(
&self.table,
+ tgt_expr,
source_ty,
None,
PlaceOp::Deref,
diff --git a/crates/hir-ty/src/infer/op.rs b/crates/hir-ty/src/infer/op.rs
index 2916a46ca3..5900027a98 100644
--- a/crates/hir-ty/src/infer/op.rs
+++ b/crates/hir-ty/src/infer/op.rs
@@ -180,7 +180,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
// e.g., adding `&'a T` and `&'b T`, given `&'x T: Add<&'x T>`, will result
// in `&'a T <: &'x T` and `&'b T <: &'x T`, instead of `'a = 'b = 'x`.
let lhs_ty = self.infer_expr_no_expect(lhs_expr, ExprIsRead::Yes);
- let fresh_var = self.table.next_ty_var();
+ let fresh_var = self.table.next_ty_var(lhs_expr.into());
self.demand_coerce(lhs_expr, lhs_ty, fresh_var, AllowTwoPhase::No, ExprIsRead::Yes)
}
};
@@ -192,7 +192,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
// using this variable as the expected type, which sometimes lets
// us do better coercions than we would be able to do otherwise,
// particularly for things like `String + &String`.
- let rhs_ty_var = self.table.next_ty_var();
+ let rhs_ty_var = self.table.next_ty_var(rhs_expr.into());
let result = self.lookup_op_method(
lhs_ty,
Some((rhs_expr, rhs_ty_var)),
diff --git a/crates/hir-ty/src/infer/pat.rs b/crates/hir-ty/src/infer/pat.rs
index 3cd7461cf3..2c38fe74b1 100644
--- a/crates/hir-ty/src/infer/pat.rs
+++ b/crates/hir-ty/src/infer/pat.rs
@@ -26,7 +26,7 @@ use span::Edition;
use tracing::{debug, instrument, trace};
use crate::{
- BindingMode, InferenceDiagnostic,
+ BindingMode, InferenceDiagnostic, Span,
infer::{
AllowTwoPhase, ByRef, Expectation, InferenceContext, PatAdjust, PatAdjustment,
TypeMismatch, expr::ExprIsRead,
@@ -928,7 +928,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
// `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)`
// is required. However, we use equality, which is stronger.
// See (note_1) for an explanation.
- self.new_ref_ty(mutbl, expected)
+ self.new_ref_ty(pat.into(), mutbl, expected)
}
// Otherwise, the type of x is the expected type `T`.
ByRef::No => expected, // As above, `T <: typeof(x)` is required, but we use equality, see (note_1).
@@ -1110,7 +1110,9 @@ https://doc.rust-lang.org/reference/types.html#trait-objects";
}
let max_len = cmp::max(expected_len, elements.len());
- let element_tys_iter = (0..max_len).map(|_| self.table.next_ty_var());
+ let element_tys_iter = (0..max_len).map(|i| {
+ self.table.next_ty_var(elements.get(i).copied().map(Span::PatId).unwrap_or(Span::Dummy))
+ });
let element_tys = Tys::new_from_iter(interner, element_tys_iter);
let pat_ty = Ty::new(interner, TyKind::Tuple(element_tys));
if self.demand_eqtype(pat.into(), expected, pat_ty).is_err() {
@@ -1249,7 +1251,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects";
.map(|()| {
// Here, `demand::subtype` is good enough, but I don't
// think any errors can be introduced by using `demand::eqtype`.
- let inner_ty = self.table.next_ty_var();
+ let inner_ty = self.table.next_ty_var(inner.into());
let box_ty = Ty::new_box(interner, inner_ty);
_ = self.demand_eqtype(pat.into(), expected, box_ty);
(box_ty, inner_ty)
@@ -1472,8 +1474,8 @@ https://doc.rust-lang.org/reference/types.html#trait-objects";
(expected, r_ty)
}
_ => {
- let inner_ty = self.table.next_ty_var();
- let ref_ty = self.new_ref_ty(pat_mutbl, inner_ty);
+ let inner_ty = self.table.next_ty_var(inner.into());
+ let ref_ty = self.new_ref_ty(inner.into(), pat_mutbl, inner_ty);
debug!("check_pat_ref: demanding {:?} = {:?}", expected, ref_ty);
_ = self.demand_eqtype(pat.into(), expected, ref_ty);
@@ -1492,8 +1494,8 @@ https://doc.rust-lang.org/reference/types.html#trait-objects";
}
/// Create a reference or pinned reference type with a fresh region variable.
- fn new_ref_ty(&self, mutbl: Mutability, ty: Ty<'db>) -> Ty<'db> {
- let region = self.table.next_region_var();
+ fn new_ref_ty(&self, span: Span, mutbl: Mutability, ty: Ty<'db>) -> Ty<'db> {
+ let region = self.table.next_region_var(span);
Ty::new_ref(self.interner(), region, ty, mutbl)
}
@@ -1501,6 +1503,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects";
&self,
before: &[PatId],
slice: Option<PatId>,
+ pat: PatId,
) -> Option<Ty<'db>> {
if slice.is_some() {
return None;
@@ -1508,7 +1511,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects";
let interner = self.interner();
let len = before.len();
- let inner_ty = self.table.next_ty_var();
+ let inner_ty = self.table.next_ty_var(pat.into());
Some(Ty::new_array(interner, inner_ty, len.try_into().unwrap()))
}
@@ -1576,7 +1579,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects";
// to an array if the given pattern allows it. See issue #76342
if self.pat_is_irrefutable(pat_info.pat_origin)
&& expected.is_ty_var()
- && let Some(resolved_arr_ty) = self.try_resolve_slice_ty_to_array_ty(before, slice)
+ && let Some(resolved_arr_ty) = self.try_resolve_slice_ty_to_array_ty(before, slice, pat)
{
debug!(?resolved_arr_ty);
let _ = self.demand_eqtype(pat.into(), expected, resolved_arr_ty);
diff --git a/crates/hir-ty/src/infer/path.rs b/crates/hir-ty/src/infer/path.rs
index 0687d56024..2c094f572f 100644
--- a/crates/hir-ty/src/infer/path.rs
+++ b/crates/hir-ty/src/infer/path.rs
@@ -11,7 +11,7 @@ use rustc_type_ir::inherent::{SliceLike, Ty as _};
use stdx::never;
use crate::{
- InferenceDiagnostic, ValueTyDefId,
+ InferenceDiagnostic, Span, ValueTyDefId,
infer::diagnostics::InferenceTyLoweringContext as TyLoweringContext,
lower::{GenericPredicates, LifetimeElisionKind},
method_resolution::{self, CandidateId, MethodError},
@@ -38,7 +38,7 @@ impl<'db> InferenceContext<'_, 'db> {
}
ValuePathResolution::NonGeneric(ty) => return Some((value, ty)),
};
- let args = self.insert_type_vars(substs);
+ let args = self.insert_type_vars(substs, Span::Dummy);
self.add_required_obligations_for_value_path(generic_def, args);
@@ -187,7 +187,7 @@ impl<'db> InferenceContext<'_, 'db> {
let (resolution, substs) = match (def, is_before_last) {
(TypeNs::TraitId(trait_), true) => {
- let self_ty = self.table.next_ty_var();
+ let self_ty = self.table.next_ty_var(id.into());
let trait_ref =
path_ctx.lower_trait_ref_from_resolved_path(trait_, self_ty, true);
drop_ctx(ctx, no_diagnostics);
@@ -290,7 +290,7 @@ impl<'db> InferenceContext<'_, 'db> {
return Some(result);
}
- let res = self.with_method_resolution(|ctx| {
+ let res = self.with_method_resolution(Span::Dummy, Span::Dummy, |ctx| {
ctx.probe_for_name(method_resolution::Mode::Path, name.clone(), ty)
});
let (item, visible) = match res {
@@ -310,7 +310,7 @@ impl<'db> InferenceContext<'_, 'db> {
};
let substs = match container {
ItemContainerId::ImplId(impl_id) => {
- let impl_substs = self.table.fresh_args_for_item(impl_id.into());
+ let impl_substs = self.table.fresh_args_for_item(id.into(), impl_id.into());
let impl_self_ty =
self.db.impl_self_ty(impl_id).instantiate(self.interner(), impl_substs);
_ = self.demand_eqtype(id, impl_self_ty, ty);
@@ -318,9 +318,12 @@ impl<'db> InferenceContext<'_, 'db> {
}
ItemContainerId::TraitId(trait_) => {
// we're picking this method
- GenericArgs::fill_rest(self.interner(), trait_.into(), [ty.into()], |_, id, _| {
- self.table.next_var_for_param(id)
- })
+ GenericArgs::fill_rest(
+ self.interner(),
+ trait_.into(),
+ [ty.into()],
+ |_, param, _| self.table.var_for_def(param, id.into()),
+ )
}
ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => {
never!("assoc item contained in module/extern block");
diff --git a/crates/hir-ty/src/infer/place_op.rs b/crates/hir-ty/src/infer/place_op.rs
index 1671b67d34..63841af682 100644
--- a/crates/hir-ty/src/infer/place_op.rs
+++ b/crates/hir-ty/src/infer/place_op.rs
@@ -29,9 +29,10 @@ pub(super) enum PlaceOp {
impl<'a, 'db> InferenceContext<'a, 'db> {
pub(super) fn try_overloaded_deref(
&self,
+ expr: ExprId,
base_ty: Ty<'db>,
) -> Option<InferOk<'db, MethodCallee<'db>>> {
- self.try_overloaded_place_op(base_ty, None, PlaceOp::Deref)
+ self.try_overloaded_place_op(expr, base_ty, None, PlaceOp::Deref)
}
/// For the overloaded place expressions (`*x`, `x[3]`), the trait
@@ -57,7 +58,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
return Some(ty);
}
- let ok = self.try_overloaded_deref(oprnd_ty)?;
+ let ok = self.try_overloaded_deref(expr, oprnd_ty)?;
let method = self.table.register_infer_ok(ok);
if let TyKind::Ref(_, _, Mutability::Not) = method.sig.inputs_and_output.inputs()[0].kind()
{
@@ -81,6 +82,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
&mut self,
expr: ExprId,
base_expr: ExprId,
+ index_expr: ExprId,
base_ty: Ty<'db>,
idx_ty: Ty<'db>,
) -> Option<(/*index type*/ Ty<'db>, /*element type*/ Ty<'db>)> {
@@ -91,7 +93,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
let mut autoderef = InferenceContextAutoderef::new_from_inference_context(self, base_ty);
let mut result = None;
while result.is_none() && autoderef.next().is_some() {
- result = Self::try_index_step(expr, base_expr, &mut autoderef, idx_ty);
+ result = Self::try_index_step(expr, base_expr, index_expr, &mut autoderef, idx_ty);
}
result
}
@@ -104,6 +106,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
fn try_index_step(
expr: ExprId,
base_expr: ExprId,
+ index_expr: ExprId,
autoderef: &mut InferenceContextAutoderef<'_, 'a, 'db>,
index_ty: Ty<'db>,
) -> Option<(/*index type*/ Ty<'db>, /*element type*/ Ty<'db>)> {
@@ -136,9 +139,13 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
// If some lookup succeeds, write callee into table and extract index/element
// type from the method signature.
// If some lookup succeeded, install method in table
- let input_ty = autoderef.ctx().table.next_ty_var();
- let method =
- autoderef.ctx().try_overloaded_place_op(self_ty, Some(input_ty), PlaceOp::Index);
+ let input_ty = autoderef.ctx().table.next_ty_var(index_expr.into());
+ let method = autoderef.ctx().try_overloaded_place_op(
+ expr,
+ self_ty,
+ Some(input_ty),
+ PlaceOp::Index,
+ );
if let Some(result) = method {
debug!("try_index_step: success, using overloaded indexing");
@@ -180,6 +187,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
/// `convert_place_derefs_to_mutable`.
pub(super) fn try_overloaded_place_op(
&self,
+ expr: ExprId,
base_ty: Ty<'db>,
opt_rhs_ty: Option<Ty<'db>>,
op: PlaceOp,
@@ -198,7 +206,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
// opaque types as rigid here to support `impl Deref<Target = impl Index<usize>>`.
let treat_opaques = TreatNotYetDefinedOpaques::AsInfer;
self.table.lookup_method_for_operator(
- ObligationCause::new(),
+ ObligationCause::with_span(expr.into()),
imm_op,
imm_tr,
base_ty,
@@ -209,6 +217,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
pub(super) fn try_mutable_overloaded_place_op(
table: &InferenceTable<'db>,
+ expr: ExprId,
base_ty: Ty<'db>,
opt_rhs_ty: Option<Ty<'db>>,
op: PlaceOp,
@@ -230,7 +239,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
// of the opaque.
let treat_opaques = TreatNotYetDefinedOpaques::AsInfer;
table.lookup_method_for_operator(
- ObligationCause::new(),
+ ObligationCause::with_span(expr.into()),
mut_op,
mut_tr,
base_ty,
@@ -276,7 +285,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
))
}
};
- let method = Self::try_mutable_overloaded_place_op(&self.table, base_ty, arg_ty, op);
+ let method = Self::try_mutable_overloaded_place_op(&self.table, expr, base_ty, arg_ty, op);
let method = match method {
Some(ok) => self.table.register_infer_ok(ok),
// Couldn't find the mutable variant of the place op, keep the
diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs
index be4d370c24..31b6d50886 100644
--- a/crates/hir-ty/src/infer/unify.rs
+++ b/crates/hir-ty/src/infer/unify.rs
@@ -7,12 +7,13 @@ use hir_def::{ExpressionStoreOwnerId, GenericParamId, TraitId};
use rustc_hash::FxHashSet;
use rustc_type_ir::{
TyVid, TypeFoldable, TypeVisitableExt,
- inherent::{Const as _, GenericArg as _, IntoKind, Ty as _},
+ inherent::{GenericArg as _, IntoKind, Ty as _},
solve::Certainty,
};
use smallvec::SmallVec;
use crate::{
+ Span,
db::HirDatabase,
next_solver::{
Canonical, ClauseKind, Const, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs,
@@ -41,6 +42,10 @@ struct NestedObligationsForSelfTy<'a, 'db> {
impl<'a, 'db> ProofTreeVisitor<'db> for NestedObligationsForSelfTy<'a, 'db> {
type Result = ();
+ fn span(&self) -> Span {
+ self.root_cause.span()
+ }
+
fn config(&self) -> InspectConfig {
// Using an intentionally low depth to minimize the chance of future
// breaking changes in case we adapt the approach later on. This also
@@ -112,7 +117,7 @@ fn could_unify_impl<'db>(
let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);
let cause = ObligationCause::dummy();
let at = infcx.at(&cause, env.param_env);
- let ((ty1_with_vars, ty2_with_vars), _) = infcx.instantiate_canonical(tys);
+ let ((ty1_with_vars, ty2_with_vars), _) = infcx.instantiate_canonical(Span::Dummy, tys);
let mut ctxt = ObligationCtxt::new(&infcx);
let can_unify = at
.eq(ty1_with_vars, ty2_with_vars)
@@ -245,12 +250,12 @@ impl<'db> InferenceTable<'db> {
self.diverging_type_vars.insert(ty);
}
- pub(crate) fn next_ty_var(&self) -> Ty<'db> {
- self.infer_ctxt.next_ty_var()
+ pub(crate) fn next_ty_var(&self, span: Span) -> Ty<'db> {
+ self.infer_ctxt.next_ty_var(span)
}
- pub(crate) fn next_const_var(&self) -> Const<'db> {
- self.infer_ctxt.next_const_var()
+ pub(crate) fn next_const_var(&self, span: Span) -> Const<'db> {
+ self.infer_ctxt.next_const_var(span)
}
pub(crate) fn next_int_var(&self) -> Ty<'db> {
@@ -261,18 +266,18 @@ impl<'db> InferenceTable<'db> {
self.infer_ctxt.next_float_var()
}
- pub(crate) fn new_maybe_never_var(&mut self) -> Ty<'db> {
- let var = self.next_ty_var();
+ pub(crate) fn new_maybe_never_var(&mut self, span: Span) -> Ty<'db> {
+ let var = self.next_ty_var(span);
self.set_diverging(var);
var
}
- pub(crate) fn next_region_var(&self) -> Region<'db> {
- self.infer_ctxt.next_region_var()
+ pub(crate) fn next_region_var(&self, span: Span) -> Region<'db> {
+ self.infer_ctxt.next_region_var(span)
}
- pub(crate) fn next_var_for_param(&self, id: GenericParamId) -> GenericArg<'db> {
- self.infer_ctxt.next_var_for_param(id)
+ pub(crate) fn var_for_def(&self, id: GenericParamId, span: Span) -> GenericArg<'db> {
+ self.infer_ctxt.var_for_def(id, span)
}
pub(crate) fn resolve_completely<T>(&mut self, value: T) -> T
@@ -319,8 +324,8 @@ impl<'db> InferenceTable<'db> {
}
/// Create a `GenericArgs` full of infer vars for `def`.
- pub(crate) fn fresh_args_for_item(&self, def: SolverDefId) -> GenericArgs<'db> {
- self.infer_ctxt.fresh_args_for_item(def)
+ pub(crate) fn fresh_args_for_item(&self, span: Span, def: SolverDefId) -> GenericArgs<'db> {
+ self.infer_ctxt.fresh_args_for_item(span, def)
}
/// Try to resolve `ty` to a structural type, normalizing aliases.
@@ -421,11 +426,11 @@ impl<'db> InferenceTable<'db> {
}
}
- pub(super) fn insert_type_vars<T>(&mut self, ty: T) -> T
+ pub(super) fn insert_type_vars<T>(&mut self, ty: T, span: Span) -> T
where
T: TypeFoldable<DbInterner<'db>>,
{
- self.infer_ctxt.insert_type_vars(ty)
+ self.infer_ctxt.insert_type_vars(ty, span)
}
/// Whenever you lower a user-written type, you should call this.
@@ -437,18 +442,13 @@ impl<'db> InferenceTable<'db> {
/// The difference of this method from `process_user_written_ty()` is that this method doesn't register a well-formed obligation,
/// while `process_user_written_ty()` should (but doesn't currently).
pub(crate) fn process_remote_user_written_ty(&mut self, ty: Ty<'db>) -> Ty<'db> {
- let ty = self.insert_type_vars(ty);
+ let ty = self.insert_type_vars(ty, Span::Dummy);
// 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)
}
-
- /// Replaces ConstScalar::Unknown by a new type var, so we can maybe still infer it.
- pub(super) fn insert_const_vars_shallow(&mut self, c: Const<'db>) -> Const<'db> {
- if c.is_ct_error() { self.next_const_var() } else { c }
- }
}
impl fmt::Debug for InferenceTable<'_> {
diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs
index 2973b970f3..3fb8632d6b 100644
--- a/crates/hir-ty/src/lib.rs
+++ b/crates/hir-ty/src/lib.rs
@@ -62,7 +62,10 @@ use std::{hash::Hash, ops::ControlFlow};
use hir_def::{
CallableDefId, ExpressionStoreOwnerId, GenericDefId, TypeAliasId, TypeOrConstParamId,
- TypeParamId, resolver::TypeNs, type_ref::Rawness,
+ TypeParamId,
+ hir::{ExprId, ExprOrPatId, PatId},
+ resolver::TypeNs,
+ type_ref::{Rawness, TypeRefId},
};
use hir_expand::name::Name;
use indexmap::{IndexMap, map::Entry};
@@ -74,6 +77,7 @@ use rustc_type_ir::{
BoundVarIndexKind, TypeSuperVisitable, TypeVisitableExt,
inherent::{IntoKind, Ty as _},
};
+use stdx::impl_from;
use syntax::ast::{ConstArg, make};
use traits::FnTrait;
@@ -541,7 +545,7 @@ pub fn callable_sig_from_fn_trait<'db>(
let impls_trait = |trait_: FnTrait| {
let mut ocx = ObligationCtxt::new(&infcx);
- let tupled_args = infcx.next_ty_var();
+ let tupled_args = infcx.next_ty_var(Span::Dummy);
let args = GenericArgs::new_from_slice(&[self_ty.into(), tupled_args.into()]);
let trait_id = trait_.get_id(lang_items)?;
let trait_ref = TraitRef::new_from_args(interner, trait_id.into(), args);
@@ -661,6 +665,30 @@ pub fn known_const_to_ast<'db>(
Some(make::expr_const_value(konst.display(db, display_target).to_string().as_str()))
}
+/// A `Span` represents some location in lowered code - a type, expression or pattern.
+///
+/// It has no meaning outside its body therefore it should not exit the pass it was created in
+/// (e.g. inference). It is usually associated with a solver obligation or an infer var, which
+/// should also not cross the pass they were created in.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum Span {
+ ExprId(ExprId),
+ PatId(PatId),
+ TypeRefId(TypeRefId),
+ /// An unimportant location. Errors on this will be suppressed.
+ Dummy,
+}
+impl_from!(ExprId, PatId, TypeRefId for Span);
+
+impl From<ExprOrPatId> for Span {
+ fn from(value: ExprOrPatId) -> Self {
+ match value {
+ ExprOrPatId::ExprId(idx) => idx.into(),
+ ExprOrPatId::PatId(idx) => idx.into(),
+ }
+ }
+}
+
pub fn setup_tracing() -> Option<tracing::subscriber::DefaultGuard> {
use std::env;
use std::sync::LazyLock;
diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs
index 25c2df0d9f..2c6c7ed9a5 100644
--- a/crates/hir-ty/src/method_resolution.rs
+++ b/crates/hir-ty/src/method_resolution.rs
@@ -36,7 +36,7 @@ use stdx::impl_from;
use triomphe::Arc;
use crate::{
- all_super_traits,
+ Span, all_super_traits,
db::HirDatabase,
infer::{InferenceContext, unify::InferenceTable},
lower::GenericPredicates,
@@ -65,6 +65,8 @@ pub struct MethodResolutionContext<'a, 'db> {
pub traits_in_scope: &'a FxHashSet<TraitId>,
pub edition: Edition,
pub features: &'a UnstableFeatures,
+ pub call_span: Span,
+ pub receiver_span: Span,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa::Update)]
@@ -134,7 +136,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
receiver: ExprId,
call_expr: ExprId,
) -> Result<(MethodCallee<'db>, bool), MethodError<'db>> {
- let (pick, is_visible) = match self.lookup_probe(name, self_ty) {
+ let (pick, is_visible) = match self.lookup_probe(call_expr, receiver, name, self_ty) {
Ok(it) => (it, true),
Err(MethodError::PrivateMatch(it)) => {
// FIXME: Report error.
@@ -159,10 +161,12 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
#[instrument(level = "debug", skip(self))]
pub(crate) fn lookup_probe(
&self,
+ call_expr: ExprId,
+ receiver: ExprId,
method_name: Name,
self_ty: Ty<'db>,
) -> probe::PickResult<'db> {
- self.with_method_resolution(|ctx| {
+ self.with_method_resolution(call_expr.into(), receiver.into(), |ctx| {
let pick = ctx.probe_for_name(probe::Mode::MethodCall, method_name, self_ty)?;
Ok(pick)
})
@@ -170,6 +174,8 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
pub(crate) fn with_method_resolution<R>(
&self,
+ call_span: Span,
+ receiver_span: Span,
f: impl FnOnce(&MethodResolutionContext<'_, 'db>) -> R,
) -> R {
let traits_in_scope = self.get_traits_in_scope();
@@ -184,6 +190,8 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
traits_in_scope,
edition: self.edition,
features: self.features,
+ call_span,
+ receiver_span,
};
f(&ctx)
}
@@ -240,7 +248,7 @@ impl<'db> InferenceTable<'db> {
// FIXME: We should stop passing `None` for the failure case
// when probing for call exprs. I.e. `opt_rhs_ty` should always
// be set when it needs to be.
- self.next_var_for_param(param_id)
+ self.var_for_def(param_id, cause.span())
}
}
},
@@ -248,7 +256,7 @@ impl<'db> InferenceTable<'db> {
let obligation = Obligation::new(
self.interner(),
- cause,
+ cause.clone(),
self.param_env,
TraitRef::new_from_args(self.interner(), trait_def_id.into(), args),
);
@@ -291,9 +299,11 @@ impl<'db> InferenceTable<'db> {
// with bound regions.
let fn_sig =
self.db.callable_item_signature(method_item.into()).instantiate(interner, args);
- let fn_sig = self
- .infer_ctxt
- .instantiate_binder_with_fresh_vars(BoundRegionConversionTime::FnCall, fn_sig);
+ let fn_sig = self.infer_ctxt.instantiate_binder_with_fresh_vars(
+ cause.span(),
+ BoundRegionConversionTime::FnCall,
+ fn_sig,
+ );
// Register obligations for the parameters. This will include the
// `Self` parameter, which in turn has a bound of the main trait,
diff --git a/crates/hir-ty/src/method_resolution/confirm.rs b/crates/hir-ty/src/method_resolution/confirm.rs
index 3bdef44dd3..6536b599c8 100644
--- a/crates/hir-ty/src/method_resolution/confirm.rs
+++ b/crates/hir-ty/src/method_resolution/confirm.rs
@@ -15,7 +15,7 @@ use tracing::debug;
use crate::{
Adjust, Adjustment, AutoBorrow, IncorrectGenericsLenKind, InferenceDiagnostic,
- LifetimeElisionKind, PointerCast,
+ LifetimeElisionKind, PointerCast, Span,
db::HirDatabase,
infer::{AllowTwoPhase, AutoBorrowMutability, InferenceContext, TypeMismatch},
lower::{
@@ -190,7 +190,7 @@ impl<'a, 'b, 'db> ConfirmContext<'a, 'b, 'db> {
self.ctx.table.register_infer_ok(autoderef.adjust_steps_as_infer_ok());
match pick.autoref_or_ptr_adjustment {
Some(probe::AutorefOrPtrAdjustment::Autoref { mutbl, unsize }) => {
- let region = self.infcx().next_region_var();
+ let region = self.infcx().next_region_var(self.expr.into());
// Type we're wrapping in a reference, used later for unsizing
let base_ty = target;
@@ -254,7 +254,7 @@ impl<'a, 'b, 'db> ConfirmContext<'a, 'b, 'db> {
) -> GenericArgs<'db> {
match pick.kind {
probe::InherentImplPick(impl_def_id) => {
- self.infcx().fresh_args_for_item(impl_def_id.into())
+ self.infcx().fresh_args_for_item(self.expr.into(), impl_def_id.into())
}
probe::ObjectPick(trait_def_id) => {
@@ -296,7 +296,7 @@ impl<'a, 'b, 'db> ConfirmContext<'a, 'b, 'db> {
// the process we will unify the transformed-self-type
// of the method with the actual type in order to
// unify some of these variables.
- self.infcx().fresh_args_for_item(trait_def_id.into())
+ self.infcx().fresh_args_for_item(self.expr.into(), trait_def_id.into())
}
probe::WhereClausePick(poly_trait_ref) => {
@@ -414,7 +414,7 @@ impl<'a, 'b, 'db> ConfirmContext<'a, 'b, 'db> {
) -> Const<'db> {
match arg {
TypeLikeConst::Path(path) => self.ctx.make_path_as_body_const(path, const_ty),
- TypeLikeConst::Infer => self.ctx.table.next_const_var(),
+ TypeLikeConst::Infer => self.ctx.table.next_const_var(Span::Dummy),
}
}
@@ -428,7 +428,7 @@ impl<'a, 'b, 'db> ConfirmContext<'a, 'b, 'db> {
) -> GenericArg<'db> {
// Always create an inference var, even when `infer_args == false`. This helps with diagnostics,
// and I think it's also required in the presence of `impl Trait` (that must be inferred).
- self.ctx.table.next_var_for_param(param_id)
+ self.ctx.table.var_for_def(param_id, Span::Dummy)
}
fn parent_arg(&mut self, param_idx: u32, _param_id: GenericParamId) -> GenericArg<'db> {
@@ -609,6 +609,10 @@ impl<'a, 'b, 'db> ConfirmContext<'a, 'b, 'db> {
where
T: TypeFoldable<DbInterner<'db>> + Copy,
{
- self.infcx().instantiate_binder_with_fresh_vars(BoundRegionConversionTime::FnCall, value)
+ self.infcx().instantiate_binder_with_fresh_vars(
+ self.expr.into(),
+ BoundRegionConversionTime::FnCall,
+ value,
+ )
}
}
diff --git a/crates/hir-ty/src/method_resolution/probe.rs b/crates/hir-ty/src/method_resolution/probe.rs
index afdc62183e..8a28b16724 100644
--- a/crates/hir-ty/src/method_resolution/probe.rs
+++ b/crates/hir-ty/src/method_resolution/probe.rs
@@ -284,7 +284,8 @@ impl<'a, 'db> MethodResolutionContext<'a, 'db> {
// special handling for this "trivial case" is a good idea.
let infcx = self.infcx;
- let (self_ty, var_values) = infcx.instantiate_canonical(&query_input);
+ let (self_ty, var_values) =
+ infcx.instantiate_canonical(self.call_span, &query_input);
debug!(?self_ty, ?query_input, "probe_op: Mode::Path");
let prev_opaque_entries =
self.infcx.inner.borrow_mut().opaque_types().num_entries();
@@ -380,7 +381,8 @@ impl<'a, 'db> MethodResolutionContext<'a, 'db> {
// chain to support recursive calls. We do error if the final
// infer var is not an opaque.
let infcx = self.infcx;
- let (self_ty, inference_vars) = infcx.instantiate_canonical(self_ty);
+ let (self_ty, inference_vars) =
+ infcx.instantiate_canonical(self.receiver_span, self_ty);
let prev_opaque_entries = infcx.inner.borrow_mut().opaque_types().num_entries();
let self_ty_is_opaque = |ty: Ty<'_>| {
@@ -921,7 +923,7 @@ impl<'a, 'db, Choice: ProbeChoice<'db>> ProbeContext<'a, 'db, Choice> {
// will still match the original object type, but it won't pollute our
// type variables in any form, so just do that!
let (QueryResponse { value: generalized_self_ty, .. }, _ignored_var_values) =
- self.infcx().instantiate_canonical(self_ty);
+ self.infcx().instantiate_canonical(self.ctx.call_span, self_ty);
self.assemble_inherent_candidates_from_object(generalized_self_ty);
self.assemble_inherent_impl_candidates_for_type(
@@ -1117,7 +1119,7 @@ impl<'a, 'db, Choice: ProbeChoice<'db>> ProbeContext<'a, 'db, Choice> {
#[instrument(level = "debug", skip(self))]
fn assemble_extension_candidates_for_trait(&mut self, trait_def_id: TraitId) {
- let trait_args = self.infcx().fresh_args_for_item(trait_def_id.into());
+ let trait_args = self.infcx().fresh_args_for_item(self.ctx.call_span, trait_def_id.into());
let trait_ref = TraitRef::new_from_args(self.interner(), trait_def_id.into(), trait_args);
self.with_trait_item(trait_def_id, |this, item| {
@@ -1510,6 +1512,7 @@ impl<'a, 'db, Choice: ProbeChoice<'db>> ProbeContext<'a, 'db, Choice> {
}
TraitCandidate(trait_ref) => self.infcx().probe(|_| {
let trait_ref = self.infcx().instantiate_binder_with_fresh_vars(
+ self.ctx.call_span,
BoundRegionConversionTime::FnCall,
trait_ref,
);
@@ -1574,7 +1577,8 @@ impl<'a, 'db, Choice: ProbeChoice<'db>> ProbeContext<'a, 'db, Choice> {
match probe.kind {
InherentImplCandidate { impl_def_id, .. } => {
- let impl_args = self.infcx().fresh_args_for_item(impl_def_id.into());
+ let impl_args =
+ self.infcx().fresh_args_for_item(self.ctx.call_span, impl_def_id.into());
let impl_ty =
self.db().impl_self_ty(impl_def_id).instantiate(self.interner(), impl_args);
(xform_self_ty, xform_ret_ty) =
@@ -1632,6 +1636,7 @@ impl<'a, 'db, Choice: ProbeChoice<'db>> ProbeContext<'a, 'db, Choice> {
}
let trait_ref = self.infcx().instantiate_binder_with_fresh_vars(
+ self.ctx.call_span,
BoundRegionConversionTime::FnCall,
poly_trait_ref,
);
@@ -1667,6 +1672,7 @@ impl<'a, 'db, Choice: ProbeChoice<'db>> ProbeContext<'a, 'db, Choice> {
}
ObjectCandidate(poly_trait_ref) | WhereClauseCandidate(poly_trait_ref) => {
let trait_ref = self.infcx().instantiate_binder_with_fresh_vars(
+ self.ctx.call_span,
BoundRegionConversionTime::FnCall,
poly_trait_ref,
);
@@ -2029,8 +2035,12 @@ impl<'a, 'db, Choice: ProbeChoice<'db>> ProbeContext<'a, 'db, Choice> {
// In general, during probe we erase regions.
Region::new_erased(self.interner()).into()
}
- GenericParamId::TypeParamId(_) => self.infcx().next_ty_var().into(),
- GenericParamId::ConstParamId(_) => self.infcx().next_const_var().into(),
+ GenericParamId::TypeParamId(_) => {
+ self.infcx().next_ty_var(self.ctx.call_span).into()
+ }
+ GenericParamId::ConstParamId(_) => {
+ self.infcx().next_const_var(self.ctx.call_span).into()
+ }
}
}
},
diff --git a/crates/hir-ty/src/next_solver/format_proof_tree.rs b/crates/hir-ty/src/next_solver/format_proof_tree.rs
index 66da6d5400..4b2f66a17d 100644
--- a/crates/hir-ty/src/next_solver/format_proof_tree.rs
+++ b/crates/hir-ty/src/next_solver/format_proof_tree.rs
@@ -3,7 +3,7 @@ use serde_derive::{Deserialize, Serialize};
use crate::next_solver::inspect::{InspectCandidate, InspectGoal};
use crate::next_solver::{AnyImplId, infer::InferCtxt};
-use crate::next_solver::{DbInterner, Span};
+use crate::{Span, next_solver::DbInterner};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProofTreeData {
@@ -59,7 +59,7 @@ impl<'a, 'db> ProofTreeSerializer<'a, 'db> {
let mut nested = Vec::new();
self.infcx.probe(|_| {
- for nested_goal in candidate.instantiate_nested_goals() {
+ for nested_goal in candidate.instantiate_nested_goals(Span::Dummy) {
nested.push(self.serialize_goal(&nested_goal));
}
});
diff --git a/crates/hir-ty/src/next_solver/fulfill.rs b/crates/hir-ty/src/next_solver/fulfill.rs
index cd0cb59760..ba9cd39d44 100644
--- a/crates/hir-ty/src/next_solver/fulfill.rs
+++ b/crates/hir-ty/src/next_solver/fulfill.rs
@@ -9,17 +9,20 @@ use rustc_next_trait_solver::{
};
use rustc_type_ir::{
Interner, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
- inherent::{IntoKind, Span as _},
+ inherent::IntoKind,
solve::{Certainty, NoSolution},
};
-use crate::next_solver::{
- DbInterner, SolverContext, SolverDefId, Span, Ty, TyKind, TypingMode,
- infer::{
- InferCtxt,
- traits::{PredicateObligation, PredicateObligations},
+use crate::{
+ Span,
+ next_solver::{
+ DbInterner, SolverContext, SolverDefId, Ty, TyKind, TypingMode,
+ infer::{
+ InferCtxt,
+ traits::{PredicateObligation, PredicateObligations},
+ },
+ inspect::ProofTreeVisitor,
},
- inspect::ProofTreeVisitor,
};
type PendingObligations<'db> =
@@ -97,7 +100,7 @@ impl<'db> ObligationStorage<'db> {
let goal = o.as_goal();
let result = <&SolverContext<'db>>::from(infcx).evaluate_root_goal(
goal,
- Span::dummy(),
+ o.cause.span(),
stalled_on.take(),
);
matches!(result, Ok(GoalEvaluation { has_changed: HasChanged::Yes, .. }))
@@ -169,7 +172,9 @@ impl<'db> FulfillmentCtxt<'db> {
let goal = obligation.as_goal();
let delegate = <&SolverContext<'db>>::from(infcx);
- if let Some(certainty) = delegate.compute_goal_fast_path(goal, Span::dummy()) {
+ if let Some(certainty) =
+ delegate.compute_goal_fast_path(goal, obligation.cause.span())
+ {
match certainty {
Certainty::Yes => {}
Certainty::Maybe { .. } => {
@@ -179,9 +184,11 @@ impl<'db> FulfillmentCtxt<'db> {
continue;
}
- let result = delegate.evaluate_root_goal(goal, Span::dummy(), stalled_on);
+ let result = delegate.evaluate_root_goal(goal, obligation.cause.span(), stalled_on);
infcx.inspect_evaluated_obligation(&obligation, &result, || {
- Some(delegate.evaluate_root_goal_for_proof_tree(goal, Span::dummy()).1)
+ Some(
+ delegate.evaluate_root_goal_for_proof_tree(goal, obligation.cause.span()).1,
+ )
});
let GoalEvaluation { goal: _, certainty, has_changed, stalled_on } = match result {
Ok(result) => result,
@@ -259,6 +266,7 @@ impl<'db> FulfillmentCtxt<'db> {
obl.as_goal(),
&mut StalledOnCoroutines {
stalled_coroutines,
+ span: obl.cause.span(),
cache: Default::default(),
},
)
@@ -280,12 +288,17 @@ impl<'db> FulfillmentCtxt<'db> {
/// so we want to keep this visitor *precise* too.
pub struct StalledOnCoroutines<'a, 'db> {
pub stalled_coroutines: &'a [SolverDefId],
+ pub span: Span,
pub cache: FxHashSet<Ty<'db>>,
}
impl<'db> ProofTreeVisitor<'db> for StalledOnCoroutines<'_, 'db> {
type Result = ControlFlow<()>;
+ fn span(&self) -> Span {
+ self.span
+ }
+
fn visit_goal(&mut self, inspect_goal: &super::inspect::InspectGoal<'_, 'db>) -> Self::Result {
inspect_goal.goal().predicate.visit_with(self)?;
diff --git a/crates/hir-ty/src/next_solver/infer/at.rs b/crates/hir-ty/src/next_solver/infer/at.rs
index dc0b584084..4784edf60f 100644
--- a/crates/hir-ty/src/next_solver/infer/at.rs
+++ b/crates/hir-ty/src/next_solver/infer/at.rs
@@ -28,13 +28,12 @@
use rustc_type_ir::{
FnSig, GenericArgKind, TypeFoldable, TypingMode, Variance,
error::ExpectedFound,
- inherent::Span as _,
relate::{Relate, TypeRelation, solver_relating::RelateExt},
};
use crate::next_solver::{
AliasTerm, AliasTy, Binder, Const, DbInterner, GenericArg, Goal, ParamEnv,
- PolyExistentialProjection, PolyExistentialTraitRef, PolyFnSig, Predicate, Region, Span, Term,
+ PolyExistentialProjection, PolyExistentialTraitRef, PolyFnSig, Predicate, Region, Term,
TraitRef, Ty,
fulfill::NextSolverError,
infer::relate::lattice::{LatticeOp, LatticeOpKind},
@@ -109,7 +108,7 @@ impl<'a, 'db> At<'a, 'db> {
expected,
Variance::Contravariant,
actual,
- Span::dummy(),
+ self.cause.span(),
)
.map(|goals| self.goals_to_obligations(goals))
}
@@ -125,7 +124,7 @@ impl<'a, 'db> At<'a, 'db> {
expected,
Variance::Covariant,
actual,
- Span::dummy(),
+ self.cause.span(),
)
.map(|goals| self.goals_to_obligations(goals))
}
@@ -141,7 +140,7 @@ impl<'a, 'db> At<'a, 'db> {
expected,
Variance::Invariant,
actual,
- Span::dummy(),
+ self.cause.span(),
)
.map(|goals| self.goals_to_obligations(goals))
}
diff --git a/crates/hir-ty/src/next_solver/infer/canonical/instantiate.rs b/crates/hir-ty/src/next_solver/infer/canonical/instantiate.rs
index 1738552a8e..bda418cf20 100644
--- a/crates/hir-ty/src/next_solver/infer/canonical/instantiate.rs
+++ b/crates/hir-ty/src/next_solver/infer/canonical/instantiate.rs
@@ -404,13 +404,17 @@ impl<'db> InferCtxt<'db> {
if kind.universe() != UniverseIndex::ROOT {
// A variable from inside a binder of the query. While ideally these shouldn't
// exist at all, we have to deal with them for now.
- self.instantiate_canonical_var(kind, var_values, |u| universe_map[u.as_usize()])
+ self.instantiate_canonical_var(cause.span(), kind, var_values, |u| {
+ universe_map[u.as_usize()]
+ })
} else if kind.is_existential() {
match opt_values[BoundVar::new(var_values.len())] {
Some(k) => k,
- None => self.instantiate_canonical_var(kind, var_values, |u| {
- universe_map[u.as_usize()]
- }),
+ None => {
+ self.instantiate_canonical_var(cause.span(), kind, var_values, |u| {
+ universe_map[u.as_usize()]
+ })
+ }
}
} else {
// For placeholders which were already part of the input, we simply map this
diff --git a/crates/hir-ty/src/next_solver/infer/canonical/mod.rs b/crates/hir-ty/src/next_solver/infer/canonical/mod.rs
index 1fefc0f265..a5e29e7836 100644
--- a/crates/hir-ty/src/next_solver/infer/canonical/mod.rs
+++ b/crates/hir-ty/src/next_solver/infer/canonical/mod.rs
@@ -21,10 +21,13 @@
//!
//! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html
-use crate::next_solver::{
- ArgOutlivesPredicate, Canonical, CanonicalVarValues, Const, DbInterner, GenericArg,
- OpaqueTypeKey, PlaceholderConst, PlaceholderRegion, PlaceholderType, Region, Ty, TyKind,
- infer::InferCtxt,
+use crate::{
+ Span,
+ next_solver::{
+ ArgOutlivesPredicate, Canonical, CanonicalVarValues, Const, DbInterner, GenericArg,
+ OpaqueTypeKey, PlaceholderConst, PlaceholderRegion, PlaceholderType, Region, Ty, TyKind,
+ infer::InferCtxt,
+ },
};
use instantiate::CanonicalExt;
use macros::{TypeFoldable, TypeVisitable};
@@ -50,6 +53,7 @@ impl<'db> InferCtxt<'db> {
/// for each of the canonical inputs to your query.
pub fn instantiate_canonical<T>(
&self,
+ span: Span,
canonical: &Canonical<'db, T>,
) -> (T, CanonicalVarValues<'db>)
where
@@ -71,7 +75,9 @@ impl<'db> InferCtxt<'db> {
let var_values = CanonicalVarValues::instantiate(
self.interner,
canonical.var_kinds,
- |var_values, info| self.instantiate_canonical_var(info, var_values, |ui| universes[ui]),
+ |var_values, info| {
+ self.instantiate_canonical_var(span, info, var_values, |ui| universes[ui])
+ },
);
let result = canonical.instantiate(self.interner, &var_values);
(result, var_values)
@@ -87,13 +93,14 @@ impl<'db> InferCtxt<'db> {
/// We should somehow deduplicate all of this.
pub fn instantiate_canonical_var(
&self,
+ span: Span,
cv_info: CanonicalVarKind<DbInterner<'db>>,
previous_var_values: &[GenericArg<'db>],
universe_map: impl Fn(UniverseIndex) -> UniverseIndex,
) -> GenericArg<'db> {
match cv_info {
CanonicalVarKind::Ty { ui, sub_root } => {
- let vid = self.next_ty_var_id_in_universe(universe_map(ui));
+ let vid = self.next_ty_var_id_in_universe(universe_map(ui), span);
// If this inference variable is related to an earlier variable
// via subtyping, we need to add that info to the inference context.
if let Some(prev) = previous_var_values.get(sub_root.as_usize()) {
@@ -117,7 +124,7 @@ impl<'db> InferCtxt<'db> {
}
CanonicalVarKind::Region(ui) => {
- self.next_region_var_in_universe(universe_map(ui)).into()
+ self.next_region_var_in_universe(universe_map(ui), span).into()
}
CanonicalVarKind::PlaceholderRegion(PlaceholderRegion { universe, bound, .. }) => {
@@ -126,7 +133,9 @@ impl<'db> InferCtxt<'db> {
Region::new_placeholder(self.interner, placeholder_mapped).into()
}
- CanonicalVarKind::Const(ui) => self.next_const_var_in_universe(universe_map(ui)).into(),
+ CanonicalVarKind::Const(ui) => {
+ self.next_const_var_in_universe(universe_map(ui), span).into()
+ }
CanonicalVarKind::PlaceholderConst(PlaceholderConst { universe, bound, .. }) => {
let universe_mapped = universe_map(universe);
let placeholder_mapped = PlaceholderConst::new(universe_mapped, bound);
diff --git a/crates/hir-ty/src/next_solver/infer/context.rs b/crates/hir-ty/src/next_solver/infer/context.rs
index 397986e2ed..9ea4665000 100644
--- a/crates/hir-ty/src/next_solver/infer/context.rs
+++ b/crates/hir-ty/src/next_solver/infer/context.rs
@@ -7,10 +7,13 @@ use rustc_type_ir::{
relate::combine::PredicateEmittingRelation,
};
-use crate::next_solver::{
- Binder, Const, ConstKind, DbInterner, ErrorGuaranteed, GenericArgs, OpaqueTypeKey, Region,
- SolverDefId, Span, Ty, TyKind,
- infer::opaque_types::{OpaqueHiddenType, table::OpaqueTypeStorageEntries},
+use crate::{
+ Span,
+ next_solver::{
+ Binder, Const, ConstKind, DbInterner, ErrorGuaranteed, GenericArgs, OpaqueTypeKey, Region,
+ SolverDefId, Ty, TyKind,
+ infer::opaque_types::{OpaqueHiddenType, table::OpaqueTypeStorageEntries},
+ },
};
use super::{BoundRegionConversionTime, InferCtxt, relate::RelateResult};
@@ -139,26 +142,30 @@ impl<'db> rustc_type_ir::InferCtxtLike for InferCtxt<'db> {
}
fn next_ty_infer(&self) -> Ty<'db> {
- self.next_ty_var()
+ self.next_ty_var(Span::Dummy)
}
fn next_region_infer(&self) -> <Self::Interner as rustc_type_ir::Interner>::Region {
- self.next_region_var()
+ self.next_region_var(Span::Dummy)
}
fn next_const_infer(&self) -> Const<'db> {
- self.next_const_var()
+ self.next_const_var(Span::Dummy)
}
fn fresh_args_for_item(&self, def_id: SolverDefId) -> GenericArgs<'db> {
- self.fresh_args_for_item(def_id)
+ self.fresh_args_for_item(Span::Dummy, def_id)
}
fn instantiate_binder_with_infer<T: TypeFoldable<DbInterner<'db>> + Clone>(
&self,
value: Binder<'db, T>,
) -> T {
- self.instantiate_binder_with_fresh_vars(BoundRegionConversionTime::HigherRankedType, value)
+ self.instantiate_binder_with_fresh_vars(
+ Span::Dummy,
+ BoundRegionConversionTime::HigherRankedType,
+ value,
+ )
}
fn enter_forall<T: TypeFoldable<DbInterner<'db>> + Clone, U>(
diff --git a/crates/hir-ty/src/next_solver/infer/mod.rs b/crates/hir-ty/src/next_solver/infer/mod.rs
index 1eacc295c9..33003f5375 100644
--- a/crates/hir-ty/src/next_solver/infer/mod.rs
+++ b/crates/hir-ty/src/next_solver/infer/mod.rs
@@ -28,16 +28,18 @@ use rustc_type_ir::{
use snapshot::undo_log::InferCtxtUndoLogs;
use tracing::{debug, instrument};
use traits::{ObligationCause, PredicateObligations};
-use type_variable::TypeVariableOrigin;
-use unify_key::{ConstVariableOrigin, ConstVariableValue, ConstVidKey};
+use unify_key::{ConstVariableValue, ConstVidKey};
pub use crate::next_solver::infer::traits::ObligationInspector;
-use crate::next_solver::{
- ArgOutlivesPredicate, BoundConst, BoundRegion, BoundTy, BoundVariableKind, Goal, Predicate,
- SolverContext,
- fold::BoundVarReplacerDelegate,
- infer::{at::ToTrace, select::EvaluationResult, traits::PredicateObligation},
- obligation_ctxt::ObligationCtxt,
+use crate::{
+ Span,
+ next_solver::{
+ ArgOutlivesPredicate, BoundConst, BoundRegion, BoundTy, BoundVariableKind, Goal, Predicate,
+ SolverContext,
+ fold::BoundVarReplacerDelegate,
+ infer::{at::ToTrace, select::EvaluationResult, traits::PredicateObligation},
+ obligation_ctxt::ObligationCtxt,
+ },
};
use super::{
@@ -364,13 +366,14 @@ impl<'db> InferCtxtBuilder<'db> {
/// (in other words, `S(C) = V`).
pub fn build_with_canonical<T>(
mut self,
+ span: Span,
input: &CanonicalQueryInput<'db, T>,
) -> (InferCtxt<'db>, T, CanonicalVarValues<'db>)
where
T: TypeFoldable<DbInterner<'db>>,
{
let infcx = self.build(input.typing_mode.0);
- let (value, args) = infcx.instantiate_canonical(&input.canonical);
+ let (value, args) = infcx.instantiate_canonical(span, &input.canonical);
(infcx, value, args)
}
@@ -427,12 +430,13 @@ impl<'db> InferCtxt<'db> {
))
}
- pub(crate) fn insert_type_vars<T>(&self, ty: T) -> T
+ pub(crate) fn insert_type_vars<T>(&self, ty: T, span: Span) -> T
where
T: TypeFoldable<DbInterner<'db>>,
{
struct Folder<'a, 'db> {
infcx: &'a InferCtxt<'db>,
+ span: Span,
}
impl<'db> TypeFolder<DbInterner<'db>> for Folder<'_, 'db> {
fn cx(&self) -> DbInterner<'db> {
@@ -444,7 +448,11 @@ impl<'db> InferCtxt<'db> {
return ty;
}
- if ty.is_ty_error() { self.infcx.next_ty_var() } else { ty.super_fold_with(self) }
+ if ty.is_ty_error() {
+ self.infcx.next_ty_var(self.span)
+ } else {
+ ty.super_fold_with(self)
+ }
}
fn fold_const(&mut self, ct: Const<'db>) -> Const<'db> {
@@ -453,18 +461,18 @@ impl<'db> InferCtxt<'db> {
}
if ct.is_ct_error() {
- self.infcx.next_const_var()
+ self.infcx.next_const_var(self.span)
} else {
ct.super_fold_with(self)
}
}
fn fold_region(&mut self, r: Region<'db>) -> Region<'db> {
- if r.is_error() { self.infcx.next_region_var() } else { r }
+ if r.is_error() { self.infcx.next_region_var(self.span) } else { r }
}
}
- ty.fold_with(&mut Folder { infcx: self })
+ ty.fold_with(&mut Folder { infcx: self, span })
}
/// Evaluates whether the predicate can be satisfied in the given
@@ -737,80 +745,49 @@ impl<'db> InferCtxt<'db> {
self.inner.borrow_mut().type_variables().num_vars()
}
- pub fn next_var_for_param(&self, id: GenericParamId) -> GenericArg<'db> {
- match id {
- GenericParamId::TypeParamId(_) => self.next_ty_var().into(),
- GenericParamId::ConstParamId(_) => self.next_const_var().into(),
- GenericParamId::LifetimeParamId(_) => self.next_region_var().into(),
- }
+ pub fn next_ty_var(&self, span: Span) -> Ty<'db> {
+ let vid = self.next_ty_vid(span);
+ Ty::new_var(self.interner, vid)
}
- pub fn next_ty_var(&self) -> Ty<'db> {
- self.next_ty_var_with_origin(TypeVariableOrigin { param_def_id: None })
+ pub fn next_ty_vid(&self, span: Span) -> TyVid {
+ self.next_ty_var_id_in_universe(self.universe(), span)
}
- pub fn next_ty_vid(&self) -> TyVid {
- self.inner
- .borrow_mut()
- .type_variables()
- .new_var(self.universe(), TypeVariableOrigin { param_def_id: None })
+ pub fn next_ty_var_id_in_universe(&self, universe: UniverseIndex, span: Span) -> TyVid {
+ self.inner.borrow_mut().type_variables().new_var(universe, span)
}
- pub fn next_ty_var_with_origin(&self, origin: TypeVariableOrigin) -> Ty<'db> {
- let vid = self.inner.borrow_mut().type_variables().new_var(self.universe(), origin);
+ pub fn next_ty_var_in_universe(&self, universe: UniverseIndex, span: Span) -> Ty<'db> {
+ let vid = self.next_ty_var_id_in_universe(universe, span);
Ty::new_var(self.interner, vid)
}
- pub fn next_ty_var_id_in_universe(&self, universe: UniverseIndex) -> TyVid {
- let origin = TypeVariableOrigin { param_def_id: None };
- self.inner.borrow_mut().type_variables().new_var(universe, origin)
- }
-
- pub fn next_ty_var_in_universe(&self, universe: UniverseIndex) -> Ty<'db> {
- let vid = self.next_ty_var_id_in_universe(universe);
- Ty::new_var(self.interner, vid)
+ pub fn next_const_var(&self, span: Span) -> Const<'db> {
+ let vid = self.next_const_vid(span);
+ Const::new_var(self.interner, vid)
}
- pub fn next_const_var(&self) -> Const<'db> {
- self.next_const_var_with_origin(ConstVariableOrigin {})
+ pub fn next_const_vid(&self, span: Span) -> ConstVid {
+ self.next_const_vid_in_universe(self.universe(), span)
}
- pub fn next_const_vid(&self) -> ConstVid {
+ pub fn next_const_vid_in_universe(&self, universe: UniverseIndex, span: Span) -> ConstVid {
self.inner
.borrow_mut()
.const_unification_table()
- .new_key(ConstVariableValue::Unknown {
- origin: ConstVariableOrigin {},
- universe: self.universe(),
- })
+ .new_key(ConstVariableValue::Unknown { span, universe })
.vid
}
- pub fn next_const_var_with_origin(&self, origin: ConstVariableOrigin) -> Const<'db> {
- let vid = self
- .inner
- .borrow_mut()
- .const_unification_table()
- .new_key(ConstVariableValue::Unknown { origin, universe: self.universe() })
- .vid;
- Const::new_var(self.interner, vid)
- }
-
- pub fn next_const_var_in_universe(&self, universe: UniverseIndex) -> Const<'db> {
- let origin = ConstVariableOrigin {};
- let vid = self
- .inner
- .borrow_mut()
- .const_unification_table()
- .new_key(ConstVariableValue::Unknown { origin, universe })
- .vid;
+ pub fn next_const_var_in_universe(&self, universe: UniverseIndex, span: Span) -> Const<'db> {
+ let vid = self.next_const_vid_in_universe(universe, span);
Const::new_var(self.interner, vid)
}
pub fn next_int_var(&self) -> Ty<'db> {
- let next_int_var_id =
- self.inner.borrow_mut().int_unification_table().new_key(IntVarValue::Unknown);
- Ty::new_int_var(self.interner, next_int_var_id)
+ let vid = self.next_int_vid();
+ Ty::new_int_var(self.interner, vid)
}
pub fn next_int_vid(&self) -> IntVid {
@@ -828,27 +805,27 @@ impl<'db> InferCtxt<'db> {
/// Creates a fresh region variable with the next available index.
/// The variable will be created in the maximum universe created
/// thus far, allowing it to name any region created thus far.
- pub fn next_region_var(&self) -> Region<'db> {
- self.next_region_var_in_universe(self.universe())
+ pub fn next_region_var(&self, span: Span) -> Region<'db> {
+ self.next_region_var_in_universe(self.universe(), span)
}
- pub fn next_region_vid(&self) -> RegionVid {
- self.inner.borrow_mut().unwrap_region_constraints().new_region_var(self.universe())
+ pub fn next_region_vid(&self, span: Span) -> RegionVid {
+ self.inner.borrow_mut().unwrap_region_constraints().new_region_var(self.universe(), span)
}
/// Creates a fresh region variable with the next available index
/// in the given universe; typically, you can use
/// `next_region_var` and just use the maximal universe.
- pub fn next_region_var_in_universe(&self, universe: UniverseIndex) -> Region<'db> {
+ pub fn next_region_var_in_universe(&self, universe: UniverseIndex, span: Span) -> Region<'db> {
let region_var =
- self.inner.borrow_mut().unwrap_region_constraints().new_region_var(universe);
+ self.inner.borrow_mut().unwrap_region_constraints().new_region_var(universe, span);
Region::new_var(self.interner, region_var)
}
- pub fn next_term_var_of_kind(&self, term: Term<'db>) -> Term<'db> {
+ pub fn next_term_var_of_kind(&self, term: Term<'db>, span: Span) -> Term<'db> {
match term.kind() {
- TermKind::Ty(_) => self.next_ty_var().into(),
- TermKind::Const(_) => self.next_const_var().into(),
+ TermKind::Ty(_) => self.next_ty_var(span).into(),
+ TermKind::Const(_) => self.next_const_var(span).into(),
}
}
@@ -866,24 +843,12 @@ impl<'db> InferCtxt<'db> {
self.inner.borrow_mut().unwrap_region_constraints().num_region_vars()
}
- /// Just a convenient wrapper of `next_region_var` for using during NLL.
- #[instrument(skip(self), level = "debug")]
- pub fn next_nll_region_var(&self) -> Region<'db> {
- self.next_region_var()
- }
-
- /// Just a convenient wrapper of `next_region_var` for using during NLL.
- #[instrument(skip(self), level = "debug")]
- pub fn next_nll_region_var_in_universe(&self, universe: UniverseIndex) -> Region<'db> {
- self.next_region_var_in_universe(universe)
- }
-
- fn var_for_def(&self, id: GenericParamId) -> GenericArg<'db> {
+ pub fn var_for_def(&self, id: GenericParamId, span: Span) -> GenericArg<'db> {
match id {
GenericParamId::LifetimeParamId(_) => {
// Create a region inference variable for the given
// region parameter definition.
- self.next_region_var().into()
+ self.next_region_var(span).into()
}
GenericParamId::TypeParamId(_) => {
// Create a type inference variable for the given
@@ -894,41 +859,27 @@ impl<'db> InferCtxt<'db> {
// used in a path such as `Foo::<T, U>::new()` will
// use an inference variable for `C` with `[T, U]`
// as the generic parameters for the default, `(T, U)`.
- let ty_var_id = self
- .inner
- .borrow_mut()
- .type_variables()
- .new_var(self.universe(), TypeVariableOrigin { param_def_id: None });
-
- Ty::new_var(self.interner, ty_var_id).into()
- }
- GenericParamId::ConstParamId(_) => {
- let origin = ConstVariableOrigin {};
- let const_var_id = self
- .inner
- .borrow_mut()
- .const_unification_table()
- .new_key(ConstVariableValue::Unknown { origin, universe: self.universe() })
- .vid;
- Const::new_var(self.interner, const_var_id).into()
+ self.next_ty_var(span).into()
}
+ GenericParamId::ConstParamId(_) => self.next_const_var(span).into(),
}
}
/// Given a set of generics defined on a type or impl, returns the generic parameters mapping
/// each type/region parameter to a fresh inference variable.
- pub fn fresh_args_for_item(&self, def_id: SolverDefId) -> GenericArgs<'db> {
- GenericArgs::for_item(self.interner, def_id, |_index, kind, _| self.var_for_def(kind))
+ pub fn fresh_args_for_item(&self, span: Span, def_id: SolverDefId) -> GenericArgs<'db> {
+ GenericArgs::for_item(self.interner, def_id, |_index, kind, _| self.var_for_def(kind, span))
}
/// Like `fresh_args_for_item()`, but first uses the args from `first`.
pub fn fill_rest_fresh_args(
&self,
+ span: Span,
def_id: SolverDefId,
first: impl IntoIterator<Item = GenericArg<'db>>,
) -> GenericArgs<'db> {
GenericArgs::fill_rest(self.interner, def_id, first, |_index, kind, _| {
- self.var_for_def(kind)
+ self.var_for_def(kind, span)
})
}
@@ -1141,7 +1092,7 @@ impl<'db> InferCtxt<'db> {
pub fn probe_const_var(&self, vid: ConstVid) -> Result<Const<'db>, UniverseIndex> {
match self.inner.borrow_mut().const_unification_table().probe_value(vid) {
ConstVariableValue::Known { value } => Ok(value),
- ConstVariableValue::Unknown { origin: _, universe } => Err(universe),
+ ConstVariableValue::Unknown { span: _, universe } => Err(universe),
}
}
@@ -1154,6 +1105,7 @@ impl<'db> InferCtxt<'db> {
// use [`InferCtxt::enter_forall`] instead.
pub fn instantiate_binder_with_fresh_vars<T>(
&self,
+ span: Span,
_lbrct: BoundRegionConversionTime,
value: Binder<'db, T>,
) -> T
@@ -1169,9 +1121,9 @@ impl<'db> InferCtxt<'db> {
for bound_var_kind in bound_vars {
let arg: GenericArg<'db> = match bound_var_kind {
- BoundVariableKind::Ty(_) => self.next_ty_var().into(),
- BoundVariableKind::Region(_) => self.next_region_var().into(),
- BoundVariableKind::Const => self.next_const_var().into(),
+ BoundVariableKind::Ty(_) => self.next_ty_var(span).into(),
+ BoundVariableKind::Region(_) => self.next_region_var(span).into(),
+ BoundVariableKind::Const => self.next_const_var(span).into(),
};
args.push(arg);
}
diff --git a/crates/hir-ty/src/next_solver/infer/region_constraints/mod.rs b/crates/hir-ty/src/next_solver/infer/region_constraints/mod.rs
index 7bb39519f5..dda1bb56ef 100644
--- a/crates/hir-ty/src/next_solver/infer/region_constraints/mod.rs
+++ b/crates/hir-ty/src/next_solver/infer/region_constraints/mod.rs
@@ -15,9 +15,12 @@ use self::CombineMapType::*;
use self::UndoLog::*;
use super::MemberConstraint;
use super::unify_key::RegionVidKey;
-use crate::next_solver::infer::snapshot::undo_log::{InferCtxtUndoLogs, Snapshot};
use crate::next_solver::infer::unify_key::RegionVariableValue;
use crate::next_solver::{AliasTy, Binder, DbInterner, ParamTy, PlaceholderType, Region, Ty};
+use crate::{
+ Span,
+ next_solver::infer::snapshot::undo_log::{InferCtxtUndoLogs, Snapshot},
+};
#[derive(Debug, Clone, Default)]
pub struct RegionConstraintStorage<'db> {
@@ -281,6 +284,7 @@ pub struct RegionVariableInfo {
// This would be currently unsound as it would cause us to drop the universe
// changes in `lexical_region_resolve`.
pub universe: UniverseIndex,
+ pub span: Span,
}
pub(crate) struct RegionSnapshot {
@@ -372,8 +376,8 @@ impl<'db> RegionConstraintCollector<'db, '_> {
self.storage.any_unifications = snapshot.any_unifications;
}
- pub(super) fn new_region_var(&mut self, universe: UniverseIndex) -> RegionVid {
- let vid = self.storage.var_infos.push(RegionVariableInfo { universe });
+ pub(super) fn new_region_var(&mut self, universe: UniverseIndex, span: Span) -> RegionVid {
+ let vid = self.storage.var_infos.push(RegionVariableInfo { universe, span });
let u_vid = self.unification_table_mut().new_key(RegionVariableValue::Unknown { universe });
assert_eq!(vid, u_vid.vid);
@@ -459,6 +463,7 @@ impl<'db> RegionConstraintCollector<'db, '_> {
pub(super) fn lub_regions(
&mut self,
db: DbInterner<'db>,
+ origin: Span,
a: Region<'db>,
b: Region<'db>,
) -> Region<'db> {
@@ -470,13 +475,14 @@ impl<'db> RegionConstraintCollector<'db, '_> {
} else if a == b {
a // LUB(a,a) = a
} else {
- self.combine_vars(db, Lub, a, b)
+ self.combine_vars(db, Lub, a, b, origin)
}
}
pub(super) fn glb_regions(
&mut self,
db: DbInterner<'db>,
+ origin: Span,
a: Region<'db>,
b: Region<'db>,
) -> Region<'db> {
@@ -490,7 +496,7 @@ impl<'db> RegionConstraintCollector<'db, '_> {
} else if a == b {
a // GLB(a,a) = a
} else {
- self.combine_vars(db, Glb, a, b)
+ self.combine_vars(db, Glb, a, b, origin)
}
}
@@ -529,6 +535,7 @@ impl<'db> RegionConstraintCollector<'db, '_> {
t: CombineMapType,
a: Region<'db>,
b: Region<'db>,
+ origin: Span,
) -> Region<'db> {
let vars = TwoRegions { a, b };
if let Some(c) = self.combine_map(t.clone()).get(&vars) {
@@ -537,7 +544,7 @@ impl<'db> RegionConstraintCollector<'db, '_> {
let a_universe = self.universe(a);
let b_universe = self.universe(b);
let c_universe = cmp::max(a_universe, b_universe);
- let c = self.new_region_var(c_universe);
+ let c = self.new_region_var(c_universe, origin);
self.combine_map(t.clone()).insert(vars.clone(), c);
self.undo_log.push(AddCombination(t.clone(), vars));
let new_r = Region::new_var(cx, c);
@@ -567,8 +574,15 @@ impl<'db> RegionConstraintCollector<'db, '_> {
}
}
- pub fn vars_since_snapshot(&self, value_count: usize) -> Range<RegionVid> {
- RegionVid::from(value_count)..RegionVid::from(self.storage.unification_table.len())
+ pub fn vars_since_snapshot(&self, value_count: usize) -> (Range<RegionVid>, Vec<Span>) {
+ let range =
+ RegionVid::from(value_count)..RegionVid::from(self.storage.unification_table.len());
+ (
+ range.clone(),
+ (range.start.as_usize()..range.end.as_usize())
+ .map(|index| self.storage.var_infos[RegionVid::from_usize(index)].span)
+ .collect(),
+ )
}
/// See `InferCtxt::region_constraints_added_in_snapshot`.
diff --git a/crates/hir-ty/src/next_solver/infer/relate/generalize.rs b/crates/hir-ty/src/next_solver/infer/relate/generalize.rs
index d621dd4906..152592683a 100644
--- a/crates/hir-ty/src/next_solver/infer/relate/generalize.rs
+++ b/crates/hir-ty/src/next_solver/infer/relate/generalize.rs
@@ -16,7 +16,6 @@ use tracing::{debug, instrument, warn};
use super::{
PredicateEmittingRelation, Relate, RelateResult, StructurallyRelateAliases, TypeRelation,
};
-use crate::next_solver::infer::unify_key::ConstVariableValue;
use crate::next_solver::infer::{InferCtxt, relate};
use crate::next_solver::util::MaxUniverse;
use crate::next_solver::{
@@ -24,6 +23,7 @@ use crate::next_solver::{
Term, TermVid, Ty, TyKind, TypingMode, UnevaluatedConst,
};
use crate::next_solver::{GenericArgs, infer::type_variable::TypeVariableValue};
+use crate::{Span, next_solver::infer::unify_key::ConstVariableValue};
impl<'db> InferCtxt<'db> {
/// The idea is that we should ensure that the type variable `target_vid`
@@ -60,6 +60,7 @@ impl<'db> InferCtxt<'db> {
// `?1 <: ?3`.
let Generalization { value_may_be_infer: generalized_ty, has_unconstrained_ty_var } = self
.generalize(
+ relation.span(),
relation.structurally_relate_aliases(),
target_vid,
instantiation_variance,
@@ -179,6 +180,7 @@ impl<'db> InferCtxt<'db> {
// constants and generic expressions are not yet handled correctly.
let Generalization { value_may_be_infer: generalized_ct, has_unconstrained_ty_var } = self
.generalize(
+ relation.span(),
relation.structurally_relate_aliases(),
target_vid,
Variance::Invariant,
@@ -220,6 +222,7 @@ impl<'db> InferCtxt<'db> {
/// This checks for cycles -- that is, whether `source_term` references `target_vid`.
fn generalize<T: Into<Term<'db>> + Relate<DbInterner<'db>>>(
&self,
+ span: Span,
structurally_relate_aliases: StructurallyRelateAliases,
target_vid: impl Into<TermVid>,
ambient_variance: Variance,
@@ -238,6 +241,7 @@ impl<'db> InferCtxt<'db> {
let mut generalizer = Generalizer {
infcx: self,
+ span,
structurally_relate_aliases,
root_vid,
for_universe,
@@ -270,6 +274,8 @@ impl<'db> InferCtxt<'db> {
struct Generalizer<'me, 'db> {
infcx: &'me InferCtxt<'db>,
+ span: Span,
+
/// Whether aliases should be related structurally. If not, we have to
/// be careful when generalizing aliases.
structurally_relate_aliases: StructurallyRelateAliases,
@@ -318,7 +324,7 @@ impl<'db> Generalizer<'_, 'db> {
/// if we're currently in a bivariant context.
fn next_ty_var_for_alias(&mut self) -> Ty<'db> {
self.has_unconstrained_ty_var |= self.ambient_variance == Variance::Bivariant;
- self.infcx.next_ty_var_in_universe(self.for_universe)
+ self.infcx.next_ty_var_in_universe(self.for_universe, self.span)
}
/// An occurs check failure inside of an alias does not mean
@@ -477,7 +483,7 @@ impl<'db> TypeRelation<DbInterner<'db>> for Generalizer<'_, 'db> {
Variance::Covariant | Variance::Contravariant => (),
}
- let origin = inner.type_variables().var_origin(vid);
+ let origin = inner.type_variables().var_span(vid);
let new_var_id =
inner.type_variables().new_var(self.for_universe, origin);
// If we're in the new solver and create a new inference
@@ -579,7 +585,7 @@ impl<'db> TypeRelation<DbInterner<'db>> for Generalizer<'_, 'db> {
}
}
- Ok(self.infcx.next_region_var_in_universe(self.for_universe))
+ Ok(self.infcx.next_region_var_in_universe(self.for_universe, self.span))
}
#[instrument(level = "debug", skip(self, c2), ret)]
@@ -605,13 +611,13 @@ impl<'db> TypeRelation<DbInterner<'db>> for Generalizer<'_, 'db> {
drop(inner);
self.relate(u, u)
}
- ConstVariableValue::Unknown { origin, universe } => {
+ ConstVariableValue::Unknown { span, universe } => {
if self.for_universe.can_name(universe) {
Ok(c)
} else {
let new_var_id = variable_table
.new_key(ConstVariableValue::Unknown {
- origin,
+ span,
universe: self.for_universe,
})
.vid;
diff --git a/crates/hir-ty/src/next_solver/infer/relate/lattice.rs b/crates/hir-ty/src/next_solver/infer/relate/lattice.rs
index 3522827a9e..0443dbd814 100644
--- a/crates/hir-ty/src/next_solver/infer/relate/lattice.rs
+++ b/crates/hir-ty/src/next_solver/infer/relate/lattice.rs
@@ -19,7 +19,7 @@
use rustc_type_ir::{
AliasRelationDirection, Interner, TypeVisitableExt, Upcast, Variance,
- inherent::{IntoKind, Span as _},
+ inherent::IntoKind,
relate::{
Relate, StructurallyRelateAliases, TypeRelation, VarianceDiagInfo,
combine::{
@@ -28,13 +28,16 @@ use rustc_type_ir::{
},
};
-use crate::next_solver::{
- AliasTy, Binder, Const, DbInterner, GenericArgs, Goal, ParamEnv, Predicate, PredicateKind,
- Region, SolverDefId, Span, Ty, TyKind,
- infer::{
- InferCtxt, TypeTrace,
- relate::RelateResult,
- traits::{Obligation, PredicateObligations},
+use crate::{
+ Span,
+ next_solver::{
+ AliasTy, Binder, Const, DbInterner, GenericArgs, Goal, ParamEnv, Predicate, PredicateKind,
+ Region, SolverDefId, Ty, TyKind,
+ infer::{
+ InferCtxt, TypeTrace,
+ relate::RelateResult,
+ traits::{Obligation, PredicateObligations},
+ },
},
};
@@ -154,12 +157,12 @@ impl<'db> TypeRelation<DbInterner<'db>> for LatticeOp<'_, 'db> {
// iterate on the subtype obligations that are returned, but I
// think this suffices. -nmatsakis
(TyKind::Infer(rustc_type_ir::TyVar(..)), _) => {
- let v = infcx.next_ty_var();
+ let v = infcx.next_ty_var(self.span());
self.relate_bound(v, b, a)?;
Ok(v)
}
(_, TyKind::Infer(rustc_type_ir::TyVar(..))) => {
- let v = infcx.next_ty_var();
+ let v = infcx.next_ty_var(self.span());
self.relate_bound(v, a, b)?;
Ok(v)
}
@@ -178,10 +181,10 @@ impl<'db> TypeRelation<DbInterner<'db>> for LatticeOp<'_, 'db> {
let mut constraints = inner.unwrap_region_constraints();
Ok(match self.kind {
// GLB(&'static u8, &'a u8) == &RegionLUB('static, 'a) u8 == &'static u8
- LatticeOpKind::Glb => constraints.lub_regions(self.cx(), a, b),
+ LatticeOpKind::Glb => constraints.lub_regions(self.cx(), self.span(), a, b),
// LUB(&'static u8, &'a u8) == &RegionGLB('static, 'a) u8 == &'a u8
- LatticeOpKind::Lub => constraints.glb_regions(self.cx(), a, b),
+ LatticeOpKind::Lub => constraints.glb_regions(self.cx(), self.span(), a, b),
})
}
@@ -239,7 +242,7 @@ impl<'infcx, 'db> LatticeOp<'infcx, 'db> {
impl<'db> PredicateEmittingRelation<InferCtxt<'db>> for LatticeOp<'_, 'db> {
fn span(&self) -> Span {
- Span::dummy()
+ self.trace.cause.span()
}
fn structurally_relate_aliases(&self) -> StructurallyRelateAliases {
diff --git a/crates/hir-ty/src/next_solver/infer/select.rs b/crates/hir-ty/src/next_solver/infer/select.rs
index bbfc8a4757..d6f0379c11 100644
--- a/crates/hir-ty/src/next_solver/infer/select.rs
+++ b/crates/hir-ty/src/next_solver/infer/select.rs
@@ -10,6 +10,7 @@ use rustc_type_ir::{
};
use crate::{
+ Span,
db::InternedOpaqueTyId,
next_solver::{
AnyImplId, Const, ErrorGuaranteed, GenericArgs, Goal, TraitRef, Ty, TypeError,
@@ -263,18 +264,24 @@ impl<'db> InferCtxt<'db> {
) -> SelectionResult<'db, Selection<'db>> {
self.visit_proof_tree(
Goal::new(self.interner, obligation.param_env, obligation.predicate),
- &mut Select {},
+ &mut Select { span: obligation.cause.span() },
)
.break_value()
.unwrap()
}
}
-struct Select {}
+struct Select {
+ span: Span,
+}
impl<'db> ProofTreeVisitor<'db> for Select {
type Result = ControlFlow<SelectionResult<'db, Selection<'db>>>;
+ fn span(&self) -> Span {
+ self.span
+ }
+
fn visit_goal(&mut self, goal: &InspectGoal<'_, 'db>) -> Self::Result {
let mut candidates = goal.candidates();
candidates.retain(|cand| cand.result().is_ok());
@@ -286,7 +293,10 @@ impl<'db> ProofTreeVisitor<'db> for Select {
// One candidate, no need to winnow.
if candidates.len() == 1 {
- return ControlFlow::Break(Ok(to_selection(candidates.into_iter().next().unwrap())));
+ return ControlFlow::Break(Ok(to_selection(
+ self.span,
+ candidates.into_iter().next().unwrap(),
+ )));
}
// Don't winnow until `Certainty::Yes` -- we don't need to winnow until
@@ -311,7 +321,7 @@ impl<'db> ProofTreeVisitor<'db> for Select {
}
}
- ControlFlow::Break(Ok(to_selection(candidates.into_iter().next().unwrap())))
+ ControlFlow::Break(Ok(to_selection(self.span, candidates.into_iter().next().unwrap())))
}
}
@@ -368,7 +378,7 @@ fn candidate_should_be_dropped_in_favor_of<'db>(
}
}
-fn to_selection<'db>(cand: InspectCandidate<'_, 'db>) -> Option<Selection<'db>> {
+fn to_selection<'db>(span: Span, cand: InspectCandidate<'_, 'db>) -> Option<Selection<'db>> {
if let Certainty::Maybe { .. } = cand.shallow_certainty() {
return None;
}
@@ -376,7 +386,7 @@ fn to_selection<'db>(cand: InspectCandidate<'_, 'db>) -> Option<Selection<'db>>
let nested = match cand.result().expect("expected positive result") {
Certainty::Yes => Vec::new(),
Certainty::Maybe { .. } => cand
- .instantiate_nested_goals()
+ .instantiate_nested_goals(span)
.into_iter()
.map(|nested| {
Obligation::new(
@@ -396,7 +406,7 @@ fn to_selection<'db>(cand: InspectCandidate<'_, 'db>) -> Option<Selection<'db>>
// For impl candidates, we do the rematch manually to compute the args.
ImplSource::UserDefined(ImplSourceUserDefinedData {
impl_def_id,
- args: cand.instantiate_impl_args(),
+ args: cand.instantiate_impl_args(span),
nested,
})
}
diff --git a/crates/hir-ty/src/next_solver/infer/snapshot/fudge.rs b/crates/hir-ty/src/next_solver/infer/snapshot/fudge.rs
index 5902f8043b..7cb3ab09d4 100644
--- a/crates/hir-ty/src/next_solver/infer/snapshot/fudge.rs
+++ b/crates/hir-ty/src/next_solver/infer/snapshot/fudge.rs
@@ -5,17 +5,19 @@ use ena::{
unify::{self as ut, UnifyKey},
};
use rustc_type_ir::{
- ConstVid, FloatVid, IntVid, RegionKind, RegionVid, TyVid, TypeFoldable, TypeFolder,
- TypeSuperFoldable, TypeVisitableExt, inherent::IntoKind,
+ ConstVid, FloatVid, IntVid, RegionVid, TyVid, TypeFoldable, TypeFolder, TypeSuperFoldable,
+ TypeVisitableExt, inherent::IntoKind,
};
-use crate::next_solver::{
- Const, ConstKind, DbInterner, Region, Ty, TyKind,
- infer::{
- InferCtxt, UnificationTable, iter_idx_range,
- snapshot::VariableLengths,
- type_variable::TypeVariableOrigin,
- unify_key::{ConstVariableOrigin, ConstVariableValue, ConstVidKey},
+use crate::{
+ Span,
+ next_solver::{
+ Const, ConstKind, DbInterner, Region, RegionKind, Ty, TyKind,
+ infer::{
+ InferCtxt, UnificationTable, iter_idx_range,
+ snapshot::VariableLengths,
+ unify_key::{ConstVariableValue, ConstVidKey},
+ },
},
};
@@ -33,7 +35,7 @@ where
fn const_vars_since_snapshot<'db>(
table: &mut UnificationTable<'_, 'db, ConstVidKey<'db>>,
snapshot_var_len: usize,
-) -> (Range<ConstVid>, Vec<ConstVariableOrigin>) {
+) -> (Range<ConstVid>, Vec<Span>) {
let range = vars_since_snapshot(table, snapshot_var_len);
let range = range.start.vid..range.end.vid;
@@ -41,8 +43,8 @@ fn const_vars_since_snapshot<'db>(
range.clone(),
iter_idx_range(range)
.map(|index| match table.probe_value(index) {
- ConstVariableValue::Known { value: _ } => ConstVariableOrigin {},
- ConstVariableValue::Unknown { origin, universe: _ } => origin,
+ ConstVariableValue::Known { value: _ } => Span::Dummy,
+ ConstVariableValue::Unknown { span, universe: _ } => span,
})
.collect(),
)
@@ -128,11 +130,11 @@ impl<'db> InferCtxt<'db> {
}
struct SnapshotVarData {
- region_vars: Range<RegionVid>,
- type_vars: (Range<TyVid>, Vec<TypeVariableOrigin>),
+ region_vars: (Range<RegionVid>, Vec<Span>),
+ type_vars: (Range<TyVid>, Vec<Span>),
int_vars: Range<IntVid>,
float_vars: Range<FloatVid>,
- const_vars: (Range<ConstVid>, Vec<ConstVariableOrigin>),
+ const_vars: (Range<ConstVid>, Vec<Span>),
}
impl SnapshotVarData {
@@ -156,7 +158,7 @@ impl SnapshotVarData {
fn is_empty(&self) -> bool {
let SnapshotVarData { region_vars, type_vars, int_vars, float_vars, const_vars } = self;
- region_vars.is_empty()
+ region_vars.0.is_empty()
&& type_vars.0.is_empty()
&& int_vars.is_empty()
&& float_vars.is_empty()
@@ -182,8 +184,8 @@ impl<'a, 'db> TypeFolder<DbInterner<'db>> for InferenceFudger<'a, 'db> {
// This variable was created during the fudging.
// Recreate it with a fresh variable here.
let idx = vid.as_usize() - self.snapshot_vars.type_vars.0.start.as_usize();
- let origin = self.snapshot_vars.type_vars.1[idx];
- self.infcx.next_ty_var_with_origin(origin)
+ let span = self.snapshot_vars.type_vars.1[idx];
+ self.infcx.next_ty_var(span)
} else {
// This variable was created before the
// "fudging". Since we refresh all type
@@ -225,8 +227,10 @@ impl<'a, 'db> TypeFolder<DbInterner<'db>> for InferenceFudger<'a, 'db> {
fn fold_region(&mut self, r: Region<'db>) -> Region<'db> {
if let RegionKind::ReVar(vid) = r.kind() {
- if self.snapshot_vars.region_vars.contains(&vid) {
- self.infcx.next_region_var()
+ if self.snapshot_vars.region_vars.0.contains(&vid) {
+ let idx = vid.index() - self.snapshot_vars.region_vars.0.start.index();
+ let span = self.snapshot_vars.region_vars.1[idx];
+ self.infcx.next_region_var(span)
} else {
r
}
@@ -241,8 +245,8 @@ impl<'a, 'db> TypeFolder<DbInterner<'db>> for InferenceFudger<'a, 'db> {
rustc_type_ir::InferConst::Var(vid) => {
if self.snapshot_vars.const_vars.0.contains(&vid) {
let idx = vid.index() - self.snapshot_vars.const_vars.0.start.index();
- let origin = self.snapshot_vars.const_vars.1[idx];
- self.infcx.next_const_var_with_origin(origin)
+ let span = self.snapshot_vars.const_vars.1[idx];
+ self.infcx.next_const_var(span)
} else {
ct
}
diff --git a/crates/hir-ty/src/next_solver/infer/traits.rs b/crates/hir-ty/src/next_solver/infer/traits.rs
index 5b875d2960..1edf256d01 100644
--- a/crates/hir-ty/src/next_solver/infer/traits.rs
+++ b/crates/hir-ty/src/next_solver/infer/traits.rs
@@ -16,9 +16,12 @@ use rustc_type_ir::{
};
use tracing::debug;
-use crate::next_solver::{
- Clause, DbInterner, Goal, ParamEnv, PolyTraitPredicate, Predicate, Span, TraitPredicate,
- TraitRef, Ty,
+use crate::{
+ Span,
+ next_solver::{
+ Clause, DbInterner, Goal, ParamEnv, PolyTraitPredicate, Predicate, TraitPredicate,
+ TraitRef, Ty,
+ },
};
use super::InferCtxt;
@@ -33,15 +36,18 @@ use super::InferCtxt;
/// only live for a short period of time.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ObligationCause {
- // FIXME: This should contain an `ExprId`/`PatId` etc., and a cause code. But for now we
- // don't report trait solving diagnostics, so this is irrelevant.
- _private: (),
+ span: Span,
}
impl ObligationCause {
#[inline]
pub fn new() -> ObligationCause {
- ObligationCause { _private: () }
+ ObligationCause { span: Span::Dummy }
+ }
+
+ #[inline]
+ pub fn with_span(span: Span) -> ObligationCause {
+ ObligationCause { span }
}
#[inline]
@@ -53,6 +59,11 @@ impl ObligationCause {
pub fn misc() -> ObligationCause {
ObligationCause::new()
}
+
+ #[inline]
+ pub(crate) fn span(&self) -> Span {
+ self.span
+ }
}
impl Default for ObligationCause {
diff --git a/crates/hir-ty/src/next_solver/infer/type_variable.rs b/crates/hir-ty/src/next_solver/infer/type_variable.rs
index 29e7b883c9..070d2582d8 100644
--- a/crates/hir-ty/src/next_solver/infer/type_variable.rs
+++ b/crates/hir-ty/src/next_solver/infer/type_variable.rs
@@ -13,7 +13,7 @@ use rustc_type_ir::UniverseIndex;
use rustc_type_ir::inherent::Ty as _;
use tracing::debug;
-use crate::next_solver::SolverDefId;
+use crate::Span;
use crate::next_solver::Ty;
use crate::next_solver::infer::{InferCtxtUndoLogs, iter_idx_range};
@@ -94,17 +94,9 @@ pub(crate) struct TypeVariableTable<'a, 'db> {
undo_log: &'a mut InferCtxtUndoLogs<'db>,
}
-#[derive(Copy, Clone, Debug)]
-pub struct TypeVariableOrigin {
- /// `DefId` of the type parameter this was instantiated for, if any.
- ///
- /// This should only be used for diagnostics.
- pub param_def_id: Option<SolverDefId>,
-}
-
#[derive(Debug, Clone)]
pub(crate) struct TypeVariableData {
- origin: TypeVariableOrigin,
+ span: Span,
}
#[derive(Clone, Debug)]
@@ -152,12 +144,12 @@ impl<'db> TypeVariableStorage<'db> {
}
impl<'db> TypeVariableTable<'_, 'db> {
- /// Returns the origin that was given when `vid` was created.
+ /// Returns the span that was given when `vid` was created.
///
/// Note that this function does not return care whether
/// `vid` has been unified with something else or not.
- pub(crate) fn var_origin(&self, vid: TyVid) -> TypeVariableOrigin {
- self.storage.values[vid].origin
+ pub(crate) fn var_span(&self, vid: TyVid) -> Span {
+ self.storage.values[vid].span
}
/// Records that `a == b`, depending on `dir`.
@@ -195,26 +187,16 @@ impl<'db> TypeVariableTable<'_, 'db> {
self.eq_relations().union_value(vid, TypeVariableValue::Known { value: ty });
}
- /// Creates a new type variable.
- ///
- /// - `diverging`: indicates if this is a "diverging" type
- /// variable, e.g., one created as the type of a `return`
- /// expression. The code in this module doesn't care if a
- /// variable is diverging, but the main Rust type-checker will
- /// sometimes "unify" such variables with the `!` or `()` types.
- /// - `origin`: indicates *why* the type variable was created.
- /// The code in this module doesn't care, but it can be useful
- /// for improving error messages.
- pub(crate) fn new_var(&mut self, universe: UniverseIndex, origin: TypeVariableOrigin) -> TyVid {
+ pub(crate) fn new_var(&mut self, universe: UniverseIndex, span: Span) -> TyVid {
let eq_key = self.eq_relations().new_key(TypeVariableValue::Unknown { universe });
let sub_key = self.sub_unification_table().new_key(());
debug_assert_eq!(eq_key.vid, sub_key.vid);
- let index = self.storage.values.push(TypeVariableData { origin });
+ let index = self.storage.values.push(TypeVariableData { span });
debug_assert_eq!(eq_key.vid, index);
- debug!("new_var(index={:?}, universe={:?}, origin={:?})", eq_key.vid, universe, origin);
+ debug!("new_var(index={:?}, universe={:?}, span={:?})", eq_key.vid, universe, span);
index
}
@@ -268,12 +250,9 @@ impl<'db> TypeVariableTable<'_, 'db> {
}
/// Returns a range of the type variables created during the snapshot.
- pub(crate) fn vars_since_snapshot(
- &mut self,
- value_count: usize,
- ) -> (Range<TyVid>, Vec<TypeVariableOrigin>) {
+ pub(crate) fn vars_since_snapshot(&mut self, value_count: usize) -> (Range<TyVid>, Vec<Span>) {
let range = TyVid::from_usize(value_count)..TyVid::from_usize(self.num_vars());
- (range.clone(), iter_idx_range(range).map(|index| self.var_origin(index)).collect())
+ (range.clone(), iter_idx_range(range).map(|index| self.var_span(index)).collect())
}
/// Returns indices of all variables that are not yet
diff --git a/crates/hir-ty/src/next_solver/infer/unify_key.rs b/crates/hir-ty/src/next_solver/infer/unify_key.rs
index a09f65f082..07eeda255b 100644
--- a/crates/hir-ty/src/next_solver/infer/unify_key.rs
+++ b/crates/hir-ty/src/next_solver/infer/unify_key.rs
@@ -6,7 +6,10 @@ use std::marker::PhantomData;
use ena::unify::{NoError, UnifyKey, UnifyValue};
use rustc_type_ir::{ConstVid, RegionKind, RegionVid, UniverseIndex, inherent::IntoKind};
-use crate::next_solver::{Const, Region};
+use crate::{
+ Span,
+ next_solver::{Const, Region},
+};
#[derive(Clone, Debug)]
pub(crate) enum RegionVariableValue<'db> {
@@ -89,13 +92,10 @@ impl<'db> UnifyValue for RegionVariableValue<'db> {
// Generic consts.
-#[derive(Copy, Clone, Debug)]
-pub struct ConstVariableOrigin {}
-
#[derive(Clone, Debug)]
pub(crate) enum ConstVariableValue<'db> {
Known { value: Const<'db> },
- Unknown { origin: ConstVariableOrigin, universe: UniverseIndex },
+ Unknown { span: Span, universe: UniverseIndex },
}
impl<'db> ConstVariableValue<'db> {
@@ -158,8 +158,8 @@ impl<'db> UnifyValue for ConstVariableValue<'db> {
// If both sides are *unknown*, it hardly matters, does it?
(
- ConstVariableValue::Unknown { origin, universe: universe1 },
- ConstVariableValue::Unknown { origin: _, universe: universe2 },
+ ConstVariableValue::Unknown { span: origin, universe: universe1 },
+ ConstVariableValue::Unknown { span: _, universe: universe2 },
) => {
// If we unify two unbound variables, ?T and ?U, then whatever
// value they wind up taking (which must be the same value) must
@@ -167,7 +167,7 @@ impl<'db> UnifyValue for ConstVariableValue<'db> {
// universe is the minimum of the two universes, because that is
// the one which contains the fewest names in scope.
let universe = cmp::min(*universe1, *universe2);
- Ok(ConstVariableValue::Unknown { origin: *origin, universe })
+ Ok(ConstVariableValue::Unknown { span: *origin, universe })
}
}
}
diff --git a/crates/hir-ty/src/next_solver/inspect.rs b/crates/hir-ty/src/next_solver/inspect.rs
index 63a225b98f..566f72fbd8 100644
--- a/crates/hir-ty/src/next_solver/inspect.rs
+++ b/crates/hir-ty/src/next_solver/inspect.rs
@@ -6,19 +6,22 @@ use rustc_next_trait_solver::{
};
use rustc_type_ir::{
VisitorResult,
- inherent::{IntoKind, Span as _},
+ inherent::IntoKind,
solve::{Certainty, GoalSource, MaybeCause, NoSolution},
};
-use crate::next_solver::{
- DbInterner, GenericArg, GenericArgs, Goal, NormalizesTo, ParamEnv, Predicate, PredicateKind,
- QueryResult, SolverContext, Span, Term,
- fulfill::NextSolverError,
- infer::{
- InferCtxt,
- traits::{Obligation, ObligationCause},
+use crate::{
+ Span,
+ next_solver::{
+ DbInterner, GenericArg, GenericArgs, Goal, NormalizesTo, ParamEnv, Predicate,
+ PredicateKind, QueryResult, SolverContext, Term,
+ fulfill::NextSolverError,
+ infer::{
+ InferCtxt,
+ traits::{Obligation, ObligationCause},
+ },
+ obligation_ctxt::ObligationCtxt,
},
- obligation_ctxt::ObligationCtxt,
};
pub(crate) struct InspectConfig {
@@ -142,7 +145,7 @@ impl<'a, 'db> InspectCandidate<'a, 'db> {
&self,
visitor: &mut V,
) -> V::Result {
- for goal in self.instantiate_nested_goals() {
+ for goal in self.instantiate_nested_goals(visitor.span()) {
try_visit!(goal.visit_with(visitor));
}
@@ -153,7 +156,7 @@ impl<'a, 'db> InspectCandidate<'a, 'db> {
/// inference constraints. This function modifies the state of the `infcx`.
///
/// See [`Self::instantiate_impl_args`] if you need the impl args too.
- pub(crate) fn instantiate_nested_goals(&self) -> Vec<InspectGoal<'a, 'db>> {
+ pub(crate) fn instantiate_nested_goals(&self, span: Span) -> Vec<InspectGoal<'a, 'db>> {
let infcx = self.goal.infcx;
let param_env = self.goal.goal.param_env;
let mut orig_values = self.goal.orig_values.to_vec();
@@ -163,13 +166,7 @@ impl<'a, 'db> InspectCandidate<'a, 'db> {
match **step {
inspect::ProbeStep::AddGoal(source, goal) => instantiated_goals.push((
source,
- instantiate_canonical_state(
- infcx,
- Span::dummy(),
- param_env,
- &mut orig_values,
- goal,
- ),
+ instantiate_canonical_state(infcx, span, param_env, &mut orig_values, goal),
)),
inspect::ProbeStep::RecordImplArgs { .. } => {}
inspect::ProbeStep::MakeCanonicalResponse { .. }
@@ -177,13 +174,8 @@ impl<'a, 'db> InspectCandidate<'a, 'db> {
}
}
- let () = instantiate_canonical_state(
- infcx,
- Span::dummy(),
- param_env,
- &mut orig_values,
- self.final_state,
- );
+ let () =
+ instantiate_canonical_state(infcx, span, param_env, &mut orig_values, self.final_state);
if let Some(term_hack) = &self.goal.normalizes_to_term_hack {
// FIXME: We ignore the expected term of `NormalizesTo` goals
@@ -194,14 +186,14 @@ impl<'a, 'db> InspectCandidate<'a, 'db> {
instantiated_goals
.into_iter()
- .map(|(source, goal)| self.instantiate_proof_tree_for_nested_goal(source, goal))
+ .map(|(source, goal)| self.instantiate_proof_tree_for_nested_goal(source, goal, span))
.collect()
}
/// Instantiate the args of an impl if this candidate came from a
/// `CandidateSource::Impl`. This function modifies the state of the
/// `infcx`.
- pub(crate) fn instantiate_impl_args(&self) -> GenericArgs<'db> {
+ pub(crate) fn instantiate_impl_args(&self, span: Span) -> GenericArgs<'db> {
let infcx = self.goal.infcx;
let param_env = self.goal.goal.param_env;
let mut orig_values = self.goal.orig_values.to_vec();
@@ -211,7 +203,7 @@ impl<'a, 'db> InspectCandidate<'a, 'db> {
inspect::ProbeStep::RecordImplArgs { impl_args } => {
let impl_args = instantiate_canonical_state(
infcx,
- Span::dummy(),
+ span,
param_env,
&mut orig_values,
impl_args,
@@ -219,7 +211,7 @@ impl<'a, 'db> InspectCandidate<'a, 'db> {
let () = instantiate_canonical_state(
infcx,
- Span::dummy(),
+ span,
param_env,
&mut orig_values,
self.final_state,
@@ -246,11 +238,12 @@ impl<'a, 'db> InspectCandidate<'a, 'db> {
&self,
source: GoalSource,
goal: Goal<'db, Predicate<'db>>,
+ span: Span,
) -> InspectGoal<'a, 'db> {
let infcx = self.goal.infcx;
match goal.predicate.kind().no_bound_vars() {
Some(PredicateKind::NormalizesTo(NormalizesTo { alias, term })) => {
- let unconstrained_term = infcx.next_term_var_of_kind(term);
+ let unconstrained_term = infcx.next_term_var_of_kind(term, span);
let goal =
goal.with(infcx.interner, NormalizesTo { alias, term: unconstrained_term });
// We have to use a `probe` here as evaluating a `NormalizesTo` can constrain the
@@ -265,8 +258,7 @@ impl<'a, 'db> InspectCandidate<'a, 'db> {
// considering the constrained RHS, and pass the resulting certainty to
// `InspectGoal::new` so that the goal has the right result (and maintains
// the impression that we don't do this normalizes-to infer hack at all).
- let (nested, proof_tree) =
- infcx.evaluate_root_goal_for_proof_tree(goal, Span::dummy());
+ let (nested, proof_tree) = infcx.evaluate_root_goal_for_proof_tree(goal, span);
let nested_goals_result = nested.and_then(|nested| {
normalizes_to_term_hack.constrain_and(
infcx,
@@ -300,7 +292,7 @@ impl<'a, 'db> InspectCandidate<'a, 'db> {
// constraints, we get an ICE if we already applied the constraints
// from the chosen candidate.
let proof_tree =
- infcx.probe(|_| infcx.evaluate_root_goal_for_proof_tree(goal, Span::dummy()).1);
+ infcx.probe(|_| infcx.evaluate_root_goal_for_proof_tree(goal, span).1);
InspectGoal::new(infcx, self.goal.depth + 1, proof_tree, None, source)
}
}
@@ -469,6 +461,8 @@ impl<'a, 'db> InspectGoal<'a, 'db> {
pub(crate) trait ProofTreeVisitor<'db> {
type Result: VisitorResult;
+ fn span(&self) -> Span;
+
fn config(&self) -> InspectConfig {
InspectConfig { max_depth: 10 }
}
@@ -496,7 +490,7 @@ impl<'db> InferCtxt<'db> {
visitor: &mut V,
) -> V::Result {
let (_, proof_tree) = <&SolverContext<'db>>::from(self)
- .evaluate_root_goal_for_proof_tree(goal, Span::dummy());
+ .evaluate_root_goal_for_proof_tree(goal, visitor.span());
visitor.visit_goal(&InspectGoal::new(self, depth, proof_tree, None, GoalSource::Misc))
}
}
diff --git a/crates/hir-ty/src/next_solver/interner.rs b/crates/hir-ty/src/next_solver/interner.rs
index 4095dbe47d..af3798f1da 100644
--- a/crates/hir-ty/src/next_solver/interner.rs
+++ b/crates/hir-ty/src/next_solver/interner.rs
@@ -37,7 +37,7 @@ use rustc_type_ir::{
};
use crate::{
- FnAbi,
+ FnAbi, Span,
db::{HirDatabase, InternedClosure, InternedCoroutineId},
lower::GenericPredicates,
method_resolution::TraitImpls,
@@ -382,13 +382,9 @@ impl<'db> DbInterner<'db> {
}
}
-// This is intentionally left as `()`
-#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
-pub struct Span(());
-
impl<'db> inherent::Span<DbInterner<'db>> for Span {
fn dummy() -> Self {
- Span(())
+ Span::Dummy
}
}
diff --git a/crates/hir-ty/src/next_solver/normalize.rs b/crates/hir-ty/src/next_solver/normalize.rs
index 5d8f3fe519..aa6f27c4c2 100644
--- a/crates/hir-ty/src/next_solver/normalize.rs
+++ b/crates/hir-ty/src/next_solver/normalize.rs
@@ -99,7 +99,7 @@ impl<'db> NormalizationFolder<'_, 'db> {
self.depth += 1;
- let infer_term = infcx.next_term_var_of_kind(alias_term);
+ let infer_term = infcx.next_term_var_of_kind(alias_term, self.at.cause.span());
let obligation = Obligation::new(
interner,
self.at.cause.clone(),
diff --git a/crates/hir-ty/src/next_solver/solver.rs b/crates/hir-ty/src/next_solver/solver.rs
index d45ac6c959..018ecd66e0 100644
--- a/crates/hir-ty/src/next_solver/solver.rs
+++ b/crates/hir-ty/src/next_solver/solver.rs
@@ -15,7 +15,7 @@ use rustc_type_ir::{
use tracing::debug;
use crate::{
- ParamEnvAndCrate,
+ ParamEnvAndCrate, Span,
next_solver::{
AliasTy, AnyImplId, CanonicalVarKind, Clause, ClauseKind, CoercePredicate, GenericArgs,
ParamEnv, Predicate, PredicateKind, SubtypePredicate, Ty, TyKind, UnevaluatedConst,
@@ -24,7 +24,7 @@ use crate::{
};
use super::{
- Const, DbInterner, ErrorGuaranteed, GenericArg, SolverDefId, Span,
+ Const, DbInterner, ErrorGuaranteed, GenericArg, SolverDefId,
infer::{DbInternerInferExt, InferCtxt, canonical::instantiate::CanonicalExt},
};
@@ -63,15 +63,15 @@ impl<'db> SolverDelegate for SolverContext<'db> {
where
V: rustc_type_ir::TypeFoldable<Self::Interner>,
{
- let (infcx, value, vars) = cx.infer_ctxt().build_with_canonical(canonical);
+ let (infcx, value, vars) = cx.infer_ctxt().build_with_canonical(Span::Dummy, canonical);
(SolverContext(infcx), value, vars)
}
- fn fresh_var_for_kind_with_span(&self, arg: GenericArg<'db>, _span: Span) -> GenericArg<'db> {
+ fn fresh_var_for_kind_with_span(&self, arg: GenericArg<'db>, span: Span) -> GenericArg<'db> {
match arg.kind() {
- GenericArgKind::Lifetime(_) => self.next_region_var().into(),
- GenericArgKind::Type(_) => self.next_ty_var().into(),
- GenericArgKind::Const(_) => self.next_const_var().into(),
+ GenericArgKind::Lifetime(_) => self.next_region_var(span).into(),
+ GenericArgKind::Type(_) => self.next_ty_var(span).into(),
+ GenericArgKind::Const(_) => self.next_const_var(span).into(),
}
}
@@ -124,11 +124,11 @@ impl<'db> SolverDelegate for SolverContext<'db> {
fn instantiate_canonical_var(
&self,
kind: CanonicalVarKind<'db>,
- _span: <Self::Interner as Interner>::Span,
+ span: Span,
var_values: &[GenericArg<'db>],
universe_map: impl Fn(rustc_type_ir::UniverseIndex) -> rustc_type_ir::UniverseIndex,
) -> GenericArg<'db> {
- self.0.instantiate_canonical_var(kind, var_values, universe_map)
+ self.0.instantiate_canonical_var(span, kind, var_values, universe_map)
}
fn add_item_bounds_for_hidden_type(
diff --git a/crates/hir-ty/src/next_solver/structural_normalize.rs b/crates/hir-ty/src/next_solver/structural_normalize.rs
index 00c3708358..7a70bae97c 100644
--- a/crates/hir-ty/src/next_solver/structural_normalize.rs
+++ b/crates/hir-ty/src/next_solver/structural_normalize.rs
@@ -34,7 +34,7 @@ impl<'db> At<'_, 'db> {
return Ok(term);
}
- let new_infer = self.infcx.next_term_var_of_kind(term);
+ let new_infer = self.infcx.next_term_var_of_kind(term, self.cause.span());
// We simply emit an `alias-eq` goal here, since that will take care of
// normalizing the LHS of the projection until it is a rigid projection
diff --git a/crates/hir-ty/src/opaques.rs b/crates/hir-ty/src/opaques.rs
index 2e85beea91..c78e9d7c5d 100644
--- a/crates/hir-ty/src/opaques.rs
+++ b/crates/hir-ty/src/opaques.rs
@@ -10,7 +10,7 @@ use rustc_type_ir::inherent::Ty as _;
use syntax::ast;
use crate::{
- ImplTraitId, InferenceResult,
+ ImplTraitId, InferenceResult, Span,
db::{HirDatabase, InternedOpaqueTyId},
lower::{ImplTraitIdx, ImplTraits},
next_solver::{
@@ -140,7 +140,7 @@ pub(crate) fn tait_hidden_types<'db>(
}
// In the presence of errors, we attempt to create a unified type from all
// types. rustc doesn't do that, but this should improve the experience.
- let hidden_type = infcx.insert_type_vars(hidden_type.as_ref());
+ let hidden_type = infcx.insert_type_vars(hidden_type.as_ref(), Span::Dummy);
match result.entry(opaque_idx) {
la_arena::Entry::Vacant(entry) => {
entry.insert(StoredEarlyBinder::bind(hidden_type.store()));
diff --git a/crates/hir-ty/src/specialization.rs b/crates/hir-ty/src/specialization.rs
index a0bac48250..7e4d3a8354 100644
--- a/crates/hir-ty/src/specialization.rs
+++ b/crates/hir-ty/src/specialization.rs
@@ -7,6 +7,7 @@ use hir_def::{
use tracing::debug;
use crate::{
+ Span,
db::HirDatabase,
lower::GenericPredicates,
next_solver::{
@@ -91,7 +92,7 @@ fn specializes_query(
let mut ocx = ObligationCtxt::new(&infcx);
- let parent_args = infcx.fresh_args_for_item(parent_impl_def_id.into());
+ let parent_args = infcx.fresh_args_for_item(Span::Dummy, parent_impl_def_id.into());
let parent_impl_trait_ref = db
.impl_trait(parent_impl_def_id)
.expect("expected source impl to be a trait impl")
diff --git a/crates/hir-ty/src/traits.rs b/crates/hir-ty/src/traits.rs
index 0dc834ddcc..ad668f2eee 100644
--- a/crates/hir-ty/src/traits.rs
+++ b/crates/hir-ty/src/traits.rs
@@ -21,6 +21,7 @@ use rustc_type_ir::{
};
use crate::{
+ Span,
db::HirDatabase,
next_solver::{
DbInterner, GenericArgs, ParamEnv, StoredClauses, Ty, TyKind,
@@ -121,7 +122,7 @@ pub fn implements_trait_unique<'db>(
trait_: TraitId,
) -> bool {
implements_trait_unique_impl(db, env, trait_, &mut |infcx| {
- infcx.fill_rest_fresh_args(trait_.into(), [ty.into()])
+ infcx.fill_rest_fresh_args(Span::Dummy, trait_.into(), [ty.into()])
})
}
diff --git a/crates/hir/src/attrs.rs b/crates/hir/src/attrs.rs
index 9943b718fd..f9cf05e73a 100644
--- a/crates/hir/src/attrs.rs
+++ b/crates/hir/src/attrs.rs
@@ -504,6 +504,8 @@ fn resolve_impl_trait_item<'db>(
traits_in_scope: &traits_in_scope,
edition: krate.edition(db),
features,
+ call_span: hir_ty::Span::Dummy,
+ receiver_span: hir_ty::Span::Dummy,
};
let resolution = ctx.probe_for_name(method_resolution::Mode::Path, name.clone(), ty.ty);
let resolution = match resolution {
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 11598f2a10..f5ca22e10c 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -1525,7 +1525,7 @@ impl Struct {
}
pub fn instantiate_infer<'db>(self, infer_ctxt: &InferCtxt<'db>) -> InstantiatedStruct<'db> {
- let args = infer_ctxt.fresh_args_for_item(self.id.into());
+ let args = infer_ctxt.fresh_args_for_item(hir_ty::Span::Dummy, self.id.into());
InstantiatedStruct { inner: self, args }
}
}
@@ -1804,8 +1804,10 @@ impl EnumVariant {
}
pub fn instantiate_infer<'db>(self, infer_ctxt: &InferCtxt<'db>) -> InstantiatedVariant<'db> {
- let args =
- infer_ctxt.fresh_args_for_item(self.parent_enum(infer_ctxt.interner.db()).id.into());
+ let args = infer_ctxt.fresh_args_for_item(
+ hir_ty::Span::Dummy,
+ self.parent_enum(infer_ctxt.interner.db()).id.into(),
+ );
InstantiatedVariant { inner: self, args }
}
}
@@ -6191,6 +6193,8 @@ impl<'db> Type<'db> {
traits_in_scope,
edition: resolver.krate().data(db).edition,
features,
+ call_span: hir_ty::Span::Dummy,
+ receiver_span: hir_ty::Span::Dummy,
};
f(&ctx)
}
@@ -6217,7 +6221,7 @@ impl<'db> Type<'db> {
self.with_method_resolution(db, scope.resolver(), traits_in_scope, |ctx| {
// There should be no inference vars in types passed here
let canonical = hir_ty::replace_errors_with_variables(ctx.infcx.interner, &self.ty);
- let (self_ty, _) = ctx.infcx.instantiate_canonical(&canonical);
+ let (self_ty, _) = ctx.infcx.instantiate_canonical(hir_ty::Span::Dummy, &canonical);
match name {
Some(name) => {
@@ -6325,7 +6329,7 @@ impl<'db> Type<'db> {
self.with_method_resolution(db, scope.resolver(), traits_in_scope, |ctx| {
// There should be no inference vars in types passed here
let canonical = hir_ty::replace_errors_with_variables(ctx.infcx.interner, &self.ty);
- let (self_ty, _) = ctx.infcx.instantiate_canonical(&canonical);
+ let (self_ty, _) = ctx.infcx.instantiate_canonical(hir_ty::Span::Dummy, &canonical);
match name {
Some(name) => {
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index 9d97dc7421..17f5b51cc3 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -36,14 +36,13 @@ use hir_ty::{
diagnostics::unsafe_operations,
infer_query_with_inspect,
next_solver::{
- AnyImplId, DbInterner, Span,
+ AnyImplId, DbInterner,
format_proof_tree::{ProofTreeData, dump_proof_tree_structured},
},
};
use intern::{Interned, Symbol, sym};
use itertools::Itertools;
use rustc_hash::{FxHashMap, FxHashSet};
-use rustc_type_ir::inherent::Span as _;
use smallvec::{SmallVec, smallvec};
use span::{FileId, SyntaxContext};
use stdx::{TupleExt, always};
@@ -2459,7 +2458,8 @@ impl<'db> SemanticsImpl<'db> {
if result.is_err()
&& let Some(tree) = proof_tree
{
- let data = dump_proof_tree_structured(tree, Span::dummy(), infer_ctxt);
+ let data =
+ dump_proof_tree_structured(tree, hir_ty::Span::Dummy, infer_ctxt);
RESULT.with(|ctx| ctx.borrow_mut().push(data));
}
}),