ImplTraitLoweringMode::Opaque => {
let idx = self.impl_trait_counter.get();
self.impl_trait_counter.set(idx + 1);
+ let func = match self.resolver.generic_def() {
+ Some(GenericDefId::FunctionId(f)) => f,
+ _ => panic!("opaque impl trait lowering in non-function"),
+ };
assert!(idx as usize == self.opaque_type_data.borrow().len());
// this dance is to make sure the data is in the right
// away instead of two.
let actual_opaque_type_data = self
.with_debruijn(DebruijnIndex::INNERMOST, |ctx| {
- ctx.lower_impl_trait(bounds)
+ ctx.lower_impl_trait(bounds, func)
});
self.opaque_type_data.borrow_mut()[idx as usize] = actual_opaque_type_data;
- 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 = self.db.intern_impl_trait_id(impl_trait_id).into();
let generics = generics(self.db.upcast(), func.into());
let mut expander = self.expander.borrow_mut();
if expander.is_some() {
(Some(expander), false)
+ } else if let Some(module_id) = self.resolver.module() {
+ *expander =
+ Some(Expander::new(self.db.upcast(), macro_call.file_id, module_id));
+ (Some(expander), true)
} else {
- if let Some(module_id) = self.resolver.module() {
- *expander = Some(Expander::new(
- self.db.upcast(),
- macro_call.file_id,
- module_id,
- ));
- (Some(expander), true)
- } else {
- (None, false)
- }
+ (None, false)
}
};
let ty = if let Some(mut expander) = expander {
res: Option<TypeNs>,
remaining_segments: PathSegments<'_>,
) -> (Ty, Option<TypeNs>) {
- if remaining_segments.len() == 1 {
- // resolve unselected assoc types
- let segment = remaining_segments.first().unwrap();
- (self.select_associated_type(res, segment), None)
- } else if remaining_segments.len() > 1 {
- // FIXME report error (ambiguous associated type)
- (TyKind::Error.intern(&Interner), None)
- } else {
- (ty, res)
+ match remaining_segments.len() {
+ 0 => (ty, res),
+ 1 => {
+ // resolve unselected assoc types
+ let segment = remaining_segments.first().unwrap();
+ (self.select_associated_type(res, segment), None)
+ }
+ _ => {
+ // FIXME report error (ambiguous associated type)
+ (TyKind::Error.intern(&Interner), None)
+ }
}
}
) -> (Ty, Option<TypeNs>) {
let ty = match resolution {
TypeNs::TraitId(trait_) => {
- // if this is a bare dyn Trait, we'll directly put the required ^0 for the self type in there
- let self_ty = if remaining_segments.len() == 0 {
- Some(
- TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
- .intern(&Interner),
- )
- } else {
- None
- };
- let trait_ref =
- 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 = self
- .db
- .trait_data(trait_ref.hir_trait_id())
- .associated_type_by_name(segment.name);
- match found {
- Some(associated_ty) => {
- // FIXME handle type parameters on the segment
- TyKind::Alias(AliasTy::Projection(ProjectionTy {
- associated_ty_id: to_assoc_type_id(associated_ty),
- substitution: trait_ref.substitution,
- }))
- .intern(&Interner)
- }
- None => {
- // FIXME: report error (associated type not found)
- TyKind::Error.intern(&Interner)
+ let ty = match remaining_segments.len() {
+ 1 => {
+ let trait_ref =
+ self.lower_trait_ref_from_resolved_path(trait_, resolved_segment, None);
+ let segment = remaining_segments.first().unwrap();
+ let found = self
+ .db
+ .trait_data(trait_ref.hir_trait_id())
+ .associated_type_by_name(segment.name);
+ match found {
+ Some(associated_ty) => {
+ // FIXME handle type parameters on the segment
+ TyKind::Alias(AliasTy::Projection(ProjectionTy {
+ associated_ty_id: to_assoc_type_id(associated_ty),
+ substitution: trait_ref.substitution,
+ }))
+ .intern(&Interner)
+ }
+ None => {
+ // FIXME: report error (associated type not found)
+ TyKind::Error.intern(&Interner)
+ }
}
}
- } else if remaining_segments.len() > 1 {
- // FIXME report error (ambiguous associated type)
- TyKind::Error.intern(&Interner)
- } else {
- let dyn_ty = DynTy {
- bounds: crate::make_only_type_binders(
- 1,
- QuantifiedWhereClauses::from_iter(
- &Interner,
- Some(crate::wrap_empty_binders(WhereClause::Implemented(
- trait_ref,
- ))),
+ 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_only_type_binders(
+ 1,
+ QuantifiedWhereClauses::from_iter(
+ &Interner,
+ Some(crate::wrap_empty_binders(WhereClause::Implemented(
+ trait_ref,
+ ))),
+ ),
),
- ),
- lifetime: static_lifetime(),
- };
- TyKind::Dyn(dyn_ty).intern(&Interner)
+ lifetime: static_lifetime(),
+ };
+ TyKind::Dyn(dyn_ty).intern(&Interner)
+ }
+ _ => {
+ // FIXME report error (ambiguous associated type)
+ TyKind::Error.intern(&Interner)
+ }
};
return (ty, None);
}
trait_ref: TraitRef,
) -> impl Iterator<Item = QuantifiedWhereClause> + 'a {
let last_segment = match bound {
- TypeBound::Path(path, TraitBoundModifier::None) | TypeBound::ForLifetime(_, path) => path.segments().last(),
+ TypeBound::Path(path, TraitBoundModifier::None) | TypeBound::ForLifetime(_, path) => {
+ path.segments().last()
+ }
TypeBound::Path(_, TraitBoundModifier::Maybe)
| TypeBound::Error
| TypeBound::Lifetime(_) => None,
})
}
- fn lower_impl_trait(&self, bounds: &[Interned<TypeBound>]) -> ReturnTypeImplTrait {
+ fn lower_impl_trait(
+ &self,
+ bounds: &[Interned<TypeBound>],
+ func: FunctionId,
+ ) -> ReturnTypeImplTrait {
cov_mark::hit!(lower_rpit);
let self_ty =
TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner);
let predicates = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
- bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false)).collect()
+ let mut predicates: Vec<_> = bounds
+ .iter()
+ .flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false))
+ .collect();
+
+ if !ctx.unsized_types.borrow().contains(&self_ty) {
+ let krate = func.lookup(ctx.db.upcast()).module(ctx.db.upcast()).krate();
+ let sized_trait = ctx
+ .db
+ .lang_item(krate, "sized".into())
+ .and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id));
+ let sized_clause = sized_trait.map(|trait_id| {
+ let clause = WhereClause::Implemented(TraitRef {
+ trait_id,
+ substitution: Substitution::from1(&Interner, self_ty.clone()),
+ });
+ crate::wrap_empty_binders(clause)
+ });
+ predicates.extend(sized_clause.into_iter());
+ predicates.shrink_to_fit();
+ }
+ predicates
});
+
ReturnTypeImplTrait { bounds: crate::make_only_type_binders(1, predicates) }
}
}
let ctx =
TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
let generics = generics(db.upcast(), param_id.parent);
- resolver
+ let mut predicates: Vec<_> = resolver
.where_predicates_in_scope()
// we have to filter out all other predicates *first*, before attempting to lower them
.filter(|pred| match pred {
WherePredicate::Lifetime { .. } => false,
})
.flat_map(|pred| ctx.lower_where_predicate(pred, true).map(|p| make_binders(&generics, p)))
- .collect()
+ .collect();
+
+ let subst = generics.bound_vars_subst(DebruijnIndex::INNERMOST);
+ let explicitly_unsized_tys = ctx.unsized_types.into_inner();
+ let implicitly_sized_predicates =
+ implicitly_sized_clauses(db, param_id.parent, &explicitly_unsized_tys, &subst, &resolver)
+ .map(|p| make_binders(&generics, crate::wrap_empty_binders(p)));
+ predicates.extend(implicitly_sized_predicates);
+ predicates.into()
}
pub(crate) fn generic_predicates_for_param_recover(
}
pub(crate) fn impl_self_ty_query(db: &dyn HirDatabase, impl_id: ImplId) -> Binders<Ty> {
+ let impl_loc = impl_id.lookup(db.upcast());
let impl_data = db.impl_data(impl_id);
let resolver = impl_id.resolver(db.upcast());
+ let _cx = stdx::panic_context::enter(format!(
+ "impl_self_ty_query({:?} -> {:?} -> {:?})",
+ impl_id, impl_loc, impl_data
+ ));
let generics = generics(db.upcast(), impl_id.into());
let ctx =
TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
}
pub(crate) fn impl_trait_query(db: &dyn HirDatabase, impl_id: ImplId) -> Option<Binders<TraitRef>> {
+ let impl_loc = impl_id.lookup(db.upcast());
let impl_data = db.impl_data(impl_id);
let resolver = impl_id.resolver(db.upcast());
+ let _cx = stdx::panic_context::enter(format!(
+ "impl_trait_query({:?} -> {:?} -> {:?})",
+ impl_id, impl_loc, impl_data
+ ));
let ctx =
TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
let (self_ty, binders) = db.impl_self_ty(impl_id).into_value_and_skipped_binders();