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.rs57
1 files changed, 48 insertions, 9 deletions
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index 3f6d0844e9..4a37a79453 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -1,8 +1,8 @@
//! Methods for lowering the HIR to types. There are two main cases here:
//!
//! - Lowering a type reference like `&usize` or `Option<foo::bar::Baz>` to a
-//! type: The entry point for this is `Ty::from_hir`.
-//! - Building the type for an item: This happens through the `type_for_def` query.
+//! type: The entry point for this is `TyLoweringContext::lower_ty`.
+//! - Building the type for an item: This happens through the `ty` query.
//!
//! This usually involves resolving names, collecting generic arguments etc.
use std::{
@@ -47,7 +47,7 @@ use crate::{
consteval::{intern_const_scalar, path_to_const, unknown_const, unknown_const_as_generic},
db::HirDatabase,
make_binders,
- mapping::ToChalk,
+ mapping::{from_chalk_trait_id, ToChalk},
static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx,
utils::Generics,
utils::{all_super_trait_refs, associated_type_by_name_including_super_traits, generics},
@@ -332,7 +332,10 @@ impl<'a> TyLoweringContext<'a> {
TypeRef::Macro(macro_call) => {
let (mut expander, recursion_start) = {
match RefMut::filter_map(self.expander.borrow_mut(), Option::as_mut) {
+ // There already is an expander here, this means we are already recursing
Ok(expander) => (expander, false),
+ // No expander was created yet, so we are at the start of the expansion recursion
+ // and therefore have to create an expander.
Err(expander) => (
RefMut::map(expander, |it| {
it.insert(Expander::new(
@@ -362,9 +365,14 @@ impl<'a> TyLoweringContext<'a> {
.exit(self.db.upcast(), mark);
Some(ty)
}
- _ => None,
+ _ => {
+ drop(expander);
+ None
+ }
}
};
+
+ // drop the expander, resetting it to pre-recursion state
if recursion_start {
*self.expander.borrow_mut() = None;
}
@@ -974,13 +982,44 @@ impl<'a> TyLoweringContext<'a> {
fn lower_dyn_trait(&self, bounds: &[Interned<TypeBound>]) -> Ty {
let self_ty = TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(Interner);
let bounds = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
- QuantifiedWhereClauses::from_iter(
+ let bounds =
+ bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false));
+
+ let mut auto_traits = SmallVec::<[_; 8]>::new();
+ let mut regular_traits = SmallVec::<[_; 2]>::new();
+ let mut other_bounds = SmallVec::<[_; 8]>::new();
+ for bound in bounds {
+ if let Some(id) = bound.trait_id() {
+ if ctx.db.trait_data(from_chalk_trait_id(id)).is_auto {
+ auto_traits.push(bound);
+ } else {
+ regular_traits.push(bound);
+ }
+ } else {
+ other_bounds.push(bound);
+ }
+ }
+
+ if regular_traits.len() > 1 {
+ return None;
+ }
+
+ auto_traits.sort_unstable_by_key(|b| b.trait_id().unwrap());
+ auto_traits.dedup();
+
+ Some(QuantifiedWhereClauses::from_iter(
Interner,
- bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false)),
- )
+ regular_traits.into_iter().chain(other_bounds).chain(auto_traits),
+ ))
});
- let bounds = crate::make_single_type_binders(bounds);
- TyKind::Dyn(DynTy { bounds, lifetime: static_lifetime() }).intern(Interner)
+
+ if let Some(bounds) = bounds {
+ let bounds = crate::make_single_type_binders(bounds);
+ TyKind::Dyn(DynTy { bounds, lifetime: static_lifetime() }).intern(Interner)
+ } else {
+ // FIXME: report error (additional non-auto traits)
+ TyKind::Error.intern(Interner)
+ }
}
fn lower_impl_trait(