Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 2 additions & 5 deletions crates/hir-def/src/body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use crate::{
path::{ModPath, Path},
src::HasSource,
type_ref::{TypeRef, TypeRefId, TypesMap, TypesSourceMap},
BlockId, DefWithBodyId, HasModule, Lookup,
BlockId, DefWithBodyId, HasModule, Lookup, SyntheticSyntax,
};

/// A wrapper around [`span::SyntaxContextId`] that is intended only for comparisons.
Expand Down Expand Up @@ -141,7 +141,7 @@ pub struct BodySourceMap {
field_map_back: FxHashMap<ExprId, FieldSource>,
pat_field_map_back: FxHashMap<PatId, PatFieldSource>,

types: TypesSourceMap,
pub types: TypesSourceMap,

// FIXME: Make this a sane struct.
template_map: Option<
Expand All @@ -160,9 +160,6 @@ pub struct BodySourceMap {
diagnostics: Vec<BodyDiagnostic>,
}

#[derive(Default, Debug, Eq, PartialEq, Clone, Copy)]
pub struct SyntheticSyntax;

#[derive(Debug, Eq, PartialEq)]
pub enum BodyDiagnostic {
InactiveCode { node: InFile<SyntaxNodePtr>, cfg: CfgExpr, opts: CfgOptions },
Expand Down
2 changes: 1 addition & 1 deletion crates/hir-def/src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ impl ImplData {

let item_tree = tree_id.item_tree(db);
let impl_def = &item_tree[tree_id.value];
let target_trait = impl_def.target_trait.clone();
let target_trait = impl_def.target_trait;
let self_ty = impl_def.self_ty;
let is_negative = impl_def.is_negative;
let is_unsafe = impl_def.is_unsafe;
Expand Down
27 changes: 19 additions & 8 deletions crates/hir-def/src/generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ use crate::{
nameres::{DefMap, MacroSubNs},
path::{AssociatedTypeBinding, GenericArg, GenericArgs, NormalPath, Path},
type_ref::{
ArrayType, ConstRef, FnType, LifetimeRef, RefType, TypeBound, TypeRef, TypeRefId, TypesMap,
TypesSourceMap,
ArrayType, ConstRef, FnType, LifetimeRef, PathId, RefType, TypeBound, TypeRef, TypeRefId,
TypesMap, TypesSourceMap,
},
AdtId, ConstParamId, GenericDefId, HasModule, ItemTreeLoc, LifetimeParamId,
LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, TypeOrConstParamId, TypeParamId,
Expand Down Expand Up @@ -224,6 +224,11 @@ impl GenericParams {
self.len() == 0
}

#[inline]
pub fn no_predicates(&self) -> bool {
self.where_predicates.is_empty()
}

#[inline]
pub fn where_predicates(&self) -> std::slice::Iter<'_, WherePredicate> {
self.where_predicates.iter()
Expand Down Expand Up @@ -874,14 +879,20 @@ fn copy_type_bound(
to: &mut TypesMap,
to_source_map: &mut TypesSourceMap,
) -> TypeBound {
let mut copy_path_id = |path: PathId| {
let new_path = copy_path(&from[path], from, from_source_map, to, to_source_map);
let new_path_id = to.types.alloc(TypeRef::Path(new_path));
if let Some(&ptr) = from_source_map.types_map_back.get(path.type_ref()) {
to_source_map.types_map_back.insert(new_path_id, ptr);
}
PathId::from_type_ref_unchecked(new_path_id)
};

match bound {
TypeBound::Path(path, modifier) => {
TypeBound::Path(copy_path(path, from, from_source_map, to, to_source_map), *modifier)
&TypeBound::Path(path, modifier) => TypeBound::Path(copy_path_id(path), modifier),
TypeBound::ForLifetime(lifetimes, path) => {
TypeBound::ForLifetime(lifetimes.clone(), copy_path_id(*path))
}
TypeBound::ForLifetime(lifetimes, path) => TypeBound::ForLifetime(
lifetimes.clone(),
copy_path(path, from, from_source_map, to, to_source_map),
),
TypeBound::Lifetime(lifetime) => TypeBound::Lifetime(lifetime.clone()),
TypeBound::Use(use_args) => TypeBound::Use(use_args.clone()),
TypeBound::Error => TypeBound::Error,
Expand Down
86 changes: 64 additions & 22 deletions crates/hir-def/src/hir/type_ref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use crate::{
hir::Literal,
lower::LowerCtx,
path::{GenericArg, Path},
SyntheticSyntax,
};

#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
Expand Down Expand Up @@ -91,19 +92,37 @@ impl Rawness {
}
}

#[derive(Clone, PartialEq, Eq, Hash, Debug)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
/// A `TypeRefId` that is guaranteed to always be `TypeRef::Path`. We use this for things like
/// impl's trait, that are always paths but need to be traced back to source code.
pub struct PathId(TypeRefId);

impl PathId {
#[inline]
pub fn from_type_ref_unchecked(type_ref: TypeRefId) -> Self {
Self(type_ref)
}

#[inline]
pub fn type_ref(self) -> TypeRefId {
self.0
}
}

#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub struct TraitRef {
pub path: Path,
pub path: PathId,
}

impl TraitRef {
/// Converts an `ast::PathType` to a `hir::TraitRef`.
pub(crate) fn from_ast(ctx: &mut LowerCtx<'_>, node: ast::Type) -> Option<Self> {
// FIXME: Use `Path::from_src`
match node {
ast::Type::PathType(path) => {
path.path().and_then(|it| ctx.lower_path(it)).map(|path| TraitRef { path })
}
match &node {
ast::Type::PathType(path) => path
.path()
.and_then(|it| ctx.lower_path(it))
.map(|path| TraitRef { path: ctx.alloc_path(path, AstPtr::new(&node)) }),
_ => None,
}
}
Expand Down Expand Up @@ -173,11 +192,24 @@ impl TypesMap {
impl Index<TypeRefId> for TypesMap {
type Output = TypeRef;

#[inline]
fn index(&self, index: TypeRefId) -> &Self::Output {
&self.types[index]
}
}

impl Index<PathId> for TypesMap {
type Output = Path;

#[inline]
fn index(&self, index: PathId) -> &Self::Output {
let TypeRef::Path(path) = &self[index.type_ref()] else {
unreachable!("`PathId` always points to `TypeRef::Path`");
};
path
}
}

pub type TypePtr = AstPtr<ast::Type>;
pub type TypeSource = InFile<TypePtr>;

Expand All @@ -187,6 +219,12 @@ pub struct TypesSourceMap {
}

impl TypesSourceMap {
pub const EMPTY: Self = Self { types_map_back: ArenaMap::new() };

pub fn type_syntax(&self, id: TypeRefId) -> Result<TypeSource, SyntheticSyntax> {
self.types_map_back.get(id).cloned().ok_or(SyntheticSyntax)
}

pub(crate) fn shrink_to_fit(&mut self) {
let TypesSourceMap { types_map_back } = self;
types_map_back.shrink_to_fit();
Expand Down Expand Up @@ -214,15 +252,15 @@ impl LifetimeRef {

#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub enum TypeBound {
Path(Path, TraitBoundModifier),
ForLifetime(Box<[Name]>, Path),
Path(PathId, TraitBoundModifier),
ForLifetime(Box<[Name]>, PathId),
Lifetime(LifetimeRef),
Use(Box<[UseArgRef]>),
Comment on lines +256 to 258
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could shrink it by another 8 bytes now if we made these wide boxes thin boxes, something to keep in mind

Error,
}

#[cfg(target_pointer_width = "64")]
const _: [(); 32] = [(); ::std::mem::size_of::<TypeBound>()];
const _: [(); 24] = [(); ::std::mem::size_of::<TypeBound>()];

#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub enum UseArgRef {
Expand Down Expand Up @@ -365,8 +403,8 @@ impl TypeRef {
TypeRef::ImplTrait(bounds) | TypeRef::DynTrait(bounds) => {
for bound in bounds {
match bound {
TypeBound::Path(path, _) | TypeBound::ForLifetime(_, path) => {
go_path(path, f, map)
&TypeBound::Path(path, _) | &TypeBound::ForLifetime(_, path) => {
go_path(&map[path], f, map)
}
TypeBound::Lifetime(_) | TypeBound::Error | TypeBound::Use(_) => (),
}
Expand Down Expand Up @@ -397,8 +435,8 @@ impl TypeRef {
}
for bound in binding.bounds.iter() {
match bound {
TypeBound::Path(path, _) | TypeBound::ForLifetime(_, path) => {
go_path(path, f, map)
&TypeBound::Path(path, _) | &TypeBound::ForLifetime(_, path) => {
go_path(&map[path], f, map)
}
TypeBound::Lifetime(_) | TypeBound::Error | TypeBound::Use(_) => (),
}
Expand All @@ -425,16 +463,18 @@ pub(crate) fn type_bounds_from_ast(

impl TypeBound {
pub(crate) fn from_ast(ctx: &mut LowerCtx<'_>, node: ast::TypeBound) -> Self {
let mut lower_path_type = |path_type: ast::PathType| ctx.lower_path(path_type.path()?);
let mut lower_path_type = |path_type: &ast::PathType| ctx.lower_path(path_type.path()?);

match node.kind() {
ast::TypeBoundKind::PathType(path_type) => {
let m = match node.question_mark_token() {
Some(_) => TraitBoundModifier::Maybe,
None => TraitBoundModifier::None,
};
lower_path_type(path_type)
.map(|p| TypeBound::Path(p, m))
lower_path_type(&path_type)
.map(|p| {
TypeBound::Path(ctx.alloc_path(p, AstPtr::new(&path_type).upcast()), m)
})
.unwrap_or(TypeBound::Error)
}
ast::TypeBoundKind::ForType(for_type) => {
Expand All @@ -445,12 +485,14 @@ impl TypeBound {
.collect(),
None => Box::default(),
};
let path = for_type.ty().and_then(|ty| match ty {
ast::Type::PathType(path_type) => lower_path_type(path_type),
let path = for_type.ty().and_then(|ty| match &ty {
ast::Type::PathType(path_type) => lower_path_type(path_type).map(|p| (p, ty)),
_ => None,
});
match path {
Some(p) => TypeBound::ForLifetime(lt_refs, p),
Some((p, ty)) => {
TypeBound::ForLifetime(lt_refs, ctx.alloc_path(p, AstPtr::new(&ty)))
}
None => TypeBound::Error,
}
}
Expand All @@ -470,10 +512,10 @@ impl TypeBound {
}
}

pub fn as_path(&self) -> Option<(&Path, &TraitBoundModifier)> {
pub fn as_path<'a>(&self, map: &'a TypesMap) -> Option<(&'a Path, TraitBoundModifier)> {
match self {
TypeBound::Path(p, m) => Some((p, m)),
TypeBound::ForLifetime(_, p) => Some((p, &TraitBoundModifier::None)),
&TypeBound::Path(p, m) => Some((&map[p], m)),
&TypeBound::ForLifetime(_, p) => Some((&map[p], TraitBoundModifier::None)),
TypeBound::Lifetime(_) | TypeBound::Error | TypeBound::Use(_) => None,
}
}
Expand Down
9 changes: 5 additions & 4 deletions crates/hir-def/src/item_tree/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use crate::{
lower::LowerCtx,
path::AssociatedTypeBinding,
type_ref::{
LifetimeRef, RefType, TraitBoundModifier, TraitRef, TypeBound, TypeRef, TypeRefId,
LifetimeRef, PathId, RefType, TraitBoundModifier, TraitRef, TypeBound, TypeRef, TypeRefId,
TypesMap, TypesSourceMap,
},
visibility::RawVisibility,
Expand Down Expand Up @@ -514,7 +514,7 @@ impl<'a> Ctx<'a> {
};

let ret_type = if func.async_token().is_some() {
let future_impl = desugar_future_path(ret_type);
let future_impl = desugar_future_path(&mut body_ctx, ret_type);
let ty_bound = TypeBound::Path(future_impl, TraitBoundModifier::None);
body_ctx.alloc_type_ref_desugared(TypeRef::ImplTrait(ThinVec::from_iter([ty_bound])))
} else {
Expand Down Expand Up @@ -936,7 +936,7 @@ impl<'a> Ctx<'a> {
}
}

fn desugar_future_path(orig: TypeRefId) -> Path {
fn desugar_future_path(ctx: &mut LowerCtx<'_>, orig: TypeRefId) -> PathId {
let path = path![core::future::Future];
let mut generic_args: Vec<_> =
std::iter::repeat(None).take(path.segments().len() - 1).collect();
Expand All @@ -948,7 +948,8 @@ fn desugar_future_path(orig: TypeRefId) -> Path {
};
generic_args.push(Some(GenericArgs { bindings: Box::new([binding]), ..GenericArgs::empty() }));

Path::from_known_path(path, generic_args)
let path = Path::from_known_path(path, generic_args);
PathId::from_type_ref_unchecked(ctx.alloc_type_ref_desugared(TypeRef::Path(path)))
}

enum HasImplicitSelf {
Expand Down
2 changes: 1 addition & 1 deletion crates/hir-def/src/item_tree/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,7 @@ impl Printer<'_> {
w!(self, "!");
}
if let Some(tr) = target_trait {
self.print_path(&tr.path, types_map);
self.print_path(&types_map[tr.path], types_map);
w!(self, " for ");
}
self.print_type_ref(*self_ty, types_map);
Expand Down
3 changes: 3 additions & 0 deletions crates/hir-def/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1535,3 +1535,6 @@ fn macro_call_as_call_id_with_eager(
pub struct UnresolvedMacro {
pub path: hir_expand::mod_path::ModPath,
}

#[derive(Default, Debug, Eq, PartialEq, Clone, Copy)]
pub struct SyntheticSyntax;
6 changes: 5 additions & 1 deletion crates/hir-def/src/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use triomphe::Arc;
use crate::{
db::DefDatabase,
path::Path,
type_ref::{TypeBound, TypePtr, TypeRef, TypeRefId, TypesMap, TypesSourceMap},
type_ref::{PathId, TypeBound, TypePtr, TypeRef, TypeRefId, TypesMap, TypesSourceMap},
};

pub struct LowerCtx<'a> {
Expand Down Expand Up @@ -142,4 +142,8 @@ impl<'a> LowerCtx<'a> {
pub(crate) fn alloc_error_type(&mut self) -> TypeRefId {
self.types_map.types.alloc(TypeRef::Error)
}

pub(crate) fn alloc_path(&mut self, path: Path, node: TypePtr) -> PathId {
PathId::from_type_ref_unchecked(self.alloc_type_ref(TypeRef::Path(path), node))
}
}
12 changes: 11 additions & 1 deletion crates/hir-def/src/path.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! A desugared representation of paths like `crate::foo` or `<Type as Trait>::bar`.
mod lower;
#[cfg(test)]
mod tests;

use std::{
fmt::{self, Display},
Expand All @@ -19,6 +21,8 @@ use syntax::ast;

pub use hir_expand::mod_path::{path, ModPath, PathKind};

pub use lower::hir_segment_to_ast_segment;

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ImportAlias {
/// Unnamed alias, as in `use Foo as _;`
Expand Down Expand Up @@ -230,7 +234,7 @@ impl Path {
}
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct PathSegment<'a> {
pub name: &'a Name,
pub args_and_bindings: Option<&'a GenericArgs>,
Expand Down Expand Up @@ -274,6 +278,12 @@ impl<'a> PathSegments<'a> {
generic_args: self.generic_args.map(|it| it.get(..len).unwrap_or(it)),
}
}
pub fn strip_last(&self) -> PathSegments<'a> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was wondering what this kind of function is usually called, given everything but the head is called usually tail. Haskell calls everything but the last element init, not sure I like that though

PathSegments {
segments: self.segments.split_last().map_or(&[], |it| it.1),
generic_args: self.generic_args.map(|it| it.split_last().map_or(&[][..], |it| it.1)),
}
}
pub fn iter(&self) -> impl Iterator<Item = PathSegment<'a>> {
self.segments
.iter()
Expand Down
Loading
Loading