From 22a65b11b3a69b3dae561b34c6b28cb2107169d1 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 24 Jan 2020 14:32:47 +0100 Subject: Introduce TyLoweringContext --- crates/ra_hir_ty/src/lower.rs | 232 ++++++++++++++++++++---------------------- 1 file changed, 110 insertions(+), 122 deletions(-) (limited to 'crates/ra_hir_ty/src/lower.rs') diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 2c2ecee9c..87c984e3f 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs @@ -31,47 +31,50 @@ use crate::{ Ty, TypeCtor, TypeWalk, }; +#[derive(Clone, Debug)] +pub struct TyLoweringContext<'a, DB: HirDatabase> { + pub db: &'a DB, + pub resolver: &'a Resolver, +} + impl Ty { - pub fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self { + pub fn from_hir(ctx: &TyLoweringContext<'_, impl HirDatabase>, type_ref: &TypeRef) -> Self { match type_ref { TypeRef::Never => Ty::simple(TypeCtor::Never), TypeRef::Tuple(inner) => { - let inner_tys: Arc<[Ty]> = - inner.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect(); + let inner_tys: Arc<[Ty]> = inner.iter().map(|tr| Ty::from_hir(ctx, tr)).collect(); Ty::apply( TypeCtor::Tuple { cardinality: inner_tys.len() as u16 }, Substs(inner_tys), ) } - TypeRef::Path(path) => Ty::from_hir_path(db, resolver, path), + TypeRef::Path(path) => Ty::from_hir_path(ctx, path), TypeRef::RawPtr(inner, mutability) => { - let inner_ty = Ty::from_hir(db, resolver, inner); + let inner_ty = Ty::from_hir(ctx, inner); Ty::apply_one(TypeCtor::RawPtr(*mutability), inner_ty) } TypeRef::Array(inner) => { - let inner_ty = Ty::from_hir(db, resolver, inner); + let inner_ty = Ty::from_hir(ctx, inner); Ty::apply_one(TypeCtor::Array, inner_ty) } TypeRef::Slice(inner) => { - let inner_ty = Ty::from_hir(db, resolver, inner); + let inner_ty = Ty::from_hir(ctx, inner); Ty::apply_one(TypeCtor::Slice, inner_ty) } TypeRef::Reference(inner, mutability) => { - let inner_ty = Ty::from_hir(db, resolver, inner); + let inner_ty = Ty::from_hir(ctx, inner); Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty) } TypeRef::Placeholder => Ty::Unknown, TypeRef::Fn(params) => { - let sig = Substs(params.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect()); + let sig = Substs(params.iter().map(|tr| Ty::from_hir(ctx, tr)).collect()); Ty::apply(TypeCtor::FnPtr { num_args: sig.len() as u16 - 1 }, sig) } TypeRef::DynTrait(bounds) => { let self_ty = Ty::Bound(0); let predicates = bounds .iter() - .flat_map(|b| { - GenericPredicate::from_type_bound(db, resolver, b, self_ty.clone()) - }) + .flat_map(|b| GenericPredicate::from_type_bound(ctx, b, self_ty.clone())) .collect(); Ty::Dyn(predicates) } @@ -79,9 +82,7 @@ impl Ty { let self_ty = Ty::Bound(0); let predicates = bounds .iter() - .flat_map(|b| { - GenericPredicate::from_type_bound(db, resolver, b, self_ty.clone()) - }) + .flat_map(|b| GenericPredicate::from_type_bound(ctx, b, self_ty.clone())) .collect(); Ty::Opaque(predicates) } @@ -93,8 +94,7 @@ impl Ty { /// lower the self types of the predicates since that could lead to cycles. /// So we just check here if the `type_ref` resolves to a generic param, and which. fn from_hir_only_param( - db: &impl HirDatabase, - resolver: &Resolver, + ctx: &TyLoweringContext<'_, impl HirDatabase>, type_ref: &TypeRef, ) -> Option { let path = match type_ref { @@ -107,12 +107,12 @@ impl Ty { if path.segments().len() > 1 { return None; } - let resolution = match resolver.resolve_path_in_type_ns(db, path.mod_path()) { + let resolution = match ctx.resolver.resolve_path_in_type_ns(ctx.db, path.mod_path()) { Some((it, None)) => it, _ => return None, }; if let TypeNs::GenericParam(param_id) = resolution { - let generics = generics(db, resolver.generic_def().expect("generics in scope")); + let generics = generics(ctx.db, ctx.resolver.generic_def().expect("generics in scope")); let idx = generics.param_idx(param_id); Some(idx) } else { @@ -121,15 +121,14 @@ impl Ty { } pub(crate) fn from_type_relative_path( - db: &impl HirDatabase, - resolver: &Resolver, + ctx: &TyLoweringContext<'_, impl HirDatabase>, ty: Ty, remaining_segments: PathSegments<'_>, ) -> Ty { if remaining_segments.len() == 1 { // resolve unselected assoc types let segment = remaining_segments.first().unwrap(); - Ty::select_associated_type(db, resolver, ty, segment) + Ty::select_associated_type(ctx, ty, segment) } else if remaining_segments.len() > 1 { // FIXME report error (ambiguous associated type) Ty::Unknown @@ -139,20 +138,18 @@ impl Ty { } pub(crate) fn from_partly_resolved_hir_path( - db: &impl HirDatabase, - resolver: &Resolver, + ctx: &TyLoweringContext<'_, impl HirDatabase>, resolution: TypeNs, resolved_segment: PathSegment<'_>, remaining_segments: PathSegments<'_>, ) -> Ty { let ty = match resolution { TypeNs::TraitId(trait_) => { - let trait_ref = - TraitRef::from_resolved_path(db, resolver, trait_, resolved_segment, None); + let trait_ref = TraitRef::from_resolved_path(ctx, trait_, resolved_segment, None); return if remaining_segments.len() == 1 { let segment = remaining_segments.first().unwrap(); let associated_ty = associated_type_by_name_including_super_traits( - db, + ctx.db, trait_ref.trait_, &segment.name, ); @@ -177,37 +174,34 @@ impl Ty { }; } TypeNs::GenericParam(param_id) => { - let generics = generics(db, resolver.generic_def().expect("generics in scope")); + let generics = + generics(ctx.db, ctx.resolver.generic_def().expect("generics in scope")); let idx = generics.param_idx(param_id); // FIXME: maybe return name in resolution? let name = generics.param_name(param_id); Ty::Param { idx, name } } - TypeNs::SelfType(impl_id) => db.impl_self_ty(impl_id).clone(), - TypeNs::AdtSelfType(adt) => db.ty(adt.into()), + TypeNs::SelfType(impl_id) => ctx.db.impl_self_ty(impl_id).clone(), + TypeNs::AdtSelfType(adt) => ctx.db.ty(adt.into()), - TypeNs::AdtId(it) => Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into()), - TypeNs::BuiltinType(it) => { - Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into()) - } - TypeNs::TypeAliasId(it) => { - Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into()) - } + 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()), // FIXME: report error TypeNs::EnumVariantId(_) => return Ty::Unknown, }; - Ty::from_type_relative_path(db, resolver, ty, remaining_segments) + Ty::from_type_relative_path(ctx, ty, remaining_segments) } - pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Ty { + pub(crate) fn from_hir_path(ctx: &TyLoweringContext<'_, impl HirDatabase>, path: &Path) -> Ty { // Resolve the path (in type namespace) if let Some(type_ref) = path.type_anchor() { - let ty = Ty::from_hir(db, resolver, &type_ref); - return Ty::from_type_relative_path(db, resolver, ty, path.segments()); + let ty = Ty::from_hir(ctx, &type_ref); + return Ty::from_type_relative_path(ctx, ty, path.segments()); } let (resolution, remaining_index) = - match resolver.resolve_path_in_type_ns(db, path.mod_path()) { + match ctx.resolver.resolve_path_in_type_ns(ctx.db, path.mod_path()) { Some(it) => it, None => return Ty::Unknown, }; @@ -218,18 +212,11 @@ impl Ty { ), Some(i) => (path.segments().get(i - 1).unwrap(), path.segments().skip(i)), }; - Ty::from_partly_resolved_hir_path( - db, - resolver, - resolution, - resolved_segment, - remaining_segments, - ) + Ty::from_partly_resolved_hir_path(ctx, resolution, resolved_segment, remaining_segments) } fn select_associated_type( - db: &impl HirDatabase, - resolver: &Resolver, + ctx: &TyLoweringContext<'_, impl HirDatabase>, self_ty: Ty, segment: PathSegment<'_>, ) -> Ty { @@ -237,20 +224,23 @@ impl Ty { Ty::Param { idx, .. } => idx, _ => return Ty::Unknown, // Error: Ambiguous associated type }; - let def = match resolver.generic_def() { + let def = match ctx.resolver.generic_def() { Some(def) => def, None => return Ty::Unknown, // this can't actually happen }; - let predicates = db.generic_predicates_for_param(def.into(), param_idx); + let predicates = ctx.db.generic_predicates_for_param(def.into(), param_idx); let traits_from_env = predicates.iter().filter_map(|pred| match pred { GenericPredicate::Implemented(tr) if tr.self_ty() == &self_ty => Some(tr.trait_), _ => None, }); - let traits = traits_from_env.flat_map(|t| all_super_traits(db, t)); + let traits = traits_from_env.flat_map(|t| all_super_traits(ctx.db, t)); for t in traits { - if let Some(associated_ty) = db.trait_data(t).associated_type_by_name(&segment.name) { - let substs = - Substs::build_for_def(db, t).push(self_ty.clone()).fill_with_unknown().build(); + if let Some(associated_ty) = ctx.db.trait_data(t).associated_type_by_name(&segment.name) + { + let substs = Substs::build_for_def(ctx.db, t) + .push(self_ty.clone()) + .fill_with_unknown() + .build(); // FIXME handle type parameters on the segment return Ty::Projection(ProjectionTy { associated_ty, parameters: substs }); } @@ -259,8 +249,7 @@ impl Ty { } fn from_hir_path_inner( - db: &impl HirDatabase, - resolver: &Resolver, + ctx: &TyLoweringContext<'_, impl HirDatabase>, segment: PathSegment<'_>, typable: TyDefId, ) -> Ty { @@ -269,15 +258,14 @@ impl Ty { TyDefId::AdtId(it) => Some(it.into()), TyDefId::TypeAliasId(it) => Some(it.into()), }; - let substs = substs_from_path_segment(db, resolver, segment, generic_def, false); - db.ty(typable).subst(&substs) + let substs = substs_from_path_segment(ctx, segment, generic_def, false); + ctx.db.ty(typable).subst(&substs) } /// Collect generic arguments from a path into a `Substs`. See also /// `create_substs_for_ast_path` and `def_to_ty` in rustc. pub(super) fn substs_from_path( - db: &impl HirDatabase, - resolver: &Resolver, + ctx: &TyLoweringContext<'_, impl HirDatabase>, path: &Path, // Note that we don't call `db.value_type(resolved)` here, // `ValueTyDefId` is just a convenient way to pass generics and @@ -305,19 +293,18 @@ impl Ty { (segment, Some(var.parent.into())) } }; - substs_from_path_segment(db, resolver, segment, generic_def, false) + substs_from_path_segment(ctx, segment, generic_def, false) } } pub(super) fn substs_from_path_segment( - db: &impl HirDatabase, - resolver: &Resolver, + ctx: &TyLoweringContext<'_, impl HirDatabase>, segment: PathSegment<'_>, def_generic: Option, add_self_param: bool, ) -> Substs { let mut substs = Vec::new(); - let def_generics = def_generic.map(|def| generics(db, def.into())); + let def_generics = def_generic.map(|def| generics(ctx.db, def.into())); let (total_len, parent_len, child_len) = def_generics.map_or((0, 0, 0), |g| g.len_split()); substs.extend(iter::repeat(Ty::Unknown).take(parent_len)); @@ -335,7 +322,7 @@ pub(super) fn substs_from_path_segment( for arg in generic_args.args.iter().take(child_len) { match arg { GenericArg::Type(type_ref) => { - let ty = Ty::from_hir(db, resolver, type_ref); + let ty = Ty::from_hir(ctx, type_ref); substs.push(ty); } } @@ -350,7 +337,7 @@ pub(super) fn substs_from_path_segment( // handle defaults if let Some(def_generic) = def_generic { - let default_substs = db.generic_defaults(def_generic.into()); + let default_substs = ctx.db.generic_defaults(def_generic.into()); assert_eq!(substs.len(), default_substs.len()); for (i, default_ty) in default_substs.iter().enumerate() { @@ -365,27 +352,25 @@ pub(super) fn substs_from_path_segment( impl TraitRef { fn from_path( - db: &impl HirDatabase, - resolver: &Resolver, + ctx: &TyLoweringContext<'_, impl HirDatabase>, path: &Path, explicit_self_ty: Option, ) -> Option { - let resolved = match resolver.resolve_path_in_type_ns_fully(db, path.mod_path())? { + let resolved = match ctx.resolver.resolve_path_in_type_ns_fully(ctx.db, path.mod_path())? { TypeNs::TraitId(tr) => tr, _ => return None, }; let segment = path.segments().last().expect("path should have at least one segment"); - Some(TraitRef::from_resolved_path(db, resolver, resolved.into(), segment, explicit_self_ty)) + Some(TraitRef::from_resolved_path(ctx, resolved.into(), segment, explicit_self_ty)) } pub(crate) fn from_resolved_path( - db: &impl HirDatabase, - resolver: &Resolver, + ctx: &TyLoweringContext<'_, impl HirDatabase>, resolved: TraitId, segment: PathSegment<'_>, explicit_self_ty: Option, ) -> Self { - let mut substs = TraitRef::substs_from_path(db, resolver, segment, resolved); + let mut substs = TraitRef::substs_from_path(ctx, segment, resolved); if let Some(self_ty) = explicit_self_ty { make_mut_slice(&mut substs.0)[0] = self_ty; } @@ -393,8 +378,7 @@ impl TraitRef { } fn from_hir( - db: &impl HirDatabase, - resolver: &Resolver, + ctx: &TyLoweringContext<'_, impl HirDatabase>, type_ref: &TypeRef, explicit_self_ty: Option, ) -> Option { @@ -402,28 +386,26 @@ impl TraitRef { TypeRef::Path(path) => path, _ => return None, }; - TraitRef::from_path(db, resolver, path, explicit_self_ty) + TraitRef::from_path(ctx, path, explicit_self_ty) } fn substs_from_path( - db: &impl HirDatabase, - resolver: &Resolver, + ctx: &TyLoweringContext<'_, impl HirDatabase>, 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(db, resolver, segment, Some(resolved.into()), !has_self_param) + substs_from_path_segment(ctx, segment, Some(resolved.into()), !has_self_param) } pub(crate) fn from_type_bound( - db: &impl HirDatabase, - resolver: &Resolver, + ctx: &TyLoweringContext<'_, impl HirDatabase>, bound: &TypeBound, self_ty: Ty, ) -> Option { match bound { - TypeBound::Path(path) => TraitRef::from_path(db, resolver, path, Some(self_ty)), + TypeBound::Path(path) => TraitRef::from_path(ctx, path, Some(self_ty)), TypeBound::Error => None, } } @@ -431,33 +413,30 @@ impl TraitRef { impl GenericPredicate { pub(crate) fn from_where_predicate<'a>( - db: &'a impl HirDatabase, - resolver: &'a Resolver, + ctx: &'a TyLoweringContext<'a, impl HirDatabase>, where_predicate: &'a WherePredicate, ) -> impl Iterator + 'a { - let self_ty = Ty::from_hir(db, resolver, &where_predicate.type_ref); - GenericPredicate::from_type_bound(db, resolver, &where_predicate.bound, self_ty) + let self_ty = Ty::from_hir(ctx, &where_predicate.type_ref); + GenericPredicate::from_type_bound(ctx, &where_predicate.bound, self_ty) } pub(crate) fn from_type_bound<'a>( - db: &'a impl HirDatabase, - resolver: &'a Resolver, + ctx: &'a TyLoweringContext<'a, impl HirDatabase>, bound: &'a TypeBound, self_ty: Ty, ) -> impl Iterator + 'a { - let trait_ref = TraitRef::from_type_bound(db, &resolver, bound, self_ty); + let trait_ref = TraitRef::from_type_bound(ctx, bound, self_ty); iter::once(trait_ref.clone().map_or(GenericPredicate::Error, GenericPredicate::Implemented)) .chain( - trait_ref.into_iter().flat_map(move |tr| { - assoc_type_bindings_from_type_bound(db, resolver, bound, tr) - }), + trait_ref + .into_iter() + .flat_map(move |tr| assoc_type_bindings_from_type_bound(ctx, bound, tr)), ) } } fn assoc_type_bindings_from_type_bound<'a>( - db: &'a impl HirDatabase, - resolver: &'a Resolver, + ctx: &'a TyLoweringContext<'a, impl HirDatabase>, bound: &'a TypeBound, trait_ref: TraitRef, ) -> impl Iterator + 'a { @@ -471,14 +450,14 @@ fn assoc_type_bindings_from_type_bound<'a>( .flat_map(|args_and_bindings| args_and_bindings.bindings.iter()) .map(move |(name, type_ref)| { let associated_ty = - associated_type_by_name_including_super_traits(db, trait_ref.trait_, &name); + associated_type_by_name_including_super_traits(ctx.db, trait_ref.trait_, &name); let associated_ty = match associated_ty { None => return GenericPredicate::Error, Some(t) => t, }; let projection_ty = ProjectionTy { associated_ty, parameters: trait_ref.substs.clone() }; - let ty = Ty::from_hir(db, resolver, type_ref); + let ty = Ty::from_hir(ctx, type_ref); let projection_predicate = ProjectionPredicate { projection_ty, ty }; GenericPredicate::Projection(projection_predicate) }) @@ -505,8 +484,9 @@ pub(crate) fn field_types_query( VariantId::EnumVariantId(it) => it.parent.resolver(db), }; let mut res = ArenaMap::default(); + let ctx = TyLoweringContext { db, resolver: &resolver }; for (field_id, field_data) in var_data.fields().iter() { - res.insert(field_id, Ty::from_hir(db, &resolver, &field_data.type_ref)) + res.insert(field_id, Ty::from_hir(&ctx, &field_data.type_ref)) } Arc::new(res) } @@ -525,11 +505,12 @@ pub(crate) fn generic_predicates_for_param_query( param_idx: u32, ) -> Arc<[GenericPredicate]> { let resolver = def.resolver(db); + let ctx = TyLoweringContext { db, resolver: &resolver }; resolver .where_predicates_in_scope() // we have to filter out all other predicates *first*, before attempting to lower them - .filter(|pred| Ty::from_hir_only_param(db, &resolver, &pred.type_ref) == Some(param_idx)) - .flat_map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred)) + .filter(|pred| Ty::from_hir_only_param(&ctx, &pred.type_ref) == Some(param_idx)) + .flat_map(|pred| GenericPredicate::from_where_predicate(&ctx, pred)) .collect() } @@ -543,10 +524,11 @@ pub(crate) fn generic_predicates_for_param_recover( } impl TraitEnvironment { - pub fn lower(db: &impl HirDatabase, resolver: &Resolver) -> Arc { - let predicates = resolver + pub fn lower(ctx: &TyLoweringContext<'_, impl HirDatabase>) -> Arc { + let predicates = ctx + .resolver .where_predicates_in_scope() - .flat_map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred)) + .flat_map(|pred| GenericPredicate::from_where_predicate(ctx, pred)) .collect::>(); Arc::new(TraitEnvironment { predicates }) @@ -559,20 +541,22 @@ pub(crate) fn generic_predicates_query( def: GenericDefId, ) -> Arc<[GenericPredicate]> { let resolver = def.resolver(db); + let ctx = TyLoweringContext { db, resolver: &resolver }; resolver .where_predicates_in_scope() - .flat_map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred)) + .flat_map(|pred| GenericPredicate::from_where_predicate(&ctx, pred)) .collect() } /// Resolve the default type params from generics pub(crate) fn generic_defaults_query(db: &impl HirDatabase, def: GenericDefId) -> Substs { let resolver = def.resolver(db); + let ctx = TyLoweringContext { db, resolver: &resolver }; let generic_params = generics(db, def.into()); let defaults = generic_params .iter() - .map(|(_idx, p)| p.default.as_ref().map_or(Ty::Unknown, |t| Ty::from_hir(db, &resolver, t))) + .map(|(_idx, p)| p.default.as_ref().map_or(Ty::Unknown, |t| Ty::from_hir(&ctx, t))) .collect(); Substs(defaults) @@ -581,8 +565,9 @@ pub(crate) fn generic_defaults_query(db: &impl HirDatabase, def: GenericDefId) - fn fn_sig_for_fn(db: &impl HirDatabase, def: FunctionId) -> FnSig { let data = db.function_data(def); let resolver = def.resolver(db); - let params = data.params.iter().map(|tr| Ty::from_hir(db, &resolver, tr)).collect::>(); - let ret = Ty::from_hir(db, &resolver, &data.ret_type); + let ctx = TyLoweringContext { db, resolver: &resolver }; + let params = data.params.iter().map(|tr| Ty::from_hir(&ctx, tr)).collect::>(); + let ret = Ty::from_hir(&ctx, &data.ret_type); FnSig::from_params_and_return(params, ret) } @@ -598,16 +583,18 @@ fn type_for_fn(db: &impl HirDatabase, def: FunctionId) -> Ty { fn type_for_const(db: &impl HirDatabase, def: ConstId) -> Ty { let data = db.const_data(def); let resolver = def.resolver(db); + let ctx = TyLoweringContext { db, resolver: &resolver }; - Ty::from_hir(db, &resolver, &data.type_ref) + Ty::from_hir(&ctx, &data.type_ref) } /// Build the declared type of a static. fn type_for_static(db: &impl HirDatabase, def: StaticId) -> Ty { let data = db.static_data(def); let resolver = def.resolver(db); + let ctx = TyLoweringContext { db, resolver: &resolver }; - Ty::from_hir(db, &resolver, &data.type_ref) + Ty::from_hir(&ctx, &data.type_ref) } /// Build the declared type of a static. @@ -625,10 +612,9 @@ fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> FnSig let struct_data = db.struct_data(def.into()); let fields = struct_data.variant_data.fields(); let resolver = def.resolver(db); - let params = fields - .iter() - .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) - .collect::>(); + let ctx = TyLoweringContext { db, resolver: &resolver }; + let params = + fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::>(); let ret = type_for_adt(db, def.into()); FnSig::from_params_and_return(params, ret) } @@ -649,10 +635,9 @@ fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId let var_data = &enum_data.variants[def.local_id]; let fields = var_data.variant_data.fields(); let resolver = def.parent.resolver(db); - let params = fields - .iter() - .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) - .collect::>(); + let ctx = TyLoweringContext { db, resolver: &resolver }; + let params = + fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::>(); let generics = generics(db, def.parent.into()); let substs = Substs::identity(&generics); let ret = type_for_adt(db, def.parent.into()).subst(&substs); @@ -679,9 +664,10 @@ fn type_for_adt(db: &impl HirDatabase, adt: AdtId) -> Ty { fn type_for_type_alias(db: &impl HirDatabase, t: TypeAliasId) -> Ty { let generics = generics(db, t.into()); let resolver = t.resolver(db); + let ctx = TyLoweringContext { db, resolver: &resolver }; let type_ref = &db.type_alias_data(t).type_ref; let substs = Substs::identity(&generics); - let inner = Ty::from_hir(db, &resolver, type_ref.as_ref().unwrap_or(&TypeRef::Error)); + let inner = Ty::from_hir(&ctx, type_ref.as_ref().unwrap_or(&TypeRef::Error)); inner.subst(&substs) } @@ -761,7 +747,8 @@ pub(crate) fn value_ty_query(db: &impl HirDatabase, def: ValueTyDefId) -> Ty { pub(crate) fn impl_self_ty_query(db: &impl HirDatabase, impl_id: ImplId) -> Ty { let impl_data = db.impl_data(impl_id); let resolver = impl_id.resolver(db); - Ty::from_hir(db, &resolver, &impl_data.target_type) + let ctx = TyLoweringContext { db, resolver: &resolver }; + Ty::from_hir(&ctx, &impl_data.target_type) } pub(crate) fn impl_self_ty_recover( @@ -775,7 +762,8 @@ pub(crate) fn impl_self_ty_recover( pub(crate) fn impl_trait_query(db: &impl HirDatabase, impl_id: ImplId) -> Option { let impl_data = db.impl_data(impl_id); let resolver = impl_id.resolver(db); + let ctx = TyLoweringContext { db, resolver: &resolver }; let self_ty = db.impl_self_ty(impl_id); let target_trait = impl_data.target_trait.as_ref()?; - TraitRef::from_hir(db, &resolver, target_trait, Some(self_ty.clone())) + TraitRef::from_hir(&ctx, target_trait, Some(self_ty.clone())) } -- cgit v1.2.3 From 7ea4bce1b292d455c313f914b3aa3051293c502b Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 24 Jan 2020 15:22:00 +0100 Subject: Add impl trait lowering mode --- crates/ra_hir_ty/src/lower.rs | 98 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 80 insertions(+), 18 deletions(-) (limited to 'crates/ra_hir_ty/src/lower.rs') diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 87c984e3f..3d2421223 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs @@ -35,6 +35,14 @@ use crate::{ pub struct TyLoweringContext<'a, DB: HirDatabase> { pub db: &'a DB, pub resolver: &'a Resolver, + pub impl_trait_mode: ImplTraitLoweringMode, +} + +#[derive(Clone, Debug)] +pub enum ImplTraitLoweringMode { + Opaque, + Placeholder, + Disallowed, } impl Ty { @@ -484,7 +492,11 @@ pub(crate) fn field_types_query( VariantId::EnumVariantId(it) => it.parent.resolver(db), }; let mut res = ArenaMap::default(); - let ctx = TyLoweringContext { db, resolver: &resolver }; + let ctx = TyLoweringContext { + db, + resolver: &resolver, + impl_trait_mode: ImplTraitLoweringMode::Disallowed, + }; for (field_id, field_data) in var_data.fields().iter() { res.insert(field_id, Ty::from_hir(&ctx, &field_data.type_ref)) } @@ -505,7 +517,11 @@ pub(crate) fn generic_predicates_for_param_query( param_idx: u32, ) -> Arc<[GenericPredicate]> { let resolver = def.resolver(db); - let ctx = TyLoweringContext { db, resolver: &resolver }; + let ctx = TyLoweringContext { + db, + resolver: &resolver, + impl_trait_mode: ImplTraitLoweringMode::Disallowed, + }; resolver .where_predicates_in_scope() // we have to filter out all other predicates *first*, before attempting to lower them @@ -524,11 +540,12 @@ pub(crate) fn generic_predicates_for_param_recover( } impl TraitEnvironment { - pub fn lower(ctx: &TyLoweringContext<'_, impl HirDatabase>) -> Arc { - let predicates = ctx - .resolver + pub fn lower(db: &impl HirDatabase, resolver: &Resolver) -> Arc { + let ctx = + TyLoweringContext { db, resolver, impl_trait_mode: ImplTraitLoweringMode::Disallowed }; + let predicates = resolver .where_predicates_in_scope() - .flat_map(|pred| GenericPredicate::from_where_predicate(ctx, pred)) + .flat_map(|pred| GenericPredicate::from_where_predicate(&ctx, pred)) .collect::>(); Arc::new(TraitEnvironment { predicates }) @@ -541,7 +558,11 @@ pub(crate) fn generic_predicates_query( def: GenericDefId, ) -> Arc<[GenericPredicate]> { let resolver = def.resolver(db); - let ctx = TyLoweringContext { db, resolver: &resolver }; + let ctx = TyLoweringContext { + db, + resolver: &resolver, + impl_trait_mode: ImplTraitLoweringMode::Disallowed, + }; resolver .where_predicates_in_scope() .flat_map(|pred| GenericPredicate::from_where_predicate(&ctx, pred)) @@ -551,7 +572,11 @@ pub(crate) fn generic_predicates_query( /// Resolve the default type params from generics pub(crate) fn generic_defaults_query(db: &impl HirDatabase, def: GenericDefId) -> Substs { let resolver = def.resolver(db); - let ctx = TyLoweringContext { db, resolver: &resolver }; + let ctx = TyLoweringContext { + db, + resolver: &resolver, + impl_trait_mode: ImplTraitLoweringMode::Disallowed, + }; let generic_params = generics(db, def.into()); let defaults = generic_params @@ -565,9 +590,18 @@ pub(crate) fn generic_defaults_query(db: &impl HirDatabase, def: GenericDefId) - fn fn_sig_for_fn(db: &impl HirDatabase, def: FunctionId) -> FnSig { let data = db.function_data(def); let resolver = def.resolver(db); - let ctx = TyLoweringContext { db, resolver: &resolver }; - let params = data.params.iter().map(|tr| Ty::from_hir(&ctx, tr)).collect::>(); - let ret = Ty::from_hir(&ctx, &data.ret_type); + let ctx_params = TyLoweringContext { + db, + resolver: &resolver, + impl_trait_mode: ImplTraitLoweringMode::Placeholder, + }; + let params = data.params.iter().map(|tr| Ty::from_hir(&ctx_params, tr)).collect::>(); + let ctx_ret = TyLoweringContext { + db, + resolver: &resolver, + impl_trait_mode: ImplTraitLoweringMode::Opaque, + }; + let ret = Ty::from_hir(&ctx_ret, &data.ret_type); FnSig::from_params_and_return(params, ret) } @@ -583,7 +617,11 @@ fn type_for_fn(db: &impl HirDatabase, def: FunctionId) -> Ty { fn type_for_const(db: &impl HirDatabase, def: ConstId) -> Ty { let data = db.const_data(def); let resolver = def.resolver(db); - let ctx = TyLoweringContext { db, resolver: &resolver }; + let ctx = TyLoweringContext { + db, + resolver: &resolver, + impl_trait_mode: ImplTraitLoweringMode::Disallowed, + }; Ty::from_hir(&ctx, &data.type_ref) } @@ -592,7 +630,11 @@ fn type_for_const(db: &impl HirDatabase, def: ConstId) -> Ty { fn type_for_static(db: &impl HirDatabase, def: StaticId) -> Ty { let data = db.static_data(def); let resolver = def.resolver(db); - let ctx = TyLoweringContext { db, resolver: &resolver }; + let ctx = TyLoweringContext { + db, + resolver: &resolver, + impl_trait_mode: ImplTraitLoweringMode::Disallowed, + }; Ty::from_hir(&ctx, &data.type_ref) } @@ -612,7 +654,11 @@ fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> FnSig let struct_data = db.struct_data(def.into()); let fields = struct_data.variant_data.fields(); let resolver = def.resolver(db); - let ctx = TyLoweringContext { db, resolver: &resolver }; + let ctx = TyLoweringContext { + db, + resolver: &resolver, + impl_trait_mode: ImplTraitLoweringMode::Disallowed, + }; let params = fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::>(); let ret = type_for_adt(db, def.into()); @@ -635,7 +681,11 @@ fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId let var_data = &enum_data.variants[def.local_id]; let fields = var_data.variant_data.fields(); let resolver = def.parent.resolver(db); - let ctx = TyLoweringContext { db, resolver: &resolver }; + let ctx = TyLoweringContext { + db, + resolver: &resolver, + impl_trait_mode: ImplTraitLoweringMode::Disallowed, + }; let params = fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::>(); let generics = generics(db, def.parent.into()); @@ -664,7 +714,11 @@ fn type_for_adt(db: &impl HirDatabase, adt: AdtId) -> Ty { fn type_for_type_alias(db: &impl HirDatabase, t: TypeAliasId) -> Ty { let generics = generics(db, t.into()); let resolver = t.resolver(db); - let ctx = TyLoweringContext { db, resolver: &resolver }; + let ctx = TyLoweringContext { + db, + resolver: &resolver, + impl_trait_mode: ImplTraitLoweringMode::Disallowed, + }; let type_ref = &db.type_alias_data(t).type_ref; let substs = Substs::identity(&generics); let inner = Ty::from_hir(&ctx, type_ref.as_ref().unwrap_or(&TypeRef::Error)); @@ -747,7 +801,11 @@ pub(crate) fn value_ty_query(db: &impl HirDatabase, def: ValueTyDefId) -> Ty { pub(crate) fn impl_self_ty_query(db: &impl HirDatabase, impl_id: ImplId) -> Ty { let impl_data = db.impl_data(impl_id); let resolver = impl_id.resolver(db); - let ctx = TyLoweringContext { db, resolver: &resolver }; + let ctx = TyLoweringContext { + db, + resolver: &resolver, + impl_trait_mode: ImplTraitLoweringMode::Disallowed, + }; Ty::from_hir(&ctx, &impl_data.target_type) } @@ -762,7 +820,11 @@ pub(crate) fn impl_self_ty_recover( pub(crate) fn impl_trait_query(db: &impl HirDatabase, impl_id: ImplId) -> Option { let impl_data = db.impl_data(impl_id); let resolver = impl_id.resolver(db); - let ctx = TyLoweringContext { db, resolver: &resolver }; + let ctx = TyLoweringContext { + db, + resolver: &resolver, + impl_trait_mode: ImplTraitLoweringMode::Disallowed, + }; let self_ty = db.impl_self_ty(impl_id); let target_trait = impl_data.target_trait.as_ref()?; TraitRef::from_hir(&ctx, target_trait, Some(self_ty.clone())) -- cgit v1.2.3 From 9dec65d3b1aa703ceef993e46136f8949d7e0e48 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 24 Jan 2020 16:46:43 +0100 Subject: wip implement lowering mode --- crates/ra_hir_ty/src/lower.rs | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) (limited to 'crates/ra_hir_ty/src/lower.rs') diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 3d2421223..39406d8ce 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs @@ -40,8 +40,17 @@ pub struct TyLoweringContext<'a, DB: HirDatabase> { #[derive(Clone, Debug)] pub enum ImplTraitLoweringMode { + /// `impl Trait` gets lowered into an opaque type that doesn't unify with + /// anything except itself. This is used in places where values flow 'out', + /// i.e. for arguments of the function we're currently checking, and return + /// types of functions we're calling. Opaque, + /// `impl Trait` gets lowered into a placeholder that can unify with some + /// type. This is used in places where values flow 'in', i.e. for arguments + /// of functions we're calling, and the return type of the function we're + /// currently checking. Placeholder, + /// `impl Trait` is disallowed and will be an error. Disallowed, } @@ -87,12 +96,23 @@ impl Ty { Ty::Dyn(predicates) } TypeRef::ImplTrait(bounds) => { - let self_ty = Ty::Bound(0); - let predicates = bounds - .iter() - .flat_map(|b| GenericPredicate::from_type_bound(ctx, b, self_ty.clone())) - .collect(); - Ty::Opaque(predicates) + match ctx.impl_trait_mode { + ImplTraitLoweringMode::Opaque => { + let self_ty = Ty::Bound(0); + let predicates = bounds + .iter() + .flat_map(|b| GenericPredicate::from_type_bound(ctx, b, self_ty.clone())) + .collect(); + Ty::Opaque(predicates) + }, + ImplTraitLoweringMode::Placeholder => { + todo!() + }, + ImplTraitLoweringMode::Disallowed => { + // FIXME: report error + Ty::Unknown + }, + } } TypeRef::Error => Ty::Unknown, } -- cgit v1.2.3 From 93aa166748eef9560df2435391dc3f3b53f8262d Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 24 Jan 2020 19:35:09 +0100 Subject: wip lower impl trait to type args --- crates/ra_hir_ty/src/lower.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'crates/ra_hir_ty/src/lower.rs') diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 39406d8ce..6f7681475 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs @@ -341,6 +341,7 @@ pub(super) fn substs_from_path_segment( // Self type as an implicit first type parameter, but it can't be // actually provided in the type arguments // (well, actually sometimes it can, in the form of type-relative paths: `::default()`) + // TODO handle this using type param provenance substs.push(Ty::Unknown); } if let Some(generic_args) = &segment.args_and_bindings { -- cgit v1.2.3 From 16c69374471a0072541c21a5551b4fd97f7e12ba Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 25 Jan 2020 23:38:33 +0100 Subject: Lower impl trait to variables, move away from using placeholders where they don't belong --- crates/ra_hir_ty/src/lower.rs | 263 ++++++++++++++++++++++-------------------- 1 file changed, 141 insertions(+), 122 deletions(-) (limited to 'crates/ra_hir_ty/src/lower.rs') diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 6f7681475..006101f2f 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs @@ -28,32 +28,62 @@ use crate::{ variant_data, }, FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef, - Ty, TypeCtor, TypeWalk, + Ty, TypeCtor, PolyFnSig, Binders, }; -#[derive(Clone, Debug)] +#[derive(Debug)] pub struct TyLoweringContext<'a, DB: HirDatabase> { pub db: &'a DB, pub resolver: &'a Resolver, + /// Note: Conceptually, it's thinkable that we could be in a location where + /// some type params are quantified universally (and should be represented + /// as placeholders), and others are quantified existentially (and should be + /// converted to variables). I think in practice, this isn't 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, } -#[derive(Clone, Debug)] +impl<'a, DB: HirDatabase> TyLoweringContext<'a, DB> { + pub fn new(db: &'a DB, resolver: &'a Resolver) -> Self { + let impl_trait_counter = std::cell::Cell::new(0); + let impl_trait_mode = ImplTraitLoweringMode::Disallowed; + let type_param_mode = TypeParamLoweringMode::Placeholder; + Self { db, resolver, impl_trait_mode, impl_trait_counter, type_param_mode } + } + + pub fn with_impl_trait_mode(self, impl_trait_mode: ImplTraitLoweringMode) -> Self { + Self { impl_trait_mode, ..self } + } + + pub fn with_type_param_mode(self, type_param_mode: TypeParamLoweringMode) -> Self { + Self { type_param_mode, ..self } + } +} + +#[derive(Copy, Clone, Debug)] pub enum ImplTraitLoweringMode { /// `impl Trait` gets lowered into an opaque type that doesn't unify with /// anything except itself. This is used in places where values flow 'out', /// i.e. for arguments of the function we're currently checking, and return /// types of functions we're calling. Opaque, - /// `impl Trait` gets lowered into a placeholder that can unify with some + /// `impl Trait` gets lowered into a variable that can unify with some /// type. This is used in places where values flow 'in', i.e. for arguments /// of functions we're calling, and the return type of the function we're /// currently checking. - Placeholder, + Variable, /// `impl Trait` is disallowed and will be an error. Disallowed, } +#[derive(Copy, Clone, Debug)] +pub enum TypeParamLoweringMode { + Placeholder, + Variable, +} + impl Ty { pub fn from_hir(ctx: &TyLoweringContext<'_, impl HirDatabase>, type_ref: &TypeRef) -> Self { match type_ref { @@ -101,17 +131,25 @@ impl Ty { let self_ty = Ty::Bound(0); let predicates = bounds .iter() - .flat_map(|b| GenericPredicate::from_type_bound(ctx, b, self_ty.clone())) + .flat_map(|b| { + GenericPredicate::from_type_bound(ctx, b, self_ty.clone()) + }) .collect(); Ty::Opaque(predicates) - }, - ImplTraitLoweringMode::Placeholder => { - todo!() - }, + } + ImplTraitLoweringMode::Variable => { + let idx = ctx.impl_trait_counter.get(); + ctx.impl_trait_counter.set(idx + 1); + let generics = + generics(ctx.db, ctx.resolver.generic_def().expect("generics in scope")); + let (self_params, list_params, impl_trait_params) = generics.provenance_split(); + assert!((idx as usize) < impl_trait_params); + Ty::Bound(idx as u32 + self_params as u32 + list_params as u32) + } ImplTraitLoweringMode::Disallowed => { // FIXME: report error Ty::Unknown - }, + } } } TypeRef::Error => Ty::Unknown, @@ -205,12 +243,31 @@ impl Ty { let generics = generics(ctx.db, ctx.resolver.generic_def().expect("generics in scope")); let idx = generics.param_idx(param_id); - // FIXME: maybe return name in resolution? - let name = generics.param_name(param_id); - Ty::Param { idx, name } + match ctx.type_param_mode { + TypeParamLoweringMode::Placeholder => { + // FIXME: maybe return name in resolution? + let name = generics.param_name(param_id); + Ty::Param { idx, name } + }, + TypeParamLoweringMode::Variable => Ty::Bound(idx), + } } - TypeNs::SelfType(impl_id) => ctx.db.impl_self_ty(impl_id).clone(), - TypeNs::AdtSelfType(adt) => ctx.db.ty(adt.into()), + TypeNs::SelfType(impl_id) => { + let generics = generics(ctx.db, impl_id.into()); + let substs = match ctx.type_param_mode { + TypeParamLoweringMode::Placeholder => Substs::identity(&generics), + TypeParamLoweringMode::Variable => Substs::bound_vars(&generics), + }; + ctx.db.impl_self_ty(impl_id).subst(&substs) + }, + TypeNs::AdtSelfType(adt) => { + let generics = generics(ctx.db, adt.into()); + let substs = match ctx.type_param_mode { + TypeParamLoweringMode::Placeholder => Substs::identity(&generics), + TypeParamLoweringMode::Variable => Substs::bound_vars(&generics), + }; + 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()), @@ -341,7 +398,7 @@ pub(super) fn substs_from_path_segment( // Self type as an implicit first type parameter, but it can't be // actually provided in the type arguments // (well, actually sometimes it can, in the form of type-relative paths: `::default()`) - // TODO handle this using type param provenance + // TODO handle this using type param provenance (if there's a self param, and not one provided, add unknown) substs.push(Ty::Unknown); } if let Some(generic_args) = &segment.args_and_bindings { @@ -493,7 +550,7 @@ fn assoc_type_bindings_from_type_bound<'a>( } /// Build the signature of a callable item (function, struct or enum variant). -pub fn callable_item_sig(db: &impl HirDatabase, def: CallableDef) -> FnSig { +pub fn callable_item_sig(db: &impl HirDatabase, def: CallableDef) -> PolyFnSig { match def { CallableDef::FunctionId(f) => fn_sig_for_fn(db, f), CallableDef::StructId(s) => fn_sig_for_struct_constructor(db, s), @@ -513,11 +570,7 @@ pub(crate) fn field_types_query( VariantId::EnumVariantId(it) => it.parent.resolver(db), }; let mut res = ArenaMap::default(); - let ctx = TyLoweringContext { - db, - resolver: &resolver, - impl_trait_mode: ImplTraitLoweringMode::Disallowed, - }; + let ctx = TyLoweringContext::new(db, &resolver); for (field_id, field_data) in var_data.fields().iter() { res.insert(field_id, Ty::from_hir(&ctx, &field_data.type_ref)) } @@ -538,11 +591,7 @@ pub(crate) fn generic_predicates_for_param_query( param_idx: u32, ) -> Arc<[GenericPredicate]> { let resolver = def.resolver(db); - let ctx = TyLoweringContext { - db, - resolver: &resolver, - impl_trait_mode: ImplTraitLoweringMode::Disallowed, - }; + let ctx = TyLoweringContext::new(db, &resolver); resolver .where_predicates_in_scope() // we have to filter out all other predicates *first*, before attempting to lower them @@ -562,8 +611,7 @@ pub(crate) fn generic_predicates_for_param_recover( impl TraitEnvironment { pub fn lower(db: &impl HirDatabase, resolver: &Resolver) -> Arc { - let ctx = - TyLoweringContext { db, resolver, impl_trait_mode: ImplTraitLoweringMode::Disallowed }; + let ctx = TyLoweringContext::new(db, &resolver); let predicates = resolver .where_predicates_in_scope() .flat_map(|pred| GenericPredicate::from_where_predicate(&ctx, pred)) @@ -579,11 +627,7 @@ pub(crate) fn generic_predicates_query( def: GenericDefId, ) -> Arc<[GenericPredicate]> { let resolver = def.resolver(db); - let ctx = TyLoweringContext { - db, - resolver: &resolver, - impl_trait_mode: ImplTraitLoweringMode::Disallowed, - }; + let ctx = TyLoweringContext::new(db, &resolver); resolver .where_predicates_in_scope() .flat_map(|pred| GenericPredicate::from_where_predicate(&ctx, pred)) @@ -593,11 +637,7 @@ pub(crate) fn generic_predicates_query( /// Resolve the default type params from generics pub(crate) fn generic_defaults_query(db: &impl HirDatabase, def: GenericDefId) -> Substs { let resolver = def.resolver(db); - let ctx = TyLoweringContext { - db, - resolver: &resolver, - impl_trait_mode: ImplTraitLoweringMode::Disallowed, - }; + let ctx = TyLoweringContext::new(db, &resolver); let generic_params = generics(db, def.into()); let defaults = generic_params @@ -608,56 +648,46 @@ pub(crate) fn generic_defaults_query(db: &impl HirDatabase, def: GenericDefId) - Substs(defaults) } -fn fn_sig_for_fn(db: &impl HirDatabase, def: FunctionId) -> FnSig { +fn fn_sig_for_fn(db: &impl HirDatabase, def: FunctionId) -> PolyFnSig { let data = db.function_data(def); let resolver = def.resolver(db); - let ctx_params = TyLoweringContext { - db, - resolver: &resolver, - impl_trait_mode: ImplTraitLoweringMode::Placeholder, - }; + let ctx_params = TyLoweringContext::new(db, &resolver) + .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 = TyLoweringContext { - db, - resolver: &resolver, - impl_trait_mode: ImplTraitLoweringMode::Opaque, - }; + let ctx_ret = ctx_params.with_impl_trait_mode(ImplTraitLoweringMode::Opaque); let ret = Ty::from_hir(&ctx_ret, &data.ret_type); - FnSig::from_params_and_return(params, ret) + let generics = generics(db, def.into()); + let num_binders = generics.len(); + Binders::new(num_binders, FnSig::from_params_and_return(params, ret)) } /// Build the declared type of a function. This should not need to look at the /// function body. -fn type_for_fn(db: &impl HirDatabase, def: FunctionId) -> Ty { +fn type_for_fn(db: &impl HirDatabase, def: FunctionId) -> Binders { let generics = generics(db, def.into()); - let substs = Substs::identity(&generics); - Ty::apply(TypeCtor::FnDef(def.into()), substs) + let substs = Substs::bound_vars(&generics); + Binders::new(substs.len(), Ty::apply(TypeCtor::FnDef(def.into()), substs)) } /// Build the declared type of a const. -fn type_for_const(db: &impl HirDatabase, def: ConstId) -> Ty { +fn type_for_const(db: &impl HirDatabase, def: ConstId) -> Binders { let data = db.const_data(def); + let generics = generics(db, def.into()); let resolver = def.resolver(db); - let ctx = TyLoweringContext { - db, - resolver: &resolver, - impl_trait_mode: ImplTraitLoweringMode::Disallowed, - }; + let ctx = TyLoweringContext::new(db, &resolver) + .with_type_param_mode(TypeParamLoweringMode::Variable); - Ty::from_hir(&ctx, &data.type_ref) + Binders::new(generics.len(), Ty::from_hir(&ctx, &data.type_ref)) } /// Build the declared type of a static. -fn type_for_static(db: &impl HirDatabase, def: StaticId) -> Ty { +fn type_for_static(db: &impl HirDatabase, def: StaticId) -> Binders { let data = db.static_data(def); let resolver = def.resolver(db); - let ctx = TyLoweringContext { - db, - resolver: &resolver, - impl_trait_mode: ImplTraitLoweringMode::Disallowed, - }; + let ctx = TyLoweringContext::new(db, &resolver); - Ty::from_hir(&ctx, &data.type_ref) + Binders::new(0, Ty::from_hir(&ctx, &data.type_ref)) } /// Build the declared type of a static. @@ -671,79 +701,71 @@ fn type_for_builtin(def: BuiltinType) -> Ty { }) } -fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> FnSig { +fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> PolyFnSig { let struct_data = db.struct_data(def.into()); let fields = struct_data.variant_data.fields(); let resolver = def.resolver(db); - let ctx = TyLoweringContext { - db, - resolver: &resolver, - impl_trait_mode: ImplTraitLoweringMode::Disallowed, - }; + let ctx = TyLoweringContext::new(db, &resolver) + .with_type_param_mode(TypeParamLoweringMode::Variable); let params = fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::>(); let ret = type_for_adt(db, def.into()); - FnSig::from_params_and_return(params, ret) + Binders::new(ret.num_binders, FnSig::from_params_and_return(params, ret.value)) } /// Build the type of a tuple struct constructor. -fn type_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> Ty { +fn type_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> Binders { let struct_data = db.struct_data(def.into()); if struct_data.variant_data.is_unit() { return type_for_adt(db, def.into()); // Unit struct } let generics = generics(db, def.into()); - let substs = Substs::identity(&generics); - Ty::apply(TypeCtor::FnDef(def.into()), substs) + let substs = Substs::bound_vars(&generics); + Binders::new(substs.len(), Ty::apply(TypeCtor::FnDef(def.into()), substs)) } -fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> FnSig { +fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> PolyFnSig { let enum_data = db.enum_data(def.parent); let var_data = &enum_data.variants[def.local_id]; let fields = var_data.variant_data.fields(); let resolver = def.parent.resolver(db); - let ctx = TyLoweringContext { - db, - resolver: &resolver, - impl_trait_mode: ImplTraitLoweringMode::Disallowed, - }; + let ctx = TyLoweringContext::new(db, &resolver); let params = fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::>(); let generics = generics(db, def.parent.into()); - let substs = Substs::identity(&generics); + let substs = Substs::bound_vars(&generics); let ret = type_for_adt(db, def.parent.into()).subst(&substs); - FnSig::from_params_and_return(params, ret) + let num_binders = generics.len(); + Binders::new(num_binders, FnSig::from_params_and_return(params, ret)) } /// Build the type of a tuple enum variant constructor. -fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> Ty { +fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> Binders { let enum_data = db.enum_data(def.parent); let var_data = &enum_data.variants[def.local_id].variant_data; if var_data.is_unit() { return type_for_adt(db, def.parent.into()); // Unit variant } let generics = generics(db, def.parent.into()); - let substs = Substs::identity(&generics); - Ty::apply(TypeCtor::FnDef(EnumVariantId::from(def).into()), substs) + let substs = Substs::bound_vars(&generics); + Binders::new(substs.len(), Ty::apply(TypeCtor::FnDef(EnumVariantId::from(def).into()), substs)) } -fn type_for_adt(db: &impl HirDatabase, adt: AdtId) -> Ty { +fn type_for_adt(db: &impl HirDatabase, adt: AdtId) -> Binders { let generics = generics(db, adt.into()); - Ty::apply(TypeCtor::Adt(adt), Substs::identity(&generics)) + let substs = Substs::bound_vars(&generics); + Binders::new(substs.len(), Ty::apply(TypeCtor::Adt(adt), substs)) } -fn type_for_type_alias(db: &impl HirDatabase, t: TypeAliasId) -> Ty { +fn type_for_type_alias(db: &impl HirDatabase, t: TypeAliasId) -> Binders { let generics = generics(db, t.into()); let resolver = t.resolver(db); - let ctx = TyLoweringContext { - db, - resolver: &resolver, - impl_trait_mode: ImplTraitLoweringMode::Disallowed, - }; + let ctx = TyLoweringContext::new(db, &resolver) + .with_type_param_mode(TypeParamLoweringMode::Variable); let type_ref = &db.type_alias_data(t).type_ref; - let substs = Substs::identity(&generics); + let substs = Substs::bound_vars(&generics); let inner = Ty::from_hir(&ctx, type_ref.as_ref().unwrap_or(&TypeRef::Error)); - inner.subst(&substs) + Binders::new(substs.len(), inner) } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] @@ -797,19 +819,20 @@ impl_froms!(ValueTyDefId: FunctionId, StructId, EnumVariantId, ConstId, StaticId /// `struct Foo(usize)`, we have two types: The type of the struct itself, and /// the constructor function `(usize) -> Foo` which lives in the values /// namespace. -pub(crate) fn ty_query(db: &impl HirDatabase, def: TyDefId) -> Ty { +pub(crate) fn ty_query(db: &impl HirDatabase, def: TyDefId) -> Binders { match def { - TyDefId::BuiltinType(it) => type_for_builtin(it), + TyDefId::BuiltinType(it) => Binders::new(0, type_for_builtin(it)), TyDefId::AdtId(it) => type_for_adt(db, it), TyDefId::TypeAliasId(it) => type_for_type_alias(db, it), } } -pub(crate) fn ty_recover(_db: &impl HirDatabase, _cycle: &[String], _def: &TyDefId) -> Ty { - Ty::Unknown +pub(crate) fn ty_recover(_db: &impl HirDatabase, _cycle: &[String], _def: &TyDefId) -> Binders { + // TODO still need correct number of binders here + Binders::new(0, Ty::Unknown) } -pub(crate) fn value_ty_query(db: &impl HirDatabase, def: ValueTyDefId) -> Ty { +pub(crate) fn value_ty_query(db: &impl HirDatabase, def: ValueTyDefId) -> Binders { match def { ValueTyDefId::FunctionId(it) => type_for_fn(db, it), ValueTyDefId::StructId(it) => type_for_struct_constructor(db, it), @@ -819,34 +842,30 @@ pub(crate) fn value_ty_query(db: &impl HirDatabase, def: ValueTyDefId) -> Ty { } } -pub(crate) fn impl_self_ty_query(db: &impl HirDatabase, impl_id: ImplId) -> Ty { +pub(crate) fn impl_self_ty_query(db: &impl HirDatabase, impl_id: ImplId) -> Binders { let impl_data = db.impl_data(impl_id); let resolver = impl_id.resolver(db); - let ctx = TyLoweringContext { - db, - resolver: &resolver, - impl_trait_mode: ImplTraitLoweringMode::Disallowed, - }; - Ty::from_hir(&ctx, &impl_data.target_type) + let generics = generics(db, impl_id.into()); + let ctx = TyLoweringContext::new(db, &resolver) + .with_type_param_mode(TypeParamLoweringMode::Variable); + Binders::new(generics.len(), Ty::from_hir(&ctx, &impl_data.target_type)) } pub(crate) fn impl_self_ty_recover( - _db: &impl HirDatabase, + db: &impl HirDatabase, _cycle: &[String], - _impl_id: &ImplId, -) -> Ty { - Ty::Unknown + impl_id: &ImplId, +) -> Binders { + let generics = generics(db, (*impl_id).into()); + Binders::new(generics.len(), Ty::Unknown) } pub(crate) fn impl_trait_query(db: &impl HirDatabase, impl_id: ImplId) -> Option { let impl_data = db.impl_data(impl_id); let resolver = impl_id.resolver(db); - let ctx = TyLoweringContext { - db, - resolver: &resolver, - impl_trait_mode: ImplTraitLoweringMode::Disallowed, - }; - let self_ty = db.impl_self_ty(impl_id); + let generics = generics(db, impl_id.into()); + let ctx = TyLoweringContext::new(db, &resolver); + let self_ty = db.impl_self_ty(impl_id).subst(&Substs::identity(&generics)); let target_trait = impl_data.target_trait.as_ref()?; TraitRef::from_hir(&ctx, target_trait, Some(self_ty.clone())) } -- cgit v1.2.3 From a5554dcb17defd2cda729ce0ae732062990391db Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Wed, 29 Jan 2020 21:30:24 +0100 Subject: Fix enum constructors --- crates/ra_hir_ty/src/lower.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'crates/ra_hir_ty/src/lower.rs') diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 006101f2f..25c894c95 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs @@ -729,14 +729,12 @@ fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId let var_data = &enum_data.variants[def.local_id]; let fields = var_data.variant_data.fields(); let resolver = def.parent.resolver(db); - let ctx = TyLoweringContext::new(db, &resolver); + let ctx = TyLoweringContext::new(db, &resolver) + .with_type_param_mode(TypeParamLoweringMode::Variable); let params = fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::>(); - let generics = generics(db, def.parent.into()); - let substs = Substs::bound_vars(&generics); - let ret = type_for_adt(db, def.parent.into()).subst(&substs); - let num_binders = generics.len(); - Binders::new(num_binders, FnSig::from_params_and_return(params, ret)) + let ret = type_for_adt(db, def.parent.into()); + Binders::new(ret.num_binders, FnSig::from_params_and_return(params, ret.value)) } /// Build the type of a tuple enum variant constructor. -- cgit v1.2.3 From a9430865b319ab2fc28602fe98df21146e54b7bf Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Wed, 29 Jan 2020 22:32:37 +0100 Subject: Fix crash --- crates/ra_hir_ty/src/lower.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'crates/ra_hir_ty/src/lower.rs') diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 25c894c95..459b96280 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs @@ -140,10 +140,13 @@ impl Ty { ImplTraitLoweringMode::Variable => { let idx = ctx.impl_trait_counter.get(); ctx.impl_trait_counter.set(idx + 1); - let generics = - generics(ctx.db, ctx.resolver.generic_def().expect("generics in scope")); - let (self_params, list_params, impl_trait_params) = generics.provenance_split(); - assert!((idx as usize) < impl_trait_params); + let (self_params, list_params, _impl_trait_params) = if let Some(def) = ctx.resolver.generic_def() { + let generics = generics(ctx.db, def); + generics.provenance_split() + } else { + (0, 0, 0) + }; + // assert!((idx as usize) < impl_trait_params); // TODO return position impl trait Ty::Bound(idx as u32 + self_params as u32 + list_params as u32) } ImplTraitLoweringMode::Disallowed => { -- cgit v1.2.3 From dbc14f9d570e5bc1ddae05e9ccd8f163082b3cac Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 31 Jan 2020 15:17:48 +0100 Subject: First stab at desugaring bounds for APIT --- crates/ra_hir_ty/src/lower.rs | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) (limited to 'crates/ra_hir_ty/src/lower.rs') diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 459b96280..f1a11e073 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs @@ -10,7 +10,7 @@ use std::sync::Arc; use hir_def::{ builtin_type::BuiltinType, - generics::WherePredicate, + generics::{WherePredicateTarget, WherePredicate}, path::{GenericArg, Path, PathSegment, PathSegments}, resolver::{HasResolver, Resolver, TypeNs}, type_ref::{TypeBound, TypeRef}, @@ -505,7 +505,22 @@ impl GenericPredicate { ctx: &'a TyLoweringContext<'a, impl HirDatabase>, where_predicate: &'a WherePredicate, ) -> impl Iterator + 'a { - let self_ty = Ty::from_hir(ctx, &where_predicate.type_ref); + let self_ty = match &where_predicate.target { + WherePredicateTarget::TypeRef(type_ref) => Ty::from_hir(ctx, type_ref), + WherePredicateTarget::TypeParam(param_id) => { + let generic_def = ctx.resolver.generic_def().expect("generics in scope"); + let generics = generics(ctx.db, generic_def); + let param_id = hir_def::TypeParamId { parent: generic_def, local_id: *param_id }; + let idx = generics.param_idx(param_id); + match ctx.type_param_mode { + TypeParamLoweringMode::Placeholder => { + let name = generics.param_name(param_id); + Ty::Param { idx, name } + }, + TypeParamLoweringMode::Variable => Ty::Bound(idx), + } + }, + }; GenericPredicate::from_type_bound(ctx, &where_predicate.bound, self_ty) } @@ -595,10 +610,18 @@ pub(crate) fn generic_predicates_for_param_query( ) -> Arc<[GenericPredicate]> { let resolver = def.resolver(db); let ctx = TyLoweringContext::new(db, &resolver); + let generics = generics(db, def); resolver .where_predicates_in_scope() // we have to filter out all other predicates *first*, before attempting to lower them - .filter(|pred| Ty::from_hir_only_param(&ctx, &pred.type_ref) == Some(param_idx)) + .filter(|pred| match &pred.target { + WherePredicateTarget::TypeRef(type_ref) => Ty::from_hir_only_param(&ctx, type_ref) == Some(param_idx), + WherePredicateTarget::TypeParam(local_id) => { + let param_id = hir_def::TypeParamId { parent: def, local_id: *local_id }; + let idx = generics.param_idx(param_id); + idx == param_idx + } + }) .flat_map(|pred| GenericPredicate::from_where_predicate(&ctx, pred)) .collect() } -- cgit v1.2.3 From 33aa2f8e4f2b9c7c3a6b28427cb6d6f2aef7b802 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 31 Jan 2020 15:57:44 +0100 Subject: Fix assoc type selection --- crates/ra_hir_ty/src/lower.rs | 69 +++++++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 29 deletions(-) (limited to 'crates/ra_hir_ty/src/lower.rs') diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index f1a11e073..5138019c7 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs @@ -10,7 +10,7 @@ use std::sync::Arc; use hir_def::{ builtin_type::BuiltinType, - generics::{WherePredicateTarget, WherePredicate}, + generics::{WherePredicate, WherePredicateTarget}, path::{GenericArg, Path, PathSegment, PathSegments}, resolver::{HasResolver, Resolver, TypeNs}, type_ref::{TypeBound, TypeRef}, @@ -27,8 +27,8 @@ use crate::{ all_super_traits, associated_type_by_name_including_super_traits, generics, make_mut_slice, variant_data, }, - FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef, - Ty, TypeCtor, PolyFnSig, Binders, + Binders, FnSig, GenericPredicate, PolyFnSig, ProjectionPredicate, ProjectionTy, Substs, + TraitEnvironment, TraitRef, Ty, TypeCtor, }; #[derive(Debug)] @@ -62,7 +62,7 @@ impl<'a, DB: HirDatabase> TyLoweringContext<'a, DB> { } } -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum ImplTraitLoweringMode { /// `impl Trait` gets lowered into an opaque type that doesn't unify with /// anything except itself. This is used in places where values flow 'out', @@ -78,7 +78,7 @@ pub enum ImplTraitLoweringMode { Disallowed, } -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum TypeParamLoweringMode { Placeholder, Variable, @@ -140,12 +140,13 @@ impl Ty { ImplTraitLoweringMode::Variable => { let idx = ctx.impl_trait_counter.get(); ctx.impl_trait_counter.set(idx + 1); - let (self_params, list_params, _impl_trait_params) = if let Some(def) = ctx.resolver.generic_def() { - let generics = generics(ctx.db, def); - generics.provenance_split() - } else { - (0, 0, 0) - }; + let (self_params, list_params, _impl_trait_params) = + if let Some(def) = ctx.resolver.generic_def() { + let generics = generics(ctx.db, def); + generics.provenance_split() + } else { + (0, 0, 0) + }; // assert!((idx as usize) < impl_trait_params); // TODO return position impl trait Ty::Bound(idx as u32 + self_params as u32 + list_params as u32) } @@ -251,7 +252,7 @@ impl Ty { // FIXME: maybe return name in resolution? let name = generics.param_name(param_id); Ty::Param { idx, name } - }, + } TypeParamLoweringMode::Variable => Ty::Bound(idx), } } @@ -262,7 +263,7 @@ impl Ty { TypeParamLoweringMode::Variable => Substs::bound_vars(&generics), }; ctx.db.impl_self_ty(impl_id).subst(&substs) - }, + } TypeNs::AdtSelfType(adt) => { let generics = generics(ctx.db, adt.into()); let substs = match ctx.type_param_mode { @@ -270,7 +271,7 @@ impl Ty { TypeParamLoweringMode::Variable => Substs::bound_vars(&generics), }; 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()), @@ -309,7 +310,8 @@ impl Ty { segment: PathSegment<'_>, ) -> Ty { let param_idx = match self_ty { - Ty::Param { idx, .. } => idx, + Ty::Param { idx, .. } if ctx.type_param_mode == TypeParamLoweringMode::Placeholder => idx, + Ty::Bound(idx) if ctx.type_param_mode == TypeParamLoweringMode::Variable => idx, _ => return Ty::Unknown, // Error: Ambiguous associated type }; let def = match ctx.resolver.generic_def() { @@ -318,7 +320,14 @@ impl Ty { }; let predicates = ctx.db.generic_predicates_for_param(def.into(), param_idx); let traits_from_env = predicates.iter().filter_map(|pred| match pred { - GenericPredicate::Implemented(tr) if tr.self_ty() == &self_ty => Some(tr.trait_), + GenericPredicate::Implemented(tr) => { + if let Ty::Param { idx, .. } = tr.self_ty() { + if *idx == param_idx { + return Some(tr.trait_); + } + } + None + } _ => None, }); let traits = traits_from_env.flat_map(|t| all_super_traits(ctx.db, t)); @@ -516,10 +525,10 @@ impl GenericPredicate { TypeParamLoweringMode::Placeholder => { let name = generics.param_name(param_id); Ty::Param { idx, name } - }, + } TypeParamLoweringMode::Variable => Ty::Bound(idx), } - }, + } }; GenericPredicate::from_type_bound(ctx, &where_predicate.bound, self_ty) } @@ -615,7 +624,9 @@ pub(crate) fn generic_predicates_for_param_query( .where_predicates_in_scope() // we have to filter out all other predicates *first*, before attempting to lower them .filter(|pred| match &pred.target { - WherePredicateTarget::TypeRef(type_ref) => Ty::from_hir_only_param(&ctx, type_ref) == Some(param_idx), + WherePredicateTarget::TypeRef(type_ref) => { + Ty::from_hir_only_param(&ctx, type_ref) == Some(param_idx) + } WherePredicateTarget::TypeParam(local_id) => { let param_id = hir_def::TypeParamId { parent: def, local_id: *local_id }; let idx = generics.param_idx(param_id); @@ -701,8 +712,8 @@ fn type_for_const(db: &impl HirDatabase, def: ConstId) -> Binders { let data = db.const_data(def); let generics = generics(db, def.into()); let resolver = def.resolver(db); - let ctx = TyLoweringContext::new(db, &resolver) - .with_type_param_mode(TypeParamLoweringMode::Variable); + let ctx = + TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); Binders::new(generics.len(), Ty::from_hir(&ctx, &data.type_ref)) } @@ -731,8 +742,8 @@ fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> PolyFn let struct_data = db.struct_data(def.into()); let fields = struct_data.variant_data.fields(); let resolver = def.resolver(db); - let ctx = TyLoweringContext::new(db, &resolver) - .with_type_param_mode(TypeParamLoweringMode::Variable); + let ctx = + TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); let params = fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::>(); let ret = type_for_adt(db, def.into()); @@ -755,8 +766,8 @@ fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId let var_data = &enum_data.variants[def.local_id]; let fields = var_data.variant_data.fields(); let resolver = def.parent.resolver(db); - let ctx = TyLoweringContext::new(db, &resolver) - .with_type_param_mode(TypeParamLoweringMode::Variable); + let ctx = + TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); let params = fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::>(); let ret = type_for_adt(db, def.parent.into()); @@ -784,8 +795,8 @@ fn type_for_adt(db: &impl HirDatabase, adt: AdtId) -> Binders { fn type_for_type_alias(db: &impl HirDatabase, t: TypeAliasId) -> Binders { let generics = generics(db, t.into()); let resolver = t.resolver(db); - let ctx = TyLoweringContext::new(db, &resolver) - .with_type_param_mode(TypeParamLoweringMode::Variable); + let ctx = + TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); let type_ref = &db.type_alias_data(t).type_ref; let substs = Substs::bound_vars(&generics); let inner = Ty::from_hir(&ctx, type_ref.as_ref().unwrap_or(&TypeRef::Error)); @@ -870,8 +881,8 @@ pub(crate) fn impl_self_ty_query(db: &impl HirDatabase, impl_id: ImplId) -> Bind let impl_data = db.impl_data(impl_id); let resolver = impl_id.resolver(db); let generics = generics(db, impl_id.into()); - let ctx = TyLoweringContext::new(db, &resolver) - .with_type_param_mode(TypeParamLoweringMode::Variable); + let ctx = + TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); Binders::new(generics.len(), Ty::from_hir(&ctx, &impl_data.target_type)) } -- cgit v1.2.3 From f8b7b64bce772f21124b4790538ca97418cc23ca Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 31 Jan 2020 16:05:58 +0100 Subject: WIP use params for APIT --- crates/ra_hir_ty/src/lower.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'crates/ra_hir_ty/src/lower.rs') diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 5138019c7..88d962b47 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs @@ -30,6 +30,7 @@ use crate::{ Binders, FnSig, GenericPredicate, PolyFnSig, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, }; +use hir_expand::name::Name; #[derive(Debug)] pub struct TyLoweringContext<'a, DB: HirDatabase> { @@ -69,6 +70,10 @@ pub enum ImplTraitLoweringMode { /// i.e. for arguments of the function we're currently checking, and return /// types of functions we're calling. Opaque, + /// `impl Trait` gets lowered into a type variable. Used for argument + /// position impl Trait currently, since it allows us to support that + /// without Chalk. + Param, /// `impl Trait` gets lowered into a variable that can unify with some /// type. This is used in places where values flow 'in', i.e. for arguments /// of functions we're calling, and the return type of the function we're @@ -137,6 +142,11 @@ impl Ty { .collect(); Ty::Opaque(predicates) } + ImplTraitLoweringMode::Param => { + let idx = ctx.impl_trait_counter.get(); + ctx.impl_trait_counter.set(idx + 1); + Ty::Param { idx: idx as u32, name: Name::missing() } + } ImplTraitLoweringMode::Variable => { let idx = ctx.impl_trait_counter.get(); ctx.impl_trait_counter.set(idx + 1); -- cgit v1.2.3 From ed25cf70d5e0df9c7a33deb503ea14c2d97bd7a7 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 31 Jan 2020 16:52:43 +0100 Subject: Change Ty::Param to contain param ID --- crates/ra_hir_ty/src/lower.rs | 108 +++++++++++++++++++++++------------------- 1 file changed, 59 insertions(+), 49 deletions(-) (limited to 'crates/ra_hir_ty/src/lower.rs') diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 88d962b47..d60b59433 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs @@ -30,7 +30,7 @@ use crate::{ Binders, FnSig, GenericPredicate, PolyFnSig, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, }; -use hir_expand::name::Name; +use hir_def::TypeParamId; #[derive(Debug)] pub struct TyLoweringContext<'a, DB: HirDatabase> { @@ -145,7 +145,16 @@ impl Ty { ImplTraitLoweringMode::Param => { let idx = ctx.impl_trait_counter.get(); ctx.impl_trait_counter.set(idx + 1); - Ty::Param { idx: idx as u32, name: Name::missing() } + if let Some(def) = ctx.resolver.generic_def() { + let generics = generics(ctx.db, def); + let param = generics + .iter() + .nth(idx as usize) + .map_or(Ty::Unknown, |(id, _)| Ty::Param(id)); + param + } else { + Ty::Unknown + } } ImplTraitLoweringMode::Variable => { let idx = ctx.impl_trait_counter.get(); @@ -176,7 +185,7 @@ impl Ty { fn from_hir_only_param( ctx: &TyLoweringContext<'_, impl HirDatabase>, type_ref: &TypeRef, - ) -> Option { + ) -> Option { let path = match type_ref { TypeRef::Path(path) => path, _ => return None, @@ -192,9 +201,7 @@ impl Ty { _ => return None, }; if let TypeNs::GenericParam(param_id) = resolution { - let generics = generics(ctx.db, ctx.resolver.generic_def().expect("generics in scope")); - let idx = generics.param_idx(param_id); - Some(idx) + Some(param_id) } else { None } @@ -256,20 +263,18 @@ impl Ty { TypeNs::GenericParam(param_id) => { let generics = generics(ctx.db, ctx.resolver.generic_def().expect("generics in scope")); - let idx = generics.param_idx(param_id); match ctx.type_param_mode { - TypeParamLoweringMode::Placeholder => { - // FIXME: maybe return name in resolution? - let name = generics.param_name(param_id); - Ty::Param { idx, name } + TypeParamLoweringMode::Placeholder => Ty::Param(param_id), + TypeParamLoweringMode::Variable => { + let idx = generics.param_idx(param_id).expect("matching generics"); + Ty::Bound(idx) } - TypeParamLoweringMode::Variable => Ty::Bound(idx), } } TypeNs::SelfType(impl_id) => { let generics = generics(ctx.db, impl_id.into()); let substs = match ctx.type_param_mode { - TypeParamLoweringMode::Placeholder => Substs::identity(&generics), + TypeParamLoweringMode::Placeholder => Substs::type_params(&generics), TypeParamLoweringMode::Variable => Substs::bound_vars(&generics), }; ctx.db.impl_self_ty(impl_id).subst(&substs) @@ -277,7 +282,7 @@ impl Ty { TypeNs::AdtSelfType(adt) => { let generics = generics(ctx.db, adt.into()); let substs = match ctx.type_param_mode { - TypeParamLoweringMode::Placeholder => Substs::identity(&generics), + TypeParamLoweringMode::Placeholder => Substs::type_params(&generics), TypeParamLoweringMode::Variable => Substs::bound_vars(&generics), }; ctx.db.ty(adt.into()).subst(&substs) @@ -319,20 +324,28 @@ impl Ty { self_ty: Ty, segment: PathSegment<'_>, ) -> Ty { - let param_idx = match self_ty { - Ty::Param { idx, .. } if ctx.type_param_mode == TypeParamLoweringMode::Placeholder => idx, - Ty::Bound(idx) if ctx.type_param_mode == TypeParamLoweringMode::Variable => idx, - _ => return Ty::Unknown, // Error: Ambiguous associated type - }; let def = match ctx.resolver.generic_def() { Some(def) => def, None => return Ty::Unknown, // this can't actually happen }; - let predicates = ctx.db.generic_predicates_for_param(def.into(), param_idx); + let param_id = match self_ty { + Ty::Param(id) if ctx.type_param_mode == TypeParamLoweringMode::Placeholder => id, + Ty::Bound(idx) if ctx.type_param_mode == TypeParamLoweringMode::Variable => { + let generics = generics(ctx.db, def); + let param_id = if let Some((id, _)) = generics.iter().nth(idx as usize) { + id + } else { + return Ty::Unknown; + }; + param_id + }, + _ => return Ty::Unknown, // Error: Ambiguous associated type + }; + let predicates = ctx.db.generic_predicates_for_param(param_id); let traits_from_env = predicates.iter().filter_map(|pred| match pred { GenericPredicate::Implemented(tr) => { - if let Ty::Param { idx, .. } = tr.self_ty() { - if *idx == param_idx { + if let Ty::Param(id) = tr.self_ty() { + if *id == param_id { return Some(tr.trait_); } } @@ -530,13 +543,12 @@ impl GenericPredicate { let generic_def = ctx.resolver.generic_def().expect("generics in scope"); let generics = generics(ctx.db, generic_def); let param_id = hir_def::TypeParamId { parent: generic_def, local_id: *param_id }; - let idx = generics.param_idx(param_id); match ctx.type_param_mode { - TypeParamLoweringMode::Placeholder => { - let name = generics.param_name(param_id); - Ty::Param { idx, name } + TypeParamLoweringMode::Placeholder => Ty::Param(param_id), + TypeParamLoweringMode::Variable => { + let idx = generics.param_idx(param_id).expect("matching generics"); + Ty::Bound(idx) } - TypeParamLoweringMode::Variable => Ty::Bound(idx), } } }; @@ -599,17 +611,19 @@ pub fn callable_item_sig(db: &impl HirDatabase, def: CallableDef) -> PolyFnSig { pub(crate) fn field_types_query( db: &impl HirDatabase, variant_id: VariantId, -) -> Arc> { +) -> Arc>> { let var_data = variant_data(db, variant_id); - let resolver = match variant_id { - VariantId::StructId(it) => it.resolver(db), - VariantId::UnionId(it) => it.resolver(db), - VariantId::EnumVariantId(it) => it.parent.resolver(db), + let (resolver, def): (_, GenericDefId) = match variant_id { + VariantId::StructId(it) => (it.resolver(db), it.into()), + VariantId::UnionId(it) => (it.resolver(db), it.into()), + VariantId::EnumVariantId(it) => (it.parent.resolver(db), it.parent.into()), }; + let generics = generics(db, def); let mut res = ArenaMap::default(); - let ctx = TyLoweringContext::new(db, &resolver); + let ctx = TyLoweringContext::new(db, &resolver) + .with_type_param_mode(TypeParamLoweringMode::Variable); for (field_id, field_data) in var_data.fields().iter() { - res.insert(field_id, Ty::from_hir(&ctx, &field_data.type_ref)) + res.insert(field_id, Binders::new(generics.len(), Ty::from_hir(&ctx, &field_data.type_ref))) } Arc::new(res) } @@ -624,23 +638,20 @@ pub(crate) fn field_types_query( /// these are fine: `T: Foo, U: Foo<()>`. pub(crate) fn generic_predicates_for_param_query( db: &impl HirDatabase, - def: GenericDefId, - param_idx: u32, + param_id: TypeParamId, ) -> Arc<[GenericPredicate]> { - let resolver = def.resolver(db); + let resolver = param_id.parent.resolver(db); let ctx = TyLoweringContext::new(db, &resolver); - let generics = generics(db, def); + // let generics = generics(db, def); resolver .where_predicates_in_scope() // we have to filter out all other predicates *first*, before attempting to lower them .filter(|pred| match &pred.target { WherePredicateTarget::TypeRef(type_ref) => { - Ty::from_hir_only_param(&ctx, type_ref) == Some(param_idx) + Ty::from_hir_only_param(&ctx, type_ref) == Some(param_id) } WherePredicateTarget::TypeParam(local_id) => { - let param_id = hir_def::TypeParamId { parent: def, local_id: *local_id }; - let idx = generics.param_idx(param_id); - idx == param_idx + *local_id == param_id.local_id } }) .flat_map(|pred| GenericPredicate::from_where_predicate(&ctx, pred)) @@ -650,8 +661,7 @@ pub(crate) fn generic_predicates_for_param_query( pub(crate) fn generic_predicates_for_param_recover( _db: &impl HirDatabase, _cycle: &[String], - _def: &GenericDefId, - _param_idx: &u32, + _param_id: &TypeParamId, ) -> Arc<[GenericPredicate]> { Arc::new([]) } @@ -905,12 +915,12 @@ pub(crate) fn impl_self_ty_recover( Binders::new(generics.len(), Ty::Unknown) } -pub(crate) fn impl_trait_query(db: &impl HirDatabase, impl_id: ImplId) -> Option { +pub(crate) fn impl_trait_query(db: &impl HirDatabase, impl_id: ImplId) -> Option> { let impl_data = db.impl_data(impl_id); let resolver = impl_id.resolver(db); - let generics = generics(db, impl_id.into()); - let ctx = TyLoweringContext::new(db, &resolver); - let self_ty = db.impl_self_ty(impl_id).subst(&Substs::identity(&generics)); + let ctx = TyLoweringContext::new(db, &resolver) + .with_type_param_mode(TypeParamLoweringMode::Variable); + let self_ty = db.impl_self_ty(impl_id); let target_trait = impl_data.target_trait.as_ref()?; - TraitRef::from_hir(&ctx, target_trait, Some(self_ty.clone())) + Some(Binders::new(self_ty.num_binders, TraitRef::from_hir(&ctx, target_trait, Some(self_ty.value.clone()))?)) } -- cgit v1.2.3 From c6654fd4a70ef149a842e42dc9ef86838148fbe7 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 1 Feb 2020 17:45:43 +0100 Subject: Fix APIT --- crates/ra_hir_ty/src/lower.rs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'crates/ra_hir_ty/src/lower.rs') diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index d60b59433..42367b181 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs @@ -31,6 +31,7 @@ use crate::{ TraitEnvironment, TraitRef, Ty, TypeCtor, }; use hir_def::TypeParamId; +use hir_def::generics::TypeParamProvenance; #[derive(Debug)] pub struct TyLoweringContext<'a, DB: HirDatabase> { @@ -149,6 +150,7 @@ impl Ty { let generics = generics(ctx.db, def); let param = generics .iter() + .filter(|(_, data)| data.provenance == TypeParamProvenance::ArgumentImplTrait) .nth(idx as usize) .map_or(Ty::Unknown, |(id, _)| Ty::Param(id)); param -- cgit v1.2.3 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/lower.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'crates/ra_hir_ty/src/lower.rs') 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> { -- cgit v1.2.3 From 86348f5994cdc3831edf3a5582d6d9d576fd1d80 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 2 Feb 2020 13:43:04 +0100 Subject: Comment fixes / todos --- crates/ra_hir_ty/src/lower.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'crates/ra_hir_ty/src/lower.rs') diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index e375c4847..76e2fbabf 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs @@ -37,10 +37,9 @@ pub struct TyLoweringContext<'a, DB: HirDatabase> { pub db: &'a DB, pub resolver: &'a Resolver, /// Note: Conceptually, it's thinkable that we could be in a location where - /// some type params are quantified universally (and should be represented - /// as placeholders), and others are quantified existentially (and should be - /// converted to variables). I think in practice, this isn't possible - /// currently, so this should be fine for now. + /// some type params should be represented as placeholders, and others + /// should be converted to variables. I think in practice, this isn't + /// 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, @@ -71,8 +70,8 @@ pub enum ImplTraitLoweringMode { /// types of functions we're calling. Opaque, /// `impl Trait` gets lowered into a type variable. Used for argument - /// position impl Trait currently, since it allows us to support that - /// without Chalk. + /// position impl Trait when inside the respective function, since it allows + /// us to support that without Chalk. Param, /// `impl Trait` gets lowered into a variable that can unify with some /// type. This is used in places where values flow 'in', i.e. for arguments -- cgit v1.2.3 From a3d8cffde39bfb0d50b87a8ded5e0534adec4cd5 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 2 Feb 2020 17:11:54 +0100 Subject: Use variables in predicates as well --- crates/ra_hir_ty/src/lower.rs | 73 ++++++++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 32 deletions(-) (limited to 'crates/ra_hir_ty/src/lower.rs') diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 76e2fbabf..847111748 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs @@ -10,13 +10,13 @@ use std::sync::Arc; use hir_def::{ builtin_type::BuiltinType, - generics::{WherePredicate, WherePredicateTarget, TypeParamProvenance}, + generics::{TypeParamProvenance, WherePredicate, WherePredicateTarget}, 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 + LocalStructFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId, + VariantId, }; use ra_arena::map::ArenaMap; use ra_db::CrateId; @@ -148,7 +148,9 @@ impl Ty { let generics = generics(ctx.db, def); let param = generics .iter() - .filter(|(_, data)| data.provenance == TypeParamProvenance::ArgumentImplTrait) + .filter(|(_, data)| { + data.provenance == TypeParamProvenance::ArgumentImplTrait + }) .nth(idx as usize) .map_or(Ty::Unknown, |(id, _)| Ty::Param(id)); param @@ -338,19 +340,12 @@ impl Ty { return Ty::Unknown; }; param_id - }, + } _ => return Ty::Unknown, // Error: Ambiguous associated type }; let predicates = ctx.db.generic_predicates_for_param(param_id); - let traits_from_env = predicates.iter().filter_map(|pred| match pred { - GenericPredicate::Implemented(tr) => { - if let Ty::Param(id) = tr.self_ty() { - if *id == param_id { - return Some(tr.trait_); - } - } - None - } + let traits_from_env = predicates.iter().filter_map(|pred| match &pred.value { + GenericPredicate::Implemented(tr) => Some(tr.trait_), _ => None, }); let traits = traits_from_env.flat_map(|t| all_super_traits(ctx.db, t)); @@ -620,8 +615,8 @@ pub(crate) fn field_types_query( }; let generics = generics(db, def); let mut res = ArenaMap::default(); - let ctx = TyLoweringContext::new(db, &resolver) - .with_type_param_mode(TypeParamLoweringMode::Variable); + let ctx = + TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); for (field_id, field_data) in var_data.fields().iter() { res.insert(field_id, Binders::new(generics.len(), Ty::from_hir(&ctx, &field_data.type_ref))) } @@ -639,10 +634,11 @@ pub(crate) fn field_types_query( pub(crate) fn generic_predicates_for_param_query( db: &impl HirDatabase, param_id: TypeParamId, -) -> Arc<[GenericPredicate]> { +) -> Arc<[Binders]> { let resolver = param_id.parent.resolver(db); - let ctx = TyLoweringContext::new(db, &resolver); - // let generics = generics(db, def); + let ctx = + TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); + let generics = generics(db, param_id.parent); resolver .where_predicates_in_scope() // we have to filter out all other predicates *first*, before attempting to lower them @@ -650,11 +646,12 @@ pub(crate) fn generic_predicates_for_param_query( WherePredicateTarget::TypeRef(type_ref) => { Ty::from_hir_only_param(&ctx, type_ref) == Some(param_id) } - WherePredicateTarget::TypeParam(local_id) => { - *local_id == param_id.local_id - } + WherePredicateTarget::TypeParam(local_id) => *local_id == param_id.local_id, + }) + .flat_map(|pred| { + GenericPredicate::from_where_predicate(&ctx, pred) + .map(|p| Binders::new(generics.len(), p)) }) - .flat_map(|pred| GenericPredicate::from_where_predicate(&ctx, pred)) .collect() } @@ -662,13 +659,14 @@ pub(crate) fn generic_predicates_for_param_recover( _db: &impl HirDatabase, _cycle: &[String], _param_id: &TypeParamId, -) -> Arc<[GenericPredicate]> { +) -> Arc<[Binders]> { Arc::new([]) } impl TraitEnvironment { pub fn lower(db: &impl HirDatabase, resolver: &Resolver) -> Arc { - let ctx = TyLoweringContext::new(db, &resolver); + let ctx = TyLoweringContext::new(db, &resolver) + .with_type_param_mode(TypeParamLoweringMode::Placeholder); let predicates = resolver .where_predicates_in_scope() .flat_map(|pred| GenericPredicate::from_where_predicate(&ctx, pred)) @@ -682,12 +680,17 @@ impl TraitEnvironment { pub(crate) fn generic_predicates_query( db: &impl HirDatabase, def: GenericDefId, -) -> Arc<[GenericPredicate]> { +) -> Arc<[Binders]> { let resolver = def.resolver(db); - let ctx = TyLoweringContext::new(db, &resolver); + let ctx = + TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); + let generics = generics(db, def); resolver .where_predicates_in_scope() - .flat_map(|pred| GenericPredicate::from_where_predicate(&ctx, pred)) + .flat_map(|pred| { + GenericPredicate::from_where_predicate(&ctx, pred) + .map(|p| Binders::new(generics.len(), p)) + }) .collect() } @@ -915,12 +918,18 @@ pub(crate) fn impl_self_ty_recover( Binders::new(generics.len(), Ty::Unknown) } -pub(crate) fn impl_trait_query(db: &impl HirDatabase, impl_id: ImplId) -> Option> { +pub(crate) fn impl_trait_query( + db: &impl HirDatabase, + impl_id: ImplId, +) -> Option> { let impl_data = db.impl_data(impl_id); let resolver = impl_id.resolver(db); - let ctx = TyLoweringContext::new(db, &resolver) - .with_type_param_mode(TypeParamLoweringMode::Variable); + let ctx = + TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); let self_ty = db.impl_self_ty(impl_id); let target_trait = impl_data.target_trait.as_ref()?; - Some(Binders::new(self_ty.num_binders, TraitRef::from_hir(&ctx, target_trait, Some(self_ty.value.clone()))?)) + Some(Binders::new( + self_ty.num_binders, + TraitRef::from_hir(&ctx, target_trait, Some(self_ty.value.clone()))?, + )) } -- cgit v1.2.3 From 0718682cffaae34e5c106c793c60f6706fc04b05 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Tue, 4 Feb 2020 21:33:03 +0100 Subject: Fix compilation of other crates --- crates/ra_hir_ty/src/lower.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'crates/ra_hir_ty/src/lower.rs') diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 847111748..0d4c075af 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs @@ -276,7 +276,7 @@ impl Ty { TypeNs::SelfType(impl_id) => { let generics = generics(ctx.db, impl_id.into()); let substs = match ctx.type_param_mode { - TypeParamLoweringMode::Placeholder => Substs::type_params(&generics), + TypeParamLoweringMode::Placeholder => Substs::type_params_for_generics(&generics), TypeParamLoweringMode::Variable => Substs::bound_vars(&generics), }; ctx.db.impl_self_ty(impl_id).subst(&substs) @@ -284,7 +284,7 @@ impl Ty { TypeNs::AdtSelfType(adt) => { let generics = generics(ctx.db, adt.into()); let substs = match ctx.type_param_mode { - TypeParamLoweringMode::Placeholder => Substs::type_params(&generics), + TypeParamLoweringMode::Placeholder => Substs::type_params_for_generics(&generics), TypeParamLoweringMode::Variable => Substs::bound_vars(&generics), }; ctx.db.ty(adt.into()).subst(&substs) -- cgit v1.2.3 From dded90a748737c3661aad043524f2248e324c867 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 7 Feb 2020 15:13:15 +0100 Subject: Formatting --- crates/ra_hir_ty/src/lower.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'crates/ra_hir_ty/src/lower.rs') diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 0d4c075af..4168e7509 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs @@ -276,7 +276,9 @@ impl Ty { TypeNs::SelfType(impl_id) => { let generics = generics(ctx.db, impl_id.into()); let substs = match ctx.type_param_mode { - TypeParamLoweringMode::Placeholder => Substs::type_params_for_generics(&generics), + TypeParamLoweringMode::Placeholder => { + Substs::type_params_for_generics(&generics) + } TypeParamLoweringMode::Variable => Substs::bound_vars(&generics), }; ctx.db.impl_self_ty(impl_id).subst(&substs) @@ -284,7 +286,9 @@ impl Ty { TypeNs::AdtSelfType(adt) => { let generics = generics(ctx.db, adt.into()); let substs = match ctx.type_param_mode { - TypeParamLoweringMode::Placeholder => Substs::type_params_for_generics(&generics), + TypeParamLoweringMode::Placeholder => { + Substs::type_params_for_generics(&generics) + } TypeParamLoweringMode::Variable => Substs::bound_vars(&generics), }; ctx.db.ty(adt.into()).subst(&substs) -- cgit v1.2.3 From 6c70619b0126bc0e40bd9df39dcd6e711cac69c5 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 7 Feb 2020 16:24:09 +0100 Subject: Deal better with implicit type parameters and argument lists --- crates/ra_hir_ty/src/lower.rs | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) (limited to 'crates/ra_hir_ty/src/lower.rs') diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 4168e7509..d2df3fe2b 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs @@ -161,15 +161,19 @@ impl Ty { ImplTraitLoweringMode::Variable => { let idx = ctx.impl_trait_counter.get(); ctx.impl_trait_counter.set(idx + 1); - let (self_params, list_params, _impl_trait_params) = + let (parent_params, self_params, list_params, _impl_trait_params) = if let Some(def) = ctx.resolver.generic_def() { let generics = generics(ctx.db, def); generics.provenance_split() } else { - (0, 0, 0) + (0, 0, 0, 0) }; - // assert!((idx as usize) < impl_trait_params); // TODO return position impl trait - Ty::Bound(idx as u32 + self_params as u32 + list_params as u32) + Ty::Bound( + idx as u32 + + parent_params as u32 + + self_params as u32 + + list_params as u32, + ) } ImplTraitLoweringMode::Disallowed => { // FIXME: report error @@ -420,26 +424,23 @@ pub(super) fn substs_from_path_segment( ctx: &TyLoweringContext<'_, impl HirDatabase>, segment: PathSegment<'_>, def_generic: Option, - add_self_param: bool, + _add_self_param: bool, ) -> Substs { let mut substs = Vec::new(); let def_generics = def_generic.map(|def| generics(ctx.db, def.into())); - let (total_len, parent_len, child_len) = def_generics.map_or((0, 0, 0), |g| g.len_split()); - substs.extend(iter::repeat(Ty::Unknown).take(parent_len)); - if add_self_param { - // FIXME this add_self_param argument is kind of a hack: Traits have the - // Self type as an implicit first type parameter, but it can't be - // actually provided in the type arguments - // (well, actually sometimes it can, in the form of type-relative paths: `::default()`) - // TODO handle this using type param provenance (if there's a self param, and not one provided, add unknown) - substs.push(Ty::Unknown); - } + let (parent_params, self_params, type_params, impl_trait_params) = + def_generics.map_or((0, 0, 0, 0), |g| g.provenance_split()); + substs.extend(iter::repeat(Ty::Unknown).take(parent_params)); if let Some(generic_args) = &segment.args_and_bindings { + if !generic_args.has_self_type { + substs.extend(iter::repeat(Ty::Unknown).take(self_params)); + } + let expected_num = + if generic_args.has_self_type { self_params + type_params } else { type_params }; + let skip = if generic_args.has_self_type && self_params == 0 { 1 } else { 0 }; // if args are provided, it should be all of them, but we can't rely on that - let self_param_correction = if add_self_param { 1 } else { 0 }; - let child_len = child_len - self_param_correction; - for arg in generic_args.args.iter().take(child_len) { + for arg in generic_args.args.iter().skip(skip).take(expected_num) { match arg { GenericArg::Type(type_ref) => { let ty = Ty::from_hir(ctx, type_ref); @@ -448,9 +449,9 @@ pub(super) fn substs_from_path_segment( } } } + let total_len = parent_params + self_params + type_params + impl_trait_params; // add placeholders for args that were not provided - let supplied_params = substs.len(); - for _ in supplied_params..total_len { + for _ in substs.len()..total_len { substs.push(Ty::Unknown); } assert_eq!(substs.len(), total_len); -- cgit v1.2.3 From 9d6061f3bb935c914a6d58df803dd42770f2f7e2 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 7 Feb 2020 18:17:23 +0100 Subject: Fix some TODOs --- crates/ra_hir_ty/src/lower.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'crates/ra_hir_ty/src/lower.rs') diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index d2df3fe2b..c68c5852b 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs @@ -890,9 +890,13 @@ pub(crate) fn ty_query(db: &impl HirDatabase, def: TyDefId) -> Binders { } } -pub(crate) fn ty_recover(_db: &impl HirDatabase, _cycle: &[String], _def: &TyDefId) -> Binders { - // TODO still need correct number of binders here - Binders::new(0, Ty::Unknown) +pub(crate) fn ty_recover(db: &impl HirDatabase, _cycle: &[String], def: &TyDefId) -> Binders { + let num_binders = match *def { + TyDefId::BuiltinType(_) => 0, + TyDefId::AdtId(it) => generics(db, it.into()).len(), + TyDefId::TypeAliasId(it) => generics(db, it.into()).len(), + }; + Binders::new(num_binders, Ty::Unknown) } pub(crate) fn value_ty_query(db: &impl HirDatabase, def: ValueTyDefId) -> Binders { -- cgit v1.2.3