mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
Rollup merge of #105267 - compiler-errors:issue-104613, r=oli-obk
Don't ICE in ExprUseVisitor on FRU for non-existent struct Fixes #104613 Fixes #105202
This commit is contained in:
commit
3bcfa4c459
@ -1647,6 +1647,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// the fields with the base_expr. This could cause us to hit errors later
|
||||
// when certain fields are assumed to exist that in fact do not.
|
||||
if error_happened {
|
||||
if let Some(base_expr) = base_expr {
|
||||
self.check_expr(base_expr);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -523,6 +523,11 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
|
||||
// Consume the expressions supplying values for each field.
|
||||
for field in fields {
|
||||
self.consume_expr(field.expr);
|
||||
|
||||
// The struct path probably didn't resolve
|
||||
if self.mc.typeck_results.opt_field_index(field.hir_id).is_none() {
|
||||
self.tcx().sess.delay_span_bug(field.span, "couldn't resolve index for field");
|
||||
}
|
||||
}
|
||||
|
||||
let with_expr = match *opt_with {
|
||||
@ -540,9 +545,9 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
|
||||
ty::Adt(adt, substs) if adt.is_struct() => {
|
||||
// Consume those fields of the with expression that are needed.
|
||||
for (f_index, with_field) in adt.non_enum_variant().fields.iter().enumerate() {
|
||||
let is_mentioned = fields.iter().any(|f| {
|
||||
self.tcx().field_index(f.hir_id, self.mc.typeck_results) == f_index
|
||||
});
|
||||
let is_mentioned = fields
|
||||
.iter()
|
||||
.any(|f| self.mc.typeck_results.opt_field_index(f.hir_id) == Some(f_index));
|
||||
if !is_mentioned {
|
||||
let field_place = self.mc.cat_projection(
|
||||
&*with_expr,
|
||||
|
@ -259,7 +259,7 @@ impl<'tcx> LateLintPass<'tcx> for NonShorthandFieldPatterns {
|
||||
}
|
||||
if let PatKind::Binding(binding_annot, _, ident, None) = fieldpat.pat.kind {
|
||||
if cx.tcx.find_field_index(ident, &variant)
|
||||
== Some(cx.tcx.field_index(fieldpat.hir_id, cx.typeck_results()))
|
||||
== Some(cx.typeck_results().field_index(fieldpat.hir_id))
|
||||
{
|
||||
cx.struct_span_lint(
|
||||
NON_SHORTHAND_FIELD_PATTERNS,
|
||||
|
@ -667,6 +667,14 @@ impl<'tcx> TypeckResults<'tcx> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.field_indices }
|
||||
}
|
||||
|
||||
pub fn field_index(&self, id: hir::HirId) -> usize {
|
||||
self.field_indices().get(id).cloned().expect("no index for a field")
|
||||
}
|
||||
|
||||
pub fn opt_field_index(&self, id: hir::HirId) -> Option<usize> {
|
||||
self.field_indices().get(id).cloned()
|
||||
}
|
||||
|
||||
pub fn user_provided_types(&self) -> LocalTableInContext<'_, CanonicalUserType<'tcx>> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.user_provided_types }
|
||||
}
|
||||
|
@ -2142,10 +2142,6 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn field_index(self, hir_id: hir::HirId, typeck_results: &TypeckResults<'_>) -> usize {
|
||||
typeck_results.field_indices().get(hir_id).cloned().expect("no index for a field")
|
||||
}
|
||||
|
||||
pub fn find_field_index(self, ident: Ident, variant: &VariantDef) -> Option<usize> {
|
||||
variant
|
||||
.fields
|
||||
|
@ -704,7 +704,7 @@ impl<'tcx> Cx<'tcx> {
|
||||
hir::ExprKind::Field(ref source, ..) => ExprKind::Field {
|
||||
lhs: self.mirror_expr(source),
|
||||
variant_index: VariantIdx::new(0),
|
||||
name: Field::new(tcx.field_index(expr.hir_id, self.typeck_results)),
|
||||
name: Field::new(self.typeck_results.field_index(expr.hir_id)),
|
||||
},
|
||||
hir::ExprKind::Cast(ref source, ref cast_ty) => {
|
||||
// Check for a user-given type annotation on this `cast`
|
||||
@ -1079,7 +1079,7 @@ impl<'tcx> Cx<'tcx> {
|
||||
fields
|
||||
.iter()
|
||||
.map(|field| FieldExpr {
|
||||
name: Field::new(self.tcx.field_index(field.hir_id, self.typeck_results)),
|
||||
name: Field::new(self.typeck_results.field_index(field.hir_id)),
|
||||
expr: self.mirror_expr(field.expr),
|
||||
})
|
||||
.collect()
|
||||
|
@ -321,7 +321,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
||||
let subpatterns = fields
|
||||
.iter()
|
||||
.map(|field| FieldPat {
|
||||
field: Field::new(self.tcx.field_index(field.hir_id, self.typeck_results)),
|
||||
field: Field::new(self.typeck_results.field_index(field.hir_id)),
|
||||
pattern: self.lower_pattern(&field.pat),
|
||||
})
|
||||
.collect();
|
||||
|
@ -124,7 +124,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
|
||||
fn handle_field_access(&mut self, lhs: &hir::Expr<'_>, hir_id: hir::HirId) {
|
||||
match self.typeck_results().expr_ty_adjusted(lhs).kind() {
|
||||
ty::Adt(def, _) => {
|
||||
let index = self.tcx.field_index(hir_id, self.typeck_results());
|
||||
let index = self.typeck_results().field_index(hir_id);
|
||||
self.insert_def_id(def.non_enum_variant().fields[index].did);
|
||||
}
|
||||
ty::Tuple(..) => {}
|
||||
@ -208,7 +208,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
|
||||
if let PatKind::Wild = pat.pat.kind {
|
||||
continue;
|
||||
}
|
||||
let index = self.tcx.field_index(pat.hir_id, self.typeck_results());
|
||||
let index = self.typeck_results().field_index(pat.hir_id);
|
||||
self.insert_def_id(variant.fields[index].did);
|
||||
}
|
||||
}
|
||||
@ -341,7 +341,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
|
||||
fn mark_as_used_if_union(&mut self, adt: ty::AdtDef<'tcx>, fields: &[hir::ExprField<'_>]) {
|
||||
if adt.is_union() && adt.non_enum_variant().fields.len() > 1 && adt.did().is_local() {
|
||||
for field in fields {
|
||||
let index = self.tcx.field_index(field.hir_id, self.typeck_results());
|
||||
let index = self.typeck_results().field_index(field.hir_id);
|
||||
self.insert_def_id(adt.non_enum_variant().fields[index].did);
|
||||
}
|
||||
}
|
||||
|
@ -1065,9 +1065,9 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> {
|
||||
// are checked for privacy (RFC 736). Rather than computing the set of
|
||||
// unmentioned fields, just check them all.
|
||||
for (vf_index, variant_field) in variant.fields.iter().enumerate() {
|
||||
let field = fields.iter().find(|f| {
|
||||
self.tcx.field_index(f.hir_id, self.typeck_results()) == vf_index
|
||||
});
|
||||
let field = fields
|
||||
.iter()
|
||||
.find(|f| self.typeck_results().field_index(f.hir_id) == vf_index);
|
||||
let (use_ctxt, span) = match field {
|
||||
Some(field) => (field.ident.span, field.span),
|
||||
None => (base.span, base.span),
|
||||
@ -1077,7 +1077,7 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> {
|
||||
} else {
|
||||
for field in fields {
|
||||
let use_ctxt = field.ident.span;
|
||||
let index = self.tcx.field_index(field.hir_id, self.typeck_results());
|
||||
let index = self.typeck_results().field_index(field.hir_id);
|
||||
self.check_field(use_ctxt, field.span, adt, &variant.fields[index], false);
|
||||
}
|
||||
}
|
||||
@ -1093,7 +1093,7 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> {
|
||||
let variant = adt.variant_of_res(res);
|
||||
for field in fields {
|
||||
let use_ctxt = field.ident.span;
|
||||
let index = self.tcx.field_index(field.hir_id, self.typeck_results());
|
||||
let index = self.typeck_results().field_index(field.hir_id);
|
||||
self.check_field(use_ctxt, field.span, adt, &variant.fields[index], false);
|
||||
}
|
||||
}
|
||||
|
10
src/test/ui/async-await/drop-track-bad-field-in-fru.rs
Normal file
10
src/test/ui/async-await/drop-track-bad-field-in-fru.rs
Normal file
@ -0,0 +1,10 @@
|
||||
// compile-flags: -Zdrop-tracking
|
||||
// edition: 2021
|
||||
|
||||
fn main() {}
|
||||
|
||||
async fn foo() {
|
||||
None { value: (), ..Default::default() }.await;
|
||||
//~^ ERROR `Option<_>` is not a future
|
||||
//~| ERROR variant `Option<_>::None` has no field named `value`
|
||||
}
|
23
src/test/ui/async-await/drop-track-bad-field-in-fru.stderr
Normal file
23
src/test/ui/async-await/drop-track-bad-field-in-fru.stderr
Normal file
@ -0,0 +1,23 @@
|
||||
error[E0559]: variant `Option<_>::None` has no field named `value`
|
||||
--> $DIR/drop-track-bad-field-in-fru.rs:7:12
|
||||
|
|
||||
LL | None { value: (), ..Default::default() }.await;
|
||||
| ^^^^^ `Option<_>::None` does not have this field
|
||||
|
||||
error[E0277]: `Option<_>` is not a future
|
||||
--> $DIR/drop-track-bad-field-in-fru.rs:7:45
|
||||
|
|
||||
LL | None { value: (), ..Default::default() }.await;
|
||||
| ^^^^^^
|
||||
| |
|
||||
| `Option<_>` is not a future
|
||||
| help: remove the `.await`
|
||||
|
|
||||
= help: the trait `Future` is not implemented for `Option<_>`
|
||||
= note: Option<_> must be a future or must implement `IntoFuture` to be awaited
|
||||
= note: required for `Option<_>` to implement `IntoFuture`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0559.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
12
src/test/ui/structs/unresolved-struct-with-fru.rs
Normal file
12
src/test/ui/structs/unresolved-struct-with-fru.rs
Normal file
@ -0,0 +1,12 @@
|
||||
struct S {
|
||||
a: u32,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let s1 = S { a: 1 };
|
||||
|
||||
let _ = || {
|
||||
let s2 = Oops { a: 2, ..s1 };
|
||||
//~^ ERROR cannot find struct, variant or union type `Oops` in this scope
|
||||
};
|
||||
}
|
9
src/test/ui/structs/unresolved-struct-with-fru.stderr
Normal file
9
src/test/ui/structs/unresolved-struct-with-fru.stderr
Normal file
@ -0,0 +1,9 @@
|
||||
error[E0422]: cannot find struct, variant or union type `Oops` in this scope
|
||||
--> $DIR/unresolved-struct-with-fru.rs:9:18
|
||||
|
|
||||
LL | let s2 = Oops { a: 2, ..s1 };
|
||||
| ^^^^ not found in this scope
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0422`.
|
Loading…
Reference in New Issue
Block a user