From 01ab8542fbcfbea2cb0dcdc538e56a7167f70f51 Mon Sep 17 00:00:00 2001 From: Joshua Yanovski Date: Mon, 28 Oct 2013 19:22:42 -0700 Subject: [PATCH 1/2] Field identifiers now include specific spans (Closes #8263). --- src/librustc/middle/moves.rs | 2 +- src/librustc/middle/privacy.rs | 4 ++-- src/librustc/middle/trans/consts.rs | 2 +- src/librustc/middle/trans/expr.rs | 2 +- src/librustc/middle/typeck/check/mod.rs | 12 ++++++------ src/libsyntax/ast.rs | 4 +++- src/libsyntax/ext/build.rs | 2 +- src/libsyntax/fold.rs | 7 ++++--- src/libsyntax/parse/parser.rs | 3 ++- src/libsyntax/print/pprust.rs | 2 +- 10 files changed, 22 insertions(+), 18 deletions(-) diff --git a/src/librustc/middle/moves.rs b/src/librustc/middle/moves.rs index d4dce789192..6317e3a1abc 100644 --- a/src/librustc/middle/moves.rs +++ b/src/librustc/middle/moves.rs @@ -420,7 +420,7 @@ impl VisitContext { // specified and (2) have a type that // moves-by-default: let consume_with = with_fields.iter().any(|tf| { - !fields.iter().any(|f| f.ident.name == tf.ident.name) && + !fields.iter().any(|f| f.ident.node.name == tf.ident.name) && ty::type_moves_by_default(self.tcx, tf.mt.ty) }); diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index 17aab598289..70aa05848f3 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -716,7 +716,7 @@ impl<'self> Visitor<()> for PrivacyVisitor<'self> { match ty::get(ty::expr_ty(self.tcx, expr)).sty { ty::ty_struct(id, _) => { for field in (*fields).iter() { - self.check_field(expr.span, id, field.ident); + self.check_field(expr.span, id, field.ident.node); } } ty::ty_enum(_, _) => { @@ -724,7 +724,7 @@ impl<'self> Visitor<()> for PrivacyVisitor<'self> { ast::DefVariant(_, variant_id, _) => { for field in fields.iter() { self.check_field(expr.span, variant_id, - field.ident); + field.ident.node); } } _ => self.tcx.sess.span_bug(expr.span, diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs index 2667752e93e..9f497afb121 100644 --- a/src/librustc/middle/trans/consts.rs +++ b/src/librustc/middle/trans/consts.rs @@ -508,7 +508,7 @@ fn const_expr_unadjusted(cx: @mut CrateContext, |discr, field_tys| { let cs = field_tys.iter().enumerate() .map(|(ix, &field_ty)| { - match fs.iter().find(|f| field_ty.ident.name == f.ident.name) { + match fs.iter().find(|f| field_ty.ident.name == f.ident.node.name) { Some(f) => const_expr(cx, (*f).expr), None => { match base_val { diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index d4c57d7ce18..1c856f04b06 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -1211,7 +1211,7 @@ fn trans_rec_or_struct(bcx: @mut Block, let numbered_fields = do fields.map |field| { let opt_pos = field_tys.iter().position(|field_ty| - field_ty.ident.name == field.ident.name); + field_ty.ident.name == field.ident.node.name); match opt_pos { Some(i) => { need_base[i] = false; diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 50ab7825de6..218a76a8e93 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -2030,20 +2030,20 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, for field in ast_fields.iter() { let mut expected_field_type = ty::mk_err(); - let pair = class_field_map.find(&field.ident.name).map(|x| *x); + let pair = class_field_map.find(&field.ident.node.name).map(|x| *x); match pair { None => { tcx.sess.span_err( - field.span, + field.ident.span, format!("structure has no field named `{}`", - tcx.sess.str_of(field.ident))); + tcx.sess.str_of(field.ident.node))); error_happened = true; } Some((_, true)) => { tcx.sess.span_err( - field.span, + field.ident.span, format!("field `{}` specified more than once", - tcx.sess.str_of(field.ident))); + tcx.sess.str_of(field.ident.node))); error_happened = true; } Some((field_id, false)) => { @@ -2051,7 +2051,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, ty::lookup_field_type( tcx, class_id, field_id, &substitutions); class_field_map.insert( - field.ident.name, (field_id, true)); + field.ident.node.name, (field_id, true)); fields_found += 1; } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 6647c4c811e..3467e1aaadc 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -471,11 +471,13 @@ pub struct Arm { #[deriving(Clone, Eq, Encodable, Decodable, IterBytes)] pub struct Field { - ident: Ident, + ident: SpannedIdent, expr: @Expr, span: Span, } +pub type SpannedIdent = Spanned; + #[deriving(Clone, Eq, Encodable, Decodable, IterBytes)] pub enum BlockCheckMode { DefaultBlock, diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 4c3ab840b44..273ce180a5f 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -529,7 +529,7 @@ impl AstBuilder for @ExtCtxt { self.expr(b.span, ast::ExprBlock(b)) } fn field_imm(&self, span: Span, name: Ident, e: @ast::Expr) -> ast::Field { - ast::Field { ident: name, expr: e, span: span } + ast::Field { ident: respan(span, name), expr: e, span: span } } fn expr_struct(&self, span: Span, path: ast::Path, fields: ~[ast::Field]) -> @ast::Expr { self.expr(span, ast::ExprStruct(path, fields, None)) diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index e9ecb95c545..fddf674a846 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -10,7 +10,7 @@ use ast::*; use ast; -use codemap::{Span, Spanned}; +use codemap::{respan, Span, Spanned}; use parse::token; use opt_vec::OptVec; @@ -551,7 +551,7 @@ fn fold_struct_field(f: @struct_field, fld: &T) -> @struct_field { fn fold_field_(field: Field, folder: &T) -> Field { ast::Field { - ident: folder.fold_ident(field.ident), + ident: respan(field.ident.span, folder.fold_ident(field.ident.node)), expr: folder.fold_expr(field.expr), span: folder.new_span(field.span), } @@ -797,7 +797,8 @@ pub fn noop_fold_expr(e: @ast::Expr, folder: &T) -> @ast::Expr { folder.fold_expr(er)) } ExprField(el, id, ref tys) => { - ExprField(folder.fold_expr(el), folder.fold_ident(id), + ExprField(folder.fold_expr(el), + folder.fold_ident(id), tys.map(|x| folder.fold_ty(x))) } ExprIndex(callee_id, el, er) => { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 5a5e310e56f..8b399266676 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1549,10 +1549,11 @@ impl Parser { pub fn parse_field(&self) -> Field { let lo = self.span.lo; let i = self.parse_ident(); + let hi = self.last_span.hi; self.expect(&token::COLON); let e = self.parse_expr(); ast::Field { - ident: i, + ident: spanned(lo, hi, i), expr: e, span: mk_sp(lo, e.span.hi), } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 12193411910..f3090c7dd16 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1111,7 +1111,7 @@ pub fn print_call_post(s: @ps, pub fn print_expr(s: @ps, expr: &ast::Expr) { fn print_field(s: @ps, field: &ast::Field) { ibox(s, indent_unit); - print_ident(s, field.ident); + print_ident(s, field.ident.node); word_space(s, ":"); print_expr(s, field.expr); end(s); From a71665798bdd629ff8d328ef325723b79a2542a7 Mon Sep 17 00:00:00 2001 From: Joshua Yanovski Date: Mon, 28 Oct 2013 23:30:26 -0700 Subject: [PATCH 2/2] #8263 part 2: Adding struct name. --- src/librustc/middle/typeck/check/mod.rs | 13 +++++++++---- src/test/compile-fail/issue-4736.rs | 2 +- src/test/compile-fail/struct-fields-too-many.rs | 2 +- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 218a76a8e93..d71aa776689 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -2009,6 +2009,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } fn check_struct_or_variant_fields(fcx: @mut FnCtxt, + struct_ty: ty::t, span: Span, class_id: ast::DefId, node_id: ast::NodeId, @@ -2033,10 +2034,12 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, let pair = class_field_map.find(&field.ident.node.name).map(|x| *x); match pair { None => { - tcx.sess.span_err( - field.ident.span, - format!("structure has no field named `{}`", - tcx.sess.str_of(field.ident.node))); + fcx.type_error_message( + field.ident.span, + |actual| { + format!("structure `{}` has no field named `{}`", + actual, tcx.sess.str_of(field.ident.node)) + }, struct_ty, None); error_happened = true; } Some((_, true)) => { @@ -2161,6 +2164,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, // Look up and check the fields. let class_fields = ty::lookup_struct_fields(tcx, class_id); check_struct_or_variant_fields(fcx, + struct_type, span, class_id, id, @@ -2248,6 +2252,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, // Look up and check the enum variant fields. let variant_fields = ty::lookup_struct_fields(tcx, variant_id); check_struct_or_variant_fields(fcx, + enum_type, span, variant_id, id, diff --git a/src/test/compile-fail/issue-4736.rs b/src/test/compile-fail/issue-4736.rs index 6f410ea3c37..b63db7c5a30 100644 --- a/src/test/compile-fail/issue-4736.rs +++ b/src/test/compile-fail/issue-4736.rs @@ -11,5 +11,5 @@ struct NonCopyable(()); fn main() { - let z = NonCopyable{ p: () }; //~ ERROR structure has no field named `p` + let z = NonCopyable{ p: () }; //~ ERROR structure `NonCopyable` has no field named `p` } diff --git a/src/test/compile-fail/struct-fields-too-many.rs b/src/test/compile-fail/struct-fields-too-many.rs index 67897f6ef93..de58b5d110e 100644 --- a/src/test/compile-fail/struct-fields-too-many.rs +++ b/src/test/compile-fail/struct-fields-too-many.rs @@ -15,6 +15,6 @@ struct BuildData { fn main() { let foo = BuildData { foo: 0, - bar: 0 //~ ERROR structure has no field named `bar` + bar: 0 //~ ERROR structure `BuildData` has no field named `bar` }; }