Skip to content

Commit 0f10ba6

Browse files
committed
Make hir::TyKind::TraitObject use tagged ptr
1 parent 3cd8fcb commit 0f10ba6

File tree

20 files changed

+84
-48
lines changed

20 files changed

+84
-48
lines changed

compiler/rustc_ast/src/ast.rs

+26-3
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use rustc_data_structures::packed::Pu128;
2828
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
2929
use rustc_data_structures::stack::ensure_sufficient_stack;
3030
use rustc_data_structures::sync::Lrc;
31+
use rustc_data_structures::tagged_ptr::Tag;
3132
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
3233
pub use rustc_span::AttrId;
3334
use rustc_span::source_map::{Spanned, respan};
@@ -2269,10 +2270,32 @@ impl TyKind {
22692270

22702271
/// Syntax used to declare a trait object.
22712272
#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
2273+
#[repr(u8)]
22722274
pub enum TraitObjectSyntax {
2273-
Dyn,
2274-
DynStar,
2275-
None,
2275+
// SAFETY: When adding new variants make sure to update the `Tag` impl.
2276+
Dyn = 0,
2277+
DynStar = 1,
2278+
None = 2,
2279+
}
2280+
2281+
/// SAFETY: `TraitObjectSyntax` only has 3 data-less variants which means
2282+
/// it can be represented with a `u2`. We use `repr(u8)` to guarantee the
2283+
/// discriminants of the variants are no greater than `3`.
2284+
unsafe impl Tag for TraitObjectSyntax {
2285+
const BITS: u32 = 2;
2286+
2287+
fn into_usize(self) -> usize {
2288+
self as u8 as usize
2289+
}
2290+
2291+
unsafe fn from_usize(tag: usize) -> Self {
2292+
match tag {
2293+
0 => TraitObjectSyntax::Dyn,
2294+
1 => TraitObjectSyntax::DynStar,
2295+
2 => TraitObjectSyntax::None,
2296+
_ => unreachable!(),
2297+
}
2298+
}
22762299
}
22772300

22782301
#[derive(Clone, Encodable, Decodable, Debug)]

compiler/rustc_ast_lowering/src/lib.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ use rustc_data_structures::fingerprint::Fingerprint;
4848
use rustc_data_structures::sorted_map::SortedMap;
4949
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
5050
use rustc_data_structures::sync::Lrc;
51+
use rustc_data_structures::tagged_ptr::TaggedRef;
5152
use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, StashKey};
5253
use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
5354
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId};
@@ -1158,7 +1159,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
11581159
let lifetime_bound = this.elided_dyn_bound(t.span);
11591160
(bounds, lifetime_bound)
11601161
});
1161-
let kind = hir::TyKind::TraitObject(bounds, lifetime_bound, TraitObjectSyntax::None);
1162+
let kind = hir::TyKind::TraitObject(
1163+
bounds,
1164+
TaggedRef::new(lifetime_bound, TraitObjectSyntax::None),
1165+
);
11621166
return hir::Ty { kind, span: self.lower_span(t.span), hir_id: self.next_id() };
11631167
}
11641168

@@ -1309,7 +1313,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
13091313
lifetime_bound.unwrap_or_else(|| this.elided_dyn_bound(t.span));
13101314
(bounds, lifetime_bound)
13111315
});
1312-
hir::TyKind::TraitObject(bounds, lifetime_bound, *kind)
1316+
hir::TyKind::TraitObject(bounds, TaggedRef::new(lifetime_bound, *kind))
13131317
}
13141318
TyKind::ImplTrait(def_node_id, bounds) => {
13151319
let span = t.span;
@@ -2365,8 +2369,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
23652369
hir_id = self.next_id();
23662370
hir::TyKind::TraitObject(
23672371
arena_vec![self; principal],
2368-
self.elided_dyn_bound(span),
2369-
TraitObjectSyntax::None,
2372+
TaggedRef::new(self.elided_dyn_bound(span), TraitObjectSyntax::None),
23702373
)
23712374
}
23722375
_ => hir::TyKind::Path(hir::QPath::Resolved(None, path)),

