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 https://github.com/rust-lang/rust/issues/46314
This commit is contained in:
bors 2018-04-13 01:43:09 +00:00
commit defcfe7142
87 changed files with 759 additions and 676 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

@ -658,6 +658,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
PatKind::Struct(ref qpath, ref fields, _) => {
visitor.visit_qpath(qpath, pattern.id, pattern.span);
for field in fields {
visitor.visit_id(field.node.id);
visitor.visit_name(field.span, field.node.name);
visitor.visit_pat(&field.node.pat)
}
@ -959,6 +960,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
ExprStruct(ref qpath, ref fields, ref optional_base) => {
visitor.visit_qpath(qpath, expression.id, expression.span);
for field in fields {
visitor.visit_id(field.id);
visitor.visit_name(field.name.span, field.name.node);
visitor.visit_expr(&field.expr)
}
@ -1025,9 +1027,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

@ -2100,6 +2100,7 @@ impl<'a> LoweringContext<'a> {
fn lower_field(&mut self, f: &Field) -> hir::Field {
hir::Field {
id: self.next_id().node_id,
name: respan(f.ident.span, self.lower_ident(f.ident)),
expr: P(self.lower_expr(&f.expr)),
span: f.span,
@ -2863,6 +2864,7 @@ impl<'a> LoweringContext<'a> {
.map(|f| Spanned {
span: f.span,
node: hir::FieldPat {
id: self.next_id().node_id,
name: self.lower_ident(f.node.ident),
pat: self.lower_pat(&f.node.pat),
is_shorthand: f.node.is_shorthand,
@ -3095,7 +3097,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)))
}
@ -3742,6 +3743,7 @@ impl<'a> LoweringContext<'a> {
fn field(&mut self, name: Name, expr: P<hir::Expr>, span: Span) -> hir::Field {
hir::Field {
id: self.next_id().node_id,
name: Spanned { node: name, span },
span,
expr,

View file

@ -827,6 +827,7 @@ impl Pat {
/// except is_shorthand is true
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct FieldPat {
pub id: NodeId,
/// The identifier for the field
pub name: Name,
/// The pattern the field is destructured to
@ -1172,6 +1173,7 @@ pub struct Arm {
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct Field {
pub id: NodeId,
pub name: Spanned<Name>,
pub expr: P<Expr>,
pub span: Span,
@ -1276,7 +1278,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 +1364,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

@ -420,11 +420,23 @@ impl<'a> HashStable<StableHashingContext<'a>> for hir::Pat {
}
impl_stable_hash_for_spanned!(hir::FieldPat);
impl_stable_hash_for!(struct hir::FieldPat {
name,
pat,
is_shorthand
});
impl<'a> HashStable<StableHashingContext<'a>> for hir::FieldPat {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher<W>) {
let hir::FieldPat {
id: _,
name,
ref pat,
is_shorthand,
} = *self;
name.hash_stable(hcx, hasher);
pat.hash_stable(hcx, hasher);
is_shorthand.hash_stable(hcx, hasher);
}
}
impl_stable_hash_for!(enum hir::BindingAnnotation {
Unannotated,
@ -507,12 +519,24 @@ impl_stable_hash_for!(struct hir::Arm {
body
});
impl_stable_hash_for!(struct hir::Field {
name,
expr,
span,
is_shorthand
});
impl<'a> HashStable<StableHashingContext<'a>> for hir::Field {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher<W>) {
let hir::Field {
id: _,
name,
ref expr,
span,
is_shorthand,
} = *self;
name.hash_stable(hcx, hasher);
expr.hash_stable(hcx, hasher);
span.hash_stable(hcx, hasher);
is_shorthand.hash_stable(hcx, hasher);
}
}
impl_stable_hash_for_spanned!(ast::Name);
@ -569,7 +593,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

@ -13,7 +13,7 @@
// from live codes are live, and everything else is dead.
use hir::map as hir_map;
use hir::{self, Item_, PatKind};
use hir::{self, PatKind};
use hir::intravisit::{self, Visitor, NestedVisitorMap};
use hir::itemlikevisit::ItemLikeVisitor;
@ -99,22 +99,14 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
self.check_def_id(self.tables.type_dependent_defs()[id].def_id());
}
fn handle_field_access(&mut self, lhs: &hir::Expr, name: ast::Name) {
fn handle_field_access(&mut self, lhs: &hir::Expr, node_id: ast::NodeId) {
match self.tables.expr_ty_adjusted(lhs).sty {
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);
let index = self.tcx.field_index(node_id, self.tables);
self.insert_def_id(def.non_enum_variant().fields[index].did);
}
ty::TyTuple(..) => {}
_ => span_bug!(lhs.span, "numeric field access on non-ADT"),
_ => span_bug!(lhs.span, "named field access on non-ADT"),
}
}
@ -128,7 +120,8 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
if let PatKind::Wild = pat.node.pat.node {
continue;
}
self.insert_def_id(variant.field_named(pat.node.name).did);
let index = self.tcx.field_index(pat.node.id, self.tables);
self.insert_def_id(variant.fields[index].did);
}
}
@ -191,18 +184,11 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
self.inherited_pub_visibility = had_inherited_pub_visibility;
}
fn mark_as_used_if_union(&mut self, did: DefId, fields: &hir::HirVec<hir::Field>) {
if let Some(node_id) = self.tcx.hir.as_local_node_id(did) {
if let Some(hir_map::NodeItem(item)) = self.tcx.hir.find(node_id) {
if let Item_::ItemUnion(ref variant, _) = item.node {
if variant.fields().len() > 1 {
for field in variant.fields() {
if fields.iter().find(|x| x.name.node == field.name).is_some() {
self.live_symbols.insert(field.id);
}
}
}
}
fn mark_as_used_if_union(&mut self, adt: &ty::AdtDef, fields: &hir::HirVec<hir::Field>) {
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.id, self.tables);
self.insert_def_id(adt.non_enum_variant().fields[index].did);
}
}
}
@ -242,17 +228,12 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> {
hir::ExprMethodCall(..) => {
self.lookup_and_handle_method(expr.hir_id);
}
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::ExprField(ref lhs, ..) => {
self.handle_field_access(&lhs, expr.id);
}
hir::ExprStruct(_, ref fields, _) => {
if let ty::TypeVariants::TyAdt(ref def, _) = self.tables.expr_ty(expr).sty {
if def.is_union() {
self.mark_as_used_if_union(def.did, fields);
}
if let ty::TypeVariants::TyAdt(ref adt, _) = self.tables.expr_ty(expr).sty {
self.mark_as_used_if_union(adt, fields);
}
}
_ => ()

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);
@ -663,11 +659,15 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
match with_cmt.ty.sty {
ty::TyAdt(adt, substs) if adt.is_struct() => {
// Consume those fields of the with expression that are needed.
for with_field in &adt.non_enum_variant().fields {
if !contains_field_named(with_field, fields) {
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.id, self.mc.tables) == f_index
});
if !is_mentioned {
let cmt_field = self.mc.cat_field(
&*with_expr,
with_cmt.clone(),
f_index,
with_field.name,
with_field.ty(self.tcx(), substs)
);
@ -691,14 +691,6 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
// walk the with expression so that complex expressions
// are properly handled.
self.walk_expr(with_expr);
fn contains_field_named(field: &ty::FieldDef,
fields: &[hir::Field])
-> bool
{
fields.iter().any(
|f| f.name.node == field.name)
}
}
// Invoke the appropriate delegate calls for anything that gets

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,10 +80,11 @@ 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;
use std::hash::{Hash, Hasher};
use rustc_data_structures::sync::Lrc;
use std::rc::Rc;
use util::nodemap::ItemLocalSet;
@ -129,14 +129,25 @@ 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)
// Contains index of a field that is actually used for loan path comparisons and
// string representation of the field that should be used only for diagnostics.
#[derive(Clone, Copy, Eq)]
pub struct FieldIndex(pub usize, pub Name);
impl PartialEq for FieldIndex {
fn eq(&self, rhs: &Self) -> bool {
self.0 == rhs.0
}
}
impl Hash for FieldIndex {
fn hash<H: Hasher>(&self, h: &mut H) {
self.0.hash(h)
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
@ -198,7 +209,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_index: usize) -> Option<(&'tcx ty::AdtDef, &'tcx ty::FieldDef)>
{
let adt_def = match self.ty.sty {
ty::TyAdt(def, _) => def,
@ -215,11 +226,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.fields[field_index]))
}
pub fn immutability_blame(&self) -> Option<ImmutabilityBlame<'tcx>> {
@ -230,8 +237,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)
})
}
@ -646,12 +653,8 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
expr.id,
expr,
base_cmt);
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))
let f_index = self.tcx.field_index(expr.id, self.tables);
Ok(self.cat_field(expr, base_cmt, f_index, f_name.node, expr_ty))
}
hir::ExprIndex(ref base, _) => {
@ -979,14 +982,15 @@ 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_index: usize,
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_index, f_name))),
ty: f_ty,
note: NoteNone
});
@ -994,24 +998,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 +1278,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(i, Name::intern(&i.to_string())));
let subcmt = self.cat_imm_interior(pat, cmt.clone(), subpat_ty, interior);
self.cat_pattern_(subcmt, &subpat, op)?;
}
}
@ -1315,7 +1301,8 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
for fp in field_pats {
let field_ty = self.pat_ty(&fp.node.pat)?; // see (*2)
let cmt_field = self.cat_field(pat, cmt.clone(), fp.node.name, field_ty);
let f_index = self.tcx.field_index(fp.node.id, self.tables);
let cmt_field = self.cat_field(pat, cmt.clone(), f_index, fp.node.name, field_ty);
self.cat_pattern_(cmt_field, &fp.node.pat, op)?;
}
}
@ -1332,8 +1319,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(i, 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 +1503,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 +1538,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(_, info)) => write!(f, "{}", info),
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

