Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/lower.rs')
-rw-r--r--crates/hir-ty/src/lower.rs92
1 files changed, 59 insertions, 33 deletions
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index 67cdb99744..370d9ba99c 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -6,7 +6,7 @@
//!
//! This usually involves resolving names, collecting generic arguments etc.
use std::{
- cell::{Cell, RefCell, RefMut},
+ cell::{Cell, OnceCell, RefCell, RefMut},
iter,
ops::{self, Not as _},
};
@@ -43,7 +43,6 @@ use hir_def::{
use hir_expand::{name::Name, ExpandResult};
use intern::Interned;
use la_arena::{Arena, ArenaMap};
-use once_cell::unsync::OnceCell;
use rustc_hash::FxHashSet;
use rustc_pattern_analysis::Captures;
use smallvec::SmallVec;
@@ -378,26 +377,25 @@ impl<'a> TyLoweringContext<'a> {
// Count the number of `impl Trait` things that appear within our bounds.
// Since t hose have been emitted as implicit type args already.
counter.set(idx + count_impl_traits(type_ref) as u16);
- let (
- _parent_params,
- self_param,
- type_params,
- const_params,
- _impl_trait_params,
- lifetime_params,
- ) = self
+ let kind = self
.generics()
.expect("variable impl trait lowering must be in a generic def")
- .provenance_split();
- TyKind::BoundVar(BoundVar::new(
- self.in_binders,
- idx as usize
- + self_param as usize
- + type_params
- + const_params
- + lifetime_params,
- ))
- .intern(Interner)
+ .iter()
+ .enumerate()
+ .filter_map(|(i, (id, data))| match (id, data) {
+ (
+ GenericParamId::TypeParamId(_),
+ GenericParamDataRef::TypeParamData(data),
+ ) if data.provenance == TypeParamProvenance::ArgumentImplTrait => {
+ Some(i)
+ }
+ _ => None,
+ })
+ .nth(idx as usize)
+ .map_or(TyKind::Error, |id| {
+ TyKind::BoundVar(BoundVar { debruijn: self.in_binders, index: id })
+ });
+ kind.intern(Interner)
}
ImplTraitLoweringState::Disallowed => {
// FIXME: report error
@@ -1553,6 +1551,10 @@ pub(crate) fn generic_predicates_for_param_query(
}
};
if invalid_target {
+ // If this is filtered out without lowering, `?Sized` is not gathered into `ctx.unsized_types`
+ if let TypeBound::Path(_, TraitBoundModifier::Maybe) = &**bound {
+ ctx.lower_where_predicate(pred, &def, true).for_each(drop);
+ }
return false;
}
@@ -1741,15 +1743,39 @@ fn implicitly_sized_clauses<'a, 'subst: 'a>(
substitution: &'subst Substitution,
resolver: &Resolver,
) -> Option<impl Iterator<Item = WhereClause> + Captures<'a> + Captures<'subst>> {
- let is_trait_def = matches!(def, GenericDefId::TraitId(..));
- let generic_args = &substitution.as_slice(Interner)[is_trait_def as usize..];
let sized_trait = db
.lang_item(resolver.krate(), LangItem::Sized)
- .and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id));
+ .and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id))?;
- sized_trait.map(move |sized_trait| {
- generic_args
- .iter()
+ let get_trait_self_idx = |container: ItemContainerId| {
+ if matches!(container, ItemContainerId::TraitId(_)) {
+ let generics = generics(db.upcast(), def);
+ Some(generics.len_self())
+ } else {
+ None
+ }
+ };
+ let trait_self_idx = match def {
+ GenericDefId::TraitId(_) => Some(0),
+ GenericDefId::FunctionId(it) => get_trait_self_idx(it.lookup(db.upcast()).container),
+ GenericDefId::ConstId(it) => get_trait_self_idx(it.lookup(db.upcast()).container),
+ GenericDefId::TypeAliasId(it) => get_trait_self_idx(it.lookup(db.upcast()).container),
+ _ => None,
+ };
+
+ Some(
+ substitution
+ .iter(Interner)
+ .enumerate()
+ .filter_map(
+ move |(idx, generic_arg)| {
+ if Some(idx) == trait_self_idx {
+ None
+ } else {
+ Some(generic_arg)
+ }
+ },
+ )
.filter_map(|generic_arg| generic_arg.ty(Interner))
.filter(move |&self_ty| !explicitly_unsized_tys.contains(self_ty))
.map(move |self_ty| {
@@ -1757,8 +1783,8 @@ fn implicitly_sized_clauses<'a, 'subst: 'a>(
trait_id: sized_trait,
substitution: Substitution::from1(Interner, self_ty.clone()),
})
- })
- })
+ }),
+ )
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -1978,13 +2004,13 @@ fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> {
.with_impl_trait_mode(ImplTraitLoweringMode::Opaque)
.with_type_param_mode(ParamLoweringMode::Variable);
let type_alias_data = db.type_alias_data(t);
- if type_alias_data.is_extern {
- Binders::empty(Interner, TyKind::Foreign(crate::to_foreign_def_id(t)).intern(Interner))
+ let inner = if type_alias_data.is_extern {
+ TyKind::Foreign(crate::to_foreign_def_id(t)).intern(Interner)
} else {
let type_ref = &type_alias_data.type_ref;
- let inner = ctx.lower_ty(type_ref.as_deref().unwrap_or(&TypeRef::Error));
- make_binders(db, &generics, inner)
- }
+ ctx.lower_ty(type_ref.as_deref().unwrap_or(&TypeRef::Error))
+ };
+ make_binders(db, &generics, inner)
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]