about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2021-11-06 23:12:03 +0100
committerGitHub <noreply@github.com>2021-11-06 23:12:03 +0100
commit4c49db35fc671a522dbe07bfbeda8c7e7897108c (patch)
tree34b20baf5a11984124823ef681e2e856d79a7ea6
parentde332b52afa45dc60d1fda2b8122241632f7ebb0 (diff)
parentf5560754591532d7cde4c9f5dd51dfbd7670e98f (diff)
downloadrust-4c49db35fc671a522dbe07bfbeda8c7e7897108c.tar.gz
rust-4c49db35fc671a522dbe07bfbeda8c7e7897108c.zip
Rollup merge of #90508 - nbdd0121:issue-90483, r=davidtwco
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.

Fix #90483

``@rustbot`` label: T-compiler
-rw-r--r--compiler/rustc_typeck/src/check/expr.rs9
-rw-r--r--src/test/ui/typeck/issue-90483-inaccessible-field-adjustment.rs14
-rw-r--r--src/test/ui/typeck/issue-90483-inaccessible-field-adjustment.stderr14
3 files changed, 34 insertions, 3 deletions
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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         // 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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
         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`.