diff --git a/crates/ra_hir_ty/src/traits.rs b/crates/ra_hir_ty/src/traits.rs index 786f758e992..f7edb4c8b6a 100644 --- a/crates/ra_hir_ty/src/traits.rs +++ b/crates/ra_hir_ty/src/traits.rs @@ -295,13 +295,8 @@ pub enum Impl { /// A normal impl from an impl block. ImplDef(ImplId), /// Closure types implement the Fn traits synthetically. + // FIXME: implement closure support from Chalk, remove this ClosureFnTraitImpl(ClosureFnTraitImplData), - /// [T; n]: Unsize<[T]> - UnsizeArray, - /// T: Unsize where T: Trait - UnsizeToTraitObject(TraitId), - /// dyn Trait: Unsize if Trait: SuperTrait - UnsizeToSuperTraitObject(UnsizeToSuperTraitObjectData), } /// This exists just for Chalk, because our ImplIds are only unique per module. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] diff --git a/crates/ra_hir_ty/src/traits/builtin.rs b/crates/ra_hir_ty/src/traits/builtin.rs index 6d5f2d46a72..86e22e45954 100644 --- a/crates/ra_hir_ty/src/traits/builtin.rs +++ b/crates/ra_hir_ty/src/traits/builtin.rs @@ -1,15 +1,12 @@ //! This module provides the built-in trait implementations, e.g. to make //! closures implement `Fn`. -use hir_def::{expr::Expr, lang_item::LangItemTarget, TraitId, TypeAliasId}; +use hir_def::{expr::Expr, TraitId, TypeAliasId}; use hir_expand::name::name; use ra_db::CrateId; -use super::{AssocTyValue, Impl, UnsizeToSuperTraitObjectData}; +use super::{AssocTyValue, Impl}; use crate::{ - db::HirDatabase, - utils::{all_super_traits, generics}, - ApplicationTy, Binders, BoundVar, DebruijnIndex, GenericPredicate, Substs, TraitRef, Ty, - TypeCtor, TypeWalk, + db::HirDatabase, ApplicationTy, BoundVar, DebruijnIndex, Substs, TraitRef, Ty, TypeCtor, }; pub(super) struct BuiltinImplData { @@ -31,7 +28,7 @@ pub(super) fn get_builtin_impls( krate: CrateId, ty: &Ty, // The first argument for the trait, if present - arg: &Option, + _arg: &Option, trait_: TraitId, mut callback: impl FnMut(Impl), ) { @@ -50,60 +47,12 @@ pub(super) fn get_builtin_impls( } } } - - let unsize_trait = get_unsize_trait(db, krate); - if let Some(actual_trait) = unsize_trait { - if trait_ == actual_trait { - get_builtin_unsize_impls(db, krate, ty, arg, callback); - } - } -} - -fn get_builtin_unsize_impls( - db: &dyn HirDatabase, - krate: CrateId, - ty: &Ty, - // The first argument for the trait, if present - arg: &Option, - mut callback: impl FnMut(Impl), -) { - if !check_unsize_impl_prerequisites(db, krate) { - return; - } - - if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Array, .. }) = ty { - callback(Impl::UnsizeArray); - return; // array is unsized, the rest of the impls shouldn't apply - } - - if let Some(target_trait) = arg.as_ref().and_then(|t| t.dyn_trait_ref()) { - // FIXME what about more complicated dyn tys with marker traits? - if let Some(trait_ref) = ty.dyn_trait_ref() { - if trait_ref.trait_ != target_trait.trait_ { - let super_traits = all_super_traits(db.upcast(), trait_ref.trait_); - if super_traits.contains(&target_trait.trait_) { - callback(Impl::UnsizeToSuperTraitObject(UnsizeToSuperTraitObjectData { - trait_: trait_ref.trait_, - super_trait: target_trait.trait_, - })); - } - } - } else { - // FIXME only for sized types - callback(Impl::UnsizeToTraitObject(target_trait.trait_)); - } - } } pub(super) fn impl_datum(db: &dyn HirDatabase, krate: CrateId, impl_: Impl) -> BuiltinImplData { match impl_ { Impl::ImplDef(_) => unreachable!(), Impl::ClosureFnTraitImpl(data) => closure_fn_trait_impl_datum(db, krate, data), - Impl::UnsizeArray => array_unsize_impl_datum(db, krate), - Impl::UnsizeToTraitObject(trait_) => trait_object_unsize_impl_datum(db, krate, trait_), - Impl::UnsizeToSuperTraitObject(data) => { - super_trait_object_unsize_impl_datum(db, krate, data) - } } } @@ -227,145 +176,3 @@ fn closure_fn_trait_output_assoc_ty_value( value: output_ty, } } - -// Array unsizing - -fn check_unsize_impl_prerequisites(db: &dyn HirDatabase, krate: CrateId) -> bool { - // the Unsize trait needs to exist and have two type parameters (Self and T) - let unsize_trait = match get_unsize_trait(db, krate) { - Some(t) => t, - None => return false, - }; - let generic_params = generics(db.upcast(), unsize_trait.into()); - generic_params.len() == 2 -} - -fn array_unsize_impl_datum(db: &dyn HirDatabase, krate: CrateId) -> BuiltinImplData { - // impl Unsize<[T]> for [T; _] - // (this can be a single impl because we don't distinguish array sizes currently) - - let trait_ = get_unsize_trait(db, krate) // get unsize trait - // the existence of the Unsize trait has been checked before - .expect("Unsize trait missing"); - - let var = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)); - let substs = Substs::builder(2) - .push(Ty::apply_one(TypeCtor::Array, var.clone())) - .push(Ty::apply_one(TypeCtor::Slice, var)) - .build(); - - let trait_ref = TraitRef { trait_, substs }; - - BuiltinImplData { - num_vars: 1, - trait_ref, - where_clauses: Vec::new(), - assoc_ty_values: Vec::new(), - } -} - -// Trait object unsizing - -fn trait_object_unsize_impl_datum( - db: &dyn HirDatabase, - krate: CrateId, - trait_: TraitId, -) -> BuiltinImplData { - // impl Unsize> for T where T: Trait - - let unsize_trait = get_unsize_trait(db, krate) // get unsize trait - // the existence of the Unsize trait has been checked before - .expect("Unsize trait missing"); - - let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)); - - let target_substs = Substs::build_for_def(db, trait_) - .push(Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0))) - .fill_with_bound_vars(DebruijnIndex::ONE, 1) - .build(); - let num_vars = target_substs.len(); - let target_trait_ref = TraitRef { trait_, substs: target_substs }; - let target_bounds = vec![GenericPredicate::Implemented(target_trait_ref)]; - - let self_substs = - Substs::build_for_def(db, trait_).fill_with_bound_vars(DebruijnIndex::INNERMOST, 0).build(); - let self_trait_ref = TraitRef { trait_, substs: self_substs }; - let where_clauses = vec![GenericPredicate::Implemented(self_trait_ref)]; - - let impl_substs = Substs::builder(2).push(self_ty).push(Ty::Dyn(target_bounds.into())).build(); - - let trait_ref = TraitRef { trait_: unsize_trait, substs: impl_substs }; - - BuiltinImplData { num_vars, trait_ref, where_clauses, assoc_ty_values: Vec::new() } -} - -fn super_trait_object_unsize_impl_datum( - db: &dyn HirDatabase, - krate: CrateId, - data: UnsizeToSuperTraitObjectData, -) -> BuiltinImplData { - // impl Unsize for dyn Trait - - let unsize_trait = get_unsize_trait(db, krate) // get unsize trait - // the existence of the Unsize trait has been checked before - .expect("Unsize trait missing"); - - let self_substs = Substs::build_for_def(db, data.trait_) - .fill_with_bound_vars(DebruijnIndex::INNERMOST, 0) - .build(); - let self_trait_ref = TraitRef { trait_: data.trait_, substs: self_substs.clone() }; - - let num_vars = self_substs.len() - 1; - - // we need to go from our trait to the super trait, substituting type parameters - let path = crate::utils::find_super_trait_path(db.upcast(), data.trait_, data.super_trait); - - let mut current_trait_ref = self_trait_ref.clone(); - for t in path.into_iter().skip(1) { - let bounds = db.generic_predicates(current_trait_ref.trait_.into()); - let super_trait_ref = bounds - .iter() - .find_map(|b| match &b.value { - GenericPredicate::Implemented(tr) - if tr.trait_ == t - && tr.substs[0] - == Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)) => - { - Some(Binders { value: tr, num_binders: b.num_binders }) - } - _ => None, - }) - .expect("trait bound for known super trait not found"); - current_trait_ref = super_trait_ref.cloned().subst(¤t_trait_ref.substs); - } - - // We need to renumber the variables a bit now: from ^0.0, ^0.1, ^0.2, ... - // to ^0.0, ^1.0, ^1.1. The reason for this is that the first variable comes - // from the dyn Trait binder, while the other variables come from the impl. - let new_substs = Substs::builder(num_vars + 1) - .push(Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0))) - .fill_with_bound_vars(DebruijnIndex::ONE, 0) - .build(); - - let self_bounds = - vec![GenericPredicate::Implemented(self_trait_ref.subst_bound_vars(&new_substs))]; - let super_bounds = - vec![GenericPredicate::Implemented(current_trait_ref.subst_bound_vars(&new_substs))]; - - let substs = Substs::builder(2) - .push(Ty::Dyn(self_bounds.into())) - .push(Ty::Dyn(super_bounds.into())) - .build(); - - let trait_ref = TraitRef { trait_: unsize_trait, substs }; - - BuiltinImplData { num_vars, trait_ref, where_clauses: Vec::new(), assoc_ty_values: Vec::new() } -} - -fn get_unsize_trait(db: &dyn HirDatabase, krate: CrateId) -> Option { - let target = db.lang_item(krate, "unsize".into())?; - match target { - LangItemTarget::TraitId(t) => Some(t), - _ => None, - } -} diff --git a/crates/ra_hir_ty/src/traits/chalk/mapping.rs b/crates/ra_hir_ty/src/traits/chalk/mapping.rs index 848cb6e7dbc..7bdb6264e6a 100644 --- a/crates/ra_hir_ty/src/traits/chalk/mapping.rs +++ b/crates/ra_hir_ty/src/traits/chalk/mapping.rs @@ -271,6 +271,7 @@ fn to_chalk(self, db: &dyn HirDatabase) -> TypeName { } TypeCtor::Never => TypeName::Never, + // FIXME convert these TypeCtor::Adt(_) | TypeCtor::Array | TypeCtor::FnPtr { .. } diff --git a/crates/ra_hir_ty/src/utils.rs b/crates/ra_hir_ty/src/utils.rs index c45820ff059..e3e2442680e 100644 --- a/crates/ra_hir_ty/src/utils.rs +++ b/crates/ra_hir_ty/src/utils.rs @@ -110,38 +110,6 @@ pub(super) fn all_super_trait_refs(db: &dyn HirDatabase, trait_ref: TraitRef) -> result } -/// Finds a path from a trait to one of its super traits. Returns an empty -/// vector if there is no path. -pub(super) fn find_super_trait_path( - db: &dyn DefDatabase, - trait_: TraitId, - super_trait: TraitId, -) -> Vec { - let mut result = Vec::with_capacity(2); - result.push(trait_); - return if go(db, super_trait, &mut result) { result } else { Vec::new() }; - - fn go(db: &dyn DefDatabase, super_trait: TraitId, path: &mut Vec) -> bool { - let trait_ = *path.last().unwrap(); - if trait_ == super_trait { - return true; - } - - for tt in direct_super_traits(db, trait_) { - if path.contains(&tt) { - continue; - } - path.push(tt); - if go(db, super_trait, path) { - return true; - } else { - path.pop(); - } - } - false - } -} - pub(super) fn associated_type_by_name_including_super_traits( db: &dyn HirDatabase, trait_ref: TraitRef,