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/infer.rs | 7 +- crates/ra_hir_ty/src/lib.rs | 153 ++++++++++++++++++----------------- crates/ra_hir_ty/src/lower.rs | 5 +- crates/ra_hir_ty/src/tests/traits.rs | 51 ++++++------ 4 files changed, 115 insertions(+), 101 deletions(-) (limited to 'crates/ra_hir_ty') diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs index 0d65984ee..8d5b7c943 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs @@ -479,8 +479,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { fn collect_fn(&mut self, data: &FunctionData) { let body = Arc::clone(&self.body); // avoid borrow checker problem - for (type_ref, pat) in data.params.iter().zip(body.params.iter()) { - let ty = self.make_ty_with_mode(type_ref, ImplTraitLoweringMode::Param); + let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver).with_impl_trait_mode(ImplTraitLoweringMode::Param); + let param_tys = data.params.iter().map(|type_ref| Ty::from_hir(&ctx, type_ref)).collect::>(); + for (ty, pat) in param_tys.into_iter().zip(body.params.iter()) { + let ty = self.insert_type_vars(ty); + let ty = self.normalize_associated_types_in(ty); self.infer_pat(*pat, &ty, BindingMode::default()); } 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() { diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 42367b181..e375c4847 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs @@ -10,12 +10,13 @@ use std::sync::Arc; use hir_def::{ builtin_type::BuiltinType, - generics::{WherePredicate, WherePredicateTarget}, + generics::{WherePredicate, WherePredicateTarget, TypeParamProvenance}, path::{GenericArg, Path, PathSegment, PathSegments}, resolver::{HasResolver, Resolver, TypeNs}, type_ref::{TypeBound, TypeRef}, AdtId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, LocalStructFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, UnionId, VariantId, + TypeParamId }; use ra_arena::map::ArenaMap; use ra_db::CrateId; @@ -30,8 +31,6 @@ use crate::{ Binders, FnSig, GenericPredicate, PolyFnSig, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, }; -use hir_def::TypeParamId; -use hir_def::generics::TypeParamProvenance; #[derive(Debug)] pub struct TyLoweringContext<'a, DB: HirDatabase> { diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs index e6f697fa3..bae5eae07 100644 --- a/crates/ra_hir_ty/src/tests/traits.rs +++ b/crates/ra_hir_ty/src/tests/traits.rs @@ -856,11 +856,11 @@ trait Trait { fn foo(&self) -> T; fn foo2(&self) -> i64; } -fn bar(impl Trait) {} +fn bar(x: impl Trait) {} struct S(T); impl Trait for S {} -fn test(x: impl Trait, y: &impl Trait) { +fn test(x: impl Trait, y: &impl Trait) { x; y; let z = S(1); @@ -876,27 +876,32 @@ fn test(x: impl Trait, y: &impl Trait) { @r###" [30; 34) 'self': &Self [55; 59) 'self': &Self - [99; 101) '{}': () - [111; 112) 'x': impl Trait - [131; 132) 'y': &impl Trait - [152; 269) '{ ...2(); }': () - [158; 159) 'x': impl Trait - [165; 166) 'y': &impl Trait - [176; 177) 'z': impl Trait - [180; 183) 'bar': fn bar() -> impl Trait - [180; 185) 'bar()': impl Trait - [191; 192) 'x': impl Trait - [191; 198) 'x.foo()': u64 - [204; 205) 'y': &impl Trait - [204; 211) 'y.foo()': u64 - [217; 218) 'z': impl Trait - [217; 224) 'z.foo()': u64 - [230; 231) 'x': impl Trait - [230; 238) 'x.foo2()': i64 - [244; 245) 'y': &impl Trait - [244; 252) 'y.foo2()': i64 - [258; 259) 'z': impl Trait - [258; 266) 'z.foo2()': i64 + [78; 79) 'x': impl Trait + [98; 100) '{}': () + [155; 156) 'x': impl Trait + [175; 176) 'y': &impl Trait + [196; 324) '{ ...2(); }': () + [202; 203) 'x': impl Trait + [209; 210) 'y': &impl Trait + [220; 221) 'z': S + [224; 225) 'S': S(u16) -> S + [224; 228) 'S(1)': S + [226; 227) '1': u16 + [234; 237) 'bar': fn bar>(S) -> () + [234; 240) 'bar(z)': () + [238; 239) 'z': S + [246; 247) 'x': impl Trait + [246; 253) 'x.foo()': u64 + [259; 260) 'y': &impl Trait + [259; 266) 'y.foo()': u32 + [272; 273) 'z': S + [272; 279) 'z.foo()': u16 + [285; 286) 'x': impl Trait + [285; 293) 'x.foo2()': i64 + [299; 300) 'y': &impl Trait + [299; 307) 'y.foo2()': i64 + [313; 314) 'z': S + [313; 321) 'z.foo2()': i64 "### ); } -- cgit v1.2.3