From e63c00f100e960f7b72997026b4b2cd3cd29774b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 5 Jun 2020 14:55:23 +0200 Subject: Rename resolve_relative_path -> resolve_path For things like `concant!(env!("OUT_DIR"))`, we need to support abs paths --- crates/ra_hir_ty/src/test_db.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'crates/ra_hir_ty') diff --git a/crates/ra_hir_ty/src/test_db.rs b/crates/ra_hir_ty/src/test_db.rs index 8498d3d96..43927c991 100644 --- a/crates/ra_hir_ty/src/test_db.rs +++ b/crates/ra_hir_ty/src/test_db.rs @@ -72,12 +72,8 @@ impl FileLoader for TestDB { fn file_text(&self, file_id: FileId) -> Arc { FileLoaderDelegate(self).file_text(file_id) } - fn resolve_relative_path( - &self, - anchor: FileId, - relative_path: &RelativePath, - ) -> Option { - FileLoaderDelegate(self).resolve_relative_path(anchor, relative_path) + fn resolve_path(&self, anchor: FileId, relative_path: &RelativePath) -> Option { + FileLoaderDelegate(self).resolve_path(anchor, relative_path) } fn relevant_crates(&self, file_id: FileId) -> Arc> { FileLoaderDelegate(self).relevant_crates(file_id) -- cgit v1.2.3 From bba374bab2ee53643a899e7ea459b4ab27663bd0 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 5 Jun 2020 15:07:30 +0200 Subject: More direct signature for resolve_path --- crates/ra_hir_ty/src/test_db.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'crates/ra_hir_ty') diff --git a/crates/ra_hir_ty/src/test_db.rs b/crates/ra_hir_ty/src/test_db.rs index 43927c991..21a3bdfd1 100644 --- a/crates/ra_hir_ty/src/test_db.rs +++ b/crates/ra_hir_ty/src/test_db.rs @@ -72,8 +72,8 @@ impl FileLoader for TestDB { fn file_text(&self, file_id: FileId) -> Arc { FileLoaderDelegate(self).file_text(file_id) } - fn resolve_path(&self, anchor: FileId, relative_path: &RelativePath) -> Option { - FileLoaderDelegate(self).resolve_path(anchor, relative_path) + fn resolve_path(&self, anchor: FileId, path: &str) -> Option { + FileLoaderDelegate(self).resolve_path(anchor, path) } fn relevant_crates(&self, file_id: FileId) -> Arc> { FileLoaderDelegate(self).relevant_crates(file_id) -- cgit v1.2.3 From 69854f7795e2a5f961f4e35c13a655f0d41cc306 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 5 Jun 2020 17:06:07 +0200 Subject: Upgrade Chalk to published version --- crates/ra_hir_ty/Cargo.toml | 4 ++-- crates/ra_hir_ty/src/traits/chalk/mapping.rs | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'crates/ra_hir_ty') diff --git a/crates/ra_hir_ty/Cargo.toml b/crates/ra_hir_ty/Cargo.toml index 4b8dcdc07..112fcd07e 100644 --- a/crates/ra_hir_ty/Cargo.toml +++ b/crates/ra_hir_ty/Cargo.toml @@ -27,8 +27,8 @@ test_utils = { path = "../test_utils" } scoped-tls = "1" -chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "329b7f3fdd2431ed6f6778cde53f22374c7d094c" } -chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "329b7f3fdd2431ed6f6778cde53f22374c7d094c" } +chalk-solve = "0.11" +chalk-ir = "0.11" [dev-dependencies] insta = "0.16.0" diff --git a/crates/ra_hir_ty/src/traits/chalk/mapping.rs b/crates/ra_hir_ty/src/traits/chalk/mapping.rs index 5f6daf842..9150f65d4 100644 --- a/crates/ra_hir_ty/src/traits/chalk/mapping.rs +++ b/crates/ra_hir_ty/src/traits/chalk/mapping.rs @@ -447,6 +447,11 @@ impl ToChalk for GenericPredicate { let ty = from_chalk(db, projection_eq.ty); GenericPredicate::Projection(ProjectionPredicate { projection_ty, ty }) } + + chalk_ir::WhereClause::LifetimeOutlives(_) => { + // we shouldn't get these from Chalk + panic!("encountered LifetimeOutlives from Chalk") + } } } } -- cgit v1.2.3 From 02962b374ecefd6f2a75956f4fb18806531d1d51 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Wed, 4 Mar 2020 23:00:44 +0100 Subject: Implement return position impl trait / opaque type support This is working, but I'm not that happy with how the lowering works. We might need an additional representation between `TypeRef` and `Ty` where names are resolved and `impl Trait` bounds are separated out, but things like inference variables don't exist and `impl Trait` is always represented the same way. Also note that this doesn't implement correct handling of RPIT *inside* the function (which involves turning the `impl Trait`s into variables and creating obligations for them). That intermediate representation might help there as well. --- crates/ra_hir_ty/src/db.rs | 20 +++- crates/ra_hir_ty/src/display.rs | 37 +++++-- crates/ra_hir_ty/src/infer.rs | 23 +---- crates/ra_hir_ty/src/lib.rs | 98 ++++++++++++++++-- crates/ra_hir_ty/src/lower.rs | 143 ++++++++++++++++++++++---- crates/ra_hir_ty/src/tests/traits.rs | 47 ++++++++- crates/ra_hir_ty/src/traits/chalk.rs | 52 ++++++++-- crates/ra_hir_ty/src/traits/chalk/interner.rs | 2 + crates/ra_hir_ty/src/traits/chalk/mapping.rs | 45 +++++++- crates/ra_hir_ty/src/traits/chalk/tls.rs | 5 + 10 files changed, 395 insertions(+), 77 deletions(-) (limited to 'crates/ra_hir_ty') diff --git a/crates/ra_hir_ty/src/db.rs b/crates/ra_hir_ty/src/db.rs index 0a8bb24ac..bf71d38d6 100644 --- a/crates/ra_hir_ty/src/db.rs +++ b/crates/ra_hir_ty/src/db.rs @@ -3,8 +3,8 @@ use std::sync::Arc; use hir_def::{ - db::DefDatabase, DefWithBodyId, GenericDefId, ImplId, LocalFieldId, TraitId, TypeParamId, - VariantId, + db::DefDatabase, DefWithBodyId, FunctionId, GenericDefId, ImplId, LocalFieldId, TraitId, + TypeParamId, VariantId, }; use ra_arena::map::ArenaMap; use ra_db::{impl_intern_key, salsa, CrateId, Upcast}; @@ -13,8 +13,8 @@ use ra_prof::profile; use crate::{ method_resolution::{CrateImplDefs, TyFingerprint}, traits::{chalk, AssocTyValue, Impl}, - Binders, CallableDef, GenericPredicate, InferenceResult, PolyFnSig, Substs, TraitRef, Ty, - TyDefId, TypeCtor, ValueTyDefId, + Binders, CallableDef, GenericPredicate, InferenceResult, OpaqueTyId, PolyFnSig, + ReturnTypeImplTraits, Substs, TraitRef, Ty, TyDefId, TypeCtor, ValueTyDefId, }; use hir_expand::name::Name; @@ -48,6 +48,12 @@ pub trait HirDatabase: DefDatabase + Upcast { #[salsa::invoke(crate::callable_item_sig)] fn callable_item_signature(&self, def: CallableDef) -> PolyFnSig; + #[salsa::invoke(crate::lower::return_type_impl_traits)] + fn return_type_impl_traits( + &self, + def: FunctionId, + ) -> Option>>; + #[salsa::invoke(crate::lower::generic_predicates_for_param_query)] #[salsa::cycle(crate::lower::generic_predicates_for_param_recover)] fn generic_predicates_for_param( @@ -80,6 +86,8 @@ pub trait HirDatabase: DefDatabase + Upcast { #[salsa::interned] fn intern_type_param_id(&self, param_id: TypeParamId) -> GlobalTypeParamId; #[salsa::interned] + fn intern_impl_trait_id(&self, id: OpaqueTyId) -> InternedOpaqueTyId; + #[salsa::interned] fn intern_chalk_impl(&self, impl_: Impl) -> crate::traits::GlobalImplId; #[salsa::interned] fn intern_assoc_ty_value(&self, assoc_ty_value: AssocTyValue) -> crate::traits::AssocTyValueId; @@ -142,3 +150,7 @@ fn hir_database_is_object_safe() { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct GlobalTypeParamId(salsa::InternId); impl_intern_key!(GlobalTypeParamId); + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct InternedOpaqueTyId(salsa::InternId); +impl_intern_key!(InternedOpaqueTyId); diff --git a/crates/ra_hir_ty/src/display.rs b/crates/ra_hir_ty/src/display.rs index b9c4d2e89..3e63a2415 100644 --- a/crates/ra_hir_ty/src/display.rs +++ b/crates/ra_hir_ty/src/display.rs @@ -359,6 +359,21 @@ impl HirDisplay for ApplicationTy { write!(f, ">")?; } } + TypeCtor::OpaqueType(opaque_ty_id) => { + let bounds = match opaque_ty_id { + crate::OpaqueTyId::ReturnTypeImplTrait(func, idx) => { + let datas = + f.db.return_type_impl_traits(func).expect("impl trait id without data"); + let data = (*datas) + .as_ref() + .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); + data.clone().subst(&self.parameters) + } + }; + write!(f, "impl ")?; + write_bounds_like_dyn_trait(&bounds.value, f)?; + // FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution + } TypeCtor::Closure { .. } => { let sig = self.parameters[0].callable_sig(f.db); if let Some(sig) = sig { @@ -427,14 +442,24 @@ impl HirDisplay for Ty { } } Ty::Bound(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?, - Ty::Dyn(predicates) | Ty::Opaque(predicates) => { - match self { - Ty::Dyn(_) => write!(f, "dyn ")?, - Ty::Opaque(_) => write!(f, "impl ")?, - _ => unreachable!(), - }; + Ty::Dyn(predicates) => { + write!(f, "dyn ")?; write_bounds_like_dyn_trait(predicates, f)?; } + Ty::Opaque(opaque_ty) => { + let bounds = match opaque_ty.opaque_ty_id { + crate::OpaqueTyId::ReturnTypeImplTrait(func, idx) => { + let datas = + f.db.return_type_impl_traits(func).expect("impl trait id without data"); + let data = (*datas) + .as_ref() + .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); + data.clone().subst(&opaque_ty.parameters) + } + }; + write!(f, "impl ")?; + write_bounds_like_dyn_trait(&bounds.value, f)?; + } Ty::Unknown => write!(f, "{{unknown}}")?, Ty::Infer(..) => write!(f, "_")?, } diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs index dc77e88e5..d9bf3c2f0 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs @@ -39,8 +39,8 @@ use ra_syntax::SmolStr; use super::{ primitive::{FloatTy, IntTy}, traits::{Guidance, Obligation, ProjectionPredicate, Solution}, - ApplicationTy, GenericPredicate, InEnvironment, ProjectionTy, Substs, TraitEnvironment, - TraitRef, Ty, TypeCtor, TypeWalk, Uncertain, + ApplicationTy, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, + TypeWalk, Uncertain, }; use crate::{ db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, @@ -383,25 +383,6 @@ impl<'a> InferenceContext<'a> { ) -> Ty { match assoc_ty { Some(res_assoc_ty) => { - // FIXME: - // Check if inner_ty is is `impl Trait` and contained input TypeAlias id - // this is a workaround while Chalk assoc type projection doesn't always work yet, - // but once that is fixed I don't think we should keep this - // (we'll probably change how associated types are resolved anyway) - if let Ty::Opaque(ref predicates) = inner_ty { - for p in predicates.iter() { - if let GenericPredicate::Projection(projection) = p { - if projection.projection_ty.associated_ty == res_assoc_ty { - if let ty_app!(_, params) = &projection.ty { - if params.len() == 0 { - return projection.ty.clone(); - } - } - } - } - } - } - let ty = self.table.new_type_var(); let builder = Substs::build_for_def(self.db, res_assoc_ty) .push(inner_ty) diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs index 9fa8d3bdc..135976fcd 100644 --- a/crates/ra_hir_ty/src/lib.rs +++ b/crates/ra_hir_ty/src/lib.rs @@ -147,6 +147,12 @@ pub enum TypeCtor { /// an **application type** like `(Iterator::Item)`. AssociatedType(TypeAliasId), + /// This represents a placeholder for an opaque type in situations where we + /// don't know the hidden type (i.e. currently almost always). This is + /// analogous to the `AssociatedType` type constructor. As with that one, + /// these are only produced by Chalk. + OpaqueType(OpaqueTyId), + /// The type of a specific closure. /// /// The closure signature is stored in a `FnPtr` type in the first type @@ -194,6 +200,14 @@ impl TypeCtor { let generic_params = generics(db.upcast(), type_alias.into()); generic_params.len() } + TypeCtor::OpaqueType(opaque_ty_id) => { + match opaque_ty_id { + OpaqueTyId::ReturnTypeImplTrait(func, _) => { + let generic_params = generics(db.upcast(), func.into()); + generic_params.len() + } + } + } TypeCtor::FnPtr { num_args } => num_args as usize + 1, TypeCtor::Tuple { cardinality } => cardinality as usize, } @@ -220,6 +234,11 @@ impl TypeCtor { TypeCtor::AssociatedType(type_alias) => { Some(type_alias.lookup(db.upcast()).module(db.upcast()).krate) } + TypeCtor::OpaqueType(opaque_ty_id) => match opaque_ty_id { + OpaqueTyId::ReturnTypeImplTrait(func, _) => { + Some(func.lookup(db.upcast()).module(db.upcast()).krate) + } + }, } } @@ -241,6 +260,7 @@ impl TypeCtor { TypeCtor::Adt(adt) => Some(adt.into()), TypeCtor::FnDef(callable) => Some(callable.into()), TypeCtor::AssociatedType(type_alias) => Some(type_alias.into()), + TypeCtor::OpaqueType(_impl_trait_id) => None, } } } @@ -254,6 +274,12 @@ pub struct ApplicationTy { pub parameters: Substs, } +#[derive(Clone, PartialEq, Eq, Debug, Hash)] +pub struct OpaqueTy { + pub opaque_ty_id: OpaqueTyId, + pub parameters: Substs, +} + /// A "projection" type corresponds to an (unnormalized) /// projection like `>::Foo`. Note that the /// trait and all its parameters are fully known. @@ -308,6 +334,12 @@ pub enum Ty { /// trait and all its parameters are fully known. Projection(ProjectionTy), + /// An opaque type (`impl Trait`). + /// + /// This is currently only used for return type impl trait; each instance of + /// `impl Trait` in a return type gets its own ID. + Opaque(OpaqueTy), + /// A placeholder for a type parameter; for example, `T` in `fn f(x: T) /// {}` when we're type-checking the body of that function. In this /// situation, we know this stands for *some* type, but don't know the exact @@ -332,12 +364,6 @@ pub enum Ty { /// didn't seem worth the overhead yet. Dyn(Arc<[GenericPredicate]>), - /// An opaque type (`impl Trait`). - /// - /// The predicates are quantified over the `Self` type; see `Ty::Dyn` for - /// more. - Opaque(Arc<[GenericPredicate]>), - /// A placeholder for a type which could not be computed; this is propagated /// to avoid useless error messages. Doubles as a placeholder where type /// variables are inserted before type checking, since we want to try to @@ -490,7 +516,7 @@ impl Deref for Substs { } } -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] pub struct Binders { pub num_binders: usize, pub value: T, @@ -534,6 +560,20 @@ impl Binders { } } +impl TypeWalk for Binders { + fn walk(&self, f: &mut impl FnMut(&Ty)) { + self.value.walk(f); + } + + fn walk_mut_binders( + &mut self, + f: &mut impl FnMut(&mut Ty, DebruijnIndex), + binders: DebruijnIndex, + ) { + self.value.walk_mut_binders(f, binders.shifted_in()) + } +} + /// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait. /// Name to be bikeshedded: TraitBound? TraitImplements? #[derive(Clone, PartialEq, Eq, Debug, Hash)] @@ -947,11 +987,16 @@ impl TypeWalk for Ty { t.walk(f); } } - Ty::Dyn(predicates) | Ty::Opaque(predicates) => { + Ty::Dyn(predicates) => { for p in predicates.iter() { p.walk(f); } } + Ty::Opaque(o_ty) => { + for t in o_ty.parameters.iter() { + t.walk(f); + } + } Ty::Placeholder { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} } f(self); @@ -969,13 +1014,48 @@ impl TypeWalk for Ty { Ty::Projection(p_ty) => { p_ty.parameters.walk_mut_binders(f, binders); } - Ty::Dyn(predicates) | Ty::Opaque(predicates) => { + Ty::Dyn(predicates) => { for p in make_mut_slice(predicates) { p.walk_mut_binders(f, binders.shifted_in()); } } + Ty::Opaque(o_ty) => { + o_ty.parameters.walk_mut_binders(f, binders); + } Ty::Placeholder { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} } f(self, binders); } } + +impl TypeWalk for Vec { + fn walk(&self, f: &mut impl FnMut(&Ty)) { + for t in self { + t.walk(f); + } + } + fn walk_mut_binders( + &mut self, + f: &mut impl FnMut(&mut Ty, DebruijnIndex), + binders: DebruijnIndex, + ) { + for t in self { + t.walk_mut_binders(f, binders); + } + } +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] +pub enum OpaqueTyId { + ReturnTypeImplTrait(hir_def::FunctionId, u16), +} + +#[derive(Clone, PartialEq, Eq, Debug, Hash)] +pub struct ReturnTypeImplTraits { + pub(crate) impl_traits: Vec, +} + +#[derive(Clone, PartialEq, Eq, Debug, Hash)] +pub(crate) struct ReturnTypeImplTrait { + pub(crate) bounds: Binders>, +} diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 35ac86a46..dfc018b0b 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs @@ -31,8 +31,9 @@ use crate::{ all_super_trait_refs, associated_type_by_name_including_super_traits, generics, make_mut_slice, variant_data, }, - Binders, BoundVar, DebruijnIndex, FnSig, GenericPredicate, PolyFnSig, ProjectionPredicate, - ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk, + Binders, BoundVar, DebruijnIndex, FnSig, GenericPredicate, OpaqueTy, OpaqueTyId, PolyFnSig, + ProjectionPredicate, ProjectionTy, ReturnTypeImplTrait, ReturnTypeImplTraits, Substs, + TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk, }; use hir_expand::name::Name; @@ -47,7 +48,16 @@ pub struct TyLoweringContext<'a> { /// possible currently, so this should be fine for now. pub type_param_mode: TypeParamLoweringMode, pub impl_trait_mode: ImplTraitLoweringMode, - pub impl_trait_counter: std::cell::Cell, + impl_trait_counter: std::cell::Cell, + /// When turning `impl Trait` into opaque types, we have to collect the + /// bounds at the same time to get the IDs correct (without becoming too + /// complicated). I don't like using interior mutability (as for the + /// counter), but I've tried and failed to make the lifetimes work for + /// passing around a `&mut TyLoweringContext`. The core problem is that + /// we're grouping the mutable data (the counter and this field) together + /// with the immutable context (the references to the DB and resolver). + /// Splitting this up would be a possible fix. + opaque_type_data: std::cell::RefCell>, } impl<'a> TyLoweringContext<'a> { @@ -56,26 +66,42 @@ impl<'a> TyLoweringContext<'a> { let impl_trait_mode = ImplTraitLoweringMode::Disallowed; let type_param_mode = TypeParamLoweringMode::Placeholder; let in_binders = DebruijnIndex::INNERMOST; - Self { db, resolver, in_binders, impl_trait_mode, impl_trait_counter, type_param_mode } + let opaque_type_data = std::cell::RefCell::new(Vec::new()); + Self { + db, + resolver, + in_binders, + impl_trait_mode, + impl_trait_counter, + type_param_mode, + opaque_type_data, + } } - pub fn with_shifted_in( + pub fn with_debruijn( &self, debruijn: DebruijnIndex, f: impl FnOnce(&TyLoweringContext) -> T, ) -> T { + let opaque_ty_data_vec = self.opaque_type_data.replace(Vec::new()); let new_ctx = Self { - in_binders: self.in_binders.shifted_in_from(debruijn), + in_binders: debruijn, impl_trait_counter: std::cell::Cell::new(self.impl_trait_counter.get()), + opaque_type_data: std::cell::RefCell::new(opaque_ty_data_vec), ..*self }; let result = f(&new_ctx); self.impl_trait_counter.set(new_ctx.impl_trait_counter.get()); + self.opaque_type_data.replace(new_ctx.opaque_type_data.into_inner()); result } - pub fn shifted_in(self, debruijn: DebruijnIndex) -> Self { - Self { in_binders: self.in_binders.shifted_in_from(debruijn), ..self } + pub fn with_shifted_in( + &self, + debruijn: DebruijnIndex, + f: impl FnOnce(&TyLoweringContext) -> T, + ) -> T { + self.with_debruijn(self.in_binders.shifted_in_from(debruijn), f) } pub fn with_impl_trait_mode(self, impl_trait_mode: ImplTraitLoweringMode) -> Self { @@ -167,20 +193,47 @@ impl Ty { TypeRef::ImplTrait(bounds) => { match ctx.impl_trait_mode { ImplTraitLoweringMode::Opaque => { - let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)); - let predicates = ctx.with_shifted_in(DebruijnIndex::ONE, |ctx| { - bounds - .iter() - .flat_map(|b| { - GenericPredicate::from_type_bound(ctx, b, self_ty.clone()) - }) - .collect() - }); - Ty::Opaque(predicates) + let idx = ctx.impl_trait_counter.get(); + ctx.impl_trait_counter.set(idx + 1); + + assert!(idx as usize == ctx.opaque_type_data.borrow().len()); + // this dance is to make sure the data is in the right + // place even if we encounter more opaque types while + // lowering the bounds + ctx.opaque_type_data + .borrow_mut() + .push(ReturnTypeImplTrait { bounds: Binders::new(1, Vec::new()) }); + // We don't want to lower the bounds inside the binders + // we're currently in, because they don't end up inside + // those binders. E.g. when we have `impl Trait>`, the `impl OtherTrait` can't refer + // to the self parameter from `impl Trait`, and the + // bounds aren't actually stored nested within each + // other, but separately. So if the `T` refers to a type + // parameter of the outer function, it's just one binder + // away instead of two. + let actual_opaque_type_data = ctx + .with_debruijn(DebruijnIndex::INNERMOST, |ctx| { + ReturnTypeImplTrait::from_hir(ctx, &bounds) + }); + ctx.opaque_type_data.borrow_mut()[idx as usize] = actual_opaque_type_data; + + let func = match ctx.resolver.generic_def() { + Some(GenericDefId::FunctionId(f)) => f, + _ => { + // this shouldn't happen + return (Ty::Unknown, None); + } + }; + let impl_trait_id = OpaqueTyId::ReturnTypeImplTrait(func, idx); + let generics = generics(ctx.db.upcast(), func.into()); + let parameters = Substs::bound_vars(&generics, ctx.in_binders); + Ty::Opaque(OpaqueTy { opaque_ty_id: impl_trait_id, parameters }) } ImplTraitLoweringMode::Param => { let idx = ctx.impl_trait_counter.get(); - ctx.impl_trait_counter.set(idx + 1); + // FIXME we're probably doing something wrong here + ctx.impl_trait_counter.set(idx + count_impl_traits(type_ref) as u16); if let Some(def) = ctx.resolver.generic_def() { let generics = generics(ctx.db.upcast(), def); let param = generics @@ -197,7 +250,8 @@ impl Ty { } ImplTraitLoweringMode::Variable => { let idx = ctx.impl_trait_counter.get(); - ctx.impl_trait_counter.set(idx + 1); + // FIXME we're probably doing something wrong here + ctx.impl_trait_counter.set(idx + count_impl_traits(type_ref) as u16); let (parent_params, self_params, list_params, _impl_trait_params) = if let Some(def) = ctx.resolver.generic_def() { let generics = generics(ctx.db.upcast(), def); @@ -663,6 +717,29 @@ fn assoc_type_bindings_from_type_bound<'a>( }) } +impl ReturnTypeImplTrait { + fn from_hir(ctx: &TyLoweringContext, bounds: &[TypeBound]) -> Self { + let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)); + let predicates = ctx.with_shifted_in(DebruijnIndex::ONE, |ctx| { + bounds + .iter() + .flat_map(|b| GenericPredicate::from_type_bound(ctx, b, self_ty.clone())) + .collect() + }); + ReturnTypeImplTrait { bounds: Binders::new(1, predicates) } + } +} + +fn count_impl_traits(type_ref: &TypeRef) -> usize { + let mut count = 0; + type_ref.walk(&mut |type_ref| { + if matches!(type_ref, TypeRef::ImplTrait(_)) { + count += 1; + } + }); + count +} + /// Build the signature of a callable item (function, struct or enum variant). pub fn callable_item_sig(db: &dyn HirDatabase, def: CallableDef) -> PolyFnSig { match def { @@ -864,7 +941,9 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig { .with_impl_trait_mode(ImplTraitLoweringMode::Variable) .with_type_param_mode(TypeParamLoweringMode::Variable); let params = data.params.iter().map(|tr| Ty::from_hir(&ctx_params, tr)).collect::>(); - let ctx_ret = ctx_params.with_impl_trait_mode(ImplTraitLoweringMode::Opaque); + let ctx_ret = TyLoweringContext::new(db, &resolver) + .with_impl_trait_mode(ImplTraitLoweringMode::Opaque) + .with_type_param_mode(TypeParamLoweringMode::Variable); let ret = Ty::from_hir(&ctx_ret, &data.ret_type); let generics = generics(db.upcast(), def.into()); let num_binders = generics.len(); @@ -1084,3 +1163,25 @@ pub(crate) fn impl_trait_query(db: &dyn HirDatabase, impl_id: ImplId) -> Option< TraitRef::from_hir(&ctx, target_trait, Some(self_ty.value))?, )) } + +pub(crate) fn return_type_impl_traits( + db: &impl HirDatabase, + def: hir_def::FunctionId, +) -> Option>> { + // FIXME unify with fn_sig_for_fn instead of doing lowering twice, maybe + let data = db.function_data(def); + let resolver = def.resolver(db.upcast()); + let ctx_ret = TyLoweringContext::new(db, &resolver) + .with_impl_trait_mode(ImplTraitLoweringMode::Opaque) + .with_type_param_mode(TypeParamLoweringMode::Variable); + let _ret = Ty::from_hir(&ctx_ret, &data.ret_type); + let generics = generics(db.upcast(), def.into()); + let num_binders = generics.len(); + let return_type_impl_traits = + ReturnTypeImplTraits { impl_traits: ctx_ret.opaque_type_data.into_inner() }; + if return_type_impl_traits.impl_traits.is_empty() { + None + } else { + Some(Arc::new(Binders::new(num_binders, return_type_impl_traits))) + } +} diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs index e8778d419..d83dc6d79 100644 --- a/crates/ra_hir_ty/src/tests/traits.rs +++ b/crates/ra_hir_ty/src/tests/traits.rs @@ -1110,7 +1110,6 @@ fn test() { } #[test] -#[ignore] fn impl_trait() { assert_snapshot!( infer(r#" @@ -1160,6 +1159,52 @@ fn test(x: impl Trait, y: &impl Trait) { ); } +#[test] +fn return_pos_impl_trait() { + assert_snapshot!( + infer(r#" +trait Iterator { + type Item; + fn next(&mut self) -> Self::Item; +} +trait Trait { + fn foo(&self) -> T; +} +fn bar() -> (impl Iterator>, impl Trait) { loop {} } +fn baz(t: T) -> (impl Iterator>, impl Trait) { loop {} } + +fn test() { + // let (a, b) = bar(); + // a.next().foo(); + // b.foo(); + let (c, d) = baz(1u128); + c.next();//.foo(); + // d.foo(); +} +"#), + @r###" + 50..54 'self': &mut Self + 102..106 'self': &Self + 185..196 '{ loop {} }': ({unknown}, {unknown}) + 187..194 'loop {}': ! + 192..194 '{}': () + 207..208 't': T + 269..280 '{ loop {} }': ({unknown}, {unknown}) + 271..278 'loop {}': ! + 276..278 '{}': () + 292..429 '{ ...o(); }': () + 368..374 '(c, d)': (impl Iterator>, impl Trait) + 369..370 'c': impl Iterator> + 372..373 'd': impl Trait + 377..380 'baz': fn baz(u128) -> (impl Iterator>, impl Trait) + 377..387 'baz(1u128)': (impl Iterator>, impl Trait) + 381..386 '1u128': u128 + 393..394 'c': impl Iterator> + 393..401 'c.next()': impl Trait + "### + ); +} + #[test] fn dyn_trait() { assert_snapshot!( diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index 61de3cc30..a72a82f5a 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs @@ -4,7 +4,7 @@ use std::sync::Arc; use log::debug; use chalk_ir::{fold::shift::Shift, GenericArg, TypeName}; -use chalk_solve::rust_ir::{self, WellKnownTrait}; +use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait}; use hir_def::{ lang_item::{lang_attr, LangItemTarget}, @@ -100,6 +100,7 @@ impl<'a> chalk_solve::RustIrDatabase for ChalkContext<'a> { fn associated_ty_value(&self, id: AssociatedTyValueId) -> Arc { self.db.associated_ty_value(self.krate, id) } + fn custom_clauses(&self) -> Vec> { vec![] } @@ -130,11 +131,34 @@ impl<'a> chalk_solve::RustIrDatabase for ChalkContext<'a> { self.db.program_clauses_for_chalk_env(self.krate, environment.clone()) } - fn opaque_ty_data( - &self, - _id: chalk_ir::OpaqueTyId, - ) -> Arc> { - unimplemented!() + fn opaque_ty_data(&self, id: chalk_ir::OpaqueTyId) -> Arc { + let interned_id = crate::db::InternedOpaqueTyId::from(id); + let full_id = self.db.lookup_intern_impl_trait_id(interned_id); + let (func, idx) = match full_id { + crate::OpaqueTyId::ReturnTypeImplTrait(func, idx) => (func, idx), + }; + let datas = + self.db.return_type_impl_traits(func).expect("impl trait id without impl traits"); + let data = &datas.value.impl_traits[idx as usize]; + let bound = OpaqueTyDatumBound { + bounds: make_binders( + data.bounds + .value + .iter() + .cloned() + .filter(|b| !b.is_error()) + .map(|b| b.to_chalk(self.db)) + .collect(), + 1, + ), + }; + let num_vars = datas.num_binders; + Arc::new(OpaqueTyDatum { opaque_ty_id: id, bound: make_binders(bound, num_vars) }) + } + + fn hidden_opaque_type(&self, _id: chalk_ir::OpaqueTyId) -> chalk_ir::Ty { + // FIXME: actually provide the hidden type; it is relevant for auto traits + Ty::Unknown.to_chalk(self.db) } fn force_impl_for( @@ -150,10 +174,6 @@ impl<'a> chalk_solve::RustIrDatabase for ChalkContext<'a> { // FIXME: implement actual object safety true } - - fn hidden_opaque_type(&self, _id: chalk_ir::OpaqueTyId) -> chalk_ir::Ty { - Ty::Unknown.to_chalk(self.db) - } } pub(crate) fn program_clauses_for_chalk_env_query( @@ -460,6 +480,18 @@ impl From for ImplId { } } +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::traits::AssocTyValueId { fn from(id: rust_ir::AssociatedTyValueId) -> Self { Self::from_intern_id(id.0) diff --git a/crates/ra_hir_ty/src/traits/chalk/interner.rs b/crates/ra_hir_ty/src/traits/chalk/interner.rs index e27074ba6..56aab640c 100644 --- a/crates/ra_hir_ty/src/traits/chalk/interner.rs +++ b/crates/ra_hir_ty/src/traits/chalk/interner.rs @@ -22,6 +22,8 @@ pub type AssociatedTyValueId = chalk_solve::rust_ir::AssociatedTyValueId; pub type FnDefId = chalk_ir::FnDefId; pub type FnDefDatum = chalk_solve::rust_ir::FnDefDatum; +pub type OpaqueTyId = chalk_ir::OpaqueTyId; +pub type OpaqueTyDatum = chalk_solve::rust_ir::OpaqueTyDatum; impl chalk_ir::interner::Interner for Interner { type InternedType = Box>; // FIXME use Arc? diff --git a/crates/ra_hir_ty/src/traits/chalk/mapping.rs b/crates/ra_hir_ty/src/traits/chalk/mapping.rs index 5f6daf842..834360430 100644 --- a/crates/ra_hir_ty/src/traits/chalk/mapping.rs +++ b/crates/ra_hir_ty/src/traits/chalk/mapping.rs @@ -16,8 +16,8 @@ use crate::{ db::HirDatabase, primitive::{FloatBitness, FloatTy, IntBitness, IntTy, Signedness, Uncertain}, traits::{builtin, AssocTyValue, Canonical, Impl, Obligation}, - ApplicationTy, CallableDef, GenericPredicate, InEnvironment, ProjectionPredicate, ProjectionTy, - Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, + ApplicationTy, CallableDef, GenericPredicate, InEnvironment, OpaqueTy, OpaqueTyId, + ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, }; use super::interner::*; @@ -68,7 +68,16 @@ impl ToChalk for Ty { let bounded_ty = chalk_ir::DynTy { bounds: make_binders(where_clauses, 1) }; chalk_ir::TyData::Dyn(bounded_ty).intern(&Interner) } - Ty::Opaque(_) | Ty::Unknown => { + Ty::Opaque(opaque_ty) => { + let opaque_ty_id = opaque_ty.opaque_ty_id.to_chalk(db); + let substitution = opaque_ty.parameters.to_chalk(db); + chalk_ir::TyData::Alias(chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy { + opaque_ty_id, + substitution, + })) + .intern(&Interner) + } + Ty::Unknown => { let substitution = chalk_ir::Substitution::empty(&Interner); let name = TypeName::Error; chalk_ir::ApplicationTy { name, substitution }.cast(&Interner).intern(&Interner) @@ -98,7 +107,11 @@ impl ToChalk for Ty { let parameters = from_chalk(db, proj.substitution); Ty::Projection(ProjectionTy { associated_ty, parameters }) } - chalk_ir::TyData::Alias(chalk_ir::AliasTy::Opaque(_)) => unimplemented!(), + chalk_ir::TyData::Alias(chalk_ir::AliasTy::Opaque(opaque_ty)) => { + let impl_trait_id = from_chalk(db, opaque_ty.opaque_ty_id); + let parameters = from_chalk(db, opaque_ty.substitution); + Ty::Opaque(OpaqueTy { opaque_ty_id: impl_trait_id, parameters }) + } chalk_ir::TyData::Function(chalk_ir::Fn { num_binders: _, substitution }) => { let parameters: Substs = from_chalk(db, substitution); Ty::Apply(ApplicationTy { @@ -204,6 +217,21 @@ impl ToChalk for hir_def::TraitId { } } +impl ToChalk for OpaqueTyId { + type Chalk = chalk_ir::OpaqueTyId; + + fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::OpaqueTyId { + db.intern_impl_trait_id(self).into() + } + + fn from_chalk( + db: &dyn HirDatabase, + opaque_ty_id: chalk_ir::OpaqueTyId, + ) -> OpaqueTyId { + db.lookup_intern_impl_trait_id(opaque_ty_id.into()) + } +} + impl ToChalk for TypeCtor { type Chalk = TypeName; @@ -214,6 +242,11 @@ impl ToChalk for TypeCtor { TypeName::AssociatedType(type_id) } + TypeCtor::OpaqueType(impl_trait_id) => { + let id = impl_trait_id.to_chalk(db); + TypeName::OpaqueType(id) + } + TypeCtor::Bool => TypeName::Scalar(Scalar::Bool), TypeCtor::Char => TypeName::Scalar(Scalar::Char), TypeCtor::Int(Uncertain::Known(int_ty)) => TypeName::Scalar(int_ty_to_chalk(int_ty)), @@ -252,7 +285,9 @@ impl ToChalk for TypeCtor { match type_name { TypeName::Adt(struct_id) => db.lookup_intern_type_ctor(struct_id.into()), TypeName::AssociatedType(type_id) => TypeCtor::AssociatedType(from_chalk(db, type_id)), - TypeName::OpaqueType(_) => unreachable!(), + TypeName::OpaqueType(opaque_type_id) => { + TypeCtor::OpaqueType(from_chalk(db, opaque_type_id)) + } TypeName::Scalar(Scalar::Bool) => TypeCtor::Bool, TypeName::Scalar(Scalar::Char) => TypeCtor::Char, diff --git a/crates/ra_hir_ty/src/traits/chalk/tls.rs b/crates/ra_hir_ty/src/traits/chalk/tls.rs index d88828c7c..556af7098 100644 --- a/crates/ra_hir_ty/src/traits/chalk/tls.rs +++ b/crates/ra_hir_ty/src/traits/chalk/tls.rs @@ -69,6 +69,11 @@ impl DebugContext<'_> { let name = self.0.type_alias_data(type_alias).name.clone(); write!(f, "{}::{}", trait_name, name)?; } + TypeCtor::OpaqueType(opaque_ty_id) => match opaque_ty_id { + crate::OpaqueTyId::ReturnTypeImplTrait(func, idx) => { + write!(f, "{{impl trait {} of {:?}}}", idx, func)?; + } + }, TypeCtor::Closure { def, expr } => { write!(f, "{{closure {:?} in ", expr.into_raw())?; match def { -- cgit v1.2.3 From bbb40d746368eb6a38498649a723c7ead0ef8136 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 5 Jun 2020 16:45:20 +0200 Subject: Minimize FileLoader interface --- crates/ra_hir_ty/src/test_db.rs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'crates/ra_hir_ty') diff --git a/crates/ra_hir_ty/src/test_db.rs b/crates/ra_hir_ty/src/test_db.rs index 21a3bdfd1..e484968a0 100644 --- a/crates/ra_hir_ty/src/test_db.rs +++ b/crates/ra_hir_ty/src/test_db.rs @@ -7,9 +7,7 @@ use std::{ use hir_def::{db::DefDatabase, AssocItemId, ModuleDefId, ModuleId}; use hir_expand::{db::AstDatabase, diagnostics::DiagnosticSink}; -use ra_db::{ - salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, RelativePath, SourceDatabase, Upcast, -}; +use ra_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, SourceDatabase, Upcast}; use stdx::format_to; use crate::{db::HirDatabase, diagnostics::Diagnostic, expr::ExprValidator}; @@ -78,13 +76,6 @@ impl FileLoader for TestDB { fn relevant_crates(&self, file_id: FileId) -> Arc> { FileLoaderDelegate(self).relevant_crates(file_id) } - fn resolve_extern_path( - &self, - extern_id: ra_db::ExternSourceId, - relative_path: &RelativePath, - ) -> Option { - FileLoaderDelegate(self).resolve_extern_path(extern_id, relative_path) - } } impl TestDB { -- cgit v1.2.3 From 0d2328f3eaf69c6a50fe6c1e946257bd3503d751 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 5 Jun 2020 17:41:58 +0200 Subject: Review fixes --- crates/ra_hir_ty/src/display.rs | 6 +-- crates/ra_hir_ty/src/lower.rs | 9 ++--- crates/ra_hir_ty/src/tests/traits.rs | 73 ++++++++++++++++++++++++++++-------- 3 files changed, 65 insertions(+), 23 deletions(-) (limited to 'crates/ra_hir_ty') diff --git a/crates/ra_hir_ty/src/display.rs b/crates/ra_hir_ty/src/display.rs index 3e63a2415..3c97e1354 100644 --- a/crates/ra_hir_ty/src/display.rs +++ b/crates/ra_hir_ty/src/display.rs @@ -4,7 +4,7 @@ use std::fmt; use crate::{ db::HirDatabase, utils::generics, ApplicationTy, CallableDef, FnSig, GenericPredicate, - Obligation, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, + Obligation, OpaqueTyId, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, }; use hir_def::{ find_path, generics::TypeParamProvenance, item_scope::ItemInNs, AdtId, AssocContainerId, @@ -361,7 +361,7 @@ impl HirDisplay for ApplicationTy { } TypeCtor::OpaqueType(opaque_ty_id) => { let bounds = match opaque_ty_id { - crate::OpaqueTyId::ReturnTypeImplTrait(func, idx) => { + OpaqueTyId::ReturnTypeImplTrait(func, idx) => { let datas = f.db.return_type_impl_traits(func).expect("impl trait id without data"); let data = (*datas) @@ -448,7 +448,7 @@ impl HirDisplay for Ty { } Ty::Opaque(opaque_ty) => { let bounds = match opaque_ty.opaque_ty_id { - crate::OpaqueTyId::ReturnTypeImplTrait(func, idx) => { + OpaqueTyId::ReturnTypeImplTrait(func, idx) => { let datas = f.db.return_type_impl_traits(func).expect("impl trait id without data"); let data = (*datas) diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index dfc018b0b..a05cbd7fc 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs @@ -21,8 +21,10 @@ use hir_def::{ HasModule, ImplId, LocalFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId, VariantId, }; +use hir_expand::name::Name; use ra_arena::map::ArenaMap; use ra_db::CrateId; +use test_utils::mark; use crate::{ db::HirDatabase, @@ -35,7 +37,6 @@ use crate::{ ProjectionPredicate, ProjectionTy, ReturnTypeImplTrait, ReturnTypeImplTraits, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk, }; -use hir_expand::name::Name; #[derive(Debug)] pub struct TyLoweringContext<'a> { @@ -220,10 +221,7 @@ impl Ty { let func = match ctx.resolver.generic_def() { Some(GenericDefId::FunctionId(f)) => f, - _ => { - // this shouldn't happen - return (Ty::Unknown, None); - } + _ => panic!("opaque impl trait lowering in non-function"), }; let impl_trait_id = OpaqueTyId::ReturnTypeImplTrait(func, idx); let generics = generics(ctx.db.upcast(), func.into()); @@ -719,6 +717,7 @@ fn assoc_type_bindings_from_type_bound<'a>( impl ReturnTypeImplTrait { fn from_hir(ctx: &TyLoweringContext, bounds: &[TypeBound]) -> Self { + mark::hit!(lower_rpit); let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)); let predicates = ctx.with_shifted_in(DebruijnIndex::ONE, |ctx| { bounds diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs index d83dc6d79..0c538a62d 100644 --- a/crates/ra_hir_ty/src/tests/traits.rs +++ b/crates/ra_hir_ty/src/tests/traits.rs @@ -1160,7 +1160,37 @@ fn test(x: impl Trait, y: &impl Trait) { } #[test] -fn return_pos_impl_trait() { +fn simple_return_pos_impl_trait() { + mark::check!(lower_rpit); + assert_snapshot!( + infer(r#" +trait Trait { + fn foo(&self) -> T; +} +fn bar() -> impl Trait { loop {} } + +fn test() { + let a = bar(); + a.foo(); +} +"#), + @r###" + 30..34 'self': &Self + 72..83 '{ loop {} }': ! + 74..81 'loop {}': ! + 79..81 '{}': () + 95..130 '{ ...o(); }': () + 105..106 'a': impl Trait + 109..112 'bar': fn bar() -> impl Trait + 109..114 'bar()': impl Trait + 120..121 'a': impl Trait + 120..127 'a.foo()': u64 + "### + ); +} + +#[test] +fn more_return_pos_impl_trait() { assert_snapshot!( infer(r#" trait Iterator { @@ -1174,12 +1204,12 @@ fn bar() -> (impl Iterator>, impl Trait) { loop {} } fn baz(t: T) -> (impl Iterator>, impl Trait) { loop {} } fn test() { - // let (a, b) = bar(); - // a.next().foo(); - // b.foo(); + let (a, b) = bar(); + a.next().foo(); + b.foo(); let (c, d) = baz(1u128); - c.next();//.foo(); - // d.foo(); + c.next().foo(); + d.foo(); } "#), @r###" @@ -1192,15 +1222,28 @@ fn test() { 269..280 '{ loop {} }': ({unknown}, {unknown}) 271..278 'loop {}': ! 276..278 '{}': () - 292..429 '{ ...o(); }': () - 368..374 '(c, d)': (impl Iterator>, impl Trait) - 369..370 'c': impl Iterator> - 372..373 'd': impl Trait - 377..380 'baz': fn baz(u128) -> (impl Iterator>, impl Trait) - 377..387 'baz(1u128)': (impl Iterator>, impl Trait) - 381..386 '1u128': u128 - 393..394 'c': impl Iterator> - 393..401 'c.next()': impl Trait + 292..414 '{ ...o(); }': () + 302..308 '(a, b)': (impl Iterator>, impl Trait) + 303..304 'a': impl Iterator> + 306..307 'b': impl Trait + 311..314 'bar': fn bar() -> (impl Iterator>, impl Trait) + 311..316 'bar()': (impl Iterator>, impl Trait) + 322..323 'a': impl Iterator> + 322..330 'a.next()': impl Trait + 322..336 'a.next().foo()': u32 + 342..343 'b': impl Trait + 342..349 'b.foo()': u64 + 359..365 '(c, d)': (impl Iterator>, impl Trait) + 360..361 'c': impl Iterator> + 363..364 'd': impl Trait + 368..371 'baz': fn baz(u128) -> (impl Iterator>, impl Trait) + 368..378 'baz(1u128)': (impl Iterator>, impl Trait) + 372..377 '1u128': u128 + 384..385 'c': impl Iterator> + 384..392 'c.next()': impl Trait + 384..398 'c.next().foo()': u128 + 404..405 'd': impl Trait + 404..411 'd.foo()': u128 "### ); } -- cgit v1.2.3 From a4a4a1854ebb53e1cdd7a5e3b308112bbbf3c676 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 29 May 2020 19:14:04 +0200 Subject: Fix type parameter defaults They should not be applied in expression or pattern contexts, unless there are other explicitly given type args. --- crates/ra_hir_ty/src/infer.rs | 4 +- crates/ra_hir_ty/src/infer/path.rs | 3 +- crates/ra_hir_ty/src/lower.rs | 70 +++++++++----- crates/ra_hir_ty/src/tests/display_source_code.rs | 4 +- crates/ra_hir_ty/src/tests/method_resolution.rs | 54 ----------- crates/ra_hir_ty/src/tests/simple.rs | 108 ++++++++++++++++++++++ crates/ra_hir_ty/src/tests/traits.rs | 54 +++++------ 7 files changed, 187 insertions(+), 110 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 d9bf3c2f0..2e16e5120 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs @@ -439,13 +439,13 @@ impl<'a> InferenceContext<'a> { }; return match resolution { TypeNs::AdtId(AdtId::StructId(strukt)) => { - let substs = Ty::substs_from_path(&ctx, path, strukt.into()); + let substs = Ty::substs_from_path(&ctx, path, strukt.into(), true); let ty = self.db.ty(strukt.into()); let ty = self.insert_type_vars(ty.subst(&substs)); forbid_unresolved_segments((ty, Some(strukt.into())), unresolved) } TypeNs::EnumVariantId(var) => { - let substs = Ty::substs_from_path(&ctx, path, var.into()); + let substs = Ty::substs_from_path(&ctx, path, var.into(), true); let ty = self.db.ty(var.parent.into()); let ty = self.insert_type_vars(ty.subst(&substs)); forbid_unresolved_segments((ty, Some(var.into())), unresolved) diff --git a/crates/ra_hir_ty/src/infer/path.rs b/crates/ra_hir_ty/src/infer/path.rs index 1c2e56fb0..1ad0d8397 100644 --- a/crates/ra_hir_ty/src/infer/path.rs +++ b/crates/ra_hir_ty/src/infer/path.rs @@ -95,7 +95,7 @@ impl<'a> InferenceContext<'a> { // self_subst is just for the parent let parent_substs = self_subst.unwrap_or_else(Substs::empty); let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver); - let substs = Ty::substs_from_path(&ctx, path, typable); + let substs = Ty::substs_from_path(&ctx, path, typable, true); let full_substs = Substs::builder(substs.len()) .use_parent_substs(&parent_substs) .fill(substs.0[parent_substs.len()..].iter().cloned()) @@ -141,6 +141,7 @@ impl<'a> InferenceContext<'a> { def, resolved_segment, remaining_segments_for_ty, + true, ); if let Ty::Unknown = ty { return None; diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index a05cbd7fc..42713928f 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs @@ -323,6 +323,7 @@ impl Ty { resolution: TypeNs, resolved_segment: PathSegment<'_>, remaining_segments: PathSegments<'_>, + infer_args: bool, ) -> (Ty, Option) { let ty = match resolution { TypeNs::TraitId(trait_) => { @@ -400,9 +401,15 @@ impl Ty { ctx.db.ty(adt.into()).subst(&substs) } - TypeNs::AdtId(it) => Ty::from_hir_path_inner(ctx, resolved_segment, it.into()), - TypeNs::BuiltinType(it) => Ty::from_hir_path_inner(ctx, resolved_segment, it.into()), - TypeNs::TypeAliasId(it) => Ty::from_hir_path_inner(ctx, resolved_segment, it.into()), + TypeNs::AdtId(it) => { + Ty::from_hir_path_inner(ctx, resolved_segment, it.into(), infer_args) + } + TypeNs::BuiltinType(it) => { + Ty::from_hir_path_inner(ctx, resolved_segment, it.into(), infer_args) + } + TypeNs::TypeAliasId(it) => { + Ty::from_hir_path_inner(ctx, resolved_segment, it.into(), infer_args) + } // FIXME: report error TypeNs::EnumVariantId(_) => return (Ty::Unknown, None), }; @@ -428,7 +435,13 @@ impl Ty { ), Some(i) => (path.segments().get(i - 1).unwrap(), path.segments().skip(i)), }; - Ty::from_partly_resolved_hir_path(ctx, resolution, resolved_segment, remaining_segments) + Ty::from_partly_resolved_hir_path( + ctx, + resolution, + resolved_segment, + remaining_segments, + false, + ) } fn select_associated_type( @@ -474,13 +487,14 @@ impl Ty { ctx: &TyLoweringContext<'_>, segment: PathSegment<'_>, typable: TyDefId, + infer_args: bool, ) -> Ty { let generic_def = match typable { TyDefId::BuiltinType(_) => None, TyDefId::AdtId(it) => Some(it.into()), TyDefId::TypeAliasId(it) => Some(it.into()), }; - let substs = substs_from_path_segment(ctx, segment, generic_def, false); + let substs = substs_from_path_segment(ctx, segment, generic_def, infer_args); ctx.db.ty(typable).subst(&substs) } @@ -493,6 +507,7 @@ impl Ty { // `ValueTyDefId` is just a convenient way to pass generics and // special-case enum variants resolved: ValueTyDefId, + infer_args: bool, ) -> Substs { let last = path.segments().last().expect("path should have at least one segment"); let (segment, generic_def) = match resolved { @@ -515,22 +530,27 @@ impl Ty { (segment, Some(var.parent.into())) } }; - substs_from_path_segment(ctx, segment, generic_def, false) + substs_from_path_segment(ctx, segment, generic_def, infer_args) } } -pub(super) fn substs_from_path_segment( +fn substs_from_path_segment( ctx: &TyLoweringContext<'_>, segment: PathSegment<'_>, def_generic: Option, - _add_self_param: bool, + infer_args: bool, ) -> Substs { let mut substs = Vec::new(); let def_generics = def_generic.map(|def| generics(ctx.db.upcast(), def)); let (parent_params, self_params, type_params, impl_trait_params) = def_generics.map_or((0, 0, 0, 0), |g| g.provenance_split()); + let total_len = parent_params + self_params + type_params + impl_trait_params; + substs.extend(iter::repeat(Ty::Unknown).take(parent_params)); + + let mut had_explicit_args = false; + if let Some(generic_args) = &segment.args_and_bindings { if !generic_args.has_self_type { substs.extend(iter::repeat(Ty::Unknown).take(self_params)); @@ -542,31 +562,35 @@ pub(super) fn substs_from_path_segment( for arg in generic_args.args.iter().skip(skip).take(expected_num) { match arg { GenericArg::Type(type_ref) => { + had_explicit_args = true; let ty = Ty::from_hir(ctx, type_ref); substs.push(ty); } } } } - let total_len = parent_params + self_params + type_params + impl_trait_params; - // add placeholders for args that were not provided - for _ in substs.len()..total_len { - substs.push(Ty::Unknown); - } - assert_eq!(substs.len(), total_len); - // handle defaults - if let Some(def_generic) = def_generic { - let default_substs = ctx.db.generic_defaults(def_generic); - assert_eq!(substs.len(), default_substs.len()); + // handle defaults. In expression or pattern path segments without + // explicitly specified type arguments, missing type arguments are inferred + // (i.e. defaults aren't used). + if !infer_args || had_explicit_args { + if let Some(def_generic) = def_generic { + let default_substs = ctx.db.generic_defaults(def_generic); + assert_eq!(total_len, default_substs.len()); - for (i, default_ty) in default_substs.iter().enumerate() { - if substs[i] == Ty::Unknown { - substs[i] = default_ty.clone(); + for default_ty in default_substs.iter().skip(substs.len()) { + substs.push(default_ty.clone()); } } } + // add placeholders for args that were not provided + // FIXME: emit diagnostics in contexts where this is not allowed + for _ in substs.len()..total_len { + substs.push(Ty::Unknown); + } + assert_eq!(substs.len(), total_len); + Substs(substs.into()) } @@ -615,9 +639,7 @@ impl TraitRef { segment: PathSegment<'_>, resolved: TraitId, ) -> Substs { - let has_self_param = - segment.args_and_bindings.as_ref().map(|a| a.has_self_type).unwrap_or(false); - substs_from_path_segment(ctx, segment, Some(resolved.into()), !has_self_param) + substs_from_path_segment(ctx, segment, Some(resolved.into()), false) } pub(crate) fn from_type_bound( diff --git a/crates/ra_hir_ty/src/tests/display_source_code.rs b/crates/ra_hir_ty/src/tests/display_source_code.rs index 4088b1d22..5dfa0a014 100644 --- a/crates/ra_hir_ty/src/tests/display_source_code.rs +++ b/crates/ra_hir_ty/src/tests/display_source_code.rs @@ -29,7 +29,7 @@ fn omit_default_type_parameters() { //- /main.rs struct Foo { t: T } fn main() { - let foo = Foo { t: 5 }; + let foo = Foo { t: 5u8 }; foo<|>; } ", @@ -41,7 +41,7 @@ fn omit_default_type_parameters() { //- /main.rs struct Foo { k: K, t: T } fn main() { - let foo = Foo { k: 400, t: 5 }; + let foo = Foo { k: 400, t: 5u8 }; foo<|>; } ", diff --git a/crates/ra_hir_ty/src/tests/method_resolution.rs b/crates/ra_hir_ty/src/tests/method_resolution.rs index 558a70022..804297315 100644 --- a/crates/ra_hir_ty/src/tests/method_resolution.rs +++ b/crates/ra_hir_ty/src/tests/method_resolution.rs @@ -183,60 +183,6 @@ fn test() { ); } -#[test] -fn infer_associated_method_generics_with_default_param() { - assert_snapshot!( - infer(r#" -struct Gen { - val: T -} - -impl Gen { - pub fn make() -> Gen { - loop { } - } -} - -fn test() { - let a = Gen::make(); -} -"#), - @r###" - 80..104 '{ ... }': Gen - 90..98 'loop { }': ! - 95..98 '{ }': () - 118..146 '{ ...e(); }': () - 128..129 'a': Gen - 132..141 'Gen::make': fn make() -> Gen - 132..143 'Gen::make()': Gen - "### - ); -} - -#[test] -fn infer_associated_method_generics_with_default_tuple_param() { - let t = type_at( - r#" -//- /main.rs -struct Gen { - val: T -} - -impl Gen { - pub fn make() -> Gen { - loop { } - } -} - -fn test() { - let a = Gen::make(); - a.val<|>; -} -"#, - ); - assert_eq!(t, "()"); -} - #[test] fn infer_associated_method_generics_without_args() { assert_snapshot!( diff --git a/crates/ra_hir_ty/src/tests/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs index 88309157b..8a5031756 100644 --- a/crates/ra_hir_ty/src/tests/simple.rs +++ b/crates/ra_hir_ty/src/tests/simple.rs @@ -1997,3 +1997,111 @@ fn foo() { "### ); } + +#[test] +fn generic_default() { + assert_snapshot!( + infer(r#" +struct Thing { t: T } +enum OtherThing { + One { t: T }, + Two(T), +} + +fn test(t1: Thing, t2: OtherThing, t3: Thing, t4: OtherThing) { + t1.t; + t3.t; + match t2 { + OtherThing::One { t } => { t; }, + OtherThing::Two(t) => { t; }, + } + match t4 { + OtherThing::One { t } => { t; }, + OtherThing::Two(t) => { t; }, + } +} +"#), + @r###" + 98..100 't1': Thing<()> + 109..111 't2': OtherThing<()> + 125..127 't3': Thing + 141..143 't4': OtherThing + 162..385 '{ ... } }': () + 168..170 't1': Thing<()> + 168..172 't1.t': () + 178..180 't3': Thing + 178..182 't3.t': i32 + 188..283 'match ... }': () + 194..196 't2': OtherThing<()> + 207..228 'OtherT... { t }': OtherThing<()> + 225..226 't': () + 232..238 '{ t; }': () + 234..235 't': () + 248..266 'OtherT...Two(t)': OtherThing<()> + 264..265 't': () + 270..276 '{ t; }': () + 272..273 't': () + 288..383 'match ... }': () + 294..296 't4': OtherThing + 307..328 'OtherT... { t }': OtherThing + 325..326 't': i32 + 332..338 '{ t; }': () + 334..335 't': i32 + 348..366 'OtherT...Two(t)': OtherThing + 364..365 't': i32 + 370..376 '{ t; }': () + 372..373 't': i32 + "### + ); +} + +#[test] +fn generic_default_in_struct_literal() { + assert_snapshot!( + infer(r#" +struct Thing { t: T } +enum OtherThing { + One { t: T }, + Two(T), +} + +fn test() { + let x = Thing { t: loop {} }; + let y = Thing { t: () }; + let z = Thing { t: 1i32 }; + if let Thing { t } = z { + t; + } + + let a = OtherThing::One { t: 1i32 }; + let b = OtherThing::Two(1i32); +} +"#), + @r###" + 100..320 '{ ...32); }': () + 110..111 'x': Thing + 114..134 'Thing ...p {} }': Thing + 125..132 'loop {}': ! + 130..132 '{}': () + 144..145 'y': Thing<()> + 148..163 'Thing { t: () }': Thing<()> + 159..161 '()': () + 173..174 'z': Thing + 177..194 'Thing ...1i32 }': Thing + 188..192 '1i32': i32 + 200..241 'if let... }': () + 207..218 'Thing { t }': Thing + 215..216 't': i32 + 221..222 'z': Thing + 223..241 '{ ... }': () + 233..234 't': i32 + 251..252 'a': OtherThing + 255..282 'OtherT...1i32 }': OtherThing + 276..280 '1i32': i32 + 292..293 'b': OtherThing + 296..311 'OtherThing::Two': Two(i32) -> OtherThing + 296..317 'OtherT...(1i32)': OtherThing + 312..316 '1i32': i32 + "### + ); +} diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs index 0c538a62d..133fb5f39 100644 --- a/crates/ra_hir_ty/src/tests/traits.rs +++ b/crates/ra_hir_ty/src/tests/traits.rs @@ -1806,33 +1806,33 @@ fn test() { } "#), @r###" -65..69 'self': &Self -166..170 'self': Self -172..176 'args': Args -240..244 'self': &Foo -255..257 '{}': () -335..336 'f': F -355..357 '{}': () -444..690 '{ ...o(); }': () -454..459 'lazy1': Lazy T> -476..485 'Lazy::new': fn new T>(fn() -> T) -> Lazy T> -476..493 'Lazy::...| Foo)': Lazy T> -486..492 '|| Foo': || -> T -489..492 'Foo': Foo -503..505 'r1': {unknown} -508..513 'lazy1': Lazy T> -508..519 'lazy1.foo()': {unknown} -561..576 'make_foo_fn_ptr': fn() -> Foo -592..603 'make_foo_fn': fn make_foo_fn() -> Foo -613..618 'lazy2': Lazy T> -635..644 'Lazy::new': fn new T>(fn() -> T) -> Lazy T> -635..661 'Lazy::...n_ptr)': Lazy T> -645..660 'make_foo_fn_ptr': fn() -> Foo -671..673 'r2': {unknown} -676..681 'lazy2': Lazy T> -676..687 'lazy2.foo()': {unknown} -550..552 '{}': () -"### + 65..69 'self': &Self + 166..170 'self': Self + 172..176 'args': Args + 240..244 'self': &Foo + 255..257 '{}': () + 335..336 'f': F + 355..357 '{}': () + 444..690 '{ ...o(); }': () + 454..459 'lazy1': Lazy Foo> + 476..485 'Lazy::new': fn new Foo>(|| -> Foo) -> Lazy Foo> + 476..493 'Lazy::...| Foo)': Lazy Foo> + 486..492 '|| Foo': || -> Foo + 489..492 'Foo': Foo + 503..505 'r1': usize + 508..513 'lazy1': Lazy Foo> + 508..519 'lazy1.foo()': usize + 561..576 'make_foo_fn_ptr': fn() -> Foo + 592..603 'make_foo_fn': fn make_foo_fn() -> Foo + 613..618 'lazy2': Lazy Foo> + 635..644 'Lazy::new': fn new Foo>(fn() -> Foo) -> Lazy Foo> + 635..661 'Lazy::...n_ptr)': Lazy Foo> + 645..660 'make_foo_fn_ptr': fn() -> Foo + 671..673 'r2': {unknown} + 676..681 'lazy2': Lazy Foo> + 676..687 'lazy2.foo()': {unknown} + 550..552 '{}': () + "### ); } -- cgit v1.2.3 From d66daee84906358c0119ed2eb29386454f5e4350 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 6 Jun 2020 17:52:00 +0200 Subject: Clean up handling of int/float literal types 'Unknown' int/float types actually never exist as such, they get replaced by type variables immediately. So the whole `Uncertain` thing was unnecessary and just led to a bunch of match branches that were never hit. --- crates/ra_hir_ty/src/infer.rs | 13 ++----- crates/ra_hir_ty/src/infer/expr.rs | 28 +++++++-------- crates/ra_hir_ty/src/lib.rs | 6 ++-- crates/ra_hir_ty/src/method_resolution.rs | 12 +++---- crates/ra_hir_ty/src/primitive.rs | 54 ---------------------------- crates/ra_hir_ty/src/traits/chalk/mapping.rs | 24 ++++++------- 6 files changed, 33 insertions(+), 104 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 2e16e5120..f965eb2b5 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs @@ -39,8 +39,7 @@ use ra_syntax::SmolStr; use super::{ primitive::{FloatTy, IntTy}, traits::{Guidance, Obligation, ProjectionPredicate, Solution}, - ApplicationTy, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, - TypeWalk, Uncertain, + InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk, }; use crate::{ db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, @@ -312,12 +311,6 @@ impl<'a> InferenceContext<'a> { fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty { match ty { Ty::Unknown => self.table.new_type_var(), - Ty::Apply(ApplicationTy { ctor: TypeCtor::Int(Uncertain::Unknown), .. }) => { - self.table.new_integer_var() - } - Ty::Apply(ApplicationTy { ctor: TypeCtor::Float(Uncertain::Unknown), .. }) => { - self.table.new_float_var() - } _ => ty, } } @@ -664,8 +657,8 @@ impl InferTy { fn fallback_value(self) -> Ty { match self { InferTy::TypeVar(..) => Ty::Unknown, - InferTy::IntVar(..) => Ty::simple(TypeCtor::Int(Uncertain::Known(IntTy::i32()))), - InferTy::FloatVar(..) => Ty::simple(TypeCtor::Float(Uncertain::Known(FloatTy::f64()))), + InferTy::IntVar(..) => Ty::simple(TypeCtor::Int(IntTy::i32())), + InferTy::FloatVar(..) => Ty::simple(TypeCtor::Float(FloatTy::f64())), InferTy::MaybeNeverTypeVar(..) => Ty::simple(TypeCtor::Never), } } diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index 4a98e2deb..9fd310f69 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs @@ -18,7 +18,7 @@ use crate::{ traits::InEnvironment, utils::{generics, variant_data, Generics}, ApplicationTy, Binders, CallableDef, InferTy, IntTy, Mutability, Obligation, Rawness, Substs, - TraitRef, Ty, TypeCtor, Uncertain, + TraitRef, Ty, TypeCtor, }; use super::{ @@ -426,15 +426,7 @@ impl<'a> InferenceContext<'a> { match &inner_ty { // Fast path for builtins Ty::Apply(ApplicationTy { - ctor: - TypeCtor::Int(Uncertain::Known(IntTy { - signedness: Signedness::Signed, - .. - })), - .. - }) - | Ty::Apply(ApplicationTy { - ctor: TypeCtor::Int(Uncertain::Unknown), + ctor: TypeCtor::Int(IntTy { signedness: Signedness::Signed, .. }), .. }) | Ty::Apply(ApplicationTy { ctor: TypeCtor::Float(_), .. }) @@ -577,9 +569,7 @@ impl<'a> InferenceContext<'a> { ); self.infer_expr( *repeat, - &Expectation::has_type(Ty::simple(TypeCtor::Int(Uncertain::Known( - IntTy::usize(), - )))), + &Expectation::has_type(Ty::simple(TypeCtor::Int(IntTy::usize()))), ); } } @@ -592,13 +582,19 @@ impl<'a> InferenceContext<'a> { Ty::apply_one(TypeCtor::Ref(Mutability::Shared), Ty::simple(TypeCtor::Str)) } Literal::ByteString(..) => { - let byte_type = Ty::simple(TypeCtor::Int(Uncertain::Known(IntTy::u8()))); + let byte_type = Ty::simple(TypeCtor::Int(IntTy::u8())); let array_type = Ty::apply_one(TypeCtor::Array, byte_type); Ty::apply_one(TypeCtor::Ref(Mutability::Shared), array_type) } Literal::Char(..) => Ty::simple(TypeCtor::Char), - Literal::Int(_v, ty) => Ty::simple(TypeCtor::Int((*ty).into())), - Literal::Float(_v, ty) => Ty::simple(TypeCtor::Float((*ty).into())), + Literal::Int(_v, ty) => match ty { + Some(int_ty) => Ty::simple(TypeCtor::Int((*int_ty).into())), + None => self.table.new_integer_var(), + }, + Literal::Float(_v, ty) => match ty { + Some(float_ty) => Ty::simple(TypeCtor::Float((*float_ty).into())), + None => self.table.new_float_var(), + }, }, }; // use a new type variable if we got Ty::Unknown here diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs index 135976fcd..2b9372b4b 100644 --- a/crates/ra_hir_ty/src/lib.rs +++ b/crates/ra_hir_ty/src/lib.rs @@ -58,7 +58,7 @@ use ra_db::{impl_intern_key, salsa, CrateId}; use crate::{ db::HirDatabase, - primitive::{FloatTy, IntTy, Uncertain}, + primitive::{FloatTy, IntTy}, utils::{generics, make_mut_slice, Generics}, }; use display::HirDisplay; @@ -87,10 +87,10 @@ pub enum TypeCtor { Char, /// A primitive integer type. For example, `i32`. - Int(Uncertain), + Int(IntTy), /// A primitive floating-point type. For example, `f64`. - Float(Uncertain), + Float(FloatTy), /// Structures, enumerations and unions. Adt(AdtId), diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs index e19628fdf..e83b39456 100644 --- a/crates/ra_hir_ty/src/method_resolution.rs +++ b/crates/ra_hir_ty/src/method_resolution.rs @@ -16,12 +16,8 @@ use rustc_hash::{FxHashMap, FxHashSet}; use super::Substs; use crate::{ - autoderef, - db::HirDatabase, - primitive::{FloatBitness, Uncertain}, - utils::all_super_traits, - ApplicationTy, Canonical, DebruijnIndex, InEnvironment, TraitEnvironment, TraitRef, Ty, - TypeCtor, TypeWalk, + autoderef, db::HirDatabase, primitive::FloatBitness, utils::all_super_traits, ApplicationTy, + Canonical, DebruijnIndex, InEnvironment, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk, }; /// This is used as a key for indexing impls. @@ -147,12 +143,12 @@ impl Ty { } TypeCtor::Bool => lang_item_crate!("bool"), TypeCtor::Char => lang_item_crate!("char"), - TypeCtor::Float(Uncertain::Known(f)) => match f.bitness { + TypeCtor::Float(f) => match f.bitness { // There are two lang items: one in libcore (fXX) and one in libstd (fXX_runtime) FloatBitness::X32 => lang_item_crate!("f32", "f32_runtime"), FloatBitness::X64 => lang_item_crate!("f64", "f64_runtime"), }, - TypeCtor::Int(Uncertain::Known(i)) => lang_item_crate!(i.ty_to_string()), + TypeCtor::Int(i) => lang_item_crate!(i.ty_to_string()), TypeCtor::Str => lang_item_crate!("str_alloc", "str"), TypeCtor::Slice => lang_item_crate!("slice_alloc", "slice"), TypeCtor::RawPtr(Mutability::Shared) => lang_item_crate!("const_ptr"), diff --git a/crates/ra_hir_ty/src/primitive.rs b/crates/ra_hir_ty/src/primitive.rs index 02a8179d9..37966b709 100644 --- a/crates/ra_hir_ty/src/primitive.rs +++ b/crates/ra_hir_ty/src/primitive.rs @@ -7,42 +7,6 @@ use std::fmt; pub use hir_def::builtin_type::{BuiltinFloat, BuiltinInt, FloatBitness, IntBitness, Signedness}; -#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)] -pub enum Uncertain { - Unknown, - Known(T), -} - -impl From for Uncertain { - fn from(ty: IntTy) -> Self { - Uncertain::Known(ty) - } -} - -impl fmt::Display for Uncertain { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - Uncertain::Unknown => write!(f, "{{integer}}"), - Uncertain::Known(ty) => write!(f, "{}", ty), - } - } -} - -impl From for Uncertain { - fn from(ty: FloatTy) -> Self { - Uncertain::Known(ty) - } -} - -impl fmt::Display for Uncertain { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - Uncertain::Unknown => write!(f, "{{float}}"), - Uncertain::Known(ty) => write!(f, "{}", ty), - } - } -} - #[derive(Copy, Clone, Eq, PartialEq, Hash)] pub struct IntTy { pub signedness: Signedness, @@ -173,21 +137,3 @@ impl From for FloatTy { FloatTy { bitness: t.bitness } } } - -impl From> for Uncertain { - fn from(t: Option) -> Self { - match t { - None => Uncertain::Unknown, - Some(t) => Uncertain::Known(t.into()), - } - } -} - -impl From> for Uncertain { - fn from(t: Option) -> Self { - match t { - None => Uncertain::Unknown, - Some(t) => Uncertain::Known(t.into()), - } - } -} diff --git a/crates/ra_hir_ty/src/traits/chalk/mapping.rs b/crates/ra_hir_ty/src/traits/chalk/mapping.rs index 28a5fbe3e..18e5c9c16 100644 --- a/crates/ra_hir_ty/src/traits/chalk/mapping.rs +++ b/crates/ra_hir_ty/src/traits/chalk/mapping.rs @@ -14,7 +14,7 @@ use ra_db::salsa::InternKey; use crate::{ db::HirDatabase, - primitive::{FloatBitness, FloatTy, IntBitness, IntTy, Signedness, Uncertain}, + primitive::{FloatBitness, FloatTy, IntBitness, IntTy, Signedness}, traits::{builtin, AssocTyValue, Canonical, Impl, Obligation}, ApplicationTy, CallableDef, GenericPredicate, InEnvironment, OpaqueTy, OpaqueTyId, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, @@ -249,11 +249,11 @@ impl ToChalk for TypeCtor { TypeCtor::Bool => TypeName::Scalar(Scalar::Bool), TypeCtor::Char => TypeName::Scalar(Scalar::Char), - TypeCtor::Int(Uncertain::Known(int_ty)) => TypeName::Scalar(int_ty_to_chalk(int_ty)), - TypeCtor::Float(Uncertain::Known(FloatTy { bitness: FloatBitness::X32 })) => { + TypeCtor::Int(int_ty) => TypeName::Scalar(int_ty_to_chalk(int_ty)), + TypeCtor::Float(FloatTy { bitness: FloatBitness::X32 }) => { TypeName::Scalar(Scalar::Float(chalk_ir::FloatTy::F32)) } - TypeCtor::Float(Uncertain::Known(FloatTy { bitness: FloatBitness::X64 })) => { + TypeCtor::Float(FloatTy { bitness: FloatBitness::X64 }) => { TypeName::Scalar(Scalar::Float(chalk_ir::FloatTy::F64)) } @@ -268,9 +268,7 @@ impl ToChalk for TypeCtor { } TypeCtor::Never => TypeName::Never, - TypeCtor::Int(Uncertain::Unknown) - | TypeCtor::Float(Uncertain::Unknown) - | TypeCtor::Adt(_) + TypeCtor::Adt(_) | TypeCtor::Array | TypeCtor::FnPtr { .. } | TypeCtor::Closure { .. } => { @@ -291,19 +289,19 @@ impl ToChalk for TypeCtor { TypeName::Scalar(Scalar::Bool) => TypeCtor::Bool, TypeName::Scalar(Scalar::Char) => TypeCtor::Char, - TypeName::Scalar(Scalar::Int(int_ty)) => TypeCtor::Int(Uncertain::Known(IntTy { + TypeName::Scalar(Scalar::Int(int_ty)) => TypeCtor::Int(IntTy { signedness: Signedness::Signed, bitness: bitness_from_chalk_int(int_ty), - })), - TypeName::Scalar(Scalar::Uint(uint_ty)) => TypeCtor::Int(Uncertain::Known(IntTy { + }), + TypeName::Scalar(Scalar::Uint(uint_ty)) => TypeCtor::Int(IntTy { signedness: Signedness::Unsigned, bitness: bitness_from_chalk_uint(uint_ty), - })), + }), TypeName::Scalar(Scalar::Float(chalk_ir::FloatTy::F32)) => { - TypeCtor::Float(Uncertain::Known(FloatTy { bitness: FloatBitness::X32 })) + TypeCtor::Float(FloatTy { bitness: FloatBitness::X32 }) } TypeName::Scalar(Scalar::Float(chalk_ir::FloatTy::F64)) => { - TypeCtor::Float(Uncertain::Known(FloatTy { bitness: FloatBitness::X64 })) + TypeCtor::Float(FloatTy { bitness: FloatBitness::X64 }) } TypeName::Tuple(cardinality) => TypeCtor::Tuple { cardinality: cardinality as u16 }, TypeName::Raw(mutability) => TypeCtor::RawPtr(from_chalk(db, mutability)), -- cgit v1.2.3 From d8a5d39c2d05fb59b6c243935111714e18334599 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 11 Jun 2020 11:30:06 +0200 Subject: Make relevant_crates return a Set --- crates/ra_hir_ty/src/test_db.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'crates/ra_hir_ty') diff --git a/crates/ra_hir_ty/src/test_db.rs b/crates/ra_hir_ty/src/test_db.rs index e484968a0..ad04e3e0f 100644 --- a/crates/ra_hir_ty/src/test_db.rs +++ b/crates/ra_hir_ty/src/test_db.rs @@ -8,6 +8,7 @@ use std::{ use hir_def::{db::DefDatabase, AssocItemId, ModuleDefId, ModuleId}; use hir_expand::{db::AstDatabase, diagnostics::DiagnosticSink}; use ra_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, SourceDatabase, Upcast}; +use rustc_hash::FxHashSet; use stdx::format_to; use crate::{db::HirDatabase, diagnostics::Diagnostic, expr::ExprValidator}; @@ -73,7 +74,7 @@ impl FileLoader for TestDB { fn resolve_path(&self, anchor: FileId, path: &str) -> Option { FileLoaderDelegate(self).resolve_path(anchor, path) } - fn relevant_crates(&self, file_id: FileId) -> Arc> { + fn relevant_crates(&self, file_id: FileId) -> Arc> { FileLoaderDelegate(self).relevant_crates(file_id) } } -- cgit v1.2.3 From 90331ea0350eaea281d35bd0aa13df7f20a8600d Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 11 Jun 2020 16:22:31 +0200 Subject: Make known paths use `core` instead of `std` --- crates/ra_hir_ty/src/expr.rs | 10 ++++++---- crates/ra_hir_ty/src/infer.rs | 16 ++++++++-------- crates/ra_hir_ty/src/tests/simple.rs | 4 ++-- crates/ra_hir_ty/src/tests/traits.rs | 30 ++++++++++++++++-------------- 4 files changed, 32 insertions(+), 28 deletions(-) (limited to 'crates/ra_hir_ty') diff --git a/crates/ra_hir_ty/src/expr.rs b/crates/ra_hir_ty/src/expr.rs index f04968e14..7db928dde 100644 --- a/crates/ra_hir_ty/src/expr.rs +++ b/crates/ra_hir_ty/src/expr.rs @@ -226,17 +226,19 @@ impl<'a, 'b> ExprValidator<'a, 'b> { None => return, }; - let std_result_path = path![std::result::Result]; + let core_result_path = path![core::result::Result]; let resolver = self.func.resolver(db.upcast()); - let std_result_enum = match resolver.resolve_known_enum(db.upcast(), &std_result_path) { + let core_result_enum = match resolver.resolve_known_enum(db.upcast(), &core_result_path) { Some(it) => it, _ => return, }; - let std_result_ctor = TypeCtor::Adt(AdtId::EnumId(std_result_enum)); + let core_result_ctor = TypeCtor::Adt(AdtId::EnumId(core_result_enum)); let params = match &mismatch.expected { - Ty::Apply(ApplicationTy { ctor, parameters }) if ctor == &std_result_ctor => parameters, + Ty::Apply(ApplicationTy { ctor, parameters }) if ctor == &core_result_ctor => { + parameters + } _ => return, }; diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs index f965eb2b5..3719f76a6 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs @@ -555,13 +555,13 @@ impl<'a> InferenceContext<'a> { } fn resolve_into_iter_item(&self) -> Option { - let path = path![std::iter::IntoIterator]; + let path = path![core::iter::IntoIterator]; let trait_ = self.resolver.resolve_known_trait(self.db.upcast(), &path)?; self.db.trait_data(trait_).associated_type_by_name(&name![Item]) } fn resolve_ops_try_ok(&self) -> Option { - let path = path![std::ops::Try]; + let path = path![core::ops::Try]; let trait_ = self.resolver.resolve_known_trait(self.db.upcast(), &path)?; self.db.trait_data(trait_).associated_type_by_name(&name![Ok]) } @@ -587,37 +587,37 @@ impl<'a> InferenceContext<'a> { } fn resolve_range_full(&self) -> Option { - let path = path![std::ops::RangeFull]; + let path = path![core::ops::RangeFull]; let struct_ = self.resolver.resolve_known_struct(self.db.upcast(), &path)?; Some(struct_.into()) } fn resolve_range(&self) -> Option { - let path = path![std::ops::Range]; + let path = path![core::ops::Range]; let struct_ = self.resolver.resolve_known_struct(self.db.upcast(), &path)?; Some(struct_.into()) } fn resolve_range_inclusive(&self) -> Option { - let path = path![std::ops::RangeInclusive]; + let path = path![core::ops::RangeInclusive]; let struct_ = self.resolver.resolve_known_struct(self.db.upcast(), &path)?; Some(struct_.into()) } fn resolve_range_from(&self) -> Option { - let path = path![std::ops::RangeFrom]; + let path = path![core::ops::RangeFrom]; let struct_ = self.resolver.resolve_known_struct(self.db.upcast(), &path)?; Some(struct_.into()) } fn resolve_range_to(&self) -> Option { - let path = path![std::ops::RangeTo]; + let path = path![core::ops::RangeTo]; let struct_ = self.resolver.resolve_known_struct(self.db.upcast(), &path)?; Some(struct_.into()) } fn resolve_range_to_inclusive(&self) -> Option { - let path = path![std::ops::RangeToInclusive]; + let path = path![core::ops::RangeToInclusive]; let struct_ = self.resolver.resolve_known_struct(self.db.upcast(), &path)?; Some(struct_.into()) } diff --git a/crates/ra_hir_ty/src/tests/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs index 8a5031756..37659cd02 100644 --- a/crates/ra_hir_ty/src/tests/simple.rs +++ b/crates/ra_hir_ty/src/tests/simple.rs @@ -95,7 +95,7 @@ fn foo() { fn infer_ranges() { let (db, pos) = TestDB::with_position( r#" -//- /main.rs crate:main deps:std +//- /main.rs crate:main deps:core fn test() { let a = ..; let b = 1..; @@ -108,7 +108,7 @@ fn test() { t<|>; } -//- /std.rs crate:std +//- /core.rs crate:core #[prelude_import] use prelude::*; mod prelude {} diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs index 133fb5f39..e81193a3c 100644 --- a/crates/ra_hir_ty/src/tests/traits.rs +++ b/crates/ra_hir_ty/src/tests/traits.rs @@ -10,7 +10,7 @@ use super::{infer, infer_with_mismatches, type_at, type_at_pos}; fn infer_await() { let (db, pos) = TestDB::with_position( r#" -//- /main.rs crate:main deps:std +//- /main.rs crate:main deps:core struct IntFuture; @@ -24,7 +24,7 @@ fn test() { v<|>; } -//- /std.rs crate:std +//- /core.rs crate:core #[prelude_import] use future::*; mod future { #[lang = "future_trait"] @@ -42,7 +42,7 @@ mod future { fn infer_async() { let (db, pos) = TestDB::with_position( r#" -//- /main.rs crate:main deps:std +//- /main.rs crate:main deps:core async fn foo() -> u64 { 128 @@ -54,7 +54,7 @@ fn test() { v<|>; } -//- /std.rs crate:std +//- /core.rs crate:core #[prelude_import] use future::*; mod future { #[lang = "future_trait"] @@ -72,7 +72,7 @@ mod future { fn infer_desugar_async() { let (db, pos) = TestDB::with_position( r#" -//- /main.rs crate:main deps:std +//- /main.rs crate:main deps:core async fn foo() -> u64 { 128 @@ -83,7 +83,7 @@ fn test() { r<|>; } -//- /std.rs crate:std +//- /core.rs crate:core #[prelude_import] use future::*; mod future { trait Future { @@ -100,7 +100,7 @@ mod future { fn infer_try() { let (db, pos) = TestDB::with_position( r#" -//- /main.rs crate:main deps:std +//- /main.rs crate:main deps:core fn test() { let r: Result = Result::Ok(1); @@ -108,7 +108,7 @@ fn test() { v<|>; } -//- /std.rs crate:std +//- /core.rs crate:core #[prelude_import] use ops::*; mod ops { @@ -140,9 +140,9 @@ mod result { fn infer_for_loop() { let (db, pos) = TestDB::with_position( r#" -//- /main.rs crate:main deps:std +//- /main.rs crate:main deps:core,alloc -use std::collections::Vec; +use alloc::collections::Vec; fn test() { let v = Vec::new(); @@ -152,7 +152,7 @@ fn test() { } } -//- /std.rs crate:std +//- /core.rs crate:core #[prelude_import] use iter::*; mod iter { @@ -161,6 +161,8 @@ mod iter { } } +//- /alloc.rs crate:alloc deps:core + mod collections { struct Vec {} impl Vec { @@ -168,7 +170,7 @@ mod collections { fn push(&mut self, t: T) { } } - impl crate::iter::IntoIterator for Vec { + impl IntoIterator for Vec { type Item=T; } } @@ -2846,12 +2848,12 @@ fn test() { fn integer_range_iterate() { let t = type_at( r#" -//- /main.rs crate:main deps:std +//- /main.rs crate:main deps:core fn test() { for x in 0..100 { x<|>; } } -//- /std.rs crate:std +//- /core.rs crate:core pub mod ops { pub struct Range { pub start: Idx, -- cgit v1.2.3