Skip to content

Commit f92a04b

Browse files
committed
use FieldPath in offset_of!
1 parent 297bdad commit f92a04b

File tree

17 files changed

+377
-243
lines changed

17 files changed

+377
-243
lines changed

compiler/rustc_hir_analysis/src/collect.rs

Lines changed: 84 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@ use std::cell::Cell;
1919
use std::iter;
2020
use std::ops::Bound;
2121

22-
use rustc_abi::ExternAbi;
22+
use rustc_abi::{ExternAbi, FIRST_VARIANT};
2323
use rustc_ast::Recovered;
2424
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
2525
use rustc_data_structures::unord::UnordMap;
2626
use rustc_errors::{
27-
Applicability, Diag, DiagCtxtHandle, E0228, ErrorGuaranteed, StashKey, struct_span_code_err,
27+
Applicability, Diag, DiagCtxtHandle, E0228, E0616, ErrorGuaranteed, StashKey,
28+
struct_span_code_err,
2829
};
2930
use rustc_hir::attrs::AttributeKind;
3031
use rustc_hir::def::DefKind;
@@ -36,7 +37,8 @@ use rustc_infer::traits::{DynCompatibilityViolation, ObligationCause};
3637
use rustc_middle::query::Providers;
3738
use rustc_middle::ty::util::{Discr, IntTypeExt};
3839
use rustc_middle::ty::{
39-
self, AdtKind, Const, IsSuggestable, Ty, TyCtxt, TypeVisitableExt, TypingMode, fold_regions,
40+
self, AdtKind, Const, FieldPath, FieldPathKind, IsSuggestable, Ty, TyCtxt, TypeVisitableExt,
41+
TypingMode, fold_regions,
4042
};
4143
use rustc_middle::{bug, span_bug};
4244
use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
@@ -47,7 +49,7 @@ use rustc_trait_selection::traits::{
4749
};
4850
use tracing::{debug, instrument};
4951

50-
use crate::errors;
52+
use crate::errors::{self, NoFieldOnType};
5153
use crate::hir_ty_lowering::{
5254
FeedConstTy, HirTyLowerer, InherentAssocCandidate, RegionInferReason,
5355
};
@@ -346,6 +348,84 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
346348
ty::Const::new_error_with_message(self.tcx(), span, "bad placeholder constant")
347349
}
348350

351+
fn lower_field_path(
352+
&self,
353+
container: &rustc_hir::Ty<'tcx>,
354+
fields: &[Ident],
355+
span: Span,
356+
hir_id: HirId,
357+
field_path_kind: FieldPathKind,
358+
) -> Result<(Ty<'tcx>, FieldPath<'tcx>), ErrorGuaranteed> {
359+
assert_eq!(field_path_kind, FieldPathKind::FieldOf);
360+
let container = self.lower_ty(container);
361+
362+
let mut field_indices = Vec::with_capacity(fields.len());
363+
let mut current_container = container;
364+
let mut fields = fields.into_iter();
365+
let mut infcx = None;
366+
let infcx = self.infcx().unwrap_or_else(|| {
367+
assert!(!container.has_infer());
368+
infcx = Some(self.tcx().infer_ctxt().build(ty::TypingMode::non_body_analysis()));
369+
infcx.as_ref().unwrap()
370+
});
371+
372+
while let Some(&field) = fields.next() {
373+
let container = infcx.shallow_resolve(current_container);
374+
match container.kind() {
375+
ty::Adt(def, args) if !def.is_enum() => {
376+
let block = self.tcx.local_def_id_to_hir_id(self.item_def_id);
377+
let (ident, def_scope) =
378+
self.tcx.adjust_ident_and_get_scope(field, def.did(), block);
379+
380+
let fields = &def.non_enum_variant().fields;
381+
if let Some((index, field)) = fields
382+
.iter_enumerated()
383+
.find(|(_, f)| f.ident(self.tcx).normalize_to_macros_2_0() == ident)
384+
{
385+
let field_ty = field.ty(self.tcx, args);
386+
387+
if field.vis.is_accessible_from(def_scope, self.tcx) {
388+
self.tcx.check_stability(field.did, Some(hir_id), span, None);
389+
} else {
390+
let base_did = def.did();
391+
let struct_path = self.tcx().def_path_str(base_did);
392+
let kind_name = self.tcx().def_descr(base_did);
393+
struct_span_code_err!(
394+
self.dcx(),
395+
ident.span,
396+
E0616,
397+
"field `{ident}` of {kind_name} `{struct_path}` is private",
398+
)
399+
.with_span_label(ident.span, "private field")
400+
.emit();
401+
}
402+
403+
field_indices.push((FIRST_VARIANT, index));
404+
current_container = field_ty;
405+
406+
continue;
407+
}
408+
}
409+
ty::Tuple(tys) => {
410+
if let Ok(index) = field.as_str().parse::<usize>()
411+
&& field.name == sym::integer(index)
412+
&& let Some(&field_ty) = tys.get(index)
413+
{
414+
field_indices.push((FIRST_VARIANT, index.into()));
415+
current_container = field_ty;
416+
continue;
417+
}
418+
}
419+
_ => {}
420+
}
421+
return Err(self
422+
.dcx()
423+
.create_err(NoFieldOnType { span: field.span, ty: container, field })
424+
.emit());
425+
}
426+
Ok((container, self.tcx.mk_field_path_from_iter(field_indices.into_iter())))
427+
}
428+
349429
fn register_trait_ascription_bounds(
350430
&self,
351431
_: Vec<(ty::Clause<'tcx>, Span)>,

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ use rustc_middle::middle::stability::AllowUnstable;
3939
use rustc_middle::mir::interpret::LitToConstInput;
4040
use rustc_middle::ty::print::PrintPolyTraitRefExt as _;
4141
use rustc_middle::ty::{
42-
self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, Ty, TyCtxt, TypeVisitableExt,
43-
TypingMode, Upcast, fold_regions,
42+
self, Const, FieldPath, FieldPathKind, GenericArgKind, GenericArgsRef, GenericParamDefKind, Ty,
43+
TyCtxt, TypeVisitableExt, TypingMode, Upcast, fold_regions,
4444
};
4545
use rustc_middle::{bug, span_bug};
4646
use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
@@ -135,6 +135,15 @@ pub trait HirTyLowerer<'tcx> {
135135
span: Span,
136136
);
137137

138+
fn lower_field_path(
139+
&self,
140+
container: &hir::Ty<'tcx>,
141+
fields: &[Ident],
142+
span: Span,
143+
hir_id: HirId,
144+
field_path_kind: FieldPathKind,
145+
) -> Result<(Ty<'tcx>, FieldPath<'tcx>), ErrorGuaranteed>;
146+
138147
/// Probe bounds in scope where the bounded type coincides with the given type parameter.
139148
///
140149
/// Rephrased, this returns bounds of the form `T: Trait`, where `T` is a type parameter

0 commit comments

Comments
 (0)