Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 39aab98

Browse files
authored
Merge pull request rust-lang#18541 from ChayimFriedman2/different-generic-args
feat: Complete diagnostics in ty lowering groundwork and serve a first diagnostic 🎉
2 parents 609621d + 1aae522 commit 39aab98

File tree

34 files changed

+1549
-233
lines changed

34 files changed

+1549
-233
lines changed

src/tools/rust-analyzer/Cargo.lock

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,7 @@ dependencies = [
509509
"base-db",
510510
"cfg",
511511
"either",
512+
"expect-test",
512513
"hir-def",
513514
"hir-expand",
514515
"hir-ty",
@@ -519,6 +520,9 @@ dependencies = [
519520
"span",
520521
"stdx",
521522
"syntax",
523+
"syntax-bridge",
524+
"test-fixture",
525+
"test-utils",
522526
"tracing",
523527
"triomphe",
524528
"tt",

src/tools/rust-analyzer/crates/hir-def/src/body.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use crate::{
3131
path::{ModPath, Path},
3232
src::HasSource,
3333
type_ref::{TypeRef, TypeRefId, TypesMap, TypesSourceMap},
34-
BlockId, DefWithBodyId, HasModule, Lookup,
34+
BlockId, DefWithBodyId, HasModule, Lookup, SyntheticSyntax,
3535
};
3636

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

144-
types: TypesSourceMap,
144+
pub types: TypesSourceMap,
145145

146146
// FIXME: Make this a sane struct.
147147
template_map: Option<
@@ -160,9 +160,6 @@ pub struct BodySourceMap {
160160
diagnostics: Vec<BodyDiagnostic>,
161161
}
162162

163-
#[derive(Default, Debug, Eq, PartialEq, Clone, Copy)]
164-
pub struct SyntheticSyntax;
165-
166163
#[derive(Debug, Eq, PartialEq)]
167164
pub enum BodyDiagnostic {
168165
InactiveCode { node: InFile<SyntaxNodePtr>, cfg: CfgExpr, opts: CfgOptions },

src/tools/rust-analyzer/crates/hir-def/src/data.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ impl ImplData {
369369

370370
let item_tree = tree_id.item_tree(db);
371371
let impl_def = &item_tree[tree_id.value];
372-
let target_trait = impl_def.target_trait.clone();
372+
let target_trait = impl_def.target_trait;
373373
let self_ty = impl_def.self_ty;
374374
let is_negative = impl_def.is_negative;
375375
let is_unsafe = impl_def.is_unsafe;

src/tools/rust-analyzer/crates/hir-def/src/generics.rs

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ use crate::{
2626
nameres::{DefMap, MacroSubNs},
2727
path::{AssociatedTypeBinding, GenericArg, GenericArgs, NormalPath, Path},
2828
type_ref::{
29-
ArrayType, ConstRef, FnType, LifetimeRef, RefType, TypeBound, TypeRef, TypeRefId, TypesMap,
30-
TypesSourceMap,
29+
ArrayType, ConstRef, FnType, LifetimeRef, PathId, RefType, TypeBound, TypeRef, TypeRefId,
30+
TypesMap, TypesSourceMap,
3131
},
3232
AdtId, ConstParamId, GenericDefId, HasModule, ItemTreeLoc, LifetimeParamId,
3333
LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, TypeOrConstParamId, TypeParamId,
@@ -224,6 +224,11 @@ impl GenericParams {
224224
self.len() == 0
225225
}
226226

227+
#[inline]
228+
pub fn no_predicates(&self) -> bool {
229+
self.where_predicates.is_empty()
230+
}
231+
227232
#[inline]
228233
pub fn where_predicates(&self) -> std::slice::Iter<'_, WherePredicate> {
229234
self.where_predicates.iter()
@@ -874,14 +879,20 @@ fn copy_type_bound(
874879
to: &mut TypesMap,
875880
to_source_map: &mut TypesSourceMap,
876881
) -> TypeBound {
882+
let mut copy_path_id = |path: PathId| {
883+
let new_path = copy_path(&from[path], from, from_source_map, to, to_source_map);
884+
let new_path_id = to.types.alloc(TypeRef::Path(new_path));
885+
if let Some(&ptr) = from_source_map.types_map_back.get(path.type_ref()) {
886+
to_source_map.types_map_back.insert(new_path_id, ptr);
887+
}
888+
PathId::from_type_ref_unchecked(new_path_id)
889+
};
890+
877891
match bound {
878-
TypeBound::Path(path, modifier) => {
879-
TypeBound::Path(copy_path(path, from, from_source_map, to, to_source_map), *modifier)
892+
&TypeBound::Path(path, modifier) => TypeBound::Path(copy_path_id(path), modifier),
893+
TypeBound::ForLifetime(lifetimes, path) => {
894+
TypeBound::ForLifetime(lifetimes.clone(), copy_path_id(*path))
880895
}
881-
TypeBound::ForLifetime(lifetimes, path) => TypeBound::ForLifetime(
882-
lifetimes.clone(),
883-
copy_path(path, from, from_source_map, to, to_source_map),
884-
),
885896
TypeBound::Lifetime(lifetime) => TypeBound::Lifetime(lifetime.clone()),
886897
TypeBound::Use(use_args) => TypeBound::Use(use_args.clone()),
887898
TypeBound::Error => TypeBound::Error,

src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs

Lines changed: 64 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use crate::{
2323
hir::Literal,
2424
lower::LowerCtx,
2525
path::{GenericArg, Path},
26+
SyntheticSyntax,
2627
};
2728

2829
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
@@ -91,19 +92,37 @@ impl Rawness {
9192
}
9293
}
9394

94-
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
95+
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
96+
/// A `TypeRefId` that is guaranteed to always be `TypeRef::Path`. We use this for things like
97+
/// impl's trait, that are always paths but need to be traced back to source code.
98+
pub struct PathId(TypeRefId);
99+
100+
impl PathId {
101+
#[inline]
102+
pub fn from_type_ref_unchecked(type_ref: TypeRefId) -> Self {
103+
Self(type_ref)
104+
}
105+
106+
#[inline]
107+
pub fn type_ref(self) -> TypeRefId {
108+
self.0
109+
}
110+
}
111+
112+
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
95113
pub struct TraitRef {
96-
pub path: Path,
114+
pub path: PathId,
97115
}
98116

99117
impl TraitRef {
100118
/// Converts an `ast::PathType` to a `hir::TraitRef`.
101119
pub(crate) fn from_ast(ctx: &mut LowerCtx<'_>, node: ast::Type) -> Option<Self> {
102120
// FIXME: Use `Path::from_src`
103-
match node {
104-
ast::Type::PathType(path) => {
105-
path.path().and_then(|it| ctx.lower_path(it)).map(|path| TraitRef { path })
106-
}
121+
match &node {
122+
ast::Type::PathType(path) => path
123+
.path()
124+
.and_then(|it| ctx.lower_path(it))
125+
.map(|path| TraitRef { path: ctx.alloc_path(path, AstPtr::new(&node)) }),
107126
_ => None,
108127
}
109128
}
@@ -173,11 +192,24 @@ impl TypesMap {
173192
impl Index<TypeRefId> for TypesMap {
174193
type Output = TypeRef;
175194

195+
#[inline]
176196
fn index(&self, index: TypeRefId) -> &Self::Output {
177197
&self.types[index]
178198
}
179199
}
180200

201+
impl Index<PathId> for TypesMap {
202+
type Output = Path;
203+
204+
#[inline]
205+
fn index(&self, index: PathId) -> &Self::Output {
206+
let TypeRef::Path(path) = &self[index.type_ref()] else {
207+
unreachable!("`PathId` always points to `TypeRef::Path`");
208+
};
209+
path
210+
}
211+
}
212+
181213
pub type TypePtr = AstPtr<ast::Type>;
182214
pub type TypeSource = InFile<TypePtr>;
183215

@@ -187,6 +219,12 @@ pub struct TypesSourceMap {
187219
}
188220

189221
impl TypesSourceMap {
222+
pub const EMPTY: Self = Self { types_map_back: ArenaMap::new() };
223+
224+
pub fn type_syntax(&self, id: TypeRefId) -> Result<TypeSource, SyntheticSyntax> {
225+
self.types_map_back.get(id).cloned().ok_or(SyntheticSyntax)
226+
}
227+
190228
pub(crate) fn shrink_to_fit(&mut self) {
191229
let TypesSourceMap { types_map_back } = self;
192230
types_map_back.shrink_to_fit();
@@ -214,15 +252,15 @@ impl LifetimeRef {
214252

215253
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
216254
pub enum TypeBound {
217-
Path(Path, TraitBoundModifier),
218-
ForLifetime(Box<[Name]>, Path),
255+
Path(PathId, TraitBoundModifier),
256+
ForLifetime(Box<[Name]>, PathId),
219257
Lifetime(LifetimeRef),
220258
Use(Box<[UseArgRef]>),
221259
Error,
222260
}
223261

224262
#[cfg(target_pointer_width = "64")]
225-
const _: [(); 32] = [(); ::std::mem::size_of::<TypeBound>()];
263+
const _: [(); 24] = [(); ::std::mem::size_of::<TypeBound>()];
226264

227265
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
228266
pub enum UseArgRef {
@@ -365,8 +403,8 @@ impl TypeRef {
365403
TypeRef::ImplTrait(bounds) | TypeRef::DynTrait(bounds) => {
366404
for bound in bounds {
367405
match bound {
368-
TypeBound::Path(path, _) | TypeBound::ForLifetime(_, path) => {
369-
go_path(path, f, map)
406+
&TypeBound::Path(path, _) | &TypeBound::ForLifetime(_, path) => {
407+
go_path(&map[path], f, map)
370408
}
371409
TypeBound::Lifetime(_) | TypeBound::Error | TypeBound::Use(_) => (),
372410
}
@@ -397,8 +435,8 @@ impl TypeRef {
397435
}
398436
for bound in binding.bounds.iter() {
399437
match bound {
400-
TypeBound::Path(path, _) | TypeBound::ForLifetime(_, path) => {
401-
go_path(path, f, map)
438+
&TypeBound::Path(path, _) | &TypeBound::ForLifetime(_, path) => {
439+
go_path(&map[path], f, map)
402440
}
403441
TypeBound::Lifetime(_) | TypeBound::Error | TypeBound::Use(_) => (),
404442
}
@@ -425,16 +463,18 @@ pub(crate) fn type_bounds_from_ast(
425463

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

430468
match node.kind() {
431469
ast::TypeBoundKind::PathType(path_type) => {
432470
let m = match node.question_mark_token() {
433471
Some(_) => TraitBoundModifier::Maybe,
434472
None => TraitBoundModifier::None,
435473
};
436-
lower_path_type(path_type)
437-
.map(|p| TypeBound::Path(p, m))
474+
lower_path_type(&path_type)
475+
.map(|p| {
476+
TypeBound::Path(ctx.alloc_path(p, AstPtr::new(&path_type).upcast()), m)
477+
})
438478
.unwrap_or(TypeBound::Error)
439479
}
440480
ast::TypeBoundKind::ForType(for_type) => {
@@ -445,12 +485,14 @@ impl TypeBound {
445485
.collect(),
446486
None => Box::default(),
447487
};
448-
let path = for_type.ty().and_then(|ty| match ty {
449-
ast::Type::PathType(path_type) => lower_path_type(path_type),
488+
let path = for_type.ty().and_then(|ty| match &ty {
489+
ast::Type::PathType(path_type) => lower_path_type(path_type).map(|p| (p, ty)),
450490
_ => None,
451491
});
452492
match path {
453-
Some(p) => TypeBound::ForLifetime(lt_refs, p),
493+
Some((p, ty)) => {
494+
TypeBound::ForLifetime(lt_refs, ctx.alloc_path(p, AstPtr::new(&ty)))
495+
}
454496
None => TypeBound::Error,
455497
}
456498
}
@@ -470,10 +512,10 @@ impl TypeBound {
470512
}
471513
}
472514

473-
pub fn as_path(&self) -> Option<(&Path, &TraitBoundModifier)> {
515+
pub fn as_path<'a>(&self, map: &'a TypesMap) -> Option<(&'a Path, TraitBoundModifier)> {
474516
match self {
475-
TypeBound::Path(p, m) => Some((p, m)),
476-
TypeBound::ForLifetime(_, p) => Some((p, &TraitBoundModifier::None)),
517+
&TypeBound::Path(p, m) => Some((&map[p], m)),
518+
&TypeBound::ForLifetime(_, p) => Some((&map[p], TraitBoundModifier::None)),
477519
TypeBound::Lifetime(_) | TypeBound::Error | TypeBound::Use(_) => None,
478520
}
479521
}

src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use crate::{
3434
lower::LowerCtx,
3535
path::AssociatedTypeBinding,
3636
type_ref::{
37-
LifetimeRef, RefType, TraitBoundModifier, TraitRef, TypeBound, TypeRef, TypeRefId,
37+
LifetimeRef, PathId, RefType, TraitBoundModifier, TraitRef, TypeBound, TypeRef, TypeRefId,
3838
TypesMap, TypesSourceMap,
3939
},
4040
visibility::RawVisibility,
@@ -514,7 +514,7 @@ impl<'a> Ctx<'a> {
514514
};
515515

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

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

951-
Path::from_known_path(path, generic_args)
951+
let path = Path::from_known_path(path, generic_args);
952+
PathId::from_type_ref_unchecked(ctx.alloc_type_ref_desugared(TypeRef::Path(path)))
952953
}
953954

954955
enum HasImplicitSelf {

src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,7 @@ impl Printer<'_> {
484484
w!(self, "!");
485485
}
486486
if let Some(tr) = target_trait {
487-
self.print_path(&tr.path, types_map);
487+
self.print_path(&types_map[tr.path], types_map);
488488
w!(self, " for ");
489489
}
490490
self.print_type_ref(*self_ty, types_map);

src/tools/rust-analyzer/crates/hir-def/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1535,3 +1535,6 @@ fn macro_call_as_call_id_with_eager(
15351535
pub struct UnresolvedMacro {
15361536
pub path: hir_expand::mod_path::ModPath,
15371537
}
1538+
1539+
#[derive(Default, Debug, Eq, PartialEq, Clone, Copy)]
1540+
pub struct SyntheticSyntax;

src/tools/rust-analyzer/crates/hir-def/src/lower.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use triomphe::Arc;
1010
use crate::{
1111
db::DefDatabase,
1212
path::Path,
13-
type_ref::{TypeBound, TypePtr, TypeRef, TypeRefId, TypesMap, TypesSourceMap},
13+
type_ref::{PathId, TypeBound, TypePtr, TypeRef, TypeRefId, TypesMap, TypesSourceMap},
1414
};
1515

1616
pub struct LowerCtx<'a> {
@@ -142,4 +142,8 @@ impl<'a> LowerCtx<'a> {
142142
pub(crate) fn alloc_error_type(&mut self) -> TypeRefId {
143143
self.types_map.types.alloc(TypeRef::Error)
144144
}
145+
146+
pub(crate) fn alloc_path(&mut self, path: Path, node: TypePtr) -> PathId {
147+
PathId::from_type_ref_unchecked(self.alloc_type_ref(TypeRef::Path(path), node))
148+
}
145149
}

src/tools/rust-analyzer/crates/hir-def/src/path.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//! A desugared representation of paths like `crate::foo` or `<Type as Trait>::bar`.
22
mod lower;
3+
#[cfg(test)]
4+
mod tests;
35

46
use std::{
57
fmt::{self, Display},
@@ -19,6 +21,8 @@ use syntax::ast;
1921

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

24+
pub use lower::hir_segment_to_ast_segment;
25+
2226
#[derive(Debug, Clone, PartialEq, Eq)]
2327
pub enum ImportAlias {
2428
/// Unnamed alias, as in `use Foo as _;`
@@ -230,7 +234,7 @@ impl Path {
230234
}
231235
}
232236

233-
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
237+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
234238
pub struct PathSegment<'a> {
235239
pub name: &'a Name,
236240
pub args_and_bindings: Option<&'a GenericArgs>,
@@ -274,6 +278,12 @@ impl<'a> PathSegments<'a> {
274278
generic_args: self.generic_args.map(|it| it.get(..len).unwrap_or(it)),
275279
}
276280
}
281+
pub fn strip_last(&self) -> PathSegments<'a> {
282+
PathSegments {
283+
segments: self.segments.split_last().map_or(&[], |it| it.1),
284+
generic_args: self.generic_args.map(|it| it.split_last().map_or(&[][..], |it| it.1)),
285+
}
286+
}
277287
pub fn iter(&self) -> impl Iterator<Item = PathSegment<'a>> {
278288
self.segments
279289
.iter()

0 commit comments

Comments
 (0)