@ -346,6 +346,12 @@ pub struct TypeckTables<'tcx> {
/// method calls, including those of overloaded operators.
type_dependent_defs: ItemLocalMap<Def>,
/// Resolved field indices for field accesses in expressions (`S { field }`, `obj.field`)
/// or patterns (`S { field }`). The index is often useful by itself, but to learn more
/// about the field you also need definition of the variant to which the field
/// belongs, but it may not exist if it's a tuple field (`tuple.0`).
field_indices: ItemLocalMap<usize>,
/// Stores the canonicalized types provided by the user. See also `UserAssertTy` statement in
/// MIR.
user_provided_tys: ItemLocalMap<CanonicalTy<'tcx>>,
@ -426,6 +432,7 @@ impl<'tcx> TypeckTables<'tcx> {
TypeckTables {
local_id_root,
type_dependent_defs: ItemLocalMap(),
field_indices: ItemLocalMap(),
user_provided_tys: ItemLocalMap(),
node_types: ItemLocalMap(),
node_substs: ItemLocalMap(),
@ -468,6 +475,20 @@ impl<'tcx> TypeckTables<'tcx> {
}
}
pub fn field_indices(&self) -> LocalTableInContext<usize> {
LocalTableInContext {
local_id_root: self.local_id_root,
data: &self.field_indices
}
}
pub fn field_indices_mut(&mut self) -> LocalTableInContextMut<usize> {
LocalTableInContextMut {
local_id_root: self.local_id_root,
data: &mut self.field_indices
}
}
pub fn user_provided_tys(&self) -> LocalTableInContext<CanonicalTy<'tcx>> {
LocalTableInContext {
local_id_root: self.local_id_root,
@ -706,6 +727,7 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for TypeckTables<'gcx> {
let ty::TypeckTables {
local_id_root,
ref type_dependent_defs,
ref field_indices,
ref user_provided_tys,
ref node_types,
ref node_substs,
@ -726,6 +748,7 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for TypeckTables<'gcx> {
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
type_dependent_defs.hash_stable(hcx, hasher);
field_indices.hash_stable(hcx, hasher);
user_provided_tys.hash_stable(hcx, hasher);
node_types.hash_stable(hcx, hasher);
node_substs.hash_stable(hcx, hasher);

View file

@ -50,7 +50,7 @@ use std::vec::IntoIter;
use std::mem;
use syntax::ast::{self, DUMMY_NODE_ID, Name, Ident, NodeId};
use syntax::attr;
use syntax::ext::hygiene::{Mark, SyntaxContext};
use syntax::ext::hygiene::Mark;
use syntax::symbol::{Symbol, InternedString};
use syntax_pos::{DUMMY_SP, Span};
@ -2107,32 +2107,6 @@ impl<'a, 'gcx, 'tcx> AdtDef {
}
}
impl<'a, 'gcx, 'tcx> VariantDef {
#[inline]
pub fn find_field_named(&self, name: ast::Name) -> Option<&FieldDef> {
self.index_of_field_named(name).map(|index| &self.fields[index])
}
pub fn index_of_field_named(&self, name: ast::Name) -> Option<usize> {
if let Some(index) = self.fields.iter().position(|f| f.name == name) {
return Some(index);
}
let mut ident = name.to_ident();
while ident.span.ctxt() != SyntaxContext::empty() {
ident.span.remove_mark();
if let Some(field) = self.fields.iter().position(|f| f.name.to_ident() == ident) {
return Some(field);
}
}
None
}
#[inline]
pub fn field_named(&self, name: ast::Name) -> &FieldDef {
self.find_field_named(name).unwrap()
}
}
impl<'a, 'gcx, 'tcx> FieldDef {
pub fn ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, subst: &Substs<'tcx>) -> Ty<'tcx> {
tcx.type_of(self.did).subst(tcx, subst)
@ -2399,6 +2373,17 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
}
}
pub fn field_index(self, node_id: NodeId, tables: &TypeckTables) -> usize {
let hir_id = self.hir.node_to_hir_id(node_id);
tables.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.iter().position(|field| {
self.adjust_ident(ident.modern(), variant.did, DUMMY_NODE_ID).0 == field.name.to_ident()
})
}
pub fn associated_items(
self,
def_id: DefId,

View file

@ -33,7 +33,7 @@ use rustc_data_structures::fx::FxHashMap;
use std::{cmp, fmt};
use std::hash::Hash;
use std::intrinsics;
use syntax::ast::{self, Name};
use syntax::ast;
use syntax::attr::{self, SignedInt, UnsignedInt};
use syntax_pos::{Span, DUMMY_SP};
@ -270,42 +270,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
false
}
/// Returns the type of element at index `i` in tuple or tuple-like type `t`.
/// For an enum `t`, `variant` is None only if `t` is a univariant enum.
pub fn positional_element_ty(self,
ty: Ty<'tcx>,
i: usize,
variant: Option<DefId>) -> Option<Ty<'tcx>> {
match (&ty.sty, variant) {
(&TyAdt(adt, substs), Some(vid)) => {
adt.variant_with_id(vid).fields.get(i).map(|f| f.ty(self, substs))
}
(&TyAdt(adt, substs), None) => {
// Don't use `non_enum_variant`, this may be a univariant enum.
adt.variants[0].fields.get(i).map(|f| f.ty(self, substs))
}
(&TyTuple(ref v), None) => v.get(i).cloned(),
_ => None,
}
}
/// Returns the type of element at field `n` in struct or struct-like type `t`.
/// For an enum `t`, `variant` must be some def id.
pub fn named_element_ty(self,
ty: Ty<'tcx>,
n: Name,
variant: Option<DefId>) -> Option<Ty<'tcx>> {
match (&ty.sty, variant) {
(&TyAdt(adt, substs), Some(vid)) => {
adt.variant_with_id(vid).find_field_named(n).map(|f| f.ty(self, substs))
}
(&TyAdt(adt, substs), None) => {
adt.non_enum_variant().find_field_named(n).map(|f| f.ty(self, substs))
}
_ => return None
}
}
/// Returns the deeply last field of nested structures, or the same type,
/// if not a structure at all. Corresponds to the only possible unsized
/// field, and its type can be used to determine unsizing strategy.

