Skip to content

add comments in check_expr_field #134148

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_errors/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1291,7 +1291,7 @@ impl<'a> DiagCtxtHandle<'a> {
Diag::<ErrorGuaranteed>::new(self, DelayedBug, msg.into()).emit()
}

/// Ensures that an error is printed. See `Level::DelayedBug`.
/// Ensures that an error is printed. See [`Level::DelayedBug`].
///
/// Note: this function used to be called `delay_span_bug`. It was renamed
/// to match similar functions like `span_err`, `span_warn`, etc.
Expand Down
27 changes: 22 additions & 5 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2688,33 +2688,46 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
None
}

// Check field access expressions
/// Check field access expressions, this works for both structs and tuples.
/// Returns the Ty of the field.
///
/// ```not_rust
/// base.field
/// ^^^^^^^^^^ expr
/// ^^^^ base
/// ^^^^^ field
/// ```
fn check_expr_field(
&self,
expr: &'tcx hir::Expr<'tcx>,
base: &'tcx hir::Expr<'tcx>,
field: Ident,
// The expected type hint of the field.
expected: Expectation<'tcx>,
) -> Ty<'tcx> {
debug!("check_field(expr: {:?}, base: {:?}, field: {:?})", expr, base, field);
let base_ty = self.check_expr(base);
let base_ty = self.structurally_resolve_type(base.span, base_ty);

// Whether we are trying to access a private field. Used for error reporting.
let mut private_candidate = None;

// Field expressions automatically deref
let mut autoderef = self.autoderef(expr.span, base_ty);
while let Some((deref_base_ty, _)) = autoderef.next() {
debug!("deref_base_ty: {:?}", deref_base_ty);
match deref_base_ty.kind() {
ty::Adt(base_def, args) if !base_def.is_enum() => {
debug!("struct named {:?}", deref_base_ty);
let body_hir_id = self.tcx.local_def_id_to_hir_id(self.body_id);
let (ident, def_scope) =
self.tcx.adjust_ident_and_get_scope(field, base_def.did(), body_hir_id);

// we don't care to report errors for a struct if the struct itself is tainted
if let Err(guar) = base_def.non_enum_variant().has_errors() {
return Ty::new_error(self.tcx(), guar);
}

let fn_body_hir_id = self.tcx.local_def_id_to_hir_id(self.body_id);
let (ident, def_scope) =
self.tcx.adjust_ident_and_get_scope(field, base_def.did(), fn_body_hir_id);

if let Some((idx, field)) = self.find_adt_field(*base_def, ident) {
self.write_field_index(expr.hir_id, idx);

Expand Down Expand Up @@ -2748,6 +2761,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
_ => {}
}
}
// We failed to check the expression, report an error.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment doesn't really describe what this is doing. It's attempting to emit an error if we end up derefing to an infer var, like calling .field on a base type of &_.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That comment was more general, as in "ok we're no longer in the happy path"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well it's useful regardless to document the random structural resolve call. Pls do that :)


// Emits an error if we deref an infer variable, like calling `.field` on a base type of &_.
self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false));

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