diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 651ee221b2..124f7b1278 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,7 @@ jobs: name: Tests runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@nightly with: components: rustc-dev @@ -41,7 +41,7 @@ jobs: env: target: ${{matrix.target && format('--target={0}', matrix.target)}} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@master with: toolchain: ${{matrix.rust}} @@ -70,7 +70,7 @@ jobs: name: Examples runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@nightly - run: cargo check --manifest-path examples/dump-syntax/Cargo.toml - run: cargo check --manifest-path examples/heapsize/example/Cargo.toml @@ -83,7 +83,7 @@ jobs: env: RUSTDOCFLAGS: --cfg=doc_cfg -Dbroken_intra_doc_links steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@nightly - run: cargo test --all-features --doc - run: cargo doc --all-features @@ -92,7 +92,7 @@ jobs: name: Codegen runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@stable - run: cd codegen && cargo run - run: git diff --exit-code @@ -101,7 +101,7 @@ jobs: name: Minimal versions runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@nightly - run: cargo update -Z minimal-versions - run: cargo check --all-features @@ -110,18 +110,18 @@ jobs: name: Miri runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: dtolnay/rust-toolchain@nightly - with: - components: miri + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@miri - run: cargo miri test --all-features + env: + MIRIFLAGS: '-Zmiri-tag-raw-pointers' clippy: name: Clippy runs-on: ubuntu-latest if: github.event_name != 'pull_request' steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@nightly with: components: clippy,rustc-dev @@ -132,6 +132,6 @@ jobs: runs-on: ubuntu-latest if: github.event_name != 'pull_request' steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dtolnay/install@cargo-outdated - run: cargo outdated --exit-code 1 diff --git a/Cargo.toml b/Cargo.toml index baa1f4e9e6..07e1482e05 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "syn" -version = "1.0.91" # don't forget to update html_root_url and syn.json +version = "1.0.92" # don't forget to update html_root_url and syn.json authors = ["David Tolnay "] license = "MIT OR Apache-2.0" description = "Parser for Rust source code" diff --git a/benches/rust.rs b/benches/rust.rs index 1b1143d20d..5e4fba182d 100644 --- a/benches/rust.rs +++ b/benches/rust.rs @@ -38,12 +38,14 @@ mod syn_parse { #[cfg(not(syn_only))] mod librustc_parse { extern crate rustc_data_structures; + extern crate rustc_error_messages; extern crate rustc_errors; extern crate rustc_parse; extern crate rustc_session; extern crate rustc_span; use rustc_data_structures::sync::Lrc; + use rustc_error_messages::FluentBundle; use rustc_errors::{emitter::Emitter, Diagnostic, Handler}; use rustc_session::parse::ParseSess; use rustc_span::source_map::{FilePathMapping, SourceMap}; @@ -57,6 +59,12 @@ mod librustc_parse { fn source_map(&self) -> Option<&Lrc> { None } + fn fluent_bundle(&self) -> Option<&Lrc> { + None + } + fn fallback_fluent_bundle(&self) -> &FluentBundle { + panic!("silent emitter attempted to translate a diagnostic"); + } } rustc_span::create_session_if_not_set_then(Edition::Edition2018, |_| { diff --git a/src/buffer.rs b/src/buffer.rs index 43e77e97f7..2cb6690f0b 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -88,25 +88,25 @@ impl TokenBuffer { // length of the backing buffer. The backing buffer must remain at a // constant address after this point, as we are going to store a raw // pointer into it. - let mut entries = entries.into_boxed_slice(); + let entries = entries.into_boxed_slice(); + let len = entries.len(); + // Convert boxed slice into a pointer to the first element early, to + // avoid invalidating pointers into this slice when we move the Box. + // See https://github.com/rust-lang/unsafe-code-guidelines/issues/326 + let entries = Box::into_raw(entries) as *mut Entry; for (idx, group) in groups { // We know that this index refers to one of the temporary // `End(null)` entries, and we know that the last entry is // `End(up)`, so the next index is also valid. - let group_up = unsafe { entries.as_ptr().add(idx + 1) }; + let group_up = unsafe { entries.add(idx + 1) }; // The end entry stored at the end of this Entry::Group should // point to the Entry which follows the Group in the list. let inner = Self::inner_new(group.stream(), group_up); - entries[idx] = Entry::Group(group, inner); + unsafe { *entries.add(idx) = Entry::Group(group, inner) }; } - let len = entries.len(); - let ptr = Box::into_raw(entries); - TokenBuffer { - ptr: ptr as *const Entry, - len, - } + TokenBuffer { ptr: entries, len } } /// Creates a `TokenBuffer` containing all the tokens from the input diff --git a/src/ident.rs b/src/ident.rs index 61e088774d..039daf46c1 100644 --- a/src/ident.rs +++ b/src/ident.rs @@ -90,7 +90,7 @@ impl From for Ident { pub fn xid_ok(symbol: &str) -> bool { let mut chars = symbol.chars(); let first = chars.next().unwrap(); - if !(UnicodeXID::is_xid_start(first) || first == '_') { + if !(first == '_' || UnicodeXID::is_xid_start(first)) { return false; } for ch in chars { diff --git a/src/lib.rs b/src/lib.rs index b59a8dfc5f..741aaac713 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -250,7 +250,7 @@ //! dynamic library libproc_macro from rustc toolchain. // Syn types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/syn/1.0.91")] +#![doc(html_root_url = "https://docs.rs/syn/1.0.92")] #![cfg_attr(doc_cfg, feature(doc_cfg))] #![allow(non_camel_case_types)] // Ignored clippy lints. diff --git a/src/ty.rs b/src/ty.rs index 8249d997ef..0f1341fddd 100644 --- a/src/ty.rs +++ b/src/ty.rs @@ -54,7 +54,7 @@ ast_enum_of_structs! { /// A dynamically sized slice type: `[T]`. Slice(TypeSlice), - /// A trait object type `Bound1 + Bound2 + Bound3` where `Bound` is a + /// A trait object type `dyn Bound1 + Bound2 + Bound3` where `Bound` is a /// trait or a lifetime. TraitObject(TypeTraitObject), @@ -244,7 +244,7 @@ ast_struct! { } ast_struct! { - /// A trait object type `Bound1 + Bound2 + Bound3` where `Bound` is a + /// A trait object type `dyn Bound1 + Bound2 + Bound3` where `Bound` is a /// trait or a lifetime. /// /// *This type is available only if Syn is built with the `"derive"` or diff --git a/syn.json b/syn.json index 664a4d19b6..566f50f47c 100644 --- a/syn.json +++ b/syn.json @@ -1,5 +1,5 @@ { - "version": "1.0.91", + "version": "1.0.92", "types": [ { "ident": "Abi", diff --git a/tests/common/eq.rs b/tests/common/eq.rs index 0696983406..a3f0baae9e 100644 --- a/tests/common/eq.rs +++ b/tests/common/eq.rs @@ -9,18 +9,19 @@ use rustc_ast::ast::{ Defaultness, EnumDef, Expr, ExprField, ExprKind, Extern, FieldDef, FloatTy, Fn, FnDecl, FnHeader, FnRetTy, FnSig, ForeignItemKind, ForeignMod, GenericArg, GenericArgs, GenericBound, GenericParam, GenericParamKind, Generics, Impl, ImplPolarity, Inline, InlineAsm, - InlineAsmOperand, InlineAsmOptions, InlineAsmRegOrRegClass, InlineAsmTemplatePiece, IntTy, - IsAuto, Item, ItemKind, Label, Lifetime, Lit, LitFloatType, LitIntType, LitKind, Local, - LocalKind, MacArgs, MacCall, MacCallStmt, MacDelimiter, MacStmtStyle, MacroDef, ModKind, - ModSpans, Movability, MutTy, Mutability, NodeId, Param, ParenthesizedArgs, Pat, PatField, - PatKind, Path, PathSegment, PolyTraitRef, QSelf, RangeEnd, RangeLimits, RangeSyntax, Stmt, - StmtKind, StrLit, StrStyle, StructExpr, StructRest, Term, Trait, TraitBoundModifier, - TraitObjectSyntax, TraitRef, Ty, TyAlias, TyAliasWhereClause, TyKind, UintTy, UnOp, Unsafe, - UnsafeSource, UseTree, UseTreeKind, Variant, VariantData, Visibility, VisibilityKind, - WhereBoundPredicate, WhereClause, WhereEqPredicate, WherePredicate, WhereRegionPredicate, + InlineAsmOperand, InlineAsmOptions, InlineAsmRegOrRegClass, InlineAsmSym, + InlineAsmTemplatePiece, IntTy, IsAuto, Item, ItemKind, Label, Lifetime, Lit, LitFloatType, + LitIntType, LitKind, Local, LocalKind, MacArgs, MacCall, MacCallStmt, MacDelimiter, + MacStmtStyle, MacroDef, ModKind, ModSpans, Movability, MutTy, Mutability, NodeId, Param, + ParenthesizedArgs, Pat, PatField, PatKind, Path, PathSegment, PolyTraitRef, QSelf, RangeEnd, + RangeLimits, RangeSyntax, Stmt, StmtKind, StrLit, StrStyle, StructExpr, StructRest, Term, + Trait, TraitBoundModifier, TraitObjectSyntax, TraitRef, Ty, TyAlias, TyAliasWhereClause, + TyKind, UintTy, UnOp, Unsafe, UnsafeSource, UseTree, UseTreeKind, Variant, VariantData, + Visibility, VisibilityKind, WhereBoundPredicate, WhereClause, WhereEqPredicate, WherePredicate, + WhereRegionPredicate, }; use rustc_ast::ptr::P; -use rustc_ast::token::{self, CommentKind, DelimToken, Nonterminal, Token, TokenKind}; +use rustc_ast::token::{self, CommentKind, Delimiter, Nonterminal, Token, TokenKind}; use rustc_ast::tokenstream::{ AttrAnnotatedTokenStream, AttrAnnotatedTokenTree, AttributesData, DelimSpan, LazyTokenStream, Spacing, TokenStream, TokenTree, @@ -141,7 +142,7 @@ spanless_eq_partial_eq!(char); spanless_eq_partial_eq!(String); spanless_eq_partial_eq!(Symbol); spanless_eq_partial_eq!(CommentKind); -spanless_eq_partial_eq!(DelimToken); +spanless_eq_partial_eq!(Delimiter); spanless_eq_partial_eq!(InlineAsmOptions); spanless_eq_partial_eq!(token::LitKind); @@ -316,6 +317,7 @@ spanless_eq_struct!(GenericParam; id ident attrs bounds is_placeholder kind); spanless_eq_struct!(Generics; params where_clause span); spanless_eq_struct!(Impl; defaultness unsafety generics constness polarity of_trait self_ty items); spanless_eq_struct!(InlineAsm; template template_strs operands clobber_abis options line_spans); +spanless_eq_struct!(InlineAsmSym; id qself path); spanless_eq_struct!(Item; attrs id span vis ident kind !tokens); spanless_eq_struct!(Label; ident); spanless_eq_struct!(Lifetime; id ident); @@ -413,7 +415,7 @@ spanless_eq_enum!(ExprKind; Box(0) Array(0) ConstBlock(0) Call(0 1) MacCall(0) Struct(0) Repeat(0 1) Paren(0) Try(0) Yield(0) Err); spanless_eq_enum!(InlineAsmOperand; In(reg expr) Out(reg late expr) InOut(reg late expr) SplitInOut(reg late in_expr out_expr) Const(anon_const) - Sym(expr)); + Sym(sym)); spanless_eq_enum!(ItemKind; ExternCrate(0) Use(0) Static(0 1 2) Const(0 1 2) Fn(0) Mod(0 1) ForeignMod(0) GlobalAsm(0) TyAlias(0) Enum(0 1) Struct(0 1) Union(0 1) Trait(0) TraitAlias(0 1) Impl(0) MacCall(0) MacroDef(0)); @@ -544,7 +546,7 @@ fn doc_comment( } } let stream = match trees.next() { - Some(TokenTree::Delimited(_span, DelimToken::Bracket, stream)) => stream, + Some(TokenTree::Delimited(_span, Delimiter::Bracket, stream)) => stream, _ => return false, }; let mut trees = stream.trees(); diff --git a/tests/macros/mod.rs b/tests/macros/mod.rs index 86cdb5f6ca..61cd67b882 100644 --- a/tests/macros/mod.rs +++ b/tests/macros/mod.rs @@ -1,9 +1,10 @@ +#![allow(unused_macros)] + #[path = "../debug/mod.rs"] pub mod debug; use syn::parse::{Parse, Result}; -#[macro_export] macro_rules! errorf { ($($tt:tt)*) => {{ use ::std::io::Write; @@ -12,7 +13,6 @@ macro_rules! errorf { }}; } -#[macro_export] macro_rules! punctuated { ($($e:expr,)+) => {{ let mut seq = ::syn::punctuated::Punctuated::new(); @@ -27,14 +27,12 @@ macro_rules! punctuated { }; } -#[macro_export] macro_rules! snapshot { ($($args:tt)*) => { snapshot_impl!(() $($args)*) }; } -#[macro_export] macro_rules! snapshot_impl { (($expr:ident) as $t:ty, @$snapshot:literal) => { let $expr = crate::macros::Tokens::parse::<$t>($expr).unwrap(); diff --git a/tests/test_round_trip.rs b/tests/test_round_trip.rs index b9202371e9..c7e6e488fe 100644 --- a/tests/test_round_trip.rs +++ b/tests/test_round_trip.rs @@ -5,6 +5,8 @@ #![allow(clippy::manual_assert)] extern crate rustc_ast; +extern crate rustc_data_structures; +extern crate rustc_error_messages; extern crate rustc_errors; extern crate rustc_expand; extern crate rustc_parse as parse; @@ -19,7 +21,8 @@ use rustc_ast::ast::{ WhereClause, }; use rustc_ast::mut_visit::{self, MutVisitor}; -use rustc_errors::PResult; +use rustc_error_messages::{DiagnosticMessage, FluentArgs, LazyFallbackBundle}; +use rustc_errors::{Diagnostic, PResult}; use rustc_session::parse::ParseSess; use rustc_span::source_map::FilePathMapping; use rustc_span::FileName; @@ -94,18 +97,11 @@ fn test(path: &Path, failed: &AtomicUsize, abort_after: usize) { let before = match librustc_parse(content, &sess) { Ok(before) => before, Err(diagnostic) => { - if diagnostic - .message() - .starts_with("file not found for module") - { - errorf!("=== {}: ignore\n", path.display()); - } else { - errorf!( - "=== {}: ignore - librustc failed to parse original content: {}\n", - path.display(), - diagnostic.message(), - ); - } + errorf!( + "=== {}: ignore - librustc failed to parse original content: {}\n", + path.display(), + translate_message(&diagnostic), + ); diagnostic.cancel(); return Err(true); } @@ -162,6 +158,42 @@ fn librustc_parse(content: String, sess: &ParseSess) -> PResult { parse::parse_crate_from_source_str(name, content, sess) } +fn translate_message(diagnostic: &Diagnostic) -> String { + thread_local! { + static FLUENT_BUNDLE: LazyFallbackBundle = { + let resources = rustc_error_messages::DEFAULT_LOCALE_RESOURCES; + let with_directionality_markers = false; + rustc_error_messages::fallback_fluent_bundle(resources, with_directionality_markers) + }; + } + + let message = &diagnostic.message[0].0; + let args = diagnostic.args().iter().cloned().collect::(); + + let (identifier, attr) = match message { + DiagnosticMessage::Str(msg) => return msg.clone(), + DiagnosticMessage::FluentIdentifier(identifier, attr) => (identifier, attr), + }; + + FLUENT_BUNDLE.with(|fluent_bundle| { + let message = fluent_bundle + .get_message(identifier) + .expect("missing diagnostic in fluent bundle"); + let value = match attr { + Some(attr) => message + .get_attribute(attr) + .expect("missing attribute in fluent message") + .value(), + None => message.value().expect("missing value in fluent message"), + }; + + let mut err = Vec::new(); + let translated = fluent_bundle.format_pattern(value, Some(&args), &mut err); + assert!(err.is_empty()); + translated.into_owned() + }) +} + fn normalize(krate: &mut Crate) { struct NormalizeVisitor;