From 743faa21e74cc5b627935e2c4c3365807a5c722f Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 9 Apr 2021 14:11:37 +0200 Subject: Reorganize hir_ty modules Chalk isn't really a 'traits' thing anymore, so it doesn't make sense to have all the Chalk-related stuff in submodules of `traits`. --- crates/hir_ty/src/chalk_db.rs | 714 ++++++++++++++++++++++++++++ crates/hir_ty/src/db.rs | 47 +- crates/hir_ty/src/display.rs | 2 +- crates/hir_ty/src/infer/expr.rs | 3 +- crates/hir_ty/src/interner.rs | 405 ++++++++++++++++ crates/hir_ty/src/lib.rs | 7 +- crates/hir_ty/src/lower.rs | 3 +- crates/hir_ty/src/mapping.rs | 125 +++++ crates/hir_ty/src/tls.rs | 274 +++++++++++ crates/hir_ty/src/traits.rs | 14 +- crates/hir_ty/src/traits/chalk.rs | 716 ----------------------------- crates/hir_ty/src/traits/chalk/interner.rs | 421 ----------------- crates/hir_ty/src/traits/chalk/mapping.rs | 131 ------ crates/hir_ty/src/traits/chalk/tls.rs | 275 ----------- 14 files changed, 1555 insertions(+), 1582 deletions(-) create mode 100644 crates/hir_ty/src/chalk_db.rs create mode 100644 crates/hir_ty/src/interner.rs create mode 100644 crates/hir_ty/src/mapping.rs create mode 100644 crates/hir_ty/src/tls.rs delete mode 100644 crates/hir_ty/src/traits/chalk.rs delete mode 100644 crates/hir_ty/src/traits/chalk/interner.rs delete mode 100644 crates/hir_ty/src/traits/chalk/mapping.rs delete mode 100644 crates/hir_ty/src/traits/chalk/tls.rs (limited to 'crates/hir_ty/src') diff --git a/crates/hir_ty/src/chalk_db.rs b/crates/hir_ty/src/chalk_db.rs new file mode 100644 index 000000000..566e4f406 --- /dev/null +++ b/crates/hir_ty/src/chalk_db.rs @@ -0,0 +1,714 @@ +//! Conversion code from/to Chalk. +use std::sync::Arc; + +use log::debug; + +use chalk_ir::{fold::shift::Shift, CanonicalVarKinds}; +use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait}; + +use base_db::{salsa::InternKey, CrateId}; +use hir_def::{ + lang_item::{lang_attr, LangItemTarget}, + AssocContainerId, AssocItemId, HasModule, Lookup, TypeAliasId, +}; +use hir_expand::name::name; + +use crate::{AliasEq, AliasTy, BoundVar, CallableDefId, DebruijnIndex, FnDefId, Interner, ProjectionTy, Substitution, TraitRef, TraitRefExt, Ty, TyBuilder, TyExt, TyKind, WhereClause, traits::ChalkContext, db::HirDatabase, display::HirDisplay, from_assoc_type_id, make_only_type_binders, mapping::{convert_where_clauses, generic_predicate_to_inline_bound, TypeAliasAsValue}, method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS}, to_assoc_type_id, to_chalk_trait_id, utils::generics}; + +pub(crate) type AssociatedTyDatum = chalk_solve::rust_ir::AssociatedTyDatum; +pub(crate) type TraitDatum = chalk_solve::rust_ir::TraitDatum; +pub(crate) type StructDatum = chalk_solve::rust_ir::AdtDatum; +pub(crate) type ImplDatum = chalk_solve::rust_ir::ImplDatum; +pub(crate) type OpaqueTyDatum = chalk_solve::rust_ir::OpaqueTyDatum; + +pub(crate) type AssocTypeId = chalk_ir::AssocTypeId; +pub(crate) type TraitId = chalk_ir::TraitId; +pub(crate) type AdtId = chalk_ir::AdtId; +pub(crate) type OpaqueTyId = chalk_ir::OpaqueTyId; +pub(crate) type ImplId = chalk_ir::ImplId; +pub(crate) type AssociatedTyValueId = chalk_solve::rust_ir::AssociatedTyValueId; +pub(crate) type AssociatedTyValue = chalk_solve::rust_ir::AssociatedTyValue; +pub(crate) type FnDefDatum = chalk_solve::rust_ir::FnDefDatum; +pub(crate) type Variances = chalk_ir::Variances; + +pub(crate) trait ToChalk { + type Chalk; + fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk; + fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self; +} + +pub(crate) fn from_chalk(db: &dyn HirDatabase, chalk: ChalkT) -> T +where + T: ToChalk, +{ + T::from_chalk(db, chalk) +} + +impl<'a> chalk_solve::RustIrDatabase for ChalkContext<'a> { + fn associated_ty_data(&self, id: AssocTypeId) -> Arc { + self.db.associated_ty_data(id) + } + fn trait_datum(&self, trait_id: TraitId) -> Arc { + self.db.trait_datum(self.krate, trait_id) + } + fn adt_datum(&self, struct_id: AdtId) -> Arc { + self.db.struct_datum(self.krate, struct_id) + } + fn adt_repr(&self, _struct_id: AdtId) -> Arc> { + // FIXME: keep track of these + Arc::new(rust_ir::AdtRepr { c: false, packed: false, int: None }) + } + fn discriminant_type(&self, _ty: chalk_ir::Ty) -> chalk_ir::Ty { + // FIXME: keep track of this + chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Uint(chalk_ir::UintTy::U32)).intern(&Interner) + } + fn impl_datum(&self, impl_id: ImplId) -> Arc { + self.db.impl_datum(self.krate, impl_id) + } + + fn fn_def_datum( + &self, + fn_def_id: chalk_ir::FnDefId, + ) -> Arc> { + self.db.fn_def_datum(self.krate, fn_def_id) + } + + fn impls_for_trait( + &self, + trait_id: TraitId, + parameters: &[chalk_ir::GenericArg], + binders: &CanonicalVarKinds, + ) -> Vec { + debug!("impls_for_trait {:?}", trait_id); + let trait_: hir_def::TraitId = from_chalk(self.db, trait_id); + + let ty: Ty = parameters[0].assert_ty_ref(&Interner).clone(); + + fn binder_kind( + ty: &Ty, + binders: &CanonicalVarKinds, + ) -> Option { + if let TyKind::BoundVar(bv) = ty.kind(&Interner) { + let binders = binders.as_slice(&Interner); + if bv.debruijn == DebruijnIndex::INNERMOST { + if let chalk_ir::VariableKind::Ty(tk) = binders[bv.index].kind { + return Some(tk); + } + } + } + None + } + + let self_ty_fp = TyFingerprint::for_trait_impl(&ty); + let fps: &[TyFingerprint] = match binder_kind(&ty, binders) { + Some(chalk_ir::TyVariableKind::Integer) => &ALL_INT_FPS, + Some(chalk_ir::TyVariableKind::Float) => &ALL_FLOAT_FPS, + _ => self_ty_fp.as_ref().map(std::slice::from_ref).unwrap_or(&[]), + }; + + // Note: Since we're using impls_for_trait, only impls where the trait + // can be resolved should ever reach Chalk. Symbol’s value as variable is void: impl_datum relies on that + // and will panic if the trait can't be resolved. + let in_deps = self.db.trait_impls_in_deps(self.krate); + let in_self = self.db.trait_impls_in_crate(self.krate); + let impl_maps = [in_deps, in_self]; + + let id_to_chalk = |id: hir_def::ImplId| id.to_chalk(self.db); + + let result: Vec<_> = if fps.is_empty() { + debug!("Unrestricted search for {:?} impls...", trait_); + impl_maps + .iter() + .flat_map(|crate_impl_defs| crate_impl_defs.for_trait(trait_).map(id_to_chalk)) + .collect() + } else { + impl_maps + .iter() + .flat_map(|crate_impl_defs| { + fps.iter().flat_map(move |fp| { + crate_impl_defs.for_trait_and_self_ty(trait_, *fp).map(id_to_chalk) + }) + }) + .collect() + }; + + debug!("impls_for_trait returned {} impls", result.len()); + result + } + fn impl_provided_for(&self, auto_trait_id: TraitId, kind: &chalk_ir::TyKind) -> bool { + debug!("impl_provided_for {:?}, {:?}", auto_trait_id, kind); + false // FIXME + } + fn associated_ty_value(&self, id: AssociatedTyValueId) -> Arc { + self.db.associated_ty_value(self.krate, id) + } + + fn custom_clauses(&self) -> Vec> { + vec![] + } + fn local_impls_to_coherence_check(&self, _trait_id: TraitId) -> Vec { + // We don't do coherence checking (yet) + unimplemented!() + } + fn interner(&self) -> &Interner { + &Interner + } + fn well_known_trait_id( + &self, + well_known_trait: rust_ir::WellKnownTrait, + ) -> Option> { + let lang_attr = lang_attr_from_well_known_trait(well_known_trait); + let trait_ = match self.db.lang_item(self.krate, lang_attr.into()) { + Some(LangItemTarget::TraitId(trait_)) => trait_, + _ => return None, + }; + Some(trait_.to_chalk(self.db)) + } + + fn program_clauses_for_env( + &self, + environment: &chalk_ir::Environment, + ) -> chalk_ir::ProgramClauses { + self.db.program_clauses_for_chalk_env(self.krate, environment.clone()) + } + + fn opaque_ty_data(&self, id: chalk_ir::OpaqueTyId) -> Arc { + let full_id = self.db.lookup_intern_impl_trait_id(id.into()); + let bound = match full_id { + crate::ImplTraitId::ReturnTypeImplTrait(func, idx) => { + let datas = self + .db + .return_type_impl_traits(func) + .expect("impl trait id without impl traits"); + let (datas, binders) = (*datas).as_ref().into_value_and_skipped_binders(); + let data = &datas.impl_traits[idx as usize]; + let bound = OpaqueTyDatumBound { + bounds: make_only_type_binders( + 1, + data.bounds.skip_binders().iter().cloned().collect(), + ), + where_clauses: make_only_type_binders(0, vec![]), + }; + chalk_ir::Binders::new(binders, bound) + } + crate::ImplTraitId::AsyncBlockTypeImplTrait(..) => { + if let Some((future_trait, future_output)) = self + .db + .lang_item(self.krate, "future_trait".into()) + .and_then(|item| item.as_trait()) + .and_then(|trait_| { + let alias = + self.db.trait_data(trait_).associated_type_by_name(&name![Output])?; + Some((trait_, alias)) + }) + { + // Making up Symbol’s value as variable is void: AsyncBlock: + // + // |--------------------OpaqueTyDatum-------------------| + // |-------------OpaqueTyDatumBound--------------| + // for [Future, Future::Output = T] + // ^1 ^0 ^0 ^0 ^1 + let impl_bound = WhereClause::Implemented(TraitRef { + trait_id: to_chalk_trait_id(future_trait), + // Self type as the first parameter. + substitution: Substitution::from1( + &Interner, + TyKind::BoundVar(BoundVar { + debruijn: DebruijnIndex::INNERMOST, + index: 0, + }) + .intern(&Interner), + ), + }); + let proj_bound = WhereClause::AliasEq(AliasEq { + alias: AliasTy::Projection(ProjectionTy { + associated_ty_id: to_assoc_type_id(future_output), + // Self type as the first parameter. + substitution: Substitution::from1( + &Interner, + TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)) + .intern(&Interner), + ), + }), + // The parameter of the opaque type. + ty: TyKind::BoundVar(BoundVar { debruijn: DebruijnIndex::ONE, index: 0 }) + .intern(&Interner), + }); + let bound = OpaqueTyDatumBound { + bounds: make_only_type_binders( + 1, + vec![ + crate::wrap_empty_binders(impl_bound), + crate::wrap_empty_binders(proj_bound), + ], + ), + where_clauses: make_only_type_binders(0, vec![]), + }; + // The opaque type has 1 parameter. + make_only_type_binders(1, bound) + } else { + // If failed to find Symbol’s value as variable is void: Future::Output, return empty bounds as fallback. + let bound = OpaqueTyDatumBound { + bounds: make_only_type_binders(0, vec![]), + where_clauses: make_only_type_binders(0, vec![]), + }; + // The opaque type has 1 parameter. + make_only_type_binders(1, bound) + } + } + }; + + Arc::new(OpaqueTyDatum { opaque_ty_id: id, bound }) + } + + fn hidden_opaque_type(&self, _id: chalk_ir::OpaqueTyId) -> chalk_ir::Ty { + // FIXME: actually provide the hidden type; it is relevant for auto traits + TyKind::Error.intern(&Interner) + } + + fn is_object_safe(&self, _trait_id: chalk_ir::TraitId) -> bool { + // FIXME: implement actual object safety + true + } + + fn closure_kind( + &self, + _closure_id: chalk_ir::ClosureId, + _substs: &chalk_ir::Substitution, + ) -> rust_ir::ClosureKind { + // Fn is the closure kind that implements all three traits + rust_ir::ClosureKind::Fn + } + fn closure_inputs_and_output( + &self, + _closure_id: chalk_ir::ClosureId, + substs: &chalk_ir::Substitution, + ) -> chalk_ir::Binders> { + let sig_ty = substs.at(&Interner, 0).assert_ty_ref(&Interner).clone(); + let sig = &sig_ty.callable_sig(self.db).expect("first closure param should be fn ptr"); + let io = rust_ir::FnDefInputsAndOutputDatum { + argument_types: sig.params().iter().cloned().collect(), + return_type: sig.ret().clone(), + }; + make_only_type_binders(0, io.shifted_in(&Interner)) + } + fn closure_upvars( + &self, + _closure_id: chalk_ir::ClosureId, + _substs: &chalk_ir::Substitution, + ) -> chalk_ir::Binders> { + let ty = TyBuilder::unit(); + make_only_type_binders(0, ty) + } + fn closure_fn_substitution( + &self, + _closure_id: chalk_ir::ClosureId, + _substs: &chalk_ir::Substitution, + ) -> chalk_ir::Substitution { + Substitution::empty(&Interner) + } + + fn trait_name(&self, trait_id: chalk_ir::TraitId) -> String { + let id = from_chalk(self.db, trait_id); + self.db.trait_data(id).name.to_string() + } + fn adt_name(&self, chalk_ir::AdtId(adt_id): AdtId) -> String { + match adt_id { + hir_def::AdtId::StructId(id) => self.db.struct_data(id).name.to_string(), + hir_def::AdtId::EnumId(id) => self.db.enum_data(id).name.to_string(), + hir_def::AdtId::UnionId(id) => self.db.union_data(id).name.to_string(), + } + } + fn assoc_type_name(&self, assoc_ty_id: chalk_ir::AssocTypeId) -> String { + let id = self.db.associated_ty_data(assoc_ty_id).name; + self.db.type_alias_data(id).name.to_string() + } + fn opaque_type_name(&self, opaque_ty_id: chalk_ir::OpaqueTyId) -> String { + format!("Opaque_{}", opaque_ty_id.0) + } + fn fn_def_name(&self, fn_def_id: chalk_ir::FnDefId) -> String { + format!("fn_{}", fn_def_id.0) + } + fn generator_datum( + &self, + _: chalk_ir::GeneratorId, + ) -> std::sync::Arc> { + // FIXME + unimplemented!() + } + fn generator_witness_datum( + &self, + _: chalk_ir::GeneratorId, + ) -> std::sync::Arc> { + // FIXME + unimplemented!() + } + + fn unification_database(&self) -> &dyn chalk_ir::UnificationDatabase { + self + } +} + +impl<'a> chalk_ir::UnificationDatabase for ChalkContext<'a> { + fn fn_def_variance( + &self, + fn_def_id: chalk_ir::FnDefId, + ) -> chalk_ir::Variances { + self.db.fn_def_variance(self.krate, fn_def_id) + } + + fn adt_variance(&self, adt_id: chalk_ir::AdtId) -> chalk_ir::Variances { + self.db.adt_variance(self.krate, adt_id) + } +} + +pub(crate) fn program_clauses_for_chalk_env_query( + db: &dyn HirDatabase, + krate: CrateId, + environment: chalk_ir::Environment, +) -> chalk_ir::ProgramClauses { + chalk_solve::program_clauses_for_env(&ChalkContext { db, krate }, &environment) +} + +pub(crate) fn associated_ty_data_query( + db: &dyn HirDatabase, + id: AssocTypeId, +) -> Arc { + debug!("associated_ty_data {:?}", id); + let type_alias: TypeAliasId = from_assoc_type_id(id); + let trait_ = match type_alias.lookup(db.upcast()).container { + AssocContainerId::TraitId(t) => t, + _ => panic!("associated type not in trait"), + }; + + // Lower bounds -- we could/should maybe move this to a separate query in `lower` + let type_alias_data = db.type_alias_data(type_alias); + let generic_params = generics(db.upcast(), type_alias.into()); + let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST); + let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db.upcast()); + let ctx = crate::TyLoweringContext::new(db, &resolver) + .with_type_param_mode(crate::lower::TypeParamLoweringMode::Variable); + let self_ty = + TyKind::BoundVar(BoundVar::new(crate::DebruijnIndex::INNERMOST, 0)).intern(&Interner); + let bounds = type_alias_data + .bounds + .iter() + .flat_map(|bound| ctx.lower_type_bound(bound, self_ty.clone(), false)) + .filter_map(|pred| generic_predicate_to_inline_bound(db, &pred, &self_ty)) + .collect(); + + let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars); + let bound_data = rust_ir::AssociatedTyDatumBound { bounds, where_clauses }; + let datum = AssociatedTyDatum { + trait_id: to_chalk_trait_id(trait_), + id, + name: type_alias, + binders: make_only_type_binders(generic_params.len(), bound_data), + }; + Arc::new(datum) +} + +pub(crate) fn trait_datum_query( + db: &dyn HirDatabase, + krate: CrateId, + trait_id: TraitId, +) -> Arc { + debug!("trait_datum {:?}", trait_id); + let trait_: hir_def::TraitId = from_chalk(db, trait_id); + let trait_data = db.trait_data(trait_); + debug!("trait {:?} = {:?}", trait_id, trait_data.name); + let generic_params = generics(db.upcast(), trait_.into()); + let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST); + let flags = rust_ir::TraitFlags { + auto: trait_data.is_auto, + upstream: trait_.lookup(db.upcast()).container.krate() != krate, + non_enumerable: true, + coinductive: false, // only relevant for Chalk testing + // FIXME: set these flags correctly + marker: false, + fundamental: false, + }; + let where_clauses = convert_where_clauses(db, trait_.into(), &bound_vars); + let associated_ty_ids = + trait_data.associated_types().map(|type_alias| to_assoc_type_id(type_alias)).collect(); + let trait_datum_bound = rust_ir::TraitDatumBound { where_clauses }; + let well_known = + lang_attr(db.upcast(), trait_).and_then(|name| well_known_trait_from_lang_attr(&name)); + let trait_datum = TraitDatum { + id: trait_id, + binders: make_only_type_binders(bound_vars.len(&Interner), trait_datum_bound), + flags, + associated_ty_ids, + well_known, + }; + Arc::new(trait_datum) +} + +fn well_known_trait_from_lang_attr(name: &str) -> Option { + Some(match name { + "sized" => WellKnownTrait::Sized, + "copy" => WellKnownTrait::Copy, + "clone" => WellKnownTrait::Clone, + "drop" => WellKnownTrait::Drop, + "fn_once" => WellKnownTrait::FnOnce, + "fn_mut" => WellKnownTrait::FnMut, + "fn" => WellKnownTrait::Fn, + "unsize" => WellKnownTrait::Unsize, + "coerce_unsized" => WellKnownTrait::CoerceUnsized, + "discriminant_kind" => WellKnownTrait::DiscriminantKind, + _ => return None, + }) +} + +fn lang_attr_from_well_known_trait(attr: WellKnownTrait) -> &'static str { + match attr { + WellKnownTrait::Sized => "sized", + WellKnownTrait::Copy => "copy", + WellKnownTrait::Clone => "clone", + WellKnownTrait::Drop => "drop", + WellKnownTrait::FnOnce => "fn_once", + WellKnownTrait::FnMut => "fn_mut", + WellKnownTrait::Fn => "fn", + WellKnownTrait::Unsize => "unsize", + WellKnownTrait::Unpin => "unpin", + WellKnownTrait::CoerceUnsized => "coerce_unsized", + WellKnownTrait::DiscriminantKind => "discriminant_kind", + } +} + +pub(crate) fn struct_datum_query( + db: &dyn HirDatabase, + krate: CrateId, + struct_id: AdtId, +) -> Arc { + debug!("struct_datum {:?}", struct_id); + let chalk_ir::AdtId(adt_id) = struct_id; + let num_params = generics(db.upcast(), adt_id.into()).len(); + let upstream = adt_id.module(db.upcast()).krate() != krate; + let where_clauses = { + let generic_params = generics(db.upcast(), adt_id.into()); + let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST); + convert_where_clauses(db, adt_id.into(), &bound_vars) + }; + let flags = rust_ir::AdtFlags { + upstream, + // FIXME set fundamental and phantom_data flags correctly + fundamental: false, + phantom_data: false, + }; + // FIXME provide enum variants properly (for auto traits) + let variant = rust_ir::AdtVariantDatum { + fields: Vec::new(), // FIXME add fields (only relevant for auto traits), + }; + let struct_datum_bound = rust_ir::AdtDatumBound { variants: vec![variant], where_clauses }; + let struct_datum = StructDatum { + // FIXME set ADT kind + kind: rust_ir::AdtKind::Struct, + id: struct_id, + binders: make_only_type_binders(num_params, struct_datum_bound), + flags, + }; + Arc::new(struct_datum) +} + +pub(crate) fn impl_datum_query( + db: &dyn HirDatabase, + krate: CrateId, + impl_id: ImplId, +) -> Arc { + let _p = profile::span("impl_datum"); + debug!("impl_datum {:?}", impl_id); + let impl_: hir_def::ImplId = from_chalk(db, impl_id); + impl_def_datum(db, krate, impl_id, impl_) +} + +fn impl_def_datum( + db: &dyn HirDatabase, + krate: CrateId, + chalk_id: ImplId, + impl_id: hir_def::ImplId, +) -> Arc { + let trait_ref = db + .impl_trait(impl_id) + // ImplIds for impls where the trait ref can't be resolved should never reach Chalk + .expect("invalid impl passed to Chalk") + .into_value_and_skipped_binders() + .0; + let impl_data = db.impl_data(impl_id); + + let generic_params = generics(db.upcast(), impl_id.into()); + let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST); + let trait_ = trait_ref.hir_trait_id(); + let impl_type = if impl_id.lookup(db.upcast()).container.krate() == krate { + rust_ir::ImplType::Local + } else { + rust_ir::ImplType::External + }; + let where_clauses = convert_where_clauses(db, impl_id.into(), &bound_vars); + let negative = impl_data.is_negative; + debug!( + "impl {:?}: {}{} where {:?}", + chalk_id, + if negative { "!" } else { "" }, + trait_ref.display(db), + where_clauses + ); + + let polarity = if negative { rust_ir::Polarity::Negative } else { rust_ir::Polarity::Positive }; + + let impl_datum_bound = rust_ir::ImplDatumBound { trait_ref, where_clauses }; + let trait_data = db.trait_data(trait_); + let associated_ty_value_ids = impl_data + .items + .iter() + .filter_map(|item| match item { + AssocItemId::TypeAliasId(type_alias) => Some(*type_alias), + _ => None, + }) + .filter(|&type_alias| { + // don't include associated types that don't exist in the trait + let name = &db.type_alias_data(type_alias).name; + trait_data.associated_type_by_name(name).is_some() + }) + .map(|type_alias| TypeAliasAsValue(type_alias).to_chalk(db)) + .collect(); + debug!("impl_datum: {:?}", impl_datum_bound); + let impl_datum = ImplDatum { + binders: make_only_type_binders(bound_vars.len(&Interner), impl_datum_bound), + impl_type, + polarity, + associated_ty_value_ids, + }; + Arc::new(impl_datum) +} + +pub(crate) fn associated_ty_value_query( + db: &dyn HirDatabase, + krate: CrateId, + id: AssociatedTyValueId, +) -> Arc { + let type_alias: TypeAliasAsValue = from_chalk(db, id); + type_alias_associated_ty_value(db, krate, type_alias.0) +} + +fn type_alias_associated_ty_value( + db: &dyn HirDatabase, + _krate: CrateId, + type_alias: TypeAliasId, +) -> Arc { + let type_alias_data = db.type_alias_data(type_alias); + let impl_id = match type_alias.lookup(db.upcast()).container { + AssocContainerId::ImplId(it) => it, + _ => panic!("assoc ty value should be in impl"), + }; + + let trait_ref = db + .impl_trait(impl_id) + .expect("assoc ty value should not exist") + .into_value_and_skipped_binders() + .0; // we don't return any assoc ty values if the impl'd trait can't be resolved + + let assoc_ty = db + .trait_data(trait_ref.hir_trait_id()) + .associated_type_by_name(&type_alias_data.name) + .expect("assoc ty value should not exist"); // validated when building the impl data as well + let (ty, binders) = db.ty(type_alias.into()).into_value_and_skipped_binders(); + let value_bound = rust_ir::AssociatedTyValueBound { ty }; + let value = rust_ir::AssociatedTyValue { + impl_id: impl_id.to_chalk(db), + associated_ty_id: to_assoc_type_id(assoc_ty), + value: chalk_ir::Binders::new(binders, value_bound), + }; + Arc::new(value) +} + +pub(crate) fn fn_def_datum_query( + db: &dyn HirDatabase, + _krate: CrateId, + fn_def_id: FnDefId, +) -> Arc { + let callable_def: CallableDefId = from_chalk(db, fn_def_id); + let generic_params = generics(db.upcast(), callable_def.into()); + let (sig, binders) = db.callable_item_signature(callable_def).into_value_and_skipped_binders(); + let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST); + let where_clauses = convert_where_clauses(db, callable_def.into(), &bound_vars); + let bound = rust_ir::FnDefDatumBound { + // Note: Chalk doesn't actually use this information yet as far as I am aware, but we provide it anyway + inputs_and_output: make_only_type_binders( + 0, + rust_ir::FnDefInputsAndOutputDatum { + argument_types: sig.params().iter().cloned().collect(), + return_type: sig.ret().clone(), + } + .shifted_in(&Interner), + ), + where_clauses, + }; + let datum = FnDefDatum { + id: fn_def_id, + sig: chalk_ir::FnSig { abi: (), safety: chalk_ir::Safety::Safe, variadic: sig.is_varargs }, + binders: chalk_ir::Binders::new(binders, bound), + }; + Arc::new(datum) +} + +pub(crate) fn fn_def_variance_query( + db: &dyn HirDatabase, + _krate: CrateId, + fn_def_id: FnDefId, +) -> Variances { + let callable_def: CallableDefId = from_chalk(db, fn_def_id); + let generic_params = generics(db.upcast(), callable_def.into()); + Variances::from_iter( + &Interner, + std::iter::repeat(chalk_ir::Variance::Invariant).take(generic_params.len()), + ) +} + +pub(crate) fn adt_variance_query( + db: &dyn HirDatabase, + _krate: CrateId, + chalk_ir::AdtId(adt_id): AdtId, +) -> Variances { + let generic_params = generics(db.upcast(), adt_id.into()); + Variances::from_iter( + &Interner, + std::iter::repeat(chalk_ir::Variance::Invariant).take(generic_params.len()), + ) +} + +impl From for crate::db::InternedCallableDefId { + fn from(fn_def_id: FnDefId) -> Self { + InternKey::from_intern_id(fn_def_id.0) + } +} + +impl From for FnDefId { + fn from(callable_def_id: crate::db::InternedCallableDefId) -> Self { + chalk_ir::FnDefId(callable_def_id.as_intern_id()) + } +} + +impl From for crate::db::InternedOpaqueTyId { + fn from(id: OpaqueTyId) -> Self { + InternKey::from_intern_id(id.0) + } +} + +impl From for OpaqueTyId { + fn from(id: crate::db::InternedOpaqueTyId) -> Self { + chalk_ir::OpaqueTyId(id.as_intern_id()) + } +} + +impl From> for crate::db::InternedClosureId { + fn from(id: chalk_ir::ClosureId) -> Self { + Self::from_intern_id(id.0) + } +} + +impl From for chalk_ir::ClosureId { + fn from(id: crate::db::InternedClosureId) -> Self { + chalk_ir::ClosureId(id.as_intern_id()) + } +} diff --git a/crates/hir_ty/src/db.rs b/crates/hir_ty/src/db.rs index 326c20240..ea0580df1 100644 --- a/crates/hir_ty/src/db.rs +++ b/crates/hir_ty/src/db.rs @@ -9,12 +9,7 @@ use hir_def::{ }; use la_arena::ArenaMap; -use crate::{ - method_resolution::{InherentImpls, TraitImpls}, - traits::chalk, - Binders, CallableDefId, FnDefId, ImplTraitId, InferenceResult, PolyFnSig, - QuantifiedWhereClause, ReturnTypeImplTraits, TraitRef, Ty, TyDefId, ValueTyDefId, -}; +use crate::{Binders, CallableDefId, FnDefId, ImplTraitId, InferenceResult, Interner, PolyFnSig, QuantifiedWhereClause, ReturnTypeImplTraits, TraitRef, Ty, TyDefId, ValueTyDefId, chalk_db, method_resolution::{InherentImpls, TraitImpls}}; use hir_expand::name::Name; #[salsa::query_group(HirDatabaseStorage)] @@ -94,33 +89,33 @@ pub trait HirDatabase: DefDatabase + Upcast { #[salsa::interned] fn intern_closure(&self, id: (DefWithBodyId, ExprId)) -> InternedClosureId; - #[salsa::invoke(chalk::associated_ty_data_query)] - fn associated_ty_data(&self, id: chalk::AssocTypeId) -> Arc; + #[salsa::invoke(chalk_db::associated_ty_data_query)] + fn associated_ty_data(&self, id: chalk_db::AssocTypeId) -> Arc; - #[salsa::invoke(chalk::trait_datum_query)] - fn trait_datum(&self, krate: CrateId, trait_id: chalk::TraitId) -> Arc; + #[salsa::invoke(chalk_db::trait_datum_query)] + fn trait_datum(&self, krate: CrateId, trait_id: chalk_db::TraitId) -> Arc; - #[salsa::invoke(chalk::struct_datum_query)] - fn struct_datum(&self, krate: CrateId, struct_id: chalk::AdtId) -> Arc; + #[salsa::invoke(chalk_db::struct_datum_query)] + fn struct_datum(&self, krate: CrateId, struct_id: chalk_db::AdtId) -> Arc; - #[salsa::invoke(crate::traits::chalk::impl_datum_query)] - fn impl_datum(&self, krate: CrateId, impl_id: chalk::ImplId) -> Arc; + #[salsa::invoke(chalk_db::impl_datum_query)] + fn impl_datum(&self, krate: CrateId, impl_id: chalk_db::ImplId) -> Arc; - #[salsa::invoke(crate::traits::chalk::fn_def_datum_query)] - fn fn_def_datum(&self, krate: CrateId, fn_def_id: FnDefId) -> Arc; + #[salsa::invoke(chalk_db::fn_def_datum_query)] + fn fn_def_datum(&self, krate: CrateId, fn_def_id: FnDefId) -> Arc; - #[salsa::invoke(crate::traits::chalk::fn_def_variance_query)] - fn fn_def_variance(&self, krate: CrateId, fn_def_id: FnDefId) -> chalk::Variances; + #[salsa::invoke(chalk_db::fn_def_variance_query)] + fn fn_def_variance(&self, krate: CrateId, fn_def_id: FnDefId) -> chalk_db::Variances; - #[salsa::invoke(crate::traits::chalk::adt_variance_query)] - fn adt_variance(&self, krate: CrateId, adt_id: chalk::AdtId) -> chalk::Variances; + #[salsa::invoke(chalk_db::adt_variance_query)] + fn adt_variance(&self, krate: CrateId, adt_id: chalk_db::AdtId) -> chalk_db::Variances; - #[salsa::invoke(crate::traits::chalk::associated_ty_value_query)] + #[salsa::invoke(chalk_db::associated_ty_value_query)] fn associated_ty_value( &self, krate: CrateId, - id: chalk::AssociatedTyValueId, - ) -> Arc; + id: chalk_db::AssociatedTyValueId, + ) -> Arc; #[salsa::invoke(crate::traits::trait_solve_query)] fn trait_solve( @@ -129,12 +124,12 @@ pub trait HirDatabase: DefDatabase + Upcast { goal: crate::Canonical>, ) -> Option; - #[salsa::invoke(crate::traits::chalk::program_clauses_for_chalk_env_query)] + #[salsa::invoke(chalk_db::program_clauses_for_chalk_env_query)] fn program_clauses_for_chalk_env( &self, krate: CrateId, - env: chalk_ir::Environment, - ) -> chalk_ir::ProgramClauses; + env: chalk_ir::Environment, + ) -> chalk_ir::ProgramClauses; } fn infer_wait(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc { diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index 92224b46b..a0746cd8f 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs @@ -21,7 +21,7 @@ use hir_expand::name::Name; use crate::{ const_from_placeholder_idx, db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, lt_from_placeholder_idx, primitive, subst_prefix, to_assoc_type_id, - traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy, CallableDefId, + chalk_db::from_chalk, utils::generics, AdtId, AliasEq, AliasTy, CallableDefId, CallableSig, Const, ConstValue, DomainGoal, GenericArg, ImplTraitId, Interner, Lifetime, LifetimeData, LifetimeOutlives, Mutability, OpaqueTy, ProjectionTy, ProjectionTyExt, QuantifiedWhereClause, Scalar, TraitRef, TraitRefExt, Ty, TyExt, TyKind, WhereClause, diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 7961f4a52..d42383012 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs @@ -20,7 +20,8 @@ use crate::{ method_resolution, op, primitive::{self, UintTy}, static_lifetime, to_chalk_trait_id, - traits::{chalk::from_chalk, FnTrait}, + traits::FnTrait, + chalk_db::from_chalk, utils::{generics, Generics}, AdtId, Binders, CallableDefId, FnPointer, FnSig, FnSubst, InEnvironment, Interner, ProjectionTyExt, Rawness, Scalar, Substitution, TraitRef, Ty, TyBuilder, TyExt, TyKind, diff --git a/crates/hir_ty/src/interner.rs b/crates/hir_ty/src/interner.rs new file mode 100644 index 000000000..0187767ce --- /dev/null +++ b/crates/hir_ty/src/interner.rs @@ -0,0 +1,405 @@ +//! Implementation of the Chalk `Interner` trait, which allows customizing the +//! representation of the various objects Chalk deals with (types, goals etc.). + +use crate::{GenericArg, tls, chalk_db}; +use base_db::salsa::InternId; +use chalk_ir::{Goal, GoalData}; +use hir_def::{ + intern::{impl_internable, InternStorage, Internable, Interned}, + TypeAliasId, +}; +use smallvec::SmallVec; +use std::{fmt, sync::Arc}; + +#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] +pub struct Interner; + +#[derive(PartialEq, Eq, Hash, Debug)] +pub struct InternedWrapper(T); + +impl std::ops::Deref for InternedWrapper { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl_internable!( + InternedWrapper>>, + InternedWrapper>, + InternedWrapper>, + InternedWrapper>, + InternedWrapper>, + InternedWrapper>>, + InternedWrapper>>, + InternedWrapper>>, + InternedWrapper>, +); + +impl chalk_ir::interner::Interner for Interner { + type InternedType = Interned>>; + type InternedLifetime = Interned>>; + type InternedConst = Interned>>; + type InternedConcreteConst = (); + type InternedGenericArg = chalk_ir::GenericArgData; + type InternedGoal = Arc>; + type InternedGoals = Vec>; + type InternedSubstitution = Interned>>; + type InternedProgramClause = chalk_ir::ProgramClauseData; + type InternedProgramClauses = Interned>>>; + type InternedQuantifiedWhereClauses = + Interned>>>; + type InternedVariableKinds = Interned>>>; + type InternedCanonicalVarKinds = + Interned>>>; + type InternedConstraints = Vec>>; + type InternedVariances = Interned>>; + type DefId = InternId; + type InternedAdtId = hir_def::AdtId; + type Identifier = TypeAliasId; + type FnAbi = (); + + fn debug_adt_id(type_kind_id: chalk_db::AdtId, fmt: &mut fmt::Formatter<'_>) -> Option { + tls::with_current_program(|prog| Some(prog?.debug_struct_id(type_kind_id, fmt))) + } + + fn debug_trait_id(type_kind_id: chalk_db::TraitId, fmt: &mut fmt::Formatter<'_>) -> Option { + tls::with_current_program(|prog| Some(prog?.debug_trait_id(type_kind_id, fmt))) + } + + fn debug_assoc_type_id(id: chalk_db::AssocTypeId, fmt: &mut fmt::Formatter<'_>) -> Option { + tls::with_current_program(|prog| Some(prog?.debug_assoc_type_id(id, fmt))) + } + + fn debug_alias( + alias: &chalk_ir::AliasTy, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + tls::with_current_program(|prog| Some(prog?.debug_alias(alias, fmt))) + } + + fn debug_projection_ty( + proj: &chalk_ir::ProjectionTy, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + tls::with_current_program(|prog| Some(prog?.debug_projection_ty(proj, fmt))) + } + + fn debug_opaque_ty( + opaque_ty: &chalk_ir::OpaqueTy, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + tls::with_current_program(|prog| Some(prog?.debug_opaque_ty(opaque_ty, fmt))) + } + + fn debug_opaque_ty_id( + opaque_ty_id: chalk_ir::OpaqueTyId, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + tls::with_current_program(|prog| Some(prog?.debug_opaque_ty_id(opaque_ty_id, fmt))) + } + + fn debug_ty(ty: &chalk_ir::Ty, fmt: &mut fmt::Formatter<'_>) -> Option { + tls::with_current_program(|prog| Some(prog?.debug_ty(ty, fmt))) + } + + fn debug_lifetime( + lifetime: &chalk_ir::Lifetime, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + tls::with_current_program(|prog| Some(prog?.debug_lifetime(lifetime, fmt))) + } + + fn debug_generic_arg( + parameter: &GenericArg, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + tls::with_current_program(|prog| Some(prog?.debug_generic_arg(parameter, fmt))) + } + + fn debug_goal(goal: &Goal, fmt: &mut fmt::Formatter<'_>) -> Option { + tls::with_current_program(|prog| Some(prog?.debug_goal(goal, fmt))) + } + + fn debug_goals( + goals: &chalk_ir::Goals, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + tls::with_current_program(|prog| Some(prog?.debug_goals(goals, fmt))) + } + + fn debug_program_clause_implication( + pci: &chalk_ir::ProgramClauseImplication, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + tls::with_current_program(|prog| Some(prog?.debug_program_clause_implication(pci, fmt))) + } + + fn debug_substitution( + substitution: &chalk_ir::Substitution, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + tls::with_current_program(|prog| Some(prog?.debug_substitution(substitution, fmt))) + } + + fn debug_separator_trait_ref( + separator_trait_ref: &chalk_ir::SeparatorTraitRef, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + tls::with_current_program(|prog| { + Some(prog?.debug_separator_trait_ref(separator_trait_ref, fmt)) + }) + } + + fn debug_fn_def_id( + fn_def_id: chalk_ir::FnDefId, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + tls::with_current_program(|prog| Some(prog?.debug_fn_def_id(fn_def_id, fmt))) + } + fn debug_const( + constant: &chalk_ir::Const, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + tls::with_current_program(|prog| Some(prog?.debug_const(constant, fmt))) + } + fn debug_variable_kinds( + variable_kinds: &chalk_ir::VariableKinds, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + tls::with_current_program(|prog| Some(prog?.debug_variable_kinds(variable_kinds, fmt))) + } + fn debug_variable_kinds_with_angles( + variable_kinds: &chalk_ir::VariableKinds, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + tls::with_current_program(|prog| { + Some(prog?.debug_variable_kinds_with_angles(variable_kinds, fmt)) + }) + } + fn debug_canonical_var_kinds( + canonical_var_kinds: &chalk_ir::CanonicalVarKinds, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + tls::with_current_program(|prog| { + Some(prog?.debug_canonical_var_kinds(canonical_var_kinds, fmt)) + }) + } + fn debug_program_clause( + clause: &chalk_ir::ProgramClause, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + tls::with_current_program(|prog| Some(prog?.debug_program_clause(clause, fmt))) + } + fn debug_program_clauses( + clauses: &chalk_ir::ProgramClauses, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + tls::with_current_program(|prog| Some(prog?.debug_program_clauses(clauses, fmt))) + } + fn debug_quantified_where_clauses( + clauses: &chalk_ir::QuantifiedWhereClauses, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + tls::with_current_program(|prog| Some(prog?.debug_quantified_where_clauses(clauses, fmt))) + } + + fn intern_ty(&self, kind: chalk_ir::TyKind) -> Self::InternedType { + let flags = kind.compute_flags(self); + Interned::new(InternedWrapper(chalk_ir::TyData { kind, flags })) + } + + fn ty_data<'a>(&self, ty: &'a Self::InternedType) -> &'a chalk_ir::TyData { + &ty.0 + } + + fn intern_lifetime(&self, lifetime: chalk_ir::LifetimeData) -> Self::InternedLifetime { + Interned::new(InternedWrapper(lifetime)) + } + + fn lifetime_data<'a>( + &self, + lifetime: &'a Self::InternedLifetime, + ) -> &'a chalk_ir::LifetimeData { + &lifetime.0 + } + + fn intern_const(&self, constant: chalk_ir::ConstData) -> Self::InternedConst { + Interned::new(InternedWrapper(constant)) + } + + fn const_data<'a>(&self, constant: &'a Self::InternedConst) -> &'a chalk_ir::ConstData { + &constant.0 + } + + fn const_eq( + &self, + _ty: &Self::InternedType, + _c1: &Self::InternedConcreteConst, + _c2: &Self::InternedConcreteConst, + ) -> bool { + true + } + + fn intern_generic_arg( + &self, + parameter: chalk_ir::GenericArgData, + ) -> Self::InternedGenericArg { + parameter + } + + fn generic_arg_data<'a>( + &self, + parameter: &'a Self::InternedGenericArg, + ) -> &'a chalk_ir::GenericArgData { + parameter + } + + fn intern_goal(&self, goal: GoalData) -> Self::InternedGoal { + Arc::new(goal) + } + + fn intern_goals( + &self, + data: impl IntoIterator, E>>, + ) -> Result { + data.into_iter().collect() + } + + fn goal_data<'a>(&self, goal: &'a Self::InternedGoal) -> &'a GoalData { + goal + } + + fn goals_data<'a>(&self, goals: &'a Self::InternedGoals) -> &'a [Goal] { + goals + } + + fn intern_substitution( + &self, + data: impl IntoIterator>, + ) -> Result { + Ok(Interned::new(InternedWrapper(data.into_iter().collect::>()?))) + } + + fn substitution_data<'a>( + &self, + substitution: &'a Self::InternedSubstitution, + ) -> &'a [GenericArg] { + &substitution.as_ref().0 + } + + fn intern_program_clause( + &self, + data: chalk_ir::ProgramClauseData, + ) -> Self::InternedProgramClause { + data + } + + fn program_clause_data<'a>( + &self, + clause: &'a Self::InternedProgramClause, + ) -> &'a chalk_ir::ProgramClauseData { + clause + } + + fn intern_program_clauses( + &self, + data: impl IntoIterator, E>>, + ) -> Result { + Ok(Interned::new(InternedWrapper(data.into_iter().collect::>()?))) + } + + fn program_clauses_data<'a>( + &self, + clauses: &'a Self::InternedProgramClauses, + ) -> &'a [chalk_ir::ProgramClause] { + &clauses + } + + fn intern_quantified_where_clauses( + &self, + data: impl IntoIterator, E>>, + ) -> Result { + Ok(Interned::new(InternedWrapper(data.into_iter().collect::>()?))) + } + + fn quantified_where_clauses_data<'a>( + &self, + clauses: &'a Self::InternedQuantifiedWhereClauses, + ) -> &'a [chalk_ir::QuantifiedWhereClause] { + clauses + } + + fn intern_generic_arg_kinds( + &self, + data: impl IntoIterator, E>>, + ) -> Result { + Ok(Interned::new(InternedWrapper(data.into_iter().collect::>()?))) + } + + fn variable_kinds_data<'a>( + &self, + parameter_kinds: &'a Self::InternedVariableKinds, + ) -> &'a [chalk_ir::VariableKind] { + ¶meter_kinds.as_ref().0 + } + + fn intern_canonical_var_kinds( + &self, + data: impl IntoIterator, E>>, + ) -> Result { + Ok(Interned::new(InternedWrapper(data.into_iter().collect::>()?))) + } + + fn canonical_var_kinds_data<'a>( + &self, + canonical_var_kinds: &'a Self::InternedCanonicalVarKinds, + ) -> &'a [chalk_ir::CanonicalVarKind] { + &canonical_var_kinds + } + + fn intern_constraints( + &self, + data: impl IntoIterator>, E>>, + ) -> Result { + data.into_iter().collect() + } + + fn constraints_data<'a>( + &self, + constraints: &'a Self::InternedConstraints, + ) -> &'a [chalk_ir::InEnvironment>] { + constraints + } + fn debug_closure_id( + _fn_def_id: chalk_ir::ClosureId, + _fmt: &mut fmt::Formatter<'_>, + ) -> Option { + None + } + fn debug_constraints( + _clauses: &chalk_ir::Constraints, + _fmt: &mut fmt::Formatter<'_>, + ) -> Option { + None + } + + fn intern_variances( + &self, + data: impl IntoIterator>, + ) -> Result { + Ok(Interned::new(InternedWrapper(data.into_iter().collect::>()?))) + } + + fn variances_data<'a>( + &self, + variances: &'a Self::InternedVariances, + ) -> &'a [chalk_ir::Variance] { + &variances + } +} + +impl chalk_ir::interner::HasInterner for Interner { + type Interner = Self; +} diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index beb58d711..0743d3d30 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs @@ -18,6 +18,10 @@ mod chalk_cast; mod chalk_ext; mod builder; mod walk; +mod tls; +mod interner; +mod mapping; +mod chalk_db; pub mod display; pub mod db; @@ -51,8 +55,9 @@ pub use lower::{ associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode, TyDefId, TyLoweringContext, ValueTyDefId, }; -pub use traits::{chalk::Interner, TraitEnvironment}; +pub use traits::TraitEnvironment; pub use walk::TypeWalk; +pub use interner::Interner; pub use chalk_ir::{ cast::Cast, AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind, diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index 8a22d9ea3..0cdded3e1 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs @@ -28,7 +28,8 @@ use stdx::impl_from; use crate::{ db::HirDatabase, dummy_usize_const, static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx, - traits::chalk::{Interner, ToChalk}, + chalk_db::ToChalk, + Interner, utils::{ all_super_trait_refs, associated_type_by_name_including_super_traits, generics, Generics, }, diff --git a/crates/hir_ty/src/mapping.rs b/crates/hir_ty/src/mapping.rs new file mode 100644 index 000000000..4d3c41b2c --- /dev/null +++ b/crates/hir_ty/src/mapping.rs @@ -0,0 +1,125 @@ +//! This module contains the implementations of the `ToChalk` trait, which +//! handles conversion between our data types and their corresponding types in +//! Chalk (in both directions); plus some helper functions for more specialized +//! conversions. + +use chalk_ir::{DebruijnIndex, cast::Cast, fold::Shift}; +use chalk_solve::rust_ir; + +use base_db::salsa::InternKey; +use hir_def::{GenericDefId, TypeAliasId}; + +use crate::{AliasEq, AliasTy, CallableDefId, FnDefId, Interner, ProjectionTyExt, QuantifiedWhereClause, Substitution, Ty, WhereClause, chalk_db::{self, ToChalk}, db::HirDatabase}; + +impl ToChalk for hir_def::TraitId { + type Chalk = chalk_db::TraitId; + + fn to_chalk(self, _db: &dyn HirDatabase) -> chalk_db::TraitId { + chalk_ir::TraitId(self.as_intern_id()) + } + + fn from_chalk(_db: &dyn HirDatabase, trait_id: chalk_db::TraitId) -> hir_def::TraitId { + InternKey::from_intern_id(trait_id.0) + } +} + +impl ToChalk for hir_def::ImplId { + type Chalk = chalk_db::ImplId; + + fn to_chalk(self, _db: &dyn HirDatabase) -> chalk_db::ImplId { + chalk_ir::ImplId(self.as_intern_id()) + } + + fn from_chalk(_db: &dyn HirDatabase, impl_id: chalk_db::ImplId) -> hir_def::ImplId { + InternKey::from_intern_id(impl_id.0) + } +} + +impl ToChalk for CallableDefId { + type Chalk = FnDefId; + + fn to_chalk(self, db: &dyn HirDatabase) -> FnDefId { + db.intern_callable_def(self).into() + } + + fn from_chalk(db: &dyn HirDatabase, fn_def_id: FnDefId) -> CallableDefId { + db.lookup_intern_callable_def(fn_def_id.into()) + } +} + +pub(crate) struct TypeAliasAsValue(pub(crate) TypeAliasId); + +impl ToChalk for TypeAliasAsValue { + type Chalk = chalk_db::AssociatedTyValueId; + + fn to_chalk(self, _db: &dyn HirDatabase) -> chalk_db::AssociatedTyValueId { + rust_ir::AssociatedTyValueId(self.0.as_intern_id()) + } + + fn from_chalk( + _db: &dyn HirDatabase, + assoc_ty_value_id: chalk_db::AssociatedTyValueId, + ) -> TypeAliasAsValue { + TypeAliasAsValue(TypeAliasId::from_intern_id(assoc_ty_value_id.0)) + } +} + +pub(super) fn convert_where_clauses( + db: &dyn HirDatabase, + def: GenericDefId, + substs: &Substitution, +) -> Vec> { + let generic_predicates = db.generic_predicates(def); + let mut result = Vec::with_capacity(generic_predicates.len()); + for pred in generic_predicates.iter() { + result.push(pred.clone().substitute(&Interner, substs)); + } + result +} + +pub(super) fn generic_predicate_to_inline_bound( + db: &dyn HirDatabase, + pred: &QuantifiedWhereClause, + self_ty: &Ty, +) -> Option>> { + // An InlineBound is like a GenericPredicate, except the self type is left out. + // We don't have a special type for this, but Chalk does. + let self_ty_shifted_in = self_ty.clone().shifted_in_from(&Interner, DebruijnIndex::ONE); + let (pred, binders) = pred.as_ref().into_value_and_skipped_binders(); + match pred { + WhereClause::Implemented(trait_ref) => { + if trait_ref.self_type_parameter(&Interner) != self_ty_shifted_in { + // we can only convert predicates back to type bounds if they + // have the expected self type + return None; + } + let args_no_self = trait_ref.substitution.as_slice(&Interner)[1..] + .iter() + .map(|ty| ty.clone().cast(&Interner)) + .collect(); + let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self }; + Some(chalk_ir::Binders::new(binders, rust_ir::InlineBound::TraitBound(trait_bound))) + } + WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => { + if projection_ty.self_type_parameter(&Interner) != self_ty_shifted_in { + return None; + } + let trait_ = projection_ty.trait_(db); + let args_no_self = projection_ty.substitution.as_slice(&Interner)[1..] + .iter() + .map(|ty| ty.clone().cast(&Interner)) + .collect(); + let alias_eq_bound = rust_ir::AliasEqBound { + value: ty.clone(), + trait_bound: rust_ir::TraitBound { trait_id: trait_.to_chalk(db), args_no_self }, + associated_ty_id: projection_ty.associated_ty_id, + parameters: Vec::new(), // FIXME we don't support generic associated types yet + }; + Some(chalk_ir::Binders::new( + binders, + rust_ir::InlineBound::AliasEqBound(alias_eq_bound), + )) + } + _ => None, + } +} diff --git a/crates/hir_ty/src/tls.rs b/crates/hir_ty/src/tls.rs new file mode 100644 index 000000000..c319bcf70 --- /dev/null +++ b/crates/hir_ty/src/tls.rs @@ -0,0 +1,274 @@ +//! Implementation of Chalk debug helper functions using TLS. +use std::fmt; + +use chalk_ir::{AliasTy, GenericArg, Goal, Goals, Lifetime, ProgramClauseImplication}; +use itertools::Itertools; + +use crate::{db::HirDatabase, from_assoc_type_id, CallableDefId, chalk_db::{from_chalk, self}, Interner}; +use hir_def::{AdtId, AssocContainerId, Lookup, TypeAliasId}; + +pub(crate) use unsafe_tls::{set_current_program, with_current_program}; + +pub(crate) struct DebugContext<'a>(&'a dyn HirDatabase); + +impl DebugContext<'_> { + pub(crate) fn debug_struct_id( + &self, + id: chalk_db::AdtId, + f: &mut fmt::Formatter<'_>, + ) -> Result<(), fmt::Error> { + let name = match id.0 { + AdtId::StructId(it) => self.0.struct_data(it).name.clone(), + AdtId::UnionId(it) => self.0.union_data(it).name.clone(), + AdtId::EnumId(it) => self.0.enum_data(it).name.clone(), + }; + write!(f, "{}", name) + } + + pub(crate) fn debug_trait_id( + &self, + id: chalk_db::TraitId, + fmt: &mut fmt::Formatter<'_>, + ) -> Result<(), fmt::Error> { + let trait_: hir_def::TraitId = from_chalk(self.0, id); + let trait_data = self.0.trait_data(trait_); + write!(fmt, "{}", trait_data.name) + } + + pub(crate) fn debug_assoc_type_id( + &self, + id: chalk_db::AssocTypeId, + fmt: &mut fmt::Formatter<'_>, + ) -> Result<(), fmt::Error> { + let type_alias: TypeAliasId = from_assoc_type_id(id); + let type_alias_data = self.0.type_alias_data(type_alias); + let trait_ = match type_alias.lookup(self.0.upcast()).container { + AssocContainerId::TraitId(t) => t, + _ => panic!("associated type not in trait"), + }; + let trait_data = self.0.trait_data(trait_); + write!(fmt, "{}::{}", trait_data.name, type_alias_data.name) + } + + pub(crate) fn debug_opaque_ty_id( + &self, + opaque_ty_id: chalk_ir::OpaqueTyId, + fmt: &mut fmt::Formatter<'_>, + ) -> Result<(), fmt::Error> { + fmt.debug_struct("OpaqueTyId").field("index", &opaque_ty_id.0).finish() + } + + pub(crate) fn debug_alias( + &self, + alias_ty: &AliasTy, + fmt: &mut fmt::Formatter<'_>, + ) -> Result<(), fmt::Error> { + match alias_ty { + AliasTy::Projection(projection_ty) => self.debug_projection_ty(projection_ty, fmt), + AliasTy::Opaque(opaque_ty) => self.debug_opaque_ty(opaque_ty, fmt), + } + } + + pub(crate) fn debug_projection_ty( + &self, + projection_ty: &chalk_ir::ProjectionTy, + fmt: &mut fmt::Formatter<'_>, + ) -> Result<(), fmt::Error> { + let type_alias = from_assoc_type_id(projection_ty.associated_ty_id); + let type_alias_data = self.0.type_alias_data(type_alias); + let trait_ = match type_alias.lookup(self.0.upcast()).container { + AssocContainerId::TraitId(t) => t, + _ => panic!("associated type not in trait"), + }; + let trait_data = self.0.trait_data(trait_); + let params = projection_ty.substitution.as_slice(&Interner); + write!(fmt, "<{:?} as {}", ¶ms[0], trait_data.name,)?; + if params.len() > 1 { + write!( + fmt, + "<{}>", + ¶ms[1..].iter().format_with(", ", |x, f| f(&format_args!("{:?}", x))), + )?; + } + write!(fmt, ">::{}", type_alias_data.name) + } + + pub(crate) fn debug_opaque_ty( + &self, + opaque_ty: &chalk_ir::OpaqueTy, + fmt: &mut fmt::Formatter<'_>, + ) -> Result<(), fmt::Error> { + write!(fmt, "{:?}", opaque_ty.opaque_ty_id) + } + + pub(crate) fn debug_ty( + &self, + ty: &chalk_ir::Ty, + fmt: &mut fmt::Formatter<'_>, + ) -> Result<(), fmt::Error> { + write!(fmt, "{:?}", ty.data(&Interner)) + } + + pub(crate) fn debug_lifetime( + &self, + lifetime: &Lifetime, + fmt: &mut fmt::Formatter<'_>, + ) -> Result<(), fmt::Error> { + write!(fmt, "{:?}", lifetime.data(&Interner)) + } + + pub(crate) fn debug_generic_arg( + &self, + parameter: &GenericArg, + fmt: &mut fmt::Formatter<'_>, + ) -> Result<(), fmt::Error> { + write!(fmt, "{:?}", parameter.data(&Interner).inner_debug()) + } + + pub(crate) fn debug_goal( + &self, + goal: &Goal, + fmt: &mut fmt::Formatter<'_>, + ) -> Result<(), fmt::Error> { + let goal_data = goal.data(&Interner); + write!(fmt, "{:?}", goal_data) + } + + pub(crate) fn debug_goals( + &self, + goals: &Goals, + fmt: &mut fmt::Formatter<'_>, + ) -> Result<(), fmt::Error> { + write!(fmt, "{:?}", goals.debug(&Interner)) + } + + pub(crate) fn debug_program_clause_implication( + &self, + pci: &ProgramClauseImplication, + fmt: &mut fmt::Formatter<'_>, + ) -> Result<(), fmt::Error> { + write!(fmt, "{:?}", pci.debug(&Interner)) + } + + pub(crate) fn debug_substitution( + &self, + substitution: &chalk_ir::Substitution, + fmt: &mut fmt::Formatter<'_>, + ) -> Result<(), fmt::Error> { + write!(fmt, "{:?}", substitution.debug(&Interner)) + } + + pub(crate) fn debug_separator_trait_ref( + &self, + separator_trait_ref: &chalk_ir::SeparatorTraitRef, + fmt: &mut fmt::Formatter<'_>, + ) -> Result<(), fmt::Error> { + write!(fmt, "{:?}", separator_trait_ref.debug(&Interner)) + } + + pub(crate) fn debug_fn_def_id( + &self, + fn_def_id: chalk_ir::FnDefId, + fmt: &mut fmt::Formatter<'_>, + ) -> Result<(), fmt::Error> { + let def: CallableDefId = from_chalk(self.0, fn_def_id); + let name = match def { + CallableDefId::FunctionId(ff) => self.0.function_data(ff).name.clone(), + CallableDefId::StructId(s) => self.0.struct_data(s).name.clone(), + CallableDefId::EnumVariantId(e) => { + let enum_data = self.0.enum_data(e.parent); + enum_data.variants[e.local_id].name.clone() + } + }; + match def { + CallableDefId::FunctionId(_) => write!(fmt, "{{fn {}}}", name), + CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_) => { + write!(fmt, "{{ctor {}}}", name) + } + } + } + + pub(crate) fn debug_const( + &self, + _constant: &chalk_ir::Const, + fmt: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + write!(fmt, "const") + } + + pub(crate) fn debug_variable_kinds( + &self, + variable_kinds: &chalk_ir::VariableKinds, + fmt: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + write!(fmt, "{:?}", variable_kinds.as_slice(&Interner)) + } + pub(crate) fn debug_variable_kinds_with_angles( + &self, + variable_kinds: &chalk_ir::VariableKinds, + fmt: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + write!(fmt, "{:?}", variable_kinds.inner_debug(&Interner)) + } + pub(crate) fn debug_canonical_var_kinds( + &self, + canonical_var_kinds: &chalk_ir::CanonicalVarKinds, + fmt: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + write!(fmt, "{:?}", canonical_var_kinds.as_slice(&Interner)) + } + pub(crate) fn debug_program_clause( + &self, + clause: &chalk_ir::ProgramClause, + fmt: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + write!(fmt, "{:?}", clause.data(&Interner)) + } + pub(crate) fn debug_program_clauses( + &self, + clauses: &chalk_ir::ProgramClauses, + fmt: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + write!(fmt, "{:?}", clauses.as_slice(&Interner)) + } + pub(crate) fn debug_quantified_where_clauses( + &self, + clauses: &chalk_ir::QuantifiedWhereClauses, + fmt: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + write!(fmt, "{:?}", clauses.as_slice(&Interner)) + } +} + +mod unsafe_tls { + use super::DebugContext; + use crate::db::HirDatabase; + use scoped_tls::scoped_thread_local; + + scoped_thread_local!(static PROGRAM: DebugContext); + + pub(crate) fn with_current_program( + op: impl for<'a> FnOnce(Option<&'a DebugContext<'a>>) -> R, + ) -> R { + if PROGRAM.is_set() { + PROGRAM.with(|prog| op(Some(prog))) + } else { + op(None) + } + } + + pub(crate) fn set_current_program(p: &dyn HirDatabase, op: OP) -> R + where + OP: FnOnce() -> R, + { + let ctx = DebugContext(p); + // we're transmuting the lifetime in the DebugContext to static. This is + // fine because we only keep the reference for the lifetime of this + // function, *and* the only way to access the context is through + // `with_current_program`, which hides the lifetime through the `for` + // type. + let static_p: &DebugContext<'static> = + unsafe { std::mem::transmute::<&DebugContext, &DebugContext<'static>>(&ctx) }; + PROGRAM.set(static_p, || op()) + } +} diff --git a/crates/hir_ty/src/traits.rs b/crates/hir_ty/src/traits.rs index 1cda72d22..5f8666d90 100644 --- a/crates/hir_ty/src/traits.rs +++ b/crates/hir_ty/src/traits.rs @@ -9,20 +9,16 @@ use stdx::panic_context; use crate::{ db::HirDatabase, AliasEq, AliasTy, Canonical, DomainGoal, Guidance, HirDisplay, InEnvironment, - Solution, TraitRefExt, Ty, TyKind, WhereClause, + Solution, TraitRefExt, Ty, TyKind, WhereClause, Interner, }; -use self::chalk::Interner; - -pub(crate) mod chalk; - /// This controls how much 'time' we give the Chalk solver before giving up. const CHALK_SOLVER_FUEL: i32 = 100; #[derive(Debug, Copy, Clone)] -struct ChalkContext<'a> { - db: &'a dyn HirDatabase, - krate: CrateId, +pub(crate) struct ChalkContext<'a> { + pub(crate) db: &'a dyn HirDatabase, + pub(crate) krate: CrateId, } fn create_chalk_solver() -> chalk_recursive::RecursiveSolver { @@ -148,7 +144,7 @@ fn solve( // don't set the TLS for Chalk unless Chalk debugging is active, to make // extra sure we only use it for debugging let solution = - if is_chalk_debug() { chalk::tls::set_current_program(db, solve) } else { solve() }; + if is_chalk_debug() { crate::tls::set_current_program(db, solve) } else { solve() }; solution } diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs deleted file mode 100644 index cd511477b..000000000 --- a/crates/hir_ty/src/traits/chalk.rs +++ /dev/null @@ -1,716 +0,0 @@ -//! Conversion code from/to Chalk. -use std::sync::Arc; - -use log::debug; - -use chalk_ir::{fold::shift::Shift, CanonicalVarKinds}; -use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait}; - -use base_db::{salsa::InternKey, CrateId}; -use hir_def::{ - lang_item::{lang_attr, LangItemTarget}, - AssocContainerId, AssocItemId, HasModule, Lookup, TypeAliasId, -}; -use hir_expand::name::name; - -use super::ChalkContext; -use crate::{ - db::HirDatabase, - display::HirDisplay, - from_assoc_type_id, make_only_type_binders, - method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS}, - to_assoc_type_id, to_chalk_trait_id, - utils::generics, - AliasEq, AliasTy, BoundVar, CallableDefId, DebruijnIndex, FnDefId, ProjectionTy, Substitution, - TraitRef, TraitRefExt, Ty, TyBuilder, TyExt, TyKind, WhereClause, -}; -use mapping::{convert_where_clauses, generic_predicate_to_inline_bound, TypeAliasAsValue}; - -pub use self::interner::Interner; -pub(crate) use self::interner::*; - -pub(super) mod tls; -mod interner; -mod mapping; - -pub(crate) trait ToChalk { - type Chalk; - fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk; - fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self; -} - -pub(crate) fn from_chalk(db: &dyn HirDatabase, chalk: ChalkT) -> T -where - T: ToChalk, -{ - T::from_chalk(db, chalk) -} - -impl<'a> chalk_solve::RustIrDatabase for ChalkContext<'a> { - fn associated_ty_data(&self, id: AssocTypeId) -> Arc { - self.db.associated_ty_data(id) - } - fn trait_datum(&self, trait_id: TraitId) -> Arc { - self.db.trait_datum(self.krate, trait_id) - } - fn adt_datum(&self, struct_id: AdtId) -> Arc { - self.db.struct_datum(self.krate, struct_id) - } - fn adt_repr(&self, _struct_id: AdtId) -> Arc> { - // FIXME: keep track of these - Arc::new(rust_ir::AdtRepr { c: false, packed: false, int: None }) - } - fn discriminant_type(&self, _ty: chalk_ir::Ty) -> chalk_ir::Ty { - // FIXME: keep track of this - chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Uint(chalk_ir::UintTy::U32)).intern(&Interner) - } - fn impl_datum(&self, impl_id: ImplId) -> Arc { - self.db.impl_datum(self.krate, impl_id) - } - - fn fn_def_datum( - &self, - fn_def_id: chalk_ir::FnDefId, - ) -> Arc> { - self.db.fn_def_datum(self.krate, fn_def_id) - } - - fn impls_for_trait( - &self, - trait_id: TraitId, - parameters: &[chalk_ir::GenericArg], - binders: &CanonicalVarKinds, - ) -> Vec { - debug!("impls_for_trait {:?}", trait_id); - let trait_: hir_def::TraitId = from_chalk(self.db, trait_id); - - let ty: Ty = parameters[0].assert_ty_ref(&Interner).clone(); - - fn binder_kind( - ty: &Ty, - binders: &CanonicalVarKinds, - ) -> Option { - if let TyKind::BoundVar(bv) = ty.kind(&Interner) { - let binders = binders.as_slice(&Interner); - if bv.debruijn == DebruijnIndex::INNERMOST { - if let chalk_ir::VariableKind::Ty(tk) = binders[bv.index].kind { - return Some(tk); - } - } - } - None - } - - let self_ty_fp = TyFingerprint::for_trait_impl(&ty); - let fps: &[TyFingerprint] = match binder_kind(&ty, binders) { - Some(chalk_ir::TyVariableKind::Integer) => &ALL_INT_FPS, - Some(chalk_ir::TyVariableKind::Float) => &ALL_FLOAT_FPS, - _ => self_ty_fp.as_ref().map(std::slice::from_ref).unwrap_or(&[]), - }; - - // Note: Since we're using impls_for_trait, only impls where the trait - // can be resolved should ever reach Chalk. Symbol’s value as variable is void: impl_datum relies on that - // and will panic if the trait can't be resolved. - let in_deps = self.db.trait_impls_in_deps(self.krate); - let in_self = self.db.trait_impls_in_crate(self.krate); - let impl_maps = [in_deps, in_self]; - - let id_to_chalk = |id: hir_def::ImplId| id.to_chalk(self.db); - - let result: Vec<_> = if fps.is_empty() { - debug!("Unrestricted search for {:?} impls...", trait_); - impl_maps - .iter() - .flat_map(|crate_impl_defs| crate_impl_defs.for_trait(trait_).map(id_to_chalk)) - .collect() - } else { - impl_maps - .iter() - .flat_map(|crate_impl_defs| { - fps.iter().flat_map(move |fp| { - crate_impl_defs.for_trait_and_self_ty(trait_, *fp).map(id_to_chalk) - }) - }) - .collect() - }; - - debug!("impls_for_trait returned {} impls", result.len()); - result - } - fn impl_provided_for(&self, auto_trait_id: TraitId, kind: &chalk_ir::TyKind) -> bool { - debug!("impl_provided_for {:?}, {:?}", auto_trait_id, kind); - false // FIXME - } - fn associated_ty_value(&self, id: AssociatedTyValueId) -> Arc { - self.db.associated_ty_value(self.krate, id) - } - - fn custom_clauses(&self) -> Vec> { - vec![] - } - fn local_impls_to_coherence_check(&self, _trait_id: TraitId) -> Vec { - // We don't do coherence checking (yet) - unimplemented!() - } - fn interner(&self) -> &Interner { - &Interner - } - fn well_known_trait_id( - &self, - well_known_trait: rust_ir::WellKnownTrait, - ) -> Option> { - let lang_attr = lang_attr_from_well_known_trait(well_known_trait); - let trait_ = match self.db.lang_item(self.krate, lang_attr.into()) { - Some(LangItemTarget::TraitId(trait_)) => trait_, - _ => return None, - }; - Some(trait_.to_chalk(self.db)) - } - - fn program_clauses_for_env( - &self, - environment: &chalk_ir::Environment, - ) -> chalk_ir::ProgramClauses { - self.db.program_clauses_for_chalk_env(self.krate, environment.clone()) - } - - fn opaque_ty_data(&self, id: chalk_ir::OpaqueTyId) -> Arc { - let full_id = self.db.lookup_intern_impl_trait_id(id.into()); - let bound = match full_id { - crate::ImplTraitId::ReturnTypeImplTrait(func, idx) => { - let datas = self - .db - .return_type_impl_traits(func) - .expect("impl trait id without impl traits"); - let (datas, binders) = (*datas).as_ref().into_value_and_skipped_binders(); - let data = &datas.impl_traits[idx as usize]; - let bound = OpaqueTyDatumBound { - bounds: make_only_type_binders( - 1, - data.bounds.skip_binders().iter().cloned().collect(), - ), - where_clauses: make_only_type_binders(0, vec![]), - }; - chalk_ir::Binders::new(binders, bound) - } - crate::ImplTraitId::AsyncBlockTypeImplTrait(..) => { - if let Some((future_trait, future_output)) = self - .db - .lang_item(self.krate, "future_trait".into()) - .and_then(|item| item.as_trait()) - .and_then(|trait_| { - let alias = - self.db.trait_data(trait_).associated_type_by_name(&name![Output])?; - Some((trait_, alias)) - }) - { - // Making up Symbol’s value as variable is void: AsyncBlock: - // - // |--------------------OpaqueTyDatum-------------------| - // |-------------OpaqueTyDatumBound--------------| - // for [Future, Future::Output = T] - // ^1 ^0 ^0 ^0 ^1 - let impl_bound = WhereClause::Implemented(TraitRef { - trait_id: to_chalk_trait_id(future_trait), - // Self type as the first parameter. - substitution: Substitution::from1( - &Interner, - TyKind::BoundVar(BoundVar { - debruijn: DebruijnIndex::INNERMOST, - index: 0, - }) - .intern(&Interner), - ), - }); - let proj_bound = WhereClause::AliasEq(AliasEq { - alias: AliasTy::Projection(ProjectionTy { - associated_ty_id: to_assoc_type_id(future_output), - // Self type as the first parameter. - substitution: Substitution::from1( - &Interner, - TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)) - .intern(&Interner), - ), - }), - // The parameter of the opaque type. - ty: TyKind::BoundVar(BoundVar { debruijn: DebruijnIndex::ONE, index: 0 }) - .intern(&Interner), - }); - let bound = OpaqueTyDatumBound { - bounds: make_only_type_binders( - 1, - vec![ - crate::wrap_empty_binders(impl_bound), - crate::wrap_empty_binders(proj_bound), - ], - ), - where_clauses: make_only_type_binders(0, vec![]), - }; - // The opaque type has 1 parameter. - make_only_type_binders(1, bound) - } else { - // If failed to find Symbol’s value as variable is void: Future::Output, return empty bounds as fallback. - let bound = OpaqueTyDatumBound { - bounds: make_only_type_binders(0, vec![]), - where_clauses: make_only_type_binders(0, vec![]), - }; - // The opaque type has 1 parameter. - make_only_type_binders(1, bound) - } - } - }; - - Arc::new(OpaqueTyDatum { opaque_ty_id: id, bound }) - } - - fn hidden_opaque_type(&self, _id: chalk_ir::OpaqueTyId) -> chalk_ir::Ty { - // FIXME: actually provide the hidden type; it is relevant for auto traits - TyKind::Error.intern(&Interner) - } - - fn is_object_safe(&self, _trait_id: chalk_ir::TraitId) -> bool { - // FIXME: implement actual object safety - true - } - - fn closure_kind( - &self, - _closure_id: chalk_ir::ClosureId, - _substs: &chalk_ir::Substitution, - ) -> rust_ir::ClosureKind { - // Fn is the closure kind that implements all three traits - rust_ir::ClosureKind::Fn - } - fn closure_inputs_and_output( - &self, - _closure_id: chalk_ir::ClosureId, - substs: &chalk_ir::Substitution, - ) -> chalk_ir::Binders> { - let sig_ty = substs.at(&Interner, 0).assert_ty_ref(&Interner).clone(); - let sig = &sig_ty.callable_sig(self.db).expect("first closure param should be fn ptr"); - let io = rust_ir::FnDefInputsAndOutputDatum { - argument_types: sig.params().iter().cloned().collect(), - return_type: sig.ret().clone(), - }; - make_only_type_binders(0, io.shifted_in(&Interner)) - } - fn closure_upvars( - &self, - _closure_id: chalk_ir::ClosureId, - _substs: &chalk_ir::Substitution, - ) -> chalk_ir::Binders> { - let ty = TyBuilder::unit(); - make_only_type_binders(0, ty) - } - fn closure_fn_substitution( - &self, - _closure_id: chalk_ir::ClosureId, - _substs: &chalk_ir::Substitution, - ) -> chalk_ir::Substitution { - Substitution::empty(&Interner) - } - - fn trait_name(&self, trait_id: chalk_ir::TraitId) -> String { - let id = from_chalk(self.db, trait_id); - self.db.trait_data(id).name.to_string() - } - fn adt_name(&self, chalk_ir::AdtId(adt_id): AdtId) -> String { - match adt_id { - hir_def::AdtId::StructId(id) => self.db.struct_data(id).name.to_string(), - hir_def::AdtId::EnumId(id) => self.db.enum_data(id).name.to_string(), - hir_def::AdtId::UnionId(id) => self.db.union_data(id).name.to_string(), - } - } - fn assoc_type_name(&self, assoc_ty_id: chalk_ir::AssocTypeId) -> String { - let id = self.db.associated_ty_data(assoc_ty_id).name; - self.db.type_alias_data(id).name.to_string() - } - fn opaque_type_name(&self, opaque_ty_id: chalk_ir::OpaqueTyId) -> String { - format!("Opaque_{}", opaque_ty_id.0) - } - fn fn_def_name(&self, fn_def_id: chalk_ir::FnDefId) -> String { - format!("fn_{}", fn_def_id.0) - } - fn generator_datum( - &self, - _: chalk_ir::GeneratorId, - ) -> std::sync::Arc> { - // FIXME - unimplemented!() - } - fn generator_witness_datum( - &self, - _: chalk_ir::GeneratorId, - ) -> std::sync::Arc> { - // FIXME - unimplemented!() - } - - fn unification_database(&self) -> &dyn chalk_ir::UnificationDatabase { - self - } -} - -impl<'a> chalk_ir::UnificationDatabase for ChalkContext<'a> { - fn fn_def_variance( - &self, - fn_def_id: chalk_ir::FnDefId, - ) -> chalk_ir::Variances { - self.db.fn_def_variance(self.krate, fn_def_id) - } - - fn adt_variance(&self, adt_id: chalk_ir::AdtId) -> chalk_ir::Variances { - self.db.adt_variance(self.krate, adt_id) - } -} - -pub(crate) fn program_clauses_for_chalk_env_query( - db: &dyn HirDatabase, - krate: CrateId, - environment: chalk_ir::Environment, -) -> chalk_ir::ProgramClauses { - chalk_solve::program_clauses_for_env(&ChalkContext { db, krate }, &environment) -} - -pub(crate) fn associated_ty_data_query( - db: &dyn HirDatabase, - id: AssocTypeId, -) -> Arc { - debug!("associated_ty_data {:?}", id); - let type_alias: TypeAliasId = from_assoc_type_id(id); - let trait_ = match type_alias.lookup(db.upcast()).container { - AssocContainerId::TraitId(t) => t, - _ => panic!("associated type not in trait"), - }; - - // Lower bounds -- we could/should maybe move this to a separate query in `lower` - let type_alias_data = db.type_alias_data(type_alias); - let generic_params = generics(db.upcast(), type_alias.into()); - let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST); - let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db.upcast()); - let ctx = crate::TyLoweringContext::new(db, &resolver) - .with_type_param_mode(crate::lower::TypeParamLoweringMode::Variable); - let self_ty = - TyKind::BoundVar(BoundVar::new(crate::DebruijnIndex::INNERMOST, 0)).intern(&Interner); - let bounds = type_alias_data - .bounds - .iter() - .flat_map(|bound| ctx.lower_type_bound(bound, self_ty.clone(), false)) - .filter_map(|pred| generic_predicate_to_inline_bound(db, &pred, &self_ty)) - .collect(); - - let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars); - let bound_data = rust_ir::AssociatedTyDatumBound { bounds, where_clauses }; - let datum = AssociatedTyDatum { - trait_id: to_chalk_trait_id(trait_), - id, - name: type_alias, - binders: make_only_type_binders(generic_params.len(), bound_data), - }; - Arc::new(datum) -} - -pub(crate) fn trait_datum_query( - db: &dyn HirDatabase, - krate: CrateId, - trait_id: TraitId, -) -> Arc { - debug!("trait_datum {:?}", trait_id); - let trait_: hir_def::TraitId = from_chalk(db, trait_id); - let trait_data = db.trait_data(trait_); - debug!("trait {:?} = {:?}", trait_id, trait_data.name); - let generic_params = generics(db.upcast(), trait_.into()); - let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST); - let flags = rust_ir::TraitFlags { - auto: trait_data.is_auto, - upstream: trait_.lookup(db.upcast()).container.krate() != krate, - non_enumerable: true, - coinductive: false, // only relevant for Chalk testing - // FIXME: set these flags correctly - marker: false, - fundamental: false, - }; - let where_clauses = convert_where_clauses(db, trait_.into(), &bound_vars); - let associated_ty_ids = - trait_data.associated_types().map(|type_alias| to_assoc_type_id(type_alias)).collect(); - let trait_datum_bound = rust_ir::TraitDatumBound { where_clauses }; - let well_known = - lang_attr(db.upcast(), trait_).and_then(|name| well_known_trait_from_lang_attr(&name)); - let trait_datum = TraitDatum { - id: trait_id, - binders: make_only_type_binders(bound_vars.len(&Interner), trait_datum_bound), - flags, - associated_ty_ids, - well_known, - }; - Arc::new(trait_datum) -} - -fn well_known_trait_from_lang_attr(name: &str) -> Option { - Some(match name { - "sized" => WellKnownTrait::Sized, - "copy" => WellKnownTrait::Copy, - "clone" => WellKnownTrait::Clone, - "drop" => WellKnownTrait::Drop, - "fn_once" => WellKnownTrait::FnOnce, - "fn_mut" => WellKnownTrait::FnMut, - "fn" => WellKnownTrait::Fn, - "unsize" => WellKnownTrait::Unsize, - "coerce_unsized" => WellKnownTrait::CoerceUnsized, - "discriminant_kind" => WellKnownTrait::DiscriminantKind, - _ => return None, - }) -} - -fn lang_attr_from_well_known_trait(attr: WellKnownTrait) -> &'static str { - match attr { - WellKnownTrait::Sized => "sized", - WellKnownTrait::Copy => "copy", - WellKnownTrait::Clone => "clone", - WellKnownTrait::Drop => "drop", - WellKnownTrait::FnOnce => "fn_once", - WellKnownTrait::FnMut => "fn_mut", - WellKnownTrait::Fn => "fn", - WellKnownTrait::Unsize => "unsize", - WellKnownTrait::Unpin => "unpin", - WellKnownTrait::CoerceUnsized => "coerce_unsized", - WellKnownTrait::DiscriminantKind => "discriminant_kind", - } -} - -pub(crate) fn struct_datum_query( - db: &dyn HirDatabase, - krate: CrateId, - struct_id: AdtId, -) -> Arc { - debug!("struct_datum {:?}", struct_id); - let chalk_ir::AdtId(adt_id) = struct_id; - let num_params = generics(db.upcast(), adt_id.into()).len(); - let upstream = adt_id.module(db.upcast()).krate() != krate; - let where_clauses = { - let generic_params = generics(db.upcast(), adt_id.into()); - let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST); - convert_where_clauses(db, adt_id.into(), &bound_vars) - }; - let flags = rust_ir::AdtFlags { - upstream, - // FIXME set fundamental and phantom_data flags correctly - fundamental: false, - phantom_data: false, - }; - // FIXME provide enum variants properly (for auto traits) - let variant = rust_ir::AdtVariantDatum { - fields: Vec::new(), // FIXME add fields (only relevant for auto traits), - }; - let struct_datum_bound = rust_ir::AdtDatumBound { variants: vec![variant], where_clauses }; - let struct_datum = StructDatum { - // FIXME set ADT kind - kind: rust_ir::AdtKind::Struct, - id: struct_id, - binders: make_only_type_binders(num_params, struct_datum_bound), - flags, - }; - Arc::new(struct_datum) -} - -pub(crate) fn impl_datum_query( - db: &dyn HirDatabase, - krate: CrateId, - impl_id: ImplId, -) -> Arc { - let _p = profile::span("impl_datum"); - debug!("impl_datum {:?}", impl_id); - let impl_: hir_def::ImplId = from_chalk(db, impl_id); - impl_def_datum(db, krate, impl_id, impl_) -} - -fn impl_def_datum( - db: &dyn HirDatabase, - krate: CrateId, - chalk_id: ImplId, - impl_id: hir_def::ImplId, -) -> Arc { - let trait_ref = db - .impl_trait(impl_id) - // ImplIds for impls where the trait ref can't be resolved should never reach Chalk - .expect("invalid impl passed to Chalk") - .into_value_and_skipped_binders() - .0; - let impl_data = db.impl_data(impl_id); - - let generic_params = generics(db.upcast(), impl_id.into()); - let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST); - let trait_ = trait_ref.hir_trait_id(); - let impl_type = if impl_id.lookup(db.upcast()).container.krate() == krate { - rust_ir::ImplType::Local - } else { - rust_ir::ImplType::External - }; - let where_clauses = convert_where_clauses(db, impl_id.into(), &bound_vars); - let negative = impl_data.is_negative; - debug!( - "impl {:?}: {}{} where {:?}", - chalk_id, - if negative { "!" } else { "" }, - trait_ref.display(db), - where_clauses - ); - - let polarity = if negative { rust_ir::Polarity::Negative } else { rust_ir::Polarity::Positive }; - - let impl_datum_bound = rust_ir::ImplDatumBound { trait_ref, where_clauses }; - let trait_data = db.trait_data(trait_); - let associated_ty_value_ids = impl_data - .items - .iter() - .filter_map(|item| match item { - AssocItemId::TypeAliasId(type_alias) => Some(*type_alias), - _ => None, - }) - .filter(|&type_alias| { - // don't include associated types that don't exist in the trait - let name = &db.type_alias_data(type_alias).name; - trait_data.associated_type_by_name(name).is_some() - }) - .map(|type_alias| TypeAliasAsValue(type_alias).to_chalk(db)) - .collect(); - debug!("impl_datum: {:?}", impl_datum_bound); - let impl_datum = ImplDatum { - binders: make_only_type_binders(bound_vars.len(&Interner), impl_datum_bound), - impl_type, - polarity, - associated_ty_value_ids, - }; - Arc::new(impl_datum) -} - -pub(crate) fn associated_ty_value_query( - db: &dyn HirDatabase, - krate: CrateId, - id: AssociatedTyValueId, -) -> Arc { - let type_alias: TypeAliasAsValue = from_chalk(db, id); - type_alias_associated_ty_value(db, krate, type_alias.0) -} - -fn type_alias_associated_ty_value( - db: &dyn HirDatabase, - _krate: CrateId, - type_alias: TypeAliasId, -) -> Arc { - let type_alias_data = db.type_alias_data(type_alias); - let impl_id = match type_alias.lookup(db.upcast()).container { - AssocContainerId::ImplId(it) => it, - _ => panic!("assoc ty value should be in impl"), - }; - - let trait_ref = db - .impl_trait(impl_id) - .expect("assoc ty value should not exist") - .into_value_and_skipped_binders() - .0; // we don't return any assoc ty values if the impl'd trait can't be resolved - - let assoc_ty = db - .trait_data(trait_ref.hir_trait_id()) - .associated_type_by_name(&type_alias_data.name) - .expect("assoc ty value should not exist"); // validated when building the impl data as well - let (ty, binders) = db.ty(type_alias.into()).into_value_and_skipped_binders(); - let value_bound = rust_ir::AssociatedTyValueBound { ty }; - let value = rust_ir::AssociatedTyValue { - impl_id: impl_id.to_chalk(db), - associated_ty_id: to_assoc_type_id(assoc_ty), - value: chalk_ir::Binders::new(binders, value_bound), - }; - Arc::new(value) -} - -pub(crate) fn fn_def_datum_query( - db: &dyn HirDatabase, - _krate: CrateId, - fn_def_id: FnDefId, -) -> Arc { - let callable_def: CallableDefId = from_chalk(db, fn_def_id); - let generic_params = generics(db.upcast(), callable_def.into()); - let (sig, binders) = db.callable_item_signature(callable_def).into_value_and_skipped_binders(); - let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST); - let where_clauses = convert_where_clauses(db, callable_def.into(), &bound_vars); - let bound = rust_ir::FnDefDatumBound { - // Note: Chalk doesn't actually use this information yet as far as I am aware, but we provide it anyway - inputs_and_output: make_only_type_binders( - 0, - rust_ir::FnDefInputsAndOutputDatum { - argument_types: sig.params().iter().cloned().collect(), - return_type: sig.ret().clone(), - } - .shifted_in(&Interner), - ), - where_clauses, - }; - let datum = FnDefDatum { - id: fn_def_id, - sig: chalk_ir::FnSig { abi: (), safety: chalk_ir::Safety::Safe, variadic: sig.is_varargs }, - binders: chalk_ir::Binders::new(binders, bound), - }; - Arc::new(datum) -} - -pub(crate) fn fn_def_variance_query( - db: &dyn HirDatabase, - _krate: CrateId, - fn_def_id: FnDefId, -) -> Variances { - let callable_def: CallableDefId = from_chalk(db, fn_def_id); - let generic_params = generics(db.upcast(), callable_def.into()); - Variances::from_iter( - &Interner, - std::iter::repeat(chalk_ir::Variance::Invariant).take(generic_params.len()), - ) -} - -pub(crate) fn adt_variance_query( - db: &dyn HirDatabase, - _krate: CrateId, - chalk_ir::AdtId(adt_id): AdtId, -) -> Variances { - let generic_params = generics(db.upcast(), adt_id.into()); - Variances::from_iter( - &Interner, - std::iter::repeat(chalk_ir::Variance::Invariant).take(generic_params.len()), - ) -} - -impl From for crate::db::InternedCallableDefId { - fn from(fn_def_id: FnDefId) -> Self { - InternKey::from_intern_id(fn_def_id.0) - } -} - -impl From for FnDefId { - fn from(callable_def_id: crate::db::InternedCallableDefId) -> Self { - chalk_ir::FnDefId(callable_def_id.as_intern_id()) - } -} - -impl From for crate::db::InternedOpaqueTyId { - fn from(id: OpaqueTyId) -> Self { - InternKey::from_intern_id(id.0) - } -} - -impl From for OpaqueTyId { - fn from(id: crate::db::InternedOpaqueTyId) -> Self { - chalk_ir::OpaqueTyId(id.as_intern_id()) - } -} - -impl From> for crate::db::InternedClosureId { - fn from(id: chalk_ir::ClosureId) -> Self { - Self::from_intern_id(id.0) - } -} - -impl From for chalk_ir::ClosureId { - fn from(id: crate::db::InternedClosureId) -> Self { - chalk_ir::ClosureId(id.as_intern_id()) - } -} diff --git a/crates/hir_ty/src/traits/chalk/interner.rs b/crates/hir_ty/src/traits/chalk/interner.rs deleted file mode 100644 index b6a3cec6d..000000000 --- a/crates/hir_ty/src/traits/chalk/interner.rs +++ /dev/null @@ -1,421 +0,0 @@ -//! Implementation of the Chalk `Interner` trait, which allows customizing the -//! representation of the various objects Chalk deals with (types, goals etc.). - -use super::tls; -use crate::GenericArg; -use base_db::salsa::InternId; -use chalk_ir::{Goal, GoalData}; -use hir_def::{ - intern::{impl_internable, InternStorage, Internable, Interned}, - TypeAliasId, -}; -use smallvec::SmallVec; -use std::{fmt, sync::Arc}; - -#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] -pub struct Interner; - -pub(crate) type AssocTypeId = chalk_ir::AssocTypeId; -pub(crate) type AssociatedTyDatum = chalk_solve::rust_ir::AssociatedTyDatum; -pub(crate) type TraitId = chalk_ir::TraitId; -pub(crate) type TraitDatum = chalk_solve::rust_ir::TraitDatum; -pub(crate) type AdtId = chalk_ir::AdtId; -pub(crate) type StructDatum = chalk_solve::rust_ir::AdtDatum; -pub(crate) type ImplId = chalk_ir::ImplId; -pub(crate) type ImplDatum = chalk_solve::rust_ir::ImplDatum; -pub(crate) type AssociatedTyValueId = chalk_solve::rust_ir::AssociatedTyValueId; -pub(crate) type AssociatedTyValue = chalk_solve::rust_ir::AssociatedTyValue; -pub(crate) type FnDefDatum = chalk_solve::rust_ir::FnDefDatum; -pub(crate) type OpaqueTyId = chalk_ir::OpaqueTyId; -pub(crate) type OpaqueTyDatum = chalk_solve::rust_ir::OpaqueTyDatum; -pub(crate) type Variances = chalk_ir::Variances; - -#[derive(PartialEq, Eq, Hash, Debug)] -pub struct InternedWrapper(T); - -impl std::ops::Deref for InternedWrapper { - type Target = T; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl_internable!( - InternedWrapper>>, - InternedWrapper>, - InternedWrapper>, - InternedWrapper>, - InternedWrapper>, - InternedWrapper>>, - InternedWrapper>>, - InternedWrapper>>, - InternedWrapper>, -); - -impl chalk_ir::interner::Interner for Interner { - type InternedType = Interned>>; - type InternedLifetime = Interned>>; - type InternedConst = Interned>>; - type InternedConcreteConst = (); - type InternedGenericArg = chalk_ir::GenericArgData; - type InternedGoal = Arc>; - type InternedGoals = Vec>; - type InternedSubstitution = Interned>>; - type InternedProgramClause = chalk_ir::ProgramClauseData; - type InternedProgramClauses = Interned>>>; - type InternedQuantifiedWhereClauses = - Interned>>>; - type InternedVariableKinds = Interned>>>; - type InternedCanonicalVarKinds = - Interned>>>; - type InternedConstraints = Vec>>; - type InternedVariances = Interned>>; - type DefId = InternId; - type InternedAdtId = hir_def::AdtId; - type Identifier = TypeAliasId; - type FnAbi = (); - - fn debug_adt_id(type_kind_id: AdtId, fmt: &mut fmt::Formatter<'_>) -> Option { - tls::with_current_program(|prog| Some(prog?.debug_struct_id(type_kind_id, fmt))) - } - - fn debug_trait_id(type_kind_id: TraitId, fmt: &mut fmt::Formatter<'_>) -> Option { - tls::with_current_program(|prog| Some(prog?.debug_trait_id(type_kind_id, fmt))) - } - - fn debug_assoc_type_id(id: AssocTypeId, fmt: &mut fmt::Formatter<'_>) -> Option { - tls::with_current_program(|prog| Some(prog?.debug_assoc_type_id(id, fmt))) - } - - fn debug_alias( - alias: &chalk_ir::AliasTy, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - tls::with_current_program(|prog| Some(prog?.debug_alias(alias, fmt))) - } - - fn debug_projection_ty( - proj: &chalk_ir::ProjectionTy, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - tls::with_current_program(|prog| Some(prog?.debug_projection_ty(proj, fmt))) - } - - fn debug_opaque_ty( - opaque_ty: &chalk_ir::OpaqueTy, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - tls::with_current_program(|prog| Some(prog?.debug_opaque_ty(opaque_ty, fmt))) - } - - fn debug_opaque_ty_id( - opaque_ty_id: chalk_ir::OpaqueTyId, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - tls::with_current_program(|prog| Some(prog?.debug_opaque_ty_id(opaque_ty_id, fmt))) - } - - fn debug_ty(ty: &chalk_ir::Ty, fmt: &mut fmt::Formatter<'_>) -> Option { - tls::with_current_program(|prog| Some(prog?.debug_ty(ty, fmt))) - } - - fn debug_lifetime( - lifetime: &chalk_ir::Lifetime, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - tls::with_current_program(|prog| Some(prog?.debug_lifetime(lifetime, fmt))) - } - - fn debug_generic_arg( - parameter: &GenericArg, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - tls::with_current_program(|prog| Some(prog?.debug_generic_arg(parameter, fmt))) - } - - fn debug_goal(goal: &Goal, fmt: &mut fmt::Formatter<'_>) -> Option { - tls::with_current_program(|prog| Some(prog?.debug_goal(goal, fmt))) - } - - fn debug_goals( - goals: &chalk_ir::Goals, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - tls::with_current_program(|prog| Some(prog?.debug_goals(goals, fmt))) - } - - fn debug_program_clause_implication( - pci: &chalk_ir::ProgramClauseImplication, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - tls::with_current_program(|prog| Some(prog?.debug_program_clause_implication(pci, fmt))) - } - - fn debug_substitution( - substitution: &chalk_ir::Substitution, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - tls::with_current_program(|prog| Some(prog?.debug_substitution(substitution, fmt))) - } - - fn debug_separator_trait_ref( - separator_trait_ref: &chalk_ir::SeparatorTraitRef, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - tls::with_current_program(|prog| { - Some(prog?.debug_separator_trait_ref(separator_trait_ref, fmt)) - }) - } - - fn debug_fn_def_id( - fn_def_id: chalk_ir::FnDefId, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - tls::with_current_program(|prog| Some(prog?.debug_fn_def_id(fn_def_id, fmt))) - } - fn debug_const( - constant: &chalk_ir::Const, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - tls::with_current_program(|prog| Some(prog?.debug_const(constant, fmt))) - } - fn debug_variable_kinds( - variable_kinds: &chalk_ir::VariableKinds, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - tls::with_current_program(|prog| Some(prog?.debug_variable_kinds(variable_kinds, fmt))) - } - fn debug_variable_kinds_with_angles( - variable_kinds: &chalk_ir::VariableKinds, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - tls::with_current_program(|prog| { - Some(prog?.debug_variable_kinds_with_angles(variable_kinds, fmt)) - }) - } - fn debug_canonical_var_kinds( - canonical_var_kinds: &chalk_ir::CanonicalVarKinds, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - tls::with_current_program(|prog| { - Some(prog?.debug_canonical_var_kinds(canonical_var_kinds, fmt)) - }) - } - fn debug_program_clause( - clause: &chalk_ir::ProgramClause, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - tls::with_current_program(|prog| Some(prog?.debug_program_clause(clause, fmt))) - } - fn debug_program_clauses( - clauses: &chalk_ir::ProgramClauses, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - tls::with_current_program(|prog| Some(prog?.debug_program_clauses(clauses, fmt))) - } - fn debug_quantified_where_clauses( - clauses: &chalk_ir::QuantifiedWhereClauses, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - tls::with_current_program(|prog| Some(prog?.debug_quantified_where_clauses(clauses, fmt))) - } - - fn intern_ty(&self, kind: chalk_ir::TyKind) -> Self::InternedType { - let flags = kind.compute_flags(self); - Interned::new(InternedWrapper(chalk_ir::TyData { kind, flags })) - } - - fn ty_data<'a>(&self, ty: &'a Self::InternedType) -> &'a chalk_ir::TyData { - &ty.0 - } - - fn intern_lifetime(&self, lifetime: chalk_ir::LifetimeData) -> Self::InternedLifetime { - Interned::new(InternedWrapper(lifetime)) - } - - fn lifetime_data<'a>( - &self, - lifetime: &'a Self::InternedLifetime, - ) -> &'a chalk_ir::LifetimeData { - &lifetime.0 - } - - fn intern_const(&self, constant: chalk_ir::ConstData) -> Self::InternedConst { - Interned::new(InternedWrapper(constant)) - } - - fn const_data<'a>(&self, constant: &'a Self::InternedConst) -> &'a chalk_ir::ConstData { - &constant.0 - } - - fn const_eq( - &self, - _ty: &Self::InternedType, - _c1: &Self::InternedConcreteConst, - _c2: &Self::InternedConcreteConst, - ) -> bool { - true - } - - fn intern_generic_arg( - &self, - parameter: chalk_ir::GenericArgData, - ) -> Self::InternedGenericArg { - parameter - } - - fn generic_arg_data<'a>( - &self, - parameter: &'a Self::InternedGenericArg, - ) -> &'a chalk_ir::GenericArgData { - parameter - } - - fn intern_goal(&self, goal: GoalData) -> Self::InternedGoal { - Arc::new(goal) - } - - fn intern_goals( - &self, - data: impl IntoIterator, E>>, - ) -> Result { - data.into_iter().collect() - } - - fn goal_data<'a>(&self, goal: &'a Self::InternedGoal) -> &'a GoalData { - goal - } - - fn goals_data<'a>(&self, goals: &'a Self::InternedGoals) -> &'a [Goal] { - goals - } - - fn intern_substitution( - &self, - data: impl IntoIterator>, - ) -> Result { - Ok(Interned::new(InternedWrapper(data.into_iter().collect::>()?))) - } - - fn substitution_data<'a>( - &self, - substitution: &'a Self::InternedSubstitution, - ) -> &'a [GenericArg] { - &substitution.as_ref().0 - } - - fn intern_program_clause( - &self, - data: chalk_ir::ProgramClauseData, - ) -> Self::InternedProgramClause { - data - } - - fn program_clause_data<'a>( - &self, - clause: &'a Self::InternedProgramClause, - ) -> &'a chalk_ir::ProgramClauseData { - clause - } - - fn intern_program_clauses( - &self, - data: impl IntoIterator, E>>, - ) -> Result { - Ok(Interned::new(InternedWrapper(data.into_iter().collect::>()?))) - } - - fn program_clauses_data<'a>( - &self, - clauses: &'a Self::InternedProgramClauses, - ) -> &'a [chalk_ir::ProgramClause] { - &clauses - } - - fn intern_quantified_where_clauses( - &self, - data: impl IntoIterator, E>>, - ) -> Result { - Ok(Interned::new(InternedWrapper(data.into_iter().collect::>()?))) - } - - fn quantified_where_clauses_data<'a>( - &self, - clauses: &'a Self::InternedQuantifiedWhereClauses, - ) -> &'a [chalk_ir::QuantifiedWhereClause] { - clauses - } - - fn intern_generic_arg_kinds( - &self, - data: impl IntoIterator, E>>, - ) -> Result { - Ok(Interned::new(InternedWrapper(data.into_iter().collect::>()?))) - } - - fn variable_kinds_data<'a>( - &self, - parameter_kinds: &'a Self::InternedVariableKinds, - ) -> &'a [chalk_ir::VariableKind] { - ¶meter_kinds.as_ref().0 - } - - fn intern_canonical_var_kinds( - &self, - data: impl IntoIterator, E>>, - ) -> Result { - Ok(Interned::new(InternedWrapper(data.into_iter().collect::>()?))) - } - - fn canonical_var_kinds_data<'a>( - &self, - canonical_var_kinds: &'a Self::InternedCanonicalVarKinds, - ) -> &'a [chalk_ir::CanonicalVarKind] { - &canonical_var_kinds - } - - fn intern_constraints( - &self, - data: impl IntoIterator>, E>>, - ) -> Result { - data.into_iter().collect() - } - - fn constraints_data<'a>( - &self, - constraints: &'a Self::InternedConstraints, - ) -> &'a [chalk_ir::InEnvironment>] { - constraints - } - fn debug_closure_id( - _fn_def_id: chalk_ir::ClosureId, - _fmt: &mut fmt::Formatter<'_>, - ) -> Option { - None - } - fn debug_constraints( - _clauses: &chalk_ir::Constraints, - _fmt: &mut fmt::Formatter<'_>, - ) -> Option { - None - } - - fn intern_variances( - &self, - data: impl IntoIterator>, - ) -> Result { - Ok(Interned::new(InternedWrapper(data.into_iter().collect::>()?))) - } - - fn variances_data<'a>( - &self, - variances: &'a Self::InternedVariances, - ) -> &'a [chalk_ir::Variance] { - &variances - } -} - -impl chalk_ir::interner::HasInterner for Interner { - type Interner = Self; -} diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs deleted file mode 100644 index e78581ea5..000000000 --- a/crates/hir_ty/src/traits/chalk/mapping.rs +++ /dev/null @@ -1,131 +0,0 @@ -//! This module contains the implementations of the `ToChalk` trait, which -//! handles conversion between our data types and their corresponding types in -//! Chalk (in both directions); plus some helper functions for more specialized -//! conversions. - -use chalk_ir::cast::Cast; -use chalk_solve::rust_ir; - -use base_db::salsa::InternKey; -use hir_def::{GenericDefId, TypeAliasId}; - -use crate::{ - db::HirDatabase, AliasTy, CallableDefId, ProjectionTyExt, QuantifiedWhereClause, Substitution, - Ty, WhereClause, -}; - -use super::interner::*; -use super::*; - -impl ToChalk for hir_def::TraitId { - type Chalk = TraitId; - - fn to_chalk(self, _db: &dyn HirDatabase) -> TraitId { - chalk_ir::TraitId(self.as_intern_id()) - } - - fn from_chalk(_db: &dyn HirDatabase, trait_id: TraitId) -> hir_def::TraitId { - InternKey::from_intern_id(trait_id.0) - } -} - -impl ToChalk for hir_def::ImplId { - type Chalk = ImplId; - - fn to_chalk(self, _db: &dyn HirDatabase) -> ImplId { - chalk_ir::ImplId(self.as_intern_id()) - } - - fn from_chalk(_db: &dyn HirDatabase, impl_id: ImplId) -> hir_def::ImplId { - InternKey::from_intern_id(impl_id.0) - } -} - -impl ToChalk for CallableDefId { - type Chalk = FnDefId; - - fn to_chalk(self, db: &dyn HirDatabase) -> FnDefId { - db.intern_callable_def(self).into() - } - - fn from_chalk(db: &dyn HirDatabase, fn_def_id: FnDefId) -> CallableDefId { - db.lookup_intern_callable_def(fn_def_id.into()) - } -} - -pub(crate) struct TypeAliasAsValue(pub(crate) TypeAliasId); - -impl ToChalk for TypeAliasAsValue { - type Chalk = AssociatedTyValueId; - - fn to_chalk(self, _db: &dyn HirDatabase) -> AssociatedTyValueId { - rust_ir::AssociatedTyValueId(self.0.as_intern_id()) - } - - fn from_chalk( - _db: &dyn HirDatabase, - assoc_ty_value_id: AssociatedTyValueId, - ) -> TypeAliasAsValue { - TypeAliasAsValue(TypeAliasId::from_intern_id(assoc_ty_value_id.0)) - } -} - -pub(super) fn convert_where_clauses( - db: &dyn HirDatabase, - def: GenericDefId, - substs: &Substitution, -) -> Vec> { - let generic_predicates = db.generic_predicates(def); - let mut result = Vec::with_capacity(generic_predicates.len()); - for pred in generic_predicates.iter() { - result.push(pred.clone().substitute(&Interner, substs)); - } - result -} - -pub(super) fn generic_predicate_to_inline_bound( - db: &dyn HirDatabase, - pred: &QuantifiedWhereClause, - self_ty: &Ty, -) -> Option>> { - // An InlineBound is like a GenericPredicate, except the self type is left out. - // We don't have a special type for this, but Chalk does. - let self_ty_shifted_in = self_ty.clone().shifted_in_from(&Interner, DebruijnIndex::ONE); - let (pred, binders) = pred.as_ref().into_value_and_skipped_binders(); - match pred { - WhereClause::Implemented(trait_ref) => { - if trait_ref.self_type_parameter(&Interner) != self_ty_shifted_in { - // we can only convert predicates back to type bounds if they - // have the expected self type - return None; - } - let args_no_self = trait_ref.substitution.as_slice(&Interner)[1..] - .iter() - .map(|ty| ty.clone().cast(&Interner)) - .collect(); - let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self }; - Some(chalk_ir::Binders::new(binders, rust_ir::InlineBound::TraitBound(trait_bound))) - } - WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => { - if projection_ty.self_type_parameter(&Interner) != self_ty_shifted_in { - return None; - } - let trait_ = projection_ty.trait_(db); - let args_no_self = projection_ty.substitution.as_slice(&Interner)[1..] - .iter() - .map(|ty| ty.clone().cast(&Interner)) - .collect(); - let alias_eq_bound = rust_ir::AliasEqBound { - value: ty.clone(), - trait_bound: rust_ir::TraitBound { trait_id: trait_.to_chalk(db), args_no_self }, - associated_ty_id: projection_ty.associated_ty_id, - parameters: Vec::new(), // FIXME we don't support generic associated types yet - }; - Some(chalk_ir::Binders::new( - binders, - rust_ir::InlineBound::AliasEqBound(alias_eq_bound), - )) - } - _ => None, - } -} diff --git a/crates/hir_ty/src/traits/chalk/tls.rs b/crates/hir_ty/src/traits/chalk/tls.rs deleted file mode 100644 index 8892a63a9..000000000 --- a/crates/hir_ty/src/traits/chalk/tls.rs +++ /dev/null @@ -1,275 +0,0 @@ -//! Implementation of Chalk debug helper functions using TLS. -use std::fmt; - -use chalk_ir::{AliasTy, GenericArg, Goal, Goals, Lifetime, ProgramClauseImplication}; -use itertools::Itertools; - -use super::{from_chalk, Interner}; -use crate::{db::HirDatabase, from_assoc_type_id, CallableDefId}; -use hir_def::{AdtId, AssocContainerId, Lookup, TypeAliasId}; - -pub(crate) use unsafe_tls::{set_current_program, with_current_program}; - -pub(crate) struct DebugContext<'a>(&'a dyn HirDatabase); - -impl DebugContext<'_> { - pub(crate) fn debug_struct_id( - &self, - id: super::AdtId, - f: &mut fmt::Formatter<'_>, - ) -> Result<(), fmt::Error> { - let name = match id.0 { - AdtId::StructId(it) => self.0.struct_data(it).name.clone(), - AdtId::UnionId(it) => self.0.union_data(it).name.clone(), - AdtId::EnumId(it) => self.0.enum_data(it).name.clone(), - }; - write!(f, "{}", name) - } - - pub(crate) fn debug_trait_id( - &self, - id: super::TraitId, - fmt: &mut fmt::Formatter<'_>, - ) -> Result<(), fmt::Error> { - let trait_: hir_def::TraitId = from_chalk(self.0, id); - let trait_data = self.0.trait_data(trait_); - write!(fmt, "{}", trait_data.name) - } - - pub(crate) fn debug_assoc_type_id( - &self, - id: super::AssocTypeId, - fmt: &mut fmt::Formatter<'_>, - ) -> Result<(), fmt::Error> { - let type_alias: TypeAliasId = from_assoc_type_id(id); - let type_alias_data = self.0.type_alias_data(type_alias); - let trait_ = match type_alias.lookup(self.0.upcast()).container { - AssocContainerId::TraitId(t) => t, - _ => panic!("associated type not in trait"), - }; - let trait_data = self.0.trait_data(trait_); - write!(fmt, "{}::{}", trait_data.name, type_alias_data.name) - } - - pub(crate) fn debug_opaque_ty_id( - &self, - opaque_ty_id: chalk_ir::OpaqueTyId, - fmt: &mut fmt::Formatter<'_>, - ) -> Result<(), fmt::Error> { - fmt.debug_struct("OpaqueTyId").field("index", &opaque_ty_id.0).finish() - } - - pub(crate) fn debug_alias( - &self, - alias_ty: &AliasTy, - fmt: &mut fmt::Formatter<'_>, - ) -> Result<(), fmt::Error> { - match alias_ty { - AliasTy::Projection(projection_ty) => self.debug_projection_ty(projection_ty, fmt), - AliasTy::Opaque(opaque_ty) => self.debug_opaque_ty(opaque_ty, fmt), - } - } - - pub(crate) fn debug_projection_ty( - &self, - projection_ty: &chalk_ir::ProjectionTy, - fmt: &mut fmt::Formatter<'_>, - ) -> Result<(), fmt::Error> { - let type_alias = from_assoc_type_id(projection_ty.associated_ty_id); - let type_alias_data = self.0.type_alias_data(type_alias); - let trait_ = match type_alias.lookup(self.0.upcast()).container { - AssocContainerId::TraitId(t) => t, - _ => panic!("associated type not in trait"), - }; - let trait_data = self.0.trait_data(trait_); - let params = projection_ty.substitution.as_slice(&Interner); - write!(fmt, "<{:?} as {}", ¶ms[0], trait_data.name,)?; - if params.len() > 1 { - write!( - fmt, - "<{}>", - ¶ms[1..].iter().format_with(", ", |x, f| f(&format_args!("{:?}", x))), - )?; - } - write!(fmt, ">::{}", type_alias_data.name) - } - - pub(crate) fn debug_opaque_ty( - &self, - opaque_ty: &chalk_ir::OpaqueTy, - fmt: &mut fmt::Formatter<'_>, - ) -> Result<(), fmt::Error> { - write!(fmt, "{:?}", opaque_ty.opaque_ty_id) - } - - pub(crate) fn debug_ty( - &self, - ty: &chalk_ir::Ty, - fmt: &mut fmt::Formatter<'_>, - ) -> Result<(), fmt::Error> { - write!(fmt, "{:?}", ty.data(&Interner)) - } - - pub(crate) fn debug_lifetime( - &self, - lifetime: &Lifetime, - fmt: &mut fmt::Formatter<'_>, - ) -> Result<(), fmt::Error> { - write!(fmt, "{:?}", lifetime.data(&Interner)) - } - - pub(crate) fn debug_generic_arg( - &self, - parameter: &GenericArg, - fmt: &mut fmt::Formatter<'_>, - ) -> Result<(), fmt::Error> { - write!(fmt, "{:?}", parameter.data(&Interner).inner_debug()) - } - - pub(crate) fn debug_goal( - &self, - goal: &Goal, - fmt: &mut fmt::Formatter<'_>, - ) -> Result<(), fmt::Error> { - let goal_data = goal.data(&Interner); - write!(fmt, "{:?}", goal_data) - } - - pub(crate) fn debug_goals( - &self, - goals: &Goals, - fmt: &mut fmt::Formatter<'_>, - ) -> Result<(), fmt::Error> { - write!(fmt, "{:?}", goals.debug(&Interner)) - } - - pub(crate) fn debug_program_clause_implication( - &self, - pci: &ProgramClauseImplication, - fmt: &mut fmt::Formatter<'_>, - ) -> Result<(), fmt::Error> { - write!(fmt, "{:?}", pci.debug(&Interner)) - } - - pub(crate) fn debug_substitution( - &self, - substitution: &chalk_ir::Substitution, - fmt: &mut fmt::Formatter<'_>, - ) -> Result<(), fmt::Error> { - write!(fmt, "{:?}", substitution.debug(&Interner)) - } - - pub(crate) fn debug_separator_trait_ref( - &self, - separator_trait_ref: &chalk_ir::SeparatorTraitRef, - fmt: &mut fmt::Formatter<'_>, - ) -> Result<(), fmt::Error> { - write!(fmt, "{:?}", separator_trait_ref.debug(&Interner)) - } - - pub(crate) fn debug_fn_def_id( - &self, - fn_def_id: chalk_ir::FnDefId, - fmt: &mut fmt::Formatter<'_>, - ) -> Result<(), fmt::Error> { - let def: CallableDefId = from_chalk(self.0, fn_def_id); - let name = match def { - CallableDefId::FunctionId(ff) => self.0.function_data(ff).name.clone(), - CallableDefId::StructId(s) => self.0.struct_data(s).name.clone(), - CallableDefId::EnumVariantId(e) => { - let enum_data = self.0.enum_data(e.parent); - enum_data.variants[e.local_id].name.clone() - } - }; - match def { - CallableDefId::FunctionId(_) => write!(fmt, "{{fn {}}}", name), - CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_) => { - write!(fmt, "{{ctor {}}}", name) - } - } - } - - pub(crate) fn debug_const( - &self, - _constant: &chalk_ir::Const, - fmt: &mut fmt::Formatter<'_>, - ) -> fmt::Result { - write!(fmt, "const") - } - - pub(crate) fn debug_variable_kinds( - &self, - variable_kinds: &chalk_ir::VariableKinds, - fmt: &mut fmt::Formatter<'_>, - ) -> fmt::Result { - write!(fmt, "{:?}", variable_kinds.as_slice(&Interner)) - } - pub(crate) fn debug_variable_kinds_with_angles( - &self, - variable_kinds: &chalk_ir::VariableKinds, - fmt: &mut fmt::Formatter<'_>, - ) -> fmt::Result { - write!(fmt, "{:?}", variable_kinds.inner_debug(&Interner)) - } - pub(crate) fn debug_canonical_var_kinds( - &self, - canonical_var_kinds: &chalk_ir::CanonicalVarKinds, - fmt: &mut fmt::Formatter<'_>, - ) -> fmt::Result { - write!(fmt, "{:?}", canonical_var_kinds.as_slice(&Interner)) - } - pub(crate) fn debug_program_clause( - &self, - clause: &chalk_ir::ProgramClause, - fmt: &mut fmt::Formatter<'_>, - ) -> fmt::Result { - write!(fmt, "{:?}", clause.data(&Interner)) - } - pub(crate) fn debug_program_clauses( - &self, - clauses: &chalk_ir::ProgramClauses, - fmt: &mut fmt::Formatter<'_>, - ) -> fmt::Result { - write!(fmt, "{:?}", clauses.as_slice(&Interner)) - } - pub(crate) fn debug_quantified_where_clauses( - &self, - clauses: &chalk_ir::QuantifiedWhereClauses, - fmt: &mut fmt::Formatter<'_>, - ) -> fmt::Result { - write!(fmt, "{:?}", clauses.as_slice(&Interner)) - } -} - -mod unsafe_tls { - use super::DebugContext; - use crate::db::HirDatabase; - use scoped_tls::scoped_thread_local; - - scoped_thread_local!(static PROGRAM: DebugContext); - - pub(crate) fn with_current_program( - op: impl for<'a> FnOnce(Option<&'a DebugContext<'a>>) -> R, - ) -> R { - if PROGRAM.is_set() { - PROGRAM.with(|prog| op(Some(prog))) - } else { - op(None) - } - } - - pub(crate) fn set_current_program(p: &dyn HirDatabase, op: OP) -> R - where - OP: FnOnce() -> R, - { - let ctx = DebugContext(p); - // we're transmuting the lifetime in the DebugContext to static. This is - // fine because we only keep the reference for the lifetime of this - // function, *and* the only way to access the context is through - // `with_current_program`, which hides the lifetime through the `for` - // type. - let static_p: &DebugContext<'static> = - unsafe { std::mem::transmute::<&DebugContext, &DebugContext<'static>>(&ctx) }; - PROGRAM.set(static_p, || op()) - } -} -- cgit v1.2.3 From 5ca481bbdc75bd3a9dbce4c94b014bd0eb8bd9e8 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 9 Apr 2021 14:15:26 +0200 Subject: Move ToChalk -> mapping --- crates/hir_ty/src/chalk_db.rs | 32 +++++++++++++++++--------------- crates/hir_ty/src/db.rs | 16 +++++++++++++--- crates/hir_ty/src/display.rs | 10 +++++----- crates/hir_ty/src/infer/expr.rs | 2 +- crates/hir_ty/src/interner.rs | 17 +++++++++++++---- crates/hir_ty/src/lib.rs | 2 +- crates/hir_ty/src/lower.rs | 8 ++++---- crates/hir_ty/src/mapping.rs | 20 ++++++++++++++++++-- crates/hir_ty/src/tls.rs | 4 +++- crates/hir_ty/src/traits.rs | 2 +- 10 files changed, 76 insertions(+), 37 deletions(-) (limited to 'crates/hir_ty/src') diff --git a/crates/hir_ty/src/chalk_db.rs b/crates/hir_ty/src/chalk_db.rs index 566e4f406..f5b2c5ff0 100644 --- a/crates/hir_ty/src/chalk_db.rs +++ b/crates/hir_ty/src/chalk_db.rs @@ -1,4 +1,5 @@ -//! Conversion code from/to Chalk. +//! The implementation of `RustIrDatabase` for Chalk, which provides information +//! about the code that Chalk needs. use std::sync::Arc; use log::debug; @@ -13,7 +14,21 @@ use hir_def::{ }; use hir_expand::name::name; -use crate::{AliasEq, AliasTy, BoundVar, CallableDefId, DebruijnIndex, FnDefId, Interner, ProjectionTy, Substitution, TraitRef, TraitRefExt, Ty, TyBuilder, TyExt, TyKind, WhereClause, traits::ChalkContext, db::HirDatabase, display::HirDisplay, from_assoc_type_id, make_only_type_binders, mapping::{convert_where_clauses, generic_predicate_to_inline_bound, TypeAliasAsValue}, method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS}, to_assoc_type_id, to_chalk_trait_id, utils::generics}; +use crate::{ + db::HirDatabase, + display::HirDisplay, + from_assoc_type_id, make_only_type_binders, + mapping::{ + convert_where_clauses, from_chalk, generic_predicate_to_inline_bound, ToChalk, + TypeAliasAsValue, + }, + method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS}, + to_assoc_type_id, to_chalk_trait_id, + traits::ChalkContext, + utils::generics, + AliasEq, AliasTy, BoundVar, CallableDefId, DebruijnIndex, FnDefId, Interner, ProjectionTy, + Substitution, TraitRef, TraitRefExt, Ty, TyBuilder, TyExt, TyKind, WhereClause, +}; pub(crate) type AssociatedTyDatum = chalk_solve::rust_ir::AssociatedTyDatum; pub(crate) type TraitDatum = chalk_solve::rust_ir::TraitDatum; @@ -31,19 +46,6 @@ pub(crate) type AssociatedTyValue = chalk_solve::rust_ir::AssociatedTyValue; pub(crate) type Variances = chalk_ir::Variances; -pub(crate) trait ToChalk { - type Chalk; - fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk; - fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self; -} - -pub(crate) fn from_chalk(db: &dyn HirDatabase, chalk: ChalkT) -> T -where - T: ToChalk, -{ - T::from_chalk(db, chalk) -} - impl<'a> chalk_solve::RustIrDatabase for ChalkContext<'a> { fn associated_ty_data(&self, id: AssocTypeId) -> Arc { self.db.associated_ty_data(id) diff --git a/crates/hir_ty/src/db.rs b/crates/hir_ty/src/db.rs index ea0580df1..e11fc579e 100644 --- a/crates/hir_ty/src/db.rs +++ b/crates/hir_ty/src/db.rs @@ -9,7 +9,12 @@ use hir_def::{ }; use la_arena::ArenaMap; -use crate::{Binders, CallableDefId, FnDefId, ImplTraitId, InferenceResult, Interner, PolyFnSig, QuantifiedWhereClause, ReturnTypeImplTraits, TraitRef, Ty, TyDefId, ValueTyDefId, chalk_db, method_resolution::{InherentImpls, TraitImpls}}; +use crate::{ + chalk_db, + method_resolution::{InherentImpls, TraitImpls}, + Binders, CallableDefId, FnDefId, ImplTraitId, InferenceResult, Interner, PolyFnSig, + QuantifiedWhereClause, ReturnTypeImplTraits, TraitRef, Ty, TyDefId, ValueTyDefId, +}; use hir_expand::name::Name; #[salsa::query_group(HirDatabaseStorage)] @@ -93,10 +98,15 @@ pub trait HirDatabase: DefDatabase + Upcast { fn associated_ty_data(&self, id: chalk_db::AssocTypeId) -> Arc; #[salsa::invoke(chalk_db::trait_datum_query)] - fn trait_datum(&self, krate: CrateId, trait_id: chalk_db::TraitId) -> Arc; + fn trait_datum(&self, krate: CrateId, trait_id: chalk_db::TraitId) + -> Arc; #[salsa::invoke(chalk_db::struct_datum_query)] - fn struct_datum(&self, krate: CrateId, struct_id: chalk_db::AdtId) -> Arc; + fn struct_datum( + &self, + krate: CrateId, + struct_id: chalk_db::AdtId, + ) -> Arc; #[salsa::invoke(chalk_db::impl_datum_query)] fn impl_datum(&self, krate: CrateId, impl_id: chalk_db::ImplId) -> Arc; diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index a0746cd8f..ae3a82780 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs @@ -20,11 +20,11 @@ use hir_expand::name::Name; use crate::{ const_from_placeholder_idx, db::HirDatabase, from_assoc_type_id, from_foreign_def_id, - from_placeholder_idx, lt_from_placeholder_idx, primitive, subst_prefix, to_assoc_type_id, - chalk_db::from_chalk, utils::generics, AdtId, AliasEq, AliasTy, CallableDefId, - CallableSig, Const, ConstValue, DomainGoal, GenericArg, ImplTraitId, Interner, Lifetime, - LifetimeData, LifetimeOutlives, Mutability, OpaqueTy, ProjectionTy, ProjectionTyExt, - QuantifiedWhereClause, Scalar, TraitRef, TraitRefExt, Ty, TyExt, TyKind, WhereClause, + from_placeholder_idx, lt_from_placeholder_idx, mapping::from_chalk, primitive, subst_prefix, + to_assoc_type_id, utils::generics, AdtId, AliasEq, AliasTy, CallableDefId, CallableSig, Const, + ConstValue, DomainGoal, GenericArg, ImplTraitId, Interner, Lifetime, LifetimeData, + LifetimeOutlives, Mutability, OpaqueTy, ProjectionTy, ProjectionTyExt, QuantifiedWhereClause, + Scalar, TraitRef, TraitRefExt, Ty, TyExt, TyKind, WhereClause, }; pub struct HirFormatter<'a> { diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index d42383012..50497eecb 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs @@ -17,11 +17,11 @@ use syntax::ast::RangeOp; use crate::{ autoderef, dummy_usize_const, lower::lower_to_chalk_mutability, + mapping::from_chalk, method_resolution, op, primitive::{self, UintTy}, static_lifetime, to_chalk_trait_id, traits::FnTrait, - chalk_db::from_chalk, utils::{generics, Generics}, AdtId, Binders, CallableDefId, FnPointer, FnSig, FnSubst, InEnvironment, Interner, ProjectionTyExt, Rawness, Scalar, Substitution, TraitRef, Ty, TyBuilder, TyExt, TyKind, diff --git a/crates/hir_ty/src/interner.rs b/crates/hir_ty/src/interner.rs index 0187767ce..02e26c04e 100644 --- a/crates/hir_ty/src/interner.rs +++ b/crates/hir_ty/src/interner.rs @@ -1,7 +1,7 @@ //! Implementation of the Chalk `Interner` trait, which allows customizing the //! representation of the various objects Chalk deals with (types, goals etc.). -use crate::{GenericArg, tls, chalk_db}; +use crate::{chalk_db, tls, GenericArg}; use base_db::salsa::InternId; use chalk_ir::{Goal, GoalData}; use hir_def::{ @@ -60,15 +60,24 @@ impl chalk_ir::interner::Interner for Interner { type Identifier = TypeAliasId; type FnAbi = (); - fn debug_adt_id(type_kind_id: chalk_db::AdtId, fmt: &mut fmt::Formatter<'_>) -> Option { + fn debug_adt_id( + type_kind_id: chalk_db::AdtId, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { tls::with_current_program(|prog| Some(prog?.debug_struct_id(type_kind_id, fmt))) } - fn debug_trait_id(type_kind_id: chalk_db::TraitId, fmt: &mut fmt::Formatter<'_>) -> Option { + fn debug_trait_id( + type_kind_id: chalk_db::TraitId, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { tls::with_current_program(|prog| Some(prog?.debug_trait_id(type_kind_id, fmt))) } - fn debug_assoc_type_id(id: chalk_db::AssocTypeId, fmt: &mut fmt::Formatter<'_>) -> Option { + fn debug_assoc_type_id( + id: chalk_db::AssocTypeId, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { tls::with_current_program(|prog| Some(prog?.debug_assoc_type_id(id, fmt))) } diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index 0743d3d30..434e2e533 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs @@ -51,13 +51,13 @@ pub use autoderef::autoderef; pub use builder::TyBuilder; pub use chalk_ext::*; pub use infer::{could_unify, InferenceResult}; +pub use interner::Interner; pub use lower::{ associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode, TyDefId, TyLoweringContext, ValueTyDefId, }; pub use traits::TraitEnvironment; pub use walk::TypeWalk; -pub use interner::Interner; pub use chalk_ir::{ cast::Cast, AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind, diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index 0cdded3e1..a035686bc 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs @@ -27,14 +27,14 @@ use stdx::impl_from; use crate::{ db::HirDatabase, - dummy_usize_const, static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx, - chalk_db::ToChalk, - Interner, + dummy_usize_const, + mapping::ToChalk, + static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx, utils::{ all_super_trait_refs, associated_type_by_name_including_super_traits, generics, Generics, }, AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, DynTy, FnPointer, FnSig, - FnSubst, ImplTraitId, OpaqueTy, PolyFnSig, ProjectionTy, QuantifiedWhereClause, + FnSubst, ImplTraitId, Interner, OpaqueTy, PolyFnSig, ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses, ReturnTypeImplTrait, ReturnTypeImplTraits, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyKind, WhereClause, }; diff --git a/crates/hir_ty/src/mapping.rs b/crates/hir_ty/src/mapping.rs index 4d3c41b2c..f57115de6 100644 --- a/crates/hir_ty/src/mapping.rs +++ b/crates/hir_ty/src/mapping.rs @@ -3,13 +3,29 @@ //! Chalk (in both directions); plus some helper functions for more specialized //! conversions. -use chalk_ir::{DebruijnIndex, cast::Cast, fold::Shift}; +use chalk_ir::{cast::Cast, fold::Shift, DebruijnIndex}; use chalk_solve::rust_ir; use base_db::salsa::InternKey; use hir_def::{GenericDefId, TypeAliasId}; -use crate::{AliasEq, AliasTy, CallableDefId, FnDefId, Interner, ProjectionTyExt, QuantifiedWhereClause, Substitution, Ty, WhereClause, chalk_db::{self, ToChalk}, db::HirDatabase}; +use crate::{ + chalk_db, db::HirDatabase, AliasEq, AliasTy, CallableDefId, FnDefId, Interner, ProjectionTyExt, + QuantifiedWhereClause, Substitution, Ty, WhereClause, +}; + +pub(crate) trait ToChalk { + type Chalk; + fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk; + fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self; +} + +pub(crate) fn from_chalk(db: &dyn HirDatabase, chalk: ChalkT) -> T +where + T: ToChalk, +{ + T::from_chalk(db, chalk) +} impl ToChalk for hir_def::TraitId { type Chalk = chalk_db::TraitId; diff --git a/crates/hir_ty/src/tls.rs b/crates/hir_ty/src/tls.rs index c319bcf70..92989f11f 100644 --- a/crates/hir_ty/src/tls.rs +++ b/crates/hir_ty/src/tls.rs @@ -4,7 +4,9 @@ use std::fmt; use chalk_ir::{AliasTy, GenericArg, Goal, Goals, Lifetime, ProgramClauseImplication}; use itertools::Itertools; -use crate::{db::HirDatabase, from_assoc_type_id, CallableDefId, chalk_db::{from_chalk, self}, Interner}; +use crate::{ + chalk_db, db::HirDatabase, from_assoc_type_id, mapping::from_chalk, CallableDefId, Interner, +}; use hir_def::{AdtId, AssocContainerId, Lookup, TypeAliasId}; pub(crate) use unsafe_tls::{set_current_program, with_current_program}; diff --git a/crates/hir_ty/src/traits.rs b/crates/hir_ty/src/traits.rs index 5f8666d90..7f77e421d 100644 --- a/crates/hir_ty/src/traits.rs +++ b/crates/hir_ty/src/traits.rs @@ -9,7 +9,7 @@ use stdx::panic_context; use crate::{ db::HirDatabase, AliasEq, AliasTy, Canonical, DomainGoal, Guidance, HirDisplay, InEnvironment, - Solution, TraitRefExt, Ty, TyKind, WhereClause, Interner, + Interner, Solution, TraitRefExt, Ty, TyKind, WhereClause, }; /// This controls how much 'time' we give the Chalk solver before giving up. -- cgit v1.2.3 From 9fba7cf827cf332800053eb26f10d67efeee7886 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 9 Apr 2021 14:18:58 +0200 Subject: Move some more stuff to better places --- crates/hir_ty/src/chalk_db.rs | 101 +++++++++++++++++++++++++----------------- crates/hir_ty/src/mapping.rs | 92 +++++++++++++------------------------- 2 files changed, 93 insertions(+), 100 deletions(-) (limited to 'crates/hir_ty/src') diff --git a/crates/hir_ty/src/chalk_db.rs b/crates/hir_ty/src/chalk_db.rs index f5b2c5ff0..9d07ad597 100644 --- a/crates/hir_ty/src/chalk_db.rs +++ b/crates/hir_ty/src/chalk_db.rs @@ -4,13 +4,13 @@ use std::sync::Arc; use log::debug; -use chalk_ir::{fold::shift::Shift, CanonicalVarKinds}; +use chalk_ir::{cast::Cast, fold::shift::Shift, CanonicalVarKinds}; use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait}; -use base_db::{salsa::InternKey, CrateId}; +use base_db::CrateId; use hir_def::{ lang_item::{lang_attr, LangItemTarget}, - AssocContainerId, AssocItemId, HasModule, Lookup, TypeAliasId, + AssocContainerId, AssocItemId, GenericDefId, HasModule, Lookup, TypeAliasId, }; use hir_expand::name::name; @@ -18,16 +18,14 @@ use crate::{ db::HirDatabase, display::HirDisplay, from_assoc_type_id, make_only_type_binders, - mapping::{ - convert_where_clauses, from_chalk, generic_predicate_to_inline_bound, ToChalk, - TypeAliasAsValue, - }, + mapping::{from_chalk, ToChalk, TypeAliasAsValue}, method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS}, to_assoc_type_id, to_chalk_trait_id, traits::ChalkContext, utils::generics, AliasEq, AliasTy, BoundVar, CallableDefId, DebruijnIndex, FnDefId, Interner, ProjectionTy, - Substitution, TraitRef, TraitRefExt, Ty, TyBuilder, TyExt, TyKind, WhereClause, + ProjectionTyExt, QuantifiedWhereClause, Substitution, TraitRef, TraitRefExt, Ty, TyBuilder, + TyExt, TyKind, WhereClause, }; pub(crate) type AssociatedTyDatum = chalk_solve::rust_ir::AssociatedTyDatum; @@ -39,7 +37,6 @@ pub(crate) type OpaqueTyDatum = chalk_solve::rust_ir::OpaqueTyDatum; pub(crate) type AssocTypeId = chalk_ir::AssocTypeId; pub(crate) type TraitId = chalk_ir::TraitId; pub(crate) type AdtId = chalk_ir::AdtId; -pub(crate) type OpaqueTyId = chalk_ir::OpaqueTyId; pub(crate) type ImplId = chalk_ir::ImplId; pub(crate) type AssociatedTyValueId = chalk_solve::rust_ir::AssociatedTyValueId; pub(crate) type AssociatedTyValue = chalk_solve::rust_ir::AssociatedTyValue; @@ -679,38 +676,62 @@ pub(crate) fn adt_variance_query( ) } -impl From for crate::db::InternedCallableDefId { - fn from(fn_def_id: FnDefId) -> Self { - InternKey::from_intern_id(fn_def_id.0) - } -} - -impl From for FnDefId { - fn from(callable_def_id: crate::db::InternedCallableDefId) -> Self { - chalk_ir::FnDefId(callable_def_id.as_intern_id()) - } -} - -impl From for crate::db::InternedOpaqueTyId { - fn from(id: OpaqueTyId) -> Self { - InternKey::from_intern_id(id.0) - } -} - -impl From for OpaqueTyId { - fn from(id: crate::db::InternedOpaqueTyId) -> Self { - chalk_ir::OpaqueTyId(id.as_intern_id()) - } -} - -impl From> for crate::db::InternedClosureId { - fn from(id: chalk_ir::ClosureId) -> Self { - Self::from_intern_id(id.0) - } +pub(super) fn convert_where_clauses( + db: &dyn HirDatabase, + def: GenericDefId, + substs: &Substitution, +) -> Vec> { + let generic_predicates = db.generic_predicates(def); + let mut result = Vec::with_capacity(generic_predicates.len()); + for pred in generic_predicates.iter() { + result.push(pred.clone().substitute(&Interner, substs)); + } + result } -impl From for chalk_ir::ClosureId { - fn from(id: crate::db::InternedClosureId) -> Self { - chalk_ir::ClosureId(id.as_intern_id()) +pub(super) fn generic_predicate_to_inline_bound( + db: &dyn HirDatabase, + pred: &QuantifiedWhereClause, + self_ty: &Ty, +) -> Option>> { + // An InlineBound is like a GenericPredicate, except the self type is left out. + // We don't have a special type for this, but Chalk does. + let self_ty_shifted_in = self_ty.clone().shifted_in_from(&Interner, DebruijnIndex::ONE); + let (pred, binders) = pred.as_ref().into_value_and_skipped_binders(); + match pred { + WhereClause::Implemented(trait_ref) => { + if trait_ref.self_type_parameter(&Interner) != self_ty_shifted_in { + // we can only convert predicates back to type bounds if they + // have the expected self type + return None; + } + let args_no_self = trait_ref.substitution.as_slice(&Interner)[1..] + .iter() + .map(|ty| ty.clone().cast(&Interner)) + .collect(); + let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self }; + Some(chalk_ir::Binders::new(binders, rust_ir::InlineBound::TraitBound(trait_bound))) + } + WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => { + if projection_ty.self_type_parameter(&Interner) != self_ty_shifted_in { + return None; + } + let trait_ = projection_ty.trait_(db); + let args_no_self = projection_ty.substitution.as_slice(&Interner)[1..] + .iter() + .map(|ty| ty.clone().cast(&Interner)) + .collect(); + let alias_eq_bound = rust_ir::AliasEqBound { + value: ty.clone(), + trait_bound: rust_ir::TraitBound { trait_id: trait_.to_chalk(db), args_no_self }, + associated_ty_id: projection_ty.associated_ty_id, + parameters: Vec::new(), // FIXME we don't support generic associated types yet + }; + Some(chalk_ir::Binders::new( + binders, + rust_ir::InlineBound::AliasEqBound(alias_eq_bound), + )) + } + _ => None, } } diff --git a/crates/hir_ty/src/mapping.rs b/crates/hir_ty/src/mapping.rs index f57115de6..37c935194 100644 --- a/crates/hir_ty/src/mapping.rs +++ b/crates/hir_ty/src/mapping.rs @@ -3,16 +3,12 @@ //! Chalk (in both directions); plus some helper functions for more specialized //! conversions. -use chalk_ir::{cast::Cast, fold::Shift, DebruijnIndex}; use chalk_solve::rust_ir; use base_db::salsa::InternKey; -use hir_def::{GenericDefId, TypeAliasId}; +use hir_def::TypeAliasId; -use crate::{ - chalk_db, db::HirDatabase, AliasEq, AliasTy, CallableDefId, FnDefId, Interner, ProjectionTyExt, - QuantifiedWhereClause, Substitution, Ty, WhereClause, -}; +use crate::{chalk_db, db::HirDatabase, CallableDefId, FnDefId, Interner, OpaqueTyId}; pub(crate) trait ToChalk { type Chalk; @@ -80,62 +76,38 @@ impl ToChalk for TypeAliasAsValue { } } -pub(super) fn convert_where_clauses( - db: &dyn HirDatabase, - def: GenericDefId, - substs: &Substitution, -) -> Vec> { - let generic_predicates = db.generic_predicates(def); - let mut result = Vec::with_capacity(generic_predicates.len()); - for pred in generic_predicates.iter() { - result.push(pred.clone().substitute(&Interner, substs)); +impl From for crate::db::InternedCallableDefId { + fn from(fn_def_id: FnDefId) -> Self { + InternKey::from_intern_id(fn_def_id.0) } - result } -pub(super) fn generic_predicate_to_inline_bound( - db: &dyn HirDatabase, - pred: &QuantifiedWhereClause, - self_ty: &Ty, -) -> Option>> { - // An InlineBound is like a GenericPredicate, except the self type is left out. - // We don't have a special type for this, but Chalk does. - let self_ty_shifted_in = self_ty.clone().shifted_in_from(&Interner, DebruijnIndex::ONE); - let (pred, binders) = pred.as_ref().into_value_and_skipped_binders(); - match pred { - WhereClause::Implemented(trait_ref) => { - if trait_ref.self_type_parameter(&Interner) != self_ty_shifted_in { - // we can only convert predicates back to type bounds if they - // have the expected self type - return None; - } - let args_no_self = trait_ref.substitution.as_slice(&Interner)[1..] - .iter() - .map(|ty| ty.clone().cast(&Interner)) - .collect(); - let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self }; - Some(chalk_ir::Binders::new(binders, rust_ir::InlineBound::TraitBound(trait_bound))) - } - WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => { - if projection_ty.self_type_parameter(&Interner) != self_ty_shifted_in { - return None; - } - let trait_ = projection_ty.trait_(db); - let args_no_self = projection_ty.substitution.as_slice(&Interner)[1..] - .iter() - .map(|ty| ty.clone().cast(&Interner)) - .collect(); - let alias_eq_bound = rust_ir::AliasEqBound { - value: ty.clone(), - trait_bound: rust_ir::TraitBound { trait_id: trait_.to_chalk(db), args_no_self }, - associated_ty_id: projection_ty.associated_ty_id, - parameters: Vec::new(), // FIXME we don't support generic associated types yet - }; - Some(chalk_ir::Binders::new( - binders, - rust_ir::InlineBound::AliasEqBound(alias_eq_bound), - )) - } - _ => None, +impl From for FnDefId { + fn from(callable_def_id: crate::db::InternedCallableDefId) -> Self { + chalk_ir::FnDefId(callable_def_id.as_intern_id()) + } +} + +impl From for crate::db::InternedOpaqueTyId { + fn from(id: OpaqueTyId) -> Self { + InternKey::from_intern_id(id.0) + } +} + +impl From for OpaqueTyId { + fn from(id: crate::db::InternedOpaqueTyId) -> Self { + chalk_ir::OpaqueTyId(id.as_intern_id()) + } +} + +impl From> for crate::db::InternedClosureId { + fn from(id: chalk_ir::ClosureId) -> Self { + Self::from_intern_id(id.0) + } +} + +impl From for chalk_ir::ClosureId { + fn from(id: crate::db::InternedClosureId) -> Self { + chalk_ir::ClosureId(id.as_intern_id()) } } -- cgit v1.2.3 From 2f02977e56a44a5f78576a25547672cd8f910f13 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 9 Apr 2021 14:28:04 +0200 Subject: More moving stuff around --- crates/hir_ty/src/chalk_db.rs | 15 +++++---- crates/hir_ty/src/lib.rs | 61 ++++--------------------------------- crates/hir_ty/src/mapping.rs | 71 ++++++++++++++++++++++++++++++++++--------- crates/hir_ty/src/tls.rs | 5 +-- 4 files changed, 74 insertions(+), 78 deletions(-) (limited to 'crates/hir_ty/src') diff --git a/crates/hir_ty/src/chalk_db.rs b/crates/hir_ty/src/chalk_db.rs index 9d07ad597..8f054d06b 100644 --- a/crates/hir_ty/src/chalk_db.rs +++ b/crates/hir_ty/src/chalk_db.rs @@ -17,7 +17,7 @@ use hir_expand::name::name; use crate::{ db::HirDatabase, display::HirDisplay, - from_assoc_type_id, make_only_type_binders, + from_assoc_type_id, from_chalk_trait_id, make_only_type_binders, mapping::{from_chalk, ToChalk, TypeAliasAsValue}, method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS}, to_assoc_type_id, to_chalk_trait_id, @@ -79,7 +79,7 @@ impl<'a> chalk_solve::RustIrDatabase for ChalkContext<'a> { binders: &CanonicalVarKinds, ) -> Vec { debug!("impls_for_trait {:?}", trait_id); - let trait_: hir_def::TraitId = from_chalk(self.db, trait_id); + let trait_: hir_def::TraitId = from_chalk_trait_id(trait_id); let ty: Ty = parameters[0].assert_ty_ref(&Interner).clone(); @@ -161,7 +161,7 @@ impl<'a> chalk_solve::RustIrDatabase for ChalkContext<'a> { Some(LangItemTarget::TraitId(trait_)) => trait_, _ => return None, }; - Some(trait_.to_chalk(self.db)) + Some(to_chalk_trait_id(trait_)) } fn program_clauses_for_env( @@ -308,7 +308,7 @@ impl<'a> chalk_solve::RustIrDatabase for ChalkContext<'a> { } fn trait_name(&self, trait_id: chalk_ir::TraitId) -> String { - let id = from_chalk(self.db, trait_id); + let id = from_chalk_trait_id(trait_id); self.db.trait_data(id).name.to_string() } fn adt_name(&self, chalk_ir::AdtId(adt_id): AdtId) -> String { @@ -413,7 +413,7 @@ pub(crate) fn trait_datum_query( trait_id: TraitId, ) -> Arc { debug!("trait_datum {:?}", trait_id); - let trait_: hir_def::TraitId = from_chalk(db, trait_id); + let trait_ = from_chalk_trait_id(trait_id); let trait_data = db.trait_data(trait_); debug!("trait {:?} = {:?}", trait_id, trait_data.name); let generic_params = generics(db.upcast(), trait_.into()); @@ -723,7 +723,10 @@ pub(super) fn generic_predicate_to_inline_bound( .collect(); let alias_eq_bound = rust_ir::AliasEqBound { value: ty.clone(), - trait_bound: rust_ir::TraitBound { trait_id: trait_.to_chalk(db), args_no_self }, + trait_bound: rust_ir::TraitBound { + trait_id: to_chalk_trait_id(trait_), + args_no_self, + }, associated_ty_id: projection_ty.associated_ty_id, parameters: Vec::new(), // FIXME we don't support generic associated types yet }; diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index 434e2e533..6b5006f5d 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs @@ -34,16 +34,12 @@ mod test_db; use std::sync::Arc; -use base_db::salsa; use chalk_ir::{ fold::{Fold, Shift}, interner::HasInterner, UintTy, }; -use hir_def::{ - expr::ExprId, type_ref::Rawness, ConstParamId, LifetimeParamId, TraitId, TypeAliasId, - TypeParamId, -}; +use hir_def::{expr::ExprId, type_ref::Rawness, TypeParamId}; use crate::{db::HirDatabase, display::HirDisplay, utils::generics}; @@ -56,6 +52,11 @@ pub use lower::{ associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode, TyDefId, TyLoweringContext, ValueTyDefId, }; +pub use mapping::{ + const_from_placeholder_idx, from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, + from_placeholder_idx, lt_from_placeholder_idx, to_assoc_type_id, to_chalk_trait_id, + to_foreign_def_id, to_placeholder_idx, +}; pub use traits::TraitEnvironment; pub use walk::TypeWalk; @@ -242,56 +243,6 @@ pub(crate) struct ReturnTypeImplTrait { pub(crate) bounds: Binders>, } -pub fn to_foreign_def_id(id: TypeAliasId) -> ForeignDefId { - chalk_ir::ForeignDefId(salsa::InternKey::as_intern_id(&id)) -} - -pub fn from_foreign_def_id(id: ForeignDefId) -> TypeAliasId { - salsa::InternKey::from_intern_id(id.0) -} - -pub fn to_assoc_type_id(id: TypeAliasId) -> AssocTypeId { - chalk_ir::AssocTypeId(salsa::InternKey::as_intern_id(&id)) -} - -pub fn from_assoc_type_id(id: AssocTypeId) -> TypeAliasId { - salsa::InternKey::from_intern_id(id.0) -} - -pub fn from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> TypeParamId { - assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT); - let interned_id = salsa::InternKey::from_intern_id(salsa::InternId::from(idx.idx)); - db.lookup_intern_type_param_id(interned_id) -} - -pub fn to_placeholder_idx(db: &dyn HirDatabase, id: TypeParamId) -> PlaceholderIndex { - let interned_id = db.intern_type_param_id(id); - PlaceholderIndex { - ui: chalk_ir::UniverseIndex::ROOT, - idx: salsa::InternKey::as_intern_id(&interned_id).as_usize(), - } -} - -pub fn lt_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> LifetimeParamId { - assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT); - let interned_id = salsa::InternKey::from_intern_id(salsa::InternId::from(idx.idx)); - db.lookup_intern_lifetime_param_id(interned_id) -} - -pub fn const_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> ConstParamId { - assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT); - let interned_id = salsa::InternKey::from_intern_id(salsa::InternId::from(idx.idx)); - db.lookup_intern_const_param_id(interned_id) -} - -pub fn to_chalk_trait_id(id: TraitId) -> ChalkTraitId { - chalk_ir::TraitId(salsa::InternKey::as_intern_id(&id)) -} - -pub fn from_chalk_trait_id(id: ChalkTraitId) -> TraitId { - salsa::InternKey::from_intern_id(id.0) -} - pub fn static_lifetime() -> Lifetime { LifetimeData::Static.intern(&Interner) } diff --git a/crates/hir_ty/src/mapping.rs b/crates/hir_ty/src/mapping.rs index 37c935194..5e86fafe5 100644 --- a/crates/hir_ty/src/mapping.rs +++ b/crates/hir_ty/src/mapping.rs @@ -5,10 +5,13 @@ use chalk_solve::rust_ir; -use base_db::salsa::InternKey; -use hir_def::TypeAliasId; +use base_db::salsa::{self, InternKey}; +use hir_def::{ConstParamId, LifetimeParamId, TraitId, TypeAliasId, TypeParamId}; -use crate::{chalk_db, db::HirDatabase, CallableDefId, FnDefId, Interner, OpaqueTyId}; +use crate::{ + chalk_db, db::HirDatabase, AssocTypeId, CallableDefId, ChalkTraitId, FnDefId, ForeignDefId, + Interner, OpaqueTyId, PlaceholderIndex, +}; pub(crate) trait ToChalk { type Chalk; @@ -23,18 +26,6 @@ where T::from_chalk(db, chalk) } -impl ToChalk for hir_def::TraitId { - type Chalk = chalk_db::TraitId; - - fn to_chalk(self, _db: &dyn HirDatabase) -> chalk_db::TraitId { - chalk_ir::TraitId(self.as_intern_id()) - } - - fn from_chalk(_db: &dyn HirDatabase, trait_id: chalk_db::TraitId) -> hir_def::TraitId { - InternKey::from_intern_id(trait_id.0) - } -} - impl ToChalk for hir_def::ImplId { type Chalk = chalk_db::ImplId; @@ -111,3 +102,53 @@ impl From for chalk_ir::ClosureId { chalk_ir::ClosureId(id.as_intern_id()) } } + +pub fn to_foreign_def_id(id: TypeAliasId) -> ForeignDefId { + chalk_ir::ForeignDefId(salsa::InternKey::as_intern_id(&id)) +} + +pub fn from_foreign_def_id(id: ForeignDefId) -> TypeAliasId { + salsa::InternKey::from_intern_id(id.0) +} + +pub fn to_assoc_type_id(id: TypeAliasId) -> AssocTypeId { + chalk_ir::AssocTypeId(salsa::InternKey::as_intern_id(&id)) +} + +pub fn from_assoc_type_id(id: AssocTypeId) -> TypeAliasId { + salsa::InternKey::from_intern_id(id.0) +} + +pub fn from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> TypeParamId { + assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT); + let interned_id = salsa::InternKey::from_intern_id(salsa::InternId::from(idx.idx)); + db.lookup_intern_type_param_id(interned_id) +} + +pub fn to_placeholder_idx(db: &dyn HirDatabase, id: TypeParamId) -> PlaceholderIndex { + let interned_id = db.intern_type_param_id(id); + PlaceholderIndex { + ui: chalk_ir::UniverseIndex::ROOT, + idx: salsa::InternKey::as_intern_id(&interned_id).as_usize(), + } +} + +pub fn lt_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> LifetimeParamId { + assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT); + let interned_id = salsa::InternKey::from_intern_id(salsa::InternId::from(idx.idx)); + db.lookup_intern_lifetime_param_id(interned_id) +} + +pub fn const_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> ConstParamId { + assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT); + let interned_id = salsa::InternKey::from_intern_id(salsa::InternId::from(idx.idx)); + db.lookup_intern_const_param_id(interned_id) +} + +pub fn to_chalk_trait_id(id: TraitId) -> ChalkTraitId { + chalk_ir::TraitId(salsa::InternKey::as_intern_id(&id)) +} + +pub fn from_chalk_trait_id(id: ChalkTraitId) -> TraitId { + salsa::InternKey::from_intern_id(id.0) +} diff --git a/crates/hir_ty/src/tls.rs b/crates/hir_ty/src/tls.rs index 92989f11f..87c671a42 100644 --- a/crates/hir_ty/src/tls.rs +++ b/crates/hir_ty/src/tls.rs @@ -5,7 +5,8 @@ use chalk_ir::{AliasTy, GenericArg, Goal, Goals, Lifetime, ProgramClauseImplicat use itertools::Itertools; use crate::{ - chalk_db, db::HirDatabase, from_assoc_type_id, mapping::from_chalk, CallableDefId, Interner, + chalk_db, db::HirDatabase, from_assoc_type_id, from_chalk_trait_id, mapping::from_chalk, + CallableDefId, Interner, }; use hir_def::{AdtId, AssocContainerId, Lookup, TypeAliasId}; @@ -32,7 +33,7 @@ impl DebugContext<'_> { id: chalk_db::TraitId, fmt: &mut fmt::Formatter<'_>, ) -> Result<(), fmt::Error> { - let trait_: hir_def::TraitId = from_chalk(self.0, id); + let trait_: hir_def::TraitId = from_chalk_trait_id(id); let trait_data = self.0.trait_data(trait_); write!(fmt, "{}", trait_data.name) } -- cgit v1.2.3 From 8a2c4820821a9b266ed979ed9321431362cdb1b3 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 9 Apr 2021 14:33:03 +0200 Subject: More cleanups --- crates/hir_ty/src/chalk_cast.rs | 16 ---------------- crates/hir_ty/src/interner.rs | 9 +++++++++ crates/hir_ty/src/lib.rs | 42 ++++++++++++++++++++--------------------- 3 files changed, 29 insertions(+), 38 deletions(-) delete mode 100644 crates/hir_ty/src/chalk_cast.rs (limited to 'crates/hir_ty/src') diff --git a/crates/hir_ty/src/chalk_cast.rs b/crates/hir_ty/src/chalk_cast.rs deleted file mode 100644 index f27dee3fd..000000000 --- a/crates/hir_ty/src/chalk_cast.rs +++ /dev/null @@ -1,16 +0,0 @@ -//! Implementations of the Chalk `Cast` trait for our types. - -use chalk_ir::interner::HasInterner; - -use crate::{CallableSig, ReturnTypeImplTraits}; - -macro_rules! has_interner { - ($t:ty) => { - impl HasInterner for $t { - type Interner = crate::Interner; - } - }; -} - -has_interner!(CallableSig); -has_interner!(ReturnTypeImplTraits); diff --git a/crates/hir_ty/src/interner.rs b/crates/hir_ty/src/interner.rs index 02e26c04e..a1656115d 100644 --- a/crates/hir_ty/src/interner.rs +++ b/crates/hir_ty/src/interner.rs @@ -412,3 +412,12 @@ impl chalk_ir::interner::Interner for Interner { impl chalk_ir::interner::HasInterner for Interner { type Interner = Self; } + +#[macro_export] +macro_rules! has_interner { + ($t:ty) => { + impl HasInterner for $t { + type Interner = crate::Interner; + } + }; +} diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index 6b5006f5d..ef1bdefac 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs @@ -7,25 +7,23 @@ macro_rules! eprintln { } mod autoderef; -pub mod primitive; -pub mod traits; -pub mod method_resolution; -mod op; -mod lower; -pub(crate) mod infer; -pub(crate) mod utils; -mod chalk_cast; -mod chalk_ext; mod builder; -mod walk; -mod tls; +mod chalk_db; +mod chalk_ext; +mod infer; mod interner; +mod lower; mod mapping; -mod chalk_db; - -pub mod display; +mod op; +mod tls; +mod utils; +mod walk; pub mod db; pub mod diagnostics; +pub mod display; +pub mod method_resolution; +pub mod primitive; +pub mod traits; #[cfg(test)] mod tests; @@ -100,6 +98,10 @@ pub type ConstValue = chalk_ir::ConstValue; pub type ConcreteConst = chalk_ir::ConcreteConst; pub type ChalkTraitId = chalk_ir::TraitId; +pub type TraitRef = chalk_ir::TraitRef; +pub type QuantifiedWhereClause = Binders; +pub type QuantifiedWhereClauses = chalk_ir::QuantifiedWhereClauses; +pub type Canonical = chalk_ir::Canonical; pub type FnSig = chalk_ir::FnSig; @@ -159,14 +161,6 @@ pub fn make_canonical>( Canonical { value, binders: chalk_ir::CanonicalVarKinds::from_iter(&Interner, kinds) } } -pub type TraitRef = chalk_ir::TraitRef; - -pub type QuantifiedWhereClause = Binders; - -pub type QuantifiedWhereClauses = chalk_ir::QuantifiedWhereClauses; - -pub type Canonical = chalk_ir::Canonical; - /// A function signature as seen by type inference: Several parameter types and /// one return type. #[derive(Clone, PartialEq, Eq, Debug)] @@ -175,6 +169,8 @@ pub struct CallableSig { is_varargs: bool, } +has_interner!(CallableSig); + /// A polymorphic function signature. pub type PolyFnSig = Binders; @@ -238,6 +234,8 @@ pub struct ReturnTypeImplTraits { pub(crate) impl_traits: Vec, } +has_interner!(ReturnTypeImplTraits); + #[derive(Clone, PartialEq, Eq, Debug, Hash)] pub(crate) struct ReturnTypeImplTrait { pub(crate) bounds: Binders>, -- cgit v1.2.3 From fbe98047d419ade6c87ccf432eb9534393d20020 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 9 Apr 2021 14:39:07 +0200 Subject: More cleanups / module docs --- crates/hir_ty/src/db.rs | 3 ++- crates/hir_ty/src/diagnostics.rs | 2 +- crates/hir_ty/src/display.rs | 4 +++- crates/hir_ty/src/lib.rs | 4 ++-- crates/hir_ty/src/primitive.rs | 5 +---- crates/hir_ty/src/traits.rs | 4 +++- 6 files changed, 12 insertions(+), 10 deletions(-) (limited to 'crates/hir_ty/src') diff --git a/crates/hir_ty/src/db.rs b/crates/hir_ty/src/db.rs index e11fc579e..1690926ad 100644 --- a/crates/hir_ty/src/db.rs +++ b/crates/hir_ty/src/db.rs @@ -1,4 +1,5 @@ -//! FIXME: write short doc here +//! The home of `HirDatabase`, which is the Salsa database containing all the +//! type inference-related queries. use std::sync::Arc; diff --git a/crates/hir_ty/src/diagnostics.rs b/crates/hir_ty/src/diagnostics.rs index 86f937e1d..84fc8ce14 100644 --- a/crates/hir_ty/src/diagnostics.rs +++ b/crates/hir_ty/src/diagnostics.rs @@ -1,4 +1,4 @@ -//! FIXME: write short doc here +//! Type inference-based diagnostics. mod expr; mod match_check; mod unsafe_check; diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index ae3a82780..e7c9dabc2 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs @@ -1,4 +1,6 @@ -//! FIXME: write short doc here +//! The `HirDisplay` trait, which serves two purposes: Turning various bits from +//! HIR back into source code, and just displaying them for debugging/testing +//! purposes. use std::{ array, diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index ef1bdefac..113234fa4 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs @@ -126,14 +126,14 @@ pub fn param_idx(db: &dyn HirDatabase, id: TypeParamId) -> Option { generics(db.upcast(), id.parent).param_idx(id) } -pub fn wrap_empty_binders(value: T) -> Binders +pub(crate) fn wrap_empty_binders(value: T) -> Binders where T: Fold + HasInterner, { Binders::empty(&Interner, value.shifted_in_from(&Interner, DebruijnIndex::ONE)) } -pub fn make_only_type_binders>( +pub(crate) fn make_only_type_binders>( num_vars: usize, value: T, ) -> Binders { diff --git a/crates/hir_ty/src/primitive.rs b/crates/hir_ty/src/primitive.rs index 2449addfb..d7f48c69a 100644 --- a/crates/hir_ty/src/primitive.rs +++ b/crates/hir_ty/src/primitive.rs @@ -1,7 +1,4 @@ -//! Defines primitive types, which have a couple of peculiarities: -//! -//! * during type inference, they can be uncertain (ie, `let x = 92;`) -//! * they don't belong to any particular crate. +//! A few helper functions for dealing with primitives. pub use chalk_ir::{FloatTy, IntTy, UintTy}; pub use hir_def::builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint}; diff --git a/crates/hir_ty/src/traits.rs b/crates/hir_ty/src/traits.rs index 7f77e421d..9936d0803 100644 --- a/crates/hir_ty/src/traits.rs +++ b/crates/hir_ty/src/traits.rs @@ -1,9 +1,11 @@ //! Trait solving using Chalk. + use std::env::var; -use base_db::CrateId; use chalk_ir::cast::Cast; use chalk_solve::{logging_db::LoggingRustIrDatabase, Solver}; + +use base_db::CrateId; use hir_def::{lang_item::LangItemTarget, TraitId}; use stdx::panic_context; -- cgit v1.2.3