View file

@ -107,8 +107,9 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> {
ty::TyAdt(adt_def, _) if adt_def.is_union() => match result {
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));
for (i, field) in adt_def.non_enum_variant().fields.iter().enumerate() {
let field =
InteriorKind::InteriorField(mc::FieldIndex(i, 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(_, info)))) => {
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(&info.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(_, info)) => write!(f, "{}", info),
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};
@ -343,8 +342,8 @@ impl<'a, 'tcx> MoveData<'tcx> {
if let (&ty::TyAdt(adt_def, _), LpInterior(opt_variant_id, interior))
= (&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));
for (i, field) in adt_def.non_enum_variant().fields.iter().enumerate() {
let field = InteriorKind::InteriorField(mc::FieldIndex(i, field.name));
if field != interior {
let sibling_lp_kind =
LpExtend(base_lp.clone(), mutbl, LpInterior(opt_variant_id, field));
@ -395,8 +394,8 @@ impl<'a, 'tcx> MoveData<'tcx> {
if let LpExtend(ref base_lp, mutbl, LpInterior(opt_variant_id, interior)) = lp.kind {
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));
for (i, field) in adt_def.non_enum_variant().fields.iter().enumerate() {
let field = InteriorKind::InteriorField(mc::FieldIndex(i, field.name));
let field_ty = if field == interior {
lp.ty
} else {

View file

@ -166,19 +166,24 @@ impl LintPass for NonShorthandFieldPatterns {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonShorthandFieldPatterns {
fn check_pat(&mut self, cx: &LateContext, pat: &hir::Pat) {
if let PatKind::Struct(_, ref field_pats, _) = pat.node {
if let PatKind::Struct(ref qpath, ref field_pats, _) = pat.node {
let variant = cx.tables.pat_ty(pat).ty_adt_def()
.expect("struct pattern type is not an ADT")
.variant_of_def(cx.tables.qpath_def(qpath, pat.hir_id));
for fieldpat in field_pats {
if fieldpat.node.is_shorthand {
continue;
}
if fieldpat.span.ctxt().outer().expn_info().is_some() {
// Don't lint if this is a macro expansion: macro authors
// shouldn't have to worry about this kind of style issue
// (Issue #49588)
continue;
}
if let PatKind::Binding(_, _, name, None) = fieldpat.node.pat.node {
if name.node == fieldpat.node.name {
if let Some(_) = fieldpat.span.ctxt().outer().expn_info() {
// Don't lint if this is a macro expansion: macro authors
// shouldn't have to worry about this kind of style issue
// (Issue #49588)
return;
}
let binding_ident = ast::Ident::new(name.node, name.span);
if cx.tcx.find_field_index(binding_ident, &variant) ==
Some(cx.tcx.field_index(fieldpat.node.id, cx.tables)) {
let mut err = cx.struct_span_lint(NON_SHORTHAND_FIELD_PATTERNS,
fieldpat.span,
&format!("the `{}:` in this pattern is redundant",

View file

@ -16,7 +16,7 @@ use hair::cx::to_ref::ToRef;
use rustc::hir::def::{Def, CtorKind};
use rustc::middle::const_val::ConstVal;
use rustc::mir::interpret::{GlobalId, Value, PrimVal};
use rustc::ty::{self, AdtKind, VariantDef, Ty};
use rustc::ty::{self, AdtKind, Ty};
use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability};
use rustc::ty::cast::CastKind as TyCastKind;
use rustc::hir;
@ -420,12 +420,11 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
ty::TyAdt(adt, substs) => {
match adt.adt_kind() {
AdtKind::Struct | AdtKind::Union => {
let field_refs = field_refs(&adt.variants[0], fields);
ExprKind::Adt {
adt_def: adt,
variant_index: 0,
substs,
fields: field_refs,
fields: field_refs(cx, fields),
base: base.as_ref().map(|base| {
FruInfo {
base: base.to_ref(),
@ -446,12 +445,11 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
assert!(base.is_none());
let index = adt.variant_index_with_id(variant_id);
let field_refs = field_refs(&adt.variants[index], fields);
ExprKind::Adt {
adt_def: adt,
variant_index: index,
substs,
fields: field_refs,
fields: field_refs(cx, fields),
base: None,
}
}
@ -581,24 +579,10 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
body: block::to_expr_ref(cx, body),
}
}
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),
ref ty => span_bug!(expr.span, "field of non-ADT: {:?}", ty),
};
let index =
index.unwrap_or_else(|| {
span_bug!(expr.span, "no index found for field `{}`", name.node)
});
hir::ExprField(ref source, ..) => {
ExprKind::Field {
lhs: source.to_ref(),
name: Field::new(index),
}
}
hir::ExprTupField(ref source, index) => {
ExprKind::Field {
lhs: source.to_ref(),
name: Field::new(index.node as usize),
name: Field::new(cx.tcx.field_index(expr.id, cx.tables)),
}
}
hir::ExprCast(ref source, _) => {
@ -999,13 +983,13 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
}
/// Converts a list of named fields (i.e. for struct-like struct/enum ADTs) into FieldExprRef.
fn field_refs<'tcx>(variant: &'tcx VariantDef,
fields: &'tcx [hir::Field])
-> Vec<FieldExprRef<'tcx>> {
fn field_refs<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
fields: &'tcx [hir::Field])
-> Vec<FieldExprRef<'tcx>> {
fields.iter()
.map(|field| {
FieldExprRef {
name: Field::new(variant.index_of_field_named(field.name.node).unwrap()),
name: Field::new(cx.tcx.field_index(field.id, cx.tables)),
expr: field.expr.to_ref(),
}
})

View file

@ -528,28 +528,12 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
PatKind::Struct(ref qpath, ref fields, _) => {
let def = self.tables.qpath_def(qpath, pat.hir_id);
let adt_def = match ty.sty {
ty::TyAdt(adt_def, _) => adt_def,
_ => {
span_bug!(
pat.span,
"struct pattern not applied to an ADT");
}
};
let variant_def = adt_def.variant_of_def(def);
let subpatterns =
fields.iter()
.map(|field| {
let index = variant_def.index_of_field_named(field.node.name);
let index = index.unwrap_or_else(|| {
span_bug!(
pat.span,
"no field with name {:?}",
field.node.name);
});
FieldPattern {
field: Field::new(index),
field: Field::new(self.tcx.field_index(field.node.id,
self.tables)),
pattern: self.lower_pattern(&field.node.pat),
}
})

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

@ -568,8 +568,10 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
// If the expression uses FRU we need to make sure all the unmentioned fields
// are checked for privacy (RFC 736). Rather than computing the set of
// unmentioned fields, just check them all.
for variant_field in &variant.fields {
let field = fields.iter().find(|f| f.name.node == variant_field.name);
for (vf_index, variant_field) in variant.fields.iter().enumerate() {
let field = fields.iter().find(|f| {
self.tcx.field_index(f.id, self.tables) == vf_index
});
let (use_ctxt, span) = match field {
Some(field) => (field.name.node.to_ident().span, field.span),
None => (base.span, base.span),
@ -579,8 +581,8 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
} else {
for field in fields {
let use_ctxt = field.name.node.to_ident().span;
let field_def = variant.field_named(field.name.node);
self.check_field(use_ctxt, field.span, adt, field_def);
let index = self.tcx.field_index(field.id, self.tables);
self.check_field(use_ctxt, field.span, adt, &variant.fields[index]);
}
}
}
@ -598,8 +600,8 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
let variant = adt.variant_of_def(def);
for field in fields {
let use_ctxt = field.node.name.to_ident().span;
let field_def = variant.field_named(field.node.name);
self.check_field(use_ctxt, field.span, adt, field_def);
let index = self.tcx.field_index(field.node.id, self.tables);
self.check_field(use_ctxt, field.span, adt, &variant.fields[index]);
}
}
_ => {}

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;
@ -1006,20 +1005,16 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
};
let variant = adt.variant_of_def(self.save_ctxt.get_path_def(p.id));
for &Spanned {
node: ref field,
span,
} in fields
{
for &Spanned { node: ref field, span } in fields {
let sub_span = self.span.span_for_first_ident(span);
if let Some(f) = variant.find_field_named(field.ident.name) {
if let Some(index) = self.tcx.find_field_index(field.ident, variant) {
if !self.span.filter_generated(sub_span, span) {
let span =
self.span_from_span(sub_span.expect("No span fund for var ref"));
self.dumper.dump_ref(Ref {
kind: RefKind::Variable,
span,
ref_id: ::id_from_def_id(f.did),
ref_id: ::id_from_def_id(variant.fields[index].did),
});
}
}
@ -1638,52 +1633,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

@ -553,16 +553,18 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
};
match self.tables.expr_ty_adjusted(&hir_node).sty {
ty::TyAdt(def, _) if !def.is_enum() => {
let f = def.non_enum_variant().field_named(ident.name);
let variant = &def.non_enum_variant();
let index = self.tcx.find_field_index(ident, variant).unwrap();
let sub_span = self.span_utils.span_for_last_ident(expr.span);
filter!(self.span_utils, sub_span, expr.span, None);
let span = self.span_from_span(sub_span.unwrap());
return Some(Data::RefData(Ref {
kind: RefKind::Variable,
span,
ref_id: id_from_def_id(f.did),
ref_id: id_from_def_id(variant.fields[index].did),
}));
}
ty::TyTuple(..) => None,
_ => {
debug!("Expected struct or union type, found {:?}", ty);
None
@ -816,7 +818,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
field_ref: &ast::Field,
variant: &ty::VariantDef,
) -> Option<Ref> {
let f = variant.find_field_named(field_ref.ident.name)?;
let index = self.tcx.find_field_index(field_ref.ident, variant).unwrap();
// We don't really need a sub-span here, but no harm done
let sub_span = self.span_utils.span_for_last_ident(field_ref.ident.span);
filter!(self.span_utils, sub_span, field_ref.ident.span, None);
@ -824,7 +826,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
Some(Ref {
kind: RefKind::Variable,
span,
ref_id: id_from_def_id(f.did),
ref_id: id_from_def_id(variant.fields[index].did),
})
}

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

@ -860,7 +860,8 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
// Index the struct fields' types.
let field_map = variant.fields
.iter()
.map(|field| (field.name, field))
.enumerate()
.map(|(i, field)| (field.name.to_ident(), (i, field)))
.collect::<FxHashMap<_, _>>();
// Keep track of which fields have already appeared in the pattern.
@ -869,7 +870,8 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
let mut inexistent_fields = vec![];
// Typecheck each field.
for &Spanned { node: ref field, span } in fields {
let field_ty = match used_fields.entry(field.name) {
let ident = tcx.adjust(field.name, variant.did, self.body_id).0;
let field_ty = match used_fields.entry(ident) {
Occupied(occupied) => {
struct_span_err!(tcx.sess, span, E0025,
"field `{}` bound multiple times \
@ -883,10 +885,10 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
}
Vacant(vacant) => {
vacant.insert(span);
field_map.get(&field.name)
.map(|f| {
field_map.get(&ident)
.map(|(i, f)| {
self.write_field_index(field.id, *i);
self.tcx.check_stability(f.did, Some(pat_id), span);
self.field_ty(span, f, substs)
})
.unwrap_or_else(|| {
@ -958,8 +960,8 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
} else if !etc {
let unmentioned_fields = variant.fields
.iter()
.map(|field| field.name)
.filter(|field| !used_fields.contains_key(&field))
.map(|field| field.name.to_ident())
.filter(|ident| !used_fields.contains_key(&ident))
.collect::<Vec<_>>();
if unmentioned_fields.len() > 0 {
let field_names = if unmentioned_fields.len() == 1 {

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

@ -304,8 +304,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
for (ty, _) in self.autoderef(span, rcvr_ty) {
match ty.sty {
ty::TyAdt(def, substs) if !def.is_enum() => {
if let Some(field) = def.non_enum_variant()
.find_field_named(item_name) {
let variant = &def.non_enum_variant();
if let Some(index) =
self.tcx.find_field_index(item_name.to_ident(), variant) {
let field = &variant.fields[index];
let snippet = tcx.sess.codemap().span_to_snippet(expr.span);
let expr_string = match snippet {
Ok(expr_string) => expr_string,

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};
@ -1938,6 +1938,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
}
}
pub fn write_field_index(&self, node_id: ast::NodeId, index: usize) {
let hir_id = self.tcx.hir.node_to_hir_id(node_id);
self.tables.borrow_mut().field_indices_mut().insert(hir_id, index);
}
// The NodeId and the ItemLocalId must identify the same item. We just pass
// both of them for consistency checking.
pub fn write_method_call(&self,
@ -2266,7 +2271,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
hir::ExprUnary(hir::UnDeref, _) |
hir::ExprField(..) |
hir::ExprTupField(..) |
hir::ExprIndex(..) => {
true
}
@ -3070,20 +3074,36 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let (ident, def_scope) =
self.tcx.adjust(field.node, 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) {
if let Some(index) = fields.iter().position(|f| f.name.to_ident() == ident) {
let field = &fields[index];
let field_ty = self.field_ty(expr.span, field, substs);
if field.vis.is_accessible_from(def_scope, self.tcx) {
let adjustments = autoderef.adjust_steps(needs);
self.apply_adjustments(base, adjustments);
autoderef.finalize();
self.write_field_index(expr.id, index);
self.tcx.check_stability(field.did, Some(expr.id), expr.span);
return field_ty;
}
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();
self.write_field_index(expr.id, index);
return field_ty;
}
}
}
}
_ => {}
}
}
@ -3189,78 +3209,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,
@ -3343,8 +3291,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
};
let mut remaining_fields = FxHashMap();
for field in &variant.fields {
remaining_fields.insert(field.name.to_ident(), field);
for (i, field) in variant.fields.iter().enumerate() {
remaining_fields.insert(field.name.to_ident(), (i, field));
}
let mut seen_fields = FxHashMap();
@ -3354,8 +3302,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// Typecheck each field.
for field in ast_fields {
let ident = tcx.adjust(field.name.node, variant.did, self.body_id).0;
let field_type = if let Some(v_field) = remaining_fields.remove(&ident) {
seen_fields.insert(field.name.node, field.span);
let field_type = if let Some((i, v_field)) = remaining_fields.remove(&ident) {
seen_fields.insert(ident, field.span);
self.write_field_index(field.id, i);
// we don't look at stability attributes on
// struct-like enums (yet...), but it's definitely not
@ -3367,18 +3316,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
self.field_ty(field.span, v_field, substs)
} else {
error_happened = true;
if let Some(_) = variant.find_field_named(field.name.node) {
if let Some(prev_span) = seen_fields.get(&ident) {
let mut err = struct_span_err!(self.tcx.sess,
field.name.span,
E0062,
"field `{}` specified more than once",
field.name.node);
ident);
err.span_label(field.name.span, "used more than once");
if let Some(prev_span) = seen_fields.get(&field.name.node) {
err.span_label(*prev_span, format!("first use of `{}`", field.name.node));
}
err.span_label(*prev_span, format!("first use of `{}`", ident));
err.emit();
} else {
@ -4121,9 +4067,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

@ -226,13 +226,24 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> {
self.visit_node_id(e.span, e.hir_id);
if let hir::ExprClosure(_, _, body, _, _) = e.node {
let body = self.fcx.tcx.hir.body(body);
for arg in &body.arguments {
self.visit_node_id(e.span, arg.hir_id);
}
match e.node {
hir::ExprClosure(_, _, body, _, _) => {
let body = self.fcx.tcx.hir.body(body);
for arg in &body.arguments {
self.visit_node_id(e.span, arg.hir_id);
}
self.visit_body(body);
self.visit_body(body);
}
hir::ExprStruct(_, ref fields, _) => {
for field in fields {
self.visit_field_id(field.id);
}
}
hir::ExprField(..) => {
self.visit_field_id(e.id);
}
_ => {}
}
intravisit::walk_expr(self, e);
@ -254,6 +265,11 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> {
.expect("missing binding mode");
self.tables.pat_binding_modes_mut().insert(p.hir_id, bm);
}
hir::PatKind::Struct(_, ref fields, _) => {
for field in fields {
self.visit_field_id(field.node.id);
}
}
_ => {}
};
@ -384,6 +400,13 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
}
}
fn visit_field_id(&mut self, node_id: ast::NodeId) {
let hir_id = self.tcx().hir.node_to_hir_id(node_id);
if let Some(index) = self.fcx.tables.borrow_mut().field_indices_mut().remove(hir_id) {
self.tables.field_indices_mut().insert(hir_id, index);
}
}
fn visit_node_id(&mut self, span: Span, hir_id: hir::HirId) {
// Export associated path extensions and method resultions.
if let Some(def) = self.fcx

View file

@ -514,11 +514,11 @@ fn convert_struct_variant<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
discr: ty::VariantDiscr,
def: &hir::VariantData)
-> ty::VariantDef {
let mut seen_fields: FxHashMap<ast::Name, Span> = FxHashMap();
let mut seen_fields: FxHashMap<ast::Ident, Span> = FxHashMap();
let node_id = tcx.hir.as_local_node_id(did).unwrap();
let fields = def.fields().iter().map(|f| {
let fid = tcx.hir.local_def_id(f.id);
let dup_span = seen_fields.get(&f.name).cloned();
let dup_span = seen_fields.get(&f.name.to_ident()).cloned();
if let Some(prev_span) = dup_span {
struct_span_err!(tcx.sess, f.span, E0124,
"field `{}` is already declared",
@ -527,7 +527,7 @@ fn convert_struct_variant<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
.span_label(prev_span, format!("`{}` first declared here", f.name))
.emit();
} else {
seen_fields.insert(f.name, f.span);
seen_fields.insert(f.name.to_ident(), f.span);
}
ty::FieldDef {

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)
E0627, // yield statement outside of generator literal
E0632, // cannot provide explicit type parameters when `impl Trait` is used in

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 ident = Ident::from_str(&idx.to_string()).with_span_pos(sp);
self.expr(sp, ast::ExprKind::Field(expr, ident))
}
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,11 @@ 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 field = ExprKind::Field(e, Ident::new(name, span));
e = self.mk_expr(lo.to(span), field, ThinVec::new());
}
token::Literal(token::Float(n), _suf) => {
self.bump();
@ -7058,7 +7030,7 @@ impl<'a> Parser<'a> {
match self.token {
token::Ident(ident, false) if ident.name == keywords::Underscore.name() => {
self.bump(); // `_`
Ok(Some(Ident { name: ident.name.gensymed(), ..ident }))
Ok(Some(Ident::new(ident.name.gensymed(), ident.span)))
}
_ => self.parse_ident().map(Some),
}

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

@ -36,7 +36,7 @@ fn main() {
let mut line1 = Line::default();
let _moved = line1.origin;
let _ = line1.origin.x + 1; //[ast]~ ERROR use of collaterally moved value: `line1.origin.x`
let _ = line1.origin.x + 1; //[ast]~ ERROR use of moved value: `line1.origin.x`
//[mir]~^ [E0382]
let mut line2 = Line::default();

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

@ -40,29 +40,29 @@ fn query() -> bool { true }
// END RUST SOURCE
// START rustc.main.SimplifyCfg-qualify-consts.after.mir
// fn main() -> () {
// fn main() -> (){
// let mut _0: ();
// scope 1 {
// let _2: S<'35_0rs>;
// let _2: S<'36_0rs>;
// }
// scope 2 {
// }
// ...
// let mut _1: ();
// let mut _3: std::cell::Cell<std::option::Option<&'35_0rs S<'35_0rs>>>;
// let mut _4: std::option::Option<&'35_0rs S<'35_0rs>>;
// let mut _3: std::cell::Cell<std::option::Option<&'36_0rs S<'36_0rs>>>;
// let mut _4: std::option::Option<&'36_0rs S<'36_0rs>>;
// let mut _5: ();
// let mut _6: &'16s std::cell::Cell<std::option::Option<&'35_0rs S<'35_0rs>>>;
// let mut _7: std::option::Option<&'35_0rs S<'35_0rs>>;
// let mut _8: &'35_0rs S<'35_0rs>;
// let mut _9: &'35_0rs S<'35_0rs>;
// let mut _6: &'17s std::cell::Cell<std::option::Option<&'36_0rs S<'36_0rs>>>;
// let mut _7: std::option::Option<&'36_0rs S<'36_0rs>>;
// let mut _8: &'36_0rs S<'36_0rs>;
// let mut _9: &'36_0rs S<'36_0rs>;
// let mut _10: ();
// let mut _11: bool;
// let mut _12: !;
// let mut _13: ();
// let mut _14: &'33s std::cell::Cell<std::option::Option<&'35_0rs S<'35_0rs>>>;
// let mut _15: std::option::Option<&'35_0rs S<'35_0rs>>;
// let mut _16: &'35_0rs S<'35_0rs>;
// let mut _17: &'35_0rs S<'35_0rs>;
//
// let mut _14: &'34s std::cell::Cell<std::option::Option<&'36_0rs S<'36_0rs>>>;
// let mut _15: std::option::Option<&'36_0rs S<'36_0rs>>;
// let mut _16: &'36_0rs S<'36_0rs>;
// let mut _17: &'36_0rs S<'36_0rs>;
// bb0: {
// goto -> bb1;
// }
@ -73,7 +73,7 @@ fn query() -> bool { true }
// StorageLive(_2);
// StorageLive(_3);
// StorageLive(_4);
// _4 = std::option::Option<&'35_0rs S<'35_0rs>>::None;
// _4 = std::option::Option<&'36_0rs S<'36_0rs>>::None;
// _3 = const <std::cell::Cell<T>>::new(move _4) -> [return: bb4, unwind: bb3];
// }
// bb3: {
@ -81,21 +81,21 @@ fn query() -> bool { true }
// }
// bb4: {
// StorageDead(_4);
// _2 = S<'35_0rs> { r: move _3 };
// _2 = S<'36_0rs> { r: move _3 };
// StorageDead(_3);
// StorageLive(_6);
// _6 = &'16s (_2.0: std::cell::Cell<std::option::Option<&'35_0rs S<'35_0rs>>>);
// _6 = &'17s (_2.0: std::cell::Cell<std::option::Option<&'36_0rs S<'36_0rs>>>);
// StorageLive(_7);
// StorageLive(_8);
// StorageLive(_9);
// _9 = &'35_0rs _2;
// _8 = &'35_0rs (*_9);
// _7 = std::option::Option<&'35_0rs S<'35_0rs>>::Some(move _8,);
// _9 = &'36_0rs _2;
// _8 = &'36_0rs (*_9);
// _7 = std::option::Option<&'36_0rs S<'36_0rs>>::Some(move _8,);
// StorageDead(_8);
// _5 = const <std::cell::Cell<T>>::set(move _6, move _7) -> [return: bb5, unwind: bb3];
// }
// bb5: {
// EndRegion('16s);
// EndRegion('17s);
// StorageDead(_7);
// StorageDead(_6);
// StorageDead(_9);
@ -108,7 +108,7 @@ fn query() -> bool { true }
// bb7: {
// _0 = ();
// StorageDead(_11);
// EndRegion('35_0rs);
// EndRegion('36_0rs);
// StorageDead(_2);
// return;
// }
@ -116,23 +116,23 @@ fn query() -> bool { true }
// _10 = ();
// StorageDead(_11);
// StorageLive(_14);
// _14 = &'33s (_2.0: std::cell::Cell<std::option::Option<&'35_0rs S<'35_0rs>>>);
// _14 = &'34s (_2.0: std::cell::Cell<std::option::Option<&'36_0rs S<'36_0rs>>>);
// StorageLive(_15);
// StorageLive(_16);
// StorageLive(_17);
// _17 = &'35_0rs _2;
// _16 = &'35_0rs (*_17);
// _15 = std::option::Option<&'35_0rs S<'35_0rs>>::Some(move _16,);
// _17 = &'36_0rs _2;
// _16 = &'36_0rs (*_17);
// _15 = std::option::Option<&'36_0rs S<'36_0rs>>::Some(move _16,);
// StorageDead(_16);
// _13 = const <std::cell::Cell<T>>::set(move _14, move _15) -> [return: bb9, unwind: bb3];
// }
// bb9: {
// EndRegion('33s);
// EndRegion('34s);
// StorageDead(_15);
// StorageDead(_14);
// StorageDead(_17);
// _1 = ();
// EndRegion('35_0rs);
// EndRegion('36_0rs);
// StorageDead(_2);
// goto -> bb1;
// }

View file

@ -29,34 +29,46 @@ fn main() {
// END RUST SOURCE
// START rustc.main.EraseRegions.after.mir
// fn main() -> () {
// ...
// fn main() -> (){
// let mut _0: ();
// scope 1 {
// let _1: Test;
// scope 3 {
// let _2: &ReErased Test;
// }
// scope 4 {
// }
// }
// scope 2 {
// }
// let mut _3: ();
// let mut _4: &ReErased i32;
// let mut _5: &ReErased i32;
// bb0: {
// StorageLive(_1);
// _1 = Test { x: const 0i32 };
// StorageLive(_2);
// Validate(Suspend(ReScope(Remainder(BlockRemainder { block: ItemLocalId(19), first_statement_index: 3 }))), [_1: Test]);
// Validate(Suspend(ReScope(Remainder(BlockRemainder { block: ItemLocalId(20), first_statement_index: 3 }))), [_1: Test]);
// _2 = &ReErased _1;
// Validate(Acquire, [(*_2): Test/ReScope(Remainder(BlockRemainder { block: ItemLocalId(19), first_statement_index: 3 })) (imm)]);
// Validate(Acquire, [(*_2): Test/ReScope(Remainder(BlockRemainder { block: ItemLocalId(20), first_statement_index: 3 })) (imm)]);
// StorageLive(_4);
// StorageLive(_5);
// Validate(Suspend(ReScope(Node(ItemLocalId(17)))), [((*_2).0: i32): i32/ReScope(Remainder(BlockRemainder { block: ItemLocalId(19), first_statement_index: 3 })) (imm)]);
// Validate(Suspend(ReScope(Node(ItemLocalId(18)))), [((*_2).0: i32): i32/ReScope(Remainder(BlockRemainder { block: ItemLocalId(20), first_statement_index: 3 })) (imm)]);
// _5 = &ReErased ((*_2).0: i32);
// Validate(Acquire, [(*_5): i32/ReScope(Node(ItemLocalId(17))) (imm)]);
// Validate(Suspend(ReScope(Node(ItemLocalId(17)))), [(*_5): i32/ReScope(Node(ItemLocalId(17))) (imm)]);
// Validate(Acquire, [(*_5): i32/ReScope(Node(ItemLocalId(18))) (imm)]);
// Validate(Suspend(ReScope(Node(ItemLocalId(18)))), [(*_5): i32/ReScope(Node(ItemLocalId(18))) (imm)]);
// _4 = &ReErased (*_5);
// Validate(Acquire, [(*_4): i32/ReScope(Node(ItemLocalId(17))) (imm)]);
// Validate(Release, [_3: (), _4: &ReScope(Node(ItemLocalId(17))) i32]);
// Validate(Acquire, [(*_4): i32/ReScope(Node(ItemLocalId(18))) (imm)]);
// Validate(Release, [_3: (), _4: &ReScope(Node(ItemLocalId(18))) i32]);
// _3 = const foo(move _4) -> bb1;
// }
// bb1: {
// Validate(Acquire, [_3: ()]);
// EndRegion(ReScope(Node(ItemLocalId(17))));
// EndRegion(ReScope(Node(ItemLocalId(18))));
// StorageDead(_4);
// StorageDead(_5);
// _0 = ();
// EndRegion(ReScope(Remainder(BlockRemainder { block: ItemLocalId(19), first_statement_index: 3 })));
// EndRegion(ReScope(Remainder(BlockRemainder { block: ItemLocalId(20), first_statement_index: 3 })));
// StorageDead(_2);
// StorageDead(_1);
// return;

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

@ -0,0 +1,25 @@
error[E0407]: method `method` is not a member of trait `Tr`
--> $DIR/assoc_item_ctxt.rs:45:13
|
LL | fn method() {} //~ ERROR method `method` is not a member of trait `Tr`
| ^^^^^^^^^^^^^^ not a member of trait `Tr`
...
LL | mac_trait_impl!();
| ------------------ in this macro invocation
error[E0046]: not all trait items implemented, missing: `method`
--> $DIR/assoc_item_ctxt.rs:44:9
|
LL | fn method();
| ------------ `method` from trait
...
LL | impl Tr for u8 { //~ ERROR not all trait items implemented, missing: `method`
| ^^^^^^^^^^^^^^ missing `method` in implementation
...
LL | mac_trait_impl!();
| ------------------ in this macro invocation
error: aborting due to 2 previous errors
Some errors occurred: E0046, E0407.
For more information about an error, try `rustc --explain E0046`.

View file

@ -0,0 +1,8 @@
error: compilation successful
--> $DIR/assoc_ty_bindings.rs:49:1
|
LL | fn main() {} //~ ERROR compilation successful
| ^^^^^^^^^^^^
error: aborting due to previous error

View file

@ -0,0 +1,32 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(decl_macro)]
macro modern($a: ident) {
struct Modern {
a: u8,
$a: u8, // OK
}
}
macro_rules! legacy {
($a: ident) => {
struct Legacy {
a: u8,
$a: u8, //~ ERROR field `a` is already declared
}
}
}
modern!(a);
legacy!(a);
fn main() {}

View file

@ -0,0 +1,14 @@
error[E0124]: field `a` is already declared
--> $DIR/fields-definition.rs:24:17
|
LL | a: u8,
| ----- `a` first declared here
LL | $a: u8, //~ ERROR field `a` is already declared
| ^^ field already declared
...
LL | legacy!(a);
| ----------- in this macro invocation
error: aborting due to previous error
For more information about this error, try `rustc --explain E0124`.

View file

@ -0,0 +1,40 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// issue #46314
#![feature(decl_macro)]
#[derive(Debug)]
struct NonCopy(String);
struct Foo {
x: NonCopy,
}
macro copy_modern($foo: ident) {
$foo.x
}
macro_rules! copy_legacy {
($foo: ident) => {
$foo.x //~ ERROR use of moved value: `foo.x`
}
}
fn assert_two_copies(a: NonCopy, b: NonCopy) {
println!("Got two copies: {:?}, {:?}", a, b);
}
fn main() {
let foo = Foo { x: NonCopy("foo".into()) };
assert_two_copies(copy_modern!(foo), foo.x); //~ ERROR use of moved value: `foo.x`
assert_two_copies(copy_legacy!(foo), foo.x); //~ ERROR use of moved value: `foo.x`
}

View file

@ -0,0 +1,39 @@
error[E0382]: use of moved value: `foo.x`
--> $DIR/fields-move.rs:38:42
|
LL | $foo.x
| ------ value moved here
...
LL | assert_two_copies(copy_modern!(foo), foo.x); //~ ERROR use of moved value: `foo.x`
| ^^^^^ value used here after move
|
= note: move occurs because `foo.x` has type `NonCopy`, which does not implement the `Copy` trait
error[E0382]: use of moved value: `foo.x`
--> $DIR/fields-move.rs:28:9
|
LL | $foo.x
| ------ value moved here
...
LL | $foo.x //~ ERROR use of moved value: `foo.x`
| ^^^^^^ value used here after move
...
LL | assert_two_copies(copy_legacy!(foo), foo.x); //~ ERROR use of moved value: `foo.x`
| ----------------- in this macro invocation
|
= note: move occurs because `foo.x` has type `NonCopy`, which does not implement the `Copy` trait
error[E0382]: use of moved value: `foo.x`
--> $DIR/fields-move.rs:39:42
|
LL | $foo.x
| ------ value moved here
...
LL | assert_two_copies(copy_legacy!(foo), foo.x); //~ ERROR use of moved value: `foo.x`
| ^^^^^ value used here after move
|
= note: move occurs because `foo.x` has type `NonCopy`, which does not implement the `Copy` trait
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0382`.

View file

@ -0,0 +1,18 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
struct S(u8);
fn main() {
let mut s = S(0);
let borrow1 = &mut s.0;
let S { 0: ref mut borrow2 } = s;
//~^ ERROR cannot borrow `s.0` as mutable more than once at a time
}

View file

@ -0,0 +1,14 @@
error[E0499]: cannot borrow `s.0` as mutable more than once at a time
--> $DIR/fields-numeric-borrowck.rs:16:16
|
LL | let borrow1 = &mut s.0;
| --- first mutable borrow occurs here
LL | let S { 0: ref mut borrow2 } = s;
| ^^^^^^^^^^^^^^^ second mutable borrow occurs here
LL | //~^ ERROR cannot borrow `s.0` as mutable more than once at a time
LL | }
| - first borrow ends here
error: aborting due to previous error
For more information about this error, try `rustc --explain E0499`.

View file

@ -0,0 +1,38 @@
error: type `foo::S` is private
--> $DIR/fields.rs:25:17
|
LL | let s = S { x: 0 }; //~ ERROR type `foo::S` is private
| ^^^^^^^^^^
...
LL | let s = foo::m!(S, x);
| ------------- in this macro invocation
error: type `foo::S` is private
--> $DIR/fields.rs:26:17
|
LL | let _ = s.x; //~ ERROR type `foo::S` is private
| ^
...
LL | let s = foo::m!(S, x);
| ------------- in this macro invocation
error: type `foo::T` is private
--> $DIR/fields.rs:28:17
|
LL | let t = T(0); //~ ERROR type `foo::T` is private
| ^^^^
...
LL | let s = foo::m!(S, x);
| ------------- in this macro invocation
error: type `foo::T` is private
--> $DIR/fields.rs:29:17
|
LL | let _ = t.0; //~ ERROR type `foo::T` is private
| ^
...
LL | let s = foo::m!(S, x);
| ------------- in this macro invocation
error: aborting due to 4 previous errors

View file

@ -0,0 +1,9 @@
error[E0425]: cannot find value `iter` in this scope
--> $DIR/for-loop.rs:16:9
|
LL | iter.next(); //~ ERROR cannot find value `iter` in this scope
| ^^^^ not found in this scope
error: aborting due to previous error
For more information about this error, try `rustc --explain E0425`.

View file

@ -0,0 +1,49 @@
error[E0425]: cannot find function `f` in this scope
--> $DIR/globs.rs:32:9
|
LL | f(); //~ ERROR cannot find function `f` in this scope
| ^ not found in this scope
help: possible candidates are found in other modules, you can import them into scope
|
LL | use foo::f;
|
LL | use foo::f;
|
LL | use foo::f;
|
error[E0425]: cannot find function `g` in this scope
--> $DIR/globs.rs:25:5
|
LL | g(); //~ ERROR cannot find function `g` in this scope
| ^ not found in this scope
...
LL | / m! {
LL | | use bar::*;
LL | | g();
LL | | f(); //~ ERROR cannot find function `f` in this scope
LL | | }
| |_____- in this macro invocation
help: possible candidates are found in other modules, you can import them into scope
|
LL | use bar::g;
|
LL | use foo::test2::test::g;
|
LL | use foo::test::g;
|
LL | use foo::test::g;
|
error[E0425]: cannot find function `f` in this scope
--> $DIR/globs.rs:64:17
|
LL | n!(f);
| ------ in this macro invocation
...
LL | f //~ ERROR cannot find function `f` in this scope
| ^ not found in this scope
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0425`.

View file

@ -0,0 +1,11 @@
error: type `for<'r> fn(&'r foo::S) {foo::S::f}` is private
--> $DIR/impl_items.rs:22:23
|
LL | let _: () = S.f(); //~ ERROR type `for<'r> fn(&'r foo::S) {foo::S::f}` is private
| ^
...
LL | foo::m!();
| ---------- in this macro invocation
error: aborting due to previous error

View file

@ -0,0 +1,10 @@
error: type `fn() -> u32 {intercrate::foo::bar::f}` is private
--> $DIR/intercrate.rs:22:16
|
LL | assert_eq!(intercrate::foo::m!(), 1);
| ^^^^^^^^^^^^^^^^^^^^^
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error: aborting due to previous error

View file

@ -0,0 +1,9 @@
error[E0616]: field `i` of struct `foo::S` is private
--> $DIR/nested_macro_privacy.rs:25:5
|
LL | S::default().i; //~ ERROR field `i` of struct `foo::S` is private
| ^^^^^^^^^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0616`.

View file

@ -0,0 +1,30 @@
error[E0433]: failed to resolve. Use of undeclared type or module `Vec`
--> $DIR/no_implicit_prelude.rs:21:9
|
LL | fn f() { ::bar::m!(); }
| ------------ in this macro invocation
...
LL | Vec::new(); //~ ERROR failed to resolve
| ^^^ Use of undeclared type or module `Vec`
error[E0601]: `main` function not found in crate `no_implicit_prelude`
|
= note: consider adding a `main` function to `$DIR/no_implicit_prelude.rs`
error[E0599]: no method named `clone` found for type `()` in the current scope
--> $DIR/no_implicit_prelude.rs:22:12
|
LL | fn f() { ::bar::m!(); }
| ------------ in this macro invocation
...
LL | ().clone() //~ ERROR no method named `clone` found
| ^^^^^
|
= help: items from traits can only be used if the trait is in scope
= note: the following trait is implemented but not in scope, perhaps add a `use` for it:
candidate #1: `use std::clone::Clone;`
error: aborting due to 3 previous errors
Some errors occurred: E0433, E0599, E0601.
For more information about an error, try `rustc --explain E0433`.

View file

@ -0,0 +1,9 @@
error[E0425]: cannot find value `x` in this scope
--> $DIR/pattern-macro.rs:15:5
|
LL | x + 1; //~ ERROR cannot find value `x` in this scope
| ^ not found in this scope
error: aborting due to previous error
For more information about this error, try `rustc --explain E0425`.

View file

@ -0,0 +1,9 @@
error[E0603]: function `f` is private
--> $DIR/privacy.rs:26:9
|
LL | foo::f() //~ ERROR `f` is private
| ^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0603`.

View file

@ -0,0 +1,16 @@
error[E0599]: no method named `f` found for type `()` in the current scope
--> $DIR/trait_items.rs:27:24
|
LL | fn f() { ::baz::m!(); }
| ------------ in this macro invocation
...
LL | pub macro m() { ().f() } //~ ERROR no method named `f` found for type `()` in the current scope
| ^
|
= help: items from traits can only be used if the trait is in scope
= note: the following trait is implemented but not in scope, perhaps add a `use` for it:
candidate #1: `use foo::T;`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0599`.

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`.