//! FIXME: write short doc here
-use std::fmt;
+use std::{array, fmt};
-use arrayvec::ArrayVec;
use chalk_ir::Mutability;
use hir_def::{
db::DefDatabase,
find_path,
generics::TypeParamProvenance,
item_scope::ItemInNs,
- path::{GenericArg, Path, PathKind},
+ path::{Path, PathKind},
type_ref::{TypeBound, TypeRef},
visibility::Visibility,
AssocContainerId, Lookup, ModuleId, TraitId,
use crate::{
db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive,
to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy,
- CallableDefId, CallableSig, DomainGoal, ImplTraitId, Interner, Lifetime, OpaqueTy,
- ProjectionTy, QuantifiedWhereClause, Scalar, Substitution, TraitRef, Ty, TyKind, WhereClause,
+ CallableDefId, CallableSig, DomainGoal, GenericArg, ImplTraitId, Interner, Lifetime, OpaqueTy,
+ ProjectionTy, QuantifiedWhereClause, Scalar, TraitRef, Ty, TyExt, TyKind, WhereClause,
};
pub struct HirFormatter<'a> {
pub enum DisplaySourceCodeError {
PathNotFound,
UnknownType,
+ Closure,
}
pub enum HirDisplayError {
}
let trait_ = f.db.trait_data(self.trait_(f.db));
- let first_parameter = self.substitution[0].into_displayable(
+ let first_parameter = self.self_type_parameter().into_displayable(
f.db,
f.max_size,
f.omit_verbose_types,
f.display_target,
);
write!(f, "<{} as {}", first_parameter, trait_.name)?;
- if self.substitution.len() > 1 {
+ if self.substitution.len(&Interner) > 1 {
write!(f, "<")?;
- f.write_joined(&self.substitution[1..], ", ")?;
+ f.write_joined(&self.substitution.interned()[1..], ", ")?;
write!(f, ">")?;
}
write!(f, ">::{}", f.db.type_alias_data(from_assoc_type_id(self.associated_ty_id)).name)?;
return write!(f, "{}", TYPE_HINT_TRUNCATION);
}
- self.substitution[0].hir_fmt(f)
+ self.substitution.at(&Interner, 0).hir_fmt(f)
+ }
+}
+
+impl HirDisplay for GenericArg {
+ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
+ match self.interned() {
+ crate::GenericArgData::Ty(ty) => ty.hir_fmt(f),
+ }
}
}
return write!(f, "{}", TYPE_HINT_TRUNCATION);
}
- match self.interned(&Interner) {
+ match self.kind(&Interner) {
TyKind::Never => write!(f, "!")?,
TyKind::Str => write!(f, "str")?,
TyKind::Scalar(Scalar::Bool) => write!(f, "bool")?,
let ty_display =
t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target);
- if matches!(self.interned(&Interner), TyKind::Raw(..)) {
+ if matches!(self.kind(&Interner), TyKind::Raw(..)) {
write!(
f,
"*{}",
// FIXME: all this just to decide whether to use parentheses...
let datas;
- let predicates: Vec<_> = match t.interned(&Interner) {
+ let predicates: Vec<_> = match t.kind(&Interner) {
TyKind::Dyn(dyn_ty) if dyn_ty.bounds.skip_binders().interned().len() > 1 => {
dyn_ty.bounds.skip_binders().interned().iter().cloned().collect()
}
}
}
TyKind::Tuple(_, substs) => {
- if substs.len() == 1 {
+ if substs.len(&Interner) == 1 {
write!(f, "(")?;
- substs[0].hir_fmt(f)?;
+ substs.at(&Interner, 0).hir_fmt(f)?;
write!(f, ",)")?;
} else {
write!(f, "(")?;
- f.write_joined(&*substs.0, ", ")?;
+ f.write_joined(&*substs.interned(), ", ")?;
write!(f, ")")?;
}
}
write!(f, "{}", f.db.enum_data(e.parent).variants[e.local_id].name)?
}
};
- if parameters.len() > 0 {
+ if parameters.len(&Interner) > 0 {
let generics = generics(f.db.upcast(), def.into());
let (parent_params, self_param, type_params, _impl_trait_params) =
generics.provenance_split();
// We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self?
if total_len > 0 {
write!(f, "<")?;
- f.write_joined(¶meters.0[..total_len], ", ")?;
+ f.write_joined(¶meters.interned()[..total_len], ", ")?;
write!(f, ">")?;
}
}
f.write_joined(sig.params(), ", ")?;
write!(f, ")")?;
let ret = sig.ret();
- if *ret != Ty::unit() {
+ if !ret.is_unit() {
let ret_display = ret.into_displayable(
f.db,
f.max_size,
}
}
- if parameters.len() > 0 {
+ if parameters.len(&Interner) > 0 {
let parameters_to_write = if f.display_target.is_source_code()
|| f.omit_verbose_types()
{
.map(|generic_def_id| f.db.generic_defaults(generic_def_id))
.filter(|defaults| !defaults.is_empty())
{
- None => parameters.0.as_ref(),
+ None => parameters.interned().as_ref(),
Some(default_parameters) => {
let mut default_from = 0;
- for (i, parameter) in parameters.iter().enumerate() {
- match (parameter.interned(&Interner), default_parameters.get(i))
- {
- (&TyKind::Unknown, _) | (_, None) => {
+ for (i, parameter) in parameters.iter(&Interner).enumerate() {
+ match (
+ parameter.assert_ty_ref(&Interner).kind(&Interner),
+ default_parameters.get(i),
+ ) {
+ (&TyKind::Error, _) | (_, None) => {
default_from = i + 1;
}
(_, Some(default_parameter)) => {
let actual_default = default_parameter
.clone()
.subst(¶meters.prefix(i));
- if parameter != &actual_default {
+ if parameter.assert_ty_ref(&Interner) != &actual_default
+ {
default_from = i + 1;
}
}
}
}
- ¶meters.0[0..default_from]
+ ¶meters.interned()[0..default_from]
}
}
} else {
- parameters.0.as_ref()
+ parameters.interned().as_ref()
};
if !parameters_to_write.is_empty() {
write!(f, "<")?;
// Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types)
if f.display_target.is_test() {
write!(f, "{}::{}", trait_.name, type_alias_data.name)?;
- if parameters.len() > 0 {
+ if parameters.len(&Interner) > 0 {
write!(f, "<")?;
- f.write_joined(&*parameters.0, ", ")?;
+ f.write_joined(&*parameters.interned(), ", ")?;
write!(f, ">")?;
}
} else {
projection_ty.hir_fmt(f)?;
}
}
- TyKind::ForeignType(type_alias) => {
+ TyKind::Foreign(type_alias) => {
let type_alias = f.db.type_alias_data(from_foreign_def_id(*type_alias));
write!(f, "{}", type_alias.name)?;
}
}
ImplTraitId::AsyncBlockTypeImplTrait(..) => {
write!(f, "impl Future<Output = ")?;
- parameters[0].hir_fmt(f)?;
+ parameters.at(&Interner, 0).hir_fmt(f)?;
write!(f, ">")?;
}
}
}
TyKind::Closure(.., substs) => {
- let sig = substs[0].callable_sig(f.db);
+ if f.display_target.is_source_code() {
+ return Err(HirDisplayError::DisplaySourceCodeError(
+ DisplaySourceCodeError::Closure,
+ ));
+ }
+ let sig = substs.at(&Interner, 0).assert_ty_ref(&Interner).callable_sig(f.db);
if let Some(sig) = sig {
if sig.params().is_empty() {
write!(f, "||")?;
write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))?
}
TypeParamProvenance::ArgumentImplTrait => {
- let substs = Substitution::type_params_for_generics(f.db, &generics);
+ let substs = generics.type_params_subst(f.db);
let bounds = f
.db
.generic_predicates(id.parent)
}
};
}
- TyKind::Unknown => {
+ TyKind::Error => {
if f.display_target.is_source_code() {
return Err(HirDisplayError::DisplaySourceCodeError(
DisplaySourceCodeError::UnknownType,
}
write!(f, ")")?;
let ret = self.ret();
- if *ret != Ty::unit() {
+ if !ret.is_unit() {
let ret_display =
ret.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target);
write!(f, " -> {}", ret_display)?;
db.lang_item(krate, "fn_mut".into()),
db.lang_item(krate, "fn_once".into()),
];
- // FIXME: Replace ArrayVec when into_iter is a thing on arrays
- ArrayVec::from(fn_traits).into_iter().flatten().flat_map(|it| it.as_trait())
+ array::IntoIter::new(fn_traits).into_iter().flatten().flat_map(|it| it.as_trait())
}
pub fn write_bounds_like_dyn_trait_with_prefix(
// existential) here, which is the only thing that's
// possible in actual Rust, and hence don't print it
write!(f, "{}", f.db.trait_data(trait_).name)?;
- if let [_, params @ ..] = &*trait_ref.substitution.0 {
+ if let [_, params @ ..] = &*trait_ref.substitution.interned() {
if is_fn_trait {
- if let Some(args) = params.first().and_then(|it| it.as_tuple()) {
+ if let Some(args) =
+ params.first().and_then(|it| it.assert_ty_ref(&Interner).as_tuple())
+ {
write!(f, "(")?;
- f.write_joined(&*args.0, ", ")?;
+ f.write_joined(&*args.interned(), ", ")?;
write!(f, ")")?;
}
} else if !params.is_empty() {
return write!(f, "{}", TYPE_HINT_TRUNCATION);
}
- self.substitution[0].hir_fmt(f)?;
+ self.self_type_parameter().hir_fmt(f)?;
if use_as {
write!(f, " as ")?;
} else {
write!(f, ": ")?;
}
write!(f, "{}", f.db.trait_data(self.hir_trait_id()).name)?;
- if self.substitution.len() > 1 {
+ if self.substitution.len(&Interner) > 1 {
write!(f, "<")?;
- f.write_joined(&self.substitution[1..], ", ")?;
+ f.write_joined(&self.substitution.interned()[1..], ", ")?;
write!(f, ">")?;
}
Ok(())
}
}
-impl HirDisplay for GenericArg {
+impl HirDisplay for hir_def::path::GenericArg {
fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
match self {
- GenericArg::Type(ty) => ty.hir_fmt(f),
- GenericArg::Lifetime(lifetime) => write!(f, "{}", lifetime.name),
+ hir_def::path::GenericArg::Type(ty) => ty.hir_fmt(f),
+ hir_def::path::GenericArg::Lifetime(lifetime) => write!(f, "{}", lifetime.name),
}
}
}