diff options
52 files changed, 586 insertions, 422 deletions
diff --git a/Cargo.lock b/Cargo.lock index 6885ac65ca9..0aa132fe29a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -646,9 +646,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.46" +version = "0.1.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d69484e04eab372f5f345920e3a8c7a06e7dcbb75c0944eccdc3e3160aeee3c7" +checksum = "fd4ed89e0a5c3e50b15c0045fbe1ff8567b703bc07544faf935ddff0aaa7b65f" dependencies = [ "cc", "rustc-std-workspace-core", diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs index 71bbae1161b..a8c61d53346 100644 --- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs +++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs @@ -5,7 +5,7 @@ use rustc_ast::ptr::P; use rustc_ast::visit::{self, Visitor}; use rustc_ast::{self as ast, NodeId}; use rustc_ast_pretty::pprust; -use rustc_expand::base::{ExtCtxt, ResolverExpand}; +use rustc_expand::base::{parse_macro_name_and_helper_attrs, ExtCtxt, ResolverExpand}; use rustc_expand::expand::{AstFragment, ExpansionConfig}; use rustc_session::Session; use rustc_span::hygiene::AstPass; @@ -109,86 +109,17 @@ impl<'a> CollectProcMacros<'a> { } fn collect_custom_derive(&mut self, item: &'a ast::Item, attr: &'a ast::Attribute) { - // Once we've located the `#[proc_macro_derive]` attribute, verify - // that it's of the form `#[proc_macro_derive(Foo)]` or - // `#[proc_macro_derive(Foo, attributes(A, ..))]` - let list = match attr.meta_item_list() { - Some(list) => list, - None => return, - }; - if list.len() != 1 && list.len() != 2 { - self.handler.span_err(attr.span, "attribute must have either one or two arguments"); - return; - } - let trait_attr = match list[0].meta_item() { - Some(meta_item) => meta_item, - _ => { - self.handler.span_err(list[0].span(), "not a meta item"); - return; - } - }; - let trait_ident = match trait_attr.ident() { - Some(trait_ident) if trait_attr.is_word() => trait_ident, - _ => { - self.handler.span_err(trait_attr.span, "must only be one word"); - return; - } - }; - - if !trait_ident.name.can_be_raw() { - self.handler.span_err( - trait_attr.span, - &format!("`{}` cannot be a name of derive macro", trait_ident), - ); - } - - let attributes_attr = list.get(1); - let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr { - if !attr.has_name(sym::attributes) { - self.handler.span_err(attr.span(), "second argument must be `attributes`") - } - attr.meta_item_list() - .unwrap_or_else(|| { - self.handler - .span_err(attr.span(), "attribute must be of form: `attributes(foo, bar)`"); - &[] - }) - .iter() - .filter_map(|attr| { - let attr = match attr.meta_item() { - Some(meta_item) => meta_item, - _ => { - self.handler.span_err(attr.span(), "not a meta item"); - return None; - } - }; - - let ident = match attr.ident() { - Some(ident) if attr.is_word() => ident, - _ => { - self.handler.span_err(attr.span, "must only be one word"); - return None; - } - }; - if !ident.name.can_be_raw() { - self.handler.span_err( - attr.span, - &format!("`{}` cannot be a name of derive helper attribute", ident), - ); - } - - Some(ident.name) - }) - .collect() - } else { - Vec::new() - }; + let (trait_name, proc_attrs) = + match parse_macro_name_and_helper_attrs(self.handler, attr, "derive") { + Some(name_and_attrs) => name_and_attrs, + None => return, + }; if self.in_root && item.vis.kind.is_pub() { self.macros.push(ProcMacro::Derive(ProcMacroDerive { id: item.id, span: item.span, - trait_name: trait_ident.name, + trait_name, function_name: item.ident, attrs: proc_attrs, })); diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index b3c14d9072c..25268d9a555 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -12,12 +12,15 @@ // * `"` is treated as the start of a string. use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData}; +use rustc_middle::ich::NodeIdHashingMode; +use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt}; -use rustc_target::abi::{TagEncoding, Variants}; +use rustc_target::abi::{Integer, TagEncoding, Variants}; use std::fmt::Write; @@ -47,7 +50,7 @@ pub fn push_debuginfo_type_name<'tcx>( ) { // When targeting MSVC, emit C++ style type names for compatibility with // .natvis visualizers (and perhaps other existing native debuggers?) - let cpp_like_names = tcx.sess.target.is_like_msvc; + let cpp_like_names = cpp_like_names(tcx); match *t.kind() { ty::Bool => output.push_str("bool"), @@ -424,8 +427,6 @@ fn push_unqualified_item_name( disambiguated_data: DisambiguatedDefPathData, output: &mut String, ) { - let cpp_like_names = tcx.sess.target.is_like_msvc; - match disambiguated_data.data { DefPathData::CrateRoot => { output.push_str(&tcx.crate_name(def_id.krate).as_str()); @@ -433,7 +434,7 @@ fn push_unqualified_item_name( DefPathData::ClosureExpr if tcx.generator_kind(def_id).is_some() => { // Generators look like closures, but we want to treat them differently // in the debug info. - if cpp_like_names { + if cpp_like_names(tcx) { write!(output, "generator${}", disambiguated_data.disambiguator).unwrap(); } else { write!(output, "{{generator#{}}}", disambiguated_data.disambiguator).unwrap(); @@ -444,7 +445,7 @@ fn push_unqualified_item_name( output.push_str(&name.as_str()); } DefPathDataName::Anon { namespace } => { - if cpp_like_names { + if cpp_like_names(tcx) { write!(output, "{}${}", namespace, disambiguated_data.disambiguator).unwrap(); } else { write!(output, "{{{}#{}}}", namespace, disambiguated_data.disambiguator) @@ -478,19 +479,14 @@ fn push_generic_params_internal<'tcx>( match type_parameter { GenericArgKind::Type(type_parameter) => { push_debuginfo_type_name(tcx, type_parameter, true, output, visited); - output.push_str(", "); - } - GenericArgKind::Const(const_parameter) => match const_parameter.val { - ty::ConstKind::Param(param) => write!(output, "{}, ", param.name).unwrap(), - _ => write!( - output, - "0x{:x}, ", - const_parameter.eval_bits(tcx, ty::ParamEnv::reveal_all(), const_parameter.ty) - ) - .unwrap(), - }, + } + GenericArgKind::Const(ct) => { + push_const_param(tcx, ct, output); + } other => bug!("Unexpected non-erasable generic: {:?}", other), } + + output.push_str(", "); } output.pop(); @@ -499,6 +495,51 @@ fn push_generic_params_internal<'tcx>( push_close_angle_bracket(tcx, output); } +fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: &'tcx ty::Const<'tcx>, output: &mut String) { + match ct.val { + ty::ConstKind::Param(param) => { + write!(output, "{}", param.name) + } + _ => match ct.ty.kind() { + ty::Int(ity) => { + let bits = ct.eval_bits(tcx, ty::ParamEnv::reveal_all(), ct.ty); + let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128; + write!(output, "{}", val) + } + ty::Uint(_) => { + let val = ct.eval_bits(tcx, ty::ParamEnv::reveal_all(), ct.ty); + write!(output, "{}", val) + } + ty::Bool => { + let val = ct.try_eval_bool(tcx, ty::ParamEnv::reveal_all()).unwrap(); + write!(output, "{}", val) + } + _ => { + // If we cannot evaluate the constant to a known type, we fall back + // to emitting a stable hash value of the constant. This isn't very pretty + // but we get a deterministic, virtually unique value for the constant. + let hcx = &mut tcx.create_stable_hashing_context(); + let mut hasher = StableHasher::new(); + hcx.while_hashing_spans(false, |hcx| { + hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { + ct.val.hash_stable(hcx, &mut hasher); + }); + }); + // Let's only emit 64 bits of the hash value. That should be plenty for + // avoiding collisions and will make the emitted type names shorter. + let hash: u64 = hasher.finish(); + + if cpp_like_names(tcx) { + write!(output, "CONST${:x}", hash) + } else { + write!(output, "{{CONST#{:x}}}", hash) + } + } + }, + } + .unwrap(); +} + pub fn push_generic_params<'tcx>(tcx: TyCtxt<'tcx>, substs: SubstsRef<'tcx>, output: &mut String) { let mut visited = FxHashSet::default(); push_generic_params_internal(tcx, substs, output, &mut visited); @@ -507,9 +548,13 @@ pub fn push_generic_params<'tcx>(tcx: TyCtxt<'tcx>, substs: SubstsRef<'tcx>, out fn push_close_angle_bracket<'tcx>(tcx: TyCtxt<'tcx>, output: &mut String) { // MSVC debugger always treats `>>` as a shift, even when parsing templates, // so add a space to avoid confusion. - if tcx.sess.target.is_like_msvc && output.ends_with('>') { + if cpp_like_names(tcx) && output.ends_with('>') { output.push(' ') }; output.push('>'); } + +fn cpp_like_names(tcx: TyCtxt<'_>) -> bool { + tcx.sess.target.is_like_msvc +} diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index b3e52502b07..0183add4957 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -745,9 +745,17 @@ impl SyntaxExtension { } } - let builtin_name = sess + let (builtin_name, helper_attrs) = sess .find_by_name(attrs, sym::rustc_builtin_macro) - .map(|a| a.value_str().unwrap_or(name)); + .map(|attr| { + // Override `helper_attrs` passed above if it's a built-in macro, + // marking `proc_macro_derive` macros as built-in is not a realistic use case. + parse_macro_name_and_helper_attrs(sess.diagnostic(), attr, "built-in").map_or_else( + || (Some(name), Vec::new()), + |(name, helper_attrs)| (Some(name), helper_attrs), + ) + }) + .unwrap_or_else(|| (None, helper_attrs)); let (stability, const_stability) = attr::find_stability(&sess, attrs, span); if let Some((_, sp)) = const_stability { sess.parse_sess @@ -1213,6 +1221,88 @@ pub fn get_exprs_from_tts( Some(es) } +pub fn parse_macro_name_and_helper_attrs( + diag: &rustc_errors::Handler, + attr: &Attribute, + descr: &str, +) -> Option<(Symbol, Vec<Symbol>)> { + // Once we've located the `#[proc_macro_derive]` attribute, verify + // that it's of the form `#[proc_macro_derive(Foo)]` or + // `#[proc_macro_derive(Foo, attributes(A, ..))]` + let list = match attr.meta_item_list() { + Some(list) => list, + None => return None, + }; + if list.len() != 1 && list.len() != 2 { + diag.span_err(attr.span, "attribute must have either one or two arguments"); + return None; + } + let trait_attr = match list[0].meta_item() { + Some(meta_item) => meta_item, + _ => { + diag.span_err(list[0].span(), "not a meta item"); + return None; + } + }; + let trait_ident = match trait_attr.ident() { + Some(trait_ident) if trait_attr.is_word() => trait_ident, + _ => { + diag.span_err(trait_attr.span, "must only be one word"); + return None; + } + }; + + if !trait_ident.name.can_be_raw() { + diag.span_err( + trait_attr.span, + &format!("`{}` cannot be a name of {} macro", trait_ident, descr), + ); + } + + let attributes_attr = list.get(1); + let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr { + if !attr.has_name(sym::attributes) { + diag.span_err(attr.span(), "second argument must be `attributes`") + } + attr.meta_item_list() + .unwrap_or_else(|| { + diag.span_err(attr.span(), "attribute must be of form: `attributes(foo, bar)`"); + &[] + }) + .iter() + .filter_map(|attr| { + let attr = match attr.meta_item() { + Some(meta_item) => meta_item, + _ => { + diag.span_err(attr.span(), "not a meta item"); + return None; + } + }; + + let ident = match attr.ident() { + Some(ident) if attr.is_word() => ident, + _ => { + diag.span_err(attr.span, "must only be one word"); + return None; + } + }; + if !ident.name.can_be_raw() { + diag.span_err( + attr.span, + &format!("`{}` cannot be a name of derive helper attribute", ident), + ); + } + + Some(ident.name) + }) + .collect() + } else { + Vec::new() + }; + + Some((trait_ident.name, proc_attrs)) +} + /// This nonterminal looks like some specific enums from /// `proc-macro-hack` and `procedural-masquerade` crates. /// We need to maintain some special pretty-printing behavior for them due to incorrect diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 77d8f0f920c..b1c725ecd85 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -448,7 +448,11 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // Internal attributes, Macro related: // ========================================================================== - rustc_attr!(rustc_builtin_macro, AssumedUsed, template!(Word, NameValueStr: "name"), IMPL_DETAIL), + rustc_attr!( + rustc_builtin_macro, AssumedUsed, + template!(Word, List: "name, /*opt*/ attributes(name1, name2, ...)"), + IMPL_DETAIL, + ), rustc_attr!(rustc_proc_macro_decls, Normal, template!(Word), INTERNAL_UNSTABLE), rustc_attr!( rustc_macro_transparency, AssumedUsed, diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index e568b5ca501..958a4ab6802 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -18,7 +18,7 @@ use rustc_metadata::creader::CStore; use rustc_middle::arena::Arena; use rustc_middle::dep_graph::DepGraph; use rustc_middle::middle; -use rustc_middle::middle::cstore::{CrateStore, MetadataLoader, MetadataLoaderDyn}; +use rustc_middle::middle::cstore::{MetadataLoader, MetadataLoaderDyn}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, GlobalCtxt, ResolverOutputs, TyCtxt}; use rustc_mir as mir; @@ -860,11 +860,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { tcx.ensure().proc_macro_decls_static(()) }); - let cstore = tcx - .cstore_as_any() - .downcast_ref::<CStore>() - .expect("`tcx.cstore` is not a `CStore`"); - cstore.report_unused_deps(tcx); + CStore::from_tcx(tcx).report_unused_deps(tcx); }, { par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| { diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index a053253ec16..5a362a37f2b 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -633,6 +633,7 @@ fn test_debugging_options_tracking_hash() { untracked!(dump_mir_graphviz, true); untracked!(emit_future_incompat_report, true); untracked!(emit_stack_sizes, true); + untracked!(future_incompat_test, true); untracked!(hir_stats, true); untracked!(identify_regions, true); untracked!(incremental_ignore_spans, true); diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 250af3c6e89..70b3efa1d16 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -130,7 +130,7 @@ impl<'a> std::fmt::Debug for CrateDump<'a> { } impl CStore { - crate fn from_tcx(tcx: TyCtxt<'_>) -> &CStore { + pub fn from_tcx(tcx: TyCtxt<'_>) -> &CStore { tcx.cstore_as_any().downcast_ref::<CStore>().expect("`tcx.cstore` is not a `CStore`") } @@ -599,7 +599,11 @@ impl<'a> CrateLoader<'a> { // don't want to match a host crate against an equivalent target one // already loaded. let root = library.metadata.get_root(); - Ok(Some(if locator.triple == self.sess.opts.target_triple { + // FIXME: why is this condition necessary? It was adding in #33625 but I + // don't know why and the original author doesn't remember ... + let can_reuse_cratenum = + locator.triple == self.sess.opts.target_triple || locator.is_proc_macro == Some(true); + Ok(Some(if can_reuse_cratenum { let mut result = LoadResult::Loaded(library); self.cstore.iter_crate_data(|cnum, data| { if data.name() == root.name() && root.hash() == data.hash() { diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index d96034c951c..ce8dfeae076 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -5,7 +5,6 @@ use crate::rmeta::encoder; use rustc_ast as ast; use rustc_data_structures::stable_map::FxHashMap; -use rustc_data_structures::svh::Svh; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE}; @@ -369,6 +368,7 @@ pub fn provide(providers: &mut Providers) { tcx.arena .alloc_slice(&CStore::from_tcx(tcx).crate_dependencies_in_postorder(LOCAL_CRATE)) }, + crates: |tcx, ()| tcx.arena.alloc_slice(&CStore::from_tcx(tcx).crates_untracked()), ..*providers }; @@ -451,6 +451,16 @@ impl CStore { self.get_crate_data(def_id.krate).get_span(def_id.index, sess) } + pub fn def_kind(&self, def: DefId) -> DefKind { + self.get_crate_data(def.krate).def_kind(def.index) + } + + pub fn crates_untracked(&self) -> Vec<CrateNum> { + let mut result = vec![]; + self.iter_crate_data(|cnum, _| result.push(cnum)); + result + } + pub fn item_generics_num_lifetimes(&self, def_id: DefId, sess: &Session) -> usize { self.get_crate_data(def_id.krate).get_generics(def_id.index, sess).own_counts().lifetimes } @@ -485,18 +495,14 @@ impl CrateStore for CStore { self } - fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol { + fn crate_name(&self, cnum: CrateNum) -> Symbol { self.get_crate_data(cnum).root.name } - fn stable_crate_id_untracked(&self, cnum: CrateNum) -> StableCrateId { + fn stable_crate_id(&self, cnum: CrateNum) -> StableCrateId { self.get_crate_data(cnum).root.stable_crate_id } - fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh { - self.get_crate_data(cnum).root.hash - } - /// Returns the `DefKey` for a given `DefId`. This indicates the /// parent `DefId` as well as some idea of what kind of data the /// `DefId` refers to. @@ -504,10 +510,6 @@ impl CrateStore for CStore { self.get_crate_data(def.krate).def_key(def.index) } - fn def_kind(&self, def: DefId) -> DefKind { - self.get_crate_data(def.krate).def_kind(def.index) - } - fn def_path(&self, def: DefId) -> DefPath { self.get_crate_data(def.krate).def_path(def.index) } @@ -526,12 +528,6 @@ impl CrateStore for CStore { self.get_crate_data(cnum).def_path_hash_to_def_id(cnum, index_guess, hash) } - fn crates_untracked(&self) -> Vec<CrateNum> { - let mut result = vec![]; - self.iter_crate_data(|cnum, _| result.push(cnum)); - result - } - fn encode_metadata(&self, tcx: TyCtxt<'_>) -> EncodedMetadata { encoder::encode_metadata(tcx) } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 602e1fd822c..5c7d84e2bc9 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1061,10 +1061,7 @@ impl EncodeContext<'a, 'tcx> { Lazy::empty() }; - let data = ModData { - reexports, - expansion: tcx.resolutions(()).definitions.expansion_that_defined(local_def_id), - }; + let data = ModData { reexports, expansion: tcx.expn_that_defined(local_def_id) }; record!(self.tables.kind[def_id] <- EntryKind::Mod(self.lazy(data))); if self.is_proc_macro { diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 5c32c0fdb6c..ae53f1ac3bb 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -1,7 +1,6 @@ use self::collector::NodeCollector; use crate::hir::{AttributeMap, IndexedHir}; -use crate::middle::cstore::CrateStore; use crate::ty::TyCtxt; use rustc_ast as ast; use rustc_data_structures::fingerprint::Fingerprint; @@ -991,7 +990,7 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh { }, ); - let upstream_crates = upstream_crates(&*tcx.untracked_resolutions.cstore); + let upstream_crates = upstream_crates(tcx); // We hash the final, remapped names of all local source files so we // don't have to include the path prefix remapping commandline args. @@ -1021,13 +1020,13 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh { Svh::new(crate_hash.to_smaller_hash()) } -fn upstream_crates(cstore: &dyn CrateStore) -> Vec<(StableCrateId, Svh)> { - let mut upstream_crates: Vec<_> = cstore - .crates_untracked() +fn upstream_crates(tcx: TyCtxt<'_>) -> Vec<(StableCrateId, Svh)> { + let mut upstream_crates: Vec<_> = tcx + .crates(()) .iter() .map(|&cnum| { - let stable_crate_id = cstore.stable_crate_id_untracked(cnum); - let hash = cstore.crate_hash_untracked(cnum); + let stable_crate_id = tcx.resolutions(()).cstore.stable_crate_id(cnum); + let hash = tcx.crate_hash(cnum); (stable_crate_id, hash) }) .collect(); diff --git a/compiler/rustc_middle/src/ich/impls_syntax.rs b/compiler/rustc_middle/src/ich/impls_syntax.rs index 2d8f661ef59..1c66f831b5f 100644 --- a/compiler/rustc_middle/src/ich/impls_syntax.rs +++ b/compiler/rustc_middle/src/ich/impls_syntax.rs @@ -6,6 +6,7 @@ use crate::ich::StableHashingContext; use rustc_ast as ast; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_span::{BytePos, NormalizedPos, SourceFile}; +use std::assert::assert_matches; use smallvec::SmallVec; diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 484e30027e5..848e60fe134 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -8,7 +8,7 @@ use rustc_hir::HirId; use rustc_index::vec::IndexVec; use rustc_session::lint::{ builtin::{self, FORBIDDEN_LINT_GROUPS}, - FutureIncompatibilityReason, FutureIncompatibleInfo, Level, Lint, LintId, + FutureIncompatibilityReason, Level, Lint, LintId, }; use rustc_session::{DiagnosticMessageId, Session}; use rustc_span::hygiene::MacroKind; @@ -223,12 +223,12 @@ pub fn struct_lint_level<'s, 'd>( let lint_id = LintId::of(lint); let future_incompatible = lint.future_incompatible; - let has_future_breakage = matches!( - future_incompatible, - Some(FutureIncompatibleInfo { - reason: FutureIncompatibilityReason::FutureReleaseErrorReportNow, - .. - }) + let has_future_breakage = future_incompatible.map_or( + // Default allow lints trigger too often for testing. + sess.opts.debugging_opts.future_incompat_test && lint.default_level != Level::Allow, + |incompat| { + matches!(incompat.reason, FutureIncompatibilityReason::FutureReleaseErrorReportNow) + }, ); let mut err = match (level, span) { diff --git a/compiler/rustc_middle/src/middle/cstore.rs b/compiler/rustc_middle/src/middle/cstore.rs index fcd4988635b..7efe8e061e8 100644 --- a/compiler/rustc_middle/src/middle/cstore.rs +++ b/compiler/rustc_middle/src/middle/cstore.rs @@ -5,9 +5,7 @@ use crate::ty::TyCtxt; use rustc_ast as ast; -use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::{self, MetadataRef}; -use rustc_hir::def::DefKind; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc_hir::definitions::{DefKey, DefPath, DefPathHash}; use rustc_macros::HashStable; @@ -190,11 +188,19 @@ pub type MetadataLoaderDyn = dyn MetadataLoader + Sync; pub trait CrateStore: std::fmt::Debug { fn as_any(&self) -> &dyn Any; - // resolve + // Foreign definitions. + // This information is safe to access, since it's hashed as part of the DefPathHash, which incr. + // comp. uses to identify a DefId. fn def_key(&self, def: DefId) -> DefKey; - fn def_kind(&self, def: DefId) -> DefKind; fn def_path(&self, def: DefId) -> DefPath; fn def_path_hash(&self, def: DefId) -> DefPathHash; + + // This information is safe to access, since it's hashed as part of the StableCrateId, which + // incr. comp. uses to identify a CrateNum. + fn crate_name(&self, cnum: CrateNum) -> Symbol; + fn stable_crate_id(&self, cnum: CrateNum) -> StableCrateId; + + /// Fetch a DefId from a DefPathHash for a foreign crate. fn def_path_hash_to_def_id( &self, cnum: CrateNum, @@ -202,15 +208,6 @@ pub trait CrateStore: std::fmt::Debug { hash: DefPathHash, ) -> Option<DefId>; - // "queries" used in resolve that aren't tracked for incremental compilation - fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol; - fn stable_crate_id_untracked(&self, cnum: CrateNum) -> StableCrateId; - fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh; - - // This is basically a 1-based range of ints, which is a little - // silly - I may fix that. - fn crates_untracked(&self) -> Vec<CrateNum>; - // utility functions fn encode_metadata(&self, tcx: TyCtxt<'_>) -> EncodedMetadata; } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index bc471aff2d0..80c4ff2ae5d 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -213,6 +213,8 @@ rustc_queries! { } query expn_that_defined(key: DefId) -> rustc_span::ExpnId { + // This query reads from untracked data in definitions. + eval_always desc { |tcx| "expansion that defined `{}`", tcx.def_path_str(key) } } @@ -1446,6 +1448,7 @@ rustc_queries! { desc { "calculating the stability index for the local crate" } } query crates(_: ()) -> &'tcx [CrateNum] { + eval_always desc { "fetching all foreign CrateNum instances" } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 1afeb4a138f..f52686c9b5f 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1277,7 +1277,7 @@ impl<'tcx> TyCtxt<'tcx> { if crate_num == LOCAL_CRATE { self.sess.local_stable_crate_id() } else { - self.untracked_resolutions.cstore.stable_crate_id_untracked(crate_num) + self.untracked_resolutions.cstore.stable_crate_id(crate_num) } } @@ -1290,10 +1290,7 @@ impl<'tcx> TyCtxt<'tcx> { (self.crate_name, self.sess.local_stable_crate_id()) } else { let cstore = &self.untracked_resolutions.cstore; - ( - cstore.crate_name_untracked(def_id.krate), - cstore.stable_crate_id_untracked(def_id.krate), - ) + (cstore.crate_name(def_id.krate), cstore.stable_crate_id(def_id.krate)) }; format!( @@ -2831,8 +2828,6 @@ pub fn provide(providers: &mut ty::query::Providers) { }; providers.extern_mod_stmt_cnum = |tcx, id| tcx.resolutions(()).extern_crate_map.get(&id).cloned(); - providers.crates = - |tcx, ()| tcx.arena.alloc_slice(&tcx.resolutions(()).cstore.crates_untracked()); providers.output_filenames = |tcx, ()| tcx.output_filenames.clone(); providers.features_query = |tcx, ()| tcx.sess.features_untracked(); providers.is_panic_runtime = |tcx, cnum| { diff --git a/compiler/rustc_mir/src/interpret/memory.rs b/compiler/rustc_mir/src/interpret/memory.rs index 5f719cc1607..194c478cc99 100644 --- a/compiler/rustc_mir/src/interpret/memory.rs +++ b/compiler/rustc_mir/src/interpret/memory.rs @@ -6,6 +6,7 @@ //! integer. It is crucial that these operations call `check_align` *before* //! short-circuiting the empty case! +use std::assert::assert_matches; use std::borrow::Cow; use std::collections::VecDeque; use std::convert::{TryFrom, TryInto}; diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index f91bf0cbab7..35e7688fbe4 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -128,7 +128,7 @@ impl<'a> Resolver<'a> { let (name, parent) = if def_id.index == CRATE_DEF_INDEX { // This is the crate root - (self.cstore().crate_name_untracked(def_id.krate), None) + (self.cstore().crate_name(def_id.krate), None) } else { let def_key = self.cstore().def_key(def_id); let name = def_key diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 4c40d0c367e..474cd86f43b 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1084,6 +1084,8 @@ options! { "set the optimization fuel quota for a crate"), function_sections: Option<bool> = (None, parse_opt_bool, [TRACKED], "whether each function should go in its own section"), + future_incompat_test: bool = (false, parse_bool, [UNTRACKED], + "forces all lints to be future incompatible, used for internal testing (default: no)"), gcc_ld: Option<LdImpl> = (None, parse_gcc_ld, [TRACKED], "implementation of ld used by cc"), graphviz_dark_mode: bool = (false, parse_bool, [UNTRACKED], "use dark-themed colors in graphviz output (default: no)"), diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 4b34a7dc894..d821e715622 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -19,7 +19,6 @@ use core::marker::{PhantomData, Unpin, Unsize}; use core::mem::size_of_val; use core::mem::{self, align_of_val_raw}; use core::ops::{CoerceUnsized, Deref, DispatchFromDyn, Receiver}; -#[cfg(not(no_global_oom_handling))] use core::pin::Pin; use core::ptr::{self, NonNull}; #[cfg(not(no_global_oom_handling))] @@ -494,6 +493,13 @@ impl<T> Arc<T> { unsafe { Pin::new_unchecked(Arc::new(data)) } } + /// Constructs a new `Pin<Arc<T>>`, return an error if allocation fails. + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn try_pin(data: T) -> Result<Pin<Arc<T>>, AllocError> { + unsafe { Ok(Pin::new_unchecked(Arc::try_new(data)?)) } + } + /// Constructs a new `Arc<T>`, returning an error if allocation fails. /// /// # Examples diff --git a/library/core/src/iter/adapters/fuse.rs b/library/core/src/iter/adapters/fuse.rs index 0c21df4f12c..408328adeec 100644 --- a/library/core/src/iter/adapters/fuse.rs +++ b/library/core/src/iter/adapters/fuse.rs @@ -1,5 +1,5 @@ use crate::intrinsics; -use crate::iter::adapters::{zip::try_get_unchecked, InPlaceIterable, SourceIter}; +use crate::iter::adapters::zip::try_get_unchecked; use crate::iter::{ DoubleEndedIterator, ExactSizeIterator, FusedIterator, TrustedLen, TrustedRandomAccess, }; @@ -14,7 +14,9 @@ use crate::ops::Try; #[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] pub struct Fuse<I> { - // NOTE: for `I: FusedIterator`, this is always assumed `Some`! + // NOTE: for `I: FusedIterator`, we never bother setting `None`, but + // we still have to be prepared for that state due to variance. + // See rust-lang/rust#85863 iter: Option<I>, } impl<I> Fuse<I> { @@ -42,19 +44,19 @@ macro_rules! fuse { }; } -// NOTE: for `I: FusedIterator`, we assume that the iterator is always `Some`. -// Implementing this as a directly-expanded macro helps codegen performance. -macro_rules! unchecked { - ($self:ident) => { - match $self { - Fuse { iter: Some(iter) } => iter, - // SAFETY: the specialized iterator never sets `None` - Fuse { iter: None } => unsafe { intrinsics::unreachable() }, +/// Specialized macro that doesn't check if the expression is `None`. +/// (We trust that a `FusedIterator` will fuse itself.) +macro_rules! spec { + ($self:ident . iter . $($call:tt)+) => { + match $self.iter { + Some(ref mut iter) => iter.$($call)+, + None => None, } }; } -// Any implementation here is made internal to avoid exposing default fns outside this trait +// Any specialized implementation here is made internal +// to avoid exposing default fns outside this trait. #[stable(feature = "rust1", since = "1.0.0")] impl<I> Iterator for Fuse<I> where @@ -74,17 +76,26 @@ where #[inline] fn last(self) -> Option<Self::Item> { - FuseImpl::last(self) + match self.iter { + Some(iter) => iter.last(), + None => None, + } } #[inline] fn count(self) -> usize { - FuseImpl::count(self) + match self.iter { + Some(iter) => iter.count(), + None => 0, + } } #[inline] fn size_hint(&self) -> (usize, Option<usize>) { - FuseImpl::size_hint(self) + match self.iter { + Some(ref iter) => iter.size_hint(), + None => (0, Some(0)), + } } #[inline] @@ -98,11 +109,14 @@ where } #[inline] - fn fold<Acc, Fold>(self, acc: Acc, fold: Fold) -> Acc + fn fold<Acc, Fold>(self, mut acc: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { - FuseImpl::fold(self, acc, fold) + if let Some(iter) = self.iter { + acc = iter.fold(acc, fold); + } + acc } #[inline] @@ -155,11 +169,14 @@ where } #[inline] - fn rfold<Acc, Fold>(self, acc: Acc, fold: Fold) -> Acc + fn rfold<Acc, Fold>(self, mut acc: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { - FuseImpl::rfold(self, acc, fold) + if let Some(iter) = self.iter { + acc = iter.rfold(acc, fold); + } + acc } #[inline] @@ -177,11 +194,17 @@ where I: ExactSizeIterator, { fn len(&self) -> usize { - FuseImpl::len(self) + match self.iter { + Some(ref iter) => iter.len(), + None => 0, + } } fn is_empty(&self) -> bool { - FuseImpl::is_empty(self) + match self.iter { + Some(ref iter) => iter.is_empty(), + None => true, + } } } @@ -205,7 +228,10 @@ where const MAY_HAVE_SIDE_EFFECT: bool = I::MAY_HAVE_SIDE_EFFECT; } -// Fuse specialization trait +/// Fuse specialization trait +/// +/// We only need to worry about `&mut self` methods, which +/// may exhaust the iterator without consuming it. #[doc(hidden)] trait FuseImpl<I> { type Item; @@ -213,17 +239,11 @@ trait FuseImpl<I> { // Functions specific to any normal Iterators fn next(&mut self) -> Option<Self::Item>; fn nth(&mut self, n: usize) -> Option<Self::Item>; - fn last(self) -> Option<Self::Item>; - fn count(self) -> usize; - fn size_hint(&self) -> (usize, Option<usize>); fn try_fold<Acc, Fold, R>(&mut self, acc: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Output = Acc>; - fn fold<Acc, Fold>(self, acc: Acc, fold: Fold) -> Acc - where - Fold: FnMut(Acc, Self::Item) -> Acc; fn find<P>(&mut self, predicate: P) -> Option<Self::Item> where P: FnMut(&Self::Item) -> bool; @@ -241,25 +261,13 @@ trait FuseImpl<I> { Fold: FnMut(Acc, Self::Item) -> R, R: Try<Output = Acc>, I: DoubleEndedIterator; - fn rfold<Acc, Fold>(self, acc: Acc, fold: Fold) -> Acc - where - Fold: FnMut(Acc, Self::Item) -> Acc, - I: DoubleEndedIterator; fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item> where P: FnMut(&Self::Item) -> bool, I: DoubleEndedIterator; - - // Functions specific to ExactSizeIterator - fn len(&self) -> usize - where - I: ExactSizeIterator; - fn is_empty(&self) -> bool - where - I: ExactSizeIterator; } -// General Fuse impl +/// General `Fuse` impl which sets `iter = None` when exhausted. #[doc(hidden)] impl<I> FuseImpl<I> for Fuse<I> where @@ -278,30 +286,6 @@ where } #[inline] - default fn last(self) -> Option<I::Item> { - match self.iter { - Some(iter) => iter.last(), - None => None, - } - } - - #[inline] - default fn count(self) -> usize { - match self.iter { - Some(iter) => iter.count(), - None => 0, - } - } - - #[inline] - default fn size_hint(&self) -> (usize, Option<usize>) { - match self.iter { - Some(ref iter) => iter.size_hint(), - None => (0, Some(0)), - } - } - - #[inline] default fn try_fold<Acc, Fold, R>(&mut self, mut acc: Acc, fold: Fold) -> R where Self: Sized, @@ -316,17 +300,6 @@ where } #[inline] - default fn fold<Acc, Fold>(self, mut acc: Acc, fold: Fold) -> Acc - where - Fold: FnMut(Acc, Self::Item) -> Acc, - { - if let Some(iter) = self.iter { - acc = iter.fold(acc, fold); - } - acc - } - - #[inline] default fn find<P>(&mut self, predicate: P) -> Option<Self::Item> where P: FnMut(&Self::Item) -> bool, @@ -366,18 +339,6 @@ where } #[inline] - default fn rfold<Acc, Fold>(self, mut acc: Acc, fold: Fold) -> Acc - where - Fold: FnMut(Acc, Self::Item) -> Acc, - I: DoubleEndedIterator, - { - if let Some(iter) = self.iter { - acc = iter.rfold(acc, fold); - } - acc - } - - #[inline] default fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item> where P: FnMut(&Self::Item) -> bool, @@ -385,30 +346,10 @@ where { fuse!(self.iter.rfind(predicate)) } - - #[inline] - default fn len(&self) -> usize - where - I: ExactSizeIterator, - { - match self.iter { - Some(ref iter) => iter.len(), - None => 0, - } - } - - #[inline] - default fn is_empty(&self) -> bool - where - I: ExactSizeIterator, - { - match self.iter { - Some(ref iter) => iter.is_empty(), - None => true, - } - } } +/// Specialized `Fuse` impl which doesn't bother clearing `iter` when exhausted. +/// However, we must still be prepared for the possibility that it was already cleared! #[doc(hidden)] impl<I> FuseImpl<I> for Fuse<I> where @@ -416,45 +357,25 @@ where { #[inline] fn next(&mut self) -> Option<<I as Iterator>::Item> { - unchecked!(self).next() + spec!(self.iter.next()) } #[inline] fn nth(&mut self, n: usize) -> Option<I::Item> { - unchecked!(self).nth(n) - } - - #[inline] - fn last(self) -> Option<I::Item> { - unchecked!(self).last() + spec!(self.iter.nth(n)) } #[inline] - fn count(self) -> usize { - unchecked!(self).count() - } - - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - unchecked!(self).size_hint() - } - - #[inline] - fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R + fn try_fold<Acc, Fold, R>(&mut self, mut acc: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Output = Acc>, { - unchecked!(self).try_fold(init, fold) - } - - #[inline] - fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc - where - Fold: FnMut(Acc, Self::Item) -> Acc, - { - unchecked!(self).fold(init, fold) + if let Some(ref mut iter) = self.iter { + acc = iter.try_fold(acc, fold)?; + } + try { acc } } #[inline] @@ -462,7 +383,7 @@ where where P: FnMut(&Self::Item) -> bool, { - unchecked!(self).find(predicate) + spec!(self.iter.find(predicate)) } #[inline] @@ -470,7 +391,7 @@ where where I: DoubleEndedIterator, { - unchecked!(self).next_back() + spec!(self.iter.next_back()) } #[inline] @@ -478,27 +399,21 @@ where where I: DoubleEndedIterator, { - unchecked!(self).nth_back(n) + spec!(self.iter.nth_back(n)) } #[inline] - fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R + fn try_rfold<Acc, Fold, R>(&mut self, mut acc: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Output = Acc>, I: DoubleEndedIterator, { - unchecked!(self).try_rfold(init, fold) - } - - #[inline] - fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc - where - Fold: FnMut(Acc, Self::Item) -> Acc, - I: DoubleEndedIterator, - { - unchecked!(self).rfold(init, fold) + if let Some(ref mut iter) = self.iter { + acc = iter.try_rfold(acc, fold)?; + } + try { acc } } #[inline] @@ -507,43 +422,6 @@ where P: FnMut(&Self::Item) -> bool, I: DoubleEndedIterator, { - unchecked!(self).rfind(predicate) - } - - #[inline] - fn len(&self) -> usize - where - I: ExactSizeIterator, - { - unchecked!(self).len() - } - - #[inline] - fn is_empty(&self) -> bool - where - I: ExactSizeIterator, - { - unchecked!(self).is_empty() + spec!(self.iter.rfind(predicate)) } } - -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl<S: Iterator, I: FusedIterator> SourceIter for Fuse<I> -where - I: SourceIter<Source = S>, -{ - type Source = S; - - #[inline] - unsafe fn as_inner(&mut self) -> &mut S { - match self.iter { - // SAFETY: unsafe function forwarding to unsafe function with the same requirements - Some(ref mut iter) => unsafe { SourceIter::as_inner(iter) }, - // SAFETY: the specialized iterator never sets `None` - None => unsafe { intrinsics::unreachable() }, - } - } -} - -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl<I: InPlaceIterable> InPlaceIterable for Fuse<I> {} diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 3557dbad90c..01d33409a42 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -179,6 +179,16 @@ use prelude::v1::*; #[macro_use] mod macros; +// We don't export this through #[macro_export] for now, to avoid breakage. +// See https://github.com/rust-lang/rust/issues/82913 +#[cfg(not(test))] +#[unstable(feature = "assert_matches", issue = "82775")] +/// Unstable module containing the unstable `assert_matches` macro. +pub mod assert { + #[unstable(feature = "assert_matches", issue = "82775")] + pub use crate::macros::{assert_matches, debug_assert_matches}; +} + #[macro_use] mod internal_macros; diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 7eb65483b99..8ce441e80bf 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1,6 +1,7 @@ #[doc = include_str!("panic.md")] #[macro_export] -#[rustc_builtin_macro = "core_panic"] +#[cfg_attr(bootstrap, rustc_builtin_macro = "core_panic")] +#[cfg_attr(not(bootstrap), rustc_builtin_macro(core_panic))] #[allow_internal_unstable(edition_panic)] #[stable(feature = "core", since = "1.6.0")] #[rustc_diagnostic_item = "core_panic_macro"] @@ -126,6 +127,8 @@ macro_rules! assert_ne { /// ``` /// #![feature(assert_matches)] /// +/// use std::assert::assert_matches; +/// /// let a = 1u32.checked_add(2); /// let b = 1u32.checked_sub(2); /// assert_matches!(a, Some(_)); @@ -134,10 +137,10 @@ macro_rules! assert_ne { /// let c = Ok("abc".to_string()); /// assert_matches!(c, Ok(x) | Err(x) if x.len() < 100); /// ``` -#[macro_export] #[unstable(feature = "assert_matches", issue = "82775")] #[allow_internal_unstable(core_panic)] -macro_rules! assert_matches { +#[rustc_macro_transparency = "semitransparent"] +pub macro assert_matches { ($left:expr, $( $pattern:pat_param )|+ $( if $guard: expr )? $(,)?) => ({ match $left { $( $pattern )|+ $( if $guard )? => {} @@ -149,7 +152,7 @@ macro_rules! assert_matches { ); } } - }); + }), ($left:expr, $( $pattern:pat_param )|+ $( if $guard: expr )?, $($arg:tt)+) => ({ match $left { $( $pattern )|+ $( if $guard )? => {} @@ -161,7 +164,7 @@ macro_rules! assert_matches { ); } } - }); + }), } /// Asserts that a boolean expression is `true` at runtime. @@ -283,6 +286,8 @@ macro_rules! debug_assert_ne { /// ``` /// #![feature(assert_matches)] /// +/// use std::assert::debug_assert_matches; +/// /// let a = 1u32.checked_add(2); /// let b = 1u32.checked_sub(2); /// debug_assert_matches!(a, Some(_)); @@ -294,8 +299,9 @@ macro_rules! debug_assert_ne { #[macro_export] #[unstable(feature = "assert_matches", issue = "82775")] #[allow_internal_unstable(assert_matches)] -macro_rules! debug_assert_matches { - ($($arg:tt)*) => (if $crate::cfg!(debug_assertions) { $crate::assert_matches!($($arg)*); }) +#[rustc_macro_transparency = "semitransparent"] +pub macro debug_assert_matches($($arg:tt)*) { + if $crate::cfg!(debug_assertions) { $crate::assert::assert_matches!($($arg)*); } } /// Returns whether the given expression matches any of the given patterns. diff --git a/library/core/src/slice/rotate.rs b/library/core/src/slice/rotate.rs index a89596b15ef..7528927ef33 100644 --- a/library/core/src/slice/rotate.rs +++ b/library/core/src/slice/rotate.rs @@ -1,5 +1,3 @@ -// ignore-tidy-undocumented-unsafe - use crate::cmp; use crate::mem::{self, MaybeUninit}; use crate::ptr; @@ -79,8 +77,10 @@ pub unsafe fn ptr_rotate<T>(mut left: usize, mut mid: *mut T, mut right: usize) // the way until about `left + right == 32`, but the worst case performance breaks even // around 16. 24 was chosen as middle ground. If the size of `T` is larger than 4 // `usize`s, this algorithm also outperforms other algorithms. + // SAFETY: callers must ensure `mid - left` is valid for reading and writing. let x = unsafe { mid.sub(left) }; // beginning of first round + // SAFETY: see previous comment. let mut tmp: T = unsafe { x.read() }; let mut i = right; // `gcd` can be found before hand by calculating `gcd(left + right, right)`, @@ -92,6 +92,21 @@ pub unsafe fn ptr_rotate<T>(mut left: usize, mut mid: *mut T, mut right: usize) // the very end. This is possibly due to the fact that swapping or replacing temporaries // uses only one memory address in the loop instead of needing to manage two. loop { + // [long-safety-expl] + // SAFETY: callers must ensure `[left, left+mid+right)` are all valid for reading and + // writing. + // + // - `i` start with `right` so `mid-left <= x+i = x+right = mid-left+right < mid+right` + // - `i <= left+right-1` is always true + // - if `i < left`, `right` is added so `i < left+right` and on the next + // iteration `left` is removed from `i` so it doesn't go further + // - if `i >= left`, `left` is removed immediately and so it doesn't go further. + // - overflows cannot happen for `i` since the function's safety contract ask for + // `mid+right-1 = x+left+right` to be valid for writing + // - underflows cannot happen because `i` must be bigger or equal to `left` for + // a substraction of `left` to happen. + // + // So `x+i` is valid for reading and writing if the caller respected the contract tmp = unsafe { x.add(i).replace(tmp) }; // instead of incrementing `i` and then checking if it is outside the bounds, we // check if `i` will go outside the bounds on the next increment. This prevents @@ -100,6 +115,8 @@ pub unsafe fn ptr_rotate<T>(mut left: usize, mut mid: *mut T, mut right: usize) i -= left; if i == 0 { // end of first round + // SAFETY: tmp has been read from a valid source and x is valid for writing + // according to the caller. unsafe { x.write(tmp) }; break; } @@ -113,13 +130,24 @@ pub unsafe fn ptr_rotate<T>(mut left: usize, mut mid: *mut T, mut right: usize) } // finish the chunk with more rounds for start in 1..gcd { + // SAFETY: `gcd` is at most equal to `right` so all values in `1..gcd` are valid for + // reading and writing as per the function's safety contract, see [long-safety-expl] + // above tmp = unsafe { x.add(start).read() }; + // [safety-expl-addition] + // + // Here `start < gcd` so `start < right` so `i < right+right`: `right` being the + // greatest common divisor of `(left+right, right)` means that `left = right` so + // `i < left+right` so `x+i = mid-left+i` is always valid for reading and writing + // according to the function's safety contract. i = start + right; loop { + // SAFETY: see [long-safety-expl] and [safety-expl-addition] tmp = unsafe { x.add(i).replace(tmp) }; if i >= left { i -= left; if i == start { + // SAFETY: see [long-safety-expl] and [safety-expl-addition] unsafe { x.add(start).write(tmp) }; break; } @@ -135,14 +163,30 @@ pub unsafe fn ptr_rotate<T>(mut left: usize, mut mid: *mut T, mut right: usize) // The `[T; 0]` here is to ensure this is appropriately aligned for T let mut rawarray = MaybeUninit::<(BufType, [T; 0])>::uninit(); let buf = rawarray.as_mut_ptr() as *mut T; + // SAFETY: `mid-left <= mid-left+right < mid+right` let dim = unsafe { mid.sub(left).add(right) }; if left <= right { + // SAFETY: + // + // 1) The `else if` condition about the sizes ensures `[mid-left; left]` will fit in + // `buf` without overflow and `buf` was created just above and so cannot be + // overlapped with any value of `[mid-left; left]` + // 2) [mid-left, mid+right) are all valid for reading and writing and we don't care + // about overlaps here. + // 3) The `if` condition about `left <= right` ensures writing `left` elements to + // `dim = mid-left+right` is valid because: + // - `buf` is valid and `left` elements were written in it in 1) + // - `dim+left = mid-left+right+left = mid+right` and we write `[dim, dim+left)` unsafe { + // 1) ptr::copy_nonoverlapping(mid.sub(left), buf, left); + // 2) ptr::copy(mid, mid.sub(left), right); + // 3) ptr::copy_nonoverlapping(buf, dim, left); } } else { + // SAFETY: same reasoning as above but with `left` and `right` reversed unsafe { ptr::copy_nonoverlapping(mid, buf, right); ptr::copy(mid.sub(left), dim, left); @@ -156,6 +200,10 @@ pub unsafe fn ptr_rotate<T>(mut left: usize, mut mid: *mut T, mut right: usize) // of this algorithm would be, and swapping using that last chunk instead of swapping // adjacent chunks like this algorithm is doing, but this way is still faster. loop { + // SAFETY: + // `left >= right` so `[mid-right, mid+right)` is valid for reading and writing + // Substracting `right` from `mid` each turn is counterbalanced by the addition and + // check after it. unsafe { ptr::swap_nonoverlapping(mid.sub(right), mid, right); mid = mid.sub(right); @@ -168,6 +216,10 @@ pub unsafe fn ptr_rotate<T>(mut left: usize, mut mid: *mut T, mut right: usize) } else { // Algorithm 3, `left < right` loop { + // SAFETY: `[mid-left, mid+left)` is valid for reading and writing because + // `left < right` so `mid+left < mid+right`. + // Adding `left` to `mid` each turn is counterbalanced by the substraction and check + // after it. unsafe { ptr::swap_nonoverlapping(mid.sub(left), mid, left); mid = mid.add(left); diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 8c120f4af28..472bca3460f 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -548,8 +548,8 @@ pub use std_detect::{ #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated, deprecated_in_future)] pub use core::{ - assert_eq, assert_matches, assert_ne, debug_assert, debug_assert_eq, debug_assert_matches, - debug_assert_ne, matches, r#try, todo, unimplemented, unreachable, write, writeln, + assert_eq, assert_ne, debug_assert, debug_assert_eq, debug_assert_ne, matches, r#try, todo, + unimplemented, unreachable, write, writeln, }; // Re-export built-in macros defined through libcore. diff --git a/library/std/src/macros.rs b/library/std/src/macros.rs index b2c5df5410d..7afe52a3fd6 100644 --- a/library/std/src/macros.rs +++ b/library/std/src/macros.rs @@ -6,7 +6,8 @@ #[doc = include_str!("../../core/src/macros/panic.md")] #[macro_export] -#[rustc_builtin_macro = "std_panic"] +#[cfg_attr(bootstrap, rustc_builtin_macro = "std_panic")] +#[cfg_attr(not(bootstrap), rustc_builtin_macro(std_panic))] #[stable(feature = "rust1", since = "1.0.0")] #[allow_internal_unstable(edition_panic)] #[cfg_attr(not(test), rustc_diagnostic_item = "std_panic_macro")] diff --git a/library/std/src/os/wasi/fs.rs b/library/std/src/os/wasi/fs.rs index 7f26f419a4b..bd30d6ae3f3 100644 --- a/library/std/src/os/wasi/fs.rs +++ b/library/std/src/os/wasi/fs.rs @@ -1,7 +1,7 @@ //! WASI-specific extensions to primitives in the `std::fs` module. #![deny(unsafe_op_in_unsafe_fn)] -#![unstable(feature = "wasi_ext", issue = "none")] +#![unstable(feature = "wasi_ext", issue = "71213")] use crate::ffi::OsStr; use crate::fs::{self, File, Metadata, OpenOptions}; diff --git a/library/std/src/os/wasi/io.rs b/library/std/src/os/wasi/io.rs index b2e79cc1b4a..cf4501b98cb 100644 --- a/library/std/src/os/wasi/io.rs +++ b/library/std/src/os/wasi/io.rs @@ -1,7 +1,7 @@ //! WASI-specific extensions to general I/O primitives #![deny(unsafe_op_in_unsafe_fn)] -#![unstable(feature = "wasi_ext", issue = "none")] +#![unstable(feature = "wasi_ext", issue = "71213")] use crate::fs; use crate::io; diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile index 6dcf0bdcba4..779b301ff61 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile @@ -72,7 +72,7 @@ ENV PATH="/node-v14.4.0-linux-x64/bin:${PATH}" # https://github.com/puppeteer/puppeteer/issues/375 # # We also specify the version in case we need to update it to go around cache limitations. -RUN npm install -g browser-ui-test@0.4.1 --unsafe-perm=true +RUN npm install -g browser-ui-test@0.4.2 --unsafe-perm=true ENV RUST_CONFIGURE_ARGS \ --build=x86_64-unknown-linux-gnu \ diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index cd914f05e68..c5ca396e720 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -167,11 +167,7 @@ crate fn run(options: Options) -> Result<(), ErrorReported> { test_args.insert(0, "rustdoctest".to_string()); - testing::test_main( - &test_args, - tests, - Some(testing::Options::new().display_output(display_warnings)), - ); + test::test_main(&test_args, tests, Some(test::Options::new().display_output(display_warnings))); // Collect and warn about unused externs, but only if we've gotten // reports for each doctest @@ -769,7 +765,7 @@ crate trait Tester { } crate struct Collector { - crate tests: Vec<testing::TestDescAndFn>, + crate tests: Vec<test::TestDescAndFn>, // The name of the test displayed to the user, separated by `::`. // @@ -930,22 +926,22 @@ impl Tester for Collector { }; debug!("creating test {}: {}", name, test); - self.tests.push(testing::TestDescAndFn { - desc: testing::TestDesc { - name: testing::DynTestName(name), + self.tests.push(test::TestDescAndFn { + desc: test::TestDesc { + name: test::DynTestName(name), ignore: match config.ignore { Ignore::All => true, Ignore::None => false, Ignore::Some(ref ignores) => ignores.iter().any(|s| target_str.contains(s)), }, // compiler failures are test failures - should_panic: testing::ShouldPanic::No, + should_panic: test::ShouldPanic::No, allow_fail: config.allow_fail, compile_fail: config.compile_fail, no_run, - test_type: testing::TestType::DocTest, + test_type: test::TestType::DocTest, }, - testfn: testing::DynTestFn(box move || { + testfn: test::DynTestFn(box move || { let report_unused_externs = |uext| { unused_externs.lock().unwrap().push(uext); }; diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 9fff508165a..3b599e4997a 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -33,6 +33,7 @@ use std::str; use crate::clean::RenderedLink; use crate::doctest; +use crate::html::escape::Escape; use crate::html::highlight; use crate::html::toc::TocBuilder; @@ -207,26 +208,11 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> { let should_panic; let ignore; let edition; - if let Some(Event::Start(Tag::CodeBlock(kind))) = event { - let parse_result = match kind { - CodeBlockKind::Fenced(ref lang) => { - LangString::parse_without_check(&lang, self.check_error_codes, false) - } - CodeBlockKind::Indented => Default::default(), - }; - if !parse_result.rust { - return Some(Event::Start(Tag::CodeBlock(kind))); - } - compile_fail = parse_result.compile_fail; - should_panic = parse_result.should_panic; - ignore = parse_result.ignore; - edition = parse_result.edition; + let kind = if let Some(Event::Start(Tag::CodeBlock(kind))) = event { + kind } else { return event; - } - - let explicit_edition = edition.is_some(); - let edition = edition.unwrap_or(self.edition); + }; let mut origtext = String::new(); for event in &mut self.inner { @@ -241,6 +227,35 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> { let lines = origtext.lines().filter_map(|l| map_line(l).for_html()); let text = lines.collect::<Vec<Cow<'_, str>>>().join("\n"); + let parse_result = match kind { + CodeBlockKind::Fenced(ref lang) => { + let parse_result = + LangString::parse_without_check(&lang, self.check_error_codes, false); + if !parse_result.rust { + return Some(Event::Html( + format!( + "<div class=\"example-wrap\">\ + <pre{}>{}</pre>\ + </div>", + format!(" class=\"language-{}\"", lang), + Escape(&text), + ) + .into(), + )); + } + parse_result + } + CodeBlockKind::Indented => Default::default(), + }; + + compile_fail = parse_result.compile_fail; + should_panic = parse_result.should_panic; + ignore = parse_result.ignore; + edition = parse_result.edition; + + let explicit_edition = edition.is_some(); + let edition = edition.unwrap_or(self.edition); + let playground_button = self.playground.as_ref().and_then(|playground| { let krate = &playground.crate_name; let url = &playground.url; diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 66dfd2fac84..208e8f723f4 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -435,7 +435,7 @@ nav.sub { border-bottom-left-radius: 5px; } -.rustdoc:not(.source) .example-wrap > pre.rust { +.rustdoc:not(.source) .example-wrap > pre:not(.line-number) { width: 100%; overflow-x: auto; } diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index 9da3fe07ade..8296c3f91ca 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -34,7 +34,7 @@ h4 { background: rgba(0, 0, 0, 0); } -code { +.docblock code { color: #ffb454; } h3 > code, h4 > code, h5 > code { diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index bc635190f42..d4d87819c0d 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -53,11 +53,11 @@ extern crate rustc_parse; extern crate rustc_passes; extern crate rustc_resolve; extern crate rustc_session; -extern crate rustc_span as rustc_span; +extern crate rustc_span; extern crate rustc_target; extern crate rustc_trait_selection; extern crate rustc_typeck; -extern crate test as testing; +extern crate test; #[cfg(feature = "jemalloc")] extern crate tikv_jemalloc_sys; diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index 5da3a75e876..45966c0058d 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -136,10 +136,10 @@ crate fn test(mut options: Options) -> Result<(), String> { find_testable_code(&input_str, &mut collector, codes, options.enable_per_target_ignores, None); options.test_args.insert(0, "rustdoctest".to_string()); - testing::test_main( + test::test_main( &options.test_args, collector.tests, - Some(testing::Options::new().display_output(options.display_warnings)), + Some(test::Options::new().display_output(options.display_warnings)), ); Ok(()) } diff --git a/src/test/debuginfo/function-names.rs b/src/test/debuginfo/function-names.rs index 26317f5c3ff..20a49f0bd26 100644 --- a/src/test/debuginfo/function-names.rs +++ b/src/test/debuginfo/function-names.rs @@ -33,6 +33,13 @@ // Generator // Generators don't seem to appear in GDB's symbol table. +// Const generic parameter +// gdb-command:info functions -q function_names::const_generic_fn.* +// gdb-check:[...]static fn function_names::const_generic_fn_bool(); +// gdb-check:[...]static fn function_names::const_generic_fn_non_int(); +// gdb-check:[...]static fn function_names::const_generic_fn_signed_int(); +// gdb-check:[...]static fn function_names::const_generic_fn_unsigned_int(); + // === CDB TESTS =================================================================================== // Top-level function @@ -49,9 +56,9 @@ // Trait implementations // cdb-command:x a!function_names::*::trait_function* -// cdb-check:[...] a!function_names::impl$6::trait_function<i32, 0x1> (void) // cdb-check:[...] a!function_names::impl$3::trait_function<i32> (void) // cdb-check:[...] a!function_names::impl$1::trait_function (void) +// cdb-check:[...] a!function_names::impl$6::trait_function<i32, 1> (void) // cdb-check:[...] a!function_names::impl$5::trait_function3<function_names::TestStruct1> (void) // cdb-check:[...] a!function_names::Mod1::impl$1::trait_function (void) @@ -65,10 +72,18 @@ // cdb-command:x a!function_names::*::generator* // cdb-check:[...] a!function_names::main::generator$1 (void) +// Const generic parameter +// cdb-command:x a!function_names::const_generic_fn* +// cdb-check:[...] a!function_names::const_generic_fn_bool<false> (void) +// cdb-check:[...] a!function_names::const_generic_fn_non_int<CONST$fe3cfa0214ac55c7> (void) +// cdb-check:[...] a!function_names::const_generic_fn_unsigned_int<14> (void) +// cdb-check:[...] a!function_names::const_generic_fn_signed_int<-7> (void) + #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] -#![feature(generators, generator_trait)] +#![feature(const_generics, generators, generator_trait)] +#![allow(incomplete_features)] // for const_generics use Mod1::TestTrait2; use std::ops::Generator; @@ -97,6 +112,12 @@ fn main() { // Generator let mut generator = || { yield; return; }; Pin::new(&mut generator).resume(()); + + // Const generic functions + const_generic_fn_bool::<false>(); + const_generic_fn_non_int::<{()}>(); + const_generic_fn_signed_int::<-7>(); + const_generic_fn_unsigned_int::<14>(); } struct TestStruct1; @@ -173,3 +194,8 @@ fn generic_func<T>(value: T) -> T { value } + +fn const_generic_fn_bool<const C: bool>() {} +fn const_generic_fn_non_int<const C: ()>() {} +fn const_generic_fn_signed_int<const C: i64>() {} +fn const_generic_fn_unsigned_int<const C: u32>() {} diff --git a/src/test/rustdoc-gui/ayu-code-tag-colors.goml b/src/test/rustdoc-gui/ayu-code-tag-colors.goml new file mode 100644 index 00000000000..50af36fa3d6 --- /dev/null +++ b/src/test/rustdoc-gui/ayu-code-tag-colors.goml @@ -0,0 +1,13 @@ +// The ayu theme has a different color for the "<code>" tags in the doc blocks. We need to +// check that the rule isn't applied on other "<code>" elements. +goto: file://|DOC_PATH|/test_docs/enum.AnEnum.html +// We need to show the text, otherwise the colors aren't "computed" by the web browser. +show-text: true +// We set the theme to ayu. +local-storage: {"rustdoc-theme": "ayu", "rustdoc-preferred-dark-theme": "ayu", "rustdoc-use-system-theme": "false"} +// We reload to get the text appearing and the theme applied. +reload: + +assert-css: (".docblock code", {"color": "rgb(255, 180, 84)"}, ALL) +// It includes variants and the "titles" as well (for example: "impl RefUnwindSafe for AnEnum"). +assert-css: ("div:not(.docblock) > code", {"color": "rgb(197, 197, 197)"}, ALL) diff --git a/src/test/rustdoc-gui/code-blocks-overflow.goml b/src/test/rustdoc-gui/code-blocks-overflow.goml new file mode 100644 index 00000000000..ee4dad444e9 --- /dev/null +++ b/src/test/rustdoc-gui/code-blocks-overflow.goml @@ -0,0 +1,8 @@ +// This test ensures that codeblocks content don't overflow. +goto: file://|DOC_PATH|/lib2/sub_mod/struct.Foo.html +size: (1080, 600) +// There should be two codeblocks: a rust one and a non-rust one. +assert-count: (".docblock > .example-wrap", 2) +assert: ".docblock > .example-wrap > .language-txt" +assert: ".docblock > .example-wrap > .rust-example-rendered" +assert-css: (".docblock > .example-wrap > pre", {"width": "796px", "overflow-x": "auto"}, ALL) diff --git a/src/test/rustdoc-gui/src/lib2/lib.rs b/src/test/rustdoc-gui/src/lib2/lib.rs index 72ef3cbd202..ec8ab339e28 100644 --- a/src/test/rustdoc-gui/src/lib2/lib.rs +++ b/src/test/rustdoc-gui/src/lib2/lib.rs @@ -1,3 +1,5 @@ +// ignore-tidy-linelength + pub mod module { pub mod sub_module { pub mod sub_sub_module { @@ -32,4 +34,16 @@ impl Trait for Foo { const Y: u32 = 0; } + impl implementors::Whatever for Foo {} + +pub mod sub_mod { + /// ```txt + /// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + /// ``` + /// + /// ``` + /// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + /// ``` + pub struct Foo; +} diff --git a/src/test/rustdoc-gui/src/test_docs/lib.rs b/src/test/rustdoc-gui/src/test_docs/lib.rs index 1b9f652120e..85dd8805fbc 100644 --- a/src/test/rustdoc-gui/src/test_docs/lib.rs +++ b/src/test/rustdoc-gui/src/test_docs/lib.rs @@ -96,6 +96,7 @@ pub fn check_list_code_block() {} #[doc(cfg(unix))] pub fn replaced_function() {} +/// Some doc with `code`! pub enum AnEnum { WithVariants { and: usize, sub: usize, variants: usize }, } diff --git a/src/test/ui/crate-loading/auxiliary/proc-macro.rs b/src/test/ui/crate-loading/auxiliary/proc-macro.rs new file mode 100644 index 00000000000..52631de5757 --- /dev/null +++ b/src/test/ui/crate-loading/auxiliary/proc-macro.rs @@ -0,0 +1,12 @@ +// force-host +// no-prefer-dynamic +#![crate_name = "reproduction"] +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro] +pub fn mac(input: TokenStream) -> TokenStream { + input +} diff --git a/src/test/ui/crate-loading/cross-compiled-proc-macro.rs b/src/test/ui/crate-loading/cross-compiled-proc-macro.rs new file mode 100644 index 00000000000..c1f4331438e --- /dev/null +++ b/src/test/ui/crate-loading/cross-compiled-proc-macro.rs @@ -0,0 +1,8 @@ +// edition:2018 +// compile-flags:--extern reproduction +// aux-build:proc-macro.rs +// check-pass + +reproduction::mac!(); + +fn main() {} diff --git a/src/test/ui/deriving/deriving-with-helper.rs b/src/test/ui/deriving/deriving-with-helper.rs new file mode 100644 index 00000000000..ea74a15624c --- /dev/null +++ b/src/test/ui/deriving/deriving-with-helper.rs @@ -0,0 +1,36 @@ +// check-pass +// compile-flags: --crate-type=lib + +#![feature(decl_macro)] +#![feature(lang_items)] +#![feature(no_core)] +#![feature(rustc_attrs)] + +#![no_core] + +#[rustc_builtin_macro] +macro derive() {} + +#[rustc_builtin_macro(Default, attributes(default))] +macro Default() {} + +mod default { + pub trait Default { + fn default() -> Self; + } + + impl Default for u8 { + fn default() -> u8 { + 0 + } + } +} + +#[lang = "sized"] +trait Sized {} + +#[derive(Default)] +struct S { + #[default] // OK + field: u8, +} diff --git a/src/test/ui/lint/future-incompat-test.rs b/src/test/ui/lint/future-incompat-test.rs new file mode 100644 index 00000000000..ce8c118dab2 --- /dev/null +++ b/src/test/ui/lint/future-incompat-test.rs @@ -0,0 +1,10 @@ +// compile-flags: -Zfuture-incompat-test -Zemit-future-incompat-report +// check-pass + +// The `-Zfuture-incompat-test flag causes any normal warning to be included +// in the future-incompatible report. The stderr output here should mention +// the future incompatible report (as extracted by compiletest). + +fn main() { + let x = 1; +} diff --git a/src/test/ui/lint/future-incompat-test.stderr b/src/test/ui/lint/future-incompat-test.stderr new file mode 100644 index 00000000000..52674a84384 --- /dev/null +++ b/src/test/ui/lint/future-incompat-test.stderr @@ -0,0 +1,9 @@ +Future incompatibility report: Future breakage diagnostic: +warning: unused variable: `x` + --> $DIR/future-incompat-test.rs:9:9 + | +LL | let x = 1; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | + = note: `-A unused-variables` implied by `-A unused` + diff --git a/src/test/ui/macros/assert-matches-macro-msg.rs b/src/test/ui/macros/assert-matches-macro-msg.rs index 43be9532f5d..714a6561a6d 100644 --- a/src/test/ui/macros/assert-matches-macro-msg.rs +++ b/src/test/ui/macros/assert-matches-macro-msg.rs @@ -6,6 +6,8 @@ #![feature(assert_matches)] +use std::assert::assert_matches; + fn main() { assert_matches!(1 + 1, 3, "1 + 1 definitely should be 3"); } diff --git a/src/test/ui/matches2021.rs b/src/test/ui/matches2021.rs index 1090b1578ba..a6fa5128d2f 100644 --- a/src/test/ui/matches2021.rs +++ b/src/test/ui/matches2021.rs @@ -6,6 +6,8 @@ #![feature(assert_matches)] +use std::assert::assert_matches; + fn main() { assert!(matches!((), ())); assert_matches!((), ()); diff --git a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr index e764480e8e5..070b0667213 100644 --- a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr +++ b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr @@ -81,7 +81,7 @@ LL | tuple_from_req!(Foo); warning: 5 warnings emitted -Future incompatibility report: Future breakage date: None, diagnostic: +Future incompatibility report: Future breakage diagnostic: warning: using an old version of `time-macros-impl` --> $DIR/time-macros-impl/src/lib.rs:5:32 | @@ -99,7 +99,7 @@ LL | impl_macros!(Foo); = note: the `time-macros-impl` crate will stop compiling in futures version of Rust. Please update to the latest version of the `time` crate to avoid breakage = note: this warning originates in the macro `impl_macros` (in Nightly builds, run with -Z macro-backtrace for more info) -Future breakage date: None, diagnostic: +Future breakage diagnostic: warning: using an old version of `time-macros-impl` --> $DIR/time-macros-impl-0.1.0/src/lib.rs:5:32 | @@ -116,7 +116,7 @@ LL | impl_macros!(Foo); = note: the `time-macros-impl` crate will stop compiling in futures version of Rust. Please update to the latest version of the `time` crate to avoid breakage = note: this warning originates in the macro `impl_macros` (in Nightly builds, run with -Z macro-backtrace for more info) -Future breakage date: None, diagnostic: +Future breakage diagnostic: warning: using an old version of `js-sys` --> $DIR/js-sys-0.3.17/src/lib.rs:5:32 | @@ -133,7 +133,7 @@ LL | arrays!(Foo); = note: older versions of the `js-sys` crate will stop compiling in future versions of Rust; please update to `js-sys` v0.3.40 or above = note: this warning originates in the macro `arrays` (in Nightly builds, run with -Z macro-backtrace for more info) -Future breakage date: None, diagnostic: +Future breakage diagnostic: warning: using an old version of `actix-web` --> $DIR/actix-web/src/extract.rs:5:34 | @@ -150,7 +150,7 @@ LL | tuple_from_req!(Foo); = note: the version of `actix-web` you are using might stop compiling in future versions of Rust; please update to the latest version of the `actix-web` crate to avoid breakage = note: this warning originates in the macro `tuple_from_req` (in Nightly builds, run with -Z macro-backtrace for more info) -Future breakage date: None, diagnostic: +Future breakage diagnostic: warning: using an old version of `actix-web` --> $DIR/actix-web-2.0.0/src/extract.rs:5:34 | diff --git a/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr index 0b930705e35..4d6edab08e2 100644 --- a/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr +++ b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr @@ -11,7 +11,7 @@ LL | enum ProceduralMasqueradeDummyType { warning: 1 warning emitted -Future incompatibility report: Future breakage date: None, diagnostic: +Future incompatibility report: Future breakage diagnostic: warning: using `procedural-masquerade` crate --> $DIR/issue-73933-procedural-masquerade.rs:8:6 | diff --git a/src/test/ui/resolve/resolve-hint-macro.rs b/src/test/ui/resolve/resolve-hint-macro.rs index 6155ae7bcdf..5532c8b90e3 100644 --- a/src/test/ui/resolve/resolve-hint-macro.rs +++ b/src/test/ui/resolve/resolve-hint-macro.rs @@ -1,4 +1,4 @@ fn main() { - assert(true); - //~^ ERROR expected function, found macro `assert` + assert_eq(1, 1); + //~^ ERROR expected function, found macro `assert_eq` } diff --git a/src/test/ui/resolve/resolve-hint-macro.stderr b/src/test/ui/resolve/resolve-hint-macro.stderr index 7d35ce7e65e..efcfc7198ab 100644 --- a/src/test/ui/resolve/resolve-hint-macro.stderr +++ b/src/test/ui/resolve/resolve-hint-macro.stderr @@ -1,13 +1,13 @@ -error[E0423]: expected function, found macro `assert` +error[E0423]: expected function, found macro `assert_eq` --> $DIR/resolve-hint-macro.rs:2:5 | -LL | assert(true); - | ^^^^^^ not a function +LL | assert_eq(1, 1); + | ^^^^^^^^^ not a function | help: use `!` to invoke the macro | -LL | assert!(true); - | ^ +LL | assert_eq!(1, 1); + | ^ error: aborting due to previous error diff --git a/src/tools/compiletest/src/json.rs b/src/tools/compiletest/src/json.rs index 8d23227fdb8..dc6d67983c5 100644 --- a/src/tools/compiletest/src/json.rs +++ b/src/tools/compiletest/src/json.rs @@ -43,7 +43,6 @@ struct FutureIncompatReport { #[derive(Deserialize)] struct FutureBreakageItem { - future_breakage_date: Option<String>, diagnostic: Diagnostic, } @@ -104,9 +103,7 @@ pub fn extract_rendered(output: &str) -> String { .into_iter() .map(|item| { format!( - "Future breakage date: {}, diagnostic:\n{}", - item.future_breakage_date - .unwrap_or_else(|| "None".to_string()), + "Future breakage diagnostic:\n{}", item.diagnostic .rendered .unwrap_or_else(|| "Not rendered".to_string()) |
