Skip to content

Commit 6a76e20

Browse files
committed
Extend HIR to track the source of a type
1 parent 96d0406 commit 6a76e20

File tree

14 files changed

+75
-28
lines changed

14 files changed

+75
-28
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3889,6 +3889,7 @@ dependencies = [
38893889
name = "rustc_hir"
38903890
version = "0.0.0"
38913891
dependencies = [
3892+
"bitflags",
38923893
"odht",
38933894
"rustc_abi",
38943895
"rustc_arena",

compiler/rustc_ast_lowering/src/delegation.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ use std::iter;
4040

4141
use ast::visit::Visitor;
4242
use hir::def::{DefKind, PartialRes, Res};
43-
use hir::{BodyId, HirId};
43+
use hir::{BodyId, HirId, PathFlags};
4444
use rustc_abi::ExternAbi;
4545
use rustc_ast::*;
4646
use rustc_errors::ErrorGuaranteed;
@@ -264,7 +264,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
264264
hir_id: self.next_id(),
265265
res: Res::Local(param_id),
266266
args: None,
267-
infer_args: false,
267+
flags: PathFlags::empty(),
268268
}));
269269

270270
let path = self.arena.alloc(hir::Path { span, res: Res::Local(param_id), segments });
@@ -366,6 +366,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
366366
GenericArgsMode::Err,
367367
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
368368
None,
369+
PathFlags::empty(),
369370
);
370371
let segment = self.arena.alloc(segment);
371372

compiler/rustc_ast_lowering/src/expr.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@ use rustc_ast::ptr::P as AstP;
55
use rustc_ast::*;
66
use rustc_ast_pretty::pprust::expr_to_string;
77
use rustc_data_structures::stack::ensure_sufficient_stack;
8-
use rustc_hir as hir;
98
use rustc_hir::attrs::AttributeKind;
109
use rustc_hir::def::{DefKind, Res};
11-
use rustc_hir::{HirId, find_attr};
10+
use rustc_hir::{self as hir, HirId, PathFlags, find_attr};
1211
use rustc_middle::span_bug;
1312
use rustc_middle::ty::TyCtxt;
1413
use rustc_session::errors::report_lit_error;
@@ -126,6 +125,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
126125
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
127126
// Method calls can't have bound modifiers
128127
None,
128+
PathFlags::empty(),
129129
));
130130
let receiver = self.lower_expr(receiver);
131131
let args =

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId};
5454
use rustc_hir::lints::DelayedLint;
5555
use rustc_hir::{
5656
self as hir, AngleBrackets, ConstArg, GenericArg, HirId, ItemLocalMap, LifetimeSource,
57-
LifetimeSyntax, ParamName, TraitCandidate,
57+
LifetimeSyntax, ParamName, PathFlags, TraitCandidate,
5858
};
5959
use rustc_index::{Idx, IndexSlice, IndexVec};
6060
use rustc_macros::extension;
@@ -781,6 +781,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
781781
let def_id = self.tcx.require_lang_item(lang_item, span);
782782
let def_kind = self.tcx.def_kind(def_id);
783783
let res = Res::Def(def_kind, def_id);
784+
let mut flags = PathFlags::empty();
785+
flags.set(PathFlags::INFER_ARGS, args.is_none());
784786
self.arena.alloc(hir::Path {
785787
span,
786788
res,
@@ -789,7 +791,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
789791
hir_id: self.next_id(),
790792
res,
791793
args,
792-
infer_args: args.is_none(),
794+
flags,
793795
}]),
794796
})
795797
}

compiler/rustc_ast_lowering/src/path.rs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::sync::Arc;
33
use rustc_ast::{self as ast, *};
44
use rustc_hir::def::{DefKind, PartialRes, PerNS, Res};
55
use rustc_hir::def_id::DefId;
6-
use rustc_hir::{self as hir, GenericArg};
6+
use rustc_hir::{self as hir, GenericArg, PathFlags};
77
use rustc_middle::{span_bug, ty};
88
use rustc_session::parse::add_feature_diagnostics;
99
use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Ident, Span, Symbol, sym};
@@ -135,6 +135,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
135135
generic_args_mode,
136136
itctx(i),
137137
bound_modifier_allowed_features.clone(),
138+
PathFlags::empty(),
138139
)
139140
},
140141
)),
@@ -160,16 +161,23 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
160161
}
161162

