From 65af429c681e874bee6fb3a864ae3496517a72f4 Mon Sep 17 00:00:00 2001 From: Ethan Brierley Date: Tue, 24 Sep 2019 20:19:32 +0100 Subject: [PATCH 01/10] Stabilize `Option::flatten` --- src/liballoc/tests/lib.rs | 1 - src/libcore/option.rs | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs index 676874c8b27df..79e5ba340b784 100644 --- a/src/liballoc/tests/lib.rs +++ b/src/liballoc/tests/lib.rs @@ -3,7 +3,6 @@ #![feature(drain_filter)] #![feature(exact_size_is_empty)] #![feature(new_uninit)] -#![feature(option_flattening)] #![feature(pattern)] #![feature(trusted_len)] #![feature(try_reserve)] diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 47e3a0d21676f..a0f09fabb3456 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -1568,7 +1568,6 @@ impl Option> { /// # Examples /// Basic usage: /// ``` - /// #![feature(option_flattening)] /// let x: Option> = Some(Some(6)); /// assert_eq!(Some(6), x.flatten()); /// @@ -1580,13 +1579,12 @@ impl Option> { /// ``` /// Flattening once only removes one level of nesting: /// ``` - /// #![feature(option_flattening)] /// let x: Option>> = Some(Some(Some(6))); /// assert_eq!(Some(Some(6)), x.flatten()); /// assert_eq!(Some(6), x.flatten().flatten()); /// ``` #[inline] - #[unstable(feature = "option_flattening", issue = "60258")] + #[stable(feature = "option_flattening", since = "1.40.0")] pub fn flatten(self) -> Option { self.and_then(convert::identity) } From 16329402bff5115135804580386ffa8a9e89f1f9 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 9 Oct 2019 13:19:15 +0200 Subject: [PATCH 02/10] syntax/attr: reduce reliance on parser --- src/libsyntax/attr/mod.rs | 29 ++--------------------------- src/libsyntax/config.rs | 4 +++- src/libsyntax/lib.rs | 3 +-- src/libsyntax/parse/mod.rs | 21 +++++++++++++++++++++ src/libsyntax/parse/parser/path.rs | 2 +- src/libsyntax_expand/proc_macro.rs | 9 ++++++++- 6 files changed, 36 insertions(+), 32 deletions(-) diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index 27de084ae98ca..3e240a855e280 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -15,7 +15,7 @@ use crate::ast::{Lit, LitKind, Expr, Item, Local, Stmt, StmtKind, GenericParam}; use crate::mut_visit::visit_clobber; use crate::source_map::{BytePos, Spanned}; use crate::parse::lexer::comments::doc_comment_style; -use crate::parse::parser::Parser; +use crate::parse; use crate::parse::PResult; use crate::parse::token::{self, Token}; use crate::ptr::P; @@ -280,35 +280,10 @@ impl Attribute { self.item.meta(self.span) } - crate fn parse<'a, T, F>(&self, sess: &'a ParseSess, mut f: F) -> PResult<'a, T> - where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>, - { - let mut parser = Parser::new( - sess, - self.tokens.clone(), - None, - false, - false, - Some("attribute"), - ); - let result = f(&mut parser)?; - if parser.token != token::Eof { - parser.unexpected()?; - } - Ok(result) - } - - pub fn parse_derive_paths<'a>(&self, sess: &'a ParseSess) -> PResult<'a, Vec> { - if self.tokens.is_empty() { - return Ok(Vec::new()); - } - self.parse(sess, |p| p.parse_derive_paths()) - } - pub fn parse_meta<'a>(&self, sess: &'a ParseSess) -> PResult<'a, MetaItem> { Ok(MetaItem { path: self.path.clone(), - kind: self.parse(sess, |parser| parser.parse_meta_item_kind())?, + kind: parse::parse_in_attr(sess, self, |p| p.parse_meta_item_kind())?, span: self.span, }) } diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 54dc95291d67f..6003fd1d2861a 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -10,6 +10,7 @@ use crate::attr; use crate::ast; use crate::edition::Edition; use crate::mut_visit::*; +use crate::parse; use crate::ptr::P; use crate::sess::ParseSess; use crate::symbol::sym; @@ -112,7 +113,8 @@ impl<'a> StripUnconfigured<'a> { return vec![]; } - let (cfg_predicate, expanded_attrs) = match attr.parse(self.sess, |p| p.parse_cfg_attr()) { + let res = parse::parse_in_attr(self.sess, &attr, |p| p.parse_cfg_attr()); + let (cfg_predicate, expanded_attrs) = match res { Ok(result) => result, Err(mut e) => { e.emit(); diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 3a2af96f7db64..c1114674f14f8 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -96,8 +96,7 @@ pub mod json; pub mod ast; pub mod attr; pub mod source_map; -#[macro_use] -pub mod config; +#[macro_use] pub mod config; pub mod entry; pub mod feature_gate; pub mod mut_visit; diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index e6ddf8778ccf0..f5e416b722bbf 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -288,6 +288,27 @@ pub fn stream_to_parser_with_base_dir<'a>( Parser::new(sess, stream, Some(base_dir), true, false, None) } +/// Runs the given subparser `f` on the tokens of the given `attr`'s item. +pub fn parse_in_attr<'a, T>( + sess: &'a ParseSess, + attr: &ast::Attribute, + mut f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>, +) -> PResult<'a, T> { + let mut parser = Parser::new( + sess, + attr.tokens.clone(), + None, + false, + false, + Some("attribute"), + ); + let result = f(&mut parser)?; + if parser.token != token::Eof { + parser.unexpected()?; + } + Ok(result) +} + // NOTE(Centril): The following probably shouldn't be here but it acknowledges the // fact that architecturally, we are using parsing (read on below to understand why). diff --git a/src/libsyntax/parse/parser/path.rs b/src/libsyntax/parse/parser/path.rs index 77709a2295339..38a28224daba4 100644 --- a/src/libsyntax/parse/parser/path.rs +++ b/src/libsyntax/parse/parser/path.rs @@ -130,7 +130,7 @@ impl<'a> Parser<'a> { } /// Parse a list of paths inside `#[derive(path_0, ..., path_n)]`. - crate fn parse_derive_paths(&mut self) -> PResult<'a, Vec> { + pub fn parse_derive_paths(&mut self) -> PResult<'a, Vec> { self.expect(&token::OpenDelim(token::Paren))?; let mut list = Vec::new(); while !self.eat(&token::CloseDelim(token::Paren)) { diff --git a/src/libsyntax_expand/proc_macro.rs b/src/libsyntax_expand/proc_macro.rs index 07b618c99a556..8146566549812 100644 --- a/src/libsyntax_expand/proc_macro.rs +++ b/src/libsyntax_expand/proc_macro.rs @@ -200,7 +200,14 @@ crate fn collect_derives(cx: &mut ExtCtxt<'_>, attrs: &mut Vec) return false; } - match attr.parse_derive_paths(cx.parse_sess) { + let parse_derive_paths = |attr: &ast::Attribute| { + if attr.tokens.is_empty() { + return Ok(Vec::new()); + } + parse::parse_in_attr(cx.parse_sess, attr, |p| p.parse_derive_paths()) + }; + + match parse_derive_paths(attr) { Ok(traits) => { result.extend(traits); true From fb12c708521d66b1f727ad4c1ec752a78799980d Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 9 Oct 2019 16:47:38 +0200 Subject: [PATCH 03/10] rustc, rustc_passes: don't depend on syntax_expand. This is done by moving some data definitions to syntax::expand. --- Cargo.lock | 3 --- src/librustc/Cargo.toml | 1 - src/librustc/hir/def.rs | 2 +- src/librustc/hir/lowering.rs | 2 +- src/librustc/hir/lowering/item.rs | 2 +- src/librustc/hir/map/def_collector.rs | 2 +- src/librustc/hir/map/definitions.rs | 4 ++-- src/librustc/hir/map/mod.rs | 2 +- src/librustc/ich/hcx.rs | 3 +-- src/librustc/ich/impls_syntax.rs | 2 +- src/librustc/lint/mod.rs | 2 +- src/librustc/session/mod.rs | 2 +- src/librustc/ty/mod.rs | 4 ++-- src/librustc_codegen_llvm/allocator.rs | 2 +- src/librustc_codegen_llvm/lib.rs | 3 +-- src/librustc_codegen_ssa/Cargo.toml | 1 - .../back/symbol_export.rs | 2 +- src/librustc_codegen_ssa/back/write.rs | 2 +- src/librustc_codegen_ssa/traits/backend.rs | 2 +- src/librustc_interface/passes.rs | 2 +- src/librustc_metadata/creader.rs | 2 +- src/librustc_metadata/decoder.rs | 8 +++---- src/librustc_metadata/encoder.rs | 2 +- src/librustc_passes/Cargo.toml | 1 - src/librustc_passes/ast_validation.rs | 2 +- src/librustc_resolve/build_reduced_graph.rs | 7 +++---- src/librustc_resolve/diagnostics.rs | 2 +- src/librustc_resolve/late/diagnostics.rs | 2 +- src/librustc_resolve/lib.rs | 11 +++++----- src/librustc_resolve/macros.rs | 13 ++++++------ src/librustc_resolve/resolve_imports.rs | 2 +- src/librustdoc/clean/inline.rs | 2 +- src/librustdoc/clean/mod.rs | 4 ++-- src/librustdoc/doctree.rs | 2 +- src/librustdoc/html/item_type.rs | 2 +- src/librustdoc/html/render.rs | 2 +- src/librustdoc/visit_ast.rs | 2 +- .../expand}/allocator.rs | 4 ++-- src/libsyntax/expand/mod.rs | 21 +++++++++++++++++++ src/libsyntax/lib.rs | 1 + src/libsyntax_expand/base.rs | 16 +++----------- src/libsyntax_expand/lib.rs | 3 +-- src/libsyntax_expand/proc_macro.rs | 5 ----- src/libsyntax_ext/deriving/clone.rs | 3 ++- src/libsyntax_ext/deriving/cmp/eq.rs | 3 ++- src/libsyntax_ext/deriving/cmp/partial_eq.rs | 5 +++-- src/libsyntax_ext/deriving/generic/mod.rs | 5 +++-- src/libsyntax_ext/global_allocator.rs | 4 ++-- src/libsyntax_ext/proc_macro_harness.rs | 2 +- src/libsyntax_ext/standard_library_imports.rs | 2 +- 50 files changed, 94 insertions(+), 91 deletions(-) rename src/{libsyntax_expand => libsyntax/expand}/allocator.rs (96%) create mode 100644 src/libsyntax/expand/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 64f3a7ac619c2..4b264ef3f9faf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3135,7 +3135,6 @@ dependencies = [ "serialize", "smallvec", "syntax", - "syntax_expand", "syntax_pos", ] @@ -3451,7 +3450,6 @@ dependencies = [ "rustc_target", "serialize", "syntax", - "syntax_expand", "syntax_pos", "tempfile", ] @@ -3707,7 +3705,6 @@ dependencies = [ "rustc_index", "rustc_target", "syntax", - "syntax_expand", "syntax_pos", ] diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml index 38631224fd359..9d26ff6001767 100644 --- a/src/librustc/Cargo.toml +++ b/src/librustc/Cargo.toml @@ -29,7 +29,6 @@ rustc_index = { path = "../librustc_index" } errors = { path = "../librustc_errors", package = "rustc_errors" } rustc_serialize = { path = "../libserialize", package = "serialize" } syntax = { path = "../libsyntax" } -syntax_expand = { path = "../libsyntax_expand" } syntax_pos = { path = "../libsyntax_pos" } backtrace = "0.3.3" parking_lot = "0.9" diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index a071a539e01df..d4d7af92fe359 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -6,8 +6,8 @@ use crate::ty; use crate::util::nodemap::DefIdMap; use syntax::ast; -use syntax_expand::base::MacroKind; use syntax::ast::NodeId; +use syntax_pos::hygiene::MacroKind; use syntax_pos::Span; use rustc_macros::HashStable; diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 002e6874466bb..12ab44515c38d 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -64,7 +64,7 @@ use syntax::ast; use syntax::ptr::P as AstP; use syntax::ast::*; use syntax::errors; -use syntax_expand::base::SpecialDerives; +use syntax::expand::SpecialDerives; use syntax::print::pprust; use syntax::parse::token::{self, Nonterminal, Token}; use syntax::tokenstream::{TokenStream, TokenTree}; diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs index 73d2ac5c134d3..9da87090c79bb 100644 --- a/src/librustc/hir/lowering/item.rs +++ b/src/librustc/hir/lowering/item.rs @@ -18,7 +18,7 @@ use smallvec::SmallVec; use syntax::attr; use syntax::ast::*; use syntax::visit::{self, Visitor}; -use syntax_expand::base::SpecialDerives; +use syntax::expand::SpecialDerives; use syntax::source_map::{respan, DesugaringKind, Spanned}; use syntax::symbol::{kw, sym}; use syntax_pos::Span; diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index 7c8fdcc8b12e9..e9970e30bf9e5 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -2,10 +2,10 @@ use crate::hir::map::definitions::*; use crate::hir::def_id::DefIndex; use syntax::ast::*; -use syntax_expand::hygiene::ExpnId; use syntax::visit; use syntax::symbol::{kw, sym}; use syntax::parse::token::{self, Token}; +use syntax_pos::hygiene::ExpnId; use syntax_pos::Span; /// Creates `DefId`s for nodes in the AST. diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 58e638e93ba34..4e163314f6b07 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -17,8 +17,8 @@ use std::borrow::Borrow; use std::fmt::Write; use std::hash::Hash; use syntax::ast; -use syntax_expand::hygiene::ExpnId; -use syntax::symbol::{Symbol, sym}; +use syntax_pos::symbol::{Symbol, sym}; +use syntax_pos::hygiene::ExpnId; use syntax_pos::{Span, DUMMY_SP}; /// The `DefPathTable` maps `DefIndex`es to `DefKey`s and vice versa. diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index f839087ec0271..cd36944253dbb 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -20,7 +20,7 @@ use rustc_data_structures::svh::Svh; use rustc_index::vec::IndexVec; use syntax::ast::{self, Name, NodeId}; use syntax::source_map::Spanned; -use syntax_expand::base::MacroKind; +use syntax_pos::hygiene::MacroKind; use syntax_pos::{Span, DUMMY_SP}; pub mod blocks; diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs index 14d0673ecc03f..957dab39414f0 100644 --- a/src/librustc/ich/hcx.rs +++ b/src/librustc/ich/hcx.rs @@ -13,11 +13,10 @@ use std::cell::RefCell; use syntax::ast; use syntax::source_map::SourceMap; -use syntax_expand::hygiene::SyntaxContext; use syntax::symbol::Symbol; use syntax::tokenstream::DelimSpan; use syntax_pos::{Span, DUMMY_SP}; -use syntax_pos::hygiene; +use syntax_pos::hygiene::{self, SyntaxContext}; use rustc_data_structures::stable_hasher::{ HashStable, StableHasher, ToStableHashKey, diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index 2510d7efb59e7..51aa79078f2fc 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -60,7 +60,7 @@ impl_stable_hash_for!(enum ::syntax::ast::AsmDialect { Intel }); -impl_stable_hash_for!(enum ::syntax_expand::base::MacroKind { +impl_stable_hash_for!(enum ::syntax_pos::hygiene::MacroKind { Bang, Attr, Derive, diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 3c35bdae66e9d..4da146b1e5d57 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -39,8 +39,8 @@ use syntax::ast; use syntax::source_map::{MultiSpan, ExpnKind, DesugaringKind}; use syntax::early_buffered_lints::BufferedEarlyLintId; use syntax::edition::Edition; -use syntax_expand::base::MacroKind; use syntax::symbol::{Symbol, sym}; +use syntax_pos::hygiene::MacroKind; use syntax_pos::Span; pub use crate::lint::context::{LateContext, EarlyContext, LintContext, LintStore, diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index bd2460cfab116..8bf4765111d36 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -24,7 +24,7 @@ use errors::emitter::HumanReadableErrorType; use errors::annotate_snippet_emitter_writer::{AnnotateSnippetEmitterWriter}; use syntax::ast::{self, NodeId}; use syntax::edition::Edition; -use syntax_expand::allocator::AllocatorKind; +use syntax::expand::allocator::AllocatorKind; use syntax::feature_gate::{self, AttributeType}; use syntax::json::JsonEmitter; use syntax::source_map; diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 260b525507e80..1353fe89017c4 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -46,8 +46,8 @@ use std::{mem, ptr}; use std::ops::Range; use syntax::ast::{self, Name, Ident, NodeId}; use syntax::attr; -use syntax_expand::hygiene::ExpnId; -use syntax::symbol::{kw, sym, Symbol}; +use syntax_pos::symbol::{kw, sym, Symbol}; +use syntax_pos::hygiene::ExpnId; use syntax_pos::Span; use smallvec; diff --git a/src/librustc_codegen_llvm/allocator.rs b/src/librustc_codegen_llvm/allocator.rs index 8c60c030eacdb..11b6e0befa1b1 100644 --- a/src/librustc_codegen_llvm/allocator.rs +++ b/src/librustc_codegen_llvm/allocator.rs @@ -3,7 +3,7 @@ use std::ffi::CString; use crate::attributes; use libc::c_uint; use rustc::ty::TyCtxt; -use syntax_expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS}; +use syntax::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS}; use crate::ModuleLlvm; use crate::llvm::{self, False, True}; diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index e09b600afd4e5..2ad6c28cd0838 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -39,7 +39,6 @@ extern crate rustc_driver as _; #[macro_use] extern crate log; extern crate syntax; -extern crate syntax_expand; extern crate syntax_pos; extern crate rustc_errors as errors; @@ -49,7 +48,7 @@ use rustc_codegen_ssa::back::lto::{SerializedModule, LtoModuleCodegen, ThinModul use rustc_codegen_ssa::CompiledModule; use errors::{FatalError, Handler}; use rustc::dep_graph::WorkProduct; -use syntax_expand::allocator::AllocatorKind; +use syntax::expand::allocator::AllocatorKind; pub use llvm_util::target_features; use std::any::Any; use std::sync::Arc; diff --git a/src/librustc_codegen_ssa/Cargo.toml b/src/librustc_codegen_ssa/Cargo.toml index 6992f93d99949..c7d09a423d5e3 100644 --- a/src/librustc_codegen_ssa/Cargo.toml +++ b/src/librustc_codegen_ssa/Cargo.toml @@ -21,7 +21,6 @@ tempfile = "3.1" rustc_serialize = { path = "../libserialize", package = "serialize" } syntax = { path = "../libsyntax" } -syntax_expand = { path = "../libsyntax_expand" } syntax_pos = { path = "../libsyntax_pos" } rustc = { path = "../librustc" } rustc_apfloat = { path = "../librustc_apfloat" } diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs index d866a10f06935..9443f22572378 100644 --- a/src/librustc_codegen_ssa/back/symbol_export.rs +++ b/src/librustc_codegen_ssa/back/symbol_export.rs @@ -14,7 +14,7 @@ use rustc::ty::query::Providers; use rustc::ty::subst::SubstsRef; use rustc::util::nodemap::{FxHashMap, DefIdMap}; use rustc_index::vec::IndexVec; -use syntax_expand::allocator::ALLOCATOR_METHODS; +use syntax::expand::allocator::ALLOCATOR_METHODS; pub type ExportedSymbols = FxHashMap< CrateNum, diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index 762b50f1659cc..b302b9ae7f0e4 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -27,7 +27,7 @@ use rustc_errors::{Handler, Level, FatalError, DiagnosticId, SourceMapperDyn}; use rustc_errors::emitter::{Emitter}; use rustc_target::spec::MergeFunctions; use syntax::attr; -use syntax_expand::hygiene::ExpnId; +use syntax_pos::hygiene::ExpnId; use syntax_pos::symbol::{Symbol, sym}; use jobserver::{Client, Acquired}; diff --git a/src/librustc_codegen_ssa/traits/backend.rs b/src/librustc_codegen_ssa/traits/backend.rs index 1fff740d7403f..8ab8243afdab7 100644 --- a/src/librustc_codegen_ssa/traits/backend.rs +++ b/src/librustc_codegen_ssa/traits/backend.rs @@ -9,7 +9,7 @@ use rustc::ty::TyCtxt; use rustc_codegen_utils::codegen_backend::CodegenBackend; use std::sync::Arc; use std::sync::mpsc; -use syntax_expand::allocator::AllocatorKind; +use syntax::expand::allocator::AllocatorKind; use syntax_pos::symbol::Symbol; pub trait BackendTypes { diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 58936172c5bce..b8593bd91990e 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -502,7 +502,7 @@ pub fn lower_to_hir( // Discard hygiene data, which isn't required after lowering to HIR. if !sess.opts.debugging_opts.keep_hygiene_data { - syntax_expand::hygiene::clear_syntax_context_map(); + syntax_pos::hygiene::clear_syntax_context_map(); } Ok(hir_forest) diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index f0a68058de8ca..234a5395047c6 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -25,7 +25,7 @@ use std::{cmp, fs}; use syntax::ast; use syntax::attr; -use syntax_expand::allocator::{global_allocator_spans, AllocatorKind}; +use syntax::expand::allocator::{global_allocator_spans, AllocatorKind}; use syntax::symbol::{Symbol, sym}; use syntax::span_fatal; use syntax_pos::{Span, DUMMY_SP}; diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 09ff7891a9deb..0e6ecbbf0176a 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -33,12 +33,12 @@ use rustc_serialize::{Decodable, Decoder, Encodable, SpecializedDecoder, opaque} use syntax::attr; use syntax::ast::{self, Ident}; use syntax::source_map::{self, respan, Spanned}; -use syntax::symbol::{Symbol, sym}; -use syntax_expand::base::{MacroKind, SyntaxExtensionKind, SyntaxExtension}; -use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP}; +use syntax_expand::base::{SyntaxExtensionKind, SyntaxExtension}; +use syntax_expand::proc_macro::{AttrProcMacro, ProcMacroDerive, BangProcMacro}; +use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP, hygiene::MacroKind}; +use syntax_pos::symbol::{Symbol, sym}; use log::debug; use proc_macro::bridge::client::ProcMacro; -use syntax_expand::proc_macro::{AttrProcMacro, ProcMacroDerive, BangProcMacro}; crate struct DecodeContext<'a, 'tcx> { opaque: opaque::Decoder<'a>, diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 0dc9f91ae00e1..fa961fe04dcc4 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -32,7 +32,7 @@ use std::path::Path; use std::u32; use syntax::ast; use syntax::attr; -use syntax_expand::proc_macro::is_proc_macro_attr; +use syntax::expand::is_proc_macro_attr; use syntax::source_map::Spanned; use syntax::symbol::{kw, sym, Ident, Symbol}; use syntax_pos::{self, FileName, SourceFile, Span}; diff --git a/src/librustc_passes/Cargo.toml b/src/librustc_passes/Cargo.toml index 118deb560d62f..9d29a23031443 100644 --- a/src/librustc_passes/Cargo.toml +++ b/src/librustc_passes/Cargo.toml @@ -13,7 +13,6 @@ log = "0.4" rustc = { path = "../librustc" } rustc_data_structures = { path = "../librustc_data_structures" } syntax = { path = "../libsyntax" } -syntax_expand = { path = "../libsyntax_expand" } syntax_pos = { path = "../libsyntax_pos" } errors = { path = "../librustc_errors", package = "rustc_errors" } rustc_target = { path = "../librustc_target" } diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 74de31263d394..994e9405fb643 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -14,7 +14,7 @@ use rustc::session::Session; use rustc_data_structures::fx::FxHashMap; use syntax::ast::*; use syntax::attr; -use syntax_expand::proc_macro::is_proc_macro_attr; +use syntax::expand::is_proc_macro_attr; use syntax::feature_gate::is_builtin_attr; use syntax::source_map::Spanned; use syntax::symbol::{kw, sym}; diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index c0fb8e33a819e..d0725c7b8028d 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -32,9 +32,6 @@ use syntax::attr; use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, NodeId}; use syntax::ast::{MetaItemKind, StmtKind, TraitItem, TraitItemKind}; -use syntax_expand::base::{MacroKind, SyntaxExtension}; -use syntax_expand::expand::AstFragment; -use syntax_expand::hygiene::ExpnId; use syntax::feature_gate::is_builtin_attr; use syntax::parse::token::{self, Token}; use syntax::print::pprust; @@ -42,7 +39,9 @@ use syntax::{span_err, struct_span_err}; use syntax::source_map::{respan, Spanned}; use syntax::symbol::{kw, sym}; use syntax::visit::{self, Visitor}; - +use syntax_expand::base::SyntaxExtension; +use syntax_expand::expand::AstFragment; +use syntax_pos::hygiene::{MacroKind, ExpnId}; use syntax_pos::{Span, DUMMY_SP}; use log::debug; diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 7634093fbefba..c0dfb7381acc2 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -10,12 +10,12 @@ use rustc::session::Session; use rustc::ty::{self, DefIdTree}; use rustc::util::nodemap::FxHashSet; use syntax::ast::{self, Ident, Path}; -use syntax_expand::base::MacroKind; use syntax::feature_gate::BUILTIN_ATTRIBUTES; use syntax::source_map::SourceMap; use syntax::struct_span_err; use syntax::symbol::{Symbol, kw}; use syntax::util::lev_distance::find_best_match_for_name; +use syntax_pos::hygiene::MacroKind; use syntax_pos::{BytePos, Span, MultiSpan}; use crate::resolve_imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver}; diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index 2721df4c68763..9c31f89987ed0 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -13,9 +13,9 @@ use rustc::hir::PrimTy; use rustc::session::config::nightly_options; use rustc::util::nodemap::FxHashSet; use syntax::ast::{self, Expr, ExprKind, Ident, NodeId, Path, Ty, TyKind}; -use syntax_expand::base::MacroKind; use syntax::symbol::kw; use syntax::util::lev_distance::find_best_match_for_name; +use syntax_pos::hygiene::MacroKind; use syntax_pos::Span; type Res = def::Res; diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 9239280634724..cea205a823665 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -35,17 +35,18 @@ use rustc::span_bug; use rustc_metadata::creader::CrateLoader; use rustc_metadata::cstore::CStore; -use syntax_expand::hygiene::{ExpnId, Transparency, SyntaxContext}; -use syntax_expand::base::{SyntaxExtension, MacroKind, SpecialDerives}; use syntax::{struct_span_err, unwrap_or}; -use syntax::attr; +use syntax::expand::SpecialDerives; use syntax::ast::{self, Name, NodeId, Ident, FloatTy, IntTy, UintTy}; -use syntax::ast::{ItemKind, Path, CRATE_NODE_ID, Crate}; +use syntax::ast::{CRATE_NODE_ID, Crate}; +use syntax::ast::{ItemKind, Path}; +use syntax::attr; use syntax::print::pprust; use syntax::symbol::{kw, sym}; use syntax::source_map::Spanned; use syntax::visit::{self, Visitor}; - +use syntax_expand::base::SyntaxExtension; +use syntax_pos::hygiene::{MacroKind, ExpnId, Transparency, SyntaxContext}; use syntax_pos::{Span, DUMMY_SP}; use errors::{Applicability, DiagnosticBuilder}; diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 94fe0cc57403e..8b1b6db3ddc23 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -14,20 +14,21 @@ use rustc::{ty, lint, span_bug}; use syntax::ast::{self, NodeId, Ident}; use syntax::attr::StabilityLevel; use syntax::edition::Edition; -use syntax_expand::base::{self, InvocationRes, Indeterminate, SpecialDerives}; -use syntax_expand::base::{MacroKind, SyntaxExtension}; -use syntax_expand::expand::{AstFragment, AstFragmentKind, Invocation, InvocationKind}; -use syntax_expand::hygiene::{self, ExpnId, ExpnData, ExpnKind}; -use syntax_expand::compile_declarative_macro; +use syntax::expand::SpecialDerives; use syntax::feature_gate::{emit_feature_err, is_builtin_attr_name}; use syntax::feature_gate::GateIssue; use syntax::print::pprust; use syntax::symbol::{Symbol, kw, sym}; +use syntax_expand::base::{self, InvocationRes, Indeterminate}; +use syntax_expand::base::SyntaxExtension; +use syntax_expand::expand::{AstFragment, AstFragmentKind, Invocation, InvocationKind}; +use syntax_expand::compile_declarative_macro; +use syntax_pos::hygiene::{self, ExpnId, ExpnData, ExpnKind}; use syntax_pos::{Span, DUMMY_SP}; use std::{mem, ptr}; use rustc_data_structures::sync::Lrc; -use syntax_pos::hygiene::AstPass; +use syntax_pos::hygiene::{MacroKind, AstPass}; type Res = def::Res; diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 31340ddd68372..c95009858e4c0 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -28,10 +28,10 @@ use rustc::util::nodemap::FxHashSet; use rustc::{bug, span_bug}; use syntax::ast::{Ident, Name, NodeId, CRATE_NODE_ID}; -use syntax_expand::hygiene::ExpnId; use syntax::symbol::kw; use syntax::util::lev_distance::find_best_match_for_name; use syntax::{struct_span_err, unwrap_or}; +use syntax_pos::hygiene::ExpnId; use syntax_pos::{MultiSpan, Span}; use log::*; diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index a6a8fec429e20..b3b3750320a95 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -3,8 +3,8 @@ use std::iter::once; use syntax::ast; -use syntax_expand::base::MacroKind; use syntax::symbol::sym; +use syntax_pos::hygiene::MacroKind; use syntax_pos::Span; use rustc::hir; diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index a642491b28181..bdc0206223036 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -28,10 +28,10 @@ use rustc::ty::layout::VariantIdx; use rustc::util::nodemap::{FxHashMap, FxHashSet}; use syntax::ast::{self, Attribute, AttrStyle, AttrItem, Ident}; use syntax::attr; -use syntax_expand::base::MacroKind; use syntax::parse::lexer::comments; use syntax::source_map::DUMMY_SP; -use syntax::symbol::{Symbol, kw, sym}; +use syntax_pos::symbol::{Symbol, kw, sym}; +use syntax_pos::hygiene::MacroKind; use syntax_pos::{self, Pos, FileName}; use std::collections::hash_map::Entry; diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index bbc00147ee14e..002ca6fe983ba 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -4,7 +4,7 @@ pub use self::StructType::*; use syntax::ast; use syntax::ast::Name; -use syntax_expand::base::MacroKind; +use syntax_pos::hygiene::MacroKind; use syntax_pos::{self, Span}; use rustc::hir; diff --git a/src/librustdoc/html/item_type.rs b/src/librustdoc/html/item_type.rs index e015739b03c40..f5e45924893ea 100644 --- a/src/librustdoc/html/item_type.rs +++ b/src/librustdoc/html/item_type.rs @@ -1,7 +1,7 @@ //! Item types. use std::fmt; -use syntax_expand::base::MacroKind; +use syntax_pos::hygiene::MacroKind; use crate::clean; /// Item type. Corresponds to `clean::ItemEnum` variants. diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 414c3137376a9..c4ee84d33f39b 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -49,7 +49,7 @@ use syntax::feature_gate::UnstableFeatures; use syntax::print::pprust; use syntax::source_map::FileName; use syntax::symbol::{Symbol, sym}; -use syntax_expand::base::MacroKind; +use syntax_pos::hygiene::MacroKind; use rustc::hir::def_id::DefId; use rustc::middle::privacy::AccessLevels; use rustc::middle::stability; diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 70c30687dabca..5a83569f02a5c 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -8,9 +8,9 @@ use rustc::middle::privacy::AccessLevel; use rustc::util::nodemap::{FxHashSet, FxHashMap}; use rustc::ty::TyCtxt; use syntax::ast; -use syntax_expand::base::MacroKind; use syntax::source_map::Spanned; use syntax::symbol::sym; +use syntax_pos::hygiene::MacroKind; use syntax_pos::{self, Span}; use std::mem; diff --git a/src/libsyntax_expand/allocator.rs b/src/libsyntax/expand/allocator.rs similarity index 96% rename from src/libsyntax_expand/allocator.rs rename to src/libsyntax/expand/allocator.rs index 3526be17721a8..20487b9af03a6 100644 --- a/src/libsyntax_expand/allocator.rs +++ b/src/libsyntax/expand/allocator.rs @@ -1,5 +1,5 @@ -use syntax::{ast, attr, visit}; -use syntax::symbol::{sym, Symbol}; +use crate::{ast, attr, visit}; +use syntax_pos::symbol::{sym, Symbol}; use syntax_pos::Span; #[derive(Clone, Copy)] diff --git a/src/libsyntax/expand/mod.rs b/src/libsyntax/expand/mod.rs new file mode 100644 index 0000000000000..038f60287befd --- /dev/null +++ b/src/libsyntax/expand/mod.rs @@ -0,0 +1,21 @@ +//! Definitions shared by macros / syntax extensions and e.g. librustc. + +use crate::ast::Attribute; +use syntax_pos::symbol::sym; + +pub mod allocator; + +bitflags::bitflags! { + /// Built-in derives that need some extra tracking beyond the usual macro functionality. + #[derive(Default)] + pub struct SpecialDerives: u8 { + const PARTIAL_EQ = 1 << 0; + const EQ = 1 << 1; + const COPY = 1 << 2; + } +} + +pub fn is_proc_macro_attr(attr: &Attribute) -> bool { + [sym::proc_macro, sym::proc_macro_attribute, sym::proc_macro_derive] + .iter().any(|kind| attr.check_name(*kind)) +} diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index c1114674f14f8..7be6e6c7e1876 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -95,6 +95,7 @@ pub mod json; pub mod ast; pub mod attr; +pub mod expand; pub mod source_map; #[macro_use] pub mod config; pub mod entry; diff --git a/src/libsyntax_expand/base.rs b/src/libsyntax_expand/base.rs index 58edf23a5b1e2..a66263a9a028a 100644 --- a/src/libsyntax_expand/base.rs +++ b/src/libsyntax_expand/base.rs @@ -1,5 +1,4 @@ use crate::expand::{self, AstFragment, Invocation}; -use crate::hygiene::ExpnId; use syntax::ast::{self, NodeId, Attribute, Name, PatKind}; use syntax::attr::{self, HasAttrs, Stability, Deprecation}; @@ -14,11 +13,12 @@ use syntax::symbol::{kw, sym, Ident, Symbol}; use syntax::{ThinVec, MACRO_ARGUMENTS}; use syntax::tokenstream::{self, TokenStream}; use syntax::visit::Visitor; +crate use syntax::expand::SpecialDerives; use errors::{DiagnosticBuilder, DiagnosticId}; use smallvec::{smallvec, SmallVec}; use syntax_pos::{FileName, Span, MultiSpan, DUMMY_SP}; -use syntax_pos::hygiene::{AstPass, ExpnData, ExpnKind}; +use syntax_pos::hygiene::{AstPass, ExpnId, ExpnData, ExpnKind}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::{self, Lrc}; @@ -27,7 +27,7 @@ use std::path::PathBuf; use std::rc::Rc; use std::default::Default; -pub use syntax_pos::hygiene::MacroKind; +crate use syntax_pos::hygiene::MacroKind; #[derive(Debug,Clone)] pub enum Annotatable { @@ -837,16 +837,6 @@ pub enum InvocationRes { /// Error type that denotes indeterminacy. pub struct Indeterminate; -bitflags::bitflags! { - /// Built-in derives that need some extra tracking beyond the usual macro functionality. - #[derive(Default)] - pub struct SpecialDerives: u8 { - const PARTIAL_EQ = 1 << 0; - const EQ = 1 << 1; - const COPY = 1 << 2; - } -} - pub trait Resolver { fn next_node_id(&mut self) -> NodeId; diff --git a/src/libsyntax_expand/lib.rs b/src/libsyntax_expand/lib.rs index db292b619be39..10eb3ecb20bd0 100644 --- a/src/libsyntax_expand/lib.rs +++ b/src/libsyntax_expand/lib.rs @@ -28,9 +28,8 @@ macro_rules! panictry { mod placeholders; mod proc_macro_server; -pub use syntax_pos::hygiene; +crate use syntax_pos::hygiene; pub use mbe::macro_rules::compile_declarative_macro; -pub mod allocator; pub mod base; pub mod build; pub mod expand; diff --git a/src/libsyntax_expand/proc_macro.rs b/src/libsyntax_expand/proc_macro.rs index 8146566549812..bda9478ce96a9 100644 --- a/src/libsyntax_expand/proc_macro.rs +++ b/src/libsyntax_expand/proc_macro.rs @@ -178,11 +178,6 @@ impl<'a> Visitor<'a> for MarkAttrs<'a> { fn visit_mac(&mut self, _mac: &Mac) {} } -pub fn is_proc_macro_attr(attr: &Attribute) -> bool { - [sym::proc_macro, sym::proc_macro_attribute, sym::proc_macro_derive] - .iter().any(|kind| attr.check_name(*kind)) -} - crate fn collect_derives(cx: &mut ExtCtxt<'_>, attrs: &mut Vec) -> Vec { let mut result = Vec::new(); attrs.retain(|attr| { diff --git a/src/libsyntax_ext/deriving/clone.rs b/src/libsyntax_ext/deriving/clone.rs index 67ef69babdc0a..061afa379c6e3 100644 --- a/src/libsyntax_ext/deriving/clone.rs +++ b/src/libsyntax_ext/deriving/clone.rs @@ -3,7 +3,8 @@ use crate::deriving::generic::*; use crate::deriving::generic::ty::*; use syntax::ast::{self, Expr, GenericArg, Generics, ItemKind, MetaItem, VariantData}; -use syntax_expand::base::{Annotatable, ExtCtxt, SpecialDerives}; +use syntax::expand::SpecialDerives; +use syntax_expand::base::{Annotatable, ExtCtxt}; use syntax::ptr::P; use syntax::symbol::{kw, sym, Symbol}; use syntax_pos::Span; diff --git a/src/libsyntax_ext/deriving/cmp/eq.rs b/src/libsyntax_ext/deriving/cmp/eq.rs index 162aaedafea32..eddf8eea1db32 100644 --- a/src/libsyntax_ext/deriving/cmp/eq.rs +++ b/src/libsyntax_ext/deriving/cmp/eq.rs @@ -3,9 +3,10 @@ use crate::deriving::generic::*; use crate::deriving::generic::ty::*; use syntax::ast::{self, Ident, Expr, MetaItem, GenericArg}; -use syntax_expand::base::{Annotatable, ExtCtxt, SpecialDerives}; +use syntax::expand::SpecialDerives; use syntax::ptr::P; use syntax::symbol::{sym, Symbol}; +use syntax_expand::base::{Annotatable, ExtCtxt}; use syntax_pos::Span; pub fn expand_deriving_eq(cx: &mut ExtCtxt<'_>, diff --git a/src/libsyntax_ext/deriving/cmp/partial_eq.rs b/src/libsyntax_ext/deriving/cmp/partial_eq.rs index c3e2b78bbe506..2e2be91de8a46 100644 --- a/src/libsyntax_ext/deriving/cmp/partial_eq.rs +++ b/src/libsyntax_ext/deriving/cmp/partial_eq.rs @@ -3,10 +3,11 @@ use crate::deriving::generic::*; use crate::deriving::generic::ty::*; use syntax::ast::{BinOpKind, Expr, MetaItem}; -use syntax_expand::base::{Annotatable, ExtCtxt, SpecialDerives}; +use syntax::expand::SpecialDerives; use syntax::ptr::P; use syntax::symbol::sym; -use syntax_pos::{self, Span}; +use syntax_expand::base::{Annotatable, ExtCtxt}; +use syntax_pos::Span; pub fn expand_deriving_partial_eq(cx: &mut ExtCtxt<'_>, span: Span, diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 216338c1a8861..c04b65245e1f7 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -186,13 +186,14 @@ use rustc_target::spec::abi::Abi; use syntax::ast::{self, BinOpKind, EnumDef, Expr, Generics, Ident, PatKind}; use syntax::ast::{VariantData, GenericParamKind, GenericArg}; use syntax::attr; +use syntax::expand::SpecialDerives; use syntax::source_map::respan; use syntax::util::map_in_place::MapInPlace; use syntax::ptr::P; use syntax::sess::ParseSess; use syntax::symbol::{Symbol, kw, sym}; -use syntax_expand::base::{Annotatable, ExtCtxt, SpecialDerives}; -use syntax_pos::{Span}; +use syntax_expand::base::{Annotatable, ExtCtxt}; +use syntax_pos::Span; use ty::{LifetimeBounds, Path, Ptr, PtrTy, Self_, Ty}; diff --git a/src/libsyntax_ext/global_allocator.rs b/src/libsyntax_ext/global_allocator.rs index 75dda9535b333..90d2ea38bc336 100644 --- a/src/libsyntax_ext/global_allocator.rs +++ b/src/libsyntax_ext/global_allocator.rs @@ -2,10 +2,10 @@ use crate::util::check_builtin_macro_attribute; use syntax::ast::{ItemKind, Mutability, Stmt, Ty, TyKind, Unsafety}; use syntax::ast::{self, Param, Attribute, Expr, FnHeader, Generics, Ident}; -use syntax_expand::allocator::{AllocatorKind, AllocatorMethod, AllocatorTy, ALLOCATOR_METHODS}; -use syntax_expand::base::{Annotatable, ExtCtxt}; +use syntax::expand::allocator::{AllocatorKind, AllocatorMethod, AllocatorTy, ALLOCATOR_METHODS}; use syntax::ptr::P; use syntax::symbol::{kw, sym, Symbol}; +use syntax_expand::base::{Annotatable, ExtCtxt}; use syntax_pos::Span; pub fn expand( diff --git a/src/libsyntax_ext/proc_macro_harness.rs b/src/libsyntax_ext/proc_macro_harness.rs index c874f1ffb1175..fc4a7a0a0fe47 100644 --- a/src/libsyntax_ext/proc_macro_harness.rs +++ b/src/libsyntax_ext/proc_macro_harness.rs @@ -3,6 +3,7 @@ use std::mem; use smallvec::smallvec; use syntax::ast::{self, Ident}; use syntax::attr; +use syntax::expand::is_proc_macro_attr; use syntax::print::pprust; use syntax::ptr::P; use syntax::sess::ParseSess; @@ -10,7 +11,6 @@ use syntax::symbol::{kw, sym}; use syntax::visit::{self, Visitor}; use syntax_expand::base::{ExtCtxt, Resolver}; use syntax_expand::expand::{AstFragment, ExpansionConfig}; -use syntax_expand::proc_macro::is_proc_macro_attr; use syntax_pos::{Span, DUMMY_SP}; use syntax_pos::hygiene::AstPass; diff --git a/src/libsyntax_ext/standard_library_imports.rs b/src/libsyntax_ext/standard_library_imports.rs index fd27a21890698..6514ff5e25268 100644 --- a/src/libsyntax_ext/standard_library_imports.rs +++ b/src/libsyntax_ext/standard_library_imports.rs @@ -4,9 +4,9 @@ use syntax::ptr::P; use syntax::sess::ParseSess; use syntax::symbol::{Ident, Symbol, kw, sym}; use syntax_expand::expand::ExpansionConfig; -use syntax_expand::hygiene::AstPass; use syntax_expand::base::{ExtCtxt, Resolver}; use syntax_pos::DUMMY_SP; +use syntax_pos::hygiene::AstPass; pub fn inject( mut krate: ast::Crate, From 993b920032b17def5c773ed78b09890abb95854e Mon Sep 17 00:00:00 2001 From: Igor Aleksanov Date: Sat, 26 Oct 2019 19:12:58 +0300 Subject: [PATCH 04/10] librustc_lexer: Enhance documentation Apply review suggestions Apply review suggestions --- src/librustc_lexer/src/cursor.rs | 19 +++- src/librustc_lexer/src/lib.rs | 156 +++++++++++++++++++++++++++-- src/librustc_lexer/src/unescape.rs | 74 +++++++++++--- 3 files changed, 225 insertions(+), 24 deletions(-) diff --git a/src/librustc_lexer/src/cursor.rs b/src/librustc_lexer/src/cursor.rs index 5831159c344d7..73d305c6d4fe2 100644 --- a/src/librustc_lexer/src/cursor.rs +++ b/src/librustc_lexer/src/cursor.rs @@ -1,5 +1,9 @@ use std::str::Chars; +/// Peekable iterator over a char sequence. +/// +/// Next characters can be peeked via `nth_char` method, +/// and position can be shifted forward via `bump` method. pub(crate) struct Cursor<'a> { initial_len: usize, chars: Chars<'a>, @@ -18,7 +22,9 @@ impl<'a> Cursor<'a> { prev: EOF_CHAR, } } + /// For debug assertions only + /// Returns the last eaten symbol (or '\0' in release builds). pub(crate) fn prev(&self) -> char { #[cfg(debug_assertions)] { @@ -30,19 +36,30 @@ impl<'a> Cursor<'a> { '\0' } } + + /// Returns nth character relative to the current cursor position. + /// If requested position doesn't exist, `EOF_CHAR` is returned. + /// However, getting `EOF_CHAR` doesn't always mean actual end of file, + /// it should be checked with `is_eof` method. pub(crate) fn nth_char(&self, n: usize) -> char { self.chars().nth(n).unwrap_or(EOF_CHAR) } + + /// Checks if there is nothing more to consume. pub(crate) fn is_eof(&self) -> bool { self.chars.as_str().is_empty() } + + /// Returns amount of already consumed symbols. pub(crate) fn len_consumed(&self) -> usize { self.initial_len - self.chars.as_str().len() } - /// Returns an iterator over the remaining characters. + + /// Returns a `Chars` iterator over the remaining characters. fn chars(&self) -> Chars<'a> { self.chars.clone() } + /// Moves to the next character. pub(crate) fn bump(&mut self) -> Option { let c = self.chars.next()?; diff --git a/src/librustc_lexer/src/lib.rs b/src/librustc_lexer/src/lib.rs index 30a5175d8cdb0..d55ef46d7506e 100644 --- a/src/librustc_lexer/src/lib.rs +++ b/src/librustc_lexer/src/lib.rs @@ -1,3 +1,16 @@ +//! Low-level Rust lexer. +//! +//! Tokens produced by this lexer are not yet ready for parsing the Rust syntax, +//! for that see `libsyntax::parse::lexer`, which converts this basic token stream +//! into wide tokens used by actual parser. +//! +//! The purpose of this crate is to convert raw sources into a labeled sequence +//! of well-known token types, so building an actual Rust token stream will +//! be easier. +//! +//! Main entity of this crate is [`TokenKind`] enum which represents common +//! lexeme types. + // We want to be able to build this crate with a stable compiler, so no // `#![feature]` attributes should be added. @@ -6,78 +19,144 @@ pub mod unescape; use crate::cursor::{Cursor, EOF_CHAR}; +/// Parsed token. +/// It doesn't contain information about data that has been parsed, +/// only the type of the token and its size. pub struct Token { pub kind: TokenKind, pub len: usize, } +impl Token { + fn new(kind: TokenKind, len: usize) -> Token { + Token { kind, len } + } +} + +/// Enum represening common lexeme types. #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum TokenKind { + // Multi-char tokens: + + /// "// comment" LineComment, + /// "/* block comment */" + /// Block comments can be recursive, so the sequence like "/* /* */" + /// will not be considered terminated and will result in a parsing error. BlockComment { terminated: bool }, + /// Any whitespace characters sequence. Whitespace, + /// "ident" or "continue" + /// At this step keywords are also considered identifiers. Ident, + /// "r#ident" RawIdent, + /// "12_u8", "1.0e-40", "b"123"". See `LiteralKind` for more details. Literal { kind: LiteralKind, suffix_start: usize }, + /// "'a" Lifetime { starts_with_number: bool }, + + // One-char tokens: + + /// ";" Semi, + /// "," Comma, + /// "." Dot, + /// "(" OpenParen, + /// ")" CloseParen, + /// "{" OpenBrace, + /// "}" CloseBrace, + /// "[" OpenBracket, + /// "]" CloseBracket, + /// "@" At, + /// "#" Pound, + /// "~" Tilde, + /// "?" Question, + /// ":" Colon, + /// "$" Dollar, + /// "=" Eq, + /// "!" Not, + /// "<" Lt, + /// ">" Gt, + /// "-" Minus, + /// "&" And, + /// "|" Or, + /// "+" Plus, + /// "*" Star, + /// "/" Slash, + /// "^" Caret, + /// "%" Percent, + + /// Unknown token, not expected by the lexer, e.g. "№" Unknown, } use self::TokenKind::*; #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum LiteralKind { + /// "12_u8", "0o100", "0b120i99" Int { base: Base, empty_int: bool }, + /// "12.34f32", "0b100.100" Float { base: Base, empty_exponent: bool }, + /// "'a'", "'\\'", "'''", "';" Char { terminated: bool }, + /// "b'a'", "b'\\'", "b'''", "b';" Byte { terminated: bool }, + /// ""abc"", ""abc" Str { terminated: bool }, + /// "b"abc"", "b"abc" ByteStr { terminated: bool }, + /// "r"abc"", "r#"abc"#", "r####"ab"###"c"####", "r#"a" RawStr { n_hashes: usize, started: bool, terminated: bool }, + /// "br"abc"", "br#"abc"#", "br####"ab"###"c"####", "br#"a" RawByteStr { n_hashes: usize, started: bool, terminated: bool }, } use self::LiteralKind::*; +/// Base of numeric literal encoding according to its prefix. #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum Base { + /// Literal starts with "0b". Binary, + /// Literal starts with "0o". Octal, + /// Literal starts with "0x". Hexadecimal, + /// Literal doesn't contain a prefix. Decimal, } -impl Token { - fn new(kind: TokenKind, len: usize) -> Token { - Token { kind, len } - } -} - +/// `rustc` allows files to have a shebang, e.g. "#!/usr/bin/rustrun", +/// but shebang isn't a part of rust syntax, so this function +/// skips the line if it starts with a shebang ("#!"). +/// Line won't be skipped if it represents a valid Rust syntax +/// (e.g. "#![deny(missing_docs)]"). pub fn strip_shebang(input: &str) -> Option { debug_assert!(!input.is_empty()); if !input.starts_with("#!") || input.starts_with("#![") { @@ -86,11 +165,13 @@ pub fn strip_shebang(input: &str) -> Option { Some(input.find('\n').unwrap_or(input.len())) } +/// Parses the first token from the provided input string. pub fn first_token(input: &str) -> Token { debug_assert!(!input.is_empty()); Cursor::new(input).advance_token() } +/// Creates an iterator that produces tokens from the input string. pub fn tokenize(mut input: &str) -> impl Iterator + '_ { std::iter::from_fn(move || { if input.is_empty() { @@ -102,10 +183,9 @@ pub fn tokenize(mut input: &str) -> impl Iterator + '_ { }) } -// See [UAX #31](http://unicode.org/reports/tr31) for definitions of these -// classes. - /// True if `c` is considered a whitespace according to Rust language definition. +/// See [Rust language reference](https://doc.rust-lang.org/reference/whitespace.html) +/// for definitions of these classes. pub fn is_whitespace(c: char) -> bool { // This is Pattern_White_Space. // @@ -137,6 +217,8 @@ pub fn is_whitespace(c: char) -> bool { } /// True if `c` is valid as a first character of an identifier. +/// See [Rust language reference](https://doc.rust-lang.org/reference/identifiers.html) for +/// a formal definition of valid identifier name. pub fn is_id_start(c: char) -> bool { // This is XID_Start OR '_' (which formally is not a XID_Start). // We also add fast-path for ascii idents @@ -147,6 +229,8 @@ pub fn is_id_start(c: char) -> bool { } /// True if `c` is valid as a non-first character of an identifier. +/// See [Rust language reference](https://doc.rust-lang.org/reference/identifiers.html) for +/// a formal definition of valid identifier name. pub fn is_id_continue(c: char) -> bool { // This is exactly XID_Continue. // We also add fast-path for ascii idents @@ -159,15 +243,21 @@ pub fn is_id_continue(c: char) -> bool { impl Cursor<'_> { + /// Parses a token from the input string. fn advance_token(&mut self) -> Token { let first_char = self.bump().unwrap(); let token_kind = match first_char { + // Slash, comment or block comment. '/' => match self.nth_char(0) { '/' => self.line_comment(), '*' => self.block_comment(), _ => Slash, }, + + // Whitespace sequence. c if is_whitespace(c) => self.whitespace(), + + // Raw string literal or identifier. 'r' => match (self.nth_char(0), self.nth_char(1)) { ('#', c1) if is_id_start(c1) => self.raw_ident(), ('#', _) | ('"', _) => { @@ -181,6 +271,8 @@ impl Cursor<'_> { } _ => self.ident(), }, + + // Byte literal, byte string literal, raw byte string literal or identifier. 'b' => match (self.nth_char(0), self.nth_char(1)) { ('\'', _) => { self.bump(); @@ -214,13 +306,20 @@ impl Cursor<'_> { } _ => self.ident(), }, + + // Identifier (this should be checked after other variant that can + // start as identifier). c if is_id_start(c) => self.ident(), + + // Numeric literal. c @ '0'..='9' => { let literal_kind = self.number(c); let suffix_start = self.len_consumed(); self.eat_literal_suffix(); TokenKind::Literal { kind: literal_kind, suffix_start } } + + // One-symbol tokens. ';' => Semi, ',' => Comma, '.' => Dot, @@ -247,7 +346,11 @@ impl Cursor<'_> { '*' => Star, '^' => Caret, '%' => Percent, + + // Lifetime or character literal. '\'' => self.lifetime_or_char(), + + // String literal. '"' => { let terminated = self.double_quoted_string(); let suffix_start = self.len_consumed(); @@ -291,6 +394,9 @@ impl Cursor<'_> { self.bump(); depth -= 1; if depth == 0 { + // This block comment is closed, so for a construction like "/* */ */" + // there will be a successfully parsed block comment "/* */" + // and " */" will be processed separately. break; } } @@ -335,6 +441,7 @@ impl Cursor<'_> { debug_assert!('0' <= self.prev() && self.prev() <= '9'); let mut base = Base::Decimal; if first_digit == '0' { + // Attempt to parse encoding base. let has_digits = match self.nth_char(0) { 'b' => { base = Base::Binary; @@ -351,17 +458,21 @@ impl Cursor<'_> { self.bump(); self.eat_hexadecimal_digits() } + // Not a base prefix. '0'..='9' | '_' | '.' | 'e' | 'E' => { self.eat_decimal_digits(); true } - // just a 0 + // Just a 0. _ => return Int { base, empty_int: false }, }; + // Base prefix was provided, but there were no digits + // after it, e.g. "0x". if !has_digits { return Int { base, empty_int: true }; } } else { + // No base prefix, parse number in the usual way. self.eat_decimal_digits(); }; @@ -400,6 +511,9 @@ impl Cursor<'_> { fn lifetime_or_char(&mut self) -> TokenKind { debug_assert!(self.prev() == '\''); let mut starts_with_number = false; + + // Check if the first symbol after '\'' is a valid identifier + // character or a number (not a digit followed by '\''). if (is_id_start(self.nth_char(0)) || self.nth_char(0).is_digit(10) && { starts_with_number = true; @@ -408,6 +522,8 @@ impl Cursor<'_> { && self.nth_char(1) != '\'' { self.bump(); + + // Skip the identifier. while is_id_continue(self.nth_char(0)) { self.bump(); } @@ -420,6 +536,8 @@ impl Cursor<'_> { Lifetime { starts_with_number } }; } + + // This is not a lifetime (checked above), parse a char literal. let terminated = self.single_quoted_string(); let suffix_start = self.len_consumed(); if terminated { @@ -431,24 +549,32 @@ impl Cursor<'_> { fn single_quoted_string(&mut self) -> bool { debug_assert!(self.prev() == '\''); - // parse `'''` as a single char literal + // Parse `'''` as a single char literal. if self.nth_char(0) == '\'' && self.nth_char(1) == '\'' { self.bump(); } + // Parse until either quotes are terminated or error is detected. let mut first = true; loop { match self.nth_char(0) { + // Probably beginning of the comment, which we don't want to include + // to the error report. '/' if !first => break, + // Newline without following '\'' means unclosed quote, stop parsing. '\n' if self.nth_char(1) != '\'' => break, + // End of file, stop parsing. EOF_CHAR if self.is_eof() => break, + // Quotes are terminated, finish parsing. '\'' => { self.bump(); return true; } + // Escaped slash is considered one character, so bump twice. '\\' => { self.bump(); self.bump(); } + // Skip the character. _ => { self.bump(); } @@ -458,6 +584,8 @@ impl Cursor<'_> { false } + /// Eats double-quoted string and returns true + /// if string is terminated. fn double_quoted_string(&mut self) -> bool { debug_assert!(self.prev() == '"'); loop { @@ -476,8 +604,11 @@ impl Cursor<'_> { } } + /// Eats the double-quoted string and returns a tuple of + /// (amount of the '#' symbols, raw string started, raw string terminated) fn raw_double_quoted_string(&mut self) -> (usize, bool, bool) { debug_assert!(self.prev() == 'r'); + // Count opening '#' symbols. let n_hashes = { let mut acc: usize = 0; loop { @@ -489,6 +620,8 @@ impl Cursor<'_> { } }; + // Skip the string itself and check that amount of closing '#' + // symbols is equal to the amount of opening ones. loop { match self.bump() { Some('"') => { @@ -549,6 +682,7 @@ impl Cursor<'_> { if self.eat_decimal_digits() { Ok(()) } else { Err(()) } } + // Eats the suffix if it's an identifier. fn eat_literal_suffix(&mut self) { if !is_id_start(self.nth_char(0)) { return; diff --git a/src/librustc_lexer/src/unescape.rs b/src/librustc_lexer/src/unescape.rs index c709b7526082f..dee7bc2260bf0 100644 --- a/src/librustc_lexer/src/unescape.rs +++ b/src/librustc_lexer/src/unescape.rs @@ -7,32 +7,54 @@ use std::ops::Range; #[cfg(test)] mod tests; +/// Errors that can occur during string unescaping. #[derive(Debug, PartialEq, Eq)] pub enum EscapeError { + /// Expected 1 char, but 0 were found. ZeroChars, + /// Expected 1 char, but more than 1 were found. MoreThanOneChar, + /// Escaped '\' character without continuation. LoneSlash, + /// Invalid escape characted (e.g. '\z'). InvalidEscape, + /// Raw '\r' encountered. BareCarriageReturn, + /// Raw '\r' encountered in raw string. BareCarriageReturnInRawString, + /// Unescaped character that was expected to be escaped (e.g. raw '\t'). EscapeOnlyChar, + /// Numeric character escape is too short (e.g. '\x1'). TooShortHexEscape, + /// Invalid character in numeric escape (e.g. '\xz') InvalidCharInHexEscape, + /// Character code in numeric escape is non-ascii (e.g. '\xFF'). OutOfRangeHexEscape, + /// '\u' not followed by '{'. NoBraceInUnicodeEscape, + /// Non-hexadecimal value in '\u{..}'. InvalidCharInUnicodeEscape, + /// '\u{}' EmptyUnicodeEscape, + /// No closing brace in '\u{..}', e.g. '\u{12'. UnclosedUnicodeEscape, + /// '\u{_12}' LeadingUnderscoreUnicodeEscape, + /// More than 6 charactes in '\u{..}', e.g. '\u{10FFFF_FF}' OverlongUnicodeEscape, + /// Invalid in-bound unicode character code, e.g. '\u{DFFF}'. LoneSurrogateUnicodeEscape, + /// Out of bounds unicode character code, e.g. '\u{FFFFFF}'. OutOfRangeUnicodeEscape, + /// Unicode escape code in byte literal. UnicodeEscapeInByte, + /// Non-ascii character in byte literal. NonAsciiCharInByte, + /// Non-ascii character in byte string literal. NonAsciiCharInByteString, } @@ -44,15 +66,8 @@ pub fn unescape_char(literal_text: &str) -> Result { .map_err(|err| (literal_text.len() - chars.as_str().len(), err)) } -/// Takes a contents of a string literal (without quotes) and produces a -/// sequence of escaped characters or errors. -pub fn unescape_str(literal_text: &str, callback: &mut F) -where - F: FnMut(Range, Result), -{ - unescape_str_or_byte_str(literal_text, Mode::Str, callback) -} - +/// Takes a contents of a byte literal (without quotes), and returns an +/// unescaped byte or an error. pub fn unescape_byte(literal_text: &str) -> Result { let mut chars = literal_text.chars(); unescape_char_or_byte(&mut chars, Mode::Byte) @@ -62,6 +77,17 @@ pub fn unescape_byte(literal_text: &str) -> Result { /// Takes a contents of a string literal (without quotes) and produces a /// sequence of escaped characters or errors. +/// Values are returned through invoking of the provided callback. +pub fn unescape_str(literal_text: &str, callback: &mut F) +where + F: FnMut(Range, Result), +{ + unescape_str_or_byte_str(literal_text, Mode::Str, callback) +} + +/// Takes a contents of a byte string literal (without quotes) and produces a +/// sequence of bytes or errors. +/// Values are returned through invoking of the provided callback. pub fn unescape_byte_str(literal_text: &str, callback: &mut F) where F: FnMut(Range, Result), @@ -71,8 +97,9 @@ where }) } -/// Takes a contents of a string literal (without quotes) and produces a +/// Takes a contents of a raw string literal (without quotes) and produces a /// sequence of characters or errors. +/// Values are returned through invoking of the provided callback. /// NOTE: Raw strings do not perform any explicit character escaping, here we /// only translate CRLF to LF and produce errors on bare CR. pub fn unescape_raw_str(literal_text: &str, callback: &mut F) @@ -82,8 +109,9 @@ where unescape_raw_str_or_byte_str(literal_text, Mode::Str, callback) } -/// Takes a contents of a string literal (without quotes) and produces a -/// sequence of characters or errors. +/// Takes a contents of a raw byte string literal (without quotes) and produces a +/// sequence of bytes or errors. +/// Values are returned through invoking of the provided callback. /// NOTE: Raw strings do not perform any explicit character escaping, here we /// only translate CRLF to LF and produce errors on bare CR. pub fn unescape_raw_byte_str(literal_text: &str, callback: &mut F) @@ -95,6 +123,7 @@ where }) } +/// What kind of literal do we parse. #[derive(Debug, Clone, Copy)] pub enum Mode { Char, @@ -126,6 +155,8 @@ impl Mode { fn scan_escape(first_char: char, chars: &mut Chars<'_>, mode: Mode) -> Result { if first_char != '\\' { + // Previous character was not a slash, and we don't expect it to be + // an escape-only character. return match first_char { '\t' | '\n' => Err(EscapeError::EscapeOnlyChar), '\r' => Err(EscapeError::BareCarriageReturn), @@ -133,6 +164,7 @@ fn scan_escape(first_char: char, chars: &mut Chars<'_>, mode: Mode) -> Result Err(EscapeError::EscapeOnlyChar), _ => { if mode.is_bytes() && !first_char.is_ascii() { + // Byte literal can't be a non-ascii character. return Err(EscapeError::NonAsciiCharInByte); } Ok(first_char) @@ -140,6 +172,8 @@ fn scan_escape(first_char: char, chars: &mut Chars<'_>, mode: Mode) -> Result, mode: Mode) -> Result '\0', 'x' => { + // Parse hexadecimal character code. + let hi = chars.next().ok_or(EscapeError::TooShortHexEscape)?; let hi = hi.to_digit(16).ok_or(EscapeError::InvalidCharInHexEscape)?; @@ -160,6 +196,7 @@ fn scan_escape(first_char: char, chars: &mut Chars<'_>, mode: Mode) -> Result, mode: Mode) -> Result { + // We've parsed '\u', now we have to parse '{..}'. + if chars.next() != Some('{') { return Err(EscapeError::NoBraceInUnicodeEscape); } + // First characrer must be a hexadecimal digit. let mut n_digits = 1; let mut value: u32 = match chars.next().ok_or(EscapeError::UnclosedUnicodeEscape)? { '_' => return Err(EscapeError::LeadingUnderscoreUnicodeEscape), @@ -180,6 +220,8 @@ fn scan_escape(first_char: char, chars: &mut Chars<'_>, mode: Mode) -> Result c.to_digit(16).ok_or(EscapeError::InvalidCharInUnicodeEscape)?, }; + // First character is valid, now parse the rest of the number + // and closing brace. loop { match chars.next() { None => return Err(EscapeError::UnclosedUnicodeEscape), @@ -188,6 +230,9 @@ fn scan_escape(first_char: char, chars: &mut Chars<'_>, mode: Mode) -> Result 6 { return Err(EscapeError::OverlongUnicodeEscape); } + + // Incorrect syntax has higher priority for error reporting + // than unallowed value for a literal. if mode.is_bytes() { return Err(EscapeError::UnicodeEscapeInByte); } @@ -204,6 +249,7 @@ fn scan_escape(first_char: char, chars: &mut Chars<'_>, mode: Mode) -> Result 6 { + // Stop updating value since we're sure that it's is incorrect already. continue; } let digit = digit as u32; @@ -243,6 +289,10 @@ where let second_char = chars.clone().next(); match second_char { Some('\n') => { + // Rust language specification requires us to skip whitespaces + // if unescaped '\' character is followed by '\n'. + // For details see [Rust language reference] + // (https://doc.rust-lang.org/reference/tokens.html#string-literals). skip_ascii_whitespace(&mut chars); continue; } From 3f980785fb55e31aca9215faa474d751e5a28d69 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Sun, 27 Oct 2019 17:31:01 +0000 Subject: [PATCH 05/10] doc: explain why it is unsafe to construct Vec from Vec Co-authored-by: Steve Klabnik --- src/liballoc/vec.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 641f9eafa8d23..5e733fa43d705 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -411,7 +411,11 @@ impl Vec { /// /// Violating these may cause problems like corrupting the allocator's /// internal data structures. For example it is **not** safe - /// to build a `Vec` from a pointer to a C `char` array and a `size_t`. + /// to build a `Vec` from a pointer to a C `char` array with length `size_t`. + /// It's also not safe to build one from a `Vec` and its length, because + /// the allocator cares about the alignment, and these two types have different + /// alignments. The buffer was allocated with alignment 2 (for `u16`), but after + /// turning it into a `Vec` it'll be deallocated with alignment 1. /// /// The ownership of `ptr` is effectively transferred to the /// `Vec` which may then deallocate, reallocate or change the From 743964ad3fe566ca2ce5c2de14f8733887d283fd Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Wed, 9 Oct 2019 08:25:41 -0700 Subject: [PATCH 06/10] Implement core::intrinsics::caller_location. Returns a `&core::panic::Location` corresponding to where it was called, also making `Location` a lang item. --- src/libcore/intrinsics.rs | 4 ++++ src/libcore/panic.rs | 1 + src/librustc/middle/lang_items.rs | 1 + src/librustc_codegen_llvm/builder.rs | 15 ++++++++++++ src/librustc_codegen_llvm/common.rs | 7 ++++++ src/librustc_codegen_ssa/mir/block.rs | 16 +++++++++++++ src/librustc_codegen_ssa/traits/consts.rs | 2 ++ src/librustc_codegen_ssa/traits/statics.rs | 2 ++ src/librustc_mir/const_eval.rs | 23 +++++++++++++++++++ src/librustc_typeck/check/intrinsic.rs | 18 ++++++++++++--- .../caller-location-intrinsic.rs | 9 ++++++++ 11 files changed, 95 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/rfc-2091-track-caller/caller-location-intrinsic.rs diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 4655d39fb8f1f..4e0f18b88fe0a 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -696,6 +696,10 @@ extern "rust-intrinsic" { /// This will statically either panic, or do nothing. pub fn panic_if_uninhabited(); + /// Gets a reference to a static `Location` indicating where it was called. + #[cfg(not(bootstrap))] + pub fn caller_location() -> &'static crate::panic::Location<'static>; + /// Creates a value initialized to zero. /// /// `init` is unsafe because it returns a zeroed-out datum, diff --git a/src/libcore/panic.rs b/src/libcore/panic.rs index 989fc96732a5a..9428ff3ef15c4 100644 --- a/src/libcore/panic.rs +++ b/src/libcore/panic.rs @@ -162,6 +162,7 @@ impl fmt::Display for PanicInfo<'_> { /// /// panic!("Normal panic"); /// ``` +#[cfg_attr(not(bootstrap), lang = "panic_location")] #[derive(Debug)] #[stable(feature = "panic_hooks", since = "1.10.0")] pub struct Location<'a> { diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index cab929389d6a4..a17b5a115b86b 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -366,6 +366,7 @@ language_item_table! { PanicFnLangItem, "panic", panic_fn, Target::Fn; PanicBoundsCheckFnLangItem, "panic_bounds_check", panic_bounds_check_fn, Target::Fn; PanicInfoLangItem, "panic_info", panic_info, Target::Struct; + PanicLocationLangItem, "panic_location", panic_location, Target::Struct; PanicImplLangItem, "panic_impl", panic_impl, Target::Fn; // Libstd panic entry point. Necessary for const eval to be able to catch it BeginPanicFnLangItem, "begin_panic", begin_panic_fn, Target::Fn; diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index 98be0ae44335f..ffaf8050bcbb2 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -2,6 +2,7 @@ use crate::llvm::{AtomicRmwBinOp, AtomicOrdering, SynchronizationScope}; use crate::llvm::{self, False, BasicBlock}; use crate::common::Funclet; use crate::context::CodegenCx; +use crate::syntax_pos::Pos; use crate::type_::Type; use crate::type_of::LayoutLlvmExt; use crate::value::Value; @@ -1068,6 +1069,20 @@ impl StaticBuilderMethods for Builder<'a, 'll, 'tcx> { self.cx().get_static(def_id) } + fn static_panic_location(&mut self, loc: &syntax::source_map::Loc) -> Self::Value { + let filename = Symbol::intern(&loc.file.name.to_string()); + let filename = self.const_str(filename); + let line = self.const_u32(loc.line as u32); + let col = self.const_u32(loc.col.to_usize() as u32 + 1); + let struct_ = self.const_struct(&[filename.0, filename.1, line, col], false); + + let align = self.tcx.data_layout.aggregate_align.abi + .max(self.tcx.data_layout.i32_align.abi) + .max(self.tcx.data_layout.pointer_align.abi); + // FIXME(eddyb) move this into miri, it can be correct if e.g. field order changes + self.static_addr_of(struct_, align, Some("panic_loc")) + } + fn static_panic_msg( &mut self, msg: Option, diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs index a1a5232d58832..b4b82f67c74b3 100644 --- a/src/librustc_codegen_llvm/common.rs +++ b/src/librustc_codegen_llvm/common.rs @@ -237,6 +237,13 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { unsafe { llvm::LLVMConstReal(t, val) } } + fn const_str(&self, s: Symbol) -> (&'ll Value, &'ll Value) { + let len = s.as_str().len(); + let cs = consts::ptrcast(self.const_cstr(s, false), + self.type_ptr_to(self.layout_of(self.tcx.mk_str()).llvm_type(self))); + (cs, self.const_usize(len as u64)) + } + fn const_struct( &self, elts: &[&'ll Value], diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 28441cae26e3f..22ea6a3955216 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -613,6 +613,22 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ReturnDest::Nothing }; + if intrinsic == Some("caller_location") { + if let Some((_, target)) = destination.as_ref() { + let loc = bx.sess().source_map().lookup_char_pos(span.lo()); + let location = bx.static_panic_location(&loc); + + if let ReturnDest::IndirectOperand(tmp, _) = ret_dest { + Immediate(location).store(&mut bx, tmp); + } + self.store_return(&mut bx, ret_dest, &fn_ty.ret, location); + + helper.maybe_sideeffect(self.mir, &mut bx, &[*target]); + helper.funclet_br(self, &mut bx, *target); + } + return; + } + if intrinsic.is_some() && intrinsic != Some("drop_in_place") { let dest = match ret_dest { _ if fn_ty.ret.is_indirect() => llargs[0], diff --git a/src/librustc_codegen_ssa/traits/consts.rs b/src/librustc_codegen_ssa/traits/consts.rs index 95ada60fae08d..8c462e77d5e05 100644 --- a/src/librustc_codegen_ssa/traits/consts.rs +++ b/src/librustc_codegen_ssa/traits/consts.rs @@ -3,6 +3,7 @@ use crate::mir::place::PlaceRef; use rustc::mir::interpret::Allocation; use rustc::mir::interpret::Scalar; use rustc::ty::layout; +use syntax_pos::Symbol; pub trait ConstMethods<'tcx>: BackendTypes { // Constant constructors @@ -19,6 +20,7 @@ pub trait ConstMethods<'tcx>: BackendTypes { fn const_u8(&self, i: u8) -> Self::Value; fn const_real(&self, t: Self::Type, val: f64) -> Self::Value; + fn const_str(&self, s: Symbol) -> (Self::Value, Self::Value); fn const_struct(&self, elts: &[Self::Value], packed: bool) -> Self::Value; fn const_to_opt_uint(&self, v: Self::Value) -> Option; diff --git a/src/librustc_codegen_ssa/traits/statics.rs b/src/librustc_codegen_ssa/traits/statics.rs index 73c4c05397917..b51f15b5823e2 100644 --- a/src/librustc_codegen_ssa/traits/statics.rs +++ b/src/librustc_codegen_ssa/traits/statics.rs @@ -1,4 +1,5 @@ use super::BackendTypes; +use syntax::source_map::Loc; use syntax_pos::symbol::Symbol; use rustc::hir::def_id::DefId; use rustc::ty::layout::Align; @@ -10,6 +11,7 @@ pub trait StaticMethods: BackendTypes { pub trait StaticBuilderMethods: BackendTypes { fn get_static(&mut self, def_id: DefId) -> Self::Value; + fn static_panic_location(&mut self, loc: &Loc) -> Self::Value; fn static_panic_msg( &mut self, msg: Option, diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index bb02b99dd8d87..eeaa3c6792d3c 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -9,6 +9,7 @@ use std::convert::TryInto; use rustc::hir::def::DefKind; use rustc::hir::def_id::DefId; +use rustc::middle::lang_items::PanicLocationLangItem; use rustc::mir::interpret::{ConstEvalErr, ErrorHandled, ScalarMaybeUndef}; use rustc::mir; use rustc::ty::{self, Ty, TyCtxt, subst::Subst}; @@ -505,6 +506,28 @@ pub fn const_field<'tcx>( op_to_const(&ecx, field) } +pub fn const_caller_location<'tcx>( + tcx: TyCtxt<'tcx>, + (file, line, col): (Symbol, u32, u32), +) -> &'tcx ty::Const<'tcx> { + trace!("const_caller_location: {}:{}:{}", file, line, col); + let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all()); + + let loc_ty = tcx.mk_imm_ref( + tcx.lifetimes.re_static, + tcx.type_of(tcx.require_lang_item(PanicLocationLangItem, None)) + .subst(tcx, tcx.mk_substs([tcx.lifetimes.re_static.into()].iter())), + ); + let loc_place = ecx.alloc_caller_location(file, line, col).unwrap(); + intern_const_alloc_recursive(&mut ecx, None, loc_place).unwrap(); + let loc_const = ty::Const { + ty: loc_ty, + val: ConstValue::Scalar(loc_place.ptr.into()), + }; + + tcx.mk_const(loc_const) +} + // this function uses `unwrap` copiously, because an already validated constant must have valid // fields and can thus never fail outside of compiler bugs pub fn const_variant_index<'tcx>( diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 72a0fe887b964..2c5757b1c9fd2 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -1,6 +1,8 @@ //! Type-checking for the rust-intrinsic and platform-intrinsic //! intrinsics that the compiler exposes. +use rustc::hir::{self, Mutability}; +use rustc::middle::lang_items::PanicLocationLangItem; use rustc::traits::{ObligationCause, ObligationCauseCode}; use rustc::ty::{self, TyCtxt, Ty}; use rustc::ty::subst::Subst; @@ -9,8 +11,6 @@ use crate::require_same_types; use rustc_target::spec::abi::Abi; use syntax::symbol::Symbol; -use rustc::hir; - use std::iter; fn equate_intrinsic_type<'tcx>( @@ -65,7 +65,7 @@ fn equate_intrinsic_type<'tcx>( /// Returns `true` if the given intrinsic is unsafe to call or not. pub fn intrinsic_operation_unsafety(intrinsic: &str) -> hir::Unsafety { match intrinsic { - "size_of" | "min_align_of" | "needs_drop" | + "size_of" | "min_align_of" | "needs_drop" | "caller_location" | "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" | "wrapping_add" | "wrapping_sub" | "wrapping_mul" | "saturating_add" | "saturating_sub" | @@ -143,6 +143,18 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) { ], tcx.types.usize) } "rustc_peek" => (1, vec![param(0)], param(0)), + "caller_location" => ( + 0, + vec![], + tcx.mk_ref( + tcx.lifetimes.re_static, + ty::TypeAndMut { + mutbl: Mutability::MutImmutable, + ty: tcx.type_of(tcx.require_lang_item(PanicLocationLangItem, None)) + .subst(tcx, tcx.mk_substs([tcx.lifetimes.re_static.into()].iter())), + }, + ), + ), "panic_if_uninhabited" => (1, Vec::new(), tcx.mk_unit()), "init" => (1, Vec::new(), param(0)), "uninit" => (1, Vec::new(), param(0)), diff --git a/src/test/ui/rfc-2091-track-caller/caller-location-intrinsic.rs b/src/test/ui/rfc-2091-track-caller/caller-location-intrinsic.rs new file mode 100644 index 0000000000000..ab6c59384c43b --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/caller-location-intrinsic.rs @@ -0,0 +1,9 @@ +// run-pass + +#![feature(core_intrinsics)] +fn main() { + let loc = core::intrinsics::caller_location(); + assert_eq!(loc.file(), file!()); + assert_eq!(loc.line(), 5); + assert_eq!(loc.column(), 15); +} From aec97e050ea5247fa13612399a7a812dbce89ec9 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Wed, 23 Oct 2019 19:30:21 -0700 Subject: [PATCH 07/10] Panicking infra uses &core::panic::Location. This allows us to remove `static_panic_msg` from the SSA<->LLVM boundary, along with its fat pointer representation for &str. Also changes the signature of PanicInfo::internal_contructor to avoid copying. Closes #65856. --- src/libcore/macros.rs | 35 ++++++++++- src/libcore/panic.rs | 17 +++-- src/libcore/panicking.rs | 63 +++++++++++++++++-- src/librustc_codegen_llvm/builder.rs | 30 --------- src/librustc_codegen_llvm/common.rs | 18 ------ src/librustc_codegen_ssa/mir/block.rs | 47 +++----------- src/librustc_codegen_ssa/traits/statics.rs | 9 --- src/librustc_mir/interpret/intrinsics.rs | 21 ++++--- src/libstd/panicking.rs | 12 ++-- ...llow-unwind-when-calling-panic-directly.rs | 5 +- 10 files changed, 130 insertions(+), 127 deletions(-) diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index 35558e3abcddd..8ccd31c95d510 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -1,8 +1,9 @@ /// Panics the current thread. /// /// For details, see `std::macros`. +#[cfg(bootstrap)] #[macro_export] -#[allow_internal_unstable(core_panic)] +#[allow_internal_unstable(core_panic, panic_internals)] #[stable(feature = "core", since = "1.6.0")] macro_rules! panic { () => ( @@ -20,6 +21,38 @@ macro_rules! panic { }); } +/// Panics the current thread. +/// +/// For details, see `std::macros`. +#[cfg(not(bootstrap))] +#[macro_export] +#[allow_internal_unstable(core_panic, panic_internals)] +#[stable(feature = "core", since = "1.6.0")] +macro_rules! panic { + () => ( + $crate::panic!("explicit panic") + ); + ($msg:expr) => ({ + const LOC: &$crate::panic::Location<'_> = &$crate::panic::Location::internal_constructor( + $crate::file!(), + $crate::line!(), + $crate::column!(), + ); + $crate::panicking::panic($msg, LOC) + }); + ($msg:expr,) => ( + $crate::panic!($msg) + ); + ($fmt:expr, $($arg:tt)+) => ({ + const LOC: &$crate::panic::Location<'_> = &$crate::panic::Location::internal_constructor( + $crate::file!(), + $crate::line!(), + $crate::column!(), + ); + $crate::panicking::panic_fmt($crate::format_args!($fmt, $($arg)+), LOC) + }); +} + /// Asserts that two expressions are equal to each other (using [`PartialEq`]). /// /// On panic, this macro will print the values of the expressions with their diff --git a/src/libcore/panic.rs b/src/libcore/panic.rs index 9428ff3ef15c4..51bbf3a8fd221 100644 --- a/src/libcore/panic.rs +++ b/src/libcore/panic.rs @@ -35,7 +35,7 @@ use crate::fmt; pub struct PanicInfo<'a> { payload: &'a (dyn Any + Send), message: Option<&'a fmt::Arguments<'a>>, - location: Location<'a>, + location: &'a Location<'a>, } impl<'a> PanicInfo<'a> { @@ -45,11 +45,16 @@ impl<'a> PanicInfo<'a> { issue = "0")] #[doc(hidden)] #[inline] - pub fn internal_constructor(message: Option<&'a fmt::Arguments<'a>>, - location: Location<'a>) - -> Self { + pub fn internal_constructor( + message: Option<&'a fmt::Arguments<'a>>, + location: &'a Location<'a>, + ) -> Self { struct NoPayload; - PanicInfo { payload: &NoPayload, location, message } + PanicInfo { + location, + message, + payload: &NoPayload, + } } #[doc(hidden)] @@ -177,7 +182,7 @@ impl<'a> Location<'a> { and related macros", issue = "0")] #[doc(hidden)] - pub fn internal_constructor(file: &'a str, line: u32, col: u32) -> Self { + pub const fn internal_constructor(file: &'a str, line: u32, col: u32) -> Self { Location { file, line, col } } diff --git a/src/libcore/panicking.rs b/src/libcore/panicking.rs index e8f0561604aec..685b749776b1d 100644 --- a/src/libcore/panicking.rs +++ b/src/libcore/panicking.rs @@ -29,6 +29,7 @@ use crate::fmt; use crate::panic::{Location, PanicInfo}; +#[cfg(bootstrap)] #[cold] // never inline unless panic_immediate_abort to avoid code // bloat at the call sites as much as possible @@ -49,6 +50,27 @@ pub fn panic(expr_file_line_col: &(&'static str, &'static str, u32, u32)) -> ! { panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), &(file, line, col)) } +#[cfg(not(bootstrap))] +#[cold] +// never inline unless panic_immediate_abort to avoid code +// bloat at the call sites as much as possible +#[cfg_attr(not(feature="panic_immediate_abort"),inline(never))] +#[lang = "panic"] +pub fn panic(expr: &str, location: &Location<'_>) -> ! { + if cfg!(feature = "panic_immediate_abort") { + unsafe { super::intrinsics::abort() } + } + + // Use Arguments::new_v1 instead of format_args!("{}", expr) to potentially + // reduce size overhead. The format_args! macro uses str's Display trait to + // write expr, which calls Formatter::pad, which must accommodate string + // truncation and padding (even though none is used here). Using + // Arguments::new_v1 may allow the compiler to omit Formatter::pad from the + // output binary, saving up to a few kilobytes. + panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), location) +} + +#[cfg(bootstrap)] #[cold] #[cfg_attr(not(feature="panic_immediate_abort"),inline(never))] #[lang = "panic_bounds_check"] @@ -62,6 +84,22 @@ fn panic_bounds_check(file_line_col: &(&'static str, u32, u32), len, index), file_line_col) } +#[cfg(not(bootstrap))] +#[cold] +#[cfg_attr(not(feature="panic_immediate_abort"),inline(never))] +#[lang = "panic_bounds_check"] +fn panic_bounds_check(location: &Location<'_>, index: usize, len: usize) -> ! { + if cfg!(feature = "panic_immediate_abort") { + unsafe { super::intrinsics::abort() } + } + + panic_fmt( + format_args!("index out of bounds: the len is {} but the index is {}", len, index), + location + ) +} + +#[cfg(bootstrap)] #[cold] #[cfg_attr(not(feature="panic_immediate_abort"),inline(never))] #[cfg_attr( feature="panic_immediate_abort" ,inline)] @@ -77,9 +115,26 @@ pub fn panic_fmt(fmt: fmt::Arguments<'_>, file_line_col: &(&'static str, u32, u3 } let (file, line, col) = *file_line_col; - let pi = PanicInfo::internal_constructor( - Some(&fmt), - Location::internal_constructor(file, line, col), - ); + let location = Location::internal_constructor(file, line, col); + let pi = PanicInfo::internal_constructor(Some(&fmt), &location); + unsafe { panic_impl(&pi) } +} + +#[cfg(not(bootstrap))] +#[cold] +#[cfg_attr(not(feature="panic_immediate_abort"),inline(never))] +#[cfg_attr( feature="panic_immediate_abort" ,inline)] +pub fn panic_fmt(fmt: fmt::Arguments<'_>, location: &Location<'_>) -> ! { + if cfg!(feature = "panic_immediate_abort") { + unsafe { super::intrinsics::abort() } + } + + // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call + extern "Rust" { + #[lang = "panic_impl"] + fn panic_impl(pi: &PanicInfo<'_>) -> !; + } + + let pi = PanicInfo::internal_constructor(Some(&fmt), location); unsafe { panic_impl(&pi) } } diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index ffaf8050bcbb2..8ac1c7b36fc3f 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -1082,36 +1082,6 @@ impl StaticBuilderMethods for Builder<'a, 'll, 'tcx> { // FIXME(eddyb) move this into miri, it can be correct if e.g. field order changes self.static_addr_of(struct_, align, Some("panic_loc")) } - - fn static_panic_msg( - &mut self, - msg: Option, - filename: Symbol, - line: Self::Value, - col: Self::Value, - kind: &str, - ) -> Self::Value { - let align = self.tcx.data_layout.aggregate_align.abi - .max(self.tcx.data_layout.i32_align.abi) - .max(self.tcx.data_layout.pointer_align.abi); - - let filename = self.const_str_slice(filename); - - let with_msg_components; - let without_msg_components; - - let components = if let Some(msg) = msg { - let msg = self.const_str_slice(msg); - with_msg_components = [msg, filename, line, col]; - &with_msg_components as &[_] - } else { - without_msg_components = [filename, line, col]; - &without_msg_components as &[_] - }; - - let struct_ = self.const_struct(&components, false); - self.static_addr_of(struct_, align, Some(kind)) - } } impl Builder<'a, 'll, 'tcx> { diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs index b4b82f67c74b3..f38f9dfecd387 100644 --- a/src/librustc_codegen_llvm/common.rs +++ b/src/librustc_codegen_llvm/common.rs @@ -3,7 +3,6 @@ //! Code that is useful in various codegen modules. use crate::llvm::{self, True, False, Bool, BasicBlock, OperandBundleDef, ConstantInt}; -use crate::abi; use crate::consts; use crate::type_::Type; use crate::type_of::LayoutLlvmExt; @@ -96,16 +95,6 @@ impl BackendTypes for CodegenCx<'ll, 'tcx> { } impl CodegenCx<'ll, 'tcx> { - pub fn const_fat_ptr( - &self, - ptr: &'ll Value, - meta: &'ll Value - ) -> &'ll Value { - assert_eq!(abi::FAT_PTR_ADDR, 0); - assert_eq!(abi::FAT_PTR_EXTRA, 1); - self.const_struct(&[ptr, meta], false) - } - pub fn const_array(&self, ty: &'ll Type, elts: &[&'ll Value]) -> &'ll Value { unsafe { return llvm::LLVMConstArray(ty, elts.as_ptr(), elts.len() as c_uint); @@ -150,13 +139,6 @@ impl CodegenCx<'ll, 'tcx> { } } - pub fn const_str_slice(&self, s: Symbol) -> &'ll Value { - let len = s.as_str().len(); - let cs = consts::ptrcast(self.const_cstr(s, false), - self.type_ptr_to(self.layout_of(self.tcx.mk_str()).llvm_type(self))); - self.const_fat_ptr(cs, self.const_usize(len as u64)) - } - pub fn const_get_elt(&self, v: &'ll Value, idx: u64) -> &'ll Value { unsafe { assert_eq!(idx as c_uint as u64, idx); diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 22ea6a3955216..2462ba0a33e8e 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -16,7 +16,6 @@ use crate::traits::*; use std::borrow::Cow; use syntax::symbol::Symbol; -use syntax_pos::Pos; use super::{FunctionCx, LocalRef}; use super::place::PlaceRef; @@ -422,37 +421,19 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Get the location information. let loc = bx.sess().source_map().lookup_char_pos(span.lo()); - let filename = Symbol::intern(&loc.file.name.to_string()); - let line = bx.const_u32(loc.line as u32); - let col = bx.const_u32(loc.col.to_usize() as u32 + 1); + let location = bx.static_panic_location(&loc); // Put together the arguments to the panic entry point. let (lang_item, args) = match msg { PanicInfo::BoundsCheck { ref len, ref index } => { let len = self.codegen_operand(&mut bx, len).immediate(); let index = self.codegen_operand(&mut bx, index).immediate(); - - let file_line_col = bx.static_panic_msg( - None, - filename, - line, - col, - "panic_bounds_check_loc", - ); - (lang_items::PanicBoundsCheckFnLangItem, - vec![file_line_col, index, len]) + (lang_items::PanicBoundsCheckFnLangItem, vec![location, index, len]) } _ => { let msg_str = Symbol::intern(msg.description()); - let msg_file_line_col = bx.static_panic_msg( - Some(msg_str), - filename, - line, - col, - "panic_loc", - ); - (lang_items::PanicFnLangItem, - vec![msg_file_line_col]) + let msg = bx.const_str(msg_str); + (lang_items::PanicFnLangItem, vec![msg.0, msg.1, location]) } }; @@ -554,22 +535,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let layout = bx.layout_of(ty); if layout.abi.is_uninhabited() { let loc = bx.sess().source_map().lookup_char_pos(span.lo()); - let filename = Symbol::intern(&loc.file.name.to_string()); - let line = bx.const_u32(loc.line as u32); - let col = bx.const_u32(loc.col.to_usize() as u32 + 1); - let str = format!( - "Attempted to instantiate uninhabited type {}", - ty - ); - let msg_str = Symbol::intern(&str); - let msg_file_line_col = bx.static_panic_msg( - Some(msg_str), - filename, - line, - col, - "panic_loc", - ); + let msg_str = format!("Attempted to instantiate uninhabited type {}", ty); + let msg = bx.const_str(Symbol::intern(&msg_str)); + let location = bx.static_panic_location(&loc); // Obtain the panic entry point. let def_id = @@ -587,7 +556,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { &mut bx, fn_ty, llfn, - &[msg_file_line_col], + &[msg.0, msg.1, location], destination.as_ref().map(|(_, bb)| (ReturnDest::Nothing, *bb)), cleanup, ); diff --git a/src/librustc_codegen_ssa/traits/statics.rs b/src/librustc_codegen_ssa/traits/statics.rs index b51f15b5823e2..f63cea51f4395 100644 --- a/src/librustc_codegen_ssa/traits/statics.rs +++ b/src/librustc_codegen_ssa/traits/statics.rs @@ -1,6 +1,5 @@ use super::BackendTypes; use syntax::source_map::Loc; -use syntax_pos::symbol::Symbol; use rustc::hir::def_id::DefId; use rustc::ty::layout::Align; @@ -12,12 +11,4 @@ pub trait StaticMethods: BackendTypes { pub trait StaticBuilderMethods: BackendTypes { fn get_static(&mut self, def_id: DefId) -> Self::Value; fn static_panic_location(&mut self, loc: &Loc) -> Self::Value; - fn static_panic_msg( - &mut self, - msg: Option, - filename: Symbol, - line: Self::Value, - col: Self::Value, - kind: &str, - ) -> Self::Value; } diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index 5fc23b4a69ec5..20cb2926d66b5 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -301,18 +301,19 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) -> InterpResult<'tcx, bool> { let def_id = instance.def_id(); if Some(def_id) == self.tcx.lang_items().panic_fn() { - assert!(args.len() == 1); - // &(&'static str, &'static str, u32, u32) - let place = self.deref_operand(args[0])?; - let (msg, file, line, col) = ( - self.mplace_field(place, 0)?, - self.mplace_field(place, 1)?, - self.mplace_field(place, 2)?, - self.mplace_field(place, 3)?, - ); + // &'static str, &core::panic::Location { &'static str, u32, u32 } + assert!(args.len() == 2); - let msg_place = self.deref_operand(msg.into())?; + let msg_place = self.deref_operand(args[0])?; let msg = Symbol::intern(self.read_str(msg_place)?); + + let location = self.deref_operand(args[1])?; + let (file, line, col) = ( + self.mplace_field(location, 0)?, + self.mplace_field(location, 1)?, + self.mplace_field(location, 2)?, + ); + let file_place = self.deref_operand(file.into())?; let file = Symbol::intern(self.read_str(file_place)?); let line = self.read_scalar(line.into())?.to_u32()?; diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 619b182019081..f76969146fdd2 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -323,10 +323,8 @@ pub fn begin_panic_fmt(msg: &fmt::Arguments<'_>, } let (file, line, col) = *file_line_col; - let info = PanicInfo::internal_constructor( - Some(msg), - Location::internal_constructor(file, line, col), - ); + let location = Location::internal_constructor(file, line, col); + let info = PanicInfo::internal_constructor(Some(msg), &location); continue_panic_fmt(&info) } @@ -453,10 +451,8 @@ fn rust_panic_with_hook(payload: &mut dyn BoxMeUp, } unsafe { - let mut info = PanicInfo::internal_constructor( - message, - Location::internal_constructor(file, line, col), - ); + let location = Location::internal_constructor(file, line, col); + let mut info = PanicInfo::internal_constructor(message, &location); HOOK_LOCK.read(); match HOOK { // Some platforms know that printing to stderr won't ever actually diff --git a/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs b/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs index ff10d412a110a..8727c9d1ca655 100644 --- a/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs +++ b/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs @@ -22,7 +22,7 @@ //[thin]compile-flags: -C lto=thin //[fat]compile-flags: -C lto=fat -#![feature(core_panic)] +#![feature(core_panic, panic_internals)] // (For some reason, reproducing the LTO issue requires pulling in std // explicitly this way.) @@ -51,7 +51,8 @@ fn main() { let _guard = Droppable; let s = "issue-64655-allow-unwind-when-calling-panic-directly.rs"; - core::panicking::panic(&("???", s, 17, 4)); + let location = core::panic::Location::internal_constructor(s, 17, 4); + core::panicking::panic("???", &location); }); let wait = handle.join(); From 017877cbbe7903beb483f13678aedae1e40b6ab0 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Thu, 24 Oct 2019 08:03:57 -0700 Subject: [PATCH 08/10] Implementation of const caller_location. --- src/librustc_mir/const_eval.rs | 3 +- src/librustc_mir/interpret/intrinsics.rs | 7 +++ .../interpret/intrinsics/caller_location.rs | 54 +++++++++++++++++++ src/librustc_mir/interpret/machine.rs | 2 + src/librustc_mir/interpret/terminator.rs | 2 +- src/librustc_mir/transform/const_prop.rs | 1 + .../const-eval/const_caller_location.rs | 23 ++++++++ 7 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 src/librustc_mir/interpret/intrinsics/caller_location.rs create mode 100644 src/test/ui/consts/const-eval/const_caller_location.rs diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index eeaa3c6792d3c..eed26c32b7a9b 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -375,11 +375,12 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, fn call_intrinsic( ecx: &mut InterpCx<'mir, 'tcx, Self>, + span: Span, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx>], dest: PlaceTy<'tcx>, ) -> InterpResult<'tcx> { - if ecx.emulate_intrinsic(instance, args, dest)? { + if ecx.emulate_intrinsic(span, instance, args, dest)? { return Ok(()); } // An intrinsic that we do not support diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index 20cb2926d66b5..12e080869c7f8 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -3,6 +3,7 @@ //! and miri. use syntax::symbol::Symbol; +use syntax_pos::Span; use rustc::ty; use rustc::ty::layout::{LayoutOf, Primitive, Size}; use rustc::ty::subst::SubstsRef; @@ -15,6 +16,7 @@ use super::{ Machine, PlaceTy, OpTy, InterpCx, }; +mod caller_location; mod type_name; fn numeric_intrinsic<'tcx, Tag>( @@ -86,6 +88,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Returns `true` if emulation happened. pub fn emulate_intrinsic( &mut self, + span: Span, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx, M::PointerTag>], dest: PlaceTy<'tcx, M::PointerTag>, @@ -94,6 +97,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let intrinsic_name = &self.tcx.item_name(instance.def_id()).as_str()[..]; match intrinsic_name { + "caller_location" => { + self.write_caller_location(span, dest)?; + } + "min_align_of" | "pref_align_of" | "needs_drop" | diff --git a/src/librustc_mir/interpret/intrinsics/caller_location.rs b/src/librustc_mir/interpret/intrinsics/caller_location.rs new file mode 100644 index 0000000000000..5addb13b61c42 --- /dev/null +++ b/src/librustc_mir/interpret/intrinsics/caller_location.rs @@ -0,0 +1,54 @@ +use rustc::middle::lang_items::PanicLocationLangItem; +use rustc::mir::interpret::{Pointer, PointerArithmetic, Scalar}; +use rustc::ty::subst::Subst; +use rustc_target::abi::{LayoutOf, Size}; +use syntax_pos::Span; + +use crate::interpret::{ + MemoryKind, + intrinsics::{InterpCx, InterpResult, Machine, PlaceTy}, +}; + +impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { + pub fn write_caller_location( + &mut self, + span: Span, + dest: PlaceTy<'tcx, M::PointerTag>, + ) -> InterpResult<'tcx> { + let caller = self.tcx.sess.source_map().lookup_char_pos(span.lo()); + let filename = caller.file.name.to_string(); + let line = Scalar::from_u32(caller.line as u32); + let col = Scalar::from_u32(caller.col_display as u32 + 1); + + let ptr_size = self.pointer_size(); + let u32_size = Size::from_bits(32); + + let loc_ty = self.tcx.type_of(self.tcx.require_lang_item(PanicLocationLangItem, None)) + .subst(*self.tcx, self.tcx.mk_substs([self.tcx.lifetimes.re_static.into()].iter())); + let loc_layout = self.layout_of(loc_ty)?; + + let file_alloc = self.tcx.allocate_bytes(filename.as_bytes()); + let file_ptr = Pointer::new(file_alloc, Size::ZERO); + let file = Scalar::Ptr(self.tag_static_base_pointer(file_ptr)); + let file_len = Scalar::from_uint(filename.len() as u128, ptr_size); + + let location = self.allocate(loc_layout, MemoryKind::Stack); + + let file_out = self.mplace_field(location, 0)?; + let file_ptr_out = self.force_ptr(self.mplace_field(file_out, 0)?.ptr)?; + let file_len_out = self.force_ptr(self.mplace_field(file_out, 1)?.ptr)?; + let line_out = self.force_ptr(self.mplace_field(location, 1)?.ptr)?; + let col_out = self.force_ptr(self.mplace_field(location, 2)?.ptr)?; + + let layout = &self.tcx.data_layout; + let alloc = self.memory.get_mut(file_ptr_out.alloc_id)?; + + alloc.write_scalar(layout, file_ptr_out, file.into(), ptr_size)?; + alloc.write_scalar(layout, file_len_out, file_len.into(), ptr_size)?; + alloc.write_scalar(layout, line_out, line.into(), u32_size)?; + alloc.write_scalar(layout, col_out, col.into(), u32_size)?; + + self.write_scalar(location.ptr, dest)?; + Ok(()) + } +} diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index c30c59bbf10c8..870e50a3cbb9a 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -8,6 +8,7 @@ use std::hash::Hash; use rustc::hir::def_id::DefId; use rustc::mir; use rustc::ty::{self, Ty, TyCtxt}; +use syntax_pos::Span; use super::{ Allocation, AllocId, InterpResult, Scalar, AllocationExtra, @@ -152,6 +153,7 @@ pub trait Machine<'mir, 'tcx>: Sized { /// If this returns successfully, the engine will take care of jumping to the next block. fn call_intrinsic( ecx: &mut InterpCx<'mir, 'tcx, Self>, + span: Span, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx, Self::PointerTag>], dest: PlaceTy<'tcx, Self::PointerTag>, diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index 7f6baf0bb49c1..d90f2058aa74f 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -255,7 +255,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Some(dest) => dest, None => throw_ub!(Unreachable) }; - M::call_intrinsic(self, instance, args, dest)?; + M::call_intrinsic(self, span, instance, args, dest)?; // No stack frame gets pushed, the main loop will just act as if the // call completed. self.goto_block(ret)?; diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 13097a2156167..e7095101f465d 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -158,6 +158,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { fn call_intrinsic( _ecx: &mut InterpCx<'mir, 'tcx, Self>, + _span: Span, _instance: ty::Instance<'tcx>, _args: &[OpTy<'tcx>], _dest: PlaceTy<'tcx>, diff --git a/src/test/ui/consts/const-eval/const_caller_location.rs b/src/test/ui/consts/const-eval/const_caller_location.rs new file mode 100644 index 0000000000000..c63822f052b2f --- /dev/null +++ b/src/test/ui/consts/const-eval/const_caller_location.rs @@ -0,0 +1,23 @@ +// run-pass + +#![feature(const_fn, core_intrinsics)] + +use std::{intrinsics::caller_location, panic::Location}; + +const LOCATION: &Location = caller_location(); +const NESTED: &Location = { + const fn nested_location() -> &'static Location<'static> { + caller_location() + }; + nested_location() +}; + +fn main() { + assert_eq!(LOCATION.file(), file!()); + assert_eq!(LOCATION.line(), 7); + assert_eq!(LOCATION.column(), 29); + + assert_eq!(NESTED.file(), file!()); + assert_eq!(NESTED.line(), 10); + assert_eq!(NESTED.column(), 9); +} From 86e55b1882ac492d6234e5c5f97c7f151a11f5d2 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Thu, 24 Oct 2019 17:35:02 -0700 Subject: [PATCH 09/10] Always use consteval to codegen caller_location. --- src/librustc/query/mod.rs | 6 ++++ src/librustc/ty/query/keys.rs | 10 +++++++ src/librustc_codegen_llvm/builder.rs | 16 ---------- src/librustc_codegen_ssa/mir/block.rs | 30 ++++++++++++------- src/librustc_codegen_ssa/traits/statics.rs | 2 -- src/librustc_mir/const_eval.rs | 8 ++--- src/librustc_mir/interpret/intern.rs | 7 ++--- src/librustc_mir/interpret/intrinsics.rs | 8 ++++- .../interpret/intrinsics/caller_location.rs | 29 ++++++++---------- src/librustc_mir/lib.rs | 1 + src/librustc_typeck/check/intrinsic.rs | 12 ++++---- 11 files changed, 66 insertions(+), 63 deletions(-) diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index fdca6d0e17a1d..aa37cbb92a724 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -466,6 +466,12 @@ rustc_queries! { no_force desc { "extract field of const" } } + + query const_caller_location(key: (syntax_pos::Symbol, u32, u32)) -> &'tcx ty::Const<'tcx> { + eval_always + no_force + desc { "get a &core::panic::Location referring to a span" } + } } TypeChecking { diff --git a/src/librustc/ty/query/keys.rs b/src/librustc/ty/query/keys.rs index 0a217e9ae666d..a9e0a5d6ab564 100644 --- a/src/librustc/ty/query/keys.rs +++ b/src/librustc/ty/query/keys.rs @@ -208,3 +208,13 @@ impl<'tcx, T> Key for Canonical<'tcx, T> { DUMMY_SP } } + +impl Key for (Symbol, u32, u32) { + fn query_crate(&self) -> CrateNum { + LOCAL_CRATE + } + + fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { + DUMMY_SP + } +} diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index 8ac1c7b36fc3f..312c41b88b092 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -2,7 +2,6 @@ use crate::llvm::{AtomicRmwBinOp, AtomicOrdering, SynchronizationScope}; use crate::llvm::{self, False, BasicBlock}; use crate::common::Funclet; use crate::context::CodegenCx; -use crate::syntax_pos::Pos; use crate::type_::Type; use crate::type_of::LayoutLlvmExt; use crate::value::Value; @@ -24,7 +23,6 @@ use std::ffi::CStr; use std::ops::{Deref, Range}; use std::ptr; use std::iter::TrustedLen; -use syntax::symbol::Symbol; // All Builders must have an llfn associated with them #[must_use] @@ -1068,20 +1066,6 @@ impl StaticBuilderMethods for Builder<'a, 'll, 'tcx> { // Forward to the `get_static` method of `CodegenCx` self.cx().get_static(def_id) } - - fn static_panic_location(&mut self, loc: &syntax::source_map::Loc) -> Self::Value { - let filename = Symbol::intern(&loc.file.name.to_string()); - let filename = self.const_str(filename); - let line = self.const_u32(loc.line as u32); - let col = self.const_u32(loc.col.to_usize() as u32 + 1); - let struct_ = self.const_struct(&[filename.0, filename.1, line, col], false); - - let align = self.tcx.data_layout.aggregate_align.abi - .max(self.tcx.data_layout.i32_align.abi) - .max(self.tcx.data_layout.pointer_align.abi); - // FIXME(eddyb) move this into miri, it can be correct if e.g. field order changes - self.static_addr_of(struct_, align, Some("panic_loc")) - } } impl Builder<'a, 'll, 'tcx> { diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 2462ba0a33e8e..79855311f370a 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -15,7 +15,7 @@ use crate::traits::*; use std::borrow::Cow; -use syntax::symbol::Symbol; +use syntax::{source_map::Span, symbol::Symbol}; use super::{FunctionCx, LocalRef}; use super::place::PlaceRef; @@ -420,8 +420,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.set_debug_loc(&mut bx, terminator.source_info); // Get the location information. - let loc = bx.sess().source_map().lookup_char_pos(span.lo()); - let location = bx.static_panic_location(&loc); + let location = self.get_caller_location(&mut bx, span).immediate(); // Put together the arguments to the panic entry point. let (lang_item, args) = match msg { @@ -534,11 +533,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let ty = instance.unwrap().substs.type_at(0); let layout = bx.layout_of(ty); if layout.abi.is_uninhabited() { - let loc = bx.sess().source_map().lookup_char_pos(span.lo()); - let msg_str = format!("Attempted to instantiate uninhabited type {}", ty); let msg = bx.const_str(Symbol::intern(&msg_str)); - let location = bx.static_panic_location(&loc); + let location = self.get_caller_location(&mut bx, span).immediate(); // Obtain the panic entry point. let def_id = @@ -584,13 +581,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if intrinsic == Some("caller_location") { if let Some((_, target)) = destination.as_ref() { - let loc = bx.sess().source_map().lookup_char_pos(span.lo()); - let location = bx.static_panic_location(&loc); + let location = self.get_caller_location(&mut bx, span); if let ReturnDest::IndirectOperand(tmp, _) = ret_dest { - Immediate(location).store(&mut bx, tmp); + location.val.store(&mut bx, tmp); } - self.store_return(&mut bx, ret_dest, &fn_ty.ret, location); + self.store_return(&mut bx, ret_dest, &fn_ty.ret, location.immediate()); helper.maybe_sideeffect(self.mir, &mut bx, &[*target]); helper.funclet_br(self, &mut bx, *target); @@ -994,6 +990,20 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } + fn get_caller_location( + &mut self, + bx: &mut Bx, + span: Span, + ) -> OperandRef<'tcx, Bx::Value> { + let caller = bx.tcx().sess.source_map().lookup_char_pos(span.lo()); + let const_loc = bx.tcx().const_caller_location(( + Symbol::intern(&caller.file.name.to_string()), + caller.line as u32, + caller.col_display as u32 + 1, + )); + OperandRef::from_const(bx, const_loc) + } + fn get_personality_slot( &mut self, bx: &mut Bx diff --git a/src/librustc_codegen_ssa/traits/statics.rs b/src/librustc_codegen_ssa/traits/statics.rs index f63cea51f4395..5c108f9fa6cc5 100644 --- a/src/librustc_codegen_ssa/traits/statics.rs +++ b/src/librustc_codegen_ssa/traits/statics.rs @@ -1,5 +1,4 @@ use super::BackendTypes; -use syntax::source_map::Loc; use rustc::hir::def_id::DefId; use rustc::ty::layout::Align; @@ -10,5 +9,4 @@ pub trait StaticMethods: BackendTypes { pub trait StaticBuilderMethods: BackendTypes { fn get_static(&mut self, def_id: DefId) -> Self::Value; - fn static_panic_location(&mut self, loc: &Loc) -> Self::Value; } diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index eed26c32b7a9b..89bdf7391c3e8 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -18,7 +18,7 @@ use rustc::traits::Reveal; use rustc_data_structures::fx::FxHashMap; use crate::interpret::eval_nullary_intrinsic; -use syntax::source_map::{Span, DUMMY_SP}; +use syntax::{source_map::{Span, DUMMY_SP}, symbol::Symbol}; use crate::interpret::{self, PlaceTy, MPlaceTy, OpTy, ImmTy, Immediate, Scalar, Pointer, @@ -159,11 +159,7 @@ fn eval_body_using_ecx<'mir, 'tcx>( ecx.run()?; // Intern the result - intern_const_alloc_recursive( - ecx, - cid.instance.def_id(), - ret, - )?; + intern_const_alloc_recursive(ecx, tcx.static_mutability(cid.instance.def_id()), ret)?; debug!("eval_body_using_ecx done: {:?}", *ret); Ok(ret) diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs index 646d1783c8ec9..924529d7f5579 100644 --- a/src/librustc_mir/interpret/intern.rs +++ b/src/librustc_mir/interpret/intern.rs @@ -6,7 +6,6 @@ use rustc::ty::{Ty, self}; use rustc::mir::interpret::{InterpResult, ErrorHandled}; use rustc::hir; -use rustc::hir::def_id::DefId; use super::validity::RefTracking; use rustc_data_structures::fx::FxHashSet; @@ -270,12 +269,12 @@ for pub fn intern_const_alloc_recursive( ecx: &mut CompileTimeEvalContext<'mir, 'tcx>, - def_id: DefId, + // The `mutability` of the place, ignoring the type. + place_mut: Option, ret: MPlaceTy<'tcx>, ) -> InterpResult<'tcx> { let tcx = ecx.tcx; - // this `mutability` is the mutability of the place, ignoring the type - let (base_mutability, base_intern_mode) = match tcx.static_mutability(def_id) { + let (base_mutability, base_intern_mode) = match place_mut { Some(hir::Mutability::MutImmutable) => (Mutability::Immutable, InternMode::Static), // `static mut` doesn't care about interior mutability, it's mutable anyway Some(hir::Mutability::MutMutable) => (Mutability::Mutable, InternMode::Static), diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index 12e080869c7f8..519f4f0322228 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -98,7 +98,13 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let intrinsic_name = &self.tcx.item_name(instance.def_id()).as_str()[..]; match intrinsic_name { "caller_location" => { - self.write_caller_location(span, dest)?; + let caller = self.tcx.sess.source_map().lookup_char_pos(span.lo()); + let location = self.alloc_caller_location( + Symbol::intern(&caller.file.name.to_string()), + caller.line as u32, + caller.col_display as u32 + 1, + )?; + self.write_scalar(location.ptr, dest)?; } "min_align_of" | diff --git a/src/librustc_mir/interpret/intrinsics/caller_location.rs b/src/librustc_mir/interpret/intrinsics/caller_location.rs index 5addb13b61c42..249d2f9ff536a 100644 --- a/src/librustc_mir/interpret/intrinsics/caller_location.rs +++ b/src/librustc_mir/interpret/intrinsics/caller_location.rs @@ -2,23 +2,19 @@ use rustc::middle::lang_items::PanicLocationLangItem; use rustc::mir::interpret::{Pointer, PointerArithmetic, Scalar}; use rustc::ty::subst::Subst; use rustc_target::abi::{LayoutOf, Size}; -use syntax_pos::Span; +use syntax_pos::Symbol; -use crate::interpret::{ - MemoryKind, - intrinsics::{InterpCx, InterpResult, Machine, PlaceTy}, -}; +use crate::interpret::{MemoryKind, MPlaceTy, intrinsics::{InterpCx, InterpResult, Machine}}; impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { - pub fn write_caller_location( + pub fn alloc_caller_location( &mut self, - span: Span, - dest: PlaceTy<'tcx, M::PointerTag>, - ) -> InterpResult<'tcx> { - let caller = self.tcx.sess.source_map().lookup_char_pos(span.lo()); - let filename = caller.file.name.to_string(); - let line = Scalar::from_u32(caller.line as u32); - let col = Scalar::from_u32(caller.col_display as u32 + 1); + filename: Symbol, + line: u32, + col: u32, + ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { + let line = Scalar::from_u32(line); + let col = Scalar::from_u32(col); let ptr_size = self.pointer_size(); let u32_size = Size::from_bits(32); @@ -27,10 +23,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { .subst(*self.tcx, self.tcx.mk_substs([self.tcx.lifetimes.re_static.into()].iter())); let loc_layout = self.layout_of(loc_ty)?; - let file_alloc = self.tcx.allocate_bytes(filename.as_bytes()); + let file_alloc = self.tcx.allocate_bytes(filename.as_str().as_bytes()); let file_ptr = Pointer::new(file_alloc, Size::ZERO); let file = Scalar::Ptr(self.tag_static_base_pointer(file_ptr)); - let file_len = Scalar::from_uint(filename.len() as u128, ptr_size); + let file_len = Scalar::from_uint(filename.as_str().len() as u128, ptr_size); let location = self.allocate(loc_layout, MemoryKind::Stack); @@ -48,7 +44,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { alloc.write_scalar(layout, line_out, line.into(), u32_size)?; alloc.write_scalar(layout, col_out, col.into(), u32_size)?; - self.write_scalar(location.ptr, dest)?; - Ok(()) + Ok(location) } } diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index 98d5487870a4d..4d604cb025c8e 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -58,6 +58,7 @@ pub fn provide(providers: &mut Providers<'_>) { providers.const_eval = const_eval::const_eval_provider; providers.const_eval_raw = const_eval::const_eval_raw_provider; providers.check_match = hair::pattern::check_match; + providers.const_caller_location = const_eval::const_caller_location; providers.const_field = |tcx, param_env_and_value| { let (param_env, (value, field)) = param_env_and_value.into_parts(); const_eval::const_field(tcx, param_env, None, field, value) diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 2c5757b1c9fd2..76cc7062d3b87 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -1,7 +1,6 @@ //! Type-checking for the rust-intrinsic and platform-intrinsic //! intrinsics that the compiler exposes. -use rustc::hir::{self, Mutability}; use rustc::middle::lang_items::PanicLocationLangItem; use rustc::traits::{ObligationCause, ObligationCauseCode}; use rustc::ty::{self, TyCtxt, Ty}; @@ -11,6 +10,8 @@ use crate::require_same_types; use rustc_target::spec::abi::Abi; use syntax::symbol::Symbol; +use rustc::hir; + use std::iter; fn equate_intrinsic_type<'tcx>( @@ -146,13 +147,10 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) { "caller_location" => ( 0, vec![], - tcx.mk_ref( + tcx.mk_imm_ref( tcx.lifetimes.re_static, - ty::TypeAndMut { - mutbl: Mutability::MutImmutable, - ty: tcx.type_of(tcx.require_lang_item(PanicLocationLangItem, None)) - .subst(tcx, tcx.mk_substs([tcx.lifetimes.re_static.into()].iter())), - }, + tcx.type_of(tcx.require_lang_item(PanicLocationLangItem, None)) + .subst(tcx, tcx.mk_substs([tcx.lifetimes.re_static.into()].iter())), ), ), "panic_if_uninhabited" => (1, Vec::new(), tcx.mk_unit()), From 09f9947ebc68a8199c3dff8607a41571c48cc377 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sat, 28 Sep 2019 16:05:38 +0200 Subject: [PATCH 10/10] Gather together usefulness tests I took most tests that were testing only for match exhaustiveness, pattern refutability or match arm reachability, and put them in the same test folder. --- src/librustc_mir/hair/pattern/_match.rs | 3 +++ .../usefulness}/always-inhabited-union-ref.rs | 0 .../usefulness}/always-inhabited-union-ref.stderr | 0 .../{ => pattern/usefulness}/exhaustive_integer_patterns.rs | 0 .../usefulness}/exhaustive_integer_patterns.stderr | 0 .../ui/{ => pattern/usefulness}/guards-not-exhaustive.rs | 0 .../irrefutable-exhaustive-integer-binding.rs | 0 src/test/ui/{ => pattern/usefulness}/irrefutable-unit.rs | 0 .../ui/{check_match => pattern/usefulness}/issue-35609.rs | 0 .../{check_match => pattern/usefulness}/issue-35609.stderr | 0 .../ui/{check_match => pattern/usefulness}/issue-43253.rs | 0 .../{check_match => pattern/usefulness}/issue-43253.stderr | 0 .../usefulness/match-arm-statics-2.rs} | 0 .../usefulness/match-arm-statics-2.stderr} | 6 +++--- .../ui/{match => pattern/usefulness}/match-arm-statics.rs | 0 .../{match => pattern/usefulness}/match-arm-statics.stderr | 0 .../usefulness}/match-byte-array-patterns-2.rs | 0 .../usefulness}/match-byte-array-patterns-2.stderr | 0 .../usefulness}/match-byte-array-patterns.rs | 0 .../usefulness}/match-byte-array-patterns.stderr | 0 .../{match => pattern/usefulness}/match-non-exhaustive.rs | 0 .../usefulness}/match-non-exhaustive.stderr | 0 .../{match => pattern/usefulness}/match-privately-empty.rs | 0 .../usefulness}/match-privately-empty.stderr | 0 .../usefulness}/match-range-fail-dominate.rs | 0 .../usefulness}/match-range-fail-dominate.stderr | 0 src/test/ui/{match => pattern/usefulness}/match-ref-ice.rs | 0 .../ui/{match => pattern/usefulness}/match-ref-ice.stderr | 0 .../{match => pattern/usefulness}/match-slice-patterns.rs | 0 .../usefulness}/match-slice-patterns.stderr | 0 .../ui/{match => pattern/usefulness}/match-vec-fixed.rs | 0 .../ui/{match => pattern/usefulness}/match-vec-fixed.stderr | 0 .../{match => pattern/usefulness}/match-vec-unreachable.rs | 0 .../usefulness}/match-vec-unreachable.stderr | 0 .../usefulness}/nested-exhaustive-match.rs | 0 .../usefulness}/non-exhaustive-defined-here.rs | 0 .../usefulness}/non-exhaustive-defined-here.stderr | 0 .../usefulness}/non-exhaustive-float-range-match.rs | 0 .../usefulness}/non-exhaustive-float-range-match.stderr | 0 .../usefulness}/non-exhaustive-match-nested.rs | 0 .../usefulness}/non-exhaustive-match-nested.stderr | 0 .../usefulness}/non-exhaustive-match.rs | 0 .../usefulness}/non-exhaustive-match.stderr | 0 .../usefulness}/non-exhaustive-pattern-witness.rs | 0 .../usefulness}/non-exhaustive-pattern-witness.stderr | 0 .../ui/{ => pattern/usefulness}/refutable-pattern-errors.rs | 0 .../usefulness}/refutable-pattern-errors.stderr | 0 .../{ => pattern/usefulness}/refutable-pattern-in-fn-arg.rs | 0 .../usefulness}/refutable-pattern-in-fn-arg.stderr | 0 .../usefulness}/struct-like-enum-nonexhaustive.rs | 0 .../usefulness}/struct-like-enum-nonexhaustive.stderr | 0 .../usefulness}/struct-pattern-match-useless.rs | 0 .../usefulness}/struct-pattern-match-useless.stderr | 0 .../usefulness}/tuple-struct-nonexhaustive.rs | 0 .../usefulness}/tuple-struct-nonexhaustive.stderr | 0 55 files changed, 6 insertions(+), 3 deletions(-) rename src/test/ui/{uninhabited => pattern/usefulness}/always-inhabited-union-ref.rs (100%) rename src/test/ui/{uninhabited => pattern/usefulness}/always-inhabited-union-ref.stderr (100%) rename src/test/ui/{ => pattern/usefulness}/exhaustive_integer_patterns.rs (100%) rename src/test/ui/{ => pattern/usefulness}/exhaustive_integer_patterns.stderr (100%) rename src/test/ui/{ => pattern/usefulness}/guards-not-exhaustive.rs (100%) rename src/test/ui/pattern/{ => usefulness}/irrefutable-exhaustive-integer-binding.rs (100%) rename src/test/ui/{ => pattern/usefulness}/irrefutable-unit.rs (100%) rename src/test/ui/{check_match => pattern/usefulness}/issue-35609.rs (100%) rename src/test/ui/{check_match => pattern/usefulness}/issue-35609.stderr (100%) rename src/test/ui/{check_match => pattern/usefulness}/issue-43253.rs (100%) rename src/test/ui/{check_match => pattern/usefulness}/issue-43253.stderr (100%) rename src/test/ui/{match/match-argm-statics-2.rs => pattern/usefulness/match-arm-statics-2.rs} (100%) rename src/test/ui/{match/match-argm-statics-2.stderr => pattern/usefulness/match-arm-statics-2.stderr} (90%) rename src/test/ui/{match => pattern/usefulness}/match-arm-statics.rs (100%) rename src/test/ui/{match => pattern/usefulness}/match-arm-statics.stderr (100%) rename src/test/ui/{match => pattern/usefulness}/match-byte-array-patterns-2.rs (100%) rename src/test/ui/{match => pattern/usefulness}/match-byte-array-patterns-2.stderr (100%) rename src/test/ui/{match => pattern/usefulness}/match-byte-array-patterns.rs (100%) rename src/test/ui/{match => pattern/usefulness}/match-byte-array-patterns.stderr (100%) rename src/test/ui/{match => pattern/usefulness}/match-non-exhaustive.rs (100%) rename src/test/ui/{match => pattern/usefulness}/match-non-exhaustive.stderr (100%) rename src/test/ui/{match => pattern/usefulness}/match-privately-empty.rs (100%) rename src/test/ui/{match => pattern/usefulness}/match-privately-empty.stderr (100%) rename src/test/ui/{match => pattern/usefulness}/match-range-fail-dominate.rs (100%) rename src/test/ui/{match => pattern/usefulness}/match-range-fail-dominate.stderr (100%) rename src/test/ui/{match => pattern/usefulness}/match-ref-ice.rs (100%) rename src/test/ui/{match => pattern/usefulness}/match-ref-ice.stderr (100%) rename src/test/ui/{match => pattern/usefulness}/match-slice-patterns.rs (100%) rename src/test/ui/{match => pattern/usefulness}/match-slice-patterns.stderr (100%) rename src/test/ui/{match => pattern/usefulness}/match-vec-fixed.rs (100%) rename src/test/ui/{match => pattern/usefulness}/match-vec-fixed.stderr (100%) rename src/test/ui/{match => pattern/usefulness}/match-vec-unreachable.rs (100%) rename src/test/ui/{match => pattern/usefulness}/match-vec-unreachable.stderr (100%) rename src/test/ui/{binding => pattern/usefulness}/nested-exhaustive-match.rs (100%) rename src/test/ui/{match => pattern/usefulness}/non-exhaustive-defined-here.rs (100%) rename src/test/ui/{match => pattern/usefulness}/non-exhaustive-defined-here.stderr (100%) rename src/test/ui/{non-exhaustive => pattern/usefulness}/non-exhaustive-float-range-match.rs (100%) rename src/test/ui/{non-exhaustive => pattern/usefulness}/non-exhaustive-float-range-match.stderr (100%) rename src/test/ui/{non-exhaustive => pattern/usefulness}/non-exhaustive-match-nested.rs (100%) rename src/test/ui/{non-exhaustive => pattern/usefulness}/non-exhaustive-match-nested.stderr (100%) rename src/test/ui/{non-exhaustive => pattern/usefulness}/non-exhaustive-match.rs (100%) rename src/test/ui/{non-exhaustive => pattern/usefulness}/non-exhaustive-match.stderr (100%) rename src/test/ui/{non-exhaustive => pattern/usefulness}/non-exhaustive-pattern-witness.rs (100%) rename src/test/ui/{non-exhaustive => pattern/usefulness}/non-exhaustive-pattern-witness.stderr (100%) rename src/test/ui/{ => pattern/usefulness}/refutable-pattern-errors.rs (100%) rename src/test/ui/{ => pattern/usefulness}/refutable-pattern-errors.stderr (100%) rename src/test/ui/{ => pattern/usefulness}/refutable-pattern-in-fn-arg.rs (100%) rename src/test/ui/{ => pattern/usefulness}/refutable-pattern-in-fn-arg.stderr (100%) rename src/test/ui/{structs => pattern/usefulness}/struct-like-enum-nonexhaustive.rs (100%) rename src/test/ui/{structs => pattern/usefulness}/struct-like-enum-nonexhaustive.stderr (100%) rename src/test/ui/{structs => pattern/usefulness}/struct-pattern-match-useless.rs (100%) rename src/test/ui/{structs => pattern/usefulness}/struct-pattern-match-useless.stderr (100%) rename src/test/ui/{tuple => pattern/usefulness}/tuple-struct-nonexhaustive.rs (100%) rename src/test/ui/{tuple => pattern/usefulness}/tuple-struct-nonexhaustive.stderr (100%) diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 907c84b6f8cf0..0009524ef6f93 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -1,3 +1,6 @@ +/// Note: most tests relevant to this file can be found (at the time of writing) +/// in src/tests/ui/pattern/usefulness. +/// /// This file includes the logic for exhaustiveness and usefulness checking for /// pattern-matching. Specifically, given a list of patterns for a type, we can /// tell whether: diff --git a/src/test/ui/uninhabited/always-inhabited-union-ref.rs b/src/test/ui/pattern/usefulness/always-inhabited-union-ref.rs similarity index 100% rename from src/test/ui/uninhabited/always-inhabited-union-ref.rs rename to src/test/ui/pattern/usefulness/always-inhabited-union-ref.rs diff --git a/src/test/ui/uninhabited/always-inhabited-union-ref.stderr b/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr similarity index 100% rename from src/test/ui/uninhabited/always-inhabited-union-ref.stderr rename to src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr diff --git a/src/test/ui/exhaustive_integer_patterns.rs b/src/test/ui/pattern/usefulness/exhaustive_integer_patterns.rs similarity index 100% rename from src/test/ui/exhaustive_integer_patterns.rs rename to src/test/ui/pattern/usefulness/exhaustive_integer_patterns.rs diff --git a/src/test/ui/exhaustive_integer_patterns.stderr b/src/test/ui/pattern/usefulness/exhaustive_integer_patterns.stderr similarity index 100% rename from src/test/ui/exhaustive_integer_patterns.stderr rename to src/test/ui/pattern/usefulness/exhaustive_integer_patterns.stderr diff --git a/src/test/ui/guards-not-exhaustive.rs b/src/test/ui/pattern/usefulness/guards-not-exhaustive.rs similarity index 100% rename from src/test/ui/guards-not-exhaustive.rs rename to src/test/ui/pattern/usefulness/guards-not-exhaustive.rs diff --git a/src/test/ui/pattern/irrefutable-exhaustive-integer-binding.rs b/src/test/ui/pattern/usefulness/irrefutable-exhaustive-integer-binding.rs similarity index 100% rename from src/test/ui/pattern/irrefutable-exhaustive-integer-binding.rs rename to src/test/ui/pattern/usefulness/irrefutable-exhaustive-integer-binding.rs diff --git a/src/test/ui/irrefutable-unit.rs b/src/test/ui/pattern/usefulness/irrefutable-unit.rs similarity index 100% rename from src/test/ui/irrefutable-unit.rs rename to src/test/ui/pattern/usefulness/irrefutable-unit.rs diff --git a/src/test/ui/check_match/issue-35609.rs b/src/test/ui/pattern/usefulness/issue-35609.rs similarity index 100% rename from src/test/ui/check_match/issue-35609.rs rename to src/test/ui/pattern/usefulness/issue-35609.rs diff --git a/src/test/ui/check_match/issue-35609.stderr b/src/test/ui/pattern/usefulness/issue-35609.stderr similarity index 100% rename from src/test/ui/check_match/issue-35609.stderr rename to src/test/ui/pattern/usefulness/issue-35609.stderr diff --git a/src/test/ui/check_match/issue-43253.rs b/src/test/ui/pattern/usefulness/issue-43253.rs similarity index 100% rename from src/test/ui/check_match/issue-43253.rs rename to src/test/ui/pattern/usefulness/issue-43253.rs diff --git a/src/test/ui/check_match/issue-43253.stderr b/src/test/ui/pattern/usefulness/issue-43253.stderr similarity index 100% rename from src/test/ui/check_match/issue-43253.stderr rename to src/test/ui/pattern/usefulness/issue-43253.stderr diff --git a/src/test/ui/match/match-argm-statics-2.rs b/src/test/ui/pattern/usefulness/match-arm-statics-2.rs similarity index 100% rename from src/test/ui/match/match-argm-statics-2.rs rename to src/test/ui/pattern/usefulness/match-arm-statics-2.rs diff --git a/src/test/ui/match/match-argm-statics-2.stderr b/src/test/ui/pattern/usefulness/match-arm-statics-2.stderr similarity index 90% rename from src/test/ui/match/match-argm-statics-2.stderr rename to src/test/ui/pattern/usefulness/match-arm-statics-2.stderr index 8c54e030823af..8521e37d3fddc 100644 --- a/src/test/ui/match/match-argm-statics-2.stderr +++ b/src/test/ui/pattern/usefulness/match-arm-statics-2.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: `(true, false)` not covered - --> $DIR/match-argm-statics-2.rs:17:11 + --> $DIR/match-arm-statics-2.rs:17:11 | LL | match (true, false) { | ^^^^^^^^^^^^^ pattern `(true, false)` not covered @@ -7,7 +7,7 @@ LL | match (true, false) { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `Some(Some(West))` not covered - --> $DIR/match-argm-statics-2.rs:29:11 + --> $DIR/match-arm-statics-2.rs:29:11 | LL | match Some(Some(North)) { | ^^^^^^^^^^^^^^^^^ pattern `Some(Some(West))` not covered @@ -15,7 +15,7 @@ LL | match Some(Some(North)) { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `Foo { bar: Some(North), baz: NewBool(true) }` not covered - --> $DIR/match-argm-statics-2.rs:48:11 + --> $DIR/match-arm-statics-2.rs:48:11 | LL | / struct Foo { LL | | bar: Option, diff --git a/src/test/ui/match/match-arm-statics.rs b/src/test/ui/pattern/usefulness/match-arm-statics.rs similarity index 100% rename from src/test/ui/match/match-arm-statics.rs rename to src/test/ui/pattern/usefulness/match-arm-statics.rs diff --git a/src/test/ui/match/match-arm-statics.stderr b/src/test/ui/pattern/usefulness/match-arm-statics.stderr similarity index 100% rename from src/test/ui/match/match-arm-statics.stderr rename to src/test/ui/pattern/usefulness/match-arm-statics.stderr diff --git a/src/test/ui/match/match-byte-array-patterns-2.rs b/src/test/ui/pattern/usefulness/match-byte-array-patterns-2.rs similarity index 100% rename from src/test/ui/match/match-byte-array-patterns-2.rs rename to src/test/ui/pattern/usefulness/match-byte-array-patterns-2.rs diff --git a/src/test/ui/match/match-byte-array-patterns-2.stderr b/src/test/ui/pattern/usefulness/match-byte-array-patterns-2.stderr similarity index 100% rename from src/test/ui/match/match-byte-array-patterns-2.stderr rename to src/test/ui/pattern/usefulness/match-byte-array-patterns-2.stderr diff --git a/src/test/ui/match/match-byte-array-patterns.rs b/src/test/ui/pattern/usefulness/match-byte-array-patterns.rs similarity index 100% rename from src/test/ui/match/match-byte-array-patterns.rs rename to src/test/ui/pattern/usefulness/match-byte-array-patterns.rs diff --git a/src/test/ui/match/match-byte-array-patterns.stderr b/src/test/ui/pattern/usefulness/match-byte-array-patterns.stderr similarity index 100% rename from src/test/ui/match/match-byte-array-patterns.stderr rename to src/test/ui/pattern/usefulness/match-byte-array-patterns.stderr diff --git a/src/test/ui/match/match-non-exhaustive.rs b/src/test/ui/pattern/usefulness/match-non-exhaustive.rs similarity index 100% rename from src/test/ui/match/match-non-exhaustive.rs rename to src/test/ui/pattern/usefulness/match-non-exhaustive.rs diff --git a/src/test/ui/match/match-non-exhaustive.stderr b/src/test/ui/pattern/usefulness/match-non-exhaustive.stderr similarity index 100% rename from src/test/ui/match/match-non-exhaustive.stderr rename to src/test/ui/pattern/usefulness/match-non-exhaustive.stderr diff --git a/src/test/ui/match/match-privately-empty.rs b/src/test/ui/pattern/usefulness/match-privately-empty.rs similarity index 100% rename from src/test/ui/match/match-privately-empty.rs rename to src/test/ui/pattern/usefulness/match-privately-empty.rs diff --git a/src/test/ui/match/match-privately-empty.stderr b/src/test/ui/pattern/usefulness/match-privately-empty.stderr similarity index 100% rename from src/test/ui/match/match-privately-empty.stderr rename to src/test/ui/pattern/usefulness/match-privately-empty.stderr diff --git a/src/test/ui/match/match-range-fail-dominate.rs b/src/test/ui/pattern/usefulness/match-range-fail-dominate.rs similarity index 100% rename from src/test/ui/match/match-range-fail-dominate.rs rename to src/test/ui/pattern/usefulness/match-range-fail-dominate.rs diff --git a/src/test/ui/match/match-range-fail-dominate.stderr b/src/test/ui/pattern/usefulness/match-range-fail-dominate.stderr similarity index 100% rename from src/test/ui/match/match-range-fail-dominate.stderr rename to src/test/ui/pattern/usefulness/match-range-fail-dominate.stderr diff --git a/src/test/ui/match/match-ref-ice.rs b/src/test/ui/pattern/usefulness/match-ref-ice.rs similarity index 100% rename from src/test/ui/match/match-ref-ice.rs rename to src/test/ui/pattern/usefulness/match-ref-ice.rs diff --git a/src/test/ui/match/match-ref-ice.stderr b/src/test/ui/pattern/usefulness/match-ref-ice.stderr similarity index 100% rename from src/test/ui/match/match-ref-ice.stderr rename to src/test/ui/pattern/usefulness/match-ref-ice.stderr diff --git a/src/test/ui/match/match-slice-patterns.rs b/src/test/ui/pattern/usefulness/match-slice-patterns.rs similarity index 100% rename from src/test/ui/match/match-slice-patterns.rs rename to src/test/ui/pattern/usefulness/match-slice-patterns.rs diff --git a/src/test/ui/match/match-slice-patterns.stderr b/src/test/ui/pattern/usefulness/match-slice-patterns.stderr similarity index 100% rename from src/test/ui/match/match-slice-patterns.stderr rename to src/test/ui/pattern/usefulness/match-slice-patterns.stderr diff --git a/src/test/ui/match/match-vec-fixed.rs b/src/test/ui/pattern/usefulness/match-vec-fixed.rs similarity index 100% rename from src/test/ui/match/match-vec-fixed.rs rename to src/test/ui/pattern/usefulness/match-vec-fixed.rs diff --git a/src/test/ui/match/match-vec-fixed.stderr b/src/test/ui/pattern/usefulness/match-vec-fixed.stderr similarity index 100% rename from src/test/ui/match/match-vec-fixed.stderr rename to src/test/ui/pattern/usefulness/match-vec-fixed.stderr diff --git a/src/test/ui/match/match-vec-unreachable.rs b/src/test/ui/pattern/usefulness/match-vec-unreachable.rs similarity index 100% rename from src/test/ui/match/match-vec-unreachable.rs rename to src/test/ui/pattern/usefulness/match-vec-unreachable.rs diff --git a/src/test/ui/match/match-vec-unreachable.stderr b/src/test/ui/pattern/usefulness/match-vec-unreachable.stderr similarity index 100% rename from src/test/ui/match/match-vec-unreachable.stderr rename to src/test/ui/pattern/usefulness/match-vec-unreachable.stderr diff --git a/src/test/ui/binding/nested-exhaustive-match.rs b/src/test/ui/pattern/usefulness/nested-exhaustive-match.rs similarity index 100% rename from src/test/ui/binding/nested-exhaustive-match.rs rename to src/test/ui/pattern/usefulness/nested-exhaustive-match.rs diff --git a/src/test/ui/match/non-exhaustive-defined-here.rs b/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.rs similarity index 100% rename from src/test/ui/match/non-exhaustive-defined-here.rs rename to src/test/ui/pattern/usefulness/non-exhaustive-defined-here.rs diff --git a/src/test/ui/match/non-exhaustive-defined-here.stderr b/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.stderr similarity index 100% rename from src/test/ui/match/non-exhaustive-defined-here.stderr rename to src/test/ui/pattern/usefulness/non-exhaustive-defined-here.stderr diff --git a/src/test/ui/non-exhaustive/non-exhaustive-float-range-match.rs b/src/test/ui/pattern/usefulness/non-exhaustive-float-range-match.rs similarity index 100% rename from src/test/ui/non-exhaustive/non-exhaustive-float-range-match.rs rename to src/test/ui/pattern/usefulness/non-exhaustive-float-range-match.rs diff --git a/src/test/ui/non-exhaustive/non-exhaustive-float-range-match.stderr b/src/test/ui/pattern/usefulness/non-exhaustive-float-range-match.stderr similarity index 100% rename from src/test/ui/non-exhaustive/non-exhaustive-float-range-match.stderr rename to src/test/ui/pattern/usefulness/non-exhaustive-float-range-match.stderr diff --git a/src/test/ui/non-exhaustive/non-exhaustive-match-nested.rs b/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.rs similarity index 100% rename from src/test/ui/non-exhaustive/non-exhaustive-match-nested.rs rename to src/test/ui/pattern/usefulness/non-exhaustive-match-nested.rs diff --git a/src/test/ui/non-exhaustive/non-exhaustive-match-nested.stderr b/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.stderr similarity index 100% rename from src/test/ui/non-exhaustive/non-exhaustive-match-nested.stderr rename to src/test/ui/pattern/usefulness/non-exhaustive-match-nested.stderr diff --git a/src/test/ui/non-exhaustive/non-exhaustive-match.rs b/src/test/ui/pattern/usefulness/non-exhaustive-match.rs similarity index 100% rename from src/test/ui/non-exhaustive/non-exhaustive-match.rs rename to src/test/ui/pattern/usefulness/non-exhaustive-match.rs diff --git a/src/test/ui/non-exhaustive/non-exhaustive-match.stderr b/src/test/ui/pattern/usefulness/non-exhaustive-match.stderr similarity index 100% rename from src/test/ui/non-exhaustive/non-exhaustive-match.stderr rename to src/test/ui/pattern/usefulness/non-exhaustive-match.stderr diff --git a/src/test/ui/non-exhaustive/non-exhaustive-pattern-witness.rs b/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.rs similarity index 100% rename from src/test/ui/non-exhaustive/non-exhaustive-pattern-witness.rs rename to src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.rs diff --git a/src/test/ui/non-exhaustive/non-exhaustive-pattern-witness.stderr b/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr similarity index 100% rename from src/test/ui/non-exhaustive/non-exhaustive-pattern-witness.stderr rename to src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr diff --git a/src/test/ui/refutable-pattern-errors.rs b/src/test/ui/pattern/usefulness/refutable-pattern-errors.rs similarity index 100% rename from src/test/ui/refutable-pattern-errors.rs rename to src/test/ui/pattern/usefulness/refutable-pattern-errors.rs diff --git a/src/test/ui/refutable-pattern-errors.stderr b/src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr similarity index 100% rename from src/test/ui/refutable-pattern-errors.stderr rename to src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr diff --git a/src/test/ui/refutable-pattern-in-fn-arg.rs b/src/test/ui/pattern/usefulness/refutable-pattern-in-fn-arg.rs similarity index 100% rename from src/test/ui/refutable-pattern-in-fn-arg.rs rename to src/test/ui/pattern/usefulness/refutable-pattern-in-fn-arg.rs diff --git a/src/test/ui/refutable-pattern-in-fn-arg.stderr b/src/test/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr similarity index 100% rename from src/test/ui/refutable-pattern-in-fn-arg.stderr rename to src/test/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr diff --git a/src/test/ui/structs/struct-like-enum-nonexhaustive.rs b/src/test/ui/pattern/usefulness/struct-like-enum-nonexhaustive.rs similarity index 100% rename from src/test/ui/structs/struct-like-enum-nonexhaustive.rs rename to src/test/ui/pattern/usefulness/struct-like-enum-nonexhaustive.rs diff --git a/src/test/ui/structs/struct-like-enum-nonexhaustive.stderr b/src/test/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr similarity index 100% rename from src/test/ui/structs/struct-like-enum-nonexhaustive.stderr rename to src/test/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr diff --git a/src/test/ui/structs/struct-pattern-match-useless.rs b/src/test/ui/pattern/usefulness/struct-pattern-match-useless.rs similarity index 100% rename from src/test/ui/structs/struct-pattern-match-useless.rs rename to src/test/ui/pattern/usefulness/struct-pattern-match-useless.rs diff --git a/src/test/ui/structs/struct-pattern-match-useless.stderr b/src/test/ui/pattern/usefulness/struct-pattern-match-useless.stderr similarity index 100% rename from src/test/ui/structs/struct-pattern-match-useless.stderr rename to src/test/ui/pattern/usefulness/struct-pattern-match-useless.stderr diff --git a/src/test/ui/tuple/tuple-struct-nonexhaustive.rs b/src/test/ui/pattern/usefulness/tuple-struct-nonexhaustive.rs similarity index 100% rename from src/test/ui/tuple/tuple-struct-nonexhaustive.rs rename to src/test/ui/pattern/usefulness/tuple-struct-nonexhaustive.rs diff --git a/src/test/ui/tuple/tuple-struct-nonexhaustive.stderr b/src/test/ui/pattern/usefulness/tuple-struct-nonexhaustive.stderr similarity index 100% rename from src/test/ui/tuple/tuple-struct-nonexhaustive.stderr rename to src/test/ui/pattern/usefulness/tuple-struct-nonexhaustive.stderr