Skip to content

Commit 7de90d5

Browse files
authored
Rollup merge of #93214 - ibraheemdev:issue-93210, r=davidtwco
Respect doc(hidden) when suggesting available fields Resolves #93210
2 parents 1cb22e4 + b734abc commit 7de90d5

File tree

3 files changed

+75
-9
lines changed

3 files changed

+75
-9
lines changed

compiler/rustc_typeck/src/check/expr.rs

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ use rustc_hir::{ExprKind, HirId, QPath};
3535
use rustc_infer::infer;
3636
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
3737
use rustc_infer::infer::InferOk;
38+
use rustc_middle::middle::stability;
3839
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase};
3940
use rustc_middle::ty::error::ExpectedFound;
4041
use rustc_middle::ty::error::TypeError::{FieldMisMatch, Sorts};
@@ -1720,9 +1721,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17201721
_ => {
17211722
// prevent all specified fields from being suggested
17221723
let skip_fields = skip_fields.iter().map(|x| x.ident.name);
1723-
if let Some(field_name) =
1724-
Self::suggest_field_name(variant, field.ident.name, skip_fields.collect())
1725-
{
1724+
if let Some(field_name) = self.suggest_field_name(
1725+
variant,
1726+
field.ident.name,
1727+
skip_fields.collect(),
1728+
expr_span,
1729+
) {
17261730
err.span_suggestion(
17271731
field.ident.span,
17281732
"a field with a similar name exists",
@@ -1743,7 +1747,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17431747
format!("`{}` does not have this field", ty),
17441748
);
17451749
}
1746-
let available_field_names = self.available_field_names(variant);
1750+
let available_field_names =
1751+
self.available_field_names(variant, expr_span);
17471752
if !available_field_names.is_empty() {
17481753
err.note(&format!(
17491754
"available fields are: {}",
@@ -1759,19 +1764,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17591764
err.emit();
17601765
}
17611766

1762-
// Return an hint about the closest match in field names
1767+
// Return a hint about the closest match in field names
17631768
fn suggest_field_name(
1769+
&self,
17641770
variant: &'tcx ty::VariantDef,
17651771
field: Symbol,
17661772
skip: Vec<Symbol>,
1773+
// The span where stability will be checked
1774+
span: Span,
17671775
) -> Option<Symbol> {
17681776
let names = variant
17691777
.fields
17701778
.iter()
17711779
.filter_map(|field| {
17721780
// ignore already set fields and private fields from non-local crates
1781+
// and unstable fields.
17731782
if skip.iter().any(|&x| x == field.name)
17741783
|| (!variant.def_id.is_local() && !field.vis.is_public())
1784+
|| matches!(
1785+
self.tcx.eval_stability(field.did, None, span, None),
1786+
stability::EvalResult::Deny { .. }
1787+
)
17751788
{
17761789
None
17771790
} else {
@@ -1783,7 +1796,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17831796
find_best_match_for_name(&names, field, None)
17841797
}
17851798

1786-
fn available_field_names(&self, variant: &'tcx ty::VariantDef) -> Vec<Symbol> {
1799+
fn available_field_names(
1800+
&self,
1801+
variant: &'tcx ty::VariantDef,
1802+
access_span: Span,
1803+
) -> Vec<Symbol> {
17871804
variant
17881805
.fields
17891806
.iter()
@@ -1793,7 +1810,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17931810
.adjust_ident_and_get_scope(field.ident(self.tcx), variant.def_id, self.body_id)
17941811
.1;
17951812
field.vis.is_accessible_from(def_scope, self.tcx)
1813+
&& !matches!(
1814+
self.tcx.eval_stability(field.did, None, access_span, None),
1815+
stability::EvalResult::Deny { .. }
1816+
)
17961817
})
1818+
.filter(|field| !self.tcx.is_doc_hidden(field.did))
17971819
.map(|field| field.name)
17981820
.collect()
17991821
}
@@ -1958,7 +1980,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
19581980
self.suggest_first_deref_field(&mut err, expr, base, field);
19591981
}
19601982
ty::Adt(def, _) if !def.is_enum() => {
1961-
self.suggest_fields_on_recordish(&mut err, def, field);
1983+
self.suggest_fields_on_recordish(&mut err, def, field, expr.span);
19621984
}
19631985
ty::Param(param_ty) => {
19641986
self.point_at_param_definition(&mut err, param_ty);
@@ -2121,9 +2143,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21212143
err: &mut DiagnosticBuilder<'_>,
21222144
def: &'tcx ty::AdtDef,
21232145
field: Ident,
2146+
access_span: Span,
21242147
) {
21252148
if let Some(suggested_field_name) =
2126-
Self::suggest_field_name(def.non_enum_variant(), field.name, vec![])
2149+
self.suggest_field_name(def.non_enum_variant(), field.name, vec![], access_span)
21272150
{
21282151
err.span_suggestion(
21292152
field.span,
@@ -2134,7 +2157,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21342157
} else {
21352158
err.span_label(field.span, "unknown field");
21362159
let struct_variant_def = def.non_enum_variant();
2137-
let field_names = self.available_field_names(struct_variant_def);
2160+
let field_names = self.available_field_names(struct_variant_def, access_span);
21382161
if !field_names.is_empty() {
21392162
err.note(&format!(
21402163
"available fields are: {}",
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#[derive(Default)]
2+
pub struct A {
3+
#[doc(hidden)]
4+
pub hello: i32,
5+
pub bye: i32,
6+
}
7+
8+
#[derive(Default)]
9+
pub struct B {
10+
pub hello: i32,
11+
pub bye: i32,
12+
}
13+
14+
fn main() {
15+
A::default().hey;
16+
//~^ ERROR no field `hey` on type `A`
17+
//~| NOTE unknown field
18+
//~| NOTE available fields are: `bye`
19+
20+
B::default().hey;
21+
//~^ ERROR no field `hey` on type `B`
22+
//~| NOTE unknown field
23+
//~| NOTE available fields are: `hello`, `bye`
24+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error[E0609]: no field `hey` on type `A`
2+
--> $DIR/issue-93210-ignore-doc-hidden.rs:15:18
3+
|
4+
LL | A::default().hey;
5+
| ^^^ unknown field
6+
|
7+
= note: available fields are: `bye`
8+
9+
error[E0609]: no field `hey` on type `B`
10+
--> $DIR/issue-93210-ignore-doc-hidden.rs:20:18
11+
|
12+
LL | B::default().hey;
13+
| ^^^ unknown field
14+
|
15+
= note: available fields are: `hello`, `bye`
16+
17+
error: aborting due to 2 previous errors
18+
19+
For more information about this error, try `rustc --explain E0609`.

0 commit comments

Comments
 (0)