AST/HIR: Merge field access expressions for named and numeric fields

This commit is contained in:
Vadim Petrochenkov 2018-04-01 21:48:39 +03:00
parent 6c537493d0
commit 44acea4d88
43 changed files with 105 additions and 432 deletions

View File

@ -389,7 +389,6 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
hir::ExprType(ref e, _) |
hir::ExprUnary(_, ref e) |
hir::ExprField(ref e, _) |
hir::ExprTupField(ref e, _) |
hir::ExprYield(ref e) |
hir::ExprRepeat(ref e, _) => {
self.straightline(expr, pred, Some(&**e).into_iter())

View File

@ -1025,9 +1025,6 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
visitor.visit_expr(subexpression);
visitor.visit_name(name.span, name.node);
}
ExprTupField(ref subexpression, _) => {
visitor.visit_expr(subexpression);
}
ExprIndex(ref main_expression, ref index_expression) => {
visitor.visit_expr(main_expression);
visitor.visit_expr(index_expression)

View File

@ -3095,7 +3095,6 @@ impl<'a> LoweringContext<'a> {
P(self.lower_expr(el)),
respan(ident.span, self.lower_ident(ident)),
),
ExprKind::TupField(ref el, ident) => hir::ExprTupField(P(self.lower_expr(el)), ident),
ExprKind::Index(ref el, ref er) => {
hir::ExprIndex(P(self.lower_expr(el)), P(self.lower_expr(er)))
}

View File

@ -1276,7 +1276,6 @@ impl Expr {
ExprAssign(..) => ExprPrecedence::Assign,
ExprAssignOp(..) => ExprPrecedence::AssignOp,
ExprField(..) => ExprPrecedence::Field,
ExprTupField(..) => ExprPrecedence::TupField,
ExprIndex(..) => ExprPrecedence::Index,
ExprPath(..) => ExprPrecedence::Path,
ExprAddrOf(..) => ExprPrecedence::AddrOf,
@ -1363,12 +1362,8 @@ pub enum Expr_ {
///
/// For example, `a += 1`.
ExprAssignOp(BinOp, P<Expr>, P<Expr>),
/// Access of a named struct field (`obj.foo`)
/// Access of a named (`obj.foo`) or unnamed (`obj.0`) struct or tuple field
ExprField(P<Expr>, Spanned<Name>),
/// Access of an unnamed field of a struct or tuple-struct
///
/// For example, `foo.0`.
ExprTupField(P<Expr>, Spanned<usize>),
/// An indexing operation (`foo[2]`)
ExprIndex(P<Expr>, P<Expr>),

View File

@ -1201,8 +1201,7 @@ impl<'a> State<'a> {
fn print_expr_call(&mut self, func: &hir::Expr, args: &[hir::Expr]) -> io::Result<()> {
let prec =
match func.node {
hir::ExprField(..) |
hir::ExprTupField(..) => parser::PREC_FORCE_PAREN,
hir::ExprField(..) => parser::PREC_FORCE_PAREN,
_ => parser::PREC_POSTFIX,
};
@ -1405,11 +1404,6 @@ impl<'a> State<'a> {
self.s.word(".")?;
self.print_name(name.node)?;
}
hir::ExprTupField(ref expr, id) => {
self.print_expr_maybe_paren(&expr, parser::PREC_POSTFIX)?;
self.s.word(".")?;
self.print_usize(id.node)?;
}
hir::ExprIndex(ref expr, ref index) => {
self.print_expr_maybe_paren(&expr, parser::PREC_POSTFIX)?;
self.s.word("[")?;
@ -2376,7 +2370,6 @@ fn contains_exterior_struct_lit(value: &hir::Expr) -> bool {
hir::ExprCast(ref x, _) |
hir::ExprType(ref x, _) |
hir::ExprField(ref x, _) |
hir::ExprTupField(ref x, _) |
hir::ExprIndex(ref x, _) => {
// &X { y: 1 }, X { y: 1 }.y
contains_exterior_struct_lit(&x)

View File

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

View File

@ -104,17 +104,8 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
ty::TyAdt(def, _) => {
self.insert_def_id(def.non_enum_variant().field_named(name).did);
}
_ => span_bug!(lhs.span, "named field access on non-ADT"),
}
}
fn handle_tup_field_access(&mut self, lhs: &hir::Expr, idx: usize) {
match self.tables.expr_ty_adjusted(lhs).sty {
ty::TyAdt(def, _) => {
self.insert_def_id(def.non_enum_variant().fields[idx].did);
}
ty::TyTuple(..) => {}
_ => span_bug!(lhs.span, "numeric field access on non-ADT"),
_ => span_bug!(lhs.span, "named field access on non-ADT"),
}
}
@ -245,9 +236,6 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> {
hir::ExprField(ref lhs, ref name) => {
self.handle_field_access(&lhs, name.node);
}
hir::ExprTupField(ref lhs, idx) => {
self.handle_tup_field_access(&lhs, idx.node);
}
hir::ExprStruct(_, ref fields, _) => {
if let ty::TypeVariants::TyAdt(ref def, _) = self.tables.expr_ty(expr).sty {
if def.is_union() {

View File

@ -404,10 +404,6 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
self.select_from_expr(&base);
}
hir::ExprTupField(ref base, _) => { // base.<n>
self.select_from_expr(&base);
}
hir::ExprIndex(ref lhs, ref rhs) => { // lhs[rhs]
self.select_from_expr(&lhs);
self.consume_expr(&rhs);

View File

@ -476,7 +476,7 @@ fn visit_expr<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, expr: &'tcx Expr) {
}
// otherwise, live nodes are not required:
hir::ExprIndex(..) | hir::ExprField(..) | hir::ExprTupField(..) |
hir::ExprIndex(..) | hir::ExprField(..) |
hir::ExprArray(..) | hir::ExprCall(..) | hir::ExprMethodCall(..) |
hir::ExprTup(..) | hir::ExprBinary(..) | hir::ExprAddrOf(..) |
hir::ExprCast(..) | hir::ExprUnary(..) | hir::ExprBreak(..) |
@ -912,10 +912,6 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
self.propagate_through_expr(&e, succ)
}
hir::ExprTupField(ref e, _) => {
self.propagate_through_expr(&e, succ)
}
hir::ExprClosure(.., blk_id, _, _) => {
debug!("{} is an ExprClosure", self.ir.tcx.hir.node_to_pretty_string(expr.id));
@ -1226,7 +1222,6 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
match expr.node {
hir::ExprPath(_) => succ,
hir::ExprField(ref e, _) => self.propagate_through_expr(&e, succ),
hir::ExprTupField(ref e, _) => self.propagate_through_expr(&e, succ),
_ => self.propagate_through_expr(expr, succ)
}
}
@ -1419,7 +1414,7 @@ fn check_expr<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, expr: &'tcx Expr) {
// no correctness conditions related to liveness
hir::ExprCall(..) | hir::ExprMethodCall(..) | hir::ExprIf(..) |
hir::ExprMatch(..) | hir::ExprWhile(..) | hir::ExprLoop(..) |
hir::ExprIndex(..) | hir::ExprField(..) | hir::ExprTupField(..) |
hir::ExprIndex(..) | hir::ExprField(..) |
hir::ExprArray(..) | hir::ExprTup(..) | hir::ExprBinary(..) |
hir::ExprCast(..) | hir::ExprUnary(..) | hir::ExprRet(..) |
hir::ExprBreak(..) | hir::ExprAgain(..) | hir::ExprLit(_) |

View File

@ -62,7 +62,6 @@
pub use self::PointerKind::*;
pub use self::InteriorKind::*;
pub use self::FieldName::*;
pub use self::MutabilityCategory::*;
pub use self::AliasableReason::*;
pub use self::Note::*;
@ -81,7 +80,7 @@ use ty::fold::TypeFoldable;
use hir::{MutImmutable, MutMutable, PatKind};
use hir::pat_util::EnumerateAndAdjustIterator;
use hir;
use syntax::ast;
use syntax::ast::{self, Name};
use syntax_pos::Span;
use std::fmt;
@ -129,15 +128,13 @@ pub enum PointerKind<'tcx> {
// base without a pointer dereference", e.g. a field
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub enum InteriorKind {
InteriorField(FieldName),
InteriorField(FieldIndex),
InteriorElement(InteriorOffsetKind),
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub enum FieldName {
NamedField(ast::Name),
PositionalField(usize)
}
// FIXME: Use actual index instead of `ast::Name` with questionable hygiene
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct FieldIndex(pub ast::Name);
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub enum InteriorOffsetKind {
@ -198,7 +195,7 @@ pub enum ImmutabilityBlame<'tcx> {
}
impl<'tcx> cmt_<'tcx> {
fn resolve_field(&self, field_name: FieldName) -> Option<(&'tcx ty::AdtDef, &'tcx ty::FieldDef)>
fn resolve_field(&self, field_name: Name) -> Option<(&'tcx ty::AdtDef, &'tcx ty::FieldDef)>
{
let adt_def = match self.ty.sty {
ty::TyAdt(def, _) => def,
@ -215,11 +212,7 @@ impl<'tcx> cmt_<'tcx> {
&adt_def.variants[0]
}
};
let field_def = match field_name {
NamedField(name) => variant_def.field_named(name),
PositionalField(idx) => &variant_def.fields[idx]
};
Some((adt_def, field_def))
Some((adt_def, variant_def.field_named(field_name)))
}
pub fn immutability_blame(&self) -> Option<ImmutabilityBlame<'tcx>> {
@ -230,8 +223,8 @@ impl<'tcx> cmt_<'tcx> {
match base_cmt.cat {
Categorization::Local(node_id) =>
Some(ImmutabilityBlame::LocalDeref(node_id)),
Categorization::Interior(ref base_cmt, InteriorField(field_name)) => {
base_cmt.resolve_field(field_name).map(|(adt_def, field_def)| {
Categorization::Interior(ref base_cmt, InteriorField(field_index)) => {
base_cmt.resolve_field(field_index.0).map(|(adt_def, field_def)| {
ImmutabilityBlame::AdtFieldDeref(adt_def, field_def)
})
}
@ -649,11 +642,6 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
Ok(self.cat_field(expr, base_cmt, f_name.node, expr_ty))
}
hir::ExprTupField(ref base, idx) => {
let base_cmt = self.cat_expr(&base)?;
Ok(self.cat_tup_field(expr, base_cmt, idx.node, expr_ty))
}
hir::ExprIndex(ref base, _) => {
if self.tables.is_method_call(expr) {
// If this is an index implemented by a method call, then it
@ -979,14 +967,14 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
pub fn cat_field<N:ast_node>(&self,
node: &N,
base_cmt: cmt<'tcx>,
f_name: ast::Name,
f_name: Name,
f_ty: Ty<'tcx>)
-> cmt<'tcx> {
let ret = Rc::new(cmt_ {
id: node.id(),
span: node.span(),
mutbl: base_cmt.mutbl.inherit(),
cat: Categorization::Interior(base_cmt, InteriorField(NamedField(f_name))),
cat: Categorization::Interior(base_cmt, InteriorField(FieldIndex(f_name))),
ty: f_ty,
note: NoteNone
});
@ -994,24 +982,6 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
ret
}
pub fn cat_tup_field<N:ast_node>(&self,
node: &N,
base_cmt: cmt<'tcx>,
f_idx: usize,
f_ty: Ty<'tcx>)
-> cmt<'tcx> {
let ret = Rc::new(cmt_ {
id: node.id(),
span: node.span(),
mutbl: base_cmt.mutbl.inherit(),
cat: Categorization::Interior(base_cmt, InteriorField(PositionalField(f_idx))),
ty: f_ty,
note: NoteNone
});
debug!("cat_tup_field ret {:?}", ret);
ret
}
fn cat_overloaded_place(&self,
expr: &hir::Expr,
base: &hir::Expr,
@ -1292,8 +1262,8 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
let subpat_ty = self.pat_ty(&subpat)?; // see (*2)
let subcmt = self.cat_imm_interior(pat, cmt.clone(), subpat_ty,
InteriorField(PositionalField(i)));
let interior = InteriorField(FieldIndex(Name::intern(&i.to_string())));
let subcmt = self.cat_imm_interior(pat, cmt.clone(), subpat_ty, interior);
self.cat_pattern_(subcmt, &subpat, op)?;
}
}
@ -1332,8 +1302,8 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
};
for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
let subpat_ty = self.pat_ty(&subpat)?; // see (*2)
let subcmt = self.cat_imm_interior(pat, cmt.clone(), subpat_ty,
InteriorField(PositionalField(i)));
let interior = InteriorField(FieldIndex(Name::intern(&i.to_string())));
let subcmt = self.cat_imm_interior(pat, cmt.clone(), subpat_ty, interior);
self.cat_pattern_(subcmt, &subpat, op)?;
}
}
@ -1516,12 +1486,9 @@ impl<'tcx> cmt_<'tcx> {
}
}
}
Categorization::Interior(_, InteriorField(NamedField(_))) => {
Categorization::Interior(_, InteriorField(..)) => {
"field".to_string()
}
Categorization::Interior(_, InteriorField(PositionalField(_))) => {
"anonymous field".to_string()
}
Categorization::Interior(_, InteriorElement(InteriorOffsetKind::Index)) => {
"indexed content".to_string()
}
@ -1554,8 +1521,7 @@ pub fn ptr_sigil(ptr: PointerKind) -> &'static str {
impl fmt::Debug for InteriorKind {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
InteriorField(NamedField(fld)) => write!(f, "{}", fld),
InteriorField(PositionalField(i)) => write!(f, "#{}", i),
InteriorField(FieldIndex(name)) => write!(f, "{}", name),
InteriorElement(..) => write!(f, "[]"),
}
}

View File

@ -1307,7 +1307,6 @@ fn resolve_local<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>,
hir::ExprAddrOf(_, ref subexpr) |
hir::ExprUnary(hir::UnDeref, ref subexpr) |
hir::ExprField(ref subexpr, _) |
hir::ExprTupField(ref subexpr, _) |
hir::ExprIndex(ref subexpr, _) => {
expr = &subexpr;
}

View File

@ -108,7 +108,7 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> {
RestrictionResult::Safe => RestrictionResult::Safe,
RestrictionResult::SafeIf(base_lp, mut base_vec) => {
for field in &adt_def.non_enum_variant().fields {
let field = InteriorKind::InteriorField(mc::NamedField(field.name));
let field = InteriorKind::InteriorField(mc::FieldIndex(field.name));
let field_ty = if field == interior {
cmt.ty
} else {

View File

@ -370,7 +370,7 @@ const DOWNCAST_PRINTED_OPERATOR: &'static str = " as ";
// is tracked is irrelevant here.)
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub enum InteriorKind {
InteriorField(mc::FieldName),
InteriorField(mc::FieldIndex),
InteriorElement,
}
@ -1336,18 +1336,10 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
out.push(')');
}
LpExtend(ref lp_base, _, LpInterior(_, InteriorField(fname))) => {
LpExtend(ref lp_base, _, LpInterior(_, InteriorField(mc::FieldIndex(fname)))) => {
self.append_autoderefd_loan_path_to_string(&lp_base, out);
match fname {
mc::NamedField(fname) => {
out.push('.');
out.push_str(&fname.as_str());
}
mc::PositionalField(idx) => {
out.push('.');
out.push_str(&idx.to_string());
}
}
out.push('.');
out.push_str(&fname.as_str());
}
LpExtend(ref lp_base, _, LpInterior(_, InteriorElement)) => {
@ -1422,8 +1414,7 @@ impl DataFlowOperator for LoanDataFlowOperator {
impl<'tcx> fmt::Debug for InteriorKind {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
InteriorField(mc::NamedField(fld)) => write!(f, "{}", fld),
InteriorField(mc::PositionalField(i)) => write!(f, "#{}", i),
InteriorField(mc::FieldIndex(name)) => write!(f, "{}", name),
InteriorElement => write!(f, "[]"),
}
}

View File

@ -21,7 +21,6 @@ use rustc::middle::dataflow::DataFlowOperator;
use rustc::middle::dataflow::KillFrom;
use rustc::middle::expr_use_visitor as euv;
use rustc::middle::expr_use_visitor::MutateMode;
use rustc::middle::mem_categorization as mc;
use rustc::ty::{self, TyCtxt};
use rustc::util::nodemap::{FxHashMap, FxHashSet};
@ -344,7 +343,7 @@ impl<'a, 'tcx> MoveData<'tcx> {
= (&base_lp.ty.sty, lp_elem) {
if adt_def.is_union() {
for field in &adt_def.non_enum_variant().fields {
let field = InteriorKind::InteriorField(mc::NamedField(field.name));
let field = InteriorKind::InteriorField(mc::FieldIndex(field.name));
if field != interior {
let sibling_lp_kind =
LpExtend(base_lp.clone(), mutbl, LpInterior(opt_variant_id, field));
@ -396,7 +395,7 @@ impl<'a, 'tcx> MoveData<'tcx> {
if let ty::TyAdt(adt_def, _) = base_lp.ty.sty {
if adt_def.is_union() {
for field in &adt_def.non_enum_variant().fields {
let field = InteriorKind::InteriorField(mc::NamedField(field.name));
let field = InteriorKind::InteriorField(mc::FieldIndex(field.name));
let field_ty = if field == interior {
lp.ty
} else {

View File

@ -584,6 +584,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
hir::ExprField(ref source, name) => {
let index = match cx.tables().expr_ty_adjusted(source).sty {
ty::TyAdt(adt_def, _) => adt_def.variants[0].index_of_field_named(name.node),
ty::TyTuple(..) => name.node.as_str().parse::<usize>().ok(),
ref ty => span_bug!(expr.span, "field of non-ADT: {:?}", ty),
};
let index =
@ -595,12 +596,6 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
name: Field::new(index),
}
}
hir::ExprTupField(ref source, index) => {
ExprKind::Field {
lhs: source.to_ref(),
name: Field::new(index.node as usize),
}
}
hir::ExprCast(ref source, _) => {
// Check to see if this cast is a "coercion cast", where the cast is actually done
// using a coercion (or is a no-op).

View File

@ -407,7 +407,6 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
hir::ExprBlock(_) |
hir::ExprIndex(..) |
hir::ExprField(..) |
hir::ExprTupField(..) |
hir::ExprArray(_) |
hir::ExprType(..) |
hir::ExprTup(..) => {}

View File

@ -25,7 +25,6 @@
use rustc::hir::def::Def as HirDef;
use rustc::hir::def_id::DefId;
use rustc::hir::map::Node;
use rustc::ty::{self, TyCtxt};
use rustc_data_structures::fx::FxHashSet;
@ -1638,52 +1637,6 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
}
}
}
ast::ExprKind::TupField(ref sub_ex, idx) => {
self.visit_expr(&sub_ex);
let hir_node = match self.save_ctxt.tcx.hir.find(sub_ex.id) {
Some(Node::NodeExpr(expr)) => expr,
_ => {
debug!(
"Missing or weird node for sub-expression {} in {:?}",
sub_ex.id,
ex
);
return;
}
};
let ty = match self.save_ctxt.tables.expr_ty_adjusted_opt(&hir_node) {
Some(ty) => &ty.sty,
None => {
visit::walk_expr(self, ex);
return;
}
};
match *ty {
ty::TyAdt(def, _) => {
let sub_span = self.span.sub_span_after_token(ex.span, token::Dot);
if !self.span.filter_generated(sub_span, ex.span) {
let span =
self.span_from_span(sub_span.expect("No span found for var ref"));
if let Some(field) = def.non_enum_variant().fields.get(idx.node) {
let ref_id = ::id_from_def_id(field.did);
self.dumper.dump_ref(Ref {
kind: RefKind::Variable,
span,
ref_id,
});
} else {
return;
}
}
}
ty::TyTuple(..) => {}
_ => {
debug!("Expected struct or tuple type, found {:?}", ty);
return;
}
}
}
ast::ExprKind::Closure(_, _, ref decl, ref body, _fn_decl_span) => {
let mut id = String::from("$");
id.push_str(&ex.id.to_string());

View File

@ -563,6 +563,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
ref_id: id_from_def_id(f.did),
}));
}
ty::TyTuple(..) => None,
_ => {
debug!("Expected struct or union type, found {:?}", ty);
None

View File

@ -202,10 +202,6 @@ impl<'a> SpanUtils<'a> {
self.sub_span_after(span, |t| t.is_keyword(keyword))
}
pub fn sub_span_after_token(&self, span: Span, tok: Token) -> Option<Span> {
self.sub_span_after(span, |t| t == tok)
}
fn sub_span_after<F: Fn(Token) -> bool>(&self, span: Span, f: F) -> Option<Span> {
let mut toks = self.retokenise_span(span);
loop {

View File

@ -433,7 +433,6 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
let last = exprs[exprs.len() - 1];
match last.node {
hir::ExprField(ref expr, _) |
hir::ExprTupField(ref expr, _) |
hir::ExprIndex(ref expr, _) |
hir::ExprUnary(hir::UnDeref, ref expr) => exprs.push(&expr),
_ => break,

View File

@ -85,7 +85,7 @@ use self::method::MethodCallee;
use self::TupleArgumentsFlag::*;
use astconv::AstConv;
use hir::def::{Def, CtorKind};
use hir::def::Def;
use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use std::slice;
use namespace::Namespace;
@ -121,7 +121,7 @@ use std::ops::{self, Deref};
use syntax::abi::Abi;
use syntax::ast;
use syntax::attr;
use syntax::codemap::{self, original_sp, Spanned};
use syntax::codemap::{original_sp, Spanned};
use syntax::feature_gate::{GateIssue, emit_feature_err};
use syntax::ptr::P;
use syntax::symbol::{Symbol, InternedString, keywords};
@ -2266,7 +2266,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
hir::ExprUnary(hir::UnDeref, _) |
hir::ExprField(..) |
hir::ExprTupField(..) |
hir::ExprIndex(..) => {
true
}
@ -3084,6 +3083,20 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
private_candidate = Some((base_def.did, field_ty));
}
}
ty::TyTuple(ref tys) => {
let fstr = field.node.as_str();
if let Ok(index) = fstr.parse::<usize>() {
if fstr == index.to_string() {
if let Some(field_ty) = tys.get(index) {
let adjustments = autoderef.adjust_steps(needs);
self.apply_adjustments(base, adjustments);
autoderef.finalize();
return field_ty;
}
}
}
}
_ => {}
}
}
@ -3189,78 +3202,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
display
}
// Check tuple index expressions
fn check_tup_field(&self,
expr: &'gcx hir::Expr,
needs: Needs,
base: &'gcx hir::Expr,
idx: codemap::Spanned<usize>) -> Ty<'tcx> {
let expr_t = self.check_expr_with_needs(base, needs);
let expr_t = self.structurally_resolved_type(expr.span,
expr_t);
let mut private_candidate = None;
let mut tuple_like = false;
let mut autoderef = self.autoderef(expr.span, expr_t);
while let Some((base_t, _)) = autoderef.next() {
let field = match base_t.sty {
ty::TyAdt(base_def, substs) if base_def.is_struct() => {
tuple_like = base_def.non_enum_variant().ctor_kind == CtorKind::Fn;
if !tuple_like { continue }
debug!("tuple struct named {:?}", base_t);
let ident =
ast::Ident::new(Symbol::intern(&idx.node.to_string()), idx.span.modern());
let (ident, def_scope) =
self.tcx.adjust_ident(ident, base_def.did, self.body_id);
let fields = &base_def.non_enum_variant().fields;
if let Some(field) = fields.iter().find(|f| f.name.to_ident() == ident) {
let field_ty = self.field_ty(expr.span, field, substs);
if field.vis.is_accessible_from(def_scope, self.tcx) {
self.tcx.check_stability(field.did, Some(expr.id), expr.span);
Some(field_ty)
} else {
private_candidate = Some((base_def.did, field_ty));
None
}
} else {
None
}
}
ty::TyTuple(ref v) => {
tuple_like = true;
v.get(idx.node).cloned()
}
_ => continue
};
if let Some(field_ty) = field {
let adjustments = autoderef.adjust_steps(needs);
self.apply_adjustments(base, adjustments);
autoderef.finalize();
return field_ty;
}
}
autoderef.unambiguous_final_ty();
if let Some((did, field_ty)) = private_candidate {
let struct_path = self.tcx().item_path_str(did);
struct_span_err!(self.tcx().sess, expr.span, E0611,
"field `{}` of tuple-struct `{}` is private",
idx.node, struct_path).emit();
return field_ty;
}
if tuple_like {
type_error_struct!(self.tcx().sess, expr.span, expr_t, E0612,
"attempted out-of-bounds tuple index `{}` on type `{}`",
idx.node, expr_t).emit();
} else {
self.no_such_field_err(expr.span, idx.node, expr_t).emit();
}
self.tcx().types.err
}
fn no_such_field_err<T: Display>(&self, span: Span, field: T, expr_t: &ty::TyS)
-> DiagnosticBuilder {
type_error_struct!(self.tcx().sess, span, expr_t, E0609,
@ -4121,9 +4062,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
hir::ExprField(ref base, ref field) => {
self.check_field(expr, needs, &base, field)
}
hir::ExprTupField(ref base, idx) => {
self.check_tup_field(expr, needs, &base, idx)
}
hir::ExprIndex(ref base, ref idx) => {
let base_t = self.check_expr_with_needs(&base, needs);
let idx_t = self.check_expr(&idx);

View File

@ -4138,86 +4138,6 @@ https://doc.rust-lang.org/book/first-edition/primitive-types.html
https://doc.rust-lang.org/book/first-edition/structs.html
"##,
E0611: r##"
Attempted to access a private field on a tuple-struct.
Erroneous code example:
```compile_fail,E0611
mod some_module {
pub struct Foo(u32);
impl Foo {
pub fn new() -> Foo { Foo(0) }
}
}
let y = some_module::Foo::new();
println!("{}", y.0); // error: field `0` of tuple-struct `some_module::Foo`
// is private
```
Since the field is private, you have two solutions:
1) Make the field public:
```
mod some_module {
pub struct Foo(pub u32); // The field is now public.
impl Foo {
pub fn new() -> Foo { Foo(0) }
}
}
let y = some_module::Foo::new();
println!("{}", y.0); // So we can access it directly.
```
2) Add a getter function to keep the field private but allow for accessing its
value:
```
mod some_module {
pub struct Foo(u32);
impl Foo {
pub fn new() -> Foo { Foo(0) }
// We add the getter function.
pub fn get(&self) -> &u32 { &self.0 }
}
}
let y = some_module::Foo::new();
println!("{}", y.get()); // So we can get the value through the function.
```
"##,
E0612: r##"
Attempted out-of-bounds tuple index.
Erroneous code example:
```compile_fail,E0612
struct Foo(u32);
let y = Foo(0);
println!("{}", y.1); // error: attempted out-of-bounds tuple index `1`
// on type `Foo`
```
If a tuple/tuple-struct type has n fields, you can only try to access these n
fields from 0 to (n - 1). So in this case, you can only index `0`. Example:
```
struct Foo(u32);
let y = Foo(0);
println!("{}", y.0); // ok!
```
"##,
E0614: r##"
Attempted to dereference a variable which cannot be dereferenced.
@ -4839,6 +4759,8 @@ register_diagnostics! {
E0587, // type has conflicting packed and align representation hints
E0588, // packed type cannot transitively contain a `[repr(align)]` type
E0592, // duplicate definitions with name `{}`
// E0611, // merged into E0616
// E0612, // merged into E0609
// E0613, // Removed (merged with E0609)
E0640, // infer outlives
E0627, // yield statement outside of generator literal

View File

@ -1018,7 +1018,6 @@ impl Expr {
ExprKind::Assign(..) => ExprPrecedence::Assign,
ExprKind::AssignOp(..) => ExprPrecedence::AssignOp,
ExprKind::Field(..) => ExprPrecedence::Field,
ExprKind::TupField(..) => ExprPrecedence::TupField,
ExprKind::Index(..) => ExprPrecedence::Index,
ExprKind::Range(..) => ExprPrecedence::Range,
ExprKind::Path(..) => ExprPrecedence::Path,
@ -1133,12 +1132,8 @@ pub enum ExprKind {
///
/// For example, `a += 1`.
AssignOp(BinOp, P<Expr>, P<Expr>),
/// Access of a named struct field (`obj.foo`)
/// Access of a named (`obj.foo`) or unnamed (`obj.0`) struct field
Field(P<Expr>, Ident),
/// Access of an unnamed field of a struct or tuple-struct
///
/// For example, `foo.0`.
TupField(P<Expr>, Spanned<usize>),
/// An indexing operation (`foo[2]`)
Index(P<Expr>, P<Expr>),
/// A range (`1..2`, `1..`, `..2`, `1...2`, `1...`, `...2`)

View File

@ -636,8 +636,8 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
self.expr(sp, ast::ExprKind::Field(expr, ident.with_span_pos(sp)))
}
fn expr_tup_field_access(&self, sp: Span, expr: P<ast::Expr>, idx: usize) -> P<ast::Expr> {
let id = Spanned { node: idx, span: sp };
self.expr(sp, ast::ExprKind::TupField(expr, id))
let id = Spanned { node: Ident::from_str(&idx.to_string()), span: sp };
self.expr(sp, ast::ExprKind::Field(expr, id))
}
fn expr_addr_of(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr> {
self.expr(sp, ast::ExprKind::AddrOf(ast::Mutability::Immutable, e))

View File

@ -1267,11 +1267,6 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu
ExprKind::Field(el, ident) => {
ExprKind::Field(folder.fold_expr(el), folder.fold_ident(ident))
}
ExprKind::TupField(el, index) => {
ExprKind::TupField(folder.fold_expr(el),
respan(folder.new_span(index.span),
folder.fold_usize(index.node)))
}
ExprKind::Index(el, er) => {
ExprKind::Index(folder.fold_expr(el), folder.fold_expr(er))
}

View File

@ -2144,10 +2144,6 @@ impl<'a> Parser<'a> {
}
}
pub fn mk_tup_field(&mut self, expr: P<Expr>, idx: codemap::Spanned<usize>) -> ast::ExprKind {
ExprKind::TupField(expr, idx)
}
pub fn mk_assign_op(&mut self, binop: ast::BinOp,
lhs: P<Expr>, rhs: P<Expr>) -> ast::ExprKind {
ExprKind::AssignOp(binop, lhs, rhs)
@ -2605,35 +2601,12 @@ impl<'a> Parser<'a> {
token::Ident(..) => {
e = self.parse_dot_suffix(e, lo)?;
}
token::Literal(token::Integer(index_ident), suf) => {
let sp = self.span;
// A tuple index may not have a suffix
self.expect_no_suffix(sp, "tuple index", suf);
let idx_span = self.span;
token::Literal(token::Integer(name), _) => {
let span = self.span;
self.bump();
let invalid_msg = "invalid tuple or struct index";
let index = index_ident.as_str().parse::<usize>().ok();
match index {
Some(n) => {
if n.to_string() != index_ident.as_str() {
let mut err = self.struct_span_err(self.prev_span, invalid_msg);
err.span_suggestion(self.prev_span,
"try simplifying the index",
n.to_string());
err.emit();
}
let field = self.mk_tup_field(e, respan(idx_span, n));
e = self.mk_expr(lo.to(idx_span), field, ThinVec::new());
}
None => {
let prev_span = self.prev_span;
self.span_err(prev_span, invalid_msg);
}
}
let ident = Ident { name, ctxt: span.ctxt() };
let field = ExprKind::Field(e, respan(span, ident));
e = self.mk_expr(lo.to(span), field, ThinVec::new());
}
token::Literal(token::Float(n), _suf) => {
self.bump();

View File

@ -1966,8 +1966,7 @@ impl<'a> State<'a> {
args: &[P<ast::Expr>]) -> io::Result<()> {
let prec =
match func.node {
ast::ExprKind::Field(..) |
ast::ExprKind::TupField(..) => parser::PREC_FORCE_PAREN,
ast::ExprKind::Field(..) => parser::PREC_FORCE_PAREN,
_ => parser::PREC_POSTFIX,
};
@ -2203,11 +2202,6 @@ impl<'a> State<'a> {
self.s.word(".")?;
self.print_ident(ident)?;
}
ast::ExprKind::TupField(ref expr, id) => {
self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX)?;
self.s.word(".")?;
self.print_usize(id.node)?;
}
ast::ExprKind::Index(ref expr, ref index) => {
self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX)?;
self.s.word("[")?;

View File

@ -251,7 +251,6 @@ pub enum ExprPrecedence {
Call,
MethodCall,
Field,
TupField,
Index,
Try,
InlineAsm,
@ -320,7 +319,6 @@ impl ExprPrecedence {
ExprPrecedence::Call |
ExprPrecedence::MethodCall |
ExprPrecedence::Field |
ExprPrecedence::TupField |
ExprPrecedence::Index |
ExprPrecedence::Try |
ExprPrecedence::InlineAsm |
@ -365,7 +363,6 @@ pub fn contains_exterior_struct_lit(value: &ast::Expr) -> bool {
ast::ExprKind::Cast(ref x, _) |
ast::ExprKind::Type(ref x, _) |
ast::ExprKind::Field(ref x, _) |
ast::ExprKind::TupField(ref x, _) |
ast::ExprKind::Index(ref x, _) => {
// &X { y: 1 }, X { y: 1 }.y
contains_exterior_struct_lit(&x)

View File

@ -749,9 +749,6 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
visitor.visit_expr(subexpression);
visitor.visit_ident(ident);
}
ExprKind::TupField(ref subexpression, _) => {
visitor.visit_expr(subexpression);
}
ExprKind::Index(ref main_expression, ref index_expression) => {
visitor.visit_expr(main_expression);
visitor.visit_expr(index_expression)

View File

@ -12,5 +12,5 @@ const TUP: (usize,) = (42,);
fn main() {
let a: [isize; TUP.1];
//~^ ERROR attempted out-of-bounds tuple index
//~^ ERROR no field `1` on type `(usize,)`
}

View File

@ -42,7 +42,7 @@ fn test(a: A, b: inner::A, c: inner::B, d: xc::A, e: xc::B, z: inner::Z) {
e.b; //~ ERROR: field `b` of struct `xc::B` is private
z.0;
z.1; //~ ERROR: field `1` of tuple-struct `inner::Z` is private
z.1; //~ ERROR: field `1` of struct `inner::Z` is private
}
fn main() {}

View File

@ -15,10 +15,10 @@ fn main() {
origin.0;
origin.1;
origin.2;
//~^ ERROR attempted out-of-bounds tuple index `2` on type `Point`
//~^ ERROR no field `2` on type `Point`
let tuple = (0, 0);
tuple.0;
tuple.1;
tuple.2;
//~^ ERROR attempted out-of-bounds tuple index `2` on type `({integer}, {integer})`
//~^ ERROR no field `2` on type `({integer}, {integer})`
}

View File

@ -7,10 +7,10 @@ LL | let _ = x.foo; //~ ERROR E0609
= note: available fields are: `x`
error[E0609]: no field `1` on type `Bar`
--> $DIR/E0609.rs:21:5
--> $DIR/E0609.rs:21:7
|
LL | y.1; //~ ERROR E0609
| ^^^
| ^ unknown field
error: aborting due to 2 previous errors

View File

@ -1,9 +0,0 @@
error[E0611]: field `0` of tuple-struct `a::Foo` is private
--> $DIR/E0611.rs:21:4
|
LL | y.0; //~ ERROR E0611
| ^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0611`.

View File

@ -1,9 +0,0 @@
error[E0612]: attempted out-of-bounds tuple index `1` on type `Foo`
--> $DIR/E0612.rs:15:4
|
LL | y.1; //~ ERROR E0612
| ^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0612`.

View File

@ -18,5 +18,5 @@ mod a {
fn main() {
let y = a::Foo::new();
y.0; //~ ERROR E0611
y.0; //~ ERROR field `0` of struct `a::Foo` is private
}

View File

@ -0,0 +1,9 @@
error[E0616]: field `0` of struct `a::Foo` is private
--> $DIR/ex-E0611.rs:21:4
|
LL | y.0; //~ ERROR field `0` of struct `a::Foo` is private
| ^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0616`.

View File

@ -12,5 +12,5 @@ struct Foo(u32);
fn main() {
let y = Foo(0);
y.1; //~ ERROR E0612
y.1; //~ ERROR no field `1` on type `Foo`
}

View File

@ -0,0 +1,9 @@
error[E0609]: no field `1` on type `Foo`
--> $DIR/ex-E0612.rs:15:6
|
LL | y.1; //~ ERROR no field `1` on type `Foo`
| ^ did you mean `0`?
error: aborting due to previous error
For more information about this error, try `rustc --explain E0609`.

View File

@ -16,7 +16,7 @@ struct Verdict(Guilty, Option<FineDollars>);
fn main() {
let justice = Verdict(true, Some(2718));
let _condemned = justice.00;
//~^ ERROR invalid tuple or struct index
//~^ ERROR no field `00` on type `Verdict`
let _punishment = justice.001;
//~^ ERROR invalid tuple or struct index
//~^ ERROR no field `001` on type `Verdict`
}

View File

@ -1,14 +1,17 @@
error: invalid tuple or struct index
error[E0609]: no field `00` on type `Verdict`
--> $DIR/issue-47073-zero-padded-tuple-struct-indices.rs:18:30
|
LL | let _condemned = justice.00;
| ^^ help: try simplifying the index: `0`
| ^^ did you mean `0`?
error: invalid tuple or struct index
error[E0609]: no field `001` on type `Verdict`
--> $DIR/issue-47073-zero-padded-tuple-struct-indices.rs:20:31
|
LL | let _punishment = justice.001;
| ^^^ help: try simplifying the index: `1`
| ^^^ unknown field
|
= note: available fields are: `0`, `1`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0609`.

View File

@ -24,7 +24,7 @@ macro_rules! fake_field_stmt {
macro_rules! fake_anon_field_stmt {
() => {
(1).0 //~ ERROR no field
(1).0 //~ ERROR doesn't have fields
}
}
@ -42,7 +42,7 @@ macro_rules! fake_field_expr {
macro_rules! fake_anon_field_expr {
() => {
(1).0 //~ ERROR no field
(1).0 //~ ERROR doesn't have fields
}
}

View File

@ -16,11 +16,11 @@ LL | 1.fake //~ ERROR doesn't have fields
LL | fake_field_stmt!();
| ------------------- in this macro invocation
error[E0609]: no field `0` on type `{integer}`
--> $DIR/macro-backtrace-invalid-internals.rs:27:11
error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
--> $DIR/macro-backtrace-invalid-internals.rs:27:15
|
LL | (1).0 //~ ERROR no field
| ^^^^^
LL | (1).0 //~ ERROR doesn't have fields
| ^
...
LL | fake_anon_field_stmt!();
| ------------------------ in this macro invocation
@ -56,11 +56,11 @@ LL | 1.fake //~ ERROR doesn't have fields
LL | let _ = fake_field_expr!();
| ------------------ in this macro invocation
error[E0609]: no field `0` on type `{integer}`
--> $DIR/macro-backtrace-invalid-internals.rs:45:11
error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
--> $DIR/macro-backtrace-invalid-internals.rs:45:15
|
LL | (1).0 //~ ERROR no field
| ^^^^^
LL | (1).0 //~ ERROR doesn't have fields
| ^
...
LL | let _ = fake_anon_field_expr!();
| ----------------------- in this macro invocation
@ -80,5 +80,5 @@ LL | 2.0_f32.powi(2) //~ ERROR can't call method `powi` on ambiguous n
error: aborting due to 8 previous errors
Some errors occurred: E0599, E0609, E0610, E0689.
Some errors occurred: E0599, E0610, E0689.
For more information about an error, try `rustc --explain E0599`.