]> git.lizzy.rs Git - rust.git/blobdiff - crates/hir_ty/src/display.rs
Rename TyKind::ForeignType to Foreign
[rust.git] / crates / hir_ty / src / display.rs
index 9d3b79be39e5b08ef75715f85d235afed53fcdf1..5ff70c893a2328542c4768124b502659484b34f1 100644 (file)
@@ -1,15 +1,14 @@
 //! FIXME: write short doc here
 
-use std::{borrow::Cow, 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,
@@ -19,8 +18,8 @@
 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, 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> {
@@ -190,6 +189,7 @@ fn is_test(&self) -> bool {
 pub enum DisplaySourceCodeError {
     PathNotFound,
     UnknownType,
+    Closure,
 }
 
 pub enum HirDisplayError {
@@ -251,16 +251,16 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), 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)?;
@@ -274,7 +274,15 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
             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),
+        }
     }
 }
 
@@ -284,7 +292,7 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
             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")?,
@@ -306,7 +314,7 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
                 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,
                         "*{}",
@@ -328,9 +336,9 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
 
                 // FIXME: all this just to decide whether to use parentheses...
                 let datas;
-                let predicates = match t.interned(&Interner) {
-                    TyKind::Dyn(predicates) if predicates.len() > 1 => {
-                        Cow::Borrowed(predicates.as_ref())
+                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::Alias(AliasTy::Opaque(OpaqueTy {
                         opaque_ty_id,
@@ -345,17 +353,21 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
                                 .as_ref()
                                 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
                             let bounds = data.subst(parameters);
-                            Cow::Owned(bounds.value)
+                            bounds.value
                         } else {
-                            Cow::Borrowed(&[][..])
+                            Vec::new()
                         }
                     }
-                    _ => Cow::Borrowed(&[][..]),
+                    _ => Vec::new(),
                 };
 
-                if let [WhereClause::Implemented(trait_ref), _] = predicates.as_ref() {
+                if let Some(WhereClause::Implemented(trait_ref)) =
+                    predicates.get(0).map(|b| b.skip_binders())
+                {
                     let trait_ = trait_ref.hir_trait_id();
-                    if fn_traits(f.db.upcast(), trait_).any(|it| it == trait_) {
+                    if fn_traits(f.db.upcast(), trait_).any(|it| it == trait_)
+                        && predicates.len() <= 2
+                    {
                         return write!(f, "{}", ty_display);
                     }
                 }
@@ -369,13 +381,13 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
                 }
             }
             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, ")")?;
                 }
             }
@@ -395,7 +407,7 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
                         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();
@@ -403,7 +415,7 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
                     // 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(&parameters.0[..total_len], ", ")?;
+                        f.write_joined(&parameters.interned()[..total_len], ", ")?;
                         write!(f, ">")?;
                     }
                 }
@@ -411,7 +423,7 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
                 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,
@@ -447,7 +459,7 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
                     }
                 }
 
-                if parameters.len() > 0 {
+                if parameters.len(&Interner) > 0 {
                     let parameters_to_write = if f.display_target.is_source_code()
                         || f.omit_verbose_types()
                     {
@@ -456,30 +468,33 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
                             .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(&parameters.prefix(i));
-                                            if parameter != &actual_default {
+                                            if parameter.assert_ty_ref(&Interner) != &actual_default
+                                            {
                                                 default_from = i + 1;
                                             }
                                         }
                                     }
                                 }
-                                &parameters.0[0..default_from]
+                                &parameters.interned()[0..default_from]
                             }
                         }
                     } else {
-                        parameters.0.as_ref()
+                        parameters.interned().as_ref()
                     };
                     if !parameters_to_write.is_empty() {
                         write!(f, "<")?;
@@ -500,9 +515,9 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
                 // 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 {
@@ -514,7 +529,7 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
                     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)?;
             }
@@ -533,13 +548,18 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
                     }
                     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, "||")?;
@@ -571,13 +591,13 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
                         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)
                             .into_iter()
                             .map(|pred| pred.clone().subst(&substs))
-                            .filter(|wc| match &wc {
+                            .filter(|wc| match &wc.skip_binders() {
                                 WhereClause::Implemented(tr) => tr.self_type_parameter() == self,
                                 WhereClause::AliasEq(AliasEq {
                                     alias: AliasTy::Projection(proj),
@@ -591,8 +611,12 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
                 }
             }
             TyKind::BoundVar(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?,
-            TyKind::Dyn(predicates) => {
-                write_bounds_like_dyn_trait_with_prefix("dyn", predicates, f)?;
+            TyKind::Dyn(dyn_ty) => {
+                write_bounds_like_dyn_trait_with_prefix(
+                    "dyn",
+                    dyn_ty.bounds.skip_binders().interned(),
+                    f,
+                )?;
             }
             TyKind::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?,
             TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
@@ -612,7 +636,7 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
                     }
                 };
             }
-            TyKind::Unknown => {
+            TyKind::Error => {
                 if f.display_target.is_source_code() {
                     return Err(HirDisplayError::DisplaySourceCodeError(
                         DisplaySourceCodeError::UnknownType,
@@ -639,7 +663,7 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
         }
         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)?;
@@ -655,13 +679,12 @@ fn fn_traits(db: &dyn DefDatabase, trait_: TraitId) -> impl Iterator<Item = Trai
         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(
     prefix: &str,
-    predicates: &[WhereClause],
+    predicates: &[QuantifiedWhereClause],
     f: &mut HirFormatter,
 ) -> Result<(), HirDisplayError> {
     write!(f, "{}", prefix)?;
@@ -674,7 +697,7 @@ pub fn write_bounds_like_dyn_trait_with_prefix(
 }
 
 fn write_bounds_like_dyn_trait(
-    predicates: &[WhereClause],
+    predicates: &[QuantifiedWhereClause],
     f: &mut HirFormatter,
 ) -> Result<(), HirDisplayError> {
     // Note: This code is written to produce nice results (i.e.
@@ -687,7 +710,7 @@ fn write_bounds_like_dyn_trait(
     let mut angle_open = false;
     let mut is_fn_trait = false;
     for p in predicates.iter() {
-        match p {
+        match p.skip_binders() {
             WhereClause::Implemented(trait_ref) => {
                 let trait_ = trait_ref.hir_trait_id();
                 if !is_fn_trait {
@@ -704,11 +727,13 @@ fn write_bounds_like_dyn_trait(
                 // 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() {
@@ -755,16 +780,16 @@ fn hir_fmt_ext(&self, f: &mut HirFormatter, use_as: bool) -> Result<(), HirDispl
             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(())
@@ -1004,11 +1029,11 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
     }
 }
 
-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),
         }
     }
 }