From f5560754591532d7cde4c9f5dd51dfbd7670e98f Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Tue, 2 Nov 2021 17:20:21 +0000 Subject: [PATCH] Apply adjustments for field expression even if inaccessible The adjustments are used later by ExprUseVisitor to build Place projections and without adjustments it can produce invalid result. --- compiler/rustc_typeck/src/check/expr.rs | 9 ++++++--- .../issue-90483-inaccessible-field-adjustment.rs | 14 ++++++++++++++ ...ssue-90483-inaccessible-field-adjustment.stderr | 14 ++++++++++++++ 3 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/typeck/issue-90483-inaccessible-field-adjustment.rs create mode 100644 src/test/ui/typeck/issue-90483-inaccessible-field-adjustment.stderr diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 3846aad2cfc..2d0a4068fbb 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -1698,15 +1698,15 @@ fn check_field( // Save the index of all fields regardless of their visibility in case // of error recovery. self.write_field_index(expr.hir_id, index); + let adjustments = self.adjust_steps(&autoderef); if field.vis.is_accessible_from(def_scope, self.tcx) { - let adjustments = self.adjust_steps(&autoderef); self.apply_adjustments(base, adjustments); self.register_predicates(autoderef.into_obligations()); self.tcx.check_stability(field.did, Some(expr.hir_id), expr.span, None); return field_ty; } - private_candidate = Some((base_def.did, field_ty)); + private_candidate = Some((adjustments, base_def.did, field_ty)); } } ty::Tuple(tys) => { @@ -1729,7 +1729,10 @@ fn check_field( } self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false)); - if let Some((did, field_ty)) = private_candidate { + if let Some((adjustments, did, field_ty)) = private_candidate { + // (#90483) apply adjustments to avoid ExprUseVisitor from + // creating erroneous projection. + self.apply_adjustments(base, adjustments); self.ban_private_field_access(expr, expr_t, field, did); return field_ty; } diff --git a/src/test/ui/typeck/issue-90483-inaccessible-field-adjustment.rs b/src/test/ui/typeck/issue-90483-inaccessible-field-adjustment.rs new file mode 100644 index 00000000000..74e50d46e8d --- /dev/null +++ b/src/test/ui/typeck/issue-90483-inaccessible-field-adjustment.rs @@ -0,0 +1,14 @@ +// edition:2021 + +mod m { + pub struct S { foo: i32 } + impl S { + pub fn foo(&self) -> i32 { 42 } + } +} + +fn bar(s: &m::S) { + || s.foo() + s.foo; //~ ERROR E0616 +} + +fn main() {} diff --git a/src/test/ui/typeck/issue-90483-inaccessible-field-adjustment.stderr b/src/test/ui/typeck/issue-90483-inaccessible-field-adjustment.stderr new file mode 100644 index 00000000000..02cdc102c15 --- /dev/null +++ b/src/test/ui/typeck/issue-90483-inaccessible-field-adjustment.stderr @@ -0,0 +1,14 @@ +error[E0616]: field `foo` of struct `S` is private + --> $DIR/issue-90483-inaccessible-field-adjustment.rs:11:18 + | +LL | || s.foo() + s.foo; + | ^^^ private field + | +help: a method `foo` also exists, call it with parentheses + | +LL | || s.foo() + s.foo(); + | ++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0616`.