Skip to content

Commit defcfe7

Browse files
committed
Auto merge of #49718 - petrochenkov:fieldcmp, r=eddyb
Hygiene 2.0: Avoid comparing fields by name There are two separate commits here (not counting tests): - The first one unifies named (`obj.name`) and numeric (`obj.0`) field access expressions in AST and HIR. Before field references in these expressions are resolved it doesn't matter whether the field is named or numeric (it's just a symbol) and 99% of code is common. After field references are resolved we work with them by index for all fields (see the second commit), so it's again not important whether the field was named or numeric (this includes MIR where all fields were already by index). (This refactoring actually fixed some bugs in HIR-based borrow checker where borrows through names (`S { 0: ref x }`) and indices (`&s.0`) weren't considered overlapping.) - The second commit removes all by-name field comparison and instead resolves field references to their indices once, and then uses those resolutions. (There are still a few name comparisons in save-analysis, because save-analysis is weird, but they are made correctly hygienic). Thus we are fixing a bunch of "secondary" field hygiene bugs (in borrow checker, lints). Fixes #46314
2 parents c4a0328 + fcf4852 commit defcfe7

File tree

87 files changed

+759
-676
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

87 files changed

+759
-676
lines changed

src/librustc/cfg/construct.rs

-1
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,6 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
389389
hir::ExprType(ref e, _) |
390390
hir::ExprUnary(_, ref e) |
391391
hir::ExprField(ref e, _) |
392-
hir::ExprTupField(ref e, _) |
393392
hir::ExprYield(ref e) |
394393
hir::ExprRepeat(ref e, _) => {
395394
self.straightline(expr, pred, Some(&**e).into_iter())

src/librustc/hir/intravisit.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
658658
PatKind::Struct(ref qpath, ref fields, _) => {
659659
visitor.visit_qpath(qpath, pattern.id, pattern.span);
660660
for field in fields {
661+
visitor.visit_id(field.node.id);
661662
visitor.visit_name(field.span, field.node.name);
662663
visitor.visit_pat(&field.node.pat)
663664
}
@@ -959,6 +960,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
959960
ExprStruct(ref qpath, ref fields, ref optional_base) => {
960961
visitor.visit_qpath(qpath, expression.id, expression.span);
961962
for field in fields {
963+
visitor.visit_id(field.id);
962964
visitor.visit_name(field.name.span, field.name.node);
963965
visitor.visit_expr(&field.expr)
964966
}
@@ -1025,9 +1027,6 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
10251027
visitor.visit_expr(subexpression);
10261028
visitor.visit_name(name.span, name.node);
10271029
}
1028-
ExprTupField(ref subexpression, _) => {
1029-
visitor.visit_expr(subexpression);
1030-
}
10311030
ExprIndex(ref main_expression, ref index_expression) => {
10321031
visitor.visit_expr(main_expression);
10331032
visitor.visit_expr(index_expression)

src/librustc/hir/lowering.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -2100,6 +2100,7 @@ impl<'a> LoweringContext<'a> {
21002100

21012101
fn lower_field(&mut self, f: &Field) -> hir::Field {
21022102
hir::Field {
2103+
id: self.next_id().node_id,
21032104
name: respan(f.ident.span, self.lower_ident(f.ident)),
21042105
expr: P(self.lower_expr(&f.expr)),
21052106
span: f.span,
@@ -2863,6 +2864,7 @@ impl<'a> LoweringContext<'a> {
28632864
.map(|f| Spanned {
28642865
span: f.span,
28652866
node: hir::FieldPat {
2867+
id: self.next_id().node_id,
28662868
name: self.lower_ident(f.node.ident),
28672869
pat: self.lower_pat(&f.node.pat),
28682870
is_shorthand: f.node.is_shorthand,
@@ -3095,7 +3097,6 @@ impl<'a> LoweringContext<'a> {
30953097
P(self.lower_expr(el)),
30963098
respan(ident.span, self.lower_ident(ident)),
30973099
),
3098-
ExprKind::TupField(ref el, ident) => hir::ExprTupField(P(self.lower_expr(el)), ident),
30993100
ExprKind::Index(ref el, ref er) => {
31003101
hir::ExprIndex(P(self.lower_expr(el)), P(self.lower_expr(er)))
31013102
}
@@ -3742,6 +3743,7 @@ impl<'a> LoweringContext<'a> {
37423743

37433744
fn field(&mut self, name: Name, expr: P<hir::Expr>, span: Span) -> hir::Field {
37443745
hir::Field {
3746+
id: self.next_id().node_id,
37453747
name: Spanned { node: name, span },
37463748
span,
37473749
expr,

src/librustc/hir/mod.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -827,6 +827,7 @@ impl Pat {
827827
/// except is_shorthand is true
828828
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
829829
pub struct FieldPat {
830+
pub id: NodeId,
830831
/// The identifier for the field
831832
pub name: Name,
832833
/// The pattern the field is destructured to
@@ -1172,6 +1173,7 @@ pub struct Arm {
11721173

11731174
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
11741175
pub struct Field {
1176+
pub id: NodeId,
11751177
pub name: Spanned<Name>,
11761178
pub expr: P<Expr>,
11771179
pub span: Span,
@@ -1276,7 +1278,6 @@ impl Expr {
12761278
ExprAssign(..) => ExprPrecedence::Assign,
12771279
ExprAssignOp(..) => ExprPrecedence::AssignOp,
12781280
ExprField(..) => ExprPrecedence::Field,
1279-
ExprTupField(..) => ExprPrecedence::TupField,
12801281
ExprIndex(..) => ExprPrecedence::Index,
12811282
ExprPath(..) => ExprPrecedence::Path,
12821283
ExprAddrOf(..) => ExprPrecedence::AddrOf,
@@ -1363,12 +1364,8 @@ pub enum Expr_ {
13631364
///
13641365
/// For example, `a += 1`.
13651366
ExprAssignOp(BinOp, P<Expr>, P<Expr>),
1366-
/// Access of a named struct field (`obj.foo`)
1367+
/// Access of a named (`obj.foo`) or unnamed (`obj.0`) struct or tuple field
13671368
ExprField(P<Expr>, Spanned<Name>),
1368-
/// Access of an unnamed field of a struct or tuple-struct
1369-
///
1370-
/// For example, `foo.0`.
1371-
ExprTupField(P<Expr>, Spanned<usize>),
13721369
/// An indexing operation (`foo[2]`)
13731370
ExprIndex(P<Expr>, P<Expr>),
13741371

src/librustc/hir/print.rs

+1-8
Original file line numberDiff line numberDiff line change
@@ -1201,8 +1201,7 @@ impl<'a> State<'a> {
12011201
fn print_expr_call(&mut self, func: &hir::Expr, args: &[hir::Expr]) -> io::Result<()> {
12021202
let prec =
12031203
match func.node {
1204-
hir::ExprField(..) |
1205-
hir::ExprTupField(..) => parser::PREC_FORCE_PAREN,
1204+
hir::ExprField(..) => parser::PREC_FORCE_PAREN,
12061205
_ => parser::PREC_POSTFIX,
12071206
};
12081207

@@ -1405,11 +1404,6 @@ impl<'a> State<'a> {
14051404
self.s.word(".")?;
14061405
self.print_name(name.node)?;
14071406
}
1408-
hir::ExprTupField(ref expr, id) => {
1409-
self.print_expr_maybe_paren(&expr, parser::PREC_POSTFIX)?;
1410-
self.s.word(".")?;
1411-
self.print_usize(id.node)?;
1412-
}
14131407
hir::ExprIndex(ref expr, ref index) => {
14141408
self.print_expr_maybe_paren(&expr, parser::PREC_POSTFIX)?;
14151409
self.s.word("[")?;
@@ -2376,7 +2370,6 @@ fn contains_exterior_struct_lit(value: &hir::Expr) -> bool {
23762370
hir::ExprCast(ref x, _) |
23772371
hir::ExprType(ref x, _) |
23782372
hir::ExprField(ref x, _) |
2379-
hir::ExprTupField(ref x, _) |
23802373
hir::ExprIndex(ref x, _) => {
23812374
// &X { y: 1 }, X { y: 1 }.y
23822375
contains_exterior_struct_lit(&x)

src/librustc/ich/impls_hir.rs

+35-12
Original file line numberDiff line numberDiff line change
@@ -420,11 +420,23 @@ impl<'a> HashStable<StableHashingContext<'a>> for hir::Pat {
420420
}
421421

422422
impl_stable_hash_for_spanned!(hir::FieldPat);
423-
impl_stable_hash_for!(struct hir::FieldPat {
424-
name,
425-
pat,
426-
is_shorthand
427-
});
423+
424+
impl<'a> HashStable<StableHashingContext<'a>> for hir::FieldPat {
425+
fn hash_stable<W: StableHasherResult>(&self,
426+
hcx: &mut StableHashingContext<'a>,
427+
hasher: &mut StableHasher<W>) {
428+
let hir::FieldPat {
429+
id: _,
430+
name,
431+
ref pat,
432+
is_shorthand,
433+
} = *self;
434+
435+
name.hash_stable(hcx, hasher);
436+
pat.hash_stable(hcx, hasher);
437+
is_shorthand.hash_stable(hcx, hasher);
438+
}
439+
}
428440

429441
impl_stable_hash_for!(enum hir::BindingAnnotation {
430442
Unannotated,
@@ -507,12 +519,24 @@ impl_stable_hash_for!(struct hir::Arm {
507519
body
508520
});
509521

510-
impl_stable_hash_for!(struct hir::Field {
511-
name,
512-
expr,
513-
span,
514-
is_shorthand
515-
});
522+
impl<'a> HashStable<StableHashingContext<'a>> for hir::Field {
523+
fn hash_stable<W: StableHasherResult>(&self,
524+
hcx: &mut StableHashingContext<'a>,
525+
hasher: &mut StableHasher<W>) {
526+
let hir::Field {
527+
id: _,
528+
name,
529+
ref expr,
530+
span,
531+
is_shorthand,
532+
} = *self;
533+
534+
name.hash_stable(hcx, hasher);
535+
expr.hash_stable(hcx, hasher);
536+
span.hash_stable(hcx, hasher);
537+
is_shorthand.hash_stable(hcx, hasher);
538+
}
539+
}
516540

517541
impl_stable_hash_for_spanned!(ast::Name);
518542

@@ -569,7 +593,6 @@ impl_stable_hash_for!(enum hir::Expr_ {
569593
ExprAssign(lhs, rhs),
570594
ExprAssignOp(op, lhs, rhs),
571595
ExprField(owner, field_name),
572-
ExprTupField(owner, idx),
573596
ExprIndex(lhs, rhs),
574597
ExprPath(path),
575598
ExprAddrOf(mutability, sub),

src/librustc/middle/dead.rs

+16-35
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
// from live codes are live, and everything else is dead.
1414

1515
use hir::map as hir_map;
16-
use hir::{self, Item_, PatKind};
16+
use hir::{self, PatKind};
1717
use hir::intravisit::{self, Visitor, NestedVisitorMap};
1818
use hir::itemlikevisit::ItemLikeVisitor;
1919

@@ -99,22 +99,14 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
9999
self.check_def_id(self.tables.type_dependent_defs()[id].def_id());
100100
}
101101

102-
fn handle_field_access(&mut self, lhs: &hir::Expr, name: ast::Name) {
102+
fn handle_field_access(&mut self, lhs: &hir::Expr, node_id: ast::NodeId) {
103103
match self.tables.expr_ty_adjusted(lhs).sty {
104104
ty::TyAdt(def, _) => {
105-
self.insert_def_id(def.non_enum_variant().field_named(name).did);
106-
}
107-
_ => span_bug!(lhs.span, "named field access on non-ADT"),
108-
}
109-
}
110-
111-
fn handle_tup_field_access(&mut self, lhs: &hir::Expr, idx: usize) {
112-
match self.tables.expr_ty_adjusted(lhs).sty {
113-
ty::TyAdt(def, _) => {
114-
self.insert_def_id(def.non_enum_variant().fields[idx].did);
105+
let index = self.tcx.field_index(node_id, self.tables);
106+
self.insert_def_id(def.non_enum_variant().fields[index].did);
115107
}
116108
ty::TyTuple(..) => {}
117-
_ => span_bug!(lhs.span, "numeric field access on non-ADT"),
109+
_ => span_bug!(lhs.span, "named field access on non-ADT"),
118110
}
119111
}
120112

@@ -128,7 +120,8 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
128120
if let PatKind::Wild = pat.node.pat.node {
129121
continue;
130122
}
131-
self.insert_def_id(variant.field_named(pat.node.name).did);
123+
let index = self.tcx.field_index(pat.node.id, self.tables);
124+
self.insert_def_id(variant.fields[index].did);
132125
}
133126
}
134127

@@ -191,18 +184,11 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
191184
self.inherited_pub_visibility = had_inherited_pub_visibility;
192185
}
193186

194-
fn mark_as_used_if_union(&mut self, did: DefId, fields: &hir::HirVec<hir::Field>) {
195-
if let Some(node_id) = self.tcx.hir.as_local_node_id(did) {
196-
if let Some(hir_map::NodeItem(item)) = self.tcx.hir.find(node_id) {
197-
if let Item_::ItemUnion(ref variant, _) = item.node {
198-
if variant.fields().len() > 1 {
199-
for field in variant.fields() {
200-
if fields.iter().find(|x| x.name.node == field.name).is_some() {
201-
self.live_symbols.insert(field.id);
202-
}
203-
}
204-
}
205-
}
187+
fn mark_as_used_if_union(&mut self, adt: &ty::AdtDef, fields: &hir::HirVec<hir::Field>) {
188+
if adt.is_union() && adt.non_enum_variant().fields.len() > 1 && adt.did.is_local() {
189+
for field in fields {
190+
let index = self.tcx.field_index(field.id, self.tables);
191+
self.insert_def_id(adt.non_enum_variant().fields[index].did);
206192
}
207193
}
208194
}
@@ -242,17 +228,12 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> {
242228
hir::ExprMethodCall(..) => {
243229
self.lookup_and_handle_method(expr.hir_id);
244230
}
245-
hir::ExprField(ref lhs, ref name) => {
246-
self.handle_field_access(&lhs, name.node);
247-
}
248-
hir::ExprTupField(ref lhs, idx) => {
249-
self.handle_tup_field_access(&lhs, idx.node);
231+
hir::ExprField(ref lhs, ..) => {
232+
self.handle_field_access(&lhs, expr.id);
250233
}
251234
hir::ExprStruct(_, ref fields, _) => {
252-
if let ty::TypeVariants::TyAdt(ref def, _) = self.tables.expr_ty(expr).sty {
253-
if def.is_union() {
254-
self.mark_as_used_if_union(def.did, fields);
255-
}
235+
if let ty::TypeVariants::TyAdt(ref adt, _) = self.tables.expr_ty(expr).sty {
236+
self.mark_as_used_if_union(adt, fields);
256237
}
257238
}
258239
_ => ()

src/librustc/middle/expr_use_visitor.rs

+6-14
Original file line numberDiff line numberDiff line change
@@ -404,10 +404,6 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
404404
self.select_from_expr(&base);
405405
}
406406

407-
hir::ExprTupField(ref base, _) => { // base.<n>
408-
self.select_from_expr(&base);
409-
}
410-
411407
hir::ExprIndex(ref lhs, ref rhs) => { // lhs[rhs]
412408
self.select_from_expr(&lhs);
413409
self.consume_expr(&rhs);
@@ -663,11 +659,15 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
663659
match with_cmt.ty.sty {
664660
ty::TyAdt(adt, substs) if adt.is_struct() => {
665661
// Consume those fields of the with expression that are needed.
666-
for with_field in &adt.non_enum_variant().fields {
667-
if !contains_field_named(with_field, fields) {
662+
for (f_index, with_field) in adt.non_enum_variant().fields.iter().enumerate() {
663+
let is_mentioned = fields.iter().any(|f| {
664+
self.tcx().field_index(f.id, self.mc.tables) == f_index
665+
});
666+
if !is_mentioned {
668667
let cmt_field = self.mc.cat_field(
669668
&*with_expr,
670669
with_cmt.clone(),
670+
f_index,
671671
with_field.name,
672672
with_field.ty(self.tcx(), substs)
673673
);
@@ -691,14 +691,6 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
691691
// walk the with expression so that complex expressions
692692
// are properly handled.
693693
self.walk_expr(with_expr);
694-
695-
fn contains_field_named(field: &ty::FieldDef,
696-
fields: &[hir::Field])
697-
-> bool
698-
{
699-
fields.iter().any(
700-
|f| f.name.node == field.name)
701-
}
702694
}
703695

704696
// Invoke the appropriate delegate calls for anything that gets

src/librustc/middle/liveness.rs

+2-7
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,7 @@ fn visit_expr<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, expr: &'tcx Expr) {
476476
}
477477

478478
// otherwise, live nodes are not required:
479-
hir::ExprIndex(..) | hir::ExprField(..) | hir::ExprTupField(..) |
479+
hir::ExprIndex(..) | hir::ExprField(..) |
480480
hir::ExprArray(..) | hir::ExprCall(..) | hir::ExprMethodCall(..) |
481481
hir::ExprTup(..) | hir::ExprBinary(..) | hir::ExprAddrOf(..) |
482482
hir::ExprCast(..) | hir::ExprUnary(..) | hir::ExprBreak(..) |
@@ -912,10 +912,6 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
912912
self.propagate_through_expr(&e, succ)
913913
}
914914

915-
hir::ExprTupField(ref e, _) => {
916-
self.propagate_through_expr(&e, succ)
917-
}
918-
919915
hir::ExprClosure(.., blk_id, _, _) => {
920916
debug!("{} is an ExprClosure", self.ir.tcx.hir.node_to_pretty_string(expr.id));
921917

@@ -1226,7 +1222,6 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
12261222
match expr.node {
12271223
hir::ExprPath(_) => succ,
12281224
hir::ExprField(ref e, _) => self.propagate_through_expr(&e, succ),
1229-
hir::ExprTupField(ref e, _) => self.propagate_through_expr(&e, succ),
12301225
_ => self.propagate_through_expr(expr, succ)
12311226
}
12321227
}
@@ -1419,7 +1414,7 @@ fn check_expr<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, expr: &'tcx Expr) {
14191414
// no correctness conditions related to liveness
14201415
hir::ExprCall(..) | hir::ExprMethodCall(..) | hir::ExprIf(..) |
14211416
hir::ExprMatch(..) | hir::ExprWhile(..) | hir::ExprLoop(..) |
1422-
hir::ExprIndex(..) | hir::ExprField(..) | hir::ExprTupField(..) |
1417+
hir::ExprIndex(..) | hir::ExprField(..) |
14231418
hir::ExprArray(..) | hir::ExprTup(..) | hir::ExprBinary(..) |
14241419
hir::ExprCast(..) | hir::ExprUnary(..) | hir::ExprRet(..) |
14251420
hir::ExprBreak(..) | hir::ExprAgain(..) | hir::ExprLit(_) |

0 commit comments

Comments
 (0)