162163
// Create the innermost type that we're projecting from.
163-
let mut ty = if path.segments.is_empty() {
164+
let (mut ty, flags) = if path.segments.is_empty() {
164165
// If the base path is empty that means there exists a
165166
// syntactical `Self`, e.g., `&i32` in `<&i32>::clone`.
166-
qself.expect("missing QSelf for <T>::...")
167+
(qself.expect("missing QSelf for <T>::..."), PathFlags::empty())
167168
} else {
168169
// Otherwise, the base path is an implicit `Self` type path,
169170
// e.g., `Vec` in `Vec::new` or `<I as Iterator>::Item` in
170171
// `<I as Iterator>::Item::default`.
171172
let new_id = self.next_id();
172-
self.arena.alloc(self.ty_path(new_id, path.span, hir::QPath::Resolved(qself, path)))
173+
(
174+
&*self.arena.alloc(self.ty_path(
175+
new_id,
176+
path.span,
177+
hir::QPath::Resolved(qself, path),
178+
)),
179+
PathFlags::IMPLICIT_SELF,
180+
)
173181
};
174182

175183
// Anything after the base path are associated "extensions",
@@ -199,6 +207,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
199207
generic_args_mode,
200208
itctx(i),
201209
None,
210+
flags,
202211
));
203212
let qpath = hir::QPath::TypeRelative(ty, hir_segment);
204213

@@ -241,6 +250,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
241250
GenericArgsMode::Err,
242251
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
243252
None,
253+
PathFlags::empty(),
244254
)
245255
})),
246256
span: self.lower_span(p.span),
@@ -258,6 +268,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
258268
// This is passed down to the implicit associated type binding in
259269
// parenthesized bounds.
260270
bound_modifier_allowed_features: Option<Arc<[Symbol]>>,
271+
mut flags: PathFlags,
261272
) -> hir::PathSegment<'hir> {
262273
debug!("path_span: {:?}, lower_path_segment(segment: {:?})", path_span, segment);
263274
let (mut generic_args, infer_args) = if let Some(generic_args) = segment.args.as_deref() {
@@ -400,11 +411,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
400411
segment.ident, segment.id, hir_id,
401412
);
402413

414+
flags.set(PathFlags::INFER_ARGS, infer_args);
415+
403416
hir::PathSegment {
404417
ident: self.lower_ident(segment.ident),
405418
hir_id,
406419
res: self.lower_res(res),
407-
infer_args,
420+
flags,
408421
args: if generic_args.is_empty() && generic_args.span.is_empty() {
409422
None
410423
} else {

compiler/rustc_hir/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ edition = "2024"
55

66
[dependencies]
77
# tidy-alphabetical-start
8+
bitflags = "2.4.1"
89
odht = { version = "0.3.1", features = ["nightly"] }
910
rustc_abi = { path = "../rustc_abi" }
1011
rustc_arena = { path = "../rustc_arena" }

compiler/rustc_hir/src/hir.rs

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ pub use rustc_ast::{
1616
};
1717
use rustc_data_structures::fingerprint::Fingerprint;
1818
use rustc_data_structures::sorted_map::SortedMap;
19+
use rustc_data_structures::stable_hasher::HashStable;
1920
use rustc_data_structures::tagged_ptr::TaggedRef;
2021
use rustc_index::IndexVec;
2122
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
@@ -374,17 +375,37 @@ pub struct PathSegment<'hir> {
374375
/// distinction.
375376
pub args: Option<&'hir GenericArgs<'hir>>,
376377

377-
/// Whether to infer remaining type parameters, if any.
378-
/// This only applies to expression and pattern paths, and
379-
/// out of those only the segments with no type parameters
380-
/// to begin with, e.g., `Vec::new` is `<Vec<..>>::new::<..>`.
381-
pub infer_args: bool,
378+
pub flags: PathFlags,
379+
}
380+
381+
bitflags::bitflags! {
382+
#[derive(Debug, Clone, Copy)]
383+
pub struct PathFlags: u8 {
384+
/// Whether to infer remaining type parameters, if any.
385+
/// This only applies to expression and pattern paths, and
386+
/// out of those only the segments with no type parameters
387+
/// to begin with, e.g., `Vec::new` is `<Vec<..>>::new::<..>`.
388+
const INFER_ARGS = 1 << 0;
389+
390+
/// Whether this path is an implicit `Self` type path.
391+
const IMPLICIT_SELF = 1 << 1;
392+
}
393+
}
394+
395+
impl<CTX> HashStable<CTX> for PathFlags {
396+
fn hash_stable(
397+
&self,
398+
hcx: &mut CTX,
399+
hasher: &mut rustc_data_structures::stable_hasher::StableHasher,
400+
) {
401+
self.bits().hash_stable(hcx, hasher)
402+
}
382403
}
383404

384405
impl<'hir> PathSegment<'hir> {
385406
/// Converts an identifier to the corresponding segment.
386407
pub fn new(ident: Ident, hir_id: HirId, res: Res) -> PathSegment<'hir> {
387-
PathSegment { ident, hir_id, res, infer_args: true, args: None }
408+
PathSegment { ident, hir_id, res, flags: PathFlags::INFER_ARGS, args: None }
388409
}
389410

390411
pub fn invalid() -> Self {
@@ -399,6 +420,14 @@ impl<'hir> PathSegment<'hir> {
399420
DUMMY
400421
}
401422
}
423+
424+
pub fn infer_args(&self) -> bool {
425+
self.flags.contains(PathFlags::INFER_ARGS)
426+
}
427+
428+
pub fn implicit_self(&self) -> bool {
429+
self.flags.contains(PathFlags::IMPLICIT_SELF)
430+
}
402431
}
403432

