Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir/src/lib.rs')
| -rw-r--r-- | crates/hir/src/lib.rs | 454 |
1 files changed, 306 insertions, 148 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index a323f97997..f8dacf0fb8 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -20,6 +20,12 @@ #![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] #![recursion_limit = "512"] +#[cfg(feature = "in-rust-tree")] +extern crate rustc_type_ir; + +#[cfg(not(feature = "in-rust-tree"))] +extern crate ra_ap_rustc_type_ir as rustc_type_ir; + mod attrs; mod from_id; mod has_source; @@ -46,7 +52,7 @@ use hir_def::{ CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId, ExternBlockId, ExternCrateId, FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, ItemContainerId, LifetimeParamId, LocalFieldId, Lookup, MacroExpander, MacroId, ModuleId, StaticId, StructId, SyntheticSyntax, - TraitAliasId, TupleId, TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId, + TupleId, TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId, expr_store::{ExpressionStoreDiagnostics, ExpressionStoreSourceMap}, hir::{ BindingAnnotation, BindingId, Expr, ExprId, ExprOrPatId, LabelId, Pat, @@ -54,10 +60,13 @@ use hir_def::{ }, item_tree::ImportAlias, layout::{self, ReprOptions, TargetDataLayout}, - nameres::{self, assoc::TraitItems, diagnostics::DefDiagnostic}, + nameres::{ + assoc::TraitItems, + diagnostics::{DefDiagnostic, DefDiagnosticKind}, + }, per_ns::PerNs, resolver::{HasResolver, Resolver}, - signatures::{ImplFlags, StaticFlags, TraitFlags, VariantFields}, + signatures::{ImplFlags, StaticFlags, StructFlags, TraitFlags, VariantFields}, src::HasSource as _, visibility::visibility_from_ast, }; @@ -67,7 +76,7 @@ use hir_expand::{ }; use hir_ty::{ AliasTy, CallableSig, Canonical, CanonicalVarKinds, Cast, ClosureId, GenericArg, - GenericArgData, Interner, ParamKind, QuantifiedWhereClause, Scalar, Substitution, + GenericArgData, Interner, ParamKind, ProjectionTy, QuantifiedWhereClause, Scalar, Substitution, TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, TyLoweringDiagnostic, ValueTyDefId, WhereClause, all_super_traits, autoderef, check_orphan_rules, consteval::{ConstExt, try_const_usize, unknown_const_as_generic}, @@ -76,11 +85,13 @@ use hir_ty::{ layout::{Layout as TyLayout, RustcEnumVariantIdx, RustcFieldIdx, TagEncoding}, method_resolution, mir::{MutBorrowKind, interpret_mir}, + next_solver::{ + ClauseKind, DbInterner, GenericArgs, infer::InferCtxt, mapping::ChalkToNextSolver, + }, primitive::UintTy, traits::FnTrait, }; use itertools::Itertools; -use nameres::diagnostics::DefDiagnosticKind; use rustc_hash::FxHashSet; use smallvec::SmallVec; use span::{AstIdNode, Edition, FileId}; @@ -103,6 +114,7 @@ pub use crate::{ VisibleTraits, }, }; +use rustc_type_ir::inherent::{IntoKind, SliceLike}; // Be careful with these re-exports. // @@ -117,7 +129,7 @@ pub use { cfg::{CfgAtom, CfgExpr, CfgOptions}, hir_def::{ Complete, - ImportPathConfig, + FindPathConfig, attr::{AttrSourceMap, Attrs, AttrsWithOwner}, find_path::PrefixKind, import_map, @@ -187,6 +199,10 @@ pub struct CrateDependency { } impl Crate { + pub fn base(self) -> base_db::Crate { + self.id + } + pub fn origin(self, db: &dyn HirDatabase) -> CrateOrigin { self.id.data(db).origin.clone() } @@ -320,7 +336,6 @@ pub enum ModuleDef { Const(Const), Static(Static), Trait(Trait), - TraitAlias(TraitAlias), TypeAlias(TypeAlias), BuiltinType(BuiltinType), Macro(Macro), @@ -333,7 +348,6 @@ impl_from!( Const, Static, Trait, - TraitAlias, TypeAlias, BuiltinType, Macro @@ -360,7 +374,6 @@ impl ModuleDef { ModuleDef::Const(it) => Some(it.module(db)), ModuleDef::Static(it) => Some(it.module(db)), ModuleDef::Trait(it) => Some(it.module(db)), - ModuleDef::TraitAlias(it) => Some(it.module(db)), ModuleDef::TypeAlias(it) => Some(it.module(db)), ModuleDef::Macro(it) => Some(it.module(db)), ModuleDef::BuiltinType(_) => None, @@ -389,7 +402,6 @@ impl ModuleDef { ModuleDef::Const(it) => it.name(db)?, ModuleDef::Adt(it) => it.name(db), ModuleDef::Trait(it) => it.name(db), - ModuleDef::TraitAlias(it) => it.name(db), ModuleDef::Function(it) => it.name(db), ModuleDef::Variant(it) => it.name(db), ModuleDef::TypeAlias(it) => it.name(db), @@ -412,7 +424,6 @@ impl ModuleDef { Adt::Union(it) => it.id.into(), }, ModuleDef::Trait(it) => it.id.into(), - ModuleDef::TraitAlias(it) => it.id.into(), ModuleDef::Function(it) => it.id.into(), ModuleDef::TypeAlias(it) => it.id.into(), ModuleDef::Module(it) => it.id.into(), @@ -452,7 +463,6 @@ impl ModuleDef { ModuleDef::Module(_) | ModuleDef::Adt(_) | ModuleDef::Trait(_) - | ModuleDef::TraitAlias(_) | ModuleDef::TypeAlias(_) | ModuleDef::Macro(_) | ModuleDef::BuiltinType(_) => None, @@ -465,7 +475,6 @@ impl ModuleDef { ModuleDef::Function(it) => Some(it.into()), ModuleDef::Adt(it) => Some(it.into()), ModuleDef::Trait(it) => Some(it.into()), - ModuleDef::TraitAlias(it) => Some(it.into()), ModuleDef::TypeAlias(it) => Some(it.into()), ModuleDef::Module(_) | ModuleDef::Variant(_) @@ -485,7 +494,6 @@ impl ModuleDef { ModuleDef::Const(it) => it.attrs(db), ModuleDef::Static(it) => it.attrs(db), ModuleDef::Trait(it) => it.attrs(db), - ModuleDef::TraitAlias(it) => it.attrs(db), ModuleDef::TypeAlias(it) => it.attrs(db), ModuleDef::Macro(it) => it.attrs(db), ModuleDef::BuiltinType(_) => return None, @@ -511,7 +519,6 @@ impl HasVisibility for ModuleDef { ModuleDef::Const(it) => it.visibility(db), ModuleDef::Static(it) => it.visibility(db), ModuleDef::Trait(it) => it.visibility(db), - ModuleDef::TraitAlias(it) => it.visibility(db), ModuleDef::TypeAlias(it) => it.visibility(db), ModuleDef::Variant(it) => it.visibility(db), ModuleDef::Macro(it) => it.visibility(db), @@ -949,7 +956,7 @@ impl Module { self, db: &dyn DefDatabase, item: impl Into<ItemInNs>, - cfg: ImportPathConfig, + cfg: FindPathConfig, ) -> Option<ModPath> { hir_def::find_path::find_path( db, @@ -968,7 +975,7 @@ impl Module { db: &dyn DefDatabase, item: impl Into<ItemInNs>, prefix_kind: PrefixKind, - cfg: ImportPathConfig, + cfg: FindPathConfig, ) -> Option<ModPath> { hir_def::find_path::find_path(db, item.into().into(), self.into(), prefix_kind, true, cfg) } @@ -1247,6 +1254,25 @@ 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 krate = self.inner.krate(db); + let interner = DbInterner::new_with(db, Some(krate.base()), None); + + let var_id = self.inner.parent.into(); + let field = db.field_types_ns(var_id)[self.inner.id]; + let ty = field.instantiate(interner, self.args); + TypeNs::new(db, var_id, ty) + } +} + #[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] pub struct TupleField { pub owner: DefWithBodyId, @@ -1362,8 +1388,9 @@ impl Field { } pub fn layout(&self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> { + let interner = DbInterner::new_with(db, None, None); db.layout_of_ty( - self.ty(db).ty, + self.ty(db).ty.to_nextsolver(interner), db.trait_environment(match hir_def::VariantId::from(self.parent) { hir_def::VariantId::EnumVariantId(id) => { GenericDefId::AdtId(id.lookup(db).parent.into()) @@ -1444,6 +1471,11 @@ impl Struct { pub fn is_unstable(self, db: &dyn HirDatabase) -> bool { db.attrs(self.id.into()).is_unstable() } + + pub fn instantiate_infer<'db>(self, infer_ctxt: &InferCtxt<'db>) -> InstantiatedStruct<'db> { + let args = infer_ctxt.fresh_args_for_item(self.id.into()); + InstantiatedStruct { inner: self, args } + } } impl HasVisibility for Struct { @@ -1455,6 +1487,35 @@ 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 krate = self.inner.krate(db); + let interner = DbInterner::new_with(db, Some(krate.base()), None); + + let ty = db.ty_ns(self.inner.id.into()); + TypeNs::new(db, self.inner.id, ty.instantiate(interner, self.args)) + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Union { pub(crate) id: UnionId, } @@ -1598,6 +1659,22 @@ 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 krate = self.inner.krate(db); + let interner = DbInterner::new_with(db, Some(krate.base()), None); + + let ty = db.ty_ns(self.inner.id.into()); + TypeNs::new(db, self.inner.id, ty.instantiate(interner, self.args)) + } +} + impl From<&Variant> for DefWithBodyId { fn from(&v: &Variant) -> Self { DefWithBodyId::VariantId(v.into()) @@ -1673,6 +1750,38 @@ impl Variant { pub fn is_unstable(self, db: &dyn HirDatabase) -> bool { db.attrs(self.id.into()).is_unstable() } + + pub fn instantiate_infer<'db>(self, infer_ctxt: &InferCtxt<'db>) -> InstantiatedVariant<'db> { + let args = + infer_ctxt.fresh_args_for_item(self.parent_enum(infer_ctxt.interner.db()).id.into()); + InstantiatedVariant { inner: self, args } + } +} + +// FIXME: Rename to `EnumVariant` +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct InstantiatedVariant<'db> { + pub(crate) inner: Variant, + 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)] @@ -1709,12 +1818,15 @@ impl Adt { } pub fn layout(self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> { + let env = db.trait_environment(self.into()); + let interner = DbInterner::new_with(db, Some(env.krate), env.block); db.layout_of_adt( self.into(), TyBuilder::adt(db, self.into()) .fill_with_defaults(db, || TyKind::Error.intern(Interner)) - .build_into_subst(), - db.trait_environment(self.into()), + .build_into_subst() + .to_nextsolver(interner), + env, ) .map(|layout| Layout(layout, db.target_data_layout(self.krate(db).id).unwrap())) } @@ -2430,11 +2542,28 @@ impl Function { caller: Option<Function>, call_edition: Edition, ) -> bool { - let target_features = caller - .map(|caller| hir_ty::TargetFeatures::from_attrs(&db.attrs(caller.id.into()))) - .unwrap_or_default(); + let (target_features, target_feature_is_safe_in_target) = caller + .map(|caller| { + let target_features = + hir_ty::TargetFeatures::from_attrs(&db.attrs(caller.id.into())); + let target_feature_is_safe_in_target = + match &caller.krate(db).id.workspace_data(db).target { + Ok(target) => hir_ty::target_feature_is_safe_in_target(target), + Err(_) => hir_ty::TargetFeatureIsSafeInTarget::No, + }; + (target_features, target_feature_is_safe_in_target) + }) + .unwrap_or_else(|| { + (hir_ty::TargetFeatures::default(), hir_ty::TargetFeatureIsSafeInTarget::No) + }); matches!( - hir_ty::is_fn_unsafe_to_call(db, self.id, &target_features, call_edition), + hir_ty::is_fn_unsafe_to_call( + db, + self.id, + &target_features, + call_edition, + target_feature_is_safe_in_target + ), hir_ty::Unsafety::Unsafe ) } @@ -2932,29 +3061,6 @@ impl HasVisibility for Trait { } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct TraitAlias { - pub(crate) id: TraitAliasId, -} - -impl TraitAlias { - pub fn module(self, db: &dyn HirDatabase) -> Module { - Module { id: self.id.lookup(db).container } - } - - pub fn name(self, db: &dyn HirDatabase) -> Name { - db.trait_alias_signature(self.id).name.clone() - } -} - -impl HasVisibility for TraitAlias { - fn visibility(&self, db: &dyn HirDatabase) -> Visibility { - let loc = self.id.lookup(db); - let source = loc.source(db); - visibility_from_ast(db, self.id, source.map(|src| src.visibility())) - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct TypeAlias { pub(crate) id: TypeAliasId, } @@ -3576,7 +3682,6 @@ pub enum GenericDef { Function(Function), Adt(Adt), Trait(Trait), - TraitAlias(TraitAlias), TypeAlias(TypeAlias), Impl(Impl), // consts can have type parameters from their parents (i.e. associated consts of traits) @@ -3587,7 +3692,6 @@ impl_from!( Function, Adt(Struct, Enum, Union), Trait, - TraitAlias, TypeAlias, Impl, Const, @@ -3637,7 +3741,6 @@ impl GenericDef { GenericDef::Function(it) => it.id.into(), GenericDef::Adt(it) => it.into(), GenericDef::Trait(it) => it.id.into(), - GenericDef::TraitAlias(it) => it.id.into(), GenericDef::TypeAlias(it) => it.id.into(), GenericDef::Impl(it) => it.id.into(), GenericDef::Const(it) => it.id.into(), @@ -3662,7 +3765,6 @@ impl GenericDef { GenericDefId::FunctionId(it) => db.function_signature_with_source_map(it).1, GenericDefId::ImplId(it) => db.impl_signature_with_source_map(it).1, GenericDefId::StaticId(_) => return, - GenericDefId::TraitAliasId(it) => db.trait_alias_signature_with_source_map(it).1, GenericDefId::TraitId(it) => db.trait_signature_with_source_map(it).1, GenericDefId::TypeAliasId(it) => db.type_alias_signature_with_source_map(it).1, }; @@ -3672,7 +3774,7 @@ impl GenericDef { push_ty_diagnostics( db, acc, - db.generic_predicates_without_parent_with_diagnostics(def).1, + db.generic_predicates_without_parent_with_diagnostics_ns(def).1, &source_map, ); for (param_id, param) in generics.iter_type_or_consts() { @@ -3699,7 +3801,6 @@ impl GenericDef { GenericDef::Adt(Adt::Enum(_)) => "enum", GenericDef::Adt(Adt::Union(_)) => "union", GenericDef::Trait(_) => "trait", - GenericDef::TraitAlias(_) => "trait alias", GenericDef::TypeAlias(_) => "type alias", GenericDef::Impl(_) => "impl", GenericDef::Const(_) => "constant", @@ -3976,49 +4077,25 @@ impl DeriveHelper { } } -// FIXME: Wrong name? This is could also be a registered attribute #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub struct BuiltinAttr { - krate: Option<base_db::Crate>, idx: u32, } impl BuiltinAttr { - // FIXME: consider crates\hir_def\src\nameres\attr_resolution.rs? - pub(crate) fn by_name(db: &dyn HirDatabase, krate: Crate, name: &str) -> Option<Self> { - if let builtin @ Some(_) = Self::builtin(name) { - return builtin; - } - let idx = crate_def_map(db, krate.id) - .registered_attrs() - .iter() - .position(|it| it.as_str() == name)? as u32; - Some(BuiltinAttr { krate: Some(krate.id), idx }) - } - fn builtin(name: &str) -> Option<Self> { hir_expand::inert_attr_macro::find_builtin_attr_idx(&Symbol::intern(name)) - .map(|idx| BuiltinAttr { krate: None, idx: idx as u32 }) + .map(|idx| BuiltinAttr { idx: idx as u32 }) } - pub fn name(&self, db: &dyn HirDatabase) -> Name { - match self.krate { - Some(krate) => Name::new_symbol_root( - crate_def_map(db, krate).registered_attrs()[self.idx as usize].clone(), - ), - None => Name::new_symbol_root(Symbol::intern( - hir_expand::inert_attr_macro::INERT_ATTRIBUTES[self.idx as usize].name, - )), - } + pub fn name(&self) -> Name { + Name::new_symbol_root(Symbol::intern( + hir_expand::inert_attr_macro::INERT_ATTRIBUTES[self.idx as usize].name, + )) } - pub fn template(&self, _: &dyn HirDatabase) -> Option<AttributeTemplate> { - match self.krate { - Some(_) => None, - None => { - Some(hir_expand::inert_attr_macro::INERT_ATTRIBUTES[self.idx as usize].template) - } - } + pub fn template(&self) -> Option<AttributeTemplate> { + Some(hir_expand::inert_attr_macro::INERT_ATTRIBUTES[self.idx as usize].template) } } @@ -4154,8 +4231,8 @@ impl TypeParam { pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> { let resolver = self.id.parent().resolver(db); - let ty = - TyKind::Placeholder(hir_ty::to_placeholder_idx(db, self.id.into())).intern(Interner); + let ty = TyKind::Placeholder(hir_ty::to_placeholder_idx_no_index(db, self.id.into())) + .intern(Interner); Type::new_with_resolver_inner(db, &resolver, ty) } @@ -4163,12 +4240,10 @@ impl TypeParam { /// 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> { - db.generic_predicates_for_param(self.id.parent(), self.id.into(), None) + db.generic_predicates_for_param_ns(self.id.parent(), self.id.into(), None) .iter() - .filter_map(|pred| match &pred.skip_binders().skip_binders() { - hir_ty::WhereClause::Implemented(trait_ref) => { - Some(Trait::from(trait_ref.hir_trait_id())) - } + .filter_map(|pred| match &pred.kind().skip_binder() { + ClauseKind::Trait(trait_ref) => Some(Trait::from(trait_ref.def_id().0)), _ => None, }) .collect() @@ -4424,14 +4499,13 @@ impl Impl { } pub fn trait_(self, db: &dyn HirDatabase) -> Option<Trait> { - let trait_ref = db.impl_trait(self.id)?; - let id = trait_ref.skip_binders().hir_trait_id(); - Some(Trait { id }) + let trait_ref = db.impl_trait_ns(self.id)?; + let id = trait_ref.skip_binder().def_id; + Some(Trait { id: id.0 }) } pub fn trait_ref(self, db: &dyn HirDatabase) -> Option<TraitRef<'_>> { - let substs = TyBuilder::placeholder_subst(db, self.id); - let trait_ref = db.impl_trait(self.id)?.substitute(Interner, &substs); + let trait_ref = db.impl_trait_ns(self.id)?.instantiate_identity(); let resolver = self.id.resolver(db); Some(TraitRef::new_with_resolver(db, &resolver, trait_ref)) } @@ -4500,7 +4574,7 @@ impl Impl { #[derive(Clone, PartialEq, Eq, Debug, Hash)] pub struct TraitRef<'db> { env: Arc<TraitEnvironment>, - trait_ref: hir_ty::TraitRef, + trait_ref: hir_ty::next_solver::TraitRef<'db>, _pd: PhantomCovariantLifetime<'db>, } @@ -4508,7 +4582,7 @@ impl<'db> TraitRef<'db> { pub(crate) fn new_with_resolver( db: &'db dyn HirDatabase, resolver: &Resolver<'_>, - trait_ref: hir_ty::TraitRef, + trait_ref: hir_ty::next_solver::TraitRef<'db>, ) -> Self { let env = resolver .generic_def() @@ -4517,25 +4591,22 @@ impl<'db> TraitRef<'db> { } pub fn trait_(&self) -> Trait { - let id = self.trait_ref.hir_trait_id(); - Trait { id } + Trait { id: self.trait_ref.def_id.0 } } - pub fn self_ty(&self) -> Type<'_> { - let ty = self.trait_ref.self_type_parameter(Interner); - Type { env: self.env.clone(), ty, _pd: PhantomCovariantLifetime::new() } + pub fn self_ty(&self) -> TypeNs<'_> { + let ty = self.trait_ref.self_ty(); + TypeNs { env: self.env.clone(), ty, _pd: PhantomCovariantLifetime::new() } } /// 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<Type<'db>> { - self.trait_ref - .substitution - .as_slice(Interner) - .get(idx) - .and_then(|arg| arg.ty(Interner)) - .cloned() - .map(|ty| Type { env: self.env.clone(), ty, _pd: PhantomCovariantLifetime::new() }) + pub fn get_type_argument(&self, idx: usize) -> Option<TypeNs<'db>> { + self.trait_ref.args.as_slice().get(idx).and_then(|arg| arg.ty()).map(|ty| TypeNs { + env: self.env.clone(), + ty, + _pd: PhantomCovariantLifetime::new(), + }) } } @@ -4591,7 +4662,7 @@ impl Closure { .iter() .map(|capture| Type { env: db.trait_environment_for_body(owner), - ty: capture.ty(&self.subst), + ty: capture.ty(db, &self.subst), _pd: PhantomCovariantLifetime::new(), }) .collect() @@ -4852,42 +4923,80 @@ impl<'db> Type<'db> { } pub fn contains_reference(&self, db: &'db dyn HirDatabase) -> bool { - return go(db, self.env.krate, &self.ty); + return go(db, &self.ty); + + fn is_phantom_data(db: &dyn HirDatabase, adt_id: AdtId) -> bool { + match adt_id { + hir_def::AdtId::StructId(s) => { + let flags = db.struct_signature(s).flags; + flags.contains(StructFlags::IS_PHANTOM_DATA) + } + hir_def::AdtId::UnionId(_) => false, + hir_def::AdtId::EnumId(_) => false, + } + } - fn go(db: &dyn HirDatabase, krate: base_db::Crate, ty: &Ty) -> bool { + fn go(db: &dyn HirDatabase, ty: &Ty) -> bool { match ty.kind(Interner) { // Reference itself TyKind::Ref(_, _, _) => true, // For non-phantom_data adts we check variants/fields as well as generic parameters - TyKind::Adt(adt_id, substitution) - if !db.adt_datum(krate, *adt_id).flags.phantom_data => - { - let adt_datum = &db.adt_datum(krate, *adt_id); - let adt_datum_bound = - adt_datum.binders.clone().substitute(Interner, substitution); - adt_datum_bound - .variants + TyKind::Adt(adt_id, substitution) if !is_phantom_data(db, adt_id.0) => { + let _variant_id_to_fields = |id: VariantId| { + let variant_data = &id.fields(db); + if variant_data.fields().is_empty() { + vec![] + } else { + let field_types = db.field_types(id); + variant_data + .fields() + .iter() + .map(|(idx, _)| { + field_types[idx].clone().substitute(Interner, substitution) + }) + .filter(|it| !it.contains_unknown()) + .collect() + } + }; + let variant_id_to_fields = |_: VariantId| vec![]; + + let variants = match adt_id.0 { + hir_def::AdtId::StructId(id) => { + vec![variant_id_to_fields(id.into())] + } + hir_def::AdtId::EnumId(id) => id + .enum_variants(db) + .variants + .iter() + .map(|&(variant_id, _, _)| variant_id_to_fields(variant_id.into())) + .collect(), + hir_def::AdtId::UnionId(id) => { + vec![variant_id_to_fields(id.into())] + } + }; + + variants .into_iter() - .flat_map(|variant| variant.fields.into_iter()) - .any(|ty| go(db, krate, &ty)) + .flat_map(|variant| variant.into_iter()) + .any(|ty| go(db, &ty)) || substitution .iter(Interner) .filter_map(|x| x.ty(Interner)) - .any(|ty| go(db, krate, ty)) + .any(|ty| go(db, ty)) } // And for `PhantomData<T>`, we check `T`. TyKind::Adt(_, substitution) | TyKind::Tuple(_, substitution) | TyKind::OpaqueType(_, substitution) | TyKind::AssociatedType(_, substitution) - | TyKind::FnDef(_, substitution) => substitution - .iter(Interner) - .filter_map(|x| x.ty(Interner)) - .any(|ty| go(db, krate, ty)), + | TyKind::Alias(AliasTy::Projection(ProjectionTy { substitution, .. })) + | TyKind::FnDef(_, substitution) => { + substitution.iter(Interner).filter_map(|x| x.ty(Interner)).any(|ty| go(db, ty)) + } // For `[T]` or `*T` we check `T` - TyKind::Array(ty, _) | TyKind::Slice(ty) | TyKind::Raw(_, ty) => go(db, krate, ty), + TyKind::Array(ty, _) | TyKind::Slice(ty) | TyKind::Raw(_, ty) => go(db, ty), // Consider everything else as not reference _ => false, @@ -5072,7 +5181,7 @@ impl<'db> Type<'db> { binders: CanonicalVarKinds::empty(Interner), }; - db.trait_solve(self.env.krate, self.env.block, goal).is_some() + !db.trait_solve(self.env.krate, self.env.block, goal).no_solution() } pub fn normalize_trait_assoc_type( @@ -5520,7 +5629,11 @@ impl<'db> Type<'db> { .map_or_else(|| TraitEnvironment::empty(krate.id), |d| db.trait_environment(d)); _ = method_resolution::iterate_method_candidates_dyn( - &canonical, + &canonical.to_nextsolver(DbInterner::new_with( + db, + Some(environment.krate), + environment.block, + )), db, environment, traits_in_scope, @@ -5607,7 +5720,11 @@ impl<'db> Type<'db> { .map_or_else(|| TraitEnvironment::empty(krate.id), |d| db.trait_environment(d)); _ = method_resolution::iterate_path_candidates( - &canonical, + &canonical.to_nextsolver(DbInterner::new_with( + db, + Some(environment.krate), + environment.block, + )), db, environment, traits_in_scope, @@ -5720,7 +5837,11 @@ impl<'db> Type<'db> { cb(type_.derived(ty.clone())); walk_substs(db, type_, substs, cb); } - TyKind::AssociatedType(_, substs) => { + TyKind::AssociatedType(_, substs) + | TyKind::Alias(AliasTy::Projection(hir_ty::ProjectionTy { + substitution: substs, + .. + })) => { if ty.associated_type_parent_trait(db).is_some() { cb(type_.derived(ty.clone())); } @@ -5803,7 +5924,7 @@ impl<'db> Type<'db> { pub fn as_type_param(&self, db: &'db dyn HirDatabase) -> Option<TypeParam> { match self.ty.kind(Interner) { TyKind::Placeholder(p) => Some(TypeParam { - id: TypeParamId::from_unchecked(hir_ty::from_placeholder_idx(db, *p)), + id: TypeParamId::from_unchecked(hir_ty::from_placeholder_idx(db, *p).0), }), _ => None, } @@ -5818,7 +5939,8 @@ impl<'db> Type<'db> { } pub fn layout(&self, db: &'db dyn HirDatabase) -> Result<Layout, LayoutError> { - db.layout_of_ty(self.ty.clone(), self.env.clone()) + let interner = DbInterner::new_with(db, None, None); + db.layout_of_ty(self.ty.to_nextsolver(interner), self.env.clone()) .map(|layout| Layout(layout, db.target_data_layout(self.env.krate).unwrap())) } @@ -5827,6 +5949,51 @@ impl<'db> Type<'db> { } } +#[derive(Clone, PartialEq, Eq, Debug, Hash)] +pub struct TypeNs<'db> { + env: Arc<TraitEnvironment>, + ty: hir_ty::next_solver::Ty<'db>, + _pd: PhantomCovariantLifetime<'db>, +} + +impl<'db> TypeNs<'db> { + fn new( + db: &'db dyn HirDatabase, + lexical_env: impl HasResolver, + ty: hir_ty::next_solver::Ty<'db>, + ) -> Self { + let resolver = lexical_env.resolver(db); + let environment = resolver + .generic_def() + .map_or_else(|| TraitEnvironment::empty(resolver.krate()), |d| db.trait_environment(d)); + TypeNs { env: environment, ty, _pd: PhantomCovariantLifetime::new() } + } + + // 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(|t| t.into()), + ); + let trait_ref = hir_ty::next_solver::TraitRef::new(infcx.interner, trait_.id.into(), args); + + let pred_kind = rustc_type_ir::Binder::dummy(rustc_type_ir::PredicateKind::Clause( + rustc_type_ir::ClauseKind::Trait(rustc_type_ir::TraitPredicate { + trait_ref, + polarity: rustc_type_ir::PredicatePolarity::Positive, + }), + )); + let predicate = hir_ty::next_solver::Predicate::new(infcx.interner, pred_kind); + let goal = hir_ty::next_solver::Goal::new( + infcx.interner, + hir_ty::next_solver::ParamEnv::empty(), + predicate, + ); + let res = hir_ty::traits::next_trait_solve_in_ctxt(&infcx, goal); + res.map_or(false, |res| matches!(res.1, rustc_type_ir::solve::Certainty::Yes)) + } +} + #[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] pub struct InlineAsmOperand { owner: DefWithBodyId, @@ -6238,12 +6405,6 @@ impl HasCrate for Trait { } } -impl HasCrate for TraitAlias { - fn krate(&self, db: &dyn HirDatabase) -> Crate { - self.module(db).krate() - } -} - impl HasCrate for Static { fn krate(&self, db: &dyn HirDatabase) -> Crate { self.module(db).krate() @@ -6337,12 +6498,6 @@ impl HasContainer for Trait { } } -impl HasContainer for TraitAlias { - fn container(&self, db: &dyn HirDatabase) -> ItemContainer { - ItemContainer::Module(Module { id: self.id.lookup(db).container }) - } -} - impl HasContainer for ExternBlock { fn container(&self, db: &dyn HirDatabase) -> ItemContainer { ItemContainer::Module(Module { id: self.id.lookup(db).container }) @@ -6476,3 +6631,6 @@ pub fn resolve_absolute_path<'a, I: Iterator<Item = Symbol> + Clone + 'a>( fn as_name_opt(name: Option<impl AsName>) -> Name { name.map_or_else(Name::missing, |name| name.as_name()) } + +pub use hir_ty::next_solver; +pub use hir_ty::setup_tracing; |