Skip to content

Commit 55806e5

Browse files
author
Orion Gonzalez
committed
document check_expr_field
1 parent 33c245b commit 55806e5

File tree

2 files changed

+23
-6
lines changed

2 files changed

+23
-6
lines changed

compiler/rustc_errors/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1291,7 +1291,7 @@ impl<'a> DiagCtxtHandle<'a> {
12911291
Diag::<ErrorGuaranteed>::new(self, DelayedBug, msg.into()).emit()
12921292
}
12931293

1294-
/// Ensures that an error is printed. See `Level::DelayedBug`.
1294+
/// Ensures that an error is printed. See [`Level::DelayedBug`].
12951295
///
12961296
/// Note: this function used to be called `delay_span_bug`. It was renamed
12971297
/// to match similar functions like `span_err`, `span_warn`, etc.

compiler/rustc_hir_typeck/src/expr.rs

+22-5
Original file line numberDiff line numberDiff line change
@@ -2688,33 +2688,46 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26882688
None
26892689
}
26902690

2691-
// Check field access expressions
2691+
/// Check field access expressions, this works for both structs and tuples.
2692+
/// Returns the Ty of the field.
2693+
///
2694+
/// ```not_rust
2695+
/// base.field
2696+
/// ^^^^^^^^^^ expr
2697+
/// ^^^^ base
2698+
/// ^^^^^ field
2699+
/// ```
26922700
fn check_expr_field(
26932701
&self,
26942702
expr: &'tcx hir::Expr<'tcx>,
26952703
base: &'tcx hir::Expr<'tcx>,
26962704
field: Ident,
2705+
// The expected type hint of the field.
26972706
expected: Expectation<'tcx>,
26982707
) -> Ty<'tcx> {
26992708
debug!("check_field(expr: {:?}, base: {:?}, field: {:?})", expr, base, field);
27002709
let base_ty = self.check_expr(base);
27012710
let base_ty = self.structurally_resolve_type(base.span, base_ty);
2711+
2712+
// Whether we are trying to access a private field. Used for error reporting.
27022713
let mut private_candidate = None;
2714+
2715+
// Field expressions automatically deref
27032716
let mut autoderef = self.autoderef(expr.span, base_ty);
27042717
while let Some((deref_base_ty, _)) = autoderef.next() {
27052718
debug!("deref_base_ty: {:?}", deref_base_ty);
27062719
match deref_base_ty.kind() {
27072720
ty::Adt(base_def, args) if !base_def.is_enum() => {
27082721
debug!("struct named {:?}", deref_base_ty);
2709-
let body_hir_id = self.tcx.local_def_id_to_hir_id(self.body_id);
2710-
let (ident, def_scope) =
2711-
self.tcx.adjust_ident_and_get_scope(field, base_def.did(), body_hir_id);
2712-
27132722
// we don't care to report errors for a struct if the struct itself is tainted
27142723
if let Err(guar) = base_def.non_enum_variant().has_errors() {
27152724
return Ty::new_error(self.tcx(), guar);
27162725
}
27172726

2727+
let fn_body_hir_id = self.tcx.local_def_id_to_hir_id(self.body_id);
2728+
let (ident, def_scope) =
2729+
self.tcx.adjust_ident_and_get_scope(field, base_def.did(), fn_body_hir_id);
2730+
27182731
if let Some((idx, field)) = self.find_adt_field(*base_def, ident) {
27192732
self.write_field_index(expr.hir_id, idx);
27202733

@@ -2748,6 +2761,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
27482761
_ => {}
27492762
}
27502763
}
2764+
// We failed to check the expression, report an error.
2765+
2766+
// Emits an error if we deref an infer variable, like calling `.field` on a base type of &_.
27512767
self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false));
27522768

27532769
if let Some((adjustments, did)) = private_candidate {
@@ -2772,6 +2788,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
27722788
expr.hir_id,
27732789
expected.only_has_type(self),
27742790
) {
2791+
// If taking a method instead of calling it
27752792
self.ban_take_value_of_method(expr, base_ty, field)
27762793
} else if !base_ty.is_primitive_ty() {
27772794
self.ban_nonexisting_field(field, base, expr, base_ty)

0 commit comments

Comments
 (0)