Unnamed repository; edit this file 'description' to name the repository.
Store a span (`ExprId`, `PatId` or `TypeRefId`) in infer vars
This is required for reporting unresolved vars, which will come in the next commit.
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)); } }), |