Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #22237 from ChayimFriedman2/infcx-ty-lowering
fix: Provide an InferCtxt to TyLoweringContext
| -rw-r--r-- | crates/hir-ty/src/consteval.rs | 14 | ||||
| -rw-r--r-- | crates/hir-ty/src/generics.rs | 2 | ||||
| -rw-r--r-- | crates/hir-ty/src/infer.rs | 154 | ||||
| -rw-r--r-- | crates/hir-ty/src/infer/closure.rs | 8 | ||||
| -rw-r--r-- | crates/hir-ty/src/infer/diagnostics.rs | 19 | ||||
| -rw-r--r-- | crates/hir-ty/src/infer/path.rs | 31 | ||||
| -rw-r--r-- | crates/hir-ty/src/infer/unify.rs | 11 | ||||
| -rw-r--r-- | crates/hir-ty/src/lib.rs | 29 | ||||
| -rw-r--r-- | crates/hir-ty/src/lower.rs | 205 | ||||
| -rw-r--r-- | crates/hir-ty/src/lower/path.rs | 152 | ||||
| -rw-r--r-- | crates/hir-ty/src/method_resolution/confirm.rs | 7 | ||||
| -rw-r--r-- | crates/hir-ty/src/next_solver.rs | 3 | ||||
| -rw-r--r-- | crates/hir-ty/src/next_solver/infer/mod.rs | 11 | ||||
| -rw-r--r-- | crates/hir-ty/src/opaques.rs | 4 | ||||
| -rw-r--r-- | crates/hir-ty/src/tests/simple.rs | 3 | ||||
| -rw-r--r-- | crates/hir/src/source_analyzer.rs | 11 | ||||
| -rw-r--r-- | crates/ide-diagnostics/src/handlers/incorrect_generics_len.rs | 12 |
17 files changed, 413 insertions, 263 deletions
diff --git a/crates/hir-ty/src/consteval.rs b/crates/hir-ty/src/consteval.rs index 67e40fa811..21e368c88f 100644 --- a/crates/hir-ty/src/consteval.rs +++ b/crates/hir-ty/src/consteval.rs @@ -25,23 +25,15 @@ use crate::{ generics::Generics, mir::{MirEvalError, MirLowerError, pad16}, next_solver::{ - Allocation, Const, ConstKind, Consts, DbInterner, DefaultAny, ErrorGuaranteed, GenericArg, - GenericArgs, ParamConst, ScalarInt, StoredAllocation, StoredEarlyBinder, StoredGenericArgs, - Ty, TyKind, UnevaluatedConst, ValTreeKind, default_types, infer::InferCtxt, + Allocation, Const, ConstKind, Consts, DbInterner, DefaultAny, GenericArgs, ParamConst, + ScalarInt, StoredAllocation, StoredEarlyBinder, StoredGenericArgs, Ty, TyKind, + UnevaluatedConst, ValTreeKind, default_types, infer::InferCtxt, }, traits::StoredParamEnvAndCrate, }; use super::mir::interpret_mir; -pub fn unknown_const<'db>(_ty: Ty<'db>) -> Const<'db> { - Const::new(DbInterner::conjure(), rustc_type_ir::ConstKind::Error(ErrorGuaranteed)) -} - -pub fn unknown_const_as_generic<'db>(ty: Ty<'db>) -> GenericArg<'db> { - unknown_const(ty).into() -} - #[derive(Debug, Clone, PartialEq, Eq)] pub enum ConstEvalError { MirLowerError(MirLowerError), diff --git a/crates/hir-ty/src/generics.rs b/crates/hir-ty/src/generics.rs index 25a31e2f58..c4321e8a61 100644 --- a/crates/hir-ty/src/generics.rs +++ b/crates/hir-ty/src/generics.rs @@ -39,7 +39,7 @@ pub(crate) fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics<'_> } #[derive(Debug)] -pub(crate) struct Generics<'db> { +pub struct Generics<'db> { chain: ArrayVec<SingleGenerics<'db>, 2>, } diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs index b399a7e0ed..8aadab6cdb 100644 --- a/crates/hir-ty/src/infer.rs +++ b/crates/hir-ty/src/infer.rs @@ -50,7 +50,7 @@ use hir_def::{ layout::Integer, resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs}, signatures::{ConstSignature, EnumSignature, FunctionSignature, StaticSignature}, - type_ref::{LifetimeRefId, TypeRef, TypeRefId}, + type_ref::{LifetimeRefId, TypeRefId}, unstable_features::UnstableFeatures, }; use hir_expand::{mod_path::ModPath, name::Name}; @@ -61,7 +61,7 @@ use rustc_ast_ir::Mutability; use rustc_hash::{FxHashMap, FxHashSet}; use rustc_type_ir::{ AliasTyKind, TypeFoldable, TypeVisitableExt, - inherent::{IntoKind, Ty as _}, + inherent::{GenericArgs as _, IntoKind, Ty as _}, }; use smallvec::SmallVec; use span::Edition; @@ -72,7 +72,6 @@ use crate::{ ImplTraitId, IncorrectGenericsLenKind, InferBodyId, PathLoweringDiagnostic, Span, TargetFeatures, closure_analysis::PlaceBase, - collect_type_inference_vars, consteval::{create_anon_const, path_to_const}, db::{AnonConstId, GeneralConstId, HirDatabase, InternedOpaqueTyId}, generics::Generics, @@ -89,7 +88,8 @@ use crate::{ unify::resolve_completely::WriteBackCtxt, }, lower::{ - ImplTraitIdx, ImplTraitLoweringMode, LifetimeElisionKind, diagnostics::TyLoweringDiagnostic, + ImplTraitIdx, ImplTraitLoweringMode, LifetimeElisionKind, TyLoweringInferVarsCtx, + diagnostics::TyLoweringDiagnostic, }, method_resolution::CandidateId, next_solver::{ @@ -1189,6 +1189,7 @@ pub(crate) struct InferenceContext<'body, 'db> { pub(crate) edition: Edition, allow_using_generic_params: bool, generics: OnceCell<Generics<'db>>, + identity_args: OnceCell<GenericArgs<'db>>, pub(crate) table: unify::InferenceTable<'db>, pub(crate) lang_items: &'db LangItems, pub(crate) features: &'db UnstableFeatures, @@ -1302,6 +1303,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> { generic_def, allow_using_generic_params, generics: OnceCell::new(), + identity_args: OnceCell::new(), store, traits_in_scope: resolver.traits_in_scope(db), resolver, @@ -1611,7 +1613,6 @@ impl<'body, 'db> InferenceContext<'body, 'db> { InferenceTyDiagnosticSource::Signature, ExpressionStoreOwnerId::Signature(id.into()), LifetimeElisionKind::for_const(self.interner(), id.loc(self.db).container), - Span::Dummy, ); self.return_ty = return_ty; @@ -1624,7 +1625,6 @@ impl<'body, 'db> InferenceContext<'body, 'db> { InferenceTyDiagnosticSource::Signature, ExpressionStoreOwnerId::Signature(id.into()), LifetimeElisionKind::Elided(self.types.regions.statik), - Span::Dummy, ); self.return_ty = return_ty; @@ -1662,12 +1662,12 @@ impl<'body, 'db> InferenceContext<'body, 'db> { if let Some(self_param) = self_param && let Some(ty) = param_tys.next() { - let ty = self.process_user_written_ty(Span::Dummy, ty); + let ty = self.process_user_written_ty(ty); self.write_binding_ty(self_param, ty); } for pat in params { let ty = param_tys.next().unwrap_or_else(|| self.table.next_ty_var(Span::Dummy)); - let ty = self.process_user_written_ty(Span::Dummy, ty); + let ty = self.process_user_written_ty(ty); self.infer_top_pat(*pat, ty, PatOrigin::Param); } @@ -1683,7 +1683,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> { ctx.lower_ty(return_ty) }, ); - self.process_user_written_ty(Span::Dummy, return_ty) + self.process_user_written_ty(return_ty) } None => self.types.types.unit, }; @@ -1797,10 +1797,6 @@ impl<'body, 'db> InferenceContext<'body, 'db> { self.result.type_of_pat.insert(pat, ty.store()); } - fn write_type_placeholder_ty(&mut self, type_ref: TypeRefId, ty: Ty<'db>) { - self.result.type_of_type_placeholder.insert(type_ref, ty.store()); - } - fn write_binding_ty(&mut self, id: BindingId, ty: Ty<'db>) { self.result.type_of_binding.insert(id, ty.store()); } @@ -1832,6 +1828,13 @@ impl<'body, 'db> InferenceContext<'body, 'db> { lifetime_elision: LifetimeElisionKind<'db>, f: impl FnOnce(&mut TyLoweringContext<'db, '_>) -> R, ) -> R { + let infer_vars = match types_source { + InferenceTyDiagnosticSource::Body => Some(TyLoweringInferVarsCtx { + table: &mut self.table, + type_of_placeholder: &mut self.result.type_of_type_placeholder, + }), + InferenceTyDiagnosticSource::Signature => None, + }; let mut ctx = TyLoweringContext::new( self.db, &self.resolver, @@ -1840,8 +1843,10 @@ impl<'body, 'db> InferenceContext<'body, 'db> { types_source, store_owner, self.generic_def, + &self.generics, lifetime_elision, self.allow_using_generic_params, + infer_vars, &self.defined_anon_consts, ); f(&mut ctx) @@ -1867,30 +1872,11 @@ impl<'body, 'db> InferenceContext<'body, 'db> { type_source: InferenceTyDiagnosticSource, store_owner: ExpressionStoreOwnerId, lifetime_elision: LifetimeElisionKind<'db>, - span: Span, ) -> Ty<'db> { let ty = self.with_ty_lowering(store, type_source, store_owner, lifetime_elision, |ctx| { ctx.lower_ty(type_ref) }); - let ty = self.process_user_written_ty(span, ty); - - // Record the association from placeholders' TypeRefId to type variables. - // We only record them if their number matches. This assumes TypeRef::walk and TypeVisitable process the items in the same order. - let type_variables = collect_type_inference_vars(&ty); - let mut placeholder_ids = vec![]; - TypeRef::walk(type_ref, store, &mut |type_ref_id, type_ref| { - if matches!(type_ref, TypeRef::Placeholder) { - placeholder_ids.push(type_ref_id); - } - }); - - if placeholder_ids.len() == type_variables.len() { - for (placeholder_id, type_variable) in placeholder_ids.into_iter().zip(type_variables) { - self.write_type_placeholder_ty(placeholder_id, type_variable); - } - } - - ty + self.process_user_written_ty(ty) } pub(crate) fn make_body_ty(&mut self, type_ref: TypeRefId) -> Ty<'db> { @@ -1900,13 +1886,16 @@ impl<'body, 'db> InferenceContext<'body, 'db> { InferenceTyDiagnosticSource::Body, self.store_owner, LifetimeElisionKind::Infer, - type_ref.into(), ) } fn generics(&self) -> &Generics<'db> { - self.generics.get_or_init(|| { - crate::generics::generics(self.db, self.store_owner.generic_def(self.db)) + self.generics.get_or_init(|| crate::generics::generics(self.db, self.generic_def)) + } + + fn identity_args(&self) -> GenericArgs<'db> { + *self.identity_args.get_or_init(|| { + GenericArgs::identity_for_item(self.interner(), self.store_owner.into()) }) } @@ -1960,14 +1949,14 @@ impl<'body, 'db> InferenceContext<'body, 'db> { LifetimeElisionKind::Infer, |ctx| ctx.lower_lifetime(lifetime_ref), ); - self.insert_type_vars(lt, Span::Dummy) + self.insert_type_vars(lt) } - fn insert_type_vars<T>(&mut self, ty: T, span: Span) -> T + fn insert_type_vars<T>(&mut self, ty: T) -> T where T: TypeFoldable<DbInterner<'db>>, { - self.table.insert_type_vars(ty, span) + self.table.insert_type_vars(ty) } /// Attempts to returns the deeply last field of nested structures, but @@ -2032,8 +2021,8 @@ impl<'body, 'db> InferenceContext<'body, 'db> { } /// Whenever you lower a user-written type, you should call this. - fn process_user_written_ty(&mut self, span: Span, ty: Ty<'db>) -> Ty<'db> { - self.table.process_user_written_ty(span, ty) + fn process_user_written_ty(&mut self, ty: Ty<'db>) -> Ty<'db> { + self.table.process_user_written_ty(ty) } /// The difference of this method from `process_user_written_ty()` is that this method doesn't register a well-formed obligation, @@ -2174,6 +2163,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> { path: &Path, value_ns: bool, ) -> (Ty<'db>, Option<VariantId>) { + let interner = self.interner(); let mut ctx = TyLoweringContext::new( self.db, &self.resolver, @@ -2182,18 +2172,23 @@ impl<'body, 'db> InferenceContext<'body, 'db> { InferenceTyDiagnosticSource::Body, self.store_owner, self.generic_def, + &self.generics, LifetimeElisionKind::Infer, self.allow_using_generic_params, + Some(TyLoweringInferVarsCtx { + table: &mut self.table, + type_of_placeholder: &mut self.result.type_of_type_placeholder, + }), &self.defined_anon_consts, ); if let Some(type_anchor) = path.type_anchor() { let mut segments = path.segments(); if segments.is_empty() { - return (self.err_ty(), None); + return (self.types.types.error, None); } let (mut ty, type_ns) = ctx.lower_ty_ext(type_anchor); - ty = self.table.process_user_written_ty(type_anchor.into(), ty); + ty = ctx.expect_table().process_user_written_ty(ty); if let Some(TypeNs::SelfType(impl_)) = type_ns && let Some(trait_ref) = self.db.impl_trait(impl_) @@ -2205,20 +2200,20 @@ impl<'body, 'db> InferenceContext<'body, 'db> { .associated_type_by_name(segments.first().unwrap().name) { // `<Self>::AssocType` - let args = self.infcx().fill_rest_fresh_args( + let args = ctx.expect_table().infer_ctxt.fill_rest_fresh_args( node.into(), assoc_type.into(), trait_ref.args, ); let alias = Ty::new_alias( - self.interner(), + interner, AliasTy::new_from_args( - self.interner(), + interner, AliasTyKind::Projection { def_id: assoc_type.into() }, args, ), ); - ty = self.table.try_structurally_resolve_type(node.into(), alias); + ty = ctx.expect_table().try_structurally_resolve_type(node.into(), alias); segments = segments.skip(1); } @@ -2234,15 +2229,15 @@ impl<'body, 'db> InferenceContext<'body, 'db> { segments = segments.skip(1); variant.into() } else { - return (self.err_ty(), None); + return (self.types.types.error, None); } } - None => return (self.err_ty(), None), + None => return (self.types.types.error, None), }; if !segments.is_empty() { // FIXME: Report an error. - return (self.err_ty(), None); + return (self.types.types.error, None); } else { return (ty, Some(variant)); } @@ -2252,33 +2247,34 @@ impl<'body, 'db> InferenceContext<'body, 'db> { let interner = DbInterner::conjure(); let (resolution, unresolved) = if value_ns { let Some(res) = path_ctx.resolve_path_in_value_ns(HygieneId::ROOT) else { - return (self.err_ty(), None); + return (self.types.types.error, None); }; match res { ResolveValueResult::ValueNs(value) => match value { ValueNs::EnumVariantId(var) => { - let args = path_ctx.substs_from_path(var.into(), true, false); + let args = path_ctx.substs_from_path(var.into(), true, false, node.into()); drop(ctx); let ty = self .db .ty(var.lookup(self.db).parent.into()) .instantiate(interner, args) .skip_norm_wip(); - let ty = self.insert_type_vars(ty, Span::Dummy); + let ty = self.insert_type_vars(ty); return (ty, Some(var.into())); } ValueNs::StructId(strukt) => { - let args = path_ctx.substs_from_path(strukt.into(), true, false); + let args = + path_ctx.substs_from_path(strukt.into(), true, false, node.into()); drop(ctx); let ty = self.db.ty(strukt.into()).instantiate(interner, args).skip_norm_wip(); - let ty = self.insert_type_vars(ty, Span::Dummy); + let ty = self.insert_type_vars(ty); return (ty, Some(strukt.into())); } ValueNs::ImplSelf(impl_id) => (TypeNs::SelfType(impl_id), None), _ => { drop(ctx); - return (self.err_ty(), None); + return (self.types.types.error, None); } }, ResolveValueResult::Partial(typens, unresolved) => (typens, Some(unresolved)), @@ -2286,33 +2282,33 @@ impl<'body, 'db> InferenceContext<'body, 'db> { } else { match path_ctx.resolve_path_in_type_ns() { Some((it, idx)) => (it, idx), - None => return (self.err_ty(), None), + None => return (self.types.types.error, None), } }; return match resolution { TypeNs::AdtId(AdtId::StructId(strukt)) => { - let args = path_ctx.substs_from_path(strukt.into(), true, false); + let args = path_ctx.substs_from_path(strukt.into(), true, false, node.into()); drop(ctx); let ty = self.db.ty(strukt.into()).instantiate(interner, args).skip_norm_wip(); - let ty = self.insert_type_vars(ty, Span::Dummy); + let ty = self.insert_type_vars(ty); 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); + let args = path_ctx.substs_from_path(u.into(), true, false, node.into()); drop(ctx); let ty = self.db.ty(u.into()).instantiate(interner, args).skip_norm_wip(); - let ty = self.insert_type_vars(ty, Span::Dummy); + let ty = self.insert_type_vars(ty); forbid_unresolved_segments(self, (ty, Some(u.into())), unresolved) } TypeNs::EnumVariantId(var) => { - let args = path_ctx.substs_from_path(var.into(), true, false); + let args = path_ctx.substs_from_path(var.into(), true, false, node.into()); drop(ctx); let ty = self .db .ty(var.lookup(self.db).parent.into()) .instantiate(interner, args) .skip_norm_wip(); - let ty = self.insert_type_vars(ty, Span::Dummy); + let ty = self.insert_type_vars(ty); forbid_unresolved_segments(self, (ty, Some(var.into())), unresolved) } TypeNs::SelfType(impl_id) => { @@ -2322,7 +2318,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> { drop(ctx); let Some(mod_path) = path.mod_path() else { never!("resolver should always resolve lang item paths"); - return (self.err_ty(), None); + return (self.types.types.error, None); }; return self.resolve_variant_on_alias(node, ty, None, mod_path); }; @@ -2350,7 +2346,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> { // We still have unresolved paths, but enum variants never have // associated types! // FIXME: Report an error. - (self.err_ty(), None) + (self.types.types.error, None) }; } } @@ -2364,12 +2360,12 @@ impl<'body, 'db> InferenceContext<'body, 'db> { // `lower_partly_resolved_path()` returns `None` as type namespace unless // `remaining_segments` is empty, which is never the case here. We don't know // which namespace the new `ty` is in until normalized anyway. - (ty, _) = path_ctx.lower_partly_resolved_path(resolution, true); + (ty, _) = path_ctx.lower_partly_resolved_path(resolution, true, node.into()); tried_resolving_once = true; - ty = self.table.process_user_written_ty(node.into(), ty); + ty = path_ctx.expect_table().process_user_written_ty(ty); if ty.is_ty_error() { - return (self.err_ty(), None); + return (self.types.types.error, None); } remaining_segments = remaining_segments.skip(1); @@ -2388,7 +2384,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> { } TypeNs::TraitId(_) => { let Some(remaining_idx) = unresolved else { - return (self.err_ty(), None); + return (self.types.types.error, None); }; let remaining_segments = path.segments().skip(remaining_idx); @@ -2397,8 +2393,9 @@ impl<'body, 'db> InferenceContext<'body, 'db> { path_ctx.ignore_last_segment(); } - let (mut ty, _) = path_ctx.lower_partly_resolved_path(resolution, true); - ty = self.table.process_user_written_ty(node.into(), ty); + let (mut ty, _) = + path_ctx.lower_partly_resolved_path(resolution, true, node.into()); + ty = ctx.expect_table().process_user_written_ty(ty); if let Some(segment) = remaining_segments.get(1) && let Some((AdtId::EnumId(id), _)) = ty.as_adt() @@ -2411,7 +2408,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> { // We still have unresolved paths, but enum variants never have // associated types! // FIXME: Report an error. - (self.err_ty(), None) + (self.types.types.error, None) }; } } @@ -2429,27 +2426,28 @@ impl<'body, 'db> InferenceContext<'body, 'db> { TypeNs::TypeAliasId(it) => { let Some(mod_path) = path.mod_path() else { never!("resolver should always resolve lang item paths"); - return (self.err_ty(), None); + return (self.types.types.error, None); }; - let args = path_ctx.substs_from_path_segment(it.into(), true, None, false); + let args = + path_ctx.substs_from_path_segment(it.into(), true, None, false, node.into()); drop(ctx); let interner = DbInterner::conjure(); let ty = self.db.ty(it.into()).instantiate(interner, args).skip_norm_wip(); - let ty = self.insert_type_vars(ty, Span::Dummy); + let ty = self.insert_type_vars(ty); self.resolve_variant_on_alias(node, ty, unresolved, mod_path) } TypeNs::AdtSelfType(_) => { // FIXME this could happen in array size expressions, once we're checking them - (self.err_ty(), None) + (self.types.types.error, None) } TypeNs::GenericParam(_) => { // FIXME potentially resolve assoc type - (self.err_ty(), None) + (self.types.types.error, None) } TypeNs::AdtId(AdtId::EnumId(_)) | TypeNs::BuiltinType(_) | TypeNs::ModuleId(_) => { // FIXME diagnostic - (self.err_ty(), None) + (self.types.types.error, None) } }; diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs index 90578e30c2..ab111736d5 100644 --- a/crates/hir-ty/src/infer/closure.rs +++ b/crates/hir-ty/src/infer/closure.rs @@ -23,9 +23,9 @@ use crate::{ db::{InternedClosure, InternedClosureId, InternedCoroutineClosureId, InternedCoroutineId}, infer::{BreakableKind, Diverges, coerce::CoerceMany, pat::PatOrigin}, next_solver::{ - AliasTy, Binder, ClauseKind, DbInterner, ErrorGuaranteed, FnSig, GenericArg, GenericArgs, - PolyFnSig, PolyProjectionPredicate, Predicate, PredicateKind, SolverDefId, TermId, Ty, - TyKind, Unnormalized, + AliasTy, Binder, ClauseKind, DbInterner, ErrorGuaranteed, FnSig, GenericArg, PolyFnSig, + PolyProjectionPredicate, Predicate, PredicateKind, SolverDefId, TermId, Ty, TyKind, + Unnormalized, abi::Safety, infer::{ BoundRegionConversionTime, InferOk, InferResult, @@ -99,7 +99,7 @@ impl<'db> InferenceContext<'_, 'db> { debug!(?bound_sig, ?liberated_sig); - let parent_args = GenericArgs::identity_for_item(interner, self.store_owner.into()); + let parent_args = self.identity_args(); let tupled_upvars_ty = self.table.next_ty_var(closure_expr.into()); diff --git a/crates/hir-ty/src/infer/diagnostics.rs b/crates/hir-ty/src/infer/diagnostics.rs index 71aa35e634..50feab8dd4 100644 --- a/crates/hir-ty/src/infer/diagnostics.rs +++ b/crates/hir-ty/src/infer/diagnostics.rs @@ -2,7 +2,7 @@ //! and a wrapper around [`TyLoweringContext`] ([`InferenceTyLoweringContext`]) that replaces //! it and takes care of diagnostics in inference. -use std::cell::RefCell; +use std::cell::{OnceCell, RefCell}; use std::ops::{Deref, DerefMut}; use either::Either; @@ -16,8 +16,9 @@ use thin_vec::ThinVec; use crate::{ InferenceDiagnostic, InferenceTyDiagnosticSource, TyLoweringDiagnostic, db::{AnonConstId, HirDatabase}, + generics::Generics, lower::{ - ForbidParamsAfterReason, LifetimeElisionKind, TyLoweringContext, + ForbidParamsAfterReason, LifetimeElisionKind, TyLoweringContext, TyLoweringInferVarsCtx, path::{PathDiagnosticCallback, PathLoweringContext}, }, }; @@ -71,12 +72,22 @@ impl<'db, 'a> InferenceTyLoweringContext<'db, 'a> { source: InferenceTyDiagnosticSource, def: ExpressionStoreOwnerId, generic_def: GenericDefId, + generics: &'a OnceCell<Generics<'db>>, lifetime_elision: LifetimeElisionKind<'db>, allow_using_generic_params: bool, + infer_vars: Option<TyLoweringInferVarsCtx<'a, 'db>>, defined_anon_consts: &'a RefCell<ThinVec<AnonConstId>>, ) -> Self { - let mut ctx = - TyLoweringContext::new(db, resolver, store, def, generic_def, lifetime_elision); + let mut ctx = TyLoweringContext::new( + db, + resolver, + store, + def, + generic_def, + generics, + lifetime_elision, + ) + .with_infer_vars_behavior(infer_vars); if !allow_using_generic_params { ctx.forbid_params_after(0, ForbidParamsAfterReason::AnonConst); } diff --git a/crates/hir-ty/src/infer/path.rs b/crates/hir-ty/src/infer/path.rs index a2bcf02589..c5b3d184b1 100644 --- a/crates/hir-ty/src/infer/path.rs +++ b/crates/hir-ty/src/infer/path.rs @@ -13,7 +13,7 @@ use stdx::never; use crate::{ InferenceDiagnostic, Span, ValueTyDefId, infer::diagnostics::InferenceTyLoweringContext as TyLoweringContext, - lower::{GenericPredicates, LifetimeElisionKind}, + lower::{GenericPredicates, LifetimeElisionKind, TyLoweringInferVarsCtx}, method_resolution::{self, CandidateId, MethodError}, next_solver::{ GenericArg, GenericArgs, TraitRef, Ty, Unnormalized, infer::traits::ObligationCause, @@ -38,7 +38,7 @@ impl<'db> InferenceContext<'_, 'db> { } ValuePathResolution::NonGeneric(ty) => return Some((value, ty)), }; - let args = self.insert_type_vars(substs, id.into()); + let args = self.insert_type_vars(substs); self.add_required_obligations_for_value_path(id, generic_def, args); @@ -117,7 +117,7 @@ impl<'db> InferenceContext<'_, 'db> { if let Some(last_segment) = last_segment { path_ctx.set_current_segment(last_segment) } - path_ctx.substs_from_path(value_def, true, false) + path_ctx.substs_from_path(value_def, true, false, id.into()) }) }; @@ -147,8 +147,13 @@ impl<'db> InferenceContext<'_, 'db> { InferenceTyDiagnosticSource::Body, self.store_owner, self.generic_def, + &self.generics, LifetimeElisionKind::Infer, self.allow_using_generic_params, + Some(TyLoweringInferVarsCtx { + table: &mut self.table, + type_of_placeholder: &mut self.result.type_of_type_placeholder, + }), &self.defined_anon_consts, ); let mut path_ctx = if no_diagnostics { @@ -160,12 +165,12 @@ impl<'db> InferenceContext<'_, 'db> { let last = path.segments().last()?; let (ty, orig_ns) = path_ctx.ty_ctx().lower_ty_ext(type_ref); - let ty = self.table.process_user_written_ty(type_ref.into(), ty); + let ty = path_ctx.expect_table().process_user_written_ty(ty); path_ctx.ignore_last_segment(); - let (ty, _) = path_ctx.lower_ty_relative_path(ty, orig_ns, true); + let (ty, _) = path_ctx.lower_ty_relative_path(ty, orig_ns, true, id.into()); drop_ctx(ctx, no_diagnostics); - let ty = self.table.process_user_written_ty(id.into(), ty); + let ty = self.table.process_user_written_ty(ty); self.resolve_ty_assoc_item(ty, last.name, id).map(|(it, substs)| (it, Some(substs)))? } else { let hygiene = self.store.expr_or_pat_path_hygiene(id); @@ -190,9 +195,13 @@ impl<'db> InferenceContext<'_, 'db> { let (resolution, substs) = match (def, is_before_last) { (TypeNs::TraitId(trait_), true) => { - 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); + let self_ty = path_ctx.expect_table().next_ty_var(id.into()); + let trait_ref = path_ctx.lower_trait_ref_from_resolved_path( + trait_, + self_ty, + true, + id.into(), + ); drop_ctx(ctx, no_diagnostics); self.resolve_trait_assoc_item(trait_ref, last_segment, id) } @@ -202,13 +211,13 @@ impl<'db> InferenceContext<'_, 'db> { // should resolve to an associated type of that trait (e.g. `<T // as Iterator>::Item::default`) path_ctx.ignore_last_segment(); - let (ty, _) = path_ctx.lower_partly_resolved_path(def, true); + let (ty, _) = path_ctx.lower_partly_resolved_path(def, true, id.into()); drop_ctx(ctx, no_diagnostics); if ty.is_ty_error() { return None; } - let ty = self.process_user_written_ty(id.into(), ty); + let ty = self.process_user_written_ty(ty); self.resolve_ty_assoc_item(ty, last_segment.name, id) } diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs index 8527b42d78..168da95600 100644 --- a/crates/hir-ty/src/infer/unify.rs +++ b/crates/hir-ty/src/infer/unify.rs @@ -442,23 +442,22 @@ impl<'db> InferenceTable<'db> { } } - pub(super) fn insert_type_vars<T>(&mut self, ty: T, span: Span) -> T + pub(super) fn insert_type_vars<T>(&mut self, ty: T) -> T where T: TypeFoldable<DbInterner<'db>>, { - self.infer_ctxt.insert_type_vars(ty, span) + self.infer_ctxt.insert_type_vars(ty) } /// Whenever you lower a user-written type, you should call this. - pub(crate) fn process_user_written_ty(&mut self, span: Span, ty: Ty<'db>) -> Ty<'db> { - let ty = self.insert_type_vars(ty, span); - self.try_structurally_resolve_type(span, ty) + pub(crate) fn process_user_written_ty(&mut self, ty: Ty<'db>) -> Ty<'db> { + self.process_remote_user_written_ty(ty) } /// 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, Span::Dummy); + let ty = self.insert_type_vars(ty); // 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`. diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs index dc8b8d6c99..4c80921423 100644 --- a/crates/hir-ty/src/lib.rs +++ b/crates/hir-ty/src/lib.rs @@ -502,35 +502,6 @@ where Vec::from_iter(collector.params) } -struct TypeInferenceVarCollector<'db> { - type_inference_vars: Vec<Ty<'db>>, -} - -impl<'db> rustc_type_ir::TypeVisitor<DbInterner<'db>> for TypeInferenceVarCollector<'db> { - type Result = (); - - fn visit_ty(&mut self, ty: Ty<'db>) -> Self::Result { - use crate::rustc_type_ir::Flags; - if ty.is_ty_var() { - self.type_inference_vars.push(ty); - } else if ty.flags().intersects(rustc_type_ir::TypeFlags::HAS_TY_INFER) { - ty.super_visit_with(self); - } else { - // Fast path: don't visit inner types (e.g. generic arguments) when `flags` indicate - // that there are no placeholders. - } - } -} - -pub fn collect_type_inference_vars<'db, T>(value: &T) -> Vec<Ty<'db>> -where - T: ?Sized + rustc_type_ir::TypeVisitable<DbInterner<'db>>, -{ - let mut collector = TypeInferenceVarCollector { type_inference_vars: vec![] }; - value.visit_with(&mut collector); - collector.type_inference_vars -} - pub fn known_const_to_ast<'db>( konst: Const<'db>, db: &'db dyn HirDatabase, diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index f79bcddef0..61329f6c88 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -39,7 +39,7 @@ use la_arena::{Arena, ArenaMap, Idx}; use path::{PathDiagnosticCallback, PathLoweringContext}; use rustc_abi::ExternAbi; use rustc_ast_ir::Mutability; -use rustc_hash::FxHashSet; +use rustc_hash::{FxHashMap, FxHashSet}; use rustc_type_ir::{ AliasTyKind, BoundVarIndexKind, DebruijnIndex, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig, Interner, OutlivesPredicate, TermKind, TyKind, TypeFoldable, @@ -52,16 +52,17 @@ use thin_vec::ThinVec; use tracing::debug; use crate::{ - ImplTraitId, TyLoweringDiagnostic, TyLoweringDiagnosticKind, + ImplTraitId, Span, TyLoweringDiagnostic, TyLoweringDiagnosticKind, consteval::{create_anon_const, path_to_const}, db::{AnonConstId, GeneralConstId, HirDatabase, InternedOpaqueTyId}, generics::{Generics, SingleGenerics, generics}, + infer::unify::InferenceTable, next_solver::{ AliasTy, Binder, BoundExistentialPredicates, Clause, ClauseKind, Clauses, Const, ConstKind, - DbInterner, EarlyBinder, EarlyParamRegion, ErrorGuaranteed, FnSigKind, FxIndexMap, - GenericArg, GenericArgs, ParamConst, ParamEnv, PolyFnSig, Predicate, Region, StoredClauses, - StoredEarlyBinder, StoredGenericArg, StoredGenericArgs, StoredPolyFnSig, StoredTraitRef, - StoredTy, TraitPredicate, TraitRef, Ty, Tys, Unnormalized, abi::Safety, + DbInterner, DefaultAny, EarlyBinder, EarlyParamRegion, ErrorGuaranteed, FnSigKind, + FxIndexMap, GenericArg, GenericArgs, ParamConst, ParamEnv, PolyFnSig, Predicate, Region, + StoredClauses, StoredEarlyBinder, StoredGenericArg, StoredGenericArgs, StoredPolyFnSig, + StoredTraitRef, StoredTy, TraitPredicate, TraitRef, Ty, Tys, Unnormalized, abi::Safety, util::BottomUpFolder, }, }; @@ -184,7 +185,12 @@ pub(crate) enum ForbidParamsAfterReason { ConstParamTy, } -#[derive(Debug)] +pub(crate) struct TyLoweringInferVarsCtx<'a, 'db> { + // Technically we can just put an `&InferCtxt` here, but borrowck constraints requires us to put this: + pub(crate) table: &'a mut InferenceTable<'db>, + pub(crate) type_of_placeholder: &'a mut FxHashMap<TypeRefId, StoredTy>, +} + pub struct TyLoweringContext<'db, 'a> { pub db: &'db dyn HirDatabase, interner: DbInterner<'db>, @@ -194,7 +200,7 @@ pub struct TyLoweringContext<'db, 'a> { store: &'a ExpressionStore, def: ExpressionStoreOwnerId, generic_def: GenericDefId, - generics: OnceCell<Generics<'db>>, + generics: &'a OnceCell<Generics<'db>>, in_binders: DebruijnIndex, impl_trait_mode: ImplTraitLoweringState, /// Tracks types with explicit `?Sized` bounds. @@ -204,6 +210,7 @@ pub struct TyLoweringContext<'db, 'a> { forbid_params_after: Option<u32>, forbid_params_after_reason: ForbidParamsAfterReason, pub(crate) defined_anon_consts: ThinVec<AnonConstId>, + infer_vars: Option<TyLoweringInferVarsCtx<'a, 'db>>, } impl<'db, 'a> TyLoweringContext<'db, 'a> { @@ -213,6 +220,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { store: &'a ExpressionStore, def: ExpressionStoreOwnerId, generic_def: GenericDefId, + generics: &'a OnceCell<Generics<'db>>, lifetime_elision: LifetimeElisionKind<'db>, ) -> Self { let impl_trait_mode = ImplTraitLoweringState::new(ImplTraitLoweringMode::Disallowed); @@ -227,7 +235,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { resolver, def, generic_def, - generics: Default::default(), + generics, store, in_binders, impl_trait_mode, @@ -237,6 +245,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { forbid_params_after: None, forbid_params_after_reason: ForbidParamsAfterReason::AnonConst, defined_anon_consts: ThinVec::new(), + infer_vars: None, } } @@ -277,9 +286,66 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { self.forbid_params_after_reason = reason; } + pub(crate) fn with_infer_vars_behavior( + mut self, + behavior: Option<TyLoweringInferVarsCtx<'a, 'db>>, + ) -> Self { + self.infer_vars = behavior; + self + } + pub(crate) fn push_diagnostic(&mut self, type_ref: TypeRefId, kind: TyLoweringDiagnosticKind) { self.diagnostics.push(TyLoweringDiagnostic { source: type_ref, kind }); } + + #[track_caller] + pub(crate) fn expect_table(&mut self) -> &mut InferenceTable<'db> { + self.infer_vars.as_mut().unwrap().table + } + + fn next_ty_var(&mut self, type_ref: TypeRefId) -> Ty<'db> { + match &mut self.infer_vars { + Some(infer_vars) => { + let var = infer_vars.table.next_ty_var(type_ref.into()); + infer_vars.type_of_placeholder.insert(type_ref, var.store()); + var + } + None => { + // FIXME: Emit an error: no infer vars allowed here. + self.types.types.error + } + } + } + + fn next_ty_var_no_placeholder(&mut self, span: Span) -> Ty<'db> { + match &mut self.infer_vars { + Some(infer_vars) => infer_vars.table.next_ty_var(span), + None => { + // FIXME: Emit an error: no infer vars allowed here. + self.types.types.error + } + } + } + + fn next_const_var(&mut self, span: Span) -> Const<'db> { + match &mut self.infer_vars { + Some(infer_vars) => infer_vars.table.next_const_var(span), + None => { + // FIXME: Emit an error: no infer vars allowed here. + self.types.consts.error + } + } + } + + fn next_region_var(&mut self, span: Span) -> Region<'db> { + match &mut self.infer_vars { + Some(infer_vars) => infer_vars.table.next_region_var(span), + None => { + // FIXME: Emit an error: no infer vars allowed here. + self.types.regions.error + } + } + } } #[derive(Copy, Clone, Debug, PartialEq, Eq, Default)] @@ -308,7 +374,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { self.resolver, const_type, &|| self.generics(), - None, + self.infer_vars.as_ref().map(|vars_ctx| &vars_ctx.table.infer_ctxt), self.forbid_params_after, ); @@ -344,7 +410,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { fn type_param(&mut self, id: TypeParamId, index: u32) -> Ty<'db> { if self.param_index_is_disallowed(index) { // FIXME: Report an error. - Ty::new_error(self.interner, ErrorGuaranteed) + self.types.types.error } else { Ty::new_param(self.interner, id, index) } @@ -353,7 +419,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { fn region_param(&mut self, id: LifetimeParamId, index: u32) -> Region<'db> { if self.param_index_is_disallowed(index) { // FIXME: Report an error. - Region::error(self.interner) + self.types.regions.error } else { Region::new_early_param(self.interner, EarlyParamRegion { id, index }) } @@ -390,7 +456,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { } TypeRef::Array(array) => { let inner_ty = self.lower_ty(array.ty); - let const_len = self.lower_const(array.len, Ty::new_usize(interner)); + let const_len = self.lower_const(array.len, self.types.types.usize); Ty::new_array_with_const_len(interner, inner_ty, const_len) } &TypeRef::Slice(inner) => { @@ -400,12 +466,11 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { TypeRef::Reference(ref_) => { let inner_ty = self.lower_ty(ref_.ty); // FIXME: It should infer the eldided lifetimes instead of stubbing with error - let lifetime = ref_ - .lifetime - .map_or_else(|| Region::error(interner), |lr| self.lower_lifetime(lr)); + let lifetime = + ref_.lifetime.map_or(self.types.regions.error, |lr| self.lower_lifetime(lr)); Ty::new_ref(interner, lifetime, inner_ty, lower_mutability(ref_.mutability)) } - TypeRef::Placeholder => Ty::new_error(interner, ErrorGuaranteed), + TypeRef::Placeholder => self.next_ty_var(type_ref_id), TypeRef::Fn(fn_) => self.lower_fn_ptr(fn_), TypeRef::DynTrait(bounds) => self.lower_dyn_trait(bounds), TypeRef::ImplTrait(bounds) => { @@ -461,11 +526,11 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { } ImplTraitLoweringMode::Disallowed => { // FIXME: report error - Ty::new_error(self.interner, ErrorGuaranteed) + self.types.types.error } } } - TypeRef::Error => Ty::new_error(self.interner, ErrorGuaranteed), + TypeRef::Error => self.types.types.error, }; (ty, res) } @@ -547,13 +612,13 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { if let Some(type_ref) = path.type_anchor() { let (ty, res) = self.lower_ty_ext(type_ref); let mut ctx = self.at_path(path_id); - return ctx.lower_ty_relative_path(ty, res, false); + return ctx.lower_ty_relative_path(ty, res, false, path_id.type_ref().into()); } let mut ctx = self.at_path(path_id); let (resolution, remaining_index) = match ctx.resolve_path_in_type_ns() { Some(it) => it, - None => return (Ty::new_error(self.interner, ErrorGuaranteed), None), + None => return (self.types.types.error, None), }; if matches!(resolution, TypeNs::TraitId(_)) && remaining_index.is_none() { @@ -563,7 +628,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { return (ty, None); } - ctx.lower_partly_resolved_path(resolution, false) + ctx.lower_partly_resolved_path(resolution, false, path_id.type_ref().into()) } fn lower_trait_ref_from_path( @@ -577,7 +642,15 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { TypeNs::TraitId(tr) => tr, _ => return None, }; - Some((ctx.lower_trait_ref_from_resolved_path(resolved, explicit_self_ty, false), ctx)) + Some(( + ctx.lower_trait_ref_from_resolved_path( + resolved, + explicit_self_ty, + false, + path_id.type_ref().into(), + ), + ctx, + )) } fn lower_trait_ref( @@ -639,7 +712,10 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { ctx.ty_ctx().unsized_types.insert(self_ty); } else { if !ignore_bindings { - assoc_bounds = ctx.assoc_type_bindings_from_type_bound(trait_ref); + assoc_bounds = ctx.assoc_type_bindings_from_type_bound( + trait_ref, + path.type_ref().into(), + ); } clause = Some(Clause(Predicate::new( interner, @@ -686,7 +762,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { fn lower_dyn_trait(&mut self, bounds: &[TypeBound]) -> Ty<'db> { let interner = self.interner; - let dummy_self_ty = dyn_trait_dummy_self(interner); + let dummy_self_ty = self.types.types.dyn_trait_dummy_self; let mut region = None; // INVARIANT: The principal trait bound, if present, must come first. Others may be in any // order but should be in the same order for the same set but possibly different order of @@ -884,7 +960,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { .map(|arg| { if arg.walk().any(|arg| arg == dummy_self_ty.into()) { // FIXME: Report an error. - Ty::new_error(interner, ErrorGuaranteed).into() + self.types.types.error.into() } else { arg } @@ -910,8 +986,11 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { false }); if references_self { - proj.projection_term = - replace_dummy_self_with_error(interner, proj.projection_term); + proj.projection_term = replace_dummy_self_with_error( + interner, + self.types, + proj.projection_term, + ); } ExistentialPredicate::Projection(ExistentialProjection::erase_self_ty( @@ -949,7 +1028,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { } else { // FIXME: report error // (additional non-auto traits, associated type rebound, or no resolved trait) - Ty::new_error(self.interner, ErrorGuaranteed) + self.types.types.error } } @@ -1083,20 +1162,15 @@ impl<T> TyLoweringResult<T> { } } -fn dyn_trait_dummy_self(interner: DbInterner<'_>) -> Ty<'_> { - // This type must not appear anywhere except here. - Ty::new_fresh(interner, 0) -} - fn replace_dummy_self_with_error<'db, T: TypeFoldable<DbInterner<'db>>>( interner: DbInterner<'db>, + types: &DefaultAny<'db>, t: T, ) -> T { - let dyn_trait_dummy_self = dyn_trait_dummy_self(interner); t.fold_with(&mut BottomUpFolder { interner, ty_op: |ty| { - if ty == dyn_trait_dummy_self { Ty::new_error(interner, ErrorGuaranteed) } else { ty } + if ty == types.types.dyn_trait_dummy_self { types.types.error } else { ty } }, lt_op: |lt| lt, ct_op: |ct| ct, @@ -1126,12 +1200,14 @@ pub(crate) fn impl_trait_with_diagnostics( ) -> Option<TyLoweringResult<StoredEarlyBinder<StoredTraitRef>>> { let impl_data = ImplSignature::of(db, impl_id); let resolver = impl_id.resolver(db); + let generics = OnceCell::new(); let mut ctx = TyLoweringContext::new( db, &resolver, &impl_data.store, ExpressionStoreOwnerId::Signature(impl_id.into()), impl_id.into(), + &generics, LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true }, ); let self_ty = db.impl_self_ty(impl_id).skip_binder(); @@ -1208,12 +1284,14 @@ impl ImplTraits { // FIXME unify with fn_sig_for_fn instead of doing lowering twice, maybe let data = FunctionSignature::of(db, def); let resolver = def.resolver(db); + let generics = OnceCell::new(); let mut ctx_ret = TyLoweringContext::new( db, &resolver, &data.store, ExpressionStoreOwnerId::Signature(def.into()), def.into(), + &generics, LifetimeElisionKind::Infer, ) .with_impl_trait_mode(ImplTraitLoweringMode::Opaque); @@ -1237,12 +1315,14 @@ impl ImplTraits { ) -> Option<Box<StoredEarlyBinder<ImplTraits>>> { let data = TypeAliasSignature::of(db, def); let resolver = def.resolver(db); + let generics = OnceCell::new(); let mut ctx = TyLoweringContext::new( db, &resolver, &data.store, ExpressionStoreOwnerId::Signature(def.into()), def.into(), + &generics, LifetimeElisionKind::AnonymousReportError, ) .with_impl_trait_mode(ImplTraitLoweringMode::Opaque); @@ -1336,12 +1416,14 @@ pub(crate) fn type_for_const_with_diagnostics( let resolver = def.resolver(db); let data = ConstSignature::of(db, def); let parent = def.loc(db).container; + let generics = OnceCell::new(); let mut ctx = TyLoweringContext::new( db, &resolver, &data.store, ExpressionStoreOwnerId::Signature(def.into()), def.into(), + &generics, LifetimeElisionKind::AnonymousReportError, ); ctx.set_lifetime_elision(LifetimeElisionKind::for_const(ctx.interner, parent)); @@ -1364,12 +1446,14 @@ pub(crate) fn type_for_static_with_diagnostics( ) -> TyLoweringResult<StoredEarlyBinder<StoredTy>> { let resolver = def.resolver(db); let data = StaticSignature::of(db, def); + let generics = OnceCell::new(); let mut ctx = TyLoweringContext::new( db, &resolver, &data.store, ExpressionStoreOwnerId::Signature(def.into()), def.into(), + &generics, LifetimeElisionKind::AnonymousReportError, ); ctx.set_lifetime_elision(LifetimeElisionKind::Elided(Region::new_static(ctx.interner))); @@ -1437,19 +1521,21 @@ pub(crate) fn type_for_type_alias_with_diagnostics( t: TypeAliasId, ) -> TyLoweringResult<StoredEarlyBinder<StoredTy>> { let type_alias_data = TypeAliasSignature::of(db, t); - let resolver = t.resolver(db); let interner = DbInterner::new_no_crate(db); if type_alias_data.flags.contains(TypeAliasFlags::IS_EXTERN) { TyLoweringResult::empty(StoredEarlyBinder::bind( Ty::new_foreign(interner, t.into()).store(), )) } else { + let resolver = t.resolver(db); + let generics = OnceCell::new(); let mut ctx = TyLoweringContext::new( db, &resolver, &type_alias_data.store, ExpressionStoreOwnerId::Signature(t.into()), t.into(), + &generics, LifetimeElisionKind::AnonymousReportError, ) .with_impl_trait_mode(ImplTraitLoweringMode::Opaque); @@ -1487,7 +1573,7 @@ pub(crate) fn impl_self_ty_with_diagnostics( impl_id: ImplId, ) -> TyLoweringResult<StoredEarlyBinder<StoredTy>> { let resolver = impl_id.resolver(db); - + let generics = OnceCell::new(); let impl_data = ImplSignature::of(db, impl_id); let mut ctx = TyLoweringContext::new( db, @@ -1495,6 +1581,7 @@ pub(crate) fn impl_self_ty_with_diagnostics( &impl_data.store, ExpressionStoreOwnerId::Signature(impl_id.into()), impl_id.into(), + &generics, LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true }, ); let ty = ctx.lower_ty(impl_data.self_ty); @@ -1535,12 +1622,14 @@ pub(crate) fn const_param_types_with_diagnostics( let mut result = ArenaMap::new(); let (data, store) = GenericParams::with_store(db, def); let resolver = def.resolver(db); + let generics = OnceCell::new(); let mut ctx = TyLoweringContext::new( db, &resolver, store, ExpressionStoreOwnerId::Signature(def), def, + &generics, LifetimeElisionKind::AnonymousReportError, ); ctx.forbid_params_after(0, ForbidParamsAfterReason::ConstParamTy); @@ -1585,6 +1674,7 @@ pub(crate) fn field_types_with_diagnostics( VariantId::UnionId(it) => (it.resolver(db), it.into()), VariantId::EnumVariantId(it) => (it.resolver(db), it.lookup(db).parent.into()), }; + let generics = OnceCell::new(); let mut res = ArenaMap::default(); let mut ctx = TyLoweringContext::new( db, @@ -1592,6 +1682,7 @@ pub(crate) fn field_types_with_diagnostics( &var_data.store, ExpressionStoreOwnerId::VariantFields(variant_id), generic_def, + &generics, LifetimeElisionKind::AnonymousReportError, ); for (field_id, field_data) in var_data.fields().iter() { @@ -1714,16 +1805,20 @@ fn resolve_type_param_assoc_type_shorthand( assoc_name: Name, ) -> AssocTypeShorthandResolution { let generics = generics(db, def); + let store = generics.store(); + let generics = &OnceCell::from(generics); let resolver = def.resolver(db); let mut ctx = TyLoweringContext::new( db, &resolver, - generics.store(), + store, ExpressionStoreOwnerId::Signature(def), def, + generics, LifetimeElisionKind::AnonymousReportError, ); let interner = ctx.interner; + let generics = generics.get().unwrap(); let param_ty = Ty::new_param(interner, param, generics.type_or_const_param_idx(param.into())); let mut this_trait_resolution = None; @@ -1891,13 +1986,15 @@ pub(crate) fn type_alias_bounds_with_diagnostics( type_alias: TypeAliasId, ) -> TyLoweringResult<TypeAliasBounds<StoredEarlyBinder<StoredClauses>>> { let type_alias_data = TypeAliasSignature::of(db, type_alias); - let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db); + let resolver = type_alias.resolver(db); + let generics = OnceCell::new(); let mut ctx = TyLoweringContext::new( db, &resolver, &type_alias_data.store, ExpressionStoreOwnerId::Signature(type_alias.into()), type_alias.into(), + &generics, LifetimeElisionKind::AnonymousReportError, ); let interner = ctx.interner; @@ -2130,16 +2227,20 @@ fn generic_predicates( def: GenericDefId, ) -> TyLoweringResult<GenericPredicates> { let generics = generics(db, def); + let store = generics.store(); + let generics = &OnceCell::from(generics); let resolver = def.resolver(db); let interner = DbInterner::new_no_crate(db); let mut ctx = TyLoweringContext::new( db, &resolver, - generics.store(), + store, ExpressionStoreOwnerId::Signature(def), def, + generics, LifetimeElisionKind::AnonymousReportError, ); + let generics = generics.get().unwrap(); let sized_trait = ctx.lang_items.Sized; // We need to lower parents and self separately - see the comment below lowering of implicit @@ -2339,24 +2440,27 @@ pub(crate) fn generic_defaults_with_diagnostics( db: &dyn HirDatabase, def: GenericDefId, ) -> TyLoweringResult<GenericDefaults> { - let generic_params = generics(db, def); - if generic_params.has_no_params() { + let generics = generics(db, def); + if generics.has_no_params() { return TyLoweringResult::empty(GenericDefaults(ThinVec::new())); } let resolver = def.resolver(db); - let store_for_self = generic_params.store(); + let store_for_self = generics.store(); + let generics = &OnceCell::from(generics); let mut ctx = TyLoweringContext::new( db, &resolver, store_for_self, ExpressionStoreOwnerId::Signature(def), def, + generics, LifetimeElisionKind::AnonymousReportError, ) .with_impl_trait_mode(ImplTraitLoweringMode::Disallowed); + let generics = generics.get().unwrap(); let mut defaults = ThinVec::new(); - if let Some(parent) = generic_params.parent() { + if let Some(parent) = generics.parent() { ctx.store = parent.store(); defaults.extend( parent.iter_with_idx().map(|(idx, _id, p)| handle_generic_param(&mut ctx, idx, p)), @@ -2366,9 +2470,7 @@ pub(crate) fn generic_defaults_with_diagnostics( ctx.defined_anon_consts.clear(); ctx.store = store_for_self; defaults.extend( - generic_params - .iter_self_with_idx() - .map(|(idx, _id, p)| handle_generic_param(&mut ctx, idx, p)), + generics.iter_self_with_idx().map(|(idx, _id, p)| handle_generic_param(&mut ctx, idx, p)), ); defaults.shrink_to_fit(); return TyLoweringResult::from_ctx(GenericDefaults(defaults), ctx); @@ -2434,12 +2536,14 @@ fn fn_sig_for_fn( let data = FunctionSignature::of(db, def); let resolver = def.resolver(db); let interner = DbInterner::new_no_crate(db); + let generics = OnceCell::new(); let mut ctx_params = TyLoweringContext::new( db, &resolver, &data.store, ExpressionStoreOwnerId::Signature(def.into()), def.into(), + &generics, LifetimeElisionKind::for_fn_params(data), ); let params = data.params.iter().map(|&tr| ctx_params.lower_ty(tr)); @@ -2450,6 +2554,7 @@ fn fn_sig_for_fn( &data.store, ExpressionStoreOwnerId::Signature(def.into()), def.into(), + &generics, LifetimeElisionKind::for_fn_ret(interner), ) .with_impl_trait_mode(ImplTraitLoweringMode::Opaque); @@ -2521,14 +2626,16 @@ pub(crate) fn associated_ty_item_bounds<'db>( type_alias: TypeAliasId, ) -> EarlyBinder<'db, BoundExistentialPredicates<'db>> { let type_alias_data = TypeAliasSignature::of(db, type_alias); - let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db); + let resolver = type_alias.resolver(db); let interner = DbInterner::new_no_crate(db); + let generics = OnceCell::new(); let mut ctx = TyLoweringContext::new( db, &resolver, &type_alias_data.store, ExpressionStoreOwnerId::Signature(type_alias.into()), type_alias.into(), + &generics, LifetimeElisionKind::AnonymousReportError, ); // FIXME: we should never create non-existential predicates in the first place diff --git a/crates/hir-ty/src/lower/path.rs b/crates/hir-ty/src/lower/path.rs index dfa8873b86..0757d57500 100644 --- a/crates/hir-ty/src/lower/path.rs +++ b/crates/hir-ty/src/lower/path.rs @@ -25,10 +25,10 @@ use smallvec::SmallVec; use crate::{ GenericArgsProhibitedReason, IncorrectGenericsLenKind, PathGenericsSource, - PathLoweringDiagnostic, TyDefId, ValueTyDefId, - consteval::{unknown_const, unknown_const_as_generic}, + PathLoweringDiagnostic, Span, TyDefId, ValueTyDefId, db::HirDatabase, generics::{Generics, generics}, + infer::unify::InferenceTable, lower::{ AssocTypeShorthandResolution, ForbidParamsAfterReason, GenericPredicateSource, LifetimeElisionKind, PathDiagnosticCallbackData, const_param_ty, @@ -84,6 +84,11 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { } } + #[track_caller] + pub(crate) fn expect_table(&mut self) -> &mut InferenceTable<'db> { + self.ctx.expect_table() + } + #[inline] #[cold] fn on_diagnostic(&mut self, diag: PathLoweringDiagnostic) { @@ -149,17 +154,18 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { // We need the original resolution to lower `Self::AssocTy` correctly res: Option<TypeNs>, infer_args: bool, + span: Span, ) -> (Ty<'db>, Option<TypeNs>) { let remaining_segments = self.segments.len() - self.current_segment_idx; match remaining_segments { 0 => (ty, res), 1 => { // resolve unselected assoc types - (self.select_associated_type(res, infer_args), None) + (self.select_associated_type(res, infer_args, span), None) } _ => { // FIXME report error (ambiguous associated type) - (Ty::new_error(self.ctx.interner, ErrorGuaranteed), None) + (self.ctx.types.types.error, None) } } } @@ -169,6 +175,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { &mut self, resolution: TypeNs, infer_args: bool, + span: Span, ) -> (Ty<'db>, Option<TypeNs>) { let remaining_segments = self.segments.skip(self.current_segment_idx + 1); tracing::debug!(?remaining_segments); @@ -181,8 +188,9 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { 1 => { let trait_ref = self.lower_trait_ref_from_resolved_path( trait_, - Ty::new_error(self.ctx.interner, ErrorGuaranteed), + self.ctx.types.types.error, infer_args, + span, ); tracing::debug!(?trait_ref); self.skip_resolved_segment(); @@ -203,6 +211,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { infer_args, None, true, + span, ); let args = GenericArgs::new_from_iter( self.ctx.interner, @@ -222,7 +231,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { } None => { // FIXME: report error (associated type not found) - Ty::new_error(self.ctx.interner, ErrorGuaranteed) + self.ctx.types.types.error } } } @@ -230,11 +239,11 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { // Trait object type without dyn; this should be handled in upstream. See // `lower_path()`. stdx::never!("unexpected fully resolved trait path"); - Ty::new_error(self.ctx.interner, ErrorGuaranteed) + self.ctx.types.types.error } _ => { // FIXME report error (ambiguous associated type) - Ty::new_error(self.ctx.interner, ErrorGuaranteed) + self.ctx.types.types.error } }; return (ty, None); @@ -250,19 +259,19 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { Ty::new_adt(self.ctx.interner, adt, args) } - TypeNs::AdtId(it) => self.lower_path_inner(it.into(), infer_args), - TypeNs::BuiltinType(it) => self.lower_path_inner(it.into(), infer_args), - TypeNs::TypeAliasId(it) => self.lower_path_inner(it.into(), infer_args), + TypeNs::AdtId(it) => self.lower_path_inner(it.into(), infer_args, span), + TypeNs::BuiltinType(it) => self.lower_path_inner(it.into(), infer_args, span), + TypeNs::TypeAliasId(it) => self.lower_path_inner(it.into(), infer_args, span), // FIXME: report error TypeNs::EnumVariantId(_) | TypeNs::ModuleId(_) => { - return (Ty::new_error(self.ctx.interner, ErrorGuaranteed), None); + return (self.ctx.types.types.error, None); } }; tracing::debug!(?ty); self.skip_resolved_segment(); - self.lower_ty_relative_path(ty, Some(resolution), infer_args) + self.lower_ty_relative_path(ty, Some(resolution), infer_args, span) } /// This returns whether to keep the resolution (`true`) of throw it (`false`). @@ -470,13 +479,17 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { } #[tracing::instrument(skip(self), ret)] - fn select_associated_type(&mut self, res: Option<TypeNs>, infer_args: bool) -> Ty<'db> { + fn select_associated_type( + &mut self, + res: Option<TypeNs>, + infer_args: bool, + span: Span, + ) -> Ty<'db> { let interner = self.ctx.interner; let db = self.ctx.db; let def = self.ctx.generic_def; let segment = self.current_or_prev_segment; let assoc_name = segment.name; - let error_ty = || Ty::new_error(self.ctx.interner, ErrorGuaranteed); let (assoc_type, trait_args) = match res { Some(TypeNs::GenericParam(param)) => { let AssocTypeShorthandResolution::Resolved(assoc_type) = @@ -488,7 +501,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { ) else { // FIXME: Emit an error. - return error_ty(); + return self.ctx.types.types.error; }; assoc_type .get_with(|(assoc_type, trait_args)| (*assoc_type, trait_args.as_ref())) @@ -496,7 +509,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { } Some(TypeNs::SelfType(impl_)) => { let Some(impl_trait) = db.impl_trait(impl_) else { - return error_ty(); + return self.ctx.types.types.error; }; let impl_trait = impl_trait.instantiate_identity().skip_norm_wip(); // Searching for `Self::Assoc` in `impl Trait for Type` is like searching for `Self::Assoc` in `Trait`. @@ -509,7 +522,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { ) else { // FIXME: Emit an error. - return error_ty(); + return self.ctx.types.types.error; }; let (assoc_type, trait_args) = assoc_type .get_with(|(assoc_type, trait_args)| (*assoc_type, trait_args.as_ref())) @@ -521,14 +534,14 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { .skip_norm_wip(), ) } - _ => return error_ty(), + _ => return self.ctx.types.types.error, }; // FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent // generic params. It's inefficient to splice the `Substitution`s, so we may want // that method to optionally take parent `Substitution` as we already know them at // this point (`t.substitution`). - let substs = self.substs_from_path_segment(assoc_type.into(), infer_args, None, true); + let substs = self.substs_from_path_segment(assoc_type.into(), infer_args, None, true, span); let substs = GenericArgs::new_from_iter( interner, @@ -538,7 +551,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { Ty::new_projection_from_args(interner, assoc_type.into(), substs) } - fn lower_path_inner(&mut self, typeable: TyDefId, infer_args: bool) -> Ty<'db> { + fn lower_path_inner(&mut self, typeable: TyDefId, infer_args: bool, span: Span) -> Ty<'db> { let generic_def = match typeable { TyDefId::BuiltinType(builtinty) => { return Ty::from_builtin_type(self.ctx.interner, builtinty); @@ -546,7 +559,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { TyDefId::AdtId(it) => it.into(), TyDefId::TypeAliasId(it) => it.into(), }; - let args = self.substs_from_path_segment(generic_def, infer_args, None, false); + let args = self.substs_from_path_segment(generic_def, infer_args, None, false, span); let ty = ty_query(self.ctx.db, typeable); ty.instantiate(self.ctx.interner, args).skip_norm_wip() } @@ -561,6 +574,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { resolved: ValueTyDefId, infer_args: bool, lowering_assoc_type_generics: bool, + span: Span, ) -> GenericArgs<'db> { let interner = self.ctx.interner; let prev_current_segment_idx = self.current_segment_idx; @@ -604,6 +618,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { infer_args, None, lowering_assoc_type_generics, + span, ); self.current_segment_idx = prev_current_segment_idx; self.current_or_prev_segment = prev_current_segment; @@ -616,6 +631,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { infer_args: bool, explicit_self_ty: Option<Ty<'db>>, lowering_assoc_type_generics: bool, + span: Span, ) -> GenericArgs<'db> { let old_lifetime_elision = self.ctx.lifetime_elision; @@ -656,6 +672,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { PathGenericsSource::Segment(self.current_segment_u32()), lowering_assoc_type_generics, self.ctx.lifetime_elision, + span, ); self.ctx.lifetime_elision = old_lifetime_elision; result @@ -670,10 +687,12 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { generics_source: PathGenericsSource, lowering_assoc_type_generics: bool, lifetime_elision: LifetimeElisionKind<'db>, + span: Span, ) -> GenericArgs<'db> { struct LowererCtx<'a, 'b, 'c, 'db> { ctx: &'a mut PathLoweringContext<'b, 'c, 'db>, generics_source: PathGenericsSource, + span: Span, } impl<'db> GenericArgsLowerer<'db> for LowererCtx<'_, '_, '_, 'db> { @@ -736,13 +755,13 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { fn provided_type_like_const( &mut self, - _type_ref: TypeRefId, + type_ref: TypeRefId, const_ty: Ty<'db>, arg: TypeLikeConst<'_>, ) -> Const<'db> { match arg { TypeLikeConst::Path(path) => self.ctx.ctx.lower_path_as_const(path, const_ty), - TypeLikeConst::Infer => unknown_const(const_ty), + TypeLikeConst::Infer => self.ctx.ctx.next_const_var(type_ref.into()), } } @@ -753,16 +772,18 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { param: GenericParamDataRef<'_>, infer_args: bool, preceding_args: &[GenericArg<'db>], + had_count_error: bool, ) -> GenericArg<'db> { let default = || { self.ctx.ctx.db.generic_defaults(def).get(preceding_args.len()).map(|default| { default.instantiate(self.ctx.ctx.interner, preceding_args).skip_norm_wip() }) }; + // If `!infer_args`, we've already emitted an error, so put a dummy span. + let span = if !infer_args || had_count_error { Span::Dummy } else { self.span }; match param { GenericParamDataRef::LifetimeParamData(_) => { - Region::new(self.ctx.ctx.interner, rustc_type_ir::ReError(ErrorGuaranteed)) - .into() + self.ctx.ctx.next_region_var(span).into() } GenericParamDataRef::TypeParamData(param) => { if !infer_args @@ -771,7 +792,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { { return default; } - Ty::new_error(self.ctx.ctx.interner, ErrorGuaranteed).into() + self.ctx.ctx.next_ty_var_no_placeholder(span).into() } GenericParamDataRef::ConstParamData(param) => { if !infer_args @@ -780,10 +801,10 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { { return default; } - let GenericParamId::ConstParamId(const_id) = param_id else { + let GenericParamId::ConstParamId(_) = param_id else { unreachable!("non-const param ID for const param"); }; - unknown_const_as_generic(const_param_ty(self.ctx.ctx.db, const_id)) + self.ctx.ctx.next_const_var(span).into() } } } @@ -793,13 +814,8 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { GenericParamId::TypeParamId(_) => { Ty::new_error(self.ctx.ctx.interner, ErrorGuaranteed).into() } - GenericParamId::ConstParamId(const_id) => { - unknown_const_as_generic(const_param_ty(self.ctx.ctx.db, const_id)) - } - GenericParamId::LifetimeParamId(_) => { - Region::new(self.ctx.ctx.interner, rustc_type_ir::ReError(ErrorGuaranteed)) - .into() - } + GenericParamId::ConstParamId(_) => self.ctx.ctx.types.consts.error.into(), + GenericParamId::LifetimeParamId(_) => self.ctx.ctx.types.regions.error.into(), } } @@ -843,7 +859,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { lifetime_elision, lowering_assoc_type_generics, explicit_self_ty, - &mut LowererCtx { ctx: self, generics_source }, + &mut LowererCtx { ctx: self, generics_source, span }, ) } @@ -852,8 +868,9 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { resolved: TraitId, explicit_self_ty: Ty<'db>, infer_args: bool, + span: Span, ) -> TraitRef<'db> { - let args = self.trait_ref_substs_from_path(resolved, explicit_self_ty, infer_args); + let args = self.trait_ref_substs_from_path(resolved, explicit_self_ty, infer_args, span); TraitRef::new_from_args(self.ctx.interner, resolved.into(), args) } @@ -862,13 +879,21 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { resolved: TraitId, explicit_self_ty: Ty<'db>, infer_args: bool, + span: Span, ) -> GenericArgs<'db> { - self.substs_from_path_segment(resolved.into(), infer_args, Some(explicit_self_ty), false) + self.substs_from_path_segment( + resolved.into(), + infer_args, + Some(explicit_self_ty), + false, + span, + ) } pub(super) fn assoc_type_bindings_from_type_bound<'c>( mut self, trait_ref: TraitRef<'db>, + span: Span, ) -> Option<impl Iterator<Item = (Clause<'db>, GenericPredicateSource)> + use<'a, 'b, 'c, 'db>> { let interner = self.ctx.interner; @@ -900,6 +925,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { }, false, this.ctx.lifetime_elision, + span, ) }); let args = GenericArgs::new_from_iter( @@ -1019,6 +1045,7 @@ pub(crate) trait GenericArgsLowerer<'db> { param: GenericParamDataRef<'_>, infer_args: bool, preceding_args: &[GenericArg<'db>], + had_count_error: bool, ) -> GenericArg<'db>; fn parent_arg(&mut self, param_idx: u32, param_id: GenericParamId) -> GenericArg<'db>; @@ -1187,7 +1214,14 @@ pub(crate) fn substs_from_args_and_bindings<'db>( ctx.provided_kind(self_param_id, self_param, self_ty) } else { explicit_self_ty.map(|it| it.into()).unwrap_or_else(|| { - ctx.inferred_kind(def, self_param_id, self_param, infer_args, &substs) + ctx.inferred_kind( + def, + self_param_id, + self_param, + infer_args, + &substs, + had_count_error, + ) }) }; params.next(); @@ -1206,7 +1240,14 @@ pub(crate) fn substs_from_args_and_bindings<'db>( { // Do not allow specifying `impl Trait` explicitly. We already err at that, but if we won't handle it here // we will handle it as if it was specified, instead of inferring it. - substs.push(ctx.inferred_kind(def, param_id, param, infer_args, &substs)); + substs.push(ctx.inferred_kind( + def, + param_id, + param, + infer_args, + &substs, + had_count_error, + )); params.next(); } (HirGenericArg::Lifetime(_), GenericParamDataRef::LifetimeParamData(_)) @@ -1222,7 +1263,14 @@ pub(crate) fn substs_from_args_and_bindings<'db>( ) => { // We expected a lifetime argument, but got a type or const // argument. That means we're inferring the lifetime. - substs.push(ctx.inferred_kind(def, param_id, param, infer_args, &substs)); + substs.push(ctx.inferred_kind( + def, + param_id, + param, + infer_args, + &substs, + had_count_error, + )); params.next(); force_infer_lt = Some((arg_idx as u32, param_id)); } @@ -1291,7 +1339,14 @@ pub(crate) fn substs_from_args_and_bindings<'db>( | LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true } | LifetimeElisionKind::AnonymousReportError => { assert!(had_count_error); - ctx.inferred_kind(def, param_id, param, infer_args, &substs) + ctx.inferred_kind( + def, + param_id, + param, + infer_args, + &substs, + had_count_error, + ) } LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: _ } => { Region::new_static(interner).into() @@ -1301,11 +1356,18 @@ pub(crate) fn substs_from_args_and_bindings<'db>( | LifetimeElisionKind::Infer => { // FIXME: With `AnonymousCreateParameter`, we need to create a new lifetime parameter here // (but this will probably be done in hir-def lowering instead). - ctx.inferred_kind(def, param_id, param, infer_args, &substs) + ctx.inferred_kind( + def, + param_id, + param, + infer_args, + &substs, + had_count_error, + ) } } } else { - ctx.inferred_kind(def, param_id, param, infer_args, &substs) + ctx.inferred_kind(def, param_id, param, infer_args, &substs, had_count_error) }; substs.push(param); params.next(); diff --git a/crates/hir-ty/src/method_resolution/confirm.rs b/crates/hir-ty/src/method_resolution/confirm.rs index a3a5a9ca54..c425e69dc5 100644 --- a/crates/hir-ty/src/method_resolution/confirm.rs +++ b/crates/hir-ty/src/method_resolution/confirm.rs @@ -427,12 +427,15 @@ impl<'a, 'b, 'db> ConfirmContext<'a, 'b, 'db> { _def: GenericDefId, param_id: GenericParamId, _param: GenericParamDataRef<'_>, - _infer_args: bool, + infer_args: bool, _preceding_args: &[GenericArg<'db>], + had_count_error: bool, ) -> 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.var_for_def(param_id, Span::Dummy) + let span = + if !infer_args || had_count_error { Span::Dummy } else { self.expr.into() }; + self.ctx.table.var_for_def(param_id, span) } fn parent_arg(&mut self, param_idx: u32, _param_id: GenericParamId) -> GenericArg<'db> { diff --git a/crates/hir-ty/src/next_solver.rs b/crates/hir-ty/src/next_solver.rs index 78fdb1548c..47b4b1dc4a 100644 --- a/crates/hir-ty/src/next_solver.rs +++ b/crates/hir-ty/src/next_solver.rs @@ -93,6 +93,7 @@ pub struct DefaultTypes<'db> { pub static_u8_slice: Ty<'db>, /// `*mut ()` pub mut_unit_ptr: Ty<'db>, + pub dyn_trait_dummy_self: Ty<'db>, } pub struct DefaultConsts<'db> { @@ -272,6 +273,8 @@ pub fn default_types<'a, 'db>(db: &'db dyn HirDatabase) -> &'a DefaultAny<'db> { u8_slice, static_u8_slice, mut_unit_ptr: create_ty(TyKind::RawPtr(unit, rustc_ast_ir::Mutability::Mut)), + // This type must not appear anywhere except here. + dyn_trait_dummy_self: create_ty(TyKind::Infer(rustc_type_ir::InferTy::FreshTy(0))), }, consts: DefaultConsts { error: create_const(ConstKind::Error(ErrorGuaranteed)), diff --git a/crates/hir-ty/src/next_solver/infer/mod.rs b/crates/hir-ty/src/next_solver/infer/mod.rs index d51a4c1312..839bdf17e7 100644 --- a/crates/hir-ty/src/next_solver/infer/mod.rs +++ b/crates/hir-ty/src/next_solver/infer/mod.rs @@ -430,13 +430,12 @@ impl<'db> InferCtxt<'db> { )) } - pub(crate) fn insert_type_vars<T>(&self, ty: T, span: Span) -> T + pub(crate) fn insert_type_vars<T>(&self, ty: T) -> 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> { @@ -449,7 +448,7 @@ impl<'db> InferCtxt<'db> { } if ty.is_ty_error() { - self.infcx.next_ty_var(self.span) + self.infcx.next_ty_var(Span::Dummy) } else { ty.super_fold_with(self) } @@ -461,18 +460,18 @@ impl<'db> InferCtxt<'db> { } if ct.is_ct_error() { - self.infcx.next_const_var(self.span) + self.infcx.next_const_var(Span::Dummy) } 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(self.span) } else { r } + if r.is_error() { self.infcx.next_region_var(Span::Dummy) } else { r } } } - ty.fold_with(&mut Folder { infcx: self, span }) + ty.fold_with(&mut Folder { infcx: self }) } /// Evaluates whether the predicate can be satisfied in the given diff --git a/crates/hir-ty/src/opaques.rs b/crates/hir-ty/src/opaques.rs index d39e74b9af..4244b1bac4 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, InferBodyId, InferenceResult, Span, + ImplTraitId, InferBodyId, InferenceResult, db::{HirDatabase, InternedOpaqueTyId}, lower::{ImplTraitIdx, ImplTraits}, next_solver::{ @@ -146,7 +146,7 @@ pub(crate) fn tait_hidden_types( } // 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(), Span::Dummy); + let hidden_type = infcx.insert_type_vars(hidden_type.as_ref()); match result.entry(opaque_idx) { la_arena::Entry::Vacant(entry) => { entry.insert(StoredEarlyBinder::bind(hidden_type.store())); diff --git a/crates/hir-ty/src/tests/simple.rs b/crates/hir-ty/src/tests/simple.rs index 76da816055..c0b8d93b47 100644 --- a/crates/hir-ty/src/tests/simple.rs +++ b/crates/hir-ty/src/tests/simple.rs @@ -2697,7 +2697,6 @@ fn generic_default_in_struct_literal() { #[test] fn generic_default_depending_on_other_type_arg() { - // FIXME: the {unknown} is a bug check_infer( r#" struct Thing<T = u128, F = fn() -> T> { t: T } @@ -2714,7 +2713,7 @@ fn generic_default_depending_on_other_type_arg() { 83..130 '{ ...2 }; }': () 89..91 't1': Thing<u32, fn() -> u32> 97..99 't2': Thing<u128, fn() -> u128> - 105..127 'Thing:...1u32 }': Thing<u32, fn() -> {unknown}> + 105..127 'Thing:...1u32 }': Thing<u32, fn() -> u32> 121..125 '1u32': u32 "#]], ); diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index 4029b004a7..0fc439b3cc 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -5,7 +5,10 @@ //! //! So, this modules should not be used during hir construction, it exists //! purely for "IDE needs". -use std::iter::{self, once}; +use std::{ + cell::OnceCell, + iter::{self, once}, +}; use either::Either; use hir_def::{ @@ -374,12 +377,14 @@ impl<'db> SourceAnalyzer<'db> { let type_ref = self.type_id(ty)?; let generic_def = self.resolver.generic_def()?; + let generics = OnceCell::new(); let mut ty = TyLoweringContext::new( db, &self.resolver, self.store()?, generic_def.into(), generic_def, + &generics, // FIXME: Is this correct here? Anyway that should impact mostly diagnostics, which we don't emit here // (this can impact the lifetimes generated, e.g. in `const` they won't be `'static`, but this seems like a // small problem). @@ -1753,12 +1758,14 @@ fn resolve_hir_path_( let types = || { let (ty, unresolved) = match path.type_anchor() { Some(type_ref) => resolver.generic_def().and_then(|def| { + let generics = OnceCell::new(); let (_, res) = TyLoweringContext::new( db, resolver, store?, def.into(), def, + &generics, LifetimeElisionKind::Infer, ) .lower_ty_ext(type_ref); @@ -1909,12 +1916,14 @@ fn resolve_hir_path_qualifier( (|| { let (ty, unresolved) = match path.type_anchor() { Some(type_ref) => resolver.generic_def().and_then(|def| { + let generics = OnceCell::new(); let (_, res) = TyLoweringContext::new( db, resolver, store, def.into(), def, + &generics, LifetimeElisionKind::Infer, ) .lower_ty_ext(type_ref); diff --git a/crates/ide-diagnostics/src/handlers/incorrect_generics_len.rs b/crates/ide-diagnostics/src/handlers/incorrect_generics_len.rs index 9c04d2be8a..5ee02279a2 100644 --- a/crates/ide-diagnostics/src/handlers/incorrect_generics_len.rs +++ b/crates/ide-diagnostics/src/handlers/incorrect_generics_len.rs @@ -43,8 +43,6 @@ struct Bar<T, U>(T, U); fn foo() { let _ = Bar::<()>; // ^^^^^^ error: this struct takes 2 generic arguments but 1 generic argument was supplied - // ^^^^^^^^^ error: type annotations needed - // | full type: `fn Bar<(), {unknown}>((), {unknown}) -> Bar<(), {unknown}>` } "#, @@ -53,10 +51,6 @@ fn foo() { #[test] fn enum_variant() { - // FIXME: We should not have a "type annotations needed" error here, but to do that - // we'll need to have access to the `InferenceContext` in `TyLoweringContext`, to - // generate the infer var with a dummy span (instead of inserting it after the fact - // with a non-dummy span). check_diagnostics( r#" enum Enum<T, U> { @@ -66,12 +60,8 @@ enum Enum<T, U> { fn foo() { let _ = Enum::<()>::Variant; // ^^^^^^ error: this enum takes 2 generic arguments but 1 generic argument was supplied - // ^^^^^^^^^^^^^^^^^^^ error: type annotations needed - // | full type: `fn Variant<(), {unknown}>((), {unknown}) -> Enum<(), {unknown}>` let _ = Enum::Variant::<()>; // ^^^^^^ error: this enum takes 2 generic arguments but 1 generic argument was supplied - // ^^^^^^^^^^^^^^^^^^^ error: type annotations needed - // | full type: `fn Variant<(), {unknown}>((), {unknown}) -> Enum<(), {unknown}>` } "#, @@ -137,8 +127,6 @@ struct Bar<T, const N: usize>(T); fn bar() { let _ = Bar::<()>; // ^^^^^^ error: this struct takes 2 generic arguments but 1 generic argument was supplied - // ^^^^^^^^^ error: type annotations needed - // | full type: `fn Bar<(), _>(()) -> Bar<(), _>` } "#, ); |