From 3743ede404d38586db9d7febca14b8bebcbbe0ef Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 13 Mar 2021 22:44:36 +0100 Subject: Move type lowering methods to TyLoweringContext --- crates/hir_ty/src/infer.rs | 10 +- crates/hir_ty/src/infer/path.rs | 10 +- crates/hir_ty/src/lower.rs | 510 ++++++++++++++++++-------------------- crates/hir_ty/src/traits/chalk.rs | 2 +- 4 files changed, 246 insertions(+), 286 deletions(-) (limited to 'crates/hir_ty/src') diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index bc52f447d..8cf59821f 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs @@ -294,7 +294,7 @@ impl<'a> InferenceContext<'a> { // FIXME use right resolver for block let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver) .with_impl_trait_mode(impl_trait_mode); - let ty = Ty::from_hir(&ctx, type_ref); + let ty = ctx.lower_ty(type_ref); let ty = self.insert_type_vars(ty); self.normalize_associated_types_in(ty) } @@ -437,19 +437,19 @@ impl<'a> InferenceContext<'a> { }; return match resolution { TypeNs::AdtId(AdtId::StructId(strukt)) => { - let substs = Ty::substs_from_path(&ctx, path, strukt.into(), true); + let substs = ctx.substs_from_path(path, strukt.into(), true); let ty = self.db.ty(strukt.into()); let ty = self.insert_type_vars(ty.subst(&substs)); forbid_unresolved_segments((ty, Some(strukt.into())), unresolved) } TypeNs::AdtId(AdtId::UnionId(u)) => { - let substs = Ty::substs_from_path(&ctx, path, u.into(), true); + let substs = ctx.substs_from_path(path, u.into(), true); let ty = self.db.ty(u.into()); let ty = self.insert_type_vars(ty.subst(&substs)); forbid_unresolved_segments((ty, Some(u.into())), unresolved) } TypeNs::EnumVariantId(var) => { - let substs = Ty::substs_from_path(&ctx, path, var.into(), true); + let substs = ctx.substs_from_path(path, var.into(), true); let ty = self.db.ty(var.parent.into()); let ty = self.insert_type_vars(ty.subst(&substs)); forbid_unresolved_segments((ty, Some(var.into())), unresolved) @@ -541,7 +541,7 @@ impl<'a> InferenceContext<'a> { let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver) .with_impl_trait_mode(ImplTraitLoweringMode::Param); let param_tys = - data.params.iter().map(|type_ref| Ty::from_hir(&ctx, type_ref)).collect::>(); + data.params.iter().map(|type_ref| ctx.lower_ty(type_ref)).collect::>(); for (ty, pat) in param_tys.into_iter().zip(body.params.iter()) { let ty = self.insert_type_vars(ty); let ty = self.normalize_associated_types_in(ty); diff --git a/crates/hir_ty/src/infer/path.rs b/crates/hir_ty/src/infer/path.rs index c6681834c..af108fb6c 100644 --- a/crates/hir_ty/src/infer/path.rs +++ b/crates/hir_ty/src/infer/path.rs @@ -40,7 +40,7 @@ impl<'a> InferenceContext<'a> { let ty = self.make_ty(type_ref); let remaining_segments_for_ty = path.segments().take(path.segments().len() - 1); let ctx = crate::lower::TyLoweringContext::new(self.db, &resolver); - let (ty, _) = Ty::from_type_relative_path(&ctx, ty, None, remaining_segments_for_ty); + let (ty, _) = ctx.lower_ty_relative_path(ty, None, remaining_segments_for_ty); self.resolve_ty_assoc_item( ty, &path.segments().last().expect("path had at least one segment").name, @@ -96,7 +96,7 @@ impl<'a> InferenceContext<'a> { // self_subst is just for the parent let parent_substs = self_subst.unwrap_or_else(Substs::empty); let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver); - let substs = Ty::substs_from_path(&ctx, path, typable, true); + let substs = ctx.substs_from_path(path, typable, true); let full_substs = Substs::builder(substs.len()) .use_parent_substs(&parent_substs) .fill(substs.0[parent_substs.len()..].iter().cloned()) @@ -126,7 +126,8 @@ impl<'a> InferenceContext<'a> { let segment = remaining_segments.last().expect("there should be at least one segment here"); let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver); - let trait_ref = TraitRef::from_resolved_path(&ctx, trait_, resolved_segment, None); + let trait_ref = + ctx.lower_trait_ref_from_resolved_path(trait_, resolved_segment, None); self.resolve_trait_assoc_item(trait_ref, segment, id) } (def, _) => { @@ -137,8 +138,7 @@ impl<'a> InferenceContext<'a> { let remaining_segments_for_ty = remaining_segments.take(remaining_segments.len() - 1); let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver); - let (ty, _) = Ty::from_partly_resolved_hir_path( - &ctx, + let (ty, _) = ctx.lower_partly_resolved_path( def, resolved_segment, remaining_segments_for_ty, diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index 3b0706530..c32dca9d7 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs @@ -140,44 +140,45 @@ pub enum TypeParamLoweringMode { Variable, } -impl Ty { - pub fn from_hir(ctx: &TyLoweringContext<'_>, type_ref: &TypeRef) -> Self { - Ty::from_hir_ext(ctx, type_ref).0 +impl<'a> TyLoweringContext<'a> { + pub fn lower_ty(&self, type_ref: &TypeRef) -> Ty { + self.lower_ty_ext(type_ref).0 } - pub fn from_hir_ext(ctx: &TyLoweringContext<'_>, type_ref: &TypeRef) -> (Self, Option) { + + fn lower_ty_ext(&self, type_ref: &TypeRef) -> (Ty, Option) { let mut res = None; let ty = match type_ref { TypeRef::Never => TyKind::Never.intern(&Interner), TypeRef::Tuple(inner) => { - let inner_tys: Arc<[Ty]> = inner.iter().map(|tr| Ty::from_hir(ctx, tr)).collect(); + let inner_tys: Arc<[Ty]> = inner.iter().map(|tr| self.lower_ty(tr)).collect(); TyKind::Tuple(inner_tys.len(), Substs(inner_tys)).intern(&Interner) } TypeRef::Path(path) => { - let (ty, res_) = Ty::from_hir_path(ctx, path); + let (ty, res_) = self.lower_path(path); res = res_; ty } TypeRef::RawPtr(inner, mutability) => { - let inner_ty = Ty::from_hir(ctx, inner); + let inner_ty = self.lower_ty(inner); TyKind::Raw(lower_to_chalk_mutability(*mutability), Substs::single(inner_ty)) .intern(&Interner) } TypeRef::Array(inner) => { - let inner_ty = Ty::from_hir(ctx, inner); + let inner_ty = self.lower_ty(inner); TyKind::Array(Substs::single(inner_ty)).intern(&Interner) } TypeRef::Slice(inner) => { - let inner_ty = Ty::from_hir(ctx, inner); + let inner_ty = self.lower_ty(inner); TyKind::Slice(Substs::single(inner_ty)).intern(&Interner) } TypeRef::Reference(inner, _, mutability) => { - let inner_ty = Ty::from_hir(ctx, inner); + let inner_ty = self.lower_ty(inner); TyKind::Ref(lower_to_chalk_mutability(*mutability), Substs::single(inner_ty)) .intern(&Interner) } TypeRef::Placeholder => TyKind::Unknown.intern(&Interner), TypeRef::Fn(params, is_varargs) => { - let substs = Substs(params.iter().map(|tr| Ty::from_hir(ctx, tr)).collect()); + let substs = Substs(params.iter().map(|tr| self.lower_ty(tr)).collect()); TyKind::Function(FnPointer { num_args: substs.len() - 1, sig: FnSig { variadic: *is_varargs }, @@ -188,25 +189,22 @@ impl Ty { TypeRef::DynTrait(bounds) => { let self_ty = TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner); - let predicates = ctx.with_shifted_in(DebruijnIndex::ONE, |ctx| { - bounds - .iter() - .flat_map(|b| GenericPredicate::from_type_bound(ctx, b, self_ty.clone())) - .collect() + let predicates = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { + bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone())).collect() }); TyKind::Dyn(predicates).intern(&Interner) } TypeRef::ImplTrait(bounds) => { - match ctx.impl_trait_mode { + match self.impl_trait_mode { ImplTraitLoweringMode::Opaque => { - let idx = ctx.impl_trait_counter.get(); - ctx.impl_trait_counter.set(idx + 1); + let idx = self.impl_trait_counter.get(); + self.impl_trait_counter.set(idx + 1); - assert!(idx as usize == ctx.opaque_type_data.borrow().len()); + assert!(idx as usize == self.opaque_type_data.borrow().len()); // this dance is to make sure the data is in the right // place even if we encounter more opaque types while // lowering the bounds - ctx.opaque_type_data + self.opaque_type_data .borrow_mut() .push(ReturnTypeImplTrait { bounds: Binders::new(1, Vec::new()) }); // We don't want to lower the bounds inside the binders @@ -218,29 +216,29 @@ impl Ty { // other, but separately. So if the `T` refers to a type // parameter of the outer function, it's just one binder // away instead of two. - let actual_opaque_type_data = ctx + let actual_opaque_type_data = self .with_debruijn(DebruijnIndex::INNERMOST, |ctx| { - ReturnTypeImplTrait::from_hir(ctx, &bounds) + ctx.lower_impl_trait(&bounds) }); - ctx.opaque_type_data.borrow_mut()[idx as usize] = actual_opaque_type_data; + self.opaque_type_data.borrow_mut()[idx as usize] = actual_opaque_type_data; - let func = match ctx.resolver.generic_def() { + let func = match self.resolver.generic_def() { Some(GenericDefId::FunctionId(f)) => f, _ => panic!("opaque impl trait lowering in non-function"), }; let impl_trait_id = ImplTraitId::ReturnTypeImplTrait(func, idx); - let opaque_ty_id = ctx.db.intern_impl_trait_id(impl_trait_id).into(); - let generics = generics(ctx.db.upcast(), func.into()); - let parameters = Substs::bound_vars(&generics, ctx.in_binders); + let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into(); + let generics = generics(self.db.upcast(), func.into()); + let parameters = Substs::bound_vars(&generics, self.in_binders); TyKind::Alias(AliasTy::Opaque(OpaqueTy { opaque_ty_id, parameters })) .intern(&Interner) } ImplTraitLoweringMode::Param => { - let idx = ctx.impl_trait_counter.get(); + let idx = self.impl_trait_counter.get(); // FIXME we're probably doing something wrong here - ctx.impl_trait_counter.set(idx + count_impl_traits(type_ref) as u16); - if let Some(def) = ctx.resolver.generic_def() { - let generics = generics(ctx.db.upcast(), def); + self.impl_trait_counter.set(idx + count_impl_traits(type_ref) as u16); + if let Some(def) = self.resolver.generic_def() { + let generics = generics(self.db.upcast(), def); let param = generics .iter() .filter(|(_, data)| { @@ -248,7 +246,7 @@ impl Ty { }) .nth(idx as usize) .map_or(TyKind::Unknown, |(id, _)| { - TyKind::Placeholder(to_placeholder_idx(ctx.db, id)) + TyKind::Placeholder(to_placeholder_idx(self.db, id)) }); param.intern(&Interner) } else { @@ -256,18 +254,18 @@ impl Ty { } } ImplTraitLoweringMode::Variable => { - let idx = ctx.impl_trait_counter.get(); + let idx = self.impl_trait_counter.get(); // FIXME we're probably doing something wrong here - ctx.impl_trait_counter.set(idx + count_impl_traits(type_ref) as u16); + self.impl_trait_counter.set(idx + count_impl_traits(type_ref) as u16); let (parent_params, self_params, list_params, _impl_trait_params) = - if let Some(def) = ctx.resolver.generic_def() { - let generics = generics(ctx.db.upcast(), def); + if let Some(def) = self.resolver.generic_def() { + let generics = generics(self.db.upcast(), def); generics.provenance_split() } else { (0, 0, 0, 0) }; TyKind::BoundVar(BoundVar::new( - ctx.in_binders, + self.in_binders, idx as usize + parent_params + self_params + list_params, )) .intern(&Interner) @@ -286,7 +284,7 @@ impl Ty { /// This is only for `generic_predicates_for_param`, where we can't just /// 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(ctx: &TyLoweringContext<'_>, type_ref: &TypeRef) -> Option { + fn lower_ty_only_param(&self, type_ref: &TypeRef) -> Option { let path = match type_ref { TypeRef::Path(path) => path, _ => return None, @@ -298,7 +296,7 @@ impl Ty { return None; } let resolution = - match ctx.resolver.resolve_path_in_type_ns(ctx.db.upcast(), path.mod_path()) { + match self.resolver.resolve_path_in_type_ns(self.db.upcast(), path.mod_path()) { Some((it, None)) => it, _ => return None, }; @@ -309,8 +307,8 @@ impl Ty { } } - pub(crate) fn from_type_relative_path( - ctx: &TyLoweringContext<'_>, + pub(crate) fn lower_ty_relative_path( + &self, ty: Ty, // We need the original resolution to lower `Self::AssocTy` correctly res: Option, @@ -319,7 +317,7 @@ impl Ty { if remaining_segments.len() == 1 { // resolve unselected assoc types let segment = remaining_segments.first().unwrap(); - (Ty::select_associated_type(ctx, res, segment), None) + (self.select_associated_type(res, segment), None) } else if remaining_segments.len() > 1 { // FIXME report error (ambiguous associated type) (TyKind::Unknown.intern(&Interner), None) @@ -328,8 +326,8 @@ impl Ty { } } - pub(crate) fn from_partly_resolved_hir_path( - ctx: &TyLoweringContext<'_>, + pub(crate) fn lower_partly_resolved_path( + &self, resolution: TypeNs, resolved_segment: PathSegment<'_>, remaining_segments: PathSegments<'_>, @@ -347,11 +345,11 @@ impl Ty { None }; let trait_ref = - TraitRef::from_resolved_path(ctx, trait_, resolved_segment, self_ty); + self.lower_trait_ref_from_resolved_path(trait_, resolved_segment, self_ty); let ty = if remaining_segments.len() == 1 { let segment = remaining_segments.first().unwrap(); let found = associated_type_by_name_including_super_traits( - ctx.db, + self.db, trait_ref, &segment.name, ); @@ -380,68 +378,66 @@ impl Ty { } TypeNs::GenericParam(param_id) => { let generics = generics( - ctx.db.upcast(), - ctx.resolver.generic_def().expect("generics in scope"), + self.db.upcast(), + self.resolver.generic_def().expect("generics in scope"), ); - match ctx.type_param_mode { + match self.type_param_mode { TypeParamLoweringMode::Placeholder => { - TyKind::Placeholder(to_placeholder_idx(ctx.db, param_id)) + TyKind::Placeholder(to_placeholder_idx(self.db, param_id)) } TypeParamLoweringMode::Variable => { let idx = generics.param_idx(param_id).expect("matching generics"); - TyKind::BoundVar(BoundVar::new(ctx.in_binders, idx)) + TyKind::BoundVar(BoundVar::new(self.in_binders, idx)) } } .intern(&Interner) } TypeNs::SelfType(impl_id) => { - let generics = generics(ctx.db.upcast(), impl_id.into()); - let substs = match ctx.type_param_mode { + let generics = generics(self.db.upcast(), impl_id.into()); + let substs = match self.type_param_mode { TypeParamLoweringMode::Placeholder => { - Substs::type_params_for_generics(ctx.db, &generics) + Substs::type_params_for_generics(self.db, &generics) } TypeParamLoweringMode::Variable => { - Substs::bound_vars(&generics, ctx.in_binders) + Substs::bound_vars(&generics, self.in_binders) } }; - ctx.db.impl_self_ty(impl_id).subst(&substs) + self.db.impl_self_ty(impl_id).subst(&substs) } TypeNs::AdtSelfType(adt) => { - let generics = generics(ctx.db.upcast(), adt.into()); - let substs = match ctx.type_param_mode { + let generics = generics(self.db.upcast(), adt.into()); + let substs = match self.type_param_mode { TypeParamLoweringMode::Placeholder => { - Substs::type_params_for_generics(ctx.db, &generics) + Substs::type_params_for_generics(self.db, &generics) } TypeParamLoweringMode::Variable => { - Substs::bound_vars(&generics, ctx.in_binders) + Substs::bound_vars(&generics, self.in_binders) } }; - ctx.db.ty(adt.into()).subst(&substs) + self.db.ty(adt.into()).subst(&substs) } - TypeNs::AdtId(it) => { - Ty::from_hir_path_inner(ctx, resolved_segment, it.into(), infer_args) - } + TypeNs::AdtId(it) => self.lower_path_inner(resolved_segment, it.into(), infer_args), TypeNs::BuiltinType(it) => { - Ty::from_hir_path_inner(ctx, resolved_segment, it.into(), infer_args) + self.lower_path_inner(resolved_segment, it.into(), infer_args) } TypeNs::TypeAliasId(it) => { - Ty::from_hir_path_inner(ctx, resolved_segment, it.into(), infer_args) + self.lower_path_inner(resolved_segment, it.into(), infer_args) } // FIXME: report error TypeNs::EnumVariantId(_) => return (TyKind::Unknown.intern(&Interner), None), }; - Ty::from_type_relative_path(ctx, ty, Some(resolution), remaining_segments) + self.lower_ty_relative_path(ty, Some(resolution), remaining_segments) } - pub(crate) fn from_hir_path(ctx: &TyLoweringContext<'_>, path: &Path) -> (Ty, Option) { + pub(crate) fn lower_path(&self, path: &Path) -> (Ty, Option) { // Resolve the path (in type namespace) if let Some(type_ref) = path.type_anchor() { - let (ty, res) = Ty::from_hir_ext(ctx, &type_ref); - return Ty::from_type_relative_path(ctx, ty, res, path.segments()); + let (ty, res) = self.lower_ty_ext(&type_ref); + return self.lower_ty_relative_path(ty, res, path.segments()); } let (resolution, remaining_index) = - match ctx.resolver.resolve_path_in_type_ns(ctx.db.upcast(), path.mod_path()) { + match self.resolver.resolve_path_in_type_ns(self.db.upcast(), path.mod_path()) { Some(it) => it, None => return (TyKind::Unknown.intern(&Interner), None), }; @@ -452,31 +448,23 @@ impl Ty { ), Some(i) => (path.segments().get(i - 1).unwrap(), path.segments().skip(i)), }; - Ty::from_partly_resolved_hir_path( - ctx, - resolution, - resolved_segment, - remaining_segments, - false, - ) + self.lower_partly_resolved_path(resolution, resolved_segment, remaining_segments, false) } - fn select_associated_type( - ctx: &TyLoweringContext<'_>, - res: Option, - segment: PathSegment<'_>, - ) -> Ty { + fn select_associated_type(&self, res: Option, segment: PathSegment<'_>) -> Ty { if let Some(res) = res { - let ty = - associated_type_shorthand_candidates(ctx.db, res, move |name, t, associated_ty| { + let ty = associated_type_shorthand_candidates( + self.db, + res, + move |name, t, associated_ty| { if name == segment.name { - let substs = match ctx.type_param_mode { + let substs = match self.type_param_mode { TypeParamLoweringMode::Placeholder => { // if we're lowering to placeholders, we have to put // them in now let s = Substs::type_params( - ctx.db, - ctx.resolver.generic_def().expect( + self.db, + self.resolver.generic_def().expect( "there should be generics if there's a generic param", ), ); @@ -486,7 +474,7 @@ impl Ty { }; // We need to shift in the bound vars, since // associated_type_shorthand_candidates does not do that - let substs = substs.shift_bound_vars(ctx.in_binders); + let substs = substs.shift_bound_vars(self.in_binders); // FIXME handle type parameters on the segment return Some( TyKind::Alias(AliasTy::Projection(ProjectionTy { @@ -498,7 +486,8 @@ impl Ty { } None - }); + }, + ); ty.unwrap_or(TyKind::Unknown.intern(&Interner)) } else { @@ -506,8 +495,8 @@ impl Ty { } } - fn from_hir_path_inner( - ctx: &TyLoweringContext<'_>, + fn lower_path_inner( + &self, segment: PathSegment<'_>, typeable: TyDefId, infer_args: bool, @@ -517,14 +506,14 @@ impl Ty { TyDefId::AdtId(it) => Some(it.into()), TyDefId::TypeAliasId(it) => Some(it.into()), }; - let substs = substs_from_path_segment(ctx, segment, generic_def, infer_args); - ctx.db.ty(typeable).subst(&substs) + let substs = self.substs_from_path_segment(segment, generic_def, infer_args); + self.db.ty(typeable).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( - ctx: &TyLoweringContext<'_>, + &self, path: &Path, // Note that we don't call `db.value_type(resolved)` here, // `ValueTyDefId` is just a convenient way to pass generics and @@ -554,145 +543,137 @@ impl Ty { (segment, Some(var.parent.into())) } }; - substs_from_path_segment(ctx, segment, generic_def, infer_args) + self.substs_from_path_segment(segment, generic_def, infer_args) } -} -fn substs_from_path_segment( - ctx: &TyLoweringContext<'_>, - segment: PathSegment<'_>, - def_generic: Option, - infer_args: bool, -) -> Substs { - let mut substs = Vec::new(); - let def_generics = def_generic.map(|def| generics(ctx.db.upcast(), def)); + fn substs_from_path_segment( + &self, + segment: PathSegment<'_>, + def_generic: Option, + infer_args: bool, + ) -> Substs { + let mut substs = Vec::new(); + let def_generics = def_generic.map(|def| generics(self.db.upcast(), def)); - let (parent_params, self_params, type_params, impl_trait_params) = - def_generics.map_or((0, 0, 0, 0), |g| g.provenance_split()); - let total_len = parent_params + self_params + type_params + impl_trait_params; + let (parent_params, self_params, type_params, impl_trait_params) = + def_generics.map_or((0, 0, 0, 0), |g| g.provenance_split()); + let total_len = parent_params + self_params + type_params + impl_trait_params; - substs.extend(iter::repeat(TyKind::Unknown.intern(&Interner)).take(parent_params)); + substs.extend(iter::repeat(TyKind::Unknown.intern(&Interner)).take(parent_params)); - let mut had_explicit_type_args = false; + let mut had_explicit_type_args = false; - if let Some(generic_args) = &segment.args_and_bindings { - if !generic_args.has_self_type { - substs.extend(iter::repeat(TyKind::Unknown.intern(&Interner)).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 - for arg in generic_args - .args - .iter() - .filter(|arg| matches!(arg, GenericArg::Type(_))) - .skip(skip) - .take(expected_num) - { - match arg { - GenericArg::Type(type_ref) => { - had_explicit_type_args = true; - let ty = Ty::from_hir(ctx, type_ref); - substs.push(ty); + if let Some(generic_args) = &segment.args_and_bindings { + if !generic_args.has_self_type { + substs.extend(iter::repeat(TyKind::Unknown.intern(&Interner)).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 + for arg in generic_args + .args + .iter() + .filter(|arg| matches!(arg, GenericArg::Type(_))) + .skip(skip) + .take(expected_num) + { + match arg { + GenericArg::Type(type_ref) => { + had_explicit_type_args = true; + let ty = self.lower_ty(type_ref); + substs.push(ty); + } + GenericArg::Lifetime(_) => {} } - GenericArg::Lifetime(_) => {} } } - } - // handle defaults. In expression or pattern path segments without - // explicitly specified type arguments, missing type arguments are inferred - // (i.e. defaults aren't used). - if !infer_args || had_explicit_type_args { - if let Some(def_generic) = def_generic { - let defaults = ctx.db.generic_defaults(def_generic); - assert_eq!(total_len, defaults.len()); - - for default_ty in defaults.iter().skip(substs.len()) { - // each default can depend on the previous parameters - let substs_so_far = Substs(substs.clone().into()); - substs.push(default_ty.clone().subst(&substs_so_far)); + // handle defaults. In expression or pattern path segments without + // explicitly specified type arguments, missing type arguments are inferred + // (i.e. defaults aren't used). + if !infer_args || had_explicit_type_args { + if let Some(def_generic) = def_generic { + let defaults = self.db.generic_defaults(def_generic); + assert_eq!(total_len, defaults.len()); + + for default_ty in defaults.iter().skip(substs.len()) { + // each default can depend on the previous parameters + let substs_so_far = Substs(substs.clone().into()); + substs.push(default_ty.clone().subst(&substs_so_far)); + } } } - } - // add placeholders for args that were not provided - // FIXME: emit diagnostics in contexts where this is not allowed - for _ in substs.len()..total_len { - substs.push(TyKind::Unknown.intern(&Interner)); - } - assert_eq!(substs.len(), total_len); + // add placeholders for args that were not provided + // FIXME: emit diagnostics in contexts where this is not allowed + for _ in substs.len()..total_len { + substs.push(TyKind::Unknown.intern(&Interner)); + } + assert_eq!(substs.len(), total_len); - Substs(substs.into()) -} + Substs(substs.into()) + } -impl TraitRef { - fn from_path( - ctx: &TyLoweringContext<'_>, + fn lower_trait_ref_from_path( + &self, path: &Path, explicit_self_ty: Option, - ) -> Option { + ) -> Option { let resolved = - match ctx.resolver.resolve_path_in_type_ns_fully(ctx.db.upcast(), path.mod_path())? { + match self.resolver.resolve_path_in_type_ns_fully(self.db.upcast(), 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(ctx, resolved, segment, explicit_self_ty)) + Some(self.lower_trait_ref_from_resolved_path(resolved, segment, explicit_self_ty)) } - pub(crate) fn from_resolved_path( - ctx: &TyLoweringContext<'_>, + pub(crate) fn lower_trait_ref_from_resolved_path( + &self, resolved: TraitId, segment: PathSegment<'_>, explicit_self_ty: Option, - ) -> Self { - let mut substs = TraitRef::substs_from_path(ctx, segment, resolved); + ) -> TraitRef { + let mut substs = self.trait_ref_substs_from_path(segment, resolved); if let Some(self_ty) = explicit_self_ty { make_mut_slice(&mut substs.0)[0] = self_ty; } TraitRef { trait_: resolved, substs } } - fn from_hir( - ctx: &TyLoweringContext<'_>, + fn lower_trait_ref( + &self, type_ref: &TypeRef, explicit_self_ty: Option, - ) -> Option { + ) -> Option { let path = match type_ref { TypeRef::Path(path) => path, _ => return None, }; - TraitRef::from_path(ctx, path, explicit_self_ty) + self.lower_trait_ref_from_path(path, explicit_self_ty) } - fn substs_from_path( - ctx: &TyLoweringContext<'_>, - segment: PathSegment<'_>, - resolved: TraitId, - ) -> Substs { - substs_from_path_segment(ctx, segment, Some(resolved.into()), false) + fn trait_ref_substs_from_path(&self, segment: PathSegment<'_>, resolved: TraitId) -> Substs { + self.substs_from_path_segment(segment, Some(resolved.into()), false) } -} -impl GenericPredicate { - pub(crate) fn from_where_predicate<'a>( - ctx: &'a TyLoweringContext<'a>, + pub(crate) fn lower_where_predicate( + &'a self, where_predicate: &'a WherePredicate, ) -> impl Iterator + 'a { match where_predicate { WherePredicate::ForLifetime { target, bound, .. } | WherePredicate::TypeBound { target, bound } => { let self_ty = match target { - WherePredicateTypeTarget::TypeRef(type_ref) => Ty::from_hir(ctx, type_ref), + WherePredicateTypeTarget::TypeRef(type_ref) => self.lower_ty(type_ref), WherePredicateTypeTarget::TypeParam(param_id) => { - let generic_def = ctx.resolver.generic_def().expect("generics in scope"); - let generics = generics(ctx.db.upcast(), generic_def); + let generic_def = self.resolver.generic_def().expect("generics in scope"); + let generics = generics(self.db.upcast(), generic_def); let param_id = hir_def::TypeParamId { parent: generic_def, local_id: *param_id }; - let placeholder = to_placeholder_idx(ctx.db, param_id); - match ctx.type_param_mode { + let placeholder = to_placeholder_idx(self.db, param_id); + match self.type_param_mode { TypeParamLoweringMode::Placeholder => TyKind::Placeholder(placeholder), TypeParamLoweringMode::Variable => { let idx = generics.param_idx(param_id).expect("matching generics"); @@ -702,23 +683,21 @@ impl GenericPredicate { .intern(&Interner) } }; - GenericPredicate::from_type_bound(ctx, bound, self_ty) - .collect::>() - .into_iter() + self.lower_type_bound(bound, self_ty).collect::>().into_iter() } WherePredicate::Lifetime { .. } => vec![].into_iter(), } } - pub(crate) fn from_type_bound<'a>( - ctx: &'a TyLoweringContext<'a>, + pub(crate) fn lower_type_bound( + &'a self, bound: &'a TypeBound, self_ty: Ty, ) -> impl Iterator + 'a { let mut bindings = None; let trait_ref = match bound { TypeBound::Path(path) => { - bindings = TraitRef::from_path(ctx, path, Some(self_ty)); + bindings = self.lower_trait_ref_from_path(path, Some(self_ty)); Some( bindings.clone().map_or(GenericPredicate::Error, GenericPredicate::Implemented), ) @@ -729,68 +708,62 @@ impl GenericPredicate { trait_ref.into_iter().chain( bindings .into_iter() - .flat_map(move |tr| assoc_type_bindings_from_type_bound(ctx, bound, tr)), + .flat_map(move |tr| self.assoc_type_bindings_from_type_bound(bound, tr)), ) } -} -fn assoc_type_bindings_from_type_bound<'a>( - ctx: &'a TyLoweringContext<'a>, - bound: &'a TypeBound, - trait_ref: TraitRef, -) -> impl Iterator + 'a { - let last_segment = match bound { - TypeBound::Path(path) => path.segments().last(), - TypeBound::Error | TypeBound::Lifetime(_) => None, - }; - last_segment - .into_iter() - .flat_map(|segment| segment.args_and_bindings.into_iter()) - .flat_map(|args_and_bindings| args_and_bindings.bindings.iter()) - .flat_map(move |binding| { - let found = associated_type_by_name_including_super_traits( - ctx.db, - trait_ref.clone(), - &binding.name, - ); - let (super_trait_ref, associated_ty) = match found { - None => return SmallVec::<[GenericPredicate; 1]>::new(), - Some(t) => t, - }; - let projection_ty = ProjectionTy { - associated_ty: to_assoc_type_id(associated_ty), - parameters: super_trait_ref.substs, - }; - let mut preds = SmallVec::with_capacity( - binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(), - ); - if let Some(type_ref) = &binding.type_ref { - let ty = Ty::from_hir(ctx, type_ref); - let projection_predicate = - ProjectionPredicate { projection_ty: projection_ty.clone(), ty }; - preds.push(GenericPredicate::Projection(projection_predicate)); - } - for bound in &binding.bounds { - preds.extend(GenericPredicate::from_type_bound( - ctx, - bound, - TyKind::Alias(AliasTy::Projection(projection_ty.clone())).intern(&Interner), - )); - } - preds - }) -} + fn assoc_type_bindings_from_type_bound( + &'a self, + bound: &'a TypeBound, + trait_ref: TraitRef, + ) -> impl Iterator + 'a { + let last_segment = match bound { + TypeBound::Path(path) => path.segments().last(), + TypeBound::Error | TypeBound::Lifetime(_) => None, + }; + last_segment + .into_iter() + .flat_map(|segment| segment.args_and_bindings.into_iter()) + .flat_map(|args_and_bindings| args_and_bindings.bindings.iter()) + .flat_map(move |binding| { + let found = associated_type_by_name_including_super_traits( + self.db, + trait_ref.clone(), + &binding.name, + ); + let (super_trait_ref, associated_ty) = match found { + None => return SmallVec::<[GenericPredicate; 1]>::new(), + Some(t) => t, + }; + let projection_ty = ProjectionTy { + associated_ty: to_assoc_type_id(associated_ty), + parameters: super_trait_ref.substs, + }; + let mut preds = SmallVec::with_capacity( + binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(), + ); + if let Some(type_ref) = &binding.type_ref { + let ty = self.lower_ty(type_ref); + let projection_predicate = + ProjectionPredicate { projection_ty: projection_ty.clone(), ty }; + preds.push(GenericPredicate::Projection(projection_predicate)); + } + for bound in &binding.bounds { + preds.extend(self.lower_type_bound( + bound, + TyKind::Alias(AliasTy::Projection(projection_ty.clone())).intern(&Interner), + )); + } + preds + }) + } -impl ReturnTypeImplTrait { - fn from_hir(ctx: &TyLoweringContext, bounds: &[TypeBound]) -> Self { + fn lower_impl_trait(&self, bounds: &[TypeBound]) -> ReturnTypeImplTrait { cov_mark::hit!(lower_rpit); let self_ty = TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner); - let predicates = ctx.with_shifted_in(DebruijnIndex::ONE, |ctx| { - bounds - .iter() - .flat_map(|b| GenericPredicate::from_type_bound(ctx, b, self_ty.clone())) - .collect() + let predicates = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { + bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone())).collect() }); ReturnTypeImplTrait { bounds: Binders::new(1, predicates) } } @@ -886,7 +859,7 @@ pub(crate) fn field_types_query( 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))) + res.insert(field_id, Binders::new(generics.len(), ctx.lower_ty(&field_data.type_ref))) } Arc::new(res) } @@ -914,16 +887,13 @@ pub(crate) fn generic_predicates_for_param_query( WherePredicate::ForLifetime { target, .. } | WherePredicate::TypeBound { target, .. } => match target { WherePredicateTypeTarget::TypeRef(type_ref) => { - Ty::from_hir_only_param(&ctx, type_ref) == Some(param_id) + ctx.lower_ty_only_param(type_ref) == Some(param_id) } WherePredicateTypeTarget::TypeParam(local_id) => *local_id == param_id.local_id, }, WherePredicate::Lifetime { .. } => false, }) - .flat_map(|pred| { - GenericPredicate::from_where_predicate(&ctx, pred) - .map(|p| Binders::new(generics.len(), p)) - }) + .flat_map(|pred| ctx.lower_where_predicate(pred).map(|p| Binders::new(generics.len(), p))) .collect() } @@ -945,7 +915,7 @@ pub(crate) fn trait_environment_query( let mut traits_in_scope = Vec::new(); let mut clauses = Vec::new(); for pred in resolver.where_predicates_in_scope() { - for pred in GenericPredicate::from_where_predicate(&ctx, pred) { + for pred in ctx.lower_where_predicate(pred) { if pred.is_error() { continue; } @@ -997,10 +967,7 @@ pub(crate) fn generic_predicates_query( let generics = generics(db.upcast(), def); resolver .where_predicates_in_scope() - .flat_map(|pred| { - GenericPredicate::from_where_predicate(&ctx, pred) - .map(|p| Binders::new(generics.len(), p)) - }) + .flat_map(|pred| ctx.lower_where_predicate(pred).map(|p| Binders::new(generics.len(), p))) .collect() } @@ -1018,10 +985,8 @@ pub(crate) fn generic_defaults_query( .iter() .enumerate() .map(|(idx, (_, p))| { - let mut ty = p - .default - .as_ref() - .map_or(TyKind::Unknown.intern(&Interner), |t| Ty::from_hir(&ctx, t)); + let mut ty = + p.default.as_ref().map_or(TyKind::Unknown.intern(&Interner), |t| ctx.lower_ty(t)); // Each default can only refer to previous parameters. ty.walk_mut_binders( @@ -1052,11 +1017,11 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig { 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 params = data.params.iter().map(|tr| (&ctx_params).lower_ty(tr)).collect::>(); let ctx_ret = TyLoweringContext::new(db, &resolver) .with_impl_trait_mode(ImplTraitLoweringMode::Opaque) .with_type_param_mode(TypeParamLoweringMode::Variable); - let ret = Ty::from_hir(&ctx_ret, &data.ret_type); + let ret = (&ctx_ret).lower_ty(&data.ret_type); let generics = generics(db.upcast(), def.into()); let num_binders = generics.len(); Binders::new(num_binders, CallableSig::from_params_and_return(params, ret, data.is_varargs)) @@ -1081,7 +1046,7 @@ fn type_for_const(db: &dyn HirDatabase, def: ConstId) -> Binders { let ctx = TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); - Binders::new(generics.len(), Ty::from_hir(&ctx, &data.type_ref)) + Binders::new(generics.len(), ctx.lower_ty(&data.type_ref)) } /// Build the declared type of a static. @@ -1090,7 +1055,7 @@ fn type_for_static(db: &dyn HirDatabase, def: StaticId) -> Binders { let resolver = def.resolver(db.upcast()); let ctx = TyLoweringContext::new(db, &resolver); - Binders::new(0, Ty::from_hir(&ctx, &data.type_ref)) + Binders::new(0, ctx.lower_ty(&data.type_ref)) } fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnSig { @@ -1099,8 +1064,7 @@ fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnS let resolver = def.resolver(db.upcast()); 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 params = fields.iter().map(|(_, field)| ctx.lower_ty(&field.type_ref)).collect::>(); let ret = type_for_adt(db, def.into()); Binders::new(ret.num_binders, CallableSig::from_params_and_return(params, ret.value, false)) } @@ -1126,8 +1090,7 @@ fn fn_sig_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) let resolver = def.parent.resolver(db.upcast()); 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 params = fields.iter().map(|(_, field)| ctx.lower_ty(&field.type_ref)).collect::>(); let ret = type_for_adt(db, def.parent.into()); Binders::new(ret.num_binders, CallableSig::from_params_and_return(params, ret.value, false)) } @@ -1163,7 +1126,7 @@ fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders { } else { let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST); let type_ref = &db.type_alias_data(t).type_ref; - let inner = Ty::from_hir(&ctx, type_ref.as_ref().unwrap_or(&TypeRef::Error)); + let inner = ctx.lower_ty(type_ref.as_ref().unwrap_or(&TypeRef::Error)); Binders::new(substs.len(), inner) } } @@ -1255,7 +1218,7 @@ pub(crate) fn impl_self_ty_query(db: &dyn HirDatabase, impl_id: ImplId) -> Binde let generics = generics(db.upcast(), 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)) + Binders::new(generics.len(), ctx.lower_ty(&impl_data.target_type)) } pub(crate) fn const_param_ty_query(db: &dyn HirDatabase, def: ConstParamId) -> Ty { @@ -1264,7 +1227,7 @@ pub(crate) fn const_param_ty_query(db: &dyn HirDatabase, def: ConstParamId) -> T let resolver = def.parent.resolver(db.upcast()); let ctx = TyLoweringContext::new(db, &resolver); - Ty::from_hir(&ctx, &data.ty) + ctx.lower_ty(&data.ty) } pub(crate) fn impl_self_ty_recover( @@ -1283,10 +1246,7 @@ pub(crate) fn impl_trait_query(db: &dyn HirDatabase, impl_id: ImplId) -> Option< 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))?, - )) + Some(Binders::new(self_ty.num_binders, ctx.lower_trait_ref(target_trait, Some(self_ty.value))?)) } pub(crate) fn return_type_impl_traits( @@ -1299,7 +1259,7 @@ pub(crate) fn return_type_impl_traits( let ctx_ret = TyLoweringContext::new(db, &resolver) .with_impl_trait_mode(ImplTraitLoweringMode::Opaque) .with_type_param_mode(TypeParamLoweringMode::Variable); - let _ret = Ty::from_hir(&ctx_ret, &data.ret_type); + let _ret = (&ctx_ret).lower_ty(&data.ret_type); let generics = generics(db.upcast(), def.into()); let num_binders = generics.len(); let return_type_impl_traits = diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs index 1f3e1c07a..ef1e6b2df 100644 --- a/crates/hir_ty/src/traits/chalk.rs +++ b/crates/hir_ty/src/traits/chalk.rs @@ -401,7 +401,7 @@ pub(crate) fn associated_ty_data_query( let bounds = type_alias_data .bounds .iter() - .flat_map(|bound| GenericPredicate::from_type_bound(&ctx, bound, self_ty.clone())) + .flat_map(|bound| ctx.lower_type_bound(bound, self_ty.clone())) .filter_map(|pred| generic_predicate_to_inline_bound(db, &pred, &self_ty)) .map(|bound| make_binders(bound.shifted_in(&Interner), 0)) .collect(); -- cgit v1.2.3