Unnamed repository; edit this file 'description' to name the repository.
Refactor handling of generic params in `hir::Type`
The essence of the new handling is that `hir::Type` now remembers its owner (and not `ParamEnv`; we could remember both but that is unnecessary) and refuse (panics) to work with types not from the same owner. It would be best if we could enforce this statically, but unfortunately we can't.
Chayim Refael Friedman 13 days ago
parent c6786ca · commit fbe801a
-rw-r--r--crates/hir-ty/src/traits.rs6
-rw-r--r--crates/hir/src/attrs.rs15
-rw-r--r--crates/hir/src/diagnostics.rs61
-rw-r--r--crates/hir/src/display.rs12
-rw-r--r--crates/hir/src/lib.rs1353
-rw-r--r--crates/hir/src/semantics.rs10
-rw-r--r--crates/hir/src/source_analyzer.rs120
-rw-r--r--crates/hir/src/term_search/expr.rs17
-rw-r--r--crates/hir/src/term_search/tactics.rs87
-rw-r--r--crates/ide-assists/src/handlers/add_missing_match_arms.rs29
-rw-r--r--crates/ide-assists/src/handlers/auto_import.rs2
-rw-r--r--crates/ide-assists/src/handlers/expand_rest_pattern.rs8
-rw-r--r--crates/ide-assists/src/handlers/generate_from_impl_for_enum.rs7
-rw-r--r--crates/ide-assists/src/handlers/generate_single_field_struct_from.rs7
-rw-r--r--crates/ide-assists/src/handlers/replace_method_eager_lazy.rs13
-rw-r--r--crates/ide-assists/src/handlers/wrap_return_type.rs4
-rw-r--r--crates/ide-completion/src/completions.rs6
-rw-r--r--crates/ide-completion/src/completions/expr.rs3
-rw-r--r--crates/ide-completion/src/completions/record.rs12
-rw-r--r--crates/ide-completion/src/context.rs7
-rw-r--r--crates/ide-completion/src/context/analysis.rs16
-rw-r--r--crates/ide-completion/src/render.rs65
-rw-r--r--crates/ide-completion/src/render/function.rs7
-rw-r--r--crates/ide-completion/src/render/literal.rs2
-rw-r--r--crates/ide-completion/src/render/pattern.rs7
-rw-r--r--crates/ide-completion/src/render/variant.rs2
-rw-r--r--crates/ide-completion/src/tests/expression.rs4
-rw-r--r--crates/ide-completion/src/tests/predicate.rs4
-rw-r--r--crates/ide-completion/src/tests/type_pos.rs14
-rw-r--r--crates/ide-db/src/syntax_helpers/suggest_name.rs4
-rw-r--r--crates/ide-diagnostics/src/handlers/type_mismatch.rs4
-rw-r--r--crates/ide/src/goto_type_definition.rs2
-rw-r--r--crates/ide/src/hover.rs4
-rw-r--r--crates/ide/src/hover/render.rs16
-rw-r--r--crates/ide/src/rename.rs4
-rw-r--r--crates/ide/src/signature_help.rs2
-rw-r--r--crates/ide/src/view_memory_layout.rs2
-rw-r--r--crates/rust-analyzer/src/cli/analysis_stats.rs6
38 files changed, 950 insertions, 994 deletions
diff --git a/crates/hir-ty/src/traits.rs b/crates/hir-ty/src/traits.rs
index 9582f2ceba..f6b5adfb6f 100644
--- a/crates/hir-ty/src/traits.rs
+++ b/crates/hir-ty/src/traits.rs
@@ -121,7 +121,7 @@ pub fn implements_trait_unique<'db>(
env: ParamEnvAndCrate<'db>,
trait_: TraitId,
) -> bool {
- implements_trait_unique_impl(db, env, trait_, &mut |infcx| {
+ implements_trait_unique_with_infcx(db, env, trait_, &mut |infcx| {
infcx.fill_rest_fresh_args(Span::Dummy, trait_.into(), [ty.into()])
})
}
@@ -133,10 +133,10 @@ pub fn implements_trait_unique_with_args<'db>(
trait_: TraitId,
args: GenericArgs<'db>,
) -> bool {
- implements_trait_unique_impl(db, env, trait_, &mut |_| args)
+ implements_trait_unique_with_infcx(db, env, trait_, &mut |_| args)
}
-fn implements_trait_unique_impl<'db>(
+pub fn implements_trait_unique_with_infcx<'db>(
db: &'db dyn HirDatabase,
env: ParamEnvAndCrate<'db>,
trait_: TraitId,
diff --git a/crates/hir/src/attrs.rs b/crates/hir/src/attrs.rs
index f9cf05e73a..9a61885ccb 100644
--- a/crates/hir/src/attrs.rs
+++ b/crates/hir/src/attrs.rs
@@ -26,8 +26,8 @@ use stdx::never;
use crate::{
Adt, AsAssocItem, AssocItem, BuiltinType, Const, ConstParam, DocLinkDef, Enum, EnumVariant,
- ExternCrateDecl, Field, Function, GenericParam, HasCrate, Impl, LangItem, LifetimeParam, Macro,
- Module, ModuleDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, Variant,
+ ExternCrateDecl, Field, Function, GenericParam, Impl, LangItem, LifetimeParam, Macro, Module,
+ ModuleDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, Variant,
};
#[derive(Debug, Clone, Copy)]
@@ -487,27 +487,28 @@ fn resolve_impl_trait_item<'db>(
ns: Option<Namespace>,
) -> Option<DocLinkDef> {
let krate = ty.krate(db);
- let environment = crate::param_env_from_resolver(db, &resolver);
+ let param_env = ty.param_env(db);
let traits_in_scope = resolver.traits_in_scope(db);
// `ty.iterate_path_candidates()` require a scope, which is not available when resolving
// attributes here. Use path resolution directly instead.
//
// FIXME: resolve type aliases (which are not yielded by iterate_path_candidates)
- let interner = DbInterner::new_with(db, environment.krate);
+ let interner = DbInterner::new_with(db, param_env.krate);
let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);
let features = resolver.top_level_def_map().features();
let ctx = MethodResolutionContext {
infcx: &infcx,
resolver: &resolver,
- param_env: environment.param_env,
+ param_env: param_env.param_env,
traits_in_scope: &traits_in_scope,
- edition: krate.edition(db),
+ edition: krate.data(db).edition,
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 =
+ ctx.probe_for_name(method_resolution::Mode::Path, name.clone(), ty.ty.skip_binder());
let resolution = match resolution {
Ok(resolution) => resolution.item,
Err(MethodError::PrivateMatch(resolution)) => resolution.item,
diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs
index 2d2883eb60..f5b1463f6f 100644
--- a/crates/hir/src/diagnostics.rs
+++ b/crates/hir/src/diagnostics.rs
@@ -16,12 +16,11 @@ use hir_def::{
use hir_expand::{HirFileId, InFile, mod_path::ModPath, name::Name};
use hir_ty::{
CastError, ExplicitDropMethodUseKind, InferenceDiagnostic, InferenceTyDiagnosticSource,
- ParamEnvAndCrate, PathGenericsSource, PathLoweringDiagnostic, TyLoweringDiagnostic,
- TyLoweringDiagnosticKind,
+ PathGenericsSource, PathLoweringDiagnostic, TyLoweringDiagnostic, TyLoweringDiagnosticKind,
db::HirDatabase,
diagnostics::{BodyValidationDiagnostic, UnsafetyReason},
display::{DisplayTarget, HirDisplay},
- next_solver::DbInterner,
+ next_solver::{DbInterner, EarlyBinder},
solver_errors::SolverDiagnosticKind,
};
use stdx::{impl_from, never};
@@ -32,7 +31,7 @@ use syntax::{
};
use triomphe::Arc;
-use crate::{AssocItem, Field, Function, GenericDef, Local, Trait, Type, Variant};
+use crate::{AssocItem, Field, Function, GenericDef, Local, Trait, Type, TypeOwnerId, Variant};
pub use hir_def::VariantId;
pub use hir_ty::{
@@ -791,7 +790,7 @@ impl<'db> AnyDiagnostic<'db> {
d: &'db InferenceDiagnostic,
source_map: &hir_def::expr_store::BodySourceMap,
sig_map: &hir_def::expr_store::ExpressionStoreSourceMap,
- env: ParamEnvAndCrate<'db>,
+ type_owner: TypeOwnerId,
) -> Option<AnyDiagnostic<'db>> {
let expr_syntax = |expr| {
source_map
@@ -815,6 +814,7 @@ impl<'db> AnyDiagnostic<'db> {
ExprOrPatId::ExprId(expr) => expr_syntax(expr),
ExprOrPatId::PatId(pat) => pat_syntax(pat),
};
+ let new_ty = |ty| Type { owner: type_owner, ty: EarlyBinder::bind(ty) };
let span_syntax = |span| match span {
hir_ty::Span::ExprId(idx) => expr_syntax(idx).map(|it| it.upcast()),
hir_ty::Span::PatId(idx) => pat_syntax(idx).map(|it| it.upcast()),
@@ -848,7 +848,11 @@ impl<'db> AnyDiagnostic<'db> {
}
InferenceDiagnostic::ExpectedArrayOrSlicePat { pat, found } => {
let pat = pat_syntax(*pat)?.map(Into::into);
- ExpectedArrayOrSlicePat { pat, found: Type::new(db, def, found.as_ref()) }.into()
+ ExpectedArrayOrSlicePat {
+ pat,
+ found: Type { owner: type_owner, ty: EarlyBinder::bind(found.as_ref()) },
+ }
+ .into()
}
&InferenceDiagnostic::InvalidRangePatType { pat } => {
let pat = pat_syntax(pat)?.map(Into::into);
@@ -878,8 +882,7 @@ impl<'db> AnyDiagnostic<'db> {
}
InferenceDiagnostic::ExpectedFunction { call_expr, found } => {
let call_expr = expr_syntax(*call_expr)?;
- ExpectedFunction { call: call_expr, found: Type::new(db, def, found.as_ref()) }
- .into()
+ ExpectedFunction { call: call_expr, found: new_ty(found.as_ref()) }.into()
}
InferenceDiagnostic::UnresolvedField {
expr,
@@ -891,7 +894,7 @@ impl<'db> AnyDiagnostic<'db> {
UnresolvedField {
expr,
name: name.clone(),
- receiver: Type::new(db, def, receiver.as_ref()),
+ receiver: new_ty(receiver.as_ref()),
method_with_same_name_exists: *method_with_same_name_exists,
}
.into()
@@ -907,10 +910,10 @@ impl<'db> AnyDiagnostic<'db> {
UnresolvedMethodCall {
expr,
name: name.clone(),
- receiver: Type::new(db, def, receiver.as_ref()),
+ receiver: new_ty(receiver.as_ref()),
field_with_same_name: field_with_same_name
.as_ref()
- .map(|ty| Type::new(db, def, ty.as_ref())),
+ .map(|ty| new_ty(ty.as_ref())),
assoc_func_with_same_name: assoc_func_with_same_name.map(Into::into),
}
.into()
@@ -947,7 +950,7 @@ impl<'db> AnyDiagnostic<'db> {
}
InferenceDiagnostic::TypedHole { expr, expected } => {
let expr = expr_syntax(*expr)?;
- TypedHole { expr, expected: Type::new(db, def, expected.as_ref()) }.into()
+ TypedHole { expr, expected: new_ty(expected.as_ref()) }.into()
}
&InferenceDiagnostic::MismatchedTupleStructPatArgCount { pat, expected, found } => {
let InFile { file_id, value } = pat_syntax(pat)?;
@@ -958,21 +961,21 @@ impl<'db> AnyDiagnostic<'db> {
}
InferenceDiagnostic::CastToUnsized { expr, cast_ty } => {
let expr = expr_syntax(*expr)?;
- CastToUnsized { expr, cast_ty: Type::new(db, def, cast_ty.as_ref()) }.into()
+ CastToUnsized { expr, cast_ty: new_ty(cast_ty.as_ref()) }.into()
}
InferenceDiagnostic::InvalidCast { expr, error, expr_ty, cast_ty } => {
let expr = expr_syntax(*expr)?;
- let expr_ty = Type::new(db, def, expr_ty.as_ref());
- let cast_ty = Type::new(db, def, cast_ty.as_ref());
+ let expr_ty = new_ty(expr_ty.as_ref());
+ let cast_ty = new_ty(cast_ty.as_ref());
InvalidCast { expr, error: *error, expr_ty, cast_ty }.into()
}
InferenceDiagnostic::CannotBeDereferenced { expr, found } => {
let expr = expr_syntax(*expr)?;
- CannotBeDereferenced { expr, found: Type::new(db, def, found.as_ref()) }.into()
+ CannotBeDereferenced { expr, found: new_ty(found.as_ref()) }.into()
}
InferenceDiagnostic::CannotIndexInto { expr, found } => {
let expr = expr_syntax(*expr)?;
- CannotIndexInto { expr, found: Type::new(db, def, found.as_ref()) }.into()
+ CannotIndexInto { expr, found: new_ty(found.as_ref()) }.into()
}
InferenceDiagnostic::TyDiagnostic { source, diag } => {
let source_map = match source {
@@ -1047,10 +1050,7 @@ impl<'db> AnyDiagnostic<'db> {
&InferenceDiagnostic::TypeMustBeKnown { at_point, ref top_term } => {
let at_point = span_syntax(at_point)?;
let top_term = top_term.as_ref().map(|top_term| match top_term.as_ref().kind() {
- rustc_type_ir::GenericArgKind::Type(ty) => Either::Left(Type {
- ty,
- env: crate::body_param_env_from_has_crate(db, def),
- }),
+ rustc_type_ir::GenericArgKind::Type(ty) => Either::Left(new_ty(ty)),
// FIXME: Printing the const to string is definitely not the correct thing to do here.
rustc_type_ir::GenericArgKind::Const(konst) => Either::Right(
konst.display(db, DisplayTarget::from_crate(db, def.krate(db))).to_string(),
@@ -1069,14 +1069,14 @@ impl<'db> AnyDiagnostic<'db> {
let expr_or_pat = expr_or_pat_syntax(*node)?;
TypeMismatch {
expr_or_pat,
- expected: Type { env, ty: expected.as_ref() },
- actual: Type { env, ty: found.as_ref() },
+ expected: Type { owner: type_owner, ty: EarlyBinder::bind(expected.as_ref()) },
+ actual: Type { owner: type_owner, ty: EarlyBinder::bind(found.as_ref()) },
}
.into()
}
InferenceDiagnostic::SolverDiagnostic(d) => {
let span = span_syntax(d.span)?;
- Self::solver_diagnostic(db, &d.kind, span, env)?
+ Self::solver_diagnostic(db, &d.kind, span, type_owner)?
}
InferenceDiagnostic::ExplicitDropMethodUse { kind } => {
let expr_or_path = match kind {
@@ -1108,16 +1108,21 @@ impl<'db> AnyDiagnostic<'db> {
db: &'db dyn HirDatabase,
d: &'db SolverDiagnosticKind,
span: SpanSyntax,
- env: ParamEnvAndCrate<'db>,
+ type_owner: TypeOwnerId,
) -> Option<AnyDiagnostic<'db>> {
let interner = DbInterner::new_no_crate(db);
Some(match d {
SolverDiagnosticKind::TraitUnimplemented { trait_predicate, root_trait_predicate } => {
- let trait_predicate =
- crate::TraitPredicate { inner: trait_predicate.get(interner), env };
+ let trait_predicate = crate::TraitPredicate {
+ inner: trait_predicate.get(interner),
+ owner: type_owner,
+ };
let root_trait_predicate =
root_trait_predicate.as_ref().map(|root_trait_predicate| {
- crate::TraitPredicate { inner: root_trait_predicate.get(interner), env }
+ crate::TraitPredicate {
+ inner: root_trait_predicate.get(interner),
+ owner: type_owner,
+ }
});
UnimplementedTrait { span, trait_predicate, root_trait_predicate }.into()
}
diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs
index c3af5fa7ce..ed18482bf3 100644
--- a/crates/hir/src/display.rs
+++ b/crates/hir/src/display.rs
@@ -33,7 +33,7 @@ use crate::{
Adt, AnyFunctionId, AsAssocItem, AssocItem, AssocItemContainer, Const, ConstParam, Crate, Enum,
EnumVariant, ExternCrateDecl, Field, Function, GenericParam, HasCrate, HasVisibility, Impl,
LifetimeParam, Macro, Module, SelfParam, Static, Struct, StructKind, Trait, TraitPredicate,
- TraitRef, TupleField, Type, TypeAlias, TypeNs, TypeOrConstParam, TypeParam, Union,
+ TraitRef, TupleField, Type, TypeAlias, TypeOrConstParam, TypeParam, Union,
};
fn write_builtin_derive_impl_method<'db>(
@@ -552,13 +552,7 @@ impl<'db> HirDisplay<'db> for EnumVariant {
impl<'db> HirDisplay<'db> for Type<'db> {
fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
- self.ty.hir_fmt(f)
- }
-}
-
-impl<'db> HirDisplay<'db> for TypeNs<'db> {
- fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
- self.ty.hir_fmt(f)
+ self.ty.skip_binder().hir_fmt(f)
}
}
@@ -598,7 +592,7 @@ impl<'db> HirDisplay<'db> for TypeParam {
let params = GenericParams::of(f.db, self.id.parent());
let param_data = &params[self.id.local_id()];
let krate = self.id.parent().krate(f.db).id;
- let ty = self.ty(f.db).ty;
+ let ty = self.ty(f.db).ty.skip_binder();
let predicates = GenericPredicates::query_all(f.db, self.id.parent());
let predicates = predicates
.iter_identity()
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 02800fda98..d187763151 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -39,7 +39,8 @@ mod display;
pub use hir_def::ModuleId;
use std::{
- fmt,
+ borrow::Borrow,
+ fmt, iter,
mem::discriminant,
ops::{ControlFlow, Not},
};
@@ -93,19 +94,17 @@ use hir_ty::{
method_resolution::{self, InherentImpls, MethodResolutionContext},
mir::interpret_mir,
next_solver::{
- AliasTy, AnyImplId, ClauseKind, ConstKind, DbInterner, EarlyBinder, EarlyParamRegion,
- ErrorGuaranteed, GenericArg, GenericArgs, ParamConst, ParamEnv, PolyFnSig, Region,
- RegionKind, SolverDefId, Ty, TyKind, TypingMode,
+ AliasTy, AnyImplId, ClauseKind, DbInterner, EarlyBinder, ErrorGuaranteed, GenericArg,
+ GenericArgs, ParamEnv, PolyFnSig, Region, SolverDefId, Ty, TyKind, TypingMode,
infer::{DbInternerInferExt, InferCtxt},
},
traits::{self, is_inherent_impl_coherent, structurally_normalize_ty},
};
use itertools::Itertools;
-use rustc_hash::FxHashSet;
+use rustc_hash::{FxHashMap, FxHashSet};
use rustc_type_ir::{
- AliasTyKind, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable,
- TypeVisitor, fast_reject,
- inherent::{GenericArgs as _, IntoKind, SliceLike, Term as _, Ty as _},
+ AliasTyKind, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, fast_reject,
+ inherent::{AdtDef as _, GenericArgs as _, IntoKind, SliceLike, Term as _, Ty as _},
};
use span::{AstIdNode, Edition, FileId};
use stdx::{format_to, impl_from, never};
@@ -183,6 +182,7 @@ pub use {
mir::{MirEvalError, MirLowerError},
next_solver::abi::Safety,
next_solver::{clear_tls_solver_cache, collect_ty_garbage},
+ setup_tracing,
},
// FIXME: These are needed for import assets, properly encapsulate them.
hir_ty::{method_resolution::TraitImpls, next_solver::SimplifiedType},
@@ -198,6 +198,7 @@ use {
name::AsName,
span_map::{ExpansionSpanMap, RealSpanMap, SpanMap},
},
+ hir_ty::next_solver,
};
/// hir::Crate describes a single crate. It's the main interface with which
@@ -945,7 +946,7 @@ impl Module {
if !missing.is_empty() {
let env = ParamEnvAndCrate {
- param_env: db.trait_environment(GenericDefId::from(impl_id).into()),
+ param_env: db.trait_environment(GenericDefId::from(impl_id)),
krate: self.id.krate(db),
};
let self_ty = db.impl_self_ty(impl_id).instantiate_identity().skip_norm_wip();
@@ -1333,24 +1334,6 @@ pub struct Field {
pub(crate) id: LocalFieldId,
}
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct InstantiatedField<'db> {
- pub(crate) inner: Field,
- pub(crate) args: GenericArgs<'db>,
-}
-
-impl<'db> InstantiatedField<'db> {
- /// Returns the type as in the signature of the struct.
- pub fn ty(&self, db: &'db dyn HirDatabase) -> TypeNs<'db> {
- let interner = DbInterner::new_no_crate(db);
-
- let var_id = self.inner.parent.into();
- let field = db.field_types(var_id)[self.inner.id].get();
- let ty = field.instantiate(interner, self.args).skip_norm_wip();
- TypeNs::new(db, var_id, ty)
- }
-}
-
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
pub struct TupleField {
pub owner: InferBodyId,
@@ -1371,7 +1354,7 @@ impl TupleField {
.get(self.index as usize)
.copied()
.unwrap_or_else(|| Ty::new_error(interner, ErrorGuaranteed));
- Type { env: body_param_env_from_has_crate(db, self.owner.expression_store_owner(db)), ty }
+ Type::new_body(db, self.owner.expression_store_owner(db), ty)
}
}
@@ -1421,46 +1404,14 @@ impl Field {
/// Returns the type as in the signature of the struct. Only use this in the
/// context of the field definition.
- pub fn ty<'db>(&self, db: &'db dyn HirDatabase) -> TypeNs<'db> {
- let var_id = self.parent.into();
- let ty = db.field_types(var_id)[self.id].get().skip_binder();
- TypeNs::new(db, var_id, ty)
- }
-
- // FIXME: Find better API to also handle const generics
- pub fn ty_with_args<'db>(
- &self,
- db: &'db dyn HirDatabase,
- generics: impl Iterator<Item = Type<'db>>,
- ) -> Type<'db> {
+ pub fn ty<'db>(&self, db: &'db dyn HirDatabase) -> Type<'db> {
let var_id = self.parent.into();
- let def_id: AdtId = match self.parent {
- Variant::Struct(it) => it.id.into(),
- Variant::Union(it) => it.id.into(),
- Variant::EnumVariant(it) => it.parent_enum(db).id.into(),
- };
- let interner = DbInterner::new_no_crate(db);
- let args = generic_args_from_tys(interner, def_id.into(), generics.map(|ty| ty.ty));
- let ty = db.field_types(var_id)[self.id].get().instantiate(interner, args).skip_norm_wip();
- Type::new(db, var_id, ty)
+ let ty = db.field_types(var_id)[self.id].get().instantiate_identity().skip_norm_wip();
+ Type::new(var_id.adt_id(db).into(), ty)
}
pub fn layout<'db>(&self, db: &'db dyn HirDatabase) -> Result<Layout<'db>, LayoutError> {
- db.layout_of_ty(
- self.ty(db).ty.store(),
- param_env_from_has_crate(
- db,
- match hir_def::VariantId::from(self.parent) {
- hir_def::VariantId::EnumVariantId(id) => {
- GenericDefId::AdtId(id.lookup(db).parent.into())
- }
- hir_def::VariantId::StructId(id) => GenericDefId::AdtId(id.into()),
- hir_def::VariantId::UnionId(id) => GenericDefId::AdtId(id.into()),
- },
- )
- .store(),
- )
- .map(|layout| Layout(layout, db.target_data_layout(self.krate(db).into()).unwrap()))
+ self.ty(db).layout(db)
}
pub fn parent_def(&self, _db: &dyn HirDatabase) -> Variant {
@@ -1505,10 +1456,6 @@ impl Struct {
Type::from_def(db, self.id)
}
- pub fn ty_params(self, db: &dyn HirDatabase) -> Type<'_> {
- Type::from_def_params(db, self.id)
- }
-
pub fn constructor_ty(self, db: &dyn HirDatabase) -> Type<'_> {
Type::from_value_def(db, self.id)
}
@@ -1532,11 +1479,6 @@ impl Struct {
pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
AttrFlags::query(db, self.id.into()).contains(AttrFlags::IS_UNSTABLE)
}
-
- pub fn instantiate_infer<'db>(self, infer_ctxt: &InferCtxt<'db>) -> InstantiatedStruct<'db> {
- let args = infer_ctxt.fresh_args_for_item(hir_ty::Span::Dummy, self.id.into());
- InstantiatedStruct { inner: self, args }
- }
}
impl HasVisibility for Struct {
@@ -1548,34 +1490,6 @@ impl HasVisibility for Struct {
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct InstantiatedStruct<'db> {
- pub(crate) inner: Struct,
- pub(crate) args: GenericArgs<'db>,
-}
-
-impl<'db> InstantiatedStruct<'db> {
- pub fn fields(self, db: &dyn HirDatabase) -> Vec<InstantiatedField<'db>> {
- self.inner
- .id
- .fields(db)
- .fields()
- .iter()
- .map(|(id, _)| InstantiatedField {
- inner: Field { parent: self.inner.into(), id },
- args: self.args,
- })
- .collect()
- }
-
- pub fn ty(self, db: &'db dyn HirDatabase) -> TypeNs<'db> {
- let interner = DbInterner::new_no_crate(db);
-
- let ty = db.ty(self.inner.id.into());
- TypeNs::new(db, self.inner.id, ty.instantiate(interner, self.args).skip_norm_wip())
- }
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Union {
pub(crate) id: UnionId,
}
@@ -1593,10 +1507,6 @@ impl Union {
Type::from_def(db, self.id)
}
- pub fn ty_params(self, db: &dyn HirDatabase) -> Type<'_> {
- Type::from_def_params(db, self.id)
- }
-
pub fn constructor_ty(self, db: &dyn HirDatabase) -> Type<'_> {
Type::from_value_def(db, self.id)
}
@@ -1660,17 +1570,11 @@ impl Enum {
Type::from_def(db, self.id)
}
- pub fn ty_params<'db>(self, db: &'db dyn HirDatabase) -> Type<'db> {
- Type::from_def_params(db, self.id)
- }
-
/// The type of the enum variant bodies.
pub fn variant_body_ty<'db>(self, db: &'db dyn HirDatabase) -> Type<'db> {
- let krate = self.id.lookup(db).container.krate(db);
- let interner = DbInterner::new_with(db, krate);
- Type::new_for_crate(
- db,
- krate,
+ let interner = DbInterner::new_no_crate(db);
+ Type::no_params(
+ Type::builtin_type_crate(db),
match EnumSignature::variant_body_type(db, self.id) {
layout::IntegerType::Pointer(sign) => match sign {
true => Ty::new_int(interner, rustc_type_ir::IntTy::Isize),
@@ -1725,27 +1629,6 @@ impl HasVisibility for Enum {
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct InstantiatedEnum<'db> {
- pub(crate) inner: Enum,
- pub(crate) args: GenericArgs<'db>,
-}
-
-impl<'db> InstantiatedEnum<'db> {
- pub fn ty(self, db: &'db dyn HirDatabase) -> TypeNs<'db> {
- let interner = DbInterner::new_no_crate(db);
-
- let ty = db.ty(self.inner.id.into());
- TypeNs::new(db, self.inner.id, ty.instantiate(interner, self.args).skip_norm_wip())
- }
-}
-
-impl From<&EnumVariant> for DefWithBodyId {
- fn from(&v: &EnumVariant) -> Self {
- DefWithBodyId::VariantId(v.into())
- }
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct EnumVariant {
pub(crate) id: EnumVariantId,
}
@@ -1811,40 +1694,6 @@ impl EnumVariant {
pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
AttrFlags::query(db, self.id.into()).contains(AttrFlags::IS_UNSTABLE)
}
-
- pub fn instantiate_infer<'db>(self, infer_ctxt: &InferCtxt<'db>) -> InstantiatedVariant<'db> {
- 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 }
- }
-}
-
-// FIXME: Rename to `EnumVariant`
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct InstantiatedVariant<'db> {
- pub(crate) inner: EnumVariant,
- pub(crate) args: GenericArgs<'db>,
-}
-
-impl<'db> InstantiatedVariant<'db> {
- pub fn parent_enum(self, db: &dyn HirDatabase) -> InstantiatedEnum<'db> {
- InstantiatedEnum { inner: self.inner.id.lookup(db).parent.into(), args: self.args }
- }
-
- pub fn fields(self, db: &dyn HirDatabase) -> Vec<InstantiatedField<'db>> {
- self.inner
- .id
- .fields(db)
- .fields()
- .iter()
- .map(|(id, _)| InstantiatedField {
- inner: Field { parent: self.inner.into(), id },
- args: self.args,
- })
- .collect()
- }
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -1893,23 +1742,6 @@ impl Adt {
Type::from_def(db, id)
}
- /// Turns this ADT into a type with the given type parameters. This isn't
- /// the greatest API, FIXME find a better one.
- pub fn ty_with_args<'db>(
- self,
- db: &'db dyn HirDatabase,
- args: impl IntoIterator<Item = Type<'db>>,
- ) -> Type<'db> {
- let id = AdtId::from(self);
- let interner = DbInterner::new_no_crate(db);
- let ty = Ty::new_adt(
- interner,
- id,
- generic_args_from_tys(interner, id.into(), args.into_iter().map(|ty| ty.ty)),
- );
- Type::new(db, id, ty)
- }
-
pub fn module(self, db: &dyn HirDatabase) -> Module {
match self {
Adt::Struct(s) => s.module(db),
@@ -2017,8 +1849,7 @@ impl AnonConst {
pub fn ty<'db>(self, db: &'db dyn HirDatabase) -> Type<'db> {
let loc = self.id.loc(db);
- let env = body_param_env_from_has_crate(db, loc.owner);
- Type { env, ty: loc.ty.get().instantiate_identity().skip_norm_wip() }
+ Type { owner: self.id.into(), ty: loc.ty.get() }
}
pub fn eval(self, db: &dyn HirDatabase) -> Result<EvaluatedConst<'_>, ConstEvalError> {
@@ -2128,7 +1959,7 @@ impl DefWithBody {
},
DefWithBody::Static(it) => it.id.into(),
DefWithBody::Const(it) => it.id.into(),
- DefWithBody::EnumVariant(it) => it.into(),
+ DefWithBody::EnumVariant(it) => it.id.into(),
})
}
@@ -2168,8 +1999,6 @@ impl DefWithBody {
let Ok(id) = self.try_into() else {
return;
};
- let krate = self.module(db).id.krate(db);
- let env = body_param_env_from_has_crate(db, id);
let (body, source_map) = Body::with_source_map(db, id);
let sig_source_map = match self {
@@ -2192,6 +2021,7 @@ impl DefWithBody {
expr_store_diagnostics(db, acc, source_map);
let infer = InferenceResult::of(db, id);
+ let type_owner = id.generic_def(db).into();
for d in infer.diagnostics() {
acc.extend(AnyDiagnostic::inference_diagnostic(
db,
@@ -2199,7 +2029,7 @@ impl DefWithBody {
d,
source_map,
sig_source_map,
- env,
+ type_owner,
));
}
@@ -2269,7 +2099,7 @@ impl DefWithBody {
};
acc.push(
MovedOutOfRef {
- ty: Type::new_for_crate(db, krate, moof.ty.as_ref()),
+ ty: Type { owner: type_owner, ty: EarlyBinder::bind(moof.ty.as_ref()) },
span,
}
.into(),
@@ -2369,9 +2199,9 @@ impl DefWithBody {
) -> impl Iterator<Item = Type<'db>> {
self.id().into_iter().flat_map(move |def_id| {
let infer = InferenceResult::of(db, def_id);
- let resolver = def_id.resolver(db);
+ let def_id = def_id.generic_def(db);
- infer.expression_types().map(move |(_, ty)| Type::new_with_resolver(db, &resolver, ty))
+ infer.expression_types().map(move |(_, ty)| Type::new(def_id, ty))
})
}
@@ -2379,9 +2209,9 @@ impl DefWithBody {
pub fn pattern_types<'db>(self, db: &'db dyn HirDatabase) -> impl Iterator<Item = Type<'db>> {
self.id().into_iter().flat_map(move |def_id| {
let infer = InferenceResult::of(db, def_id);
- let resolver = def_id.resolver(db);
+ let def_id = def_id.generic_def(db);
- infer.pattern_types().map(move |(_, ty)| Type::new_with_resolver(db, &resolver, ty))
+ infer.pattern_types().map(move |(_, ty)| Type::new(def_id, ty))
})
}
@@ -2389,9 +2219,9 @@ impl DefWithBody {
pub fn binding_types<'db>(self, db: &'db dyn HirDatabase) -> impl Iterator<Item = Type<'db>> {
self.id().into_iter().flat_map(move |def_id| {
let infer = InferenceResult::of(db, def_id);
- let resolver = def_id.resolver(db);
+ let def_id = def_id.generic_def(db);
- infer.binding_types().map(move |(_, ty)| Type::new_with_resolver(db, &resolver, ty))
+ infer.binding_types().map(move |(_, ty)| Type::new(def_id, ty))
})
}
}
@@ -2475,12 +2305,9 @@ impl Function {
AnyFunctionId::BuiltinDeriveImplMethod { method, impl_ } => {
// Get the type for the trait function, as we can't get the type for the impl function
// because it has not `CallableDefId`.
- let krate = impl_.module(db).krate(db);
- let interner = DbInterner::new_with(db, krate);
- let param_env = hir_ty::builtin_derive::param_env(interner, impl_);
- let env = ParamEnvAndCrate { param_env, krate };
+ // FIXME: This does not account for replacing `Self`. Do we really need that?
let Some(trait_method) = method.trait_method(db, impl_) else {
- return Type { env, ty: Ty::new_error(interner, ErrorGuaranteed) };
+ return Type::unknown();
};
Function::from(trait_method).ty(db)
}
@@ -2490,160 +2317,36 @@ impl Function {
pub fn fn_ptr_type(self, db: &dyn HirDatabase) -> Type<'_> {
match self.id {
AnyFunctionId::FunctionId(id) => {
- let resolver = id.resolver(db);
let interner = DbInterner::new_no_crate(db);
- // FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s.
let callable_sig =
db.callable_item_signature(id.into()).instantiate_identity().skip_norm_wip();
let ty = Ty::new_fn_ptr(interner, callable_sig);
- Type::new_with_resolver_inner(db, &resolver, ty)
+ Type::new(id.into(), ty)
}
AnyFunctionId::BuiltinDeriveImplMethod { method, impl_ } => {
- struct ParamsShifter<'db> {
- interner: DbInterner<'db>,
- shift_by: i32,
- }
-
- impl<'db> TypeFolder<DbInterner<'db>> for ParamsShifter<'db> {
- fn cx(&self) -> DbInterner<'db> {
- self.interner
- }
-
- fn fold_ty(&mut self, ty: Ty<'db>) -> Ty<'db> {
- if let TyKind::Param(param) = ty.kind() {
- Ty::new_param(
- self.interner,
- param.id,
- param.index.checked_add_signed(self.shift_by).unwrap(),
- )
- } else {
- ty.super_fold_with(self)
- }
- }
-
- fn fold_const(
- &mut self,
- ct: hir_ty::next_solver::Const<'db>,
- ) -> hir_ty::next_solver::Const<'db> {
- if let ConstKind::Param(param) = ct.kind() {
- hir_ty::next_solver::Const::new_param(
- self.interner,
- ParamConst {
- id: param.id,
- index: param.index.checked_add_signed(self.shift_by).unwrap(),
- },
- )
- } else {
- ct.super_fold_with(self)
- }
- }
-
- fn fold_region(&mut self, r: Region<'db>) -> Region<'db> {
- if let RegionKind::ReEarlyParam(param) = r.kind() {
- Region::new_early_param(
- self.interner,
- EarlyParamRegion {
- id: param.id,
- index: param.index.checked_add_signed(self.shift_by).unwrap(),
- },
- )
- } else {
- r
- }
- }
- }
-
// Get the type for the trait function, as we can't get the type for the impl function
// because it has not `CallableDefId`.
- let krate = impl_.module(db).krate(db);
- let interner = DbInterner::new_with(db, krate);
- let param_env = hir_ty::builtin_derive::param_env(interner, impl_);
- let env = ParamEnvAndCrate { param_env, krate };
+ // FIXME: This does not account for replacing `Self`. Do we really need that?
let Some(trait_method) = method.trait_method(db, impl_) else {
- return Type { env, ty: Ty::new_error(interner, ErrorGuaranteed) };
+ return Type::unknown();
};
- // The procedure works as follows: the method may have additional generic parameters (e.g. `Hash::hash()`),
- // and we want them to be params of the impl method as well. So we start with the trait method identity
- // args and extract from them the trait method own args. In parallel, we retrieve the impl trait ref.
- // Now we can put our args as [...impl_trait_ref.args, ...trait_method_own_args], but we have one problem:
- // the args in `trait_method_own_args` use indices appropriate for the trait method, which are not necessarily
- // good for the impl method. So we shift them by `impl_generics_len - trait_generics_len`, which is essentially
- // `impl_generics_len - impl_trait_ref.args.len()`.
- let trait_method_fn_ptr = Ty::new_fn_ptr(
- interner,
- db.callable_item_signature(trait_method.into())
- .instantiate_identity()
- .skip_norm_wip(),
- );
- let impl_trait_ref = hir_ty::builtin_derive::impl_trait(interner, impl_)
- .instantiate_identity()
- .skip_norm_wip();
- let trait_method_args =
- GenericArgs::identity_for_item(interner, trait_method.into());
- let trait_method_own_args = GenericArgs::new_from_iter(
- interner,
- trait_method_args.iter().skip(impl_trait_ref.args.len()),
- );
- let impl_params_count = hir_ty::builtin_derive::generic_params_count(db, impl_);
- let shift_args_by = impl_params_count as i32 - impl_trait_ref.args.len() as i32;
- let shifted_trait_method_own_args = trait_method_own_args
- .fold_with(&mut ParamsShifter { interner, shift_by: shift_args_by });
- let impl_method_args = GenericArgs::new_from_iter(
- interner,
- impl_trait_ref.args.iter().chain(shifted_trait_method_own_args),
- );
- let impl_method_fn_ptr = EarlyBinder::bind(trait_method_fn_ptr)
- .instantiate(interner, impl_method_args)
- .skip_norm_wip();
- Type { env, ty: impl_method_fn_ptr }
+ Function::from(trait_method).fn_ptr_type(db)
}
}
}
- fn fn_sig<'db>(self, db: &'db dyn HirDatabase) -> (ParamEnvAndCrate<'db>, PolyFnSig<'db>) {
+ fn fn_sig<'db>(self, db: &'db dyn HirDatabase) -> (TypeOwnerId, PolyFnSig<'db>) {
let fn_ptr = self.fn_ptr_type(db);
- let TyKind::FnPtr(sig_tys, hdr) = fn_ptr.ty.kind() else {
+ let TyKind::FnPtr(sig_tys, hdr) = fn_ptr.ty.skip_binder().kind() else {
unreachable!();
};
- (fn_ptr.env, sig_tys.with(hdr))
+ (fn_ptr.owner, sig_tys.with(hdr))
}
- // FIXME: Find a better API to express all combinations here, perhaps we should have `PreInstantiationType`?
-
/// Get this function's return type
pub fn ret_type(self, db: &dyn HirDatabase) -> Type<'_> {
- let (env, sig) = self.fn_sig(db);
- Type { env, ty: sig.skip_binder().output() }
- }
-
- // FIXME: Find better API to also handle const generics
- pub fn ret_type_with_args<'db>(
- self,
- db: &'db dyn HirDatabase,
- generics: impl Iterator<Item = Type<'db>>,
- ) -> Type<'db> {
- let ret_type = self.ret_type(db);
- let interner = DbInterner::new_no_crate(db);
- let args = self.adapt_generic_args(interner, generics);
- ret_type.derived(EarlyBinder::bind(ret_type.ty).instantiate(interner, args).skip_norm_wip())
- }
-
- fn adapt_generic_args<'db>(
- self,
- interner: DbInterner<'db>,
- generics: impl Iterator<Item = Type<'db>>,
- ) -> GenericArgs<'db> {
- let generics = generics.map(|ty| ty.ty);
- match self.id {
- AnyFunctionId::FunctionId(id) => generic_args_from_tys(interner, id.into(), generics),
- AnyFunctionId::BuiltinDeriveImplMethod { impl_, .. } => {
- let impl_args = GenericArgs::identity_for_item(interner, impl_.into());
- GenericArgs::new_from_iter(
- interner,
- impl_args.iter().chain(generics.map(Into::into)),
- )
- }
- }
+ let (owner, sig) = self.fn_sig(db);
+ Type { owner, ty: EarlyBinder::bind(sig.skip_binder().output()) }
}
pub fn async_ret_type<'db>(self, db: &'db dyn HirDatabase) -> Option<Type<'db>> {
@@ -2653,15 +2356,13 @@ impl Function {
if !self.is_async(db) {
return None;
}
- let resolver = id.resolver(db);
- // FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s.
let ret_ty =
db.callable_item_signature(id.into()).instantiate_identity().skip_binder().output();
for pred in ret_ty.impl_trait_bounds(db).into_iter().flatten() {
if let ClauseKind::Projection(projection) = pred.kind().skip_binder()
&& let Some(output_ty) = projection.term.as_type()
{
- return Type::new_with_resolver_inner(db, &resolver, output_ty).into();
+ return Some(Type::new(id.into(), output_ty));
}
}
None
@@ -2687,7 +2388,7 @@ impl Function {
}
pub fn assoc_fn_params(self, db: &dyn HirDatabase) -> Vec<Param<'_>> {
- let (env, sig) = self.fn_sig(db);
+ let (owner, sig) = self.fn_sig(db);
let func = match self.id {
AnyFunctionId::FunctionId(id) => Callee::Def(CallableDefId::FunctionId(id)),
AnyFunctionId::BuiltinDeriveImplMethod { method, impl_ } => {
@@ -2698,7 +2399,11 @@ impl Function {
.inputs()
.iter()
.enumerate()
- .map(|(idx, &ty)| Param { func: func.clone(), ty: Type { env, ty }, idx })
+ .map(|(idx, &ty)| Param {
+ func: func.clone(),
+ ty: Type { owner, ty: EarlyBinder::bind(ty) },
+ idx,
+ })
.collect()
}
@@ -2724,28 +2429,6 @@ impl Function {
params
}
- // FIXME: Find better API to also handle const generics
- pub fn params_without_self_with_args<'db>(
- self,
- db: &'db dyn HirDatabase,
- generics: impl Iterator<Item = Type<'db>>,
- ) -> Vec<Param<'db>> {
- let interner = DbInterner::new_no_crate(db);
- let args = self.adapt_generic_args(interner, generics);
- let params = self.params_without_self(db);
- params
- .into_iter()
- .map(|param| Param {
- func: param.func,
- idx: param.idx,
- ty: Type {
- env: param.ty.env,
- ty: EarlyBinder::bind(param.ty.ty).instantiate(interner, args).skip_norm_wip(),
- },
- })
- .collect()
- }
-
pub fn is_const(self, db: &dyn HirDatabase) -> bool {
match self.id {
AnyFunctionId::FunctionId(id) => FunctionSignature::of(db, id).is_const(),
@@ -3099,20 +2782,8 @@ impl SelfParam {
}
pub fn ty<'db>(&self, db: &'db dyn HirDatabase) -> Type<'db> {
- let (env, sig) = self.func.fn_sig(db);
- Type { env, ty: sig.skip_binder().inputs()[0] }
- }
-
- // FIXME: Find better API to also handle const generics
- pub fn ty_with_args<'db>(
- &self,
- db: &'db dyn HirDatabase,
- generics: impl Iterator<Item = Type<'db>>,
- ) -> Type<'db> {
- let interner = DbInterner::new_no_crate(db);
- let args = self.func.adapt_generic_args(interner, generics);
- let Type { env, ty } = self.ty(db);
- Type { env, ty: EarlyBinder::bind(ty).instantiate(interner, args).skip_norm_wip() }
+ let (owner, sig) = self.func.fn_sig(db);
+ Type { owner, ty: EarlyBinder::bind(sig.skip_binder().inputs()[0]) }
}
}
@@ -3444,10 +3115,6 @@ impl TypeAlias {
Type::from_def(db, self.id)
}
- pub fn ty_params(self, db: &dyn HirDatabase) -> Type<'_> {
- Type::from_def_params(db, self.id)
- }
-
pub fn name(self, db: &dyn HirDatabase) -> Name {
TypeAliasSignature::of(db, self.id).name.clone()
}
@@ -3496,10 +3163,13 @@ impl BuiltinType {
}
}
+ pub fn bool() -> BuiltinType {
+ BuiltinType { inner: hir_def::builtin_type::BuiltinType::Bool }
+ }
+
pub fn ty<'db>(self, db: &'db dyn HirDatabase) -> Type<'db> {
- let core = Crate::core(db).map(|core| core.id).unwrap_or_else(|| all_crates(db)[0]);
let interner = DbInterner::new_no_crate(db);
- Type::new_for_crate(db, core, Ty::from_builtin_type(interner, self.inner))
+ Type::no_params(Type::builtin_type_crate(db), Ty::from_builtin_type(interner, self.inner))
}
pub fn name(self) -> Name {
@@ -4294,23 +3964,19 @@ impl GenericDef {
// We cannot call this `Substitution` unfortunately...
#[derive(Debug)]
pub struct GenericSubstitution<'db> {
+ owner: TypeOwnerId,
def: GenericDefId,
subst: GenericArgs<'db>,
- env: ParamEnvAndCrate<'db>,
}
impl<'db> GenericSubstitution<'db> {
- fn new(def: GenericDefId, subst: GenericArgs<'db>, env: ParamEnvAndCrate<'db>) -> Self {
- Self { def, subst, env }
+ fn new(def: GenericDefId, subst: GenericArgs<'db>, owner: TypeOwnerId) -> Self {
+ Self { owner, def, subst }
}
- fn new_from_fn(
- def: Function,
- subst: GenericArgs<'db>,
- env: ParamEnvAndCrate<'db>,
- ) -> Option<Self> {
+ fn new_from_fn(def: Function, subst: GenericArgs<'db>, owner: TypeOwnerId) -> Option<Self> {
match def.id {
- AnyFunctionId::FunctionId(def) => Some(Self::new(def.into(), subst, env)),
+ AnyFunctionId::FunctionId(def) => Some(Self::new(def.into(), subst, owner)),
AnyFunctionId::BuiltinDeriveImplMethod { .. } => None,
}
}
@@ -4357,7 +4023,12 @@ impl<'db> GenericSubstitution<'db> {
.zip(type_params);
container_params
.chain(self_params)
- .filter_map(|(ty, name)| Some((name?.symbol().clone(), Type { ty, env: self.env })))
+ .filter_map(|(ty, name)| {
+ Some((
+ name?.symbol().clone(),
+ Type { ty: EarlyBinder::bind(ty), owner: self.owner },
+ ))
+ })
.collect()
}
}
@@ -4470,7 +4141,7 @@ impl Local {
let def = self.parent;
let infer = InferenceResult::of(db, self.parent_infer);
let ty = infer.binding_ty(self.binding_id);
- Type::new(db, def, ty)
+ Type::new_body(db, def, ty)
}
/// All definitions for this local. Example: `let (a$0, _) | (_, a$0) = it;`
@@ -4770,18 +4441,17 @@ impl TypeParam {
}
pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
- let resolver = self.id.parent().resolver(db);
let interner = DbInterner::new_no_crate(db);
let index = hir_ty::type_or_const_param_idx(db, self.id.into());
let ty = Ty::new_param(interner, self.id, index);
- Type::new_with_resolver_inner(db, &resolver, ty)
+ Type::new(self.id.parent(), ty)
}
/// FIXME: this only lists trait bounds from the item defining the type
/// parameter, not additional bounds that might be added e.g. by a method if
/// the parameter comes from an impl!
pub fn trait_bounds(self, db: &dyn HirDatabase) -> Vec<Trait> {
- let self_ty = self.ty(db).ty;
+ let self_ty = self.ty(db).ty.instantiate_identity().skip_norm_wip();
GenericPredicates::query_explicit(db, self.id.parent())
.iter_identity()
.filter_map(|pred| match &pred.kind().skip_binder() {
@@ -4795,10 +4465,9 @@ impl TypeParam {
pub fn default(self, db: &dyn HirDatabase) -> Option<Type<'_>> {
let ty = generic_arg_from_param(db, self.id.into())?;
- let resolver = self.id.parent().resolver(db);
match ty.kind() {
rustc_type_ir::GenericArgKind::Type(it) if !it.is_ty_error() => {
- Some(Type::new_with_resolver_inner(db, &resolver, it))
+ Some(Type::new(self.id.parent(), it))
}
_ => None,
}
@@ -4859,7 +4528,7 @@ impl ConstParam {
}
pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
- Type::new(db, self.id.parent(), db.const_param_ty(self.id))
+ Type::new(self.id.parent(), db.const_param_ty(self.id))
}
pub fn default(self, db: &dyn HirDatabase, display_target: DisplayTarget) -> Option<String> {
@@ -4981,21 +4650,26 @@ impl Impl {
/// blanket impls, and only does a shallow type constructor check. In fact, this should've probably been on `Adt`
/// etc., and not on `Type`. If you would want to create a precise list of all impls applying to a type,
/// you would need to include blanket impls, and try to prove to predicates for each candidate.
- pub fn all_for_type<'db>(db: &'db dyn HirDatabase, Type { ty, env }: Type<'db>) -> Vec<Impl> {
+ pub fn all_for_type<'db>(db: &'db dyn HirDatabase, ty: Type<'db>) -> Vec<Impl> {
let mut result = Vec::new();
let interner = DbInterner::new_no_crate(db);
- let Some(simplified_ty) =
- fast_reject::simplify_type(interner, ty, fast_reject::TreatParams::AsRigid)
- else {
+ let Some(simplified_ty) = fast_reject::simplify_type(
+ interner,
+ ty.ty.skip_binder(),
+ fast_reject::TreatParams::AsRigid,
+ ) else {
return Vec::new();
};
let mut extend_with_impls = |impls: Either<&[ImplId], &[BuiltinDeriveImplId]>| match impls {
Either::Left(impls) => result.extend(impls.iter().copied().map(Impl::from)),
Either::Right(impls) => result.extend(impls.iter().copied().map(Impl::from)),
};
- method_resolution::with_incoherent_inherent_impls(db, env.krate, &simplified_ty, |impls| {
- extend_with_impls(Either::Left(impls))
- });
+ method_resolution::with_incoherent_inherent_impls(
+ db,
+ ty.krate(db),
+ &simplified_ty,
+ |impls| extend_with_impls(Either::Left(impls)),
+ );
if let Some(module) = method_resolution::simplified_type_module(db, &simplified_ty) {
InherentImpls::for_each_crate_and_block(
db,
@@ -5003,7 +4677,7 @@ impl Impl {
module.block(db),
&mut |impls| extend_with_impls(Either::Left(impls.for_self_ty(&simplified_ty))),
);
- std::iter::successors(module.block(db), |block| block.loc(db).module.block(db))
+ iter::successors(module.block(db), |block| block.loc(db).module.block(db))
.filter_map(|block| TraitImpls::for_block(db, block).as_deref())
.for_each(|impls| impls.for_self_ty(&simplified_ty, &mut extend_with_impls));
for &krate in &*all_crates(db) {
@@ -5058,21 +4732,16 @@ impl Impl {
match self.id {
AnyImplId::ImplId(id) => {
let trait_ref = db.impl_trait(id)?.instantiate_identity().skip_norm_wip();
- let resolver = id.resolver(db);
- Some(TraitRef::new_with_resolver(db, &resolver, trait_ref))
+ Some(TraitRef::new(id.into(), trait_ref))
}
AnyImplId::BuiltinDeriveImplId(id) => {
let loc = id.loc(db);
let krate = loc.module(db).krate(db);
let interner = DbInterner::new_with(db, krate);
- let env = ParamEnvAndCrate {
- param_env: hir_ty::builtin_derive::param_env(interner, id),
- krate,
- };
let trait_ref = hir_ty::builtin_derive::impl_trait(interner, id)
.instantiate_identity()
.skip_norm_wip();
- Some(TraitRef { env, trait_ref })
+ Some(TraitRef { owner: TypeOwnerId::BuiltinDeriveImplId(id), trait_ref })
}
}
}
@@ -5080,24 +4749,16 @@ impl Impl {
pub fn self_ty(self, db: &dyn HirDatabase) -> Type<'_> {
match self.id {
AnyImplId::ImplId(id) => {
- let resolver = id.resolver(db);
- // FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s.
let ty = db.impl_self_ty(id).instantiate_identity().skip_norm_wip();
- Type::new_with_resolver_inner(db, &resolver, ty)
+ Type::new(id.into(), ty)
}
AnyImplId::BuiltinDeriveImplId(id) => {
let loc = id.loc(db);
let krate = loc.module(db).krate(db);
let interner = DbInterner::new_with(db, krate);
- let env = ParamEnvAndCrate {
- param_env: hir_ty::builtin_derive::param_env(interner, id),
- krate,
- };
- let ty = hir_ty::builtin_derive::impl_trait(interner, id)
- .instantiate_identity()
- .skip_norm_wip()
- .self_ty();
- Type { env, ty }
+ let ty =
+ hir_ty::builtin_derive::impl_trait(interner, id).map_bound(|it| it.self_ty());
+ Type { owner: TypeOwnerId::BuiltinDeriveImplId(id), ty }
}
}
}
@@ -5159,38 +4820,33 @@ impl Impl {
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct TraitRef<'db> {
- env: ParamEnvAndCrate<'db>,
+ owner: TypeOwnerId,
trait_ref: hir_ty::next_solver::TraitRef<'db>,
}
impl<'db> TraitRef<'db> {
- pub(crate) fn new_with_resolver(
- db: &'db dyn HirDatabase,
- resolver: &Resolver<'_>,
- trait_ref: hir_ty::next_solver::TraitRef<'db>,
- ) -> Self {
- let env = param_env_from_resolver(db, resolver);
- TraitRef { env, trait_ref }
+ fn new(owner: GenericDefId, trait_ref: hir_ty::next_solver::TraitRef<'db>) -> Self {
+ Self { owner: TypeOwnerId::GenericDefId(owner), trait_ref }
}
pub fn trait_(&self) -> Trait {
Trait { id: self.trait_ref.def_id.0 }
}
- pub fn self_ty(&self) -> TypeNs<'_> {
+ pub fn self_ty(&self) -> Type<'_> {
let ty = self.trait_ref.self_ty();
- TypeNs { env: self.env, ty }
+ Type { owner: self.owner, ty: EarlyBinder::bind(ty) }
}
/// Returns `idx`-th argument of this trait reference if it is a type argument. Note that the
/// first argument is the `Self` type.
- pub fn get_type_argument(&self, idx: usize) -> Option<TypeNs<'db>> {
+ pub fn get_type_argument(&self, idx: usize) -> Option<Type<'db>> {
self.trait_ref
.args
.as_slice()
.get(idx)
.and_then(|arg| arg.ty())
- .map(|ty| TypeNs { env: self.env, ty })
+ .map(|ty| Type { owner: self.owner, ty: EarlyBinder::bind(ty) })
}
}
@@ -5202,6 +4858,7 @@ enum AnyClosureId {
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Closure<'db> {
+ owner: TypeOwnerId,
id: AnyClosureId,
subst: GenericArgs<'db>,
}
@@ -5239,12 +4896,11 @@ impl<'db> Closure<'db> {
let InternedClosure { owner: infer_owner, expr: closure, .. } = closure;
let infer = InferenceResult::of(db, infer_owner);
let owner = infer_owner.expression_store_owner(db);
- let param_env = body_param_env_from_has_crate(db, owner);
infer.closures_data[&closure]
.min_captures
.values()
.flatten()
- .map(|capture| ClosureCapture { owner, infer_owner, closure, capture, param_env })
+ .map(|capture| ClosureCapture { owner, infer_owner, closure, capture })
.collect()
}
@@ -5335,7 +4991,6 @@ pub struct ClosureCapture<'db> {
infer_owner: InferBodyId,
closure: ExprId,
capture: &'db hir_ty::closure_analysis::CapturedPlace,
- param_env: ParamEnvAndCrate<'db>,
}
impl<'db> ClosureCapture<'db> {
@@ -5443,14 +5098,14 @@ impl<'db> ClosureCapture<'db> {
result
}
- pub fn ty(&self, _db: &'db dyn HirDatabase) -> Type<'db> {
- Type { env: self.param_env, ty: self.capture.place.ty() }
+ pub fn ty(&self, db: &'db dyn HirDatabase) -> Type<'db> {
+ Type::new_body(db, self.owner, self.capture.place.ty())
}
/// The type that is stored in the closure, which is different from [`Self::ty()`], representing
/// the place's type, when the capture is by ref.
pub fn captured_ty(&self, db: &'db dyn HirDatabase) -> Type<'db> {
- Type { env: self.param_env, ty: self.capture.captured_ty(db) }
+ Type::new_body(db, self.owner, self.capture.captured_ty(db))
}
}
@@ -5526,74 +5181,143 @@ impl CaptureUsageSource {
}
}
-#[derive(Clone, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
+enum TypeOwnerId {
+ GenericDefId(GenericDefId),
+ BuiltinDeriveImplId(BuiltinDeriveImplId),
+ AnonConstId(AnonConstId),
+ // FIXME: What do when we unify two different crates? Currently we just randomly keep one.
+ NoParams(base_db::Crate),
+}
+impl_from!(GenericDefId, BuiltinDeriveImplId, AnonConstId for TypeOwnerId);
+
+impl TypeOwnerId {
+ fn unify(self, other: Self) -> Option<Self> {
+ match (self, other) {
+ (TypeOwnerId::NoParams(_), owner) => Some(owner),
+ (owner, TypeOwnerId::NoParams(_)) => Some(owner),
+ (_, _) => {
+ if self == other {
+ Some(self)
+ } else {
+ None
+ }
+ }
+ }
+ }
+
+ #[track_caller]
+ fn must_unify(self, other: Self) -> Self {
+ self.unify(other).expect("failed to unify type owners")
+ }
+
+ fn can_rebase_into(
+ self,
+ db: &dyn HirDatabase,
+ rebase_into: Self,
+ self_ty: EarlyBinder<'_, Ty<'_>>,
+ ) -> bool {
+ if self == rebase_into || !self_ty.skip_binder().has_param() {
+ return true;
+ }
+ let self_def = match self {
+ TypeOwnerId::GenericDefId(def) => def,
+ TypeOwnerId::BuiltinDeriveImplId(_) | TypeOwnerId::AnonConstId(_) => return false,
+ TypeOwnerId::NoParams(_) => return true,
+ };
+ let self_def = match self_def {
+ GenericDefId::ImplId(def) => ItemContainerId::ImplId(def),
+ GenericDefId::TraitId(def) => ItemContainerId::TraitId(def),
+ GenericDefId::AdtId(_)
+ | GenericDefId::ConstId(_)
+ | GenericDefId::FunctionId(_)
+ | GenericDefId::StaticId(_)
+ | GenericDefId::TypeAliasId(_) => return false,
+ };
+ let rebase_into_def = match rebase_into {
+ TypeOwnerId::GenericDefId(def) => def,
+ TypeOwnerId::BuiltinDeriveImplId(_)
+ | TypeOwnerId::AnonConstId(_)
+ | TypeOwnerId::NoParams(_) => return false,
+ };
+ let rebase_into_parent = match rebase_into_def {
+ GenericDefId::ConstId(def) => def.loc(db).container,
+ GenericDefId::FunctionId(def) => def.loc(db).container,
+ GenericDefId::TypeAliasId(def) => def.loc(db).container,
+ GenericDefId::AdtId(_)
+ | GenericDefId::ImplId(_)
+ | GenericDefId::StaticId(_)
+ | GenericDefId::TraitId(_) => return false,
+ };
+ self_def == rebase_into_parent
+ }
+}
+
+/// Note: A [`Type`] remembers its origin. Trying to do anything (except comparing)
+/// with types of different origins will cause errors or panics. Instead, use the `instantiate` methods.
+#[derive(Clone, Debug)]
pub struct Type<'db> {
- env: ParamEnvAndCrate<'db>,
- ty: Ty<'db>,
+ owner: TypeOwnerId,
+ ty: EarlyBinder<'db, Ty<'db>>,
}
-impl<'db> Type<'db> {
- pub(crate) fn new_with_resolver(
- db: &'db dyn HirDatabase,
- resolver: &Resolver<'_>,
- ty: Ty<'db>,
- ) -> Self {
- Type::new_with_resolver_inner(db, resolver, ty)
+impl<'db> std::hash::Hash for Type<'db> {
+ fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+ // Do not hash the owner as different owners can compare the same.
+ // self.owner.hash(state);
+ self.ty.hash(state);
}
+}
- pub(crate) fn new_with_resolver_inner(
- db: &'db dyn HirDatabase,
- resolver: &Resolver<'_>,
- ty: Ty<'db>,
- ) -> Self {
- let environment = param_env_from_resolver(db, resolver);
- Type { env: environment, ty }
+impl<'db> PartialEq for Type<'db> {
+ fn eq(&self, other: &Self) -> bool {
+ if self.ty != other.ty {
+ return false;
+ }
+ hir_ty::with_attached_db(|db| {
+ self.owner.can_rebase_into(db, other.owner, self.ty)
+ || other.owner.can_rebase_into(db, self.owner, other.ty)
+ })
}
+}
- pub(crate) fn new_for_crate(
- db: &'db dyn HirDatabase,
- krate: base_db::Crate,
- ty: Ty<'db>,
- ) -> Self {
- let interner = DbInterner::new_with(db, krate);
- Type { env: ParamEnvAndCrate { param_env: ParamEnv::empty(interner), krate }, ty }
+impl<'db> Eq for Type<'db> {}
+
+impl<'db> Type<'db> {
+ fn new(owner: GenericDefId, ty: Ty<'db>) -> Self {
+ Type { owner: TypeOwnerId::GenericDefId(owner), ty: EarlyBinder::bind(ty) }
}
- fn new(db: &'db dyn HirDatabase, lexical_env: impl HasResolver, ty: Ty<'db>) -> Self {
- let resolver = lexical_env.resolver(db);
- let environment = param_env_from_resolver(db, &resolver);
- Type { env: environment, ty }
+ fn new_body(db: &dyn HirDatabase, owner: ExpressionStoreOwnerId, ty: Ty<'db>) -> Self {
+ Self::new(owner.generic_def(db), ty)
}
- fn from_def(db: &'db dyn HirDatabase, def: impl Into<TyDefId> + HasResolver) -> Self {
- let interner = DbInterner::new_no_crate(db);
- let ty = db.ty(def.into());
- let def = match def.into() {
- TyDefId::AdtId(it) => GenericDefId::AdtId(it),
- TyDefId::TypeAliasId(it) => GenericDefId::TypeAliasId(it),
- TyDefId::BuiltinType(_) => {
- return Type::new(db, def, ty.skip_binder());
- }
- };
- let args = GenericArgs::error_for_item(interner, def.into());
- Type::new(db, def, ty.instantiate(interner, args).skip_norm_wip())
+ fn no_params(krate: base_db::Crate, ty: Ty<'db>) -> Self {
+ Type { owner: TypeOwnerId::NoParams(krate), ty: EarlyBinder::bind(ty) }
}
- // FIXME: We shouldn't leak `TyKind::Param`s.
- fn from_def_params(db: &'db dyn HirDatabase, def: impl Into<TyDefId> + HasResolver) -> Self {
- let ty = db.ty(def.into());
- Type::new(db, def, ty.instantiate_identity().skip_norm_wip())
+ fn builtin_type_crate(db: &'db dyn HirDatabase) -> base_db::Crate {
+ // It doesn't really matter.
+ all_crates(db)[0]
}
- fn from_value_def(
- db: &'db dyn HirDatabase,
- def: impl Into<ValueTyDefId> + HasResolver,
- ) -> Self {
- let interner = DbInterner::new_no_crate(db);
- let Some(ty) = db.value_ty(def.into()) else {
- return Type::new(db, def, Ty::new_error(interner, ErrorGuaranteed));
+ fn from_def(db: &'db dyn HirDatabase, def: impl Into<TyDefId>) -> Self {
+ let def = def.into();
+ let ty = db.ty(def);
+ let owner = match def {
+ TyDefId::AdtId(it) => TypeOwnerId::GenericDefId(GenericDefId::AdtId(it)),
+ TyDefId::TypeAliasId(it) => TypeOwnerId::GenericDefId(GenericDefId::TypeAliasId(it)),
+ TyDefId::BuiltinType(_) => TypeOwnerId::NoParams(Self::builtin_type_crate(db)),
+ };
+ Type { owner, ty }
+ }
+
+ fn from_value_def(db: &'db dyn HirDatabase, def: impl Into<ValueTyDefId>) -> Self {
+ let def = def.into();
+ let Some(ty) = db.value_ty(def) else {
+ return Type::unknown();
};
- let def = match def.into() {
+ let def = match def {
ValueTyDefId::ConstId(it) => GenericDefId::ConstId(it),
ValueTyDefId::FunctionId(it) => GenericDefId::FunctionId(it),
ValueTyDefId::StructId(it) => GenericDefId::AdtId(AdtId::StructId(it)),
@@ -5601,55 +5325,192 @@ impl<'db> Type<'db> {
ValueTyDefId::EnumVariantId(it) => {
GenericDefId::AdtId(AdtId::EnumId(it.lookup(db).parent))
}
- ValueTyDefId::StaticId(_) => {
- return Type::new(db, def, ty.skip_binder());
+ ValueTyDefId::StaticId(it) => {
+ return Type::no_params(hir_def::HasModule::krate(&it, db), ty.skip_binder());
+ }
+ };
+ Type::new(def, ty.instantiate_identity().skip_norm_wip())
+ }
+
+ /// Replace any generic parameters with error types.
+ pub fn instantiate_with_errors(&self) -> Self {
+ let interner = DbInterner::conjure();
+ let krate = self.krate(interner.db());
+ let args = match self.owner {
+ TypeOwnerId::GenericDefId(def) => GenericArgs::error_for_item(interner, def.into()),
+ TypeOwnerId::BuiltinDeriveImplId(def) => {
+ GenericArgs::error_for_item(interner, def.into())
}
+ TypeOwnerId::AnonConstId(def) => GenericArgs::error_for_item(interner, def.into()),
+ TypeOwnerId::NoParams(_) => GenericArgs::empty(interner),
};
- let args = GenericArgs::error_for_item(interner, def.into());
- Type::new(db, def, ty.instantiate(interner, args).skip_norm_wip())
+ Type::no_params(krate, self.ty.instantiate(interner, args).skip_norm_wip())
+ }
+
+ // FIXME: Find some way with const params, maybe even lifetimes?
+ pub fn instantiate(&self, args: impl IntoIterator<Item: Borrow<Type<'db>>>) -> Type<'db> {
+ let interner = DbInterner::conjure();
+ let (args, owner) = match self.owner {
+ TypeOwnerId::GenericDefId(def) => generic_args_from_tys(interner, def.into(), args),
+ TypeOwnerId::BuiltinDeriveImplId(def) => {
+ generic_args_from_tys(interner, def.into(), args)
+ }
+ TypeOwnerId::AnonConstId(def) => generic_args_from_tys(interner, def.into(), args),
+ TypeOwnerId::NoParams(krate) => {
+ (GenericArgs::empty(interner), TypeOwnerId::NoParams(krate))
+ }
+ };
+ Type { owner, ty: EarlyBinder::bind(self.ty.instantiate(interner, args).skip_norm_wip()) }
+ }
+
+ /// Instantiates multiple types with infer vars, keeping the same infer vars for the same owners.
+ fn instantiate_many_with_infer(
+ tys: impl IntoIterator<Item: Borrow<Type<'db>>>,
+ infcx: &InferCtxt<'db>,
+ ) -> impl Iterator<Item = Ty<'db>> {
+ let mut var_for_param = FxHashMap::default();
+ tys.into_iter().map(move |ty| {
+ let ty = ty.borrow();
+ let owner = match ty.owner {
+ TypeOwnerId::GenericDefId(def) => def.into(),
+ TypeOwnerId::BuiltinDeriveImplId(def) => def.into(),
+ TypeOwnerId::AnonConstId(def) => def.into(),
+ TypeOwnerId::NoParams(_) => return ty.ty.skip_binder(),
+ };
+ let args = GenericArgs::for_item(infcx.interner, owner, |_, param, _| {
+ *var_for_param
+ .entry(param)
+ .or_insert_with(|| infcx.var_for_def(param, hir_ty::Span::Dummy))
+ });
+
+ ty.ty.instantiate(infcx.interner, args).skip_norm_wip()
+ })
+ }
+
+ /// Tries to put this type as-is in the context of `rebase_into`. This will return `Some(_)` if:
+ ///
+ /// - The type does not reference generic parameters, or
+ /// - `rebase_into` is in the context of a child of our context (for example, a function in an impl).
+ pub fn try_rebase_into(
+ &self,
+ db: &'db dyn HirDatabase,
+ rebase_into: &Type<'db>,
+ ) -> Option<Self> {
+ if self.owner.can_rebase_into(db, rebase_into.owner, self.ty) {
+ Some(Type { owner: rebase_into.owner, ty: self.ty })
+ } else {
+ None
+ }
+ }
+
+ /// If `self` can be rebased into `rebase_into`, returns that. Otherwise, instantiates `self` with errors
+ /// and returns that.
+ pub fn rebase_into_or_error(
+ &self,
+ db: &'db dyn HirDatabase,
+ rebase_into: &Type<'db>,
+ ) -> Type<'db> {
+ self.try_rebase_into(db, rebase_into).unwrap_or_else(|| self.instantiate_with_errors())
+ }
+
+ pub fn try_rebase_into_owner(
+ &self,
+ db: &'db dyn HirDatabase,
+ new_owner: GenericDef,
+ ) -> Option<Self> {
+ let new_owner = new_owner.id()?.into();
+ if self.owner.can_rebase_into(db, new_owner, self.ty) {
+ Some(Type { owner: new_owner, ty: self.ty })
+ } else {
+ None
+ }
+ }
+
+ pub fn rebase_into_owner_or_error(
+ &self,
+ db: &'db dyn HirDatabase,
+ new_owner: GenericDef,
+ ) -> Self {
+ self.try_rebase_into_owner(db, new_owner).unwrap_or_else(|| self.instantiate_with_errors())
+ }
+
+ pub fn unknown() -> Self {
+ let interner = DbInterner::conjure();
+ Type::no_params(
+ Self::builtin_type_crate(interner.db()),
+ Ty::new_error(interner, ErrorGuaranteed),
+ )
}
pub fn new_slice(db: &'db dyn HirDatabase, ty: Self) -> Self {
let interner = DbInterner::new_no_crate(db);
- Type { env: ty.env, ty: Ty::new_slice(interner, ty.ty) }
+ Type { owner: ty.owner, ty: ty.ty.map_bound(|ty| Ty::new_slice(interner, ty)) }
}
- pub fn new_tuple(db: &'db dyn HirDatabase, krate: base_db::Crate, tys: &[Self]) -> Self {
- let tys = tys.iter().map(|it| it.ty);
- let interner = DbInterner::new_with(db, krate);
- Type {
- env: ParamEnvAndCrate { param_env: ParamEnv::empty(interner), krate },
- ty: Ty::new_tup_from_iter(interner, tys),
- }
+ pub fn new_tuple(
+ db: &'db dyn HirDatabase,
+ tys: impl IntoIterator<Item: Borrow<Type<'db>>>,
+ ) -> Self {
+ let interner = DbInterner::new_no_crate(db);
+ let mut owner = None::<TypeOwnerId>;
+ let ty = EarlyBinder::bind(Ty::new_tup_from_iter(
+ interner,
+ tys.into_iter().map(|ty| {
+ let ty = ty.borrow();
+
+ match &mut owner {
+ Some(owner) => *owner = owner.must_unify(ty.owner),
+ None => owner = Some(ty.owner),
+ }
+
+ ty.ty.skip_binder()
+ }),
+ ));
+ let owner =
+ owner.unwrap_or_else(|| TypeOwnerId::NoParams(Self::builtin_type_crate(interner.db())));
+ Type { owner, ty }
+ }
+
+ pub fn new_unit() -> Self {
+ let interner = DbInterner::conjure();
+ Type::no_params(Self::builtin_type_crate(interner.db()), Ty::new_unit(interner))
}
pub fn is_unit(&self) -> bool {
- self.ty.is_unit()
+ self.ty.skip_binder().is_unit()
}
pub fn is_bool(&self) -> bool {
- matches!(self.ty.kind(), TyKind::Bool)
+ matches!(self.ty.skip_binder().kind(), TyKind::Bool)
}
pub fn is_str(&self) -> bool {
- matches!(self.ty.kind(), TyKind::Str)
+ matches!(self.ty.skip_binder().kind(), TyKind::Str)
}
pub fn is_never(&self) -> bool {
- matches!(self.ty.kind(), TyKind::Never)
+ matches!(self.ty.skip_binder().kind(), TyKind::Never)
}
pub fn is_mutable_reference(&self) -> bool {
- matches!(self.ty.kind(), TyKind::Ref(.., hir_ty::next_solver::Mutability::Mut))
+ matches!(
+ self.ty.skip_binder().kind(),
+ TyKind::Ref(.., hir_ty::next_solver::Mutability::Mut)
+ )
}
pub fn is_reference(&self) -> bool {
- matches!(self.ty.kind(), TyKind::Ref(..))
+ matches!(self.ty.skip_binder().kind(), TyKind::Ref(..))
}
pub fn contains_reference(&self, db: &'db dyn HirDatabase) -> bool {
let interner = DbInterner::new_no_crate(db);
- return self.ty.visit_with(&mut Visitor { interner }).is_break();
+ return self
+ .ty
+ .instantiate_identity()
+ .skip_norm_wip()
+ .visit_with(&mut Visitor { interner })
+ .is_break();
fn is_phantom_data(db: &dyn HirDatabase, adt_id: AdtId) -> bool {
match adt_id {
@@ -5727,89 +5588,129 @@ impl<'db> Type<'db> {
}
pub fn as_reference(&self) -> Option<(Type<'db>, Mutability)> {
- let TyKind::Ref(_lt, ty, m) = self.ty.kind() else { return None };
+ let TyKind::Ref(_lt, ty, m) = self.ty.skip_binder().kind() else { return None };
let m = Mutability::from_mutable(matches!(m, hir_ty::next_solver::Mutability::Mut));
Some((self.derived(ty), m))
}
+ pub fn as_reference_inner(&self) -> Option<Type<'db>> {
+ self.as_reference().map(|(inner, _)| inner)
+ }
+
pub fn add_reference(&self, db: &'db dyn HirDatabase, mutability: Mutability) -> Self {
let interner = DbInterner::new_no_crate(db);
let ty_mutability = match mutability {
Mutability::Shared => hir_ty::next_solver::Mutability::Not,
Mutability::Mut => hir_ty::next_solver::Mutability::Mut,
};
- self.derived(Ty::new_ref(interner, Region::error(interner), self.ty, ty_mutability))
+ self.derived(Ty::new_ref(
+ interner,
+ Region::error(interner),
+ self.ty.skip_binder(),
+ ty_mutability,
+ ))
}
pub fn is_slice(&self) -> bool {
- matches!(self.ty.kind(), TyKind::Slice(..))
+ matches!(self.ty.skip_binder().kind(), TyKind::Slice(..))
}
pub fn is_usize(&self) -> bool {
- matches!(self.ty.kind(), TyKind::Uint(rustc_type_ir::UintTy::Usize))
+ matches!(self.ty.skip_binder().kind(), TyKind::Uint(rustc_type_ir::UintTy::Usize))
}
pub fn is_float(&self) -> bool {
- matches!(self.ty.kind(), TyKind::Float(_))
+ matches!(self.ty.skip_binder().kind(), TyKind::Float(_))
}
pub fn is_char(&self) -> bool {
- matches!(self.ty.kind(), TyKind::Char)
+ matches!(self.ty.skip_binder().kind(), TyKind::Char)
}
pub fn is_int_or_uint(&self) -> bool {
- matches!(self.ty.kind(), TyKind::Int(_) | TyKind::Uint(_))
+ matches!(self.ty.skip_binder().kind(), TyKind::Int(_) | TyKind::Uint(_))
}
pub fn is_scalar(&self) -> bool {
matches!(
- self.ty.kind(),
+ self.ty.skip_binder().kind(),
TyKind::Bool | TyKind::Char | TyKind::Int(_) | TyKind::Uint(_) | TyKind::Float(_)
)
}
pub fn is_tuple(&self) -> bool {
- matches!(self.ty.kind(), TyKind::Tuple(..))
- }
-
- pub fn remove_ref(&self) -> Option<Type<'db>> {
- match self.ty.kind() {
- TyKind::Ref(_, ty, _) => Some(self.derived(ty)),
- _ => None,
- }
+ matches!(self.ty.skip_binder().kind(), TyKind::Tuple(..))
}
pub fn as_slice(&self) -> Option<Type<'db>> {
- match self.ty.kind() {
+ match self.ty.skip_binder().kind() {
TyKind::Slice(ty) => Some(self.derived(ty)),
_ => None,
}
}
pub fn strip_references(&self) -> Self {
- self.derived(self.ty.strip_references())
+ self.derived(self.ty.skip_binder().strip_references())
}
// FIXME: This is the same as `remove_ref()`, remove one of these methods.
pub fn strip_reference(&self) -> Self {
- self.derived(self.ty.strip_reference())
+ self.derived(self.ty.skip_binder().strip_reference())
}
pub fn is_unknown(&self) -> bool {
- self.ty.is_ty_error()
+ self.ty.skip_binder().is_ty_error()
+ }
+
+ fn krate(&self, db: &'db dyn HirDatabase) -> base_db::Crate {
+ match self.owner {
+ TypeOwnerId::GenericDefId(def) => hir_def::HasModule::krate(&def, db),
+ TypeOwnerId::BuiltinDeriveImplId(def) => {
+ hir_def::HasModule::krate(&def.loc(db).adt, db)
+ }
+ TypeOwnerId::AnonConstId(def) => hir_def::HasModule::krate(&def, db),
+ TypeOwnerId::NoParams(krate) => krate,
+ }
+ }
+
+ fn param_env(&self, db: &'db dyn HirDatabase) -> ParamEnvAndCrate<'db> {
+ let interner = DbInterner::new_no_crate(db);
+ let krate = self.krate(db);
+ match self.owner {
+ TypeOwnerId::GenericDefId(def) => {
+ ParamEnvAndCrate { param_env: db.trait_environment(def), krate }
+ }
+ TypeOwnerId::BuiltinDeriveImplId(def) => ParamEnvAndCrate {
+ param_env: hir_ty::builtin_derive::param_env(interner, def),
+ krate,
+ },
+ TypeOwnerId::AnonConstId(def) => ParamEnvAndCrate {
+ param_env: db.trait_environment(def.loc(db).owner.generic_def(db)),
+ krate,
+ },
+ TypeOwnerId::NoParams(_) => {
+ ParamEnvAndCrate { param_env: ParamEnv::empty(interner), krate }
+ }
+ }
}
/// Checks that particular type `ty` implements `std::future::IntoFuture` or
/// `std::future::Future` and returns the `Output` associated type.
/// This function is used in `.await` syntax completion.
pub fn into_future_output(&self, db: &'db dyn HirDatabase) -> Option<Type<'db>> {
- let lang_items = hir_def::lang_item::lang_items(db, self.env.krate);
+ let env = self.param_env(db);
+ let lang_items = hir_def::lang_item::lang_items(db, env.krate);
let (trait_, output_assoc_type) = lang_items
.IntoFuture
.zip(lang_items.IntoFutureOutput)
.or(lang_items.Future.zip(lang_items.FutureOutput))?;
- if !traits::implements_trait_unique(self.ty, db, self.env, trait_) {
+ if !traits::implements_trait_unique(
+ self.ty.instantiate_identity().skip_norm_wip(),
+ db,
+ env,
+ trait_,
+ ) {
return None;
}
@@ -5818,32 +5719,46 @@ impl<'db> Type<'db> {
/// This does **not** resolve `IntoFuture`, only `Future`.
pub fn future_output(self, db: &'db dyn HirDatabase) -> Option<Type<'db>> {
- let lang_items = hir_def::lang_item::lang_items(db, self.env.krate);
+ let krate = self.krate(db);
+ let lang_items = hir_def::lang_item::lang_items(db, krate);
let future_output = lang_items.FutureOutput?;
self.normalize_trait_assoc_type(db, &[], future_output.into())
}
/// This does **not** resolve `IntoIterator`, only `Iterator`.
pub fn iterator_item(self, db: &'db dyn HirDatabase) -> Option<Type<'db>> {
- let lang_items = hir_def::lang_item::lang_items(db, self.env.krate);
+ let krate = self.krate(db);
+ let lang_items = hir_def::lang_item::lang_items(db, krate);
let iterator_item = lang_items.IteratorItem?;
self.normalize_trait_assoc_type(db, &[], iterator_item.into())
}
pub fn impls_iterator(self, db: &'db dyn HirDatabase) -> bool {
- let lang_items = hir_def::lang_item::lang_items(db, self.env.krate);
+ let env = self.param_env(db);
+ let lang_items = hir_def::lang_item::lang_items(db, env.krate);
let Some(iterator_trait) = lang_items.Iterator else {
return false;
};
- traits::implements_trait_unique(self.ty, db, self.env, iterator_trait)
+ traits::implements_trait_unique(
+ self.ty.instantiate_identity().skip_norm_wip(),
+ db,
+ env,
+ iterator_trait,
+ )
}
/// Resolves the projection `<Self as IntoIterator>::IntoIter` and returns the resulting type
pub fn into_iterator_iter(self, db: &'db dyn HirDatabase) -> Option<Type<'db>> {
- let lang_items = hir_def::lang_item::lang_items(db, self.env.krate);
+ let env = self.param_env(db);
+ let lang_items = hir_def::lang_item::lang_items(db, env.krate);
let trait_ = lang_items.IntoIterator?;
- if !traits::implements_trait_unique(self.ty, db, self.env, trait_) {
+ if !traits::implements_trait_unique(
+ self.ty.instantiate_identity().skip_norm_wip(),
+ db,
+ env,
+ trait_,
+ ) {
return None;
}
@@ -5856,24 +5771,63 @@ impl<'db> Type<'db> {
/// This function can be used to check if a particular type is callable, since FnOnce is a
/// supertrait of Fn and FnMut, so all callable types implements at least FnOnce.
pub fn impls_fnonce(&self, db: &'db dyn HirDatabase) -> bool {
- let lang_items = hir_def::lang_item::lang_items(db, self.env.krate);
+ let env = self.param_env(db);
+ let lang_items = hir_def::lang_item::lang_items(db, env.krate);
let fnonce_trait = match lang_items.FnOnce {
Some(it) => it,
None => return false,
};
- traits::implements_trait_unique(self.ty, db, self.env, fnonce_trait)
+ traits::implements_trait_unique(
+ self.ty.instantiate_identity().skip_norm_wip(),
+ db,
+ env,
+ fnonce_trait,
+ )
}
// FIXME: Find better API that also handles const generics
pub fn impls_trait(&self, db: &'db dyn HirDatabase, trait_: Trait, args: &[Type<'db>]) -> bool {
+ let env = self.param_env(db);
let interner = DbInterner::new_no_crate(db);
- let args = generic_args_from_tys(
- interner,
- trait_.id.into(),
- std::iter::once(self.ty).chain(args.iter().map(|ty| ty.ty)),
- );
- traits::implements_trait_unique_with_args(db, self.env, trait_.id, args)
+ let (args, _owner) =
+ generic_args_from_tys(interner, trait_.id.into(), iter::once(self).chain(args));
+ traits::implements_trait_unique_with_args(db, env, trait_.id, args)
+ }
+
+ /// Unlike [`Type::impls_trait()`], which checks whether the type always implements the trait,
+ /// this check whether there are any generic args substitution for `args`` that will cause the
+ /// trait to be implemented.
+ ///
+ /// For example, suppose we're there's `struct Foo<T>` and we're checking `Foo<T>: Trait`.
+ /// `impls_trait()` will return true only if there is `impl<T> Trait for Foo<T>`, while this
+ /// method will also return true if there is only `impl Trait for Foo<i32>`.
+ ///
+ /// Note that you can of course instantiate `Foo<T>` with `<i32>` and then the checks will
+ /// be the same, but this check for *any* substitution.
+ ///
+ /// Unlike almost anything that takes more than one type, you *can* pass types from different origins
+ /// to this function.
+ pub fn has_any_impl(
+ &self,
+ db: &'db dyn HirDatabase,
+ trait_: Trait,
+ args: &[Type<'db>],
+ ) -> bool {
+ let interner = DbInterner::new_no_crate(db);
+ let env = ParamEnvAndCrate { param_env: ParamEnv::empty(interner), krate: self.krate(db) };
+ traits::implements_trait_unique_with_infcx(db, env, trait_.id, &mut |infcx| {
+ let mut args = Self::instantiate_many_with_infer(iter::once(self).chain(args), infcx);
+ GenericArgs::for_item(infcx.interner, trait_.id.into(), |_, param, _| {
+ if let GenericParamId::TypeParamId(_) = param
+ && let Some(arg) = args.next()
+ {
+ arg.into()
+ } else {
+ infcx.var_for_def(param, hir_ty::Span::Dummy)
+ }
+ })
+ })
}
pub fn normalize_trait_assoc_type(
@@ -5882,12 +5836,10 @@ impl<'db> Type<'db> {
args: &[Type<'db>],
alias: TypeAlias,
) -> Option<Type<'db>> {
- let interner = DbInterner::new_with(db, self.env.krate);
- let args = generic_args_from_tys(
- interner,
- alias.id.into(),
- std::iter::once(self.ty).chain(args.iter().map(|ty| ty.ty)),
- );
+ let env = self.param_env(db);
+ let interner = DbInterner::new_with(db, env.krate);
+ let (args, owner) =
+ generic_args_from_tys(interner, alias.id.into(), iter::once(self).chain(args));
// FIXME: We don't handle GATs yet.
let projection = Ty::new_alias(
interner,
@@ -5899,12 +5851,13 @@ impl<'db> Type<'db> {
);
let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);
- let ty = structurally_normalize_ty(&infcx, projection, self.env.param_env);
- if ty.is_ty_error() { None } else { Some(self.derived(ty)) }
+ let ty = structurally_normalize_ty(&infcx, projection, env.param_env);
+ if ty.is_ty_error() { None } else { Some(Type { owner, ty: EarlyBinder::bind(ty) }) }
}
pub fn is_copy(&self, db: &'db dyn HirDatabase) -> bool {
- let lang_items = hir_def::lang_item::lang_items(db, self.env.krate);
+ let env = self.param_env(db);
+ let lang_items = hir_def::lang_item::lang_items(db, env.krate);
let Some(copy_trait) = lang_items.Copy else {
return false;
};
@@ -5913,7 +5866,7 @@ impl<'db> Type<'db> {
pub fn as_callable(&self, db: &'db dyn HirDatabase) -> Option<Callable<'db>> {
let interner = DbInterner::new_no_crate(db);
- let callee = match self.ty.kind() {
+ let callee = match self.ty.skip_binder().kind() {
TyKind::Closure(id, subst) => Callee::Closure(id.0, subst),
TyKind::CoroutineClosure(id, subst) => Callee::CoroutineClosure(id.0, subst),
TyKind::FnPtr(..) => Callee::FnPtr,
@@ -5921,7 +5874,9 @@ impl<'db> Type<'db> {
// This will happen when it implements fn or fn mut, since we add an autoborrow adjustment
TyKind::Ref(_, inner_ty, _) => return self.derived(inner_ty).as_callable(db),
_ => {
- let (fn_trait, sig) = hir_ty::callable_sig_from_fn_trait(self.ty, self.env, db)?;
+ let env = self.param_env(db);
+ let (fn_trait, sig) =
+ hir_ty::callable_sig_from_fn_trait(self.ty.skip_binder(), env, db)?;
return Some(Callable {
ty: self.clone(),
sig,
@@ -5931,74 +5886,77 @@ impl<'db> Type<'db> {
}
};
- let sig = self.ty.callable_sig(interner)?;
+ let sig = self.ty.skip_binder().callable_sig(interner)?;
Some(Callable { ty: self.clone(), sig, callee, is_bound_method: false })
}
pub fn is_closure(&self) -> bool {
- matches!(self.ty.kind(), TyKind::Closure { .. })
+ matches!(self.ty.skip_binder().kind(), TyKind::Closure { .. })
}
pub fn as_closure(&self) -> Option<Closure<'db>> {
- match self.ty.kind() {
+ match self.ty.skip_binder().kind() {
TyKind::Closure(id, subst) => {
- Some(Closure { id: AnyClosureId::ClosureId(id.0), subst })
- }
- TyKind::CoroutineClosure(id, subst) => {
- Some(Closure { id: AnyClosureId::CoroutineClosureId(id.0), subst })
+ Some(Closure { id: AnyClosureId::ClosureId(id.0), subst, owner: self.owner })
}
+ TyKind::CoroutineClosure(id, subst) => Some(Closure {
+ id: AnyClosureId::CoroutineClosureId(id.0),
+ subst,
+ owner: self.owner,
+ }),
_ => None,
}
}
pub fn is_fn(&self) -> bool {
- matches!(self.ty.kind(), TyKind::FnDef(..) | TyKind::FnPtr { .. })
+ matches!(self.ty.skip_binder().kind(), TyKind::FnDef(..) | TyKind::FnPtr { .. })
}
pub fn is_array(&self) -> bool {
- matches!(self.ty.kind(), TyKind::Array(..))
+ matches!(self.ty.skip_binder().kind(), TyKind::Array(..))
}
- pub fn is_packed(&self, db: &'db dyn HirDatabase) -> bool {
- let adt_id = match self.ty.kind() {
- TyKind::Adt(adt_def, ..) => adt_def.def_id(),
- _ => return false,
- };
-
- let adt = adt_id.into();
- match adt {
- Adt::Struct(s) => s.repr(db).unwrap_or_default().pack.is_some(),
+ pub fn is_packed(&self, _db: &'db dyn HirDatabase) -> bool {
+ match self.ty.skip_binder().kind() {
+ TyKind::Adt(adt_def, ..) => adt_def.is_packed(),
_ => false,
}
}
pub fn is_raw_ptr(&self) -> bool {
- matches!(self.ty.kind(), TyKind::RawPtr(..))
+ matches!(self.ty.skip_binder().kind(), TyKind::RawPtr(..))
}
pub fn is_mutable_raw_ptr(&self) -> bool {
// Used outside of rust-analyzer (e.g. by `ra_ap_hir` consumers).
- matches!(self.ty.kind(), TyKind::RawPtr(.., hir_ty::next_solver::Mutability::Mut))
+ matches!(
+ self.ty.skip_binder().kind(),
+ TyKind::RawPtr(.., hir_ty::next_solver::Mutability::Mut)
+ )
}
pub fn as_raw_ptr(&self) -> Option<(Type<'db>, Mutability)> {
// Used outside of rust-analyzer (e.g. by `ra_ap_hir` consumers).
- let TyKind::RawPtr(ty, m) = self.ty.kind() else { return None };
+ let TyKind::RawPtr(ty, m) = self.ty.skip_binder().kind() else { return None };
let m = Mutability::from_mutable(matches!(m, hir_ty::next_solver::Mutability::Mut));
Some((self.derived(ty), m))
}
pub fn remove_raw_ptr(&self) -> Option<Type<'db>> {
- if let TyKind::RawPtr(ty, _) = self.ty.kind() { Some(self.derived(ty)) } else { None }
+ if let TyKind::RawPtr(ty, _) = self.ty.skip_binder().kind() {
+ Some(self.derived(ty))
+ } else {
+ None
+ }
}
pub fn contains_unknown(&self) -> bool {
- self.ty.references_non_lt_error()
+ self.ty.skip_binder().references_non_lt_error()
}
pub fn fields(&self, db: &'db dyn HirDatabase) -> Vec<(Field, Self)> {
let interner = DbInterner::new_no_crate(db);
- let (variant_id, substs) = match self.ty.kind() {
+ let (variant_id, substs) = match self.ty.skip_binder().kind() {
TyKind::Adt(adt_def, substs) => {
let id = match adt_def.def_id() {
AdtId::StructId(id) => id.into(),
@@ -6021,7 +5979,7 @@ impl<'db> Type<'db> {
}
pub fn tuple_fields(&self, _db: &'db dyn HirDatabase) -> Vec<Self> {
- if let TyKind::Tuple(substs) = self.ty.kind() {
+ if let TyKind::Tuple(substs) = self.ty.skip_binder().kind() {
substs.iter().map(|ty| self.derived(ty)).collect()
} else {
Vec::new()
@@ -6029,17 +5987,18 @@ impl<'db> Type<'db> {
}
pub fn as_array(&self, db: &'db dyn HirDatabase) -> Option<(Self, usize)> {
- if let TyKind::Array(ty, len) = self.ty.kind() {
+ if let TyKind::Array(ty, len) = self.ty.skip_binder().kind() {
try_const_usize(db, len).map(|it| (self.derived(ty), it as usize))
} else {
None
}
}
+ // FIXME: We should probably remove this.
pub fn fingerprint_for_trait_impl(&self, db: &'db dyn HirDatabase) -> Option<SimplifiedType> {
fast_reject::simplify_type(
DbInterner::new_no_crate(db),
- self.ty,
+ self.ty.skip_binder(),
fast_reject::TreatParams::AsRigid,
)
}
@@ -6055,9 +6014,10 @@ impl<'db> Type<'db> {
fn autoderef_(&self, db: &'db dyn HirDatabase) -> impl Iterator<Item = Ty<'db>> {
let interner = DbInterner::new_no_crate(db);
+ let env = self.param_env(db);
// There should be no inference vars in types passed here
- let canonical = hir_ty::replace_errors_with_variables(interner, &self.ty);
- autoderef(db, self.env, canonical)
+ let canonical = hir_ty::replace_errors_with_variables(interner, &self.ty.skip_binder());
+ autoderef(db, env, canonical)
}
// This would be nicer if it just returned an iterator, but that runs into
@@ -6089,17 +6049,20 @@ impl<'db> Type<'db> {
}
}
};
+ let krate = self.krate(db);
let interner = DbInterner::new_no_crate(db);
- let Some(simplified_type) =
- fast_reject::simplify_type(interner, self.ty, fast_reject::TreatParams::AsRigid)
- else {
+ let Some(simplified_type) = fast_reject::simplify_type(
+ interner,
+ self.ty.skip_binder(),
+ fast_reject::TreatParams::AsRigid,
+ ) else {
return;
};
method_resolution::with_incoherent_inherent_impls(
db,
- self.env.krate,
+ krate,
&simplified_type,
&mut handle_impls,
);
@@ -6135,12 +6098,12 @@ impl<'db> Type<'db> {
/// - "U"
/// ```
pub fn type_arguments(&self) -> impl Iterator<Item = Type<'db>> + '_ {
- match self.ty.strip_references().kind() {
+ match self.ty.skip_binder().strip_references().kind() {
TyKind::Adt(_, substs) => Either::Left(substs.types().map(move |ty| self.derived(ty))),
TyKind::Tuple(substs) => {
Either::Right(Either::Left(substs.iter().map(move |ty| self.derived(ty))))
}
- _ => Either::Right(Either::Right(std::iter::empty())),
+ _ => Either::Right(Either::Right(iter::empty())),
}
}
@@ -6168,6 +6131,7 @@ impl<'db> Type<'db> {
display_target: DisplayTarget,
) -> impl Iterator<Item = SmolStr> + 'a {
self.ty
+ .skip_binder()
.strip_references()
.as_adt()
.into_iter()
@@ -6258,7 +6222,7 @@ impl<'db> Type<'db> {
};
let infcx = interner.infer_ctxt().build(typing_mode);
let features = resolver.top_level_def_map().features();
- let environment = param_env_from_resolver(db, resolver);
+ let environment = self.param_env(db);
let ctx = MethodResolutionContext {
infcx: &infcx,
resolver,
@@ -6293,7 +6257,8 @@ 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 canonical =
+ hir_ty::replace_errors_with_variables(ctx.infcx.interner, &self.ty.skip_binder());
let (self_ty, _) = ctx.infcx.instantiate_canonical(hir_ty::Span::Dummy, &canonical);
match name {
@@ -6401,7 +6366,8 @@ 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 canonical =
+ hir_ty::replace_errors_with_variables(ctx.infcx.interner, &self.ty.skip_binder());
let (self_ty, _) = ctx.infcx.instantiate_canonical(hir_ty::Span::Dummy, &canonical);
match name {
@@ -6450,23 +6416,23 @@ impl<'db> Type<'db> {
}
pub fn as_adt(&self) -> Option<Adt> {
- let (adt, _subst) = self.ty.as_adt()?;
+ let (adt, _subst) = self.ty.skip_binder().as_adt()?;
Some(adt.into())
}
/// Holes in the args can come from lifetime/const params.
pub fn as_adt_with_args(&self) -> Option<(Adt, Vec<Option<Type<'db>>>)> {
- let (adt, args) = self.ty.as_adt()?;
+ let (adt, args) = self.ty.skip_binder().as_adt()?;
let args = args.iter().map(|arg| Some(self.derived(arg.ty()?))).collect();
Some((adt.into(), args))
}
pub fn as_builtin(&self) -> Option<BuiltinType> {
- self.ty.as_builtin().map(|inner| BuiltinType { inner })
+ self.ty.skip_binder().as_builtin().map(|inner| BuiltinType { inner })
}
pub fn as_dyn_trait(&self) -> Option<Trait> {
- self.ty.dyn_trait().map(Into::into)
+ self.ty.skip_binder().dyn_trait().map(Into::into)
}
/// If a type can be represented as `dyn Trait`, returns all traits accessible via this type,
@@ -6485,11 +6451,11 @@ impl<'db> Type<'db> {
pub fn env_traits(&self, db: &'db dyn HirDatabase) -> impl Iterator<Item = Trait> {
let _p = tracing::info_span!("env_traits").entered();
+ let env = self.param_env(db);
self.autoderef_(db)
.filter(|ty| matches!(ty.kind(), TyKind::Param(_)))
- .flat_map(|ty| {
- self.env
- .param_env
+ .flat_map(move |ty| {
+ env.param_env
.clauses()
.iter()
.filter_map(move |pred| match pred.kind().skip_binder() {
@@ -6503,7 +6469,7 @@ impl<'db> Type<'db> {
}
pub fn as_impl_traits(&self, db: &'db dyn HirDatabase) -> Option<impl Iterator<Item = Trait>> {
- self.ty.impl_trait_bounds(db).map(|it| {
+ self.ty.skip_binder().impl_trait_bounds(db).map(|it| {
it.into_iter().filter_map(|pred| match pred.kind().skip_binder() {
ClauseKind::Trait(trait_ref) => Some(Trait::from(trait_ref.def_id().0)),
_ => None,
@@ -6513,7 +6479,7 @@ impl<'db> Type<'db> {
pub fn as_associated_type_parent_trait(&self, db: &'db dyn HirDatabase) -> Option<Trait> {
let TyKind::Alias(AliasTy { kind: AliasTyKind::Projection { def_id }, .. }) =
- self.ty.kind()
+ self.ty.skip_binder().kind()
else {
return None;
};
@@ -6524,7 +6490,7 @@ impl<'db> Type<'db> {
}
fn derived(&self, ty: Ty<'db>) -> Self {
- Type { env: self.env, ty }
+ Type { owner: self.owner, ty: EarlyBinder::bind(ty) }
}
/// Visits every type, including generic arguments, in this type. `callback` is called with type
@@ -6532,7 +6498,7 @@ impl<'db> Type<'db> {
pub fn walk(&self, db: &'db dyn HirDatabase, callback: impl FnMut(Type<'db>)) {
struct Visitor<'db, F> {
db: &'db dyn HirDatabase,
- env: ParamEnvAndCrate<'db>,
+ owner: TypeOwnerId,
callback: F,
visited: FxHashSet<Ty<'db>>,
}
@@ -6547,7 +6513,7 @@ impl<'db> Type<'db> {
return;
}
- (self.callback)(Type { env: self.env, ty });
+ (self.callback)(Type { owner: self.owner, ty: EarlyBinder::bind(ty) });
if let Some(bounds) = ty.impl_trait_bounds(self.db) {
bounds.visit_with(self);
@@ -6557,17 +6523,23 @@ impl<'db> Type<'db> {
}
}
- let mut visitor = Visitor { db, env: self.env, callback, visited: FxHashSet::default() };
- self.ty.visit_with(&mut visitor);
+ let mut visitor =
+ Visitor { db, owner: self.owner, callback, visited: FxHashSet::default() };
+ self.ty.skip_binder().visit_with(&mut visitor);
}
/// Check if type unifies with another type.
///
/// Note that we consider placeholder types to unify with everything.
/// For example `Option<T>` and `Option<U>` unify although there is unresolved goal `T = U`.
pub fn could_unify_with(&self, db: &'db dyn HirDatabase, other: &Type<'db>) -> bool {
+ self.owner.must_unify(other.owner);
+ let env = self.param_env(db);
let interner = DbInterner::new_no_crate(db);
- let tys = hir_ty::replace_errors_with_variables(interner, &(self.ty, other.ty));
- hir_ty::could_unify(db, self.env, &tys)
+ let tys = hir_ty::replace_errors_with_variables(
+ interner,
+ &(self.ty.skip_binder(), other.ty.skip_binder()),
+ );
+ hir_ty::could_unify(db, env, &tys)
}
/// Check if type unifies with another type eagerly making sure there are no unresolved goals.
@@ -6575,19 +6547,29 @@ impl<'db> Type<'db> {
/// This means that placeholder types are not considered to unify if there are any bounds set on
/// them. For example `Option<T>` and `Option<U>` do not unify as we cannot show that `T = U`
pub fn could_unify_with_deeply(&self, db: &'db dyn HirDatabase, other: &Type<'db>) -> bool {
+ self.owner.must_unify(other.owner);
+ let env = self.param_env(db);
let interner = DbInterner::new_no_crate(db);
- let tys = hir_ty::replace_errors_with_variables(interner, &(self.ty, other.ty));
- hir_ty::could_unify_deeply(db, self.env, &tys)
+ let tys = hir_ty::replace_errors_with_variables(
+ interner,
+ &(self.ty.skip_binder(), other.ty.skip_binder()),
+ );
+ hir_ty::could_unify_deeply(db, env, &tys)
}
pub fn could_coerce_to(&self, db: &'db dyn HirDatabase, to: &Type<'db>) -> bool {
+ self.owner.must_unify(to.owner);
+ let env = self.param_env(db);
let interner = DbInterner::new_no_crate(db);
- let tys = hir_ty::replace_errors_with_variables(interner, &(self.ty, to.ty));
- hir_ty::could_coerce(db, self.env, &tys)
+ let tys = hir_ty::replace_errors_with_variables(
+ interner,
+ &(self.ty.skip_binder(), to.ty.skip_binder()),
+ );
+ hir_ty::could_coerce(db, env, &tys)
}
pub fn as_type_param(&self, _db: &'db dyn HirDatabase) -> Option<TypeParam> {
- match self.ty.kind() {
+ match self.ty.skip_binder().kind() {
TyKind::Param(param) => Some(TypeParam { id: param.id }),
_ => None,
}
@@ -6595,60 +6577,23 @@ impl<'db> Type<'db> {
/// Returns unique `GenericParam`s contained in this type.
pub fn generic_params(&self, db: &'db dyn HirDatabase) -> FxHashSet<GenericParam> {
- hir_ty::collect_params(&self.ty)
+ hir_ty::collect_params(&self.ty.skip_binder())
.into_iter()
.map(|id| TypeOrConstParam { id }.split(db).either_into())
.collect()
}
pub fn layout(&self, db: &'db dyn HirDatabase) -> Result<Layout<'db>, LayoutError> {
- db.layout_of_ty(self.ty.store(), self.env.store())
- .map(|layout| Layout(layout, db.target_data_layout(self.env.krate).unwrap()))
+ let env = self.param_env(db);
+ db.layout_of_ty(self.ty.skip_binder().store(), env.store())
+ .map(|layout| Layout(layout, db.target_data_layout(env.krate).unwrap()))
}
pub fn drop_glue(&self, db: &'db dyn HirDatabase) -> DropGlue {
- let interner = DbInterner::new_with(db, self.env.krate);
+ let env = self.param_env(db);
+ let interner = DbInterner::new_with(db, env.krate);
let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);
- hir_ty::drop::has_drop_glue(&infcx, self.ty, self.env.param_env)
- }
-}
-
-#[derive(Clone, PartialEq, Eq, Debug, Hash)]
-pub struct TypeNs<'db> {
- env: ParamEnvAndCrate<'db>,
- ty: Ty<'db>,
-}
-
-impl<'db> TypeNs<'db> {
- fn new(db: &'db dyn HirDatabase, lexical_env: impl HasResolver, ty: Ty<'db>) -> Self {
- let resolver = lexical_env.resolver(db);
- let environment = param_env_from_resolver(db, &resolver);
- TypeNs { env: environment, ty }
- }
-
- pub fn to_type(&self, _db: &'db dyn HirDatabase) -> Type<'db> {
- Type { env: self.env, ty: self.ty }
- }
-
- // FIXME: Find better API that also handles const generics
- pub fn impls_trait(&self, infcx: InferCtxt<'db>, trait_: Trait, args: &[TypeNs<'db>]) -> bool {
- let args = GenericArgs::new_from_iter(
- infcx.interner,
- [self.ty].into_iter().chain(args.iter().map(|t| t.ty)).map(GenericArg::from),
- );
- let trait_ref =
- hir_ty::next_solver::TraitRef::new_from_args(infcx.interner, trait_.id.into(), args);
- let obligation = hir_ty::next_solver::infer::traits::Obligation::new(
- infcx.interner,
- hir_ty::next_solver::infer::traits::ObligationCause::dummy(),
- self.env.param_env,
- trait_ref,
- );
- infcx.predicate_must_hold_modulo_regions(&obligation)
- }
-
- pub fn is_bool(&self) -> bool {
- matches!(self.ty.kind(), rustc_type_ir::TyKind::Bool)
+ hir_ty::drop::has_drop_glue(&infcx, self.ty.skip_binder(), env.param_env)
}
}
@@ -6713,12 +6658,16 @@ impl<'db> Callable<'db> {
Callee::Def(CallableDefId::EnumVariantId(it)) => {
CallableKind::TupleEnumVariant(it.into())
}
- Callee::Closure(id, subst) => {
- CallableKind::Closure(Closure { id: AnyClosureId::ClosureId(id), subst })
- }
- Callee::CoroutineClosure(id, subst) => {
- CallableKind::Closure(Closure { id: AnyClosureId::CoroutineClosureId(id), subst })
- }
+ Callee::Closure(id, subst) => CallableKind::Closure(Closure {
+ id: AnyClosureId::ClosureId(id),
+ subst,
+ owner: self.ty.owner,
+ }),
+ Callee::CoroutineClosure(id, subst) => CallableKind::Closure(Closure {
+ id: AnyClosureId::CoroutineClosureId(id),
+ subst,
+ owner: self.ty.owner,
+ }),
Callee::FnPtr => CallableKind::FnPtr,
Callee::FnImpl(fn_) => CallableKind::FnImpl(fn_.into()),
}
@@ -6859,7 +6808,7 @@ impl<'db> Layout<'db> {
reverse_index
.into_iter()
.flatten()
- .chain(std::iter::once((0, self.0.size.bytes())))
+ .chain(iter::once((0, self.0.size.bytes())))
.tuple_windows()
.filter_map(|((i, start), (_, end))| {
let size = field_size(i)?;
@@ -7017,7 +6966,7 @@ pub enum PredicatePolarity {
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TraitPredicate<'db> {
inner: hir_ty::next_solver::TraitPredicate<'db>,
- env: ParamEnvAndCrate<'db>,
+ owner: TypeOwnerId,
}
impl<'db> TraitPredicate<'db> {
@@ -7029,7 +6978,7 @@ impl<'db> TraitPredicate<'db> {
}
pub fn trait_ref(&self) -> TraitRef<'db> {
- TraitRef { env: self.env, trait_ref: self.inner.trait_ref }
+ TraitRef { owner: self.owner, trait_ref: self.inner.trait_ref }
}
}
@@ -7099,8 +7048,8 @@ impl HasCrate for TypeAlias {
}
impl HasCrate for Type<'_> {
- fn krate(&self, _db: &dyn HirDatabase) -> Crate {
- self.env.krate.into()
+ fn krate(&self, db: &dyn HirDatabase) -> Crate {
+ self.krate(db).into()
}
}
@@ -7419,21 +7368,33 @@ fn as_name_opt(name: Option<impl AsName>) -> Name {
name.map_or_else(Name::missing, |name| name.as_name())
}
+#[track_caller]
fn generic_args_from_tys<'db>(
interner: DbInterner<'db>,
def_id: SolverDefId,
- args: impl IntoIterator<Item = Ty<'db>>,
-) -> GenericArgs<'db> {
+ args: impl IntoIterator<Item: Borrow<Type<'db>>>,
+) -> (GenericArgs<'db>, TypeOwnerId) {
+ let mut owner = None::<TypeOwnerId>;
let mut args = args.into_iter();
- GenericArgs::for_item(interner, def_id, |_, id, _| {
+ let args = GenericArgs::for_item(interner, def_id, |_, id, _| {
if matches!(id, GenericParamId::TypeParamId(_))
&& let Some(arg) = args.next()
{
- arg.into()
+ let arg = arg.borrow();
+
+ match &mut owner {
+ Some(owner) => *owner = owner.must_unify(arg.owner),
+ None => owner = Some(arg.owner),
+ }
+
+ arg.ty.skip_binder().into()
} else {
next_solver::GenericArg::error_from_id(interner, id)
}
- })
+ });
+ let owner =
+ owner.unwrap_or_else(|| TypeOwnerId::NoParams(Type::builtin_type_crate(interner.db())));
+ (args, owner)
}
fn has_non_default_type_params(db: &dyn HirDatabase, generic_def: GenericDefId) -> bool {
@@ -7449,19 +7410,6 @@ fn has_non_default_type_params(db: &dyn HirDatabase, generic_def: GenericDefId)
})
}
-fn param_env_from_resolver<'db>(
- db: &'db dyn HirDatabase,
- resolver: &Resolver<'_>,
-) -> ParamEnvAndCrate<'db> {
- ParamEnvAndCrate {
- param_env: resolver.generic_def().map_or_else(
- || ParamEnv::empty(DbInterner::new_no_crate(db)),
- |generic_def| db.trait_environment(generic_def),
- ),
- krate: resolver.krate(),
- }
-}
-
fn param_env_from_has_crate<'db>(
db: &'db dyn HirDatabase,
id: impl hir_def::HasModule + Into<GenericDefId> + Copy,
@@ -7469,16 +7417,6 @@ fn param_env_from_has_crate<'db>(
ParamEnvAndCrate { param_env: db.trait_environment(id.into()), krate: id.krate(db) }
}
-fn body_param_env_from_has_crate<'db>(
- db: &'db dyn HirDatabase,
- id: impl hir_def::HasModule + Into<ExpressionStoreOwnerId> + Copy,
-) -> ParamEnvAndCrate<'db> {
- ParamEnvAndCrate {
- param_env: db.trait_environment(id.into().generic_def(db)),
- krate: id.krate(db),
- }
-}
-
// FIXME: We probably don't want to expose this.
pub trait MacroCallIdExt {
fn loc(self, db: &dyn HirDatabase) -> &hir_expand::MacroCallLoc;
@@ -7527,6 +7465,3 @@ pub fn struct_tail_raw<'db>(
}
ty
}
-
-pub use hir_ty::next_solver;
-pub use hir_ty::setup_tracing;
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index 562c78809a..a23d045c6f 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -1745,11 +1745,7 @@ impl<'db> SemanticsImpl<'db> {
analyzer.expr_adjustments(expr).map(|it| {
it.iter()
.map(|adjust| {
- let target = Type::new_with_resolver(
- self.db,
- &analyzer.resolver,
- adjust.target.as_ref(),
- );
+ let target = analyzer.ty(adjust.target.as_ref());
let kind = match adjust.kind {
hir_ty::Adjust::NeverToAny => Adjust::NeverToAny,
hir_ty::Adjust::Deref(Some(hir_ty::OverloadedDeref(m))) => {
@@ -1840,10 +1836,10 @@ impl<'db> SemanticsImpl<'db> {
let substs =
hir_ty::next_solver::GenericArgs::for_item(interner, trait_.id.into(), |_, id, _| {
assert!(matches!(id, hir_def::GenericParamId::TypeParamId(_)), "expected a type");
- subst.next().expect("too few subst").ty.into()
+ subst.next().expect("too few subst").ty.skip_binder().into()
});
assert!(subst.next().is_none(), "too many subst");
- Some(match self.db.lookup_impl_method(env.env, func, substs).0 {
+ Some(match self.db.lookup_impl_method(env.param_env(self.db), func, substs).0 {
Either::Left(it) => it.into(),
Either::Right((impl_, method)) => {
Function { id: AnyFunctionId::BuiltinDeriveImplMethod { method, impl_ } }
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index 3afa98365e..f24ec420b5 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -41,8 +41,8 @@ use hir_ty::{
lang_items::lang_items_for_bin_op,
method_resolution::{self, CandidateId},
next_solver::{
- AliasTy, DbInterner, DefaultAny, ErrorGuaranteed, GenericArgs, ParamEnv, Region, Ty,
- TyKind, TypingMode, infer::DbInternerInferExt,
+ AliasTy, DbInterner, DefaultAny, EarlyBinder, ErrorGuaranteed, GenericArgs, ParamEnv,
+ Region, Ty, TyKind, TypingMode, infer::DbInternerInferExt,
},
traits::structurally_normalize_ty,
};
@@ -63,7 +63,7 @@ use syntax::{
use crate::{
Adt, AnyFunctionId, AssocItem, BindingMode, BuiltinAttr, BuiltinType, Callable, Const,
DeriveHelper, EnumVariant, Field, Function, GenericSubstitution, Local, Macro, ModuleDef,
- SemanticsImpl, Static, Struct, ToolModule, Trait, TupleField, Type, TypeAlias,
+ SemanticsImpl, Static, Struct, ToolModule, Trait, TupleField, Type, TypeAlias, TypeOwnerId,
db::HirDatabase,
semantics::{PathResolution, PathResolutionPerNs},
};
@@ -75,6 +75,7 @@ pub(crate) struct SourceAnalyzer<'db> {
pub(crate) file_id: HirFileId,
pub(crate) resolver: Resolver<'db>,
pub(crate) body_or_sig: Option<BodyOrSig<'db>>,
+ pub(crate) type_owner: TypeOwnerId,
pub(crate) infer_body: Option<InferBodyId>,
}
@@ -148,6 +149,7 @@ impl<'db> SourceAnalyzer<'db> {
resolver,
body_or_sig: Some(BodyOrSig::Body { def, body, source_map, infer }),
file_id,
+ type_owner: def.generic_def(db).into(),
infer_body: Some(def.into()),
}
}
@@ -212,6 +214,7 @@ impl<'db> SourceAnalyzer<'db> {
resolver,
body_or_sig: Some(BodyOrSig::Sig { def, store, source_map, generics, infer }),
file_id,
+ type_owner: def.into(),
infer_body,
}
}
@@ -261,6 +264,7 @@ impl<'db> SourceAnalyzer<'db> {
infer,
}),
file_id,
+ type_owner: GenericDefId::from(def.adt_id(db)).into(),
infer_body,
}
}
@@ -269,7 +273,16 @@ impl<'db> SourceAnalyzer<'db> {
resolver: Resolver<'db>,
node: InFile<&SyntaxNode>,
) -> SourceAnalyzer<'db> {
- SourceAnalyzer { resolver, body_or_sig: None, file_id: node.file_id, infer_body: None }
+ SourceAnalyzer {
+ type_owner: resolver
+ .generic_def()
+ .map(Into::into)
+ .unwrap_or_else(|| TypeOwnerId::NoParams(resolver.krate())),
+ resolver,
+ body_or_sig: None,
+ file_id: node.file_id,
+ infer_body: None,
+ }
}
fn owner(&self) -> Option<ExpressionStoreOwnerId> {
@@ -288,6 +301,10 @@ impl<'db> SourceAnalyzer<'db> {
})
}
+ pub(crate) fn ty(&self, ty: Ty<'db>) -> Type<'db> {
+ Type { owner: self.type_owner, ty: EarlyBinder::bind(ty) }
+ }
+
pub(crate) fn def(
&self,
) -> Option<(
@@ -426,12 +443,12 @@ impl<'db> SourceAnalyzer<'db> {
}
}
- Some(Type::new_with_resolver(db, &self.resolver, ty))
+ Some(self.ty(ty))
}
pub(crate) fn type_of_expr(
&self,
- db: &'db dyn HirDatabase,
+ _db: &'db dyn HirDatabase,
expr: &ast::Expr,
) -> Option<(Type<'db>, Option<Type<'db>>)> {
let expr_id = self.expr_id(expr.clone())?;
@@ -441,13 +458,13 @@ impl<'db> SourceAnalyzer<'db> {
.and_then(|expr_id| infer.expr_adjustment(expr_id))
.and_then(|adjusts| adjusts.last().map(|adjust| adjust.target.as_ref()));
let ty = infer.expr_or_pat_ty(expr_id);
- let mk_ty = |ty: Ty<'db>| Type::new_with_resolver(db, &self.resolver, ty);
+ let mk_ty = |ty: Ty<'db>| self.ty(ty);
Some((mk_ty(ty), coerced.map(mk_ty)))
}
pub(crate) fn type_of_pat(
&self,
- db: &'db dyn HirDatabase,
+ _db: &'db dyn HirDatabase,
pat: &ast::Pat,
) -> Option<(Type<'db>, Option<Type<'db>>)> {
let expr_or_pat_id = self.pat_id(pat)?;
@@ -464,25 +481,25 @@ impl<'db> SourceAnalyzer<'db> {
};
let ty = infer.expr_or_pat_ty(expr_or_pat_id);
- let mk_ty = |ty: Ty<'db>| Type::new_with_resolver(db, &self.resolver, ty);
+ let mk_ty = |ty: Ty<'db>| self.ty(ty);
Some((mk_ty(ty), coerced.map(mk_ty)))
}
pub(crate) fn type_of_binding_in_pat(
&self,
- db: &'db dyn HirDatabase,
+ _db: &'db dyn HirDatabase,
pat: &ast::IdentPat,
) -> Option<Type<'db>> {
let binding_id = self.binding_id_of_pat(pat)?;
let infer = self.infer()?;
let ty = infer.binding_ty(binding_id);
- let mk_ty = |ty: Ty<'db>| Type::new_with_resolver(db, &self.resolver, ty);
+ let mk_ty = |ty: Ty<'db>| self.ty(ty);
Some(mk_ty(ty))
}
pub(crate) fn type_of_self(
&self,
- db: &'db dyn HirDatabase,
+ _db: &'db dyn HirDatabase,
_param: &ast::SelfParam,
) -> Option<Type<'db>> {
let binding = match self.body_or_sig.as_ref()? {
@@ -490,7 +507,7 @@ impl<'db> SourceAnalyzer<'db> {
BodyOrSig::Body { body, .. } => body.self_param()?,
};
let ty = self.infer()?.binding_ty(binding);
- Some(Type::new_with_resolver(db, &self.resolver, ty))
+ Some(self.ty(ty))
}
pub(crate) fn binding_mode_of_pat(
@@ -512,7 +529,7 @@ impl<'db> SourceAnalyzer<'db> {
}
pub(crate) fn pattern_adjustments(
&self,
- db: &'db dyn HirDatabase,
+ _db: &'db dyn HirDatabase,
pat: &ast::Pat,
) -> Option<SmallVec<[Type<'db>; 1]>> {
let pat_id = self.pat_id(pat)?;
@@ -521,7 +538,7 @@ impl<'db> SourceAnalyzer<'db> {
infer
.pat_adjustment(pat_id.as_pat()?)?
.iter()
- .map(|adjust| Type::new_with_resolver(db, &self.resolver, adjust.source.as_ref()))
+ .map(|adjust| self.ty(adjust.source.as_ref()))
.collect(),
)
}
@@ -535,7 +552,7 @@ impl<'db> SourceAnalyzer<'db> {
let (func, args) = self.infer()?.method_resolution(expr_id)?;
let interner = DbInterner::new_no_crate(db);
let ty = db.value_ty(func.into())?.instantiate(interner, args).skip_norm_wip();
- let ty = Type::new_with_resolver(db, &self.resolver, ty);
+ let ty = self.ty(ty);
let mut res = ty.as_callable(db)?;
res.is_bound_method = true;
Some(res)
@@ -565,7 +582,7 @@ impl<'db> SourceAnalyzer<'db> {
self.resolve_impl_method_or_trait_def_with_subst(db, f_in_trait, substs);
Some((
Either::Left(fn_),
- GenericSubstitution::new_from_fn(fn_, subst, self.trait_environment(db)),
+ GenericSubstitution::new_from_fn(fn_, subst, self.type_owner),
))
}
None => {
@@ -600,12 +617,12 @@ impl<'db> SourceAnalyzer<'db> {
&self,
field_expr: ExprId,
infer: &InferenceResult,
- db: &'db dyn HirDatabase,
+ _db: &'db dyn HirDatabase,
) -> Option<GenericSubstitution<'db>> {
let body = self.store()?;
if let Expr::Field { expr: object_expr, name: _ } = body[field_expr] {
let (adt, subst) = infer.type_of_expr_with_adjust(object_expr)?.as_adt()?;
- return Some(GenericSubstitution::new(adt.into(), subst, self.trait_environment(db)));
+ return Some(GenericSubstitution::new(adt.into(), subst, self.type_owner));
}
None
}
@@ -636,10 +653,7 @@ impl<'db> SourceAnalyzer<'db> {
},
None => inference_result.method_resolution(expr_id).map(|(f, substs)| {
let (f, subst) = self.resolve_impl_method_or_trait_def_with_subst(db, f, substs);
- (
- Either::Right(f),
- GenericSubstitution::new_from_fn(f, subst, self.trait_environment(db)),
- )
+ (Either::Right(f), GenericSubstitution::new_from_fn(f, subst, self.type_owner))
}),
}
}
@@ -729,7 +743,7 @@ impl<'db> SourceAnalyzer<'db> {
.map(Trait::from);
if let Some(into_future_trait) = into_future_trait {
- let type_ = Type::new_with_resolver(db, &self.resolver, ty);
+ let type_ = self.ty(ty);
if type_.impls_trait(db, into_future_trait, &[]) {
let items = into_future_trait.items(db);
let into_future_type = items.into_iter().find_map(|item| match item {
@@ -741,7 +755,7 @@ impl<'db> SourceAnalyzer<'db> {
_ => None,
})?;
let future_trait = type_.normalize_trait_assoc_type(db, &[], into_future_type)?;
- ty = future_trait.ty;
+ ty = future_trait.ty.skip_binder();
}
}
@@ -890,8 +904,8 @@ impl<'db> SourceAnalyzer<'db> {
Some((
field.into(),
local,
- Type::new_with_resolver(db, &self.resolver, field_ty),
- GenericSubstitution::new(adt.into(), subst, self.trait_environment(db)),
+ self.ty(field_ty),
+ GenericSubstitution::new(adt.into(), subst, self.type_owner),
))
}
@@ -914,8 +928,8 @@ impl<'db> SourceAnalyzer<'db> {
.skip_norm_wip();
Some((
field.into(),
- Type::new_with_resolver(db, &self.resolver, field_ty),
- GenericSubstitution::new(adt.into(), subst, self.trait_environment(db)),
+ self.ty(field_ty),
+ GenericSubstitution::new(adt.into(), subst, self.type_owner),
))
}
@@ -970,15 +984,15 @@ impl<'db> SourceAnalyzer<'db> {
let container = offset_of_expr.ty()?;
let container = self.type_of_type(db, &container)?;
- let trait_env = container.env;
+ let env = self.trait_environment(db);
- let interner = DbInterner::new_with(db, trait_env.krate);
+ let interner = DbInterner::new_with(db, env.krate);
let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);
- let mut container = Either::Right(container.ty);
+ let mut container = Either::Right(container.ty.skip_binder());
for field_name in offset_of_expr.fields() {
if let Either::Right(container) = &mut container {
- *container = structurally_normalize_ty(&infcx, *container, trait_env.param_env);
+ *container = structurally_normalize_ty(&infcx, *container, env.param_env);
}
let handle_variants =
|variant: VariantId, subst: GenericArgs<'db>, container: &mut _| {
@@ -1025,7 +1039,10 @@ impl<'db> SourceAnalyzer<'db> {
};
if field_name.syntax().text_range() == name_ref.syntax().text_range() {
- return Some((field_def, GenericSubstitution::new(generic_def, subst, trait_env)));
+ return Some((
+ field_def,
+ GenericSubstitution::new(generic_def, subst, self.type_owner),
+ ));
}
}
never!("the `NameRef` is a child of the `OffsetOfExpr`, we should've visited it");
@@ -1053,7 +1070,7 @@ impl<'db> SourceAnalyzer<'db> {
let subst = GenericSubstitution::new(
f_in_trait.into(),
subs,
- self.trait_environment(db),
+ self.type_owner,
);
(AssocItem::Function(f_in_trait.into()), Some(subst))
}
@@ -1066,14 +1083,14 @@ impl<'db> SourceAnalyzer<'db> {
let subst = GenericSubstitution::new_from_fn(
fn_,
subst,
- self.trait_environment(db),
+ self.type_owner,
);
(AssocItem::Function(fn_), subst)
} else {
let subst = GenericSubstitution::new(
f_in_trait.into(),
subs,
- self.trait_environment(db),
+ self.type_owner,
);
(AssocItem::Function(f_in_trait.into()), Some(subst))
}
@@ -1083,11 +1100,8 @@ impl<'db> SourceAnalyzer<'db> {
CandidateId::ConstId(const_id) => {
let (konst, subst) =
self.resolve_impl_const_or_trait_def_with_subst(db, const_id, subs);
- let subst = GenericSubstitution::new(
- konst.into(),
- subst,
- self.trait_environment(db),
- );
+ let subst =
+ GenericSubstitution::new(konst.into(), subst, self.type_owner);
(AssocItem::Const(konst.into()), Some(subst))
}
};
@@ -1111,20 +1125,13 @@ impl<'db> SourceAnalyzer<'db> {
CandidateId::ConstId(const_id) => {
let (konst, subst) =
self.resolve_impl_const_or_trait_def_with_subst(db, const_id, subs);
- let subst = GenericSubstitution::new(
- konst.into(),
- subst,
- self.trait_environment(db),
- );
+ let subst =
+ GenericSubstitution::new(konst.into(), subst, self.type_owner);
(AssocItemId::from(konst), subst)
}
CandidateId::FunctionId(function_id) => (
function_id.into(),
- GenericSubstitution::new(
- function_id.into(),
- subs,
- self.trait_environment(db),
- ),
+ GenericSubstitution::new(function_id.into(), subs, self.type_owner),
),
};
return Some((PathResolution::Def(AssocItem::from(assoc).into()), Some(subst)));
@@ -1328,12 +1335,11 @@ impl<'db> SourceAnalyzer<'db> {
} else {
return None;
};
- let env = self.trait_environment(db);
let (subst, expected_resolution) = match ty.kind() {
TyKind::Adt(adt_def, subst) => {
let adt_id = adt_def.def_id();
(
- GenericSubstitution::new(adt_id.into(), subst, env),
+ GenericSubstitution::new(adt_id.into(), subst, self.type_owner),
PathResolution::Def(ModuleDef::Adt(adt_id.into())),
)
}
@@ -1344,7 +1350,7 @@ impl<'db> SourceAnalyzer<'db> {
}) => {
let assoc_id = def_id.0;
(
- GenericSubstitution::new(assoc_id.into(), args, env),
+ GenericSubstitution::new(assoc_id.into(), args, self.type_owner),
PathResolution::Def(ModuleDef::TypeAlias(assoc_id.into())),
)
}
@@ -1355,7 +1361,7 @@ impl<'db> SourceAnalyzer<'db> {
CallableDefId::EnumVariantId(_) => return None,
};
(
- GenericSubstitution::new(generic_def_id, subst, env),
+ GenericSubstitution::new(generic_def_id, subst, self.type_owner),
PathResolution::Def(ModuleDefId::from(fn_id.0).into()),
)
}
@@ -1474,7 +1480,7 @@ impl<'db> SourceAnalyzer<'db> {
.map(|local_id| {
let field = FieldId { parent: variant, local_id };
let ty = field_types[local_id].get().instantiate(interner, substs).skip_norm_wip();
- (field.into(), Type::new_with_resolver_inner(db, &self.resolver, ty))
+ (field.into(), self.ty(ty))
})
.collect()
}
diff --git a/crates/hir/src/term_search/expr.rs b/crates/hir/src/term_search/expr.rs
index e3d0121e49..a824c8bdca 100644
--- a/crates/hir/src/term_search/expr.rs
+++ b/crates/hir/src/term_search/expr.rs
@@ -310,21 +310,18 @@ impl<'db> Expr<'db> {
Expr::Local(it) => it.ty(db),
Expr::ConstParam(it) => it.ty(db),
Expr::FamousType { ty, .. } => ty.clone(),
- Expr::Function { func, generics, .. } => {
- func.ret_type_with_args(db, generics.iter().cloned())
- }
- Expr::Method { func, generics, target, .. } => func.ret_type_with_args(
- db,
- target.ty(db).type_arguments().chain(generics.iter().cloned()),
- ),
+ Expr::Function { func, generics, .. } => func.ret_type(db).instantiate(generics),
+ Expr::Method { func, generics, target, .. } => func
+ .ret_type(db)
+ .instantiate(target.ty(db).type_arguments().chain(generics.iter().cloned())),
Expr::Variant { variant, generics, .. } => {
- Adt::from(variant.parent_enum(db)).ty_with_args(db, generics.iter().cloned())
+ Adt::from(variant.parent_enum(db)).ty(db).instantiate(generics)
}
Expr::Struct { strukt, generics, .. } => {
- Adt::from(*strukt).ty_with_args(db, generics.iter().cloned())
+ Adt::from(*strukt).ty(db).instantiate(generics)
}
Expr::Tuple { ty, .. } => ty.clone(),
- Expr::Field { expr, field } => field.ty_with_args(db, expr.ty(db).type_arguments()),
+ Expr::Field { expr, field } => field.ty(db).instantiate(expr.ty(db).type_arguments()),
Expr::Reference(it) => it.ty(db),
Expr::Many(ty) => ty.clone(),
}
diff --git a/crates/hir/src/term_search/tactics.rs b/crates/hir/src/term_search/tactics.rs
index 67b6fd64c1..2b7f7da3bf 100644
--- a/crates/hir/src/term_search/tactics.rs
+++ b/crates/hir/src/term_search/tactics.rs
@@ -10,18 +10,13 @@
use std::iter;
-use hir_ty::{
- db::HirDatabase,
- mir::BorrowKind,
- next_solver::{DbInterner, Ty},
-};
+use hir_ty::{db::HirDatabase, mir::BorrowKind};
use itertools::Itertools;
use rustc_hash::FxHashSet;
-use rustc_type_ir::inherent::Ty as _;
use crate::{
- Adt, AssocItem, GenericDef, GenericParam, HasAttrs, HasVisibility, Impl, ModuleDef, ScopeDef,
- Type, TypeParam, term_search::Expr,
+ Adt, AssocItem, BuiltinType, GenericDef, GenericParam, HasAttrs, HasVisibility, Impl,
+ ModuleDef, ScopeDef, Type, TypeParam, term_search::Expr,
};
use super::{LookupTable, NewTypesKey, TermSearchCtx};
@@ -87,7 +82,7 @@ pub(super) fn trivial<'a, 'lt, 'db, DB: HirDatabase>(
return None;
}
- ty.could_unify_with_deeply(db, &ctx.goal).then_some(expr)
+ ty.instantiate_with_errors().could_unify_with_deeply(db, &ctx.goal).then_some(expr)
})
}
@@ -137,7 +132,7 @@ pub(super) fn assoc_const<'a, 'lt, 'db, DB: HirDatabase>(
lookup.insert(ty.clone(), std::iter::once(expr.clone()));
- ty.could_unify_with_deeply(db, &ctx.goal).then_some(expr)
+ ty.instantiate_with_errors().could_unify_with_deeply(db, &ctx.goal).then_some(expr)
})
}
@@ -202,7 +197,9 @@ pub(super) fn data_constructor<'a, 'lt, 'db, DB: HirDatabase>(
// Early exit if some param cannot be filled from lookup
let param_exprs: Vec<Vec<Expr<'_>>> = fields
.into_iter()
- .map(|field| lookup.find(db, &field.ty_with_args(db, generics.iter().cloned())))
+ .map(|field| {
+ lookup.find(db, &field.ty(db).instantiate(generics.iter().cloned()))
+ })
.collect::<Option<_>>()?;
// Note that we need special case for 0 param constructors because of multi cartesian
@@ -252,7 +249,7 @@ pub(super) fn data_constructor<'a, 'lt, 'db, DB: HirDatabase>(
.fields(db)
.into_iter()
.map(|field| {
- lookup.find(db, &field.ty_with_args(db, generics.iter().cloned()))
+ lookup.find(db, &field.ty(db).instantiate(generics.iter().cloned()))
})
.collect::<Option<_>>()?;
@@ -285,7 +282,9 @@ pub(super) fn data_constructor<'a, 'lt, 'db, DB: HirDatabase>(
}
Adt::Union(_) => None,
})
- .filter_map(|(ty, exprs)| ty.could_unify_with_deeply(db, &ctx.goal).then_some(exprs))
+ .filter_map(|(ty, exprs)| {
+ ty.instantiate_with_errors().could_unify_with_deeply(db, &ctx.goal).then_some(exprs)
+ })
.flatten()
}
@@ -364,7 +363,7 @@ pub(super) fn free_function<'a, 'lt, 'db, DB: HirDatabase>(
})
.collect::<Option<_>>()?;
- let ret_ty = it.ret_type_with_args(db, generics.iter().cloned());
+ let ret_ty = it.ret_type(db).instantiate(generics.iter().cloned());
// Filter out private and unsafe functions
if !it.is_visible_from(db, module)
|| it.is_unsafe_to_call(
@@ -381,10 +380,10 @@ pub(super) fn free_function<'a, 'lt, 'db, DB: HirDatabase>(
// Early exit if some param cannot be filled from lookup
let param_exprs: Vec<Vec<Expr<'_>>> = it
- .params_without_self_with_args(db, generics.iter().cloned())
+ .params_without_self(db)
.into_iter()
.map(|field| {
- let ty = field.ty();
+ let ty = &field.ty().instantiate(&generics);
match ty.is_mutable_reference() {
true => None,
false => lookup.find_autoref(db, ty),
@@ -418,7 +417,9 @@ pub(super) fn free_function<'a, 'lt, 'db, DB: HirDatabase>(
_ => None,
})
.flatten()
- .filter_map(|(ty, exprs)| ty.could_unify_with_deeply(db, &ctx.goal).then_some(exprs))
+ .filter_map(|(ty, exprs)| {
+ ty.instantiate_with_errors().could_unify_with_deeply(db, &ctx.goal).then_some(exprs)
+ })
.flatten()
}
@@ -493,7 +494,7 @@ pub(super) fn impl_method<'a, 'lt, 'db, DB: HirDatabase>(
return None;
}
- let ret_ty = it.ret_type_with_args(db, ty.type_arguments());
+ let ret_ty = it.ret_type(db).instantiate(ty.type_arguments());
// Filter out functions that return references
if ctx.config.enable_borrowcheck && ret_ty.contains_reference(db) || ret_ty.is_raw_ptr()
{
@@ -501,12 +502,12 @@ pub(super) fn impl_method<'a, 'lt, 'db, DB: HirDatabase>(
}
// Ignore functions that do not change the type
- if ty.could_unify_with_deeply(db, &ret_ty) {
+ if ty.instantiate_with_errors().could_unify_with_deeply(db, &ret_ty) {
return None;
}
let self_ty =
- it.self_param(db).expect("No self param").ty_with_args(db, ty.type_arguments());
+ it.self_param(db).expect("No self param").ty(db).instantiate(ty.type_arguments());
// Ignore functions that have different self type
if !self_ty.autoderef(db).any(|s_ty| ty == s_ty) {
@@ -517,9 +518,9 @@ pub(super) fn impl_method<'a, 'lt, 'db, DB: HirDatabase>(
// Early exit if some param cannot be filled from lookup
let param_exprs: Vec<Vec<Expr<'_>>> = it
- .params_without_self_with_args(db, ty.type_arguments())
+ .params_without_self(db)
.into_iter()
- .map(|field| lookup.find_autoref(db, field.ty()))
+ .map(|field| lookup.find_autoref(db, &field.ty().instantiate(ty.type_arguments())))
.collect::<Option<_>>()?;
let generics: Vec<_> = ty.type_arguments().collect();
@@ -540,7 +541,9 @@ pub(super) fn impl_method<'a, 'lt, 'db, DB: HirDatabase>(
Some((ret_ty, fn_exprs))
})
- .filter_map(|(ty, exprs)| ty.could_unify_with_deeply(db, &ctx.goal).then_some(exprs))
+ .filter_map(|(ty, exprs)| {
+ ty.instantiate_with_errors().could_unify_with_deeply(db, &ctx.goal).then_some(exprs)
+ })
.flatten()
}
@@ -581,7 +584,9 @@ pub(super) fn struct_projection<'a, 'lt, 'db, DB: HirDatabase>(
Some((filed_ty, exprs))
})
})
- .filter_map(|(ty, exprs)| ty.could_unify_with_deeply(db, &ctx.goal).then_some(exprs))
+ .filter_map(|(ty, exprs)| {
+ ty.instantiate_with_errors().could_unify_with_deeply(db, &ctx.goal).then_some(exprs)
+ })
.flatten()
}
@@ -604,20 +609,18 @@ pub(super) fn famous_types<'a, 'lt, 'db, DB: HirDatabase>(
lookup: &'lt mut LookupTable<'db>,
) -> impl Iterator<Item = Expr<'db>> + use<'a, 'db, 'lt, DB> {
let db = ctx.sema.db;
- let module = ctx.scope.module();
- let interner = DbInterner::new_no_crate(db);
- let bool_ty = Ty::new_bool(interner);
- let unit_ty = Ty::new_unit(interner);
+ let bool_ty = BuiltinType::bool().ty(db);
+ let unit_ty = Type::new_unit();
[
- Expr::FamousType { ty: Type::new(db, module.id, bool_ty), value: "true" },
- Expr::FamousType { ty: Type::new(db, module.id, bool_ty), value: "false" },
- Expr::FamousType { ty: Type::new(db, module.id, unit_ty), value: "()" },
+ Expr::FamousType { ty: bool_ty.clone(), value: "true" },
+ Expr::FamousType { ty: bool_ty, value: "false" },
+ Expr::FamousType { ty: unit_ty, value: "()" },
]
.into_iter()
.inspect(|exprs| {
lookup.insert(exprs.ty(db), std::iter::once(exprs.clone()));
})
- .filter(|expr| expr.ty(db).could_unify_with_deeply(db, &ctx.goal))
+ .filter(|expr| expr.ty(db).instantiate_with_errors().could_unify_with_deeply(db, &ctx.goal))
}
/// # Impl static method (without self type) tactic
@@ -691,7 +694,7 @@ pub(super) fn impl_static_method<'a, 'lt, 'db, DB: HirDatabase>(
return None;
}
- let ret_ty = it.ret_type_with_args(db, ty.type_arguments());
+ let ret_ty = it.ret_type(db).instantiate(ty.type_arguments());
// Filter out functions that return references
if ctx.config.enable_borrowcheck && ret_ty.contains_reference(db) || ret_ty.is_raw_ptr()
{
@@ -700,9 +703,9 @@ pub(super) fn impl_static_method<'a, 'lt, 'db, DB: HirDatabase>(
// Early exit if some param cannot be filled from lookup
let param_exprs: Vec<Vec<Expr<'_>>> = it
- .params_without_self_with_args(db, ty.type_arguments())
+ .params_without_self(db)
.into_iter()
- .map(|field| lookup.find_autoref(db, field.ty()))
+ .map(|field| lookup.find_autoref(db, &field.ty().instantiate(ty.type_arguments())))
.collect::<Option<_>>()?;
// Note that we need special case for 0 param constructors because of multi cartesian
@@ -722,7 +725,9 @@ pub(super) fn impl_static_method<'a, 'lt, 'db, DB: HirDatabase>(
Some((ret_ty, fn_exprs))
})
- .filter_map(|(ty, exprs)| ty.could_unify_with_deeply(db, &ctx.goal).then_some(exprs))
+ .filter_map(|(ty, exprs)| {
+ ty.instantiate_with_errors().could_unify_with_deeply(db, &ctx.goal).then_some(exprs)
+ })
.flatten()
}
@@ -745,7 +750,6 @@ pub(super) fn make_tuple<'a, 'lt, 'db, DB: HirDatabase>(
should_continue: &'a dyn std::ops::Fn() -> bool,
) -> impl Iterator<Item = Expr<'db>> + use<'a, 'db, 'lt, DB> {
let db = ctx.sema.db;
- let module = ctx.scope.module();
lookup
.types_wishlist()
@@ -774,7 +778,7 @@ pub(super) fn make_tuple<'a, 'lt, 'db, DB: HirDatabase>(
.filter(|_| should_continue())
.map(|params| {
let tys: Vec<Type<'_>> = params.iter().map(|it| it.ty(db)).collect();
- let tuple_ty = Type::new_tuple(db, module.krate(db).into(), &tys);
+ let tuple_ty = Type::new_tuple(db, &tys);
let expr = Expr::Tuple { ty: tuple_ty.clone(), params };
lookup.insert(tuple_ty, iter::once(expr.clone()));
@@ -785,5 +789,10 @@ pub(super) fn make_tuple<'a, 'lt, 'db, DB: HirDatabase>(
Some(exprs)
})
.flatten()
- .filter_map(|expr| expr.ty(db).could_unify_with_deeply(db, &ctx.goal).then_some(expr))
+ .filter_map(|expr| {
+ expr.ty(db)
+ .instantiate_with_errors()
+ .could_unify_with_deeply(db, &ctx.goal)
+ .then_some(expr)
+ })
}
diff --git a/crates/ide-assists/src/handlers/add_missing_match_arms.rs b/crates/ide-assists/src/handlers/add_missing_match_arms.rs
index 667a1d7813..632fe0d72c 100644
--- a/crates/ide-assists/src/handlers/add_missing_match_arms.rs
+++ b/crates/ide-assists/src/handlers/add_missing_match_arms.rs
@@ -80,16 +80,25 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_,
let module = scope.module();
let cfg = ctx.config.find_path_config(ctx.sema.is_nightly(scope.krate()));
let self_ty = if ctx.config.prefer_self_ty {
- scope.expression_store_owner().and_then(|def| {
- match def {
- hir::ExpressionStoreOwner::Body(def_with_body) => {
- def_with_body.as_assoc_item(ctx.db())
+ scope
+ .expression_store_owner()
+ .and_then(|def| {
+ match def {
+ hir::ExpressionStoreOwner::Body(def_with_body) => {
+ def_with_body.as_assoc_item(ctx.db())
+ }
+ hir::ExpressionStoreOwner::Signature(def) => def.as_assoc_item(ctx.db()),
+ hir::ExpressionStoreOwner::VariantFields(_) => None,
+ }?
+ .implementing_ty(ctx.db())
+ })
+ .map(|self_ty| {
+ if let Some(owner) = scope.generic_def() {
+ self_ty.try_rebase_into_owner(ctx.db(), owner).unwrap()
+ } else {
+ self_ty
}
- hir::ExpressionStoreOwner::Signature(def) => def.as_assoc_item(ctx.db()),
- hir::ExpressionStoreOwner::VariantFields(_) => None,
- }?
- .implementing_ty(ctx.db())
- })
+ })
} else {
None
};
@@ -613,7 +622,7 @@ fn build_pat(
hir::StructKind::Tuple => {
let mut name_generator = suggest_name::NameGenerator::default();
let pats = fields.into_iter().map(|f| {
- let name = name_generator.for_type(&f.ty(db).to_type(db), db, edition);
+ let name = name_generator.for_type(&f.ty(db), db, edition);
match name {
Some(name) => make.ident_pat(false, false, make.name(&name)).into(),
None => make.wildcard_pat().into(),
diff --git a/crates/ide-assists/src/handlers/auto_import.rs b/crates/ide-assists/src/handlers/auto_import.rs
index d6e459d044..dd082476d2 100644
--- a/crates/ide-assists/src/handlers/auto_import.rs
+++ b/crates/ide-assists/src/handlers/auto_import.rs
@@ -293,7 +293,7 @@ pub(crate) fn relevance_score(
if let Some(ty) = ty {
if ty == *expected {
score = 100000;
- } else if ty.could_unify_with(ctx.db(), expected) {
+ } else if ty.could_unify_with(ctx.db(), &expected.instantiate_with_errors()) {
score = 10000;
}
}
diff --git a/crates/ide-assists/src/handlers/expand_rest_pattern.rs b/crates/ide-assists/src/handlers/expand_rest_pattern.rs
index 4aa11b4e03..8ae322c020 100644
--- a/crates/ide-assists/src/handlers/expand_rest_pattern.rs
+++ b/crates/ide-assists/src/handlers/expand_rest_pattern.rs
@@ -137,13 +137,7 @@ fn expand_tuple_struct_rest_pattern(
pat.fields()
.take(prefix_count)
.chain(fields[prefix_count..fields.len() - suffix_count].iter().map(|f| {
- gen_unnamed_pat(
- ctx,
- make,
- &mut name_gen,
- &f.ty(ctx.db()).to_type(ctx.sema.db),
- f.index(),
- )
+ gen_unnamed_pat(ctx, make, &mut name_gen, &f.ty(ctx.db()), f.index())
}))
.chain(pat.fields().skip(prefix_count + 1)),
);
diff --git a/crates/ide-assists/src/handlers/generate_from_impl_for_enum.rs b/crates/ide-assists/src/handlers/generate_from_impl_for_enum.rs
index 52df6182ac..1617016172 100644
--- a/crates/ide-assists/src/handlers/generate_from_impl_for_enum.rs
+++ b/crates/ide-assists/src/handlers/generate_from_impl_for_enum.rs
@@ -1,4 +1,3 @@
-use hir::next_solver::{DbInterner, TypingMode};
use ide_db::{RootDatabase, famous_defs::FamousDefs};
use syntax::ast::{self, AstNode, HasName, edit::AstNodeEdit, syntax_factory::SyntaxFactory};
use syntax::syntax_editor::Position;
@@ -159,16 +158,12 @@ fn existing_from_impl(
let variant = sema.to_def(variant)?;
let krate = variant.module(db).krate(db);
let from_trait = FamousDefs(sema, krate).core_convert_From()?;
- let interner = DbInterner::new_with(db, krate.base());
- use hir::next_solver::infer::DbInternerInferExt;
- let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis());
- let variant = variant.instantiate_infer(&infcx);
let enum_ = variant.parent_enum(sema.db);
let field_ty = variant.fields(sema.db).first()?.ty(sema.db);
let enum_ty = enum_.ty(sema.db);
tracing::debug!(?enum_, ?field_ty, ?enum_ty);
- enum_ty.impls_trait(infcx, from_trait, &[field_ty]).then_some(())
+ enum_ty.has_any_impl(db, from_trait, &[field_ty]).then_some(())
}
#[cfg(test)]
diff --git a/crates/ide-assists/src/handlers/generate_single_field_struct_from.rs b/crates/ide-assists/src/handlers/generate_single_field_struct_from.rs
index 4348dfa212..d5629e2e7e 100644
--- a/crates/ide-assists/src/handlers/generate_single_field_struct_from.rs
+++ b/crates/ide-assists/src/handlers/generate_single_field_struct_from.rs
@@ -1,4 +1,3 @@
-use hir::next_solver::{DbInterner, TypingMode};
use hir::{HasCrate, ModuleDef, Semantics};
use ide_db::use_trivial_constructor::use_trivial_constructor_with_factory;
use ide_db::{
@@ -233,15 +232,11 @@ fn from_impl_exists(
let strukt = sema.to_def(strukt)?;
let krate = strukt.krate(db);
let from_trait = FamousDefs(sema, krate).core_convert_From()?;
- let interner = DbInterner::new_with(db, krate.base());
- use hir::next_solver::infer::DbInternerInferExt;
- let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis());
- let strukt = strukt.instantiate_infer(&infcx);
let field_ty = strukt.fields(db).get(main_field_i)?.ty(db);
let struct_ty = strukt.ty(db);
tracing::debug!(?strukt, ?field_ty, ?struct_ty);
- struct_ty.impls_trait(infcx, from_trait, &[field_ty]).then_some(())
+ struct_ty.has_any_impl(db, from_trait, &[field_ty]).then_some(())
}
#[cfg(test)]
diff --git a/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs b/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs
index 22b8861e5f..17ee8597c1 100644
--- a/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs
+++ b/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs
@@ -67,11 +67,14 @@ pub(crate) fn replace_with_lazy_method(
let editor = builder.make_editor(call.syntax());
let add_param = match &*method_name_lazy {
"and_then" => true,
- "or_else" | "unwrap_or_else" => {
- FamousDefs(&ctx.sema, scope.krate()).core_result_Result().is_some_and(
- |result| result.ty(ctx.db()).could_unify_with(ctx.db(), &receiver_ty),
- )
- }
+ "or_else" | "unwrap_or_else" => FamousDefs(&ctx.sema, scope.krate())
+ .core_result_Result()
+ .is_some_and(|result| {
+ result
+ .ty(ctx.db())
+ .instantiate_with_errors()
+ .could_unify_with(ctx.db(), &receiver_ty)
+ }),
_ => false,
};
let closured = into_closure(&last_arg, add_param, editor.make());
diff --git a/crates/ide-assists/src/handlers/wrap_return_type.rs b/crates/ide-assists/src/handlers/wrap_return_type.rs
index f9c103aab8..032cc28858 100644
--- a/crates/ide-assists/src/handlers/wrap_return_type.rs
+++ b/crates/ide-assists/src/handlers/wrap_return_type.rs
@@ -92,7 +92,7 @@ pub(crate) fn wrap_return_type(acc: &mut Assists, ctx: &AssistContext<'_, '_>) -
};
let semantic_ty = ty_constructor
.map(|ty_constructor| {
- hir::Adt::from(ty_constructor).ty_with_args(ctx.db(), [ty.clone()])
+ hir::Adt::from(ty_constructor).ty(ctx.db()).instantiate([ty.clone()])
})
.unwrap_or_else(|| ty.clone());
(ast_ty, semantic_ty)
@@ -256,7 +256,7 @@ fn wrapper_alias<'db>(
);
let new_ty =
- hir::Adt::from(enum_ty).ty_with_args(ctx.db(), [semantic_ret_type.clone()]);
+ hir::Adt::from(enum_ty).ty(ctx.db()).instantiate([semantic_ret_type.clone()]);
Some((make.ty_path(path), new_ty))
})
diff --git a/crates/ide-completion/src/completions.rs b/crates/ide-completion/src/completions.rs
index f3190bbbc8..20048ea97b 100644
--- a/crates/ide-completion/src/completions.rs
+++ b/crates/ide-completion/src/completions.rs
@@ -199,10 +199,10 @@ impl Completions {
item.add_to(self, ctx.db);
}
- pub(crate) fn add_expr(
+ pub(crate) fn add_expr<'db>(
&mut self,
- ctx: &CompletionContext<'_, '_>,
- expr: &hir::term_search::Expr<'_>,
+ ctx: &CompletionContext<'_, 'db>,
+ expr: &hir::term_search::Expr<'db>,
) {
if let Some(item) = render_expr(ctx, expr) {
item.add_to(self, ctx.db)
diff --git a/crates/ide-completion/src/completions/expr.rs b/crates/ide-completion/src/completions/expr.rs
index a2a4cbac21..506662ca72 100644
--- a/crates/ide-completion/src/completions/expr.rs
+++ b/crates/ide-completion/src/completions/expr.rs
@@ -182,6 +182,9 @@ pub(crate) fn complete_expr_path(
}
_ => return,
};
+ // Note: this is not *required* here, we do it to also find methods that require
+ // the type to be instantiated with specific types.
+ let ty = ty.instantiate_with_errors();
if let Some(hir::Adt::Enum(e)) = ty.as_adt() {
cov_mark::hit!(completes_variant_through_alias);
diff --git a/crates/ide-completion/src/completions/record.rs b/crates/ide-completion/src/completions/record.rs
index 1238a91dad..48a5169027 100644
--- a/crates/ide-completion/src/completions/record.rs
+++ b/crates/ide-completion/src/completions/record.rs
@@ -28,11 +28,7 @@ pub(crate) fn complete_record_pattern_fields(
record_pat.record_pat_field_list().and_then(|fl| fl.fields().next()).is_some();
match were_fields_specified {
- false => un
- .fields(ctx.db)
- .into_iter()
- .map(|f| (f, f.ty(ctx.db).to_type(ctx.db)))
- .collect(),
+ false => un.fields(ctx.db).into_iter().map(|f| (f, f.ty(ctx.db))).collect(),
true => return,
}
}
@@ -60,11 +56,7 @@ pub(crate) fn complete_record_expr_fields(
record_expr.record_expr_field_list().and_then(|fl| fl.fields().next()).is_some();
match were_fields_specified {
- false => un
- .fields(ctx.db)
- .into_iter()
- .map(|f| (f, f.ty(ctx.db).to_type(ctx.db)))
- .collect(),
+ false => un.fields(ctx.db).into_iter().map(|f| (f, f.ty(ctx.db))).collect(),
true => return,
}
}
diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs
index e4d599742d..df62829269 100644
--- a/crates/ide-completion/src/context.rs
+++ b/crates/ide-completion/src/context.rs
@@ -729,6 +729,13 @@ impl<'db> CompletionContext<'_, 'db> {
vec![]
}
}
+
+ pub(crate) fn rebase_ty(&self, ty: &hir::Type<'db>) -> hir::Type<'db> {
+ self.scope
+ .generic_def()
+ .and_then(|def| ty.try_rebase_into_owner(self.db, def))
+ .unwrap_or_else(|| ty.instantiate_with_errors())
+ }
}
// CompletionContext construction
diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs
index 4fb8248e78..7aec6f7e8f 100644
--- a/crates/ide-completion/src/context/analysis.rs
+++ b/crates/ide-completion/src/context/analysis.rs
@@ -648,6 +648,16 @@ fn expected_type_and_name<'db>(
_ => ty,
};
+ let mut generic_def = None;
+ let mut rebase_ty = {
+ let node = node.clone();
+ move |ty: hir::Type<'db>| {
+ let def = *generic_def
+ .get_or_insert_with(|| sema.scope(&node).and_then(|scope| scope.generic_def()));
+ def.and_then(|def| ty.try_rebase_into_owner(sema.db, def))
+ .unwrap_or_else(|| ty.instantiate_with_errors())
+ }
+ };
let (ty, name) = loop {
break match_ast! {
match node {
@@ -793,20 +803,20 @@ fn expected_type_and_name<'db>(
ast::TupleStructPat(it) => {
let fields = sema.type_of_pat(&it.clone().into()).map(|ty| ty.original.fields(sema.db));
let nr = it.fields().take_while(|it| it.syntax().text_range().end() <= token.text_range().start()).count();
- let ty = fields.and_then(|fields| Some(fields.get(nr)?.1.clone()));
+ let ty = fields.and_then(|fields| Some(rebase_ty(fields.get(nr)?.1.clone())));
(ty, None)
},
ast::Fn(it) => {
cov_mark::hit!(expected_type_fn_ret_with_leading_char);
cov_mark::hit!(expected_type_fn_ret_without_leading_char);
let def = sema.to_def(&it);
- (def.map(|def| def.ret_type(sema.db)), None)
+ (def.map(|def| rebase_ty(def.ret_type(sema.db))), None)
},
ast::ReturnExpr(it) => {
let fn_ = sema.ancestors_with_macros(it.syntax().clone())
.find_map(Either::<ast::Fn, ast::ClosureExpr>::cast);
let ty = fn_.and_then(|f| match f {
- Either::Left(f) => Some(sema.to_def(&f)?.ret_type(sema.db)),
+ Either::Left(f) => Some(rebase_ty(sema.to_def(&f)?.ret_type(sema.db))),
Either::Right(f) => {
let ty = sema.type_of_expr(&f.into())?.original.as_callable(sema.db)?;
Some(ty.return_type())
diff --git a/crates/ide-completion/src/render.rs b/crates/ide-completion/src/render.rs
index bc71c1da2b..f559aae789 100644
--- a/crates/ide-completion/src/render.rs
+++ b/crates/ide-completion/src/render.rs
@@ -71,7 +71,7 @@ impl<'a, 'db> RenderContext<'a, 'db> {
self.completion.config.snippet_cap
}
- fn db(&self) -> &'a RootDatabase {
+ fn db(&self) -> &'db RootDatabase {
self.completion.db
}
@@ -294,9 +294,9 @@ pub(crate) fn render_resolution_with_import_pat(
Some(render_resolution_pat(ctx, pattern_ctx, local_name, Some(import_edit), resolution))
}
-pub(crate) fn render_expr(
- ctx: &CompletionContext<'_, '_>,
- expr: &hir::term_search::Expr<'_>,
+pub(crate) fn render_expr<'db>(
+ ctx: &CompletionContext<'_, 'db>,
+ expr: &hir::term_search::Expr<'db>,
) -> Option<Builder> {
let mut i = 1;
let mut snippet_formatter = |ty: &hir::Type<'_>| {
@@ -341,7 +341,7 @@ pub(crate) fn render_expr(
"Autogenerated expression by term search",
)));
item.set_relevance(crate::CompletionRelevance {
- type_match: compute_type_match(ctx, &expr.ty(ctx.db)),
+ type_match: compute_type_match(ctx, &ctx.rebase_ty(&expr.ty(ctx.db))),
..Default::default()
});
for trait_ in expr.traits_used(ctx.db) {
@@ -405,8 +405,8 @@ fn render_resolution_pat(
}
}
-fn render_resolution_path(
- ctx: RenderContext<'_, '_>,
+fn render_resolution_path<'db>(
+ ctx: RenderContext<'_, 'db>,
path_ctx: &PathCompletionCtx<'_>,
local_name: hir::Name,
import_to_add: Option<LocatedImport>,
@@ -480,11 +480,12 @@ fn render_resolution_path(
}
adds_ret_type_arrow(completion, path_ctx, &mut item, insert_text.into());
- let mut set_item_relevance = |ty: Type<'_>| {
+ let mut set_item_relevance = |ty: Type<'db>| {
if !ty.is_unknown() {
item.detail(ty.display(db, krate).to_string());
}
+ let ty = completion.rebase_ty(&ty);
item.set_relevance(CompletionRelevance {
type_match: compute_type_match(completion, &ty),
exact_name_match: compute_exact_name_match(completion, &name),
@@ -688,8 +689,8 @@ fn compute_type_match(
// &mut ty -> &ty
if completion_ty.is_mutable_reference()
- && let Some(expected_type) = expected_type.remove_ref()
- && let Some(completion_ty) = completion_ty.remove_ref()
+ && let Some((expected_type, _)) = expected_type.as_reference()
+ && let Some((completion_ty, _)) = completion_ty.as_reference()
{
return match_types(ctx, &expected_type, &completion_ty);
}
@@ -718,12 +719,12 @@ fn compute_ref_match(
completion_ty: &hir::Type<'_>,
) -> Option<CompletionItemRefMode> {
let expected_type = ctx.expected_type.as_ref()?;
- let expected_without_ref = expected_type.remove_ref();
- let completion_without_ref = completion_ty.remove_ref();
+ let expected_without_ref = expected_type.as_reference();
+ let completion_without_ref = completion_ty.as_reference();
if expected_type.could_unify_with(ctx.db, completion_ty) {
return None;
}
- if let Some(expected_without_ref) = &expected_without_ref
+ if let Some((expected_without_ref, _)) = &expected_without_ref
&& (completion_without_ref.is_none()
|| completion_ty.could_unify_with(ctx.db, expected_without_ref))
&& completion_ty
@@ -739,7 +740,7 @@ fn compute_ref_match(
return Some(CompletionItemRefMode::Reference(mutability));
}
- if let Some(completion_without_ref) = completion_without_ref
+ if let Some((completion_without_ref, _)) = completion_without_ref
&& completion_without_ref == *expected_type
&& completion_without_ref.is_copy(ctx.db)
{
@@ -952,9 +953,9 @@ fn main() {
}
"#,
expect![[r#"
- st dep::test_mod_b::Struct {…} dep::test_mod_b::Struct { } [type_could_unify]
- ex dep::test_mod_b::Struct { } [type_could_unify]
- st Struct Struct [type_could_unify+requires_import]
+ st dep::test_mod_b::Struct {…} dep::test_mod_b::Struct { } [type]
+ ex dep::test_mod_b::Struct { } [type]
+ st Struct Struct [type+requires_import]
md dep:: []
fn main() fn() []
fn test(…) fn(Struct) []
@@ -992,7 +993,7 @@ fn main() {
}
"#,
expect![[r#"
- un Union Union [type_could_unify+requires_import]
+ un Union Union [type+requires_import]
md dep:: []
fn main() fn() []
fn test(…) fn(Union) []
@@ -1028,9 +1029,9 @@ fn main() {
}
"#,
expect![[r#"
- ev dep::test_mod_b::Enum::variant dep::test_mod_b::Enum::variant [type_could_unify]
- ex dep::test_mod_b::Enum::variant [type_could_unify]
- en Enum Enum [type_could_unify+requires_import]
+ ev dep::test_mod_b::Enum::variant dep::test_mod_b::Enum::variant [type]
+ ex dep::test_mod_b::Enum::variant [type]
+ en Enum Enum [type+requires_import]
md dep:: []
fn main() fn() []
fn test(…) fn(Enum) []
@@ -1066,10 +1067,10 @@ fn main() {
}
"#,
expect![[r#"
- ev dep::test_mod_b::Enum::Variant dep::test_mod_b::Enum::Variant [type_could_unify]
- ev Variant Variant [type_could_unify+requires_import]
+ ev dep::test_mod_b::Enum::Variant dep::test_mod_b::Enum::Variant [type]
+ ev Variant Variant [type+requires_import]
+ ex dep::test_mod_b::Enum::Variant [type]
ev Variant Variant [requires_import]
- ex dep::test_mod_b::Enum::Variant [type_could_unify]
md dep:: []
fn main() fn() []
fn test(…) fn(Enum) []
@@ -1132,7 +1133,7 @@ fn main() {
}
"#,
expect![[r#"
- ct CONST i32 [type_could_unify+requires_import]
+ ct CONST i32 [type+requires_import]
md dep:: []
fn main() fn() []
fn test(…) fn(i32) []
@@ -1164,7 +1165,7 @@ fn main() {
}
"#,
expect![[r#"
- sc STATIC i32 [type_could_unify+requires_import]
+ sc STATIC i32 [type+requires_import]
md dep:: []
fn main() fn() []
fn test(…) fn(i32) []
@@ -3145,7 +3146,7 @@ fn main() {
st &mut S(…) [type]
lc ssss S<u32> [local]
lc &mut ssss [type+local]
- st S S<{unknown}> []
+ st S S<T> []
fn foo(…) fn(&mut S<T>) []
fn main() fn() []
"#]],
@@ -3168,7 +3169,7 @@ fn main() {
expect![[r#"
ex ssss.0 [type_could_unify]
lc ssss S<{unknown}> [local]
- st S S<{unknown}> []
+ st S S<T> []
md core:: []
fn foo(…) fn(&u32) []
fn main() fn() []
@@ -3916,9 +3917,9 @@ fn foo() {
lc foo Foo<u32> [type+local]
ex Foo::B [type]
ex foo [type]
- en Foo Foo<{unknown}> [type_could_unify]
+ en Foo Foo<T> [type_could_unify]
+ fn baz() fn() -> Foo<T> [type_could_unify]
fn bar() fn() -> Foo<u8> []
- fn baz() fn() -> Foo<T> []
fn foo() fn() []
"#]],
);
@@ -3948,6 +3949,7 @@ fn main() {
&[CompletionItemKind::Snippet, CompletionItemKind::SymbolKind(SymbolKind::Method)],
expect![[r#"
sn not !expr [snippet]
+ me not() fn(self) -> <Self as Not>::Output [type_could_unify+requires_import]
sn box Box::new(expr) []
sn call function(expr) []
sn const const {} []
@@ -3961,7 +3963,6 @@ fn main() {
sn return return expr []
sn unsafe unsafe {} []
sn while while expr {} []
- me not() fn(self) -> <Self as Not>::Output [requires_import]
"#]],
);
}
@@ -4012,7 +4013,7 @@ enum Foo {
en Foo Foo []
st Other Other []
sp Self Foo []
- st Vec<…> Vec<{unknown}> []
+ st Vec<…> Vec<T> []
"#]],
);
}
diff --git a/crates/ide-completion/src/render/function.rs b/crates/ide-completion/src/render/function.rs
index ea228fdd60..4f70a90aff 100644
--- a/crates/ide-completion/src/render/function.rs
+++ b/crates/ide-completion/src/render/function.rs
@@ -76,7 +76,7 @@ fn render(
completion.edition,
);
- let ret_type = func.ret_type(db);
+ let ret_type = ctx.completion.rebase_ty(&func.ret_type(db));
let assoc_item = func.as_assoc_item(db);
let trait_info =
@@ -107,6 +107,7 @@ fn render(
let function = assoc_item
.and_then(|assoc_item| assoc_item.implementing_ty(db))
+ .map(|self_type| ctx.completion.rebase_ty(&self_type))
.map(|self_type| compute_return_type_match(db, &ctx, self_type, &ret_type))
.map(|return_type| CompletionRelevanceFn {
has_params: has_self_param || func.num_params(db) > 0,
@@ -118,7 +119,7 @@ fn render(
type_match: if has_call_parens || complete_call_parens.is_some() {
compute_type_match(completion, &ret_type)
} else {
- compute_type_match(completion, &func.ty(db))
+ compute_type_match(completion, &ctx.completion.rebase_ty(&func.ty(db)))
},
exact_name_match: compute_exact_name_match(completion, &call),
function,
@@ -287,7 +288,7 @@ pub(super) fn add_call_parens<'b>(
}
fn ref_of_param(ctx: &CompletionContext<'_, '_>, arg: &str, ty: &hir::Type<'_>) -> &'static str {
- if let Some(derefed_ty) = ty.remove_ref() {
+ if let Some(derefed_ty) = ty.as_reference_inner() {
for (name, local) in ctx.locals.iter().sorted_by_key(|&(k, _)| k.clone()) {
if name.as_str() == arg {
return if local.ty(ctx.db) == derefed_ty {
diff --git a/crates/ide-completion/src/render/literal.rs b/crates/ide-completion/src/render/literal.rs
index 9e0cec62e6..943ff58219 100644
--- a/crates/ide-completion/src/render/literal.rs
+++ b/crates/ide-completion/src/render/literal.rs
@@ -127,7 +127,7 @@ fn render(
item.set_documentation(thing.docs(db)).set_deprecated(thing.is_deprecated(&ctx));
- let ty = thing.ty(db);
+ let ty = ctx.completion.rebase_ty(&thing.ty(db));
item.set_relevance(CompletionRelevance {
type_match: compute_type_match(ctx.completion, &ty),
// function is a misnomer here, this is more about constructor information
diff --git a/crates/ide-completion/src/render/pattern.rs b/crates/ide-completion/src/render/pattern.rs
index 392ecbc302..7e70aa13d4 100644
--- a/crates/ide-completion/src/render/pattern.rs
+++ b/crates/ide-completion/src/render/pattern.rs
@@ -103,17 +103,18 @@ pub(crate) fn render_variant_pat(
))
}
-fn build_completion(
- ctx: RenderContext<'_, '_>,
+fn build_completion<'db>(
+ ctx: RenderContext<'_, 'db>,
label: SmolStr,
lookup: SmolStr,
pat: String,
def: impl HasDocs,
- adt_ty: hir::Type<'_>,
+ adt_ty: hir::Type<'db>,
// Missing in context of match statement completions
is_variant_missing: bool,
) -> CompletionItem {
let mut relevance = ctx.completion_relevance();
+ let adt_ty = ctx.completion.rebase_ty(&adt_ty);
if is_variant_missing {
relevance.type_match = super::compute_type_match(ctx.completion, &adt_ty);
diff --git a/crates/ide-completion/src/render/variant.rs b/crates/ide-completion/src/render/variant.rs
index f86af6cdcb..8d1b885969 100644
--- a/crates/ide-completion/src/render/variant.rs
+++ b/crates/ide-completion/src/render/variant.rs
@@ -32,7 +32,7 @@ pub(crate) fn render_record_lit(
if let Some(local) = ctx.locals.get(&field_name)
&& local
.ty(ctx.db)
- .could_unify_with_deeply(ctx.db, &field.ty(ctx.db).to_type(ctx.db))
+ .could_unify_with_deeply(ctx.db, &ctx.rebase_ty(&field.ty(ctx.db)))
{
f(&format_args!("{}{tab}", field_name.display(ctx.db, ctx.edition)))
} else {
diff --git a/crates/ide-completion/src/tests/expression.rs b/crates/ide-completion/src/tests/expression.rs
index 4a4b09c658..595c864ae3 100644
--- a/crates/ide-completion/src/tests/expression.rs
+++ b/crates/ide-completion/src/tests/expression.rs
@@ -3120,8 +3120,8 @@ fn bar() {
}
"#,
expect![[r#"
- en Option Option<{unknown}>
- en Result Result<{unknown}, {unknown}>
+ en Option Option<T>
+ en Result Result<T, E>
fn bar() fn()
lc i i32
ma const_format_args!(…) macro_rules! const_format_args
diff --git a/crates/ide-completion/src/tests/predicate.rs b/crates/ide-completion/src/tests/predicate.rs
index 9826a8ed7b..3f3a6f4cf5 100644
--- a/crates/ide-completion/src/tests/predicate.rs
+++ b/crates/ide-completion/src/tests/predicate.rs
@@ -14,7 +14,7 @@ struct Foo<'lt, T, const C: usize> where $0 {}
en Enum Enum
ma makro!(…) macro_rules! makro
md module::
- st Foo<…> Foo<'_, {unknown}, _>
+ st Foo<…> Foo<'lt, T, C>
st Record Record
st Tuple Tuple
st Unit Unit
@@ -91,7 +91,7 @@ struct Foo<'lt, T, const C: usize> where for<'a> $0 {}
en Enum Enum
ma makro!(…) macro_rules! makro
md module::
- st Foo<…> Foo<'_, {unknown}, _>
+ st Foo<…> Foo<'lt, T, C>
st Record Record
st Tuple Tuple
st Unit Unit
diff --git a/crates/ide-completion/src/tests/type_pos.rs b/crates/ide-completion/src/tests/type_pos.rs
index 24080334ae..ad058901c0 100644
--- a/crates/ide-completion/src/tests/type_pos.rs
+++ b/crates/ide-completion/src/tests/type_pos.rs
@@ -15,8 +15,8 @@ struct Foo<'lt, T, const C: usize> {
en Enum Enum
ma makro!(…) macro_rules! makro
md module::
- sp Self Foo<'_, {unknown}, _>
- st Foo<…> Foo<'_, {unknown}, _>
+ sp Self Foo<'lt, T, C>
+ st Foo<…> Foo<'lt, T, C>
st Record Record
st Tuple Tuple
st Unit Unit
@@ -44,8 +44,8 @@ struct Foo<'lt, T, const C: usize>(f$0);
en Enum Enum
ma makro!(…) macro_rules! makro
md module::
- sp Self Foo<'_, {unknown}, _>
- st Foo<…> Foo<'_, {unknown}, _>
+ sp Self Foo<'lt, T, C>
+ st Foo<…> Foo<'lt, T, C>
st Record Record
st Tuple Tuple
st Unit Unit
@@ -409,7 +409,7 @@ const FOO: $0 = Foo(2);
en Enum Enum
ma makro!(…) macro_rules! makro
md module::
- st Foo<…> Foo<{unknown}>
+ st Foo<…> Foo<T>
st Record Record
st Tuple Tuple
st Unit Unit
@@ -438,7 +438,7 @@ static FOO: $0 = Foo(2);
en Enum Enum
ma makro!(…) macro_rules! makro
md module::
- st Foo<…> Foo<{unknown}>
+ st Foo<…> Foo<T>
st Record Record
st Tuple Tuple
st Unit Unit
@@ -629,7 +629,7 @@ fn foo<'lt, T, const C: usize>() {
en Enum Enum
ma makro!(…) macro_rules! makro
md module::
- st Foo<…> Foo<{unknown}>
+ st Foo<…> Foo<T>
st Record Record
st Tuple Tuple
st Unit Unit
diff --git a/crates/ide-db/src/syntax_helpers/suggest_name.rs b/crates/ide-db/src/syntax_helpers/suggest_name.rs
index 76fea5c262..15920595a8 100644
--- a/crates/ide-db/src/syntax_helpers/suggest_name.rs
+++ b/crates/ide-db/src/syntax_helpers/suggest_name.rs
@@ -412,7 +412,7 @@ fn from_type(
edition: Edition,
) -> Option<SmolStr> {
let ty = sema.type_of_expr(expr)?.adjusted();
- let ty = ty.remove_ref().unwrap_or(ty);
+ let ty = ty.strip_reference();
name_of_type(&ty, sema.db, edition)
}
@@ -445,7 +445,7 @@ fn name_of_type<'db>(
return None;
}
name
- } else if let Some(inner_ty) = ty.remove_ref() {
+ } else if let Some((inner_ty, _)) = ty.as_reference() {
return name_of_type(&inner_ty, db, edition);
} else if let Some(inner_ty) = ty.as_slice() {
return Some(sequence_name(Some(&inner_ty), db, edition));
diff --git a/crates/ide-diagnostics/src/handlers/type_mismatch.rs b/crates/ide-diagnostics/src/handlers/type_mismatch.rs
index 08791fecbe..678e45e145 100644
--- a/crates/ide-diagnostics/src/handlers/type_mismatch.rs
+++ b/crates/ide-diagnostics/src/handlers/type_mismatch.rs
@@ -127,7 +127,7 @@ fn add_missing_ok_or_some(
let variant_name = if Some(expected_enum) == core_result { "Ok" } else { "Some" };
let wrapped_actual_ty =
- expected_adt.ty_with_args(ctx.sema.db, std::iter::once(d.actual.clone()));
+ expected_adt.ty(ctx.sema.db).instantiate(std::iter::once(d.actual.clone()));
if !d.expected.could_unify_with(ctx.sema.db, &wrapped_actual_ty) {
return None;
@@ -225,7 +225,7 @@ fn remove_unnecessary_wrapper(
return None;
}
- let inner_type = variant.fields(db).first()?.ty_with_args(db, d.actual.type_arguments());
+ let inner_type = variant.fields(db).first()?.ty(db).instantiate(d.actual.type_arguments());
if !d.expected.could_unify_with(db, &inner_type) {
return None;
}
diff --git a/crates/ide/src/goto_type_definition.rs b/crates/ide/src/goto_type_definition.rs
index ae208fe1b5..ffd144a827 100644
--- a/crates/ide/src/goto_type_definition.rs
+++ b/crates/ide/src/goto_type_definition.rs
@@ -88,7 +88,7 @@ pub(crate) fn goto_type_definition(
ast::Pat(it) => sema.type_of_pat(&it)?.original,
ast::SelfParam(it) => sema.type_of_self(&it)?,
ast::Type(it) => sema.resolve_type(&it)?,
- ast::RecordField(it) => sema.to_def(&it)?.ty(db).to_type(db),
+ ast::RecordField(it) => sema.to_def(&it)?.ty(db),
// can't match on RecordExprField directly as `ast::Expr` will match an iteration too early otherwise
ast::NameRef(it) => {
if let Some(record_field) = ast::RecordExprField::for_name_ref(&it) {
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index df1fcecc99..c3a8e0362f 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -469,7 +469,7 @@ pub(crate) fn hover_for_definition(
Definition::Local(it) => Some(it.ty(db)),
Definition::GenericParam(hir::GenericParam::ConstParam(it)) => Some(it.ty(db)),
Definition::GenericParam(hir::GenericParam::TypeParam(it)) => Some(it.ty(db)),
- Definition::Field(field) => Some(field.ty(db).to_type(db)),
+ Definition::Field(field) => Some(field.ty(db)),
Definition::TupleField(it) => Some(it.ty(db)),
Definition::Function(it) => Some(it.ty(db)),
Definition::Adt(it) => Some(it.ty(db)),
@@ -630,7 +630,7 @@ fn goto_type_action_for_def(
let ty = match def {
Definition::Local(it) => Some(it.ty(db)),
- Definition::Field(field) => Some(field.ty(db).to_type(db)),
+ Definition::Field(field) => Some(field.ty(db)),
Definition::TupleField(field) => Some(field.ty(db)),
Definition::Const(it) => Some(it.ty(db)),
Definition::Static(it) => Some(it.ty(db)),
diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs
index e08bbc5c21..da4f185d75 100644
--- a/crates/ide/src/hover/render.rs
+++ b/crates/ide/src/hover/render.rs
@@ -664,14 +664,14 @@ pub(super) fn definition(
}
let drop_info = match def {
Definition::Field(field) => {
- DropInfo { drop_glue: field.ty(db).to_type(db).drop_glue(db), has_dtor: None }
+ DropInfo { drop_glue: field.ty(db).drop_glue(db), has_dtor: None }
}
Definition::Adt(Adt::Struct(strukt)) => {
- let struct_drop_glue = strukt.ty_params(db).drop_glue(db);
+ let struct_drop_glue = strukt.ty(db).drop_glue(db);
let mut fields_drop_glue = strukt
.fields(db)
.iter()
- .map(|field| field.ty(db).to_type(db).drop_glue(db))
+ .map(|field| field.ty(db).drop_glue(db))
.max()
.unwrap_or(DropGlue::None);
let has_dtor = match (fields_drop_glue, struct_drop_glue) {
@@ -688,10 +688,10 @@ pub(super) fn definition(
// Unions cannot have fields with drop glue.
Definition::Adt(Adt::Union(union)) => DropInfo {
drop_glue: DropGlue::None,
- has_dtor: Some(union.ty_params(db).drop_glue(db) != DropGlue::None),
+ has_dtor: Some(union.ty(db).drop_glue(db) != DropGlue::None),
},
Definition::Adt(Adt::Enum(enum_)) => {
- let enum_drop_glue = enum_.ty_params(db).drop_glue(db);
+ let enum_drop_glue = enum_.ty(db).drop_glue(db);
let fields_drop_glue = enum_
.variants(db)
.iter()
@@ -699,7 +699,7 @@ pub(super) fn definition(
variant
.fields(db)
.iter()
- .map(|field| field.ty(db).to_type(db).drop_glue(db))
+ .map(|field| field.ty(db).drop_glue(db))
.max()
.unwrap_or(DropGlue::None)
})
@@ -714,13 +714,13 @@ pub(super) fn definition(
let fields_drop_glue = variant
.fields(db)
.iter()
- .map(|field| field.ty(db).to_type(db).drop_glue(db))
+ .map(|field| field.ty(db).drop_glue(db))
.max()
.unwrap_or(DropGlue::None);
DropInfo { drop_glue: fields_drop_glue, has_dtor: None }
}
Definition::TypeAlias(type_alias) => {
- DropInfo { drop_glue: type_alias.ty_params(db).drop_glue(db), has_dtor: None }
+ DropInfo { drop_glue: type_alias.ty(db).drop_glue(db), has_dtor: None }
}
Definition::Local(local) => {
DropInfo { drop_glue: local.ty(db).drop_glue(db), has_dtor: None }
diff --git a/crates/ide/src/rename.rs b/crates/ide/src/rename.rs
index b664187932..e220cbdce8 100644
--- a/crates/ide/src/rename.rs
+++ b/crates/ide/src/rename.rs
@@ -522,11 +522,11 @@ fn rename_to_self(
};
let first_param_ty = first_param.ty();
let impl_ty = impl_.self_ty(sema.db);
- let (ty, self_param) = if impl_ty.remove_ref().is_some() {
+ let (ty, self_param) = if impl_ty.is_reference() {
// if the impl is a ref to the type we can just match the `&T` with self directly
(first_param_ty.clone(), "self")
} else {
- first_param_ty.remove_ref().map_or((first_param_ty.clone(), "self"), |ty| {
+ first_param_ty.as_reference_inner().map_or((first_param_ty.clone(), "self"), |ty| {
(ty, if first_param_ty.is_mutable_reference() { "&mut self" } else { "&self" })
})
};
diff --git a/crates/ide/src/signature_help.rs b/crates/ide/src/signature_help.rs
index 7854a14187..0022c1148a 100644
--- a/crates/ide/src/signature_help.rs
+++ b/crates/ide/src/signature_help.rs
@@ -535,7 +535,7 @@ fn signature_help_for_tuple_struct_pat(
pat.syntax(),
token,
pat.fields(),
- fields.into_iter().map(|it| it.ty(db).to_type(db)),
+ fields.into_iter().map(|it| it.ty(db)),
display_target,
))
}
diff --git a/crates/ide/src/view_memory_layout.rs b/crates/ide/src/view_memory_layout.rs
index 1b9df9722b..03bde6f3e5 100644
--- a/crates/ide/src/view_memory_layout.rs
+++ b/crates/ide/src/view_memory_layout.rs
@@ -98,7 +98,7 @@ pub(crate) fn view_memory_layout(
Definition::BuiltinType(it) => it.ty(db),
Definition::SelfType(it) => it.self_ty(db),
Definition::Local(it) => it.ty(db),
- Definition::Field(it) => it.ty(db).to_type(db),
+ Definition::Field(it) => it.ty(db),
Definition::Const(it) => it.ty(db),
Definition::Static(it) => it.ty(db),
_ => return None,
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs
index ec5503fe39..1a036c3b99 100644
--- a/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -14,14 +14,16 @@ use hir::{
Adt, AssocItem, Crate, DefWithBody, FindPathConfig, GenericDef, HasCrate, HasSource,
HirDisplay, ModuleDef, Name, Variant, crate_lang_items,
db::{DefDatabase, ExpandDatabase, HirDatabase},
- next_solver::{DbInterner, GenericArgs},
};
use hir_def::{
DefWithBodyId, ExpressionStoreOwnerId, GenericDefId, SyntheticSyntax,
expr_store::{Body, BodySourceMap, ExpressionStore},
hir::{ExprId, PatId, generics::GenericParams},
};
-use hir_ty::InferenceResult;
+use hir_ty::{
+ InferenceResult,
+ next_solver::{DbInterner, GenericArgs},
+};
use ide::{
Analysis, AnalysisHost, AnnotationConfig, DiagnosticsConfig, Edition, InlayFieldsToResolve,
InlayHintsConfig, LineCol, RaFixtureConfig, RootDatabase,