404433
/// A constant that enters the type system, used for arguments to const generics (e.g. array lengths).

compiler/rustc_hir/src/intravisit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1427,7 +1427,7 @@ pub fn walk_path_segment<'v, V: Visitor<'v>>(
14271427
visitor: &mut V,
14281428
segment: &'v PathSegment<'v>,
14291429
) -> V::Result {
1430-
let PathSegment { ident, hir_id, res: _, args, infer_args: _ } = segment;
1430+
let PathSegment { ident, hir_id, res: _, args, flags: _ } = segment;
14311431
try_visit!(visitor.visit_ident(*ident));
14321432
try_visit!(visitor.visit_id(*hir_id));
14331433
visit_opt!(visitor, visit_generic_args, *args);

compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use rustc_errors::struct_span_code_err;
66
use rustc_hir as hir;
77
use rustc_hir::def::{DefKind, Res};
88
use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
9-
use rustc_hir::{AmbigArg, PolyTraitRef};
9+
use rustc_hir::{AmbigArg, PathFlags, PolyTraitRef};
1010
use rustc_middle::bug;
1111
use rustc_middle::ty::{
1212
self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
@@ -602,7 +602,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
602602
hir_id: constraint.hir_id,
603603
res: Res::Err,
604604
args: Some(constraint.gen_args),
605-
infer_args: false,
605+
flags: PathFlags::empty(),
606606
};
607607

608608
let alias_args = self.lower_generic_args_of_assoc_item(

compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -427,8 +427,8 @@ pub(crate) fn check_generic_arg_count(
427427
})
428428
.count();
429429
let named_const_param_count = param_counts.consts - synth_const_param_count;
430-
let infer_lifetimes =
431-
(gen_pos != GenericArgPosition::Type || seg.infer_args) && !gen_args.has_lifetime_params();
430+
let infer_lifetimes = (gen_pos != GenericArgPosition::Type || seg.infer_args())
431+
&& !gen_args.has_lifetime_params();
432432

433433
if gen_pos != GenericArgPosition::Type
434434
&& let Some(c) = gen_args.constraints.first()
@@ -577,7 +577,7 @@ pub(crate) fn check_generic_arg_count(
577577
};
578578

579579
let args_correct = {
580-
let expected_min = if seg.infer_args {
580+
let expected_min = if seg.infer_args() {
581581
0
582582
} else {
583583
param_counts.consts + named_type_param_count

0 commit comments

Comments
 (0)