diff options
| author | Michael Goulet <michael@errs.io> | 2022-08-03 07:01:18 +0000 |
|---|---|---|
| committer | Michael Goulet <michael@errs.io> | 2022-08-03 07:02:56 +0000 |
| commit | 603ffebd37a26a5b8d3c7372d432f6f2c053371d (patch) | |
| tree | 9d555a91a44937144767ccac279abbe7ccfb4f89 | |
| parent | 2a3fd5053f9cd5897c4a5eed2b742699aab279a4 (diff) | |
| download | rust-603ffebd37a26a5b8d3c7372d432f6f2c053371d.tar.gz rust-603ffebd37a26a5b8d3c7372d432f6f2c053371d.zip | |
Skip over structs with no private fields that impl Deref
| -rw-r--r-- | compiler/rustc_typeck/src/check/expr.rs | 11 | ||||
| -rw-r--r-- | src/test/ui/suggestions/field-access-considering-privacy.rs | 35 | ||||
| -rw-r--r-- | src/test/ui/suggestions/field-access-considering-privacy.stderr | 14 |
3 files changed, 57 insertions, 3 deletions
diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 523a10cc36a..67d0e331012 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -2582,10 +2582,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match base_t.kind() { ty::Adt(base_def, substs) if !base_def.is_enum() => { let tcx = self.tcx; + let fields = &base_def.non_enum_variant().fields; + // Some struct, e.g. some that impl `Deref`, have all private fields + // because you're expected to deref them to access the _real_ fields. + // This, for example, will help us suggest accessing a field through a `Box<T>`. + if fields.iter().all(|field| !field.vis.is_accessible_from(mod_id, tcx)) { + continue; + } return Some(( - base_def - .non_enum_variant() - .fields + fields .iter() .filter(move |field| field.vis.is_accessible_from(mod_id, tcx)) // For compile-time reasons put a limit on number of fields we search diff --git a/src/test/ui/suggestions/field-access-considering-privacy.rs b/src/test/ui/suggestions/field-access-considering-privacy.rs new file mode 100644 index 00000000000..3de06b21420 --- /dev/null +++ b/src/test/ui/suggestions/field-access-considering-privacy.rs @@ -0,0 +1,35 @@ +use a::TyCtxt; + +mod a { + use std::ops::Deref; + pub struct TyCtxt<'tcx> { + gcx: &'tcx GlobalCtxt<'tcx>, + } + + impl<'tcx> Deref for TyCtxt<'tcx> { + type Target = &'tcx GlobalCtxt<'tcx>; + + fn deref(&self) -> &Self::Target { + &self.gcx + } + } + + pub struct GlobalCtxt<'tcx> { + pub sess: &'tcx Session, + _t: &'tcx (), + } + + pub struct Session { + pub opts: (), + } +} + +mod b { + fn foo<'tcx>(tcx: crate::TyCtxt<'tcx>) { + tcx.opts; + //~^ ERROR no field `opts` on type `TyCtxt<'tcx>` + //~| HELP one of the expressions' fields has a field of the same name + } +} + +fn main() {} diff --git a/src/test/ui/suggestions/field-access-considering-privacy.stderr b/src/test/ui/suggestions/field-access-considering-privacy.stderr new file mode 100644 index 00000000000..cbf6f3d1002 --- /dev/null +++ b/src/test/ui/suggestions/field-access-considering-privacy.stderr @@ -0,0 +1,14 @@ +error[E0609]: no field `opts` on type `TyCtxt<'tcx>` + --> $DIR/field-access-considering-privacy.rs:29:13 + | +LL | tcx.opts; + | ^^^^ unknown field + | +help: one of the expressions' fields has a field of the same name + | +LL | tcx.sess.opts; + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0609`. |
