Unnamed repository; edit this file 'description' to name the repository.
-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,