1 //! HIR for references to types. Paths in these are not yet resolved. They can
2 //! be directly created from an ast::TypeRef, without further queries.
3 use hir_expand::name::Name;
6 use crate::{body::LowerCtx, path::Path};
8 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
15 pub fn from_mutable(mutable: bool) -> Mutability {
23 pub fn as_keyword_for_ref(self) -> &'static str {
25 Mutability::Shared => "",
26 Mutability::Mut => "mut ",
30 pub fn as_keyword_for_ptr(self) -> &'static str {
32 Mutability::Shared => "const ",
33 Mutability::Mut => "mut ",
38 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
45 pub fn from_raw(is_raw: bool) -> Rawness {
54 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
60 /// Converts an `ast::PathType` to a `hir::TraitRef`.
61 pub(crate) fn from_ast(ctx: &LowerCtx, node: ast::Type) -> Option<Self> {
62 // FIXME: Use `Path::from_src`
64 ast::Type::PathType(path) => {
65 path.path().and_then(|it| ctx.lower_path(it)).map(|path| TraitRef { path })
72 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
78 RawPtr(Box<TypeRef>, Mutability),
79 Reference(Box<TypeRef>, Option<LifetimeRef>, Mutability),
80 Array(Box<TypeRef> /*, Expr*/),
82 /// A fn pointer. Last element of the vector is the return type.
83 Fn(Vec<TypeRef>, bool /*varargs*/),
85 ImplTrait(Vec<TypeBound>),
86 DynTrait(Vec<TypeBound>),
90 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
91 pub struct LifetimeRef {
96 pub(crate) fn new_name(name: Name) -> Self {
100 pub(crate) fn new(lifetime: &ast::Lifetime) -> Self {
101 LifetimeRef { name: Name::new_lifetime(lifetime) }
104 pub fn missing() -> LifetimeRef {
105 LifetimeRef { name: Name::missing() }
109 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
112 // ForLifetime(Vec<LifetimeRef>, Path), FIXME ForLifetime
113 Lifetime(LifetimeRef),
118 /// Converts an `ast::TypeRef` to a `hir::TypeRef`.
119 pub(crate) fn from_ast(ctx: &LowerCtx, node: ast::Type) -> Self {
121 ast::Type::ParenType(inner) => TypeRef::from_ast_opt(&ctx, inner.ty()),
122 ast::Type::TupleType(inner) => {
123 TypeRef::Tuple(inner.fields().map(|it| TypeRef::from_ast(ctx, it)).collect())
125 ast::Type::NeverType(..) => TypeRef::Never,
126 ast::Type::PathType(inner) => {
127 // FIXME: Use `Path::from_src`
130 .and_then(|it| ctx.lower_path(it))
132 .unwrap_or(TypeRef::Error)
134 ast::Type::PtrType(inner) => {
135 let inner_ty = TypeRef::from_ast_opt(&ctx, inner.ty());
136 let mutability = Mutability::from_mutable(inner.mut_token().is_some());
137 TypeRef::RawPtr(Box::new(inner_ty), mutability)
139 ast::Type::ArrayType(inner) => {
140 TypeRef::Array(Box::new(TypeRef::from_ast_opt(&ctx, inner.ty())))
142 ast::Type::SliceType(inner) => {
143 TypeRef::Slice(Box::new(TypeRef::from_ast_opt(&ctx, inner.ty())))
145 ast::Type::RefType(inner) => {
146 let inner_ty = TypeRef::from_ast_opt(&ctx, inner.ty());
147 let lifetime = inner.lifetime().map(|lt| LifetimeRef::new(<));
148 let mutability = Mutability::from_mutable(inner.mut_token().is_some());
149 TypeRef::Reference(Box::new(inner_ty), lifetime, mutability)
151 ast::Type::InferType(_inner) => TypeRef::Placeholder,
152 ast::Type::FnPtrType(inner) => {
155 .and_then(|rt| rt.ty())
156 .map(|it| TypeRef::from_ast(ctx, it))
157 .unwrap_or_else(|| TypeRef::Tuple(Vec::new()));
158 let mut is_varargs = false;
159 let mut params = if let Some(pl) = inner.param_list() {
160 if let Some(param) = pl.params().last() {
161 is_varargs = param.dotdotdot_token().is_some();
164 pl.params().map(|p| p.ty()).map(|it| TypeRef::from_ast_opt(&ctx, it)).collect()
169 TypeRef::Fn(params, is_varargs)
171 // for types are close enough for our purposes to the inner type for now...
172 ast::Type::ForType(inner) => TypeRef::from_ast_opt(&ctx, inner.ty()),
173 ast::Type::ImplTraitType(inner) => {
174 TypeRef::ImplTrait(type_bounds_from_ast(ctx, inner.type_bound_list()))
176 ast::Type::DynTraitType(inner) => {
177 TypeRef::DynTrait(type_bounds_from_ast(ctx, inner.type_bound_list()))
179 // FIXME: Macros in type position are not yet supported.
180 ast::Type::MacroType(_) => TypeRef::Error,
184 pub(crate) fn from_ast_opt(ctx: &LowerCtx, node: Option<ast::Type>) -> Self {
185 if let Some(node) = node {
186 TypeRef::from_ast(ctx, node)
192 pub(crate) fn unit() -> TypeRef {
193 TypeRef::Tuple(Vec::new())
196 pub fn walk(&self, f: &mut impl FnMut(&TypeRef)) {
199 fn go(type_ref: &TypeRef, f: &mut impl FnMut(&TypeRef)) {
202 TypeRef::Fn(types, _) | TypeRef::Tuple(types) => {
203 types.iter().for_each(|t| go(t, f))
205 TypeRef::RawPtr(type_ref, _)
206 | TypeRef::Reference(type_ref, ..)
207 | TypeRef::Array(type_ref)
208 | TypeRef::Slice(type_ref) => go(&type_ref, f),
209 TypeRef::ImplTrait(bounds) | TypeRef::DynTrait(bounds) => {
210 for bound in bounds {
212 TypeBound::Path(path) => go_path(path, f),
213 TypeBound::Lifetime(_) | TypeBound::Error => (),
217 TypeRef::Path(path) => go_path(path, f),
218 TypeRef::Never | TypeRef::Placeholder | TypeRef::Error => {}
222 fn go_path(path: &Path, f: &mut impl FnMut(&TypeRef)) {
223 if let Some(type_ref) = path.type_anchor() {
226 for segment in path.segments().iter() {
227 if let Some(args_and_bindings) = segment.args_and_bindings {
228 for arg in &args_and_bindings.args {
230 crate::path::GenericArg::Type(type_ref) => {
233 crate::path::GenericArg::Lifetime(_) => {}
236 for binding in &args_and_bindings.bindings {
237 if let Some(type_ref) = &binding.type_ref {
240 for bound in &binding.bounds {
242 TypeBound::Path(path) => go_path(path, f),
243 TypeBound::Lifetime(_) | TypeBound::Error => (),
253 pub(crate) fn type_bounds_from_ast(
254 lower_ctx: &LowerCtx,
255 type_bounds_opt: Option<ast::TypeBoundList>,
256 ) -> Vec<TypeBound> {
257 if let Some(type_bounds) = type_bounds_opt {
258 type_bounds.bounds().map(|it| TypeBound::from_ast(lower_ctx, it)).collect()
265 pub(crate) fn from_ast(ctx: &LowerCtx, node: ast::TypeBound) -> Self {
267 ast::TypeBoundKind::PathType(path_type) => {
268 let path = match path_type.path() {
270 None => return TypeBound::Error,
273 let path = match ctx.lower_path(path) {
275 None => return TypeBound::Error,
277 TypeBound::Path(path)
279 ast::TypeBoundKind::ForType(_) => TypeBound::Error, // FIXME ForType
280 ast::TypeBoundKind::Lifetime(lifetime) => {
281 TypeBound::Lifetime(LifetimeRef::new(&lifetime))
286 pub fn as_path(&self) -> Option<&Path> {
288 TypeBound::Path(p) => Some(p),