From 91aadf030548214da5a8f39a1b1dbd21db125625 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 13 Nov 2019 19:32:12 +0100 Subject: find_deprecation: deprecation attr may be ill-formed meta. --- src/libsyntax/attr/builtin.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/libsyntax') diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs index 2b759c205f5..75e0c141159 100644 --- a/src/libsyntax/attr/builtin.rs +++ b/src/libsyntax/attr/builtin.rs @@ -665,7 +665,10 @@ fn find_deprecation_generic<'a, I>(sess: &ParseSess, break } - let meta = attr.meta().unwrap(); + let meta = match attr.meta() { + Some(meta) => meta, + None => continue, + }; depr = match &meta.kind { MetaItemKind::Word => Some(Deprecation { since: None, note: None }), MetaItemKind::NameValue(..) => { -- cgit 1.4.1-3-g733a5 From 266f5471272532989332117e8a2e0bacb5b94ccf Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 9 Nov 2019 22:05:20 +0300 Subject: ast: Keep `extern` qualifiers in functions more precisely --- src/librustc/hir/lowering.rs | 2 +- src/librustc/hir/lowering/item.rs | 12 +++++++-- src/librustc_parse/parser/item.rs | 35 +++++++++++++++---------- src/librustc_parse/parser/mod.rs | 24 +++++++---------- src/librustc_parse/parser/ty.rs | 4 +-- src/librustc_save_analysis/sig.rs | 17 ++++++------ src/libsyntax/ast.rs | 27 +++++++++++-------- src/libsyntax/feature_gate/check.rs | 16 ++++++++--- src/libsyntax/mut_visit.rs | 4 +-- src/libsyntax/print/pprust.rs | 22 +++++++++++----- src/libsyntax_ext/deriving/generic/mod.rs | 7 ++--- src/test/ui/proc-macro/span-preservation.rs | 10 +++---- src/test/ui/proc-macro/span-preservation.stderr | 26 +++++++++++------- 13 files changed, 118 insertions(+), 88 deletions(-) (limited to 'src/libsyntax') diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index ef6a6ae23dc..12f6f66e96b 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1219,7 +1219,7 @@ impl<'a> LoweringContext<'a> { ImplTraitContext::disallowed(), ), unsafety: f.unsafety, - abi: this.lower_abi(f.abi), + abi: this.lower_extern(f.ext), decl: this.lower_fn_decl(&f.decl, None, false, None), param_names: this.lower_fn_params_to_names(&f.decl), })) diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs index 4cd42927868..2dc7e014445 100644 --- a/src/librustc/hir/lowering/item.rs +++ b/src/librustc/hir/lowering/item.rs @@ -735,7 +735,7 @@ impl LoweringContext<'_> { fn lower_foreign_mod(&mut self, fm: &ForeignMod) -> hir::ForeignMod { hir::ForeignMod { - abi: self.lower_abi(fm.abi), + abi: fm.abi.map_or(abi::Abi::C, |abi| self.lower_abi(abi)), items: fm.items .iter() .map(|x| self.lower_foreign_item(x)) @@ -1283,7 +1283,7 @@ impl LoweringContext<'_> { unsafety: h.unsafety, asyncness: self.lower_asyncness(h.asyncness.node), constness: h.constness.node, - abi: self.lower_abi(h.abi), + abi: self.lower_extern(h.ext), } } @@ -1294,6 +1294,14 @@ impl LoweringContext<'_> { }) } + pub(super) fn lower_extern(&mut self, ext: Extern) -> abi::Abi { + match ext { + Extern::None => abi::Abi::Rust, + Extern::Implicit => abi::Abi::C, + Extern::Explicit(abi) => self.lower_abi(abi), + } + } + fn error_on_invalid_abi(&self, abi: Abi) { struct_span_err!( self.sess, diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 73099169879..fe86d03c6e7 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -114,7 +114,7 @@ impl<'a> Parser<'a> { unsafety: Unsafety::Normal, asyncness: respan(fn_span, IsAsync::NotAsync), constness: respan(fn_span, Constness::NotConst), - abi, + ext: Extern::from_abi(abi), }; return self.parse_item_fn(lo, vis, attrs, header); } else if self.check(&token::OpenDelim(token::Brace)) { @@ -143,14 +143,14 @@ impl<'a> Parser<'a> { if self.check_keyword(kw::Extern) { self.sess.gated_spans.gate(sym::const_extern_fn, lo.to(self.token.span)); } - let abi = self.parse_extern_abi()?; + let ext = self.parse_extern()?; self.bump(); // `fn` let header = FnHeader { unsafety, asyncness: respan(const_span, IsAsync::NotAsync), constness: respan(const_span, Constness::Const), - abi, + ext, }; return self.parse_item_fn(lo, vis, attrs, header); } @@ -193,7 +193,7 @@ impl<'a> Parser<'a> { unsafety, asyncness, constness: respan(fn_span, Constness::NotConst), - abi: Abi::new(sym::Rust, fn_span), + ext: Extern::None, }; return self.parse_item_fn(lo, vis, attrs, header); } @@ -230,7 +230,7 @@ impl<'a> Parser<'a> { unsafety: Unsafety::Normal, asyncness: respan(fn_span, IsAsync::NotAsync), constness: respan(fn_span, Constness::NotConst), - abi: Abi::new(sym::Rust, fn_span), + ext: Extern::None, }; return self.parse_item_fn(lo, vis, attrs, header); } @@ -242,14 +242,14 @@ impl<'a> Parser<'a> { self.bump(); // `unsafe` // `{` is also expected after `unsafe`; in case of error, include it in the diagnostic. self.check(&token::OpenDelim(token::Brace)); - let abi = self.parse_extern_abi()?; + let ext = self.parse_extern()?; self.expect_keyword(kw::Fn)?; let fn_span = self.prev_span; let header = FnHeader { unsafety: Unsafety::Unsafe, asyncness: respan(fn_span, IsAsync::NotAsync), constness: respan(fn_span, Constness::NotConst), - abi, + ext, }; return self.parse_item_fn(lo, vis, attrs, header); } @@ -1100,7 +1100,7 @@ impl<'a> Parser<'a> { fn parse_item_foreign_mod( &mut self, lo: Span, - abi: Abi, + abi: Option, visibility: Visibility, mut attrs: Vec, extern_sp: Span, @@ -1775,9 +1775,16 @@ impl<'a> Parser<'a> { attrs: Vec, header: FnHeader, ) -> PResult<'a, Option>> { + let is_c_abi = match header.ext { + ast::Extern::None => false, + ast::Extern::Implicit => true, + ast::Extern::Explicit(abi) => abi.symbol == sym::C, + }; let (ident, decl, generics) = self.parse_fn_sig(ParamCfg { is_self_allowed: false, - allow_c_variadic: header.abi.symbol == sym::C && header.unsafety == Unsafety::Unsafe, + // FIXME: Parsing should not depend on ABI or unsafety and + // the variadic parameter should always be parsed. + allow_c_variadic: is_c_abi && header.unsafety == Unsafety::Unsafe, is_name_required: |_| true, })?; let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; @@ -1905,11 +1912,11 @@ impl<'a> Parser<'a> { } let asyncness = respan(self.prev_span, asyncness); let unsafety = self.parse_unsafety(); - let (constness, unsafety, abi) = if is_const_fn { - (respan(const_span, Constness::Const), unsafety, Abi::default()) + let (constness, unsafety, ext) = if is_const_fn { + (respan(const_span, Constness::Const), unsafety, Extern::None) } else { - let abi = self.parse_extern_abi()?; - (respan(self.prev_span, Constness::NotConst), unsafety, abi) + let ext = self.parse_extern()?; + (respan(self.prev_span, Constness::NotConst), unsafety, ext) }; if !self.eat_keyword(kw::Fn) { // It is possible for `expect_one_of` to recover given the contents of @@ -1917,7 +1924,7 @@ impl<'a> Parser<'a> { // account for this. if !self.expect_one_of(&[], &[])? { unreachable!() } } - Ok(FnHeader { constness, unsafety, asyncness, abi }) + Ok(FnHeader { constness, unsafety, asyncness, ext }) } /// Parse the "signature", including the identifier, parameters, and generics of a function. diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index f62f0c9a268..2d05a696791 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -15,7 +15,7 @@ use crate::{Directory, DirectoryOwnership}; use crate::lexer::UnmatchedBrace; use syntax::ast::{ - self, Abi, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Ident, + self, Abi, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Extern, Ident, IsAsync, MacDelimiter, Mutability, StrStyle, Visibility, VisibilityKind, Unsafety, }; @@ -1212,23 +1212,20 @@ impl<'a> Parser<'a> { } /// Parses `extern string_literal?`. - /// If `extern` is not found, the Rust ABI is used. - /// If `extern` is found and a `string_literal` does not follow, the C ABI is used. - fn parse_extern_abi(&mut self) -> PResult<'a, Abi> { + fn parse_extern(&mut self) -> PResult<'a, Extern> { Ok(if self.eat_keyword(kw::Extern) { - self.parse_opt_abi()? + Extern::from_abi(self.parse_opt_abi()?) } else { - Abi::default() + Extern::None }) } /// Parses a string literal as an ABI spec. - /// If one is not found, the "C" ABI is used. - fn parse_opt_abi(&mut self) -> PResult<'a, Abi> { - let span = if self.token.can_begin_literal_or_bool() { + fn parse_opt_abi(&mut self) -> PResult<'a, Option> { + if self.token.can_begin_literal_or_bool() { let ast::Lit { span, kind, .. } = self.parse_lit()?; match kind { - ast::LitKind::Str(symbol, _) => return Ok(Abi::new(symbol, span)), + ast::LitKind::Str(symbol, _) => return Ok(Some(Abi { symbol, span })), ast::LitKind::Err(_) => {} _ => { self.struct_span_err(span, "non-string ABI literal") @@ -1241,11 +1238,8 @@ impl<'a> Parser<'a> { .emit(); } } - span - } else { - self.prev_span - }; - Ok(Abi::new(sym::C, span)) + } + Ok(None) } /// We are parsing `async fn`. If we are on Rust 2015, emit an error. diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs index 4c7d1006183..8e6bc29be52 100644 --- a/src/librustc_parse/parser/ty.rs +++ b/src/librustc_parse/parser/ty.rs @@ -287,7 +287,7 @@ impl<'a> Parser<'a> { */ let unsafety = self.parse_unsafety(); - let abi = self.parse_extern_abi()?; + let ext = self.parse_extern()?; self.expect_keyword(kw::Fn)?; let cfg = ParamCfg { is_self_allowed: false, @@ -296,7 +296,7 @@ impl<'a> Parser<'a> { }; let decl = self.parse_fn_decl(cfg, false)?; Ok(TyKind::BareFn(P(BareFnTy { - abi, + ext, unsafety, generic_params, decl, diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index 50dfac62024..255938a193c 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -30,9 +30,8 @@ use crate::{id_from_def_id, id_from_node_id, SaveContext}; use rls_data::{SigElement, Signature}; use rustc::hir::def::{Res, DefKind}; -use syntax::ast::{self, NodeId}; +use syntax::ast::{self, Extern, NodeId}; use syntax::print::pprust; -use syntax_pos::sym; pub fn item_signature(item: &ast::Item, scx: &SaveContext<'_, '_>) -> Option { if !scx.config.signatures { @@ -157,9 +156,11 @@ fn text_sig(text: String) -> Signature { } } -fn push_abi(text: &mut String, abi: ast::Abi) { - if abi.symbol != sym::Rust { - text.push_str(&format!("extern \"{}\" ", abi.symbol)); +fn push_extern(text: &mut String, ext: Extern) { + match ext { + Extern::None => {} + Extern::Implicit => text.push_str("extern "), + Extern::Explicit(abi) => text.push_str(&format!("extern \"{}\" ", abi.symbol)), } } @@ -237,7 +238,7 @@ impl Sig for ast::Ty { if f.unsafety == ast::Unsafety::Unsafe { text.push_str("unsafe "); } - push_abi(&mut text, f.abi); + push_extern(&mut text, f.ext); text.push_str("fn("); let mut defs = vec![]; @@ -387,7 +388,7 @@ impl Sig for ast::Item { if header.unsafety == ast::Unsafety::Unsafe { text.push_str("unsafe "); } - push_abi(&mut text, header.abi); + push_extern(&mut text, header.ext); text.push_str("fn "); let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?; @@ -936,7 +937,7 @@ fn make_method_signature( if m.header.unsafety == ast::Unsafety::Unsafe { text.push_str("unsafe "); } - push_abi(&mut text, m.header.abi); + push_extern(&mut text, m.header.ext); text.push_str("fn "); let mut sig = name_and_generics(text, 0, generics, id, ident, scx)?; diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index d358efbe543..575795758ae 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1745,7 +1745,7 @@ pub struct Ty { #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct BareFnTy { pub unsafety: Unsafety, - pub abi: Abi, + pub ext: Extern, pub generic_params: Vec, pub decl: P, } @@ -2128,7 +2128,7 @@ pub struct Mod { /// E.g., `extern { .. }` or `extern C { .. }`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct ForeignMod { - pub abi: Abi, + pub abi: Option, pub items: Vec, } @@ -2420,15 +2420,20 @@ pub struct Abi { pub span: Span, } -impl Abi { - pub fn new(symbol: Symbol, span: Span) -> Self { - Self { symbol, span } - } +/// `extern` qualifier on a function item or function type. +#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)] +pub enum Extern { + None, + Implicit, + Explicit(Abi), } -impl Default for Abi { - fn default() -> Self { - Self::new(sym::Rust, DUMMY_SP) +impl Extern { + pub fn from_abi(abi: Option) -> Extern { + match abi { + Some(abi) => Extern::Explicit(abi), + None => Extern::Implicit, + } } } @@ -2441,7 +2446,7 @@ pub struct FnHeader { pub unsafety: Unsafety, pub asyncness: Spanned, pub constness: Spanned, - pub abi: Abi, + pub ext: Extern, } impl Default for FnHeader { @@ -2450,7 +2455,7 @@ impl Default for FnHeader { unsafety: Unsafety::Normal, asyncness: dummy_spanned(IsAsync::NotAsync), constness: dummy_spanned(Constness::NotConst), - abi: Abi::default(), + ext: Extern::None, } } } diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs index bd836eee42a..d90fa9addf7 100644 --- a/src/libsyntax/feature_gate/check.rs +++ b/src/libsyntax/feature_gate/check.rs @@ -258,6 +258,12 @@ impl<'a> PostExpansionVisitor<'a> { } } + fn check_extern(&self, ext: ast::Extern) { + if let ast::Extern::Explicit(abi) = ext { + self.check_abi(abi); + } + } + fn maybe_report_invalid_custom_discriminants(&self, variants: &[ast::Variant]) { let has_fields = variants.iter().any(|variant| match variant.data { VariantData::Tuple(..) | VariantData::Struct(..) => true, @@ -388,7 +394,9 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { fn visit_item(&mut self, i: &'a ast::Item) { match i.kind { ast::ItemKind::ForeignMod(ref foreign_module) => { - self.check_abi(foreign_module.abi); + if let Some(abi) = foreign_module.abi { + self.check_abi(abi); + } } ast::ItemKind::Fn(..) => { @@ -511,7 +519,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { fn visit_ty(&mut self, ty: &'a ast::Ty) { match ty.kind { ast::TyKind::BareFn(ref bare_fn_ty) => { - self.check_abi(bare_fn_ty.abi); + self.check_extern(bare_fn_ty.ext); } ast::TyKind::Never => { gate_feature_post!(&self, never_type, ty.span, @@ -605,7 +613,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { // Stability of const fn methods are covered in // `visit_trait_item` and `visit_impl_item` below; this is // because default methods don't pass through this point. - self.check_abi(header.abi); + self.check_extern(header.ext); } if fn_decl.c_variadic() { @@ -639,7 +647,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { match ti.kind { ast::TraitItemKind::Method(ref sig, ref block) => { if block.is_none() { - self.check_abi(sig.header.abi); + self.check_extern(sig.header.ext); } if sig.decl.c_variadic() { gate_feature_post!(&self, c_variadic, ti.span, diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index f4ef993edb9..da3c885b860 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -441,7 +441,7 @@ pub fn noop_visit_ty(ty: &mut P, vis: &mut T) { vis.visit_mt(mt); } TyKind::BareFn(bft) => { - let BareFnTy { unsafety: _, abi: _, generic_params, decl } = bft.deref_mut(); + let BareFnTy { unsafety: _, ext: _, generic_params, decl } = bft.deref_mut(); generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param)); vis.visit_fn_decl(decl); } @@ -974,7 +974,7 @@ pub fn noop_flat_map_impl_item(mut item: ImplItem, visitor: &mut } pub fn noop_visit_fn_header(header: &mut FnHeader, vis: &mut T) { - let FnHeader { unsafety: _, asyncness, constness: _, abi: _ } = header; + let FnHeader { unsafety: _, asyncness, constness: _, ext: _ } = header; vis.visit_asyncness(&mut asyncness.node); } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index ef65a744e83..de28bd6cf83 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1013,7 +1013,7 @@ impl<'a> State<'a> { self.pclose(); } ast::TyKind::BareFn(ref f) => { - self.print_ty_fn(f.abi, + self.print_ty_fn(f.ext, f.unsafety, &f.decl, None, @@ -1232,7 +1232,9 @@ impl<'a> State<'a> { } ast::ItemKind::ForeignMod(ref nmod) => { self.head("extern"); - self.print_abi(nmod.abi); + if let Some(abi) = nmod.abi { + self.print_abi(abi); + } self.bopen(); self.print_foreign_mod(nmod, &item.attrs); self.bclose(item.span); @@ -2805,7 +2807,7 @@ impl<'a> State<'a> { } crate fn print_ty_fn(&mut self, - abi: ast::Abi, + ext: ast::Extern, unsafety: ast::Unsafety, decl: &ast::FnDecl, name: Option, @@ -2825,7 +2827,7 @@ impl<'a> State<'a> { span: syntax_pos::DUMMY_SP, }; self.print_fn(decl, - ast::FnHeader { unsafety, abi, ..ast::FnHeader::default() }, + ast::FnHeader { unsafety, ext, ..ast::FnHeader::default() }, name, &generics, &source_map::dummy_spanned(ast::VisibilityKind::Inherited)); @@ -2866,9 +2868,15 @@ impl<'a> State<'a> { self.print_asyncness(header.asyncness.node); self.print_unsafety(header.unsafety); - if header.abi.symbol != sym::Rust { - self.word_nbsp("extern"); - self.print_abi(header.abi); + match header.ext { + ast::Extern::None => {} + ast::Extern::Implicit => { + self.word_nbsp("extern"); + } + ast::Extern::Explicit(abi) => { + self.word_nbsp("extern"); + self.print_abi(abi); + } } self.s.word("fn") diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index b24306def74..b6bf2f88161 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -182,7 +182,7 @@ use std::iter; use std::vec; use rustc_data_structures::thin_vec::ThinVec; -use syntax::ast::{self, Abi, BinOpKind, EnumDef, Expr, Generics, Ident, PatKind}; +use syntax::ast::{self, BinOpKind, EnumDef, Expr, Generics, Ident, PatKind}; use syntax::ast::{VariantData, GenericParamKind, GenericArg}; use syntax::attr; use syntax::source_map::respan; @@ -737,7 +737,6 @@ impl<'a> TraitDef<'a> { self, type_ident, generics, - sym::Rust, explicit_self, tys, body) @@ -792,7 +791,6 @@ impl<'a> TraitDef<'a> { self, type_ident, generics, - sym::Rust, explicit_self, tys, body) @@ -918,7 +916,6 @@ impl<'a> MethodDef<'a> { trait_: &TraitDef<'_>, type_ident: Ident, generics: &Generics, - abi: Symbol, explicit_self: Option, arg_types: Vec<(Ident, P)>, body: P) @@ -953,7 +950,7 @@ impl<'a> MethodDef<'a> { let sig = ast::FnSig { header: ast::FnHeader { unsafety, - abi: Abi::new(abi, trait_lo_sp), + ext: ast::Extern::None, ..ast::FnHeader::default() }, decl: fn_decl, diff --git a/src/test/ui/proc-macro/span-preservation.rs b/src/test/ui/proc-macro/span-preservation.rs index 55835cb88f4..8b8e12fcba6 100644 --- a/src/test/ui/proc-macro/span-preservation.rs +++ b/src/test/ui/proc-macro/span-preservation.rs @@ -1,9 +1,8 @@ -//~ ERROR mismatched types -// aux-build:test-macros.rs - // For each of these, we should get the appropriate type mismatch error message, // and the function should be echoed. +// aux-build:test-macros.rs + #[macro_use] extern crate test_macros; @@ -35,12 +34,9 @@ fn c() { let y = Foo { a: 10, b: 10isize }; //~ ERROR has no field named `b` } -// FIXME: This doesn't work at the moment. See the one below. The pretty-printer -// injects a "C" between `extern` and `fn` which causes a "probably_eq" -// `TokenStream` mismatch. The lack of `"C"` should be preserved in the AST. #[recollect_attr] extern fn bar() { - 0 + 0 //~ ERROR mismatched types } #[recollect_attr] diff --git a/src/test/ui/proc-macro/span-preservation.stderr b/src/test/ui/proc-macro/span-preservation.stderr index 0290f4b2cc9..9e9271f529c 100644 --- a/src/test/ui/proc-macro/span-preservation.stderr +++ b/src/test/ui/proc-macro/span-preservation.stderr @@ -1,10 +1,5 @@ error[E0308]: mismatched types - | - = note: expected type `()` - found type `{integer}` - -error[E0308]: mismatched types - --> $DIR/span-preservation.rs:12:20 + --> $DIR/span-preservation.rs:11:20 | LL | let x: usize = "hello"; | ^^^^^^^ expected usize, found reference @@ -13,7 +8,7 @@ LL | let x: usize = "hello"; found type `&'static str` error[E0308]: mismatched types - --> $DIR/span-preservation.rs:18:29 + --> $DIR/span-preservation.rs:17:29 | LL | fn b(x: Option) -> usize { | ----- expected `usize` because of return type @@ -22,13 +17,13 @@ LL | Some(x) => { return x }, | ^ expected usize, found isize error[E0308]: mismatched types - --> $DIR/span-preservation.rs:34:22 + --> $DIR/span-preservation.rs:33:22 | LL | let x = Foo { a: 10isize }; | ^^^^^^^ expected usize, found isize error[E0560]: struct `c::Foo` has no field named `b` - --> $DIR/span-preservation.rs:35:26 + --> $DIR/span-preservation.rs:34:26 | LL | let y = Foo { a: 10, b: 10isize }; | ^ `c::Foo` does not have this field @@ -36,7 +31,18 @@ LL | let y = Foo { a: 10, b: 10isize }; = note: available fields are: `a` error[E0308]: mismatched types - --> $DIR/span-preservation.rs:48:5 + --> $DIR/span-preservation.rs:39:5 + | +LL | extern fn bar() { + | - possibly return type missing here? +LL | 0 + | ^ expected (), found integer + | + = note: expected type `()` + found type `{integer}` + +error[E0308]: mismatched types + --> $DIR/span-preservation.rs:44:5 | LL | extern "C" fn baz() { | - possibly return type missing here? -- cgit 1.4.1-3-g733a5 From 00bc4496026a3168eed95e88c29f17dac2739d48 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 10 Nov 2019 00:44:59 +0300 Subject: ast: Keep string literals in ABIs precisely --- src/librustc/hir/lowering/item.rs | 6 +++--- src/librustc_parse/parser/item.rs | 4 ++-- src/librustc_parse/parser/mod.rs | 11 ++++++---- src/libsyntax/ast.rs | 42 ++++++++++++++++++++++++++----------- src/libsyntax/feature_gate/check.rs | 6 +++--- src/libsyntax/print/pprust.rs | 10 ++++----- 6 files changed, 49 insertions(+), 30 deletions(-) (limited to 'src/libsyntax') diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs index 2dc7e014445..f689e7f9622 100644 --- a/src/librustc/hir/lowering/item.rs +++ b/src/librustc/hir/lowering/item.rs @@ -1287,8 +1287,8 @@ impl LoweringContext<'_> { } } - pub(super) fn lower_abi(&mut self, abi: Abi) -> abi::Abi { - abi::lookup(&abi.symbol.as_str()).unwrap_or_else(|| { + pub(super) fn lower_abi(&mut self, abi: StrLit) -> abi::Abi { + abi::lookup(&abi.symbol_unescaped.as_str()).unwrap_or_else(|| { self.error_on_invalid_abi(abi); abi::Abi::Rust }) @@ -1302,7 +1302,7 @@ impl LoweringContext<'_> { } } - fn error_on_invalid_abi(&self, abi: Abi) { + fn error_on_invalid_abi(&self, abi: StrLit) { struct_span_err!( self.sess, abi.span, diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index fe86d03c6e7..3b824dc939f 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -1100,7 +1100,7 @@ impl<'a> Parser<'a> { fn parse_item_foreign_mod( &mut self, lo: Span, - abi: Option, + abi: Option, visibility: Visibility, mut attrs: Vec, extern_sp: Span, @@ -1778,7 +1778,7 @@ impl<'a> Parser<'a> { let is_c_abi = match header.ext { ast::Extern::None => false, ast::Extern::Implicit => true, - ast::Extern::Explicit(abi) => abi.symbol == sym::C, + ast::Extern::Explicit(abi) => abi.symbol_unescaped == sym::C, }; let (ident, decl, generics) = self.parse_fn_sig(ParamCfg { is_self_allowed: false, diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index 2d05a696791..2b49091192c 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -15,7 +15,7 @@ use crate::{Directory, DirectoryOwnership}; use crate::lexer::UnmatchedBrace; use syntax::ast::{ - self, Abi, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Extern, Ident, + self, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Extern, Ident, IsAsync, MacDelimiter, Mutability, StrStyle, Visibility, VisibilityKind, Unsafety, }; @@ -1221,11 +1221,14 @@ impl<'a> Parser<'a> { } /// Parses a string literal as an ABI spec. - fn parse_opt_abi(&mut self) -> PResult<'a, Option> { + fn parse_opt_abi(&mut self) -> PResult<'a, Option> { if self.token.can_begin_literal_or_bool() { - let ast::Lit { span, kind, .. } = self.parse_lit()?; + let ast::Lit { token: token::Lit { symbol, suffix, .. }, span, kind } + = self.parse_lit()?; match kind { - ast::LitKind::Str(symbol, _) => return Ok(Some(Abi { symbol, span })), + ast::LitKind::Str(symbol_unescaped, style) => return Ok(Some(StrLit { + style, symbol, suffix, span, symbol_unescaped, + })), ast::LitKind::Err(_) => {} _ => { self.struct_span_err(span, "non-string ABI literal") diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 575795758ae..dee493a708e 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1422,6 +1422,33 @@ pub struct Lit { pub span: Span, } +/// Same as `Lit`, but restricted to string literals. +#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)] +pub struct StrLit { + /// The original literal token as written in source code. + pub style: StrStyle, + pub symbol: Symbol, + pub suffix: Option, + pub span: Span, + /// The unescaped "semantic" representation of the literal lowered from the original token. + /// FIXME: Remove this and only create the semantic representation during lowering to HIR. + pub symbol_unescaped: Symbol, +} + +impl StrLit { + crate fn as_lit(&self) -> Lit { + let token_kind = match self.style { + StrStyle::Cooked => token::Str, + StrStyle::Raw(n) => token::StrRaw(n), + }; + Lit { + token: token::Lit::new(token_kind, self.symbol, self.suffix), + span: self.span, + kind: LitKind::Str(self.symbol_unescaped, self.style), + } + } +} + // Clippy uses Hash and PartialEq /// Type of the integer literal based on provided suffix. #[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, Hash, PartialEq)] @@ -2128,7 +2155,7 @@ pub struct Mod { /// E.g., `extern { .. }` or `extern C { .. }`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct ForeignMod { - pub abi: Option, + pub abi: Option, pub items: Vec, } @@ -2411,25 +2438,16 @@ impl Item { } } -/// A reference to an ABI. -/// -/// In AST our notion of an ABI is still syntactic unlike in `rustc_target::spec::abi::Abi`. -#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, PartialEq)] -pub struct Abi { - pub symbol: Symbol, - pub span: Span, -} - /// `extern` qualifier on a function item or function type. #[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)] pub enum Extern { None, Implicit, - Explicit(Abi), + Explicit(StrLit), } impl Extern { - pub fn from_abi(abi: Option) -> Extern { + pub fn from_abi(abi: Option) -> Extern { match abi { Some(abi) => Extern::Explicit(abi), None => Extern::Implicit, diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs index d90fa9addf7..abf9adefd3c 100644 --- a/src/libsyntax/feature_gate/check.rs +++ b/src/libsyntax/feature_gate/check.rs @@ -191,10 +191,10 @@ macro_rules! gate_feature_post { } impl<'a> PostExpansionVisitor<'a> { - fn check_abi(&self, abi: ast::Abi) { - let ast::Abi { symbol, span } = abi; + fn check_abi(&self, abi: ast::StrLit) { + let ast::StrLit { symbol_unescaped, span, .. } = abi; - match &*symbol.as_str() { + match &*symbol_unescaped.as_str() { // Stable "Rust" | "C" | diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index de28bd6cf83..17a7cbddff9 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1233,7 +1233,8 @@ impl<'a> State<'a> { ast::ItemKind::ForeignMod(ref nmod) => { self.head("extern"); if let Some(abi) = nmod.abi { - self.print_abi(abi); + self.print_literal(&abi.as_lit()); + self.nbsp(); } self.bopen(); self.print_foreign_mod(nmod, &item.attrs); @@ -2875,17 +2876,14 @@ impl<'a> State<'a> { } ast::Extern::Explicit(abi) => { self.word_nbsp("extern"); - self.print_abi(abi); + self.print_literal(&abi.as_lit()); + self.nbsp(); } } self.s.word("fn") } - fn print_abi(&mut self, abi: ast::Abi) { - self.word_nbsp(format!("\"{}\"", abi.symbol)); - } - crate fn print_unsafety(&mut self, s: ast::Unsafety) { match s { ast::Unsafety::Normal => {}, -- cgit 1.4.1-3-g733a5 From 11580ced403211c8c422a952a2c5dabedf6812d6 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 16 Nov 2019 20:11:05 +0300 Subject: Address review comments --- src/librustc_parse/parser/expr.rs | 3 +++ src/libsyntax/ast.rs | 5 +---- src/libsyntax_ext/asm.rs | 5 ++--- src/libsyntax_pos/symbol.rs | 1 - src/test/ui/asm/asm-parse-errors.stderr | 10 +++++----- 5 files changed, 11 insertions(+), 13 deletions(-) (limited to 'src/libsyntax') diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index be1dc4f19a7..a56a7bf1802 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -1073,6 +1073,9 @@ impl<'a> Parser<'a> { self.maybe_recover_from_bad_qpath(expr, true) } + /// Returns a string literal if the next token is a string literal. + /// In case of error returns `Some(lit)` if the next token is a literal with a wrong kind, + /// and returns `None` if the next token is not literal at all. pub fn parse_str_lit(&mut self) -> Result> { match self.parse_opt_lit() { Some(lit) => match lit.kind { diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index dee493a708e..bbf00825acb 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -2448,10 +2448,7 @@ pub enum Extern { impl Extern { pub fn from_abi(abi: Option) -> Extern { - match abi { - Some(abi) => Extern::Explicit(abi), - None => Extern::Implicit, - } + abi.map_or(Extern::Implicit, Extern::Explicit) } } diff --git a/src/libsyntax_ext/asm.rs b/src/libsyntax_ext/asm.rs index 9b37143557e..bd345a9a7da 100644 --- a/src/libsyntax_ext/asm.rs +++ b/src/libsyntax_ext/asm.rs @@ -72,9 +72,8 @@ fn parse_asm_str<'a>(p: &mut Parser<'a>) -> PResult<'a, Symbol> { Ok(str_lit) => Ok(str_lit.symbol_unescaped), Err(opt_lit) => { let span = opt_lit.map_or(p.token.span, |lit| lit.span); - let msg = "expected string literal"; - let mut err = p.sess.span_diagnostic.struct_span_fatal(span, msg); - err.span_label(span, msg); + let mut err = p.sess.span_diagnostic.struct_span_err(span, "expected string literal"); + err.span_label(span, "not a string literal"); Err(err) } } diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index b3e9576f43f..86eaeeab5a4 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -570,7 +570,6 @@ symbols! { rust_2018_preview, rust_begin_unwind, rustc, - Rust, RustcDecodable, RustcEncodable, rustc_allocator, diff --git a/src/test/ui/asm/asm-parse-errors.stderr b/src/test/ui/asm/asm-parse-errors.stderr index 9fe59d12e12..2b29332fef5 100644 --- a/src/test/ui/asm/asm-parse-errors.stderr +++ b/src/test/ui/asm/asm-parse-errors.stderr @@ -8,13 +8,13 @@ error: expected string literal --> $DIR/asm-parse-errors.rs:5:18 | LL | asm!("nop" : struct); - | ^^^^^^ expected string literal + | ^^^^^^ not a string literal error: expected string literal --> $DIR/asm-parse-errors.rs:6:30 | LL | asm!("mov %eax, $$0x2" : struct); - | ^^^^^^ expected string literal + | ^^^^^^ not a string literal error: expected `(`, found keyword `struct` --> $DIR/asm-parse-errors.rs:7:39 @@ -32,7 +32,7 @@ error: expected string literal --> $DIR/asm-parse-errors.rs:9:44 | LL | asm!("in %dx, %al" : "={al}"(result) : struct); - | ^^^^^^ expected string literal + | ^^^^^^ not a string literal error: expected `(`, found keyword `struct` --> $DIR/asm-parse-errors.rs:10:51 @@ -50,13 +50,13 @@ error: expected string literal --> $DIR/asm-parse-errors.rs:12:36 | LL | asm!("mov $$0x200, %eax" : : : struct); - | ^^^^^^ expected string literal + | ^^^^^^ not a string literal error: expected string literal --> $DIR/asm-parse-errors.rs:13:45 | LL | asm!("mov eax, 2" : "={eax}"(foo) : : : struct); - | ^^^^^^ expected string literal + | ^^^^^^ not a string literal error: inline assembly must be a string literal --> $DIR/asm-parse-errors.rs:14:10 -- cgit 1.4.1-3-g733a5