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
This commit is contained in:
Matthias Krüger 2021-11-06 23:12:03 +01:00 committed by GitHub
commit 4c49db35fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 34 additions and 3 deletions

View File

@ -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);
if field.vis.is_accessible_from(def_scope, self.tcx) {
let adjustments = self.adjust_steps(&autoderef);
if field.vis.is_accessible_from(def_scope, self.tcx) {
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;
}

View File

@ -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() {}

View File

@ -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`.