compiler/rustc_borrowck/src/diagnostics/region_errors.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -887,7 +887,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
887887
if alias_ty.span.desugaring_kind().is_some() {
888888
// Skip `async` desugaring `impl Future`.
889889
}
890-
if let TyKind::TraitObject(_, lt, _) = alias_ty.kind {
890+
if let TyKind::TraitObject(_, lt) = alias_ty.kind {
891891
if lt.ident.name == kw::Empty {
892892
spans_suggs.push((lt.ident.span.shrink_to_hi(), " + 'a".to_string()));
893893
} else {

compiler/rustc_hir/src/hir.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ pub use rustc_ast::{
1515
};
1616
use rustc_data_structures::fingerprint::Fingerprint;
1717
use rustc_data_structures::sorted_map::SortedMap;
18+
use rustc_data_structures::tagged_ptr::TaggedRef;
1819
use rustc_index::IndexVec;
1920
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
2021
use rustc_span::def_id::LocalDefId;
@@ -764,11 +765,8 @@ impl<'hir> Generics<'hir> {
764765
&& let [.., segment] = trait_ref.path.segments
765766
&& let Some(ret_ty) = segment.args().paren_sugar_output()
766767
&& let ret_ty = ret_ty.peel_refs()
767-
&& let TyKind::TraitObject(
768-
_,
769-
_,
770-
TraitObjectSyntax::Dyn | TraitObjectSyntax::DynStar,
771-
) = ret_ty.kind
768+
&& let TyKind::TraitObject(_, tagged_ptr) = ret_ty.kind
769+
&& let TraitObjectSyntax::Dyn | TraitObjectSyntax::DynStar = tagged_ptr.tag()
772770
&& ret_ty.span.can_be_used_for_suggestions()
773771
{
774772
Some(ret_ty.span)
@@ -3230,7 +3228,10 @@ pub enum TyKind<'hir> {
32303228
TraitAscription(GenericBounds<'hir>),
32313229
/// A trait object type `Bound1 + Bound2 + Bound3`
32323230
/// where `Bound` is a trait or a lifetime.
3233-
TraitObject(&'hir [PolyTraitRef<'hir>], &'hir Lifetime, TraitObjectSyntax),
3231+
///
3232+
/// We use pointer tagging to represent a `&'hir Lifetime` and `TraitObjectSyntax` pair
3233+
/// as otherwise this type being `repr(C)` would result in `TyKind` increasing in size.
3234+
TraitObject(&'hir [PolyTraitRef<'hir>], TaggedRef<'hir, Lifetime, TraitObjectSyntax>),
32343235
/// Unused for now.
32353236
Typeof(&'hir AnonConst),
32363237
/// `TyKind::Infer` means the type should be inferred instead of it having been

compiler/rustc_hir/src/intravisit.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -922,7 +922,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Resul
922922
try_visit!(visitor.visit_ty(ty));
923923
try_visit!(visitor.visit_const_arg(length));
924924
}
925-
TyKind::TraitObject(bounds, ref lifetime, _syntax) => {
925+
TyKind::TraitObject(bounds, ref lifetime) => {
926926
for bound in bounds {
927927
try_visit!(visitor.visit_poly_trait_ref(bound));
928928
}

compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -810,7 +810,9 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
810810
intravisit::walk_ty(this, ty);
811811
});
812812
}
813-
hir::TyKind::TraitObject(bounds, lifetime, _) => {
813+
hir::TyKind::TraitObject(bounds, lifetime) => {
814+
let lifetime = lifetime.pointer();
815+
814816
debug!(?bounds, ?lifetime, "TraitObject");
815817
let scope = Scope::TraitRefBoundary { s: self.scope };
816818
self.with(scope, |this| {
@@ -827,7 +829,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
827829
// use the object lifetime defaulting
828830
// rules. So e.g., `Box<dyn Debug>` becomes
829831
// `Box<dyn Debug + 'static>`.
830-
self.resolve_object_lifetime_default(lifetime)
832+
self.resolve_object_lifetime_default(&*lifetime)
831833
}
832834
LifetimeName::Infer => {
833835
// If the user writes `'_`, we use the *ordinary* elision
@@ -838,7 +840,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
838840
}
839841
LifetimeName::Param(..) | LifetimeName::Static => {
840842
// If the user wrote an explicit name, use that.
841-
self.visit_lifetime(lifetime);
843+
self.visit_lifetime(&*lifetime);
842844
}
843845
LifetimeName::Error => {}
844846
}

compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
2323
) -> Option<ErrorGuaranteed> {
2424
let tcx = self.tcx();
2525

26-
let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) =
26+
let poly_trait_ref = if let hir::TyKind::TraitObject([poly_trait_ref, ..], tagged_ptr) =
2727
self_ty.kind
28-
else {
28+
&& let TraitObjectSyntax::None = tagged_ptr.tag()
29+
{
30+
poly_trait_ref
31+
} else {
2932
return None;
3033
};
3134

@@ -294,7 +297,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
294297
let (dyn_str, paren_dyn_str) =
295298
if borrowed { ("dyn ", "(dyn ") } else { ("&dyn ", "&(dyn ") };
296299

297-
let sugg = if let hir::TyKind::TraitObject([_, _, ..], _, _) = self_ty.kind {
300+
let sugg = if let hir::TyKind::TraitObject([_, _, ..], _) = self_ty.kind {
298301
// There are more than one trait bound, we need surrounding parentheses.
299302
vec![
300303
(self_ty.span.shrink_to_lo(), paren_dyn_str.to_string()),

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -2311,7 +2311,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
23112311
tcx.late_bound_vars(hir_ty.hir_id),
23122312
),
23132313
),
2314-
hir::TyKind::TraitObject(bounds, lifetime, repr) => {
2314+
hir::TyKind::TraitObject(bounds, tagged_ptr) => {
2315+
let lifetime = tagged_ptr.pointer();
2316+
let repr = tagged_ptr.tag();
2317+
23152318
if let Some(guar) = self.prohibit_or_lint_bare_trait_object_ty(hir_ty) {
23162319
// Don't continue with type analysis if the `dyn` keyword is missing
23172320
// It generates confusing errors, especially if the user meant to use another

compiler/rustc_hir_pretty/src/lib.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,8 @@ impl<'a> State<'a> {
402402
self.print_bounds("impl", bounds);
403403
}
404404
hir::TyKind::Path(ref qpath) => self.print_qpath(qpath, false),
405-
hir::TyKind::TraitObject(bounds, lifetime, syntax) => {
405+
hir::TyKind::TraitObject(bounds, lifetime) => {
406+
let syntax = lifetime.tag();
406407
match syntax {
407408
ast::TraitObjectSyntax::Dyn => self.word_nbsp("dyn"),
408409
ast::TraitObjectSyntax::DynStar => self.word_nbsp("dyn*"),
@@ -421,7 +422,7 @@ impl<'a> State<'a> {
421422
if !lifetime.is_elided() {
422423
self.nbsp();
423424
self.word_space("+");
424-
self.print_lifetime(lifetime);
425+
self.print_lifetime(lifetime.pointer());
425426
}
426427
}
427428
hir::TyKind::Array(ty, ref length) => {

compiler/rustc_lint/src/traits.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,9 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
111111
}
112112

113113
fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx>) {
114-
let hir::TyKind::TraitObject(bounds, _lifetime, _syntax) = &ty.kind else { return };
114+
let hir::TyKind::TraitObject(bounds, _lifetime_and_syntax_pointer) = &ty.kind else {
115+
return;
116+
};
115117
for bound in &bounds[..] {
116118
let def_id = bound.trait_ref.trait_def_id();
117119
if def_id.is_some_and(|def_id| cx.tcx.is_lang_item(def_id, LangItem::Drop)) {

compiler/rustc_middle/src/ty/diagnostics.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -572,16 +572,16 @@ pub struct TraitObjectVisitor<'tcx>(pub Vec<&'tcx hir::Ty<'tcx>>, pub crate::hir
572572
impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> {
573573
fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
574574
match ty.kind {
575-
hir::TyKind::TraitObject(
576-
_,
577-
hir::Lifetime {
575+
hir::TyKind::TraitObject(_, tagged_ptr)
576+
if let hir::Lifetime {
578577
res:
579578
hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static,
580579
..
581-
},
582-
_,
583-
)
584-
| hir::TyKind::OpaqueDef(..) => self.0.push(ty),
580+
} = tagged_ptr.pointer() =>
581+
{
582+
self.0.push(ty)
583+
}
584+
hir::TyKind::OpaqueDef(..) => self.0.push(ty),
585585
_ => {}
586586
}
587587
hir::intravisit::walk_ty(self, ty);

compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ pub fn suggest_new_region_bound(
374374
}
375375
}
376376
}
377-
TyKind::TraitObject(_, lt, _) => {
377+
TyKind::TraitObject(_, lt) => {
378378
if let LifetimeName::ImplicitObjectLifetimeDefault = lt.res {
379379
err.span_suggestion_verbose(
380380
fn_return.span.shrink_to_hi(),
@@ -592,11 +592,9 @@ pub struct HirTraitObjectVisitor<'a>(pub &'a mut Vec<Span>, pub DefId);
592592

593593
impl<'a, 'tcx> Visitor<'tcx> for HirTraitObjectVisitor<'a> {
594594
fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) {
595-
if let TyKind::TraitObject(
596-
poly_trait_refs,
597-
Lifetime { res: LifetimeName::ImplicitObjectLifetimeDefault, .. },
598-
_,
599-
) = t.kind
595+
if let TyKind::TraitObject(poly_trait_refs, lifetime_ptr) = t.kind
596+
&& let Lifetime { res: LifetimeName::ImplicitObjectLifetimeDefault, .. } =
597+
lifetime_ptr.pointer()
600598
{
601599
for ptr in poly_trait_refs {
602600
if Some(self.1) == ptr.trait_ref.trait_def_id() {

compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -580,8 +580,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
580580
self.tcx.hir_node_by_def_id(obligation.cause.body_id)
581581
&& let hir::ItemKind::Impl(impl_) = item.kind
582582
&& let None = impl_.of_trait
583-
&& let hir::TyKind::TraitObject(_, _, syntax) = impl_.self_ty.kind
584-
&& let TraitObjectSyntax::None = syntax
583+
&& let hir::TyKind::TraitObject(_, tagged_ptr) = impl_.self_ty.kind
584+
&& let TraitObjectSyntax::None = tagged_ptr.tag()
585585
&& impl_.self_ty.span.edition().at_least_rust_2021()
586586
{
587587
// Silence the dyn-compatibility error in favor of the missing dyn on

compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3074,7 +3074,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
30743074
}
30753075
if let Some(ty) = ty {
30763076
match ty.kind {
3077-
hir::TyKind::TraitObject(traits, _, _) => {
3077+
hir::TyKind::TraitObject(traits, _) => {
30783078
let (span, kw) = match traits {
30793079
[first, ..] if first.span.lo() == ty.span.lo() => {
30803080
// Missing `dyn` in front of trait object.

src/librustdoc/clean/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1843,10 +1843,10 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
18431843
ImplTrait(ty.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect())
18441844
}
18451845
TyKind::Path(_) => clean_qpath(ty, cx),
1846-
TyKind::TraitObject(bounds, lifetime, _) => {
1846+
TyKind::TraitObject(bounds, lifetime) => {
18471847
let bounds = bounds.iter().map(|bound| clean_poly_trait_ref(bound, cx)).collect();
18481848
let lifetime =
1849-
if !lifetime.is_elided() { Some(clean_lifetime(lifetime, cx)) } else { None };
1849+
if !lifetime.is_elided() { Some(clean_lifetime(lifetime.pointer(), cx)) } else { None };
18501850
DynTrait(bounds, lifetime)
18511851
}
18521852
TyKind::BareFn(barefn) => BareFunction(Box::new(clean_bare_fn_ty(barefn, cx))),

src/tools/clippy/clippy_lints/src/lifetimes.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ impl<'tcx> Visitor<'tcx> for RefVisitor<'_, 'tcx> {
433433
sub_visitor.visit_fn_decl(decl);
434434
self.nested_elision_site_lts.append(&mut sub_visitor.all_lts());
435435
},
436-
TyKind::TraitObject(bounds, lt, _) => {
436+
TyKind::TraitObject(bounds, lt) => {
437437
if !lt.is_elided() {
438438
self.unelided_trait_object_lifetime = true;
439439
}

src/tools/clippy/clippy_lints/src/types/borrowed_box.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, m
4747
// Originally reported as the issue #3128.
4848
let inner_snippet = snippet(cx, inner.span, "..");
4949
let suggestion = match &inner.kind {
50-
TyKind::TraitObject(bounds, lt_bound, _) if bounds.len() > 1 || !lt_bound.is_elided() => {
50+
TyKind::TraitObject(bounds, lt_bound) if bounds.len() > 1 || !lt_bound.is_elided() => {
5151
format!("&{ltopt}({inner_snippet})")
5252
},
5353
TyKind::Path(qpath)

src/tools/clippy/clippy_lints/src/types/type_complexity.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor {
5252
// function types bring a lot of overhead
5353
TyKind::BareFn(bare) if bare.abi == Abi::Rust => (50 * self.nest, 1),
5454

55-
TyKind::TraitObject(param_bounds, _, _) => {
55+
TyKind::TraitObject(param_bounds, _) => {
5656
let has_lifetime_parameters = param_bounds.iter().any(|bound| {
5757
bound
5858
.bound_generic_params

src/tools/clippy/clippy_utils/src/check_proc_macro.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,7 @@ fn ty_search_pat(ty: &Ty<'_>) -> (Pat, Pat) {
400400
TyKind::OpaqueDef(..) => (Pat::Str("impl"), Pat::Str("")),
401401
TyKind::Path(qpath) => qpath_search_pat(&qpath),
402402
TyKind::Infer => (Pat::Str("_"), Pat::Str("_")),
403-
TyKind::TraitObject(_, _, TraitObjectSyntax::Dyn) => (Pat::Str("dyn"), Pat::Str("")),
403+
TyKind::TraitObject(_, tagged_ptr) if let TraitObjectSyntax::Dyn = tagged_ptr.tag() => (Pat::Str("dyn"), Pat::Str("")),
404404
// NOTE: `TraitObject` is incomplete. It will always return true then.
405405
_ => (Pat::Str(""), Pat::Str("")),
406406
}

src/tools/clippy/clippy_utils/src/hir_utils.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1281,7 +1281,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
12811281
}
12821282
},
12831283
TyKind::Path(qpath) => self.hash_qpath(qpath),
1284-
TyKind::TraitObject(_, lifetime, _) => {
1284+
TyKind::TraitObject(_, lifetime) => {
12851285
self.hash_lifetime(lifetime);
12861286
},
12871287
TyKind::Typeof(anon_const) => {

0 commit comments

Comments
 (0)