From 3397ca679fb0156c9f102ab82354e2bcef5f4dd1 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 2 Feb 2020 13:04:22 +0100 Subject: Fix APIT some more --- crates/ra_hir_ty/src/lib.rs | 153 +++++++++++++++++++++++--------------------- 1 file changed, 80 insertions(+), 73 deletions(-) (limited to 'crates/ra_hir_ty/src/lib.rs') diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs index 1e162943c..6eccd7fa8 100644 --- a/crates/ra_hir_ty/src/lib.rs +++ b/crates/ra_hir_ty/src/lib.rs @@ -44,11 +44,11 @@ use std::sync::Arc; use std::{fmt, iter, mem}; use hir_def::{ - expr::ExprId, type_ref::Mutability, AdtId, AssocContainerId, DefWithBodyId, GenericDefId, - HasModule, Lookup, TraitId, TypeAliasId, TypeParamId, generics::TypeParamProvenance, + expr::ExprId, generics::TypeParamProvenance, type_ref::Mutability, AdtId, AssocContainerId, + DefWithBodyId, GenericDefId, HasModule, Lookup, TraitId, TypeAliasId, TypeParamId, }; -use ra_db::{impl_intern_key, salsa, CrateId}; use hir_expand::name::Name; +use ra_db::{impl_intern_key, salsa, CrateId}; use crate::{ db::HirDatabase, @@ -360,9 +360,7 @@ impl Substs { /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`). pub(crate) fn type_params(generic_params: &Generics) -> Substs { - Substs( - generic_params.iter().map(|(id, _)| Ty::Param(id)).collect(), - ) + Substs(generic_params.iter().map(|(id, _)| Ty::Param(id)).collect()) } /// Return Substs that replace each parameter by a bound variable. @@ -448,7 +446,9 @@ pub struct Binders { } impl Binders { - pub fn new(num_binders: usize, value: T) -> Self { Self { num_binders, value } } + pub fn new(num_binders: usize, value: T) -> Self { + Self { num_binders, value } + } } impl Binders { @@ -906,8 +906,7 @@ impl HirDisplay for ApplicationTy { write!(f, ") -> {}", sig.ret().display(f.db))?; } TypeCtor::FnDef(def) => { - let sig = f.db.callable_item_signature(def) - .subst(&self.parameters); + let sig = f.db.callable_item_signature(def).subst(&self.parameters); let name = match def { CallableDef::FunctionId(ff) => f.db.function_data(ff).name.clone(), CallableDef::StructId(s) => f.db.struct_data(s).name.clone(), @@ -1037,17 +1036,19 @@ impl HirDisplay for Ty { Ty::Apply(a_ty) => a_ty.hir_fmt(f)?, Ty::Projection(p_ty) => p_ty.hir_fmt(f)?, Ty::Param(id) => { - let generic_params = f.db.generic_params(id.parent); - let param_data = &generic_params.types[id.local_id]; + let generics = generics(f.db, id.parent); + let param_data = &generics.params.types[id.local_id]; match param_data.provenance { TypeParamProvenance::TypeParamList | TypeParamProvenance::TraitSelf => { write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))? } TypeParamProvenance::ArgumentImplTrait => { - write!(f, "impl TODO")? + let bounds = f.db.generic_predicates_for_param(*id); + write!(f, "impl ")?; + write_bounds_like_dyn_trait(&bounds, f)?; } } - }, + } Ty::Bound(idx) => write!(f, "?{}", idx)?, Ty::Dyn(predicates) | Ty::Opaque(predicates) => { match self { @@ -1055,66 +1056,7 @@ impl HirDisplay for Ty { Ty::Opaque(_) => write!(f, "impl ")?, _ => unreachable!(), }; - // Note: This code is written to produce nice results (i.e. - // corresponding to surface Rust) for types that can occur in - // actual Rust. It will have weird results if the predicates - // aren't as expected (i.e. self types = $0, projection - // predicates for a certain trait come after the Implemented - // predicate for that trait). - let mut first = true; - let mut angle_open = false; - for p in predicates.iter() { - match p { - GenericPredicate::Implemented(trait_ref) => { - if angle_open { - write!(f, ">")?; - } - if !first { - write!(f, " + ")?; - } - // We assume that the self type is $0 (i.e. the - // existential) here, which is the only thing that's - // possible in actual Rust, and hence don't print it - write!(f, "{}", f.db.trait_data(trait_ref.trait_).name.clone())?; - if trait_ref.substs.len() > 1 { - write!(f, "<")?; - f.write_joined(&trait_ref.substs[1..], ", ")?; - // there might be assoc type bindings, so we leave the angle brackets open - angle_open = true; - } - } - GenericPredicate::Projection(projection_pred) => { - // in types in actual Rust, these will always come - // after the corresponding Implemented predicate - if angle_open { - write!(f, ", ")?; - } else { - write!(f, "<")?; - angle_open = true; - } - let name = - f.db.type_alias_data(projection_pred.projection_ty.associated_ty) - .name - .clone(); - write!(f, "{} = ", name)?; - projection_pred.ty.hir_fmt(f)?; - } - GenericPredicate::Error => { - if angle_open { - // impl Trait - write!(f, ", ")?; - } else if !first { - // impl Trait + {error} - write!(f, " + ")?; - } - p.hir_fmt(f)?; - } - } - first = false; - } - if angle_open { - write!(f, ">")?; - } + write_bounds_like_dyn_trait(&predicates, f)?; } Ty::Unknown => write!(f, "{{unknown}}")?, Ty::Infer(..) => write!(f, "_")?, @@ -1123,6 +1065,71 @@ impl HirDisplay for Ty { } } +fn write_bounds_like_dyn_trait( + predicates: &[GenericPredicate], + f: &mut HirFormatter, +) -> fmt::Result { + // Note: This code is written to produce nice results (i.e. + // corresponding to surface Rust) for types that can occur in + // actual Rust. It will have weird results if the predicates + // aren't as expected (i.e. self types = $0, projection + // predicates for a certain trait come after the Implemented + // predicate for that trait). + let mut first = true; + let mut angle_open = false; + for p in predicates.iter() { + match p { + GenericPredicate::Implemented(trait_ref) => { + if angle_open { + write!(f, ">")?; + } + if !first { + write!(f, " + ")?; + } + // We assume that the self type is $0 (i.e. the + // existential) here, which is the only thing that's + // possible in actual Rust, and hence don't print it + write!(f, "{}", f.db.trait_data(trait_ref.trait_).name.clone())?; + if trait_ref.substs.len() > 1 { + write!(f, "<")?; + f.write_joined(&trait_ref.substs[1..], ", ")?; + // there might be assoc type bindings, so we leave the angle brackets open + angle_open = true; + } + } + GenericPredicate::Projection(projection_pred) => { + // in types in actual Rust, these will always come + // after the corresponding Implemented predicate + if angle_open { + write!(f, ", ")?; + } else { + write!(f, "<")?; + angle_open = true; + } + let name = + f.db.type_alias_data(projection_pred.projection_ty.associated_ty).name.clone(); + write!(f, "{} = ", name)?; + projection_pred.ty.hir_fmt(f)?; + } + GenericPredicate::Error => { + if angle_open { + // impl Trait + write!(f, ", ")?; + } else if !first { + // impl Trait + {error} + write!(f, " + ")?; + } + p.hir_fmt(f)?; + } + } + first = false; + } + if angle_open { + write!(f, ">")?; + } + Ok(()) +} + impl TraitRef { fn hir_fmt_ext(&self, f: &mut HirFormatter, use_as: bool) -> fmt::Result { if f.should_truncate() { -- cgit v1.2.3