diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 368c0be794bc..05d29503180e 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -1,5 +1,6 @@ //! Borrow checker diagnostics. +use itertools::Itertools; use rustc_const_eval::util::{call_kind, CallDesugaringKind}; use rustc_errors::{Applicability, Diagnostic}; use rustc_hir as hir; @@ -161,158 +162,103 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } /// End-user visible description of `place` if one can be found. - /// If the place is a temporary for instance, None will be returned. + /// If the place is a temporary for instance, `None` will be returned. pub(super) fn describe_place(&self, place_ref: PlaceRef<'tcx>) -> Option { self.describe_place_with_options(place_ref, IncludingDowncast(false)) } - /// End-user visible description of `place` if one can be found. If the - /// place is a temporary for instance, None will be returned. - /// `IncludingDowncast` parameter makes the function return `Err` if `ProjectionElem` is + /// End-user visible description of `place` if one can be found. If the place is a temporary + /// for instance, `None` will be returned. + /// `IncludingDowncast` parameter makes the function return `None` if `ProjectionElem` is /// `Downcast` and `IncludingDowncast` is true pub(super) fn describe_place_with_options( &self, place: PlaceRef<'tcx>, including_downcast: IncludingDowncast, ) -> Option { + let local = place.local; + let mut autoderef_index = None; let mut buf = String::new(); - match self.append_place_to_string(place, &mut buf, false, &including_downcast) { - Ok(()) => Some(buf), - Err(()) => None, - } - } - - /// Appends end-user visible description of `place` to `buf`. - fn append_place_to_string( - &self, - place: PlaceRef<'tcx>, - buf: &mut String, - mut autoderef: bool, - including_downcast: &IncludingDowncast, - ) -> Result<(), ()> { - match place { - PlaceRef { local, projection: [] } => { - self.append_local_to_string(local, buf)?; - } - PlaceRef { local, projection: [ProjectionElem::Deref] } - if self.body.local_decls[local].is_ref_for_guard() => - { - self.append_place_to_string( - PlaceRef { local, projection: &[] }, - buf, - autoderef, - &including_downcast, - )?; - } - PlaceRef { local, projection: [ProjectionElem::Deref] } - if self.body.local_decls[local].is_ref_to_static() => - { - let local_info = &self.body.local_decls[local].local_info; - if let Some(box LocalInfo::StaticRef { def_id, .. }) = *local_info { - buf.push_str(self.infcx.tcx.item_name(def_id).as_str()); - } else { - unreachable!(); - } - } - PlaceRef { local, projection: [proj_base @ .., elem] } => { - match elem { - ProjectionElem::Deref => { - let upvar_field_projection = self.is_upvar_field_projection(place); - if let Some(field) = upvar_field_projection { - let var_index = field.index(); - let name = self.upvars[var_index].place.to_string(self.infcx.tcx); - if self.upvars[var_index].by_ref { - buf.push_str(&name); - } else { - buf.push('*'); - buf.push_str(&name); - } - } else { - if autoderef { - // FIXME turn this recursion into iteration - self.append_place_to_string( - PlaceRef { local, projection: proj_base }, - buf, - autoderef, - &including_downcast, - )?; - } else { - buf.push('*'); - self.append_place_to_string( - PlaceRef { local, projection: proj_base }, - buf, - autoderef, - &including_downcast, - )?; - } + let mut ok = self.append_local_to_string(local, &mut buf); + + for (index, elem) in place.projection.into_iter().enumerate() { + match elem { + ProjectionElem::Deref => { + if index == 0 { + if self.body.local_decls[local].is_ref_for_guard() { + continue; } - } - ProjectionElem::Downcast(..) => { - self.append_place_to_string( - PlaceRef { local, projection: proj_base }, - buf, - autoderef, - &including_downcast, - )?; - if including_downcast.0 { - return Err(()); + if let Some(box LocalInfo::StaticRef { def_id, .. }) = + &self.body.local_decls[local].local_info + { + buf.push_str(self.infcx.tcx.item_name(*def_id).as_str()); + ok = Ok(()); + continue; } } - ProjectionElem::Field(field, _ty) => { - autoderef = true; - - // FIXME(project-rfc_2229#36): print capture precisely here. - let upvar_field_projection = self.is_upvar_field_projection(place); - if let Some(field) = upvar_field_projection { - let var_index = field.index(); - let name = self.upvars[var_index].place.to_string(self.infcx.tcx); - buf.push_str(&name); - } else { - let field_name = self - .describe_field(PlaceRef { local, projection: proj_base }, *field); - self.append_place_to_string( - PlaceRef { local, projection: proj_base }, - buf, - autoderef, - &including_downcast, - )?; - buf.push('.'); - buf.push_str(&field_name); + if let Some(field) = self.is_upvar_field_projection(PlaceRef { + local, + projection: place.projection.split_at(index + 1).0, + }) { + let var_index = field.index(); + buf = self.upvars[var_index].place.to_string(self.infcx.tcx); + ok = Ok(()); + if !self.upvars[var_index].by_ref { + buf.insert(0, '*'); } - } - ProjectionElem::Index(index) => { - autoderef = true; - - self.append_place_to_string( - PlaceRef { local, projection: proj_base }, - buf, - autoderef, - &including_downcast, - )?; - buf.push('['); - if self.append_local_to_string(*index, buf).is_err() { - buf.push('_'); + } else { + if autoderef_index.is_none() { + autoderef_index = + match place.projection.into_iter().rev().find_position(|elem| { + !matches!( + elem, + ProjectionElem::Deref | ProjectionElem::Downcast(..) + ) + }) { + Some((index, _)) => Some(place.projection.len() - index), + None => Some(0), + }; + } + if index >= autoderef_index.unwrap() { + buf.insert(0, '*'); } - buf.push(']'); } - ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => { - autoderef = true; - // Since it isn't possible to borrow an element on a particular index and - // then use another while the borrow is held, don't output indices details - // to avoid confusing the end-user - self.append_place_to_string( - PlaceRef { local, projection: proj_base }, - buf, - autoderef, - &including_downcast, - )?; - buf.push_str("[..]"); + } + ProjectionElem::Downcast(..) if including_downcast.0 => return None, + ProjectionElem::Downcast(..) => (), + ProjectionElem::Field(field, _ty) => { + // FIXME(project-rfc_2229#36): print capture precisely here. + if let Some(field) = self.is_upvar_field_projection(PlaceRef { + local, + projection: place.projection.split_at(index + 1).0, + }) { + buf = self.upvars[field.index()].place.to_string(self.infcx.tcx); + ok = Ok(()); + } else { + let field_name = self.describe_field( + PlaceRef { local, projection: place.projection.split_at(index).0 }, + *field, + ); + buf.push('.'); + buf.push_str(&field_name); } - }; + } + ProjectionElem::Index(index) => { + buf.push('['); + if self.append_local_to_string(*index, &mut buf).is_err() { + buf.push('_'); + } + buf.push(']'); + } + ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => { + // Since it isn't possible to borrow an element on a particular index and + // then use another while the borrow is held, don't output indices details + // to avoid confusing the end-user + buf.push_str("[..]"); + } } } - - Ok(()) + ok.ok().map(|_| buf) } /// Appends end-user visible description of the `local` place to `buf`. If `local` doesn't have diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index cf9cf1b70aaa..4407297c943a 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -816,6 +816,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( span: Span, ) -> Result<&'ll Value, ()> { // macros for error handling: + #[cfg_attr(not(bootstrap), allow(unused_macro_rules))] macro_rules! emit_error { ($msg: tt) => { emit_error!($msg, ) @@ -1144,6 +1145,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( span: Span, args: &[OperandRef<'tcx, &'ll Value>], ) -> Result<&'ll Value, ()> { + #[cfg_attr(not(bootstrap), allow(unused_macro_rules))] macro_rules! emit_error { ($msg: tt) => { emit_error!($msg, ) diff --git a/compiler/rustc_error_messages/locales/en-US/typeck.ftl b/compiler/rustc_error_messages/locales/en-US/typeck.ftl index 6a3235fc7728..aef18fcafaa0 100644 --- a/compiler/rustc_error_messages/locales/en-US/typeck.ftl +++ b/compiler/rustc_error_messages/locales/en-US/typeck.ftl @@ -90,3 +90,14 @@ typeck-add-return-type-missing-here = a return type might be missing here typeck-expected-default-return-type = expected `()` because of default return type typeck-expected-return-type = expected `{$expected}` because of return type + +typeck-unconstrained-opaque-type = unconstrained opaque type + .note = `{$name}` must be used in combination with a concrete type within the same module + +typeck-explicit-generic-args-with-impl-trait = + cannot provide explicit generic arguments when `impl Trait` is used in argument position + .label = explicit generic argument not allowed + .note = see issue #83701 for more information + +typeck-explicit-generic-args-with-impl-trait-feature = + add `#![feature(explicit_generic_args_with_impl_trait)]` to the crate attributes to enable diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index df41fc00714b..e789ded2b6f5 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -426,6 +426,13 @@ struct HandlerInner { future_breakage_diagnostics: Vec, + /// The [`unstable_expect_diagnostics`] should be empty when this struct is + /// dropped. However, it can have values if the compilation is stopped early + /// or is only partially executed. To avoid ICEs, like in rust#94953 we only + /// check if [`unstable_expect_diagnostics`] is empty, if the expectation ids + /// have been converted. + check_unstable_expect_diagnostics: bool, + /// Expected [`Diagnostic`]s store a [`LintExpectationId`] as part of /// the lint level. [`LintExpectationId`]s created early during the compilation /// (before `HirId`s have been defined) are not stable and can therefore not be @@ -497,10 +504,12 @@ impl Drop for HandlerInner { ); } - assert!( - self.unstable_expect_diagnostics.is_empty(), - "all diagnostics with unstable expectations should have been converted", - ); + if self.check_unstable_expect_diagnostics { + assert!( + self.unstable_expect_diagnostics.is_empty(), + "all diagnostics with unstable expectations should have been converted", + ); + } } } @@ -574,6 +583,7 @@ impl Handler { emitted_diagnostics: Default::default(), stashed_diagnostics: Default::default(), future_breakage_diagnostics: Vec::new(), + check_unstable_expect_diagnostics: false, unstable_expect_diagnostics: Vec::new(), fulfilled_expectations: Default::default(), }), @@ -988,12 +998,13 @@ impl Handler { &self, unstable_to_stable: &FxHashMap, ) { - let diags = std::mem::take(&mut self.inner.borrow_mut().unstable_expect_diagnostics); + let mut inner = self.inner.borrow_mut(); + let diags = std::mem::take(&mut inner.unstable_expect_diagnostics); + inner.check_unstable_expect_diagnostics = true; if diags.is_empty() { return; } - let mut inner = self.inner.borrow_mut(); for mut diag in diags.into_iter() { diag.update_unstable_expectation_id(unstable_to_stable); diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 2b30ec601a0c..5d52b7047a9e 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -887,6 +887,8 @@ pub trait ResolverExpand { force: bool, ) -> Result, Indeterminate>; + fn record_macro_rule_usage(&mut self, mac_id: NodeId, rule_index: usize); + fn check_unused_macros(&mut self); // Resolver interfaces for specific built-in macros. diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 050710097c33..ba0b35470b6b 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -156,13 +156,13 @@ impl<'a> ParserAnyMacro<'a> { } struct MacroRulesMacroExpander { + node_id: NodeId, name: Ident, span: Span, transparency: Transparency, lhses: Vec>, rhses: Vec, valid: bool, - is_local: bool, } impl TTMacroExpander for MacroRulesMacroExpander { @@ -179,12 +179,12 @@ impl TTMacroExpander for MacroRulesMacroExpander { cx, sp, self.span, + self.node_id, self.name, self.transparency, input, &self.lhses, &self.rhses, - self.is_local, ) } } @@ -207,14 +207,17 @@ fn generic_extension<'cx, 'tt>( cx: &'cx mut ExtCtxt<'_>, sp: Span, def_span: Span, + node_id: NodeId, name: Ident, transparency: Transparency, arg: TokenStream, lhses: &'tt [Vec], rhses: &'tt [mbe::TokenTree], - is_local: bool, ) -> Box { let sess = &cx.sess.parse_sess; + // Macros defined in the current crate have a real node id, + // whereas macros from an external crate have a dummy id. + let is_local = node_id != DUMMY_NODE_ID; if cx.trace_macros() { let msg = format!("expanding `{}! {{ {} }}`", name, pprust::tts_to_string(&arg)); @@ -296,6 +299,10 @@ fn generic_extension<'cx, 'tt>( let mut p = Parser::new(sess, tts, false, None); p.last_type_ascription = cx.current_expansion.prior_type_ascription; + if is_local { + cx.resolver.record_macro_rule_usage(node_id, i); + } + // Let the context choose how to interpret the result. // Weird, but useful for X-macros. return Box::new(ParserAnyMacro { @@ -372,7 +379,7 @@ pub fn compile_declarative_macro( features: &Features, def: &ast::Item, edition: Edition, -) -> SyntaxExtension { +) -> (SyntaxExtension, Vec) { debug!("compile_declarative_macro: {:?}", def); let mk_syn_ext = |expander| { SyntaxExtension::new( @@ -385,6 +392,7 @@ pub fn compile_declarative_macro( &def.attrs, ) }; + let dummy_syn_ext = || (mk_syn_ext(Box::new(macro_rules_dummy_expander)), Vec::new()); let diag = &sess.parse_sess.span_diagnostic; let lhs_nm = Ident::new(sym::lhs, def.span); @@ -445,17 +453,17 @@ pub fn compile_declarative_macro( let s = parse_failure_msg(&token); let sp = token.span.substitute_dummy(def.span); sess.parse_sess.span_diagnostic.struct_span_err(sp, &s).span_label(sp, msg).emit(); - return mk_syn_ext(Box::new(macro_rules_dummy_expander)); + return dummy_syn_ext(); } Error(sp, msg) => { sess.parse_sess .span_diagnostic .struct_span_err(sp.substitute_dummy(def.span), &msg) .emit(); - return mk_syn_ext(Box::new(macro_rules_dummy_expander)); + return dummy_syn_ext(); } ErrorReported => { - return mk_syn_ext(Box::new(macro_rules_dummy_expander)); + return dummy_syn_ext(); } }; @@ -530,6 +538,15 @@ pub fn compile_declarative_macro( None => {} } + // Compute the spans of the macro rules + // We only take the span of the lhs here, + // so that the spans of created warnings are smaller. + let rule_spans = if def.id != DUMMY_NODE_ID { + lhses.iter().map(|lhs| lhs.span()).collect::>() + } else { + Vec::new() + }; + // Convert the lhses into `MatcherLoc` form, which is better for doing the // actual matching. Unless the matcher is invalid. let lhses = if valid { @@ -549,17 +566,16 @@ pub fn compile_declarative_macro( vec![] }; - mk_syn_ext(Box::new(MacroRulesMacroExpander { + let expander = Box::new(MacroRulesMacroExpander { name: def.ident, span: def.span, + node_id: def.id, transparency, lhses, rhses, valid, - // Macros defined in the current crate have a real node id, - // whereas macros from an external crate have a dummy id. - is_local: def.id != DUMMY_NODE_ID, - })) + }); + (mk_syn_ext(expander), rule_spans) } fn check_lhs_nt_follows(sess: &ParseSess, def: &ast::Item, lhs: &mbe::TokenTree) -> bool { diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 08987dff660a..00119267e856 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -1009,6 +1009,10 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { }); } ); + + // This check has to be run after all lints are done processing. We don't + // define a lint filter, as all lint checks should have finished at this point. + sess.time("check_lint_expectations", || tcx.check_expectations(None)); }); Ok(()) diff --git a/compiler/rustc_lint/src/expect.rs b/compiler/rustc_lint/src/expect.rs index 67f5aa0540fb..dc48ac0a618e 100644 --- a/compiler/rustc_lint/src/expect.rs +++ b/compiler/rustc_lint/src/expect.rs @@ -1,10 +1,16 @@ use crate::builtin; use rustc_hir::HirId; +use rustc_middle::ty::query::Providers; use rustc_middle::{lint::LintExpectation, ty::TyCtxt}; use rustc_session::lint::LintExpectationId; use rustc_span::symbol::sym; +use rustc_span::Symbol; -pub fn check_expectations(tcx: TyCtxt<'_>) { +pub(crate) fn provide(providers: &mut Providers) { + *providers = Providers { check_expectations, ..*providers }; +} + +fn check_expectations(tcx: TyCtxt<'_>, tool_filter: Option) { if !tcx.sess.features_untracked().enabled(sym::lint_reasons) { return; } @@ -13,7 +19,9 @@ pub fn check_expectations(tcx: TyCtxt<'_>) { let lint_expectations = &tcx.lint_levels(()).lint_expectations; for (id, expectation) in lint_expectations { - if !fulfilled_expectations.contains(id) { + if !fulfilled_expectations.contains(id) + && tool_filter.map_or(true, |filter| expectation.lint_tool == Some(filter)) + { // This check will always be true, since `lint_expectations` only // holds stable ids if let LintExpectationId::Stable { hir_id, .. } = id { diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index 0ac636b878e0..0ce760b64d9c 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -503,7 +503,4 @@ pub fn check_crate<'tcx, T: LateLintPass<'tcx>>( }); }, ); - - // This check has to be run after all lints are done processing for this crate - tcx.sess.time("check_lint_expectations", || crate::expect::check_expectations(tcx)); } diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 01f1d1e79ac6..257549bf1a1a 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -371,7 +371,12 @@ impl<'s> LintLevelsBuilder<'s> { }; self.lint_expectations.push(( expect_id, - LintExpectation::new(reason, sp, is_unfulfilled_lint_expectations), + LintExpectation::new( + reason, + sp, + is_unfulfilled_lint_expectations, + tool_name, + ), )); } let src = LintLevelSource::Node( @@ -400,8 +405,10 @@ impl<'s> LintLevelsBuilder<'s> { self.insert_spec(*id, (level, src)); } if let Level::Expect(expect_id) = level { - self.lint_expectations - .push((expect_id, LintExpectation::new(reason, sp, false))); + self.lint_expectations.push(( + expect_id, + LintExpectation::new(reason, sp, false, tool_name), + )); } } Err((Some(ids), ref new_lint_name)) => { @@ -444,8 +451,10 @@ impl<'s> LintLevelsBuilder<'s> { self.insert_spec(*id, (level, src)); } if let Level::Expect(expect_id) = level { - self.lint_expectations - .push((expect_id, LintExpectation::new(reason, sp, false))); + self.lint_expectations.push(( + expect_id, + LintExpectation::new(reason, sp, false, tool_name), + )); } } Err((None, _)) => { @@ -550,8 +559,10 @@ impl<'s> LintLevelsBuilder<'s> { } } if let Level::Expect(expect_id) = level { - self.lint_expectations - .push((expect_id, LintExpectation::new(reason, sp, false))); + self.lint_expectations.push(( + expect_id, + LintExpectation::new(reason, sp, false, tool_name), + )); } } else { panic!("renamed lint does not exist: {}", new_name); diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 028c14366c6a..0a0f292fe7a4 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -109,6 +109,7 @@ pub use rustc_session::lint::{LintArray, LintPass}; pub fn provide(providers: &mut Providers) { levels::provide(providers); + expect::provide(providers); *providers = Providers { lint_mod, ..*providers }; } @@ -302,6 +303,7 @@ fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) { PATH_STATEMENTS, UNUSED_ATTRIBUTES, UNUSED_MACROS, + UNUSED_MACRO_RULES, UNUSED_ALLOCATION, UNUSED_DOC_COMMENTS, UNUSED_EXTERN_CRATES, diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 34412795aeff..99f9d70f204a 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -749,6 +749,10 @@ declare_lint! { declare_lint! { /// The `unused_macros` lint detects macros that were not used. /// + /// Note that this lint is distinct from the `unused_macro_rules` lint, + /// which checks for single rules that never match of an otherwise used + /// macro, and thus never expand. + /// /// ### Example /// /// ```rust @@ -775,6 +779,45 @@ declare_lint! { "detects macros that were not used" } +declare_lint! { + /// The `unused_macro_rules` lint detects macro rules that were not used. + /// + /// Note that the lint is distinct from the `unused_macros` lint, which + /// fires if the entire macro is never called, while this lint fires for + /// single unused rules of the macro that is otherwise used. + /// `unused_macro_rules` fires only if `unused_macros` wouldn't fire. + /// + /// ### Example + /// + /// ```rust + /// macro_rules! unused_empty { + /// (hello) => { println!("Hello, world!") }; // This rule is unused + /// () => { println!("empty") }; // This rule is used + /// } + /// + /// fn main() { + /// unused_empty!(hello); + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Unused macro rules may signal a mistake or unfinished code. Furthermore, + /// they slow down compilation. Right now, silencing the warning is not + /// supported on a single rule level, so you have to add an allow to the + /// entire macro definition. + /// + /// If you intended to export the macro to make it + /// available outside of the crate, use the [`macro_export` attribute]. + /// + /// [`macro_export` attribute]: https://doc.rust-lang.org/reference/macros-by-example.html#path-based-scope + pub UNUSED_MACRO_RULES, + Warn, + "detects macro rules that were not used" +} + declare_lint! { /// The `warnings` lint allows you to change the level of other /// lints which produce warnings. @@ -3104,6 +3147,7 @@ declare_lint_pass! { OVERLAPPING_RANGE_ENDPOINTS, BINDINGS_WITH_VARIANT_NAME, UNUSED_MACROS, + UNUSED_MACRO_RULES, WARNINGS, UNUSED_FEATURES, STABLE_FEATURES, diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs index f49166433faa..83fc7bcde8ab 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs @@ -5,8 +5,8 @@ use crate::diagnostics::error::{ SessionDiagnosticDeriveError, }; use crate::diagnostics::utils::{ - option_inner_ty, report_error_if_not_applied_to_span, type_matches_path, Applicability, - FieldInfo, HasFieldMap, SetOnce, + report_error_if_not_applied_to_span, type_matches_path, Applicability, FieldInfo, FieldInnerTy, + HasFieldMap, SetOnce, }; use proc_macro2::TokenStream; use quote::{format_ident, quote}; @@ -353,35 +353,40 @@ impl SessionDiagnosticDeriveBuilder { info: FieldInfo<'_>, ) -> Result { let field_binding = &info.binding.binding; - let option_ty = option_inner_ty(&info.ty); - let generated_code = self.generate_non_option_field_code( + + let inner_ty = FieldInnerTy::from_type(&info.ty); + let name = attr.path.segments.last().unwrap().ident.to_string(); + let (binding, needs_destructure) = match (name.as_str(), &inner_ty) { + // `primary_span` can accept a `Vec` so don't destructure that. + ("primary_span", FieldInnerTy::Vec(_)) => (quote! { #field_binding.clone() }, false), + _ => (quote! { *#field_binding }, true), + }; + + let generated_code = self.generate_inner_field_code( attr, FieldInfo { vis: info.vis, binding: info.binding, - ty: option_ty.unwrap_or(&info.ty), + ty: inner_ty.inner_type().unwrap_or(&info.ty), span: info.span, }, + binding, )?; - if option_ty.is_none() { - Ok(quote! { #generated_code }) + if needs_destructure { + Ok(inner_ty.with(field_binding, generated_code)) } else { - Ok(quote! { - if let Some(#field_binding) = #field_binding { - #generated_code - } - }) + Ok(generated_code) } } - fn generate_non_option_field_code( + fn generate_inner_field_code( &mut self, attr: &Attribute, info: FieldInfo<'_>, + binding: TokenStream, ) -> Result { let diag = &self.diag; - let field_binding = &info.binding.binding; let name = attr.path.segments.last().unwrap().ident.to_string(); let name = name.as_str(); @@ -397,14 +402,14 @@ impl SessionDiagnosticDeriveBuilder { "primary_span" => { report_error_if_not_applied_to_span(attr, &info)?; Ok(quote! { - #diag.set_span(*#field_binding); + #diag.set_span(#binding); }) } "label" | "note" | "help" => { report_error_if_not_applied_to_span(attr, &info)?; - Ok(self.add_subdiagnostic(field_binding, name, name)) + Ok(self.add_subdiagnostic(binding, name, name)) } - "subdiagnostic" => Ok(quote! { #diag.subdiagnostic(*#field_binding); }), + "subdiagnostic" => Ok(quote! { #diag.subdiagnostic(#binding); }), _ => throw_invalid_attr!(attr, &meta, |diag| { diag .help("only `skip_arg`, `primary_span`, `label`, `note`, `help` and `subdiagnostic` are valid field attributes") @@ -413,7 +418,7 @@ impl SessionDiagnosticDeriveBuilder { Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(ref s), .. }) => match name { "label" | "note" | "help" => { report_error_if_not_applied_to_span(attr, &info)?; - Ok(self.add_subdiagnostic(field_binding, name, &s.value())) + Ok(self.add_subdiagnostic(binding, name, &s.value())) } _ => throw_invalid_attr!(attr, &meta, |diag| { diag.help("only `label`, `note` and `help` are valid field attributes") @@ -509,7 +514,7 @@ impl SessionDiagnosticDeriveBuilder { /// `fluent_attr_identifier`. fn add_subdiagnostic( &self, - field_binding: &proc_macro2::Ident, + field_binding: TokenStream, kind: &str, fluent_attr_identifier: &str, ) -> TokenStream { @@ -520,7 +525,7 @@ impl SessionDiagnosticDeriveBuilder { let fn_name = format_ident!("span_{}", kind); quote! { #diag.#fn_name( - *#field_binding, + #field_binding, rustc_errors::DiagnosticMessage::fluent_attr(#slug, #fluent_attr_identifier) ); } diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index 961b42f424fd..65b1328682f8 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -5,8 +5,8 @@ use crate::diagnostics::error::{ SessionDiagnosticDeriveError, }; use crate::diagnostics::utils::{ - option_inner_ty, report_error_if_not_applied_to_applicability, - report_error_if_not_applied_to_span, Applicability, FieldInfo, HasFieldMap, SetOnce, + report_error_if_not_applied_to_applicability, report_error_if_not_applied_to_span, + Applicability, FieldInfo, FieldInnerTy, HasFieldMap, SetOnce, }; use proc_macro2::TokenStream; use quote::{format_ident, quote}; @@ -301,11 +301,11 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { ) -> Result { let ast = binding.ast(); - let option_ty = option_inner_ty(&ast.ty); + let inner_ty = FieldInnerTy::from_type(&ast.ty); let info = FieldInfo { vis: &ast.vis, binding: binding, - ty: option_ty.unwrap_or(&ast.ty), + ty: inner_ty.inner_type().unwrap_or(&ast.ty), span: &ast.span(), }; @@ -353,15 +353,7 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { ); }; - if option_ty.is_none() { - Ok(quote! { #generated }) - } else { - Ok(quote! { - if let Some(#binding) = #binding { - #generated - } - }) - } + Ok(inner_ty.with(binding, generated)) } fn into_tokens(&mut self) -> Result { diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs index 1f36af0a20bc..aba861fc6aaf 100644 --- a/compiler/rustc_macros/src/diagnostics/utils.rs +++ b/compiler/rustc_macros/src/diagnostics/utils.rs @@ -1,7 +1,7 @@ use crate::diagnostics::error::{span_err, throw_span_err, SessionDiagnosticDeriveError}; use proc_macro::Span; use proc_macro2::TokenStream; -use quote::{format_ident, quote}; +use quote::{format_ident, quote, ToTokens}; use std::collections::BTreeSet; use std::str::FromStr; use syn::{spanned::Spanned, Attribute, Meta, Type, Visibility}; @@ -76,22 +76,71 @@ pub(crate) fn report_error_if_not_applied_to_span( report_error_if_not_applied_to_ty(attr, info, &["rustc_span", "Span"], "Span") } -/// If `ty` is an Option, returns `Some(inner type)`, otherwise returns `None`. -pub(crate) fn option_inner_ty(ty: &Type) -> Option<&Type> { - if type_matches_path(ty, &["std", "option", "Option"]) { +/// Inner type of a field and type of wrapper. +pub(crate) enum FieldInnerTy<'ty> { + /// Field is wrapped in a `Option<$inner>`. + Option(&'ty Type), + /// Field is wrapped in a `Vec<$inner>`. + Vec(&'ty Type), + /// Field isn't wrapped in an outer type. + None, +} + +impl<'ty> FieldInnerTy<'ty> { + /// Returns inner type for a field, if there is one. + /// + /// - If `ty` is an `Option`, returns `FieldInnerTy::Option { inner: (inner type) }`. + /// - If `ty` is a `Vec`, returns `FieldInnerTy::Vec { inner: (inner type) }`. + /// - Otherwise returns `None`. + pub(crate) fn from_type(ty: &'ty Type) -> Self { + let variant: &dyn Fn(&'ty Type) -> FieldInnerTy<'ty> = + if type_matches_path(ty, &["std", "option", "Option"]) { + &FieldInnerTy::Option + } else if type_matches_path(ty, &["std", "vec", "Vec"]) { + &FieldInnerTy::Vec + } else { + return FieldInnerTy::None; + }; + if let Type::Path(ty_path) = ty { let path = &ty_path.path; let ty = path.segments.iter().last().unwrap(); if let syn::PathArguments::AngleBracketed(bracketed) = &ty.arguments { if bracketed.args.len() == 1 { if let syn::GenericArgument::Type(ty) = &bracketed.args[0] { - return Some(ty); + return variant(ty); } } } } + + unreachable!(); + } + + /// Returns `Option` containing inner type if there is one. + pub(crate) fn inner_type(&self) -> Option<&'ty Type> { + match self { + FieldInnerTy::Option(inner) | FieldInnerTy::Vec(inner) => Some(inner), + FieldInnerTy::None => None, + } + } + + /// Surrounds `inner` with destructured wrapper type, exposing inner type as `binding`. + pub(crate) fn with(&self, binding: impl ToTokens, inner: impl ToTokens) -> TokenStream { + match self { + FieldInnerTy::Option(..) => quote! { + if let Some(#binding) = #binding { + #inner + } + }, + FieldInnerTy::Vec(..) => quote! { + for #binding in #binding { + #inner + } + }, + FieldInnerTy::None => quote! { #inner }, + } } - None } /// Field information passed to the builder. Deliberately omits attrs to discourage the diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index e55b0454eefc..c7c5f56867a5 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -210,6 +210,10 @@ pub struct LintExpectation { /// adjusted to include an additional note. Therefore, we have to track if /// the expectation is for the lint. pub is_unfulfilled_lint_expectations: bool, + /// This will hold the name of the tool that this lint belongs to. For + /// the lint `clippy::some_lint` the tool would be `clippy`, the same + /// goes for `rustdoc`. This will be `None` for rustc lints + pub lint_tool: Option, } impl LintExpectation { @@ -217,8 +221,9 @@ impl LintExpectation { reason: Option, emission_span: Span, is_unfulfilled_lint_expectations: bool, + lint_tool: Option, ) -> Self { - Self { reason, emission_span, is_unfulfilled_lint_expectations } + Self { reason, emission_span, is_unfulfilled_lint_expectations, lint_tool } } } diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index b7f695da544f..8111409b8bc0 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -448,6 +448,12 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> { self.push(&format!("+ user_ty: {:?}", user_ty)); } + let fmt_val = |val: &ConstValue<'tcx>| match val { + ConstValue::Scalar(s) => format!("Scalar({:?})", s), + ConstValue::Slice { .. } => format!("Slice(..)"), + ConstValue::ByRef { .. } => format!("ByRef(..)"), + }; + let val = match literal { ConstantKind::Ty(ct) => match ct.val() { ty::ConstKind::Param(p) => format!("Param({})", p), @@ -457,7 +463,7 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> { uv.substs, uv.promoted, ), - ty::ConstKind::Value(val) => format!("Value({:?})", val), + ty::ConstKind::Value(val) => format!("Value({})", fmt_val(&val)), ty::ConstKind::Error(_) => "Error".to_string(), // These variants shouldn't exist in the MIR. ty::ConstKind::Placeholder(_) @@ -467,7 +473,7 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> { // To keep the diffs small, we render this like we render `ty::Const::Value`. // // This changes once `ty::Const::Value` is represented using valtrees. - ConstantKind::Val(val, _) => format!("Value({:?})", val), + ConstantKind::Val(val, _) => format!("Value({})", fmt_val(&val)), }; self.push(&format!("+ literal: Const {{ ty: {}, val: {} }}", literal.ty(), val)); diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 45b1ad6df822..e2d70dd0b9c4 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -258,6 +258,7 @@ macro_rules! make_mir_visitor { // for best performance, we want to use an iterator rather // than a for-loop, to avoid calling `body::Body::invalidate` for // each basic block. + #[cfg_attr(not(bootstrap), allow(unused_macro_rules))] macro_rules! basic_blocks { (mut) => (body.basic_blocks_mut().iter_enumerated_mut()); () => (body.basic_blocks().iter_enumerated()); @@ -279,6 +280,7 @@ macro_rules! make_mir_visitor { self.visit_local_decl(local, & $($mutability)? body.local_decls[local]); } + #[cfg_attr(not(bootstrap), allow(unused_macro_rules))] macro_rules! type_annotations { (mut) => (body.user_type_annotations.iter_enumerated_mut()); () => (body.user_type_annotations.iter_enumerated()); @@ -932,6 +934,7 @@ macro_rules! make_mir_visitor { body: &$($mutability)? Body<'tcx>, location: Location ) { + #[cfg_attr(not(bootstrap), allow(unused_macro_rules))] macro_rules! basic_blocks { (mut) => (body.basic_blocks_mut()); () => (body.basic_blocks()); diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index e439d128dbc7..3eb8bb0feb12 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -157,6 +157,25 @@ rustc_queries! { desc { "running analysis passes on this crate" } } + /// This query checks the fulfillment of collected lint expectations. + /// All lint emitting queries have to be done before this is executed + /// to ensure that all expectations can be fulfilled. + /// + /// This is an extra query to enable other drivers (like rustdoc) to + /// only execute a small subset of the [`analysis`] query, while allowing + /// lints to be expected. In rustc, this query will be executed as part of + /// the [`analysis`] query and doesn't have to be called a second time. + /// + /// Tools can additionally pass in a tool filter. That will restrict the + /// expectations to only trigger for lints starting with the listed tool + /// name. This is useful for cases were not all linting code from rustc + /// was called. With the default `None` all registered lints will also + /// be checked for expectation fulfillment. + query check_expectations(key: Option) -> () { + eval_always + desc { "checking lint expectations (RFC 2383)" } + } + /// Maps from the `DefId` of an item (trait/struct/enum/fn) to its /// associated generics. query generics_of(key: DefId) -> ty::Generics { diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index 3fe68f723ec1..a1d1b6b3a785 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -136,6 +136,10 @@ pub trait Printer<'tcx>: Sized { match key.disambiguated_data.data { // Closures' own generics are only captures, don't print them. DefPathData::ClosureExpr => {} + // This covers both `DefKind::AnonConst` and `DefKind::InlineConst`. + // Anon consts doesn't have their own generics, and inline consts' own + // generics are their inferred types, so don't print them. + DefPathData::AnonConst => {} // If we have any generic arguments to print, we do that // on top of the same path, but without its own generics. diff --git a/compiler/rustc_query_impl/src/keys.rs b/compiler/rustc_query_impl/src/keys.rs index 3f0f856b5dd7..6fbafeb1d32b 100644 --- a/compiler/rustc_query_impl/src/keys.rs +++ b/compiler/rustc_query_impl/src/keys.rs @@ -435,6 +435,16 @@ impl Key for Symbol { } } +impl Key for Option { + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + true + } + fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { + DUMMY_SP + } +} + /// Canonical query goals correspond to abstract trait operations that /// are not tied to any crate in particular. impl<'tcx, T> Key for Canonical<'tcx, T> { diff --git a/compiler/rustc_resolve/Cargo.toml b/compiler/rustc_resolve/Cargo.toml index bd27c16c732a..b2178ff59954 100644 --- a/compiler/rustc_resolve/Cargo.toml +++ b/compiler/rustc_resolve/Cargo.toml @@ -4,7 +4,6 @@ version = "0.0.0" edition = "2021" [lib] -test = false doctest = false [dependencies] diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 783ff5a3f915..e68d6fdeea55 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -194,7 +194,7 @@ impl<'a> Resolver<'a> { } let ext = Lrc::new(match self.cstore().load_macro_untracked(def_id, &self.session) { - LoadedMacro::MacroDef(item, edition) => self.compile_macro(&item, edition), + LoadedMacro::MacroDef(item, edition) => self.compile_macro(&item, edition).0, LoadedMacro::ProcMacro(ext) => ext, }); @@ -1218,9 +1218,18 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { // Mark the given macro as unused unless its name starts with `_`. // Macro uses will remove items from this set, and the remaining // items will be reported as `unused_macros`. - fn insert_unused_macro(&mut self, ident: Ident, def_id: LocalDefId, node_id: NodeId) { + fn insert_unused_macro( + &mut self, + ident: Ident, + def_id: LocalDefId, + node_id: NodeId, + rule_spans: &[Span], + ) { if !ident.as_str().starts_with('_') { self.r.unused_macros.insert(def_id, (node_id, ident)); + for (rule_i, rule_span) in rule_spans.iter().enumerate() { + self.r.unused_macro_rules.insert((def_id, rule_i), (ident, *rule_span)); + } } } @@ -1228,15 +1237,16 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { let parent_scope = self.parent_scope; let expansion = parent_scope.expansion; let def_id = self.r.local_def_id(item.id); - let (ext, ident, span, macro_rules) = match &item.kind { + let (ext, ident, span, macro_rules, rule_spans) = match &item.kind { ItemKind::MacroDef(def) => { - let ext = Lrc::new(self.r.compile_macro(item, self.r.session.edition())); - (ext, item.ident, item.span, def.macro_rules) + let (ext, rule_spans) = self.r.compile_macro(item, self.r.session.edition()); + let ext = Lrc::new(ext); + (ext, item.ident, item.span, def.macro_rules, rule_spans) } ItemKind::Fn(..) => match self.proc_macro_stub(item) { Some((macro_kind, ident, span)) => { self.r.proc_macro_stubs.insert(def_id); - (self.r.dummy_ext(macro_kind), ident, span, false) + (self.r.dummy_ext(macro_kind), ident, span, false, Vec::new()) } None => return parent_scope.macro_rules, }, @@ -1264,7 +1274,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { self.r.define(module, ident, MacroNS, (res, vis, span, expansion, IsMacroExport)); } else { self.r.check_reserved_macro_name(ident, res); - self.insert_unused_macro(ident, def_id, item.id); + self.insert_unused_macro(ident, def_id, item.id, &rule_spans); } self.r.visibilities.insert(def_id, vis); let scope = self.r.arenas.alloc_macro_rules_scope(MacroRulesScope::Binding( @@ -1287,7 +1297,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { _ => self.resolve_visibility(&item.vis), }; if vis != ty::Visibility::Public { - self.insert_unused_macro(ident, def_id, item.id); + self.insert_unused_macro(ident, def_id, item.id, &rule_spans); } self.r.define(module, ident, MacroNS, (res, vis, span, expansion)); self.r.visibilities.insert(def_id, vis); diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 5d80f49626a0..05e5420e20de 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -35,6 +35,9 @@ use crate::{LexicalScopeBinding, NameBinding, NameBindingKind, PrivacyError, Vis use crate::{ParentScope, PathResult, ResolutionError, Resolver, Scope, ScopeSet}; use crate::{Segment, UseError}; +#[cfg(test)] +mod tests; + type Res = def::Res; /// A vector of spans and replacements, a message and applicability. @@ -2675,3 +2678,14 @@ fn is_span_suitable_for_use_injection(s: Span) -> bool { // import or other generated ones !s.from_expansion() } + +/// Convert the given number into the corresponding ordinal +crate fn ordinalize(v: usize) -> String { + let suffix = match ((11..=13).contains(&(v % 100)), v % 10) { + (false, 1) => "st", + (false, 2) => "nd", + (false, 3) => "rd", + _ => "th", + }; + format!("{v}{suffix}") +} diff --git a/compiler/rustc_resolve/src/diagnostics/tests.rs b/compiler/rustc_resolve/src/diagnostics/tests.rs new file mode 100644 index 000000000000..2aa6cc61e460 --- /dev/null +++ b/compiler/rustc_resolve/src/diagnostics/tests.rs @@ -0,0 +1,40 @@ +use super::ordinalize; + +#[test] +fn test_ordinalize() { + assert_eq!(ordinalize(1), "1st"); + assert_eq!(ordinalize(2), "2nd"); + assert_eq!(ordinalize(3), "3rd"); + assert_eq!(ordinalize(4), "4th"); + assert_eq!(ordinalize(5), "5th"); + // ... + assert_eq!(ordinalize(10), "10th"); + assert_eq!(ordinalize(11), "11th"); + assert_eq!(ordinalize(12), "12th"); + assert_eq!(ordinalize(13), "13th"); + assert_eq!(ordinalize(14), "14th"); + // ... + assert_eq!(ordinalize(20), "20th"); + assert_eq!(ordinalize(21), "21st"); + assert_eq!(ordinalize(22), "22nd"); + assert_eq!(ordinalize(23), "23rd"); + assert_eq!(ordinalize(24), "24th"); + // ... + assert_eq!(ordinalize(30), "30th"); + assert_eq!(ordinalize(31), "31st"); + assert_eq!(ordinalize(32), "32nd"); + assert_eq!(ordinalize(33), "33rd"); + assert_eq!(ordinalize(34), "34th"); + // ... + assert_eq!(ordinalize(7010), "7010th"); + assert_eq!(ordinalize(7011), "7011th"); + assert_eq!(ordinalize(7012), "7012th"); + assert_eq!(ordinalize(7013), "7013th"); + assert_eq!(ordinalize(7014), "7014th"); + // ... + assert_eq!(ordinalize(7020), "7020th"); + assert_eq!(ordinalize(7021), "7021st"); + assert_eq!(ordinalize(7022), "7022nd"); + assert_eq!(ordinalize(7023), "7023rd"); + assert_eq!(ordinalize(7024), "7024th"); +} diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index df6733ac45f9..723e66e9ef61 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3105,6 +3105,13 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ); } + fn resolve_inline_const(&mut self, constant: &'ast AnonConst) { + debug!("resolve_anon_const {constant:?}"); + self.with_constant_rib(IsRepeatExpr::No, HasGenericParams::Yes, None, |this| { + visit::walk_anon_const(this, constant); + }); + } + fn resolve_expr(&mut self, expr: &'ast Expr, parent: Option<&'ast Expr>) { // First, record candidate traits for this expression if it could // result in the invocation of a method call. @@ -3261,7 +3268,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { }); } ExprKind::ConstBlock(ref ct) => { - self.resolve_anon_const(ct, IsRepeatExpr::No); + self.resolve_inline_const(ct); } ExprKind::Index(ref elem, ref idx) => { self.resolve_expr(elem, Some(expr)); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 62485beac476..8d3c46c29a86 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -975,6 +975,7 @@ pub struct Resolver<'a> { local_macro_def_scopes: FxHashMap>, ast_transform_scopes: FxHashMap>, unused_macros: FxHashMap, + unused_macro_rules: FxHashMap<(LocalDefId, usize), (Ident, Span)>, proc_macro_stubs: FxHashSet, /// Traces collected during macro resolution and validated when it's complete. single_segment_macro_resolutions: @@ -1374,6 +1375,7 @@ impl<'a> Resolver<'a> { potentially_unused_imports: Vec::new(), struct_constructors: Default::default(), unused_macros: Default::default(), + unused_macro_rules: Default::default(), proc_macro_stubs: Default::default(), single_segment_macro_resolutions: Default::default(), multi_segment_macro_resolutions: Default::default(), diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 19a9c1b99fc4..2337f72f1e8b 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -22,7 +22,8 @@ use rustc_hir::def::{self, DefKind, NonMacroAttrKind}; use rustc_hir::def_id::{CrateNum, LocalDefId}; use rustc_middle::middle::stability; use rustc_middle::ty::RegisteredTools; -use rustc_session::lint::builtin::{LEGACY_DERIVE_HELPERS, SOFT_UNSTABLE, UNUSED_MACROS}; +use rustc_session::lint::builtin::{LEGACY_DERIVE_HELPERS, SOFT_UNSTABLE}; +use rustc_session::lint::builtin::{UNUSED_MACROS, UNUSED_MACRO_RULES}; use rustc_session::lint::BuiltinLintDiagnostics; use rustc_session::parse::feature_err; use rustc_session::Session; @@ -311,6 +312,11 @@ impl<'a> ResolverExpand for Resolver<'a> { Ok(ext) } + fn record_macro_rule_usage(&mut self, id: NodeId, rule_i: usize) { + let did = self.local_def_id(id); + self.unused_macro_rules.remove(&(did, rule_i)); + } + fn check_unused_macros(&mut self) { for (_, &(node_id, ident)) in self.unused_macros.iter() { self.lint_buffer.buffer_lint( @@ -320,6 +326,23 @@ impl<'a> ResolverExpand for Resolver<'a> { &format!("unused macro definition: `{}`", ident.as_str()), ); } + for (&(def_id, arm_i), &(ident, rule_span)) in self.unused_macro_rules.iter() { + if self.unused_macros.contains_key(&def_id) { + // We already lint the entire macro as unused + continue; + } + let node_id = self.def_id_to_node_id[def_id]; + self.lint_buffer.buffer_lint( + UNUSED_MACRO_RULES, + node_id, + rule_span, + &format!( + "{} rule of macro `{}` is never used", + crate::diagnostics::ordinalize(arm_i + 1), + ident.as_str() + ), + ); + } } fn has_derive_copy(&self, expn_id: LocalExpnId) -> bool { @@ -830,10 +853,15 @@ impl<'a> Resolver<'a> { } } - /// Compile the macro into a `SyntaxExtension` and possibly replace - /// its expander to a pre-defined one for built-in macros. - crate fn compile_macro(&mut self, item: &ast::Item, edition: Edition) -> SyntaxExtension { - let mut result = compile_declarative_macro( + /// Compile the macro into a `SyntaxExtension` and its rule spans. + /// + /// Possibly replace its expander to a pre-defined one for built-in macros. + crate fn compile_macro( + &mut self, + item: &ast::Item, + edition: Edition, + ) -> (SyntaxExtension, Vec) { + let (mut result, mut rule_spans) = compile_declarative_macro( &self.session, self.session.features_untracked(), item, @@ -849,6 +877,7 @@ impl<'a> Resolver<'a> { match mem::replace(builtin_macro, BuiltinMacroState::AlreadySeen(item.span)) { BuiltinMacroState::NotYetSeen(ext) => { result.kind = ext; + rule_spans = Vec::new(); if item.id != ast::DUMMY_NODE_ID { self.builtin_macro_kinds .insert(self.local_def_id(item.id), result.macro_kind()); @@ -871,6 +900,6 @@ impl<'a> Resolver<'a> { } } - result + (result, rule_spans) } } diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index e933fe1cb241..6fb87e15a330 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -289,12 +289,26 @@ impl ParseSess { self.proc_macro_quoted_spans.lock().clone() } + pub fn create_err<'a>( + &'a self, + err: impl SessionDiagnostic<'a>, + ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { + err.into_diagnostic(self) + } + pub fn emit_err<'a>(&'a self, err: impl SessionDiagnostic<'a>) -> ErrorGuaranteed { - err.into_diagnostic(self).emit() + self.create_err(err).emit() + } + + pub fn create_warning<'a>( + &'a self, + warning: impl SessionDiagnostic<'a, ()>, + ) -> DiagnosticBuilder<'a, ()> { + warning.into_diagnostic(self) } pub fn emit_warning<'a>(&'a self, warning: impl SessionDiagnostic<'a, ()>) { - warning.into_diagnostic(self).emit() + self.create_warning(warning).emit() } pub fn struct_err( diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index e8279f6fed24..b2c23cda6aae 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -413,9 +413,21 @@ impl Session { pub fn err(&self, msg: impl Into) -> ErrorGuaranteed { self.diagnostic().err(msg) } + pub fn create_err<'a>( + &'a self, + err: impl SessionDiagnostic<'a>, + ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { + self.parse_sess.create_err(err) + } pub fn emit_err<'a>(&'a self, err: impl SessionDiagnostic<'a>) -> ErrorGuaranteed { self.parse_sess.emit_err(err) } + pub fn create_warning<'a>( + &'a self, + err: impl SessionDiagnostic<'a, ()>, + ) -> DiagnosticBuilder<'a, ()> { + self.parse_sess.create_warning(err) + } pub fn emit_warning<'a>(&'a self, warning: impl SessionDiagnostic<'a, ()>) { self.parse_sess.emit_warning(warning) } diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs index 0e8fd9cc93fd..a2cd3c4c4681 100644 --- a/compiler/rustc_target/src/abi/mod.rs +++ b/compiler/rustc_target/src/abi/mod.rs @@ -276,12 +276,19 @@ impl ToJson for Endian { } /// Size of a type in bytes. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Encodable, Decodable)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] #[derive(HashStable_Generic)] pub struct Size { raw: u64, } +// This is debug-printed a lot in larger structs, don't waste too much space there +impl fmt::Debug for Size { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Size({} bytes)", self.bytes()) + } +} + impl Size { pub const ZERO: Size = Size { raw: 0 }; @@ -485,12 +492,19 @@ impl Step for Size { } /// Alignment of a type in bytes (always a power of two). -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Encodable, Decodable)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] #[derive(HashStable_Generic)] pub struct Align { pow2: u8, } +// This is debug-printed a lot in larger structs, don't waste too much space there +impl fmt::Debug for Align { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Align({} bytes)", self.bytes()) + } +} + impl Align { pub const ONE: Align = Align { pow2: 0 }; diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs index 794e711b6c83..38c29d3874c9 100644 --- a/compiler/rustc_typeck/src/astconv/generics.rs +++ b/compiler/rustc_typeck/src/astconv/generics.rs @@ -3,7 +3,10 @@ use crate::astconv::{ AstConv, CreateSubstsForGenericArgsCtxt, ExplicitLateBound, GenericArgCountMismatch, GenericArgCountResult, GenericArgPosition, }; -use crate::errors::AssocTypeBindingNotAllowed; +use crate::errors::{ + AssocTypeBindingNotAllowed, ExplicitGenericArgsWithImplTrait, + ExplicitGenericArgsWithImplTraitFeature, +}; use crate::structured_errors::{GenericArgsInfo, StructuredDiagnostic, WrongNumberOfGenericArgs}; use rustc_ast::ast::ParamKindOrd; use rustc_errors::{struct_span_err, Applicability, Diagnostic, MultiSpan}; @@ -636,29 +639,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }) .collect::>(); - let mut err = struct_span_err! { - tcx.sess, - spans.clone(), - E0632, - "cannot provide explicit generic arguments when `impl Trait` is \ - used in argument position" - }; - - for span in spans { - err.span_label(span, "explicit generic argument not allowed"); - } - - err.note( - "see issue #83701 \ - for more information", - ); + let mut err = tcx.sess.create_err(ExplicitGenericArgsWithImplTrait { spans }); if tcx.sess.is_nightly_build() { - err.help( - "add `#![feature(explicit_generic_args_with_impl_trait)]` \ - to the crate attributes to enable", - ); + err.subdiagnostic(ExplicitGenericArgsWithImplTraitFeature); } - err.emit(); } diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index 9dbb81329326..c1d4bb92173d 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -914,6 +914,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { reasons.auto_traits.extend(auto_trait_reasons); reasons.drop_order = drop_order; + // `auto_trait_reasons` are in hashset order, so sort them to put the + // diagnostics we emit later in a cross-platform-consistent order. + reasons.auto_traits.sort_unstable(); + reasons } diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 75ad584f4199..e37e0c91de46 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -14,6 +14,7 @@ use rustc_span::{Span, DUMMY_SP}; use super::ItemCtxt; use super::{bad_placeholder, is_suggestable_infer_ty}; +use crate::errors::UnconstrainedOpaqueType; /// Computes the relevant generic parameter for a potential generic const argument. /// @@ -682,13 +683,10 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { match locator.found { Some(hidden) => hidden.ty, None => { - let span = tcx.def_span(def_id); - let name = tcx.item_name(tcx.local_parent(def_id).to_def_id()); - let label = format!( - "`{}` must be used in combination with a concrete type within the same module", - name - ); - tcx.sess.struct_span_err(span, "unconstrained opaque type").note(&label).emit(); + tcx.sess.emit_err(UnconstrainedOpaqueType { + span: tcx.def_span(def_id), + name: tcx.item_name(tcx.local_parent(def_id).to_def_id()), + }); tcx.ty_error() } } diff --git a/compiler/rustc_typeck/src/errors.rs b/compiler/rustc_typeck/src/errors.rs index 3d2f93537e4e..a3e7108caae0 100644 --- a/compiler/rustc_typeck/src/errors.rs +++ b/compiler/rustc_typeck/src/errors.rs @@ -228,3 +228,25 @@ pub enum ExpectedReturnTypeLabel<'tcx> { expected: Ty<'tcx>, }, } + +#[derive(SessionDiagnostic)] +#[error(slug = "typeck-unconstrained-opaque-type")] +#[note] +pub struct UnconstrainedOpaqueType { + #[primary_span] + pub span: Span, + pub name: Symbol, +} + +#[derive(SessionDiagnostic)] +#[error(code = "E0632", slug = "typeck-explicit-generic-args-with-impl-trait")] +#[note] +pub struct ExplicitGenericArgsWithImplTrait { + #[primary_span] + #[label] + pub spans: Vec, +} + +#[derive(SessionSubdiagnostic)] +#[help(slug = "typeck-explicit-generic-args-with-impl-trait-feature")] +pub struct ExplicitGenericArgsWithImplTraitFeature; diff --git a/library/alloc/src/macros.rs b/library/alloc/src/macros.rs index 22c19243e7f5..093b02113c3a 100644 --- a/library/alloc/src/macros.rs +++ b/library/alloc/src/macros.rs @@ -56,6 +56,7 @@ macro_rules! vec { // `slice::into_vec` function which is only available with cfg(test) // NB see the slice::hack module in slice.rs for more information #[cfg(all(not(no_global_oom_handling), test))] +#[cfg_attr(not(bootstrap), allow(unused_macro_rules))] macro_rules! vec { () => ( $crate::vec::Vec::new() diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 1db6064551ca..17644aeed856 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -232,6 +232,8 @@ crate fn create_config( rustc_lint::builtin::RENAMED_AND_REMOVED_LINTS.name.to_string(), rustc_lint::builtin::UNKNOWN_LINTS.name.to_string(), rustc_lint::builtin::UNEXPECTED_CFGS.name.to_string(), + // this lint is needed to support `#[expect]` attributes + rustc_lint::builtin::UNFULFILLED_LINT_EXPECTATIONS.name.to_string(), ]; lints_to_show.extend(crate::lint::RUSTDOC_LINTS.iter().map(|lint| lint.name.to_string())); @@ -463,6 +465,8 @@ crate fn run_global_ctxt( } } + tcx.sess.time("check_lint_expectations", || tcx.check_expectations(Some(sym::rustdoc))); + if tcx.sess.diagnostic().has_errors_or_lint_errors().is_some() { rustc_errors::FatalError.raise(); } diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index b4d2772b31da..30190138750c 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -248,7 +248,16 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { } // Index this method for searching later on. - if let Some(ref s) = item.name { + if let Some(ref s) = item.name.or_else(|| { + if item.is_stripped() { + None + } else if let clean::ImportItem(ref i) = *item.kind && + let clean::ImportKind::Simple(s) = i.kind { + Some(s) + } else { + None + } + }) { let (parent, is_inherent_impl_item) = match *item.kind { clean::StrippedItem(..) => ((None, None), false), clean::AssocConstItem(..) | clean::AssocTypeItem(..) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index fedeb449b2e0..195824819101 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2542,7 +2542,16 @@ fn sidebar_module(buf: &mut Buffer, items: &[clean::Item]) { let item_sections_in_use: FxHashSet<_> = items .iter() - .filter(|it| !it.is_stripped() && it.name.is_some()) + .filter(|it| { + !it.is_stripped() + && it + .name + .or_else(|| { + if let clean::ImportItem(ref i) = *it.kind && + let clean::ImportKind::Simple(s) = i.kind { Some(s) } else { None } + }) + .is_some() + }) .map(|it| item_ty_to_section(it.type_())) .collect(); for &sec in ItemSection::ALL.iter().filter(|sec| item_sections_in_use.contains(sec)) { diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index f1915920b6d0..fbb3d3e45845 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -3,7 +3,7 @@ use clean::AttributesExt; use std::cmp::Ordering; use std::fmt; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir as hir; use rustc_hir::def::CtorKind; use rustc_hir::def_id::DefId; @@ -346,7 +346,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl w.write_str(ITEM_TABLE_ROW_OPEN); write!( w, - "
\ + "
\ {vis}{imp}\
\
{stab_tags}
", @@ -355,6 +355,11 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl vis = myitem.visibility.print_with_space(myitem.item_id, cx), imp = import.print(cx), stab_tags = stab_tags.unwrap_or_default(), + id = match import.kind { + clean::ImportKind::Simple(s) => + format!(" id=\"{}\"", cx.derive_id(format!("reexport.{}", s))), + clean::ImportKind::Glob => String::new(), + }, ); w.write_str(ITEM_TABLE_ROW_CLOSE); } @@ -790,16 +795,18 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All); let cache = cx.cache(); + let mut extern_crates = FxHashSet::default(); if let Some(implementors) = cache.implementors.get(&it.item_id.expect_def_id()) { // The DefId is for the first Type found with that name. The bool is // if any Types with the same name but different DefId have been found. let mut implementor_dups: FxHashMap = FxHashMap::default(); for implementor in implementors { - match implementor.inner_impl().for_ { - clean::Type::Path { ref path } - | clean::BorrowedRef { type_: box clean::Type::Path { ref path }, .. } - if !path.is_assoc_ty() => - { + if let Some(did) = implementor.inner_impl().for_.without_borrowed_ref().def_id(cx.cache()) && + !did.is_local() { + extern_crates.insert(did.krate); + } + match implementor.inner_impl().for_.without_borrowed_ref() { + clean::Type::Path { ref path } if !path.is_assoc_ty() => { let did = path.def_id(); let &mut (prev_did, ref mut has_duplicates) = implementor_dups.entry(path.last()).or_insert((did, false)); @@ -898,20 +905,96 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra } } + // Include implementors in crates that depend on the current crate. + // + // This is complicated by the way rustdoc is invoked, which is basically + // the same way rustc is invoked: it gets called, one at a time, for each + // crate. When building the rustdocs for the current crate, rustdoc can + // see crate metadata for its dependencies, but cannot see metadata for its + // dependents. + // + // To make this work, we generate a "hook" at this stage, and our + // dependents can "plug in" to it when they build. For simplicity's sake, + // it's [JSONP]: a JavaScript file with the data we need (and can parse), + // surrounded by a tiny wrapper that the Rust side ignores, but allows the + // JavaScript side to include without having to worry about Same Origin + // Policy. The code for *that* is in `write_shared.rs`. + // + // This is further complicated by `#[doc(inline)]`. We want all copies + // of an inlined trait to reference the same JS file, to address complex + // dependency graphs like this one (lower crates depend on higher crates): + // + // ```text + // -------------------------------------------- + // | crate A: trait Foo | + // -------------------------------------------- + // | | + // -------------------------------- | + // | crate B: impl A::Foo for Bar | | + // -------------------------------- | + // | | + // --------------------------------------------- + // | crate C: #[doc(inline)] use A::Foo as Baz | + // | impl Baz for Quux | + // --------------------------------------------- + // ``` + // + // Basically, we want `C::Baz` and `A::Foo` to show the same set of + // impls, which is easier if they both treat `/implementors/A/trait.Foo.js` + // as the Single Source of Truth. + // + // We also want the `impl Baz for Quux` to be written to + // `trait.Foo.js`. However, when we generate plain HTML for `C::Baz`, + // we're going to want to generate plain HTML for `impl Baz for Quux` too, + // because that'll load faster, and it's better for SEO. And we don't want + // the same impl to show up twice on the same page. + // + // To make this work, the implementors JS file has a structure kinda + // like this: + // + // ```js + // JSONP({ + // "B": {"impl A::Foo for Bar"}, + // "C": {"impl Baz for Quux"}, + // }); + // ``` + // + // First of all, this means we can rebuild a crate, and it'll replace its own + // data if something changes. That is, `rustdoc` is idempotent. The other + // advantage is that we can list the crates that get included in the HTML, + // and ignore them when doing the JavaScript-based part of rendering. + // So C's HTML will have something like this: + // + // ```html + // + // ``` + // + // And, when the JS runs, anything in data-ignore-extern-crates is known + // to already be in the HTML, and will be ignored. + // + // [JSONP]: https://en.wikipedia.org/wiki/JSONP let mut js_src_path: UrlPartsBuilder = std::iter::repeat("..") .take(cx.current.len()) .chain(std::iter::once("implementors")) .collect(); - if it.item_id.is_local() { - js_src_path.extend(cx.current.iter().copied()); + if let Some(did) = it.item_id.as_def_id() && + let get_extern = { || cache.external_paths.get(&did).map(|s| s.0.clone()) } && + let Some(fqp) = cache.exact_paths.get(&did).cloned().or_else(get_extern) { + js_src_path.extend(fqp[..fqp.len() - 1].iter().copied()); + js_src_path.push_fmt(format_args!("{}.{}.js", it.type_(), fqp.last().unwrap())); } else { - let (ref path, _) = cache.external_paths[&it.item_id.expect_def_id()]; - js_src_path.extend(path[..path.len() - 1].iter().copied()); + js_src_path.extend(cx.current.iter().copied()); + js_src_path.push_fmt(format_args!("{}.{}.js", it.type_(), it.name.unwrap())); } - js_src_path.push_fmt(format_args!("{}.{}.js", it.type_(), it.name.unwrap())); + let extern_crates = extern_crates + .into_iter() + .map(|cnum| cx.shared.tcx.crate_name(cnum).to_string()) + .collect::>() + .join(","); write!( w, - "", + "", src = js_src_path.finish(), ); } diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index 7c202e471adb..e8e5fa179933 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -501,10 +501,13 @@ pub(super) fn write_shared( // // FIXME: this is a vague explanation for why this can't be a `get`, in // theory it should be... - let &(ref remote_path, remote_item_type) = match cache.paths.get(&did) { - Some(p) => p, + let (remote_path, remote_item_type) = match cache.exact_paths.get(&did) { + Some(p) => match cache.paths.get(&did).or_else(|| cache.external_paths.get(&did)) { + Some((_, t)) => (p, t), + None => continue, + }, None => match cache.external_paths.get(&did) { - Some(p) => p, + Some((p, t)) => (p, t), None => continue, }, }; diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 12059e0b9c4b..eb3ce37e313d 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1333,6 +1333,11 @@ pre.rust { border-top: 2px solid; } +#titles > button:first-child:last-child { + margin-right: 1px; + width: calc(100% - 1px); +} + #titles > button:not(:last-child) { margin-right: 1px; width: calc(33.3% - 1px); diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 66a7d484f33b..2d8339e83942 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -759,8 +759,14 @@ function loadCss(cssFileName) { const traitName = document.querySelector("h1.fqn > .in-band > .trait").textContent; const baseIdName = "impl-" + traitName + "-"; const libs = Object.getOwnPropertyNames(imp); + // We don't want to include impls from this JS file, when the HTML already has them. + // The current crate should always be ignored. Other crates that should also be + // ignored are included in the attribute `data-ignore-extern-crates`. + const ignoreExternCrates = document + .querySelector("script[data-ignore-extern-crates]") + .getAttribute("data-ignore-extern-crates"); for (const lib of libs) { - if (lib === window.currentCrate) { + if (lib === window.currentCrate || ignoreExternCrates.indexOf(lib) !== -1) { continue; } const structs = imp[lib]; diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 54ce2508c468..2eafa540a1aa 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -45,26 +45,33 @@ const TY_KEYWORD = itemTypes.indexOf("keyword"); // In the search display, allows to switch between tabs. function printTab(nb) { - if (nb === 0 || nb === 1 || nb === 2) { - searchState.currentTab = nb; - } - let nb_copy = nb; + let iter = 0; + let foundCurrentTab = false; + let foundCurrentResultSet = false; onEachLazy(document.getElementById("titles").childNodes, elem => { - if (nb_copy === 0) { + if (nb === iter) { addClass(elem, "selected"); + foundCurrentTab = true; } else { removeClass(elem, "selected"); } - nb_copy -= 1; + iter += 1; }); + iter = 0; onEachLazy(document.getElementById("results").childNodes, elem => { - if (nb === 0) { + if (nb === iter) { addClass(elem, "active"); + foundCurrentResultSet = true; } else { removeClass(elem, "active"); } - nb -= 1; + iter += 1; }); + if (foundCurrentTab && foundCurrentResultSet) { + searchState.currentTab = nb; + } else if (nb != 0) { + printTab(0); + } } /** @@ -1409,18 +1416,12 @@ window.initSearch = rawSearchIndex => { for (i = 0, nSearchWords = searchWords.length; i < nSearchWords; ++i) { row = searchIndex[i]; in_returned = checkReturned(row, elem, parsedQuery.typeFilter); - addIntoResults(results_returned, row.id, i, -1, in_returned); + addIntoResults(results_others, row.id, i, -1, in_returned); } } } else if (parsedQuery.foundElems > 0) { - let container = results_others; - // In the special case where only a "returned" information is available, we want to - // put the information into the "results_returned" dict. - if (parsedQuery.returned.length !== 0 && parsedQuery.elems.length === 0) { - container = results_returned; - } for (i = 0, nSearchWords = searchWords.length; i < nSearchWords; ++i) { - handleArgs(searchIndex[i], i, container); + handleArgs(searchIndex[i], i, results_others); } } } @@ -1509,6 +1510,9 @@ window.initSearch = rawSearchIndex => { displayPath = path + "::"; href = window.rootPath + path.replace(/::/g, "/") + "/" + name + "/index.html"; + } else if (type === "import") { + displayPath = item.path + "::"; + href = window.rootPath + item.path.replace(/::/g, "/") + "/index.html#reexport." + name; } else if (type === "primitive" || type === "keyword") { displayPath = ""; href = window.rootPath + path.replace(/::/g, "/") + @@ -1725,12 +1729,26 @@ window.initSearch = rawSearchIndex => { `${typeFilter} in ${crates}
`; if (results.query.error !== null) { output += `

Query parser error: "${results.query.error}".

`; + output += '
' + + makeTabHeader(0, "In Names", ret_others[1]) + + "
"; + currentTab = 0; + } else if (results.query.foundElems <= 1 && results.query.returned.length === 0) { + output += `
` + + makeTabHeader(0, "In Names", ret_others[1]) + + makeTabHeader(1, "In Parameters", ret_in_args[1]) + + makeTabHeader(2, "In Return Types", ret_returned[1]) + + "
"; + } else { + const signatureTabTitle = + results.query.elems.length === 0 ? "In Function Return Types" : + results.query.returned.length === 0 ? "In Function Parameters" : + "In Function Signatures"; + output += '
' + + makeTabHeader(0, signatureTabTitle, ret_others[1]) + + "
"; + currentTab = 0; } - output += `
` + - makeTabHeader(0, "In Names", ret_others[1]) + - makeTabHeader(1, "In Parameters", ret_in_args[1]) + - makeTabHeader(2, "In Return Types", ret_returned[1]) + - "
"; const resultsElem = document.createElement("div"); resultsElem.id = "results"; @@ -1745,12 +1763,16 @@ window.initSearch = rawSearchIndex => { } search.appendChild(resultsElem); // Reset focused elements. - searchState.focusedByTab = [null, null, null]; searchState.showResults(search); const elems = document.getElementById("titles").childNodes; - elems[0].onclick = () => { printTab(0); }; - elems[1].onclick = () => { printTab(1); }; - elems[2].onclick = () => { printTab(2); }; + searchState.focusedByTab = []; + let i = 0; + for (const elem of elems) { + const j = i; + elem.onclick = () => { printTab(j); }; + searchState.focusedByTab.push(null); + i += 1; + } printTab(currentTab); } diff --git a/src/test/mir-opt/const_debuginfo.main.ConstDebugInfo.diff b/src/test/mir-opt/const_debuginfo.main.ConstDebugInfo.diff index 7dd420e41cef..bbde6ad4b637 100644 --- a/src/test/mir-opt/const_debuginfo.main.ConstDebugInfo.diff +++ b/src/test/mir-opt/const_debuginfo.main.ConstDebugInfo.diff @@ -77,7 +77,7 @@ _9 = const "hello, world!"; // scope 4 at $DIR/const_debuginfo.rs:14:13: 14:28 // mir::Constant // + span: $DIR/const_debuginfo.rs:14:13: 14:28 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [104, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [8191], len: Size { raw: 13 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 13 }) } + // + literal: Const { ty: &str, val: Value(Slice(..)) } StorageLive(_10); // scope 5 at $DIR/const_debuginfo.rs:16:9: 16:10 Deinit(_10); // scope 5 at $DIR/const_debuginfo.rs:16:13: 16:34 (_10.0: bool) = const true; // scope 5 at $DIR/const_debuginfo.rs:16:13: 16:34 diff --git a/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff b/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff index 49f6c1041576..cb4273ba6bd6 100644 --- a/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff +++ b/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff @@ -22,7 +22,7 @@ // + literal: Const { ty: fn(&str) -> ! {begin_panic::<&str>}, val: Value(Scalar()) } // mir::Constant // + span: $SRC_DIR/std/src/panic.rs:LL:COL - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [101, 120, 112, 108, 105, 99, 105, 116, 32, 112, 97, 110, 105, 99], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [16383], len: Size { raw: 14 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 14 }) } + // + literal: Const { ty: &str, val: Value(Slice(..)) } } bb2: { diff --git a/src/test/mir-opt/inline/inline_diverging.g.Inline.diff b/src/test/mir-opt/inline/inline_diverging.g.Inline.diff index 3b9d5e727b8a..31719b435d69 100644 --- a/src/test/mir-opt/inline/inline_diverging.g.Inline.diff +++ b/src/test/mir-opt/inline/inline_diverging.g.Inline.diff @@ -43,7 +43,7 @@ + // + literal: Const { ty: fn(&str) -> ! {begin_panic::<&str>}, val: Value(Scalar()) } + // mir::Constant + // + span: $SRC_DIR/std/src/panic.rs:LL:COL -+ // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [101, 120, 112, 108, 105, 99, 105, 116, 32, 112, 97, 110, 105, 99], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [16383], len: Size { raw: 14 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 14 }) } ++ // + literal: Const { ty: &str, val: Value(Slice(..)) } } } diff --git a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff index 7613afdf4fef..c19cbe3e5b0d 100644 --- a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff +++ b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff @@ -46,7 +46,7 @@ - bb2: { + // + span: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + // + user_ty: UserType(0) -+ // + literal: Const { ty: alloc::raw_vec::RawVec, val: Value(ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) } ++ // + literal: Const { ty: alloc::raw_vec::RawVec, val: Value(ByRef(..)) } + Deinit((*_7)); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + ((*_7).0: alloc::raw_vec::RawVec) = move _8; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + ((*_7).1: usize) = const 0_usize; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL diff --git a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff index a2f70f61cac9..c19cbe3e5b0d 100644 --- a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff +++ b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff @@ -46,7 +46,7 @@ - bb2: { + // + span: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + // + user_ty: UserType(0) -+ // + literal: Const { ty: alloc::raw_vec::RawVec, val: Value(ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [65535], len: Size { raw: 16 } }, align: Align { pow2: 3 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) } ++ // + literal: Const { ty: alloc::raw_vec::RawVec, val: Value(ByRef(..)) } + Deinit((*_7)); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + ((*_7).0: alloc::raw_vec::RawVec) = move _8; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + ((*_7).1: usize) = const 0_usize; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL diff --git a/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff b/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff index c1a4fc301d7c..f9e11439dd9d 100644 --- a/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff +++ b/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff @@ -73,7 +73,7 @@ // + literal: Const { ty: fn(&'static str) -> ! {core::panicking::panic}, val: Value(Scalar()) } // mir::Constant // + span: $SRC_DIR/core/src/panic.rs:LL:COL - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [105, 110, 116, 101, 114, 110, 97, 108, 32, 101, 114, 114, 111, 114, 58, 32, 101, 110, 116, 101, 114, 101, 100, 32, 117, 110, 114, 101, 97, 99, 104, 97, 98, 108, 101, 32, 99, 111, 100, 101], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1099511627775], len: Size { raw: 40 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 40 }) } + // + literal: Const { ty: &str, val: Value(Slice(..)) } } bb2: { diff --git a/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir b/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir index e2051c85af21..a61741748497 100644 --- a/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir +++ b/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir @@ -92,7 +92,7 @@ fn num_to_digit(_1: char) -> u32 { // + literal: Const { ty: fn(&'static str) -> ! {core::panicking::panic}, val: Value(Scalar()) } // mir::Constant // + span: $SRC_DIR/core/src/option.rs:LL:COL - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [99, 97, 108, 108, 101, 100, 32, 96, 79, 112, 116, 105, 111, 110, 58, 58, 117, 110, 119, 114, 97, 112, 40, 41, 96, 32, 111, 110, 32, 97, 32, 96, 78, 111, 110, 101, 96, 32, 118, 97, 108, 117, 101], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [8796093022207], len: Size { raw: 43 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 43 }) } + // + literal: Const { ty: &str, val: Value(Slice(..)) } } bb7: { diff --git a/src/test/mir-opt/no_drop_for_inactive_variant.unwrap.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/no_drop_for_inactive_variant.unwrap.SimplifyCfg-elaborate-drops.after.mir index d562f04560c3..2044d34a3db7 100644 --- a/src/test/mir-opt/no_drop_for_inactive_variant.unwrap.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/no_drop_for_inactive_variant.unwrap.SimplifyCfg-elaborate-drops.after.mir @@ -26,7 +26,7 @@ fn unwrap(_1: Option) -> T { // + literal: Const { ty: fn(&str) -> ! {begin_panic::<&str>}, val: Value(Scalar()) } // mir::Constant // + span: $SRC_DIR/std/src/panic.rs:LL:COL - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [101, 120, 112, 108, 105, 99, 105, 116, 32, 112, 97, 110, 105, 99], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [16383], len: Size { raw: 14 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 14 }) } + // + literal: Const { ty: &str, val: Value(Slice(..)) } } bb2: { diff --git a/src/test/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir b/src/test/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir index 22bf1acc57d7..bdab2d932221 100644 --- a/src/test/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir +++ b/src/test/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir @@ -15,7 +15,7 @@ fn main() -> () { _4 = const ""; // scope 0 at $DIR/no-spurious-drop-after-call.rs:9:20: 9:22 // mir::Constant // + span: $DIR/no-spurious-drop-after-call.rs:9:20: 9:22 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [], len: Size { raw: 0 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 0 }) } + // + literal: Const { ty: &str, val: Value(Slice(..)) } _3 = &(*_4); // scope 0 at $DIR/no-spurious-drop-after-call.rs:9:20: 9:34 _2 = ::to_string(move _3) -> bb1; // scope 0 at $DIR/no-spurious-drop-after-call.rs:9:20: 9:34 // mir::Constant diff --git a/src/test/mir-opt/storage_live_dead_in_statics.XXX.mir_map.0.mir b/src/test/mir-opt/storage_live_dead_in_statics.XXX.mir_map.0.mir index 62fbcaaa2893..e0875ab0069e 100644 --- a/src/test/mir-opt/storage_live_dead_in_statics.XXX.mir_map.0.mir +++ b/src/test/mir-opt/storage_live_dead_in_statics.XXX.mir_map.0.mir @@ -192,7 +192,7 @@ static XXX: &Foo = { _2 = Foo { tup: const "hi", data: move _3 }; // scope 0 at $DIR/storage_live_dead_in_statics.rs:5:29: 23:2 // mir::Constant // + span: $DIR/storage_live_dead_in_statics.rs:6:10: 6:14 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [104, 105], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [3], len: Size { raw: 2 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 2 }) } + // + literal: Const { ty: &str, val: Value(Slice(..)) } StorageDead(_3); // scope 0 at $DIR/storage_live_dead_in_statics.rs:23:1: 23:2 _1 = &_2; // scope 0 at $DIR/storage_live_dead_in_statics.rs:5:28: 23:2 _0 = &(*_1); // scope 0 at $DIR/storage_live_dead_in_statics.rs:5:28: 23:2 diff --git a/src/test/mir-opt/uninhabited_enum_branching.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir b/src/test/mir-opt/uninhabited_enum_branching.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir index 2b79a69b93b3..16fd328b6f96 100644 --- a/src/test/mir-opt/uninhabited_enum_branching.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir +++ b/src/test/mir-opt/uninhabited_enum_branching.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir @@ -22,7 +22,7 @@ fn main() -> () { _5 = const "C"; // scope 0 at $DIR/uninhabited_enum_branching.rs:23:21: 23:24 // mir::Constant // + span: $DIR/uninhabited_enum_branching.rs:23:21: 23:24 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } + // + literal: Const { ty: &str, val: Value(Slice(..)) } _1 = &(*_5); // scope 0 at $DIR/uninhabited_enum_branching.rs:23:21: 23:24 StorageDead(_5); // scope 0 at $DIR/uninhabited_enum_branching.rs:23:23: 23:24 StorageDead(_2); // scope 0 at $DIR/uninhabited_enum_branching.rs:24:6: 24:7 @@ -40,7 +40,7 @@ fn main() -> () { _9 = const "E"; // scope 0 at $DIR/uninhabited_enum_branching.rs:28:21: 28:24 // mir::Constant // + span: $DIR/uninhabited_enum_branching.rs:28:21: 28:24 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [69], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } + // + literal: Const { ty: &str, val: Value(Slice(..)) } _6 = &(*_9); // scope 0 at $DIR/uninhabited_enum_branching.rs:28:21: 28:24 StorageDead(_9); // scope 0 at $DIR/uninhabited_enum_branching.rs:28:23: 28:24 goto -> bb3; // scope 0 at $DIR/uninhabited_enum_branching.rs:28:23: 28:24 @@ -50,7 +50,7 @@ fn main() -> () { _6 = const "D"; // scope 0 at $DIR/uninhabited_enum_branching.rs:27:21: 27:24 // mir::Constant // + span: $DIR/uninhabited_enum_branching.rs:27:21: 27:24 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } + // + literal: Const { ty: &str, val: Value(Slice(..)) } goto -> bb3; // scope 0 at $DIR/uninhabited_enum_branching.rs:27:21: 27:24 } diff --git a/src/test/mir-opt/uninhabited_enum_branching.main.UninhabitedEnumBranching.diff b/src/test/mir-opt/uninhabited_enum_branching.main.UninhabitedEnumBranching.diff index fe87bbd8c0b8..c499e5c59dbe 100644 --- a/src/test/mir-opt/uninhabited_enum_branching.main.UninhabitedEnumBranching.diff +++ b/src/test/mir-opt/uninhabited_enum_branching.main.UninhabitedEnumBranching.diff @@ -28,7 +28,7 @@ _5 = const "C"; // scope 0 at $DIR/uninhabited_enum_branching.rs:23:21: 23:24 // mir::Constant // + span: $DIR/uninhabited_enum_branching.rs:23:21: 23:24 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } + // + literal: Const { ty: &str, val: Value(Slice(..)) } _1 = &(*_5); // scope 0 at $DIR/uninhabited_enum_branching.rs:23:21: 23:24 StorageDead(_5); // scope 0 at $DIR/uninhabited_enum_branching.rs:23:23: 23:24 goto -> bb4; // scope 0 at $DIR/uninhabited_enum_branching.rs:23:23: 23:24 @@ -38,7 +38,7 @@ _1 = const "A(Empty)"; // scope 0 at $DIR/uninhabited_enum_branching.rs:21:24: 21:34 // mir::Constant // + span: $DIR/uninhabited_enum_branching.rs:21:24: 21:34 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [65, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) } + // + literal: Const { ty: &str, val: Value(Slice(..)) } goto -> bb4; // scope 0 at $DIR/uninhabited_enum_branching.rs:21:24: 21:34 } @@ -47,7 +47,7 @@ _4 = const "B(Empty)"; // scope 0 at $DIR/uninhabited_enum_branching.rs:22:24: 22:34 // mir::Constant // + span: $DIR/uninhabited_enum_branching.rs:22:24: 22:34 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [66, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) } + // + literal: Const { ty: &str, val: Value(Slice(..)) } _1 = &(*_4); // scope 0 at $DIR/uninhabited_enum_branching.rs:22:24: 22:34 StorageDead(_4); // scope 0 at $DIR/uninhabited_enum_branching.rs:22:33: 22:34 goto -> bb4; // scope 0 at $DIR/uninhabited_enum_branching.rs:22:33: 22:34 @@ -69,7 +69,7 @@ _9 = const "E"; // scope 0 at $DIR/uninhabited_enum_branching.rs:28:21: 28:24 // mir::Constant // + span: $DIR/uninhabited_enum_branching.rs:28:21: 28:24 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [69], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } + // + literal: Const { ty: &str, val: Value(Slice(..)) } _6 = &(*_9); // scope 0 at $DIR/uninhabited_enum_branching.rs:28:21: 28:24 StorageDead(_9); // scope 0 at $DIR/uninhabited_enum_branching.rs:28:23: 28:24 goto -> bb7; // scope 0 at $DIR/uninhabited_enum_branching.rs:28:23: 28:24 @@ -79,7 +79,7 @@ _6 = const "D"; // scope 0 at $DIR/uninhabited_enum_branching.rs:27:21: 27:24 // mir::Constant // + span: $DIR/uninhabited_enum_branching.rs:27:21: 27:24 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } + // + literal: Const { ty: &str, val: Value(Slice(..)) } goto -> bb7; // scope 0 at $DIR/uninhabited_enum_branching.rs:27:21: 27:24 } diff --git a/src/test/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir b/src/test/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir index 27f9c8b7f8fe..77951bc8d7b6 100644 --- a/src/test/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir +++ b/src/test/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir @@ -40,7 +40,7 @@ fn main() -> () { _8 = const "D"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:21: 25:24 // mir::Constant // + span: $DIR/uninhabited_enum_branching2.rs:25:21: 25:24 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } + // + literal: Const { ty: &str, val: Value(Slice(..)) } _3 = &(*_8); // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:21: 25:24 StorageDead(_8); // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:23: 25:24 goto -> bb3; // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:23: 25:24 @@ -51,7 +51,7 @@ fn main() -> () { _7 = const "C"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:21: 24:24 // mir::Constant // + span: $DIR/uninhabited_enum_branching2.rs:24:21: 24:24 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } + // + literal: Const { ty: &str, val: Value(Slice(..)) } _3 = &(*_7); // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:21: 24:24 StorageDead(_7); // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:23: 24:24 goto -> bb3; // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:23: 24:24 @@ -70,7 +70,7 @@ fn main() -> () { _13 = const "D"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:21: 32:24 // mir::Constant // + span: $DIR/uninhabited_enum_branching2.rs:32:21: 32:24 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } + // + literal: Const { ty: &str, val: Value(Slice(..)) } _9 = &(*_13); // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:21: 32:24 StorageDead(_13); // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:23: 32:24 goto -> bb6; // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:23: 32:24 @@ -81,7 +81,7 @@ fn main() -> () { _12 = const "C"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:21: 31:24 // mir::Constant // + span: $DIR/uninhabited_enum_branching2.rs:31:21: 31:24 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } + // + literal: Const { ty: &str, val: Value(Slice(..)) } _9 = &(*_12); // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:21: 31:24 StorageDead(_12); // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:23: 31:24 goto -> bb6; // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:23: 31:24 diff --git a/src/test/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff b/src/test/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff index 8622fccec888..1b06c730cdab 100644 --- a/src/test/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff +++ b/src/test/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff @@ -42,7 +42,7 @@ _8 = const "D"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:21: 25:24 // mir::Constant // + span: $DIR/uninhabited_enum_branching2.rs:25:21: 25:24 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } + // + literal: Const { ty: &str, val: Value(Slice(..)) } _3 = &(*_8); // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:21: 25:24 StorageDead(_8); // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:23: 25:24 goto -> bb5; // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:23: 25:24 @@ -52,7 +52,7 @@ _3 = const "A(Empty)"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:22:24: 22:34 // mir::Constant // + span: $DIR/uninhabited_enum_branching2.rs:22:24: 22:34 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [65, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) } + // + literal: Const { ty: &str, val: Value(Slice(..)) } goto -> bb5; // scope 1 at $DIR/uninhabited_enum_branching2.rs:22:24: 22:34 } @@ -61,7 +61,7 @@ _6 = const "B(Empty)"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:23:24: 23:34 // mir::Constant // + span: $DIR/uninhabited_enum_branching2.rs:23:24: 23:34 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [66, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) } + // + literal: Const { ty: &str, val: Value(Slice(..)) } _3 = &(*_6); // scope 1 at $DIR/uninhabited_enum_branching2.rs:23:24: 23:34 StorageDead(_6); // scope 1 at $DIR/uninhabited_enum_branching2.rs:23:33: 23:34 goto -> bb5; // scope 1 at $DIR/uninhabited_enum_branching2.rs:23:33: 23:34 @@ -72,7 +72,7 @@ _7 = const "C"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:21: 24:24 // mir::Constant // + span: $DIR/uninhabited_enum_branching2.rs:24:21: 24:24 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } + // + literal: Const { ty: &str, val: Value(Slice(..)) } _3 = &(*_7); // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:21: 24:24 StorageDead(_7); // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:23: 24:24 goto -> bb5; // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:23: 24:24 @@ -92,7 +92,7 @@ _13 = const "D"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:21: 32:24 // mir::Constant // + span: $DIR/uninhabited_enum_branching2.rs:32:21: 32:24 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } + // + literal: Const { ty: &str, val: Value(Slice(..)) } _9 = &(*_13); // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:21: 32:24 StorageDead(_13); // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:23: 32:24 goto -> bb10; // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:23: 32:24 @@ -102,7 +102,7 @@ _9 = const "A(Empty)"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:29:24: 29:34 // mir::Constant // + span: $DIR/uninhabited_enum_branching2.rs:29:24: 29:34 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [65, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) } + // + literal: Const { ty: &str, val: Value(Slice(..)) } goto -> bb10; // scope 1 at $DIR/uninhabited_enum_branching2.rs:29:24: 29:34 } @@ -111,7 +111,7 @@ _11 = const "B(Empty)"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:30:24: 30:34 // mir::Constant // + span: $DIR/uninhabited_enum_branching2.rs:30:24: 30:34 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [66, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) } + // + literal: Const { ty: &str, val: Value(Slice(..)) } _9 = &(*_11); // scope 1 at $DIR/uninhabited_enum_branching2.rs:30:24: 30:34 StorageDead(_11); // scope 1 at $DIR/uninhabited_enum_branching2.rs:30:33: 30:34 goto -> bb10; // scope 1 at $DIR/uninhabited_enum_branching2.rs:30:33: 30:34 @@ -122,7 +122,7 @@ _12 = const "C"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:21: 31:24 // mir::Constant // + span: $DIR/uninhabited_enum_branching2.rs:31:21: 31:24 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } + // + literal: Const { ty: &str, val: Value(Slice(..)) } _9 = &(*_12); // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:21: 31:24 StorageDead(_12); // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:23: 31:24 goto -> bb10; // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:23: 31:24 diff --git a/src/test/rustdoc-gui/implementors.goml b/src/test/rustdoc-gui/implementors.goml index 6460a917e92d..f29613f78b1b 100644 --- a/src/test/rustdoc-gui/implementors.goml +++ b/src/test/rustdoc-gui/implementors.goml @@ -18,3 +18,10 @@ assert: "#implementors-list .impl:nth-child(2) > .code-header.in-band" goto: file://|DOC_PATH|/test_docs/struct.HasEmptyTraits.html compare-elements-position-near-false: ("#impl-EmptyTrait1", "#impl-EmptyTrait2", {"y": 30}) compare-elements-position-near: ("#impl-EmptyTrait3 h3", "#impl-EmptyTrait3 .item-info", {"y": 30}) + +// Now check that re-exports work correctly. +// There should be exactly one impl shown on both of these pages. +goto: file://|DOC_PATH|/lib2/trait.TraitToReexport.html +assert-count: ("#implementors-list .impl", 1) +goto: file://|DOC_PATH|/implementors/trait.TraitToReexport.html +assert-count: ("#implementors-list .impl", 1) diff --git a/src/test/rustdoc-gui/search-reexport.goml b/src/test/rustdoc-gui/search-reexport.goml new file mode 100644 index 000000000000..557781d48109 --- /dev/null +++ b/src/test/rustdoc-gui/search-reexport.goml @@ -0,0 +1,29 @@ +// Checks that the reexports are present in the search index, can have +// doc aliases and are highligted when their ID is the hash of the page. +goto: file://|DOC_PATH|/test_docs/index.html +local-storage: {"rustdoc-theme": "dark", "rustdoc-use-system-theme": "false"} +reload: +// First we check that the reexport has the correct ID and no background color. +assert-text: ("//*[@id='reexport.TheStdReexport']", "pub use ::std as TheStdReexport;") +assert-css: ("//*[@id='reexport.TheStdReexport']", {"background-color": "rgba(0, 0, 0, 0)"}) +write: (".search-input", "TheStdReexport") +wait-for: "//a[@class='result-import']" +assert-attribute: ( + "//a[@class='result-import']", + {"href": "../test_docs/index.html#reexport.TheStdReexport"}, +) +assert-text: ("//a[@class='result-import']", "test_docs::TheStdReexport") +click: "//a[@class='result-import']" +// We check that it has the background modified thanks to the focus. +wait-for-css: ("//*[@id='reexport.TheStdReexport']", {"background-color": "rgb(73, 74, 61)"}) + +// We now check that the alias is working as well on the reexport. +write: (".search-input", "AliasForTheStdReexport") +wait-for: "//a[@class='result-import']" +assert-text: ( + "//a[@class='result-import']", + "AliasForTheStdReexport - see test_docs::TheStdReexport", +) +// Same thing again, we click on it to ensure the background is once again set as expected. +click: "//a[@class='result-import']" +wait-for-css: ("//*[@id='reexport.TheStdReexport']", {"background-color": "rgb(73, 74, 61)"}) diff --git a/src/test/rustdoc-gui/search-tab-change-title-fn-sig.goml b/src/test/rustdoc-gui/search-tab-change-title-fn-sig.goml new file mode 100644 index 000000000000..763927f9d0fe --- /dev/null +++ b/src/test/rustdoc-gui/search-tab-change-title-fn-sig.goml @@ -0,0 +1,64 @@ +// Checks that the search tab results work correctly with function signature syntax +// First, try a search-by-name +goto: file://|DOC_PATH|/test_docs/index.html +write: (".search-input", "Foo") +// Waiting for the search results to appear... +wait-for: "#titles" +assert-attribute: ("#titles > button:nth-of-type(1)", {"class": "selected"}) +assert-text: ("#titles > button:nth-of-type(1)", "In Names", STARTS_WITH) +assert: "input.search-input:focus" +// Use left-right keys +press-key: "ArrowDown" +assert: "#results > .search-results.active > a:nth-of-type(1):focus" +press-key: "ArrowRight" +wait-for-attribute: ("#titles > button:nth-of-type(2)", {"class": "selected"}) +press-key: "ArrowRight" +wait-for-attribute: ("#titles > button:nth-of-type(3)", {"class": "selected"}) +press-key: "ArrowRight" +wait-for-attribute: ("#titles > button:nth-of-type(1)", {"class": "selected"}) +press-key: "ArrowLeft" +wait-for-attribute: ("#titles > button:nth-of-type(3)", {"class": "selected"}) + +// Now try search-by-return +goto: file://|DOC_PATH|/test_docs/index.html +write: (".search-input", "-> String") +// Waiting for the search results to appear... +wait-for: "#titles" +assert-attribute: ("#titles > button:nth-of-type(1)", {"class": "selected"}) +assert-text: ("#titles > button:nth-of-type(1)", "In Function Return Types", STARTS_WITH) +assert: "input.search-input:focus" +// Use left-right keys +press-key: "ArrowDown" +assert: "#results > .search-results.active > a:nth-of-type(1):focus" +press-key: "ArrowRight" +wait-for-attribute: ("#titles > button:nth-of-type(1)", {"class": "selected"}) +press-key: "ArrowRight" +wait-for-attribute: ("#titles > button:nth-of-type(1)", {"class": "selected"}) +press-key: "ArrowRight" +wait-for-attribute: ("#titles > button:nth-of-type(1)", {"class": "selected"}) +press-key: "ArrowLeft" +wait-for-attribute: ("#titles > button:nth-of-type(1)", {"class": "selected"}) + +// Try with a search-by-return with no results +goto: file://|DOC_PATH|/test_docs/index.html +write: (".search-input", "-> Something") +// Waiting for the search results to appear... +wait-for: "#titles" +assert-attribute: ("#titles > button:nth-of-type(1)", {"class": "selected"}) +assert-text: ("#titles > button:nth-of-type(1)", "In Function Return Types", STARTS_WITH) + +// Try with a search-by-parameter +goto: file://|DOC_PATH|/test_docs/index.html +write: (".search-input", "usize pattern") +// Waiting for the search results to appear... +wait-for: "#titles" +assert-attribute: ("#titles > button:nth-of-type(1)", {"class": "selected"}) +assert-text: ("#titles > button:nth-of-type(1)", "In Function Parameters", STARTS_WITH) + +// Try with a search-by-parameter-and-return +goto: file://|DOC_PATH|/test_docs/index.html +write: (".search-input", "pattern -> str") +// Waiting for the search results to appear... +wait-for: "#titles" +assert-attribute: ("#titles > button:nth-of-type(1)", {"class": "selected"}) +assert-text: ("#titles > button:nth-of-type(1)", "In Function Signatures", STARTS_WITH) diff --git a/src/test/rustdoc-gui/search-tab-selection-if-current-is-empty.goml b/src/test/rustdoc-gui/search-tab-selection-if-current-is-empty.goml deleted file mode 100644 index 52b3ceae7b11..000000000000 --- a/src/test/rustdoc-gui/search-tab-selection-if-current-is-empty.goml +++ /dev/null @@ -1,23 +0,0 @@ -// Checks that the first non-empty search result tab is selected if the default/currently selected -// one is empty. -goto: file://|DOC_PATH|/test_docs/index.html -write: (".search-input", "Foo") -// Waiting for the search results to appear... -wait-for: "#titles" -assert-attribute: ("#titles > button:nth-of-type(1)", {"class": "selected"}) - -// To go back to the original "state" -goto: file://|DOC_PATH|/test_docs/index.html -write: (".search-input", "-> String") -// Waiting for the search results to appear... -wait-for: "#titles" -// With this search, only the last tab shouldn't be empty so it should be selected. -assert-attribute: ("#titles > button:nth-of-type(3)", {"class": "selected"}) - -// To go back to the original "state" -goto: file://|DOC_PATH|/test_docs/index.html -write: (".search-input", "-> Something") -// Waiting for the search results to appear... -wait-for: "#titles" -// With this search, all the tabs are empty so the first one should remain selected. -assert-attribute: ("#titles > button:nth-of-type(1)", {"class": "selected"}) diff --git a/src/test/rustdoc-gui/sidebar.goml b/src/test/rustdoc-gui/sidebar.goml index 6b79b00d3f78..32fe3334f364 100644 --- a/src/test/rustdoc-gui/sidebar.goml +++ b/src/test/rustdoc-gui/sidebar.goml @@ -13,15 +13,16 @@ assert-css: ("#all-types", {"color": "rgb(53, 109, 164)"}) // We check that we have the crates list and that the "current" on is "test_docs". assert-text: (".sidebar-elems .crate > ul > li > a.current", "test_docs") // And we're also supposed to have the list of items in the current module. -assert-text: (".sidebar-elems section ul > li:nth-child(1)", "Modules") -assert-text: (".sidebar-elems section ul > li:nth-child(2)", "Macros") -assert-text: (".sidebar-elems section ul > li:nth-child(3)", "Structs") -assert-text: (".sidebar-elems section ul > li:nth-child(4)", "Enums") -assert-text: (".sidebar-elems section ul > li:nth-child(5)", "Traits") -assert-text: (".sidebar-elems section ul > li:nth-child(6)", "Functions") -assert-text: (".sidebar-elems section ul > li:nth-child(7)", "Type Definitions") -assert-text: (".sidebar-elems section ul > li:nth-child(8)", "Unions") -assert-text: (".sidebar-elems section ul > li:nth-child(9)", "Keywords") +assert-text: (".sidebar-elems section ul > li:nth-child(1)", "Re-exports") +assert-text: (".sidebar-elems section ul > li:nth-child(2)", "Modules") +assert-text: (".sidebar-elems section ul > li:nth-child(3)", "Macros") +assert-text: (".sidebar-elems section ul > li:nth-child(4)", "Structs") +assert-text: (".sidebar-elems section ul > li:nth-child(5)", "Enums") +assert-text: (".sidebar-elems section ul > li:nth-child(6)", "Traits") +assert-text: (".sidebar-elems section ul > li:nth-child(7)", "Functions") +assert-text: (".sidebar-elems section ul > li:nth-child(8)", "Type Definitions") +assert-text: (".sidebar-elems section ul > li:nth-child(9)", "Unions") +assert-text: (".sidebar-elems section ul > li:nth-child(10)", "Keywords") assert-text: ("#structs + .item-table .item-left > a", "Foo") click: "#structs + .item-table .item-left > a" diff --git a/src/test/rustdoc-gui/src/lib2/implementors/lib.rs b/src/test/rustdoc-gui/src/lib2/implementors/lib.rs index 6417a6ac5af6..1620e8422919 100644 --- a/src/test/rustdoc-gui/src/lib2/implementors/lib.rs +++ b/src/test/rustdoc-gui/src/lib2/implementors/lib.rs @@ -9,3 +9,12 @@ pub struct Struct; impl Whatever for Struct { type Foo = u8; } + +mod traits { + pub trait TraitToReexport { + fn method() {} + } +} + +#[doc(inline)] +pub use traits::TraitToReexport; diff --git a/src/test/rustdoc-gui/src/lib2/lib.rs b/src/test/rustdoc-gui/src/lib2/lib.rs index 83e86c439344..d06b46f952d0 100644 --- a/src/test/rustdoc-gui/src/lib2/lib.rs +++ b/src/test/rustdoc-gui/src/lib2/lib.rs @@ -43,6 +43,13 @@ impl implementors::Whatever for Foo { type Foo = u32; } +#[doc(inline)] +pub use implementors::TraitToReexport; + +pub struct StructToImplOnReexport; + +impl TraitToReexport for StructToImplOnReexport {} + pub mod sub_mod { /// ```txt /// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa diff --git a/src/test/rustdoc-gui/src/test_docs/lib.rs b/src/test/rustdoc-gui/src/test_docs/lib.rs index 348b1a65c786..b6fe9eb2565b 100644 --- a/src/test/rustdoc-gui/src/test_docs/lib.rs +++ b/src/test/rustdoc-gui/src/test_docs/lib.rs @@ -274,3 +274,6 @@ impl EmptyTrait3 for HasEmptyTraits {} mod macros; pub use macros::*; + +#[doc(alias = "AliasForTheStdReexport")] +pub use ::std as TheStdReexport; diff --git a/src/test/rustdoc-ui/expect-tool-lint-rfc-2383.rs b/src/test/rustdoc-ui/expect-tool-lint-rfc-2383.rs new file mode 100644 index 000000000000..0901ac3640fd --- /dev/null +++ b/src/test/rustdoc-ui/expect-tool-lint-rfc-2383.rs @@ -0,0 +1,157 @@ +// check-pass +#![feature(lint_reasons)] + +//! This file tests the `#[expect]` attribute implementation for tool lints. The same +//! file is used to test clippy and rustdoc. Any changes to this file should be synced +//! to the other test files as well. +//! +//! Expectations: +//! * rustc: only rustc lint expectations are emitted +//! * clippy: rustc and Clippy's expectations are emitted +//! * rustdoc: only rustdoc lint expectations are emitted +//! +//! This test can't cover every lint from Clippy, rustdoc and potentially other +//! tools that will be developed. This therefore only tests a small subset of lints + +#![expect(rustdoc::missing_crate_level_docs)] +//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] +//~| NOTE `#[warn(unfulfilled_lint_expectations)]` on by default + +mod rustc_ok { + //! See + + #[expect(dead_code)] + pub fn rustc_lints() { + let x = 42.0; + + #[expect(illegal_floating_point_literal_pattern)] + match x { + 5.0 => {} + 6.0 => {} + _ => {} + } + } +} + +mod rustc_warn { + //! See + + #[expect(dead_code)] + pub fn rustc_lints() { + let x = 42; + + #[expect(illegal_floating_point_literal_pattern)] + match x { + 5 => {} + 6 => {} + _ => {} + } + } +} + +pub mod rustdoc_ok { + //! See + + #[expect(rustdoc::broken_intra_doc_links)] + /// I want to link to [`Nonexistent`] but it doesn't exist! + pub fn foo() {} + + #[expect(rustdoc::invalid_html_tags)] + ///

+ pub fn bar() {} + + #[expect(rustdoc::bare_urls)] + /// http://example.org + pub fn baz() {} +} + +pub mod rustdoc_warn { + //! See + + #[expect(rustdoc::broken_intra_doc_links)] + //~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] + /// I want to link to [`bar`] but it doesn't exist! + pub fn foo() {} + + #[expect(rustdoc::invalid_html_tags)] + //~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] + ///

+ pub fn bar() {} + + #[expect(rustdoc::bare_urls)] + //~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] + /// + pub fn baz() {} +} + +mod clippy_ok { + //! See + + #[expect(clippy::almost_swapped)] + fn foo() { + let mut a = 0; + let mut b = 9; + a = b; + b = a; + } + + #[expect(clippy::bytes_nth)] + fn bar() { + let _ = "Hello".bytes().nth(3); + } + + #[expect(clippy::if_same_then_else)] + fn baz() { + let _ = if true { + 42 + } else { + 42 + }; + } + + #[expect(clippy::logic_bug)] + fn burger() { + let a = false; + let b = true; + + if a && b || a {} + } +} + +mod clippy_warn { + //! See + + #[expect(clippy::almost_swapped)] + fn foo() { + let mut a = 0; + let mut b = 9; + a = b; + } + + #[expect(clippy::bytes_nth)] + fn bar() { + let _ = "Hello".as_bytes().get(3); + } + + #[expect(clippy::if_same_then_else)] + fn baz() { + let _ = if true { + 33 + } else { + 42 + }; + } + + #[expect(clippy::logic_bug)] + fn burger() { + let a = false; + let b = true; + let c = false; + + if a && b || c {} + } +} + +fn main() { + rustc_warn::rustc_lints(); +} diff --git a/src/test/rustdoc-ui/expect-tool-lint-rfc-2383.stderr b/src/test/rustdoc-ui/expect-tool-lint-rfc-2383.stderr new file mode 100644 index 000000000000..efc5f349f4f4 --- /dev/null +++ b/src/test/rustdoc-ui/expect-tool-lint-rfc-2383.stderr @@ -0,0 +1,28 @@ +warning: this lint expectation is unfulfilled + --> $DIR/expect-tool-lint-rfc-2383.rs:16:11 + | +LL | #![expect(rustdoc::missing_crate_level_docs)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(unfulfilled_lint_expectations)]` on by default + +warning: this lint expectation is unfulfilled + --> $DIR/expect-tool-lint-rfc-2383.rs:71:14 + | +LL | #[expect(rustdoc::broken_intra_doc_links)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: this lint expectation is unfulfilled + --> $DIR/expect-tool-lint-rfc-2383.rs:76:14 + | +LL | #[expect(rustdoc::invalid_html_tags)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: this lint expectation is unfulfilled + --> $DIR/expect-tool-lint-rfc-2383.rs:81:14 + | +LL | #[expect(rustdoc::bare_urls)] + | ^^^^^^^^^^^^^^^^^^ + +warning: 4 warnings emitted + diff --git a/src/test/rustdoc/hidden-impls.rs b/src/test/rustdoc/hidden-impls.rs index 935bfb268637..8f33a6604c21 100644 --- a/src/test/rustdoc/hidden-impls.rs +++ b/src/test/rustdoc/hidden-impls.rs @@ -12,6 +12,6 @@ pub mod __hidden { // @has foo/trait.Clone.html // @!has - 'Foo' -// @has implementors/foo/trait.Clone.js +// @has implementors/core/clone/trait.Clone.js // @!has - 'Foo' pub use std::clone::Clone; diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs index efbf78ac87d7..c63410fa35bd 100644 --- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs +++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs @@ -474,3 +474,11 @@ struct Subdiagnostic { #[subdiagnostic] note: Note, } + +#[derive(SessionDiagnostic)] +#[error(code = "E0123", slug = "foo")] +struct VecField { + #[primary_span] + #[label] + spans: Vec, +} diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr index ee4907bb755c..a8367766ae1c 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr @@ -29,8 +29,8 @@ error: changes to closure capture in Rust 2021 will affect which traits the clos LL | thread::spawn(move || unsafe { | ^^^^^^^^^^^^^^ | | - | in Rust 2018, this closure implements `Sync` as `fptr` implements `Sync`, but in Rust 2021, this closure will no longer implement `Sync` because `fptr` is not fully captured and `fptr.0.0` does not implement `Sync` | in Rust 2018, this closure implements `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` because `fptr` is not fully captured and `fptr.0.0` does not implement `Send` + | in Rust 2018, this closure implements `Sync` as `fptr` implements `Sync`, but in Rust 2021, this closure will no longer implement `Sync` because `fptr` is not fully captured and `fptr.0.0` does not implement `Sync` ... LL | *fptr.0.0 = 20; | --------- in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0.0` diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr index 6594ec316532..2648b00435b3 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr @@ -4,8 +4,8 @@ error: changes to closure capture in Rust 2021 will affect which traits the clos LL | let result = panic::catch_unwind(move || { | ^^^^^^^ | | - | in Rust 2018, this closure implements `UnwindSafe` as `f` implements `UnwindSafe`, but in Rust 2021, this closure will no longer implement `UnwindSafe` because `f` is not fully captured and `f.0` does not implement `UnwindSafe` | in Rust 2018, this closure implements `RefUnwindSafe` as `f` implements `RefUnwindSafe`, but in Rust 2021, this closure will no longer implement `RefUnwindSafe` because `f` is not fully captured and `f.0` does not implement `RefUnwindSafe` + | in Rust 2018, this closure implements `UnwindSafe` as `f` implements `UnwindSafe`, but in Rust 2021, this closure will no longer implement `UnwindSafe` because `f` is not fully captured and `f.0` does not implement `UnwindSafe` ... LL | f.0() | --- in Rust 2018, this closure captures all of `f`, but in Rust 2021, it will only capture `f.0` diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr index 0008f1b2c07e..483eae6bb4b1 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr @@ -94,8 +94,8 @@ error: changes to closure capture in Rust 2021 will affect which traits the clos LL | thread::spawn(move || unsafe { | ^^^^^^^^^^^^^^ | | - | in Rust 2018, this closure implements `Sync` as `fptr1` implements `Sync`, but in Rust 2021, this closure will no longer implement `Sync` because `fptr1` is not fully captured and `fptr1.0.0` does not implement `Sync` | in Rust 2018, this closure implements `Send` as `fptr1` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` because `fptr1` is not fully captured and `fptr1.0.0` does not implement `Send` + | in Rust 2018, this closure implements `Sync` as `fptr1` implements `Sync`, but in Rust 2021, this closure will no longer implement `Sync` because `fptr1` is not fully captured and `fptr1.0.0` does not implement `Sync` | in Rust 2018, this closure implements `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` because `fptr2` is not fully captured and `fptr2.0` does not implement `Send` ... LL | *fptr1.0.0 = 20; diff --git a/src/test/ui/consts/const-float-bits-conv.rs b/src/test/ui/consts/const-float-bits-conv.rs index 310db2174aaf..fd5e42ef1707 100644 --- a/src/test/ui/consts/const-float-bits-conv.rs +++ b/src/test/ui/consts/const-float-bits-conv.rs @@ -3,6 +3,7 @@ #![feature(const_float_bits_conv)] #![feature(const_float_classify)] +#![allow(unused_macro_rules)] // Don't promote const fn nop(x: T) -> T { x } diff --git a/src/test/ui/inline-const/const-expr-generic-err.rs b/src/test/ui/inline-const/const-expr-generic-err.rs new file mode 100644 index 000000000000..4e8879af54af --- /dev/null +++ b/src/test/ui/inline-const/const-expr-generic-err.rs @@ -0,0 +1,15 @@ +// build-fail +#![feature(inline_const)] + +fn foo() { + const { assert!(std::mem::size_of::() == 0); } //~ ERROR E0080 +} + +fn bar() -> usize { + const { N - 1 } //~ ERROR E0080 +} + +fn main() { + foo::(); + bar::<0>(); +} diff --git a/src/test/ui/inline-const/const-expr-generic-err.stderr b/src/test/ui/inline-const/const-expr-generic-err.stderr new file mode 100644 index 000000000000..db0d85a2d4e7 --- /dev/null +++ b/src/test/ui/inline-const/const-expr-generic-err.stderr @@ -0,0 +1,29 @@ +error[E0080]: evaluation of `foo::::{constant#0}` failed + --> $DIR/const-expr-generic-err.rs:5:13 + | +LL | const { assert!(std::mem::size_of::() == 0); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: std::mem::size_of::() == 0', $DIR/const-expr-generic-err.rs:5:13 + | + = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: the above error was encountered while instantiating `fn foo::` + --> $DIR/const-expr-generic-err.rs:13:5 + | +LL | foo::(); + | ^^^^^^^^^^^^ + +error[E0080]: evaluation of `bar::<0_usize>::{constant#0}` failed + --> $DIR/const-expr-generic-err.rs:9:13 + | +LL | const { N - 1 } + | ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow + +note: the above error was encountered while instantiating `fn bar::<0_usize>` + --> $DIR/const-expr-generic-err.rs:14:5 + | +LL | bar::<0>(); + | ^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/inline-const/const-expr-generic-err2.rs b/src/test/ui/inline-const/const-expr-generic-err2.rs new file mode 100644 index 000000000000..e097cbe9dd6d --- /dev/null +++ b/src/test/ui/inline-const/const-expr-generic-err2.rs @@ -0,0 +1,10 @@ +#![feature(inline_const)] + +fn foo() { + let _ = [0u8; const { std::mem::size_of::() }]; + //~^ ERROR: constant expression depends on a generic parameter +} + +fn main() { + foo::(); +} diff --git a/src/test/ui/inline-const/const-expr-generic-err2.stderr b/src/test/ui/inline-const/const-expr-generic-err2.stderr new file mode 100644 index 000000000000..00b716cd2596 --- /dev/null +++ b/src/test/ui/inline-const/const-expr-generic-err2.stderr @@ -0,0 +1,10 @@ +error: constant expression depends on a generic parameter + --> $DIR/const-expr-generic-err2.rs:4:19 + | +LL | let _ = [0u8; const { std::mem::size_of::() }]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this may fail depending on what value the parameter takes + +error: aborting due to previous error + diff --git a/src/test/ui/inline-const/const-expr-generic.rs b/src/test/ui/inline-const/const-expr-generic.rs new file mode 100644 index 000000000000..3207bfa0e89e --- /dev/null +++ b/src/test/ui/inline-const/const-expr-generic.rs @@ -0,0 +1,15 @@ +// check-pass +#![feature(inline_const)] + +fn foo() -> usize { + const { std::mem::size_of::() } +} + +fn bar() -> usize { + const { N + 1 } +} + +fn main() { + foo::(); + bar::<1>(); +} diff --git a/src/test/ui/inline-const/const-match-pat-generic.rs b/src/test/ui/inline-const/const-match-pat-generic.rs index be7e1d8d4498..e1946467583e 100644 --- a/src/test/ui/inline-const/const-match-pat-generic.rs +++ b/src/test/ui/inline-const/const-match-pat-generic.rs @@ -1,6 +1,5 @@ #![allow(incomplete_features)] #![feature(inline_const_pat)] -#![feature(generic_const_exprs)] // rust-lang/rust#82518: ICE with inline-const in match referencing const-generic parameter @@ -16,7 +15,7 @@ const fn f(x: usize) -> usize { x + 1 } -fn bar() where [(); f(V)]: { +fn bar() { match 0 { const { f(V) } => {}, //~^ ERROR constant pattern depends on a generic parameter diff --git a/src/test/ui/inline-const/const-match-pat-generic.stderr b/src/test/ui/inline-const/const-match-pat-generic.stderr index 5fe5a7a6dad4..ade200d99ba3 100644 --- a/src/test/ui/inline-const/const-match-pat-generic.stderr +++ b/src/test/ui/inline-const/const-match-pat-generic.stderr @@ -1,17 +1,17 @@ error[E0158]: const parameters cannot be referenced in patterns - --> $DIR/const-match-pat-generic.rs:9:9 + --> $DIR/const-match-pat-generic.rs:8:9 | LL | const { V } => {}, | ^^^^^^^^^^^ error: constant pattern depends on a generic parameter - --> $DIR/const-match-pat-generic.rs:21:9 + --> $DIR/const-match-pat-generic.rs:20:9 | LL | const { f(V) } => {}, | ^^^^^^^^^^^^^^ error: constant pattern depends on a generic parameter - --> $DIR/const-match-pat-generic.rs:21:9 + --> $DIR/const-match-pat-generic.rs:20:9 | LL | const { f(V) } => {}, | ^^^^^^^^^^^^^^ diff --git a/src/test/ui/layout/debug.rs b/src/test/ui/layout/debug.rs index 299151df6649..a282e71235c3 100644 --- a/src/test/ui/layout/debug.rs +++ b/src/test/ui/layout/debug.rs @@ -1,4 +1,4 @@ -// normalize-stderr-test "pref: Align \{\n *pow2: [1-3],\n *\}" -> "pref: $$PREF_ALIGN" +// normalize-stderr-test "pref: Align\([1-8] bytes\)" -> "pref: $$PREF_ALIGN" #![feature(never_type, rustc_attrs, type_alias_impl_trait)] #![crate_type = "lib"] diff --git a/src/test/ui/layout/debug.stderr b/src/test/ui/layout/debug.stderr index 25f7febfef9d..56a1337e6a5e 100644 --- a/src/test/ui/layout/debug.stderr +++ b/src/test/ui/layout/debug.stderr @@ -1,9 +1,7 @@ error: layout_of(E) = Layout { fields: Arbitrary { offsets: [ - Size { - raw: 0, - }, + Size(0 bytes), ], memory_index: [ 0, @@ -33,27 +31,17 @@ error: layout_of(E) = Layout { }, largest_niche: None, align: AbiAndPrefAlign { - abi: Align { - pow2: 0, - }, + abi: Align(1 bytes), pref: $PREF_ALIGN, }, - size: Size { - raw: 4, - }, + size: Size(4 bytes), }, Layout { fields: Arbitrary { offsets: [ - Size { - raw: 4, - }, - Size { - raw: 4, - }, - Size { - raw: 8, - }, + Size(4 bytes), + Size(4 bytes), + Size(8 bytes), ], memory_index: [ 0, @@ -67,14 +55,10 @@ error: layout_of(E) = Layout { abi: Uninhabited, largest_niche: None, align: AbiAndPrefAlign { - abi: Align { - pow2: 2, - }, + abi: Align(4 bytes), pref: $PREF_ALIGN, }, - size: Size { - raw: 12, - }, + size: Size(12 bytes), }, ], }, @@ -83,9 +67,7 @@ error: layout_of(E) = Layout { }, largest_niche: Some( Niche { - offset: Size { - raw: 0, - }, + offset: Size(0 bytes), value: Int( I32, false, @@ -94,14 +76,10 @@ error: layout_of(E) = Layout { }, ), align: AbiAndPrefAlign { - abi: Align { - pow2: 2, - }, + abi: Align(4 bytes), pref: $PREF_ALIGN, }, - size: Size { - raw: 12, - }, + size: Size(12 bytes), } --> $DIR/debug.rs:6:1 | @@ -111,15 +89,9 @@ LL | enum E { Foo, Bar(!, i32, i32) } error: layout_of(S) = Layout { fields: Arbitrary { offsets: [ - Size { - raw: 0, - }, - Size { - raw: 0, - }, - Size { - raw: 4, - }, + Size(0 bytes), + Size(0 bytes), + Size(4 bytes), ], memory_index: [ 1, @@ -148,14 +120,10 @@ error: layout_of(S) = Layout { ), largest_niche: None, align: AbiAndPrefAlign { - abi: Align { - pow2: 2, - }, + abi: Align(4 bytes), pref: $PREF_ALIGN, }, - size: Size { - raw: 8, - }, + size: Size(8 bytes), } --> $DIR/debug.rs:9:1 | @@ -174,14 +142,10 @@ error: layout_of(U) = Layout { }, largest_niche: None, align: AbiAndPrefAlign { - abi: Align { - pow2: 2, - }, + abi: Align(4 bytes), pref: $PREF_ALIGN, }, - size: Size { - raw: 8, - }, + size: Size(8 bytes), } --> $DIR/debug.rs:12:1 | @@ -191,9 +155,7 @@ LL | union U { f1: (i32, i32), f3: i32 } error: layout_of(std::result::Result) = Layout { fields: Arbitrary { offsets: [ - Size { - raw: 0, - }, + Size(0 bytes), ], memory_index: [ 0, @@ -213,9 +175,7 @@ error: layout_of(std::result::Result) = Layout { Layout { fields: Arbitrary { offsets: [ - Size { - raw: 4, - }, + Size(4 bytes), ], memory_index: [ 0, @@ -229,21 +189,15 @@ error: layout_of(std::result::Result) = Layout { }, largest_niche: None, align: AbiAndPrefAlign { - abi: Align { - pow2: 2, - }, + abi: Align(4 bytes), pref: $PREF_ALIGN, }, - size: Size { - raw: 8, - }, + size: Size(8 bytes), }, Layout { fields: Arbitrary { offsets: [ - Size { - raw: 4, - }, + Size(4 bytes), ], memory_index: [ 0, @@ -257,14 +211,10 @@ error: layout_of(std::result::Result) = Layout { }, largest_niche: None, align: AbiAndPrefAlign { - abi: Align { - pow2: 2, - }, + abi: Align(4 bytes), pref: $PREF_ALIGN, }, - size: Size { - raw: 8, - }, + size: Size(8 bytes), }, ], }, @@ -286,9 +236,7 @@ error: layout_of(std::result::Result) = Layout { ), largest_niche: Some( Niche { - offset: Size { - raw: 0, - }, + offset: Size(0 bytes), value: Int( I32, false, @@ -297,14 +245,10 @@ error: layout_of(std::result::Result) = Layout { }, ), align: AbiAndPrefAlign { - abi: Align { - pow2: 2, - }, + abi: Align(4 bytes), pref: $PREF_ALIGN, }, - size: Size { - raw: 8, - }, + size: Size(8 bytes), } --> $DIR/debug.rs:15:1 | @@ -327,14 +271,10 @@ error: layout_of(i32) = Layout { ), largest_niche: None, align: AbiAndPrefAlign { - abi: Align { - pow2: 2, - }, + abi: Align(4 bytes), pref: $PREF_ALIGN, }, - size: Size { - raw: 4, - }, + size: Size(4 bytes), } --> $DIR/debug.rs:18:1 | diff --git a/src/test/ui/layout/hexagon-enum.stderr b/src/test/ui/layout/hexagon-enum.stderr index 4db8162b16bb..ba919df771fc 100644 --- a/src/test/ui/layout/hexagon-enum.stderr +++ b/src/test/ui/layout/hexagon-enum.stderr @@ -1,9 +1,7 @@ error: layout_of(A) = Layout { fields: Arbitrary { offsets: [ - Size { - raw: 0, - }, + Size(0 bytes), ], memory_index: [ 0, @@ -33,16 +31,10 @@ error: layout_of(A) = Layout { }, largest_niche: None, align: AbiAndPrefAlign { - abi: Align { - pow2: 0, - }, - pref: Align { - pow2: 0, - }, - }, - size: Size { - raw: 1, + abi: Align(1 bytes), + pref: Align(1 bytes), }, + size: Size(1 bytes), }, ], }, @@ -57,9 +49,7 @@ error: layout_of(A) = Layout { ), largest_niche: Some( Niche { - offset: Size { - raw: 0, - }, + offset: Size(0 bytes), value: Int( I8, false, @@ -68,16 +58,10 @@ error: layout_of(A) = Layout { }, ), align: AbiAndPrefAlign { - abi: Align { - pow2: 0, - }, - pref: Align { - pow2: 0, - }, - }, - size: Size { - raw: 1, + abi: Align(1 bytes), + pref: Align(1 bytes), }, + size: Size(1 bytes), } --> $DIR/hexagon-enum.rs:16:1 | @@ -87,9 +71,7 @@ LL | enum A { Apple } error: layout_of(B) = Layout { fields: Arbitrary { offsets: [ - Size { - raw: 0, - }, + Size(0 bytes), ], memory_index: [ 0, @@ -119,16 +101,10 @@ error: layout_of(B) = Layout { }, largest_niche: None, align: AbiAndPrefAlign { - abi: Align { - pow2: 0, - }, - pref: Align { - pow2: 0, - }, - }, - size: Size { - raw: 1, + abi: Align(1 bytes), + pref: Align(1 bytes), }, + size: Size(1 bytes), }, ], }, @@ -143,9 +119,7 @@ error: layout_of(B) = Layout { ), largest_niche: Some( Niche { - offset: Size { - raw: 0, - }, + offset: Size(0 bytes), value: Int( I8, false, @@ -154,16 +128,10 @@ error: layout_of(B) = Layout { }, ), align: AbiAndPrefAlign { - abi: Align { - pow2: 0, - }, - pref: Align { - pow2: 0, - }, - }, - size: Size { - raw: 1, + abi: Align(1 bytes), + pref: Align(1 bytes), }, + size: Size(1 bytes), } --> $DIR/hexagon-enum.rs:20:1 | @@ -173,9 +141,7 @@ LL | enum B { Banana = 255, } error: layout_of(C) = Layout { fields: Arbitrary { offsets: [ - Size { - raw: 0, - }, + Size(0 bytes), ], memory_index: [ 0, @@ -205,16 +171,10 @@ error: layout_of(C) = Layout { }, largest_niche: None, align: AbiAndPrefAlign { - abi: Align { - pow2: 1, - }, - pref: Align { - pow2: 1, - }, - }, - size: Size { - raw: 2, + abi: Align(2 bytes), + pref: Align(2 bytes), }, + size: Size(2 bytes), }, ], }, @@ -229,9 +189,7 @@ error: layout_of(C) = Layout { ), largest_niche: Some( Niche { - offset: Size { - raw: 0, - }, + offset: Size(0 bytes), value: Int( I16, false, @@ -240,16 +198,10 @@ error: layout_of(C) = Layout { }, ), align: AbiAndPrefAlign { - abi: Align { - pow2: 1, - }, - pref: Align { - pow2: 1, - }, - }, - size: Size { - raw: 2, + abi: Align(2 bytes), + pref: Align(2 bytes), }, + size: Size(2 bytes), } --> $DIR/hexagon-enum.rs:24:1 | @@ -259,9 +211,7 @@ LL | enum C { Chaenomeles = 256, } error: layout_of(P) = Layout { fields: Arbitrary { offsets: [ - Size { - raw: 0, - }, + Size(0 bytes), ], memory_index: [ 0, @@ -291,16 +241,10 @@ error: layout_of(P) = Layout { }, largest_niche: None, align: AbiAndPrefAlign { - abi: Align { - pow2: 2, - }, - pref: Align { - pow2: 2, - }, - }, - size: Size { - raw: 4, + abi: Align(4 bytes), + pref: Align(4 bytes), }, + size: Size(4 bytes), }, ], }, @@ -315,9 +259,7 @@ error: layout_of(P) = Layout { ), largest_niche: Some( Niche { - offset: Size { - raw: 0, - }, + offset: Size(0 bytes), value: Int( I32, false, @@ -326,16 +268,10 @@ error: layout_of(P) = Layout { }, ), align: AbiAndPrefAlign { - abi: Align { - pow2: 2, - }, - pref: Align { - pow2: 2, - }, - }, - size: Size { - raw: 4, + abi: Align(4 bytes), + pref: Align(4 bytes), }, + size: Size(4 bytes), } --> $DIR/hexagon-enum.rs:28:1 | @@ -345,9 +281,7 @@ LL | enum P { Peach = 0x1000_0000isize, } error: layout_of(T) = Layout { fields: Arbitrary { offsets: [ - Size { - raw: 0, - }, + Size(0 bytes), ], memory_index: [ 0, @@ -377,16 +311,10 @@ error: layout_of(T) = Layout { }, largest_niche: None, align: AbiAndPrefAlign { - abi: Align { - pow2: 2, - }, - pref: Align { - pow2: 2, - }, - }, - size: Size { - raw: 4, + abi: Align(4 bytes), + pref: Align(4 bytes), }, + size: Size(4 bytes), }, ], }, @@ -401,9 +329,7 @@ error: layout_of(T) = Layout { ), largest_niche: Some( Niche { - offset: Size { - raw: 0, - }, + offset: Size(0 bytes), value: Int( I32, true, @@ -412,16 +338,10 @@ error: layout_of(T) = Layout { }, ), align: AbiAndPrefAlign { - abi: Align { - pow2: 2, - }, - pref: Align { - pow2: 2, - }, - }, - size: Size { - raw: 4, + abi: Align(4 bytes), + pref: Align(4 bytes), }, + size: Size(4 bytes), } --> $DIR/hexagon-enum.rs:34:1 | diff --git a/src/test/ui/layout/homogeneous-aggr-zero-sized-c-struct.stderr b/src/test/ui/layout/homogeneous-aggr-zero-sized-c-struct.stderr index cd3fb5ca5ea4..6c97a09b0c66 100644 --- a/src/test/ui/layout/homogeneous-aggr-zero-sized-c-struct.stderr +++ b/src/test/ui/layout/homogeneous-aggr-zero-sized-c-struct.stderr @@ -1,10 +1,10 @@ -error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })) +error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) --> $DIR/homogeneous-aggr-zero-sized-c-struct.rs:22:1 | LL | pub type TestMiddle = Middle; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })) +error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) --> $DIR/homogeneous-aggr-zero-sized-c-struct.rs:33:1 | LL | pub type TestFinal = Final; diff --git a/src/test/ui/layout/homogeneous-aggr-zero-sized-repr-rust.rs b/src/test/ui/layout/homogeneous-aggr-zero-sized-repr-rust.rs index ec2c9b70224b..a473c5c97c0b 100644 --- a/src/test/ui/layout/homogeneous-aggr-zero-sized-repr-rust.rs +++ b/src/test/ui/layout/homogeneous-aggr-zero-sized-repr-rust.rs @@ -17,8 +17,7 @@ pub struct WithPhantomData { pub _unit: std::marker::PhantomData<()>, } -pub struct EmptyRustStruct { -} +pub struct EmptyRustStruct {} #[repr(C)] pub struct WithEmptyRustStruct { @@ -52,22 +51,22 @@ pub struct WithEmptyRustEnum { #[rustc_layout(homogeneous_aggregate)] pub type Test1 = BaseCase; -//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })) +//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) #[rustc_layout(homogeneous_aggregate)] pub type Test2 = WithPhantomData; -//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })) +//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) #[rustc_layout(homogeneous_aggregate)] pub type Test3 = WithEmptyRustStruct; -//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })) +//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) #[rustc_layout(homogeneous_aggregate)] pub type Test4 = WithTransitivelyEmptyRustStruct; -//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })) +//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) #[rustc_layout(homogeneous_aggregate)] pub type Test5 = WithEmptyRustEnum; -//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })) +//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) -fn main() { } +fn main() {} diff --git a/src/test/ui/layout/homogeneous-aggr-zero-sized-repr-rust.stderr b/src/test/ui/layout/homogeneous-aggr-zero-sized-repr-rust.stderr index ec2b08bf02d6..322948ff7839 100644 --- a/src/test/ui/layout/homogeneous-aggr-zero-sized-repr-rust.stderr +++ b/src/test/ui/layout/homogeneous-aggr-zero-sized-repr-rust.stderr @@ -1,29 +1,29 @@ -error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })) - --> $DIR/homogeneous-aggr-zero-sized-repr-rust.rs:54:1 +error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) + --> $DIR/homogeneous-aggr-zero-sized-repr-rust.rs:53:1 | LL | pub type Test1 = BaseCase; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })) - --> $DIR/homogeneous-aggr-zero-sized-repr-rust.rs:58:1 +error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) + --> $DIR/homogeneous-aggr-zero-sized-repr-rust.rs:57:1 | LL | pub type Test2 = WithPhantomData; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })) - --> $DIR/homogeneous-aggr-zero-sized-repr-rust.rs:62:1 +error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) + --> $DIR/homogeneous-aggr-zero-sized-repr-rust.rs:61:1 | LL | pub type Test3 = WithEmptyRustStruct; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })) - --> $DIR/homogeneous-aggr-zero-sized-repr-rust.rs:66:1 +error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) + --> $DIR/homogeneous-aggr-zero-sized-repr-rust.rs:65:1 | LL | pub type Test4 = WithTransitivelyEmptyRustStruct; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })) - --> $DIR/homogeneous-aggr-zero-sized-repr-rust.rs:70:1 +error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) + --> $DIR/homogeneous-aggr-zero-sized-repr-rust.rs:69:1 | LL | pub type Test5 = WithEmptyRustEnum; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.rs b/src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.rs index 89387e01ba57..af5f5885d67c 100644 --- a/src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.rs +++ b/src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.rs @@ -1,4 +1,4 @@ -// normalize-stderr-test "pref: Align \{\n *pow2: [1-3],\n *\}" -> "pref: $$PREF_ALIGN" +// normalize-stderr-test "pref: Align\([1-8] bytes\)" -> "pref: $$PREF_ALIGN" #![crate_type = "lib"] #![feature(rustc_attrs)] diff --git a/src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr b/src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr index 46187aae3044..1a724e6f59be 100644 --- a/src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr +++ b/src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr @@ -1,9 +1,7 @@ error: layout_of(MissingPayloadField) = Layout { fields: Arbitrary { offsets: [ - Size { - raw: 0, - }, + Size(0 bytes), ], memory_index: [ 0, @@ -23,9 +21,7 @@ error: layout_of(MissingPayloadField) = Layout { Layout { fields: Arbitrary { offsets: [ - Size { - raw: 1, - }, + Size(1 bytes), ], memory_index: [ 0, @@ -39,14 +35,10 @@ error: layout_of(MissingPayloadField) = Layout { }, largest_niche: None, align: AbiAndPrefAlign { - abi: Align { - pow2: 0, - }, + abi: Align(1 bytes), pref: $PREF_ALIGN, }, - size: Size { - raw: 2, - }, + size: Size(2 bytes), }, Layout { fields: Arbitrary { @@ -61,14 +53,10 @@ error: layout_of(MissingPayloadField) = Layout { }, largest_niche: None, align: AbiAndPrefAlign { - abi: Align { - pow2: 0, - }, + abi: Align(1 bytes), pref: $PREF_ALIGN, }, - size: Size { - raw: 1, - }, + size: Size(1 bytes), }, ], }, @@ -89,9 +77,7 @@ error: layout_of(MissingPayloadField) = Layout { ), largest_niche: Some( Niche { - offset: Size { - raw: 0, - }, + offset: Size(0 bytes), value: Int( I8, false, @@ -100,14 +86,10 @@ error: layout_of(MissingPayloadField) = Layout { }, ), align: AbiAndPrefAlign { - abi: Align { - pow2: 0, - }, + abi: Align(1 bytes), pref: $PREF_ALIGN, }, - size: Size { - raw: 2, - }, + size: Size(2 bytes), } --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:16:1 | @@ -120,9 +102,7 @@ LL | | } error: layout_of(CommonPayloadField) = Layout { fields: Arbitrary { offsets: [ - Size { - raw: 0, - }, + Size(0 bytes), ], memory_index: [ 0, @@ -142,9 +122,7 @@ error: layout_of(CommonPayloadField) = Layout { Layout { fields: Arbitrary { offsets: [ - Size { - raw: 1, - }, + Size(1 bytes), ], memory_index: [ 0, @@ -158,21 +136,15 @@ error: layout_of(CommonPayloadField) = Layout { }, largest_niche: None, align: AbiAndPrefAlign { - abi: Align { - pow2: 0, - }, + abi: Align(1 bytes), pref: $PREF_ALIGN, }, - size: Size { - raw: 2, - }, + size: Size(2 bytes), }, Layout { fields: Arbitrary { offsets: [ - Size { - raw: 1, - }, + Size(1 bytes), ], memory_index: [ 0, @@ -186,14 +158,10 @@ error: layout_of(CommonPayloadField) = Layout { }, largest_niche: None, align: AbiAndPrefAlign { - abi: Align { - pow2: 0, - }, + abi: Align(1 bytes), pref: $PREF_ALIGN, }, - size: Size { - raw: 2, - }, + size: Size(2 bytes), }, ], }, @@ -215,9 +183,7 @@ error: layout_of(CommonPayloadField) = Layout { ), largest_niche: Some( Niche { - offset: Size { - raw: 0, - }, + offset: Size(0 bytes), value: Int( I8, false, @@ -226,14 +192,10 @@ error: layout_of(CommonPayloadField) = Layout { }, ), align: AbiAndPrefAlign { - abi: Align { - pow2: 0, - }, + abi: Align(1 bytes), pref: $PREF_ALIGN, }, - size: Size { - raw: 2, - }, + size: Size(2 bytes), } --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:25:1 | @@ -246,9 +208,7 @@ LL | | } error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { fields: Arbitrary { offsets: [ - Size { - raw: 0, - }, + Size(0 bytes), ], memory_index: [ 0, @@ -268,9 +228,7 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { Layout { fields: Arbitrary { offsets: [ - Size { - raw: 1, - }, + Size(1 bytes), ], memory_index: [ 0, @@ -284,21 +242,15 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { }, largest_niche: None, align: AbiAndPrefAlign { - abi: Align { - pow2: 0, - }, + abi: Align(1 bytes), pref: $PREF_ALIGN, }, - size: Size { - raw: 2, - }, + size: Size(2 bytes), }, Layout { fields: Arbitrary { offsets: [ - Size { - raw: 1, - }, + Size(1 bytes), ], memory_index: [ 0, @@ -312,14 +264,10 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { }, largest_niche: None, align: AbiAndPrefAlign { - abi: Align { - pow2: 0, - }, + abi: Align(1 bytes), pref: $PREF_ALIGN, }, - size: Size { - raw: 2, - }, + size: Size(2 bytes), }, ], }, @@ -340,9 +288,7 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { ), largest_niche: Some( Niche { - offset: Size { - raw: 0, - }, + offset: Size(0 bytes), value: Int( I8, false, @@ -351,14 +297,10 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { }, ), align: AbiAndPrefAlign { - abi: Align { - pow2: 0, - }, + abi: Align(1 bytes), pref: $PREF_ALIGN, }, - size: Size { - raw: 2, - }, + size: Size(2 bytes), } --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:33:1 | @@ -371,9 +313,7 @@ LL | | } error: layout_of(NicheFirst) = Layout { fields: Arbitrary { offsets: [ - Size { - raw: 0, - }, + Size(0 bytes), ], memory_index: [ 0, @@ -397,12 +337,8 @@ error: layout_of(NicheFirst) = Layout { Layout { fields: Arbitrary { offsets: [ - Size { - raw: 0, - }, - Size { - raw: 1, - }, + Size(0 bytes), + Size(1 bytes), ], memory_index: [ 0, @@ -430,9 +366,7 @@ error: layout_of(NicheFirst) = Layout { ), largest_niche: Some( Niche { - offset: Size { - raw: 0, - }, + offset: Size(0 bytes), value: Int( I8, false, @@ -441,14 +375,10 @@ error: layout_of(NicheFirst) = Layout { }, ), align: AbiAndPrefAlign { - abi: Align { - pow2: 0, - }, + abi: Align(1 bytes), pref: $PREF_ALIGN, }, - size: Size { - raw: 2, - }, + size: Size(2 bytes), }, Layout { fields: Arbitrary { @@ -463,14 +393,10 @@ error: layout_of(NicheFirst) = Layout { }, largest_niche: None, align: AbiAndPrefAlign { - abi: Align { - pow2: 0, - }, + abi: Align(1 bytes), pref: $PREF_ALIGN, }, - size: Size { - raw: 0, - }, + size: Size(0 bytes), }, Layout { fields: Arbitrary { @@ -485,14 +411,10 @@ error: layout_of(NicheFirst) = Layout { }, largest_niche: None, align: AbiAndPrefAlign { - abi: Align { - pow2: 0, - }, + abi: Align(1 bytes), pref: $PREF_ALIGN, }, - size: Size { - raw: 0, - }, + size: Size(0 bytes), }, ], }, @@ -513,9 +435,7 @@ error: layout_of(NicheFirst) = Layout { ), largest_niche: Some( Niche { - offset: Size { - raw: 0, - }, + offset: Size(0 bytes), value: Int( I8, false, @@ -524,14 +444,10 @@ error: layout_of(NicheFirst) = Layout { }, ), align: AbiAndPrefAlign { - abi: Align { - pow2: 0, - }, + abi: Align(1 bytes), pref: $PREF_ALIGN, }, - size: Size { - raw: 2, - }, + size: Size(2 bytes), } --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:41:1 | @@ -545,9 +461,7 @@ LL | | } error: layout_of(NicheSecond) = Layout { fields: Arbitrary { offsets: [ - Size { - raw: 1, - }, + Size(1 bytes), ], memory_index: [ 0, @@ -571,12 +485,8 @@ error: layout_of(NicheSecond) = Layout { Layout { fields: Arbitrary { offsets: [ - Size { - raw: 0, - }, - Size { - raw: 1, - }, + Size(0 bytes), + Size(1 bytes), ], memory_index: [ 0, @@ -604,9 +514,7 @@ error: layout_of(NicheSecond) = Layout { ), largest_niche: Some( Niche { - offset: Size { - raw: 1, - }, + offset: Size(1 bytes), value: Int( I8, false, @@ -615,14 +523,10 @@ error: layout_of(NicheSecond) = Layout { }, ), align: AbiAndPrefAlign { - abi: Align { - pow2: 0, - }, + abi: Align(1 bytes), pref: $PREF_ALIGN, }, - size: Size { - raw: 2, - }, + size: Size(2 bytes), }, Layout { fields: Arbitrary { @@ -637,14 +541,10 @@ error: layout_of(NicheSecond) = Layout { }, largest_niche: None, align: AbiAndPrefAlign { - abi: Align { - pow2: 0, - }, + abi: Align(1 bytes), pref: $PREF_ALIGN, }, - size: Size { - raw: 0, - }, + size: Size(0 bytes), }, Layout { fields: Arbitrary { @@ -659,14 +559,10 @@ error: layout_of(NicheSecond) = Layout { }, largest_niche: None, align: AbiAndPrefAlign { - abi: Align { - pow2: 0, - }, + abi: Align(1 bytes), pref: $PREF_ALIGN, }, - size: Size { - raw: 0, - }, + size: Size(0 bytes), }, ], }, @@ -687,9 +583,7 @@ error: layout_of(NicheSecond) = Layout { ), largest_niche: Some( Niche { - offset: Size { - raw: 1, - }, + offset: Size(1 bytes), value: Int( I8, false, @@ -698,14 +592,10 @@ error: layout_of(NicheSecond) = Layout { }, ), align: AbiAndPrefAlign { - abi: Align { - pow2: 0, - }, + abi: Align(1 bytes), pref: $PREF_ALIGN, }, - size: Size { - raw: 2, - }, + size: Size(2 bytes), } --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:50:1 | diff --git a/src/test/ui/layout/thumb-enum.stderr b/src/test/ui/layout/thumb-enum.stderr index 9d1f234f31ad..9db9ad5a7848 100644 --- a/src/test/ui/layout/thumb-enum.stderr +++ b/src/test/ui/layout/thumb-enum.stderr @@ -1,9 +1,7 @@ error: layout_of(A) = Layout { fields: Arbitrary { offsets: [ - Size { - raw: 0, - }, + Size(0 bytes), ], memory_index: [ 0, @@ -33,16 +31,10 @@ error: layout_of(A) = Layout { }, largest_niche: None, align: AbiAndPrefAlign { - abi: Align { - pow2: 0, - }, - pref: Align { - pow2: 2, - }, - }, - size: Size { - raw: 1, + abi: Align(1 bytes), + pref: Align(4 bytes), }, + size: Size(1 bytes), }, ], }, @@ -57,9 +49,7 @@ error: layout_of(A) = Layout { ), largest_niche: Some( Niche { - offset: Size { - raw: 0, - }, + offset: Size(0 bytes), value: Int( I8, false, @@ -68,16 +58,10 @@ error: layout_of(A) = Layout { }, ), align: AbiAndPrefAlign { - abi: Align { - pow2: 0, - }, - pref: Align { - pow2: 2, - }, - }, - size: Size { - raw: 1, + abi: Align(1 bytes), + pref: Align(4 bytes), }, + size: Size(1 bytes), } --> $DIR/thumb-enum.rs:16:1 | @@ -87,9 +71,7 @@ LL | enum A { Apple } error: layout_of(B) = Layout { fields: Arbitrary { offsets: [ - Size { - raw: 0, - }, + Size(0 bytes), ], memory_index: [ 0, @@ -119,16 +101,10 @@ error: layout_of(B) = Layout { }, largest_niche: None, align: AbiAndPrefAlign { - abi: Align { - pow2: 0, - }, - pref: Align { - pow2: 2, - }, - }, - size: Size { - raw: 1, + abi: Align(1 bytes), + pref: Align(4 bytes), }, + size: Size(1 bytes), }, ], }, @@ -143,9 +119,7 @@ error: layout_of(B) = Layout { ), largest_niche: Some( Niche { - offset: Size { - raw: 0, - }, + offset: Size(0 bytes), value: Int( I8, false, @@ -154,16 +128,10 @@ error: layout_of(B) = Layout { }, ), align: AbiAndPrefAlign { - abi: Align { - pow2: 0, - }, - pref: Align { - pow2: 2, - }, - }, - size: Size { - raw: 1, + abi: Align(1 bytes), + pref: Align(4 bytes), }, + size: Size(1 bytes), } --> $DIR/thumb-enum.rs:20:1 | @@ -173,9 +141,7 @@ LL | enum B { Banana = 255, } error: layout_of(C) = Layout { fields: Arbitrary { offsets: [ - Size { - raw: 0, - }, + Size(0 bytes), ], memory_index: [ 0, @@ -205,16 +171,10 @@ error: layout_of(C) = Layout { }, largest_niche: None, align: AbiAndPrefAlign { - abi: Align { - pow2: 1, - }, - pref: Align { - pow2: 2, - }, - }, - size: Size { - raw: 2, + abi: Align(2 bytes), + pref: Align(4 bytes), }, + size: Size(2 bytes), }, ], }, @@ -229,9 +189,7 @@ error: layout_of(C) = Layout { ), largest_niche: Some( Niche { - offset: Size { - raw: 0, - }, + offset: Size(0 bytes), value: Int( I16, false, @@ -240,16 +198,10 @@ error: layout_of(C) = Layout { }, ), align: AbiAndPrefAlign { - abi: Align { - pow2: 1, - }, - pref: Align { - pow2: 2, - }, - }, - size: Size { - raw: 2, + abi: Align(2 bytes), + pref: Align(4 bytes), }, + size: Size(2 bytes), } --> $DIR/thumb-enum.rs:24:1 | @@ -259,9 +211,7 @@ LL | enum C { Chaenomeles = 256, } error: layout_of(P) = Layout { fields: Arbitrary { offsets: [ - Size { - raw: 0, - }, + Size(0 bytes), ], memory_index: [ 0, @@ -291,16 +241,10 @@ error: layout_of(P) = Layout { }, largest_niche: None, align: AbiAndPrefAlign { - abi: Align { - pow2: 2, - }, - pref: Align { - pow2: 2, - }, - }, - size: Size { - raw: 4, + abi: Align(4 bytes), + pref: Align(4 bytes), }, + size: Size(4 bytes), }, ], }, @@ -315,9 +259,7 @@ error: layout_of(P) = Layout { ), largest_niche: Some( Niche { - offset: Size { - raw: 0, - }, + offset: Size(0 bytes), value: Int( I32, false, @@ -326,16 +268,10 @@ error: layout_of(P) = Layout { }, ), align: AbiAndPrefAlign { - abi: Align { - pow2: 2, - }, - pref: Align { - pow2: 2, - }, - }, - size: Size { - raw: 4, + abi: Align(4 bytes), + pref: Align(4 bytes), }, + size: Size(4 bytes), } --> $DIR/thumb-enum.rs:28:1 | @@ -345,9 +281,7 @@ LL | enum P { Peach = 0x1000_0000isize, } error: layout_of(T) = Layout { fields: Arbitrary { offsets: [ - Size { - raw: 0, - }, + Size(0 bytes), ], memory_index: [ 0, @@ -377,16 +311,10 @@ error: layout_of(T) = Layout { }, largest_niche: None, align: AbiAndPrefAlign { - abi: Align { - pow2: 2, - }, - pref: Align { - pow2: 2, - }, - }, - size: Size { - raw: 4, + abi: Align(4 bytes), + pref: Align(4 bytes), }, + size: Size(4 bytes), }, ], }, @@ -401,9 +329,7 @@ error: layout_of(T) = Layout { ), largest_niche: Some( Niche { - offset: Size { - raw: 0, - }, + offset: Size(0 bytes), value: Int( I32, true, @@ -412,16 +338,10 @@ error: layout_of(T) = Layout { }, ), align: AbiAndPrefAlign { - abi: Align { - pow2: 2, - }, - pref: Align { - pow2: 2, - }, - }, - size: Size { - raw: 4, + abi: Align(4 bytes), + pref: Align(4 bytes), }, + size: Size(4 bytes), } --> $DIR/thumb-enum.rs:34:1 | diff --git a/src/test/ui/layout/zero-sized-array-union.stderr b/src/test/ui/layout/zero-sized-array-union.stderr index 43b1588266bb..8faf8593294c 100644 --- a/src/test/ui/layout/zero-sized-array-union.stderr +++ b/src/test/ui/layout/zero-sized-array-union.stderr @@ -1,22 +1,22 @@ -error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })) +error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) --> $DIR/zero-sized-array-union.rs:59:1 | LL | type TestBaz1 = Baz1; | ^^^^^^^^^^^^^^^^^^^^^ -error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })) +error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) --> $DIR/zero-sized-array-union.rs:70:1 | LL | type TestBaz2 = Baz2; | ^^^^^^^^^^^^^^^^^^^^^ -error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })) +error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) --> $DIR/zero-sized-array-union.rs:81:1 | LL | type TestBaz3 = Baz3; | ^^^^^^^^^^^^^^^^^^^^^ -error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size { raw: 4 } })) +error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) --> $DIR/zero-sized-array-union.rs:92:1 | LL | type TestBaz4 = Baz4; diff --git a/src/test/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.rs b/src/test/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.rs new file mode 100644 index 000000000000..f80fe88cbb97 --- /dev/null +++ b/src/test/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.rs @@ -0,0 +1,155 @@ +// check-pass +#![feature(lint_reasons)] + +//! This file tests the `#[expect]` attribute implementation for tool lints. The same +//! file is used to test clippy and rustdoc. Any changes to this file should be synced +//! to the other test files. +//! +//! Expectations: +//! * rustc: only rustc lint expectations are emitted +//! * clippy: rustc and Clippy's expectations are emitted +//! * rustdoc: only rustdoc lint expectations are emitted +//! +//! This test can't cover every lint from Clippy, rustdoc and potentially other +//! tools that will be developed. This therefore only tests a small subset of lints + +#![expect(rustdoc::missing_crate_level_docs)] + +mod rustc_ok { + //! See + + #[expect(dead_code)] + pub fn rustc_lints() { + let x = 42.0; + + #[expect(illegal_floating_point_literal_pattern)] + match x { + 5.0 => {} + 6.0 => {} + _ => {} + } + } +} + +mod rustc_warn { + //! See + + #[expect(dead_code)] + //~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] + //~| NOTE `#[warn(unfulfilled_lint_expectations)]` on by default + pub fn rustc_lints() { + let x = 42; + + #[expect(illegal_floating_point_literal_pattern)] + //~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] + match x { + 5 => {} + 6 => {} + _ => {} + } + } +} + +pub mod rustdoc_ok { + //! See + + #[expect(rustdoc::broken_intra_doc_links)] + /// I want to link to [`Nonexistent`] but it doesn't exist! + pub fn foo() {} + + #[expect(rustdoc::invalid_html_tags)] + ///

+ pub fn bar() {} + + #[expect(rustdoc::bare_urls)] + /// http://example.org + pub fn baz() {} +} + +pub mod rustdoc_warn { + //! See + + #[expect(rustdoc::broken_intra_doc_links)] + /// I want to link to [`bar`] but it doesn't exist! + pub fn foo() {} + + #[expect(rustdoc::invalid_html_tags)] + ///

+ pub fn bar() {} + + #[expect(rustdoc::bare_urls)] + /// + pub fn baz() {} +} + +mod clippy_ok { + //! See + + #[expect(clippy::almost_swapped)] + fn foo() { + let mut a = 0; + let mut b = 9; + a = b; + b = a; + } + + #[expect(clippy::bytes_nth)] + fn bar() { + let _ = "Hello".bytes().nth(3); + } + + #[expect(clippy::if_same_then_else)] + fn baz() { + let _ = if true { + 42 + } else { + 42 + }; + } + + #[expect(clippy::logic_bug)] + fn burger() { + let a = false; + let b = true; + + if a && b || a {} + } +} + +mod clippy_warn { + //! See + + #[expect(clippy::almost_swapped)] + fn foo() { + let mut a = 0; + let mut b = 9; + a = b; + } + + #[expect(clippy::bytes_nth)] + fn bar() { + let _ = "Hello".as_bytes().get(3); + } + + #[expect(clippy::if_same_then_else)] + fn baz() { + let _ = if true { + 33 + } else { + 42 + }; + } + + #[expect(clippy::logic_bug)] + fn burger() { + let a = false; + let b = true; + let c = false; + + if a && b || c {} + } +} + +fn main() { + rustc_warn::rustc_lints(); +} diff --git a/src/test/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.stderr b/src/test/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.stderr new file mode 100644 index 000000000000..6d49e7543dc5 --- /dev/null +++ b/src/test/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.stderr @@ -0,0 +1,16 @@ +warning: this lint expectation is unfulfilled + --> $DIR/expect_tool_lint_rfc_2383.rs:37:14 + | +LL | #[expect(dead_code)] + | ^^^^^^^^^ + | + = note: `#[warn(unfulfilled_lint_expectations)]` on by default + +warning: this lint expectation is unfulfilled + --> $DIR/expect_tool_lint_rfc_2383.rs:43:18 + | +LL | #[expect(illegal_floating_point_literal_pattern)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: 2 warnings emitted + diff --git a/src/test/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.rs b/src/test/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.rs new file mode 100644 index 000000000000..2b6c3c6a1fdf --- /dev/null +++ b/src/test/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.rs @@ -0,0 +1,16 @@ +// This ensures that ICEs like rust#94953 don't happen +// check-pass +// compile-flags: -Z unpretty=expanded + +#![feature(lint_reasons)] + +// This `expect` will create an expectation with an unstable expectation id +#[expect(while_true)] +fn create_early_lint_pass_expectation() { + // `while_true` is an early lint + while true {} +} + +fn main() { + create_early_lint_pass_expectation(); +} diff --git a/src/test/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.stdout b/src/test/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.stdout new file mode 100644 index 000000000000..0ee3a03c3884 --- /dev/null +++ b/src/test/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.stdout @@ -0,0 +1,20 @@ +#![feature(prelude_import)] +#![no_std] +// This ensures that ICEs like rust#94953 don't happen +// check-pass +// compile-flags: -Z unpretty=expanded + +#![feature(lint_reasons)] +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; + +// This `expect` will create an expectation with an unstable expectation id +#[expect(while_true)] +fn create_early_lint_pass_expectation() { + // `while_true` is an early lint + while true {} +} + +fn main() { create_early_lint_pass_expectation(); } diff --git a/src/test/ui/lint/unused/unused-macro-rules-decl.rs b/src/test/ui/lint/unused/unused-macro-rules-decl.rs new file mode 100644 index 000000000000..537c84940fd0 --- /dev/null +++ b/src/test/ui/lint/unused/unused-macro-rules-decl.rs @@ -0,0 +1,49 @@ +#![feature(decl_macro)] +#![deny(unused_macro_rules)] +// To make sure we are not hitting this +#![deny(unused_macros)] + +// Most simple case +macro num { + (one) => { 1 }, + (two) => { 2 }, //~ ERROR: 2nd rule of macro + (three) => { 3 }, + (four) => { 4 }, //~ ERROR: 4th rule of macro +} +const _NUM: u8 = num!(one) + num!(three); + +// Check that allowing the lint works +#[allow(unused_macro_rules)] +macro num_allowed { + (one) => { 1 }, + (two) => { 2 }, + (three) => { 3 }, + (four) => { 4 }, +} +const _NUM_ALLOWED: u8 = num_allowed!(one) + num_allowed!(three); + +// Check that macro calls inside the macro trigger as usage +macro num_rec { + (one) => { 1 }, + (two) => { + num_rec!(one) + num_rec!(one) + }, + (three) => { //~ ERROR: 3rd rule of macro + num_rec!(one) + num_rec!(two) + }, + (four) => { + num_rec!(two) + num_rec!(two) + }, +} +const _NUM_RECURSIVE: u8 = num_rec!(four); + +// No error if the macro is public +pub macro num_public { + (one) => { 1 }, + (two) => { 2 }, + (three) => { 3 }, + (four) => { 4 }, +} +const _NUM_PUBLIC: u8 = num_public!(one) + num_public!(three); + +fn main() {} diff --git a/src/test/ui/lint/unused/unused-macro-rules-decl.stderr b/src/test/ui/lint/unused/unused-macro-rules-decl.stderr new file mode 100644 index 000000000000..4d9b22feda2a --- /dev/null +++ b/src/test/ui/lint/unused/unused-macro-rules-decl.stderr @@ -0,0 +1,26 @@ +error: 4th rule of macro `num` is never used + --> $DIR/unused-macro-rules-decl.rs:11:5 + | +LL | (four) => { 4 }, + | ^^^^^^ + | +note: the lint level is defined here + --> $DIR/unused-macro-rules-decl.rs:2:9 + | +LL | #![deny(unused_macro_rules)] + | ^^^^^^^^^^^^^^^^^^ + +error: 2nd rule of macro `num` is never used + --> $DIR/unused-macro-rules-decl.rs:9:5 + | +LL | (two) => { 2 }, + | ^^^^^ + +error: 3rd rule of macro `num_rec` is never used + --> $DIR/unused-macro-rules-decl.rs:31:5 + | +LL | (three) => { + | ^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/lint/unused/unused-macro-rules.rs b/src/test/ui/lint/unused/unused-macro-rules.rs index 1a714b8f0a0d..eeaf4d1b0a9c 100644 --- a/src/test/ui/lint/unused/unused-macro-rules.rs +++ b/src/test/ui/lint/unused/unused-macro-rules.rs @@ -1,29 +1,47 @@ +#![deny(unused_macro_rules)] +// To make sure we are not hitting this #![deny(unused_macros)] // Most simple case -macro_rules! unused { //~ ERROR: unused macro definition - () => {}; +macro_rules! num { + (one) => { 1 }; + (two) => { 2 }; //~ ERROR: 2nd rule of macro + (three) => { 3 }; + (four) => { 4 }; //~ ERROR: 4th rule of macro } +const _NUM: u8 = num!(one) + num!(three); -// Test macros created by macros -macro_rules! create_macro { - () => { - macro_rules! m { //~ ERROR: unused macro definition - () => {}; - } - }; +// Check that allowing the lint works +#[allow(unused_macro_rules)] +macro_rules! num_allowed { + (one) => { 1 }; + (two) => { 2 }; + (three) => { 3 }; + (four) => { 4 }; } -create_macro!(); +const _NUM_ALLOWED: u8 = num_allowed!(one) + num_allowed!(three); -#[allow(unused_macros)] -mod bar { - // Test that putting the #[deny] close to the macro's definition - // works. +// Check that macro calls inside the macro trigger as usage +macro_rules! num_rec { + (one) => { 1 }; + (two) => { + num_rec!(one) + num_rec!(one) + }; + (three) => { //~ ERROR: 3rd rule of macro + num_rec!(one) + num_rec!(two) + }; + (four) => { num_rec!(two) + num_rec!(two) }; +} +const _NUM_RECURSIVE: u8 = num_rec!(four); - #[deny(unused_macros)] - macro_rules! unused { //~ ERROR: unused macro definition - () => {}; - } +// No error if the macro is being exported +#[macro_export] +macro_rules! num_exported { + (one) => { 1 }; + (two) => { 2 }; + (three) => { 3 }; + (four) => { 4 }; } +const _NUM_EXPORTED: u8 = num_exported!(one) + num_exported!(three); fn main() {} diff --git a/src/test/ui/lint/unused/unused-macro-rules.stderr b/src/test/ui/lint/unused/unused-macro-rules.stderr index 59db35b41118..2b3098a5128d 100644 --- a/src/test/ui/lint/unused/unused-macro-rules.stderr +++ b/src/test/ui/lint/unused/unused-macro-rules.stderr @@ -1,32 +1,26 @@ -error: unused macro definition: `unused` - --> $DIR/unused-macro-rules.rs:4:14 +error: 4th rule of macro `num` is never used + --> $DIR/unused-macro-rules.rs:10:5 | -LL | macro_rules! unused { - | ^^^^^^ +LL | (four) => { 4 }; + | ^^^^^^ | note: the lint level is defined here --> $DIR/unused-macro-rules.rs:1:9 | -LL | #![deny(unused_macros)] - | ^^^^^^^^^^^^^ +LL | #![deny(unused_macro_rules)] + | ^^^^^^^^^^^^^^^^^^ -error: unused macro definition: `m` - --> $DIR/unused-macro-rules.rs:11:22 +error: 2nd rule of macro `num` is never used + --> $DIR/unused-macro-rules.rs:8:5 | -LL | macro_rules! m { - | ^ +LL | (two) => { 2 }; + | ^^^^^ -error: unused macro definition: `unused` - --> $DIR/unused-macro-rules.rs:24:18 +error: 3rd rule of macro `num_rec` is never used + --> $DIR/unused-macro-rules.rs:30:5 | -LL | macro_rules! unused { - | ^^^^^^ - | -note: the lint level is defined here - --> $DIR/unused-macro-rules.rs:23:12 - | -LL | #[deny(unused_macros)] - | ^^^^^^^^^^^^^ +LL | (three) => { + | ^^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/lint/unused/unused-macro.rs b/src/test/ui/lint/unused/unused-macros-decl.rs similarity index 87% rename from src/test/ui/lint/unused/unused-macro.rs rename to src/test/ui/lint/unused/unused-macros-decl.rs index 302b0727d77b..21f6108b18ad 100644 --- a/src/test/ui/lint/unused/unused-macro.rs +++ b/src/test/ui/lint/unused/unused-macros-decl.rs @@ -1,5 +1,7 @@ #![feature(decl_macro)] #![deny(unused_macros)] +// To make sure we are not hitting this +#![deny(unused_macro_rules)] // Most simple case macro unused { //~ ERROR: unused macro definition diff --git a/src/test/ui/lint/unused/unused-macro.stderr b/src/test/ui/lint/unused/unused-macros-decl.stderr similarity index 74% rename from src/test/ui/lint/unused/unused-macro.stderr rename to src/test/ui/lint/unused/unused-macros-decl.stderr index 1a73279ed6db..1f426b9d91a6 100644 --- a/src/test/ui/lint/unused/unused-macro.stderr +++ b/src/test/ui/lint/unused/unused-macros-decl.stderr @@ -1,29 +1,29 @@ error: unused macro definition: `unused` - --> $DIR/unused-macro.rs:5:7 + --> $DIR/unused-macros-decl.rs:7:7 | LL | macro unused { | ^^^^^^ | note: the lint level is defined here - --> $DIR/unused-macro.rs:2:9 + --> $DIR/unused-macros-decl.rs:2:9 | LL | #![deny(unused_macros)] | ^^^^^^^^^^^^^ error: unused macro definition: `unused` - --> $DIR/unused-macro.rs:15:11 + --> $DIR/unused-macros-decl.rs:17:11 | LL | macro unused { | ^^^^^^ | note: the lint level is defined here - --> $DIR/unused-macro.rs:14:12 + --> $DIR/unused-macros-decl.rs:16:12 | LL | #[deny(unused_macros)] | ^^^^^^^^^^^^^ error: unused macro definition: `unused` - --> $DIR/unused-macro.rs:21:22 + --> $DIR/unused-macros-decl.rs:23:22 | LL | pub(crate) macro unused { | ^^^^^^ diff --git a/src/test/ui/lint/unused/unused-macros.rs b/src/test/ui/lint/unused/unused-macros.rs new file mode 100644 index 000000000000..70b50b2082b3 --- /dev/null +++ b/src/test/ui/lint/unused/unused-macros.rs @@ -0,0 +1,31 @@ +#![deny(unused_macros)] +// To make sure we are not hitting this +#![deny(unused_macro_rules)] + +// Most simple case +macro_rules! unused { //~ ERROR: unused macro definition + () => {}; +} + +// Test macros created by macros +macro_rules! create_macro { + () => { + macro_rules! m { //~ ERROR: unused macro definition + () => {}; + } + }; +} +create_macro!(); + +#[allow(unused_macros)] +mod bar { + // Test that putting the #[deny] close to the macro's definition + // works. + + #[deny(unused_macros)] + macro_rules! unused { //~ ERROR: unused macro definition + () => {}; + } +} + +fn main() {} diff --git a/src/test/ui/lint/unused/unused-macros.stderr b/src/test/ui/lint/unused/unused-macros.stderr new file mode 100644 index 000000000000..d0baf5becec4 --- /dev/null +++ b/src/test/ui/lint/unused/unused-macros.stderr @@ -0,0 +1,32 @@ +error: unused macro definition: `unused` + --> $DIR/unused-macros.rs:6:14 + | +LL | macro_rules! unused { + | ^^^^^^ + | +note: the lint level is defined here + --> $DIR/unused-macros.rs:1:9 + | +LL | #![deny(unused_macros)] + | ^^^^^^^^^^^^^ + +error: unused macro definition: `m` + --> $DIR/unused-macros.rs:13:22 + | +LL | macro_rules! m { + | ^ + +error: unused macro definition: `unused` + --> $DIR/unused-macros.rs:26:18 + | +LL | macro_rules! unused { + | ^^^^^^ + | +note: the lint level is defined here + --> $DIR/unused-macros.rs:25:12 + | +LL | #[deny(unused_macros)] + | ^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/macros/issue-41803.rs b/src/test/ui/macros/issue-41803.rs index 19ab81d04d0e..bccfdc611460 100644 --- a/src/test/ui/macros/issue-41803.rs +++ b/src/test/ui/macros/issue-41803.rs @@ -1,4 +1,6 @@ // run-pass +#![allow(unused_macro_rules)] + /// A compile-time map from identifiers to arbitrary (heterogeneous) expressions macro_rules! ident_map { ( $name:ident = { $($key:ident => $e:expr,)* } ) => { diff --git a/src/test/ui/macros/issue-52169.rs b/src/test/ui/macros/issue-52169.rs index 60be97f0aee2..f178cd30cb49 100644 --- a/src/test/ui/macros/issue-52169.rs +++ b/src/test/ui/macros/issue-52169.rs @@ -1,5 +1,6 @@ // run-pass +#[allow(unused_macro_rules)] macro_rules! a { ($i:literal) => { "right" }; ($i:tt) => { "wrong" }; diff --git a/src/test/ui/macros/macro-first-set.rs b/src/test/ui/macros/macro-first-set.rs index f85376dabcb5..eeb1ddd84ae5 100644 --- a/src/test/ui/macros/macro-first-set.rs +++ b/src/test/ui/macros/macro-first-set.rs @@ -1,4 +1,5 @@ // run-pass +#![allow(unused_macro_rules)] //{{{ issue 40569 ============================================================== diff --git a/src/test/ui/macros/macro-literal.rs b/src/test/ui/macros/macro-literal.rs index e08d0a67b434..3c2e71f9c43f 100644 --- a/src/test/ui/macros/macro-literal.rs +++ b/src/test/ui/macros/macro-literal.rs @@ -21,6 +21,7 @@ macro_rules! only_expr { }; } +#[allow(unused_macro_rules)] macro_rules! mtester_dbg { ($l:literal) => { &format!("macro caught literal: {:?}", $l) diff --git a/src/test/ui/macros/macro-pub-matcher.rs b/src/test/ui/macros/macro-pub-matcher.rs index c02e6794edbc..174056d6cdfa 100644 --- a/src/test/ui/macros/macro-pub-matcher.rs +++ b/src/test/ui/macros/macro-pub-matcher.rs @@ -1,5 +1,5 @@ // run-pass -#![allow(dead_code, unused_imports)] +#![allow(dead_code, unused_imports, unused_macro_rules)] #![feature(crate_visibility_modifier)] /** diff --git a/src/test/ui/macros/stmt_expr_attr_macro_parse.rs b/src/test/ui/macros/stmt_expr_attr_macro_parse.rs index 3ab50db0ea1b..570191d2c90a 100644 --- a/src/test/ui/macros/stmt_expr_attr_macro_parse.rs +++ b/src/test/ui/macros/stmt_expr_attr_macro_parse.rs @@ -1,4 +1,6 @@ // run-pass +#![allow(unused_macro_rules)] + macro_rules! m { ($e:expr) => { "expr includes attr" diff --git a/src/test/ui/macros/type-macros-hlist.rs b/src/test/ui/macros/type-macros-hlist.rs index 77d866cea9ce..946b5bd5d933 100644 --- a/src/test/ui/macros/type-macros-hlist.rs +++ b/src/test/ui/macros/type-macros-hlist.rs @@ -1,4 +1,6 @@ // run-pass +#![allow(unused_macro_rules)] + use std::ops::*; #[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] diff --git a/src/test/ui/parser/issues/issue-65846-rollback-gating-failing-matcher.rs b/src/test/ui/parser/issues/issue-65846-rollback-gating-failing-matcher.rs index 9d68a7bffdee..76c07bbfd810 100644 --- a/src/test/ui/parser/issues/issue-65846-rollback-gating-failing-matcher.rs +++ b/src/test/ui/parser/issues/issue-65846-rollback-gating-failing-matcher.rs @@ -3,6 +3,7 @@ // Test that failing macro matchers will not cause pre-expansion errors // even though they use a feature that is pre-expansion gated. +#[allow(unused_macro_rules)] macro_rules! m { ($e:expr) => { 0 }; // This fails on the input below due to `, foo`. ($e:expr,) => { 1 }; // This also fails to match due to `foo`. diff --git a/src/test/ui/rust-2018/async-ident.fixed b/src/test/ui/rust-2018/async-ident.fixed index f4ae518c71d2..e909c79070ca 100644 --- a/src/test/ui/rust-2018/async-ident.fixed +++ b/src/test/ui/rust-2018/async-ident.fixed @@ -1,4 +1,4 @@ -#![allow(dead_code, unused_variables, non_camel_case_types, non_upper_case_globals)] +#![allow(dead_code, unused_variables, unused_macro_rules, bad_style)] #![deny(keyword_idents)] // edition:2015 diff --git a/src/test/ui/rust-2018/async-ident.rs b/src/test/ui/rust-2018/async-ident.rs index 79c73dafac7a..2bfbc3871d12 100644 --- a/src/test/ui/rust-2018/async-ident.rs +++ b/src/test/ui/rust-2018/async-ident.rs @@ -1,4 +1,4 @@ -#![allow(dead_code, unused_variables, non_camel_case_types, non_upper_case_globals)] +#![allow(dead_code, unused_variables, unused_macro_rules, bad_style)] #![deny(keyword_idents)] // edition:2015 diff --git a/src/tools/clippy/tests/ui/expect_tool_lint_rfc_2383.rs b/src/tools/clippy/tests/ui/expect_tool_lint_rfc_2383.rs new file mode 100644 index 000000000000..28b37f96e911 --- /dev/null +++ b/src/tools/clippy/tests/ui/expect_tool_lint_rfc_2383.rs @@ -0,0 +1,142 @@ +// check-pass +#![feature(lint_reasons)] +//! This file tests the `#[expect]` attribute implementation for tool lints. The same +//! file is used to test clippy and rustdoc. Any changes to this file should be synced +//! to the other test files as well. +//! +//! Expectations: +//! * rustc: only rustc lint expectations are emitted +//! * clippy: rustc and Clippy's expectations are emitted +//! * rustdoc: only rustdoc lint expectations are emitted +//! +//! This test can't cover every lint from Clippy, rustdoc and potentially other +//! tools that will be developed. This therefore only tests a small subset of lints +#![expect(rustdoc::missing_crate_level_docs)] + +mod rustc_ok { + //! See + + #[expect(dead_code)] + pub fn rustc_lints() { + let x = 42.0; + + #[expect(illegal_floating_point_literal_pattern)] + match x { + 5.0 => {} + 6.0 => {} + _ => {} + } + } +} + +mod rustc_warn { + //! See + + #[expect(dead_code)] + pub fn rustc_lints() { + let x = 42; + + #[expect(illegal_floating_point_literal_pattern)] + match x { + 5 => {} + 6 => {} + _ => {} + } + } +} + +pub mod rustdoc_ok { + //! See + + #[expect(rustdoc::broken_intra_doc_links)] + /// I want to link to [`Nonexistent`] but it doesn't exist! + pub fn foo() {} + + #[expect(rustdoc::invalid_html_tags)] + ///

+ pub fn bar() {} + + #[expect(rustdoc::bare_urls)] + /// http://example.org + pub fn baz() {} +} + +pub mod rustdoc_warn { + //! See + + #[expect(rustdoc::broken_intra_doc_links)] + /// I want to link to [`bar`] but it doesn't exist! + pub fn foo() {} + + #[expect(rustdoc::invalid_html_tags)] + ///

+ pub fn bar() {} + + #[expect(rustdoc::bare_urls)] + /// + pub fn baz() {} +} + +mod clippy_ok { + //! See + + #[expect(clippy::almost_swapped)] + fn foo() { + let mut a = 0; + let mut b = 9; + a = b; + b = a; + } + + #[expect(clippy::bytes_nth)] + fn bar() { + let _ = "Hello".bytes().nth(3); + } + + #[expect(clippy::if_same_then_else)] + fn baz() { + let _ = if true { 42 } else { 42 }; + } + + #[expect(clippy::logic_bug)] + fn burger() { + let a = false; + let b = true; + + if a && b || a {} + } +} + +mod clippy_warn { + //! See + + #[expect(clippy::almost_swapped)] + fn foo() { + let mut a = 0; + let mut b = 9; + a = b; + } + + #[expect(clippy::bytes_nth)] + fn bar() { + let _ = "Hello".as_bytes().get(3); + } + + #[expect(clippy::if_same_then_else)] + fn baz() { + let _ = if true { 33 } else { 42 }; + } + + #[expect(clippy::logic_bug)] + fn burger() { + let a = false; + let b = true; + let c = false; + + if a && b || c {} + } +} + +fn main() { + rustc_warn::rustc_lints(); +} diff --git a/src/tools/clippy/tests/ui/expect_tool_lint_rfc_2383.stderr b/src/tools/clippy/tests/ui/expect_tool_lint_rfc_2383.stderr new file mode 100644 index 000000000000..db29e85a8219 --- /dev/null +++ b/src/tools/clippy/tests/ui/expect_tool_lint_rfc_2383.stderr @@ -0,0 +1,40 @@ +error: this lint expectation is unfulfilled + --> $DIR/expect_tool_lint_rfc_2383.rs:35:14 + | +LL | #[expect(dead_code)] + | ^^^^^^^^^ + | + = note: `-D unfulfilled-lint-expectations` implied by `-D warnings` + +error: this lint expectation is unfulfilled + --> $DIR/expect_tool_lint_rfc_2383.rs:39:18 + | +LL | #[expect(illegal_floating_point_literal_pattern)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: this lint expectation is unfulfilled + --> $DIR/expect_tool_lint_rfc_2383.rs:113:14 + | +LL | #[expect(clippy::almost_swapped)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: this lint expectation is unfulfilled + --> $DIR/expect_tool_lint_rfc_2383.rs:120:14 + | +LL | #[expect(clippy::bytes_nth)] + | ^^^^^^^^^^^^^^^^^ + +error: this lint expectation is unfulfilled + --> $DIR/expect_tool_lint_rfc_2383.rs:125:14 + | +LL | #[expect(clippy::if_same_then_else)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: this lint expectation is unfulfilled + --> $DIR/expect_tool_lint_rfc_2383.rs:130:14 + | +LL | #[expect(clippy::logic_bug)] + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + diff --git a/src/tools/clippy/tests/ui/indexing_slicing_index.stderr b/src/tools/clippy/tests/ui/indexing_slicing_index.stderr index 83a36f407d5d..6ae700753f06 100644 --- a/src/tools/clippy/tests/ui/indexing_slicing_index.stderr +++ b/src/tools/clippy/tests/ui/indexing_slicing_index.stderr @@ -1,4 +1,4 @@ -error[E0080]: evaluation of `main::{constant#3}::<&i32>` failed +error[E0080]: evaluation of `main::{constant#3}` failed --> $DIR/indexing_slicing_index.rs:31:14 | LL | const { &ARR[idx4()] }; // Ok, let rustc handle const contexts. diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs index 51ed1b5a61cb..1ce02e48c05b 100644 --- a/src/tools/error_index_generator/main.rs +++ b/src/tools/error_index_generator/main.rs @@ -280,10 +280,6 @@ fn main() { fn register_all() -> Vec<(&'static str, Option<&'static str>)> { let mut long_codes: Vec<(&'static str, Option<&'static str>)> = Vec::new(); macro_rules! register_diagnostics { - ($($ecode:ident: $message:expr,)*) => ( - register_diagnostics!{$($ecode:$message,)* ;} - ); - ($($ecode:ident: $message:expr,)* ; $($code:ident,)*) => ( $( {long_codes.extend([