diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index e65688f3532e1..b5dc9b818c340 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1256,6 +1256,19 @@ pub enum StmtKind { MacCall(Box), } +impl StmtKind { + pub fn descr(&self) -> &'static str { + match self { + StmtKind::Let(_) => "local", + StmtKind::Item(_) => "item", + StmtKind::Expr(_) => "expression", + StmtKind::Semi(_) => "statement", + StmtKind::Empty => "semicolon", + StmtKind::MacCall(_) => "macro call", + } + } +} + #[derive(Clone, Encodable, Decodable, Debug, Walkable)] pub struct MacCallStmt { pub mac: Box, diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index 5f8933aa2beba..8d7351d3a510c 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -125,9 +125,9 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { } impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { - /// Because we want to track parent items and so forth, enable - /// deep walking so that we walk nested items in the context of - /// their outer items. + // Because we want to track parent items and so forth, enable + // deep walking so that we walk nested items in the context of + // their outer items. fn visit_nested_item(&mut self, item: ItemId) { debug!("visit_nested_item: {:?}", item); diff --git a/compiler/rustc_attr_parsing/messages.ftl b/compiler/rustc_attr_parsing/messages.ftl index a2a5f8ab14236..59fae5b8dc111 100644 --- a/compiler/rustc_attr_parsing/messages.ftl +++ b/compiler/rustc_attr_parsing/messages.ftl @@ -99,6 +99,7 @@ attr_parsing_invalid_link_modifier = attr_parsing_invalid_meta_item = expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found {$descr} .remove_neg_sugg = negative numbers are not literals, try removing the `-` sign .quote_ident_sugg = surround the identifier with quotation marks to make it into a string literal + .label = {$descr}s are not allowed here attr_parsing_invalid_predicate = invalid predicate `{$predicate}` diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs b/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs new file mode 100644 index 0000000000000..8006fb963b198 --- /dev/null +++ b/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs @@ -0,0 +1,89 @@ +use rustc_ast::token::Token; +use rustc_ast::tokenstream::TokenStream; +use rustc_ast::{AttrStyle, NodeId, token}; +use rustc_feature::{AttributeTemplate, Features}; +use rustc_hir::AttrPath; +use rustc_hir::attrs::CfgEntry; +use rustc_parse::exp; +use rustc_parse::parser::Parser; +use rustc_session::Session; +use rustc_span::{ErrorGuaranteed, Ident, Span}; + +use crate::parser::MetaItemOrLitParser; +use crate::{AttributeParser, ParsedDescription, ShouldEmit, parse_cfg_entry}; + +pub enum CfgSelectPredicate { + Cfg(CfgEntry), + Wildcard(Token), +} + +#[derive(Default)] +pub struct CfgSelectBranches { + /// All the conditional branches. + pub reachable: Vec<(CfgEntry, TokenStream, Span)>, + /// The first wildcard `_ => { ... }` branch. + pub wildcard: Option<(Token, TokenStream, Span)>, + /// All branches after the first wildcard, including further wildcards. + /// These branches are kept for formatting. + pub unreachable: Vec<(CfgSelectPredicate, TokenStream, Span)>, +} + +pub fn parse_cfg_select( + p: &mut Parser<'_>, + sess: &Session, + features: Option<&Features>, + lint_node_id: NodeId, +) -> Result { + let mut branches = CfgSelectBranches::default(); + + while p.token != token::Eof { + if p.eat_keyword(exp!(Underscore)) { + let underscore = p.prev_token; + p.expect(exp!(FatArrow)).map_err(|e| e.emit())?; + + let tts = p.parse_delimited_token_tree().map_err(|e| e.emit())?; + let span = underscore.span.to(p.token.span); + + match branches.wildcard { + None => branches.wildcard = Some((underscore, tts, span)), + Some(_) => { + branches.unreachable.push((CfgSelectPredicate::Wildcard(underscore), tts, span)) + } + } + } else { + let meta = MetaItemOrLitParser::parse_single(p, ShouldEmit::ErrorsAndLints) + .map_err(|diag| diag.emit())?; + let cfg_span = meta.span(); + let cfg = AttributeParser::parse_single_args( + sess, + cfg_span, + cfg_span, + AttrStyle::Inner, + AttrPath { + segments: vec![Ident::from_str("cfg_select")].into_boxed_slice(), + span: cfg_span, + }, + ParsedDescription::Macro, + cfg_span, + lint_node_id, + features, + ShouldEmit::ErrorsAndLints, + &meta, + parse_cfg_entry, + &AttributeTemplate::default(), + )?; + + p.expect(exp!(FatArrow)).map_err(|e| e.emit())?; + + let tts = p.parse_delimited_token_tree().map_err(|e| e.emit())?; + let span = cfg_span.to(p.token.span); + + match branches.wildcard { + None => branches.reachable.push((cfg, tts, span)), + Some(_) => branches.unreachable.push((CfgSelectPredicate::Cfg(cfg), tts, span)), + } + } + } + + Ok(branches) +} diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index 093969586596d..65e0957ca9005 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -33,6 +33,7 @@ pub(crate) mod allow_unstable; pub(crate) mod body; pub(crate) mod cfg; pub(crate) mod cfg_old; +pub(crate) mod cfg_select; pub(crate) mod codegen_attrs; pub(crate) mod confusables; pub(crate) mod crate_level; diff --git a/compiler/rustc_attr_parsing/src/lib.rs b/compiler/rustc_attr_parsing/src/lib.rs index 473935abdcd50..046cca4c742b0 100644 --- a/compiler/rustc_attr_parsing/src/lib.rs +++ b/compiler/rustc_attr_parsing/src/lib.rs @@ -106,6 +106,7 @@ pub use attributes::cfg::{ CFG_TEMPLATE, EvalConfigResult, eval_config_entry, parse_cfg, parse_cfg_attr, parse_cfg_entry, }; pub use attributes::cfg_old::*; +pub use attributes::cfg_select::*; pub use attributes::util::{is_builtin_attr, is_doc_alias_attrs_contain_symbol, parse_version}; pub use context::{Early, Late, OmitDoc, ShouldEmit}; pub use interface::AttributeParser; diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs index 7474471f2fe0f..819e5630561d0 100644 --- a/compiler/rustc_attr_parsing/src/parser.rs +++ b/compiler/rustc_attr_parsing/src/parser.rs @@ -8,12 +8,12 @@ use std::fmt::{Debug, Display}; use rustc_ast::token::{self, Delimiter, MetaVarKind}; use rustc_ast::tokenstream::TokenStream; -use rustc_ast::{AttrArgs, Expr, ExprKind, LitKind, MetaItemLit, NormalAttr, Path}; +use rustc_ast::{AttrArgs, Expr, ExprKind, LitKind, MetaItemLit, NormalAttr, Path, StmtKind, UnOp}; use rustc_ast_pretty::pprust; use rustc_errors::{Diag, PResult}; use rustc_hir::{self as hir, AttrPath}; use rustc_parse::exp; -use rustc_parse::parser::{Parser, PathStyle, token_descr}; +use rustc_parse::parser::{ForceCollect, Parser, PathStyle, token_descr}; use rustc_session::errors::{create_lit_error, report_lit_error}; use rustc_session::parse::ParseSess; use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, sym}; @@ -488,33 +488,55 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> { descr: token_descr(&self.parser.token), quote_ident_sugg: None, remove_neg_sugg: None, + label: None, }; + if let token::OpenInvisible(_) = self.parser.token.kind { + // Do not attempt to suggest anything when encountered as part of a macro expansion. + return self.parser.dcx().create_err(err); + } + // Suggest quoting idents, e.g. in `#[cfg(key = value)]`. We don't use `Token::ident` and // don't `uninterpolate` the token to avoid suggesting anything butchered or questionable // when macro metavariables are involved. - if self.parser.prev_token == token::Eq - && let token::Ident(..) = self.parser.token.kind - { - let before = self.parser.token.span.shrink_to_lo(); - while let token::Ident(..) = self.parser.token.kind { - self.parser.bump(); + let snapshot = self.parser.create_snapshot_for_diagnostic(); + let stmt = self.parser.parse_stmt_without_recovery(false, ForceCollect::No, false); + match stmt { + Ok(Some(stmt)) => { + // The user tried to write something like + // `#[deprecated(note = concat!("a", "b"))]`. + err.descr = stmt.kind.descr().to_string(); + err.label = Some(stmt.span); + err.span = stmt.span; + if let StmtKind::Expr(expr) = &stmt.kind + && let ExprKind::Unary(UnOp::Neg, val) = &expr.kind + && let ExprKind::Lit(_) = val.kind + { + err.remove_neg_sugg = Some(InvalidMetaItemRemoveNegSugg { + negative_sign: expr.span.until(val.span), + }); + } else if let StmtKind::Expr(expr) = &stmt.kind + && let ExprKind::Path(None, Path { segments, .. }) = &expr.kind + && segments.len() == 1 + { + while let token::Ident(..) | token::Literal(_) | token::Dot = + self.parser.token.kind + { + // We've got a word, so we try to consume the rest of a potential sentence. + // We include `.` to correctly handle things like `A sentence here.`. + self.parser.bump(); + } + err.quote_ident_sugg = Some(InvalidMetaItemQuoteIdentSugg { + before: expr.span.shrink_to_lo(), + after: self.parser.prev_token.span.shrink_to_hi(), + }); + } + } + Ok(None) => {} + Err(e) => { + e.cancel(); + self.parser.restore_snapshot(snapshot); } - err.quote_ident_sugg = Some(InvalidMetaItemQuoteIdentSugg { - before, - after: self.parser.prev_token.span.shrink_to_hi(), - }); - } - - if self.parser.token == token::Minus - && self - .parser - .look_ahead(1, |t| matches!(t.kind, rustc_ast::token::TokenKind::Literal { .. })) - { - err.remove_neg_sugg = - Some(InvalidMetaItemRemoveNegSugg { negative_sign: self.parser.token.span }); - self.parser.bump(); - self.parser.bump(); } self.parser.dcx().create_err(err) diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index 8d783503f7be0..2e18fecc35811 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -846,6 +846,8 @@ pub(crate) struct InvalidMetaItem { pub quote_ident_sugg: Option, #[subdiagnostic] pub remove_neg_sugg: Option, + #[label] + pub label: Option, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_attr_parsing/src/validate_attr.rs b/compiler/rustc_attr_parsing/src/validate_attr.rs index 927417f89f8c0..4065fe7ce1735 100644 --- a/compiler/rustc_attr_parsing/src/validate_attr.rs +++ b/compiler/rustc_attr_parsing/src/validate_attr.rs @@ -209,7 +209,7 @@ pub fn check_attribute_safety( // - Normal builtin attribute // - Writing `#[unsafe(..)]` is not permitted on normal builtin attributes - (Some(AttributeSafety::Normal), Safety::Unsafe(unsafe_span)) => { + (None | Some(AttributeSafety::Normal), Safety::Unsafe(unsafe_span)) => { psess.dcx().emit_err(errors::InvalidAttrUnsafe { span: unsafe_span, name: attr_item.path.clone(), @@ -218,15 +218,10 @@ pub fn check_attribute_safety( // - Normal builtin attribute // - No explicit `#[unsafe(..)]` written. - (Some(AttributeSafety::Normal), Safety::Default) => { + (None | Some(AttributeSafety::Normal), Safety::Default) => { // OK } - // - Non-builtin attribute - (None, Safety::Unsafe(_) | Safety::Default) => { - // OK (not checked here) - } - ( Some(AttributeSafety::Unsafe { .. } | AttributeSafety::Normal) | None, Safety::Safe(..), diff --git a/compiler/rustc_builtin_macros/src/cfg_select.rs b/compiler/rustc_builtin_macros/src/cfg_select.rs index f22d5f255c292..f2e454c3d4373 100644 --- a/compiler/rustc_builtin_macros/src/cfg_select.rs +++ b/compiler/rustc_builtin_macros/src/cfg_select.rs @@ -1,7 +1,9 @@ use rustc_ast::tokenstream::TokenStream; use rustc_attr_parsing as attr; +use rustc_attr_parsing::{ + CfgSelectBranches, CfgSelectPredicate, EvalConfigResult, ShouldEmit, parse_cfg_select, +}; use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult}; -use rustc_parse::parser::cfg_select::{CfgSelectBranches, CfgSelectPredicate, parse_cfg_select}; use rustc_span::{Ident, Span, sym}; use crate::errors::{CfgSelectNoMatches, CfgSelectUnreachable}; @@ -9,11 +11,11 @@ use crate::errors::{CfgSelectNoMatches, CfgSelectUnreachable}; /// Selects the first arm whose predicate evaluates to true. fn select_arm(ecx: &ExtCtxt<'_>, branches: CfgSelectBranches) -> Option<(TokenStream, Span)> { for (cfg, tt, arm_span) in branches.reachable { - if attr::cfg_matches( - &cfg, + if let EvalConfigResult::True = attr::eval_config_entry( &ecx.sess, + &cfg, ecx.current_expansion.lint_node_id, - Some(ecx.ecfg.features), + ShouldEmit::ErrorsAndLints, ) { return Some((tt, arm_span)); } @@ -27,37 +29,41 @@ pub(super) fn expand_cfg_select<'cx>( sp: Span, tts: TokenStream, ) -> MacroExpanderResult<'cx> { - ExpandResult::Ready(match parse_cfg_select(&mut ecx.new_parser_from_tts(tts)) { - Ok(branches) => { - if let Some((underscore, _, _)) = branches.wildcard { - // Warn for every unreachable predicate. We store the fully parsed branch for rustfmt. - for (predicate, _, _) in &branches.unreachable { - let span = match predicate { - CfgSelectPredicate::Wildcard(underscore) => underscore.span, - CfgSelectPredicate::Cfg(cfg) => cfg.span(), - }; - let err = CfgSelectUnreachable { span, wildcard_span: underscore.span }; - ecx.dcx().emit_warn(err); + ExpandResult::Ready( + match parse_cfg_select( + &mut ecx.new_parser_from_tts(tts), + ecx.sess, + Some(ecx.ecfg.features), + ecx.current_expansion.lint_node_id, + ) { + Ok(branches) => { + if let Some((underscore, _, _)) = branches.wildcard { + // Warn for every unreachable predicate. We store the fully parsed branch for rustfmt. + for (predicate, _, _) in &branches.unreachable { + let span = match predicate { + CfgSelectPredicate::Wildcard(underscore) => underscore.span, + CfgSelectPredicate::Cfg(cfg) => cfg.span(), + }; + let err = CfgSelectUnreachable { span, wildcard_span: underscore.span }; + ecx.dcx().emit_warn(err); + } } - } - if let Some((tts, arm_span)) = select_arm(ecx, branches) { - return ExpandResult::from_tts( - ecx, - tts, - sp, - arm_span, - Ident::with_dummy_span(sym::cfg_select), - ); - } else { - // Emit a compiler error when none of the predicates matched. - let guar = ecx.dcx().emit_err(CfgSelectNoMatches { span: sp }); - DummyResult::any(sp, guar) + if let Some((tts, arm_span)) = select_arm(ecx, branches) { + return ExpandResult::from_tts( + ecx, + tts, + sp, + arm_span, + Ident::with_dummy_span(sym::cfg_select), + ); + } else { + // Emit a compiler error when none of the predicates matched. + let guar = ecx.dcx().emit_err(CfgSelectNoMatches { span: sp }); + DummyResult::any(sp, guar) + } } - } - Err(err) => { - let guar = err.emit(); - DummyResult::any(sp, guar) - } - }) + Err(guar) => DummyResult::any(sp, guar), + }, + ) } diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index 9ac282df5b5ea..09d71f5dd5579 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -916,8 +916,8 @@ pub(crate) fn codegen_call_with_unwind_action( pub(crate) fn lib_call_arg_param(tcx: TyCtxt<'_>, ty: Type, is_signed: bool) -> AbiParam { let param = AbiParam::new(ty); if ty.is_int() && u64::from(ty.bits()) < tcx.data_layout.pointer_size().bits() { - match (&tcx.sess.target.arch, tcx.sess.target.vendor.as_ref()) { - (Arch::X86_64, _) | (Arch::AArch64, "apple") => match (ty, is_signed) { + match (&tcx.sess.target.arch, tcx.sess.target.is_like_darwin) { + (Arch::X86_64, _) | (Arch::AArch64, true) => match (ty, is_signed) { (types::I8 | types::I16, true) => param.sext(), (types::I8 | types::I16, false) => param.uext(), _ => param, diff --git a/compiler/rustc_codegen_cranelift/src/codegen_f16_f128.rs b/compiler/rustc_codegen_cranelift/src/codegen_f16_f128.rs index 91f7220667ff9..86bff32dc623c 100644 --- a/compiler/rustc_codegen_cranelift/src/codegen_f16_f128.rs +++ b/compiler/rustc_codegen_cranelift/src/codegen_f16_f128.rs @@ -5,7 +5,7 @@ use crate::prelude::*; pub(crate) fn f16_to_f32(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value { let (value, arg_ty) = - if fx.tcx.sess.target.vendor == "apple" && fx.tcx.sess.target.arch == Arch::X86_64 { + if fx.tcx.sess.target.is_like_darwin && fx.tcx.sess.target.arch == Arch::X86_64 { ( fx.bcx.ins().bitcast(types::I16, MemFlags::new(), value), lib_call_arg_param(fx.tcx, types::I16, false), @@ -22,8 +22,7 @@ fn f16_to_f64(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value { } pub(crate) fn f32_to_f16(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value { - let ret_ty = if fx.tcx.sess.target.vendor == "apple" && fx.tcx.sess.target.arch == Arch::X86_64 - { + let ret_ty = if fx.tcx.sess.target.is_like_darwin && fx.tcx.sess.target.arch == Arch::X86_64 { types::I16 } else { types::F16 @@ -38,8 +37,7 @@ pub(crate) fn f32_to_f16(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value } fn f64_to_f16(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value { - let ret_ty = if fx.tcx.sess.target.vendor == "apple" && fx.tcx.sess.target.arch == Arch::X86_64 - { + let ret_ty = if fx.tcx.sess.target.is_like_darwin && fx.tcx.sess.target.arch == Arch::X86_64 { types::I16 } else { types::F16 diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index c5724c20b2165..2817dcf8e976a 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1819,7 +1819,7 @@ fn self_contained_components( LinkSelfContainedDefault::InferredForMusl => sess.crt_static(Some(crate_type)), LinkSelfContainedDefault::InferredForMingw => { sess.host == sess.target - && sess.target.vendor != "uwp" + && sess.target.abi != "uwp" && detect_self_contained_mingw(sess, linker) } } diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index eb2740d59b4b5..5abcf99b3d67a 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -83,7 +83,7 @@ pub(crate) fn get_linker<'a>( // To comply with the Windows App Certification Kit, // MSVC needs to link with the Store versions of the runtime libraries (vcruntime, msvcrt, etc). let t = &sess.target; - if matches!(flavor, LinkerFlavor::Msvc(..)) && t.vendor == "uwp" { + if matches!(flavor, LinkerFlavor::Msvc(..)) && t.abi == "uwp" { if let Some(ref tool) = msvc_tool { let original_path = tool.path(); if let Some(root_lib_path) = original_path.ancestors().nth(4) { @@ -134,7 +134,7 @@ pub(crate) fn get_linker<'a>( // FIXME: Move `/LIBPATH` addition for uwp targets from the linker construction // to the linker args construction. - assert!(cmd.get_args().is_empty() || sess.target.vendor == "uwp"); + assert!(cmd.get_args().is_empty() || sess.target.abi == "uwp"); match flavor { LinkerFlavor::Unix(Cc::No) if sess.target.os == "l4re" => { Box::new(L4Bender::new(cmd, sess)) as Box diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs index 08e2f35595332..bde36f45b3838 100644 --- a/compiler/rustc_codegen_ssa/src/common.rs +++ b/compiler/rustc_codegen_ssa/src/common.rs @@ -171,7 +171,7 @@ pub fn asm_const_to_str<'tcx>( } pub fn is_mingw_gnu_toolchain(target: &Target) -> bool { - target.vendor == "pc" && target.os == "windows" && target.env == "gnu" && target.abi.is_empty() + target.os == "windows" && target.env == "gnu" && target.abi.is_empty() } pub fn i686_decorated_name( diff --git a/compiler/rustc_data_structures/src/steal.rs b/compiler/rustc_data_structures/src/steal.rs index 0d79d98b5d966..afa9bc36f2c5e 100644 --- a/compiler/rustc_data_structures/src/steal.rs +++ b/compiler/rustc_data_structures/src/steal.rs @@ -1,5 +1,5 @@ use crate::stable_hasher::{HashStable, StableHasher}; -use crate::sync::{MappedReadGuard, ReadGuard, RwLock}; +use crate::sync::{MappedReadGuard, MappedWriteGuard, ReadGuard, RwLock, WriteGuard}; /// The `Steal` struct is intended to used as the value for a query. /// Specifically, we sometimes have queries (*cough* MIR *cough*) @@ -40,9 +40,17 @@ impl Steal { ReadGuard::map(borrow, |opt| opt.as_ref().unwrap()) } + /// An escape hatch for rustc drivers to mutate `Steal` caches. + /// + /// Use at your own risk. This can badly break incremental compilation + /// and anything else that relies on the immutability of query caches. #[track_caller] - pub fn get_mut(&mut self) -> &mut T { - self.value.get_mut().as_mut().expect("attempt to read from stolen value") + pub fn risky_hack_borrow_mut(&self) -> MappedWriteGuard<'_, T> { + let borrow = self.value.borrow_mut(); + if borrow.is_none() { + panic!("attempted to read from stolen value: {}", std::any::type_name::()); + } + WriteGuard::map(borrow, |opt| opt.as_mut().unwrap()) } #[track_caller] diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 81a7ee1ff45fe..e6fa1fa5ce50a 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -2322,11 +2322,6 @@ impl HumanEmitter { show_code_change { for part in parts { - let snippet = if let Ok(snippet) = sm.span_to_snippet(part.span) { - snippet - } else { - String::new() - }; let span_start_pos = sm.lookup_char_pos(part.span.lo()).col_display; let span_end_pos = sm.lookup_char_pos(part.span.hi()).col_display; @@ -2402,7 +2397,7 @@ impl HumanEmitter { // LL - REMOVED <- row_num - 2 - (newlines - first_i - 1) // LL + NEWER // | <- row_num - + let snippet = sm.span_to_snippet(part.span).unwrap_or_default(); let newlines = snippet.lines().count(); if newlines > 0 && row_num > newlines { // Account for removals where the part being removed spans multiple diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 2f88e587ae9f7..d5b1979ba1f65 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -303,6 +303,19 @@ impl TrimmedSubstitutionPart { /// `BB` is. Return the length of the prefix, the "trimmed" suggestion, and the length /// of the suffix. fn as_substr<'a>(original: &'a str, suggestion: &'a str) -> Option<(usize, &'a str, usize)> { + // Case for import paths where the suggestion shares a prefix with the original. + // Without this, suggesting `std::sync` for `sync` would incorrectly highlight `td::s` + // instead of `std::` because of the common 's' prefix. See #148070. + if suggestion.contains("::") + && suggestion.ends_with(original) + && suggestion.len() > original.len() + && let prefix = &suggestion[..suggestion.len() - original.len()] + && prefix.ends_with("::") + && suggestion.chars().next() == original.chars().next() + { + return Some((0, prefix, original.len())); + } + let common_prefix = original .chars() .zip(suggestion.chars()) diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 276490bc0c9d5..1dbf7b4726498 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -886,9 +886,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } } } else if let SyntaxExtensionKind::NonMacroAttr = ext { - if let ast::Safety::Unsafe(span) = attr.get_normal_item().unsafety { - self.cx.dcx().span_err(span, "unnecessary `unsafe` on safe attribute"); - } // `-Zmacro-stats` ignores these because they don't do any real expansion. self.cx.expanded_inert_attrs.mark(&attr); item.visit_attrs(|attrs| attrs.insert(pos, attr)); diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 7ddd71c346006..4ba64b240ac03 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -194,6 +194,18 @@ pub enum CfgEntry { Version(Option, Span), } +impl CfgEntry { + pub fn span(&self) -> Span { + let (CfgEntry::All(_, span) + | CfgEntry::Any(_, span) + | CfgEntry::Not(_, span) + | CfgEntry::Bool(_, span) + | CfgEntry::NameValue { span, .. } + | CfgEntry::Version(_, span)) = self; + *span + } +} + /// Possible values for the `#[linkage]` attribute, allowing to specify the /// linkage type for a `MonoItem`. /// diff --git a/compiler/rustc_hir_analysis/src/variance/terms.rs b/compiler/rustc_hir_analysis/src/variance/terms.rs index cf38957bf24aa..9c7680b921205 100644 --- a/compiler/rustc_hir_analysis/src/variance/terms.rs +++ b/compiler/rustc_hir_analysis/src/variance/terms.rs @@ -44,7 +44,7 @@ impl<'a> fmt::Debug for VarianceTerm<'a> { } } -/// The first pass over the crate simply builds up the set of inferreds. +// The first pass over the crate simply builds up the set of inferreds. pub(crate) struct TermsContext<'a, 'tcx> { pub tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs index 191eb721b3477..ae145543e70dc 100644 --- a/compiler/rustc_lint/src/passes.rs +++ b/compiler/rustc_lint/src/passes.rs @@ -55,10 +55,10 @@ macro_rules! late_lint_methods { /// Each `check` method checks a single syntax node, and should not /// invoke methods recursively (unlike `Visitor`). By default they /// do nothing. -// +/// // FIXME: eliminate the duplication with `Visitor`. But this also // contains a few lint-specific methods with no equivalent in `Visitor`. - +// macro_rules! declare_late_lint_pass { ([], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( pub trait LateLintPass<'tcx>: LintPass { diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 291f5c65dfa27..10fe23a0a65c9 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -67,7 +67,7 @@ pub fn walk_native_lib_search_dirs( // FIXME: On AIX this also has the side-effect of making the list of library search paths // non-empty, which is needed or the linker may decide to record the LIBPATH env, if // defined, as the search path instead of appending the default search paths. - if sess.target.vendor == "fortanix" + if sess.target.abi == "fortanix" || sess.target.os == "linux" || sess.target.os == "fuchsia" || sess.target.is_like_aix diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs index 5764a9c84eeaf..6985cc7ddcfa1 100644 --- a/compiler/rustc_middle/src/mir/consts.rs +++ b/compiler/rustc_middle/src/mir/consts.rs @@ -16,7 +16,7 @@ use crate::ty::{self, ConstKind, GenericArgsRef, ScalarInt, Ty, TyCtxt}; /////////////////////////////////////////////////////////////////////////// /// Evaluated Constants - +/// /// Represents the result of const evaluation via the `eval_to_allocation` query. /// Not to be confused with `ConstAllocation`, which directly refers to the underlying data! /// Here we indirect via an `AllocId`. diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index a4422abc6883a..782ea3906ef13 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -607,9 +607,9 @@ impl<'tcx> TyCtxt<'tcx> { /// have the same `DefKind`. /// /// Note that closures have a `DefId`, but the closure *expression* also has a - // `HirId` that is located within the context where the closure appears (and, sadly, - // a corresponding `NodeId`, since those are not yet phased out). The parent of - // the closure's `DefId` will also be the context where it appears. + /// `HirId` that is located within the context where the closure appears (and, sadly, + /// a corresponding `NodeId`, since those are not yet phased out). The parent of + /// the closure's `DefId` will also be the context where it appears. pub fn is_closure_like(self, def_id: DefId) -> bool { matches!(self.def_kind(def_id), DefKind::Closure) } diff --git a/compiler/rustc_parse/src/parser/cfg_select.rs b/compiler/rustc_parse/src/parser/cfg_select.rs index 08a71db4de853..9692d2c708938 100644 --- a/compiler/rustc_parse/src/parser/cfg_select.rs +++ b/compiler/rustc_parse/src/parser/cfg_select.rs @@ -1,83 +1,34 @@ -use rustc_ast::token::Token; +use rustc_ast::token; use rustc_ast::tokenstream::{TokenStream, TokenTree}; use rustc_ast::util::classify; -use rustc_ast::{MetaItemInner, token}; use rustc_errors::PResult; -use rustc_span::Span; use crate::exp; use crate::parser::{AttrWrapper, ForceCollect, Parser, Restrictions, Trailing, UsePreAttrPos}; -pub enum CfgSelectPredicate { - Cfg(MetaItemInner), - Wildcard(Token), -} - -#[derive(Default)] -pub struct CfgSelectBranches { - /// All the conditional branches. - pub reachable: Vec<(MetaItemInner, TokenStream, Span)>, - /// The first wildcard `_ => { ... }` branch. - pub wildcard: Option<(Token, TokenStream, Span)>, - /// All branches after the first wildcard, including further wildcards. - /// These branches are kept for formatting. - pub unreachable: Vec<(CfgSelectPredicate, TokenStream, Span)>, -} - -/// Parses a `TokenTree` consisting either of `{ /* ... */ }` (and strip the braces) or an -/// expression followed by a comma (and strip the comma). -fn parse_token_tree<'a>(p: &mut Parser<'a>) -> PResult<'a, TokenStream> { - if p.token == token::OpenBrace { - // Strip the outer '{' and '}'. - match p.parse_token_tree() { - TokenTree::Token(..) => unreachable!("because of the expect above"), - TokenTree::Delimited(.., tts) => return Ok(tts), - } - } - let expr = p.collect_tokens(None, AttrWrapper::empty(), ForceCollect::Yes, |p, _| { - p.parse_expr_res(Restrictions::STMT_EXPR, AttrWrapper::empty()) - .map(|(expr, _)| (expr, Trailing::No, UsePreAttrPos::No)) - })?; - if !classify::expr_is_complete(&expr) && p.token != token::CloseBrace && p.token != token::Eof { - p.expect(exp!(Comma))?; - } else { - let _ = p.eat(exp!(Comma)); - } - Ok(TokenStream::from_ast(&expr)) -} - -pub fn parse_cfg_select<'a>(p: &mut Parser<'a>) -> PResult<'a, CfgSelectBranches> { - let mut branches = CfgSelectBranches::default(); - - while p.token != token::Eof { - if p.eat_keyword(exp!(Underscore)) { - let underscore = p.prev_token; - p.expect(exp!(FatArrow))?; - - let tts = parse_token_tree(p)?; - let span = underscore.span.to(p.token.span); - - match branches.wildcard { - None => branches.wildcard = Some((underscore, tts, span)), - Some(_) => { - branches.unreachable.push((CfgSelectPredicate::Wildcard(underscore), tts, span)) - } +impl<'a> Parser<'a> { + /// Parses a `TokenTree` consisting either of `{ /* ... */ }` (and strip the braces) or an + /// expression followed by a comma (and strip the comma). + pub fn parse_delimited_token_tree(&mut self) -> PResult<'a, TokenStream> { + if self.token == token::OpenBrace { + // Strip the outer '{' and '}'. + match self.parse_token_tree() { + TokenTree::Token(..) => unreachable!("because of the expect above"), + TokenTree::Delimited(.., tts) => return Ok(tts), } + } + let expr = self.collect_tokens(None, AttrWrapper::empty(), ForceCollect::Yes, |p, _| { + p.parse_expr_res(Restrictions::STMT_EXPR, AttrWrapper::empty()) + .map(|(expr, _)| (expr, Trailing::No, UsePreAttrPos::No)) + })?; + if !classify::expr_is_complete(&expr) + && self.token != token::CloseBrace + && self.token != token::Eof + { + self.expect(exp!(Comma))?; } else { - let meta_item = p.parse_meta_item_inner()?; - p.expect(exp!(FatArrow))?; - - let tts = parse_token_tree(p)?; - let span = meta_item.span().to(p.token.span); - - match branches.wildcard { - None => branches.reachable.push((meta_item, tts, span)), - Some(_) => { - branches.unreachable.push((CfgSelectPredicate::Cfg(meta_item), tts, span)) - } - } + let _ = self.eat(exp!(Comma)); } + Ok(TokenStream::from_ast(&expr)) } - - Ok(branches) } diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index bc08faabece47..c913e6fc1d6d0 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -287,7 +287,7 @@ impl<'a> Parser<'a> { } /// Replace `self` with `snapshot.parser`. - pub(super) fn restore_snapshot(&mut self, snapshot: SnapshotParser<'a>) { + pub fn restore_snapshot(&mut self, snapshot: SnapshotParser<'a>) { *self = snapshot.parser; } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index ad3493d93e80a..0b4c52d68b6ff 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -3592,8 +3592,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { && (lt.kind == MissingLifetimeKind::Ampersand || lt.kind == MissingLifetimeKind::Underscore) { - let pre = if lt.kind == MissingLifetimeKind::Ampersand - && let Some((kind, _span)) = self.diag_metadata.current_function + let pre = if let Some((kind, _span)) = self.diag_metadata.current_function && let FnKind::Fn(_, _, ast::Fn { sig, .. }) = kind && !sig.decl.inputs.is_empty() && let sugg = sig @@ -3623,10 +3622,12 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } else { ("one of the", "s") }; + let dotdotdot = + if lt.kind == MissingLifetimeKind::Ampersand { "..." } else { "" }; err.multipart_suggestion_verbose( format!( "instead, you are more likely to want to change {the} \ - argument{s} to be borrowed...", + argument{s} to be borrowed{dotdotdot}", ), sugg, Applicability::MaybeIncorrect, diff --git a/compiler/rustc_session/src/config/cfg.rs b/compiler/rustc_session/src/config/cfg.rs index 26ff87417ab0d..50c88e8b1e62a 100644 --- a/compiler/rustc_session/src/config/cfg.rs +++ b/compiler/rustc_session/src/config/cfg.rs @@ -298,7 +298,7 @@ pub(crate) fn default_configuration(sess: &Session) -> Cfg { ins_none!(sym::target_thread_local); } - ins_str!(sym::target_vendor, &sess.target.vendor); + ins_sym!(sym::target_vendor, sess.target.vendor_symbol()); // If the user wants a test runner, then add the test cfg. if sess.is_test_crate() { @@ -456,7 +456,7 @@ impl CheckCfg { ); values_target_os.insert(Symbol::intern(&target.options.os)); values_target_pointer_width.insert(sym::integer(target.pointer_width)); - values_target_vendor.insert(Symbol::intern(&target.options.vendor)); + values_target_vendor.insert(target.vendor_symbol()); } } } diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs index 2d83caa07676a..73a0d9eea7326 100644 --- a/compiler/rustc_target/src/lib.rs +++ b/compiler/rustc_target/src/lib.rs @@ -9,7 +9,9 @@ // tidy-alphabetical-start #![cfg_attr(bootstrap, feature(debug_closure_helpers))] +#![expect(internal_features)] #![feature(iter_intersperse)] +#![feature(rustc_attrs)] // tidy-alphabetical-end use std::path::{Path, PathBuf}; diff --git a/compiler/rustc_target/src/spec/base/windows_uwp_msvc.rs b/compiler/rustc_target/src/spec/base/windows_uwp_msvc.rs index 374918d38a791..4f9d9c83761f4 100644 --- a/compiler/rustc_target/src/spec/base/windows_uwp_msvc.rs +++ b/compiler/rustc_target/src/spec/base/windows_uwp_msvc.rs @@ -1,10 +1,9 @@ use crate::spec::{LinkerFlavor, Lld, TargetOptions, base}; pub(crate) fn opts() -> TargetOptions { - let mut opts = base::windows_msvc::opts(); + let mut opts = + TargetOptions { abi: "uwp".into(), vendor: "uwp".into(), ..base::windows_msvc::opts() }; - opts.abi = "uwp".into(); - opts.vendor = "uwp".into(); opts.add_pre_link_args(LinkerFlavor::Msvc(Lld::No), &["/APPCONTAINER", "mincore.lib"]); opts diff --git a/compiler/rustc_target/src/spec/json.rs b/compiler/rustc_target/src/spec/json.rs index ab2879f6c6ea8..8ac09205fbc89 100644 --- a/compiler/rustc_target/src/spec/json.rs +++ b/compiler/rustc_target/src/spec/json.rs @@ -261,6 +261,7 @@ impl ToJson for Target { ($attr:ident) => {{ target_option_val!($attr, (stringify!($attr)).replace("_", "-")) }}; ($attr:ident, $json_name:expr) => {{ let name = $json_name; + #[allow(rustc::bad_opt_access)] if default.$attr != target.$attr { d.insert(name.into(), target.$attr.to_json()); } diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 2dd0fbc4517a5..08fae288c441c 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -2045,6 +2045,7 @@ type StaticCow = Cow<'static, T>; /// construction, all its fields logically belong to `Target` and available from `Target` /// through `Deref` impls. #[derive(PartialEq, Clone, Debug)] +#[rustc_lint_opt_ty] pub struct TargetOptions { /// Used as the `target_endian` `cfg` variable. Defaults to little endian. pub endian: Endian, @@ -2063,7 +2064,10 @@ pub struct TargetOptions { /// However, parts of the backend do check this field for specific values to enable special behavior. pub abi: StaticCow, /// Vendor name to use for conditional compilation (`target_vendor`). Defaults to "unknown". - pub vendor: StaticCow, + #[rustc_lint_opt_deny_field_access( + "use `Target::is_like_*` instead of this field; see https://github.com/rust-lang/rust/issues/100343 for rationale" + )] + vendor: StaticCow, /// Linker to invoke pub linker: Option>, @@ -3323,6 +3327,10 @@ impl Target { Align::MAX } } + + pub fn vendor_symbol(&self) -> Symbol { + Symbol::intern(&self.vendor) + } } /// Either a target tuple string or a path to a JSON file. diff --git a/compiler/rustc_target/src/spec/targets/armv6k_nintendo_3ds.rs b/compiler/rustc_target/src/spec/targets/armv6k_nintendo_3ds.rs index a79c642870126..37a8b1d878098 100644 --- a/compiler/rustc_target/src/spec/targets/armv6k_nintendo_3ds.rs +++ b/compiler/rustc_target/src/spec/targets/armv6k_nintendo_3ds.rs @@ -5,7 +5,6 @@ use crate::spec::{ /// A base target for Nintendo 3DS devices using the devkitARM toolchain. /// /// Requires the devkitARM toolchain for 3DS targets on the host system. - pub(crate) fn target() -> Target { let pre_link_args = TargetOptions::link_args( LinkerFlavor::Gnu(Cc::Yes, Lld::No), diff --git a/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs index 6c02ec26fea48..631b9770fac54 100644 --- a/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs +++ b/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs @@ -7,7 +7,6 @@ use crate::spec::{ /// A base target for PlayStation Vita devices using the VITASDK toolchain (using newlib). /// /// Requires the VITASDK toolchain on the host system. - pub(crate) fn target() -> Target { let pre_link_args = TargetOptions::link_args( LinkerFlavor::Gnu(Cc::Yes, Lld::No), diff --git a/compiler/rustc_target/src/spec/targets/i686_win7_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_win7_windows_gnu.rs index c026f915906cb..43ebc54c2b402 100644 --- a/compiler/rustc_target/src/spec/targets/i686_win7_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/i686_win7_windows_gnu.rs @@ -1,15 +1,18 @@ use crate::spec::{ - Arch, Cc, FramePointer, LinkerFlavor, Lld, RustcAbi, Target, TargetMetadata, base, + Arch, Cc, FramePointer, LinkerFlavor, Lld, RustcAbi, Target, TargetMetadata, TargetOptions, + base, }; pub(crate) fn target() -> Target { - let mut base = base::windows_gnu::opts(); - base.vendor = "win7".into(); - base.rustc_abi = Some(RustcAbi::X86Sse2); - base.cpu = "pentium4".into(); - base.max_atomic_width = Some(64); - base.frame_pointer = FramePointer::Always; // Required for backtraces - base.linker = Some("i686-w64-mingw32-gcc".into()); + let mut base = TargetOptions { + vendor: "win7".into(), + rustc_abi: Some(RustcAbi::X86Sse2), + cpu: "pentium4".into(), + max_atomic_width: Some(64), + frame_pointer: FramePointer::Always, // Required for backtraces + linker: Some("i686-w64-mingw32-gcc".into()), + ..base::windows_gnu::opts() + }; // Mark all dynamic libraries and executables as compatible with the larger 4GiB address // space available to x86 Windows binaries on x86_64. diff --git a/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs index 68131bf654264..8994c245d7b90 100644 --- a/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs @@ -1,18 +1,22 @@ -use crate::spec::{Arch, LinkerFlavor, Lld, RustcAbi, SanitizerSet, Target, TargetMetadata, base}; +use crate::spec::{ + Arch, LinkerFlavor, Lld, RustcAbi, SanitizerSet, Target, TargetMetadata, TargetOptions, base, +}; pub(crate) fn target() -> Target { - let mut base = base::windows_msvc::opts(); - base.vendor = "win7".into(); - base.rustc_abi = Some(RustcAbi::X86Sse2); - base.cpu = "pentium4".into(); - base.max_atomic_width = Some(64); - base.supported_sanitizers = SanitizerSet::ADDRESS; - // On Windows 7 32-bit, the alignment characteristic of the TLS Directory - // don't appear to be respected by the PE Loader, leading to crashes. As - // a result, let's disable has_thread_local to make sure TLS goes through - // the emulation layer. - // See https://github.com/rust-lang/rust/issues/138903 - base.has_thread_local = false; + let mut base = TargetOptions { + vendor: "win7".into(), + rustc_abi: Some(RustcAbi::X86Sse2), + cpu: "pentium4".into(), + max_atomic_width: Some(64), + supported_sanitizers: SanitizerSet::ADDRESS, + // On Windows 7 32-bit, the alignment characteristic of the TLS Directory + // don't appear to be respected by the PE Loader, leading to crashes. As + // a result, let's disable has_thread_local to make sure TLS goes through + // the emulation layer. + // See https://github.com/rust-lang/rust/issues/138903 + has_thread_local: false, + ..base::windows_msvc::opts() + }; base.add_pre_link_args( LinkerFlavor::Msvc(Lld::No), diff --git a/compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs b/compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs index 79035c791156d..498d8182ad589 100644 --- a/compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs +++ b/compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs @@ -1,15 +1,17 @@ use rustc_abi::Endian; -use crate::spec::{Arch, Cc, LinkerFlavor, Target, TargetMetadata, base}; +use crate::spec::{Arch, Cc, LinkerFlavor, Target, TargetMetadata, TargetOptions, base}; pub(crate) fn target() -> Target { - let mut base = base::solaris::opts(); - base.endian = Endian::Big; + let mut base = TargetOptions { + endian: Endian::Big, + // llvm calls this "v9" + cpu: "v9".into(), + vendor: "sun".into(), + max_atomic_width: Some(64), + ..base::solaris::opts() + }; base.add_pre_link_args(LinkerFlavor::Unix(Cc::Yes), &["-m64"]); - // llvm calls this "v9" - base.cpu = "v9".into(); - base.vendor = "sun".into(); - base.max_atomic_width = Some(64); Target { llvm_target: "sparcv9-sun-solaris".into(), diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs index 7b8d5def3a70b..39ebe62430479 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs @@ -1,16 +1,19 @@ use crate::spec::{ - Arch, Cc, LinkerFlavor, SanitizerSet, StackProbeType, Target, TargetMetadata, base, + Arch, Cc, LinkerFlavor, SanitizerSet, StackProbeType, Target, TargetMetadata, TargetOptions, + base, }; pub(crate) fn target() -> Target { - let mut base = base::solaris::opts(); + let mut base = TargetOptions { + cpu: "x86-64".into(), + plt_by_default: false, + vendor: "pc".into(), + max_atomic_width: Some(64), + stack_probes: StackProbeType::Inline, + supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::THREAD, + ..base::solaris::opts() + }; base.add_pre_link_args(LinkerFlavor::Unix(Cc::Yes), &["-m64"]); - base.cpu = "x86-64".into(); - base.plt_by_default = false; - base.vendor = "pc".into(); - base.max_atomic_width = Some(64); - base.stack_probes = StackProbeType::Inline; - base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::THREAD; Target { llvm_target: "x86_64-pc-solaris".into(), diff --git a/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_gnu.rs index 22a1a126b8912..0bd4215855264 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_gnu.rs @@ -1,18 +1,20 @@ -use crate::spec::{Arch, Cc, LinkerFlavor, Lld, Target, TargetMetadata, base}; +use crate::spec::{Arch, Cc, LinkerFlavor, Lld, Target, TargetMetadata, TargetOptions, base}; pub(crate) fn target() -> Target { - let mut base = base::windows_gnu::opts(); - base.vendor = "win7".into(); - base.cpu = "x86-64".into(); - base.plt_by_default = false; + let mut base = TargetOptions { + vendor: "win7".into(), + cpu: "x86-64".into(), + plt_by_default: false, + max_atomic_width: Some(64), + linker: Some("x86_64-w64-mingw32-gcc".into()), + ..base::windows_gnu::opts() + }; // Use high-entropy 64 bit address space for ASLR base.add_pre_link_args( LinkerFlavor::Gnu(Cc::No, Lld::No), &["-m", "i386pep", "--high-entropy-va"], ); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64", "-Wl,--high-entropy-va"]); - base.max_atomic_width = Some(64); - base.linker = Some("x86_64-w64-mingw32-gcc".into()); Target { llvm_target: "x86_64-pc-windows-gnu".into(), diff --git a/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs index 99b59154811f2..1cc2efaae5f5f 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs @@ -1,12 +1,14 @@ -use crate::spec::{Arch, SanitizerSet, Target, TargetMetadata, base}; +use crate::spec::{Arch, SanitizerSet, Target, TargetMetadata, TargetOptions, base}; pub(crate) fn target() -> Target { - let mut base = base::windows_msvc::opts(); - base.vendor = "win7".into(); - base.cpu = "x86-64".into(); - base.plt_by_default = false; - base.max_atomic_width = Some(64); - base.supported_sanitizers = SanitizerSet::ADDRESS; + let base = TargetOptions { + vendor: "win7".into(), + cpu: "x86-64".into(), + plt_by_default: false, + max_atomic_width: Some(64), + supported_sanitizers: SanitizerSet::ADDRESS, + ..base::windows_msvc::opts() + }; Target { llvm_target: "x86_64-pc-windows-msvc".into(), diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index e225656af852c..da888acc47559 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -864,6 +864,42 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } + if sub.kind() == ty::ReStatic + && let Some(node) = self.tcx.hir_get_if_local(generic_param_scope.into()) + && let hir::Node::Item(hir::Item { + kind: hir::ItemKind::Fn { sig, body, has_body: true, .. }, + .. + }) + | hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body)), + .. + }) + | hir::Node::ImplItem(hir::ImplItem { + kind: hir::ImplItemKind::Fn(sig, body), .. + }) = node + && let hir::Node::Expr(expr) = self.tcx.hir_node(body.hir_id) + && let hir::ExprKind::Block(block, _) = expr.kind + && let Some(tail) = block.expr + && tail.span == span + && let hir::FnRetTy::Return(ty) = sig.decl.output + && let hir::TyKind::Path(path) = ty.kind + && let hir::QPath::Resolved(None, path) = path + && let hir::def::Res::Def(_, def_id) = path.res + && Some(def_id) == self.tcx.lang_items().owned_box() + && let [segment] = path.segments + && let Some(args) = segment.args + && let [hir::GenericArg::Type(ty)] = args.args + && let hir::TyKind::TraitObject(_, tagged_ref) = ty.kind + && let hir::LifetimeKind::ImplicitObjectLifetimeDefault = tagged_ref.pointer().kind + { + // Explicitly look for `-> Box` to point at it as the *likely* source of + // the `'static` lifetime requirement. + err.span_label( + ty.span, + format!("this `dyn Trait` has an implicit `'static` lifetime bound"), + ); + } + err } diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 7d395eb780346..9e3aeed69572f 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -1503,7 +1503,7 @@ macro_rules! int_impl { } } - /// Strict shift right. Computes `self >> rhs`, panicking `rhs` is + /// Strict shift right. Computes `self >> rhs`, panicking if `rhs` is /// larger than or equal to the number of bits in `self`. /// /// # Panics diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 2996e7b00da4e..8b3b122998774 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1900,7 +1900,7 @@ macro_rules! uint_impl { } } - /// Strict shift right. Computes `self >> rhs`, panicking `rhs` is + /// Strict shift right. Computes `self >> rhs`, panicking if `rhs` is /// larger than or equal to the number of bits in `self`. /// /// # Panics diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 909262d563e9f..edafc9e7a089f 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -4,6 +4,7 @@ use rustc_abi::ExternAbi; use rustc_ast::ast; +use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::thin_vec::ThinVec; use rustc_hir as hir; use rustc_hir::attrs::{self, DeprecatedSince}; @@ -988,3 +989,55 @@ fn format_integer_type(it: rustc_abi::IntegerType) -> String { } .to_owned() } + +pub(super) fn target(sess: &rustc_session::Session) -> Target { + // Build a set of which features are enabled on this target + let globally_enabled_features: FxHashSet<&str> = + sess.unstable_target_features.iter().map(|name| name.as_str()).collect(); + + // Build a map of target feature stability by feature name + use rustc_target::target_features::Stability; + let feature_stability: FxHashMap<&str, Stability> = sess + .target + .rust_target_features() + .iter() + .copied() + .map(|(name, stability, _)| (name, stability)) + .collect(); + + Target { + triple: sess.opts.target_triple.tuple().into(), + target_features: sess + .target + .rust_target_features() + .iter() + .copied() + .filter(|(_, stability, _)| { + // Describe only target features which the user can toggle + stability.toggle_allowed().is_ok() + }) + .map(|(name, stability, implied_features)| { + TargetFeature { + name: name.into(), + unstable_feature_gate: match stability { + Stability::Unstable(feature_gate) => Some(feature_gate.as_str().into()), + _ => None, + }, + implies_features: implied_features + .iter() + .copied() + .filter(|name| { + // Imply only target features which the user can toggle + feature_stability + .get(name) + .map(|stability| stability.toggle_allowed().is_ok()) + .unwrap_or(false) + }) + .map(String::from) + .collect(), + globally_enabled: globally_enabled_features.contains(name), + } + }) + .collect(), + } +} diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index b724d7e866a05..b020e3d924a46 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -14,7 +14,6 @@ use std::io::{BufWriter, Write, stdout}; use std::path::PathBuf; use std::rc::Rc; -use rustc_data_structures::fx::FxHashSet; use rustc_hir::def_id::{DefId, DefIdSet}; use rustc_middle::ty::TyCtxt; use rustc_session::Session; @@ -123,58 +122,6 @@ impl<'tcx> JsonRenderer<'tcx> { } } -fn target(sess: &rustc_session::Session) -> types::Target { - // Build a set of which features are enabled on this target - let globally_enabled_features: FxHashSet<&str> = - sess.unstable_target_features.iter().map(|name| name.as_str()).collect(); - - // Build a map of target feature stability by feature name - use rustc_target::target_features::Stability; - let feature_stability: FxHashMap<&str, Stability> = sess - .target - .rust_target_features() - .iter() - .copied() - .map(|(name, stability, _)| (name, stability)) - .collect(); - - types::Target { - triple: sess.opts.target_triple.tuple().into(), - target_features: sess - .target - .rust_target_features() - .iter() - .copied() - .filter(|(_, stability, _)| { - // Describe only target features which the user can toggle - stability.toggle_allowed().is_ok() - }) - .map(|(name, stability, implied_features)| { - types::TargetFeature { - name: name.into(), - unstable_feature_gate: match stability { - Stability::Unstable(feature_gate) => Some(feature_gate.as_str().into()), - _ => None, - }, - implies_features: implied_features - .iter() - .copied() - .filter(|name| { - // Imply only target features which the user can toggle - feature_stability - .get(name) - .map(|stability| stability.toggle_allowed().is_ok()) - .unwrap_or(false) - }) - .map(String::from) - .collect(), - globally_enabled: globally_enabled_features.contains(name), - } - }) - .collect(), - } -} - impl<'tcx> JsonRenderer<'tcx> { pub(crate) fn init( krate: clean::Crate, @@ -317,7 +264,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { // multiple targets: https://github.com/rust-lang/rust/pull/137632 // // We want to describe a single target, so pass tcx.sess rather than tcx. - let target = target(self.tcx.sess); + let target = conversions::target(self.tcx.sess); debug!("Constructing Output"); let output_crate = types::Crate { diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index d09949e6868d6..8af197212f8bd 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -1215,7 +1215,6 @@ impl LinkCollector<'_, '_> { || !did.is_local() } - #[allow(rustc::potential_query_instability)] pub(crate) fn resolve_ambiguities(&mut self) { let mut ambiguous_links = mem::take(&mut self.ambiguous_links); for ((item_id, path_str), info_items) in ambiguous_links.iter_mut() { diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 304ae00b01a92..a4f8e9ccaab99 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -715,7 +715,7 @@ impl<'tcx> MiriMachine<'tcx> { match target.arch { Arch::Wasm32 | Arch::Wasm64 => 64 * 1024, // https://webassembly.github.io/spec/core/exec/runtime.html#memory-instances Arch::AArch64 => { - if target.options.vendor.as_ref() == "apple" { + if target.is_like_darwin { // No "definitive" source, but see: // https://www.wwdcnotes.com/notes/wwdc20/10214/ // https://github.com/ziglang/zig/issues/11308 etc. diff --git a/tests/run-make/rustdoc-test-builder/builder.rs b/tests/run-make/rustdoc-test-builder/builder.rs new file mode 100644 index 0000000000000..b5a2c8ae346ea --- /dev/null +++ b/tests/run-make/rustdoc-test-builder/builder.rs @@ -0,0 +1,23 @@ +use std::ffi::OsString; +use std::path::PathBuf; +use std::process::{self, Command}; +use std::{env, fs}; + +fn main() { + let args: Vec = env::args_os().collect(); + let log_path = env::var_os("BUILDER_LOG").map(PathBuf::from).expect("BUILDER_LOG must be set"); + let real_rustc = env::var_os("REAL_RUSTC").expect("REAL_RUSTC must be set"); + + let log_contents = + args.iter().skip(1).map(|arg| arg.to_string_lossy()).collect::>().join("\n"); + fs::write(&log_path, log_contents).expect("failed to write builder log"); + + let status = Command::new(real_rustc) + .args(args.iter().skip(1)) + .status() + .expect("failed to invoke real rustc"); + + if !status.success() { + process::exit(status.code().unwrap_or(1)); + } +} diff --git a/tests/run-make/rustdoc-test-builder/doctest.rs b/tests/run-make/rustdoc-test-builder/doctest.rs new file mode 100644 index 0000000000000..1a4ff6a2fdd76 --- /dev/null +++ b/tests/run-make/rustdoc-test-builder/doctest.rs @@ -0,0 +1,3 @@ +//! ```rust +//! assert_eq!(2 + 2, 4); +//! ``` diff --git a/tests/run-make/rustdoc-test-builder/rmake.rs b/tests/run-make/rustdoc-test-builder/rmake.rs index 9aa8143dc1dc4..d10a3c92cae42 100644 --- a/tests/run-make/rustdoc-test-builder/rmake.rs +++ b/tests/run-make/rustdoc-test-builder/rmake.rs @@ -1,11 +1,14 @@ -// This test ensures that if the rustdoc test binary is not executable, it will -// gracefully fail and not panic. +// This test validates the `--test-builder` rustdoc option. +// It ensures that: +// 1. When the test-builder path points to a non-executable file, rustdoc gracefully fails +// 2. When the test-builder path points to a valid executable, it receives rustc arguments //@ needs-target-std -use run_make_support::{path, rfs, rustdoc}; +use run_make_support::{bare_rustc, path, rfs, rustc_path, rustdoc, target}; fn main() { + // Test 1: Verify that a non-executable test-builder fails gracefully let absolute_path = path("foo.rs").canonicalize().expect("failed to get absolute path"); let output = rustdoc() .input("foo.rs") @@ -19,4 +22,37 @@ fn main() { output.assert_stdout_contains("Failed to spawn "); // ... and that we didn't panic. output.assert_not_ice(); + + // Some targets (for example wasm) cannot execute doctests directly even with a runner, + // so only exercise the success path when the target can run on the host. + if target().contains("wasm") || std::env::var_os("REMOTE_TEST_CLIENT").is_some() { + return; + } + + // Test 2: Verify that a valid test-builder is invoked with correct arguments + // Build a custom test-builder that logs its arguments and forwards to rustc. + // Use `bare_rustc` so we compile for the host architecture even in cross builds. + let builder_bin = path("builder-bin"); + bare_rustc().input("builder.rs").output(&builder_bin).run(); + + let log_path = path("builder.log"); + let _ = std::fs::remove_file(&log_path); + + // Run rustdoc with our custom test-builder + rustdoc() + .input("doctest.rs") + .arg("--test") + .arg("-Zunstable-options") + .arg("--test-builder") + .arg(&builder_bin) + .env("REAL_RUSTC", rustc_path()) + .env("BUILDER_LOG", &log_path) + .run(); + + // Verify the custom builder was invoked with rustc-style arguments + let log_contents = rfs::read_to_string(&log_path); + assert!( + log_contents.contains("--crate-type"), + "expected builder to receive rustc arguments, got:\n{log_contents}" + ); } diff --git a/tests/rustdoc/jump-to-def-assoc-items.rs b/tests/rustdoc/jump-to-def/assoc-items.rs similarity index 95% rename from tests/rustdoc/jump-to-def-assoc-items.rs rename to tests/rustdoc/jump-to-def/assoc-items.rs index 0dfe3c7bdc155..01beb8dd7618a 100644 --- a/tests/rustdoc/jump-to-def-assoc-items.rs +++ b/tests/rustdoc/jump-to-def/assoc-items.rs @@ -4,7 +4,7 @@ #![crate_name = "foo"] -//@ has 'src/foo/jump-to-def-assoc-items.rs.html' +//@ has 'src/foo/assoc-items.rs.html' pub trait Trait { type T; diff --git a/tests/rustdoc/jump-to-def-ice-assoc-types.rs b/tests/rustdoc/jump-to-def/assoc-types.rs similarity index 85% rename from tests/rustdoc/jump-to-def-ice-assoc-types.rs rename to tests/rustdoc/jump-to-def/assoc-types.rs index 9915c53668f0d..f430eaf16389a 100644 --- a/tests/rustdoc/jump-to-def-ice-assoc-types.rs +++ b/tests/rustdoc/jump-to-def/assoc-types.rs @@ -5,7 +5,7 @@ #![crate_name = "foo"] -//@ has 'src/foo/jump-to-def-ice-assoc-types.rs.html' +//@ has 'src/foo/assoc-types.rs.html' pub trait Trait { type Node; diff --git a/tests/rustdoc/jump-to-def/auxiliary/jump-to-def-macro.rs b/tests/rustdoc/jump-to-def/auxiliary/symbols.rs similarity index 100% rename from tests/rustdoc/jump-to-def/auxiliary/jump-to-def-macro.rs rename to tests/rustdoc/jump-to-def/auxiliary/symbols.rs diff --git a/tests/rustdoc/jump-to-def/jump-to-def-doc-links-calls.rs b/tests/rustdoc/jump-to-def/doc-links-calls.rs similarity index 90% rename from tests/rustdoc/jump-to-def/jump-to-def-doc-links-calls.rs rename to tests/rustdoc/jump-to-def/doc-links-calls.rs index 55e59f23b6f28..05a5051a762ef 100644 --- a/tests/rustdoc/jump-to-def/jump-to-def-doc-links-calls.rs +++ b/tests/rustdoc/jump-to-def/doc-links-calls.rs @@ -2,7 +2,7 @@ #![crate_name = "foo"] -//@ has 'src/foo/jump-to-def-doc-links-calls.rs.html' +//@ has 'src/foo/doc-links-calls.rs.html' //@ has - '//a[@href="../../foo/struct.Bar.html"]' 'Bar' pub struct Bar; diff --git a/tests/rustdoc/jump-to-def/jump-to-def-doc-links.rs b/tests/rustdoc/jump-to-def/doc-links.rs similarity index 95% rename from tests/rustdoc/jump-to-def/jump-to-def-doc-links.rs rename to tests/rustdoc/jump-to-def/doc-links.rs index 2abb52e0a009f..f1c5c50663822 100644 --- a/tests/rustdoc/jump-to-def/jump-to-def-doc-links.rs +++ b/tests/rustdoc/jump-to-def/doc-links.rs @@ -2,7 +2,7 @@ #![crate_name = "foo"] -//@ has 'src/foo/jump-to-def-doc-links.rs.html' +//@ has 'src/foo/doc-links.rs.html' //@ has - '//a[@href="../../foo/struct.Bar.html"]' 'Bar' //@ has - '//a[@href="../../foo/struct.Foo.html"]' 'Foo' diff --git a/tests/rustdoc/jump-to-def/jump-to-def-macro.rs b/tests/rustdoc/jump-to-def/jump-to-def-macro.rs deleted file mode 100644 index 680477937c678..0000000000000 --- a/tests/rustdoc/jump-to-def/jump-to-def-macro.rs +++ /dev/null @@ -1,15 +0,0 @@ -//@ aux-build:jump-to-def-macro.rs -//@ build-aux-docs -//@ compile-flags: -Zunstable-options --generate-link-to-definition - -#![crate_name = "foo"] - -//@ has 'src/foo/jump-to-def-macro.rs.html' - -#[macro_use] -extern crate jump_to_def_macro; - -//@ has - '//a[@href="../../jump_to_def_macro/macro.symbols.html"]' 'symbols!' -symbols! { - A = 12 -} diff --git a/tests/rustdoc/jump-to-def/macro.rs b/tests/rustdoc/jump-to-def/macro.rs new file mode 100644 index 0000000000000..fcf0c7f570d44 --- /dev/null +++ b/tests/rustdoc/jump-to-def/macro.rs @@ -0,0 +1,15 @@ +//@ aux-build:symbols.rs +//@ build-aux-docs +//@ compile-flags: -Zunstable-options --generate-link-to-definition + +#![crate_name = "foo"] + +//@ has 'src/foo/macro.rs.html' + +#[macro_use] +extern crate symbols; + +//@ has - '//a[@href="../../symbols/macro.symbols.html"]' 'symbols!' +symbols! { + A = 12 +} diff --git a/tests/rustdoc/jump-to-def-ice.rs b/tests/rustdoc/jump-to-def/no-body-items.rs similarity index 89% rename from tests/rustdoc/jump-to-def-ice.rs rename to tests/rustdoc/jump-to-def/no-body-items.rs index 5578b9af3d74f..e74640072146e 100644 --- a/tests/rustdoc/jump-to-def-ice.rs +++ b/tests/rustdoc/jump-to-def/no-body-items.rs @@ -5,7 +5,7 @@ #![crate_name = "foo"] -//@ has 'src/foo/jump-to-def-ice.rs.html' +//@ has 'src/foo/no-body-items.rs.html' pub trait A { type T; diff --git a/tests/rustdoc/jump-to-def/jump-to-non-local-method.rs b/tests/rustdoc/jump-to-def/non-local-method.rs similarity index 96% rename from tests/rustdoc/jump-to-def/jump-to-non-local-method.rs rename to tests/rustdoc/jump-to-def/non-local-method.rs index 1d6d6b8d18faa..c601f3259c4da 100644 --- a/tests/rustdoc/jump-to-def/jump-to-non-local-method.rs +++ b/tests/rustdoc/jump-to-def/non-local-method.rs @@ -2,7 +2,7 @@ #![crate_name = "foo"] -//@ has 'src/foo/jump-to-non-local-method.rs.html' +//@ has 'src/foo/non-local-method.rs.html' //@ has - '//a[@href="{{channel}}/core/sync/atomic/struct.AtomicIsize.html"]' 'std::sync::atomic::AtomicIsize' use std::sync::atomic::AtomicIsize; diff --git a/tests/rustdoc/jump-to-def/jump-to-def-pats.rs b/tests/rustdoc/jump-to-def/patterns.rs similarity index 96% rename from tests/rustdoc/jump-to-def/jump-to-def-pats.rs rename to tests/rustdoc/jump-to-def/patterns.rs index 852eba208db01..e6b354eacd126 100644 --- a/tests/rustdoc/jump-to-def/jump-to-def-pats.rs +++ b/tests/rustdoc/jump-to-def/patterns.rs @@ -4,7 +4,7 @@ #![crate_name = "foo"] -//@ has 'src/foo/jump-to-def-pats.rs.html' +//@ has 'src/foo/patterns.rs.html' use std::fmt; diff --git a/tests/rustdoc/jump-to-def/jump-to-def-prelude-types.rs b/tests/rustdoc/jump-to-def/prelude-types.rs similarity index 94% rename from tests/rustdoc/jump-to-def/jump-to-def-prelude-types.rs rename to tests/rustdoc/jump-to-def/prelude-types.rs index 43617b1bc9df7..2476d18e0b629 100644 --- a/tests/rustdoc/jump-to-def/jump-to-def-prelude-types.rs +++ b/tests/rustdoc/jump-to-def/prelude-types.rs @@ -4,7 +4,7 @@ #![crate_name = "foo"] -//@ has 'src/foo/jump-to-def-prelude-types.rs.html' +//@ has 'src/foo/prelude-types.rs.html' // FIXME: would be nice to be able to check both the class and the href at the same time so // we could check the text as well... //@ has - '//a[@class="prelude-ty"]/@href' '{{channel}}/core/result/enum.Result.html' diff --git a/tests/ui/attributes/malformed-fn-align.rs b/tests/ui/attributes/malformed-fn-align.rs index c76eda65a75b0..219218f034793 100644 --- a/tests/ui/attributes/malformed-fn-align.rs +++ b/tests/ui/attributes/malformed-fn-align.rs @@ -26,7 +26,7 @@ fn f3() {} #[repr(align(16))] //~ ERROR `#[repr(align(...))]` is not supported on functions fn f4() {} -#[rustc_align(-1)] //~ ERROR expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `-` +#[rustc_align(-1)] //~ ERROR expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found fn f5() {} #[rustc_align(3)] //~ ERROR invalid alignment value: not a power of two diff --git a/tests/ui/attributes/malformed-fn-align.stderr b/tests/ui/attributes/malformed-fn-align.stderr index 33f789b626952..b419df8ea2d18 100644 --- a/tests/ui/attributes/malformed-fn-align.stderr +++ b/tests/ui/attributes/malformed-fn-align.stderr @@ -37,11 +37,11 @@ error[E0589]: invalid alignment value: not a power of two LL | #[rustc_align(0)] | ^ -error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `-` +error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found expression --> $DIR/malformed-fn-align.rs:29:15 | LL | #[rustc_align(-1)] - | ^ + | ^^ expressions are not allowed here | help: negative numbers are not literals, try removing the `-` sign | diff --git a/tests/ui/attributes/proc-macro-unsafe.rs b/tests/ui/attributes/proc-macro-unsafe.rs new file mode 100644 index 0000000000000..7849df8256098 --- /dev/null +++ b/tests/ui/attributes/proc-macro-unsafe.rs @@ -0,0 +1,9 @@ +//@ proc-macro: external-macro-use.rs + +extern crate external_macro_use; + +#[unsafe(external_macro_use::a)] +//~^ ERROR unnecessary `unsafe` on safe attribute +fn f() {} + +fn main() {} diff --git a/tests/ui/attributes/proc-macro-unsafe.stderr b/tests/ui/attributes/proc-macro-unsafe.stderr new file mode 100644 index 0000000000000..ccc19bb01d2fe --- /dev/null +++ b/tests/ui/attributes/proc-macro-unsafe.stderr @@ -0,0 +1,8 @@ +error: unnecessary `unsafe` on safe attribute + --> $DIR/proc-macro-unsafe.rs:5:3 + | +LL | #[unsafe(external_macro_use::a)] + | ^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/attributes/unsafe/double-unsafe-attributes.rs b/tests/ui/attributes/unsafe/double-unsafe-attributes.rs index c0181d960539c..894d1327da799 100644 --- a/tests/ui/attributes/unsafe/double-unsafe-attributes.rs +++ b/tests/ui/attributes/unsafe/double-unsafe-attributes.rs @@ -1,7 +1,7 @@ #[unsafe(unsafe(no_mangle))] //~^ ERROR expected identifier, found keyword `unsafe` //~| ERROR cannot find attribute `r#unsafe` in this scope -//~| ERROR unnecessary `unsafe` +//~| ERROR `r#unsafe` is not an unsafe attribute fn a() {} fn main() {} diff --git a/tests/ui/attributes/unsafe/double-unsafe-attributes.stderr b/tests/ui/attributes/unsafe/double-unsafe-attributes.stderr index 846800daa5465..0825cf794083d 100644 --- a/tests/ui/attributes/unsafe/double-unsafe-attributes.stderr +++ b/tests/ui/attributes/unsafe/double-unsafe-attributes.stderr @@ -9,11 +9,13 @@ help: escape `unsafe` to use it as an identifier LL | #[unsafe(r#unsafe(no_mangle))] | ++ -error: unnecessary `unsafe` on safe attribute +error: `r#unsafe` is not an unsafe attribute --> $DIR/double-unsafe-attributes.rs:1:3 | LL | #[unsafe(unsafe(no_mangle))] - | ^^^^^^ + | ^^^^^^ this is not an unsafe attribute + | + = note: extraneous unsafe is not allowed in attributes error: cannot find attribute `r#unsafe` in this scope --> $DIR/double-unsafe-attributes.rs:1:10 diff --git a/tests/ui/attributes/unsafe/unsafe-safe-attribute_diagnostic.rs b/tests/ui/attributes/unsafe/unsafe-safe-attribute_diagnostic.rs index d9054248a292c..b74dffe9eb185 100644 --- a/tests/ui/attributes/unsafe/unsafe-safe-attribute_diagnostic.rs +++ b/tests/ui/attributes/unsafe/unsafe-safe-attribute_diagnostic.rs @@ -1,4 +1,4 @@ -#[unsafe(diagnostic::on_unimplemented( //~ ERROR: unnecessary `unsafe` +#[unsafe(diagnostic::on_unimplemented( //~ ERROR: `diagnostic::on_unimplemented` is not an unsafe attribute message = "testing", ))] trait Foo {} diff --git a/tests/ui/attributes/unsafe/unsafe-safe-attribute_diagnostic.stderr b/tests/ui/attributes/unsafe/unsafe-safe-attribute_diagnostic.stderr index a7662f5ee6c7d..3bc291db5acf8 100644 --- a/tests/ui/attributes/unsafe/unsafe-safe-attribute_diagnostic.stderr +++ b/tests/ui/attributes/unsafe/unsafe-safe-attribute_diagnostic.stderr @@ -1,8 +1,10 @@ -error: unnecessary `unsafe` on safe attribute +error: `diagnostic::on_unimplemented` is not an unsafe attribute --> $DIR/unsafe-safe-attribute_diagnostic.rs:1:3 | LL | #[unsafe(diagnostic::on_unimplemented( - | ^^^^^^ + | ^^^^^^ this is not an unsafe attribute + | + = note: extraneous unsafe is not allowed in attributes error: aborting due to 1 previous error diff --git a/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs b/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs index 378d0a3e72358..cdf2b76a1cccc 100644 --- a/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs +++ b/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs @@ -7,5 +7,5 @@ fn main() { } #[deprecated(note = test)] -//~^ ERROR expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `test` +//~^ ERROR expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found fn foo() {} diff --git a/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr b/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr index cd985ab5a1824..379c7f5812240 100644 --- a/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr +++ b/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr @@ -1,8 +1,8 @@ -error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `test` +error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found expression --> $DIR/issue-66340-deprecated-attr-non-meta-grammar.rs:9:21 | LL | #[deprecated(note = test)] - | ^^^^ + | ^^^^ expressions are not allowed here | help: surround the identifier with quotation marks to make it into a string literal | diff --git a/tests/ui/impl-trait/in-trait/missing-static-bound-from-impl.stderr b/tests/ui/impl-trait/in-trait/missing-static-bound-from-impl.stderr index 1f787c1842cf9..d854a457485dd 100644 --- a/tests/ui/impl-trait/in-trait/missing-static-bound-from-impl.stderr +++ b/tests/ui/impl-trait/in-trait/missing-static-bound-from-impl.stderr @@ -1,6 +1,8 @@ error[E0310]: the associated type `impl Fn()` may not live long enough --> $DIR/missing-static-bound-from-impl.rs:11:9 | +LL | fn f(&self) -> Box { + | -------- this `dyn Trait` has an implicit `'static` lifetime bound LL | Box::new(::f()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | diff --git a/tests/ui/imports/same-prefix-unresolved-import-148070.rs b/tests/ui/imports/same-prefix-unresolved-import-148070.rs new file mode 100644 index 0000000000000..e9d991aa0376e --- /dev/null +++ b/tests/ui/imports/same-prefix-unresolved-import-148070.rs @@ -0,0 +1,5 @@ +// https://github.com/rust-lang/rust/issues/148070 +#![no_main] +use stat; //~ ERROR unresolved import `stat` +use str; //~ ERROR unresolved import `str` +use sync; //~ ERROR unresolved import `sync` diff --git a/tests/ui/imports/same-prefix-unresolved-import-148070.stderr b/tests/ui/imports/same-prefix-unresolved-import-148070.stderr new file mode 100644 index 0000000000000..e4a2b060fa435 --- /dev/null +++ b/tests/ui/imports/same-prefix-unresolved-import-148070.stderr @@ -0,0 +1,43 @@ +error[E0432]: unresolved import `stat` + --> $DIR/same-prefix-unresolved-import-148070.rs:3:5 + | +LL | use stat; + | ^^^^ no `stat` in the root + | +help: consider importing this struct instead + | +LL | use std::os::linux::raw::stat; + | +++++++++++++++++++++ + +error[E0432]: unresolved import `str` + --> $DIR/same-prefix-unresolved-import-148070.rs:4:5 + | +LL | use str; + | ^^^ no `str` in the root + | +help: a similar name exists in the module + | +LL - use str; +LL + use std; + | +help: consider importing one of these items instead + | +LL | use std::primitive::str; + | ++++++++++++++++ +LL | use std::str; + | +++++ + +error[E0432]: unresolved import `sync` + --> $DIR/same-prefix-unresolved-import-148070.rs:5:5 + | +LL | use sync; + | ^^^^ no `sync` in the root + | +help: consider importing this module instead + | +LL | use std::sync; + | +++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/macros/cfg_select.rs b/tests/ui/macros/cfg_select.rs index 9241141ef9a6c..2a627cc05b93b 100644 --- a/tests/ui/macros/cfg_select.rs +++ b/tests/ui/macros/cfg_select.rs @@ -60,3 +60,38 @@ cfg_select! { cfg_select! {} //~^ ERROR none of the predicates in this `cfg_select` evaluated to true + +cfg_select! { + => {} + //~^ ERROR expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `=>` +} + +cfg_select! { + () => {} + //~^ ERROR expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `(` +} + +cfg_select! { + "str" => {} + //~^ ERROR malformed `cfg_select` macro input [E0539] +} + +cfg_select! { + a::b => {} + //~^ ERROR malformed `cfg_select` macro input [E0539] +} + +cfg_select! { + a() => {} + //~^ ERROR invalid predicate `a` [E0537] +} + +cfg_select! { + a + 1 => {} + //~^ ERROR expected one of `(`, `::`, `=>`, or `=`, found `+` +} + +cfg_select! { + cfg!() => {} + //~^ ERROR expected one of `(`, `::`, `=>`, or `=`, found `!` +} diff --git a/tests/ui/macros/cfg_select.stderr b/tests/ui/macros/cfg_select.stderr index 7280f35c16f93..3a5d2b0a1e1ee 100644 --- a/tests/ui/macros/cfg_select.stderr +++ b/tests/ui/macros/cfg_select.stderr @@ -21,5 +21,51 @@ error: none of the predicates in this `cfg_select` evaluated to true LL | cfg_select! {} | ^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors; 1 warning emitted +error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `=>` + --> $DIR/cfg_select.rs:65:5 + | +LL | => {} + | ^^ + +error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `(` + --> $DIR/cfg_select.rs:70:5 + | +LL | () => {} + | ^ + +error[E0539]: malformed `cfg_select` macro input + --> $DIR/cfg_select.rs:75:5 + | +LL | "str" => {} + | ^^^^^ expected a valid identifier here + | + +error[E0539]: malformed `cfg_select` macro input + --> $DIR/cfg_select.rs:80:5 + | +LL | a::b => {} + | ^^^^ expected a valid identifier here + | + +error[E0537]: invalid predicate `a` + --> $DIR/cfg_select.rs:85:5 + | +LL | a() => {} + | ^^^ + +error: expected one of `(`, `::`, `=>`, or `=`, found `+` + --> $DIR/cfg_select.rs:90:7 + | +LL | a + 1 => {} + | ^ expected one of `(`, `::`, `=>`, or `=` + +error: expected one of `(`, `::`, `=>`, or `=`, found `!` + --> $DIR/cfg_select.rs:95:8 + | +LL | cfg!() => {} + | ^ expected one of `(`, `::`, `=>`, or `=` + +error: aborting due to 9 previous errors; 1 warning emitted +Some errors have detailed explanations: E0537, E0539. +For more information about an error, try `rustc --explain E0537`. diff --git a/tests/ui/parser/attribute/attr-bad-meta-4.rs b/tests/ui/parser/attribute/attr-bad-meta-4.rs index 606b41e89a5f5..bfd2958ad5659 100644 --- a/tests/ui/parser/attribute/attr-bad-meta-4.rs +++ b/tests/ui/parser/attribute/attr-bad-meta-4.rs @@ -9,7 +9,7 @@ macro_rules! mac { mac!(an(arbitrary token stream)); #[cfg(feature = -1)] -//~^ ERROR expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `-` +//~^ ERROR expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found fn handler() {} fn main() {} diff --git a/tests/ui/parser/attribute/attr-bad-meta-4.stderr b/tests/ui/parser/attribute/attr-bad-meta-4.stderr index 1d939942fb9a9..8f4edca226d3b 100644 --- a/tests/ui/parser/attribute/attr-bad-meta-4.stderr +++ b/tests/ui/parser/attribute/attr-bad-meta-4.stderr @@ -1,8 +1,8 @@ -error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `-` +error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found expression --> $DIR/attr-bad-meta-4.rs:11:17 | LL | #[cfg(feature = -1)] - | ^ + | ^^ expressions are not allowed here | help: negative numbers are not literals, try removing the `-` sign | diff --git a/tests/ui/parser/attribute/attr-unquoted-ident.rs b/tests/ui/parser/attribute/attr-unquoted-ident.rs index 8a0c65b783a74..152448bf8a0f9 100644 --- a/tests/ui/parser/attribute/attr-unquoted-ident.rs +++ b/tests/ui/parser/attribute/attr-unquoted-ident.rs @@ -4,14 +4,21 @@ fn main() { #[cfg(key=foo)] - //~^ ERROR expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `foo` - //~| HELP surround the identifier with quotation marks to make it into a string literal + //~^ ERROR: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found + //~| HELP: surround the identifier with quotation marks to make it into a string literal + //~| NOTE: expressions are not allowed here println!(); #[cfg(key="bar")] println!(); #[cfg(key=foo bar baz)] - //~^ ERROR expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `foo` - //~| HELP surround the identifier with quotation marks to make it into a string literal + //~^ ERROR: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found + //~| HELP: surround the identifier with quotation marks to make it into a string literal + //~| NOTE: expressions are not allowed here + println!(); + #[cfg(key=foo 1 bar 2.0 baz.)] + //~^ ERROR: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found + //~| HELP: surround the identifier with quotation marks to make it into a string literal + //~| NOTE: expressions are not allowed here println!(); } @@ -19,7 +26,7 @@ fn main() { macro_rules! make { ($name:ident) => { #[doc(alias = $name)] pub struct S; } - //~^ ERROR expected unsuffixed literal, found identifier `nickname` + //~^ ERROR: expected unsuffixed literal, found identifier `nickname` } -make!(nickname); //~ NOTE in this expansion +make!(nickname); //~ NOTE: in this expansion diff --git a/tests/ui/parser/attribute/attr-unquoted-ident.stderr b/tests/ui/parser/attribute/attr-unquoted-ident.stderr index 8a2785280adc3..f1af60dec9bbb 100644 --- a/tests/ui/parser/attribute/attr-unquoted-ident.stderr +++ b/tests/ui/parser/attribute/attr-unquoted-ident.stderr @@ -1,27 +1,38 @@ -error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `foo` +error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found expression --> $DIR/attr-unquoted-ident.rs:6:15 | LL | #[cfg(key=foo)] - | ^^^ + | ^^^ expressions are not allowed here | help: surround the identifier with quotation marks to make it into a string literal | LL | #[cfg(key="foo")] | + + -error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `foo` - --> $DIR/attr-unquoted-ident.rs:12:15 +error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found expression + --> $DIR/attr-unquoted-ident.rs:13:15 | LL | #[cfg(key=foo bar baz)] - | ^^^ + | ^^^ expressions are not allowed here | help: surround the identifier with quotation marks to make it into a string literal | LL | #[cfg(key="foo bar baz")] | + + +error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found expression + --> $DIR/attr-unquoted-ident.rs:18:15 + | +LL | #[cfg(key=foo 1 bar 2.0 baz.)] + | ^^^ expressions are not allowed here + | +help: surround the identifier with quotation marks to make it into a string literal + | +LL | #[cfg(key="foo 1 bar 2.0 baz.")] + | + + + error: expected unsuffixed literal, found identifier `nickname` - --> $DIR/attr-unquoted-ident.rs:21:38 + --> $DIR/attr-unquoted-ident.rs:28:38 | LL | ($name:ident) => { #[doc(alias = $name)] pub struct S; } | ^^^^^ @@ -31,5 +42,5 @@ LL | make!(nickname); | = note: this error originates in the macro `make` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors diff --git a/tests/ui/parser/macro/expr-in-attribute.rs b/tests/ui/parser/macro/expr-in-attribute.rs new file mode 100644 index 0000000000000..8c8934493361b --- /dev/null +++ b/tests/ui/parser/macro/expr-in-attribute.rs @@ -0,0 +1,9 @@ +// Test for #146325. +// Ensure that when we encounter an expr invocation in an attribute, we don't suggest nonsense. + +#[deprecated(note = a!=b)] +struct X; +//~^^ ERROR: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found expression +//~| NOTE: expressions are not allowed here + +fn main() {} diff --git a/tests/ui/parser/macro/expr-in-attribute.stderr b/tests/ui/parser/macro/expr-in-attribute.stderr new file mode 100644 index 0000000000000..08d6f12d1e641 --- /dev/null +++ b/tests/ui/parser/macro/expr-in-attribute.stderr @@ -0,0 +1,8 @@ +error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found expression + --> $DIR/expr-in-attribute.rs:4:21 + | +LL | #[deprecated(note = a!=b)] + | ^^^^ expressions are not allowed here + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/macro/macro-in-attribute.rs b/tests/ui/parser/macro/macro-in-attribute.rs new file mode 100644 index 0000000000000..7a4b3b22baa91 --- /dev/null +++ b/tests/ui/parser/macro/macro-in-attribute.rs @@ -0,0 +1,9 @@ +// Test for #146325. +// Ensure that when we encounter a macro invocation in an attribute, we don't suggest nonsense. + +#[deprecated(note = concat!("a", "b"))] +struct X; +//~^^ ERROR: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found +//~| NOTE: macro calls are not allowed here + +fn main() {} diff --git a/tests/ui/parser/macro/macro-in-attribute.stderr b/tests/ui/parser/macro/macro-in-attribute.stderr new file mode 100644 index 0000000000000..d057c93ede073 --- /dev/null +++ b/tests/ui/parser/macro/macro-in-attribute.stderr @@ -0,0 +1,8 @@ +error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found macro call + --> $DIR/macro-in-attribute.rs:4:21 + | +LL | #[deprecated(note = concat!("a", "b"))] + | ^^^^^^^^^^^^^^^^^ macro calls are not allowed here + +error: aborting due to 1 previous error + diff --git a/tests/ui/suggestions/lifetimes/implicit-static-lifetime-in-dyn-trait-return-type.rs b/tests/ui/suggestions/lifetimes/implicit-static-lifetime-in-dyn-trait-return-type.rs new file mode 100644 index 0000000000000..428033b53065b --- /dev/null +++ b/tests/ui/suggestions/lifetimes/implicit-static-lifetime-in-dyn-trait-return-type.rs @@ -0,0 +1,35 @@ +// #41966 +trait Foo {} + +struct Bar(R); + +impl Foo for Bar { +} + +fn bb(r: R) -> Box { + Box::new(Bar(r)) //~ ERROR the parameter type `R` may not live long enough +} + +fn cc(r: R) -> Box { //~ ERROR missing lifetime specifier + Box::new(Bar(r)) +} + +// #54753 +pub struct Qux(T); + +pub struct Bazzzz(T); + +pub trait Baz {} +impl Baz for Bazzzz {} + +impl Qux { + fn baz(self) -> Box { + Box::new(Bazzzz(self.0)) //~ ERROR the parameter type `T` may not live long enough + } +} + +fn main() { + let a = 10; + let _b = bb(&a); + let _c = cc(&a); +} diff --git a/tests/ui/suggestions/lifetimes/implicit-static-lifetime-in-dyn-trait-return-type.stderr b/tests/ui/suggestions/lifetimes/implicit-static-lifetime-in-dyn-trait-return-type.stderr new file mode 100644 index 0000000000000..c8122dce19542 --- /dev/null +++ b/tests/ui/suggestions/lifetimes/implicit-static-lifetime-in-dyn-trait-return-type.stderr @@ -0,0 +1,53 @@ +error[E0106]: missing lifetime specifier + --> $DIR/implicit-static-lifetime-in-dyn-trait-return-type.rs:13:33 + | +LL | fn cc(r: R) -> Box { + | ^^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`, or if you will only have owned values + | +LL - fn cc(r: R) -> Box { +LL + fn cc(r: R) -> Box { + | +help: instead, you are more likely to want to change the argument to be borrowed + | +LL | fn cc(r: &R) -> Box { + | + + +error[E0310]: the parameter type `R` may not live long enough + --> $DIR/implicit-static-lifetime-in-dyn-trait-return-type.rs:10:5 + | +LL | fn bb(r: R) -> Box { + | ------- this `dyn Trait` has an implicit `'static` lifetime bound +LL | Box::new(Bar(r)) + | ^^^^^^^^^^^^^^^^ + | | + | the parameter type `R` must be valid for the static lifetime... + | ...so that the type `R` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound + | +LL | fn bb(r: R) -> Box { + | +++++++++ + +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/implicit-static-lifetime-in-dyn-trait-return-type.rs:27:9 + | +LL | fn baz(self) -> Box { + | ------- this `dyn Trait` has an implicit `'static` lifetime bound +LL | Box::new(Bazzzz(self.0)) + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound + | +LL | impl Qux { + | +++++++++ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0106, E0310. +For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/suggestions/wrap-dyn-in-suggestion-issue-120223.stderr b/tests/ui/suggestions/wrap-dyn-in-suggestion-issue-120223.stderr index 62943616e3ad0..0c331355407de 100644 --- a/tests/ui/suggestions/wrap-dyn-in-suggestion-issue-120223.stderr +++ b/tests/ui/suggestions/wrap-dyn-in-suggestion-issue-120223.stderr @@ -38,6 +38,8 @@ LL | fn without_sized &'static (dyn std::fmt::Debug) + ?Sized>() {} error[E0310]: the parameter type `impl FnOnce(T) -> dyn Future` may not live long enough --> $DIR/wrap-dyn-in-suggestion-issue-120223.rs:6:5 | +LL | ) -> Box dyn Future> { + | ---------------------------------------- this `dyn Trait` has an implicit `'static` lifetime bound LL | Box::new(executor) | ^^^^^^^^^^^^^^^^^^ | | diff --git a/tests/ui/test-attrs/inaccessible-test-modules.stderr b/tests/ui/test-attrs/inaccessible-test-modules.stderr index c66dc0d0fc26c..dfb6985730af5 100644 --- a/tests/ui/test-attrs/inaccessible-test-modules.stderr +++ b/tests/ui/test-attrs/inaccessible-test-modules.stderr @@ -13,7 +13,7 @@ LL | use test as y; help: consider importing this module instead | LL | use test::test as y; - | ++++++ + | ++++++ error: aborting due to 2 previous errors