//!
//! This usually involves resolving names, collecting generic arguments etc.
use std::{
- cell::{Cell, RefCell},
+ cell::{Cell, RefCell, RefMut},
iter,
sync::Arc,
};
use base_db::CrateId;
-use chalk_ir::{cast::Cast, fold::Fold, fold::Shift, interner::HasInterner, Mutability, Safety};
+use chalk_ir::{
+ cast::Cast, fold::Shift, fold::TypeFoldable, interner::HasInterner, Mutability, Safety,
+};
use hir_def::{
adt::StructKind,
use crate::{
all_super_traits,
- consteval::{intern_scalar_const, path_to_const, unknown_const, unknown_const_as_generic},
+ consteval::{intern_const_scalar, path_to_const, unknown_const, unknown_const_as_generic},
db::HirDatabase,
make_binders,
mapping::ToChalk,
pub fn with_debruijn<T>(
&self,
debruijn: DebruijnIndex,
- f: impl FnOnce(&TyLoweringContext) -> T,
+ f: impl FnOnce(&TyLoweringContext<'_>) -> T,
) -> T {
let opaque_ty_data_vec = self.opaque_type_data.take();
let expander = self.expander.take();
pub fn with_shifted_in<T>(
&self,
debruijn: DebruijnIndex,
- f: impl FnOnce(&TyLoweringContext) -> T,
+ f: impl FnOnce(&TyLoweringContext<'_>) -> T,
) -> T {
self.with_debruijn(self.in_binders.shifted_in_from(debruijn), f)
}
})
.intern(Interner)
}
- TypeRef::DynTrait(bounds) => {
- let self_ty =
- TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(Interner);
- let bounds = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
- QuantifiedWhereClauses::from_iter(
- Interner,
- bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false)),
- )
- });
- let bounds = crate::make_single_type_binders(bounds);
- TyKind::Dyn(DynTy { bounds, lifetime: static_lifetime() }).intern(Interner)
- }
+ TypeRef::DynTrait(bounds) => self.lower_dyn_trait(bounds),
TypeRef::ImplTrait(bounds) => {
match self.impl_trait_mode {
ImplTraitLoweringMode::Opaque => {
}
}
TypeRef::Macro(macro_call) => {
- let (expander, recursion_start) = {
- let mut expander = self.expander.borrow_mut();
- if expander.is_some() {
- (Some(expander), false)
- } else {
- *expander = Some(Expander::new(
- self.db.upcast(),
- macro_call.file_id,
- self.resolver.module(),
- ));
- (Some(expander), true)
+ let (mut expander, recursion_start) = {
+ match RefMut::filter_map(self.expander.borrow_mut(), Option::as_mut) {
+ Ok(expander) => (expander, false),
+ Err(expander) => (
+ RefMut::map(expander, |it| {
+ it.insert(Expander::new(
+ self.db.upcast(),
+ macro_call.file_id,
+ self.resolver.module(),
+ ))
+ }),
+ true,
+ ),
}
};
- let ty = if let Some(mut expander) = expander {
- let expander_mut = expander.as_mut().unwrap();
+ let ty = {
let macro_call = macro_call.to_node(self.db.upcast());
- match expander_mut.enter_expand::<ast::Type>(self.db.upcast(), macro_call) {
+ match expander.enter_expand::<ast::Type>(self.db.upcast(), macro_call) {
Ok(ExpandResult { value: Some((mark, expanded)), .. }) => {
- let ctx =
- LowerCtx::new(self.db.upcast(), expander_mut.current_file_id());
+ let ctx = LowerCtx::new(self.db.upcast(), expander.current_file_id());
let type_ref = TypeRef::from_ast(&ctx, expanded);
drop(expander);
}
_ => None,
}
- } else {
- None
};
if recursion_start {
*self.expander.borrow_mut() = None;
}
}
0 => {
- let self_ty = Some(
- TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
- .intern(Interner),
- );
- let trait_ref = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
- ctx.lower_trait_ref_from_resolved_path(
- trait_,
- resolved_segment,
- self_ty,
- )
- });
- let dyn_ty = DynTy {
- bounds: crate::make_single_type_binders(
- QuantifiedWhereClauses::from_iter(
- Interner,
- Some(crate::wrap_empty_binders(WhereClause::Implemented(
- trait_ref,
- ))),
- ),
- ),
- lifetime: static_lifetime(),
- };
- TyKind::Dyn(dyn_ty).intern(Interner)
+ // Trait object type without dyn; this should be handled in upstream. See
+ // `lower_path()`.
+ stdx::never!("unexpected fully resolved trait path");
+ TyKind::Error.intern(Interner)
}
_ => {
// FIXME report error (ambiguous associated type)
TyKind::Placeholder(to_placeholder_idx(self.db, param_id.into()))
}
ParamLoweringMode::Variable => {
- let idx = generics.param_idx(param_id.into()).expect("matching generics");
+ let idx = match generics.param_idx(param_id.into()) {
+ None => {
+ never!("no matching generics");
+ return (TyKind::Error.intern(Interner), None);
+ }
+ Some(idx) => idx,
+ };
+
TyKind::BoundVar(BoundVar::new(self.in_binders, idx))
}
}
let (ty, res) = self.lower_ty_ext(type_ref);
return self.lower_ty_relative_path(ty, res, path.segments());
}
+
let (resolution, remaining_index) =
match self.resolver.resolve_path_in_type_ns(self.db.upcast(), path.mod_path()) {
Some(it) => it,
None => return (TyKind::Error.intern(Interner), None),
};
+
+ if matches!(resolution, TypeNs::TraitId(_)) && remaining_index.is_none() {
+ // trait object type without dyn
+ let bound = TypeBound::Path(path.clone(), TraitBoundModifier::None);
+ let ty = self.lower_dyn_trait(&[Interned::new(bound)]);
+ return (ty, None);
+ }
+
let (resolved_segment, remaining_segments) = match remaining_index {
None => (
path.segments().last().expect("resolved path has at least one element"),
})
}
+ 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(
+ Interner,
+ bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false)),
+ )
+ });
+ let bounds = crate::make_single_type_binders(bounds);
+ TyKind::Dyn(DynTy { bounds, lifetime: static_lifetime() }).intern(Interner)
+ }
+
fn lower_impl_trait(
&self,
bounds: &[Interned<TypeBound>],
}
/// Build the signature of a callable item (function, struct or enum variant).
-pub fn callable_item_sig(db: &dyn HirDatabase, def: CallableDefId) -> PolyFnSig {
+pub(crate) fn callable_item_sig(db: &dyn HirDatabase, def: CallableDefId) -> PolyFnSig {
match def {
CallableDefId::FunctionId(f) => fn_sig_for_fn(db, f),
CallableDefId::StructId(s) => fn_sig_for_struct_constructor(db, s),
let ctx =
TyLoweringContext::new(db, &resolver).with_type_param_mode(ParamLoweringMode::Variable);
for (field_id, field_data) in var_data.fields().iter() {
- res.insert(field_id, make_binders(db, &generics, ctx.lower_ty(&field_data.type_ref)))
+ res.insert(field_id, make_binders(db, &generics, ctx.lower_ty(&field_data.type_ref)));
}
Arc::new(res)
}
return false;
}
}
- WherePredicateTypeTarget::TypeOrConstParam(local_id) => {
- if *local_id != param_id.local_id {
+ &WherePredicateTypeTarget::TypeOrConstParam(local_id) => {
+ let target_id = TypeOrConstParamId { parent: def, local_id };
+ if target_id != param_id {
return false;
}
}
debruijn: DebruijnIndex,
) -> Const {
match value {
- ConstScalarOrPath::Scalar(s) => intern_scalar_const(s.clone(), expected_ty),
+ ConstScalarOrPath::Scalar(s) => intern_const_scalar(s.clone(), expected_ty),
ConstScalarOrPath::Path(n) => {
let path = ModPath::from_segments(PathKind::Plain, Some(n.clone()));
path_to_const(db, resolver, &path, mode, args, debruijn)
/// This replaces any 'free' Bound vars in `s` (i.e. those with indices past
/// num_vars_to_keep) by `TyKind::Unknown`.
-fn fallback_bound_vars<T: Fold<Interner> + HasInterner<Interner = Interner>>(
+fn fallback_bound_vars<T: TypeFoldable<Interner> + HasInterner<Interner = Interner>>(
s: T,
num_vars_to_keep: usize,
-) -> T::Result {
+) -> T {
crate::fold_free_vars(
s,
|bound, binders| {