diff --git a/Cargo.lock b/Cargo.lock index 5feb21a65b774..218fa5a6842e0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -469,9 +469,9 @@ version = "0.1.0" [[package]] name = "cc" -version = "1.0.79" +version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" [[package]] name = "cfg-if" @@ -3970,6 +3970,7 @@ version = "0.0.0" dependencies = [ "itertools 0.11.0", "rustc_ast", + "rustc_ast_ir", "rustc_attr", "rustc_data_structures", "rustc_errors", @@ -4038,6 +4039,7 @@ dependencies = [ name = "rustc_infer" version = "0.0.0" dependencies = [ + "rustc_ast_ir", "rustc_data_structures", "rustc_errors", "rustc_fluent_macro", @@ -4570,6 +4572,7 @@ name = "rustc_span" version = "0.0.0" dependencies = [ "indexmap", + "itoa", "md-5", "rustc_arena", "rustc_data_structures", @@ -4632,6 +4635,7 @@ dependencies = [ "bitflags 2.4.2", "itertools 0.11.0", "rustc_ast", + "rustc_ast_ir", "rustc_attr", "rustc_data_structures", "rustc_errors", @@ -4670,6 +4674,7 @@ name = "rustc_transmute" version = "0.0.0" dependencies = [ "itertools 0.11.0", + "rustc_ast_ir", "rustc_data_structures", "rustc_hir", "rustc_infer", @@ -4685,6 +4690,7 @@ name = "rustc_ty_utils" version = "0.0.0" dependencies = [ "itertools 0.11.0", + "rustc_ast_ir", "rustc_data_structures", "rustc_errors", "rustc_fluent_macro", diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index 28e148bddb220..1c6d0495ecfa1 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -1,6 +1,9 @@ +use std::borrow::{Borrow, Cow}; +use std::cmp; use std::fmt::{self, Write}; +use std::iter; +use std::ops::Bound; use std::ops::Deref; -use std::{borrow::Borrow, cmp, iter, ops::Bound}; use rustc_index::Idx; use tracing::debug; @@ -32,7 +35,7 @@ where pub trait LayoutCalculator { type TargetDataLayoutRef: Borrow; - fn delayed_bug(&self, txt: String); + fn delayed_bug(&self, txt: impl Into>); fn current_data_layout(&self) -> Self::TargetDataLayoutRef; fn scalar_pair( diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 34529e0a086f3..4f2b9d0ef50d9 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1612,8 +1612,9 @@ pub enum PointerKind { SharedRef { frozen: bool }, /// Mutable reference. `unpin` indicates the absence of any pinned data. MutableRef { unpin: bool }, - /// Box. `unpin` indicates the absence of any pinned data. - Box { unpin: bool }, + /// Box. `unpin` indicates the absence of any pinned data. `global` indicates whether this box + /// uses the global allocator or a custom one. + Box { unpin: bool, global: bool }, } /// Note that this information is advisory only, and backends are free to ignore it. @@ -1622,6 +1623,8 @@ pub enum PointerKind { pub struct PointeeInfo { pub size: Size, pub align: Align, + /// If this is `None`, then this is a raw pointer, so size and alignment are not guaranteed to + /// be reliable. pub safe: Option, } diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 13b1a589d9ba9..d522c285e3ebe 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2302,6 +2302,9 @@ pub enum InlineAsmOperand { Sym { sym: InlineAsmSym, }, + Label { + block: P, + }, } impl InlineAsmOperand { @@ -2311,7 +2314,7 @@ impl InlineAsmOperand { | Self::Out { reg, .. } | Self::InOut { reg, .. } | Self::SplitInOut { reg, .. } => Some(reg), - Self::Const { .. } | Self::Sym { .. } => None, + Self::Const { .. } | Self::Sym { .. } | Self::Label { .. } => None, } } } diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index bbbb34f7f2f48..9ec92c9d4edfe 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1331,6 +1331,7 @@ pub fn noop_visit_inline_asm(asm: &mut InlineAsm, vis: &mut T) { } InlineAsmOperand::Const { anon_const } => vis.visit_anon_const(anon_const), InlineAsmOperand::Sym { sym } => vis.visit_inline_asm_sym(sym), + InlineAsmOperand::Label { block } => vis.visit_block(block), } } } @@ -1604,7 +1605,10 @@ pub fn noop_visit_capture_by(capture_by: &mut CaptureBy, vis: &mu } } -/// Some value for the AST node that is valid but possibly meaningless. +/// Some value for the AST node that is valid but possibly meaningless. Similar +/// to `Default` but not intended for wide use. The value will never be used +/// meaningfully, it exists just to support unwinding in `visit_clobber` in the +/// case where its closure panics. pub trait DummyAstNode { fn dummy() -> Self; } @@ -1679,19 +1683,6 @@ impl DummyAstNode for Stmt { } } -impl DummyAstNode for Block { - fn dummy() -> Self { - Block { - stmts: Default::default(), - id: DUMMY_NODE_ID, - rules: BlockCheckMode::Default, - span: Default::default(), - tokens: Default::default(), - could_be_bare_literal: Default::default(), - } - } -} - impl DummyAstNode for Crate { fn dummy() -> Self { Crate { diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index f29022386a9d3..7296e29301f35 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -15,11 +15,12 @@ use crate::ast::*; -use core::ops::ControlFlow; - use rustc_span::symbol::Ident; use rustc_span::Span; +pub use rustc_ast_ir::visit::VisitorResult; +pub use rustc_ast_ir::{try_visit, visit_opt, walk_list, walk_visitable_list}; + #[derive(Copy, Clone, Debug, PartialEq)] pub enum AssocCtxt { Trait, @@ -101,51 +102,6 @@ pub enum LifetimeCtxt { GenericArg, } -/// Similar to the `Try` trait, but also implemented for `()`. -pub trait VisitorResult { - type Residual; - fn output() -> Self; - fn from_residual(residual: Self::Residual) -> Self; - fn branch(self) -> ControlFlow; -} - -impl VisitorResult for () { - type Residual = !; - - fn output() -> Self {} - fn from_residual(_: !) -> Self {} - fn branch(self) -> ControlFlow { - ControlFlow::Continue(()) - } -} - -impl VisitorResult for ControlFlow { - type Residual = T; - - fn output() -> Self { - ControlFlow::Continue(()) - } - fn from_residual(residual: Self::Residual) -> Self { - ControlFlow::Break(residual) - } - fn branch(self) -> ControlFlow { - self - } -} - -#[macro_export] -macro_rules! try_visit { - ($e:expr) => { - match $crate::visit::VisitorResult::branch($e) { - core::ops::ControlFlow::Continue(()) => (), - #[allow(unreachable_code)] - core::ops::ControlFlow::Break(r) => { - return $crate::visit::VisitorResult::from_residual(r); - } - } - }; -} - /// Each method of the `Visitor` trait is a hook to be potentially /// overridden. Each method's default implementation recursively visits /// the substructure of the input via the corresponding `walk` method; @@ -316,24 +272,6 @@ pub trait Visitor<'ast>: Sized { } } -#[macro_export] -macro_rules! walk_list { - ($visitor: expr, $method: ident, $list: expr $(, $($extra_args: expr),* )?) => { - for elem in $list { - $crate::try_visit!($visitor.$method(elem $(, $($extra_args,)* )?)); - } - } -} - -#[macro_export] -macro_rules! visit_opt { - ($visitor: expr, $method: ident, $opt: expr $(, $($extra_args: expr),* )?) => { - if let Some(x) = $opt { - $crate::try_visit!($visitor.$method(x $(, $($extra_args,)* )?)); - } - } -} - pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) -> V::Result { walk_list!(visitor, visit_item, &krate.items); walk_list!(visitor, visit_attribute, &krate.attrs); @@ -885,6 +823,7 @@ pub fn walk_inline_asm<'a, V: Visitor<'a>>(visitor: &mut V, asm: &'a InlineAsm) try_visit!(visitor.visit_anon_const(anon_const)) } InlineAsmOperand::Sym { sym } => try_visit!(visitor.visit_inline_asm_sym(sym)), + InlineAsmOperand::Label { block } => try_visit!(visitor.visit_block(block)), } } V::Result::output() diff --git a/compiler/rustc_ast_ir/src/lib.rs b/compiler/rustc_ast_ir/src/lib.rs index 9fe1370921345..ff7a155204716 100644 --- a/compiler/rustc_ast_ir/src/lib.rs +++ b/compiler/rustc_ast_ir/src/lib.rs @@ -1,3 +1,4 @@ +#![cfg_attr(feature = "nightly", feature(never_type))] #![cfg_attr(feature = "nightly", feature(rustc_attrs))] #![cfg_attr(feature = "nightly", allow(internal_features))] @@ -5,6 +6,8 @@ #[macro_use] extern crate rustc_macros; +pub mod visit; + /// The movability of a coroutine / closure literal: /// whether a coroutine contains self-references, causing it to be `!Unpin`. #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)] diff --git a/compiler/rustc_ast_ir/src/visit.rs b/compiler/rustc_ast_ir/src/visit.rs new file mode 100644 index 0000000000000..dec9f7a47d09d --- /dev/null +++ b/compiler/rustc_ast_ir/src/visit.rs @@ -0,0 +1,82 @@ +use core::ops::ControlFlow; + +/// Similar to the `Try` trait, but also implemented for `()`. +pub trait VisitorResult { + type Residual; + fn output() -> Self; + fn from_residual(residual: Self::Residual) -> Self; + fn from_branch(b: ControlFlow) -> Self; + fn branch(self) -> ControlFlow; +} + +impl VisitorResult for () { + #[cfg(feature = "nightly")] + type Residual = !; + + #[cfg(not(feature = "nightly"))] + type Residual = core::ops::Infallible; + + fn output() -> Self {} + fn from_residual(_: Self::Residual) -> Self {} + fn from_branch(_: ControlFlow) -> Self {} + fn branch(self) -> ControlFlow { + ControlFlow::Continue(()) + } +} + +impl VisitorResult for ControlFlow { + type Residual = T; + + fn output() -> Self { + ControlFlow::Continue(()) + } + fn from_residual(residual: Self::Residual) -> Self { + ControlFlow::Break(residual) + } + fn from_branch(b: Self) -> Self { + b + } + fn branch(self) -> Self { + self + } +} + +#[macro_export] +macro_rules! try_visit { + ($e:expr) => { + match $crate::visit::VisitorResult::branch($e) { + core::ops::ControlFlow::Continue(()) => (), + #[allow(unreachable_code)] + core::ops::ControlFlow::Break(r) => { + return $crate::visit::VisitorResult::from_residual(r); + } + } + }; +} + +#[macro_export] +macro_rules! visit_opt { + ($visitor: expr, $method: ident, $opt: expr $(, $($extra_args: expr),* )?) => { + if let Some(x) = $opt { + $crate::try_visit!($visitor.$method(x $(, $($extra_args,)* )?)); + } + } +} + +#[macro_export] +macro_rules! walk_list { + ($visitor: expr, $method: ident, $list: expr $(, $($extra_args: expr),* )?) => { + for elem in $list { + $crate::try_visit!($visitor.$method(elem $(, $($extra_args,)* )?)); + } + } +} + +#[macro_export] +macro_rules! walk_visitable_list { + ($visitor: expr, $list: expr $(, $($extra_args: expr),* )?) => { + for elem in $list { + $crate::try_visit!(elem.visit_with($visitor $(, $($extra_args,)* )?)); + } + } +} diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl index e87cf05713cd3..d91d65497e1c1 100644 --- a/compiler/rustc_ast_lowering/messages.ftl +++ b/compiler/rustc_ast_lowering/messages.ftl @@ -88,6 +88,9 @@ ast_lowering_invalid_abi_suggestion = did you mean ast_lowering_invalid_asm_template_modifier_const = asm template modifiers are not allowed for `const` arguments +ast_lowering_invalid_asm_template_modifier_label = + asm template modifiers are not allowed for `label` arguments + ast_lowering_invalid_asm_template_modifier_reg_class = invalid asm template modifier for this register class diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index fd717e82d26df..cef50a70534c4 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -3,9 +3,9 @@ use crate::{ImplTraitContext, ImplTraitPosition, ParamMode, ResolverAstLoweringE use super::errors::{ AbiSpecifiedMultipleTimes, AttSyntaxOnlyX86, ClobberAbiNotSupported, InlineAsmUnsupportedTarget, InvalidAbiClobberAbi, InvalidAsmTemplateModifierConst, - InvalidAsmTemplateModifierRegClass, InvalidAsmTemplateModifierRegClassSub, - InvalidAsmTemplateModifierSym, InvalidRegister, InvalidRegisterClass, RegisterClassOnlyClobber, - RegisterConflict, + InvalidAsmTemplateModifierLabel, InvalidAsmTemplateModifierRegClass, + InvalidAsmTemplateModifierRegClassSub, InvalidAsmTemplateModifierSym, InvalidRegister, + InvalidRegisterClass, RegisterClassOnlyClobber, RegisterConflict, }; use super::LoweringContext; @@ -22,6 +22,7 @@ use std::collections::hash_map::Entry; use std::fmt::Write; impl<'a, 'hir> LoweringContext<'a, 'hir> { + #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable pub(crate) fn lower_inline_asm( &mut self, sp: Span, @@ -236,6 +237,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } } + InlineAsmOperand::Label { block } => { + if !self.tcx.features().asm_goto { + feature_err( + sess, + sym::asm_goto, + *op_sp, + "label operands for inline assembly are unstable", + ) + .emit(); + } + hir::InlineAsmOperand::Label { block: self.lower_block(block, false) } + } }; (op, self.lower_span(*op_sp)) }) @@ -295,6 +308,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { op_span: op_sp, }); } + hir::InlineAsmOperand::Label { .. } => { + self.dcx().emit_err(InvalidAsmTemplateModifierLabel { + placeholder_span, + op_span: op_sp, + }); + } } } } @@ -334,7 +353,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::SymFn { .. } - | hir::InlineAsmOperand::SymStatic { .. } => { + | hir::InlineAsmOperand::SymStatic { .. } + | hir::InlineAsmOperand::Label { .. } => { unreachable!("{op:?} is not a register operand"); } }; diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index eafbe3462bb54..76744ae62648f 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -1,5 +1,5 @@ use rustc_errors::{ - codes::*, AddToDiagnostic, Diag, DiagArgFromDisplay, EmissionGuarantee, SubdiagnosticMessageOp, + codes::*, AddToDiagnostic, Diag, DiagArgFromDisplay, EmissionGuarantee, SubdiagMessageOp, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{symbol::Ident, Span, Symbol}; @@ -41,7 +41,7 @@ pub struct InvalidAbi { pub struct InvalidAbiReason(pub &'static str); impl AddToDiagnostic for InvalidAbiReason { - fn add_to_diagnostic_with>( + fn add_to_diagnostic_with>( self, diag: &mut Diag<'_, G>, _: F, @@ -261,6 +261,16 @@ pub struct InvalidAsmTemplateModifierSym { pub op_span: Span, } +#[derive(Diagnostic, Clone, Copy)] +#[diag(ast_lowering_invalid_asm_template_modifier_label)] +pub struct InvalidAsmTemplateModifierLabel { + #[primary_span] + #[label(ast_lowering_template_modifier)] + pub placeholder_span: Span, + #[label(ast_lowering_argument)] + pub op_span: Span, +} + #[derive(Diagnostic, Clone, Copy)] #[diag(ast_lowering_register_class_only_clobber)] pub struct RegisterClassOnlyClobber { diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 9950db4784b9c..41f7418ddde42 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -125,12 +125,8 @@ impl<'hir> LoweringContext<'_, 'hir> { let lit_kind = match LitKind::from_token_lit(*token_lit) { Ok(lit_kind) => lit_kind, Err(err) => { - let guar = report_lit_error( - &self.tcx.sess.parse_sess, - err, - *token_lit, - e.span, - ); + let guar = + report_lit_error(&self.tcx.sess.psess, err, *token_lit, e.span); LitKind::Err(guar) } }; @@ -721,7 +717,7 @@ impl<'hir> LoweringContext<'_, 'hir> { sym::track_caller, span, )))), - id: self.tcx.sess.parse_sess.attr_id_generator.mk_attr_id(), + id: self.tcx.sess.psess.attr_id_generator.mk_attr_id(), style: AttrStyle::Outer, span: unstable_span, }], @@ -764,10 +760,28 @@ impl<'hir> LoweringContext<'_, 'hir> { Some(hir::CoroutineKind::Coroutine(_)) | Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)) | None => { - return hir::ExprKind::Err(self.dcx().emit_err(AwaitOnlyInAsyncFnAndBlocks { - await_kw_span, - item_span: self.current_item, - })); + // Lower to a block `{ EXPR; }` so that the awaited expr + // is not accidentally orphaned. + let stmt_id = self.next_id(); + let expr_err = self.expr( + expr.span, + hir::ExprKind::Err(self.dcx().emit_err(AwaitOnlyInAsyncFnAndBlocks { + await_kw_span, + item_span: self.current_item, + })), + ); + return hir::ExprKind::Block( + self.block_all( + expr.span, + arena_vec![self; hir::Stmt { + hir_id: stmt_id, + kind: hir::StmtKind::Semi(expr), + span: expr.span, + }], + Some(self.arena.alloc(expr_err)), + ), + None, + ); } }; @@ -1499,13 +1513,33 @@ impl<'hir> LoweringContext<'_, 'hir> { } } + #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn lower_expr_yield(&mut self, span: Span, opt_expr: Option<&Expr>) -> hir::ExprKind<'hir> { + let yielded = + opt_expr.as_ref().map(|x| self.lower_expr(x)).unwrap_or_else(|| self.expr_unit(span)); + let is_async_gen = match self.coroutine_kind { Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)) => false, Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _)) => true, Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)) => { - return hir::ExprKind::Err( - self.dcx().emit_err(AsyncCoroutinesNotSupported { span }), + // Lower to a block `{ EXPR; }` so that the awaited expr + // is not accidentally orphaned. + let stmt_id = self.next_id(); + let expr_err = self.expr( + yielded.span, + hir::ExprKind::Err(self.dcx().emit_err(AsyncCoroutinesNotSupported { span })), + ); + return hir::ExprKind::Block( + self.block_all( + yielded.span, + arena_vec![self; hir::Stmt { + hir_id: stmt_id, + kind: hir::StmtKind::Semi(yielded), + span: yielded.span, + }], + Some(self.arena.alloc(expr_err)), + ), + None, ); } Some(hir::CoroutineKind::Coroutine(_)) => { @@ -1535,9 +1569,6 @@ impl<'hir> LoweringContext<'_, 'hir> { } }; - let yielded = - opt_expr.as_ref().map(|x| self.lower_expr(x)).unwrap_or_else(|| self.expr_unit(span)); - if is_async_gen { // `yield $expr` is transformed into `task_context = yield async_gen_ready($expr)`. // This ensures that we store our resumed `ResumeContext` correctly, and also that @@ -1756,7 +1787,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // `#[allow(unreachable_code)]` let attr = attr::mk_attr_nested_word( - &self.tcx.sess.parse_sess.attr_id_generator, + &self.tcx.sess.psess.attr_id_generator, AttrStyle::Outer, sym::allow, sym::unreachable_code, diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs index 00cb09d7a541a..3f84e6b100d11 100644 --- a/compiler/rustc_ast_lowering/src/format.rs +++ b/compiler/rustc_ast_lowering/src/format.rs @@ -1,4 +1,5 @@ use super::LoweringContext; +use core::ops::ControlFlow; use rustc_ast as ast; use rustc_ast::visit::Visitor; use rustc_ast::*; @@ -594,30 +595,32 @@ fn expand_format_args<'hir>( } fn may_contain_yield_point(e: &ast::Expr) -> bool { - struct MayContainYieldPoint(bool); + struct MayContainYieldPoint; impl Visitor<'_> for MayContainYieldPoint { - fn visit_expr(&mut self, e: &ast::Expr) { + type Result = ControlFlow<()>; + + fn visit_expr(&mut self, e: &ast::Expr) -> ControlFlow<()> { if let ast::ExprKind::Await(_, _) | ast::ExprKind::Yield(_) = e.kind { - self.0 = true; + ControlFlow::Break(()) } else { visit::walk_expr(self, e); + ControlFlow::Continue(()) } } - fn visit_mac_call(&mut self, _: &ast::MacCall) { + fn visit_mac_call(&mut self, _: &ast::MacCall) -> ControlFlow<()> { // Macros should be expanded at this point. unreachable!("unexpanded macro in ast lowering"); } - fn visit_item(&mut self, _: &ast::Item) { + fn visit_item(&mut self, _: &ast::Item) -> ControlFlow<()> { // Do not recurse into nested items. + ControlFlow::Continue(()) } } - let mut visitor = MayContainYieldPoint(false); - visitor.visit_expr(e); - visitor.0 + MayContainYieldPoint.visit_expr(e).is_break() } fn for_all_argument_indexes(template: &mut [FormatArgsPiece], mut f: impl FnMut(&mut usize)) { diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 01b1e6fcaff64..523001381864d 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -275,7 +275,13 @@ impl<'hir> LoweringContext<'_, 'hir> { } Some(ty) => this.lower_ty( ty, - ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty: false }, + ImplTraitContext::OpaqueTy { + origin: hir::OpaqueTyOrigin::TyAlias { + parent: this.local_def_id(id), + in_assoc_ty: false, + }, + fn_kind: None, + }, ), }, ); @@ -936,7 +942,13 @@ impl<'hir> LoweringContext<'_, 'hir> { Some(ty) => { let ty = this.lower_ty( ty, - ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty: true }, + ImplTraitContext::OpaqueTy { + origin: hir::OpaqueTyOrigin::TyAlias { + parent: this.local_def_id(i.id), + in_assoc_ty: true, + }, + fn_kind: None, + }, ); hir::ImplItemKind::Type(ty) } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 087d240b0d50f..94e1e06a95453 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -265,13 +265,12 @@ enum ImplTraitContext { /// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually /// equivalent to a new opaque type like `type T = impl Debug; fn foo() -> T`. /// - ReturnPositionOpaqueTy { - /// Origin: Either OpaqueTyOrigin::FnReturn or OpaqueTyOrigin::AsyncFn, + OpaqueTy { origin: hir::OpaqueTyOrigin, - fn_kind: FnDeclKind, + /// Only used to change the lifetime capture rules, since + /// RPITIT captures all in scope, RPIT does not. + fn_kind: Option, }, - /// Impl trait in type aliases. - TypeAliasesOpaqueTy { in_assoc_ty: bool }, /// `impl Trait` is unstably accepted in this position. FeatureGated(ImplTraitPosition, Symbol), /// `impl Trait` is not accepted in this position. @@ -427,7 +426,7 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate<'_> { tcx.ensure_with_value().early_lint_checks(()); tcx.ensure_with_value().debugger_visualizers(LOCAL_CRATE); tcx.ensure_with_value().get_lang_items(()); - let (mut resolver, krate) = tcx.resolver_for_lowering(()).steal(); + let (mut resolver, krate) = tcx.resolver_for_lowering().steal(); let ast_index = index_crate(&resolver.node_id_to_def_id, &krate); let mut owners = IndexVec::from_fn_n( @@ -1075,9 +1074,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Disallow ATB in dyn types if self.is_in_dyn_type { let suggestion = match itctx { - ImplTraitContext::ReturnPositionOpaqueTy { .. } - | ImplTraitContext::TypeAliasesOpaqueTy { .. } - | ImplTraitContext::Universal => { + ImplTraitContext::OpaqueTy { .. } | ImplTraitContext::Universal => { let bound_end_span = constraint .gen_args .as_ref() @@ -1417,24 +1414,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { TyKind::ImplTrait(def_node_id, bounds) => { let span = t.span; match itctx { - ImplTraitContext::ReturnPositionOpaqueTy { origin, fn_kind } => self - .lower_opaque_impl_trait( - span, - origin, - *def_node_id, - bounds, - Some(fn_kind), - itctx, - ), - ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty } => self - .lower_opaque_impl_trait( - span, - hir::OpaqueTyOrigin::TyAlias { in_assoc_ty }, - *def_node_id, - bounds, - None, - itctx, - ), + ImplTraitContext::OpaqueTy { origin, fn_kind } => self.lower_opaque_impl_trait( + span, + origin, + *def_node_id, + bounds, + fn_kind, + itctx, + ), ImplTraitContext::Universal => { let span = t.span; @@ -1553,9 +1540,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let captured_lifetimes_to_duplicate = match origin { hir::OpaqueTyOrigin::TyAlias { .. } => { - // in a TAIT like `type Foo<'a> = impl Foo<'a>`, we don't duplicate any - // lifetimes, since we don't have the issue that any are late-bound. - Vec::new() + // type alias impl trait and associated type position impl trait were + // decided to capture all in-scope lifetimes, which we collect for + // all opaques during resolution. + self.resolver + .take_extra_lifetime_params(opaque_ty_node_id) + .into_iter() + .map(|(ident, id, _)| Lifetime { id, ident }) + .collect() } hir::OpaqueTyOrigin::FnReturn(..) => { if matches!( @@ -1823,9 +1815,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { FnDeclKind::Fn | FnDeclKind::Inherent | FnDeclKind::Trait - | FnDeclKind::Impl => ImplTraitContext::ReturnPositionOpaqueTy { + | FnDeclKind::Impl => ImplTraitContext::OpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(self.local_def_id(fn_node_id)), - fn_kind: kind, + fn_kind: Some(kind), }, FnDeclKind::ExternFn => { ImplTraitContext::Disallowed(ImplTraitPosition::ExternFnReturn) @@ -1919,9 +1911,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { output, coro, opaque_ty_span, - ImplTraitContext::ReturnPositionOpaqueTy { + ImplTraitContext::OpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), - fn_kind, + fn_kind: Some(fn_kind), }, ); arena_vec![this; bound] @@ -2272,6 +2264,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.expr_block(block) } + #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn lower_array_length(&mut self, c: &AnonConst) -> hir::ArrayLen { match c.value.kind { ExprKind::Underscore => { diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 48941a232c266..aeeb4bf9e763a 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -423,7 +423,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // fn f(_: impl Fn() -> impl Debug) -> impl Fn() -> impl Debug // // disallowed --^^^^^^^^^^ allowed --^^^^^^^^^^ // ``` - FnRetTy::Ty(ty) if matches!(itctx, ImplTraitContext::ReturnPositionOpaqueTy { .. }) => { + FnRetTy::Ty(ty) if matches!(itctx, ImplTraitContext::OpaqueTy { .. }) => { if self.tcx.features().impl_trait_in_fn_trait_return { self.lower_ty(ty, itctx) } else { diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index b56d695c6716a..2bef4c9122456 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -8,8 +8,7 @@ use itertools::{Either, Itertools}; use rustc_ast::ptr::P; -use rustc_ast::visit::{AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; -use rustc_ast::walk_list; +use rustc_ast::visit::{walk_list, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; use rustc_ast::*; use rustc_ast_pretty::pprust::{self, State}; use rustc_data_structures::fx::FxIndexMap; @@ -18,7 +17,7 @@ use rustc_parse::validate_attr; use rustc_session::lint::builtin::{ DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY, }; -use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer}; +use rustc_session::lint::{BuiltinLintDiag, LintBuffer}; use rustc_session::Session; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::Span; @@ -750,7 +749,7 @@ impl<'a> AstValidator<'a> { id, span, fluent::ast_passes_extern_without_abi, - BuiltinLintDiagnostics::MissingAbi(span, abi::Abi::FALLBACK), + BuiltinLintDiag::MissingAbi(span, abi::Abi::FALLBACK), ) } } @@ -835,7 +834,7 @@ fn validate_generic_param_order( impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_attribute(&mut self, attr: &Attribute) { - validate_attr::check_attr(&self.session.parse_sess, attr); + validate_attr::check_attr(&self.session.psess, attr); } fn visit_ty(&mut self, ty: &'a Ty) { @@ -930,35 +929,38 @@ impl<'a> Visitor<'a> for AstValidator<'a> { only_trait: only_trait.then_some(()), }; - self.visibility_not_permitted( - &item.vis, - errors::VisibilityNotPermittedNote::IndividualImplItems, - ); - if let &Unsafe::Yes(span) = unsafety { - self.dcx().emit_err(errors::InherentImplCannotUnsafe { - span: self_ty.span, - annotation_span: span, - annotation: "unsafe", - self_ty: self_ty.span, - }); - } - if let &ImplPolarity::Negative(span) = polarity { - self.dcx().emit_err(error(span, "negative", false)); - } - if let &Defaultness::Default(def_span) = defaultness { - self.dcx().emit_err(error(def_span, "`default`", true)); - } - if let &Const::Yes(span) = constness { - self.dcx().emit_err(error(span, "`const`", true)); - } + self.with_in_trait_impl(None, |this| { + this.visibility_not_permitted( + &item.vis, + errors::VisibilityNotPermittedNote::IndividualImplItems, + ); + if let &Unsafe::Yes(span) = unsafety { + this.dcx().emit_err(errors::InherentImplCannotUnsafe { + span: self_ty.span, + annotation_span: span, + annotation: "unsafe", + self_ty: self_ty.span, + }); + } + if let &ImplPolarity::Negative(span) = polarity { + this.dcx().emit_err(error(span, "negative", false)); + } + if let &Defaultness::Default(def_span) = defaultness { + this.dcx().emit_err(error(def_span, "`default`", true)); + } + if let &Const::Yes(span) = constness { + this.dcx().emit_err(error(span, "`const`", true)); + } - self.visit_vis(&item.vis); - self.visit_ident(item.ident); - self.with_tilde_const(Some(DisallowTildeConstContext::Impl(item.span)), |this| { - this.visit_generics(generics) + this.visit_vis(&item.vis); + this.visit_ident(item.ident); + this.with_tilde_const( + Some(DisallowTildeConstContext::Impl(item.span)), + |this| this.visit_generics(generics), + ); + this.visit_ty(self_ty); + walk_list!(this, visit_assoc_item, items, AssocCtxt::Impl); }); - self.visit_ty(self_ty); - walk_list!(self, visit_assoc_item, items, AssocCtxt::Impl); walk_list!(self, visit_attribute, &item.attrs); return; // Avoid visiting again. } @@ -1408,7 +1410,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { FnCtxt::Foreign => fluent::ast_passes_pattern_in_foreign, _ => fluent::ast_passes_pattern_in_bodiless, }; - let diag = BuiltinLintDiagnostics::PatternsInFnsWithoutBody(span, ident); + let diag = BuiltinLintDiag::PatternsInFnsWithoutBody(span, ident); self.lint_buffer.buffer_lint_with_diagnostic( PATTERNS_IN_FNS_WITHOUT_BODY, id, @@ -1491,7 +1493,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { item.id, err.span, fluent::ast_passes_deprecated_where_clause_location, - BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(sugg), + BuiltinLintDiag::DeprecatedWhereclauseLocation(sugg), ); } diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 19eed07091169..e225401ea379d 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -2,7 +2,7 @@ use rustc_ast::ParamKindOrd; use rustc_errors::{ - codes::*, AddToDiagnostic, Applicability, Diag, EmissionGuarantee, SubdiagnosticMessageOp, + codes::*, AddToDiagnostic, Applicability, Diag, EmissionGuarantee, SubdiagMessageOp, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{symbol::Ident, Span, Symbol}; @@ -374,7 +374,7 @@ pub struct EmptyLabelManySpans(pub Vec); // The derive for `Vec` does multiple calls to `span_label`, adding commas between each impl AddToDiagnostic for EmptyLabelManySpans { - fn add_to_diagnostic_with>( + fn add_to_diagnostic_with>( self, diag: &mut Diag<'_, G>, _: F, @@ -743,7 +743,7 @@ pub struct StableFeature { } impl AddToDiagnostic for StableFeature { - fn add_to_diagnostic_with>( + fn add_to_diagnostic_with>( self, diag: &mut Diag<'_, G>, _: F, diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 1b0dd9acc3782..2e14238f950f2 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -17,6 +17,7 @@ use crate::errors; macro_rules! gate { ($visitor:expr, $feature:ident, $span:expr, $explain:expr) => {{ if !$visitor.features.$feature && !$span.allows_unstable(sym::$feature) { + #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable feature_err(&$visitor.sess, sym::$feature, $span, $explain).emit(); } }}; @@ -34,6 +35,7 @@ macro_rules! gate { macro_rules! gate_alt { ($visitor:expr, $has_feature:expr, $name:expr, $span:expr, $explain:expr) => {{ if !$has_feature && !$span.allows_unstable($name) { + #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable feature_err(&$visitor.sess, $name, $span, $explain).emit(); } }}; @@ -73,6 +75,7 @@ struct PostExpansionVisitor<'a> { } impl<'a> PostExpansionVisitor<'a> { + #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn check_abi(&self, abi: ast::StrLit, constness: ast::Const) { let ast::StrLit { symbol_unescaped, span, .. } = abi; @@ -203,14 +206,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ); } } - if !attr.is_doc_comment() - && let [seg, _] = attr.get_normal_item().path.segments.as_slice() - && seg.ident.name == sym::diagnostic - && !self.features.diagnostic_namespace - { - let msg = "`#[diagnostic]` attribute name space is experimental"; - gate!(self, diagnostic_namespace, seg.ident.span, msg); - } // Emit errors for non-staged-api crates. if !self.features.staged_api { @@ -507,7 +502,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { check_incompatible_features(sess, features); let mut visitor = PostExpansionVisitor { sess, features }; - let spans = sess.parse_sess.gated_spans.spans.borrow(); + let spans = sess.psess.gated_spans.spans.borrow(); macro_rules! gate_all { ($gate:ident, $msg:literal) => { if let Some(spans) = spans.get(&sym::$gate) { @@ -579,6 +574,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { if let Ok(snippet) = sm.span_to_snippet(span) && snippet == "!" { + #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable feature_err(sess, sym::never_patterns, span, "`!` patterns are experimental") .emit(); } else { diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 6119c6c84f8b7..e5d7b8489033a 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1452,6 +1452,10 @@ impl<'a> State<'a> { s.print_path(&sym.path, true, 0); } } + InlineAsmOperand::Label { block } => { + s.head("label"); + s.print_block(block); + } } } AsmArg::ClobberAbi(abi) => { diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 3d2cf25e98bd6..814104ec78c49 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -8,7 +8,7 @@ use rustc_feature::{find_gated_cfg, is_builtin_attr_name, Features, GatedCfg}; use rustc_macros::HashStable_Generic; use rustc_session::config::ExpectedValues; use rustc_session::lint::builtin::UNEXPECTED_CFGS; -use rustc_session::lint::BuiltinLintDiagnostics; +use rustc_session::lint::BuiltinLintDiag; use rustc_session::parse::feature_err; use rustc_session::{RustcVersion, Session}; use rustc_span::hygiene::Transparency; @@ -516,6 +516,7 @@ pub struct Condition { } /// Tests if a cfg-pattern matches the cfg set +#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable pub fn cfg_matches( cfg: &ast::MetaItem, sess: &Session, @@ -524,9 +525,9 @@ pub fn cfg_matches( ) -> bool { eval_condition(cfg, sess, features, &mut |cfg| { try_gate_cfg(cfg.name, cfg.span, sess, features); - match sess.parse_sess.check_config.expecteds.get(&cfg.name) { + match sess.psess.check_config.expecteds.get(&cfg.name) { Some(ExpectedValues::Some(values)) if !values.contains(&cfg.value) => { - sess.parse_sess.buffer_lint_with_diagnostic( + sess.psess.buffer_lint_with_diagnostic( UNEXPECTED_CFGS, cfg.span, lint_node_id, @@ -535,19 +536,19 @@ pub fn cfg_matches( } else { format!("unexpected `cfg` condition value: (none)") }, - BuiltinLintDiagnostics::UnexpectedCfgValue( + BuiltinLintDiag::UnexpectedCfgValue( (cfg.name, cfg.name_span), cfg.value.map(|v| (v, cfg.value_span.unwrap())), ), ); } - None if sess.parse_sess.check_config.exhaustive_names => { - sess.parse_sess.buffer_lint_with_diagnostic( + None if sess.psess.check_config.exhaustive_names => { + sess.psess.buffer_lint_with_diagnostic( UNEXPECTED_CFGS, cfg.span, lint_node_id, format!("unexpected `cfg` condition name: `{}`", cfg.name), - BuiltinLintDiagnostics::UnexpectedCfgName( + BuiltinLintDiag::UnexpectedCfgName( (cfg.name, cfg.name_span), cfg.value.map(|v| (v, cfg.value_span.unwrap())), ), @@ -555,7 +556,7 @@ pub fn cfg_matches( } _ => { /* not unexpected */ } } - sess.parse_sess.config.contains(&(cfg.name, cfg.value)) + sess.psess.config.contains(&(cfg.name, cfg.value)) }) } @@ -566,6 +567,7 @@ fn try_gate_cfg(name: Symbol, span: Span, sess: &Session, features: Option<&Feat } } +#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &Session, features: &Features) { let (cfg, feature, has_feature) = gated_cfg; if !has_feature(features) && !cfg_span.allows_unstable(*feature) { @@ -592,13 +594,14 @@ fn parse_version(s: Symbol) -> Option { /// Evaluate a cfg-like condition (with `any` and `all`), using `eval` to /// evaluate individual items. +#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable pub fn eval_condition( cfg: &ast::MetaItem, sess: &Session, features: Option<&Features>, eval: &mut impl FnMut(Condition) -> bool, ) -> bool { - let dcx = &sess.parse_sess.dcx; + let dcx = &sess.psess.dcx; match &cfg.kind { ast::MetaItemKind::List(mis) if cfg.name_or_empty() == sym::version => { try_gate_cfg(sym::version, cfg.span, sess, features); @@ -626,7 +629,7 @@ pub fn eval_condition( }; // See https://github.com/rust-lang/rust/issues/64796#issuecomment-640851454 for details - if sess.parse_sess.assume_incomplete_release { + if sess.psess.assume_incomplete_release { RustcVersion::CURRENT > min_version } else { RustcVersion::CURRENT >= min_version diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 53e8ac121bbce..560928d394145 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -76,6 +76,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// LL | for (key, value) in dict { /// | ^^^^ /// ``` + #[allow(rustc::diagnostic_outside_of_impl)] // FIXME pub(super) fn add_moved_or_invoked_closure_note( &self, location: Location, @@ -585,6 +586,7 @@ impl UseSpans<'_> { } /// Add a span label to the arguments of the closure, if it exists. + #[allow(rustc::diagnostic_outside_of_impl)] pub(super) fn args_subdiag( self, dcx: &rustc_errors::DiagCtxt, @@ -598,6 +600,7 @@ impl UseSpans<'_> { /// Add a span label to the use of the captured variable, if it exists. /// only adds label to the `path_span` + #[allow(rustc::diagnostic_outside_of_impl)] pub(super) fn var_path_only_subdiag( self, dcx: &rustc_errors::DiagCtxt, @@ -635,6 +638,7 @@ impl UseSpans<'_> { } /// Add a subdiagnostic to the use of the captured variable, if it exists. + #[allow(rustc::diagnostic_outside_of_impl)] pub(super) fn var_subdiag( self, dcx: &rustc_errors::DiagCtxt, @@ -1008,6 +1012,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.borrow_spans(span, borrow.reserve_location) } + #[allow(rustc::diagnostic_outside_of_impl)] + #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn explain_captures( &mut self, err: &mut Diag<'_>, diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index c327e591f3cdd..ebc9f1d109ee7 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -1,6 +1,7 @@ #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] +use core::ops::ControlFlow; use hir::ExprKind; use rustc_errors::{Applicability, Diag}; use rustc_hir as hir; @@ -727,30 +728,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { _ => local_decl.source_info.span, }; - struct BindingFinder { - span: Span, - hir_id: Option, - } - - impl<'tcx> Visitor<'tcx> for BindingFinder { - fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) { - if let hir::StmtKind::Local(local) = s.kind { - if local.pat.span == self.span { - self.hir_id = Some(local.hir_id); - } - } - hir::intravisit::walk_stmt(self, s); - } - } - let def_id = self.body.source.def_id(); let hir_id = if let Some(local_def_id) = def_id.as_local() && let Some(body_id) = self.infcx.tcx.hir().maybe_body_owned_by(local_def_id) { let body = self.infcx.tcx.hir().body(body_id); - let mut v = BindingFinder { span: pat_span, hir_id: None }; - v.visit_body(body); - v.hir_id + BindingFinder { span: pat_span }.visit_body(body).break_value() } else { None }; @@ -859,17 +842,18 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { }; let hir_map = self.infcx.tcx.hir(); - struct Finder<'tcx> { + struct Finder { span: Span, - expr: Option<&'tcx Expr<'tcx>>, } - impl<'tcx> Visitor<'tcx> for Finder<'tcx> { - fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) { - if e.span == self.span && self.expr.is_none() { - self.expr = Some(e); + impl<'tcx> Visitor<'tcx> for Finder { + type Result = ControlFlow<&'tcx Expr<'tcx>>; + fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) -> Self::Result { + if e.span == self.span { + ControlFlow::Break(e) + } else { + hir::intravisit::walk_expr(self, e) } - hir::intravisit::walk_expr(self, e); } } if let Some(body_id) = hir_map.maybe_body_owned_by(self.mir_def_id()) @@ -878,9 +862,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // `span` corresponds to the expression being iterated, find the `for`-loop desugared // expression with that span in order to identify potential fixes when encountering a // read-only iterator that should be mutable. - let mut v = Finder { span, expr: None }; - v.visit_block(block); - if let Some(expr) = v.expr + if let ControlFlow::Break(expr) = (Finder { span }).visit_block(block) && let Call(_, [expr]) = expr.kind { match expr.kind { @@ -1179,29 +1161,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { ); } Some((false, err_label_span, message)) => { - struct BindingFinder { - span: Span, - hir_id: Option, - } - - impl<'tcx> Visitor<'tcx> for BindingFinder { - fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) { - if let hir::StmtKind::Local(local) = s.kind { - if local.pat.span == self.span { - self.hir_id = Some(local.hir_id); - } - } - hir::intravisit::walk_stmt(self, s); - } - } let def_id = self.body.source.def_id(); let hir_id = if let Some(local_def_id) = def_id.as_local() && let Some(body_id) = self.infcx.tcx.hir().maybe_body_owned_by(local_def_id) { let body = self.infcx.tcx.hir().body(body_id); - let mut v = BindingFinder { span: err_label_span, hir_id: None }; - v.visit_body(body); - v.hir_id + BindingFinder { span: err_label_span }.visit_body(body).break_value() } else { None }; @@ -1333,6 +1298,23 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } } +struct BindingFinder { + span: Span, +} + +impl<'tcx> Visitor<'tcx> for BindingFinder { + type Result = ControlFlow; + fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) -> Self::Result { + if let hir::StmtKind::Local(local) = s.kind + && local.pat.span == self.span + { + ControlFlow::Break(local.hir_id) + } else { + hir::intravisit::walk_stmt(self, s) + } + } +} + pub fn mut_borrow_of_mutable_ref(local_decl: &LocalDecl<'_>, local_name: Option) -> bool { debug!("local_info: {:?}, ty.kind(): {:?}", local_decl.local_info, local_decl.ty.kind()); diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 3765dfe5db53c..c06bf94a6fd5f 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -201,6 +201,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // For generic associated types (GATs) which implied 'static requirement // from higher-ranked trait bounds (HRTB). Try to locate span of the trait // and the span which bounded to the trait for adding 'static lifetime suggestion + #[allow(rustc::diagnostic_outside_of_impl)] + #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn suggest_static_lifetime_for_gat_from_hrtb( &self, diag: &mut Diag<'_>, @@ -254,9 +256,6 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { hrtb_bounds.iter().for_each(|bound| { let Trait(PolyTraitRef { trait_ref, span: trait_span, .. }, _) = bound else { return; }; - // FIXME: make this translatable - #[allow(rustc::diagnostic_outside_of_impl)] - #[allow(rustc::untranslatable_diagnostic)] diag.span_note( *trait_span, "due to current limitations in the borrow checker, this implies a `'static` lifetime" @@ -580,6 +579,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { /// executing... /// = note: ...therefore, returned references to captured variables will escape the closure /// ``` + #[allow(rustc::diagnostic_outside_of_impl)] // FIXME fn report_fnmut_error( &self, errci: &ErrorConstraintInfo<'tcx>, @@ -761,6 +761,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { /// | ^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it /// | is returning data with lifetime `'b` /// ``` + #[allow(rustc::diagnostic_outside_of_impl)] // FIXME fn report_general_error(&self, errci: &ErrorConstraintInfo<'tcx>) -> Diag<'tcx> { let ErrorConstraintInfo { fr, @@ -822,6 +823,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { /// LL | fn iter_values_anon(&self) -> impl Iterator + 'a { /// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /// ``` + #[allow(rustc::diagnostic_outside_of_impl)] + #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn add_static_impl_trait_suggestion( &self, diag: &mut Diag<'_>, @@ -972,6 +975,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { self.suggest_constrain_dyn_trait_in_impl(diag, &visitor.0, ident, self_ty); } + #[allow(rustc::diagnostic_outside_of_impl)] + #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable #[instrument(skip(self, err), level = "debug")] fn suggest_constrain_dyn_trait_in_impl( &self, @@ -1034,6 +1039,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { suggest_adding_lifetime_params(self.infcx.tcx, sub, ty_sup, ty_sub, diag); } + #[allow(rustc::diagnostic_outside_of_impl)] + #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn suggest_move_on_borrowing_closure(&self, diag: &mut Diag<'_>) { let map = self.infcx.tcx.hir(); let body_id = map.body_owned_by(self.mir_def_id()); diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index ef582033c4ea1..8dcfe014b653e 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -6,6 +6,7 @@ #![feature(assert_matches)] #![feature(associated_type_bounds)] #![feature(box_patterns)] +#![feature(control_flow_enum)] #![feature(let_chains)] #![feature(min_specialization)] #![feature(never_type)] @@ -723,7 +724,7 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro operands, options: _, line_spans: _, - destination: _, + targets: _, unwind: _, } => { for op in operands { @@ -749,7 +750,8 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro } InlineAsmOperand::Const { value: _ } | InlineAsmOperand::SymFn { value: _ } - | InlineAsmOperand::SymStatic { def_id: _ } => {} + | InlineAsmOperand::SymStatic { def_id: _ } + | InlineAsmOperand::Label { target_index: _ } => {} } } } diff --git a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs index 10941cadcbb25..956de1dec9b2b 100644 --- a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs +++ b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs @@ -161,7 +161,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'cx, 'tcx> { operands, options: _, line_spans: _, - destination: _, + targets: _, unwind: _, } => { for op in operands { @@ -182,7 +182,8 @@ impl<'cx, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'cx, 'tcx> { } InlineAsmOperand::Const { value: _ } | InlineAsmOperand::SymFn { value: _ } - | InlineAsmOperand::SymStatic { def_id: _ } => {} + | InlineAsmOperand::SymStatic { def_id: _ } + | InlineAsmOperand::Label { target_index: _ } => {} } } } diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 4b096a592344a..12b02c7fcfa1d 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -367,14 +367,17 @@ fn check_opaque_type_parameter_valid( span: Span, ) -> Result<(), ErrorGuaranteed> { let opaque_ty_hir = tcx.hir().expect_item(opaque_type_key.def_id); - let is_ty_alias = match opaque_ty_hir.expect_opaque_ty().origin { - OpaqueTyOrigin::TyAlias { .. } => true, - OpaqueTyOrigin::AsyncFn(..) | OpaqueTyOrigin::FnReturn(..) => false, + let (parent, is_ty_alias) = match opaque_ty_hir.expect_opaque_ty().origin { + OpaqueTyOrigin::TyAlias { parent, .. } => (parent, true), + OpaqueTyOrigin::AsyncFn(parent) | OpaqueTyOrigin::FnReturn(parent) => (parent, false), }; - let opaque_generics = tcx.generics_of(opaque_type_key.def_id); + let parent_generics = tcx.generics_of(parent); let mut seen_params: FxIndexMap<_, Vec<_>> = FxIndexMap::default(); - for (i, arg) in opaque_type_key.args.iter().enumerate() { + + // Only check the parent generics, which will ignore any of the + // duplicated lifetime args that come from reifying late-bounds. + for (i, arg) in opaque_type_key.args.iter().take(parent_generics.count()).enumerate() { if let Err(guar) = arg.error_reported() { return Err(guar); } @@ -395,7 +398,7 @@ fn check_opaque_type_parameter_valid( seen_params.entry(arg).or_default().push(i); } else { // Prevent `fn foo() -> Foo` from being defining. - let opaque_param = opaque_generics.param_at(i, tcx); + let opaque_param = parent_generics.param_at(i, tcx); let kind = opaque_param.kind.descr(); return Err(tcx.dcx().emit_err(NonGenericOpaqueTypeParam { @@ -409,10 +412,10 @@ fn check_opaque_type_parameter_valid( for (_, indices) in seen_params { if indices.len() > 1 { - let descr = opaque_generics.param_at(indices[0], tcx).kind.descr(); + let descr = parent_generics.param_at(indices[0], tcx).kind.descr(); let spans: Vec<_> = indices .into_iter() - .map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id)) + .map(|i| tcx.def_span(parent_generics.param_at(i, tcx).def_id)) .collect(); #[allow(rustc::diagnostic_outside_of_impl)] #[allow(rustc::untranslatable_diagnostic)] diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 26e1e24d1a120..8d38b86fa3430 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1667,7 +1667,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // (Eventually this should use const-generics, but those are not up for the task yet: // https://github.com/rust-lang/rust/issues/85229.) if let Some(name @ (sym::simd_shuffle | sym::simd_insert | sym::simd_extract)) = - self.tcx().intrinsic(def_id) + self.tcx().intrinsic(def_id).map(|i| i.name) { let idx = match name { sym::simd_shuffle => 2, @@ -1770,8 +1770,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.assert_iscleanup(body, block_data, real_target, is_cleanup); self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup); } - TerminatorKind::InlineAsm { destination, unwind, .. } => { - if let Some(target) = destination { + TerminatorKind::InlineAsm { ref targets, unwind, .. } => { + for &target in targets { self.assert_iscleanup(body, block_data, target, is_cleanup); } self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup); diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl index bc2a9d5ad1e35..ba8401393d7ab 100644 --- a/compiler/rustc_builtin_macros/messages.ftl +++ b/compiler/rustc_builtin_macros/messages.ftl @@ -19,6 +19,8 @@ builtin_macros_asm_expected_other = expected operand, {$is_global_asm -> builtin_macros_asm_explicit_register_name = explicit register arguments cannot have names +builtin_macros_asm_mayunwind = asm labels are not allowed with the `may_unwind` option + builtin_macros_asm_modifier_invalid = asm template modifier must be a single character builtin_macros_asm_mutually_exclusive = the `{$opt1}` and `{$opt2}` options are mutually exclusive diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 29bf5e9f30493..bc851fadc2e24 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -10,7 +10,6 @@ use rustc_index::bit_set::GrowableBitSet; use rustc_parse::parser::Parser; use rustc_parse_format as parse; use rustc_session::lint; -use rustc_session::parse::ParseSess; use rustc_span::symbol::Ident; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::{ErrorGuaranteed, InnerSpan, Span}; @@ -36,19 +35,17 @@ fn parse_args<'a>( is_global_asm: bool, ) -> PResult<'a, AsmArgs> { let mut p = ecx.new_parser_from_tts(tts); - let sess = &ecx.sess.parse_sess; - parse_asm_args(&mut p, sess, sp, is_global_asm) + parse_asm_args(&mut p, sp, is_global_asm) } // Primarily public for rustfmt consumption. // Internal consumers should continue to leverage `expand_asm`/`expand__global_asm` pub fn parse_asm_args<'a>( p: &mut Parser<'a>, - sess: &'a ParseSess, sp: Span, is_global_asm: bool, ) -> PResult<'a, AsmArgs> { - let dcx = &sess.dcx; + let dcx = &p.psess.dcx; if p.token == token::Eof { return Err(dcx.create_err(errors::AsmRequiresTemplate { span: sp })); @@ -167,6 +164,9 @@ pub fn parse_asm_args<'a>( path: path.clone(), }; ast::InlineAsmOperand::Sym { sym } + } else if !is_global_asm && p.eat_keyword(sym::label) { + let block = p.parse_block()?; + ast::InlineAsmOperand::Label { block } } else if allow_templates { let template = p.parse_expr()?; // If it can't possibly expand to a string, provide diagnostics here to include other @@ -243,6 +243,7 @@ pub fn parse_asm_args<'a>( let mut have_real_output = false; let mut outputs_sp = vec![]; let mut regclass_outputs = vec![]; + let mut labels_sp = vec![]; for (op, op_sp) in &args.operands { match op { ast::InlineAsmOperand::Out { reg, expr, .. } @@ -260,6 +261,9 @@ pub fn parse_asm_args<'a>( regclass_outputs.push(*op_sp); } } + ast::InlineAsmOperand::Label { .. } => { + labels_sp.push(*op_sp); + } _ => {} } } @@ -271,6 +275,9 @@ pub fn parse_asm_args<'a>( // Bail out now since this is likely to confuse MIR return Err(err); } + if args.options.contains(ast::InlineAsmOptions::MAY_UNWIND) && !labels_sp.is_empty() { + dcx.emit_err(errors::AsmMayUnwind { labels_sp }); + } if args.clobber_abis.len() > 0 { if is_global_asm { @@ -299,7 +306,7 @@ pub fn parse_asm_args<'a>( fn err_duplicate_option(p: &mut Parser<'_>, symbol: Symbol, span: Span) { // Tool-only output let full_span = if p.token.kind == token::Comma { span.to(p.token.span) } else { span }; - p.sess.dcx.emit_err(errors::AsmOptAlreadyprovided { span, symbol, full_span }); + p.psess.dcx.emit_err(errors::AsmOptAlreadyprovided { span, symbol, full_span }); } /// Try to set the provided option in the provided `AsmArgs`. @@ -371,7 +378,7 @@ fn parse_clobber_abi<'a>(p: &mut Parser<'a>, args: &mut AsmArgs) -> PResult<'a, p.expect(&token::OpenDelim(Delimiter::Parenthesis))?; if p.eat(&token::CloseDelim(Delimiter::Parenthesis)) { - return Err(p.sess.dcx.create_err(errors::NonABI { span: p.token.span })); + return Err(p.psess.dcx.create_err(errors::NonABI { span: p.token.span })); } let mut new_abis = Vec::new(); @@ -382,7 +389,7 @@ fn parse_clobber_abi<'a>(p: &mut Parser<'a>, args: &mut AsmArgs) -> PResult<'a, } Err(opt_lit) => { let span = opt_lit.map_or(p.token.span, |lit| lit.span); - let mut err = p.sess.dcx.struct_span_err(span, "expected string literal"); + let mut err = p.psess.dcx.struct_span_err(span, "expected string literal"); err.span_label(span, "not a string literal"); return Err(err); } @@ -498,7 +505,7 @@ fn expand_preparsed_asm( }; if template_str.contains(".intel_syntax") { - ecx.parse_sess().buffer_lint( + ecx.psess().buffer_lint( lint::builtin::BAD_ASM_STYLE, find_span(".intel_syntax"), ecx.current_expansion.lint_node_id, @@ -506,7 +513,7 @@ fn expand_preparsed_asm( ); } if template_str.contains(".att_syntax") { - ecx.parse_sess().buffer_lint( + ecx.psess().buffer_lint( lint::builtin::BAD_ASM_STYLE, find_span(".att_syntax"), ecx.current_expansion.lint_node_id, diff --git a/compiler/rustc_builtin_macros/src/cfg_accessible.rs b/compiler/rustc_builtin_macros/src/cfg_accessible.rs index ceb5f86107845..1933b2e1fb7fe 100644 --- a/compiler/rustc_builtin_macros/src/cfg_accessible.rs +++ b/compiler/rustc_builtin_macros/src/cfg_accessible.rs @@ -46,7 +46,7 @@ impl MultiItemModifier for Expander { ) -> ExpandResult, Annotatable> { let template = AttributeTemplate { list: Some("path"), ..Default::default() }; validate_attr::check_builtin_meta_item( - &ecx.sess.parse_sess, + &ecx.sess.psess, meta_item, ast::AttrStyle::Outer, sym::cfg_accessible, diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs index cfa94b0e78085..93f7d09546b70 100644 --- a/compiler/rustc_builtin_macros/src/cfg_eval.rs +++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs @@ -1,5 +1,6 @@ use crate::util::{check_builtin_macro_attribute, warn_on_duplicate_attribute}; +use core::ops::ControlFlow; use rustc_ast as ast; use rustc_ast::mut_visit::MutVisitor; use rustc_ast::ptr::P; @@ -87,41 +88,40 @@ fn flat_map_annotatable( } } -struct CfgFinder { - has_cfg_or_cfg_attr: bool, -} - -impl CfgFinder { - fn has_cfg_or_cfg_attr(annotatable: &Annotatable) -> bool { - let mut finder = CfgFinder { has_cfg_or_cfg_attr: false }; - match annotatable { - Annotatable::Item(item) => finder.visit_item(item), - Annotatable::TraitItem(item) => finder.visit_assoc_item(item, visit::AssocCtxt::Trait), - Annotatable::ImplItem(item) => finder.visit_assoc_item(item, visit::AssocCtxt::Impl), - Annotatable::ForeignItem(item) => finder.visit_foreign_item(item), - Annotatable::Stmt(stmt) => finder.visit_stmt(stmt), - Annotatable::Expr(expr) => finder.visit_expr(expr), - Annotatable::Arm(arm) => finder.visit_arm(arm), - Annotatable::ExprField(field) => finder.visit_expr_field(field), - Annotatable::PatField(field) => finder.visit_pat_field(field), - Annotatable::GenericParam(param) => finder.visit_generic_param(param), - Annotatable::Param(param) => finder.visit_param(param), - Annotatable::FieldDef(field) => finder.visit_field_def(field), - Annotatable::Variant(variant) => finder.visit_variant(variant), - Annotatable::Crate(krate) => finder.visit_crate(krate), - }; - finder.has_cfg_or_cfg_attr - } -} +fn has_cfg_or_cfg_attr(annotatable: &Annotatable) -> bool { + struct CfgFinder; -impl<'ast> visit::Visitor<'ast> for CfgFinder { - fn visit_attribute(&mut self, attr: &'ast Attribute) { - // We want short-circuiting behavior, so don't use the '|=' operator. - self.has_cfg_or_cfg_attr = self.has_cfg_or_cfg_attr - || attr + impl<'ast> visit::Visitor<'ast> for CfgFinder { + type Result = ControlFlow<()>; + fn visit_attribute(&mut self, attr: &'ast Attribute) -> ControlFlow<()> { + if attr .ident() - .is_some_and(|ident| ident.name == sym::cfg || ident.name == sym::cfg_attr); + .is_some_and(|ident| ident.name == sym::cfg || ident.name == sym::cfg_attr) + { + ControlFlow::Break(()) + } else { + ControlFlow::Continue(()) + } + } } + + let res = match annotatable { + Annotatable::Item(item) => CfgFinder.visit_item(item), + Annotatable::TraitItem(item) => CfgFinder.visit_assoc_item(item, visit::AssocCtxt::Trait), + Annotatable::ImplItem(item) => CfgFinder.visit_assoc_item(item, visit::AssocCtxt::Impl), + Annotatable::ForeignItem(item) => CfgFinder.visit_foreign_item(item), + Annotatable::Stmt(stmt) => CfgFinder.visit_stmt(stmt), + Annotatable::Expr(expr) => CfgFinder.visit_expr(expr), + Annotatable::Arm(arm) => CfgFinder.visit_arm(arm), + Annotatable::ExprField(field) => CfgFinder.visit_expr_field(field), + Annotatable::PatField(field) => CfgFinder.visit_pat_field(field), + Annotatable::GenericParam(param) => CfgFinder.visit_generic_param(param), + Annotatable::Param(param) => CfgFinder.visit_param(param), + Annotatable::FieldDef(field) => CfgFinder.visit_field_def(field), + Annotatable::Variant(variant) => CfgFinder.visit_variant(variant), + Annotatable::Crate(krate) => CfgFinder.visit_crate(krate), + }; + res.is_break() } impl CfgEval<'_, '_> { @@ -132,7 +132,7 @@ impl CfgEval<'_, '_> { fn configure_annotatable(&mut self, mut annotatable: Annotatable) -> Option { // Tokenizing and re-parsing the `Annotatable` can have a significant // performance impact, so try to avoid it if possible - if !CfgFinder::has_cfg_or_cfg_attr(&annotatable) { + if !has_cfg_or_cfg_attr(&annotatable) { return Some(annotatable); } @@ -195,8 +195,7 @@ impl CfgEval<'_, '_> { // Re-parse the tokens, setting the `capture_cfg` flag to save extra information // to the captured `AttrTokenStream` (specifically, we capture // `AttrTokenTree::AttributesData` for all occurrences of `#[cfg]` and `#[cfg_attr]`) - let mut parser = - rustc_parse::stream_to_parser(&self.cfg.sess.parse_sess, orig_tokens, None); + let mut parser = rustc_parse::stream_to_parser(&self.cfg.sess.psess, orig_tokens, None); parser.capture_cfg = true; match parse_annotatable_with(&mut parser) { Ok(a) => annotatable = a, diff --git a/compiler/rustc_builtin_macros/src/cmdline_attrs.rs b/compiler/rustc_builtin_macros/src/cmdline_attrs.rs index d956c096d24a1..ada82e45712d8 100644 --- a/compiler/rustc_builtin_macros/src/cmdline_attrs.rs +++ b/compiler/rustc_builtin_macros/src/cmdline_attrs.rs @@ -7,10 +7,10 @@ use rustc_ast::{self as ast, AttrItem, AttrStyle}; use rustc_session::parse::ParseSess; use rustc_span::FileName; -pub fn inject(krate: &mut ast::Crate, parse_sess: &ParseSess, attrs: &[String]) { +pub fn inject(krate: &mut ast::Crate, psess: &ParseSess, attrs: &[String]) { for raw_attr in attrs { let mut parser = rustc_parse::new_parser_from_source_str( - parse_sess, + psess, FileName::cli_crate_attr_source_code(raw_attr), raw_attr.clone(), ); @@ -25,12 +25,12 @@ pub fn inject(krate: &mut ast::Crate, parse_sess: &ParseSess, attrs: &[String]) }; let end_span = parser.token.span; if parser.token != token::Eof { - parse_sess.dcx.emit_err(errors::InvalidCrateAttr { span: start_span.to(end_span) }); + psess.dcx.emit_err(errors::InvalidCrateAttr { span: start_span.to(end_span) }); continue; } krate.attrs.push(mk_attr( - &parse_sess.attr_id_generator, + &psess.attr_id_generator, AttrStyle::Inner, path, args, diff --git a/compiler/rustc_builtin_macros/src/concat.rs b/compiler/rustc_builtin_macros/src/concat.rs index abfaa9b006edb..0bfb848859bd8 100644 --- a/compiler/rustc_builtin_macros/src/concat.rs +++ b/compiler/rustc_builtin_macros/src/concat.rs @@ -43,7 +43,7 @@ pub fn expand_concat( guar = Some(guarantee); } Err(err) => { - guar = Some(report_lit_error(&cx.sess.parse_sess, err, token_lit, e.span)); + guar = Some(report_lit_error(&cx.sess.psess, err, token_lit, e.span)); } }, // We also want to allow negative numeric literals. @@ -52,7 +52,7 @@ pub fn expand_concat( Ok(LitKind::Int(i, _)) => accumulator.push_str(&format!("-{i}")), Ok(LitKind::Float(f, _)) => accumulator.push_str(&format!("-{f}")), Err(err) => { - guar = Some(report_lit_error(&cx.sess.parse_sess, err, token_lit, e.span)); + guar = Some(report_lit_error(&cx.sess.psess, err, token_lit, e.span)); } _ => missing_literal.push(e.span), } diff --git a/compiler/rustc_builtin_macros/src/concat_bytes.rs b/compiler/rustc_builtin_macros/src/concat_bytes.rs index 3fb0b50f41756..502bfb4467e52 100644 --- a/compiler/rustc_builtin_macros/src/concat_bytes.rs +++ b/compiler/rustc_builtin_macros/src/concat_bytes.rs @@ -55,7 +55,7 @@ fn invalid_type_err( Ok(LitKind::Int(_, _)) => dcx.emit_err(ConcatBytesNonU8 { span }), Ok(LitKind::ByteStr(..) | LitKind::Byte(_)) => unreachable!(), Ok(LitKind::Err(guar)) => guar, - Err(err) => report_lit_error(&cx.sess.parse_sess, err, token_lit, span), + Err(err) => report_lit_error(&cx.sess.psess, err, token_lit, span), } } diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs index 7388e133c53e2..4f412cf79d91f 100644 --- a/compiler/rustc_builtin_macros/src/derive.rs +++ b/compiler/rustc_builtin_macros/src/derive.rs @@ -34,7 +34,7 @@ impl MultiItemModifier for Expander { let template = AttributeTemplate { list: Some("Trait1, Trait2, ..."), ..Default::default() }; validate_attr::check_builtin_meta_item( - &sess.parse_sess, + &sess.psess, meta_item, ast::AttrStyle::Outer, sym::derive, diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index 386d4a54b655b..292a916e2a78b 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -1,8 +1,10 @@ use crate::deriving::generic::ty::*; use crate::deriving::generic::*; use crate::errors; +use core::ops::ControlFlow; use rustc_ast as ast; -use rustc_ast::{attr, walk_list, EnumDef, VariantData}; +use rustc_ast::visit::walk_list; +use rustc_ast::{attr, EnumDef, VariantData}; use rustc_expand::base::{Annotatable, DummyResult, ExtCtxt}; use rustc_span::symbol::Ident; use rustc_span::symbol::{kw, sym}; @@ -230,20 +232,19 @@ impl<'a, 'b> rustc_ast::visit::Visitor<'a> for DetectNonVariantDefaultAttr<'a, ' } fn has_a_default_variant(item: &Annotatable) -> bool { - struct HasDefaultAttrOnVariant { - found: bool, - } + struct HasDefaultAttrOnVariant; impl<'ast> rustc_ast::visit::Visitor<'ast> for HasDefaultAttrOnVariant { - fn visit_variant(&mut self, v: &'ast rustc_ast::Variant) { + type Result = ControlFlow<()>; + fn visit_variant(&mut self, v: &'ast rustc_ast::Variant) -> ControlFlow<()> { if v.attrs.iter().any(|attr| attr.has_name(kw::Default)) { - self.found = true; + ControlFlow::Break(()) + } else { + // no need to subrecurse. + ControlFlow::Continue(()) } - // no need to subrecurse. } } - let mut visitor = HasDefaultAttrOnVariant { found: false }; - item.visit_with(&mut visitor); - visitor.found + item.visit_with(&mut HasDefaultAttrOnVariant).is_break() } diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index eb664b571ba85..3cb3e30daa72e 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -1603,9 +1603,10 @@ impl<'a> TraitDef<'a> { // Once use of `icu4x-0.9.0` has dropped sufficiently, this // exception should be removed. let is_simple_path = |ty: &P, sym| { - if let TyKind::Path(None, ast::Path { segments, .. }) = &ty.kind && - let [seg] = segments.as_slice() && - seg.ident.name == sym && seg.args.is_none() + if let TyKind::Path(None, ast::Path { segments, .. }) = &ty.kind + && let [seg] = segments.as_slice() + && seg.ident.name == sym + && seg.args.is_none() { true } else { @@ -1613,8 +1614,8 @@ impl<'a> TraitDef<'a> { } }; - let exception = if let TyKind::Slice(ty) = &struct_field.ty.kind && - is_simple_path(ty, sym::u8) + let exception = if let TyKind::Slice(ty) = &struct_field.ty.kind + && is_simple_path(ty, sym::u8) { Some("byte") } else if is_simple_path(&struct_field.ty, sym::str) { @@ -1624,14 +1625,14 @@ impl<'a> TraitDef<'a> { }; if let Some(ty) = exception { - cx.sess.parse_sess.buffer_lint_with_diagnostic( + cx.sess.psess.buffer_lint_with_diagnostic( BYTE_SLICE_IN_PACKED_STRUCT_WITH_DERIVE, sp, ast::CRATE_NODE_ID, format!( "{ty} slice in a packed struct that derives a built-in trait" ), - rustc_lint_defs::BuiltinLintDiagnostics::ByteSliceInPackedStructWithDerive + rustc_lint_defs::BuiltinLintDiag::ByteSliceInPackedStructWithDerive, ); } else { // Wrap the expression in `{...}`, causing a copy. diff --git a/compiler/rustc_builtin_macros/src/env.rs b/compiler/rustc_builtin_macros/src/env.rs index f057d44bf710a..193b38a83238a 100644 --- a/compiler/rustc_builtin_macros/src/env.rs +++ b/compiler/rustc_builtin_macros/src/env.rs @@ -39,7 +39,7 @@ pub fn expand_option_env<'cx>( let sp = cx.with_def_site_ctxt(sp); let value = lookup_env(cx, var); - cx.sess.parse_sess.env_depinfo.borrow_mut().insert((var, value)); + cx.sess.psess.env_depinfo.borrow_mut().insert((var, value)); let e = match value { None => { let lt = cx.lifetime(sp, Ident::new(kw::StaticLifetime, sp)); @@ -94,7 +94,7 @@ pub fn expand_env<'cx>( let span = cx.with_def_site_ctxt(sp); let value = lookup_env(cx, var); - cx.sess.parse_sess.env_depinfo.borrow_mut().insert((var, value)); + cx.sess.psess.env_depinfo.borrow_mut().insert((var, value)); let e = match value { None => { let ExprKind::Lit(token::Lit { diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index 6546a35734c63..06302ae577a7d 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -1,6 +1,6 @@ use rustc_errors::{ codes::*, AddToDiagnostic, Diag, DiagCtxt, EmissionGuarantee, IntoDiagnostic, Level, MultiSpan, - SingleLabelManySpans, SubdiagnosticMessageOp, + SingleLabelManySpans, SubdiagMessageOp, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{symbol::Ident, Span, Symbol}; @@ -590,7 +590,7 @@ pub(crate) struct FormatUnusedArg { // Allow the singular form to be a subdiagnostic of the multiple-unused // form of diagnostic. impl AddToDiagnostic for FormatUnusedArg { - fn add_to_diagnostic_with>( + fn add_to_diagnostic_with>( self, diag: &mut Diag<'_, G>, f: F, @@ -766,6 +766,13 @@ pub(crate) struct AsmNoReturn { pub(crate) outputs_sp: Vec, } +#[derive(Diagnostic)] +#[diag(builtin_macros_asm_mayunwind)] +pub(crate) struct AsmMayUnwind { + #[primary_span] + pub(crate) labels_sp: Vec, +} + #[derive(Diagnostic)] #[diag(builtin_macros_global_asm_clobber_abi)] pub(crate) struct GlobalAsmClobberAbi { diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 0ce9d7ead8217..385c90ff14b2d 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -16,7 +16,7 @@ use rustc_span::symbol::{Ident, Symbol}; use rustc_span::{BytePos, ErrorGuaranteed, InnerSpan, Span}; use rustc_lint_defs::builtin::NAMED_ARGUMENTS_USED_POSITIONALLY; -use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiagnostics, LintId}; +use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiag, LintId}; // The format_args!() macro is expanded in three steps: // 1. First, `parse_args` will parse the `(literal, arg, arg, name=arg, name=arg)` syntax, @@ -553,7 +553,7 @@ fn make_format_args( msg: format!("named argument `{}` is not used by name", arg_name.name).into(), node_id: rustc_ast::CRATE_NODE_ID, lint_id: LintId::of(NAMED_ARGUMENTS_USED_POSITIONALLY), - diagnostic: BuiltinLintDiagnostics::NamedArgumentUsedPositionally { + diagnostic: BuiltinLintDiag::NamedArgumentUsedPositionally { position_sp_to_replace, position_sp_for_msg, named_arg_sp: arg_name.span, diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs index 8e0978de23748..2da9bda19e034 100644 --- a/compiler/rustc_builtin_macros/src/source_util.rs +++ b/compiler/rustc_builtin_macros/src/source_util.rs @@ -118,7 +118,7 @@ pub fn expand_include<'cx>( return DummyResult::any(sp, guar); } }; - let p = new_parser_from_file(cx.parse_sess(), &file, Some(sp)); + let p = new_parser_from_file(cx.psess(), &file, Some(sp)); // If in the included file we have e.g., `mod bar;`, // then the path of `bar.rs` should be relative to the directory of `file`. @@ -136,7 +136,7 @@ pub fn expand_include<'cx>( fn make_expr(mut self: Box>) -> Option> { let expr = parse_expr(&mut self.p).ok()?; if self.p.token != token::Eof { - self.p.sess.buffer_lint( + self.p.psess.buffer_lint( INCOMPLETE_INCLUDE, self.p.token.span, self.node_id, diff --git a/compiler/rustc_builtin_macros/src/standard_library_imports.rs b/compiler/rustc_builtin_macros/src/standard_library_imports.rs index 3ee3112f021ca..9bcd793c45041 100644 --- a/compiler/rustc_builtin_macros/src/standard_library_imports.rs +++ b/compiler/rustc_builtin_macros/src/standard_library_imports.rs @@ -17,7 +17,7 @@ pub fn inject( features: &Features, ) -> usize { let orig_num_items = krate.items.len(); - let edition = sess.parse_sess.edition; + let edition = sess.psess.edition; // the first name in this list is the crate name of the crate with the prelude let names: &[Symbol] = if attr::contains_name(pre_configured_attrs, sym::no_core) { diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index dc28cd2ea31c4..a2015445b42c9 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -159,7 +159,7 @@ struct InnerItemLinter<'a> { impl<'a> Visitor<'a> for InnerItemLinter<'_> { fn visit_item(&mut self, i: &'a ast::Item) { if let Some(attr) = attr::find_by_name(&i.attrs, sym::rustc_test_marker) { - self.sess.parse_sess.buffer_lint( + self.sess.psess.buffer_lint( UNNAMEABLE_TEST_ITEMS, attr.span, i.id, @@ -200,7 +200,7 @@ impl<'a> MutVisitor for EntryPointCleaner<'a> { EntryPointType::MainNamed | EntryPointType::RustcMainAttr | EntryPointType::Start => { item.map(|ast::Item { id, ident, attrs, kind, vis, span, tokens }| { let allow_dead_code = attr::mk_attr_nested_word( - &self.sess.parse_sess.attr_id_generator, + &self.sess.psess.attr_id_generator, ast::AttrStyle::Outer, sym::allow, sym::dead_code, diff --git a/compiler/rustc_builtin_macros/src/util.rs b/compiler/rustc_builtin_macros/src/util.rs index eeaf00004e630..ad6b09ba57458 100644 --- a/compiler/rustc_builtin_macros/src/util.rs +++ b/compiler/rustc_builtin_macros/src/util.rs @@ -9,7 +9,7 @@ pub fn check_builtin_macro_attribute(ecx: &ExtCtxt<'_>, meta_item: &MetaItem, na // All the built-in macro attributes are "words" at the moment. let template = AttributeTemplate { word: true, ..Default::default() }; validate_attr::check_builtin_meta_item( - &ecx.sess.parse_sess, + &ecx.sess.psess, meta_item, AttrStyle::Outer, name, @@ -37,7 +37,7 @@ pub fn warn_on_duplicate_attribute(ecx: &ExtCtxt<'_>, item: &Annotatable, name: }; if let Some(attrs) = attrs { if let Some(attr) = attr::find_by_name(attrs, name) { - ecx.parse_sess().buffer_lint( + ecx.psess().buffer_lint( DUPLICATE_MACRO_ATTRIBUTES, attr.span, ecx.current_expansion.lint_node_id, diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml index cf9a105538df4..5f0f3e6549c90 100644 --- a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml +++ b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml @@ -44,9 +44,10 @@ jobs: env: TARGET_TRIPLE: x86_64-apple-darwin # cross-compile from Linux to Windows using mingw - - os: ubuntu-latest - env: - TARGET_TRIPLE: x86_64-pc-windows-gnu + # FIXME The wine version in Ubuntu 22.04 is missing ProcessPrng + #- os: ubuntu-latest + # env: + # TARGET_TRIPLE: x86_64-pc-windows-gnu - os: ubuntu-latest env: TARGET_TRIPLE: aarch64-unknown-linux-gnu @@ -80,11 +81,11 @@ jobs: if: matrix.os == 'windows-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu' run: rustup set default-host x86_64-pc-windows-gnu - - name: Install MinGW toolchain and wine - if: matrix.os == 'ubuntu-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu' - run: | - sudo apt-get update - sudo apt-get install -y gcc-mingw-w64-x86-64 wine-stable + #- name: Install MinGW toolchain and wine + # if: matrix.os == 'ubuntu-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu' + # run: | + # sudo apt-get update + # sudo apt-get install -y gcc-mingw-w64-x86-64 wine-stable - name: Install AArch64 toolchain and qemu if: matrix.os == 'ubuntu-latest' && matrix.env.TARGET_TRIPLE == 'aarch64-unknown-linux-gnu' diff --git a/compiler/rustc_codegen_cranelift/.gitignore b/compiler/rustc_codegen_cranelift/.gitignore index e6ac8c8408da6..7915fa138f8fc 100644 --- a/compiler/rustc_codegen_cranelift/.gitignore +++ b/compiler/rustc_codegen_cranelift/.gitignore @@ -1,18 +1,21 @@ -/target -/build_system/target -**/*.rs.bk -*.rlib -*.o -perf.data -perf.data.old -*.events -*.string* +# Build artifacts during normal use /y.bin /y.bin.dSYM /y.exe /y.pdb +/download /build /dist +/target +/build_system/target + +# Downloaded by certain scripts /rust -/download /git-fixed-subtree.sh + +# Various things that can be created during development +*.rlib +*.o +perf.data +perf.data.old +*.mm_profdata diff --git a/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock index b70a1234af398..e308cf80284ad 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.lock +++ b/compiler/rustc_codegen_cranelift/Cargo.lock @@ -46,18 +46,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cranelift-bforest" -version = "0.104.0" +version = "0.105.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d819feeda4c420a18f1e28236ca0ce1177b22bf7c8a44ddee92dfe40de15bcf0" +checksum = "9515fcc42b6cb5137f76b84c1a6f819782d0cf12473d145d3bc5cd67eedc8bc2" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.104.0" +version = "0.105.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9b8d03d5bdbca7e5f72b0e0a0f69933ed1f09e24be6c075aa6fe3f802b0cc0c" +checksum = "1ad827c6071bfe6d22de1bc331296a29f9ddc506ff926d8415b435ec6a6efce0" dependencies = [ "bumpalo", "cranelift-bforest", @@ -76,39 +76,39 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.104.0" +version = "0.105.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3fd3664e38e51649b17dc30cfdd561273fe2f590dcd013fb75d9eabc6272dfb" +checksum = "10e6b36237a9ca2ce2fb4cc7741d418a080afa1327402138412ef85d5367bef1" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.104.0" +version = "0.105.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b031ec5e605828975952622b5a77d49126f20ffe88d33719a0af66b23a0fc36" +checksum = "c36bf4bfb86898a94ccfa773a1f86e8a5346b1983ff72059bdd2db4600325251" [[package]] name = "cranelift-control" -version = "0.104.0" +version = "0.105.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fada054d017cf2ed8f7ed2336e0517fc1b19e6825be1790de9eb00c94788362b" +checksum = "7cbf36560e7a6bd1409ca91e7b43b2cc7ed8429f343d7605eadf9046e8fac0d0" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.104.0" +version = "0.105.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "177b6f94ae8de6348eb45bf977c79ab9e3c40fc3ac8cb7ed8109560ea39bee7d" +checksum = "a71e11061a75b1184c09bea97c026a88f08b59ade96a7bb1f259d4ea0df2e942" [[package]] name = "cranelift-frontend" -version = "0.104.0" +version = "0.105.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebebd23a69a23e3ddea78e98ff3a2de222e88c8e045d81ef4a72f042e0d79dbd" +checksum = "af5d4da63143ee3485c7bcedde0a818727d737d1083484a0ceedb8950c89e495" dependencies = [ "cranelift-codegen", "log", @@ -118,15 +118,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.104.0" +version = "0.105.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1571bfc14df8966d12c6121b5325026591a4b4009e22fea0fe3765ab7cd33b96" +checksum = "457a9832b089e26f5eea70dcf49bed8ec6edafed630ce7c83161f24d46ab8085" [[package]] name = "cranelift-jit" -version = "0.104.0" +version = "0.105.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f61e236d7622c3c43016e8b0f3ba27136e21ac7de328c7fda902e61db1de851" +checksum = "0af95fe68d5a10919012c8db82b1d59820405b8001c8c6d05f94b08031334fa9" dependencies = [ "anyhow", "cranelift-codegen", @@ -144,9 +144,9 @@ dependencies = [ [[package]] name = "cranelift-module" -version = "0.104.0" +version = "0.105.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30c6820342015c5009070e3e48d1da7b13521399de904663f1c84f5ee839657" +checksum = "11b0b201fa10a4014062d4c56c307c8d18fdf9a84cb5279efe6080241f42c7a7" dependencies = [ "anyhow", "cranelift-codegen", @@ -155,9 +155,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.104.0" +version = "0.105.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35a69c37e0c10b46fe5527f2397ac821046efbf5f7ec112c8b84df25712f465b" +checksum = "9b490d579df1ce365e1ea359e24ed86d82289fa785153327c2f6a69a59a731e4" dependencies = [ "cranelift-codegen", "libc", @@ -166,9 +166,9 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.104.0" +version = "0.105.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24425a329b4343177d5f1852243841dcec17f929d72c0e7f41262140155e55e7" +checksum = "fb7e821ac6db471bcdbd004e5a4fa0d374f1046bd3a2ce278c332e0b0c01ca63" dependencies = [ "anyhow", "cranelift-codegen", @@ -241,9 +241,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.148" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libloading" @@ -410,9 +410,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "wasmtime-jit-icache-coherence" -version = "17.0.0" +version = "18.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdc26415bb89e9ccd3bdc498fef63aabf665c4c0dd710c107691deb9694955da" +checksum = "33f4121cb29dda08139b2824a734dd095d83ce843f2d613a84eb580b9cfc17ac" dependencies = [ "cfg-if", "libc", diff --git a/compiler/rustc_codegen_cranelift/Cargo.toml b/compiler/rustc_codegen_cranelift/Cargo.toml index 586ce2286f971..c0b9e27b179d3 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.toml +++ b/compiler/rustc_codegen_cranelift/Cargo.toml @@ -8,12 +8,12 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -cranelift-codegen = { version = "0.104", default-features = false, features = ["std", "unwind", "all-arch"] } -cranelift-frontend = { version = "0.104" } -cranelift-module = { version = "0.104" } -cranelift-native = { version = "0.104" } -cranelift-jit = { version = "0.104", optional = true } -cranelift-object = { version = "0.104" } +cranelift-codegen = { version = "0.105.2", default-features = false, features = ["std", "unwind", "all-arch"] } +cranelift-frontend = { version = "0.105.2" } +cranelift-module = { version = "0.105.2" } +cranelift-native = { version = "0.105.2" } +cranelift-jit = { version = "0.105.2", optional = true } +cranelift-object = { version = "0.105.2" } target-lexicon = "0.12.0" gimli = { version = "0.28", default-features = false, features = ["write"]} object = { version = "0.32", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } diff --git a/compiler/rustc_codegen_cranelift/Readme.md b/compiler/rustc_codegen_cranelift/Readme.md index 4f45526196397..a297b22326f37 100644 --- a/compiler/rustc_codegen_cranelift/Readme.md +++ b/compiler/rustc_codegen_cranelift/Readme.md @@ -123,11 +123,6 @@ You need to do this steps to successfully compile and use the cranelift backend You can also set `rust-analyzer.rustc.source` to your rust workspace to get rust-analyzer to understand your changes. -## Configuration - -See the documentation on the `BackendConfig` struct in [config.rs](src/config.rs) for all -configuration options. - ## Not yet supported * SIMD ([tracked here](https://github.com/rust-lang/rustc_codegen_cranelift/issues/171), `std::simd` fully works, `std::arch` is partially supported) diff --git a/compiler/rustc_codegen_cranelift/build_system/prepare.rs b/compiler/rustc_codegen_cranelift/build_system/prepare.rs index c68968b4fde27..3677d0a7d3607 100644 --- a/compiler/rustc_codegen_cranelift/build_system/prepare.rs +++ b/compiler/rustc_codegen_cranelift/build_system/prepare.rs @@ -1,5 +1,6 @@ use std::ffi::OsStr; use std::fs; +use std::hash::{Hash, Hasher}; use std::path::{Path, PathBuf}; use std::process::Command; @@ -71,7 +72,11 @@ fn hash_file(file: &std::path::Path) -> u64 { let contents = std::fs::read(file).unwrap(); #[allow(deprecated)] let mut hasher = std::hash::SipHasher::new(); - std::hash::Hash::hash(&contents, &mut hasher); + // The following is equivalent to + // std::hash::Hash::hash(&contents, &mut hasher); + // but gives the same result independent of host byte order. + hasher.write_usize(contents.len().to_le()); + Hash::hash_slice(&contents, &mut hasher); std::hash::Hasher::finish(&hasher) } @@ -80,16 +85,26 @@ fn hash_dir(dir: &std::path::Path) -> u64 { for entry in std::fs::read_dir(dir).unwrap() { let entry = entry.unwrap(); if entry.file_type().unwrap().is_dir() { - sub_hashes - .insert(entry.file_name().to_str().unwrap().to_owned(), hash_dir(&entry.path())); + sub_hashes.insert( + entry.file_name().to_str().unwrap().to_owned(), + hash_dir(&entry.path()).to_le(), + ); } else { - sub_hashes - .insert(entry.file_name().to_str().unwrap().to_owned(), hash_file(&entry.path())); + sub_hashes.insert( + entry.file_name().to_str().unwrap().to_owned(), + hash_file(&entry.path()).to_le(), + ); } } #[allow(deprecated)] let mut hasher = std::hash::SipHasher::new(); - std::hash::Hash::hash(&sub_hashes, &mut hasher); + // The following is equivalent to + // std::hash::Hash::hash(&sub_hashes, &mut hasher); + // but gives the same result independent of host byte order. + hasher.write_usize(sub_hashes.len().to_le()); + for elt in sub_hashes { + elt.hash(&mut hasher); + } std::hash::Hasher::finish(&hasher) } diff --git a/compiler/rustc_codegen_cranelift/build_system/tests.rs b/compiler/rustc_codegen_cranelift/build_system/tests.rs index 818f3d6f08d26..1c3e615c7aba2 100644 --- a/compiler/rustc_codegen_cranelift/build_system/tests.rs +++ b/compiler/rustc_codegen_cranelift/build_system/tests.rs @@ -133,8 +133,8 @@ pub(crate) static REGEX: CargoProject = CargoProject::new(®EX_REPO.source_dir pub(crate) static PORTABLE_SIMD_REPO: GitRepo = GitRepo::github( "rust-lang", "portable-simd", - "97007cc2e70df8c97326ce896a79e2f0ce4dd98b", - "e54a16035cedf205", + "5794c837bc605c4cd9dbb884285976dfdb293cce", + "a64d8fdd0ed0d9c4", "portable-simd", ); diff --git a/compiler/rustc_codegen_cranelift/example/mini_core.rs b/compiler/rustc_codegen_cranelift/example/mini_core.rs index a79909ce0c878..67a0d0dabea94 100644 --- a/compiler/rustc_codegen_cranelift/example/mini_core.rs +++ b/compiler/rustc_codegen_cranelift/example/mini_core.rs @@ -525,8 +525,11 @@ pub struct Unique { impl CoerceUnsized> for Unique where T: Unsize {} impl DispatchFromDyn> for Unique where T: Unsize {} +#[lang = "global_alloc_ty"] +pub struct Global; + #[lang = "owned_box"] -pub struct Box(Unique, A); +pub struct Box(Unique, A); impl, U: ?Sized> CoerceUnsized> for Box {} @@ -536,7 +539,7 @@ impl Box { let size = intrinsics::size_of::(); let ptr = libc::malloc(size); intrinsics::copy(&val as *const T as *const u8, ptr, size); - Box(Unique { pointer: NonNull(ptr as *const T), _marker: PhantomData }, ()) + Box(Unique { pointer: NonNull(ptr as *const T), _marker: PhantomData }, Global) } } } diff --git a/compiler/rustc_codegen_cranelift/patches/0022-coretests-Disable-not-compiling-tests.patch b/compiler/rustc_codegen_cranelift/patches/0022-coretests-Disable-not-compiling-tests.patch index 6afa5c71fe51f..5442c3cef9ec2 100644 --- a/compiler/rustc_codegen_cranelift/patches/0022-coretests-Disable-not-compiling-tests.patch +++ b/compiler/rustc_codegen_cranelift/patches/0022-coretests-Disable-not-compiling-tests.patch @@ -39,6 +39,6 @@ index 42a26ae..5ac1042 100644 +#![cfg(test)] #![feature(alloc_layout_extra)] #![feature(array_chunks)] - #![feature(array_methods)] + #![feature(array_windows)] -- 2.21.0 (Apple Git-122) diff --git a/compiler/rustc_codegen_cranelift/patches/0023-coretests-Ignore-failing-tests.patch b/compiler/rustc_codegen_cranelift/patches/0023-coretests-Ignore-failing-tests.patch deleted file mode 100644 index 385f5a8a2e039..0000000000000 --- a/compiler/rustc_codegen_cranelift/patches/0023-coretests-Ignore-failing-tests.patch +++ /dev/null @@ -1,26 +0,0 @@ -From dd82e95c9de212524e14fc60155de1ae40156dfc Mon Sep 17 00:00:00 2001 -From: bjorn3 -Date: Sun, 24 Nov 2019 15:34:06 +0100 -Subject: [PATCH] [core] Ignore failing tests - ---- - library/core/tests/iter.rs | 4 ++++ - library/core/tests/num/bignum.rs | 10 ++++++++++ - library/core/tests/num/mod.rs | 5 +++-- - library/core/tests/time.rs | 1 + - 4 files changed, 18 insertions(+), 2 deletions(-) - -diff --git a/atomic.rs b/atomic.rs -index 13b12db..96fe4b9 100644 ---- a/atomic.rs -+++ b/atomic.rs -@@ -185,6 +185,7 @@ fn ptr_bitops() { - } - - #[test] -+#[cfg_attr(target_arch = "s390x", ignore)] // s390x backend doesn't support stack alignment >8 bytes - #[cfg(any(not(target_arch = "arm"), target_os = "linux"))] // Missing intrinsic in compiler-builtins - fn ptr_bitops_tagging() { - #[repr(align(16))] --- -2.21.0 (Apple Git-122) diff --git a/compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml b/compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml index ad63b0768d313..369f9c88be112 100644 --- a/compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml +++ b/compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml @@ -150,9 +150,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" dependencies = [ "compiler_builtins", "rustc-std-workspace-alloc", @@ -161,9 +161,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.150" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" dependencies = [ "rustc-std-workspace-core", ] @@ -398,6 +398,7 @@ version = "0.0.0" dependencies = [ "core", "getopts", + "libc", "panic_abort", "panic_unwind", "std", diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain b/compiler/rustc_codegen_cranelift/rust-toolchain index ccd7edbc2a917..e9f225b4e9e17 100644 --- a/compiler/rustc_codegen_cranelift/rust-toolchain +++ b/compiler/rustc_codegen_cranelift/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2024-01-26" +channel = "nightly-2024-03-08" components = ["rust-src", "rustc-dev", "llvm-tools"] diff --git a/compiler/rustc_codegen_cranelift/rustfmt.toml b/compiler/rustc_codegen_cranelift/rustfmt.toml index 0f884187adddb..6f4d4413c25d0 100644 --- a/compiler/rustc_codegen_cranelift/rustfmt.toml +++ b/compiler/rustc_codegen_cranelift/rustfmt.toml @@ -1,5 +1,4 @@ ignore = [ - "y.rs", "example/gen_block_iterate.rs", # uses edition 2024 ] diff --git a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh index 636f2875a6873..e884577d519da 100755 --- a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh +++ b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh @@ -10,12 +10,26 @@ pushd rust command -v rg >/dev/null 2>&1 || cargo install ripgrep +# FIXME(rust-lang/rust#122196) fix stage0 rmake.rs run-make tests and remove +# this workaround +for test in $(ls tests/run-make); do + if [[ -e "tests/run-make/$test/rmake.rs" ]]; then + rm -r "tests/run-make/$test" + fi +done + +# FIXME remove this workaround once ICE tests no longer emit an outdated nightly message +for test in $(rg -i --files-with-matches "//@(\[.*\])? failure-status: 101" tests/ui); do + echo "rm $test" + rm $test +done + rm -r tests/ui/{unsized-locals/,lto/,linkage*} || true for test in $(rg --files-with-matches "lto" tests/{codegen-units,ui,incremental}); do rm $test done -for test in $(rg -i --files-with-matches "//(\[\w+\])?~[^\|]*\s*ERR|// error-pattern:|// build-fail|// run-fail|-Cllvm-args" tests/ui); do +for test in $(rg -i --files-with-matches "//(\[\w+\])?~[^\|]*\s*ERR|//@ error-pattern:|//@(\[.*\])? build-fail|//@(\[.*\])? run-fail|-Cllvm-args" tests/ui); do rm $test done @@ -43,8 +57,8 @@ rm tests/ui/proc-macro/allowed-signatures.rs rm tests/ui/proc-macro/no-mangle-in-proc-macro-issue-111888.rs # vendor intrinsics -rm tests/ui/sse2.rs # CodegenBackend::target_features not yet implemented rm tests/ui/simd/array-type.rs # "Index argument for `simd_insert` is not a constant" +rm tests/ui/asm/x86_64/evex512-implicit-feature.rs # unimplemented AVX512 x86 vendor intrinsic # exotic linkages rm tests/ui/issues/issue-33992.rs # unsupported linkages @@ -62,14 +76,12 @@ rm -r tests/run-pass-valgrind/unsized-locals # misc unimplemented things rm tests/ui/intrinsics/intrinsic-nearby.rs # unimplemented nearbyintf32 and nearbyintf64 intrinsics rm tests/ui/target-feature/missing-plusminus.rs # error not implemented -rm tests/ui/fn/dyn-fn-alignment.rs # wants a 256 byte alignment rm -r tests/run-make/emit-named-files # requires full --emit support rm -r tests/run-make/repr128-dwarf # debuginfo test rm -r tests/run-make/split-debuginfo # same rm -r tests/run-make/symbols-include-type-name # --emit=asm not supported rm -r tests/run-make/target-specs # i686 not supported by Cranelift rm -r tests/run-make/mismatching-target-triples # same -rm tests/ui/asm/x86_64/issue-82869.rs # vector regs in inline asm not yet supported rm tests/ui/asm/x86_64/issue-96797.rs # const and sym inline asm operands don't work entirely correctly # requires LTO @@ -109,8 +121,6 @@ rm -r tests/run-make/optimization-remarks-dir # remarks are LLVM specific rm tests/ui/mir/mir_misc_casts.rs # depends on deduplication of constants rm tests/ui/mir/mir_raw_fat_ptr.rs # same rm tests/ui/consts/issue-33537.rs # same -rm tests/ui/layout/valid_range_oob.rs # different ICE message -rm tests/ui/const-generics/generic_const_exprs/issue-80742.rs # gives error instead of ICE with cg_clif # rustdoc-clif passes extra args, suppressing the help message when no args are passed rm -r tests/run-make/issue-88756-default-output @@ -119,15 +129,12 @@ rm -r tests/run-make/issue-88756-default-output # should work when using ./x.py test the way it is intended # ============================================================ rm -r tests/run-make/remap-path-prefix-dwarf # requires llvm-dwarfdump -rm -r tests/ui/consts/missing_span_in_backtrace.rs # expects sysroot source to be elsewhere # genuine bugs # ============ rm tests/incremental/spike-neg1.rs # errors out for some reason rm tests/incremental/spike-neg2.rs # same -rm tests/ui/simd/simd-bitmask.rs # simd_bitmask doesn't implement [u*; N] return type - rm -r tests/run-make/issue-51671 # wrong filename given in case of --emit=obj rm -r tests/run-make/issue-30063 # same rm -r tests/run-make/multiple-emits # same @@ -145,6 +152,7 @@ rm tests/ui/codegen/subtyping-enforces-type-equality.rs # assert_assignable bug # ====================== rm tests/ui/backtrace.rs # TODO warning rm tests/ui/process/nofile-limit.rs # TODO some AArch64 linking issue +rm tests/ui/async-await/async-closures/once.rs # FIXME bug in the rustc FnAbi calculation code rm tests/ui/stdio-is-blocking.rs # really slow with unoptimized libstd diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index a7e76fbc128ea..1ce920f3bdb79 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -445,7 +445,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { template, operands, options, - destination, + targets, line_spans: _, unwind: _, } => { @@ -456,13 +456,25 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { ); } + let have_labels = if options.contains(InlineAsmOptions::NORETURN) { + !targets.is_empty() + } else { + targets.len() > 1 + }; + if have_labels { + fx.tcx.dcx().span_fatal( + source_info.span, + "cranelift doesn't support labels in inline assembly.", + ); + } + crate::inline_asm::codegen_inline_asm_terminator( fx, source_info.span, template, operands, *options, - *destination, + targets.get(0).copied(), ); } TerminatorKind::UnwindTerminate(reason) => { diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index e35ec4fe1c748..7e29d407a1fa3 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -392,18 +392,25 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { } pub(crate) fn create_stack_slot(&mut self, size: u32, align: u32) -> Pointer { - if align <= 16 { + let abi_align = if self.tcx.sess.target.arch == "s390x" { 8 } else { 16 }; + if align <= abi_align { let stack_slot = self.bcx.create_sized_stack_slot(StackSlotData { kind: StackSlotKind::ExplicitSlot, - // FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to - // specify stack slot alignment. - size: (size + 15) / 16 * 16, + // FIXME Don't force the size to a multiple of bytes once Cranelift gets + // a way to specify stack slot alignment. + size: (size + abi_align - 1) / abi_align * abi_align, }); Pointer::stack_slot(stack_slot) } else { // Alignment is too big to handle using the above hack. Dynamically realign a stack slot // instead. This wastes some space for the realignment. - let base_ptr = self.create_stack_slot(size + align, 16).get_addr(self); + let stack_slot = self.bcx.create_sized_stack_slot(StackSlotData { + kind: StackSlotKind::ExplicitSlot, + // FIXME Don't force the size to a multiple of bytes once Cranelift gets + // a way to specify stack slot alignment. + size: (size + align) / abi_align * abi_align, + }); + let base_ptr = self.bcx.ins().stack_addr(self.pointer_type, stack_slot, 0); let misalign_offset = self.bcx.ins().urem_imm(base_ptr, i64::from(align)); let realign_offset = self.bcx.ins().irsub_imm(misalign_offset, i64::from(align)); Pointer::new(self.bcx.ins().iadd(base_ptr, realign_offset)) diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index b6de688130c79..18c5960ffc68a 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -372,7 +372,13 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant } let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.len()).to_vec(); - data.define(bytes.into_boxed_slice()); + if bytes.is_empty() { + // FIXME(bytecodealliance/wasmtime#7918) cranelift-jit has a bug where it causes UB on + // empty data objects + data.define(Box::new([0])); + } else { + data.define(bytes.into_boxed_slice()); + } for &(offset, prov) in alloc.provenance().ptrs().iter() { let alloc_id = prov.alloc_id(); diff --git a/compiler/rustc_codegen_cranelift/src/global_asm.rs b/compiler/rustc_codegen_cranelift/src/global_asm.rs index da07b66c762ee..44650898de897 100644 --- a/compiler/rustc_codegen_cranelift/src/global_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/global_asm.rs @@ -78,7 +78,8 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, InlineAsmOperand::In { .. } | InlineAsmOperand::Out { .. } | InlineAsmOperand::InOut { .. } - | InlineAsmOperand::SplitInOut { .. } => { + | InlineAsmOperand::SplitInOut { .. } + | InlineAsmOperand::Label { .. } => { span_bug!(op_sp, "invalid operand type for global_asm!") } } diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs index 7793b1b70924b..171ee88a11c75 100644 --- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs @@ -129,6 +129,9 @@ pub(crate) fn codegen_inline_asm_terminator<'tcx>( let instance = Instance::mono(fx.tcx, def_id).polymorphize(fx.tcx); CInlineAsmOperand::Symbol { symbol: fx.tcx.symbol_name(instance).name.to_owned() } } + InlineAsmOperand::Label { .. } => { + span_bug!(span, "asm! label operands are not yet supported"); + } }) .collect::>(); diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs index 2e3e7ce986b36..1615dc5de697b 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs @@ -170,6 +170,65 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( } } + "llvm.x86.sse.add.ss" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_add_ss&ig_expand=171 + intrinsic_args!(fx, args => (a, b); intrinsic); + + assert_eq!(a.layout(), b.layout()); + assert_eq!(a.layout(), ret.layout()); + let layout = a.layout(); + + let (_, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + assert!(lane_ty.is_floating_point()); + let ret_lane_layout = fx.layout_of(lane_ty); + + ret.write_cvalue(fx, a); + + let a_lane = a.value_lane(fx, 0).load_scalar(fx); + let b_lane = b.value_lane(fx, 0).load_scalar(fx); + + let res = fx.bcx.ins().fadd(a_lane, b_lane); + + let res_lane = CValue::by_val(res, ret_lane_layout); + ret.place_lane(fx, 0).write_cvalue(fx, res_lane); + } + + "llvm.x86.sse.sqrt.ps" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sqrt_ps&ig_expand=6245 + intrinsic_args!(fx, args => (a); intrinsic); + + // FIXME use vector instructions when possible + simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| { + fx.bcx.ins().sqrt(lane) + }); + } + + "llvm.x86.sse.max.ps" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_max_ps&ig_expand=4357 + intrinsic_args!(fx, args => (a, b); intrinsic); + + simd_pair_for_each_lane( + fx, + a, + b, + ret, + &|fx, _lane_ty, _res_lane_ty, a_lane, b_lane| fx.bcx.ins().fmax(a_lane, b_lane), + ); + } + + "llvm.x86.sse.min.ps" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_min_ps&ig_expand=4489 + intrinsic_args!(fx, args => (a, b); intrinsic); + + simd_pair_for_each_lane( + fx, + a, + b, + ret, + &|fx, _lane_ty, _res_lane_ty, a_lane, b_lane| fx.bcx.ins().fmin(a_lane, b_lane), + ); + } + "llvm.x86.sse.cmp.ps" | "llvm.x86.sse2.cmp.pd" => { let (x, y, kind) = match args { [x, y, kind] => (x, y, kind), @@ -1067,6 +1126,122 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( ); } + "llvm.x86.sha1rnds4" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sha1rnds4_epu32&ig_expand=5877 + intrinsic_args!(fx, args => (a, b, _func); intrinsic); + + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); + + let func = if let Some(func) = + crate::constant::mir_operand_get_const_val(fx, &args[2].node) + { + func + } else { + fx.tcx + .dcx() + .span_fatal(span, "Func argument for `_mm_sha1rnds4_epu32` is not a constant"); + }; + + let func = func.try_to_u8().unwrap_or_else(|_| panic!("kind not scalar: {:?}", func)); + + codegen_inline_asm_inner( + fx, + &[InlineAsmTemplatePiece::String(format!("sha1rnds4 xmm1, xmm2, {func}"))], + &[ + CInlineAsmOperand::InOut { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)), + _late: true, + in_value: a, + out_place: Some(ret), + }, + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm2)), + value: b, + }, + ], + InlineAsmOptions::NOSTACK | InlineAsmOptions::PURE | InlineAsmOptions::NOMEM, + ); + } + + "llvm.x86.sha1msg1" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sha1msg1_epu32&ig_expand=5874 + intrinsic_args!(fx, args => (a, b); intrinsic); + + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); + + codegen_inline_asm_inner( + fx, + &[InlineAsmTemplatePiece::String("sha1msg1 xmm1, xmm2".to_string())], + &[ + CInlineAsmOperand::InOut { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)), + _late: true, + in_value: a, + out_place: Some(ret), + }, + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm2)), + value: b, + }, + ], + InlineAsmOptions::NOSTACK | InlineAsmOptions::PURE | InlineAsmOptions::NOMEM, + ); + } + + "llvm.x86.sha1msg2" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sha1msg2_epu32&ig_expand=5875 + intrinsic_args!(fx, args => (a, b); intrinsic); + + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); + + codegen_inline_asm_inner( + fx, + &[InlineAsmTemplatePiece::String("sha1msg2 xmm1, xmm2".to_string())], + &[ + CInlineAsmOperand::InOut { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)), + _late: true, + in_value: a, + out_place: Some(ret), + }, + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm2)), + value: b, + }, + ], + InlineAsmOptions::NOSTACK | InlineAsmOptions::PURE | InlineAsmOptions::NOMEM, + ); + } + + "llvm.x86.sha1nexte" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sha1nexte_epu32&ig_expand=5876 + intrinsic_args!(fx, args => (a, b); intrinsic); + + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); + + codegen_inline_asm_inner( + fx, + &[InlineAsmTemplatePiece::String("sha1nexte xmm1, xmm2".to_string())], + &[ + CInlineAsmOperand::InOut { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)), + _late: true, + in_value: a, + out_place: Some(ret), + }, + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm2)), + value: b, + }, + ], + InlineAsmOptions::NOSTACK | InlineAsmOptions::PURE | InlineAsmOptions::NOMEM, + ); + } + "llvm.x86.sha256rnds2" => { // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sha256rnds2_epu32&ig_expand=5977 intrinsic_args!(fx, args => (a, b, k); intrinsic); diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index 84269ec294263..8b86a116df1fd 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -391,12 +391,15 @@ fn codegen_float_intrinsic_call<'tcx>( | sym::ceilf32 | sym::ceilf64 | sym::truncf32 - | sym::truncf64 => { + | sym::truncf64 + | sym::sqrtf32 + | sym::sqrtf64 => { let val = match intrinsic { sym::fabsf32 | sym::fabsf64 => fx.bcx.ins().fabs(args[0]), sym::floorf32 | sym::floorf64 => fx.bcx.ins().floor(args[0]), sym::ceilf32 | sym::ceilf64 => fx.bcx.ins().ceil(args[0]), sym::truncf32 | sym::truncf64 => fx.bcx.ins().trunc(args[0]), + sym::sqrtf32 | sym::sqrtf64 => fx.bcx.ins().sqrt(args[0]), _ => unreachable!(), }; @@ -1255,7 +1258,17 @@ fn codegen_regular_intrinsic_call<'tcx>( // Unimplemented intrinsics must have a fallback body. The fallback body is obtained // by converting the `InstanceDef::Intrinsic` to an `InstanceDef::Item`. - _ => return Err(Instance::new(instance.def_id(), instance.args)), + _ => { + let intrinsic = fx.tcx.intrinsic(instance.def_id()).unwrap(); + if intrinsic.must_be_overridden { + span_bug!( + source_info.span, + "intrinsic {} must be overridden by codegen_cranelift, but isn't", + intrinsic.name, + ); + } + return Err(Instance::new(instance.def_id(), instance.args)); + } } let ret_block = fx.get_block(destination.unwrap()); diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs index 8f662808522b7..79da970a58efe 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs @@ -853,7 +853,13 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( }; for lane in 0..lane_count { - let m_lane = fx.bcx.ins().ushr_imm(m, u64::from(lane) as i64); + // The bit order of the mask depends on the byte endianness, LSB-first for + // little endian and MSB-first for big endian. + let mask_lane = match fx.tcx.sess.target.endian { + Endian::Big => lane_count - 1 - lane, + Endian::Little => lane, + }; + let m_lane = fx.bcx.ins().ushr_imm(m, u64::from(mask_lane) as i64); let m_lane = fx.bcx.ins().band_imm(m_lane, 1); let a_lane = a.value_lane(fx, lane).load_scalar(fx); let b_lane = b.value_lane(fx, lane).load_scalar(fx); diff --git a/compiler/rustc_codegen_cranelift/src/unsize.rs b/compiler/rustc_codegen_cranelift/src/unsize.rs index acfa461a6f30b..7b61dc64cb1ae 100644 --- a/compiler/rustc_codegen_cranelift/src/unsize.rs +++ b/compiler/rustc_codegen_cranelift/src/unsize.rs @@ -74,10 +74,6 @@ fn unsize_ptr<'tcx>( | (&ty::RawPtr(ty::TypeAndMut { ty: a, .. }), &ty::RawPtr(ty::TypeAndMut { ty: b, .. })) => { (src, unsized_info(fx, *a, *b, old_info)) } - (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) if def_a.is_box() && def_b.is_box() => { - let (a, b) = (src_layout.ty.boxed_ty(), dst_layout.ty.boxed_ty()); - (src, unsized_info(fx, a, b, old_info)) - } (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => { assert_eq!(def_a, def_b); diff --git a/compiler/rustc_codegen_cranelift/y.rs b/compiler/rustc_codegen_cranelift/y.rs deleted file mode 100755 index e806a64d94344..0000000000000 --- a/compiler/rustc_codegen_cranelift/y.rs +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash -#![deny(unsafe_code)] /*This line is ignored by bash -# This block is ignored by rustc -echo "Warning: y.rs is a deprecated alias for y.sh" 1>&2 -exec ./y.sh "$@" -*/ diff --git a/compiler/rustc_codegen_gcc/example/mini_core.rs b/compiler/rustc_codegen_gcc/example/mini_core.rs index 230009741dc41..cc3d647c8c82f 100644 --- a/compiler/rustc_codegen_gcc/example/mini_core.rs +++ b/compiler/rustc_codegen_gcc/example/mini_core.rs @@ -472,6 +472,7 @@ pub trait Allocator { impl Allocator for () {} +#[lang = "global_alloc_ty"] pub struct Global; impl Allocator for Global {} diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs index a237f3e6490cb..f8afc5c3eb43a 100644 --- a/compiler/rustc_codegen_gcc/src/asm.rs +++ b/compiler/rustc_codegen_gcc/src/asm.rs @@ -114,7 +114,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { options: InlineAsmOptions, span: &[Span], instance: Instance<'_>, - _dest_catch_funclet: Option<(Self::BasicBlock, Self::BasicBlock, Option<&Self::Funclet>)>, + _catch_funclet: Option<(Self::BasicBlock, Self::BasicBlock, Option<&Self::Funclet>)>, ) { if options.contains(InlineAsmOptions::MAY_UNWIND) { self.sess().dcx().create_err(UnwindingInlineAsm { span: span[0] }).emit(); @@ -132,6 +132,10 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { // added to `outputs.len()` let mut inputs = vec![]; + // GCC index of a label equals its position in the array added to + // `outputs.len() + inputs.len()`. + let mut labels = vec![]; + // Clobbers collected from `out("explicit register") _` and `inout("expl_reg") var => _` let mut clobbers = vec![]; @@ -283,6 +287,10 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { constants_len += self.tcx.symbol_name(Instance::mono(self.tcx, def_id)).name.len(); } + + InlineAsmOperandRef::Label { label } => { + labels.push(label); + } } } @@ -381,6 +389,10 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { InlineAsmOperandRef::Const { .. } => { // processed in the previous pass } + + InlineAsmOperandRef::Label { .. } => { + // processed in the previous pass + } } } @@ -470,6 +482,14 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { InlineAsmOperandRef::Const { ref string } => { template_str.push_str(string); } + + InlineAsmOperandRef::Label { label } => { + let label_gcc_index = labels.iter() + .position(|&l| l == label) + .expect("wrong rust index"); + let gcc_index = label_gcc_index + outputs.len() + inputs.len(); + push_to_template(Some('l'), gcc_index); + } } } } @@ -482,7 +502,12 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { // 4. Generate Extended Asm block let block = self.llbb(); - let extended_asm = block.add_extended_asm(None, &template_str); + let extended_asm = if let Some(dest) = dest { + assert!(!labels.is_empty()); + block.end_with_extended_asm_goto(None, &template_str, &labels, Some(dest)) + } else { + block.add_extended_asm(None, &template_str) + }; for op in &outputs { extended_asm.add_output_operand(None, &op.to_constraint(), op.tmp_var); @@ -510,7 +535,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { if !options.contains(InlineAsmOptions::NOSTACK) { // TODO(@Commeownist): figure out how to align stack } - if options.contains(InlineAsmOptions::NORETURN) { + if dest.is_none() && options.contains(InlineAsmOptions::NORETURN) { let builtin_unreachable = self.context.get_builtin_function("__builtin_unreachable"); let builtin_unreachable: RValue<'gcc> = unsafe { std::mem::transmute(builtin_unreachable) }; diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index a413466093bed..74539d4d49570 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -28,7 +28,8 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { options: InlineAsmOptions, line_spans: &[Span], instance: Instance<'_>, - dest_catch_funclet: Option<(Self::BasicBlock, Self::BasicBlock, Option<&Self::Funclet>)>, + dest: Option, + catch_funclet: Option<(Self::BasicBlock, Option<&Self::Funclet>)>, ) { let asm_arch = self.tcx.sess.asm_arch.unwrap(); @@ -165,6 +166,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { } // Build the template string + let mut labels = vec![]; let mut template_str = String::new(); for piece in template { match *piece { @@ -205,6 +207,11 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { // Only emit the raw symbol name template_str.push_str(&format!("${{{}:c}}", op_idx[&operand_idx])); } + InlineAsmOperandRef::Label { label } => { + template_str.push_str(&format!("${{{}:l}}", constraints.len())); + constraints.push("!i".to_owned()); + labels.push(label); + } } } } @@ -292,12 +299,14 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { &constraints.join(","), &inputs, output_type, + &labels, volatile, alignstack, dialect, line_spans, options.contains(InlineAsmOptions::MAY_UNWIND), - dest_catch_funclet, + dest, + catch_funclet, ) .unwrap_or_else(|| span_bug!(line_spans[0], "LLVM asm constraint validation failed")); @@ -317,7 +326,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { attributes::apply_to_callsite(result, llvm::AttributePlace::Function, &{ attrs }); // Switch to the 'normal' basic block if we did an `invoke` instead of a `call` - if let Some((dest, _, _)) = dest_catch_funclet { + if let Some(dest) = dest { self.switch_to_block(dest); } @@ -415,16 +424,14 @@ pub(crate) fn inline_asm_call<'ll>( cons: &str, inputs: &[&'ll Value], output: &'ll llvm::Type, + labels: &[&'ll llvm::BasicBlock], volatile: bool, alignstack: bool, dia: llvm::AsmDialect, line_spans: &[Span], unwind: bool, - dest_catch_funclet: Option<( - &'ll llvm::BasicBlock, - &'ll llvm::BasicBlock, - Option<&Funclet<'ll>>, - )>, + dest: Option<&'ll llvm::BasicBlock>, + catch_funclet: Option<(&'ll llvm::BasicBlock, Option<&Funclet<'ll>>)>, ) -> Option<&'ll Value> { let volatile = if volatile { llvm::True } else { llvm::False }; let alignstack = if alignstack { llvm::True } else { llvm::False }; @@ -457,8 +464,11 @@ pub(crate) fn inline_asm_call<'ll>( can_throw, ); - let call = if let Some((dest, catch, funclet)) = dest_catch_funclet { - bx.invoke(fty, None, None, v, inputs, dest, catch, funclet) + let call = if !labels.is_empty() { + assert!(catch_funclet.is_none()); + bx.callbr(fty, None, None, v, inputs, dest.unwrap(), labels, None) + } else if let Some((catch, funclet)) = catch_funclet { + bx.invoke(fty, None, None, v, inputs, dest.unwrap(), catch, funclet) } else { bx.call(fty, None, None, v, inputs, None) }; diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs index ca43ac4b0e71a..0619000364b84 100644 --- a/compiler/rustc_codegen_llvm/src/back/archive.rs +++ b/compiler/rustc_codegen_llvm/src/back/archive.rs @@ -55,6 +55,7 @@ fn llvm_machine_type(cpu: &str) -> LLVMMachineType { "x86_64" => LLVMMachineType::AMD64, "x86" => LLVMMachineType::I386, "aarch64" => LLVMMachineType::ARM64, + "arm64ec" => LLVMMachineType::ARM64EC, "arm" => LLVMMachineType::ARM, _ => panic!("unsupported cpu type {cpu}"), } diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index eaedaec635fb4..ca2e2b575805f 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -1538,6 +1538,58 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { } } + pub(crate) fn callbr( + &mut self, + llty: &'ll Type, + fn_attrs: Option<&CodegenFnAttrs>, + fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, + llfn: &'ll Value, + args: &[&'ll Value], + default_dest: &'ll BasicBlock, + indirect_dest: &[&'ll BasicBlock], + funclet: Option<&Funclet<'ll>>, + ) -> &'ll Value { + debug!("invoke {:?} with args ({:?})", llfn, args); + + let args = self.check_call("callbr", llty, llfn, args); + let funclet_bundle = funclet.map(|funclet| funclet.bundle()); + let funclet_bundle = funclet_bundle.as_ref().map(|b| &*b.raw); + let mut bundles: SmallVec<[_; 2]> = SmallVec::new(); + if let Some(funclet_bundle) = funclet_bundle { + bundles.push(funclet_bundle); + } + + // Emit CFI pointer type membership test + self.cfi_type_test(fn_attrs, fn_abi, llfn); + + // Emit KCFI operand bundle + let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, llfn); + let kcfi_bundle = kcfi_bundle.as_ref().map(|b| &*b.raw); + if let Some(kcfi_bundle) = kcfi_bundle { + bundles.push(kcfi_bundle); + } + + let callbr = unsafe { + llvm::LLVMRustBuildCallBr( + self.llbuilder, + llty, + llfn, + default_dest, + indirect_dest.as_ptr(), + indirect_dest.len() as c_uint, + args.as_ptr(), + args.len() as c_uint, + bundles.as_ptr(), + bundles.len() as c_uint, + UNNAMED, + ) + }; + if let Some(fn_abi) = fn_abi { + fn_abi.apply_attrs_callsite(self, callbr); + } + callbr + } + // Emits CFI pointer type membership tests. fn cfi_type_test( &mut self, diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 16122e5557e9c..d1f32087908ee 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -260,35 +260,29 @@ pub unsafe fn create_module<'ll>( } if let Some(BranchProtection { bti, pac_ret }) = sess.opts.unstable_opts.branch_protection { - let behavior = if llvm_version >= (15, 0, 0) { - llvm::LLVMModFlagBehavior::Min - } else { - llvm::LLVMModFlagBehavior::Error - }; - if sess.target.arch == "aarch64" { llvm::LLVMRustAddModuleFlag( llmod, - behavior, + llvm::LLVMModFlagBehavior::Min, c"branch-target-enforcement".as_ptr().cast(), bti.into(), ); llvm::LLVMRustAddModuleFlag( llmod, - behavior, + llvm::LLVMModFlagBehavior::Min, c"sign-return-address".as_ptr().cast(), pac_ret.is_some().into(), ); let pac_opts = pac_ret.unwrap_or(PacRet { leaf: false, key: PAuthKey::A }); llvm::LLVMRustAddModuleFlag( llmod, - behavior, + llvm::LLVMModFlagBehavior::Min, c"sign-return-address-all".as_ptr().cast(), pac_opts.leaf.into(), ); llvm::LLVMRustAddModuleFlag( llmod, - behavior, + llvm::LLVMModFlagBehavior::Min, c"sign-return-address-with-bkey".as_ptr().cast(), u32::from(pac_opts.key == PAuthKey::B), ); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 1a5f9b4294754..660f164736775 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -454,9 +454,13 @@ pub fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll D ty::RawPtr(ty::TypeAndMut { ty: pointee_type, .. }) | ty::Ref(_, pointee_type, _) => { build_pointer_or_reference_di_node(cx, t, pointee_type, unique_type_id) } - // Box may have a non-1-ZST allocator A. In that case, we - // cannot treat Box as just an owned alias of `*mut T`. - ty::Adt(def, args) if def.is_box() && cx.layout_of(args.type_at(1)).is_1zst() => { + // Some `Box` are newtyped pointers, make debuginfo aware of that. + // Only works if the allocator argument is a 1-ZST and hence irrelevant for layout + // (or if there is no allocator argument). + ty::Adt(def, args) + if def.is_box() + && args.get(1).map_or(true, |arg| cx.layout_of(arg.expect_ty()).is_1zst()) => + { build_pointer_or_reference_di_node(cx, t, t.boxed_ty(), unique_type_id) } ty::FnDef(..) | ty::FnPtr(_) => build_subroutine_type_di_node(cx, unique_type_id), diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index f33a672aff0d7..467e02d55e332 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -448,12 +448,14 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> { constraint, inputs, self.type_void(), + &[], true, false, llvm::AsmDialect::Att, &[span], false, None, + None, ) .unwrap_or_else(|| bug!("failed to generate inline asm call for `black_box`")); diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 952f41fbd90e5..58e9803706737 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -56,6 +56,7 @@ pub enum LLVMMachineType { AMD64 = 0x8664, I386 = 0x14c, ARM64 = 0xaa64, + ARM64EC = 0xa641, ARM = 0x01c0, } @@ -1615,6 +1616,20 @@ extern "C" { Name: *const c_char, ) -> &'a Value; + pub fn LLVMRustBuildCallBr<'a>( + B: &Builder<'a>, + Ty: &'a Type, + Fn: &'a Value, + DefaultDest: &'a BasicBlock, + IndirectDests: *const &'a BasicBlock, + NumIndirectDests: c_uint, + Args: *const &'a Value, + NumArgs: c_uint, + OpBundles: *const &OperandBundleDef<'a>, + NumOpBundles: c_uint, + Name: *const c_char, + ) -> &'a Value; + pub fn LLVMRustSetFastMath(Instr: &Value); pub fn LLVMRustSetAlgebraicMath(Instr: &Value); pub fn LLVMRustSetAllowReassoc(Instr: &Value); diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 75a189aa87c01..78d47f36f918b 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -201,7 +201,13 @@ impl<'a> IntoIterator for LLVMFeature<'a> { // which might lead to failures if the oldest tested / supported LLVM version // doesn't yet support the relevant intrinsics pub fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> LLVMFeature<'a> { - let arch = if sess.target.arch == "x86_64" { "x86" } else { &*sess.target.arch }; + let arch = if sess.target.arch == "x86_64" { + "x86" + } else if sess.target.arch == "arm64ec" { + "aarch64" + } else { + &*sess.target.arch + }; match (arch, s) { ("x86", "sse4.2") => { LLVMFeature::with_dependency("sse4.2", TargetFeatureFoldStrength::EnableOnly("crc32")) diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs index b406a04af7474..220bb77d3fda3 100644 --- a/compiler/rustc_codegen_llvm/src/va_arg.rs +++ b/compiler/rustc_codegen_llvm/src/va_arg.rs @@ -288,7 +288,7 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( // Generic x86 "x86" => emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(4).unwrap(), true), // Windows AArch64 - "aarch64" if target.is_like_windows => { + "aarch64" | "arm64ec" if target.is_like_windows => { emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(8).unwrap(), false) } // macOS / iOS AArch64 diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 9359df5de6a77..81ca42e1ad802 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" # tidy-alphabetical-start ar_archive_writer = "0.1.5" bitflags = "2.4.1" -cc = "1.0.69" +cc = "1.0.90" itertools = "0.11" jobserver = "0.1.28" pathdiff = "0.2.0" diff --git a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs index cbee4877122f0..7ecc386434778 100644 --- a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs +++ b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs @@ -176,7 +176,7 @@ impl<'tcx> AssertModuleSource<'tcx> { /// Scan for a `cfg="foo"` attribute and check whether we have a /// cfg flag called `foo`. fn check_config(&self, attr: &ast::Attribute) -> bool { - let config = &self.tcx.sess.parse_sess.config; + let config = &self.tcx.sess.psess.config; let value = self.field(attr, sym::cfg); debug!("check_config(config={:?}, value={:?})", config, value); if config.iter().any(|&(name, _)| name == value) { diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index 158b8fb8727c0..ab1bc0b6cd2eb 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -8,7 +8,7 @@ use std::path::Path; use object::write::{self, StandardSegment, Symbol, SymbolSection}; use object::{ elf, pe, xcoff, Architecture, BinaryFormat, Endianness, FileFlags, Object, ObjectSection, - ObjectSymbol, SectionFlags, SectionKind, SymbolFlags, SymbolKind, SymbolScope, + ObjectSymbol, SectionFlags, SectionKind, SubArchitecture, SymbolFlags, SymbolKind, SymbolScope, }; use rustc_data_structures::memmap::Mmap; @@ -182,37 +182,40 @@ pub(crate) fn create_object_file(sess: &Session) -> Option Endianness::Little, Endian::Big => Endianness::Big, }; - let architecture = match &sess.target.arch[..] { - "arm" => Architecture::Arm, - "aarch64" => { + let (architecture, sub_architecture) = match &sess.target.arch[..] { + "arm" => (Architecture::Arm, None), + "aarch64" => ( if sess.target.pointer_width == 32 { Architecture::Aarch64_Ilp32 } else { Architecture::Aarch64 - } - } - "x86" => Architecture::I386, - "s390x" => Architecture::S390x, - "mips" | "mips32r6" => Architecture::Mips, - "mips64" | "mips64r6" => Architecture::Mips64, - "x86_64" => { + }, + None, + ), + "x86" => (Architecture::I386, None), + "s390x" => (Architecture::S390x, None), + "mips" | "mips32r6" => (Architecture::Mips, None), + "mips64" | "mips64r6" => (Architecture::Mips64, None), + "x86_64" => ( if sess.target.pointer_width == 32 { Architecture::X86_64_X32 } else { Architecture::X86_64 - } - } - "powerpc" => Architecture::PowerPc, - "powerpc64" => Architecture::PowerPc64, - "riscv32" => Architecture::Riscv32, - "riscv64" => Architecture::Riscv64, - "sparc64" => Architecture::Sparc64, - "avr" => Architecture::Avr, - "msp430" => Architecture::Msp430, - "hexagon" => Architecture::Hexagon, - "bpf" => Architecture::Bpf, - "loongarch64" => Architecture::LoongArch64, - "csky" => Architecture::Csky, + }, + None, + ), + "powerpc" => (Architecture::PowerPc, None), + "powerpc64" => (Architecture::PowerPc64, None), + "riscv32" => (Architecture::Riscv32, None), + "riscv64" => (Architecture::Riscv64, None), + "sparc64" => (Architecture::Sparc64, None), + "avr" => (Architecture::Avr, None), + "msp430" => (Architecture::Msp430, None), + "hexagon" => (Architecture::Hexagon, None), + "bpf" => (Architecture::Bpf, None), + "loongarch64" => (Architecture::LoongArch64, None), + "csky" => (Architecture::Csky, None), + "arm64ec" => (Architecture::Aarch64, Some(SubArchitecture::Arm64EC)), // Unsupported architecture. _ => return None, }; @@ -227,6 +230,7 @@ pub(crate) fn create_object_file(sess: &Session) -> Option Option e_flags |= elf::EF_LARCH_ABI_SOFT_FLOAT, "ilp32f" | "lp64f" => e_flags |= elf::EF_LARCH_ABI_SINGLE_FLOAT, "ilp32d" | "lp64d" => e_flags |= elf::EF_LARCH_ABI_DOUBLE_FLOAT, - _ => bug!("unknown RISC-V ABI name"), + _ => bug!("unknown LoongArch ABI name"), } e_flags diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 2dba04e0bb71b..72648e5ade497 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -81,6 +81,10 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap {} @@ -563,9 +567,10 @@ pub fn linking_symbol_name_for_instance_in_crate<'tcx>( return undecorated; } - let x86 = match &target.arch[..] { - "x86" => true, - "x86_64" => false, + let prefix = match &target.arch[..] { + "x86" => Some('_'), + "x86_64" => None, + "arm64ec" => Some('#'), // Only x86/64 use symbol decorations. _ => return undecorated, }; @@ -602,8 +607,8 @@ pub fn linking_symbol_name_for_instance_in_crate<'tcx>( Conv::X86Stdcall => ("_", "@"), Conv::X86VectorCall => ("", "@@"), _ => { - if x86 { - undecorated.insert(0, '_'); + if let Some(prefix) = prefix { + undecorated.insert(0, prefix); } return undecorated; } diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 60865d06ab998..bbb04652119fe 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -16,8 +16,8 @@ use rustc_data_structures::sync::Lrc; use rustc_errors::emitter::Emitter; use rustc_errors::translation::Translate; use rustc_errors::{ - Diag, DiagArgMap, DiagCtxt, DiagnosticMessage, ErrCode, FatalError, FluentBundle, Level, - MultiSpan, Style, + Diag, DiagArgMap, DiagCtxt, DiagMessage, ErrCode, FatalError, FluentBundle, Level, MultiSpan, + Style, }; use rustc_fs_util::link_or_copy; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; @@ -1004,9 +1004,9 @@ pub(crate) enum Message { /// process another codegen unit. pub struct CguMessage; -// A cut-down version of `rustc_errors::Diagnostic` that impls `Send`, which +// A cut-down version of `rustc_errors::DiagInner` that impls `Send`, which // can be used to send diagnostics from codegen threads to the main thread. -// It's missing the following fields from `rustc_errors::Diagnostic`. +// It's missing the following fields from `rustc_errors::DiagInner`. // - `span`: it doesn't impl `Send`. // - `suggestions`: it doesn't impl `Send`, and isn't used for codegen // diagnostics. @@ -1015,18 +1015,18 @@ pub struct CguMessage; // - `emitted_at`: not used for codegen diagnostics. struct Diagnostic { level: Level, - messages: Vec<(DiagnosticMessage, Style)>, + messages: Vec<(DiagMessage, Style)>, code: Option, children: Vec, args: DiagArgMap, } -// A cut-down version of `rustc_errors::SubDiagnostic` that impls `Send`. It's -// missing the following fields from `rustc_errors::SubDiagnostic`. +// A cut-down version of `rustc_errors::Subdiag` that impls `Send`. It's +// missing the following fields from `rustc_errors::Subdiag`. // - `span`: it doesn't impl `Send`. pub struct Subdiagnostic { level: Level, - messages: Vec<(DiagnosticMessage, Style)>, + messages: Vec<(DiagMessage, Style)>, } #[derive(PartialEq, Clone, Copy, Debug)] diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index f7afd22a48cab..1a3c70cedd0a1 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -510,11 +510,13 @@ fn get_argc_argv<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // Params for UEFI let param_handle = bx.get_param(0); let param_system_table = bx.get_param(1); + let ptr_size = bx.tcx().data_layout.pointer_size; + let ptr_align = bx.tcx().data_layout.pointer_align.abi; let arg_argc = bx.const_int(cx.type_isize(), 2); - let arg_argv = bx.alloca(cx.type_array(cx.type_ptr(), 2), Align::ONE); - bx.store(param_handle, arg_argv, Align::ONE); - let arg_argv_el1 = bx.gep(cx.type_ptr(), arg_argv, &[bx.const_int(cx.type_int(), 1)]); - bx.store(param_system_table, arg_argv_el1, Align::ONE); + let arg_argv = bx.alloca(cx.type_array(cx.type_ptr(), 2), ptr_align); + bx.store(param_handle, arg_argv, ptr_align); + let arg_argv_el1 = bx.inbounds_ptradd(arg_argv, bx.const_usize(ptr_size.bytes())); + bx.store(param_system_table, arg_argv_el1, ptr_align); (arg_argc, arg_argv) } else if cx.sess().target.main_needs_argc_argv { // Params from native `main()` used as args for rust start function @@ -907,7 +909,11 @@ impl CrateInfo { lang_items::required(tcx, l).then_some(name) }) .collect(); - let prefix = if target.is_like_windows && target.arch == "x86" { "_" } else { "" }; + let prefix = match (target.is_like_windows, target.arch.as_ref()) { + (true, "x86") => "_", + (true, "arm64ec") => "#", + _ => "", + }; // This loop only adds new items to values of the hash map, so the order in which we // iterate over the values is not important. diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 9c7aadb81f828..89a44d2897a76 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -12,12 +12,12 @@ use crate::MemFlags; use rustc_ast as ast; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_hir::lang_items::LangItem; -use rustc_middle::mir::{self, AssertKind, SwitchTargets, UnwindTerminateReason}; +use rustc_middle::mir::{self, AssertKind, BasicBlock, SwitchTargets, UnwindTerminateReason}; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement}; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_middle::ty::{self, Instance, Ty}; use rustc_session::config::OptLevel; -use rustc_span::{source_map::Spanned, sym, Span, Symbol}; +use rustc_span::{source_map::Spanned, sym, Span}; use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode, Reg}; use rustc_target::abi::{self, HasDataLayout, WrappingRange}; use rustc_target::spec::abi::Abi; @@ -264,7 +264,8 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { mir::UnwindAction::Unreachable => None, }; - if let Some(cleanup) = unwind_target { + if operands.iter().any(|x| matches!(x, InlineAsmOperandRef::Label { .. })) { + assert!(unwind_target.is_none()); let ret_llbb = if let Some(target) = destination { fx.llbb(target) } else { @@ -277,11 +278,29 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { options, line_spans, instance, - Some((ret_llbb, cleanup, self.funclet(fx))), + Some(ret_llbb), + None, + ); + MergingSucc::False + } else if let Some(cleanup) = unwind_target { + let ret_llbb = if let Some(target) = destination { + fx.llbb(target) + } else { + fx.unreachable_block() + }; + + bx.codegen_inline_asm( + template, + operands, + options, + line_spans, + instance, + Some(ret_llbb), + Some((cleanup, self.funclet(fx))), ); MergingSucc::False } else { - bx.codegen_inline_asm(template, operands, options, line_spans, instance, None); + bx.codegen_inline_asm(template, operands, options, line_spans, instance, None, None); if let Some(target) = destination { self.funclet_br(fx, bx, target, mergeable_succ) @@ -680,7 +699,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { &mut self, helper: &TerminatorCodegenHelper<'tcx>, bx: &mut Bx, - intrinsic: Option, + intrinsic: Option, instance: Option>, source_info: mir::SourceInfo, target: Option, @@ -690,7 +709,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Emit a panic or a no-op for `assert_*` intrinsics. // These are intrinsics that compile to panics so that we can get a message // which mentions the offending type, even from a const context. - let panic_intrinsic = intrinsic.and_then(|s| ValidityRequirement::from_intrinsic(s)); + let panic_intrinsic = intrinsic.and_then(|i| ValidityRequirement::from_intrinsic(i.name)); if let Some(requirement) = panic_intrinsic { let ty = instance.unwrap().args.type_at(0); @@ -826,14 +845,20 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // The arguments we'll be passing. Plus one to account for outptr, if used. let arg_count = fn_abi.args.len() + fn_abi.ret.is_indirect() as usize; - if intrinsic == Some(sym::caller_location) { + if matches!(intrinsic, Some(ty::IntrinsicDef { name: sym::caller_location, .. })) { return if let Some(target) = target { let location = self.get_caller_location(bx, mir::SourceInfo { span: fn_span, ..source_info }); let mut llargs = Vec::with_capacity(arg_count); - let ret_dest = - self.make_return_dest(bx, destination, &fn_abi.ret, &mut llargs, true, true); + let ret_dest = self.make_return_dest( + bx, + destination, + &fn_abi.ret, + &mut llargs, + intrinsic, + Some(target), + ); assert_eq!(llargs, []); if let ReturnDest::IndirectOperand(tmp, _) = ret_dest { location.val.store(bx, tmp); @@ -846,7 +871,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } let instance = match intrinsic { - None | Some(sym::drop_in_place) => instance, + None => instance, Some(intrinsic) => { let mut llargs = Vec::with_capacity(1); let ret_dest = self.make_return_dest( @@ -854,8 +879,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { destination, &fn_abi.ret, &mut llargs, - true, - target.is_some(), + Some(intrinsic), + target, ); let dest = match ret_dest { _ if fn_abi.ret.is_indirect() => llargs[0], @@ -873,7 +898,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // The indices passed to simd_shuffle in the // third argument must be constant. This is // checked by the type-checker. - if i == 2 && intrinsic == sym::simd_shuffle { + if i == 2 && intrinsic.name == sym::simd_shuffle { if let mir::Operand::Constant(constant) = &arg.node { let (llval, ty) = self.simd_shuffle_indices(bx, constant); return OperandRef { @@ -903,14 +928,33 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { MergingSucc::False }; } - Err(instance) => Some(instance), + Err(instance) => { + if intrinsic.must_be_overridden { + span_bug!( + span, + "intrinsic {} must be overridden by codegen backend, but isn't", + intrinsic.name, + ); + } + Some(instance) + } } } }; let mut llargs = Vec::with_capacity(arg_count); let destination = target.as_ref().map(|&target| { - (self.make_return_dest(bx, destination, &fn_abi.ret, &mut llargs, false, true), target) + ( + self.make_return_dest( + bx, + destination, + &fn_abi.ret, + &mut llargs, + None, + Some(target), + ), + target, + ) }); // Split the rust-call tupled arguments off. @@ -1075,7 +1119,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { operands: &[mir::InlineAsmOperand<'tcx>], options: ast::InlineAsmOptions, line_spans: &[Span], - destination: Option, + targets: &[mir::BasicBlock], unwind: mir::UnwindAction, instance: Instance<'_>, mergeable_succ: bool, @@ -1127,6 +1171,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::InlineAsmOperand::SymStatic { def_id } => { InlineAsmOperandRef::SymStatic { def_id } } + mir::InlineAsmOperand::Label { target_index } => { + InlineAsmOperandRef::Label { label: self.llbb(targets[target_index]) } + } }) .collect(); @@ -1137,7 +1184,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { &operands, options, line_spans, - destination, + if options.contains(InlineAsmOptions::NORETURN) { + None + } else { + targets.get(0).copied() + }, unwind, instance, mergeable_succ, @@ -1293,7 +1344,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ref operands, options, line_spans, - destination, + ref targets, unwind, } => self.codegen_asm_terminator( helper, @@ -1303,7 +1354,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { operands, options, line_spans, - destination, + targets, unwind, self.instance, mergeable_succ(), @@ -1643,10 +1694,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { dest: mir::Place<'tcx>, fn_ret: &ArgAbi<'tcx, Ty<'tcx>>, llargs: &mut Vec, - is_intrinsic: bool, - has_target: bool, + intrinsic: Option, + target: Option, ) -> ReturnDest<'tcx, Bx::Value> { - if !has_target { + if target.is_none() { return ReturnDest::Nothing; } // If the return is ignored, we can just return a do-nothing `ReturnDest`. @@ -1667,7 +1718,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { tmp.storage_live(bx); llargs.push(tmp.llval); ReturnDest::IndirectOperand(tmp, index) - } else if is_intrinsic { + } else if intrinsic.is_some() { // Currently, intrinsics always need a location to store // the result, so we create a temporary `alloca` for the // result. diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 94eb37e78e07d..932926976b58d 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -204,6 +204,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { pub fn deref>(self, cx: &Cx) -> PlaceRef<'tcx, V> { if self.layout.ty.is_box() { + // Derefer should have removed all Box derefs bug!("dereferencing {:?} in codegen", self.layout.ty); } diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index 725d3bf4431e4..1ec6c351e2537 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -104,10 +104,6 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { let mut simple = || { let llval = if offset.bytes() == 0 { self.llval - } else if field.is_zst() { - // FIXME(erikdesjardins): it should be fine to use inbounds for ZSTs too; - // keeping this logic for now to preserve previous behavior. - bx.ptradd(self.llval, bx.const_usize(offset.bytes())) } else { bx.inbounds_ptradd(self.llval, bx.const_usize(offset.bytes())) }; @@ -168,8 +164,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { debug!("struct_field_ptr: DST field offset: {:?}", offset); // Adjust pointer. - // FIXME(erikdesjardins): should be able to use inbounds here too. - let ptr = bx.ptradd(self.llval, offset); + let ptr = bx.inbounds_ptradd(self.llval, offset); PlaceRef { llval: ptr, llextra: self.llextra, layout: field, align: effective_field_align } } diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index f7ff36c0467d2..9ae82d4845e16 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -94,8 +94,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } if let OperandValue::Immediate(v) = cg_elem.val { - let zero = bx.const_usize(0); - let start = dest.project_index(bx, zero).llval; + let start = dest.llval; let size = bx.const_usize(dest.layout.size.bytes()); // Use llvm.memset.p0i8.* to initialize all zero arrays diff --git a/compiler/rustc_codegen_ssa/src/mono_item.rs b/compiler/rustc_codegen_ssa/src/mono_item.rs index 295e27691090c..1a4795c0213a1 100644 --- a/compiler/rustc_codegen_ssa/src/mono_item.rs +++ b/compiler/rustc_codegen_ssa/src/mono_item.rs @@ -76,7 +76,8 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> { hir::InlineAsmOperand::In { .. } | hir::InlineAsmOperand::Out { .. } | hir::InlineAsmOperand::InOut { .. } - | hir::InlineAsmOperand::SplitInOut { .. } => { + | hir::InlineAsmOperand::SplitInOut { .. } + | hir::InlineAsmOperand::Label { .. } => { span_bug!(*op_sp, "invalid operand type for global_asm!") } }) diff --git a/compiler/rustc_codegen_ssa/src/traits/asm.rs b/compiler/rustc_codegen_ssa/src/traits/asm.rs index c2ae74b18d81e..8d67b626bbdb5 100644 --- a/compiler/rustc_codegen_ssa/src/traits/asm.rs +++ b/compiler/rustc_codegen_ssa/src/traits/asm.rs @@ -33,6 +33,9 @@ pub enum InlineAsmOperandRef<'tcx, B: BackendTypes + ?Sized> { SymStatic { def_id: DefId, }, + Label { + label: B::BasicBlock, + }, } #[derive(Debug)] @@ -51,7 +54,8 @@ pub trait AsmBuilderMethods<'tcx>: BackendTypes { options: InlineAsmOptions, line_spans: &[Span], instance: Instance<'_>, - dest_catch_funclet: Option<(Self::BasicBlock, Self::BasicBlock, Option<&Self::Funclet>)>, + dest: Option, + catch_funclet: Option<(Self::BasicBlock, Option<&Self::Funclet>)>, ); } diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index 2805ca360ad3d..81c9e02e2ee80 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -232,9 +232,6 @@ const_eval_non_const_fn_call = const_eval_non_const_impl = impl defined here, but it is not `const` -const_eval_noreturn_asm_returned = - returned from noreturn inline assembly - const_eval_not_enough_caller_args = calling a function with fewer arguments than it requires diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs index 62bc68b1a20e9..e5b4fc3a574f0 100644 --- a/compiler/rustc_const_eval/src/const_eval/error.rs +++ b/compiler/rustc_const_eval/src/const_eval/error.rs @@ -1,8 +1,6 @@ use std::mem; -use rustc_errors::{ - DiagArgName, DiagArgValue, DiagnosticMessage, IntoDiagnostic, IntoDiagnosticArg, -}; +use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, IntoDiagnostic, IntoDiagnosticArg}; use rustc_hir::CRATE_HIR_ID; use rustc_middle::mir::AssertKind; use rustc_middle::query::TyCtxtAt; @@ -25,7 +23,7 @@ pub enum ConstEvalErrKind { } impl MachineStopType for ConstEvalErrKind { - fn diagnostic_message(&self) -> DiagnosticMessage { + fn diagnostic_message(&self) -> DiagMessage { use crate::fluent_generated::*; use ConstEvalErrKind::*; match self { diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 946ffc05cc14f..6736fc749c02d 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -24,7 +24,7 @@ use crate::errors::{LongRunning, LongRunningWarn}; use crate::fluent_generated as fluent; use crate::interpret::{ self, compile_time_machine, AllocId, AllocRange, ConstAllocation, CtfeProvenance, FnArg, FnVal, - Frame, ImmTy, InterpCx, InterpResult, OpTy, PlaceTy, Pointer, PointerArithmetic, Scalar, + Frame, ImmTy, InterpCx, InterpResult, MPlaceTy, OpTy, Pointer, PointerArithmetic, Scalar, }; use super::error::*; @@ -219,7 +219,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> { &mut self, instance: ty::Instance<'tcx>, args: &[FnArg<'tcx>], - dest: &PlaceTy<'tcx>, + dest: &MPlaceTy<'tcx>, ret: Option, ) -> InterpResult<'tcx, Option>> { let def_id = instance.def_id(); @@ -227,7 +227,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> { if self.tcx.has_attr(def_id, sym::rustc_const_panic_str) || Some(def_id) == self.tcx.lang_items().begin_panic_fn() { - let args = self.copy_fn_args(args)?; + let args = self.copy_fn_args(args); // &str or &&str assert!(args.len() == 1); @@ -254,7 +254,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> { return Ok(Some(new_instance)); } else if Some(def_id) == self.tcx.lang_items().align_offset_fn() { - let args = self.copy_fn_args(args)?; + let args = self.copy_fn_args(args); // For align_offset, we replace the function call if the pointer has no address. match self.align_offset(instance, &args, dest, ret)? { ControlFlow::Continue(()) => return Ok(Some(instance)), @@ -280,7 +280,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> { &mut self, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx>], - dest: &PlaceTy<'tcx>, + dest: &MPlaceTy<'tcx>, ret: Option, ) -> InterpResult<'tcx, ControlFlow<()>> { assert_eq!(args.len(), 2); @@ -410,7 +410,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, orig_instance: ty::Instance<'tcx>, _abi: CallAbi, args: &[FnArg<'tcx>], - dest: &PlaceTy<'tcx>, + dest: &MPlaceTy<'tcx>, ret: Option, _unwind: mir::UnwindAction, // unwinding is not supported in consts ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> { @@ -455,7 +455,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, ecx: &mut InterpCx<'mir, 'tcx, Self>, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx>], - dest: &PlaceTy<'tcx, Self::Provenance>, + dest: &MPlaceTy<'tcx, Self::Provenance>, target: Option, _unwind: mir::UnwindAction, ) -> InterpResult<'tcx> { diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index c59e0a0df9f7b..afabd9689c694 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -1,8 +1,7 @@ use std::borrow::Cow; use rustc_errors::{ - codes::*, Diag, DiagArgValue, DiagCtxt, DiagnosticMessage, EmissionGuarantee, IntoDiagnostic, - Level, + codes::*, Diag, DiagArgValue, DiagCtxt, DiagMessage, EmissionGuarantee, IntoDiagnostic, Level, }; use rustc_hir::ConstContext; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; @@ -424,7 +423,7 @@ pub struct UndefinedBehavior { pub trait ReportErrorExt { /// Returns the diagnostic message for this error. - fn diagnostic_message(&self) -> DiagnosticMessage; + fn diagnostic_message(&self) -> DiagMessage; fn add_args(self, diag: &mut Diag<'_, G>); fn debug(self) -> String @@ -433,7 +432,7 @@ pub trait ReportErrorExt { { ty::tls::with(move |tcx| { let dcx = tcx.dcx(); - let mut diag = dcx.struct_allow(DiagnosticMessage::Str(String::new().into())); + let mut diag = dcx.struct_allow(DiagMessage::Str(String::new().into())); let message = self.diagnostic_message(); self.add_args(&mut diag); let s = dcx.eagerly_translate_to_string(message, diag.args.iter()); @@ -457,7 +456,7 @@ fn bad_pointer_message(msg: CheckInAllocMsg, dcx: &DiagCtxt) -> String { } impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> { - fn diagnostic_message(&self) -> DiagnosticMessage { + fn diagnostic_message(&self) -> DiagMessage { use crate::fluent_generated::*; use UndefinedBehaviorInfo::*; match self { @@ -595,7 +594,7 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> { } impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { - fn diagnostic_message(&self) -> DiagnosticMessage { + fn diagnostic_message(&self) -> DiagMessage { use crate::fluent_generated::*; use rustc_middle::mir::interpret::ValidationErrorKind::*; match self.kind { @@ -783,7 +782,7 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { } impl ReportErrorExt for UnsupportedOpInfo { - fn diagnostic_message(&self) -> DiagnosticMessage { + fn diagnostic_message(&self) -> DiagMessage { use crate::fluent_generated::*; match self { UnsupportedOpInfo::Unsupported(s) => s.clone().into(), @@ -819,7 +818,7 @@ impl ReportErrorExt for UnsupportedOpInfo { } impl<'tcx> ReportErrorExt for InterpError<'tcx> { - fn diagnostic_message(&self) -> DiagnosticMessage { + fn diagnostic_message(&self) -> DiagMessage { match self { InterpError::UndefinedBehavior(ub) => ub.diagnostic_message(), InterpError::Unsupported(e) => e.diagnostic_message(), @@ -842,7 +841,7 @@ impl<'tcx> ReportErrorExt for InterpError<'tcx> { } impl<'tcx> ReportErrorExt for InvalidProgramInfo<'tcx> { - fn diagnostic_message(&self) -> DiagnosticMessage { + fn diagnostic_message(&self) -> DiagMessage { use crate::fluent_generated::*; match self { InvalidProgramInfo::TooGeneric => const_eval_too_generic, @@ -877,7 +876,7 @@ impl<'tcx> ReportErrorExt for InvalidProgramInfo<'tcx> { } impl ReportErrorExt for ResourceExhaustionInfo { - fn diagnostic_message(&self) -> DiagnosticMessage { + fn diagnostic_message(&self) -> DiagMessage { use crate::fluent_generated::*; match self { ResourceExhaustionInfo::StackFrameLimitReached => const_eval_stack_frame_limit_reached, diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index a88e130cd4b78..2cebea9d145bb 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -182,13 +182,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> { use rustc_type_ir::TyKind::*; - let val = match src.layout.ty.kind() { - // Floating point - Float(FloatTy::F32) => self.cast_from_float(src.to_scalar().to_f32()?, cast_to.ty), - Float(FloatTy::F64) => self.cast_from_float(src.to_scalar().to_f64()?, cast_to.ty), - _ => { - bug!("Can't cast 'Float' type into {}", cast_to.ty); - } + let Float(fty) = src.layout.ty.kind() else { + bug!("FloatToFloat/FloatToInt cast: source type {} is not a float type", src.layout.ty) + }; + let val = match fty { + FloatTy::F16 => unimplemented!("f16_f128"), + FloatTy::F32 => self.cast_from_float(src.to_scalar().to_f32()?, cast_to.ty), + FloatTy::F64 => self.cast_from_float(src.to_scalar().to_f64()?, cast_to.ty), + FloatTy::F128 => unimplemented!("f16_f128"), }; Ok(ImmTy::from_scalar(val, cast_to)) } @@ -275,6 +276,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { trace!("cast_from_scalar: {}, {} -> {}", v, src_layout.ty, cast_ty); Ok(match *cast_ty.kind() { + // int -> int Int(_) | Uint(_) => { let size = match *cast_ty.kind() { Int(t) => Integer::from_int_ty(self, t).size(), @@ -285,15 +287,26 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Scalar::from_uint(v, size) } - Float(FloatTy::F32) if signed => Scalar::from_f32(Single::from_i128(v as i128).value), - Float(FloatTy::F64) if signed => Scalar::from_f64(Double::from_i128(v as i128).value), - Float(FloatTy::F32) => Scalar::from_f32(Single::from_u128(v).value), - Float(FloatTy::F64) => Scalar::from_f64(Double::from_u128(v).value), - - Char => { - // `u8` to `char` cast - Scalar::from_u32(u8::try_from(v).unwrap().into()) + // signed int -> float + Float(fty) if signed => { + let v = v as i128; + match fty { + FloatTy::F16 => unimplemented!("f16_f128"), + FloatTy::F32 => Scalar::from_f32(Single::from_i128(v).value), + FloatTy::F64 => Scalar::from_f64(Double::from_i128(v).value), + FloatTy::F128 => unimplemented!("f16_f128"), + } } + // unsigned int -> float + Float(fty) => match fty { + FloatTy::F16 => unimplemented!("f16_f128"), + FloatTy::F32 => Scalar::from_f32(Single::from_u128(v).value), + FloatTy::F64 => Scalar::from_f64(Double::from_u128(v).value), + FloatTy::F128 => unimplemented!("f16_f128"), + }, + + // u8 -> char + Char => Scalar::from_u32(u8::try_from(v).unwrap().into()), // Casts to bool are not permitted by rustc, no need to handle them here. _ => span_bug!(self.cur_span(), "invalid int to {} cast", cast_ty), @@ -339,14 +352,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let v = f.to_i128(size.bits_usize()).value; Scalar::from_int(v, size) } - // float -> f32 - Float(FloatTy::F32) => { - Scalar::from_f32(adjust_nan(self, f, f.convert(&mut false).value)) - } - // float -> f64 - Float(FloatTy::F64) => { - Scalar::from_f64(adjust_nan(self, f, f.convert(&mut false).value)) - } + // float -> float + Float(fty) => match fty { + FloatTy::F16 => unimplemented!("f16_f128"), + FloatTy::F32 => Scalar::from_f32(adjust_nan(self, f, f.convert(&mut false).value)), + FloatTy::F64 => Scalar::from_f64(adjust_nan(self, f, f.convert(&mut false).value)), + FloatTy::F128 => unimplemented!("f16_f128"), + }, // That's it. _ => span_bug!(self.cur_span(), "invalid float to {} cast", dest_ty), } diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs index e951a77611c21..6d4f6d0cb3c52 100644 --- a/compiler/rustc_const_eval/src/interpret/discriminant.rs +++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs @@ -10,6 +10,8 @@ use super::{ImmTy, InterpCx, InterpResult, Machine, Readable, Scalar, Writeable} impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Writes the discriminant of the given variant. + /// + /// If the variant is uninhabited, this is UB. #[instrument(skip(self), level = "trace")] pub fn write_discriminant( &mut self, @@ -102,6 +104,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Read discriminant, return the runtime value as well as the variant index. /// Can also legally be called on non-enums (e.g. through the discriminant_value intrinsic)! + /// + /// Will never return an uninhabited variant. #[instrument(skip(self), level = "trace")] pub fn read_discriminant( &self, @@ -244,7 +248,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { variant } }; - // For consistency with `write_discriminant`, and to make sure that `project_downcast` cannot fail due to strange layouts, we declare immediate UB for uninhabited variants. + // Reading the discriminant of an uninhabited variant is UB. This is the basis for the + // `uninhabited_enum_branching` MIR pass. It also ensures consistency with + // `write_discriminant`. if op.layout().for_variant(self, index).abi.is_uninhabited() { throw_ub!(UninhabitedEnumVariantRead(index)) } diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index cb308ab53ecfb..a484fbd892c6d 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -108,7 +108,7 @@ pub struct Frame<'mir, 'tcx, Prov: Provenance = CtfeProvenance, Extra = ()> { /// The location where the result of the current stack frame should be written to, /// and its layout in the caller. - pub return_place: PlaceTy<'tcx, Prov>, + pub return_place: MPlaceTy<'tcx, Prov>, /// The list of locals for this stack frame, stored in order as /// `[return_ptr, arguments..., variables..., temporaries...]`. @@ -771,7 +771,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { &mut self, instance: ty::Instance<'tcx>, body: &'mir mir::Body<'tcx>, - return_place: &PlaceTy<'tcx, M::Provenance>, + return_place: &MPlaceTy<'tcx, M::Provenance>, return_to_block: StackPopCleanup, ) -> InterpResult<'tcx> { trace!("body: {:#?}", body); @@ -912,7 +912,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } else { self.copy_op_allow_transmute(&op, &dest) }; - trace!("return value: {:?}", self.dump_place(&dest)); + trace!("return value: {:?}", self.dump_place(&dest.into())); // We delay actually short-circuiting on this error until *after* the stack frame is // popped, since we want this error to be attributed to the caller, whose type defines // this transmute. diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 1cb991b38f7e9..b68bfb4211d1e 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -21,7 +21,7 @@ use rustc_span::symbol::{sym, Symbol}; use rustc_target::abi::Size; use super::{ - util::ensure_monomorphic_enough, CheckInAllocMsg, ImmTy, InterpCx, Machine, OpTy, PlaceTy, + util::ensure_monomorphic_enough, CheckInAllocMsg, ImmTy, InterpCx, MPlaceTy, Machine, OpTy, Pointer, }; @@ -104,7 +104,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { &mut self, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx, M::Provenance>], - dest: &PlaceTy<'tcx, M::Provenance>, + dest: &MPlaceTy<'tcx, M::Provenance>, ret: Option, ) -> InterpResult<'tcx, bool> { let instance_args = instance.args; @@ -377,7 +377,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let index = u64::from(self.read_scalar(&args[1])?.to_u32()?); let elem = &args[2]; let (input, input_len) = self.operand_to_simd(&args[0])?; - let (dest, dest_len) = self.place_to_simd(dest)?; + let (dest, dest_len) = self.mplace_to_simd(dest)?; assert_eq!(input_len, dest_len, "Return vector length must match input length"); // Bounds are not checked by typeck so we have to do it ourselves. if index >= input_len { @@ -430,7 +430,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { _ => return Ok(false), } - trace!("{:?}", self.dump_place(dest)); + trace!("{:?}", self.dump_place(&dest.clone().into())); self.go_to_block(ret); Ok(true) } @@ -488,7 +488,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { &mut self, a: &ImmTy<'tcx, M::Provenance>, b: &ImmTy<'tcx, M::Provenance>, - dest: &PlaceTy<'tcx, M::Provenance>, + dest: &MPlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { assert_eq!(a.layout.ty, b.layout.ty); assert!(matches!(a.layout.ty.kind(), ty::Int(..) | ty::Uint(..))); @@ -506,7 +506,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) } // `Rem` says this is all right, so we can let `Div` do its job. - self.binop_ignore_overflow(BinOp::Div, a, b, dest) + self.binop_ignore_overflow(BinOp::Div, a, b, &dest.clone().into()) } pub fn saturating_arith( diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 0106ec425bc50..90a654a12294b 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -196,7 +196,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { instance: ty::Instance<'tcx>, abi: CallAbi, args: &[FnArg<'tcx, Self::Provenance>], - destination: &PlaceTy<'tcx, Self::Provenance>, + destination: &MPlaceTy<'tcx, Self::Provenance>, target: Option, unwind: mir::UnwindAction, ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>>; @@ -208,7 +208,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { fn_val: Self::ExtraFnVal, abi: CallAbi, args: &[FnArg<'tcx, Self::Provenance>], - destination: &PlaceTy<'tcx, Self::Provenance>, + destination: &MPlaceTy<'tcx, Self::Provenance>, target: Option, unwind: mir::UnwindAction, ) -> InterpResult<'tcx>; @@ -219,7 +219,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { ecx: &mut InterpCx<'mir, 'tcx, Self>, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx, Self::Provenance>], - destination: &PlaceTy<'tcx, Self::Provenance>, + destination: &MPlaceTy<'tcx, Self::Provenance>, target: Option, unwind: mir::UnwindAction, ) -> InterpResult<'tcx>; @@ -374,11 +374,17 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { kind: Option>, ) -> InterpResult<'tcx, Cow<'b, Allocation>>; + /// Evaluate the inline assembly. + /// + /// This should take care of jumping to the next block (one of `targets`) when asm goto + /// is triggered, `targets[0]` when the assembly falls through, or diverge in case of + /// `InlineAsmOptions::NORETURN` being set. fn eval_inline_asm( _ecx: &mut InterpCx<'mir, 'tcx, Self>, _template: &'tcx [InlineAsmTemplatePiece], _operands: &[mir::InlineAsmOperand<'tcx>], _options: InlineAsmOptions, + _targets: &[mir::BasicBlock], ) -> InterpResult<'tcx> { throw_unsup_format!("inline assembly is not supported") } @@ -466,11 +472,11 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { /// argument/return value was actually copied or passed in-place.. fn protect_in_place_function_argument( ecx: &mut InterpCx<'mir, 'tcx, Self>, - place: &PlaceTy<'tcx, Self::Provenance>, + mplace: &MPlaceTy<'tcx, Self::Provenance>, ) -> InterpResult<'tcx> { // Without an aliasing model, all we can do is put `Uninit` into the place. // Conveniently this also ensures that the place actually points to suitable memory. - ecx.write_uninit(place) + ecx.write_uninit(mplace) } /// Called immediately before a new stack frame gets pushed. @@ -584,7 +590,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { fn_val: !, _abi: CallAbi, _args: &[FnArg<$tcx>], - _destination: &PlaceTy<$tcx, Self::Provenance>, + _destination: &MPlaceTy<$tcx, Self::Provenance>, _target: Option, _unwind: mir::UnwindAction, ) -> InterpResult<$tcx> { diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 6e987784ff9ee..60f7710c11d7d 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -194,6 +194,12 @@ pub(super) enum Place { Local { frame: usize, local: mir::Local, offset: Option }, } +/// An evaluated place, together with its type. +/// +/// This may reference a stack frame by its index, so `PlaceTy` should generally not be kept around +/// for longer than a single operation. Popping and then pushing a stack frame can make `PlaceTy` +/// point to the wrong destination. If the interpreter has multiple stacks, stack switching will +/// also invalidate a `PlaceTy`. #[derive(Clone)] pub struct PlaceTy<'tcx, Prov: Provenance = CtfeProvenance> { place: Place, // Keep this private; it helps enforce invariants. @@ -437,6 +443,7 @@ where trace!("deref to {} on {:?}", val.layout.ty, *val); if val.layout.ty.is_box() { + // Derefer should have removed all Box derefs bug!("dereferencing {}", val.layout.ty); } @@ -494,16 +501,6 @@ where Ok((mplace, len)) } - /// Converts a repr(simd) place into a place where `place_index` accesses the SIMD elements. - /// Also returns the number of elements. - pub fn place_to_simd( - &mut self, - place: &PlaceTy<'tcx, M::Provenance>, - ) -> InterpResult<'tcx, (MPlaceTy<'tcx, M::Provenance>, u64)> { - let mplace = self.force_allocation(place)?; - self.mplace_to_simd(&mplace) - } - pub fn local_to_place( &self, frame: usize, diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index e72ace8be3559..bafb8cb0018c2 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -1,6 +1,7 @@ use std::borrow::Cow; -use rustc_ast::ast::InlineAsmOptions; +use either::Either; + use rustc_middle::{ mir, ty::{ @@ -30,14 +31,14 @@ pub enum FnArg<'tcx, Prov: Provenance = CtfeProvenance> { Copy(OpTy<'tcx, Prov>), /// Allow for the argument to be passed in-place: destroy the value originally stored at that place and /// make the place inaccessible for the duration of the function call. - InPlace(PlaceTy<'tcx, Prov>), + InPlace(MPlaceTy<'tcx, Prov>), } impl<'tcx, Prov: Provenance> FnArg<'tcx, Prov> { pub fn layout(&self) -> &TyAndLayout<'tcx> { match self { FnArg::Copy(op) => &op.layout, - FnArg::InPlace(place) => &place.layout, + FnArg::InPlace(mplace) => &mplace.layout, } } } @@ -45,13 +46,10 @@ impl<'tcx, Prov: Provenance> FnArg<'tcx, Prov> { impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Make a copy of the given fn_arg. Any `InPlace` are degenerated to copies, no protection of the /// original memory occurs. - pub fn copy_fn_arg( - &self, - arg: &FnArg<'tcx, M::Provenance>, - ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { + pub fn copy_fn_arg(&self, arg: &FnArg<'tcx, M::Provenance>) -> OpTy<'tcx, M::Provenance> { match arg { - FnArg::Copy(op) => Ok(op.clone()), - FnArg::InPlace(place) => self.place_to_op(place), + FnArg::Copy(op) => op.clone(), + FnArg::InPlace(mplace) => mplace.clone().into(), } } @@ -60,7 +58,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { pub fn copy_fn_args( &self, args: &[FnArg<'tcx, M::Provenance>], - ) -> InterpResult<'tcx, Vec>> { + ) -> Vec> { args.iter().map(|fn_arg| self.copy_fn_arg(fn_arg)).collect() } @@ -71,7 +69,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) -> InterpResult<'tcx, FnArg<'tcx, M::Provenance>> { Ok(match arg { FnArg::Copy(op) => FnArg::Copy(self.project_field(op, field)?), - FnArg::InPlace(place) => FnArg::InPlace(self.project_field(place, field)?), + FnArg::InPlace(mplace) => FnArg::InPlace(self.project_field(mplace, field)?), }) } @@ -153,7 +151,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ), }; - let destination = self.eval_place(destination)?; + let destination = self.force_allocation(&self.eval_place(destination)?)?; self.eval_fn_call( fn_val, (fn_sig.abi, fn_abi), @@ -224,15 +222,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { terminator.kind ), - InlineAsm { template, ref operands, options, destination, .. } => { - M::eval_inline_asm(self, template, operands, options)?; - if options.contains(InlineAsmOptions::NORETURN) { - throw_ub_custom!(fluent::const_eval_noreturn_asm_returned); - } - self.go_to_block( - destination - .expect("InlineAsm terminators without noreturn must have a destination"), - ) + InlineAsm { template, ref operands, options, ref targets, .. } => { + M::eval_inline_asm(self, template, operands, options, targets)?; } } @@ -246,10 +237,36 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) -> InterpResult<'tcx, Vec>> { ops.iter() .map(|op| { - Ok(match &op.node { - mir::Operand::Move(place) => FnArg::InPlace(self.eval_place(*place)?), - _ => FnArg::Copy(self.eval_operand(&op.node, None)?), - }) + let arg = match &op.node { + mir::Operand::Copy(_) | mir::Operand::Constant(_) => { + // Make a regular copy. + let op = self.eval_operand(&op.node, None)?; + FnArg::Copy(op) + } + mir::Operand::Move(place) => { + // If this place lives in memory, preserve its location. + // We call `place_to_op` which will be an `MPlaceTy` whenever there exists + // an mplace for this place. (This is in contrast to `PlaceTy::as_mplace_or_local` + // which can return a local even if that has an mplace.) + let place = self.eval_place(*place)?; + let op = self.place_to_op(&place)?; + + match op.as_mplace_or_imm() { + Either::Left(mplace) => FnArg::InPlace(mplace), + Either::Right(_imm) => { + // This argument doesn't live in memory, so there's no place + // to make inaccessible during the call. + // We rely on there not being any stray `PlaceTy` that would let the + // caller directly access this local! + // This is also crucial for tail calls, where we want the `FnArg` to + // stay valid when the old stack frame gets popped. + FnArg::Copy(op) + } + } + } + }; + + Ok(arg) }) .collect() } @@ -359,14 +376,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ok(Some(match ty.kind() { ty::Ref(_, ty, _) => *ty, ty::RawPtr(mt) => mt.ty, - // We should only accept `Box` with the default allocator. - // It's hard to test for that though so we accept every 1-ZST allocator. - ty::Adt(def, args) - if def.is_box() - && self.layout_of(args[1].expect_ty()).is_ok_and(|l| l.is_1zst()) => - { - args[0].expect_ty() - } + // We only accept `Box` with the default allocator. + _ if ty.is_box_global(*self.tcx) => ty.boxed_ty(), _ => return Ok(None), })) }; @@ -465,7 +476,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // We work with a copy of the argument for now; if this is in-place argument passing, we // will later protect the source it comes from. This means the callee cannot observe if we // did in-place of by-copy argument passing, except for pointer equality tests. - let caller_arg_copy = self.copy_fn_arg(caller_arg)?; + let caller_arg_copy = self.copy_fn_arg(caller_arg); if !already_live { let local = callee_arg.as_local().unwrap(); let meta = caller_arg_copy.meta(); @@ -483,8 +494,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // specifically.) self.copy_op_allow_transmute(&caller_arg_copy, &callee_arg)?; // If this was an in-place pass, protect the place it comes from for the duration of the call. - if let FnArg::InPlace(place) = caller_arg { - M::protect_in_place_function_argument(self, place)?; + if let FnArg::InPlace(mplace) = caller_arg { + M::protect_in_place_function_argument(self, mplace)?; } Ok(()) } @@ -503,7 +514,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { (caller_abi, caller_fn_abi): (Abi, &FnAbi<'tcx, Ty<'tcx>>), args: &[FnArg<'tcx, M::Provenance>], with_caller_location: bool, - destination: &PlaceTy<'tcx, M::Provenance>, + destination: &MPlaceTy<'tcx, M::Provenance>, target: Option, mut unwind: mir::UnwindAction, ) -> InterpResult<'tcx> { @@ -531,7 +542,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { M::call_intrinsic( self, instance, - &self.copy_fn_args(args)?, + &self.copy_fn_args(args), destination, target, unwind, @@ -608,8 +619,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { .map(|arg| ( arg.layout().ty, match arg { - FnArg::Copy(op) => format!("copy({:?})", *op), - FnArg::InPlace(place) => format!("in-place({:?})", *place), + FnArg::Copy(op) => format!("copy({op:?})"), + FnArg::InPlace(mplace) => format!("in-place({mplace:?})"), } )) .collect::>() @@ -731,8 +742,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { callee_ty: callee_fn_abi.ret.layout.ty }); } + // Protect return place for in-place return value passing. - M::protect_in_place_function_argument(self, destination)?; + M::protect_in_place_function_argument(self, &destination)?; // Don't forget to mark "initially live" locals as live. self.storage_live_for_always_live_locals()?; @@ -755,7 +767,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // An `InPlace` does nothing here, we keep the original receiver intact. We can't // really pass the argument in-place anyway, and we are constructing a new // `Immediate` receiver. - let mut receiver = self.copy_fn_arg(&args[0])?; + let mut receiver = self.copy_fn_arg(&args[0]); let receiver_place = loop { match receiver.layout.ty.kind() { ty::Ref(..) | ty::RawPtr(..) => { diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs index 2a13671a82978..3427368421f8e 100644 --- a/compiler/rustc_const_eval/src/interpret/util.rs +++ b/compiler/rustc_const_eval/src/interpret/util.rs @@ -30,9 +30,9 @@ where } impl<'tcx> TypeVisitor> for UsedParamsNeedInstantiationVisitor<'tcx> { - type BreakTy = FoundParam; + type Result = ControlFlow; - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { if !ty.has_param() { return ControlFlow::Continue(()); } @@ -64,7 +64,7 @@ where } } - fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, c: ty::Const<'tcx>) -> Self::Result { match c.kind() { ty::ConstKind::Param(..) => ControlFlow::Break(FoundParam), _ => c.super_visit_with(self), diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index c98dc4deb7579..7ec78e7b9cfd6 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -17,7 +17,7 @@ use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt}; use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitor}; use std::mem; -use std::ops::{ControlFlow, Deref}; +use std::ops::Deref; use super::ops::{self, NonConstOp, Status}; use super::qualifs::{self, HasMutInterior, NeedsDrop, NeedsNonConstDrop}; @@ -164,9 +164,9 @@ struct LocalReturnTyVisitor<'ck, 'mir, 'tcx> { } impl<'ck, 'mir, 'tcx> TypeVisitor> for LocalReturnTyVisitor<'ck, 'mir, 'tcx> { - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) { match t.kind() { - ty::FnPtr(_) => ControlFlow::Continue(()), + ty::FnPtr(_) => {} ty::Ref(_, _, hir::Mutability::Mut) => { self.checker.check_op(ops::ty::MutRef(self.kind)); t.super_visit_with(self) @@ -581,7 +581,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { if is_int_bool_or_char(lhs_ty) && is_int_bool_or_char(rhs_ty) { // Int, bool, and char operations are fine. } else if lhs_ty.is_fn_ptr() || lhs_ty.is_unsafe_ptr() { - assert_eq!(lhs_ty, rhs_ty); assert!(matches!( op, BinOp::Eq diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs index 1107b894ab3ee..15720f25c5cff 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs @@ -62,6 +62,7 @@ impl<'tcx> NonConstOp<'tcx> for FloatingPointOp { } } + #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> { feature_err( &ccx.tcx.sess, @@ -556,6 +557,7 @@ impl<'tcx> NonConstOp<'tcx> for RawMutPtrDeref { Status::Unstable(sym::const_mut_refs) } + #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> { feature_err( &ccx.tcx.sess, @@ -589,6 +591,7 @@ impl<'tcx> NonConstOp<'tcx> for StaticAccess { } } + #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> { let mut err = feature_err( &ccx.tcx.sess, @@ -632,6 +635,7 @@ pub mod ty { } } + #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> { feature_err( &ccx.tcx.sess, diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index cc49e8ea247f7..74ba2f6039e86 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -471,9 +471,9 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { self.check_edge(location, *real_target, EdgeKind::Normal); self.check_unwind_edge(location, *unwind); } - TerminatorKind::InlineAsm { destination, unwind, .. } => { - if let Some(destination) = destination { - self.check_edge(location, *destination, EdgeKind::Normal); + TerminatorKind::InlineAsm { targets, unwind, .. } => { + for &target in targets { + self.check_edge(location, target, EdgeKind::Normal); } self.check_unwind_edge(location, *unwind); } diff --git a/compiler/rustc_data_structures/src/sync/worker_local.rs b/compiler/rustc_data_structures/src/sync/worker_local.rs index 50a614a1b0279..07a361ba26088 100644 --- a/compiler/rustc_data_structures/src/sync/worker_local.rs +++ b/compiler/rustc_data_structures/src/sync/worker_local.rs @@ -42,7 +42,7 @@ pub struct Registry(Arc); thread_local! { /// The registry associated with the thread. /// This allows the `WorkerLocal` type to clone the registry in its constructor. - static REGISTRY: OnceCell = OnceCell::new(); + static REGISTRY: OnceCell = const { OnceCell::new() }; } struct ThreadData { diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index 242aa06fe3e3c..fcc0afd3488b0 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -50,7 +50,7 @@ rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_ty_utils = { path = "../rustc_ty_utils" } serde_json = "1.0.59" shlex = "1.0" -time = { version = "0.3", default-features = false, features = ["alloc", "formatting"] } +time = { version = "0.3", default-features = false, features = ["alloc", "formatting", "parsing", "macros"] } tracing = { version = "0.1.35" } # tidy-alphabetical-end diff --git a/compiler/rustc_driver_impl/messages.ftl b/compiler/rustc_driver_impl/messages.ftl index 39462112dc287..1b69a6e2fbecc 100644 --- a/compiler/rustc_driver_impl/messages.ftl +++ b/compiler/rustc_driver_impl/messages.ftl @@ -1,6 +1,10 @@ driver_impl_ice = the compiler unexpectedly panicked. this is a bug. driver_impl_ice_bug_report = we would appreciate a bug report: {$bug_report_url} driver_impl_ice_bug_report_internal_feature = using internal features is not supported and expected to cause internal compiler errors when used incorrectly +driver_impl_ice_bug_report_outdated = + it seems that this compiler `{$version}` is outdated, a newer nightly should have been released in the mean time + .update = please consider running `rustup update nightly` to update the nightly channel and check if this problem still persists + .url = if the problem still persists, we would appreciate a bug report: {$bug_report_url} driver_impl_ice_exclude_cargo_defaults = some of the compiler flags provided by cargo are hidden driver_impl_ice_flags = compiler flags: {$flags} diff --git a/compiler/rustc_driver_impl/src/args.rs b/compiler/rustc_driver_impl/src/args.rs index 5dfd37a6da4de..28574457389fe 100644 --- a/compiler/rustc_driver_impl/src/args.rs +++ b/compiler/rustc_driver_impl/src/args.rs @@ -1,9 +1,7 @@ -use std::error; -use std::fmt; -use std::fs; -use std::io; +use std::{env, error, fmt, fs, io}; use rustc_session::EarlyDiagCtxt; +use rustc_span::ErrorGuaranteed; /// Expands argfiles in command line arguments. #[derive(Default)] @@ -86,7 +84,7 @@ impl Expander { fn read_file(path: &str) -> Result { fs::read_to_string(path).map_err(|e| { if e.kind() == io::ErrorKind::InvalidData { - Error::Utf8Error(Some(path.to_string())) + Error::Utf8Error(path.to_string()) } else { Error::IOError(path.to_string(), e) } @@ -94,22 +92,53 @@ impl Expander { } } +/// Replaces any `@file` arguments with the contents of `file`, with each line of `file` as a +/// separate argument. +/// /// **Note:** This function doesn't interpret argument 0 in any special way. /// If this function is intended to be used with command line arguments, /// `argv[0]` must be removed prior to calling it manually. -pub fn arg_expand_all(early_dcx: &EarlyDiagCtxt, at_args: &[String]) -> Vec { +#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable +pub fn arg_expand_all( + early_dcx: &EarlyDiagCtxt, + at_args: &[String], +) -> Result, ErrorGuaranteed> { let mut expander = Expander::default(); + let mut result = Ok(()); for arg in at_args { if let Err(err) = expander.arg(arg) { - early_dcx.early_fatal(format!("Failed to load argument file: {err}")); + result = Err(early_dcx.early_err(format!("failed to load argument file: {err}"))); } } - expander.finish() + result.map(|()| expander.finish()) +} + +/// Gets the raw unprocessed command-line arguments as Unicode strings, without doing any further +/// processing (e.g., without `@file` expansion). +/// +/// This function is identical to [`env::args()`] except that it emits an error when it encounters +/// non-Unicode arguments instead of panicking. +pub fn raw_args(early_dcx: &EarlyDiagCtxt) -> Result, ErrorGuaranteed> { + let mut res = Ok(Vec::new()); + for (i, arg) in env::args_os().enumerate() { + match arg.into_string() { + Ok(arg) => { + if let Ok(args) = &mut res { + args.push(arg); + } + } + Err(arg) => { + res = + Err(early_dcx.early_err(format!("argument {i} is not valid Unicode: {arg:?}"))) + } + } + } + res } #[derive(Debug)] -pub enum Error { - Utf8Error(Option), +enum Error { + Utf8Error(String), IOError(String, io::Error), ShellParseError(String), } @@ -117,10 +146,9 @@ pub enum Error { impl fmt::Display for Error { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Error::Utf8Error(None) => write!(fmt, "Utf8 error"), - Error::Utf8Error(Some(path)) => write!(fmt, "Utf8 error in {path}"), - Error::IOError(path, err) => write!(fmt, "IO Error: {path}: {err}"), - Error::ShellParseError(path) => write!(fmt, "Invalid shell-style arguments in {path}"), + Error::Utf8Error(path) => write!(fmt, "UTF-8 error in {path}"), + Error::IOError(path, err) => write!(fmt, "IO error: {path}: {err}"), + Error::ShellParseError(path) => write!(fmt, "invalid shell-style arguments in {path}"), } } } diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 410e7eba30a9c..e06d1d245b23f 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -4,6 +4,7 @@ //! //! This API is completely unstable and subject to change. +#![allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(rustdoc_internals)] @@ -58,7 +59,7 @@ use std::str; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, OnceLock}; use std::time::{Instant, SystemTime}; -use time::OffsetDateTime; +use time::{Date, OffsetDateTime, Time}; #[allow(unused_macros)] macro do_not_use_print($($t:tt)*) { @@ -291,7 +292,7 @@ fn run_compiler( // the compiler with @empty_file as argv[0] and no more arguments. let at_args = at_args.get(1..).unwrap_or_default(); - let args = args::arg_expand_all(&default_early_dcx, at_args); + let args = args::arg_expand_all(&default_early_dcx, at_args)?; let Some(matches) = handle_options(&default_early_dcx, &args) else { return Ok(()) }; @@ -314,7 +315,7 @@ fn run_compiler( file_loader, locale_resources: DEFAULT_LOCALE_RESOURCES, lint_caps: Default::default(), - parse_sess_created: None, + psess_created: None, hash_untracked_state: None, register_lints: None, override_queries: None, @@ -417,7 +418,7 @@ fn run_compiler( } // Make sure name resolution and macro expansion is run. - queries.global_ctxt()?.enter(|tcx| tcx.resolver_for_lowering(())); + queries.global_ctxt()?.enter(|tcx| tcx.resolver_for_lowering()); if callbacks.after_expansion(compiler, queries) == Compilation::Stop { return early_exit(); @@ -768,7 +769,7 @@ fn print_crate_info( } Cfg => { let mut cfgs = sess - .parse_sess + .psess .config .iter() .filter_map(|&(name, value)| { @@ -1215,12 +1216,10 @@ pub fn handle_options(early_dcx: &EarlyDiagCtxt, args: &[String]) -> Option(sess: &'a Session) -> PResult<'a, ast::AttrVec> { match &sess.io.input { - Input::File(ifile) => rustc_parse::parse_crate_attrs_from_file(ifile, &sess.parse_sess), - Input::Str { name, input } => rustc_parse::parse_crate_attrs_from_source_str( - name.clone(), - input.clone(), - &sess.parse_sess, - ), + Input::File(ifile) => rustc_parse::parse_crate_attrs_from_file(ifile, &sess.psess), + Input::Str { name, input } => { + rustc_parse::parse_crate_attrs_from_source_str(name.clone(), input.clone(), &sess.psess) + } } } @@ -1371,6 +1370,9 @@ pub fn install_ice_hook( using_internal_features } +const DATE_FORMAT: &[time::format_description::FormatItem<'static>] = + &time::macros::format_description!("[year]-[month]-[day]"); + /// Prints the ICE message, including query stack, but without backtrace. /// /// The message will point the user at `bug_report_url` to report the ICE. @@ -1399,10 +1401,34 @@ fn report_ice( dcx.emit_err(session_diagnostics::Ice); } - if using_internal_features.load(std::sync::atomic::Ordering::Relaxed) { - dcx.emit_note(session_diagnostics::IceBugReportInternalFeature); + use time::ext::NumericalDuration; + + // Try to hint user to update nightly if applicable when reporting an ICE. + // Attempt to calculate when current version was released, and add 12 hours + // as buffer. If the current version's release timestamp is older than + // the system's current time + 24 hours + 12 hours buffer if we're on + // nightly. + if let Some("nightly") = option_env!("CFG_RELEASE_CHANNEL") + && let Some(version) = option_env!("CFG_VERSION") + && let Some(ver_date_str) = option_env!("CFG_VER_DATE") + && let Ok(ver_date) = Date::parse(&ver_date_str, DATE_FORMAT) + && let ver_datetime = OffsetDateTime::new_utc(ver_date, Time::MIDNIGHT) + && let system_datetime = OffsetDateTime::from(SystemTime::now()) + && system_datetime.checked_sub(36.hours()).is_some_and(|d| d > ver_datetime) + && !using_internal_features.load(std::sync::atomic::Ordering::Relaxed) + { + dcx.emit_note(session_diagnostics::IceBugReportOutdated { + version, + bug_report_url, + note_update: (), + note_url: (), + }); } else { - dcx.emit_note(session_diagnostics::IceBugReport { bug_report_url }); + if using_internal_features.load(std::sync::atomic::Ordering::Relaxed) { + dcx.emit_note(session_diagnostics::IceBugReportInternalFeature); + } else { + dcx.emit_note(session_diagnostics::IceBugReport { bug_report_url }); + } } let version = util::version_str!().unwrap_or("unknown_version"); @@ -1489,15 +1515,7 @@ pub fn main() -> ! { let mut callbacks = TimePassesCallbacks::default(); let using_internal_features = install_ice_hook(DEFAULT_BUG_REPORT_URL, |_| ()); let exit_code = catch_with_exit_code(|| { - let args = env::args_os() - .enumerate() - .map(|(i, arg)| { - arg.into_string().unwrap_or_else(|arg| { - early_dcx.early_fatal(format!("argument {i} is not valid Unicode: {arg:?}")) - }) - }) - .collect::>(); - RunCompiler::new(&args, &mut callbacks) + RunCompiler::new(&args::raw_args(&early_dcx)?, &mut callbacks) .set_using_internal_features(using_internal_features) .run() }); diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs index ff5ffd2454a1f..c9bbe45b21276 100644 --- a/compiler/rustc_driver_impl/src/pretty.rs +++ b/compiler/rustc_driver_impl/src/pretty.rs @@ -229,7 +229,7 @@ impl<'tcx> PrintExtra<'tcx> { { match self { PrintExtra::AfterParsing { krate, .. } => f(krate), - PrintExtra::NeedsAstMap { tcx } => f(&tcx.resolver_for_lowering(()).borrow().1), + PrintExtra::NeedsAstMap { tcx } => f(&tcx.resolver_for_lowering().borrow().1), } } @@ -260,7 +260,7 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) { ExpandedIdentified => Box::new(AstIdentifiedAnn), ExpandedHygiene => Box::new(AstHygieneAnn { sess }), }; - let parse = &sess.parse_sess; + let psess = &sess.psess; let is_expanded = ppm.needs_ast_map(); ex.with_krate(|krate| { pprust_ast::print_crate( @@ -270,8 +270,8 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) { src, &*annotation, is_expanded, - parse.edition, - &sess.parse_sess.attr_id_generator, + psess.edition, + &sess.psess.attr_id_generator, ) }) } @@ -281,7 +281,7 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) { } AstTreeExpanded => { debug!("pretty-printing expanded AST"); - format!("{:#?}", ex.tcx().resolver_for_lowering(()).borrow().1) + format!("{:#?}", ex.tcx().resolver_for_lowering().borrow().1) } Hir(s) => { debug!("pretty printing HIR {:?}", s); diff --git a/compiler/rustc_driver_impl/src/session_diagnostics.rs b/compiler/rustc_driver_impl/src/session_diagnostics.rs index 2b31fdd77cca3..62d0da62d2a79 100644 --- a/compiler/rustc_driver_impl/src/session_diagnostics.rs +++ b/compiler/rustc_driver_impl/src/session_diagnostics.rs @@ -46,6 +46,17 @@ pub(crate) struct IceBugReport<'a> { #[diag(driver_impl_ice_bug_report_internal_feature)] pub(crate) struct IceBugReportInternalFeature; +#[derive(Diagnostic)] +#[diag(driver_impl_ice_bug_report_outdated)] +pub(crate) struct IceBugReportOutdated<'a> { + pub version: &'a str, + pub bug_report_url: &'a str, + #[note(driver_impl_update)] + pub note_update: (), + #[note(driver_impl_url)] + pub note_url: (), +} + #[derive(Diagnostic)] #[diag(driver_impl_ice_version)] pub(crate) struct IceVersion<'a> { diff --git a/compiler/rustc_error_codes/src/error_codes/E0657.md b/compiler/rustc_error_codes/src/error_codes/E0657.md index 7fe48c5114790..477d8e8bb6dad 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0657.md +++ b/compiler/rustc_error_codes/src/error_codes/E0657.md @@ -1,57 +1,26 @@ -A lifetime bound on a trait implementation was captured at an incorrect place. +An `impl Trait` captured a higher-ranked lifetime, which is not supported. + +Currently, `impl Trait` types are only allowed to capture lifetimes from +their parent items, and not from any `for<'a>` binders in scope. Erroneous code example: ```compile_fail,E0657 -trait Id {} -trait Lt<'a> {} - -impl<'a> Lt<'a> for () {} -impl Id for T {} - -fn free_fn_capture_hrtb_in_impl_trait() - -> Box Id>> // error! -{ - Box::new(()) -} +trait BorrowInto<'a> { + type Target; -struct Foo; -impl Foo { - fn impl_fn_capture_hrtb_in_impl_trait() - -> Box Id>> // error! - { - Box::new(()) - } + fn borrow_into(&'a self) -> Self::Target; } -``` -Here, you have used the inappropriate lifetime in the `impl Trait`, -The `impl Trait` can only capture lifetimes bound at the fn or impl -level. +impl<'a> BorrowInto<'a> for () { + type Target = &'a (); -To fix this we have to define the lifetime at the function or impl -level and use that lifetime in the `impl Trait`. For example you can -define the lifetime at the function: - -``` -trait Id {} -trait Lt<'a> {} - -impl<'a> Lt<'a> for () {} -impl Id for T {} - -fn free_fn_capture_hrtb_in_impl_trait<'b>() - -> Box Id>> // ok! -{ - Box::new(()) + fn borrow_into(&'a self) -> Self::Target { + self + } } -struct Foo; -impl Foo { - fn impl_fn_capture_hrtb_in_impl_trait<'b>() - -> Box Id>> // ok! - { - Box::new(()) - } +fn opaque() -> impl for<'a> BorrowInto<'a, Target = impl Sized + 'a> { + () } ``` diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index f91b6655f6399..ad82c2d96e7a7 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -253,11 +253,11 @@ type FluentId = Cow<'static, str>; /// translatable and non-translatable diagnostic messages. /// /// Translatable messages for subdiagnostics are typically attributes attached to a larger Fluent -/// message so messages of this type must be combined with a `DiagnosticMessage` (using -/// `DiagnosticMessage::with_subdiagnostic_message`) before rendering. However, subdiagnostics from +/// message so messages of this type must be combined with a `DiagMessage` (using +/// `DiagMessage::with_subdiagnostic_message`) before rendering. However, subdiagnostics from /// the `Subdiagnostic` derive refer to Fluent identifiers directly. -#[rustc_diagnostic_item = "SubdiagnosticMessage"] -pub enum SubdiagnosticMessage { +#[rustc_diagnostic_item = "SubdiagMessage"] +pub enum SubdiagMessage { /// Non-translatable diagnostic message. Str(Cow<'static, str>), /// Translatable message which has already been translated eagerly. @@ -265,7 +265,7 @@ pub enum SubdiagnosticMessage { /// Some diagnostics have repeated subdiagnostics where the same interpolated variables would /// be instantiated multiple times with different values. These subdiagnostics' messages /// are translated when they are added to the parent diagnostic, producing this variant of - /// `DiagnosticMessage`. + /// `DiagMessage`. Translated(Cow<'static, str>), /// Identifier of a Fluent message. Instances of this variant are generated by the /// `Subdiagnostic` derive. @@ -278,19 +278,19 @@ pub enum SubdiagnosticMessage { FluentAttr(FluentId), } -impl From for SubdiagnosticMessage { +impl From for SubdiagMessage { fn from(s: String) -> Self { - SubdiagnosticMessage::Str(Cow::Owned(s)) + SubdiagMessage::Str(Cow::Owned(s)) } } -impl From<&'static str> for SubdiagnosticMessage { +impl From<&'static str> for SubdiagMessage { fn from(s: &'static str) -> Self { - SubdiagnosticMessage::Str(Cow::Borrowed(s)) + SubdiagMessage::Str(Cow::Borrowed(s)) } } -impl From> for SubdiagnosticMessage { +impl From> for SubdiagMessage { fn from(s: Cow<'static, str>) -> Self { - SubdiagnosticMessage::Str(s) + SubdiagMessage::Str(s) } } @@ -299,8 +299,8 @@ impl From> for SubdiagnosticMessage { /// /// Intended to be removed once diagnostics are entirely translatable. #[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)] -#[rustc_diagnostic_item = "DiagnosticMessage"] -pub enum DiagnosticMessage { +#[rustc_diagnostic_item = "DiagMessage"] +pub enum DiagMessage { /// Non-translatable diagnostic message. Str(Cow<'static, str>), /// Translatable message which has been already translated. @@ -308,7 +308,7 @@ pub enum DiagnosticMessage { /// Some diagnostics have repeated subdiagnostics where the same interpolated variables would /// be instantiated multiple times with different values. These subdiagnostics' messages /// are translated when they are added to the parent diagnostic, producing this variant of - /// `DiagnosticMessage`. + /// `DiagMessage`. Translated(Cow<'static, str>), /// Identifier for a Fluent message (with optional attribute) corresponding to the diagnostic /// message. Yet to be translated. @@ -318,85 +318,80 @@ pub enum DiagnosticMessage { FluentIdentifier(FluentId, Option), } -impl DiagnosticMessage { - /// Given a `SubdiagnosticMessage` which may contain a Fluent attribute, create a new - /// `DiagnosticMessage` that combines that attribute with the Fluent identifier of `self`. +impl DiagMessage { + /// Given a `SubdiagMessage` which may contain a Fluent attribute, create a new + /// `DiagMessage` that combines that attribute with the Fluent identifier of `self`. /// - /// - If the `SubdiagnosticMessage` is non-translatable then return the message as a - /// `DiagnosticMessage`. + /// - If the `SubdiagMessage` is non-translatable then return the message as a `DiagMessage`. /// - If `self` is non-translatable then return `self`'s message. - pub fn with_subdiagnostic_message(&self, sub: SubdiagnosticMessage) -> Self { + pub fn with_subdiagnostic_message(&self, sub: SubdiagMessage) -> Self { let attr = match sub { - SubdiagnosticMessage::Str(s) => return DiagnosticMessage::Str(s), - SubdiagnosticMessage::Translated(s) => return DiagnosticMessage::Translated(s), - SubdiagnosticMessage::FluentIdentifier(id) => { - return DiagnosticMessage::FluentIdentifier(id, None); + SubdiagMessage::Str(s) => return DiagMessage::Str(s), + SubdiagMessage::Translated(s) => return DiagMessage::Translated(s), + SubdiagMessage::FluentIdentifier(id) => { + return DiagMessage::FluentIdentifier(id, None); } - SubdiagnosticMessage::FluentAttr(attr) => attr, + SubdiagMessage::FluentAttr(attr) => attr, }; match self { - DiagnosticMessage::Str(s) => DiagnosticMessage::Str(s.clone()), - DiagnosticMessage::Translated(s) => DiagnosticMessage::Translated(s.clone()), - DiagnosticMessage::FluentIdentifier(id, _) => { - DiagnosticMessage::FluentIdentifier(id.clone(), Some(attr)) + DiagMessage::Str(s) => DiagMessage::Str(s.clone()), + DiagMessage::Translated(s) => DiagMessage::Translated(s.clone()), + DiagMessage::FluentIdentifier(id, _) => { + DiagMessage::FluentIdentifier(id.clone(), Some(attr)) } } } pub fn as_str(&self) -> Option<&str> { match self { - DiagnosticMessage::Translated(s) | DiagnosticMessage::Str(s) => Some(s), - DiagnosticMessage::FluentIdentifier(_, _) => None, + DiagMessage::Translated(s) | DiagMessage::Str(s) => Some(s), + DiagMessage::FluentIdentifier(_, _) => None, } } } -impl From for DiagnosticMessage { +impl From for DiagMessage { fn from(s: String) -> Self { - DiagnosticMessage::Str(Cow::Owned(s)) + DiagMessage::Str(Cow::Owned(s)) } } -impl From<&'static str> for DiagnosticMessage { +impl From<&'static str> for DiagMessage { fn from(s: &'static str) -> Self { - DiagnosticMessage::Str(Cow::Borrowed(s)) + DiagMessage::Str(Cow::Borrowed(s)) } } -impl From> for DiagnosticMessage { +impl From> for DiagMessage { fn from(s: Cow<'static, str>) -> Self { - DiagnosticMessage::Str(s) + DiagMessage::Str(s) } } /// A workaround for must_produce_diag ICEs when formatting types in disabled lints. /// -/// Delays formatting until `.into(): DiagnosticMessage` is used. +/// Delays formatting until `.into(): DiagMessage` is used. pub struct DelayDm(pub F); -impl String> From> for DiagnosticMessage { +impl String> From> for DiagMessage { fn from(DelayDm(f): DelayDm) -> Self { - DiagnosticMessage::from(f()) + DiagMessage::from(f()) } } /// Translating *into* a subdiagnostic message from a diagnostic message is a little strange - but -/// the subdiagnostic functions (e.g. `span_label`) take a `SubdiagnosticMessage` and the -/// subdiagnostic derive refers to typed identifiers that are `DiagnosticMessage`s, so need to be -/// able to convert between these, as much as they'll be converted back into `DiagnosticMessage` +/// the subdiagnostic functions (e.g. `span_label`) take a `SubdiagMessage` and the +/// subdiagnostic derive refers to typed identifiers that are `DiagMessage`s, so need to be +/// able to convert between these, as much as they'll be converted back into `DiagMessage` /// using `with_subdiagnostic_message` eventually. Don't use this other than for the derive. -impl Into for DiagnosticMessage { - fn into(self) -> SubdiagnosticMessage { +impl Into for DiagMessage { + fn into(self) -> SubdiagMessage { match self { - DiagnosticMessage::Str(s) => SubdiagnosticMessage::Str(s), - DiagnosticMessage::Translated(s) => SubdiagnosticMessage::Translated(s), - DiagnosticMessage::FluentIdentifier(id, None) => { - SubdiagnosticMessage::FluentIdentifier(id) - } + DiagMessage::Str(s) => SubdiagMessage::Str(s), + DiagMessage::Translated(s) => SubdiagMessage::Translated(s), + DiagMessage::FluentIdentifier(id, None) => SubdiagMessage::FluentIdentifier(id), // There isn't really a sensible behaviour for this because it loses information but // this is the most sensible of the behaviours. - DiagnosticMessage::FluentIdentifier(_, Some(attr)) => { - SubdiagnosticMessage::FluentAttr(attr) - } + DiagMessage::FluentIdentifier(_, Some(attr)) => SubdiagMessage::FluentAttr(attr), } } } @@ -412,7 +407,7 @@ pub struct SpanLabel { pub is_primary: bool, /// What label should we attach to this span (if any)? - pub label: Option, + pub label: Option, } /// A collection of `Span`s. @@ -426,7 +421,7 @@ pub struct SpanLabel { #[derive(Clone, Debug, Hash, PartialEq, Eq, Encodable, Decodable)] pub struct MultiSpan { primary_spans: Vec, - span_labels: Vec<(Span, DiagnosticMessage)>, + span_labels: Vec<(Span, DiagMessage)>, } impl MultiSpan { @@ -444,7 +439,7 @@ impl MultiSpan { MultiSpan { primary_spans: vec, span_labels: vec![] } } - pub fn push_span_label(&mut self, span: Span, label: impl Into) { + pub fn push_span_label(&mut self, span: Span, label: impl Into) { self.span_labels.push((span, label.into())); } @@ -487,7 +482,7 @@ impl MultiSpan { replacements_occurred } - pub fn pop_span_label(&mut self) -> Option<(Span, DiagnosticMessage)> { + pub fn pop_span_label(&mut self) -> Option<(Span, DiagMessage)> { self.span_labels.pop() } diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index e6668769b955e..b71b93cc67c16 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -9,8 +9,8 @@ use crate::emitter::FileWithAnnotatedLines; use crate::snippet::Line; use crate::translation::{to_fluent_args, Translate}; use crate::{ - CodeSuggestion, DiagInner, DiagnosticMessage, Emitter, ErrCode, FluentBundle, - LazyFallbackBundle, Level, MultiSpan, Style, Subdiag, + CodeSuggestion, DiagInner, DiagMessage, Emitter, ErrCode, FluentBundle, LazyFallbackBundle, + Level, MultiSpan, Style, Subdiag, }; use annotate_snippets::{Annotation, AnnotationType, Renderer, Slice, Snippet, SourceAnnotation}; use rustc_data_structures::sync::Lrc; @@ -125,7 +125,7 @@ impl AnnotateSnippetEmitter { fn emit_messages_default( &mut self, level: &Level, - messages: &[(DiagnosticMessage, Style)], + messages: &[(DiagMessage, Style)], args: &FluentArgs<'_>, code: &Option, msp: &MultiSpan, diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 1c820bfd01f91..c186d5b284fc4 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -1,7 +1,7 @@ use crate::snippet::Style; use crate::{ - CodeSuggestion, DiagCtxt, DiagnosticMessage, ErrCode, ErrorGuaranteed, ExplicitBug, Level, - MultiSpan, StashKey, SubdiagnosticMessage, Substitution, SubstitutionPart, SuggestionStyle, + CodeSuggestion, DiagCtxt, DiagMessage, ErrCode, ErrorGuaranteed, ExplicitBug, Level, MultiSpan, + StashKey, SubdiagMessage, Substitution, SubstitutionPart, SuggestionStyle, }; use rustc_data_structures::fx::FxIndexMap; use rustc_error_messages::fluent_value_from_str_list_sep_by_and; @@ -182,15 +182,14 @@ where /// Add a subdiagnostic to an existing diagnostic where `f` is invoked on every message used /// (to optionally perform eager translation). - fn add_to_diagnostic_with>( + fn add_to_diagnostic_with>( self, diag: &mut Diag<'_, G>, f: F, ); } -pub trait SubdiagnosticMessageOp = - Fn(&mut Diag<'_, G>, SubdiagnosticMessage) -> SubdiagnosticMessage; +pub trait SubdiagMessageOp = Fn(&mut Diag<'_, G>, SubdiagMessage) -> SubdiagMessage; /// Trait implemented by lint types. This should not be implemented manually. Instead, use /// `#[derive(LintDiagnostic)]` -- see [rustc_macros::LintDiagnostic]. @@ -199,7 +198,7 @@ pub trait DecorateLint<'a, G: EmissionGuarantee> { /// Decorate and emit a lint. fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>); - fn msg(&self) -> DiagnosticMessage; + fn msg(&self) -> DiagMessage; } #[derive(Clone, Debug, Encodable, Decodable)] @@ -291,7 +290,7 @@ pub struct DiagInner { // outside of what methods in this crate themselves allow. pub(crate) level: Level, - pub messages: Vec<(DiagnosticMessage, Style)>, + pub messages: Vec<(DiagMessage, Style)>, pub code: Option, pub span: MultiSpan, pub children: Vec, @@ -312,12 +311,12 @@ pub struct DiagInner { impl DiagInner { #[track_caller] - pub fn new>(level: Level, message: M) -> Self { + pub fn new>(level: Level, message: M) -> Self { DiagInner::new_with_messages(level, vec![(message.into(), Style::NoStyle)]) } #[track_caller] - pub fn new_with_messages(level: Level, messages: Vec<(DiagnosticMessage, Style)>) -> Self { + pub fn new_with_messages(level: Level, messages: Vec<(DiagMessage, Style)>) -> Self { DiagInner { level, messages, @@ -396,8 +395,8 @@ impl DiagInner { // See comment on `Diag::subdiagnostic_message_to_diagnostic_message`. pub(crate) fn subdiagnostic_message_to_diagnostic_message( &self, - attr: impl Into, - ) -> DiagnosticMessage { + attr: impl Into, + ) -> DiagMessage { let msg = self.messages.iter().map(|(msg, _)| msg).next().expect("diagnostic with no messages"); msg.with_subdiagnostic_message(attr.into()) @@ -406,7 +405,7 @@ impl DiagInner { pub(crate) fn sub( &mut self, level: Level, - message: impl Into, + message: impl Into, span: MultiSpan, ) { let sub = Subdiag { @@ -429,7 +428,7 @@ impl DiagInner { &self, ) -> ( &Level, - &[(DiagnosticMessage, Style)], + &[(DiagMessage, Style)], &Option, &MultiSpan, &[Subdiag], @@ -472,7 +471,7 @@ impl PartialEq for DiagInner { #[derive(Clone, Debug, PartialEq, Hash, Encodable, Decodable)] pub struct Subdiag { pub level: Level, - pub messages: Vec<(DiagnosticMessage, Style)>, + pub messages: Vec<(DiagMessage, Style)>, pub span: MultiSpan, } @@ -578,7 +577,7 @@ macro_rules! with_fn { impl<'a, G: EmissionGuarantee> Diag<'a, G> { #[rustc_lint_diagnostics] #[track_caller] - pub fn new>(dcx: &'a DiagCtxt, level: Level, message: M) -> Self { + pub fn new(dcx: &'a DiagCtxt, level: Level, message: impl Into) -> Self { Self::new_diagnostic(dcx, DiagInner::new(level, message)) } @@ -599,6 +598,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// /// In the meantime, though, callsites are required to deal with the "bug" /// locally in whichever way makes the most sense. + #[rustc_lint_diagnostics] #[track_caller] pub fn downgrade_to_delayed_bug(&mut self) { assert!( @@ -623,7 +623,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// ["primary span"][`MultiSpan`]; only the `Span` supplied when creating the diagnostic is /// primary. #[rustc_lint_diagnostics] - pub fn span_label(&mut self, span: Span, label: impl Into) -> &mut Self { + pub fn span_label(&mut self, span: Span, label: impl Into) -> &mut Self { let msg = self.subdiagnostic_message_to_diagnostic_message(label); self.span.push_span_label(span, msg); self @@ -632,6 +632,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { with_fn! { with_span_labels, /// Labels all the given spans with the provided label. /// See [`Self::span_label()`] for more information. + #[rustc_lint_diagnostics] pub fn span_labels(&mut self, spans: impl IntoIterator, label: &str) -> &mut Self { for span in spans { self.span_label(span, label.to_string()); @@ -639,6 +640,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { self } } + #[rustc_lint_diagnostics] pub fn replace_span_with(&mut self, after: Span, keep_label: bool) -> &mut Self { let before = self.span.clone(); self.span(after); @@ -654,6 +656,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { self } + #[rustc_lint_diagnostics] pub fn note_expected_found( &mut self, expected_label: &dyn fmt::Display, @@ -664,6 +667,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { self.note_expected_found_extra(expected_label, expected, found_label, found, &"", &"") } + #[rustc_lint_diagnostics] pub fn note_expected_found_extra( &mut self, expected_label: &dyn fmt::Display, @@ -706,6 +710,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { self } + #[rustc_lint_diagnostics] pub fn note_trait_signature(&mut self, name: Symbol, signature: String) -> &mut Self { self.highlighted_note(vec![ StringPart::normal(format!("`{name}` from trait: `")), @@ -718,18 +723,20 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { with_fn! { with_note, /// Add a note attached to this diagnostic. #[rustc_lint_diagnostics] - pub fn note(&mut self, msg: impl Into) -> &mut Self { + pub fn note(&mut self, msg: impl Into) -> &mut Self { self.sub(Level::Note, msg, MultiSpan::new()); self } } + #[rustc_lint_diagnostics] fn highlighted_note(&mut self, msg: Vec) -> &mut Self { self.sub_with_highlights(Level::Note, msg, MultiSpan::new()); self } /// This is like [`Diag::note()`], but it's only printed once. - pub fn note_once(&mut self, msg: impl Into) -> &mut Self { + #[rustc_lint_diagnostics] + pub fn note_once(&mut self, msg: impl Into) -> &mut Self { self.sub(Level::OnceNote, msg, MultiSpan::new()); self } @@ -741,7 +748,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { pub fn span_note( &mut self, sp: impl Into, - msg: impl Into, + msg: impl Into, ) -> &mut Self { self.sub(Level::Note, msg, sp.into()); self @@ -749,10 +756,11 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// Prints the span with a note above it. /// This is like [`Diag::note_once()`], but it gets its own span. + #[rustc_lint_diagnostics] pub fn span_note_once>( &mut self, sp: S, - msg: impl Into, + msg: impl Into, ) -> &mut Self { self.sub(Level::OnceNote, msg, sp.into()); self @@ -761,7 +769,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { with_fn! { with_warn, /// Add a warning attached to this diagnostic. #[rustc_lint_diagnostics] - pub fn warn(&mut self, msg: impl Into) -> &mut Self { + pub fn warn(&mut self, msg: impl Into) -> &mut Self { self.sub(Level::Warning, msg, MultiSpan::new()); self } } @@ -772,7 +780,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { pub fn span_warn>( &mut self, sp: S, - msg: impl Into, + msg: impl Into, ) -> &mut Self { self.sub(Level::Warning, msg, sp.into()); self @@ -781,18 +789,20 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { with_fn! { with_help, /// Add a help message attached to this diagnostic. #[rustc_lint_diagnostics] - pub fn help(&mut self, msg: impl Into) -> &mut Self { + pub fn help(&mut self, msg: impl Into) -> &mut Self { self.sub(Level::Help, msg, MultiSpan::new()); self } } /// This is like [`Diag::help()`], but it's only printed once. - pub fn help_once(&mut self, msg: impl Into) -> &mut Self { + #[rustc_lint_diagnostics] + pub fn help_once(&mut self, msg: impl Into) -> &mut Self { self.sub(Level::OnceHelp, msg, MultiSpan::new()); self } /// Add a help message attached to this diagnostic with a customizable highlighted message. + #[rustc_lint_diagnostics] pub fn highlighted_help(&mut self, msg: Vec) -> &mut Self { self.sub_with_highlights(Level::Help, msg, MultiSpan::new()); self @@ -804,7 +814,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { pub fn span_help>( &mut self, sp: S, - msg: impl Into, + msg: impl Into, ) -> &mut Self { self.sub(Level::Help, msg, sp.into()); self @@ -813,12 +823,14 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// Disallow attaching suggestions this diagnostic. /// Any suggestions attached e.g. with the `span_suggestion_*` methods /// (before and after the call to `disable_suggestions`) will be ignored. + #[rustc_lint_diagnostics] pub fn disable_suggestions(&mut self) -> &mut Self { self.suggestions = Err(SuggestionsDisabled); self } /// Helper for pushing to `self.suggestions`, if available (not disable). + #[rustc_lint_diagnostics] fn push_suggestion(&mut self, suggestion: CodeSuggestion) { for subst in &suggestion.substitutions { for part in &subst.parts { @@ -839,9 +851,10 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { with_fn! { with_multipart_suggestion, /// Show a suggestion that has multiple parts to it. /// In other words, multiple changes need to be applied as part of this suggestion. + #[rustc_lint_diagnostics] pub fn multipart_suggestion( &mut self, - msg: impl Into, + msg: impl Into, suggestion: Vec<(Span, String)>, applicability: Applicability, ) -> &mut Self { @@ -855,9 +868,10 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// Show a suggestion that has multiple parts to it, always as it's own subdiagnostic. /// In other words, multiple changes need to be applied as part of this suggestion. + #[rustc_lint_diagnostics] pub fn multipart_suggestion_verbose( &mut self, - msg: impl Into, + msg: impl Into, suggestion: Vec<(Span, String)>, applicability: Applicability, ) -> &mut Self { @@ -870,9 +884,10 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { } /// [`Diag::multipart_suggestion()`] but you can set the [`SuggestionStyle`]. + #[rustc_lint_diagnostics] pub fn multipart_suggestion_with_style( &mut self, - msg: impl Into, + msg: impl Into, mut suggestion: Vec<(Span, String)>, applicability: Applicability, style: SuggestionStyle, @@ -912,9 +927,10 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// be from the message, showing the span label inline would be visually unpleasant /// (marginally overlapping spans or multiline spans) and showing the snippet window wouldn't /// improve understandability. + #[rustc_lint_diagnostics] pub fn tool_only_multipart_suggestion( &mut self, - msg: impl Into, + msg: impl Into, suggestion: Vec<(Span, String)>, applicability: Applicability, ) -> &mut Self { @@ -944,10 +960,11 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// * may contain a name of a function, variable, or type, but not whole expressions /// /// See `CodeSuggestion` for more information. + #[rustc_lint_diagnostics] pub fn span_suggestion( &mut self, sp: Span, - msg: impl Into, + msg: impl Into, suggestion: impl ToString, applicability: Applicability, ) -> &mut Self { @@ -962,10 +979,11 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { } } /// [`Diag::span_suggestion()`] but you can set the [`SuggestionStyle`]. + #[rustc_lint_diagnostics] pub fn span_suggestion_with_style( &mut self, sp: Span, - msg: impl Into, + msg: impl Into, suggestion: impl ToString, applicability: Applicability, style: SuggestionStyle, @@ -987,10 +1005,11 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { with_fn! { with_span_suggestion_verbose, /// Always show the suggested change. + #[rustc_lint_diagnostics] pub fn span_suggestion_verbose( &mut self, sp: Span, - msg: impl Into, + msg: impl Into, suggestion: impl ToString, applicability: Applicability, ) -> &mut Self { @@ -1007,10 +1026,11 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { with_fn! { with_span_suggestions, /// Prints out a message with multiple suggested edits of the code. /// See also [`Diag::span_suggestion()`]. + #[rustc_lint_diagnostics] pub fn span_suggestions( &mut self, sp: Span, - msg: impl Into, + msg: impl Into, suggestions: impl IntoIterator, applicability: Applicability, ) -> &mut Self { @@ -1023,10 +1043,11 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { ) } } + #[rustc_lint_diagnostics] pub fn span_suggestions_with_style( &mut self, sp: Span, - msg: impl Into, + msg: impl Into, suggestions: impl IntoIterator, applicability: Applicability, style: SuggestionStyle, @@ -1053,9 +1074,10 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// Prints out a message with multiple suggested edits of the code, where each edit consists of /// multiple parts. /// See also [`Diag::multipart_suggestion()`]. + #[rustc_lint_diagnostics] pub fn multipart_suggestions( &mut self, - msg: impl Into, + msg: impl Into, suggestions: impl IntoIterator>, applicability: Applicability, ) -> &mut Self { @@ -1099,10 +1121,11 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// inline, it will only show the message and not the suggestion. /// /// See `CodeSuggestion` for more information. + #[rustc_lint_diagnostics] pub fn span_suggestion_short( &mut self, sp: Span, - msg: impl Into, + msg: impl Into, suggestion: impl ToString, applicability: Applicability, ) -> &mut Self { @@ -1122,10 +1145,11 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// be from the message, showing the span label inline would be visually unpleasant /// (marginally overlapping spans or multiline spans) and showing the snippet window wouldn't /// improve understandability. + #[rustc_lint_diagnostics] pub fn span_suggestion_hidden( &mut self, sp: Span, - msg: impl Into, + msg: impl Into, suggestion: impl ToString, applicability: Applicability, ) -> &mut Self { @@ -1148,7 +1172,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { pub fn tool_only_span_suggestion( &mut self, sp: Span, - msg: impl Into, + msg: impl Into, suggestion: impl ToString, applicability: Applicability, ) -> &mut Self { @@ -1166,6 +1190,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// [rustc_macros::Subdiagnostic]). Performs eager translation of any translatable messages /// used in the subdiagnostic, so suitable for use with repeated messages (i.e. re-use of /// interpolated variables). + #[rustc_lint_diagnostics] pub fn subdiagnostic( &mut self, dcx: &crate::DiagCtxt, @@ -1181,6 +1206,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { with_fn! { with_span, /// Add a span. + #[rustc_lint_diagnostics] pub fn span(&mut self, sp: impl Into) -> &mut Self { self.span = sp.into(); if let Some(span) = self.span.primary_span() { @@ -1189,6 +1215,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { self } } + #[rustc_lint_diagnostics] pub fn is_lint(&mut self, name: String, has_future_breakage: bool) -> &mut Self { self.is_lint = Some(IsLint { name, has_future_breakage }); self @@ -1196,6 +1223,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { with_fn! { with_code, /// Add an error code. + #[rustc_lint_diagnostics] pub fn code(&mut self, code: ErrCode) -> &mut Self { self.code = Some(code); self @@ -1203,13 +1231,15 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { with_fn! { with_primary_message, /// Add a primary message. - pub fn primary_message(&mut self, msg: impl Into) -> &mut Self { + #[rustc_lint_diagnostics] + pub fn primary_message(&mut self, msg: impl Into) -> &mut Self { self.messages[0] = (msg.into(), Style::NoStyle); self } } with_fn! { with_arg, /// Add an argument. + #[rustc_lint_diagnostics] pub fn arg( &mut self, name: impl Into, @@ -1219,13 +1249,13 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { self } } - /// Helper function that takes a `SubdiagnosticMessage` and returns a `DiagnosticMessage` by + /// Helper function that takes a `SubdiagMessage` and returns a `DiagMessage` by /// combining it with the primary message of the diagnostic (if translatable, otherwise it just /// passes the user's string along). pub(crate) fn subdiagnostic_message_to_diagnostic_message( &self, - attr: impl Into, - ) -> DiagnosticMessage { + attr: impl Into, + ) -> DiagMessage { self.deref().subdiagnostic_message_to_diagnostic_message(attr) } @@ -1233,7 +1263,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// public methods above. /// /// Used by `proc_macro_server` for implementing `server::Diagnostic`. - pub fn sub(&mut self, level: Level, message: impl Into, span: MultiSpan) { + pub fn sub(&mut self, level: Level, message: impl Into, span: MultiSpan) { self.deref_mut().sub(level, message, span); } @@ -1338,7 +1368,7 @@ impl Drop for Diag<'_, G> { Some(diag) if !panicking() => { self.dcx.emit_diagnostic(DiagInner::new( Level::Bug, - DiagnosticMessage::from("the following error was constructed but not emitted"), + DiagMessage::from("the following error was constructed but not emitted"), )); self.dcx.emit_diagnostic(*diag); panic!("error was constructed but not emitted"); diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index 70c8d9718681d..839bd65e4a639 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -2,7 +2,7 @@ use crate::diagnostic::DiagLocation; use crate::{fluent_generated as fluent, AddToDiagnostic}; use crate::{ Diag, DiagArgValue, DiagCtxt, EmissionGuarantee, ErrCode, IntoDiagnostic, IntoDiagnosticArg, - Level, SubdiagnosticMessageOp, + Level, SubdiagMessageOp, }; use rustc_ast as ast; use rustc_ast_pretty::pprust; @@ -298,7 +298,7 @@ pub struct SingleLabelManySpans { pub label: &'static str, } impl AddToDiagnostic for SingleLabelManySpans { - fn add_to_diagnostic_with>( + fn add_to_diagnostic_with>( self, diag: &mut Diag<'_, G>, _: F, diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 5637c05d04c69..57b8df52f4b79 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -10,14 +10,13 @@ use rustc_span::source_map::SourceMap; use rustc_span::{FileLines, FileName, SourceFile, Span}; -use crate::error::TranslateError; use crate::snippet::{ Annotation, AnnotationColumn, AnnotationType, Line, MultilineAnnotation, Style, StyledString, }; use crate::styled_buffer::StyledBuffer; use crate::translation::{to_fluent_args, Translate}; use crate::{ - diagnostic::DiagLocation, CodeSuggestion, DiagCtxt, DiagInner, DiagnosticMessage, ErrCode, + diagnostic::DiagLocation, CodeSuggestion, DiagCtxt, DiagInner, DiagMessage, ErrCode, FluentBundle, LazyFallbackBundle, Level, MultiSpan, Subdiag, SubstitutionHighlight, SuggestionStyle, TerminalUrl, }; @@ -339,7 +338,7 @@ pub trait Emitter: Translate { children.push(Subdiag { level: Level::Note, - messages: vec![(DiagnosticMessage::from(msg), Style::NoStyle)], + messages: vec![(DiagMessage::from(msg), Style::NoStyle)], span: MultiSpan::new(), }); } @@ -539,20 +538,9 @@ impl Emitter for HumanEmitter { /// Fatal diagnostics are forwarded to `fatal_dcx` to avoid silent /// failures of rustc, as witnessed e.g. in issue #89358. pub struct SilentEmitter { + pub fallback_bundle: LazyFallbackBundle, pub fatal_dcx: DiagCtxt, - pub fatal_note: String, -} - -pub fn silent_translate<'a>( - message: &'a DiagnosticMessage, -) -> Result, TranslateError<'_>> { - match message { - DiagnosticMessage::Str(msg) | DiagnosticMessage::Translated(msg) => Ok(Cow::Borrowed(msg)), - DiagnosticMessage::FluentIdentifier(identifier, _) => { - // Any value works here. - Ok(identifier.clone()) - } - } + pub fatal_note: Option, } impl Translate for SilentEmitter { @@ -561,17 +549,9 @@ impl Translate for SilentEmitter { } fn fallback_fluent_bundle(&self) -> &FluentBundle { - panic!("silent emitter attempted to translate message") - } - - // Override `translate_message` for the silent emitter because eager translation of - // subdiagnostics result in a call to this. - fn translate_message<'a>( - &'a self, - message: &'a DiagnosticMessage, - _: &'a FluentArgs<'_>, - ) -> Result, TranslateError<'_>> { - silent_translate(message) + // Ideally this field wouldn't be necessary and the fallback bundle in `fatal_dcx` would be + // used but the lock prevents this. + &self.fallback_bundle } } @@ -582,7 +562,9 @@ impl Emitter for SilentEmitter { fn emit_diagnostic(&mut self, mut diag: DiagInner) { if diag.level == Level::Fatal { - diag.sub(Level::Note, self.fatal_note.clone(), MultiSpan::new()); + if let Some(fatal_note) = &self.fatal_note { + diag.sub(Level::Note, fatal_note.clone(), MultiSpan::new()); + } self.fatal_dcx.emit_diagnostic(diag); } } @@ -1216,7 +1198,7 @@ impl HumanEmitter { fn msgs_to_buffer( &self, buffer: &mut StyledBuffer, - msgs: &[(DiagnosticMessage, Style)], + msgs: &[(DiagMessage, Style)], args: &FluentArgs<'_>, padding: usize, label: &str, @@ -1291,7 +1273,7 @@ impl HumanEmitter { fn emit_messages_default_inner( &mut self, msp: &MultiSpan, - msgs: &[(DiagnosticMessage, Style)], + msgs: &[(DiagMessage, Style)], args: &FluentArgs<'_>, code: &Option, level: &Level, @@ -2060,7 +2042,7 @@ impl HumanEmitter { fn emit_messages_default( &mut self, level: &Level, - messages: &[(DiagnosticMessage, Style)], + messages: &[(DiagMessage, Style)], args: &FluentArgs<'_>, code: &Option, span: &MultiSpan, diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 6b1ccbc5f7c40..76b44f73f47b8 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -39,7 +39,7 @@ pub use codes::*; pub use diagnostic::{ AddToDiagnostic, BugAbort, DecorateLint, Diag, DiagArg, DiagArgMap, DiagArgName, DiagArgValue, DiagInner, DiagStyledString, EmissionGuarantee, FatalAbort, IntoDiagnostic, IntoDiagnosticArg, - StringPart, Subdiag, SubdiagnosticMessageOp, + StringPart, Subdiag, SubdiagMessageOp, }; pub use diagnostic_impls::{ DiagArgFromDisplay, DiagSymbolList, ExpectedLifetimeParameter, IndicateAnonymousLifetime, @@ -47,8 +47,8 @@ pub use diagnostic_impls::{ }; pub use emitter::ColorConfig; pub use rustc_error_messages::{ - fallback_fluent_bundle, fluent_bundle, DelayDm, DiagnosticMessage, FluentBundle, - LanguageIdentifier, LazyFallbackBundle, MultiSpan, SpanLabel, SubdiagnosticMessage, + fallback_fluent_bundle, fluent_bundle, DelayDm, DiagMessage, FluentBundle, LanguageIdentifier, + LazyFallbackBundle, MultiSpan, SpanLabel, SubdiagMessage, }; pub use rustc_lint_defs::{pluralize, Applicability}; pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker}; @@ -63,7 +63,7 @@ use emitter::{is_case_difference, DynEmitter, Emitter}; use registry::Registry; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::stable_hasher::{Hash128, StableHasher}; -use rustc_data_structures::sync::Lock; +use rustc_data_structures::sync::{Lock, Lrc}; use rustc_data_structures::AtomicRef; use rustc_lint_defs::LintExpectationId; use rustc_span::source_map::SourceMap; @@ -154,7 +154,7 @@ pub struct CodeSuggestion { /// ] /// ``` pub substitutions: Vec, - pub msg: DiagnosticMessage, + pub msg: DiagMessage, /// Visual representation of this suggestion. pub style: SuggestionStyle, /// Whether or not the suggestion is approximate @@ -606,37 +606,62 @@ impl DiagCtxt { } pub fn new(emitter: Box) -> Self { - Self { - inner: Lock::new(DiagCtxtInner { - flags: DiagCtxtFlags { can_emit_warnings: true, ..Default::default() }, - err_guars: Vec::new(), - lint_err_guars: Vec::new(), - delayed_bugs: Vec::new(), - deduplicated_err_count: 0, - deduplicated_warn_count: 0, - emitter, - must_produce_diag: false, - has_printed: false, - suppressed_expected_diag: false, - taught_diagnostics: Default::default(), - emitted_diagnostic_codes: Default::default(), - 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(), - ice_file: None, - }), + Self { inner: Lock::new(DiagCtxtInner::new(emitter)) } + } + + pub fn make_silent(&mut self, fallback_bundle: LazyFallbackBundle, fatal_note: Option) { + self.wrap_emitter(|old_dcx| { + Box::new(emitter::SilentEmitter { + fallback_bundle, + fatal_dcx: DiagCtxt { inner: Lock::new(old_dcx) }, + fatal_note, + }) + }); + } + + fn wrap_emitter(&mut self, f: F) + where + F: FnOnce(DiagCtxtInner) -> Box, + { + // A empty type that implements `Emitter` so that a `DiagCtxtInner` can be constructed + // to temporarily swap in place of the real one, which will be used in constructing + // its replacement. + struct FalseEmitter; + + impl Emitter for FalseEmitter { + fn emit_diagnostic(&mut self, _: DiagInner) { + unimplemented!("false emitter must only used during `wrap_emitter`") + } + + fn source_map(&self) -> Option<&Lrc> { + unimplemented!("false emitter must only used during `wrap_emitter`") + } } + + impl translation::Translate for FalseEmitter { + fn fluent_bundle(&self) -> Option<&Lrc> { + unimplemented!("false emitter must only used during `wrap_emitter`") + } + + fn fallback_fluent_bundle(&self) -> &FluentBundle { + unimplemented!("false emitter must only used during `wrap_emitter`") + } + } + + let mut inner = self.inner.borrow_mut(); + let mut prev_dcx = DiagCtxtInner::new(Box::new(FalseEmitter)); + std::mem::swap(&mut *inner, &mut prev_dcx); + let new_emitter = f(prev_dcx); + let mut new_dcx = DiagCtxtInner::new(new_emitter); + std::mem::swap(&mut *inner, &mut new_dcx); } - /// Translate `message` eagerly with `args` to `SubdiagnosticMessage::Eager`. + /// Translate `message` eagerly with `args` to `SubdiagMessage::Eager`. pub fn eagerly_translate<'a>( &self, - message: DiagnosticMessage, + message: DiagMessage, args: impl Iterator>, - ) -> SubdiagnosticMessage { + ) -> SubdiagMessage { let inner = self.inner.borrow(); inner.eagerly_translate(message, args) } @@ -644,7 +669,7 @@ impl DiagCtxt { /// Translate `message` eagerly with `args` to `String`. pub fn eagerly_translate_to_string<'a>( &self, - message: DiagnosticMessage, + message: DiagMessage, args: impl Iterator>, ) -> String { let inner = self.inner.borrow(); @@ -904,7 +929,7 @@ impl DiagCtxt { // configuration like `--cap-lints allow --force-warn bare_trait_objects`. inner.emit_diagnostic(DiagInner::new( ForceWarning(None), - DiagnosticMessage::Str(warnings), + DiagMessage::Str(warnings), )); } (_, 0) => { @@ -1076,32 +1101,36 @@ impl DiagCtxt { // Functions beginning with `struct_`/`create_` create a diagnostic. Other // functions create and emit a diagnostic all in one go. impl DiagCtxt { - // No `#[rustc_lint_diagnostics]` because bug messages aren't user-facing. + // No `#[rustc_lint_diagnostics]` and no `impl Into` because bug messages aren't + // user-facing. #[track_caller] - pub fn struct_bug(&self, msg: impl Into) -> Diag<'_, BugAbort> { - Diag::new(self, Bug, msg) + pub fn struct_bug(&self, msg: impl Into>) -> Diag<'_, BugAbort> { + Diag::new(self, Bug, msg.into()) } - // No `#[rustc_lint_diagnostics]` because bug messages aren't user-facing. + // No `#[rustc_lint_diagnostics]` and no `impl Into` because bug messages aren't + // user-facing. #[track_caller] - pub fn bug(&self, msg: impl Into) -> ! { + pub fn bug(&self, msg: impl Into>) -> ! { self.struct_bug(msg).emit() } - // No `#[rustc_lint_diagnostics]` because bug messages aren't user-facing. + // No `#[rustc_lint_diagnostics]` and no `impl Into` because bug messages aren't + // user-facing. #[track_caller] pub fn struct_span_bug( &self, span: impl Into, - msg: impl Into, + msg: impl Into>, ) -> Diag<'_, BugAbort> { self.struct_bug(msg).with_span(span) } - // No `#[rustc_lint_diagnostics]` because bug messages aren't user-facing. + // No `#[rustc_lint_diagnostics]` and no `impl Into` because bug messages aren't + // user-facing. #[track_caller] - pub fn span_bug(&self, span: impl Into, msg: impl Into) -> ! { - self.struct_span_bug(span, msg).emit() + pub fn span_bug(&self, span: impl Into, msg: impl Into>) -> ! { + self.struct_span_bug(span, msg.into()).emit() } #[track_caller] @@ -1116,13 +1145,13 @@ impl DiagCtxt { #[rustc_lint_diagnostics] #[track_caller] - pub fn struct_fatal(&self, msg: impl Into) -> Diag<'_, FatalAbort> { + pub fn struct_fatal(&self, msg: impl Into) -> Diag<'_, FatalAbort> { Diag::new(self, Fatal, msg) } #[rustc_lint_diagnostics] #[track_caller] - pub fn fatal(&self, msg: impl Into) -> ! { + pub fn fatal(&self, msg: impl Into) -> ! { self.struct_fatal(msg).emit() } @@ -1131,14 +1160,14 @@ impl DiagCtxt { pub fn struct_span_fatal( &self, span: impl Into, - msg: impl Into, + msg: impl Into, ) -> Diag<'_, FatalAbort> { self.struct_fatal(msg).with_span(span) } #[rustc_lint_diagnostics] #[track_caller] - pub fn span_fatal(&self, span: impl Into, msg: impl Into) -> ! { + pub fn span_fatal(&self, span: impl Into, msg: impl Into) -> ! { self.struct_span_fatal(span, msg).emit() } @@ -1174,13 +1203,13 @@ impl DiagCtxt { // FIXME: This method should be removed (every error should have an associated error code). #[rustc_lint_diagnostics] #[track_caller] - pub fn struct_err(&self, msg: impl Into) -> Diag<'_> { + pub fn struct_err(&self, msg: impl Into) -> Diag<'_> { Diag::new(self, Error, msg) } #[rustc_lint_diagnostics] #[track_caller] - pub fn err(&self, msg: impl Into) -> ErrorGuaranteed { + pub fn err(&self, msg: impl Into) -> ErrorGuaranteed { self.struct_err(msg).emit() } @@ -1189,7 +1218,7 @@ impl DiagCtxt { pub fn struct_span_err( &self, span: impl Into, - msg: impl Into, + msg: impl Into, ) -> Diag<'_> { self.struct_err(msg).with_span(span) } @@ -1199,7 +1228,7 @@ impl DiagCtxt { pub fn span_err( &self, span: impl Into, - msg: impl Into, + msg: impl Into, ) -> ErrorGuaranteed { self.struct_span_err(span, msg).emit() } @@ -1215,35 +1244,39 @@ impl DiagCtxt { } /// Ensures that an error is printed. See `Level::DelayedBug`. - // No `#[rustc_lint_diagnostics]` because bug messages aren't user-facing. + // + // No `#[rustc_lint_diagnostics]` and no `impl Into` because bug messages aren't + // user-facing. #[track_caller] - pub fn delayed_bug(&self, msg: impl Into) -> ErrorGuaranteed { - Diag::::new(self, DelayedBug, msg).emit() + pub fn delayed_bug(&self, msg: impl Into>) -> ErrorGuaranteed { + Diag::::new(self, DelayedBug, msg.into()).emit() } /// Ensures that an error is printed. See `Level::DelayedBug`. /// /// Note: this function used to be called `delay_span_bug`. It was renamed /// to match similar functions like `span_err`, `span_warn`, etc. - // No `#[rustc_lint_diagnostics]` because bug messages aren't user-facing. + // + // No `#[rustc_lint_diagnostics]` and no `impl Into` because bug messages aren't + // user-facing. #[track_caller] pub fn span_delayed_bug( &self, sp: impl Into, - msg: impl Into, + msg: impl Into>, ) -> ErrorGuaranteed { - Diag::::new(self, DelayedBug, msg).with_span(sp).emit() + Diag::::new(self, DelayedBug, msg.into()).with_span(sp).emit() } #[rustc_lint_diagnostics] #[track_caller] - pub fn struct_warn(&self, msg: impl Into) -> Diag<'_, ()> { + pub fn struct_warn(&self, msg: impl Into) -> Diag<'_, ()> { Diag::new(self, Warning, msg) } #[rustc_lint_diagnostics] #[track_caller] - pub fn warn(&self, msg: impl Into) { + pub fn warn(&self, msg: impl Into) { self.struct_warn(msg).emit() } @@ -1252,14 +1285,14 @@ impl DiagCtxt { pub fn struct_span_warn( &self, span: impl Into, - msg: impl Into, + msg: impl Into, ) -> Diag<'_, ()> { self.struct_warn(msg).with_span(span) } #[rustc_lint_diagnostics] #[track_caller] - pub fn span_warn(&self, span: impl Into, msg: impl Into) { + pub fn span_warn(&self, span: impl Into, msg: impl Into) { self.struct_span_warn(span, msg).emit() } @@ -1275,13 +1308,13 @@ impl DiagCtxt { #[rustc_lint_diagnostics] #[track_caller] - pub fn struct_note(&self, msg: impl Into) -> Diag<'_, ()> { + pub fn struct_note(&self, msg: impl Into) -> Diag<'_, ()> { Diag::new(self, Note, msg) } #[rustc_lint_diagnostics] #[track_caller] - pub fn note(&self, msg: impl Into) { + pub fn note(&self, msg: impl Into) { self.struct_note(msg).emit() } @@ -1290,14 +1323,14 @@ impl DiagCtxt { pub fn struct_span_note( &self, span: impl Into, - msg: impl Into, + msg: impl Into, ) -> Diag<'_, ()> { self.struct_note(msg).with_span(span) } #[rustc_lint_diagnostics] #[track_caller] - pub fn span_note(&self, span: impl Into, msg: impl Into) { + pub fn span_note(&self, span: impl Into, msg: impl Into) { self.struct_span_note(span, msg).emit() } @@ -1313,19 +1346,19 @@ impl DiagCtxt { #[rustc_lint_diagnostics] #[track_caller] - pub fn struct_help(&self, msg: impl Into) -> Diag<'_, ()> { + pub fn struct_help(&self, msg: impl Into) -> Diag<'_, ()> { Diag::new(self, Help, msg) } #[rustc_lint_diagnostics] #[track_caller] - pub fn struct_failure_note(&self, msg: impl Into) -> Diag<'_, ()> { + pub fn struct_failure_note(&self, msg: impl Into) -> Diag<'_, ()> { Diag::new(self, FailureNote, msg) } #[rustc_lint_diagnostics] #[track_caller] - pub fn struct_allow(&self, msg: impl Into) -> Diag<'_, ()> { + pub fn struct_allow(&self, msg: impl Into) -> Diag<'_, ()> { Diag::new(self, Allow, msg) } @@ -1333,7 +1366,7 @@ impl DiagCtxt { #[track_caller] pub fn struct_expect( &self, - msg: impl Into, + msg: impl Into, id: LintExpectationId, ) -> Diag<'_, ()> { Diag::new(self, Expect(id), msg) @@ -1345,6 +1378,30 @@ impl DiagCtxt { // `DiagCtxt::foo()` just borrows `inner` and forwards a call to // `DiagCtxtInner::foo`. impl DiagCtxtInner { + fn new(emitter: Box) -> Self { + Self { + flags: DiagCtxtFlags { can_emit_warnings: true, ..Default::default() }, + err_guars: Vec::new(), + lint_err_guars: Vec::new(), + delayed_bugs: Vec::new(), + deduplicated_err_count: 0, + deduplicated_warn_count: 0, + emitter, + must_produce_diag: false, + has_printed: false, + suppressed_expected_diag: false, + taught_diagnostics: Default::default(), + emitted_diagnostic_codes: Default::default(), + 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(), + ice_file: None, + } + } + /// Emit all stashed diagnostics. fn emit_stashed_diagnostics(&mut self) -> Option { let mut guar = None; @@ -1553,19 +1610,19 @@ impl DiagCtxtInner { self.has_errors().or_else(|| self.delayed_bugs.get(0).map(|(_, guar)| guar).copied()) } - /// Translate `message` eagerly with `args` to `SubdiagnosticMessage::Eager`. + /// Translate `message` eagerly with `args` to `SubdiagMessage::Eager`. pub fn eagerly_translate<'a>( &self, - message: DiagnosticMessage, + message: DiagMessage, args: impl Iterator>, - ) -> SubdiagnosticMessage { - SubdiagnosticMessage::Translated(Cow::from(self.eagerly_translate_to_string(message, args))) + ) -> SubdiagMessage { + SubdiagMessage::Translated(Cow::from(self.eagerly_translate_to_string(message, args))) } /// Translate `message` eagerly with `args` to `String`. pub fn eagerly_translate_to_string<'a>( &self, - message: DiagnosticMessage, + message: DiagMessage, args: impl Iterator>, ) -> String { let args = crate::translation::to_fluent_args(args); @@ -1575,8 +1632,8 @@ impl DiagCtxtInner { fn eagerly_translate_for_subdiag( &self, diag: &DiagInner, - msg: impl Into, - ) -> SubdiagnosticMessage { + msg: impl Into, + ) -> SubdiagMessage { let msg = diag.subdiagnostic_message_to_diagnostic_message(msg); self.eagerly_translate(msg, diag.args.iter()) } diff --git a/compiler/rustc_errors/src/markdown/term.rs b/compiler/rustc_errors/src/markdown/term.rs index 88c3c8b9ff2c4..06c1333d93dd0 100644 --- a/compiler/rustc_errors/src/markdown/term.rs +++ b/compiler/rustc_errors/src/markdown/term.rs @@ -9,9 +9,9 @@ const DEFAULT_COLUMN_WIDTH: usize = 140; thread_local! { /// Track the position of viewable characters in our buffer - static CURSOR: Cell = Cell::new(0); + static CURSOR: Cell = const { Cell::new(0) }; /// Width of the terminal - static WIDTH: Cell = Cell::new(DEFAULT_COLUMN_WIDTH); + static WIDTH: Cell = const { Cell::new(DEFAULT_COLUMN_WIDTH) }; } /// Print to terminal output to a buffer diff --git a/compiler/rustc_errors/src/tests.rs b/compiler/rustc_errors/src/tests.rs index 79a2af7f38fd7..50d58aec36a89 100644 --- a/compiler/rustc_errors/src/tests.rs +++ b/compiler/rustc_errors/src/tests.rs @@ -5,7 +5,7 @@ use crate::FluentBundle; use rustc_data_structures::sync::{IntoDynSyncSend, Lrc}; use rustc_error_messages::fluent_bundle::resolver::errors::{ReferenceKind, ResolverError}; use rustc_error_messages::langid; -use rustc_error_messages::DiagnosticMessage; +use rustc_error_messages::DiagMessage; struct Dummy { bundle: FluentBundle, @@ -53,7 +53,7 @@ fn wellformed_fluent() { args.set("name", "Foo"); args.set("ty", "std::string::String"); { - let message = DiagnosticMessage::FluentIdentifier( + let message = DiagMessage::FluentIdentifier( "mir_build_borrow_of_moved_value".into(), Some("suggestion".into()), ); @@ -65,7 +65,7 @@ fn wellformed_fluent() { } { - let message = DiagnosticMessage::FluentIdentifier( + let message = DiagMessage::FluentIdentifier( "mir_build_borrow_of_moved_value".into(), Some("value_borrowed_label".into()), ); @@ -77,7 +77,7 @@ fn wellformed_fluent() { } { - let message = DiagnosticMessage::FluentIdentifier( + let message = DiagMessage::FluentIdentifier( "mir_build_borrow_of_moved_value".into(), Some("occurs_because_label".into()), ); @@ -88,7 +88,7 @@ fn wellformed_fluent() { ); { - let message = DiagnosticMessage::FluentIdentifier( + let message = DiagMessage::FluentIdentifier( "mir_build_borrow_of_moved_value".into(), Some("label".into()), ); @@ -112,7 +112,7 @@ fn misformed_fluent() { args.set("name", "Foo"); args.set("ty", "std::string::String"); { - let message = DiagnosticMessage::FluentIdentifier( + let message = DiagMessage::FluentIdentifier( "mir_build_borrow_of_moved_value".into(), Some("value_borrowed_label".into()), ); @@ -141,7 +141,7 @@ fn misformed_fluent() { } { - let message = DiagnosticMessage::FluentIdentifier( + let message = DiagMessage::FluentIdentifier( "mir_build_borrow_of_moved_value".into(), Some("label".into()), ); @@ -168,7 +168,7 @@ fn misformed_fluent() { } { - let message = DiagnosticMessage::FluentIdentifier( + let message = DiagMessage::FluentIdentifier( "mir_build_borrow_of_moved_value".into(), Some("occurs_because_label".into()), ); diff --git a/compiler/rustc_errors/src/translation.rs b/compiler/rustc_errors/src/translation.rs index 1f98ba4c3b974..bf0026568ce23 100644 --- a/compiler/rustc_errors/src/translation.rs +++ b/compiler/rustc_errors/src/translation.rs @@ -1,6 +1,6 @@ use crate::error::{TranslateError, TranslateErrorKind}; use crate::snippet::Style; -use crate::{DiagArg, DiagnosticMessage, FluentBundle}; +use crate::{DiagArg, DiagMessage, FluentBundle}; use rustc_data_structures::sync::Lrc; pub use rustc_error_messages::FluentArgs; use std::borrow::Cow; @@ -37,10 +37,10 @@ pub trait Translate { /// unavailable for the requested locale. fn fallback_fluent_bundle(&self) -> &FluentBundle; - /// Convert `DiagnosticMessage`s to a string, performing translation if necessary. + /// Convert `DiagMessage`s to a string, performing translation if necessary. fn translate_messages( &self, - messages: &[(DiagnosticMessage, Style)], + messages: &[(DiagMessage, Style)], args: &FluentArgs<'_>, ) -> Cow<'_, str> { Cow::Owned( @@ -51,18 +51,18 @@ pub trait Translate { ) } - /// Convert a `DiagnosticMessage` to a string, performing translation if necessary. + /// Convert a `DiagMessage` to a string, performing translation if necessary. fn translate_message<'a>( &'a self, - message: &'a DiagnosticMessage, + message: &'a DiagMessage, args: &'a FluentArgs<'_>, ) -> Result, TranslateError<'_>> { trace!(?message, ?args); let (identifier, attr) = match message { - DiagnosticMessage::Str(msg) | DiagnosticMessage::Translated(msg) => { + DiagMessage::Str(msg) | DiagMessage::Translated(msg) => { return Ok(Cow::Borrowed(msg)); } - DiagnosticMessage::FluentIdentifier(identifier, attr) => (identifier, attr), + DiagMessage::FluentIdentifier(identifier, attr) => (identifier, attr), }; let translate_with_bundle = |bundle: &'a FluentBundle| -> Result, TranslateError<'_>> { diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 485f0e7e46deb..69dfb48919cdb 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -4,7 +4,6 @@ use crate::expand::{self, AstFragment, Invocation}; use crate::module::DirOwnership; use rustc_ast::attr::MarkedAttrs; -use rustc_ast::mut_visit::DummyAstNode; use rustc_ast::ptr::P; use rustc_ast::token::{self, Nonterminal}; use rustc_ast::tokenstream::TokenStream; @@ -16,7 +15,7 @@ use rustc_data_structures::sync::{self, Lrc}; use rustc_errors::{Applicability, Diag, DiagCtxt, ErrorGuaranteed, PResult}; use rustc_feature::Features; use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT; -use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiagnostics, RegisteredTools}; +use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiag, RegisteredTools}; use rustc_parse::{parser, MACRO_ARGUMENTS}; use rustc_session::config::CollapseMacroDebuginfo; use rustc_session::errors::report_lit_error; @@ -582,6 +581,17 @@ impl DummyResult { tokens: None, }) } + + /// A plain dummy crate. + pub fn raw_crate() -> ast::Crate { + ast::Crate { + attrs: Default::default(), + items: Default::default(), + spans: Default::default(), + id: ast::DUMMY_NODE_ID, + is_placeholder: Default::default(), + } + } } impl MacResult for DummyResult { @@ -650,7 +660,7 @@ impl MacResult for DummyResult { } fn make_crate(self: Box) -> Option { - Some(DummyAstNode::dummy()) + Some(DummyResult::raw_crate()) } } @@ -1135,13 +1145,13 @@ impl<'a> ExtCtxt<'a> { expand::MacroExpander::new(self, true) } pub fn new_parser_from_tts(&self, stream: TokenStream) -> parser::Parser<'a> { - rustc_parse::stream_to_parser(&self.sess.parse_sess, stream, MACRO_ARGUMENTS) + rustc_parse::stream_to_parser(&self.sess.psess, stream, MACRO_ARGUMENTS) } pub fn source_map(&self) -> &'a SourceMap { - self.sess.parse_sess.source_map() + self.sess.psess.source_map() } - pub fn parse_sess(&self) -> &'a ParseSess { - &self.sess.parse_sess + pub fn psess(&self) -> &'a ParseSess { + &self.sess.psess } pub fn call_site(&self) -> Span { self.current_expansion.id.expn_data().call_site @@ -1216,26 +1226,22 @@ impl<'a> ExtCtxt<'a> { /// Resolves a `path` mentioned inside Rust code, returning an absolute path. /// /// This unifies the logic used for resolving `include_X!`. -pub fn resolve_path( - parse_sess: &Session, - path: impl Into, - span: Span, -) -> PResult<'_, PathBuf> { +pub fn resolve_path(sess: &Session, path: impl Into, span: Span) -> PResult<'_, PathBuf> { let path = path.into(); // Relative paths are resolved relative to the file in which they are found // after macro expansion (that is, they are unhygienic). if !path.is_absolute() { let callsite = span.source_callsite(); - let mut result = match parse_sess.source_map().span_to_filename(callsite) { + let mut result = match sess.source_map().span_to_filename(callsite) { FileName::Real(name) => name .into_local_path() .expect("attempting to resolve a file path in an external file"), FileName::DocTest(path, _) => path, other => { - return Err(parse_sess.dcx().create_err(errors::ResolveRelativePath { + return Err(sess.dcx().create_err(errors::ResolveRelativePath { span, - path: parse_sess.source_map().filename_for_diagnostics(&other).to_string(), + path: sess.source_map().filename_for_diagnostics(&other).to_string(), })); } }; @@ -1281,7 +1287,7 @@ pub fn expr_to_spanned_string<'a>( Ok((err, true)) } Ok(ast::LitKind::Err(guar)) => Err(guar), - Err(err) => Err(report_lit_error(&cx.sess.parse_sess, err, token_lit, expr.span)), + Err(err) => Err(report_lit_error(&cx.sess.psess, err, token_lit, expr.span)), _ => Ok((cx.dcx().struct_span_err(expr.span, err_msg), false)), }, ast::ExprKind::Err(guar) => Err(guar), @@ -1487,12 +1493,14 @@ fn pretty_printing_compatibility_hack(item: &Item, sess: &Session) -> bool { }; if crate_matches { - sess.parse_sess.buffer_lint_with_diagnostic( + // FIXME: make this translatable + #[allow(rustc::untranslatable_diagnostic)] + sess.psess.buffer_lint_with_diagnostic( PROC_MACRO_BACK_COMPAT, item.ident.span, ast::CRATE_NODE_ID, "using an old version of `rental`", - BuiltinLintDiagnostics::ProcMacroBackCompat( + BuiltinLintDiag::ProcMacroBackCompat( "older versions of the `rental` crate will stop compiling in future versions of Rust; \ please update to `rental` v0.5.6, or switch to one of the `rental` alternatives".to_string() ) diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index 9ce2084c84704..989b7b485c992 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -665,7 +665,7 @@ impl<'a> ExtCtxt<'a> { // Builds `#[name]`. pub fn attr_word(&self, name: Symbol, span: Span) -> ast::Attribute { - let g = &self.sess.parse_sess.attr_id_generator; + let g = &self.sess.psess.attr_id_generator; attr::mk_attr_word(g, ast::AttrStyle::Outer, name, span) } @@ -673,13 +673,13 @@ impl<'a> ExtCtxt<'a> { // // Note: `span` is used for both the identifier and the value. pub fn attr_name_value_str(&self, name: Symbol, val: Symbol, span: Span) -> ast::Attribute { - let g = &self.sess.parse_sess.attr_id_generator; + let g = &self.sess.psess.attr_id_generator; attr::mk_attr_name_value_str(g, ast::AttrStyle::Outer, name, val, span) } // Builds `#[outer(inner)]`. pub fn attr_nested_word(&self, outer: Symbol, inner: Symbol, span: Span) -> ast::Attribute { - let g = &self.sess.parse_sess.attr_id_generator; + let g = &self.sess.psess.attr_id_generator; attr::mk_attr_nested_word(g, ast::AttrStyle::Outer, outer, inner, span) } } diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 435135d195989..c95d7cdeb73ab 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -239,16 +239,17 @@ impl<'a> StripUnconfigured<'a> { /// Gives a compiler warning when the `cfg_attr` contains no attributes and /// is in the original source file. Gives a compiler error if the syntax of /// the attribute is incorrect. + #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable pub(crate) fn expand_cfg_attr(&self, attr: &Attribute, recursive: bool) -> Vec { let Some((cfg_predicate, expanded_attrs)) = - rustc_parse::parse_cfg_attr(attr, &self.sess.parse_sess) + rustc_parse::parse_cfg_attr(attr, &self.sess.psess) else { return vec![]; }; // Lint on zero attributes in source. if expanded_attrs.is_empty() { - self.sess.parse_sess.buffer_lint( + self.sess.psess.buffer_lint( rustc_lint_defs::builtin::UNUSED_ATTRIBUTES, attr.span, ast::CRATE_NODE_ID, @@ -273,6 +274,7 @@ impl<'a> StripUnconfigured<'a> { } } + #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn expand_cfg_attr_item( &self, attr: &Attribute, @@ -324,14 +326,14 @@ impl<'a> StripUnconfigured<'a> { }; let tokens = Some(LazyAttrTokenStream::new(AttrTokenStream::new(trees))); let attr = attr::mk_attr_from_item( - &self.sess.parse_sess.attr_id_generator, + &self.sess.psess.attr_id_generator, item, tokens, attr.style, item_span, ); if attr.has_name(sym::crate_type) { - self.sess.parse_sess.buffer_lint( + self.sess.psess.buffer_lint( rustc_lint_defs::builtin::DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME, attr.span, ast::CRATE_NODE_ID, @@ -339,7 +341,7 @@ impl<'a> StripUnconfigured<'a> { ); } if attr.has_name(sym::crate_name) { - self.sess.parse_sess.buffer_lint( + self.sess.psess.buffer_lint( rustc_lint_defs::builtin::DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME, attr.span, ast::CRATE_NODE_ID, @@ -355,7 +357,7 @@ impl<'a> StripUnconfigured<'a> { } pub(crate) fn cfg_true(&self, attr: &Attribute) -> (bool, Option) { - let meta_item = match validate_attr::parse_meta(&self.sess.parse_sess, attr) { + let meta_item = match validate_attr::parse_meta(&self.sess.psess, attr) { Ok(meta_item) => meta_item, Err(err) => { err.emit(); @@ -371,6 +373,7 @@ impl<'a> StripUnconfigured<'a> { } /// If attributes are not allowed on expressions, emit an error for `attr` + #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable #[instrument(level = "trace", skip(self))] pub(crate) fn maybe_emit_expr_attr_err(&self, attr: &Attribute) { if self.features.is_some_and(|features| !features.stmt_expr_attributes) @@ -384,7 +387,6 @@ impl<'a> StripUnconfigured<'a> { ); if attr.is_doc_comment() { - #[allow(rustc::untranslatable_diagnostic)] err.help("`///` is for documentation comments. For a plain comment, use `//`."); } diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 9bc7b4bdd1e13..fcc439e71f95b 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -14,8 +14,7 @@ use rustc_ast::mut_visit::*; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter}; use rustc_ast::tokenstream::TokenStream; -use rustc_ast::visit::{self, AssocCtxt, Visitor, VisitorResult}; -use rustc_ast::{try_visit, walk_list}; +use rustc_ast::visit::{self, try_visit, walk_list, AssocCtxt, Visitor, VisitorResult}; use rustc_ast::{AssocItemKind, AstNodeWrapper, AttrArgs, AttrStyle, AttrVec, ExprKind}; use rustc_ast::{ForeignItemKind, HasAttrs, HasNodeId}; use rustc_ast::{Inline, ItemKind, MacStmtStyle, MetaItemKind, ModKind}; @@ -30,7 +29,7 @@ use rustc_parse::parser::{ }; use rustc_parse::validate_attr; use rustc_session::lint::builtin::{UNUSED_ATTRIBUTES, UNUSED_DOC_COMMENTS}; -use rustc_session::lint::BuiltinLintDiagnostics; +use rustc_session::lint::BuiltinLintDiag; use rustc_session::parse::feature_err; use rustc_session::{Limit, Session}; use rustc_span::symbol::{sym, Ident}; @@ -691,10 +690,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> { // fixed prior to stabilization // Fake tokens when we are invoking an inner attribute, and // we are invoking it on an out-of-line module or crate. - Annotatable::Crate(krate) => rustc_parse::fake_token_stream_for_crate( - &self.cx.sess.parse_sess, - krate, - ), + Annotatable::Crate(krate) => { + rustc_parse::fake_token_stream_for_crate(&self.cx.sess.psess, krate) + } Annotatable::Item(item_inner) if matches!(attr.style, AttrStyle::Inner) && matches!( @@ -705,10 +703,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { ) ) => { - rustc_parse::fake_token_stream_for_item( - &self.cx.sess.parse_sess, - item_inner, - ) + rustc_parse::fake_token_stream_for_item(&self.cx.sess.psess, item_inner) } _ => item.to_tokens(), }; @@ -728,7 +723,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } } SyntaxExtensionKind::LegacyAttr(expander) => { - match validate_attr::parse_meta(&self.cx.sess.parse_sess, &attr) { + match validate_attr::parse_meta(&self.cx.sess.psess, &attr) { Ok(meta) => { let items = match expander.expand(self.cx, span, &meta, item, false) { ExpandResult::Ready(items) => items, @@ -788,6 +783,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { }) } + #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) { let kind = match item { Annotatable::Item(_) @@ -830,6 +826,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } impl<'ast, 'a> Visitor<'ast> for GateProcMacroInput<'a> { + #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn visit_item(&mut self, item: &'ast ast::Item) { match &item.kind { ItemKind::Mod(_, mod_kind) @@ -962,8 +959,8 @@ pub fn ensure_complete_parse<'a>( // Avoid emitting backtrace info twice. let def_site_span = parser.token.span.with_ctxt(SyntaxContext::root()); - let semi_span = parser.sess.source_map().next_point(span); - let add_semicolon = match &parser.sess.source_map().span_to_snippet(semi_span) { + let semi_span = parser.psess.source_map().next_point(span); + let add_semicolon = match &parser.psess.source_map().span_to_snippet(semi_span) { Ok(snippet) if &snippet[..] != ";" && kind_name == "expression" => { Some(span.shrink_to_hi()) } @@ -1694,13 +1691,14 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { // Detect use of feature-gated or invalid attributes on macro invocations // since they will not be detected after macro expansion. + #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn check_attributes(&self, attrs: &[ast::Attribute], call: &ast::MacCall) { let features = self.cx.ecfg.features; let mut attrs = attrs.iter().peekable(); let mut span: Option = None; while let Some(attr) = attrs.next() { rustc_ast_passes::feature_gate::check_attribute(attr, self.cx.sess, features); - validate_attr::check_attr(&self.cx.sess.parse_sess, attr); + validate_attr::check_attr(&self.cx.sess.psess, attr); let current_span = if let Some(sp) = span { sp.to(attr.span) } else { attr.span }; span = Some(current_span); @@ -1710,24 +1708,24 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { } if attr.is_doc_comment() { - self.cx.sess.parse_sess.buffer_lint_with_diagnostic( + self.cx.sess.psess.buffer_lint_with_diagnostic( UNUSED_DOC_COMMENTS, current_span, self.cx.current_expansion.lint_node_id, "unused doc comment", - BuiltinLintDiagnostics::UnusedDocComment(attr.span), + BuiltinLintDiag::UnusedDocComment(attr.span), ); } else if rustc_attr::is_builtin_attr(attr) { let attr_name = attr.ident().unwrap().name; // `#[cfg]` and `#[cfg_attr]` are special - they are // eagerly evaluated. if attr_name != sym::cfg && attr_name != sym::cfg_attr { - self.cx.sess.parse_sess.buffer_lint_with_diagnostic( + self.cx.sess.psess.buffer_lint_with_diagnostic( UNUSED_ATTRIBUTES, attr.span, self.cx.current_expansion.lint_node_id, format!("unused attribute `{attr_name}`"), - BuiltinLintDiagnostics::UnusedBuiltinAttribute { + BuiltinLintDiag::UnusedBuiltinAttribute { attr_name, macro_name: pprust::path_to_string(&call.path), invoc_span: call.path.span, diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index 0e73abc9ed854..e550f7242c338 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -5,6 +5,7 @@ #![feature(associated_type_defaults)] #![feature(if_let_guard)] #![feature(let_chains)] +#![feature(lint_reasons)] #![feature(macro_metavar_expr)] #![feature(map_try_insert)] #![feature(proc_macro_diagnostic)] diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs index 053063b690e62..15193298ccaa2 100644 --- a/compiler/rustc_expand/src/mbe/diagnostics.rs +++ b/compiler/rustc_expand/src/mbe/diagnostics.rs @@ -7,7 +7,7 @@ use crate::mbe::{ use rustc_ast::token::{self, Token, TokenKind}; use rustc_ast::tokenstream::TokenStream; use rustc_ast_pretty::pprust; -use rustc_errors::{Applicability, Diag, DiagCtxt, DiagnosticMessage}; +use rustc_errors::{Applicability, Diag, DiagCtxt, DiagMessage}; use rustc_parse::parser::{Parser, Recovery}; use rustc_span::source_map::SourceMap; use rustc_span::symbol::Ident; @@ -24,12 +24,12 @@ pub(super) fn failed_to_match_macro<'cx>( arg: TokenStream, lhses: &[Vec], ) -> Box { - let sess = &cx.sess.parse_sess; + let psess = &cx.sess.psess; // An error occurred, try the expansion again, tracking the expansion closely for better diagnostics. let mut tracker = CollectTrackerAndEmitter::new(cx, sp); - let try_success_result = try_match_macro(sess, name, &arg, lhses, &mut tracker); + let try_success_result = try_match_macro(psess, name, &arg, lhses, &mut tracker); if try_success_result.is_ok() { // Nonterminal parser recovery might turn failed matches into successful ones, @@ -58,7 +58,7 @@ pub(super) fn failed_to_match_macro<'cx>( err.span_label(cx.source_map().guess_head_span(def_span), "when calling this macro"); } - annotate_doc_comment(cx.sess.dcx(), &mut err, sess.source_map(), span); + annotate_doc_comment(cx.sess.dcx(), &mut err, psess.source_map(), span); if let Some(span) = remaining_matcher.span() { err.span_note(span, format!("while trying to match {remaining_matcher}")); @@ -87,7 +87,7 @@ pub(super) fn failed_to_match_macro<'cx>( // Check whether there's a missing comma in this macro call, like `println!("{}" a);` if let Some((arg, comma_span)) = arg.add_comma() { for lhs in lhses { - let parser = parser_from_cx(sess, arg.clone(), Recovery::Allowed); + let parser = parser_from_cx(psess, arg.clone(), Recovery::Allowed); let mut tt_parser = TtParser::new(name); if let Success(_) = @@ -227,12 +227,12 @@ pub(super) fn emit_frag_parse_err( ) -> ErrorGuaranteed { // FIXME(davidtwco): avoid depending on the error message text if parser.token == token::Eof - && let DiagnosticMessage::Str(message) = &e.messages[0].0 + && let DiagMessage::Str(message) = &e.messages[0].0 && message.ends_with(", found ``") { let msg = &e.messages[0]; e.messages[0] = ( - DiagnosticMessage::from(format!( + DiagMessage::from(format!( "macro expansion ends with an incomplete expression: {}", message.replace(", found ``", ""), )), @@ -246,10 +246,10 @@ pub(super) fn emit_frag_parse_err( if e.span.is_dummy() { // Get around lack of span in error (#30128) e.replace_span_with(site_span, true); - if !parser.sess.source_map().is_imported(arm_span) { + if !parser.psess.source_map().is_imported(arm_span) { e.span_label(arm_span, "in this macro arm"); } - } else if parser.sess.source_map().is_imported(parser.token.span) { + } else if parser.psess.source_map().is_imported(parser.token.span) { e.span_label(site_span, "in this macro invocation"); } match kind { @@ -262,7 +262,7 @@ pub(super) fn emit_frag_parse_err( ); if parser.token == token::Semi { - if let Ok(snippet) = parser.sess.source_map().span_to_snippet(site_span) { + if let Ok(snippet) = parser.psess.source_map().span_to_snippet(site_span) { e.span_suggestion_verbose( site_span, "surround the macro invocation with `{}` to interpret the expansion as a statement", diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs index 8174cb03d337b..dce8e0c36edf7 100644 --- a/compiler/rustc_expand/src/mbe/macro_check.rs +++ b/compiler/rustc_expand/src/mbe/macro_check.rs @@ -110,7 +110,7 @@ use crate::mbe::{KleeneToken, TokenTree}; use rustc_ast::token::{Delimiter, IdentIsRaw, Token, TokenKind}; use rustc_ast::{NodeId, DUMMY_NODE_ID}; use rustc_data_structures::fx::FxHashMap; -use rustc_errors::{DiagnosticMessage, MultiSpan}; +use rustc_errors::{DiagMessage, MultiSpan}; use rustc_session::lint::builtin::{META_VARIABLE_MISUSE, MISSING_FRAGMENT_SPECIFIER}; use rustc_session::parse::ParseSess; use rustc_span::symbol::kw; @@ -193,25 +193,25 @@ struct MacroState<'a> { /// Checks that meta-variables are used correctly in a macro definition. /// /// Arguments: -/// - `sess` is used to emit diagnostics and lints +/// - `psess` is used to emit diagnostics and lints /// - `node_id` is used to emit lints /// - `span` is used when no spans are available /// - `lhses` and `rhses` should have the same length and represent the macro definition pub(super) fn check_meta_variables( - sess: &ParseSess, + psess: &ParseSess, node_id: NodeId, span: Span, lhses: &[TokenTree], rhses: &[TokenTree], ) -> Result<(), ErrorGuaranteed> { if lhses.len() != rhses.len() { - sess.dcx.span_bug(span, "length mismatch between LHSes and RHSes") + psess.dcx.span_bug(span, "length mismatch between LHSes and RHSes") } let mut guar = None; for (lhs, rhs) in iter::zip(lhses, rhses) { let mut binders = Binders::default(); - check_binders(sess, node_id, lhs, &Stack::Empty, &mut binders, &Stack::Empty, &mut guar); - check_occurrences(sess, node_id, rhs, &Stack::Empty, &binders, &Stack::Empty, &mut guar); + check_binders(psess, node_id, lhs, &Stack::Empty, &mut binders, &Stack::Empty, &mut guar); + check_occurrences(psess, node_id, rhs, &Stack::Empty, &binders, &Stack::Empty, &mut guar); } guar.map_or(Ok(()), Err) } @@ -220,7 +220,7 @@ pub(super) fn check_meta_variables( /// sets `valid` to false in case of errors. /// /// Arguments: -/// - `sess` is used to emit diagnostics and lints +/// - `psess` is used to emit diagnostics and lints /// - `node_id` is used to emit lints /// - `lhs` is checked as part of a LHS /// - `macros` is the stack of possible outer macros @@ -228,7 +228,7 @@ pub(super) fn check_meta_variables( /// - `ops` is the stack of Kleene operators from the LHS /// - `guar` is set in case of errors fn check_binders( - sess: &ParseSess, + psess: &ParseSess, node_id: NodeId, lhs: &TokenTree, macros: &Stack<'_, MacroState<'_>>, @@ -244,7 +244,7 @@ fn check_binders( // MetaVar(fragment) and not as MetaVarDecl(y, fragment). TokenTree::MetaVar(span, name) => { if macros.is_empty() { - sess.dcx.span_bug(span, "unexpected MetaVar in lhs"); + psess.dcx.span_bug(span, "unexpected MetaVar in lhs"); } let name = MacroRulesNormalizedIdent::new(name); // There are 3 possibilities: @@ -252,13 +252,13 @@ fn check_binders( // 1. The meta-variable is already bound in the current LHS: This is an error. let mut span = MultiSpan::from_span(span); span.push_span_label(prev_info.span, "previous declaration"); - buffer_lint(sess, span, node_id, "duplicate matcher binding"); + buffer_lint(psess, span, node_id, "duplicate matcher binding"); } else if get_binder_info(macros, binders, name).is_none() { // 2. The meta-variable is free: This is a binder. binders.insert(name, BinderInfo { span, ops: ops.into() }); } else { // 3. The meta-variable is bound: This is an occurrence. - check_occurrences(sess, node_id, lhs, macros, binders, ops, guar); + check_occurrences(psess, node_id, lhs, macros, binders, ops, guar); } } // Similarly, this can only happen when checking a toplevel macro. @@ -267,7 +267,7 @@ fn check_binders( // FIXME: Report this as a hard error eventually and remove equivalent errors from // `parse_tt_inner` and `nameize`. Until then the error may be reported twice, once // as a hard error and then once as a buffered lint. - sess.buffer_lint( + psess.buffer_lint( MISSING_FRAGMENT_SPECIFIER, span, node_id, @@ -275,14 +275,15 @@ fn check_binders( ); } if !macros.is_empty() { - sess.dcx.span_bug(span, "unexpected MetaVarDecl in nested lhs"); + psess.dcx.span_bug(span, "unexpected MetaVarDecl in nested lhs"); } let name = MacroRulesNormalizedIdent::new(name); if let Some(prev_info) = get_binder_info(macros, binders, name) { // Duplicate binders at the top-level macro definition are errors. The lint is only // for nested macro definitions. *guar = Some( - sess.dcx + psess + .dcx .emit_err(errors::DuplicateMatcherBinding { span, prev: prev_info.span }), ); } else { @@ -293,13 +294,13 @@ fn check_binders( TokenTree::MetaVarExpr(..) => {} TokenTree::Delimited(.., ref del) => { for tt in &del.tts { - check_binders(sess, node_id, tt, macros, binders, ops, guar); + check_binders(psess, node_id, tt, macros, binders, ops, guar); } } TokenTree::Sequence(_, ref seq) => { let ops = ops.push(seq.kleene); for tt in &seq.tts { - check_binders(sess, node_id, tt, macros, binders, &ops, guar); + check_binders(psess, node_id, tt, macros, binders, &ops, guar); } } } @@ -323,7 +324,7 @@ fn get_binder_info<'a>( /// errors. /// /// Arguments: -/// - `sess` is used to emit diagnostics and lints +/// - `psess` is used to emit diagnostics and lints /// - `node_id` is used to emit lints /// - `rhs` is checked as part of a RHS /// - `macros` is the stack of possible outer macros @@ -331,7 +332,7 @@ fn get_binder_info<'a>( /// - `ops` is the stack of Kleene operators from the RHS /// - `guar` is set in case of errors fn check_occurrences( - sess: &ParseSess, + psess: &ParseSess, node_id: NodeId, rhs: &TokenTree, macros: &Stack<'_, MacroState<'_>>, @@ -342,24 +343,24 @@ fn check_occurrences( match *rhs { TokenTree::Token(..) => {} TokenTree::MetaVarDecl(span, _name, _kind) => { - sess.dcx.span_bug(span, "unexpected MetaVarDecl in rhs") + psess.dcx.span_bug(span, "unexpected MetaVarDecl in rhs") } TokenTree::MetaVar(span, name) => { let name = MacroRulesNormalizedIdent::new(name); - check_ops_is_prefix(sess, node_id, macros, binders, ops, span, name); + check_ops_is_prefix(psess, node_id, macros, binders, ops, span, name); } TokenTree::MetaVarExpr(dl, ref mve) => { let Some(name) = mve.ident().map(MacroRulesNormalizedIdent::new) else { return; }; - check_ops_is_prefix(sess, node_id, macros, binders, ops, dl.entire(), name); + check_ops_is_prefix(psess, node_id, macros, binders, ops, dl.entire(), name); } TokenTree::Delimited(.., ref del) => { - check_nested_occurrences(sess, node_id, &del.tts, macros, binders, ops, guar); + check_nested_occurrences(psess, node_id, &del.tts, macros, binders, ops, guar); } TokenTree::Sequence(_, ref seq) => { let ops = ops.push(seq.kleene); - check_nested_occurrences(sess, node_id, &seq.tts, macros, binders, &ops, guar); + check_nested_occurrences(psess, node_id, &seq.tts, macros, binders, &ops, guar); } } } @@ -388,7 +389,7 @@ enum NestedMacroState { /// definitions, and sets `valid` to false in case of errors. /// /// Arguments: -/// - `sess` is used to emit diagnostics and lints +/// - `psess` is used to emit diagnostics and lints /// - `node_id` is used to emit lints /// - `tts` is checked as part of a RHS and may contain macro definitions /// - `macros` is the stack of possible outer macros @@ -396,7 +397,7 @@ enum NestedMacroState { /// - `ops` is the stack of Kleene operators from the RHS /// - `guar` is set in case of errors fn check_nested_occurrences( - sess: &ParseSess, + psess: &ParseSess, node_id: NodeId, tts: &[TokenTree], macros: &Stack<'_, MacroState<'_>>, @@ -434,7 +435,7 @@ fn check_nested_occurrences( (NestedMacroState::MacroRulesNot, &TokenTree::MetaVar(..)) => { state = NestedMacroState::MacroRulesNotName; // We check that the meta-variable is correctly used. - check_occurrences(sess, node_id, tt, macros, binders, ops, guar); + check_occurrences(psess, node_id, tt, macros, binders, ops, guar); } (NestedMacroState::MacroRulesNotName, TokenTree::Delimited(.., del)) | (NestedMacroState::MacroName, TokenTree::Delimited(.., del)) @@ -443,11 +444,11 @@ fn check_nested_occurrences( let macro_rules = state == NestedMacroState::MacroRulesNotName; state = NestedMacroState::Empty; let rest = - check_nested_macro(sess, node_id, macro_rules, &del.tts, &nested_macros, guar); + check_nested_macro(psess, node_id, macro_rules, &del.tts, &nested_macros, guar); // If we did not check the whole macro definition, then check the rest as if outside // the macro definition. check_nested_occurrences( - sess, + psess, node_id, &del.tts[rest..], macros, @@ -465,7 +466,7 @@ fn check_nested_occurrences( (NestedMacroState::Macro, &TokenTree::MetaVar(..)) => { state = NestedMacroState::MacroName; // We check that the meta-variable is correctly used. - check_occurrences(sess, node_id, tt, macros, binders, ops, guar); + check_occurrences(psess, node_id, tt, macros, binders, ops, guar); } (NestedMacroState::MacroName, TokenTree::Delimited(.., del)) if del.delim == Delimiter::Parenthesis => @@ -473,7 +474,7 @@ fn check_nested_occurrences( state = NestedMacroState::MacroNameParen; nested_binders = Binders::default(); check_binders( - sess, + psess, node_id, tt, &nested_macros, @@ -487,7 +488,7 @@ fn check_nested_occurrences( { state = NestedMacroState::Empty; check_occurrences( - sess, + psess, node_id, tt, &nested_macros, @@ -498,7 +499,7 @@ fn check_nested_occurrences( } (_, tt) => { state = NestedMacroState::Empty; - check_occurrences(sess, node_id, tt, macros, binders, ops, guar); + check_occurrences(psess, node_id, tt, macros, binders, ops, guar); } } } @@ -512,14 +513,14 @@ fn check_nested_occurrences( /// stopped checking because we detected we were not in a macro definition anymore. /// /// Arguments: -/// - `sess` is used to emit diagnostics and lints +/// - `psess` is used to emit diagnostics and lints /// - `node_id` is used to emit lints /// - `macro_rules` specifies whether the macro is `macro_rules` /// - `tts` is checked as a list of (LHS) => {RHS} /// - `macros` is the stack of outer macros /// - `guar` is set in case of errors fn check_nested_macro( - sess: &ParseSess, + psess: &ParseSess, node_id: NodeId, macro_rules: bool, tts: &[TokenTree], @@ -541,8 +542,8 @@ fn check_nested_macro( let lhs = &tts[i]; let rhs = &tts[i + 2]; let mut binders = Binders::default(); - check_binders(sess, node_id, lhs, macros, &mut binders, &Stack::Empty, guar); - check_occurrences(sess, node_id, rhs, macros, &binders, &Stack::Empty, guar); + check_binders(psess, node_id, lhs, macros, &mut binders, &Stack::Empty, guar); + check_occurrences(psess, node_id, rhs, macros, &binders, &Stack::Empty, guar); // Since the last semicolon is optional for `macro_rules` macros and decl_macro are not terminated, // we increment our checked position by how many token trees we already checked (the 3 // above) before checking for the separator. @@ -559,7 +560,7 @@ fn check_nested_macro( /// Checks that a meta-variable occurrence is valid. /// /// Arguments: -/// - `sess` is used to emit diagnostics and lints +/// - `psess` is used to emit diagnostics and lints /// - `node_id` is used to emit lints /// - `macros` is the stack of possible outer macros /// - `binders` contains the binders of the associated LHS @@ -567,7 +568,7 @@ fn check_nested_macro( /// - `span` is the span of the meta-variable to check /// - `name` is the name of the meta-variable to check fn check_ops_is_prefix( - sess: &ParseSess, + psess: &ParseSess, node_id: NodeId, macros: &Stack<'_, MacroState<'_>>, binders: &Binders, @@ -590,11 +591,11 @@ fn check_ops_is_prefix( for ops in acc.iter().rev() { occurrence_ops.extend_from_slice(ops); } - ops_is_prefix(sess, node_id, span, name, &binder.ops, &occurrence_ops); + ops_is_prefix(psess, node_id, span, name, &binder.ops, &occurrence_ops); return; } } - buffer_lint(sess, span.into(), node_id, format!("unknown macro variable `{name}`")); + buffer_lint(psess, span.into(), node_id, format!("unknown macro variable `{name}`")); } /// Returns whether `binder_ops` is a prefix of `occurrence_ops`. @@ -609,14 +610,14 @@ fn check_ops_is_prefix( /// It occurs under the Kleene stack ["*", "+"] and is bound under ["*"] only. /// /// Arguments: -/// - `sess` is used to emit diagnostics and lints +/// - `psess` is used to emit diagnostics and lints /// - `node_id` is used to emit lints /// - `span` is the span of the meta-variable being check /// - `name` is the name of the meta-variable being check /// - `binder_ops` is the stack of Kleene operators for the binder /// - `occurrence_ops` is the stack of Kleene operators for the occurrence fn ops_is_prefix( - sess: &ParseSess, + psess: &ParseSess, node_id: NodeId, span: Span, name: MacroRulesNormalizedIdent, @@ -628,7 +629,7 @@ fn ops_is_prefix( let mut span = MultiSpan::from_span(span); span.push_span_label(binder.span, "expected repetition"); let message = format!("variable '{name}' is still repeating at this depth"); - buffer_lint(sess, span, node_id, message); + buffer_lint(psess, span, node_id, message); return; } let occurrence = &occurrence_ops[i]; @@ -637,20 +638,20 @@ fn ops_is_prefix( span.push_span_label(binder.span, "expected repetition"); span.push_span_label(occurrence.span, "conflicting repetition"); let message = "meta-variable repeats with different Kleene operator"; - buffer_lint(sess, span, node_id, message); + buffer_lint(psess, span, node_id, message); return; } } } fn buffer_lint( - sess: &ParseSess, + psess: &ParseSess, span: MultiSpan, node_id: NodeId, - message: impl Into, + message: impl Into, ) { // Macros loaded from other crates have dummy node ids. if node_id != DUMMY_NODE_ID { - sess.buffer_lint(META_VARIABLE_MISUSE, span, node_id, message); + psess.buffer_lint(META_VARIABLE_MISUSE, span, node_id, message); } } diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index c11d538048aa9..8903fc45defbc 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -21,7 +21,7 @@ use rustc_feature::Features; use rustc_lint_defs::builtin::{ RUST_2021_INCOMPATIBLE_OR_PATTERNS, SEMICOLON_IN_EXPRESSIONS_FROM_MACROS, }; -use rustc_lint_defs::BuiltinLintDiagnostics; +use rustc_lint_defs::BuiltinLintDiag; use rustc_parse::parser::{Parser, Recovery}; use rustc_session::parse::ParseSess; use rustc_session::Session; @@ -78,12 +78,12 @@ impl<'a> ParserAnyMacro<'a> { // but `m!()` is allowed in expression positions (cf. issue #34706). if kind == AstFragmentKind::Expr && parser.token == token::Semi { if is_local { - parser.sess.buffer_lint_with_diagnostic( + parser.psess.buffer_lint_with_diagnostic( SEMICOLON_IN_EXPRESSIONS_FROM_MACROS, parser.token.span, lint_node_id, "trailing semicolon in macro used in expression position", - BuiltinLintDiagnostics::TrailingMacro(is_trailing_mac, macro_ident), + BuiltinLintDiag::TrailingMacro(is_trailing_mac, macro_ident), ); } parser.bump(); @@ -195,7 +195,7 @@ fn expand_macro<'cx>( lhses: &[Vec], rhses: &[mbe::TokenTree], ) -> Box { - let sess = &cx.sess.parse_sess; + let psess = &cx.sess.psess; // 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; @@ -206,7 +206,7 @@ fn expand_macro<'cx>( } // Track nothing for the best performance. - let try_success_result = try_match_macro(sess, name, &arg, lhses, &mut NoopTracker); + let try_success_result = try_match_macro(psess, name, &arg, lhses, &mut NoopTracker); match try_success_result { Ok((i, named_matches)) => { @@ -230,7 +230,7 @@ fn expand_macro<'cx>( trace_macros_note(&mut cx.expansions, sp, msg); } - let p = Parser::new(sess, tts, None); + let p = Parser::new(psess, tts, None); if is_local { cx.resolver.record_macro_rule_usage(node_id, i); @@ -272,9 +272,9 @@ pub(super) enum CanRetry { /// Try expanding the macro. Returns the index of the successful arm and its named_matches if it was successful, /// and nothing if it failed. On failure, it's the callers job to use `track` accordingly to record all errors /// correctly. -#[instrument(level = "debug", skip(sess, arg, lhses, track), fields(tracking = %T::description()))] +#[instrument(level = "debug", skip(psess, arg, lhses, track), fields(tracking = %T::description()))] pub(super) fn try_match_macro<'matcher, T: Tracker<'matcher>>( - sess: &ParseSess, + psess: &ParseSess, name: Ident, arg: &TokenStream, lhses: &'matcher [Vec], @@ -299,7 +299,7 @@ pub(super) fn try_match_macro<'matcher, T: Tracker<'matcher>>( // hacky, but speeds up the `html5ever` benchmark significantly. (Issue // 68836 suggests a more comprehensive but more complex change to deal with // this situation.) - let parser = parser_from_cx(sess, arg.clone(), T::recovery()); + let parser = parser_from_cx(psess, arg.clone(), T::recovery()); // Try each arm's matchers. let mut tt_parser = TtParser::new(name); for (i, lhs) in lhses.iter().enumerate() { @@ -309,7 +309,7 @@ pub(super) fn try_match_macro<'matcher, T: Tracker<'matcher>>( // This is used so that if a matcher is not `Success(..)`ful, // then the spans which became gated when parsing the unsuccessful matcher // are not recorded. On the first `Success(..)`ful matcher, the spans are merged. - let mut gated_spans_snapshot = mem::take(&mut *sess.gated_spans.spans.borrow_mut()); + let mut gated_spans_snapshot = mem::take(&mut *psess.gated_spans.spans.borrow_mut()); let result = tt_parser.parse_tt(&mut Cow::Borrowed(&parser), lhs, track); @@ -320,7 +320,7 @@ pub(super) fn try_match_macro<'matcher, T: Tracker<'matcher>>( debug!("Parsed arm successfully"); // The matcher was `Success(..)`ful. // Merge the gated spans from parsing the matcher with the preexisting ones. - sess.gated_spans.merge(gated_spans_snapshot); + psess.gated_spans.merge(gated_spans_snapshot); return Ok((i, named_matches)); } @@ -342,7 +342,7 @@ pub(super) fn try_match_macro<'matcher, T: Tracker<'matcher>>( // The matcher was not `Success(..)`ful. // Restore to the state before snapshotting and maybe try again. - mem::swap(&mut gated_spans_snapshot, &mut sess.gated_spans.spans.borrow_mut()); + mem::swap(&mut gated_spans_snapshot, &mut psess.gated_spans.spans.borrow_mut()); } Err(CanRetry::Yes) @@ -376,7 +376,7 @@ pub fn compile_declarative_macro( }; let dummy_syn_ext = |guar| (mk_syn_ext(Box::new(DummyExpander(guar))), Vec::new()); - let dcx = &sess.parse_sess.dcx; + let dcx = &sess.psess.dcx; let lhs_nm = Ident::new(sym::lhs, def.span); let rhs_nm = Ident::new(sym::rhs, def.span); let tt_spec = Some(NonterminalKind::TT); @@ -430,7 +430,7 @@ pub fn compile_declarative_macro( let create_parser = || { let body = macro_def.body.tokens.clone(); - Parser::new(&sess.parse_sess, body, rustc_parse::MACRO_ARGUMENTS) + Parser::new(&sess.psess, body, rustc_parse::MACRO_ARGUMENTS) }; let parser = create_parser(); @@ -533,7 +533,7 @@ pub fn compile_declarative_macro( } check_emission(macro_check::check_meta_variables( - &sess.parse_sess, + &sess.psess, def.id, def.span, &lhses, @@ -1149,12 +1149,12 @@ fn check_matcher_core<'tt>( name, Some(NonterminalKind::PatParam { inferred: false }), )); - sess.parse_sess.buffer_lint_with_diagnostic( + sess.psess.buffer_lint_with_diagnostic( RUST_2021_INCOMPATIBLE_OR_PATTERNS, span, ast::CRATE_NODE_ID, "the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro", - BuiltinLintDiagnostics::OrPatternsBackCompat(span, suggestion), + BuiltinLintDiag::OrPatternsBackCompat(span, suggestion), ); } match is_in_follow(next_token, kind) { @@ -1182,7 +1182,7 @@ fn check_matcher_core<'tt>( err.span_label(sp, format!("not allowed after `{kind}` fragments")); if kind == NonterminalKind::PatWithOr - && sess.parse_sess.edition.at_least_rust_2021() + && sess.psess.edition.at_least_rust_2021() && next_token.is_token(&BinOp(token::BinOpToken::Or)) { let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl( @@ -1406,10 +1406,10 @@ fn quoted_tt_to_string(tt: &mbe::TokenTree) -> String { } pub(super) fn parser_from_cx( - sess: &ParseSess, + psess: &ParseSess, mut tts: TokenStream, recovery: Recovery, ) -> Parser<'_> { tts.desugar_doc_comments(); - Parser::new(sess, tts, rustc_parse::MACRO_ARGUMENTS).recovery(recovery) + Parser::new(psess, tts, rustc_parse::MACRO_ARGUMENTS).recovery(recovery) } diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs index 84f7dc4771a9e..81e1de5b09544 100644 --- a/compiler/rustc_expand/src/mbe/metavar_expr.rs +++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs @@ -27,30 +27,30 @@ pub(crate) enum MetaVarExpr { impl MetaVarExpr { /// Attempt to parse a meta-variable expression from a token stream. - pub(crate) fn parse<'sess>( + pub(crate) fn parse<'psess>( input: &TokenStream, outer_span: Span, - sess: &'sess ParseSess, - ) -> PResult<'sess, MetaVarExpr> { + psess: &'psess ParseSess, + ) -> PResult<'psess, MetaVarExpr> { let mut tts = input.trees(); - let ident = parse_ident(&mut tts, sess, outer_span)?; + let ident = parse_ident(&mut tts, psess, outer_span)?; let Some(TokenTree::Delimited(.., Delimiter::Parenthesis, args)) = tts.next() else { let msg = "meta-variable expression parameter must be wrapped in parentheses"; - return Err(sess.dcx.struct_span_err(ident.span, msg)); + return Err(psess.dcx.struct_span_err(ident.span, msg)); }; - check_trailing_token(&mut tts, sess)?; + check_trailing_token(&mut tts, psess)?; let mut iter = args.trees(); let rslt = match ident.as_str() { - "count" => parse_count(&mut iter, sess, ident.span)?, + "count" => parse_count(&mut iter, psess, ident.span)?, "ignore" => { - eat_dollar(&mut iter, sess, ident.span)?; - MetaVarExpr::Ignore(parse_ident(&mut iter, sess, ident.span)?) + eat_dollar(&mut iter, psess, ident.span)?; + MetaVarExpr::Ignore(parse_ident(&mut iter, psess, ident.span)?) } - "index" => MetaVarExpr::Index(parse_depth(&mut iter, sess, ident.span)?), - "length" => MetaVarExpr::Length(parse_depth(&mut iter, sess, ident.span)?), + "index" => MetaVarExpr::Index(parse_depth(&mut iter, psess, ident.span)?), + "length" => MetaVarExpr::Length(parse_depth(&mut iter, psess, ident.span)?), _ => { let err_msg = "unrecognized meta-variable expression"; - let mut err = sess.dcx.struct_span_err(ident.span, err_msg); + let mut err = psess.dcx.struct_span_err(ident.span, err_msg); err.span_suggestion( ident.span, "supported expressions are count, ignore, index and length", @@ -60,7 +60,7 @@ impl MetaVarExpr { return Err(err); } }; - check_trailing_token(&mut iter, sess)?; + check_trailing_token(&mut iter, psess)?; Ok(rslt) } @@ -73,12 +73,12 @@ impl MetaVarExpr { } // Checks if there are any remaining tokens. For example, `${ignore(ident ... a b c ...)}` -fn check_trailing_token<'sess>( +fn check_trailing_token<'psess>( iter: &mut RefTokenTreeCursor<'_>, - sess: &'sess ParseSess, -) -> PResult<'sess, ()> { + psess: &'psess ParseSess, +) -> PResult<'psess, ()> { if let Some(tt) = iter.next() { - let mut diag = sess + let mut diag = psess .dcx .struct_span_err(tt.span(), format!("unexpected token: {}", pprust::tt_to_string(tt))); diag.span_note(tt.span(), "meta-variable expression must not have trailing tokens"); @@ -89,21 +89,21 @@ fn check_trailing_token<'sess>( } /// Parse a meta-variable `count` expression: `count(ident[, depth])` -fn parse_count<'sess>( +fn parse_count<'psess>( iter: &mut RefTokenTreeCursor<'_>, - sess: &'sess ParseSess, + psess: &'psess ParseSess, span: Span, -) -> PResult<'sess, MetaVarExpr> { - eat_dollar(iter, sess, span)?; - let ident = parse_ident(iter, sess, span)?; +) -> PResult<'psess, MetaVarExpr> { + eat_dollar(iter, psess, span)?; + let ident = parse_ident(iter, psess, span)?; let depth = if try_eat_comma(iter) { if iter.look_ahead(0).is_none() { - return Err(sess.dcx.struct_span_err( + return Err(psess.dcx.struct_span_err( span, "`count` followed by a comma must have an associated index indicating its depth", )); } - parse_depth(iter, sess, span)? + parse_depth(iter, psess, span)? } else { 0 }; @@ -111,14 +111,14 @@ fn parse_count<'sess>( } /// Parses the depth used by index(depth) and length(depth). -fn parse_depth<'sess>( +fn parse_depth<'psess>( iter: &mut RefTokenTreeCursor<'_>, - sess: &'sess ParseSess, + psess: &'psess ParseSess, span: Span, -) -> PResult<'sess, usize> { +) -> PResult<'psess, usize> { let Some(tt) = iter.next() else { return Ok(0) }; let TokenTree::Token(token::Token { kind: token::TokenKind::Literal(lit), .. }, _) = tt else { - return Err(sess + return Err(psess .dcx .struct_span_err(span, "meta-variable expression depth must be a literal")); }; @@ -129,16 +129,16 @@ fn parse_depth<'sess>( Ok(n_usize) } else { let msg = "only unsuffixes integer literals are supported in meta-variable expressions"; - Err(sess.dcx.struct_span_err(span, msg)) + Err(psess.dcx.struct_span_err(span, msg)) } } /// Parses an generic ident -fn parse_ident<'sess>( +fn parse_ident<'psess>( iter: &mut RefTokenTreeCursor<'_>, - sess: &'sess ParseSess, + psess: &'psess ParseSess, span: Span, -) -> PResult<'sess, Ident> { +) -> PResult<'psess, Ident> { if let Some(tt) = iter.next() && let TokenTree::Token(token, _) = tt { @@ -147,7 +147,7 @@ fn parse_ident<'sess>( } let token_str = pprust::token_to_string(token); let mut err = - sess.dcx.struct_span_err(span, format!("expected identifier, found `{}`", &token_str)); + psess.dcx.struct_span_err(span, format!("expected identifier, found `{}`", &token_str)); err.span_suggestion( token.span, format!("try removing `{}`", &token_str), @@ -156,7 +156,7 @@ fn parse_ident<'sess>( ); return Err(err); } - Err(sess.dcx.struct_span_err(span, "expected identifier")) + Err(psess.dcx.struct_span_err(span, "expected identifier")) } /// Tries to move the iterator forward returning `true` if there is a comma. If not, then the @@ -170,17 +170,17 @@ fn try_eat_comma(iter: &mut RefTokenTreeCursor<'_>) -> bool { } /// Expects that the next item is a dollar sign. -fn eat_dollar<'sess>( +fn eat_dollar<'psess>( iter: &mut RefTokenTreeCursor<'_>, - sess: &'sess ParseSess, + psess: &'psess ParseSess, span: Span, -) -> PResult<'sess, ()> { +) -> PResult<'psess, ()> { if let Some(TokenTree::Token(token::Token { kind: token::Dollar, .. }, _)) = iter.look_ahead(0) { let _ = iter.next(); return Ok(()); } - Err(sess.dcx.struct_span_err( + Err(psess.dcx.struct_span_err( span, "meta-variables within meta-variable expressions must be referenced using a dollar sign", )) diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index ec1dd807d1a4f..5fd3716743b22 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -175,8 +175,7 @@ fn parse_tree<'a>( // The delimiter is `{`. This indicates the beginning // of a meta-variable expression (e.g. `${count(ident)}`). // Try to parse the meta-variable expression. - match MetaVarExpr::parse(tts, delim_span.entire(), &sess.parse_sess) - { + match MetaVarExpr::parse(tts, delim_span.entire(), &sess.psess) { Err(err) => { err.emit(); // Returns early the same read `$` to avoid spanning diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs index 1282cf2c03a00..8a68b39e4965e 100644 --- a/compiler/rustc_expand/src/module.rs +++ b/compiler/rustc_expand/src/module.rs @@ -66,7 +66,7 @@ pub(crate) fn parse_external_mod( } // Actually parse the external file as a module. - let mut parser = new_parser_from_file(&sess.parse_sess, &mp.file_path, Some(span)); + let mut parser = new_parser_from_file(&sess.psess, &mp.file_path, Some(span)); let (inner_attrs, items, inner_span) = parser.parse_mod(&token::Eof).map_err(|err| ModError::ParserError(err))?; attrs.extend(inner_attrs); @@ -157,7 +157,7 @@ fn mod_file_path<'a>( DirOwnership::Owned { relative } => relative, DirOwnership::UnownedViaBlock => None, }; - let result = default_submod_path(&sess.parse_sess, ident, relative, dir_path); + let result = default_submod_path(&sess.psess, ident, relative, dir_path); match dir_ownership { DirOwnership::Owned { .. } => result, DirOwnership::UnownedViaBlock => Err(ModError::ModInBlock(match result { @@ -185,11 +185,7 @@ fn mod_file_path_from_attr( // complexity). Usually bad forms are checked in AstValidator (via // `check_builtin_attribute`), but by the time that runs the macro // is expanded, and it doesn't give an error. - validate_attr::emit_fatal_malformed_builtin_attribute( - &sess.parse_sess, - first_path, - sym::path, - ); + validate_attr::emit_fatal_malformed_builtin_attribute(&sess.psess, first_path, sym::path); }; let path_str = path_sym.as_str(); @@ -207,7 +203,7 @@ fn mod_file_path_from_attr( /// Returns a path to a module. // Public for rustfmt usage. pub fn default_submod_path<'a>( - sess: &'a ParseSess, + psess: &'a ParseSess, ident: Ident, relative: Option, dir_path: &Path, @@ -229,8 +225,8 @@ pub fn default_submod_path<'a>( format!("{}{}{}mod.rs", relative_prefix, ident.name, path::MAIN_SEPARATOR); let default_path = dir_path.join(&default_path_str); let secondary_path = dir_path.join(&secondary_path_str); - let default_exists = sess.source_map().file_exists(&default_path); - let secondary_exists = sess.source_map().file_exists(&secondary_path); + let default_exists = psess.source_map().file_exists(&default_path); + let secondary_exists = psess.source_map().file_exists(&secondary_path); match (default_exists, secondary_exists) { (true, false) => Ok(ModulePathSuccess { diff --git a/compiler/rustc_expand/src/parse/tests.rs b/compiler/rustc_expand/src/parse/tests.rs index 0e07b41b43c7d..066afd7a41d28 100644 --- a/compiler/rustc_expand/src/parse/tests.rs +++ b/compiler/rustc_expand/src/parse/tests.rs @@ -1,5 +1,6 @@ use crate::tests::{ - matches_codepattern, string_to_stream, with_error_checking_parse, with_expected_parse_error, + matches_codepattern, psess, string_to_stream, with_error_checking_parse, + with_expected_parse_error, }; use ast::token::IdentIsRaw; @@ -14,19 +15,10 @@ use rustc_parse::new_parser_from_source_str; use rustc_parse::parser::ForceCollect; use rustc_session::parse::ParseSess; use rustc_span::create_default_session_globals_then; -use rustc_span::source_map::FilePathMapping; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::{BytePos, FileName, Pos, Span}; - use std::path::PathBuf; -fn sess() -> ParseSess { - ParseSess::new( - vec![crate::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE], - FilePathMapping::empty(), - ) -} - /// Parses an item. /// /// Returns `Ok(Some(item))` when successful, `Ok(None)` when no item was found, and `Err` @@ -34,9 +26,9 @@ fn sess() -> ParseSess { fn parse_item_from_source_str( name: FileName, source: String, - sess: &ParseSess, + psess: &ParseSess, ) -> PResult<'_, Option>> { - new_parser_from_source_str(sess, name, source).parse_item(ForceCollect::No) + new_parser_from_source_str(psess, name, source).parse_item(ForceCollect::No) } // Produces a `rustc_span::span`. @@ -46,12 +38,12 @@ fn sp(a: u32, b: u32) -> Span { /// Parses a string, return an expression. fn string_to_expr(source_str: String) -> P { - with_error_checking_parse(source_str, &sess(), |p| p.parse_expr()) + with_error_checking_parse(source_str, &psess(), |p| p.parse_expr()) } /// Parses a string, returns an item. fn string_to_item(source_str: String) -> Option> { - with_error_checking_parse(source_str, &sess(), |p| p.parse_item(ForceCollect::No)) + with_error_checking_parse(source_str, &psess(), |p| p.parse_item(ForceCollect::No)) } #[test] @@ -287,24 +279,24 @@ let mut fflags: c_int = wb(); #[test] fn crlf_doc_comments() { create_default_session_globals_then(|| { - let sess = sess(); + let psess = psess(); let name_1 = FileName::Custom("crlf_source_1".to_string()); let source = "/// doc comment\r\nfn foo() {}".to_string(); - let item = parse_item_from_source_str(name_1, source, &sess).unwrap().unwrap(); + let item = parse_item_from_source_str(name_1, source, &psess).unwrap().unwrap(); let doc = item.attrs.iter().filter_map(|at| at.doc_str()).next().unwrap(); assert_eq!(doc.as_str(), " doc comment"); let name_2 = FileName::Custom("crlf_source_2".to_string()); let source = "/// doc comment\r\n/// line 2\r\nfn foo() {}".to_string(); - let item = parse_item_from_source_str(name_2, source, &sess).unwrap().unwrap(); + let item = parse_item_from_source_str(name_2, source, &psess).unwrap().unwrap(); let docs = item.attrs.iter().filter_map(|at| at.doc_str()).collect::>(); let b: &[_] = &[Symbol::intern(" doc comment"), Symbol::intern(" line 2")]; assert_eq!(&docs[..], b); let name_3 = FileName::Custom("clrf_source_3".to_string()); let source = "/** doc comment\r\n * with CRLF */\r\nfn foo() {}".to_string(); - let item = parse_item_from_source_str(name_3, source, &sess).unwrap().unwrap(); + let item = parse_item_from_source_str(name_3, source, &psess).unwrap().unwrap(); let doc = item.attrs.iter().filter_map(|at| at.doc_str()).next().unwrap(); assert_eq!(doc.as_str(), " doc comment\n * with CRLF "); }); @@ -315,24 +307,24 @@ fn ttdelim_span() { fn parse_expr_from_source_str( name: FileName, source: String, - sess: &ParseSess, + psess: &ParseSess, ) -> PResult<'_, P> { - new_parser_from_source_str(sess, name, source).parse_expr() + new_parser_from_source_str(psess, name, source).parse_expr() } create_default_session_globals_then(|| { - let sess = sess(); + let psess = psess(); let expr = parse_expr_from_source_str( PathBuf::from("foo").into(), "foo!( fn main() { body } )".to_string(), - &sess, + &psess, ) .unwrap(); let ast::ExprKind::MacCall(mac) = &expr.kind else { panic!("not a macro") }; let span = mac.args.tokens.trees().last().unwrap().span(); - match sess.source_map().span_to_snippet(span) { + match psess.source_map().span_to_snippet(span) { Ok(s) => assert_eq!(&s[..], "{ body }"), Err(_) => panic!("could not get snippet"), } @@ -348,7 +340,7 @@ fn out_of_line_mod() { let item = parse_item_from_source_str( PathBuf::from("foo").into(), "mod foo { struct S; mod this_does_not_exist; }".to_owned(), - &sess(), + &psess(), ) .unwrap() .unwrap(); diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs index 23caf2f193aad..4b5c148cb555d 100644 --- a/compiler/rustc_expand/src/proc_macro.rs +++ b/compiler/rustc_expand/src/proc_macro.rs @@ -162,7 +162,7 @@ impl MultiItemModifier for DeriveProcMacro { let error_count_before = ecx.dcx().err_count(); let mut parser = - rustc_parse::stream_to_parser(&ecx.sess.parse_sess, stream, Some("proc-macro derive")); + rustc_parse::stream_to_parser(&ecx.sess.psess, stream, Some("proc-macro derive")); let mut items = vec![]; loop { diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 6fe0d61136322..ddc685c9d07da 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -354,7 +354,7 @@ impl ToInternal> )] } TokenTree::Ident(self::Ident { sym, is_raw, span }) => { - rustc.sess().symbol_gallery.insert(sym, span); + rustc.psess().symbol_gallery.insert(sym, span); smallvec![tokenstream::TokenTree::token_alone(Ident(sym, is_raw.into()), span)] } TokenTree::Literal(self::Literal { @@ -429,8 +429,8 @@ impl<'a, 'b> Rustc<'a, 'b> { } } - fn sess(&self) -> &ParseSess { - self.ecx.parse_sess() + fn psess(&self) -> &ParseSess { + self.ecx.psess() } } @@ -448,19 +448,19 @@ impl server::FreeFunctions for Rustc<'_, '_> { } fn track_env_var(&mut self, var: &str, value: Option<&str>) { - self.sess() + self.psess() .env_depinfo .borrow_mut() .insert((Symbol::intern(var), value.map(Symbol::intern))); } fn track_path(&mut self, path: &str) { - self.sess().file_depinfo.borrow_mut().insert(Symbol::intern(path)); + self.psess().file_depinfo.borrow_mut().insert(Symbol::intern(path)); } fn literal_from_str(&mut self, s: &str) -> Result, ()> { let name = FileName::proc_macro_source_code(s); - let mut parser = rustc_parse::new_parser_from_source_str(self.sess(), name, s.to_owned()); + let mut parser = rustc_parse::new_parser_from_source_str(self.psess(), name, s.to_owned()); let first_span = parser.token.span.data(); let minus_present = parser.eat(&token::BinOp(token::Minus)); @@ -512,11 +512,14 @@ impl server::FreeFunctions for Rustc<'_, '_> { } fn emit_diagnostic(&mut self, diagnostic: Diagnostic) { - let message = rustc_errors::DiagnosticMessage::from(diagnostic.message); + let message = rustc_errors::DiagMessage::from(diagnostic.message); let mut diag: Diag<'_, ()> = - Diag::new(&self.sess().dcx, diagnostic.level.to_internal(), message); + Diag::new(&self.psess().dcx, diagnostic.level.to_internal(), message); diag.span(MultiSpan::from_spans(diagnostic.spans)); for child in diagnostic.children { + // This message comes from another diagnostic, and we are just reconstructing the + // diagnostic, so there's no need for translation. + #[allow(rustc::untranslatable_diagnostic)] diag.sub(child.level.to_internal(), child.message, MultiSpan::from_spans(child.spans)); } diag.emit(); @@ -532,7 +535,7 @@ impl server::TokenStream for Rustc<'_, '_> { parse_stream_from_source_str( FileName::proc_macro_source_code(src), src.to_string(), - self.sess(), + self.psess(), Some(self.call_site), ) } @@ -545,7 +548,7 @@ impl server::TokenStream for Rustc<'_, '_> { // Parse the expression from our tokenstream. let expr: PResult<'_, _> = try { let mut p = rustc_parse::stream_to_parser( - self.sess(), + self.psess(), stream.clone(), Some("proc_macro expand expr"), ); @@ -680,7 +683,7 @@ impl server::Span for Rustc<'_, '_> { } fn source_file(&mut self, span: Self::Span) -> Self::SourceFile { - self.sess().source_map().lookup_char_pos(span.lo()).file + self.psess().source_map().lookup_char_pos(span.lo()).file } fn parent(&mut self, span: Self::Span) -> Option { @@ -692,7 +695,7 @@ impl server::Span for Rustc<'_, '_> { } fn byte_range(&mut self, span: Self::Span) -> Range { - let source_map = self.sess().source_map(); + let source_map = self.psess().source_map(); let relative_start_pos = source_map.lookup_byte_offset(span.lo()).pos; let relative_end_pos = source_map.lookup_byte_offset(span.hi()).pos; @@ -708,18 +711,18 @@ impl server::Span for Rustc<'_, '_> { } fn line(&mut self, span: Self::Span) -> usize { - let loc = self.sess().source_map().lookup_char_pos(span.lo()); + let loc = self.psess().source_map().lookup_char_pos(span.lo()); loc.line } fn column(&mut self, span: Self::Span) -> usize { - let loc = self.sess().source_map().lookup_char_pos(span.lo()); + let loc = self.psess().source_map().lookup_char_pos(span.lo()); loc.col.to_usize() + 1 } fn join(&mut self, first: Self::Span, second: Self::Span) -> Option { - let self_loc = self.sess().source_map().lookup_char_pos(first.lo()); - let other_loc = self.sess().source_map().lookup_char_pos(second.lo()); + let self_loc = self.psess().source_map().lookup_char_pos(first.lo()); + let other_loc = self.psess().source_map().lookup_char_pos(second.lo()); if self_loc.file.name != other_loc.file.name { return None; @@ -769,7 +772,7 @@ impl server::Span for Rustc<'_, '_> { } fn source_text(&mut self, span: Self::Span) -> Option { - self.sess().source_map().span_to_snippet(span).ok() + self.psess().source_map().span_to_snippet(span).ok() } /// Saves the provided span into the metadata of @@ -797,7 +800,7 @@ impl server::Span for Rustc<'_, '_> { /// since we've loaded `my_proc_macro` from disk in order to execute it). /// In this way, we have obtained a span pointing into `my_proc_macro` fn save_span(&mut self, span: Self::Span) -> usize { - self.sess().save_proc_macro_span(span) + self.psess().save_proc_macro_span(span) } fn recover_proc_macro_span(&mut self, id: usize) -> Self::Span { diff --git a/compiler/rustc_expand/src/tests.rs b/compiler/rustc_expand/src/tests.rs index b242ce795fd05..a3510dc9bff4d 100644 --- a/compiler/rustc_expand/src/tests.rs +++ b/compiler/rustc_expand/src/tests.rs @@ -18,9 +18,13 @@ use std::path::{Path, PathBuf}; use std::str; use std::sync::{Arc, Mutex}; +pub(crate) fn psess() -> ParseSess { + ParseSess::new(vec![crate::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE]) +} + /// Map string to parser (via tts). -fn string_to_parser(ps: &ParseSess, source_str: String) -> Parser<'_> { - new_parser_from_source_str(ps, PathBuf::from("bogofile").into(), source_str) +fn string_to_parser(psess: &ParseSess, source_str: String) -> Parser<'_> { + new_parser_from_source_str(psess, PathBuf::from("bogofile").into(), source_str) } fn create_test_handler() -> (DiagCtxt, Lrc, Arc>>) { @@ -40,13 +44,13 @@ fn create_test_handler() -> (DiagCtxt, Lrc, Arc>>) { /// Returns the result of parsing the given string via the given callback. /// /// If there are any errors, this will panic. -pub(crate) fn with_error_checking_parse<'a, T, F>(s: String, ps: &'a ParseSess, f: F) -> T +pub(crate) fn with_error_checking_parse<'a, T, F>(s: String, psess: &'a ParseSess, f: F) -> T where F: FnOnce(&mut Parser<'a>) -> PResult<'a, T>, { - let mut p = string_to_parser(&ps, s); + let mut p = string_to_parser(&psess, s); let x = f(&mut p).unwrap(); - p.sess.dcx.abort_if_errors(); + p.psess.dcx.abort_if_errors(); x } @@ -57,8 +61,8 @@ where F: for<'a> FnOnce(&mut Parser<'a>) -> PResult<'a, T>, { let (handler, source_map, output) = create_test_handler(); - let ps = ParseSess::with_dcx(handler, source_map); - let mut p = string_to_parser(&ps, source_str.to_string()); + let psess = ParseSess::with_dcx(handler, source_map); + let mut p = string_to_parser(&psess, source_str.to_string()); let result = f(&mut p); assert!(result.is_ok()); @@ -72,24 +76,18 @@ where /// Maps a string to tts, using a made-up filename. pub(crate) fn string_to_stream(source_str: String) -> TokenStream { - let ps = ParseSess::new( - vec![crate::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE], - FilePathMapping::empty(), - ); + let psess = psess(); source_file_to_stream( - &ps, - ps.source_map().new_source_file(PathBuf::from("bogofile").into(), source_str), + &psess, + psess.source_map().new_source_file(PathBuf::from("bogofile").into(), source_str), None, ) } /// Parses a string, returns a crate. pub(crate) fn string_to_crate(source_str: String) -> ast::Crate { - let ps = ParseSess::new( - vec![crate::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE], - FilePathMapping::empty(), - ); - with_error_checking_parse(source_str, &ps, |p| p.parse_crate_mod()) + let psess = psess(); + with_error_checking_parse(source_str, &psess, |p| p.parse_crate_mod()) } /// Does the given string match the pattern? whitespace in the first string @@ -180,6 +178,7 @@ impl Write for Shared { } } +#[allow(rustc::untranslatable_diagnostic)] // no translation needed for tests fn test_harness(file_text: &str, span_labels: Vec, expected_output: &str) { create_default_session_globals_then(|| { let (handler, source_map, output) = create_test_handler(); @@ -194,7 +193,6 @@ fn test_harness(file_text: &str, span_labels: Vec, expected_output: & println!("text: {:?}", source_map.span_to_snippet(span)); } - #[allow(rustc::untranslatable_diagnostic)] handler.span_err(msp, "foo"); assert!( diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 1b2993dabdb83..7e5197f16f91e 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -146,6 +146,8 @@ declare_features! ( (accepted, derive_default_enum, "1.62.0", Some(86985)), /// Allows the use of destructuring assignments. (accepted, destructuring_assignment, "1.59.0", Some(71126)), + /// Allows using the `#[diagnostic]` attribute tool namespace + (accepted, diagnostic_namespace, "CURRENT_RUSTC_VERSION", Some(111996)), /// Allows `#[doc(alias = "...")]`. (accepted, doc_alias, "1.48.0", Some(50146)), /// Allows `..` in tuple (struct) patterns. diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 10867ae230a8c..0d51e1e46e06a 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -695,8 +695,8 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // Used by the `rustc::potential_query_instability` lint to warn methods which // might not be stable during incremental compilation. rustc_attr!(rustc_lint_query_instability, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE), - // Used by the `rustc::untranslatable_diagnostic` and `rustc::diagnostic_outside_of_impl` lints - // to assist in changes to diagnostic APIs. + // Used by the `rustc::diagnostic_outside_of_impl` lints to assist in changes to diagnostic + // APIs. Any function with this attribute will be checked by that lint. rustc_attr!(rustc_lint_diagnostics, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE), // Used by the `rustc::bad_opt_access` lint to identify `DebuggingOptions` and `CodegenOptions` // types (as well as any others in future). @@ -709,7 +709,9 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // Internal attributes, Const related: // ========================================================================== - rustc_attr!(rustc_promotable, Normal, template!(Word), WarnFollowing, IMPL_DETAIL), + rustc_attr!( + rustc_promotable, Normal, template!(Word), WarnFollowing, + @only_local: true, IMPL_DETAIL), rustc_attr!( rustc_legacy_const_generics, Normal, template!(List: "N"), ErrorFollowing, INTERNAL_UNSTABLE @@ -784,7 +786,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ the given type by annotating all impl items with #[rustc_allow_incoherent_impl]." ), rustc_attr!( - rustc_box, AttributeType::Normal, template!(Word), ErrorFollowing, + rustc_box, AttributeType::Normal, template!(Word), ErrorFollowing, @only_local: true, "#[rustc_box] allows creating boxes \ and it is only intended to be used in `alloc`." ), @@ -806,11 +808,11 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ gated!( // Used in resolve: prelude_import, Normal, template!(Word), WarnFollowing, - "`#[prelude_import]` is for use by rustc only", + @only_local: true, "`#[prelude_import]` is for use by rustc only", ), gated!( - rustc_paren_sugar, Normal, template!(Word), WarnFollowing, unboxed_closures, - "unboxed_closures are still evolving", + rustc_paren_sugar, Normal, template!(Word), WarnFollowing, @only_local: true, + unboxed_closures, "unboxed_closures are still evolving", ), rustc_attr!( rustc_inherit_overflow_checks, Normal, template!(Word), WarnFollowing, @only_local: true, @@ -826,27 +828,31 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), rustc_attr!( rustc_test_marker, Normal, template!(NameValueStr: "name"), WarnFollowing, - "the `#[rustc_test_marker]` attribute is used internally to track tests", + @only_local: true, "the `#[rustc_test_marker]` attribute is used internally to track tests", ), rustc_attr!( - rustc_unsafe_specialization_marker, Normal, template!(Word), WarnFollowing, + rustc_unsafe_specialization_marker, Normal, template!(Word), + WarnFollowing, @only_local: true, "the `#[rustc_unsafe_specialization_marker]` attribute is used to check specializations" ), rustc_attr!( - rustc_specialization_trait, Normal, template!(Word), WarnFollowing, + rustc_specialization_trait, Normal, template!(Word), + WarnFollowing, @only_local: true, "the `#[rustc_specialization_trait]` attribute is used to check specializations" ), rustc_attr!( - rustc_main, Normal, template!(Word), WarnFollowing, + rustc_main, Normal, template!(Word), WarnFollowing, @only_local: true, "the `#[rustc_main]` attribute is used internally to specify test entry point function", ), rustc_attr!( - rustc_skip_array_during_method_dispatch, Normal, template!(Word), WarnFollowing, + rustc_skip_array_during_method_dispatch, Normal, template!(Word), + WarnFollowing, @only_local: true, "the `#[rustc_skip_array_during_method_dispatch]` attribute is used to exclude a trait \ from method dispatch when the receiver is an array, for compatibility in editions < 2021." ), rustc_attr!( - rustc_must_implement_one_of, Normal, template!(List: "function1, function2, ..."), ErrorFollowing, + rustc_must_implement_one_of, Normal, template!(List: "function1, function2, ..."), + ErrorFollowing, @only_local: true, "the `#[rustc_must_implement_one_of]` attribute is used to change minimal complete \ definition of a trait, it's currently in experimental form and should be changed before \ being exposed outside of the std" @@ -857,6 +863,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), rustc_attr!( rustc_safe_intrinsic, Normal, template!(Word), WarnFollowing, + @only_local: true, "the `#[rustc_safe_intrinsic]` attribute is used internally to mark intrinsics as safe" ), rustc_attr!( @@ -867,14 +874,24 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_no_mir_inline, Normal, template!(Word), WarnFollowing, "#[rustc_no_mir_inline] prevents the MIR inliner from inlining a function while not affecting codegen" ), + rustc_attr!( + rustc_intrinsic_must_be_overridden, Normal, template!(Word), ErrorFollowing, + "the `#[rustc_intrinsic_must_be_overridden]` attribute is used to declare intrinsics without real bodies", + ), // ========================================================================== // Internal attributes, Testing: // ========================================================================== rustc_attr!(TEST, rustc_effective_visibility, Normal, template!(Word), WarnFollowing), - rustc_attr!(TEST, rustc_outlives, Normal, template!(Word), WarnFollowing), - rustc_attr!(TEST, rustc_capture_analysis, Normal, template!(Word), WarnFollowing), + rustc_attr!( + TEST, rustc_outlives, Normal, template!(Word), + WarnFollowing, @only_local: true + ), + rustc_attr!( + TEST, rustc_capture_analysis, Normal, template!(Word), + WarnFollowing, @only_local: true + ), rustc_attr!(TEST, rustc_insignificant_dtor, Normal, template!(Word), WarnFollowing), rustc_attr!(TEST, rustc_strict_coherence, Normal, template!(Word), WarnFollowing), rustc_attr!(TEST, rustc_variance, Normal, template!(Word), WarnFollowing), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 17c4d81474e27..a10f4b934ea0a 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -345,6 +345,8 @@ declare_features! ( (unstable, asm_const, "1.58.0", Some(93332)), /// Enables experimental inline assembly support for additional architectures. (unstable, asm_experimental_arch, "1.58.0", Some(93335)), + /// Allows using `label` operands in inline assembly. + (unstable, asm_goto, "CURRENT_RUSTC_VERSION", Some(119364)), /// Allows the `may_unwind` option in inline assembly. (unstable, asm_unwind, "1.58.0", Some(93334)), /// Allows users to enforce equality of associated constants `TraitImpl`. @@ -436,8 +438,6 @@ declare_features! ( (unstable, deprecated_safe, "1.61.0", Some(94978)), /// Allows having using `suggestion` in the `#[deprecated]` attribute. (unstable, deprecated_suggestion, "1.61.0", Some(94785)), - /// Allows using the `#[diagnostic]` attribute tool namespace - (unstable, diagnostic_namespace, "1.73.0", Some(111996)), /// Controls errors in trait implementations. (unstable, do_not_recommend, "1.67.0", Some(51992)), /// Tells rustdoc to automatically generate `#[doc(cfg(...))]`. diff --git a/compiler/rustc_fluent_macro/src/fluent.rs b/compiler/rustc_fluent_macro/src/fluent.rs index 520a64aaf5e23..214b6587af3b0 100644 --- a/compiler/rustc_fluent_macro/src/fluent.rs +++ b/compiler/rustc_fluent_macro/src/fluent.rs @@ -54,20 +54,20 @@ fn finish(body: TokenStream, resource: TokenStream) -> proc_macro::TokenStream { /// identifiers for different subdiagnostic kinds. pub mod _subdiag { /// Default for `#[help]` - pub const help: rustc_errors::SubdiagnosticMessage = - rustc_errors::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("help")); + pub const help: rustc_errors::SubdiagMessage = + rustc_errors::SubdiagMessage::FluentAttr(std::borrow::Cow::Borrowed("help")); /// Default for `#[note]` - pub const note: rustc_errors::SubdiagnosticMessage = - rustc_errors::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("note")); + pub const note: rustc_errors::SubdiagMessage = + rustc_errors::SubdiagMessage::FluentAttr(std::borrow::Cow::Borrowed("note")); /// Default for `#[warn]` - pub const warn: rustc_errors::SubdiagnosticMessage = - rustc_errors::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("warn")); + pub const warn: rustc_errors::SubdiagMessage = + rustc_errors::SubdiagMessage::FluentAttr(std::borrow::Cow::Borrowed("warn")); /// Default for `#[label]` - pub const label: rustc_errors::SubdiagnosticMessage = - rustc_errors::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("label")); + pub const label: rustc_errors::SubdiagMessage = + rustc_errors::SubdiagMessage::FluentAttr(std::borrow::Cow::Borrowed("label")); /// Default for `#[suggestion]` - pub const suggestion: rustc_errors::SubdiagnosticMessage = - rustc_errors::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("suggestion")); + pub const suggestion: rustc_errors::SubdiagMessage = + rustc_errors::SubdiagMessage::FluentAttr(std::borrow::Cow::Borrowed("suggestion")); } } } @@ -244,8 +244,11 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok format!("Constant referring to Fluent message `{name}` from `{crate_name}`"); constants.extend(quote! { #[doc = #docstr] - pub const #snake_name: rustc_errors::DiagnosticMessage = - rustc_errors::DiagnosticMessage::FluentIdentifier(std::borrow::Cow::Borrowed(#name), None); + pub const #snake_name: rustc_errors::DiagMessage = + rustc_errors::DiagMessage::FluentIdentifier( + std::borrow::Cow::Borrowed(#name), + None + ); }); for Attribute { id: Identifier { name: attr_name }, .. } in attributes { @@ -272,8 +275,8 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok ); constants.extend(quote! { #[doc = #msg] - pub const #snake_name: rustc_errors::SubdiagnosticMessage = - rustc_errors::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed(#attr_name)); + pub const #snake_name: rustc_errors::SubdiagMessage = + rustc_errors::SubdiagMessage::FluentAttr(std::borrow::Cow::Borrowed(#attr_name)); }); } diff --git a/compiler/rustc_fluent_macro/src/lib.rs b/compiler/rustc_fluent_macro/src/lib.rs index e3784409af8fd..2303785f94e69 100644 --- a/compiler/rustc_fluent_macro/src/lib.rs +++ b/compiler/rustc_fluent_macro/src/lib.rs @@ -35,10 +35,10 @@ mod fluent; /// /// mod fluent_generated { /// mod typeck { -/// pub const field_multiply_specified_in_initializer: DiagnosticMessage = -/// DiagnosticMessage::fluent("typeck_field_multiply_specified_in_initializer"); -/// pub const field_multiply_specified_in_initializer_label_previous_use: DiagnosticMessage = -/// DiagnosticMessage::fluent_attr( +/// pub const field_multiply_specified_in_initializer: DiagMessage = +/// DiagMessage::fluent("typeck_field_multiply_specified_in_initializer"); +/// pub const field_multiply_specified_in_initializer_label_previous_use: DiagMessage = +/// DiagMessage::fluent_attr( /// "typeck_field_multiply_specified_in_initializer", /// "previous_use_label" /// ); diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 3dac6880f17e1..7d5b4c0f06de2 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2562,6 +2562,8 @@ pub enum OpaqueTyOrigin { AsyncFn(LocalDefId), /// type aliases: `type Foo = impl Trait;` TyAlias { + /// The type alias or associated type parent of the TAIT/ATPIT + parent: LocalDefId, /// associated types in impl blocks for traits. in_assoc_ty: bool, }, @@ -2650,6 +2652,9 @@ pub enum InlineAsmOperand<'hir> { path: QPath<'hir>, def_id: DefId, }, + Label { + block: &'hir Block<'hir>, + }, } impl<'hir> InlineAsmOperand<'hir> { @@ -2659,7 +2664,10 @@ impl<'hir> InlineAsmOperand<'hir> { | Self::Out { reg, .. } | Self::InOut { reg, .. } | Self::SplitInOut { reg, .. } => Some(reg), - Self::Const { .. } | Self::SymFn { .. } | Self::SymStatic { .. } => None, + Self::Const { .. } + | Self::SymFn { .. } + | Self::SymStatic { .. } + | Self::Label { .. } => None, } } @@ -2680,6 +2688,12 @@ pub struct InlineAsm<'hir> { pub line_spans: &'hir [Span], } +impl InlineAsm<'_> { + pub fn contains_label(&self) -> bool { + self.operands.iter().any(|x| matches!(x.0, InlineAsmOperand::Label { .. })) + } +} + /// Represents a parameter in a function header. #[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Param<'hir> { diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 1c38a45d3a32f..32b4bf38fa96a 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -65,8 +65,7 @@ //! example coroutine inference, and possibly also HIR borrowck. use crate::hir::*; -use rustc_ast::visit::VisitorResult; -use rustc_ast::{try_visit, visit_opt, walk_list}; +use rustc_ast::visit::{try_visit, visit_opt, walk_list, VisitorResult}; use rustc_ast::{Attribute, Label}; use rustc_span::def_id::LocalDefId; use rustc_span::symbol::{Ident, Symbol}; @@ -1290,6 +1289,7 @@ pub fn walk_inline_asm<'v, V: Visitor<'v>>( InlineAsmOperand::SymStatic { path, .. } => { try_visit!(visitor.visit_qpath(path, id, *op_sp)); } + InlineAsmOperand::Label { block } => try_visit!(visitor.visit_block(block)), } } V::Result::output() diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 8a89a3b5faa5e..5118bf5c3b7ab 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -267,6 +267,8 @@ language_item_table! { EhCatchTypeinfo, sym::eh_catch_typeinfo, eh_catch_typeinfo, Target::Static, GenericRequirement::None; OwnedBox, sym::owned_box, owned_box, Target::Struct, GenericRequirement::Minimum(1); + GlobalAlloc, sym::global_alloc_ty, global_alloc_ty, Target::Struct, GenericRequirement::None; + // Experimental language item for Miri PtrUnique, sym::ptr_unique, ptr_unique, Target::Struct, GenericRequirement::Exact(1); diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index e376411cd95c1..bad472dcb5c06 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -312,6 +312,10 @@ hir_analysis_only_current_traits_primitive = only traits defined in the current hir_analysis_only_current_traits_ty = `{$ty}` is not defined in the current crate +hir_analysis_opaque_captures_higher_ranked_lifetime = `impl Trait` cannot capture {$bad_place} + .label = `impl Trait` implicitly captures all lifetimes in scope + .note = lifetime declared here + hir_analysis_paren_sugar_attribute = the `#[rustc_paren_sugar]` attribute is a temporary means of controlling which traits can use parenthetical notation .help = add `#![feature(unboxed_closures)]` to the crate attributes to use it diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs index ce4c4609bc85a..63afa4f7e82d2 100644 --- a/compiler/rustc_hir_analysis/src/astconv/generics.rs +++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs @@ -3,7 +3,7 @@ use crate::astconv::{ errors::prohibit_assoc_ty_binding, CreateInstantiationsForGenericArgsCtxt, ExplicitLateBound, GenericArgCountMismatch, GenericArgCountResult, GenericArgPosition, }; -use crate::structured_errors::{GenericArgsInfo, StructuredDiagnostic, WrongNumberOfGenericArgs}; +use crate::structured_errors::{GenericArgsInfo, StructuredDiag, WrongNumberOfGenericArgs}; use rustc_ast::ast::ParamKindOrd; use rustc_errors::{ codes::*, struct_span_code_err, Applicability, Diag, ErrorGuaranteed, MultiSpan, diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index b8cf72c2c73ff..325342d653dd2 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -1612,10 +1612,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .any(|impl_def_id| { let impl_header = tcx.impl_trait_header(impl_def_id); impl_header.is_some_and(|header| { - let header = header.instantiate( + let trait_ref = header.trait_ref.instantiate( tcx, infcx.fresh_args_for_item(DUMMY_SP, impl_def_id), ); + let value = tcx.fold_regions(qself_ty, |_, _| tcx.lifetimes.re_erased); // FIXME: Don't bother dealing with non-lifetime binders here... if value.has_escaping_bound_vars() { @@ -1624,7 +1625,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { infcx .can_eq( ty::ParamEnv::empty(), - header.trait_ref.self_ty(), + trait_ref.self_ty(), value, ) && header.polarity != ty::ImplPolarity::Negative }) @@ -1677,9 +1678,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .filter(|header| { // Consider only accessible traits tcx.visibility(trait_def_id).is_accessible_from(self.item_def_id(), tcx) - && header.skip_binder().polarity != ty::ImplPolarity::Negative + && header.polarity != ty::ImplPolarity::Negative }) - .map(|header| header.instantiate_identity().trait_ref.self_ty()) + .map(|header| header.trait_ref.instantiate_identity().self_ty()) // We don't care about blanket impls. .filter(|self_ty| !self_ty.has_non_region_param()) .map(|self_ty| tcx.erase_regions(self_ty).to_string()) diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs index 7705445ffaa42..b9543c7a29b2a 100644 --- a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs @@ -45,10 +45,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { dummy_self, &mut bounds, false, - // FIXME: This should be `true`, but we don't really handle - // associated type bounds or type aliases in objects in a way - // that makes this meaningful, I think. - OnlySelfBounds(false), + // True so we don't populate `bounds` with associated type bounds, even + // though they're disallowed from object types. + OnlySelfBounds(true), ) { potential_assoc_types.extend(cur_potential_assoc_types); } @@ -83,9 +82,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let expanded_traits = traits::expand_trait_aliases(tcx, trait_bounds.iter().map(|&(a, b)| (a, b))); - let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = expanded_traits - .filter(|i| i.trait_ref().self_ty().skip_binder() == dummy_self) - .partition(|i| tcx.trait_is_auto(i.trait_ref().def_id())); + let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = + expanded_traits.partition(|i| tcx.trait_is_auto(i.trait_ref().def_id())); if regular_traits.len() > 1 { let first_trait = ®ular_traits[0]; let additional_trait = ®ular_traits[1]; @@ -158,7 +156,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { for (base_trait_ref, span) in regular_traits_refs_spans { let base_pred: ty::Predicate<'tcx> = base_trait_ref.to_predicate(tcx); - for pred in traits::elaborate(tcx, [base_pred]) { + for pred in traits::elaborate(tcx, [base_pred]).filter_only_self() { debug!("conv_object_ty_poly_trait_ref: observing object predicate `{:?}`", pred); let bound_predicate = pred.kind(); @@ -312,45 +310,39 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }) }); - let existential_projections = projection_bounds - .iter() - // We filter out traits that don't have `Self` as their self type above, - // we need to do the same for projections. - .filter(|(bound, _)| bound.skip_binder().self_ty() == dummy_self) - .map(|(bound, _)| { - bound.map_bound(|mut b| { - assert_eq!(b.projection_ty.self_ty(), dummy_self); + let existential_projections = projection_bounds.iter().map(|(bound, _)| { + bound.map_bound(|mut b| { + assert_eq!(b.projection_ty.self_ty(), dummy_self); - // Like for trait refs, verify that `dummy_self` did not leak inside default type - // parameters. - let references_self = b.projection_ty.args.iter().skip(1).any(|arg| { - if arg.walk().any(|arg| arg == dummy_self.into()) { - return true; - } - false - }); - if references_self { - let guar = tcx.dcx().span_delayed_bug( - span, - "trait object projection bounds reference `Self`", - ); - let args: Vec<_> = b - .projection_ty - .args - .iter() - .map(|arg| { - if arg.walk().any(|arg| arg == dummy_self.into()) { - return Ty::new_error(tcx, guar).into(); - } - arg - }) - .collect(); - b.projection_ty.args = tcx.mk_args(&args); + // Like for trait refs, verify that `dummy_self` did not leak inside default type + // parameters. + let references_self = b.projection_ty.args.iter().skip(1).any(|arg| { + if arg.walk().any(|arg| arg == dummy_self.into()) { + return true; } + false + }); + if references_self { + let guar = tcx + .dcx() + .span_delayed_bug(span, "trait object projection bounds reference `Self`"); + let args: Vec<_> = b + .projection_ty + .args + .iter() + .map(|arg| { + if arg.walk().any(|arg| arg == dummy_self.into()) { + return Ty::new_error(tcx, guar).into(); + } + arg + }) + .collect(); + b.projection_ty.args = tcx.mk_args(&args); + } - ty::ExistentialProjection::erase_self_ty(tcx, b) - }) - }); + ty::ExistentialProjection::erase_self_ty(tcx, b) + }) + }); let regular_trait_predicates = existential_trait_refs .map(|trait_ref| trait_ref.map_bound(ty::ExistentialPredicate::Trait)); diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 96bebda582815..1b24c2b61fd07 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -339,8 +339,9 @@ fn check_opaque_meets_bounds<'tcx>( origin: &hir::OpaqueTyOrigin, ) -> Result<(), ErrorGuaranteed> { let defining_use_anchor = match *origin { - hir::OpaqueTyOrigin::FnReturn(did) | hir::OpaqueTyOrigin::AsyncFn(did) => did, - hir::OpaqueTyOrigin::TyAlias { .. } => tcx.impl_trait_parent(def_id), + hir::OpaqueTyOrigin::FnReturn(did) + | hir::OpaqueTyOrigin::AsyncFn(did) + | hir::OpaqueTyOrigin::TyAlias { parent: did, .. } => did, }; let param_env = tcx.param_env(defining_use_anchor); @@ -351,14 +352,14 @@ fn check_opaque_meets_bounds<'tcx>( let ocx = ObligationCtxt::new(&infcx); let args = match *origin { - hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent) => { - GenericArgs::identity_for_item(tcx, parent).extend_to( - tcx, - def_id.to_def_id(), - |param, _| tcx.map_rpit_lifetime_to_fn_lifetime(param.def_id.expect_local()).into(), - ) - } - hir::OpaqueTyOrigin::TyAlias { .. } => GenericArgs::identity_for_item(tcx, def_id), + hir::OpaqueTyOrigin::FnReturn(parent) + | hir::OpaqueTyOrigin::AsyncFn(parent) + | hir::OpaqueTyOrigin::TyAlias { parent, .. } => GenericArgs::identity_for_item( + tcx, parent, + ) + .extend_to(tcx, def_id.to_def_id(), |param, _| { + tcx.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local()).into() + }), }; let opaque_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args); @@ -402,39 +403,29 @@ fn check_opaque_meets_bounds<'tcx>( let guar = infcx.err_ctxt().report_fulfillment_errors(errors); return Err(guar); } - match origin { - // Checked when type checking the function containing them. - hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => { - // HACK: this should also fall through to the hidden type check below, but the original - // implementation had a bug where equivalent lifetimes are not identical. This caused us - // to reject existing stable code that is otherwise completely fine. The real fix is to - // compare the hidden types via our type equivalence/relation infra instead of doing an - // identity check. - let _ = infcx.take_opaque_types(); - return Ok(()); - } - // Nested opaque types occur only in associated types: - // ` type Opaque = impl Trait<&'static T, AssocTy = impl Nested>; ` - // They can only be referenced as ` as Trait<&'static T>>::AssocTy`. - // We don't have to check them here because their well-formedness follows from the WF of - // the projection input types in the defining- and use-sites. - hir::OpaqueTyOrigin::TyAlias { .. } - if tcx.def_kind(tcx.parent(def_id.to_def_id())) == DefKind::OpaqueTy => {} - // Can have different predicates to their defining use - hir::OpaqueTyOrigin::TyAlias { .. } => { - let wf_tys = ocx.assumed_wf_types_and_report_errors(param_env, def_id)?; - let implied_bounds = infcx.implied_bounds_tys(param_env, def_id, &wf_tys); - let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); - ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env)?; + + let wf_tys = ocx.assumed_wf_types_and_report_errors(param_env, defining_use_anchor)?; + let implied_bounds = infcx.implied_bounds_tys(param_env, def_id, &wf_tys); + let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); + ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env)?; + + if let hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) = origin { + // HACK: this should also fall through to the hidden type check below, but the original + // implementation had a bug where equivalent lifetimes are not identical. This caused us + // to reject existing stable code that is otherwise completely fine. The real fix is to + // compare the hidden types via our type equivalence/relation infra instead of doing an + // identity check. + let _ = infcx.take_opaque_types(); + Ok(()) + } else { + // Check that any hidden types found during wf checking match the hidden types that `type_of` sees. + for (mut key, mut ty) in infcx.take_opaque_types() { + ty.hidden_type.ty = infcx.resolve_vars_if_possible(ty.hidden_type.ty); + key = infcx.resolve_vars_if_possible(key); + sanity_check_found_hidden_type(tcx, key, ty.hidden_type)?; } + Ok(()) } - // Check that any hidden types found during wf checking match the hidden types that `type_of` sees. - for (mut key, mut ty) in infcx.take_opaque_types() { - ty.hidden_type.ty = infcx.resolve_vars_if_possible(ty.hidden_type.ty); - key = infcx.resolve_vars_if_possible(key); - sanity_check_found_hidden_type(tcx, key, ty.hidden_type)?; - } - Ok(()) } fn sanity_check_found_hidden_type<'tcx>( @@ -527,12 +518,12 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { check_enum(tcx, def_id); } DefKind::Fn => { - if let Some(name) = tcx.intrinsic(def_id) { + if let Some(i) = tcx.intrinsic(def_id) { intrinsic::check_intrinsic_type( tcx, def_id, tcx.def_ident_span(def_id).unwrap(), - name, + i.name, Abi::Rust, ) } @@ -540,11 +531,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { } DefKind::Impl { of_trait } => { if of_trait && let Some(impl_trait_header) = tcx.impl_trait_header(def_id) { - check_impl_items_against_trait( - tcx, - def_id, - impl_trait_header.instantiate_identity(), - ); + check_impl_items_against_trait(tcx, def_id, impl_trait_header); check_on_unimplemented(tcx, def_id); } } @@ -735,10 +722,11 @@ fn check_impl_items_against_trait<'tcx>( impl_id: LocalDefId, impl_trait_header: ty::ImplTraitHeader<'tcx>, ) { + let trait_ref = impl_trait_header.trait_ref.instantiate_identity(); // If the trait reference itself is erroneous (so the compilation is going // to fail), skip checking the items here -- the `impl_item` table in `tcx` // isn't populated for such impls. - if impl_trait_header.references_error() { + if trait_ref.references_error() { return; } @@ -762,7 +750,7 @@ fn check_impl_items_against_trait<'tcx>( } } - let trait_def = tcx.trait_def(impl_trait_header.trait_ref.def_id); + let trait_def = tcx.trait_def(trait_ref.def_id); for &impl_item in impl_item_refs { let ty_impl_item = tcx.associated_item(impl_item); @@ -781,10 +769,10 @@ fn check_impl_items_against_trait<'tcx>( )); } ty::AssocKind::Fn => { - compare_impl_method(tcx, ty_impl_item, ty_trait_item, impl_trait_header.trait_ref); + compare_impl_method(tcx, ty_impl_item, ty_trait_item, trait_ref); } ty::AssocKind::Type => { - compare_impl_ty(tcx, ty_impl_item, ty_trait_item, impl_trait_header.trait_ref); + compare_impl_ty(tcx, ty_impl_item, ty_trait_item, trait_ref); } } @@ -804,7 +792,7 @@ fn check_impl_items_against_trait<'tcx>( let mut must_implement_one_of: Option<&[Ident]> = trait_def.must_implement_one_of.as_deref(); - for &trait_item_id in tcx.associated_item_def_ids(impl_trait_header.trait_ref.def_id) { + for &trait_item_id in tcx.associated_item_def_ids(trait_ref.def_id) { let leaf_def = ancestors.leaf_def(tcx, trait_item_id); let is_implemented = leaf_def @@ -882,7 +870,7 @@ fn check_impl_items_against_trait<'tcx>( if let Some(missing_items) = must_implement_one_of { let attr_span = tcx - .get_attr(impl_trait_header.trait_ref.def_id, sym::rustc_must_implement_one_of) + .get_attr(trait_ref.def_id, sym::rustc_must_implement_one_of) .map(|attr| attr.span); missing_items_must_implement_one_of_err( @@ -1474,15 +1462,14 @@ fn opaque_type_cycle_error( closures: Vec, } impl<'tcx> ty::visit::TypeVisitor> for OpaqueTypeCollector { - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) { match *t.kind() { ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => { self.opaques.push(def); - ControlFlow::Continue(()) } ty::Closure(def_id, ..) | ty::Coroutine(def_id, ..) => { self.closures.push(def_id); - t.super_visit_with(self) + t.super_visit_with(self); } _ => t.super_visit_with(self), } @@ -1550,6 +1537,8 @@ fn opaque_type_cycle_error( err.emit() } +// FIXME(@lcnr): This should not be computed per coroutine, but instead once for +// each typeck root. pub(super) fn check_coroutine_obligations( tcx: TyCtxt<'_>, def_id: LocalDefId, @@ -1557,7 +1546,7 @@ pub(super) fn check_coroutine_obligations( debug_assert!(tcx.is_coroutine(def_id.to_def_id())); let typeck = tcx.typeck(def_id); - let param_env = tcx.param_env(def_id); + let param_env = tcx.param_env(typeck.hir_owner.def_id); let coroutine_interior_predicates = &typeck.coroutine_interior_predicates[&def_id]; debug!(?coroutine_interior_predicates); diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 435e251b130ea..ec9e928ce593d 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -1,5 +1,6 @@ use super::potentially_plural_count; use crate::errors::{LifetimesOrBoundsMismatchOnTrait, MethodShouldReturnFuture}; +use core::ops::ControlFlow; use hir::def_id::{DefId, DefIdMap, LocalDefId}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, ErrorGuaranteed}; @@ -520,14 +521,6 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( ) .fold_with(&mut collector); - if !unnormalized_trait_sig.output().references_error() { - debug_assert_ne!( - collector.types.len(), - 0, - "expect >1 RPITITs in call to `collect_return_position_impl_trait_in_trait_tys`" - ); - } - let trait_sig = ocx.normalize(&misc_cause, param_env, unnormalized_trait_sig); trait_sig.error_reported()?; let trait_return_ty = trait_sig.output(); @@ -646,6 +639,13 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( } } + if !unnormalized_trait_sig.output().references_error() { + debug_assert!( + !collector.types.is_empty(), + "expect >0 RPITITs in call to `collect_return_position_impl_trait_in_trait_tys`" + ); + } + // FIXME: This has the same issue as #108544, but since this isn't breaking // existing code, I'm not particularly inclined to do the same hack as above // where we process wf obligations manually. This can be fixed in a forward- @@ -1565,24 +1565,24 @@ fn compare_synthetic_generics<'tcx>( let (sig, _) = impl_m.expect_fn(); let input_tys = sig.decl.inputs; - struct Visitor(Option, hir::def_id::LocalDefId); + struct Visitor(hir::def_id::LocalDefId); impl<'v> intravisit::Visitor<'v> for Visitor { - fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) { - intravisit::walk_ty(self, ty); + type Result = ControlFlow; + fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) -> Self::Result { if let hir::TyKind::Path(hir::QPath::Resolved(None, path)) = ty.kind && let Res::Def(DefKind::TyParam, def_id) = path.res - && def_id == self.1.to_def_id() + && def_id == self.0.to_def_id() { - self.0 = Some(ty.span); + ControlFlow::Break(ty.span) + } else { + intravisit::walk_ty(self, ty) } } } - let mut visitor = Visitor(None, impl_def_id); - for ty in input_tys { - intravisit::Visitor::visit_ty(&mut visitor, ty); - } - let span = visitor.0?; + let span = input_tys.iter().find_map(|ty| { + intravisit::Visitor::visit_ty(&mut Visitor(impl_def_id), ty).break_value() + })?; let bounds = impl_m.generics.bounds_for_param(impl_def_id).next()?.bounds; let bounds = bounds.first()?.span().to(bounds.last()?.span()); diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs index 29dc434ab4532..8c4c4fc774ec8 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs @@ -12,7 +12,6 @@ use rustc_trait_selection::regions::InferCtxtRegionExt; use rustc_trait_selection::traits::{ elaborate, normalize_param_env_or_error, outlives_bounds::InferCtxtExt, ObligationCtxt, }; -use std::ops::ControlFlow; /// Check that an implementation does not refine an RPITIT from a trait method signature. pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>( @@ -211,9 +210,7 @@ struct ImplTraitInTraitCollector<'tcx> { } impl<'tcx> TypeVisitor> for ImplTraitInTraitCollector<'tcx> { - type BreakTy = !; - - fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) { if let ty::Alias(ty::Projection, proj) = *ty.kind() && self.tcx.is_impl_trait_in_trait(proj.def_id) { @@ -223,12 +220,11 @@ impl<'tcx> TypeVisitor> for ImplTraitInTraitCollector<'tcx> { .explicit_item_bounds(proj.def_id) .iter_instantiated_copied(self.tcx, proj.args) { - pred.visit_with(self)?; + pred.visit_with(self); } } - ControlFlow::Continue(()) } else { - ty.super_visit_with(self) + ty.super_visit_with(self); } } } diff --git a/compiler/rustc_hir_analysis/src/check/errs.rs b/compiler/rustc_hir_analysis/src/check/errs.rs index c92320bc0fee8..3d32fdd89c867 100644 --- a/compiler/rustc_hir_analysis/src/check/errs.rs +++ b/compiler/rustc_hir_analysis/src/check/errs.rs @@ -70,7 +70,7 @@ fn handle_static_mut_ref( } else { (errors::StaticMutRefSugg::Shared { span, var }, "shared") }; - tcx.sess.parse_sess.dcx.emit_err(errors::StaticMutRef { span, sugg, shared }); + tcx.sess.psess.dcx.emit_err(errors::StaticMutRef { span, sugg, shared }); return; } diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 9d8eb6ad60b31..95c51cc0486fc 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -7,7 +7,7 @@ use crate::errors::{ WrongNumberOfGenericArgumentsToIntrinsic, }; -use rustc_errors::{codes::*, struct_span_code_err, DiagnosticMessage}; +use rustc_errors::{codes::*, struct_span_code_err, DiagMessage}; use rustc_hir as hir; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -132,14 +132,15 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) - | sym::fsub_algebraic | sym::fmul_algebraic | sym::fdiv_algebraic - | sym::frem_algebraic => hir::Unsafety::Normal, + | sym::frem_algebraic + | sym::const_eval_select => hir::Unsafety::Normal, _ => hir::Unsafety::Unsafe, }; if has_safe_attr != is_in_list { tcx.dcx().struct_span_err( tcx.def_span(intrinsic_id), - DiagnosticMessage::from(format!( + DiagMessage::from(format!( "intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `{}`", tcx.item_name(intrinsic_id.into()) ) @@ -247,7 +248,6 @@ pub fn check_intrinsic_type( ], Ty::new_unit(tcx), ), - sym::drop_in_place => (1, 0, vec![Ty::new_mut_ptr(tcx, param(0))], Ty::new_unit(tcx)), sym::needs_drop => (1, 0, vec![], tcx.types.bool), sym::type_name => (1, 0, vec![], Ty::new_static_str(tcx)), diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs index d03b02f028da1..9de660407d7aa 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs @@ -470,6 +470,8 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { } }; } + // No special checking is needed for labels. + hir::InlineAsmOperand::Label { .. } => {} } } } diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 0f5fd7e99b776..2a4dd6b0e0ef3 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -6,7 +6,7 @@ //! //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/borrow_check.html -use rustc_ast::walk_list; +use rustc_ast::visit::walk_list; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def_id::DefId; diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index f03d0f8a88529..09689b22e905f 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1,7 +1,9 @@ use crate::autoderef::Autoderef; +use crate::collect::CollectItemTypesVisitor; use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter}; use crate::errors; +use hir::intravisit::Visitor; use rustc_ast as ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, ErrorGuaranteed}; @@ -225,6 +227,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<() ?item.owner_id, item.name = ? tcx.def_path_str(def_id) ); + CollectItemTypesVisitor { tcx }.visit_item(item); let res = match item.kind { // Right now we check that every default trait implementation @@ -247,7 +250,9 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<() hir::ItemKind::Impl(impl_) => { let header = tcx.impl_trait_header(def_id); let is_auto = header - .is_some_and(|header| tcx.trait_is_auto(header.skip_binder().trait_ref.def_id)); + .is_some_and(|header| tcx.trait_is_auto(header.trait_ref.skip_binder().def_id)); + + crate::impl_wf_check::check_impl_wf(tcx, def_id)?; let mut res = Ok(()); if let (hir::Defaultness::Default { .. }, true) = (impl_.defaultness, is_auto) { let sp = impl_.of_trait.as_ref().map_or(item.span, |t| t.path.span); @@ -259,7 +264,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<() .emit()); } // We match on both `ty::ImplPolarity` and `ast::ImplPolarity` just to get the `!` span. - match header.map(|h| h.skip_binder().polarity) { + match header.map(|h| h.polarity) { // `None` means this is an inherent impl Some(ty::ImplPolarity::Positive) | None => { res = res.and(check_impl(tcx, item, impl_.self_ty, &impl_.of_trait)); @@ -296,31 +301,31 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<() hir::ItemKind::Const(ty, ..) => { check_item_type(tcx, def_id, ty.span, UnsizedHandling::Forbid) } - hir::ItemKind::Struct(_, ast_generics) => { + hir::ItemKind::Struct(_, hir_generics) => { let res = check_type_defn(tcx, item, false); - check_variances_for_type_defn(tcx, item, ast_generics); + check_variances_for_type_defn(tcx, item, hir_generics); res } - hir::ItemKind::Union(_, ast_generics) => { + hir::ItemKind::Union(_, hir_generics) => { let res = check_type_defn(tcx, item, true); - check_variances_for_type_defn(tcx, item, ast_generics); + check_variances_for_type_defn(tcx, item, hir_generics); res } - hir::ItemKind::Enum(_, ast_generics) => { + hir::ItemKind::Enum(_, hir_generics) => { let res = check_type_defn(tcx, item, true); - check_variances_for_type_defn(tcx, item, ast_generics); + check_variances_for_type_defn(tcx, item, hir_generics); res } hir::ItemKind::Trait(..) => check_trait(tcx, item), hir::ItemKind::TraitAlias(..) => check_trait(tcx, item), // `ForeignItem`s are handled separately. hir::ItemKind::ForeignMod { .. } => Ok(()), - hir::ItemKind::TyAlias(hir_ty, ast_generics) => { + hir::ItemKind::TyAlias(hir_ty, hir_generics) => { if tcx.type_alias_is_lazy(item.owner_id) { // Bounds of lazy type aliases and of eager ones that contain opaque types are respected. // E.g: `type X = impl Trait;`, `type X = (impl Trait, Y);`. let res = check_item_type(tcx, def_id, hir_ty.span, UnsizedHandling::Allow); - check_variances_for_type_defn(tcx, item, ast_generics); + check_variances_for_type_defn(tcx, item, hir_generics); res } else { Ok(()) @@ -334,9 +339,14 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<() res } -fn check_foreign_item(tcx: TyCtxt<'_>, item: &hir::ForeignItem<'_>) -> Result<(), ErrorGuaranteed> { +fn check_foreign_item<'tcx>( + tcx: TyCtxt<'tcx>, + item: &'tcx hir::ForeignItem<'tcx>, +) -> Result<(), ErrorGuaranteed> { let def_id = item.owner_id.def_id; + CollectItemTypesVisitor { tcx }.visit_foreign_item(item); + debug!( ?item.owner_id, item.name = ? tcx.def_path_str(def_id) @@ -353,12 +363,14 @@ fn check_foreign_item(tcx: TyCtxt<'_>, item: &hir::ForeignItem<'_>) -> Result<() } } -fn check_trait_item( - tcx: TyCtxt<'_>, - trait_item: &hir::TraitItem<'_>, +fn check_trait_item<'tcx>( + tcx: TyCtxt<'tcx>, + trait_item: &'tcx hir::TraitItem<'tcx>, ) -> Result<(), ErrorGuaranteed> { let def_id = trait_item.owner_id.def_id; + CollectItemTypesVisitor { tcx }.visit_trait_item(trait_item); + let (method_sig, span) = match trait_item.kind { hir::TraitItemKind::Fn(ref sig, _) => (Some(sig), trait_item.span), hir::TraitItemKind::Type(_bounds, Some(ty)) => (None, ty.span), @@ -809,9 +821,7 @@ impl<'tcx> GATArgsCollector<'tcx> { } impl<'tcx> TypeVisitor> for GATArgsCollector<'tcx> { - type BreakTy = !; - - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) { match t.kind() { ty::Alias(ty::Projection, p) if p.def_id == self.gat => { for (idx, arg) in p.args.iter().enumerate() { @@ -895,7 +905,12 @@ fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem } } -fn check_impl_item(tcx: TyCtxt<'_>, impl_item: &hir::ImplItem<'_>) -> Result<(), ErrorGuaranteed> { +fn check_impl_item<'tcx>( + tcx: TyCtxt<'tcx>, + impl_item: &'tcx hir::ImplItem<'tcx>, +) -> Result<(), ErrorGuaranteed> { + CollectItemTypesVisitor { tcx }.visit_impl_item(impl_item); + let (method_sig, span) = match impl_item.kind { hir::ImplItemKind::Fn(ref sig, _) => (Some(sig), impl_item.span), // Constrain binding and overflow error spans to `` in `type foo = `. @@ -1277,16 +1292,16 @@ fn check_item_type( }) } -#[instrument(level = "debug", skip(tcx, ast_self_ty, ast_trait_ref))] +#[instrument(level = "debug", skip(tcx, hir_self_ty, hir_trait_ref))] fn check_impl<'tcx>( tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>, - ast_self_ty: &hir::Ty<'_>, - ast_trait_ref: &Option>, + hir_self_ty: &hir::Ty<'_>, + hir_trait_ref: &Option>, ) -> Result<(), ErrorGuaranteed> { enter_wf_checking_ctxt(tcx, item.span, item.owner_id.def_id, |wfcx| { - match ast_trait_ref { - Some(ast_trait_ref) => { + match hir_trait_ref { + Some(hir_trait_ref) => { // `#[rustc_reservation_impl]` impls are not real impls and // therefore don't need to be WF (the trait's `Self: Trait` predicate // won't hold). @@ -1294,8 +1309,9 @@ fn check_impl<'tcx>( // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case // other `Foo` impls are incoherent. tcx.ensure().coherent_trait(trait_ref.def_id)?; + let trait_span = hir_trait_ref.path.span; let trait_ref = wfcx.normalize( - ast_trait_ref.path.span, + trait_span, Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)), trait_ref, ); @@ -1306,14 +1322,23 @@ fn check_impl<'tcx>( wfcx.param_env, wfcx.body_def_id, trait_pred, - ast_trait_ref.path.span, + trait_span, item, ); for obligation in &mut obligations { + if obligation.cause.span != trait_span { + // We already have a better span. + continue; + } if let Some(pred) = obligation.predicate.to_opt_poly_trait_pred() - && pred.self_ty().skip_binder() == trait_ref.self_ty() + && pred.skip_binder().self_ty() == trait_ref.self_ty() { - obligation.cause.span = ast_self_ty.span; + obligation.cause.span = hir_self_ty.span; + } + if let Some(pred) = obligation.predicate.to_opt_poly_projection_pred() + && pred.skip_binder().self_ty() == trait_ref.self_ty() + { + obligation.cause.span = hir_self_ty.span; } } debug!(?obligations); @@ -1327,7 +1352,7 @@ fn check_impl<'tcx>( self_ty, ); wfcx.register_wf_obligation( - ast_self_ty.span, + hir_self_ty.span, Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)), self_ty.into(), ); @@ -1456,20 +1481,19 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id params: FxHashSet, } impl<'tcx> ty::visit::TypeVisitor> for CountParams { - type BreakTy = (); - - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + type Result = ControlFlow<()>; + fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { if let ty::Param(param) = t.kind() { self.params.insert(param.index); } t.super_visit_with(self) } - fn visit_region(&mut self, _: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, _: ty::Region<'tcx>) -> Self::Result { ControlFlow::Break(()) } - fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, c: ty::Const<'tcx>) -> Self::Result { if let ty::ConstKind::Param(param) = c.kind() { self.params.insert(param.index); } diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 6c3a9b747ef61..8d8b13d6cb397 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -25,7 +25,7 @@ use rustc_trait_selection::traits::ObligationCtxt; use rustc_trait_selection::traits::{self, ObligationCause}; use std::collections::BTreeMap; -pub fn check_trait<'tcx>( +pub(super) fn check_trait<'tcx>( tcx: TyCtxt<'tcx>, trait_def_id: DefId, impl_def_id: LocalDefId, @@ -66,10 +66,9 @@ impl<'tcx> Checker<'tcx> { fn visit_implementation_of_drop(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> { let tcx = checker.tcx; - let header = checker.impl_header; let impl_did = checker.impl_def_id; // Destructors only work on local ADT types. - match header.trait_ref.self_ty().kind() { + match checker.impl_header.trait_ref.instantiate_identity().self_ty().kind() { ty::Adt(def, _) if def.did().is_local() => return Ok(()), ty::Error(_) => return Ok(()), _ => {} @@ -86,7 +85,7 @@ fn visit_implementation_of_copy(checker: &Checker<'_>) -> Result<(), ErrorGuaran let impl_did = checker.impl_def_id; debug!("visit_implementation_of_copy: impl_did={:?}", impl_did); - let self_type = impl_header.trait_ref.self_ty(); + let self_type = impl_header.trait_ref.instantiate_identity().self_ty(); debug!("visit_implementation_of_copy: self_type={:?} (bound)", self_type); let param_env = tcx.param_env(impl_did); @@ -120,7 +119,7 @@ fn visit_implementation_of_const_param_ty(checker: &Checker<'_>) -> Result<(), E let tcx = checker.tcx; let header = checker.impl_header; let impl_did = checker.impl_def_id; - let self_type = header.trait_ref.self_ty(); + let self_type = header.trait_ref.instantiate_identity().self_ty(); assert!(!self_type.has_escaping_bound_vars()); let param_env = tcx.param_env(impl_did); @@ -157,9 +156,8 @@ fn visit_implementation_of_coerce_unsized(checker: &Checker<'_>) -> Result<(), E fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> { let tcx = checker.tcx; - let header = checker.impl_header; let impl_did = checker.impl_def_id; - let trait_ref = header.trait_ref; + let trait_ref = checker.impl_header.trait_ref.instantiate_identity(); debug!("visit_implementation_of_dispatch_from_dyn: impl_did={:?}", impl_did); let span = tcx.def_span(impl_did); diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index d6281fa08f745..fc7a73e12be0a 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -134,11 +134,12 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Result<(), ErrorGuaranteed> let mut res = tcx.ensure().specialization_graph_of(def_id); for &impl_def_id in impls { - let trait_header = tcx.impl_trait_header(impl_def_id).unwrap().instantiate_identity(); - let trait_def = tcx.trait_def(trait_header.trait_ref.def_id); + let trait_header = tcx.impl_trait_header(impl_def_id).unwrap(); + let trait_ref = trait_header.trait_ref.instantiate_identity(); + let trait_def = tcx.trait_def(trait_ref.def_id); - res = res.and(check_impl(tcx, impl_def_id, trait_header.trait_ref, trait_def)); - res = res.and(check_object_overlap(tcx, impl_def_id, trait_header.trait_ref)); + res = res.and(check_impl(tcx, impl_def_id, trait_ref, trait_def)); + res = res.and(check_object_overlap(tcx, impl_def_id, trait_ref)); res = res.and(unsafety::check_item(tcx, impl_def_id, trait_header, trait_def)); res = res.and(tcx.ensure().orphan_check_impl(impl_def_id)); diff --git a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs index 53a5ada410560..13ce4f0759377 100644 --- a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs +++ b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs @@ -13,9 +13,10 @@ pub(super) fn check_item( trait_header: ImplTraitHeader<'_>, trait_def: &TraitDef, ) -> Result<(), ErrorGuaranteed> { - let trait_ref = trait_header.trait_ref; let unsafe_attr = tcx.generics_of(def_id).params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle"); + let trait_ref = trait_header.trait_ref.instantiate_identity(); + match (trait_def.unsafety, unsafe_attr, trait_header.unsafety, trait_header.polarity) { (Unsafety::Normal, None, Unsafety::Unsafe, Positive | Reservation) => { let span = tcx.def_span(def_id); diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index b6e2695590c13..10922d534792a 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -20,7 +20,7 @@ use rustc_data_structures::unord::UnordMap; use rustc_errors::{Applicability, Diag, ErrorGuaranteed, StashKey}; use rustc_hir as hir; use rustc_hir::def::DefKind; -use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{GenericParamKind, Node}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; @@ -52,11 +52,6 @@ mod resolve_bound_vars; mod type_of; /////////////////////////////////////////////////////////////////////////// -// Main entry point - -fn collect_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { - tcx.hir().visit_item_likes_in_module(module_def_id, &mut CollectItemTypesVisitor { tcx }); -} pub fn provide(providers: &mut Providers) { resolve_bound_vars::provide(providers); @@ -82,7 +77,6 @@ pub fn provide(providers: &mut Providers) { impl_trait_header, coroutine_kind, coroutine_for_closure, - collect_mod_item_types, is_type_alias_impl_trait, find_field, ..*providers @@ -155,8 +149,8 @@ impl<'v> Visitor<'v> for HirPlaceholderCollector { } } -struct CollectItemTypesVisitor<'tcx> { - tcx: TyCtxt<'tcx>, +pub struct CollectItemTypesVisitor<'tcx> { + pub tcx: TyCtxt<'tcx>, } /// If there are any placeholder types (`_`), emit an error explaining that this is not allowed @@ -791,7 +785,12 @@ fn convert_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) { } fn find_field(tcx: TyCtxt<'_>, (def_id, ident): (DefId, Ident)) -> Option { - tcx.adt_def(def_id).non_enum_variant().fields.iter_enumerated().find_map(|(idx, field)| { + let adt = tcx.adt_def(def_id); + if adt.is_enum() { + return None; + } + + adt.non_enum_variant().fields.iter_enumerated().find_map(|(idx, field)| { if field.is_unnamed() { let field_ty = tcx.type_of(field.did).instantiate_identity(); let adt_def = field_ty.ty_adt_def().expect("expect Adt for unnamed field"); @@ -1514,10 +1513,7 @@ fn suggest_impl_trait<'tcx>( None } -fn impl_trait_header( - tcx: TyCtxt<'_>, - def_id: LocalDefId, -) -> Option>> { +fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option> { let icx = ItemCtxt::new(tcx, def_id); let item = tcx.hir().expect_item(def_id); let impl_ = item.expect_impl(); @@ -1553,11 +1549,11 @@ fn impl_trait_header( } else { icx.astconv().instantiate_mono_trait_ref(ast_trait_ref, selfty) }; - ty::EarlyBinder::bind(ty::ImplTraitHeader { - trait_ref, + ty::ImplTraitHeader { + trait_ref: ty::EarlyBinder::bind(trait_ref), unsafety: impl_.unsafety, polarity: polarity_of_impl(tcx, def_id, impl_, item.span) - }) + } }) } diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 9cc6c16c12639..c86788db988eb 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -14,6 +14,43 @@ use rustc_span::Span; pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { use rustc_hir::*; + // For an RPITIT, synthesize generics which are equal to the opaque's generics + // and parent fn's generics compressed into one list. + if let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, opaque_def_id }) = + tcx.opt_rpitit_info(def_id.to_def_id()) + { + let trait_def_id = tcx.parent(fn_def_id); + let opaque_ty_generics = tcx.generics_of(opaque_def_id); + let opaque_ty_parent_count = opaque_ty_generics.parent_count; + let mut params = opaque_ty_generics.params.clone(); + + let parent_generics = tcx.generics_of(trait_def_id); + let parent_count = parent_generics.parent_count + parent_generics.params.len(); + + let mut trait_fn_params = tcx.generics_of(fn_def_id).params.clone(); + + for param in &mut params { + param.index = param.index + parent_count as u32 + trait_fn_params.len() as u32 + - opaque_ty_parent_count as u32; + } + + trait_fn_params.extend(params); + params = trait_fn_params; + + let param_def_id_to_index = + params.iter().map(|param| (param.def_id, param.index)).collect(); + + return ty::Generics { + parent: Some(trait_def_id), + parent_count, + params, + param_def_id_to_index, + has_self: opaque_ty_generics.has_self, + has_late_bound_regions: opaque_ty_generics.has_late_bound_regions, + host_effect_index: parent_generics.host_effect_index, + }; + } + let hir_id = tcx.local_def_id_to_hir_id(def_id); let node = tcx.hir_node(hir_id); diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index f70bb8c4289f6..2675eacc06e19 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -339,7 +339,7 @@ fn compute_bidirectional_outlives_predicates<'tcx>( predicates: &mut Vec<(ty::Clause<'tcx>, Span)>, ) { for param in opaque_own_params { - let orig_lifetime = tcx.map_rpit_lifetime_to_fn_lifetime(param.def_id.expect_local()); + let orig_lifetime = tcx.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local()); if let ty::ReEarlyParam(..) = *orig_lifetime { let dup_lifetime = ty::Region::new_early_param( tcx, diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index ae01bf845751a..7936621c86829 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -6,9 +6,9 @@ //! the types in HIR to identify late-bound lifetimes and assign their Debruijn indices. This file //! is also responsible for assigning their semantics to implicit lifetimes in trait objects. -use rustc_ast::walk_list; +use core::ops::ControlFlow; +use rustc_ast::visit::walk_list; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; -use rustc_errors::{codes::*, struct_span_code_err}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::LocalDefId; @@ -417,23 +417,18 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { { if let &hir::ClosureBinder::For { span: for_sp, .. } = binder { fn span_of_infer(ty: &hir::Ty<'_>) -> Option { - struct V(Option); - + struct V; impl<'v> Visitor<'v> for V { - fn visit_ty(&mut self, t: &'v hir::Ty<'v>) { - match t.kind { - _ if self.0.is_some() => (), - hir::TyKind::Infer => { - self.0 = Some(t.span); - } - _ => intravisit::walk_ty(self, t), + type Result = ControlFlow; + fn visit_ty(&mut self, t: &'v hir::Ty<'v>) -> Self::Result { + if matches!(t.kind, hir::TyKind::Infer) { + ControlFlow::Break(t.span) + } else { + intravisit::walk_ty(self, t) } } } - - let mut v = V(None); - v.visit_ty(ty); - v.0 + V.visit_ty(ty).break_value() } let infer_in_rt_sp = match fn_decl.output { @@ -514,38 +509,11 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { // These sorts of items have no lifetime parameters at all. intravisit::walk_item(self, item); } - hir::ItemKind::OpaqueTy(hir::OpaqueTy { - origin: hir::OpaqueTyOrigin::TyAlias { .. }, - .. - }) => { - // Opaque types are visited when we visit the - // `TyKind::OpaqueDef`, so that they have the lifetimes from - // their parent opaque_ty in scope. - // - // The core idea here is that since OpaqueTys are generated with the impl Trait as - // their owner, we can keep going until we find the Item that owns that. We then - // conservatively add all resolved lifetimes. Otherwise we run into problems in - // cases like `type Foo<'a> = impl Bar`. - let parent_item = self.tcx.hir().get_parent_item(item.hir_id()); - let resolved_lifetimes: &ResolveBoundVars = - self.tcx.resolve_bound_vars(parent_item); - // We need to add *all* deps, since opaque tys may want them from *us* - for (&owner, defs) in resolved_lifetimes.defs.iter() { - defs.iter().for_each(|(&local_id, region)| { - self.map.defs.insert(hir::HirId { owner, local_id }, *region); - }); - } - for (&owner, late_bound_vars) in resolved_lifetimes.late_bound_vars.iter() { - late_bound_vars.iter().for_each(|(&local_id, late_bound_vars)| { - self.record_late_bound_vars( - hir::HirId { owner, local_id }, - late_bound_vars.clone(), - ); - }); - } - } hir::ItemKind::OpaqueTy(&hir::OpaqueTy { - origin: hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent), + origin: + hir::OpaqueTyOrigin::FnReturn(parent) + | hir::OpaqueTyOrigin::AsyncFn(parent) + | hir::OpaqueTyOrigin::TyAlias { parent, .. }, generics, .. }) => { @@ -683,26 +651,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { // the opaque_ty generics let opaque_ty = self.tcx.hir().item(item_id); match &opaque_ty.kind { - hir::ItemKind::OpaqueTy(hir::OpaqueTy { - origin: hir::OpaqueTyOrigin::TyAlias { .. }, - .. - }) => { - intravisit::walk_ty(self, ty); - - // Elided lifetimes and late-bound lifetimes (from the parent) - // are not allowed in non-return position impl Trait - let scope = Scope::LateBoundary { - s: &Scope::TraitRefBoundary { s: self.scope }, - what: "type alias impl trait", - }; - self.with(scope, |this| intravisit::walk_item(this, opaque_ty)); - - return; - } - hir::ItemKind::OpaqueTy(hir::OpaqueTy { - origin: hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..), - .. - }) => {} + hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin: _, .. }) => {} i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i), }; @@ -719,34 +668,47 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { // and ban them. Type variables instantiated inside binders aren't // well-supported at the moment, so this doesn't work. // In the future, this should be fixed and this error should be removed. - let def = self.map.defs.get(&lifetime.hir_id).cloned(); - let Some(ResolvedArg::LateBound(_, _, def_id)) = def else { continue }; - let Some(def_id) = def_id.as_local() else { continue }; - let hir_id = self.tcx.local_def_id_to_hir_id(def_id); - // Ensure that the parent of the def is an item, not HRTB - let parent_id = self.tcx.parent_hir_id(hir_id); - if !parent_id.is_owner() { - struct_span_code_err!( - self.tcx.dcx(), - lifetime.ident.span, - E0657, - "`impl Trait` can only capture lifetimes bound at the fn or impl level" - ) - .emit(); - self.uninsert_lifetime_on_error(lifetime, def.unwrap()); - } - if let hir::Node::Item(hir::Item { - kind: hir::ItemKind::OpaqueTy { .. }, .. - }) = self.tcx.hir_node(parent_id) + let def = self.map.defs.get(&lifetime.hir_id).copied(); + let Some(ResolvedArg::LateBound(_, _, lifetime_def_id)) = def else { continue }; + let Some(lifetime_def_id) = lifetime_def_id.as_local() else { continue }; + let lifetime_hir_id = self.tcx.local_def_id_to_hir_id(lifetime_def_id); + + let bad_place = match self.tcx.hir_node(self.tcx.parent_hir_id(lifetime_hir_id)) { - self.tcx.dcx().struct_span_err( - lifetime.ident.span, - "higher kinded lifetime bounds on nested opaque types are not supported yet", - ) - .with_span_note(self.tcx.def_span(def_id), "lifetime declared here") - .emit(); - self.uninsert_lifetime_on_error(lifetime, def.unwrap()); - } + // Opaques do not declare their own lifetimes, so if a lifetime comes from an opaque + // it must be a reified late-bound lifetime from a trait goal. + hir::Node::Item(hir::Item { + kind: hir::ItemKind::OpaqueTy { .. }, .. + }) => "higher-ranked lifetime from outer `impl Trait`", + // Other items are fine. + hir::Node::Item(_) | hir::Node::TraitItem(_) | hir::Node::ImplItem(_) => { + continue; + } + hir::Node::Ty(hir::Ty { kind: hir::TyKind::BareFn(_), .. }) => { + "higher-ranked lifetime from function pointer" + } + hir::Node::Ty(hir::Ty { kind: hir::TyKind::TraitObject(..), .. }) => { + "higher-ranked lifetime from `dyn` type" + } + _ => "higher-ranked lifetime", + }; + + let (span, label) = if lifetime.ident.span == self.tcx.def_span(lifetime_def_id) + { + let opaque_span = self.tcx.def_span(item_id.owner_id); + (opaque_span, Some(opaque_span)) + } else { + (lifetime.ident.span, None) + }; + + // Ensure that the parent of the def is an item, not HRTB + self.tcx.dcx().emit_err(errors::OpaqueCapturesHigherRankedLifetime { + span, + label, + decl_span: self.tcx.def_span(lifetime_def_id), + bad_place, + }); + self.uninsert_lifetime_on_error(lifetime, def.unwrap()); } } _ => intravisit::walk_ty(self, ty), @@ -1964,31 +1926,26 @@ fn is_late_bound_map( arg_is_constrained: Box<[bool]>, } - use std::ops::ControlFlow; use ty::Ty; impl<'tcx> TypeVisitor> for ConstrainedCollectorPostAstConv { - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) { match t.kind() { ty::Param(param_ty) => { self.arg_is_constrained[param_ty.index as usize] = true; } - ty::Alias(ty::Projection | ty::Inherent, _) => return ControlFlow::Continue(()), + ty::Alias(ty::Projection | ty::Inherent, _) => return, _ => (), } t.super_visit_with(self) } - fn visit_const(&mut self, _: ty::Const<'tcx>) -> ControlFlow { - ControlFlow::Continue(()) - } + fn visit_const(&mut self, _: ty::Const<'tcx>) {} - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, r: ty::Region<'tcx>) { debug!("r={:?}", r.kind()); if let ty::RegionKind::ReEarlyParam(region) = r.kind() { self.arg_is_constrained[region.index as usize] = true; } - - ControlFlow::Continue(()) } } diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 417f0fceaa81f..a1345c2d81b63 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -1,3 +1,4 @@ +use core::ops::ControlFlow; use rustc_errors::{Applicability, StashKey}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -5,7 +6,7 @@ use rustc_hir::HirId; use rustc_middle::query::plumbing::CyclePlaceholder; use rustc_middle::ty::print::with_forced_trimmed_paths; use rustc_middle::ty::util::IntTypeExt; -use rustc_middle::ty::{self, ImplTraitInTraitData, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::symbol::Ident; use rustc_span::{Span, DUMMY_SP}; @@ -350,22 +351,31 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder { - let assoc_item = tcx.associated_item(def_id); - return map[&assoc_item.trait_item_def_id.unwrap()]; - } - Err(_) => { - return ty::EarlyBinder::bind(Ty::new_error_with_message( - tcx, - DUMMY_SP, - "Could not collect return position impl trait in trait tys", - )); + match tcx.opt_rpitit_info(def_id.to_def_id()) { + Some(ty::ImplTraitInTraitData::Impl { fn_def_id }) => { + match tcx.collect_return_position_impl_trait_in_trait_tys(fn_def_id) { + Ok(map) => { + let assoc_item = tcx.associated_item(def_id); + return map[&assoc_item.trait_item_def_id.unwrap()]; + } + Err(_) => { + return ty::EarlyBinder::bind(Ty::new_error_with_message( + tcx, + DUMMY_SP, + "Could not collect return position impl trait in trait tys", + )); + } } } + // For an RPITIT in a trait, just return the corresponding opaque. + Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => { + return ty::EarlyBinder::bind(Ty::new_opaque( + tcx, + opaque_def_id, + ty::GenericArgs::identity_for_item(tcx, opaque_def_id), + )); + } + None => {} } let hir_id = tcx.local_def_id_to_hir_id(def_id); @@ -544,11 +554,11 @@ pub(super) fn type_of_opaque( Ok(ty::EarlyBinder::bind(match tcx.hir_node_by_def_id(def_id) { Node::Item(item) => match item.kind { ItemKind::OpaqueTy(OpaqueTy { - origin: hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: false }, + origin: hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: false, .. }, .. }) => opaque::find_opaque_ty_constraints_for_tait(tcx, def_id), ItemKind::OpaqueTy(OpaqueTy { - origin: hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: true }, + origin: hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: true, .. }, .. }) => opaque::find_opaque_ty_constraints_for_impl_trait_in_assoc_type(tcx, def_id), // Opaque types desugared from `impl Trait`. @@ -666,19 +676,16 @@ pub fn type_alias_is_lazy<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool { if tcx.features().lazy_type_alias { return true; } - struct HasTait { - has_type_alias_impl_trait: bool, - } + struct HasTait; impl<'tcx> Visitor<'tcx> for HasTait { - fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) { + type Result = ControlFlow<()>; + fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) -> Self::Result { if let hir::TyKind::OpaqueDef(..) = t.kind { - self.has_type_alias_impl_trait = true; + ControlFlow::Break(()) } else { - hir::intravisit::walk_ty(self, t); + hir::intravisit::walk_ty(self, t) } } } - let mut has_tait = HasTait { has_type_alias_impl_trait: false }; - has_tait.visit_ty(tcx.hir().expect_item(def_id).expect_ty_alias().0); - has_tait.has_type_alias_impl_trait + HasTait.visit_ty(tcx.hir().expect_item(def_id).expect_ty_alias().0).is_break() } diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs index f0e998b7a0032..dcb01a117b047 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs @@ -46,9 +46,7 @@ pub(super) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type( for &assoc_id in tcx.associated_item_def_ids(impl_def_id) { let assoc = tcx.associated_item(assoc_id); match assoc.kind { - ty::AssocKind::Const | ty::AssocKind::Fn => { - locator.check(assoc_id.expect_local(), ImplTraitSource::AssocTy) - } + ty::AssocKind::Const | ty::AssocKind::Fn => locator.check(assoc_id.expect_local()), // Associated types don't have bodies, so they can't constrain hidden types ty::AssocKind::Type => {} } @@ -182,15 +180,9 @@ struct TaitConstraintLocator<'tcx> { typeck_types: Vec>, } -#[derive(Debug)] -enum ImplTraitSource { - AssocTy, - TyAlias, -} - impl TaitConstraintLocator<'_> { #[instrument(skip(self), level = "debug")] - fn check(&mut self, item_def_id: LocalDefId, source: ImplTraitSource) { + fn check(&mut self, item_def_id: LocalDefId) { // Don't try to check items that cannot possibly constrain the type. if !self.tcx.has_typeck_results(item_def_id) { debug!("no constraint: no typeck results"); @@ -242,12 +234,8 @@ impl TaitConstraintLocator<'_> { continue; } constrained = true; - let opaque_types_defined_by = match source { - ImplTraitSource::AssocTy => { - self.tcx.impl_trait_in_assoc_types_defined_by(item_def_id) - } - ImplTraitSource::TyAlias => self.tcx.opaque_types_defined_by(item_def_id), - }; + let opaque_types_defined_by = self.tcx.opaque_types_defined_by(item_def_id); + if !opaque_types_defined_by.contains(&self.def_id) { self.tcx.dcx().emit_err(TaitForwardCompat { span: hidden_type.span, @@ -308,7 +296,7 @@ impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> { } fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) { if let hir::ExprKind::Closure(closure) = ex.kind { - self.check(closure.def_id, ImplTraitSource::TyAlias); + self.check(closure.def_id); } intravisit::walk_expr(self, ex); } @@ -316,7 +304,7 @@ impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> { trace!(?it.owner_id); // The opaque type itself or its children are not within its reveal scope. if it.owner_id.def_id != self.def_id { - self.check(it.owner_id.def_id, ImplTraitSource::TyAlias); + self.check(it.owner_id.def_id); intravisit::walk_item(self, it); } } @@ -324,13 +312,13 @@ impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> { trace!(?it.owner_id); // The opaque type itself or its children are not within its reveal scope. if it.owner_id.def_id != self.def_id { - self.check(it.owner_id.def_id, ImplTraitSource::TyAlias); + self.check(it.owner_id.def_id); intravisit::walk_impl_item(self, it); } } fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) { trace!(?it.owner_id); - self.check(it.owner_id.def_id, ImplTraitSource::TyAlias); + self.check(it.owner_id.def_id); intravisit::walk_trait_item(self, it); } fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem<'tcx>) { diff --git a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs index b8de2e46934dd..3b8bb0731fbd8 100644 --- a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs +++ b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs @@ -1,9 +1,8 @@ use rustc_data_structures::fx::FxHashSet; -use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; +use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitor}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::Span; use rustc_type_ir::fold::TypeFoldable; -use std::ops::ControlFlow; #[derive(Clone, PartialEq, Eq, Hash, Debug)] pub struct Parameter(pub u32); @@ -61,13 +60,13 @@ struct ParameterCollector { } impl<'tcx> TypeVisitor> for ParameterCollector { - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) { match *t.kind() { // Projections are not injective in general. ty::Alias(ty::Projection | ty::Inherent | ty::Opaque, _) if !self.include_nonconstraining => { - return ControlFlow::Continue(()); + return; } // All weak alias types should've been expanded beforehand. ty::Alias(ty::Weak, _) if !self.include_nonconstraining => { @@ -80,18 +79,17 @@ impl<'tcx> TypeVisitor> for ParameterCollector { t.super_visit_with(self) } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, r: ty::Region<'tcx>) { if let ty::ReEarlyParam(data) = *r { self.parameters.push(Parameter::from(data)); } - ControlFlow::Continue(()) } - fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, c: ty::Const<'tcx>) { match c.kind() { ty::ConstKind::Unevaluated(..) if !self.include_nonconstraining => { // Constant expressions are not injective in general. - return c.ty().visit_with(self); + return; } ty::ConstKind::Param(data) => { self.parameters.push(Parameter::from(data)); diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 5330260fbf513..26349cd1c6551 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1607,3 +1607,15 @@ pub struct UnnamedFieldsReprFieldDefined { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(hir_analysis_opaque_captures_higher_ranked_lifetime, code = E0657)] +pub struct OpaqueCapturesHigherRankedLifetime { + #[primary_span] + pub span: Span, + #[label] + pub label: Option, + #[note] + pub decl_span: Span, + pub bad_place: &'static str, +} diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs index 9d7866fe3e0cb..caa85092415b9 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs @@ -14,8 +14,7 @@ use min_specialization::check_min_specialization; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{codes::*, struct_span_code_err}; use rustc_hir::def::DefKind; -use rustc_hir::def_id::{LocalDefId, LocalModDefId}; -use rustc_middle::query::Providers; +use rustc_hir::def_id::LocalDefId; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; use rustc_span::{ErrorGuaranteed, Span, Symbol}; @@ -51,23 +50,16 @@ mod min_specialization; /// impl<'a> Trait for Bar { type X = &'a i32; } /// // ^ 'a is unused and appears in assoc type, error /// ``` -fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) -> Result<(), ErrorGuaranteed> { +pub fn check_impl_wf(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) -> Result<(), ErrorGuaranteed> { let min_specialization = tcx.features().min_specialization; - let module = tcx.hir_module_items(module_def_id); let mut res = Ok(()); - for id in module.items() { - if matches!(tcx.def_kind(id.owner_id), DefKind::Impl { .. }) { - res = res.and(enforce_impl_params_are_constrained(tcx, id.owner_id.def_id)); - if min_specialization { - res = res.and(check_min_specialization(tcx, id.owner_id.def_id)); - } - } + debug_assert!(matches!(tcx.def_kind(impl_def_id), DefKind::Impl { .. })); + res = res.and(enforce_impl_params_are_constrained(tcx, impl_def_id)); + if min_specialization { + res = res.and(check_min_specialization(tcx, impl_def_id)); } - res -} -pub fn provide(providers: &mut Providers) { - *providers = Providers { check_mod_impl_wf, ..*providers }; + res } fn enforce_impl_params_are_constrained( diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 7cb103626da77..e056c0e84cf42 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -153,27 +153,20 @@ pub fn provide(providers: &mut Providers) { check_unused::provide(providers); variance::provide(providers); outlives::provide(providers); - impl_wf_check::provide(providers); hir_wf_check::provide(providers); } pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { let _prof_timer = tcx.sess.timer("type_check_crate"); - // this ensures that later parts of type checking can assume that items - // have valid types and not error - tcx.sess.time("type_collecting", || { - tcx.hir().for_each_module(|module| tcx.ensure().collect_mod_item_types(module)) - }); - if tcx.features().rustc_attrs { tcx.sess.time("outlives_testing", || outlives::test::test_inferred_outlives(tcx))?; } tcx.sess.time("coherence_checking", || { - // Check impls constrain their parameters - let res = - tcx.hir().try_par_for_each_module(|module| tcx.ensure().check_mod_impl_wf(module)); + tcx.hir().par_for_each_module(|module| { + let _ = tcx.ensure().check_mod_type_wf(module); + }); for &trait_def_id in tcx.all_local_trait_impls(()).keys() { let _ = tcx.ensure().coherent_trait(trait_def_id); @@ -181,19 +174,12 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { // these queries are executed for side-effects (error reporting): let _ = tcx.ensure().crate_inherent_impls(()); let _ = tcx.ensure().crate_inherent_impls_overlap_check(()); - res - })?; + }); if tcx.features().rustc_attrs { tcx.sess.time("variance_testing", || variance::test::test_variance(tcx))?; } - tcx.sess.time("wf_checking", || { - tcx.hir().par_for_each_module(|module| { - let _ = tcx.ensure().check_mod_type_wf(module); - }) - }); - if tcx.features().rustc_attrs { collect::test_opaque_hidden_types(tcx)?; } diff --git a/compiler/rustc_hir_analysis/src/structured_errors.rs b/compiler/rustc_hir_analysis/src/structured_errors.rs index 9064ba8693ef5..5abfd25dd95df 100644 --- a/compiler/rustc_hir_analysis/src/structured_errors.rs +++ b/compiler/rustc_hir_analysis/src/structured_errors.rs @@ -9,7 +9,7 @@ pub use self::{ use rustc_errors::{Diag, ErrCode}; use rustc_session::Session; -pub trait StructuredDiagnostic<'tcx> { +pub trait StructuredDiag<'tcx> { fn session(&self) -> &Session; fn code(&self) -> ErrCode; diff --git a/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs b/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs index 921cf37155a2e..0e78acbeae2d4 100644 --- a/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs +++ b/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs @@ -1,4 +1,4 @@ -use crate::{errors, structured_errors::StructuredDiagnostic}; +use crate::{errors, structured_errors::StructuredDiag}; use rustc_errors::{codes::*, Diag}; use rustc_middle::ty::{Ty, TypeVisitableExt}; use rustc_session::Session; @@ -11,7 +11,7 @@ pub struct MissingCastForVariadicArg<'tcx, 's> { pub cast_ty: &'s str, } -impl<'tcx> StructuredDiagnostic<'tcx> for MissingCastForVariadicArg<'tcx, '_> { +impl<'tcx> StructuredDiag<'tcx> for MissingCastForVariadicArg<'tcx, '_> { fn session(&self) -> &Session { self.sess } diff --git a/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs b/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs index 1af5e6a9dfc4b..9e871ff9af01b 100644 --- a/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs +++ b/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs @@ -1,4 +1,4 @@ -use crate::{errors, structured_errors::StructuredDiagnostic}; +use crate::{errors, structured_errors::StructuredDiag}; use rustc_errors::{codes::*, Diag}; use rustc_middle::ty::{Ty, TypeVisitableExt}; use rustc_session::Session; @@ -11,7 +11,7 @@ pub struct SizedUnsizedCast<'tcx> { pub cast_ty: String, } -impl<'tcx> StructuredDiagnostic<'tcx> for SizedUnsizedCast<'tcx> { +impl<'tcx> StructuredDiag<'tcx> for SizedUnsizedCast<'tcx> { fn session(&self) -> &Session { self.sess } diff --git a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs index 6f4695ec92005..0f5ba26337a15 100644 --- a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs +++ b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs @@ -1,4 +1,4 @@ -use crate::structured_errors::StructuredDiagnostic; +use crate::structured_errors::StructuredDiag; use rustc_errors::{codes::*, pluralize, Applicability, Diag, MultiSpan}; use rustc_hir as hir; use rustc_middle::ty::{self as ty, AssocItems, AssocKind, TyCtxt}; @@ -1097,7 +1097,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { } } -impl<'tcx> StructuredDiagnostic<'tcx> for WrongNumberOfGenericArgs<'_, 'tcx> { +impl<'tcx> StructuredDiag<'tcx> for WrongNumberOfGenericArgs<'_, 'tcx> { fn session(&self) -> &Session { self.tcx.sess } diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index 4d5dcbadc4a24..42885b0c83282 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -10,7 +10,6 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::query::Providers; use rustc_middle::ty::{self, CrateVariancesMap, GenericArgsRef, Ty, TyCtxt}; use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable}; -use std::ops::ControlFlow; /// Defines the `TermsContext` basically houses an arena where we can /// allocate terms. @@ -89,15 +88,14 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc impl<'tcx> OpaqueTypeLifetimeCollector<'tcx> { #[instrument(level = "trace", skip(self), ret)] - fn visit_opaque(&mut self, def_id: DefId, args: GenericArgsRef<'tcx>) -> ControlFlow { + fn visit_opaque(&mut self, def_id: DefId, args: GenericArgsRef<'tcx>) { if def_id != self.root_def_id && self.tcx.is_descendant_of(def_id, self.root_def_id) { let child_variances = self.tcx.variances_of(def_id); for (a, v) in args.iter().zip_eq(child_variances) { if *v != ty::Bivariant { - a.visit_with(self)?; + a.visit_with(self); } } - ControlFlow::Continue(()) } else { args.visit_with(self) } @@ -106,20 +104,19 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc impl<'tcx> ty::TypeVisitor> for OpaqueTypeLifetimeCollector<'tcx> { #[instrument(level = "trace", skip(self), ret)] - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, r: ty::Region<'tcx>) { if let ty::RegionKind::ReEarlyParam(ebr) = r.kind() { self.variances[ebr.index as usize] = ty::Invariant; } - ControlFlow::Continue(()) } #[instrument(level = "trace", skip(self), ret)] - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) { match t.kind() { ty::Alias(_, ty::AliasTy { def_id, args, .. }) if matches!(self.tcx.def_kind(*def_id), DefKind::OpaqueTy) => { - self.visit_opaque(*def_id, args) + self.visit_opaque(*def_id, args); } _ => t.super_visit_with(self), } @@ -128,15 +125,7 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc // By default, RPIT are invariant wrt type and const generics, but they are bivariant wrt // lifetime generics. - let variances = std::iter::repeat(ty::Invariant).take(generics.count()); - - let mut variances: Vec<_> = match tcx.opaque_type_origin(item_def_id) { - rustc_hir::OpaqueTyOrigin::FnReturn(_) | rustc_hir::OpaqueTyOrigin::AsyncFn(_) => { - variances.collect() - } - // But TAIT are invariant for all generics - rustc_hir::OpaqueTyOrigin::TyAlias { .. } => return tcx.arena.alloc_from_iter(variances), - }; + let mut variances = vec![ty::Invariant; generics.count()]; // Mark all lifetimes from parent generics as unused (Bivariant). // This will be overridden later if required. diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 8f8f747339b42..b5bb063c5ed8c 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1265,6 +1265,10 @@ impl<'a> State<'a> { s.space(); s.print_qpath(path, true); } + hir::InlineAsmOperand::Label { block } => { + s.head("label"); + s.print_block(block); + } }, AsmArg::Options(opts) => { s.word("options"); diff --git a/compiler/rustc_hir_typeck/Cargo.toml b/compiler/rustc_hir_typeck/Cargo.toml index 975f93756427e..0a5fa37ed04fa 100644 --- a/compiler/rustc_hir_typeck/Cargo.toml +++ b/compiler/rustc_hir_typeck/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" # tidy-alphabetical-start itertools = "0.11" rustc_ast = { path = "../rustc_ast" } +rustc_ast_ir = { path = "../rustc_ast_ir" } rustc_attr = { path = "../rustc_attr" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index b87d71e353389..25d3453137988 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -545,7 +545,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(def_id) = def_id && self.tcx.def_kind(def_id) == hir::def::DefKind::Fn - && matches!(self.tcx.intrinsic(def_id), Some(sym::const_eval_select)) + && self.tcx.is_intrinsic(def_id, sym::const_eval_select) { let fn_sig = self.resolve_vars_if_possible(fn_sig); for idx in 0..=1 { diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 84d042da138f8..b8d1eaee81260 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -483,9 +483,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { err.emit(); } CastError::SizedUnsizedCast => { - use rustc_hir_analysis::structured_errors::{ - SizedUnsizedCast, StructuredDiagnostic, - }; + use rustc_hir_analysis::structured_errors::{SizedUnsizedCast, StructuredDiag}; SizedUnsizedCast { sess: fcx.tcx.sess, diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 5bdd9412d0e51..1ff961a90890c 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -56,18 +56,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // It's always helpful for inference if we know the kind of // closure sooner rather than later, so first examine the expected // type, and see if can glean a closure kind from there. - let (expected_sig, expected_kind) = match closure.kind { - hir::ClosureKind::Closure => match expected.to_option(self) { - Some(ty) => { - self.deduce_closure_signature(self.try_structurally_resolve_type(expr_span, ty)) - } - None => (None, None), - }, - // We don't want to deduce a signature from `Fn` bounds for coroutines - // or coroutine-closures, because the former does not implement `Fn` - // ever, and the latter's signature doesn't correspond to the coroutine - // type that it returns. - hir::ClosureKind::Coroutine(_) | hir::ClosureKind::CoroutineClosure(_) => (None, None), + let (expected_sig, expected_kind) = match expected.to_option(self) { + Some(ty) => self.deduce_closure_signature( + self.try_structurally_resolve_type(expr_span, ty), + closure.kind, + ), + None => (None, None), }; let ClosureSignatures { bound_sig, mut liberated_sig } = @@ -323,11 +317,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn deduce_closure_signature( &self, expected_ty: Ty<'tcx>, + closure_kind: hir::ClosureKind, ) -> (Option>, Option) { match *expected_ty.kind() { ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => self .deduce_closure_signature_from_predicates( expected_ty, + closure_kind, self.tcx .explicit_item_bounds(def_id) .iter_instantiated_copied(self.tcx, args) @@ -336,7 +332,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Dynamic(object_type, ..) => { let sig = object_type.projection_bounds().find_map(|pb| { let pb = pb.with_self_ty(self.tcx, self.tcx.types.trait_object_dummy_self); - self.deduce_sig_from_projection(None, pb) + self.deduce_sig_from_projection(None, closure_kind, pb) }); let kind = object_type .principal_def_id() @@ -345,12 +341,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } ty::Infer(ty::TyVar(vid)) => self.deduce_closure_signature_from_predicates( Ty::new_var(self.tcx, self.root_var(vid)), + closure_kind, self.obligations_for_self_ty(vid).map(|obl| (obl.predicate, obl.cause.span)), ), - ty::FnPtr(sig) => { - let expected_sig = ExpectedSig { cause_span: None, sig }; - (Some(expected_sig), Some(ty::ClosureKind::Fn)) - } + ty::FnPtr(sig) => match closure_kind { + hir::ClosureKind::Closure => { + let expected_sig = ExpectedSig { cause_span: None, sig }; + (Some(expected_sig), Some(ty::ClosureKind::Fn)) + } + hir::ClosureKind::Coroutine(_) | hir::ClosureKind::CoroutineClosure(_) => { + (None, None) + } + }, _ => (None, None), } } @@ -358,6 +360,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn deduce_closure_signature_from_predicates( &self, expected_ty: Ty<'tcx>, + closure_kind: hir::ClosureKind, predicates: impl DoubleEndedIterator, Span)>, ) -> (Option>, Option) { let mut expected_sig = None; @@ -386,6 +389,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span, self.deduce_sig_from_projection( Some(span), + closure_kind, bound_predicate.rebind(proj_predicate), ), ); @@ -396,9 +400,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected_ty: Ty<'tcx>, } impl<'tcx> TypeVisitor> for MentionsTy<'tcx> { - type BreakTy = (); + type Result = ControlFlow<()>; - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { if t == self.expected_ty { ControlFlow::Break(()) } else { @@ -422,13 +426,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => Some(data.def_id()), _ => None, }; - if let Some(closure_kind) = - trait_def_id.and_then(|def_id| self.tcx.fn_trait_kind_from_def_id(def_id)) - { - expected_kind = Some( - expected_kind - .map_or_else(|| closure_kind, |current| cmp::min(current, closure_kind)), - ); + + if let Some(trait_def_id) = trait_def_id { + let found_kind = match closure_kind { + hir::ClosureKind::Closure => self.tcx.fn_trait_kind_from_def_id(trait_def_id), + hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Async) => { + self.tcx.async_fn_trait_kind_from_def_id(trait_def_id) + } + _ => None, + }; + + if let Some(found_kind) = found_kind { + expected_kind = Some( + expected_kind + .map_or_else(|| found_kind, |current| cmp::min(current, found_kind)), + ); + } } } @@ -445,14 +458,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn deduce_sig_from_projection( &self, cause_span: Option, + closure_kind: hir::ClosureKind, projection: ty::PolyProjectionPredicate<'tcx>, ) -> Option> { let tcx = self.tcx; let trait_def_id = projection.trait_def_id(tcx); - // For now, we only do signature deduction based off of the `Fn` traits. - if !tcx.is_fn_trait(trait_def_id) { - return None; + + // For now, we only do signature deduction based off of the `Fn` and `AsyncFn` traits, + // for closures and async closures, respectively. + match closure_kind { + hir::ClosureKind::Closure + if self.tcx.fn_trait_kind_from_def_id(trait_def_id).is_some() => {} + hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Async) + if self.tcx.async_fn_trait_kind_from_def_id(trait_def_id).is_some() => {} + _ => return None, } let arg_param_ty = projection.skip_binder().projection_ty.args.type_at(1); diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 1d324f128f230..502b9ba6451d3 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -4,7 +4,7 @@ use std::borrow::Cow; use crate::fluent_generated as fluent; use rustc_errors::{ codes::*, AddToDiagnostic, Applicability, Diag, DiagArgValue, EmissionGuarantee, - IntoDiagnosticArg, MultiSpan, SubdiagnosticMessageOp, + IntoDiagnosticArg, MultiSpan, SubdiagMessageOp, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::Ty; @@ -195,7 +195,7 @@ pub struct TypeMismatchFruTypo { } impl AddToDiagnostic for TypeMismatchFruTypo { - fn add_to_diagnostic_with>( + fn add_to_diagnostic_with>( self, diag: &mut Diag<'_, G>, _f: F, @@ -374,7 +374,7 @@ pub struct RemoveSemiForCoerce { } impl AddToDiagnostic for RemoveSemiForCoerce { - fn add_to_diagnostic_with>( + fn add_to_diagnostic_with>( self, diag: &mut Diag<'_, G>, _f: F, @@ -550,7 +550,7 @@ pub enum CastUnknownPointerSub { } impl rustc_errors::AddToDiagnostic for CastUnknownPointerSub { - fn add_to_diagnostic_with>( + fn add_to_diagnostic_with>( self, diag: &mut Diag<'_, G>, f: F, diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index b8cceebe1036e..ceaae9cf49f28 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -390,7 +390,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); let sp = tcx.sess.source_map().start_point(expr.span).with_parent(None); if let Some(sp) = - tcx.sess.parse_sess.ambiguous_block_expr_parse.borrow().get(&sp) + tcx.sess.psess.ambiguous_block_expr_parse.borrow().get(&sp) { err.subdiagnostic(self.dcx(), ExprParenthesesNeeded::surrounding(*sp)); } @@ -3232,6 +3232,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } fn check_expr_asm(&self, asm: &'tcx hir::InlineAsm<'tcx>) -> Ty<'tcx> { + let mut diverge = asm.options.contains(ast::InlineAsmOptions::NORETURN); + for (op, _op_sp) in asm.operands { match op { hir::InlineAsmOperand::In { expr, .. } => { @@ -3253,13 +3255,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // be well-formed. hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::SymFn { .. } => {} hir::InlineAsmOperand::SymStatic { .. } => {} + hir::InlineAsmOperand::Label { block } => { + let previous_diverges = self.diverges.get(); + + // The label blocks should have unit return value or diverge. + let ty = + self.check_block_with_expected(block, ExpectHasType(self.tcx.types.unit)); + if !ty.is_never() { + self.demand_suptype(block.span, self.tcx.types.unit, ty); + diverge = false; + } + + // We need this to avoid false unreachable warning when a label diverges. + self.diverges.set(previous_diverges); + } } } - if asm.options.contains(ast::InlineAsmOptions::NORETURN) { - self.tcx.types.never - } else { - Ty::new_unit(self.tcx) - } + + if diverge { self.tcx.types.never } else { self.tcx.types.unit } } fn check_offset_of( diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 04fb7bcf4f3b4..ba0383d19b92a 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -293,6 +293,9 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { | hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::SymFn { .. } | hir::InlineAsmOperand::SymStatic { .. } => {} + hir::InlineAsmOperand::Label { block } => { + self.walk_block(block); + } } } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs index f0631dd4b5fb8..a9a5a89a41363 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs @@ -337,8 +337,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Option> { struct FindAmbiguousParameter<'a, 'tcx>(&'a FnCtxt<'a, 'tcx>, DefId); impl<'tcx> TypeVisitor> for FindAmbiguousParameter<'_, 'tcx> { - type BreakTy = ty::GenericArg<'tcx>; - fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow { + type Result = ControlFlow>; + fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { if let Some(origin) = self.0.type_var_origin(ty) && let TypeVariableOriginKind::TypeParameterDefinition(_, def_id) = origin.kind && let generics = self.0.tcx.generics_of(self.1) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index fc674520295fe..a08582a67d94c 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -27,7 +27,7 @@ use rustc_hir::{ExprKind, Node, QPath}; use rustc_hir_analysis::astconv::AstConv; use rustc_hir_analysis::check::intrinsicck::InlineAsmCtxt; use rustc_hir_analysis::check::potentially_plural_count; -use rustc_hir_analysis::structured_errors::StructuredDiagnostic; +use rustc_hir_analysis::structured_errors::StructuredDiag; use rustc_index::IndexVec; use rustc_infer::infer::error_reporting::{FailureCode, ObligationCauseExt}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 809102557acaa..5a1c7b0561185 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1117,7 +1117,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &hir::Expr<'_>, ) -> bool { let sp = self.tcx.sess.source_map().start_point(expr.span).with_parent(None); - if let Some(sp) = self.tcx.sess.parse_sess.ambiguous_block_expr_parse.borrow().get(&sp) { + if let Some(sp) = self.tcx.sess.psess.ambiguous_block_expr_parse.borrow().get(&sp) { // `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }` err.subdiagnostic(self.dcx(), ExprParenthesesNeeded::surrounding(*sp)); true diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 70ddd6b2f4cf5..d86b4912c89bd 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -61,7 +61,7 @@ use rustc_hir::{HirIdMap, Node}; use rustc_hir_analysis::astconv::AstConv; use rustc_hir_analysis::check::check_abi; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_infer::traits::ObligationInspector; +use rustc_infer::traits::{ObligationCauseCode, ObligationInspector, WellFormedLoc}; use rustc_middle::query::Providers; use rustc_middle::traits; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -253,6 +253,10 @@ fn typeck_with_fallback<'tcx>( let expected_type = expected_type.unwrap_or_else(fallback); let expected_type = fcx.normalize(body.value.span, expected_type); + + let wf_code = ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(def_id))); + fcx.register_wf_obligation(expected_type.into(), body.value.span, wf_code); + fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized); // Gather locals in statics (because of block expressions). diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index 441558da60ac3..3b26a791f6577 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -11,7 +11,7 @@ pub use self::suggest::SelfSource; pub use self::MethodError::*; use crate::FnCtxt; -use rustc_errors::{Applicability, Diag, SubdiagnosticMessage}; +use rustc_errors::{Applicability, Diag, SubdiagMessage}; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Namespace}; use rustc_hir::def_id::DefId; @@ -127,7 +127,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(crate) fn suggest_method_call( &self, err: &mut Diag<'_>, - msg: impl Into + std::fmt::Debug, + msg: impl Into + std::fmt::Debug, method_name: Ident, self_ty: Ty<'tcx>, call_expr: &hir::Expr<'tcx>, diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 440d0ad1140c4..4c413e4d1c6a5 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -6,6 +6,7 @@ use crate::errors::{self, CandidateTraitNote, NoAssociatedItem}; use crate::Expectation; use crate::FnCtxt; +use core::ops::ControlFlow; use rustc_ast::ast::Mutability; use rustc_attr::parse_confusables; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; @@ -166,7 +167,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return false; } - match ty.kind() { + match ty.peel_refs().kind() { ty::Param(param) => { let generics = self.tcx.generics_of(self.body_id); let generic_param = generics.type_param(¶m, self.tcx); @@ -184,7 +185,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - ty::Alias(ty::AliasKind::Opaque, _) => { + ty::Slice(..) | ty::Adt(..) | ty::Alias(ty::AliasKind::Opaque, _) => { for unsatisfied in unsatisfied_predicates.iter() { if is_iterator_predicate(unsatisfied.0, self.tcx) { return true; @@ -2212,30 +2213,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let map = self.infcx.tcx.hir(); let body_id = self.tcx.hir().body_owned_by(self.body_id); let body = map.body(body_id); - struct LetVisitor<'a> { - result: Option<&'a hir::Expr<'a>>, + struct LetVisitor { ident_name: Symbol, } // FIXME: This really should be taking scoping, etc into account. - impl<'v> Visitor<'v> for LetVisitor<'v> { - fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) { - if let hir::StmtKind::Local(hir::Local { pat, init, .. }) = &ex.kind + impl<'v> Visitor<'v> for LetVisitor { + type Result = ControlFlow>>; + fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) -> Self::Result { + if let hir::StmtKind::Local(&hir::Local { pat, init, .. }) = ex.kind && let Binding(_, _, ident, ..) = pat.kind && ident.name == self.ident_name { - self.result = *init; + ControlFlow::Break(init) } else { - hir::intravisit::walk_stmt(self, ex); + hir::intravisit::walk_stmt(self, ex) } } } - let mut visitor = LetVisitor { result: None, ident_name: seg1.ident.name }; - visitor.visit_body(body); - if let Node::Expr(call_expr) = self.tcx.parent_hir_node(seg1.hir_id) - && let Some(expr) = visitor.result + && let ControlFlow::Break(Some(expr)) = + (LetVisitor { ident_name: seg1.ident.name }).visit_body(body) && let Some(self_ty) = self.node_ty_opt(expr.hir_id) { let probe = self.lookup_probe_for_diagnostic( @@ -3368,11 +3367,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "inherent impls can't be candidates, only trait impls can be", ) }) - .filter(|header| { - header.skip_binder().polarity == ty::ImplPolarity::Negative - }) + .filter(|header| header.polarity == ty::ImplPolarity::Negative) .any(|header| { - let imp = header.instantiate_identity().trait_ref; + let imp = header.trait_ref.instantiate_identity(); let imp_simp = simplify_type(self.tcx, imp.self_ty(), TreatParams::ForLookup); imp_simp.is_some_and(|s| s == simp_rcvr_ty) diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index 9c9507d58522f..79f574aa7fdc4 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -818,7 +818,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let sp = self.tcx.sess.source_map().start_point(ex.span).with_parent(None); if let Some(sp) = - self.tcx.sess.parse_sess.ambiguous_block_expr_parse.borrow().get(&sp) + self.tcx.sess.psess.ambiguous_block_expr_parse.borrow().get(&sp) { // If the previous expression was a block expression, suggest parentheses // (turning this into a binary subtraction operation instead.) diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs index 8311a7351333d..24512dea93999 100644 --- a/compiler/rustc_incremental/src/persist/dirty_clean.rs +++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs @@ -395,7 +395,7 @@ impl<'tcx> DirtyCleanVisitor<'tcx> { /// a cfg flag called `foo`. fn check_config(tcx: TyCtxt<'_>, attr: &Attribute) -> bool { debug!("check_config(attr={:?})", attr); - let config = &tcx.sess.parse_sess.config; + let config = &tcx.sess.psess.config; debug!("check_config: config={:?}", config); let mut cfg = None; for item in attr.meta_item_list().unwrap_or_else(ThinVec::new) { diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs index d876174e620f4..88298150a79dc 100644 --- a/compiler/rustc_index/src/vec.rs +++ b/compiler/rustc_index/src/vec.rs @@ -12,7 +12,24 @@ use std::vec; use crate::{Idx, IndexSlice}; /// An owned contiguous collection of `T`s, indexed by `I` rather than by `usize`. -/// Its purpose is to avoid mixing indexes. +/// +/// ## Why use this instead of a `Vec`? +/// +/// An `IndexVec` allows element access only via a specific associated index type, meaning that +/// trying to use the wrong index type (possibly accessing an invalid element) will fail at +/// compile time. +/// +/// It also documents what the index is indexing: in a `HashMap` it's not +/// immediately clear what the `usize` means, while a `HashMap` makes it obvious. +/// +/// ```compile_fail +/// use rustc_index::{Idx, IndexVec}; +/// +/// fn f(vec1: IndexVec, idx1: I1, idx2: I2) { +/// &vec1[idx1]; // Ok +/// &vec1[idx2]; // Compile error! +/// } +/// ``` /// /// While it's possible to use `u32` or `usize` directly for `I`, /// you almost certainly want to use a [`newtype_index!`]-generated type instead. diff --git a/compiler/rustc_infer/Cargo.toml b/compiler/rustc_infer/Cargo.toml index 73a02a431dfc0..c1565a7d40fd5 100644 --- a/compiler/rustc_infer/Cargo.toml +++ b/compiler/rustc_infer/Cargo.toml @@ -8,6 +8,7 @@ doctest = false [dependencies] # tidy-alphabetical-start +rustc_ast_ir = { path = "../rustc_ast_ir" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_fluent_macro = { path = "../rustc_fluent_macro" } diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index cecc52c8326ef..af09ac2de960c 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -1,7 +1,7 @@ use hir::GenericParamKind; use rustc_errors::{ - codes::*, AddToDiagnostic, Applicability, Diag, DiagStyledString, DiagnosticMessage, - EmissionGuarantee, IntoDiagnosticArg, MultiSpan, SubdiagnosticMessageOp, + codes::*, AddToDiagnostic, Applicability, Diag, DiagMessage, DiagStyledString, + EmissionGuarantee, IntoDiagnosticArg, MultiSpan, SubdiagMessageOp, }; use rustc_hir as hir; use rustc_hir::FnRetTy; @@ -209,11 +209,11 @@ impl<'a> SourceKindMultiSuggestion<'a> { pub enum RegionOriginNote<'a> { Plain { span: Span, - msg: DiagnosticMessage, + msg: DiagMessage, }, WithName { span: Span, - msg: DiagnosticMessage, + msg: DiagMessage, name: &'a str, continues: bool, }, @@ -225,12 +225,12 @@ pub enum RegionOriginNote<'a> { } impl AddToDiagnostic for RegionOriginNote<'_> { - fn add_to_diagnostic_with>( + fn add_to_diagnostic_with>( self, diag: &mut Diag<'_, G>, _f: F, ) { - let mut label_or_note = |span, msg: DiagnosticMessage| { + let mut label_or_note = |span, msg: DiagMessage| { let sub_count = diag.children.iter().filter(|d| d.span.is_dummy()).count(); let expanded_sub_count = diag.children.iter().filter(|d| !d.span.is_dummy()).count(); let span_is_primary = diag.span.primary_spans().iter().all(|&sp| sp == span); @@ -290,7 +290,7 @@ pub enum LifetimeMismatchLabels { } impl AddToDiagnostic for LifetimeMismatchLabels { - fn add_to_diagnostic_with>( + fn add_to_diagnostic_with>( self, diag: &mut Diag<'_, G>, _f: F, @@ -338,7 +338,7 @@ pub struct AddLifetimeParamsSuggestion<'a> { } impl AddToDiagnostic for AddLifetimeParamsSuggestion<'_> { - fn add_to_diagnostic_with>( + fn add_to_diagnostic_with>( self, diag: &mut Diag<'_, G>, _f: F, @@ -440,7 +440,7 @@ pub struct IntroducesStaticBecauseUnmetLifetimeReq { } impl AddToDiagnostic for IntroducesStaticBecauseUnmetLifetimeReq { - fn add_to_diagnostic_with>( + fn add_to_diagnostic_with>( mut self, diag: &mut Diag<'_, G>, _f: F, @@ -759,14 +759,14 @@ pub struct ConsiderBorrowingParamHelp { } impl AddToDiagnostic for ConsiderBorrowingParamHelp { - fn add_to_diagnostic_with>( + fn add_to_diagnostic_with>( self, diag: &mut Diag<'_, G>, f: F, ) { let mut type_param_span: MultiSpan = self.spans.clone().into(); for &span in &self.spans { - // Seems like we can't call f() here as Into is required + // Seems like we can't call f() here as Into is required type_param_span.push_span_label(span, fluent::infer_tid_consider_borrowing); } let msg = f(diag, fluent::infer_tid_param_help.into()); @@ -804,7 +804,7 @@ pub struct DynTraitConstraintSuggestion { } impl AddToDiagnostic for DynTraitConstraintSuggestion { - fn add_to_diagnostic_with>( + fn add_to_diagnostic_with>( self, diag: &mut Diag<'_, G>, f: F, @@ -851,7 +851,7 @@ pub struct ReqIntroducedLocations { } impl AddToDiagnostic for ReqIntroducedLocations { - fn add_to_diagnostic_with>( + fn add_to_diagnostic_with>( mut self, diag: &mut Diag<'_, G>, f: F, @@ -874,7 +874,7 @@ pub struct MoreTargeted { } impl AddToDiagnostic for MoreTargeted { - fn add_to_diagnostic_with>( + fn add_to_diagnostic_with>( self, diag: &mut Diag<'_, G>, _f: F, @@ -1297,7 +1297,7 @@ pub struct SuggestTuplePatternMany { } impl AddToDiagnostic for SuggestTuplePatternMany { - fn add_to_diagnostic_with>( + fn add_to_diagnostic_with>( self, diag: &mut Diag<'_, G>, f: F, diff --git a/compiler/rustc_infer/src/errors/note_and_explain.rs b/compiler/rustc_infer/src/errors/note_and_explain.rs index bbcb613b3e4ae..7bb71d47031ab 100644 --- a/compiler/rustc_infer/src/errors/note_and_explain.rs +++ b/compiler/rustc_infer/src/errors/note_and_explain.rs @@ -1,8 +1,6 @@ use crate::fluent_generated as fluent; use crate::infer::error_reporting::nice_region_error::find_anon_type; -use rustc_errors::{ - AddToDiagnostic, Diag, EmissionGuarantee, IntoDiagnosticArg, SubdiagnosticMessageOp, -}; +use rustc_errors::{AddToDiagnostic, Diag, EmissionGuarantee, IntoDiagnosticArg, SubdiagMessageOp}; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::{symbol::kw, Span}; @@ -162,7 +160,7 @@ impl RegionExplanation<'_> { } impl AddToDiagnostic for RegionExplanation<'_> { - fn add_to_diagnostic_with>( + fn add_to_diagnostic_with>( self, diag: &mut Diag<'_, G>, f: F, diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 342f18a18dcc2..ea5c6b8c057ce 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -1623,7 +1623,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } impl<'tcx> ty::visit::TypeVisitor> for OpaqueTypesVisitor<'tcx> { - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) { if let Some((kind, def_id)) = TyCategory::from_ty(self.tcx, t) { let span = self.tcx.def_span(def_id); // Avoid cluttering the output when the "found" and error span overlap: @@ -2129,15 +2129,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let tykind = match self.tcx.opt_hir_node_by_def_id(trace.cause.body_id) { Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })) => { let body = hir.body(*body_id); - struct LetVisitor<'v> { + struct LetVisitor { span: Span, - result: Option<&'v hir::Ty<'v>>, } - impl<'v> Visitor<'v> for LetVisitor<'v> { - fn visit_stmt(&mut self, s: &'v hir::Stmt<'v>) { - if self.result.is_some() { - return; - } + impl<'v> Visitor<'v> for LetVisitor { + type Result = ControlFlow<&'v hir::TyKind<'v>>; + fn visit_stmt(&mut self, s: &'v hir::Stmt<'v>) -> Self::Result { // Find a local statement where the initializer has // the same span as the error and the type is specified. if let hir::Stmt { @@ -2151,13 +2148,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } = s && init_span == &self.span { - self.result = Some(*array_ty); + ControlFlow::Break(&array_ty.peel_refs().kind) + } else { + ControlFlow::Continue(()) } } } - let mut visitor = LetVisitor { span, result: None }; - visitor.visit_body(body); - visitor.result.map(|r| &r.peel_refs().kind) + LetVisitor { span }.visit_body(body).break_value() } Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(ty, _, _), .. })) => { Some(&ty.peel_refs().kind) diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs index 4f74365d06c47..265a315a55979 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs @@ -1,3 +1,4 @@ +use core::ops::ControlFlow; use rustc_hir as hir; use rustc_hir::intravisit::{self, Visitor}; use rustc_middle::hir::map::Map; @@ -43,14 +44,9 @@ fn find_component_for_bound_region<'tcx>( arg: &'tcx hir::Ty<'tcx>, br: &ty::BoundRegionKind, ) -> Option<&'tcx hir::Ty<'tcx>> { - let mut nested_visitor = FindNestedTypeVisitor { - tcx, - bound_region: *br, - found_type: None, - current_index: ty::INNERMOST, - }; - nested_visitor.visit_ty(arg); - nested_visitor.found_type + FindNestedTypeVisitor { tcx, bound_region: *br, current_index: ty::INNERMOST } + .visit_ty(arg) + .break_value() } // The FindNestedTypeVisitor captures the corresponding `hir::Ty` of the @@ -65,26 +61,24 @@ struct FindNestedTypeVisitor<'tcx> { // The bound_region corresponding to the Refree(freeregion) // associated with the anonymous region we are looking for. bound_region: ty::BoundRegionKind, - // The type where the anonymous lifetime appears - // for e.g., Vec<`&u8`> and <`&u8`> - found_type: Option<&'tcx hir::Ty<'tcx>>, current_index: ty::DebruijnIndex, } impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { + type Result = ControlFlow<&'tcx hir::Ty<'tcx>>; type NestedFilter = nested_filter::OnlyBodies; fn nested_visit_map(&mut self) -> Self::Map { self.tcx.hir() } - fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) { + fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) -> Self::Result { match arg.kind { hir::TyKind::BareFn(_) => { self.current_index.shift_in(1); intravisit::walk_ty(self, arg); self.current_index.shift_out(1); - return; + return ControlFlow::Continue(()); } hir::TyKind::TraitObject(bounds, ..) => { @@ -105,8 +99,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { (Some(rbv::ResolvedArg::EarlyBound(id)), ty::BrNamed(def_id, _)) => { debug!("EarlyBound id={:?} def_id={:?}", id, def_id); if id == def_id { - self.found_type = Some(arg); - return; // we can stop visiting now + return ControlFlow::Break(arg); } } @@ -123,8 +116,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { ); debug!("LateBound id={:?} def_id={:?}", id, def_id); if debruijn_index == self.current_index && id == def_id { - self.found_type = Some(arg); - return; // we can stop visiting now + return ControlFlow::Break(arg); } } @@ -145,23 +137,30 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { } // Checks if it is of type `hir::TyKind::Path` which corresponds to a struct. hir::TyKind::Path(_) => { - let subvisitor = &mut TyPathVisitor { - tcx: self.tcx, - found_it: false, - bound_region: self.bound_region, - current_index: self.current_index, + // Prefer using the lifetime in type arguments rather than lifetime arguments. + intravisit::walk_ty(self, arg)?; + + // Call `walk_ty` as `visit_ty` is empty. + return if intravisit::walk_ty( + &mut TyPathVisitor { + tcx: self.tcx, + bound_region: self.bound_region, + current_index: self.current_index, + }, + arg, + ) + .is_break() + { + ControlFlow::Break(arg) + } else { + ControlFlow::Continue(()) }; - intravisit::walk_ty(subvisitor, arg); // call walk_ty; as visit_ty is empty, - // this will visit only outermost type - if subvisitor.found_it { - self.found_type = Some(arg); - } } _ => {} } // walk the embedded contents: e.g., if we are visiting `Vec<&Foo>`, // go on to visit `&Foo` - intravisit::walk_ty(self, arg); + intravisit::walk_ty(self, arg) } } @@ -173,26 +172,25 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { // specific part of the type in the error message. struct TyPathVisitor<'tcx> { tcx: TyCtxt<'tcx>, - found_it: bool, bound_region: ty::BoundRegionKind, current_index: ty::DebruijnIndex, } impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> { + type Result = ControlFlow<()>; type NestedFilter = nested_filter::OnlyBodies; fn nested_visit_map(&mut self) -> Map<'tcx> { self.tcx.hir() } - fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) { + fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) -> Self::Result { match (self.tcx.named_bound_var(lifetime.hir_id), self.bound_region) { // the lifetime of the TyPath! (Some(rbv::ResolvedArg::EarlyBound(id)), ty::BrNamed(def_id, _)) => { debug!("EarlyBound id={:?} def_id={:?}", id, def_id); if id == def_id { - self.found_it = true; - return; // we can stop visiting now + return ControlFlow::Break(()); } } @@ -201,8 +199,7 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> { debug!("id={:?}", id); debug!("def_id={:?}", def_id); if debruijn_index == self.current_index && id == def_id { - self.found_it = true; - return; // we can stop visiting now + return ControlFlow::Break(()); } } @@ -220,9 +217,10 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> { debug!("no arg found"); } } + ControlFlow::Continue(()) } - fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) { + fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) -> Self::Result { // ignore nested types // // If you have a type like `Foo<'a, &Ty>` we @@ -231,5 +229,6 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> { // Making `visit_ty` empty will ignore the `&Ty` embedded // inside, it will get reached by the outer visitor. debug!("`Ty` corresponding to a struct is {:?}", arg); + ControlFlow::Continue(()) } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index 33538309b042a..adde45f081afe 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -23,7 +23,6 @@ use rustc_span::symbol::Ident; use rustc_span::Span; use rustc_span::def_id::LocalDefId; -use std::ops::ControlFlow; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { /// Print the error message for lifetime errors when the return type is a static `impl Trait`, @@ -545,13 +544,12 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { pub struct TraitObjectVisitor(pub FxIndexSet); impl<'tcx> TypeVisitor> for TraitObjectVisitor { - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) { match t.kind() { ty::Dynamic(preds, re, _) if re.is_static() => { if let Some(def_id) = preds.principal_def_id() { self.0.insert(def_id); } - ControlFlow::Continue(()) } _ => t.super_visit_with(self), } diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs index ded628fe13663..b4cf727bf8f1a 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs @@ -16,8 +16,6 @@ use rustc_middle::ty::print::RegionHighlightMode; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor}; use rustc_span::Span; -use std::ops::ControlFlow; - impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { /// Print the error message for lifetime errors when the `impl` doesn't conform to the `trait`. pub(super) fn try_report_impl_not_conforming_to_trait(&self) -> Option { @@ -76,12 +74,11 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } impl<'tcx> ty::visit::TypeVisitor> for HighlightBuilder<'tcx> { - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, r: ty::Region<'tcx>) { if !r.has_name() && self.counter <= 3 { self.highlight.highlighting_region(r, self.counter); self.counter += 1; } - ControlFlow::Continue(()) } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs index 472dab639d590..8cdf39b173987 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs @@ -1,4 +1,5 @@ use crate::infer::error_reporting::hir::Path; +use core::ops::ControlFlow; use hir::def::CtorKind; use hir::intravisit::{walk_expr, walk_stmt, Visitor}; use hir::{Local, QPath}; @@ -563,62 +564,55 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { cause: &ObligationCause<'_>, span: Span, ) -> Option { - let hir = self.tcx.hir(); - if let Some(body_id) = self.tcx.hir().maybe_body_owned_by(cause.body_id) { - let body = hir.body(body_id); - - /// Find the if expression with given span - struct IfVisitor { - pub result: bool, - pub found_if: bool, - pub err_span: Span, - } - - impl<'v> Visitor<'v> for IfVisitor { - fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) { - if self.result { - return; - } - match ex.kind { - hir::ExprKind::If(cond, _, _) => { - self.found_if = true; - walk_expr(self, cond); - self.found_if = false; - } - _ => walk_expr(self, ex), - } - } + /// Find the if expression with given span + struct IfVisitor { + pub found_if: bool, + pub err_span: Span, + } - fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) { - if let hir::StmtKind::Local(hir::Local { - span, - pat: hir::Pat { .. }, - ty: None, - init: Some(_), - .. - }) = &ex.kind - && self.found_if - && span.eq(&self.err_span) - { - self.result = true; + impl<'v> Visitor<'v> for IfVisitor { + type Result = ControlFlow<()>; + fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) -> Self::Result { + match ex.kind { + hir::ExprKind::If(cond, _, _) => { + self.found_if = true; + walk_expr(self, cond)?; + self.found_if = false; + ControlFlow::Continue(()) } - walk_stmt(self, ex); + _ => walk_expr(self, ex), } + } - fn visit_body(&mut self, body: &'v hir::Body<'v>) { - hir::intravisit::walk_body(self, body); + fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) -> Self::Result { + if let hir::StmtKind::Local(hir::Local { + span, + pat: hir::Pat { .. }, + ty: None, + init: Some(_), + .. + }) = &ex.kind + && self.found_if + && span.eq(&self.err_span) + { + ControlFlow::Break(()) + } else { + walk_stmt(self, ex) } } - let mut visitor = IfVisitor { err_span: span, found_if: false, result: false }; - visitor.visit_body(body); - if visitor.result { - return Some(TypeErrorAdditionalDiags::AddLetForLetChains { - span: span.shrink_to_lo(), - }); + fn visit_body(&mut self, body: &'v hir::Body<'v>) -> Self::Result { + hir::intravisit::walk_body(self, body) } } - None + + self.tcx.hir().maybe_body_owned_by(cause.body_id).and_then(|body_id| { + let body = self.tcx.hir().body(body_id); + IfVisitor { err_span: span, found_if: false } + .visit_body(body) + .is_break() + .then(|| TypeErrorAdditionalDiags::AddLetForLetChains { span: span.shrink_to_lo() }) + }) } /// For "one type is more general than the other" errors on closures, suggest changing the lifetime diff --git a/compiler/rustc_infer/src/infer/higher_ranked/README.md b/compiler/rustc_infer/src/infer/higher_ranked/README.md deleted file mode 100644 index 533d0ef7e6c4b..0000000000000 --- a/compiler/rustc_infer/src/infer/higher_ranked/README.md +++ /dev/null @@ -1,8 +0,0 @@ -To learn more about how Higher-ranked trait bounds work in the _old_ trait -solver, see [this chapter][oldhrtb] of the rustc-dev-guide. - -To learn more about how they work in the _new_ trait solver, see [this -chapter][newhrtb]. - -[oldhrtb]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html -[newhrtb]: https://rustc-dev-guide.rust-lang.org/borrow_check/region_inference.html#placeholders-and-universes diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 73a25637e1ade..15cdd6a910e77 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1,23 +1,25 @@ -pub use self::at::DefineOpaqueTypes; -pub use self::freshen::TypeFreshener; -pub use self::lexical_region_resolve::RegionResolutionError; -pub use self::BoundRegionConversionTime::*; -pub use self::RegionVariableOrigin::*; -pub use self::SubregionOrigin::*; -pub use self::ValuePairs::*; +pub use at::DefineOpaqueTypes; +pub use freshen::TypeFreshener; +pub use lexical_region_resolve::RegionResolutionError; +pub use relate::combine::CombineFields; pub use relate::combine::ObligationEmittingRelation; -use rustc_data_structures::captures::Captures; -use rustc_data_structures::undo_log::UndoLogs; -use rustc_middle::infer::unify_key::EffectVarValue; -use rustc_middle::infer::unify_key::{ConstVidKey, EffectVidKey}; - -use self::opaque_types::OpaqueTypeStorage; -pub(crate) use self::undo_log::{InferCtxtUndoLogs, Snapshot, UndoLog}; +pub use relate::StructurallyRelateAliases; +pub use rustc_middle::ty::IntVarValue; +pub use BoundRegionConversionTime::*; +pub use RegionVariableOrigin::*; +pub use SubregionOrigin::*; +pub use ValuePairs::*; use crate::traits::{ self, ObligationCause, ObligationInspector, PredicateObligations, TraitEngine, TraitEngineExt, }; - +use error_reporting::TypeErrCtxt; +use free_regions::RegionRelations; +use lexical_region_resolve::LexicalRegionResolutions; +use opaque_types::OpaqueTypeStorage; +use region_constraints::{GenericKind, VarInfos, VerifyBound}; +use region_constraints::{RegionConstraintCollector, RegionConstraintStorage}; +use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::Lrc; @@ -27,7 +29,9 @@ use rustc_errors::{Diag, DiagCtxt, ErrorGuaranteed}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues}; use rustc_middle::infer::unify_key::ConstVariableValue; +use rustc_middle::infer::unify_key::EffectVarValue; use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType}; +use rustc_middle::infer::unify_key::{ConstVidKey, EffectVidKey}; use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult}; use rustc_middle::mir::ConstraintCategory; use rustc_middle::traits::{select, DefiningAnchor}; @@ -36,33 +40,21 @@ use rustc_middle::ty::fold::BoundVarReplacerDelegate; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::relate::RelateResult; use rustc_middle::ty::visit::TypeVisitableExt; -pub use rustc_middle::ty::IntVarValue; use rustc_middle::ty::{self, GenericParamDefKind, InferConst, InferTy, Ty, TyCtxt}; use rustc_middle::ty::{ConstVid, EffectVid, FloatVid, IntVid, TyVid}; use rustc_middle::ty::{GenericArg, GenericArgKind, GenericArgs, GenericArgsRef}; use rustc_span::symbol::Symbol; use rustc_span::Span; - +use snapshot::undo_log::InferCtxtUndoLogs; use std::cell::{Cell, RefCell}; use std::fmt; - -use self::error_reporting::TypeErrCtxt; -use self::free_regions::RegionRelations; -use self::lexical_region_resolve::LexicalRegionResolutions; -use self::region_constraints::{GenericKind, VarInfos, VerifyBound}; -use self::region_constraints::{ - RegionConstraintCollector, RegionConstraintStorage, RegionSnapshot, -}; -pub use self::relate::combine::CombineFields; -pub use self::relate::StructurallyRelateAliases; -use self::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; pub mod at; pub mod canonical; pub mod error_reporting; pub mod free_regions; mod freshen; -mod fudge; mod lexical_region_resolve; pub mod opaque_types; pub mod outlives; @@ -70,8 +62,8 @@ mod projection; pub mod region_constraints; mod relate; pub mod resolve; +pub(crate) mod snapshot; pub mod type_variable; -mod undo_log; #[must_use] #[derive(Debug)] @@ -738,13 +730,6 @@ impl<'tcx> InferOk<'tcx, ()> { } } -#[must_use = "once you start a snapshot, you should always consume it"] -pub struct CombinedSnapshot<'tcx> { - undo_snapshot: Snapshot<'tcx>, - region_constraints_snapshot: RegionSnapshot, - universe: ty::UniverseIndex, -} - impl<'tcx> InferCtxt<'tcx> { pub fn dcx(&self) -> &'tcx DiagCtxt { self.tcx.dcx() @@ -842,90 +827,6 @@ impl<'tcx> InferCtxt<'tcx> { } } - pub fn in_snapshot(&self) -> bool { - UndoLogs::>::in_snapshot(&self.inner.borrow_mut().undo_log) - } - - pub fn num_open_snapshots(&self) -> usize { - UndoLogs::>::num_open_snapshots(&self.inner.borrow_mut().undo_log) - } - - fn start_snapshot(&self) -> CombinedSnapshot<'tcx> { - debug!("start_snapshot()"); - - let mut inner = self.inner.borrow_mut(); - - CombinedSnapshot { - undo_snapshot: inner.undo_log.start_snapshot(), - region_constraints_snapshot: inner.unwrap_region_constraints().start_snapshot(), - universe: self.universe(), - } - } - - #[instrument(skip(self, snapshot), level = "debug")] - fn rollback_to(&self, snapshot: CombinedSnapshot<'tcx>) { - let CombinedSnapshot { undo_snapshot, region_constraints_snapshot, universe } = snapshot; - - self.universe.set(universe); - - let mut inner = self.inner.borrow_mut(); - inner.rollback_to(undo_snapshot); - inner.unwrap_region_constraints().rollback_to(region_constraints_snapshot); - } - - #[instrument(skip(self, snapshot), level = "debug")] - fn commit_from(&self, snapshot: CombinedSnapshot<'tcx>) { - let CombinedSnapshot { undo_snapshot, region_constraints_snapshot: _, universe: _ } = - snapshot; - - self.inner.borrow_mut().commit(undo_snapshot); - } - - /// Execute `f` and commit the bindings if closure `f` returns `Ok(_)`. - #[instrument(skip(self, f), level = "debug")] - pub fn commit_if_ok(&self, f: F) -> Result - where - F: FnOnce(&CombinedSnapshot<'tcx>) -> Result, - { - let snapshot = self.start_snapshot(); - let r = f(&snapshot); - debug!("commit_if_ok() -- r.is_ok() = {}", r.is_ok()); - match r { - Ok(_) => { - self.commit_from(snapshot); - } - Err(_) => { - self.rollback_to(snapshot); - } - } - r - } - - /// Execute `f` then unroll any bindings it creates. - #[instrument(skip(self, f), level = "debug")] - pub fn probe(&self, f: F) -> R - where - F: FnOnce(&CombinedSnapshot<'tcx>) -> R, - { - let snapshot = self.start_snapshot(); - let r = f(&snapshot); - self.rollback_to(snapshot); - r - } - - /// Scan the constraints produced since `snapshot` and check whether - /// we added any region constraints. - pub fn region_constraints_added_in_snapshot(&self, snapshot: &CombinedSnapshot<'tcx>) -> bool { - self.inner - .borrow_mut() - .unwrap_region_constraints() - .region_constraints_added_in_snapshot(&snapshot.undo_snapshot) - } - - pub fn opaque_types_added_in_snapshot(&self, snapshot: &CombinedSnapshot<'tcx>) -> bool { - self.inner.borrow().undo_log.opaque_types_in_snapshot(&snapshot.undo_snapshot) - } - pub fn can_sub(&self, param_env: ty::ParamEnv<'tcx>, expected: T, actual: T) -> bool where T: at::ToTrace<'tcx>, diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs similarity index 94% rename from compiler/rustc_infer/src/infer/opaque_types.rs rename to compiler/rustc_infer/src/infer/opaque_types/mod.rs index 7a789a1b41bca..3d6829ba6579f 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -17,7 +17,6 @@ use rustc_middle::ty::{ TypeVisitable, TypeVisitableExt, TypeVisitor, }; use rustc_span::Span; -use std::ops::ControlFlow; mod table; @@ -101,6 +100,15 @@ impl<'tcx> InferCtxt<'tcx> { let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() { ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) if def_id.is_local() => { let def_id = def_id.expect_local(); + if self.intercrate { + // See comment on `insert_hidden_type` for why this is sufficient in coherence + return Some(self.register_hidden_type( + OpaqueTypeKey { def_id, args }, + cause.clone(), + param_env, + b, + )); + } match self.defining_use_anchor { DefiningAnchor::Bind(_) => { // Check that this is `impl Trait` type is @@ -142,8 +150,10 @@ impl<'tcx> InferCtxt<'tcx> { } } DefiningAnchor::Bubble => {} - DefiningAnchor::Error => return None, - }; + DefiningAnchor::Error => { + return None; + } + } if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }) = *b.kind() { // We could accept this, but there are various ways to handle this situation, and we don't // want to make a decision on it right now. Likely this case is so super rare anyway, that @@ -381,7 +391,7 @@ impl<'tcx> InferCtxt<'tcx> { // Anonymous `impl Trait` hir::OpaqueTyOrigin::FnReturn(parent) => parent == parent_def_id, // Named `type Foo = impl Bar;` - hir::OpaqueTyOrigin::TyAlias { in_assoc_ty } => { + hir::OpaqueTyOrigin::TyAlias { in_assoc_ty, .. } => { if in_assoc_ty { self.tcx.opaque_types_defined_by(parent_def_id).contains(&def_id) } else { @@ -415,29 +425,22 @@ impl<'tcx, OP> TypeVisitor> for ConstrainOpaqueTypeRegionVisitor<'t where OP: FnMut(ty::Region<'tcx>), { - fn visit_binder>>( - &mut self, - t: &ty::Binder<'tcx, T>, - ) -> ControlFlow { + fn visit_binder>>(&mut self, t: &ty::Binder<'tcx, T>) { t.super_visit_with(self); - ControlFlow::Continue(()) } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, r: ty::Region<'tcx>) { match *r { // ignore bound regions, keep visiting - ty::ReBound(_, _) => ControlFlow::Continue(()), - _ => { - (self.op)(r); - ControlFlow::Continue(()) - } + ty::ReBound(_, _) => {} + _ => (self.op)(r), } } - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) { // We're only interested in types involving regions if !ty.flags().intersects(ty::TypeFlags::HAS_FREE_REGIONS) { - return ControlFlow::Continue(()); + return; } match ty.kind() { @@ -488,8 +491,6 @@ where ty.super_visit_with(self); } } - - ControlFlow::Continue(()) } } @@ -591,8 +592,25 @@ impl<'tcx> InferCtxt<'tcx> { obligations: &mut Vec>, ) { let tcx = self.tcx; - let item_bounds = tcx.explicit_item_bounds(def_id); + // Require that the hidden type is well-formed. We have to + // make sure we wf-check the hidden type to fix #114728. + // + // However, we don't check that all types are well-formed. + // We only do so for types provided by the user or if they are + // "used", e.g. for method selection. + // + // This means we never check the wf requirements of the hidden + // type during MIR borrowck, causing us to infer the wrong + // lifetime for its member constraints which then results in + // unexpected region errors. + obligations.push(traits::Obligation::new( + tcx, + cause.clone(), + param_env, + ty::ClauseKind::WellFormed(hidden_ty.into()), + )); + let item_bounds = tcx.explicit_item_bounds(def_id); for (predicate, _) in item_bounds.iter_instantiated_copied(tcx, args) { let predicate = predicate.fold_with(&mut BottomUpFolder { tcx, diff --git a/compiler/rustc_infer/src/infer/opaque_types/table.rs b/compiler/rustc_infer/src/infer/opaque_types/table.rs index 9f49ed00219c9..a7ddf47543628 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/table.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/table.rs @@ -1,7 +1,7 @@ use rustc_data_structures::undo_log::UndoLogs; use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty}; -use crate::infer::{InferCtxtUndoLogs, UndoLog}; +use crate::infer::snapshot::undo_log::{InferCtxtUndoLogs, UndoLog}; use super::{OpaqueTypeDecl, OpaqueTypeMap}; diff --git a/compiler/rustc_infer/src/infer/outlives/for_liveness.rs b/compiler/rustc_infer/src/infer/outlives/for_liveness.rs index 42e3d6cad5a97..488f435994d4d 100644 --- a/compiler/rustc_infer/src/infer/outlives/for_liveness.rs +++ b/compiler/rustc_infer/src/infer/outlives/for_liveness.rs @@ -2,8 +2,6 @@ use rustc_middle::ty::{ self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, }; -use std::ops::ControlFlow; - use crate::infer::outlives::test_type_match; use crate::infer::region_constraints::VerifyIfEq; @@ -26,29 +24,22 @@ impl<'tcx, OP> TypeVisitor> for FreeRegionsVisitor<'tcx, OP> where OP: FnMut(ty::Region<'tcx>), { - fn visit_binder>>( - &mut self, - t: &ty::Binder<'tcx, T>, - ) -> ControlFlow { + fn visit_binder>>(&mut self, t: &ty::Binder<'tcx, T>) { t.super_visit_with(self); - ControlFlow::Continue(()) } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, r: ty::Region<'tcx>) { match *r { // ignore bound regions, keep visiting - ty::ReBound(_, _) => ControlFlow::Continue(()), - _ => { - (self.op)(r); - ControlFlow::Continue(()) - } + ty::ReBound(_, _) => {} + _ => (self.op)(r), } } - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) { // We're only interested in types involving regions if !ty.flags().intersects(ty::TypeFlags::HAS_FREE_REGIONS) { - return ControlFlow::Continue(()); + return; } // FIXME: Don't consider alias bounds on types that have escaping bound @@ -102,7 +93,7 @@ where && outlives_bounds[1..].iter().all(|other_r| other_r == r) { assert!(r.type_flags().intersects(ty::TypeFlags::HAS_FREE_REGIONS)); - r.visit_with(self)?; + r.visit_with(self); } else { // Skip lifetime parameters that are not captures. let variances = match kind { @@ -114,17 +105,13 @@ where if variances.map(|variances| variances[idx]) != Some(ty::Variance::Bivariant) { - s.visit_with(self)?; + s.visit_with(self); } } } } - _ => { - ty.super_visit_with(self)?; - } + _ => ty.super_visit_with(self), } - - ControlFlow::Continue(()) } } diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 8dd3a1f40cc10..fe323982ec03c 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -63,9 +63,8 @@ use crate::infer::outlives::components::{push_outlives_components, Component}; use crate::infer::outlives::env::RegionBoundPairs; use crate::infer::outlives::verify::VerifyBoundCx; use crate::infer::resolve::OpportunisticRegionResolver; -use crate::infer::{ - self, GenericKind, InferCtxt, RegionObligation, SubregionOrigin, UndoLog, VerifyBound, -}; +use crate::infer::snapshot::undo_log::UndoLog; +use crate::infer::{self, GenericKind, InferCtxt, RegionObligation, SubregionOrigin, VerifyBound}; use crate::traits::{ObligationCause, ObligationCauseCode}; use rustc_data_structures::undo_log::UndoLogs; use rustc_middle::mir::ConstraintCategory; diff --git a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs index 9e2f3a10b6a6e..06f8dd4a4c6cd 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs @@ -1,9 +1,7 @@ use super::*; -use crate::infer::CombinedSnapshot; -use rustc_data_structures::{ - fx::FxIndexMap, - graph::{scc::Sccs, vec_graph::VecGraph}, -}; +use crate::infer::snapshot::CombinedSnapshot; +use rustc_data_structures::fx::FxIndexMap; +use rustc_data_structures::graph::{scc::Sccs, vec_graph::VecGraph}; use rustc_index::Idx; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::relate::RelateResult; diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index ee97dd3680759..0f3f2bc5fa634 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -3,9 +3,8 @@ use self::CombineMapType::*; use self::UndoLog::*; -use super::{ - InferCtxtUndoLogs, MiscVariable, RegionVariableOrigin, Rollback, Snapshot, SubregionOrigin, -}; +use super::{MiscVariable, RegionVariableOrigin, Rollback, SubregionOrigin}; +use crate::infer::snapshot::undo_log::{InferCtxtUndoLogs, Snapshot}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; @@ -360,7 +359,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { /// /// Not legal during a snapshot. pub fn into_infos_and_data(self) -> (VarInfos, RegionConstraintData<'tcx>) { - assert!(!UndoLogs::>::in_snapshot(&self.undo_log)); + assert!(!UndoLogs::>::in_snapshot(&self.undo_log)); (mem::take(&mut self.storage.var_infos), mem::take(&mut self.storage.data)) } @@ -377,7 +376,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { /// /// Not legal during a snapshot. pub fn take_and_reset_data(&mut self) -> RegionConstraintData<'tcx> { - assert!(!UndoLogs::>::in_snapshot(&self.undo_log)); + assert!(!UndoLogs::>::in_snapshot(&self.undo_log)); // If you add a new field to `RegionConstraintCollector`, you // should think carefully about whether it needs to be cleared diff --git a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs index f30e366c19850..70ed7cf9af1ac 100644 --- a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs +++ b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs @@ -1,7 +1,7 @@ //! Helper routines for higher-ranked things. See the `doc` module at //! the end of the file for details. -use crate::infer::CombinedSnapshot; +use crate::infer::snapshot::CombinedSnapshot; use crate::infer::InferCtxt; use rustc_middle::ty::fold::FnMutDelegate; use rustc_middle::ty::relate::RelateResult; @@ -77,7 +77,7 @@ impl<'tcx> InferCtxt<'tcx> { // that name placeholders created in this function. Nested goals from type relations can // also contain placeholders created by this function. let value = self.enter_forall_and_leak_universe(forall); - debug!("?value"); + debug!(?value); f(value) } diff --git a/compiler/rustc_infer/src/infer/fudge.rs b/compiler/rustc_infer/src/infer/snapshot/fudge.rs similarity index 98% rename from compiler/rustc_infer/src/infer/fudge.rs rename to compiler/rustc_infer/src/infer/snapshot/fudge.rs index 99033922bdf76..14de461cd17eb 100644 --- a/compiler/rustc_infer/src/infer/fudge.rs +++ b/compiler/rustc_infer/src/infer/snapshot/fudge.rs @@ -2,9 +2,9 @@ use rustc_middle::infer::unify_key::{ConstVariableOriginKind, ConstVariableValue use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::{self, ConstVid, FloatVid, IntVid, RegionVid, Ty, TyCtxt, TyVid}; -use super::type_variable::TypeVariableOrigin; -use super::InferCtxt; -use super::{ConstVariableOrigin, RegionVariableOrigin, UnificationTable}; +use crate::infer::type_variable::TypeVariableOrigin; +use crate::infer::InferCtxt; +use crate::infer::{ConstVariableOrigin, RegionVariableOrigin, UnificationTable}; use rustc_data_structures::snapshot_vec as sv; use rustc_data_structures::unify as ut; diff --git a/compiler/rustc_infer/src/infer/snapshot/mod.rs b/compiler/rustc_infer/src/infer/snapshot/mod.rs new file mode 100644 index 0000000000000..9eef1471b1af2 --- /dev/null +++ b/compiler/rustc_infer/src/infer/snapshot/mod.rs @@ -0,0 +1,102 @@ +use super::region_constraints::RegionSnapshot; +use super::InferCtxt; +use rustc_data_structures::undo_log::UndoLogs; +use rustc_middle::ty; + +mod fudge; +pub(crate) mod undo_log; + +use undo_log::{Snapshot, UndoLog}; + +#[must_use = "once you start a snapshot, you should always consume it"] +pub struct CombinedSnapshot<'tcx> { + pub(super) undo_snapshot: Snapshot<'tcx>, + region_constraints_snapshot: RegionSnapshot, + universe: ty::UniverseIndex, +} + +impl<'tcx> InferCtxt<'tcx> { + pub fn in_snapshot(&self) -> bool { + UndoLogs::>::in_snapshot(&self.inner.borrow_mut().undo_log) + } + + pub fn num_open_snapshots(&self) -> usize { + UndoLogs::>::num_open_snapshots(&self.inner.borrow_mut().undo_log) + } + + fn start_snapshot(&self) -> CombinedSnapshot<'tcx> { + debug!("start_snapshot()"); + + let mut inner = self.inner.borrow_mut(); + + CombinedSnapshot { + undo_snapshot: inner.undo_log.start_snapshot(), + region_constraints_snapshot: inner.unwrap_region_constraints().start_snapshot(), + universe: self.universe(), + } + } + + #[instrument(skip(self, snapshot), level = "debug")] + fn rollback_to(&self, snapshot: CombinedSnapshot<'tcx>) { + let CombinedSnapshot { undo_snapshot, region_constraints_snapshot, universe } = snapshot; + + self.universe.set(universe); + + let mut inner = self.inner.borrow_mut(); + inner.rollback_to(undo_snapshot); + inner.unwrap_region_constraints().rollback_to(region_constraints_snapshot); + } + + #[instrument(skip(self, snapshot), level = "debug")] + fn commit_from(&self, snapshot: CombinedSnapshot<'tcx>) { + let CombinedSnapshot { undo_snapshot, region_constraints_snapshot: _, universe: _ } = + snapshot; + + self.inner.borrow_mut().commit(undo_snapshot); + } + + /// Execute `f` and commit the bindings if closure `f` returns `Ok(_)`. + #[instrument(skip(self, f), level = "debug")] + pub fn commit_if_ok(&self, f: F) -> Result + where + F: FnOnce(&CombinedSnapshot<'tcx>) -> Result, + { + let snapshot = self.start_snapshot(); + let r = f(&snapshot); + debug!("commit_if_ok() -- r.is_ok() = {}", r.is_ok()); + match r { + Ok(_) => { + self.commit_from(snapshot); + } + Err(_) => { + self.rollback_to(snapshot); + } + } + r + } + + /// Execute `f` then unroll any bindings it creates. + #[instrument(skip(self, f), level = "debug")] + pub fn probe(&self, f: F) -> R + where + F: FnOnce(&CombinedSnapshot<'tcx>) -> R, + { + let snapshot = self.start_snapshot(); + let r = f(&snapshot); + self.rollback_to(snapshot); + r + } + + /// Scan the constraints produced since `snapshot` and check whether + /// we added any region constraints. + pub fn region_constraints_added_in_snapshot(&self, snapshot: &CombinedSnapshot<'tcx>) -> bool { + self.inner + .borrow_mut() + .unwrap_region_constraints() + .region_constraints_added_in_snapshot(&snapshot.undo_snapshot) + } + + pub fn opaque_types_added_in_snapshot(&self, snapshot: &CombinedSnapshot<'tcx>) -> bool { + self.inner.borrow().undo_log.opaque_types_in_snapshot(&snapshot.undo_snapshot) + } +} diff --git a/compiler/rustc_infer/src/infer/undo_log.rs b/compiler/rustc_infer/src/infer/snapshot/undo_log.rs similarity index 100% rename from compiler/rustc_infer/src/infer/undo_log.rs rename to compiler/rustc_infer/src/infer/snapshot/undo_log.rs diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index 97f9a4b291d09..029bddda1e1c5 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -20,6 +20,7 @@ #![allow(rustc::untranslatable_diagnostic)] #![feature(associated_type_bounds)] #![feature(box_patterns)] +#![feature(control_flow_enum)] #![feature(extend_one)] #![feature(let_chains)] #![feature(if_let_guard)] diff --git a/compiler/rustc_infer/src/traits/project.rs b/compiler/rustc_infer/src/traits/project.rs index afba2e50a23c5..31ceb2343324d 100644 --- a/compiler/rustc_infer/src/traits/project.rs +++ b/compiler/rustc_infer/src/traits/project.rs @@ -2,7 +2,7 @@ use super::PredicateObligation; -use crate::infer::InferCtxtUndoLogs; +use crate::infer::snapshot::undo_log::InferCtxtUndoLogs; use rustc_data_structures::{ snapshot_map::{self, SnapshotMapRef, SnapshotMapStorage}, diff --git a/compiler/rustc_infer/src/traits/structural_impls.rs b/compiler/rustc_infer/src/traits/structural_impls.rs index bf4f88530d04e..064e09b875068 100644 --- a/compiler/rustc_infer/src/traits/structural_impls.rs +++ b/compiler/rustc_infer/src/traits/structural_impls.rs @@ -1,11 +1,11 @@ use crate::traits; use crate::traits::project::Normalized; +use rustc_ast_ir::try_visit; use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable}; use rustc_middle::ty::visit::{TypeVisitable, TypeVisitor}; use rustc_middle::ty::{self, TyCtxt}; use std::fmt; -use std::ops::ControlFlow; // Structural impls for the structs in `traits`. @@ -84,8 +84,8 @@ impl<'tcx, O: TypeFoldable>> TypeFoldable> impl<'tcx, O: TypeVisitable>> TypeVisitable> for traits::Obligation<'tcx, O> { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { - self.predicate.visit_with(visitor)?; + fn visit_with>>(&self, visitor: &mut V) -> V::Result { + try_visit!(self.predicate.visit_with(visitor)); self.param_env.visit_with(visitor) } } diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index cd7957c3bce29..284d965979ece 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -45,9 +45,10 @@ pub struct Compiler { pub(crate) fn parse_cfg(dcx: &DiagCtxt, cfgs: Vec) -> Cfg { cfgs.into_iter() .map(|s| { - let sess = ParseSess::with_silent_emitter(format!( - "this error occurred on the command line: `--cfg={s}`" - )); + let psess = ParseSess::with_silent_emitter( + vec![crate::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE], + format!("this error occurred on the command line: `--cfg={s}`"), + ); let filename = FileName::cfg_spec_source_code(&s); macro_rules! error { @@ -61,7 +62,7 @@ pub(crate) fn parse_cfg(dcx: &DiagCtxt, cfgs: Vec) -> Cfg { }; } - match maybe_new_parser_from_source_str(&sess, filename, s.to_string()) { + match maybe_new_parser_from_source_str(&psess, filename, s.to_string()) { Ok(mut parser) => match parser.parse_meta_item() { Ok(meta_item) if parser.token == token::Eof => { if meta_item.path.segments.len() != 1 { @@ -107,9 +108,10 @@ pub(crate) fn parse_check_cfg(dcx: &DiagCtxt, specs: Vec) -> CheckCfg { let mut check_cfg = CheckCfg { exhaustive_names, exhaustive_values, ..CheckCfg::default() }; for s in specs { - let sess = ParseSess::with_silent_emitter(format!( - "this error occurred on the command line: `--check-cfg={s}`" - )); + let psess = ParseSess::with_silent_emitter( + vec![crate::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE], + format!("this error occurred on the command line: `--check-cfg={s}`"), + ); let filename = FileName::cfg_spec_source_code(&s); macro_rules! error { @@ -127,7 +129,7 @@ pub(crate) fn parse_check_cfg(dcx: &DiagCtxt, specs: Vec) -> CheckCfg { error!("expected `cfg(name, values(\"value1\", \"value2\", ... \"valueN\"))`") }; - let mut parser = match maybe_new_parser_from_source_str(&sess, filename, s.to_string()) { + let mut parser = match maybe_new_parser_from_source_str(&psess, filename, s.to_string()) { Ok(parser) => parser, Err(errs) => { errs.into_iter().for_each(|err| err.cancel()); @@ -277,7 +279,7 @@ pub struct Config { pub lint_caps: FxHashMap, /// This is a callback from the driver that is called when [`ParseSess`] is created. - pub parse_sess_created: Option>, + pub psess_created: Option>, /// This is a callback to hash otherwise untracked state used by the caller, if the /// hash changes between runs the incremental cache will be cleared. @@ -318,6 +320,7 @@ pub struct Config { // JUSTIFICATION: before session exists, only config #[allow(rustc::bad_opt_access)] +#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Send) -> R { trace!("run_compiler"); @@ -393,14 +396,14 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se let cfg = parse_cfg(&sess.dcx(), config.crate_cfg); let mut cfg = config::build_configuration(&sess, cfg); util::add_configuration(&mut cfg, &mut sess, &*codegen_backend); - sess.parse_sess.config = cfg; + sess.psess.config = cfg; let mut check_cfg = parse_check_cfg(&sess.dcx(), config.crate_check_cfg); check_cfg.fill_well_known(&sess.target); - sess.parse_sess.check_config = check_cfg; + sess.psess.check_config = check_cfg; - if let Some(parse_sess_created) = config.parse_sess_created { - parse_sess_created(&mut sess.parse_sess); + if let Some(psess_created) = config.psess_created { + psess_created(&mut sess.psess); } if let Some(hash_untracked_state) = config.hash_untracked_state { @@ -422,7 +425,7 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se let compiler = Compiler { sess, codegen_backend, override_queries: config.override_queries }; - rustc_span::set_source_map(compiler.sess.parse_sess.clone_source_map(), move || { + rustc_span::set_source_map(compiler.sess.psess.clone_source_map(), move || { // There are two paths out of `f`. // - Normal exit. // - Panic, e.g. triggered by `abort_if_errors`. diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 661401687593d..4b4c1d6cf672b 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -44,9 +44,9 @@ use std::{env, fs, iter}; pub fn parse<'a>(sess: &'a Session) -> PResult<'a, ast::Crate> { let krate = sess.time("parse_crate", || match &sess.io.input { - Input::File(file) => parse_crate_from_file(file, &sess.parse_sess), + Input::File(file) => parse_crate_from_file(file, &sess.psess), Input::Str { input, name } => { - parse_crate_from_source_str(name.clone(), input.clone(), &sess.parse_sess) + parse_crate_from_source_str(name.clone(), input.clone(), &sess.psess) } })?; @@ -205,7 +205,7 @@ fn configure_and_expand( // The rest is error reporting - sess.parse_sess.buffered_lints.with_lock(|buffered_lints: &mut Vec| { + sess.psess.buffered_lints.with_lock(|buffered_lints: &mut Vec| { buffered_lints.append(&mut ecx.buffered_early_lint); }); @@ -280,7 +280,7 @@ fn configure_and_expand( fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) { let sess = tcx.sess; - let (resolver, krate) = &*tcx.resolver_for_lowering(()).borrow(); + let (resolver, krate) = &*tcx.resolver_for_lowering().borrow(); let mut lint_buffer = resolver.lint_buffer.steal(); if sess.opts.unstable_opts.input_stats { @@ -297,7 +297,7 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) { }); // Add all buffered lints from the `ParseSess` to the `Session`. - sess.parse_sess.buffered_lints.with_lock(|buffered_lints| { + sess.psess.buffered_lints.with_lock(|buffered_lints| { info!("{} parse sess buffered_lints", buffered_lints.len()); for early_lint in buffered_lints.drain(..) { lint_buffer.add_early_lint(early_lint); @@ -305,7 +305,7 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) { }); // Gate identifiers containing invalid Unicode codepoints that were recovered during lexing. - sess.parse_sess.bad_unicode_identifiers.with_lock(|identifiers| { + sess.psess.bad_unicode_identifiers.with_lock(|identifiers| { for (ident, mut spans) in identifiers.drain(..) { spans.sort(); if ident == sym::ferris { @@ -422,7 +422,7 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P // Account for explicitly marked-to-track files // (e.g. accessed in proc macros). - let file_depinfo = sess.parse_sess.file_depinfo.borrow(); + let file_depinfo = sess.psess.file_depinfo.borrow(); let normalize_path = |path: PathBuf| { let file = FileName::from(path); @@ -485,7 +485,7 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P } // Emit special comments with information about accessed environment variables. - let env_depinfo = sess.parse_sess.env_depinfo.borrow(); + let env_depinfo = sess.psess.env_depinfo.borrow(); if !env_depinfo.is_empty() { // We will soon sort, so the initial order does not matter. #[allow(rustc::potential_query_instability)] @@ -531,10 +531,10 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P } } -fn resolver_for_lowering<'tcx>( +fn resolver_for_lowering_raw<'tcx>( tcx: TyCtxt<'tcx>, (): (), -) -> &'tcx Steal<(ty::ResolverAstLowering, Lrc)> { +) -> (&'tcx Steal<(ty::ResolverAstLowering, Lrc)>, &'tcx ty::ResolverGlobalCtxt) { let arenas = Resolver::arenas(); let _ = tcx.registered_tools(()); // Uses `crate_for_resolver`. let (krate, pre_configured_attrs) = tcx.crate_for_resolver(()).steal(); @@ -549,16 +549,15 @@ fn resolver_for_lowering<'tcx>( ast_lowering: untracked_resolver_for_lowering, } = resolver.into_outputs(); - let feed = tcx.feed_unit_query(); - feed.resolutions(tcx.arena.alloc(untracked_resolutions)); - tcx.arena.alloc(Steal::new((untracked_resolver_for_lowering, Lrc::new(krate)))) + let resolutions = tcx.arena.alloc(untracked_resolutions); + (tcx.arena.alloc(Steal::new((untracked_resolver_for_lowering, Lrc::new(krate)))), resolutions) } pub(crate) fn write_dep_info(tcx: TyCtxt<'_>) { // Make sure name resolution and macro expansion is run for // the side-effect of providing a complete set of all // accessed files and env vars. - let _ = tcx.resolver_for_lowering(()); + let _ = tcx.resolver_for_lowering(); let sess = tcx.sess; let _timer = sess.timer("write_dep_info"); @@ -607,7 +606,10 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock = LazyLock::new(|| { let providers = &mut Providers::default(); providers.analysis = analysis; providers.hir_crate = rustc_ast_lowering::lower_to_hir; - providers.resolver_for_lowering = resolver_for_lowering; + providers.resolver_for_lowering_raw = resolver_for_lowering_raw; + providers.stripped_cfg_items = + |tcx, _| tcx.arena.alloc_from_iter(tcx.resolutions(()).stripped_cfg_items.steal()); + providers.resolutions = |tcx, ()| tcx.resolver_for_lowering_raw(()).1; providers.early_lint_checks = early_lint_checks; proc_macro_decls::provide(providers); rustc_const_eval::provide(providers); @@ -686,6 +688,11 @@ pub fn create_global_ctxt<'tcx>( /// Runs the type-checking, region checking and other miscellaneous analysis /// passes on the crate. fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { + if tcx.sess.opts.unstable_opts.hir_stats { + rustc_passes::hir_stats::print_hir_stats(tcx); + } + + #[cfg(debug_assertions)] rustc_passes::hir_id_validator::check_crate(tcx); let sess = tcx.sess; @@ -956,7 +963,7 @@ fn get_recursion_limit(krate_attrs: &[ast::Attribute], sess: &Session) -> Limit // `check_builtin_attribute`), but by the time that runs the macro // is expanded, and it doesn't give an error. validate_attr::emit_fatal_malformed_builtin_attribute( - &sess.parse_sess, + &sess.psess, attr, sym::recursion_limit, ); diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 86858bfe41d81..da11d090b7497 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -8,8 +8,7 @@ use rustc_codegen_ssa::CodegenResults; use rustc_data_structures::steal::Steal; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::{AppendOnlyIndexVec, FreezeLock, OnceLock, WorkerLocal}; -use rustc_hir::def::DefKind; -use rustc_hir::def_id::{StableCrateId, CRATE_DEF_ID, LOCAL_CRATE}; +use rustc_hir::def_id::{StableCrateId, LOCAL_CRATE}; use rustc_hir::definitions::Definitions; use rustc_incremental::setup_dep_graph; use rustc_metadata::creader::CStore; @@ -120,7 +119,7 @@ impl<'tcx> Queries<'tcx> { rustc_builtin_macros::cmdline_attrs::inject( &mut krate, - &sess.parse_sess, + &sess.psess, &sess.opts.unstable_opts.crate_attr, ); @@ -144,10 +143,8 @@ impl<'tcx> Queries<'tcx> { stable_crate_id, )) as _); let definitions = FreezeLock::new(Definitions::new(stable_crate_id)); - let source_span = AppendOnlyIndexVec::new(); - let _id = source_span.push(krate.spans.inner_span); - debug_assert_eq!(_id, CRATE_DEF_ID); - let untracked = Untracked { cstore, source_span, definitions }; + let untracked = + Untracked { cstore, source_span: AppendOnlyIndexVec::new(), definitions }; let qcx = passes::create_global_ctxt( self.compiler, @@ -172,9 +169,6 @@ impl<'tcx> Queries<'tcx> { ))); feed.crate_for_resolver(tcx.arena.alloc(Steal::new((krate, pre_configured_attrs)))); feed.output_filenames(Arc::new(outputs)); - - let feed = tcx.feed_local_def_id(CRATE_DEF_ID); - feed.def_kind(DefKind::Mod); }); Ok(qcx) }) diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 5e1fc248b801c..4f15d1c1d3a0b 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -590,7 +590,7 @@ fn test_codegen_options_tracking_hash() { tracked!(force_frame_pointers, Some(false)); tracked!(force_unwind_tables, Some(true)); tracked!(inline_threshold, Some(0xf007ba11)); - tracked!(instrument_coverage, InstrumentCoverage::All); + tracked!(instrument_coverage, InstrumentCoverage::Yes); tracked!(link_dead_code, Some(true)); tracked!(linker_plugin_lto, LinkerPluginLto::LinkerPluginAuto); tracked!(llvm_args, vec![String::from("1"), String::from("2")]); diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 823614e1f0619..0d50200133cb2 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -9,7 +9,7 @@ use rustc_parse::validate_attr; use rustc_session as session; use rustc_session::config::{self, Cfg, CrateType, OutFileName, OutputFilenames, OutputTypes}; use rustc_session::filesearch::sysroot_candidates; -use rustc_session::lint::{self, BuiltinLintDiagnostics, LintBuffer}; +use rustc_session::lint::{self, BuiltinLintDiag, LintBuffer}; use rustc_session::{filesearch, output, Session}; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::edition::Edition; @@ -160,6 +160,7 @@ pub(crate) fn run_in_thread_pool_with_globals R + Send, R: Send>( }) } +#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn load_backend_from_dylib(early_dcx: &EarlyDiagCtxt, path: &Path) -> MakeBackendFn { match unsafe { load_symbol_from_dylib::(path, "__rustc_codegen_backend") } { Ok(backend_sym) => backend_sym, @@ -227,6 +228,7 @@ fn get_rustc_path_inner(bin_path: &str) -> Option { }) } +#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn get_codegen_sysroot( early_dcx: &EarlyDiagCtxt, maybe_sysroot: &Option, @@ -319,6 +321,7 @@ fn get_codegen_sysroot( } } +#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable pub(crate) fn check_attr_crate_type( sess: &Session, attrs: &[ast::Attribute], @@ -345,7 +348,7 @@ pub(crate) fn check_attr_crate_type( ast::CRATE_NODE_ID, span, "invalid `crate_type` value", - BuiltinLintDiagnostics::UnknownCrateTypes( + BuiltinLintDiag::UnknownCrateTypes( span, "did you mean".to_string(), format!("\"{candidate}\""), @@ -369,7 +372,7 @@ pub(crate) fn check_attr_crate_type( // by the time that runs the macro is expanded, and it doesn't // give an error. validate_attr::emit_fatal_malformed_builtin_attribute( - &sess.parse_sess, + &sess.psess, a, sym::crate_type, ); diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 9f73d2e681251..5f0af6aee6ace 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -58,7 +58,7 @@ use rustc_middle::ty::GenericArgKind; use rustc_middle::ty::ToPredicate; use rustc_middle::ty::TypeVisitableExt; use rustc_middle::ty::{self, Ty, TyCtxt, VariantDef}; -use rustc_session::lint::{BuiltinLintDiagnostics, FutureIncompatibilityReason}; +use rustc_session::lint::{BuiltinLintDiag, FutureIncompatibilityReason}; use rustc_span::edition::Edition; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident, Symbol}; @@ -1231,7 +1231,7 @@ impl<'tcx> LateLintPass<'tcx> for MutableTransmutes { } fn def_id_is_transmute(cx: &LateContext<'_>, def_id: DefId) -> bool { - matches!(cx.tcx.intrinsic(def_id), Some(sym::transmute)) + cx.tcx.is_intrinsic(def_id, sym::transmute) } } } @@ -1868,7 +1868,7 @@ impl KeywordIdents { }; // Don't lint `r#foo`. - if cx.sess().parse_sess.raw_identifier_spans.contains(ident.span) { + if cx.sess().psess.raw_identifier_spans.contains(ident.span) { return; } @@ -2831,7 +2831,7 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels { Some(target_spans), fluent::lint_builtin_asm_labels, |_| {}, - BuiltinLintDiagnostics::NamedAsmLabel( + BuiltinLintDiag::NamedAsmLabel( "only local labels of the form `:` should be used in inline asm" .to_string(), ), diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index ab76da36ee314..89cdde11726ab 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -21,7 +21,7 @@ use crate::passes::{EarlyLintPassObject, LateLintPassObject}; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sync; use rustc_data_structures::unord::UnordMap; -use rustc_errors::{DecorateLint, Diag, DiagnosticMessage, MultiSpan}; +use rustc_errors::{DecorateLint, Diag, DiagMessage, MultiSpan}; use rustc_feature::Features; use rustc_hir as hir; use rustc_hir::def::Res; @@ -31,7 +31,7 @@ use rustc_middle::middle::privacy::EffectiveVisibilities; use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout}; use rustc_middle::ty::print::{with_no_trimmed_paths, PrintError}; use rustc_middle::ty::{self, print::Printer, GenericArg, RegisteredTools, Ty, TyCtxt}; -use rustc_session::lint::{BuiltinLintDiagnostics, LintExpectationId}; +use rustc_session::lint::{BuiltinLintDiag, LintExpectationId}; use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintBuffer, LintId}; use rustc_session::{LintStoreMarker, Session}; use rustc_span::edit_distance::find_best_match_for_names; @@ -536,9 +536,9 @@ pub trait LintContext { &self, lint: &'static Lint, span: Option>, - msg: impl Into, + msg: impl Into, decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>), - diagnostic: BuiltinLintDiagnostics, + diagnostic: BuiltinLintDiag, ) { // We first generate a blank diagnostic. self.opt_span_lint(lint, span, msg, |db| { @@ -559,7 +559,7 @@ pub trait LintContext { &self, lint: &'static Lint, span: Option, - msg: impl Into, + msg: impl Into, decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>), ); @@ -584,7 +584,7 @@ pub trait LintContext { &self, lint: &'static Lint, span: S, - msg: impl Into, + msg: impl Into, decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>), ) { self.opt_span_lint(lint, Some(span), msg, decorate); @@ -605,7 +605,7 @@ pub trait LintContext { fn lint( &self, lint: &'static Lint, - msg: impl Into, + msg: impl Into, decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>), ) { self.opt_span_lint(lint, None as Option, msg, decorate); @@ -621,12 +621,13 @@ pub trait LintContext { /// Note that this function should only be called for [`LintExpectationId`]s /// retrieved from the current lint pass. Buffered or manually created ids can /// cause ICEs. - #[rustc_lint_diagnostics] fn fulfill_expectation(&self, expectation: LintExpectationId) { // We need to make sure that submitted expectation ids are correctly fulfilled suppressed // and stored between compilation sessions. To not manually do these steps, we simply create - // a dummy diagnostic and emit is as usual, which will be suppressed and stored like a normal - // expected lint diagnostic. + // a dummy diagnostic and emit it as usual, which will be suppressed and stored like a + // normal expected lint diagnostic. + #[allow(rustc::diagnostic_outside_of_impl)] + #[allow(rustc::untranslatable_diagnostic)] self.sess() .dcx() .struct_expect( @@ -670,7 +671,7 @@ impl<'tcx> LintContext for LateContext<'tcx> { &self, lint: &'static Lint, span: Option, - msg: impl Into, + msg: impl Into, decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>), ) { let hir_id = self.last_node_with_lint_attrs; @@ -697,7 +698,7 @@ impl LintContext for EarlyContext<'_> { &self, lint: &'static Lint, span: Option, - msg: impl Into, + msg: impl Into, decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>), ) { self.builder.opt_span_lint(lint, span.map(|s| s.into()), msg, decorate) diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index 728996f07417c..a0be1c09c9a3d 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -6,15 +6,52 @@ use rustc_errors::{add_elided_lifetime_in_path_suggestion, Diag}; use rustc_errors::{Applicability, SuggestionStyle}; use rustc_middle::middle::stability; use rustc_session::config::ExpectedValues; -use rustc_session::lint::BuiltinLintDiagnostics; +use rustc_session::lint::BuiltinLintDiag; use rustc_session::Session; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::symbol::{sym, Symbol}; use rustc_span::BytePos; -pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag: &mut Diag<'_, ()>) { +const MAX_CHECK_CFG_NAMES_OR_VALUES: usize = 35; + +fn check_cfg_expected_note( + sess: &Session, + possibilities: &[Symbol], + type_: &str, + name: Option, + suffix: &str, +) -> String { + use std::fmt::Write; + + let n_possibilities = if sess.opts.unstable_opts.check_cfg_all_expected { + possibilities.len() + } else { + std::cmp::min(possibilities.len(), MAX_CHECK_CFG_NAMES_OR_VALUES) + }; + + let mut possibilities = possibilities.iter().map(Symbol::as_str).collect::>(); + possibilities.sort(); + + let and_more = possibilities.len().saturating_sub(n_possibilities); + let possibilities = possibilities[..n_possibilities].join("`, `"); + + let mut note = String::with_capacity(50 + possibilities.len()); + + write!(&mut note, "expected {type_}").unwrap(); + if let Some(name) = name { + write!(&mut note, " for `{name}`").unwrap(); + } + write!(&mut note, " are: {suffix}`{possibilities}`").unwrap(); + if and_more > 0 { + write!(&mut note, " and {and_more} more").unwrap(); + } + + note +} + +pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Diag<'_, ()>) { match diagnostic { - BuiltinLintDiagnostics::UnicodeTextFlow(span, content) => { + BuiltinLintDiag::UnicodeTextFlow(span, content) => { let spans: Vec<_> = content .char_indices() .filter_map(|(i, c)| { @@ -51,8 +88,8 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag: ); } } - BuiltinLintDiagnostics::Normal => (), - BuiltinLintDiagnostics::AbsPathWithModule(span) => { + BuiltinLintDiag::Normal => (), + BuiltinLintDiag::AbsPathWithModule(span) => { let (sugg, app) = match sess.source_map().span_to_snippet(span) { Ok(ref s) => { // FIXME(Manishearth) ideally the emitting code @@ -65,21 +102,16 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag: }; diag.span_suggestion(span, "use `crate`", sugg, app); } - BuiltinLintDiagnostics::ProcMacroDeriveResolutionFallback(span) => { + BuiltinLintDiag::ProcMacroDeriveResolutionFallback(span) => { diag.span_label( span, "names from parent modules are not accessible without an explicit import", ); } - BuiltinLintDiagnostics::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def) => { + BuiltinLintDiag::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def) => { diag.span_note(span_def, "the macro is defined here"); } - BuiltinLintDiagnostics::ElidedLifetimesInPaths( - n, - path_span, - incl_angl_brckt, - insertion_span, - ) => { + BuiltinLintDiag::ElidedLifetimesInPaths(n, path_span, incl_angl_brckt, insertion_span) => { add_elided_lifetime_in_path_suggestion( sess.source_map(), diag, @@ -89,10 +121,10 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag: insertion_span, ); } - BuiltinLintDiagnostics::UnknownCrateTypes(span, note, sugg) => { + BuiltinLintDiag::UnknownCrateTypes(span, note, sugg) => { diag.span_suggestion(span, note, sugg, Applicability::MaybeIncorrect); } - BuiltinLintDiagnostics::UnusedImports(message, replaces, in_test_module) => { + BuiltinLintDiag::UnusedImports(message, replaces, in_test_module) => { if !replaces.is_empty() { diag.tool_only_multipart_suggestion( message, @@ -108,21 +140,25 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag: ); } } - BuiltinLintDiagnostics::RedundantImport(spans, ident) => { + BuiltinLintDiag::RedundantImport(spans, ident) => { for (span, is_imported) in spans { let introduced = if is_imported { "imported" } else { "defined" }; - diag.span_label(span, format!("the item `{ident}` is already {introduced} here")); + let span_msg = if span.is_dummy() { "by prelude" } else { "here" }; + diag.span_label( + span, + format!("the item `{ident}` is already {introduced} {span_msg}"), + ); } } - BuiltinLintDiagnostics::DeprecatedMacro(suggestion, span) => { + BuiltinLintDiag::DeprecatedMacro(suggestion, span) => { stability::deprecation_suggestion(diag, "macro", suggestion, span) } - BuiltinLintDiagnostics::UnusedDocComment(span) => { + BuiltinLintDiag::UnusedDocComment(span) => { diag.span_label(span, "rustdoc does not generate documentation for macro invocations"); diag.help("to document an item produced by a macro, \ the macro must produce the documentation as part of its expansion"); } - BuiltinLintDiagnostics::PatternsInFnsWithoutBody(span, ident) => { + BuiltinLintDiag::PatternsInFnsWithoutBody(span, ident) => { diag.span_suggestion( span, "remove `mut` from the parameter", @@ -130,17 +166,17 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag: Applicability::MachineApplicable, ); } - BuiltinLintDiagnostics::MissingAbi(span, default_abi) => { + BuiltinLintDiag::MissingAbi(span, default_abi) => { diag.span_label(span, "ABI should be specified here"); diag.help(format!("the default ABI is {}", default_abi.name())); } - BuiltinLintDiagnostics::LegacyDeriveHelpers(span) => { + BuiltinLintDiag::LegacyDeriveHelpers(span) => { diag.span_label(span, "the attribute is introduced here"); } - BuiltinLintDiagnostics::ProcMacroBackCompat(note) => { + BuiltinLintDiag::ProcMacroBackCompat(note) => { diag.note(note); } - BuiltinLintDiagnostics::OrPatternsBackCompat(span, suggestion) => { + BuiltinLintDiag::OrPatternsBackCompat(span, suggestion) => { diag.span_suggestion( span, "use pat_param to preserve semantics", @@ -148,7 +184,7 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag: Applicability::MachineApplicable, ); } - BuiltinLintDiagnostics::ReservedPrefix(span) => { + BuiltinLintDiag::ReservedPrefix(span) => { diag.span_label(span, "unknown prefix"); diag.span_suggestion_verbose( span.shrink_to_hi(), @@ -157,19 +193,19 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag: Applicability::MachineApplicable, ); } - BuiltinLintDiagnostics::UnusedBuiltinAttribute { attr_name, macro_name, invoc_span } => { + BuiltinLintDiag::UnusedBuiltinAttribute { attr_name, macro_name, invoc_span } => { diag.span_note( invoc_span, format!("the built-in attribute `{attr_name}` will be ignored, since it's applied to the macro invocation `{macro_name}`") ); } - BuiltinLintDiagnostics::TrailingMacro(is_trailing, name) => { + BuiltinLintDiag::TrailingMacro(is_trailing, name) => { if is_trailing { diag.note("macro invocations at the end of a block are treated as expressions"); diag.note(format!("to ignore the value produced by the macro, add a semicolon after the invocation of `{name}`")); } } - BuiltinLintDiagnostics::BreakWithLabelAndLoop(span) => { + BuiltinLintDiag::BreakWithLabelAndLoop(span) => { diag.multipart_suggestion( "wrap this expression in parentheses", vec![ @@ -179,19 +215,19 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag: Applicability::MachineApplicable, ); } - BuiltinLintDiagnostics::NamedAsmLabel(help) => { + BuiltinLintDiag::NamedAsmLabel(help) => { diag.help(help); diag.note("see the asm section of Rust By Example for more information"); } - BuiltinLintDiagnostics::UnexpectedCfgName((name, name_span), value) => { + BuiltinLintDiag::UnexpectedCfgName((name, name_span), value) => { #[allow(rustc::potential_query_instability)] let possibilities: Vec = - sess.parse_sess.check_config.expecteds.keys().copied().collect(); + sess.psess.check_config.expecteds.keys().copied().collect(); let mut names_possibilities: Vec<_> = if value.is_none() { // We later sort and display all the possibilities, so the order here does not matter. #[allow(rustc::potential_query_instability)] - sess.parse_sess + sess.psess .check_config .expecteds .iter() @@ -212,7 +248,7 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag: // Suggest the most probable if we found one } else if let Some(best_match) = find_best_match_for_name(&possibilities, name, None) { if let Some(ExpectedValues::Some(best_match_values)) = - sess.parse_sess.check_config.expecteds.get(&best_match) + sess.psess.check_config.expecteds.get(&best_match) { // We will soon sort, so the initial order does not matter. #[allow(rustc::potential_query_instability)] @@ -291,16 +327,13 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag: } } if !possibilities.is_empty() { - let mut possibilities = - possibilities.iter().map(Symbol::as_str).collect::>(); - possibilities.sort(); - let possibilities = possibilities.join("`, `"); - - // The list of expected names can be long (even by default) and - // so the diagnostic produced can take a lot of space. To avoid - // cloging the user output we only want to print that diagnostic - // once. - diag.help_once(format!("expected names are: `{possibilities}`")); + diag.help_once(check_cfg_expected_note( + sess, + &possibilities, + "names", + None, + "", + )); } } @@ -321,9 +354,8 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag: diag.note("see for more information about checking conditional configuration"); } } - BuiltinLintDiagnostics::UnexpectedCfgValue((name, name_span), value) => { - let Some(ExpectedValues::Some(values)) = - &sess.parse_sess.check_config.expecteds.get(&name) + BuiltinLintDiag::UnexpectedCfgValue((name, name_span), value) => { + let Some(ExpectedValues::Some(values)) = &sess.psess.check_config.expecteds.get(&name) else { bug!( "it shouldn't be possible to have a diagnostic on a value whose name is not in values" @@ -344,16 +376,13 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag: // Show the full list if all possible values for a given name, but don't do it // for names as the possibilities could be very long if !possibilities.is_empty() { - { - let mut possibilities = - possibilities.iter().map(Symbol::as_str).collect::>(); - possibilities.sort(); - - let possibilities = possibilities.join("`, `"); - let none = if have_none_possibility { "(none), " } else { "" }; - - diag.note(format!("expected values for `{name}` are: {none}`{possibilities}`")); - } + diag.note(check_cfg_expected_note( + sess, + &possibilities, + "values", + Some(name), + if have_none_possibility { "(none), " } else { "" }, + )); if let Some((value, value_span)) = value { // Suggest the most probable if we found one @@ -398,8 +427,7 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag: // We don't want to suggest adding values to well known names // since those are defined by rustc it-self. Users can still // do it if they want, but should not encourage them. - let is_cfg_a_well_know_name = - sess.parse_sess.check_config.well_known_names.contains(&name); + let is_cfg_a_well_know_name = sess.psess.check_config.well_known_names.contains(&name); let inst = if let Some((value, _value_span)) = value { let pre = if is_from_cargo { "\\" } else { "" }; @@ -428,7 +456,7 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag: diag.note("see for more information about checking conditional configuration"); } } - BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(sugg) => { + BuiltinLintDiag::DeprecatedWhereclauseLocation(sugg) => { let left_sp = diag.span.primary_span().unwrap(); match sugg { Some((right_sp, sugg)) => diag.multipart_suggestion( @@ -445,7 +473,7 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag: }; diag.note("see issue #89122 for more information"); } - BuiltinLintDiagnostics::SingleUseLifetime { + BuiltinLintDiag::SingleUseLifetime { param_span, use_span: Some((use_span, elide)), deletion_span, @@ -476,11 +504,7 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag: diag.multipart_suggestion(msg, suggestions, Applicability::MachineApplicable); } } - BuiltinLintDiagnostics::SingleUseLifetime { - param_span: _, - use_span: None, - deletion_span, - } => { + BuiltinLintDiag::SingleUseLifetime { param_span: _, use_span: None, deletion_span } => { debug!(?deletion_span); if let Some(deletion_span) = deletion_span { diag.span_suggestion( @@ -491,7 +515,7 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag: ); } } - BuiltinLintDiagnostics::NamedArgumentUsedPositionally { + BuiltinLintDiag::NamedArgumentUsedPositionally { position_sp_to_replace, position_sp_for_msg, named_arg_sp, @@ -527,13 +551,13 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag: ); } } - BuiltinLintDiagnostics::ByteSliceInPackedStructWithDerive => { + BuiltinLintDiag::ByteSliceInPackedStructWithDerive => { diag.help("consider implementing the trait by hand, or remove the `packed` attribute"); } - BuiltinLintDiagnostics::UnusedExternCrate { removal_span } => { + BuiltinLintDiag::UnusedExternCrate { removal_span } => { diag.span_suggestion(removal_span, "remove it", "", Applicability::MachineApplicable); } - BuiltinLintDiagnostics::ExternCrateNotIdiomatic { vis_span, ident_span } => { + BuiltinLintDiag::ExternCrateNotIdiomatic { vis_span, ident_span } => { let suggestion_span = vis_span.between(ident_span); diag.span_suggestion_verbose( suggestion_span, @@ -542,10 +566,10 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag: Applicability::MachineApplicable, ); } - BuiltinLintDiagnostics::AmbiguousGlobImports { diag: ambiguity } => { + BuiltinLintDiag::AmbiguousGlobImports { diag: ambiguity } => { rustc_errors::report_ambiguity_error(diag, ambiguity); } - BuiltinLintDiagnostics::AmbiguousGlobReexports { + BuiltinLintDiag::AmbiguousGlobReexports { name, namespace, first_reexport_span, @@ -562,7 +586,7 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag: ), ); } - BuiltinLintDiagnostics::HiddenGlobReexports { + BuiltinLintDiag::HiddenGlobReexports { name, namespace, glob_reexport_span, @@ -571,7 +595,7 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag: diag.span_note(glob_reexport_span, format!("the name `{name}` in the {namespace} namespace is supposed to be publicly re-exported here")); diag.span_note(private_item_span, "but the private item here shadows it".to_owned()); } - BuiltinLintDiagnostics::UnusedQualifications { removal_span } => { + BuiltinLintDiag::UnusedQualifications { removal_span } => { diag.span_suggestion_verbose( removal_span, "remove the unnecessary path segments", @@ -579,7 +603,7 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag: Applicability::MachineApplicable, ); } - BuiltinLintDiagnostics::AssociatedConstElidedLifetime { elided, span } => { + BuiltinLintDiag::AssociatedConstElidedLifetime { elided, span } => { diag.span_suggestion_verbose( if elided { span.shrink_to_hi() } else { span }, "use the `'static` lifetime", @@ -587,7 +611,7 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag: Applicability::MachineApplicable, ); } - BuiltinLintDiagnostics::RedundantImportVisibility { max_vis, span } => { + BuiltinLintDiag::RedundantImportVisibility { max_vis, span } => { diag.span_note(span, format!("the most public imported item is `{max_vis}`")); diag.help( "reduce the glob import's visibility or increase visibility of imported items", diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 0862204d88e2d..d78ec8c0dd348 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -17,8 +17,8 @@ use crate::context::{EarlyContext, LintContext, LintStore}; use crate::passes::{EarlyLintPass, EarlyLintPassObject}; use rustc_ast::ptr::P; -use rustc_ast::visit::{self as ast_visit, Visitor}; -use rustc_ast::{self as ast, walk_list, HasAttrs}; +use rustc_ast::visit::{self as ast_visit, walk_list, Visitor}; +use rustc_ast::{self as ast, HasAttrs}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_feature::Features; use rustc_middle::ty::RegisteredTools; diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs index 3be792a9e4f27..d73f9e7a4a1d1 100644 --- a/compiler/rustc_lint/src/errors.rs +++ b/compiler/rustc_lint/src/errors.rs @@ -1,5 +1,5 @@ use crate::fluent_generated as fluent; -use rustc_errors::{codes::*, AddToDiagnostic, Diag, EmissionGuarantee, SubdiagnosticMessageOp}; +use rustc_errors::{codes::*, AddToDiagnostic, Diag, EmissionGuarantee, SubdiagMessageOp}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_session::lint::Level; use rustc_span::{Span, Symbol}; @@ -24,7 +24,7 @@ pub enum OverruledAttributeSub { } impl AddToDiagnostic for OverruledAttributeSub { - fn add_to_diagnostic_with>( + fn add_to_diagnostic_with>( self, diag: &mut Diag<'_, G>, _f: F, diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index a071fa488bc47..e8fcf4132ea73 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -10,7 +10,7 @@ use rustc_ast as ast; use rustc_hir::def::Res; use rustc_hir::{def_id::DefId, Expr, ExprKind, GenericArg, PatKind, Path, PathSegment, QPath}; use rustc_hir::{BinOp, BinOpKind, HirId, Impl, Item, ItemKind, Node, Pat, Ty, TyKind}; -use rustc_middle::ty; +use rustc_middle::ty::{self, Ty as MiddleTy}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::symbol::{kw, sym, Symbol}; @@ -338,10 +338,11 @@ impl<'tcx> LateLintPass<'tcx> for ExistingDocKeyword { } declare_tool_lint! { - /// The `untranslatable_diagnostic` lint detects diagnostics created - /// without using translatable Fluent strings. + /// The `untranslatable_diagnostic` lint detects messages passed to functions with `impl + /// Into<{D,Subd}iagMessage` parameters without using translatable Fluent strings. /// - /// More details on translatable diagnostics can be found [here](https://rustc-dev-guide.rust-lang.org/diagnostics/translation.html). + /// More details on translatable diagnostics can be found + /// [here](https://rustc-dev-guide.rust-lang.org/diagnostics/translation.html). pub rustc::UNTRANSLATABLE_DIAGNOSTIC, Deny, "prevent creation of diagnostics which cannot be translated", @@ -349,11 +350,13 @@ declare_tool_lint! { } declare_tool_lint! { - /// The `diagnostic_outside_of_impl` lint detects diagnostics created manually, - /// and inside an `IntoDiagnostic`/`AddToDiagnostic` implementation, - /// or a `#[derive(Diagnostic)]`/`#[derive(Subdiagnostic)]` expansion. + /// The `diagnostic_outside_of_impl` lint detects calls to functions annotated with + /// `#[rustc_lint_diagnostics]` that are outside an `IntoDiagnostic`, `AddToDiagnostic`, or + /// `DecorateLint` impl, or a `#[derive(Diagnostic)]`, `#[derive(Subdiagnostic)]`, + /// `#[derive(DecorateLint)]` expansion. /// - /// More details on diagnostics implementations can be found [here](https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-structs.html). + /// More details on diagnostics implementations can be found + /// [here](https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-structs.html). pub rustc::DIAGNOSTIC_OUTSIDE_OF_IMPL, Deny, "prevent creation of diagnostics outside of `IntoDiagnostic`/`AddToDiagnostic` impls", @@ -364,54 +367,132 @@ declare_lint_pass!(Diagnostics => [UNTRANSLATABLE_DIAGNOSTIC, DIAGNOSTIC_OUTSIDE impl LateLintPass<'_> for Diagnostics { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { - let Some((span, def_id, args)) = typeck_results_of_method_fn(cx, expr) else { return }; - debug!(?span, ?def_id, ?args); - let has_attr = ty::Instance::resolve(cx.tcx, cx.param_env, def_id, args) + // Only check function calls and method calls. + let (span, def_id, fn_gen_args, call_tys) = match expr.kind { + ExprKind::Call(callee, args) => { + match cx.typeck_results().node_type(callee.hir_id).kind() { + &ty::FnDef(def_id, fn_gen_args) => { + let call_tys: Vec<_> = + args.iter().map(|arg| cx.typeck_results().expr_ty(arg)).collect(); + (callee.span, def_id, fn_gen_args, call_tys) + } + _ => return, // occurs for fns passed as args + } + } + ExprKind::MethodCall(_segment, _recv, args, _span) => { + let Some((span, def_id, fn_gen_args)) = typeck_results_of_method_fn(cx, expr) + else { + return; + }; + let mut call_tys: Vec<_> = + args.iter().map(|arg| cx.typeck_results().expr_ty(arg)).collect(); + call_tys.insert(0, cx.tcx.types.self_param); // dummy inserted for `self` + (span, def_id, fn_gen_args, call_tys) + } + _ => return, + }; + + // Is the callee marked with `#[rustc_lint_diagnostics]`? + let has_attr = ty::Instance::resolve(cx.tcx, cx.param_env, def_id, fn_gen_args) .ok() .flatten() .is_some_and(|inst| cx.tcx.has_attr(inst.def_id(), sym::rustc_lint_diagnostics)); - if !has_attr { - return; - } - let mut found_parent_with_attr = false; - let mut found_impl = false; - for (hir_id, parent) in cx.tcx.hir().parent_iter(expr.hir_id) { - if let Some(owner_did) = hir_id.as_owner() { - found_parent_with_attr = found_parent_with_attr - || cx.tcx.has_attr(owner_did, sym::rustc_lint_diagnostics); + // Closure: is the type `{D,Subd}iagMessage`? + let is_diag_message = |ty: MiddleTy<'_>| { + if let Some(adt_def) = ty.ty_adt_def() + && let Some(name) = cx.tcx.get_diagnostic_name(adt_def.did()) + && matches!(name, sym::DiagMessage | sym::SubdiagMessage) + { + true + } else { + false } + }; - debug!(?parent); - if let Node::Item(Item { kind: ItemKind::Impl(impl_), .. }) = parent - && let Impl { of_trait: Some(of_trait), .. } = impl_ - && let Some(def_id) = of_trait.trait_def_id() - && let Some(name) = cx.tcx.get_diagnostic_name(def_id) - && matches!(name, sym::IntoDiagnostic | sym::AddToDiagnostic | sym::DecorateLint) - { - found_impl = true; - break; + // Does the callee have a `impl Into<{D,Subd}iagMessage>` parameter? (There should be at + // most one.) + let mut impl_into_diagnostic_message_param = None; + let fn_sig = cx.tcx.fn_sig(def_id).instantiate_identity().skip_binder(); + let predicates = cx.tcx.predicates_of(def_id).instantiate_identity(cx.tcx).predicates; + for (i, ¶m_ty) in fn_sig.inputs().iter().enumerate() { + if let ty::Param(p) = param_ty.kind() { + // It is a type parameter. Check if it is `impl Into<{D,Subd}iagMessage>`. + for pred in predicates.iter() { + if let Some(trait_pred) = pred.as_trait_clause() + && let trait_ref = trait_pred.skip_binder().trait_ref + && trait_ref.self_ty() == param_ty // correct predicate for the param? + && cx.tcx.is_diagnostic_item(sym::Into, trait_ref.def_id) + && let ty1 = trait_ref.args.type_at(1) + && is_diag_message(ty1) + { + if impl_into_diagnostic_message_param.is_some() { + cx.tcx.dcx().span_bug( + span, + "can't handle multiple `impl Into<{D,Sub}iagMessage>` params", + ); + } + impl_into_diagnostic_message_param = Some((i, p.name)); + } + } } } - debug!(?found_impl); - if !found_parent_with_attr && !found_impl { - cx.emit_span_lint(DIAGNOSTIC_OUTSIDE_OF_IMPL, span, DiagOutOfImpl); + + // Is the callee interesting? + if !has_attr && impl_into_diagnostic_message_param.is_none() { + return; } - let mut found_diagnostic_message = false; - for ty in args.types() { - debug!(?ty); - if let Some(adt_def) = ty.ty_adt_def() - && let Some(name) = cx.tcx.get_diagnostic_name(adt_def.did()) - && matches!(name, sym::DiagnosticMessage | sym::SubdiagnosticMessage) + // Is the parent method marked with `#[rustc_lint_diagnostics]`? + let mut parent_has_attr = false; + for (hir_id, _parent) in cx.tcx.hir().parent_iter(expr.hir_id) { + if let Some(owner_did) = hir_id.as_owner() + && cx.tcx.has_attr(owner_did, sym::rustc_lint_diagnostics) { - found_diagnostic_message = true; + parent_has_attr = true; break; } } - debug!(?found_diagnostic_message); - if !found_parent_with_attr && !found_diagnostic_message { - cx.emit_span_lint(UNTRANSLATABLE_DIAGNOSTIC, span, UntranslatableDiag); + + // Calls to `#[rustc_lint_diagnostics]`-marked functions should only occur: + // - inside an impl of `IntoDiagnostic`, `AddToDiagnostic`, or `DecorateLint`, or + // - inside a parent function that is itself marked with `#[rustc_lint_diagnostics]`. + // + // Otherwise, emit a `DIAGNOSTIC_OUTSIDE_OF_IMPL` lint. + if has_attr && !parent_has_attr { + let mut is_inside_appropriate_impl = false; + for (_hir_id, parent) in cx.tcx.hir().parent_iter(expr.hir_id) { + debug!(?parent); + if let Node::Item(Item { kind: ItemKind::Impl(impl_), .. }) = parent + && let Impl { of_trait: Some(of_trait), .. } = impl_ + && let Some(def_id) = of_trait.trait_def_id() + && let Some(name) = cx.tcx.get_diagnostic_name(def_id) + && matches!( + name, + sym::IntoDiagnostic | sym::AddToDiagnostic | sym::DecorateLint + ) + { + is_inside_appropriate_impl = true; + break; + } + } + debug!(?is_inside_appropriate_impl); + if !is_inside_appropriate_impl { + cx.emit_span_lint(DIAGNOSTIC_OUTSIDE_OF_IMPL, span, DiagOutOfImpl); + } + } + + // Calls to methods with an `impl Into<{D,Subd}iagMessage>` parameter must be passed an arg + // with type `{D,Subd}iagMessage` or `impl Into<{D,Subd}iagMessage>`. Otherwise, emit an + // `UNTRANSLATABLE_DIAGNOSTIC` lint. + if let Some((param_i, param_i_p_name)) = impl_into_diagnostic_message_param { + // Is the arg type `{Sub,D}iagMessage`or `impl Into<{Sub,D}iagMessage>`? + let arg_ty = call_tys[param_i]; + let is_translatable = is_diag_message(arg_ty) + || matches!(arg_ty.kind(), ty::Param(p) if p.name == param_i_p_name); + if !is_translatable { + cx.emit_span_lint(UNTRANSLATABLE_DIAGNOSTIC, span, UntranslatableDiag); + } } } } @@ -425,7 +506,7 @@ declare_tool_lint! { report_in_external_macro: true } -declare_lint_pass!(BadOptAccess => [ BAD_OPT_ACCESS ]); +declare_lint_pass!(BadOptAccess => [BAD_OPT_ACCESS]); impl LateLintPass<'_> for BadOptAccess { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs index c552b9832553a..de642f373b5c4 100644 --- a/compiler/rustc_lint/src/let_underscore.rs +++ b/compiler/rustc_lint/src/let_underscore.rs @@ -104,6 +104,7 @@ const SYNC_GUARD_SYMBOLS: [Symbol; 3] = [ ]; impl<'tcx> LateLintPass<'tcx> for LetUnderscore { + #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn check_local(&mut self, cx: &LateContext<'_>, local: &hir::Local<'_>) { if matches!(local.source, rustc_hir::LocalSource::AsyncFn) { return; diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index ad4a0fc47db4e..2f08cd53b75a1 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -16,7 +16,7 @@ use crate::{ use rustc_ast as ast; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxIndexMap; -use rustc_errors::{DecorateLint, Diag, DiagnosticMessage, MultiSpan}; +use rustc_errors::{DecorateLint, Diag, DiagMessage, MultiSpan}; use rustc_feature::{Features, GateIssue}; use rustc_hir as hir; use rustc_hir::intravisit::{self, Visitor}; @@ -724,6 +724,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { }; } + #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn add(&mut self, attrs: &[ast::Attribute], is_crate_node: bool, source_hir_id: Option) { let sess = self.sess; for (attr_index, attr) in attrs.iter().enumerate() { @@ -1106,7 +1107,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { &self, lint: &'static Lint, span: Option, - msg: impl Into, + msg: impl Into, decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>), ) { let (level, src) = self.lint_level(lint); diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index a9a2592ac7abf..7e0ac1bfff121 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -5,8 +5,8 @@ use std::num::NonZero; use crate::errors::RequestedLevel; use crate::fluent_generated as fluent; use rustc_errors::{ - codes::*, AddToDiagnostic, Applicability, DecorateLint, Diag, DiagStyledString, - DiagnosticMessage, EmissionGuarantee, SubdiagnosticMessageOp, SuggestionStyle, + codes::*, AddToDiagnostic, Applicability, DecorateLint, Diag, DiagMessage, DiagStyledString, + EmissionGuarantee, SubdiagMessageOp, SuggestionStyle, }; use rustc_hir::def_id::DefId; use rustc_macros::{LintDiagnostic, Subdiagnostic}; @@ -141,7 +141,7 @@ impl<'a> DecorateLint<'a, ()> for BuiltinMissingDebugImpl<'_> { diag.arg("debug", self.tcx.def_path_str(self.def_id)); } - fn msg(&self) -> DiagnosticMessage { + fn msg(&self) -> DiagMessage { fluent::lint_builtin_missing_debug_impl } } @@ -251,7 +251,7 @@ impl<'a> DecorateLint<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> { ); } - fn msg(&self) -> DiagnosticMessage { + fn msg(&self) -> DiagMessage { fluent::lint_ungated_async_fn_track_caller } } @@ -271,7 +271,7 @@ pub struct SuggestChangingAssocTypes<'a, 'b> { } impl<'a, 'b> AddToDiagnostic for SuggestChangingAssocTypes<'a, 'b> { - fn add_to_diagnostic_with>( + fn add_to_diagnostic_with>( self, diag: &mut Diag<'_, G>, _f: F, @@ -327,7 +327,7 @@ pub struct BuiltinTypeAliasGenericBoundsSuggestion { } impl AddToDiagnostic for BuiltinTypeAliasGenericBoundsSuggestion { - fn add_to_diagnostic_with>( + fn add_to_diagnostic_with>( self, diag: &mut Diag<'_, G>, _f: F, @@ -416,7 +416,7 @@ pub struct BuiltinFeatureIssueNote { } pub struct BuiltinUnpermittedTypeInit<'a> { - pub msg: DiagnosticMessage, + pub msg: DiagMessage, pub ty: Ty<'a>, pub label: Span, pub sub: BuiltinUnpermittedTypeInitSub, @@ -437,7 +437,7 @@ impl<'a> DecorateLint<'a, ()> for BuiltinUnpermittedTypeInit<'_> { self.sub.add_to_diagnostic(diag); } - fn msg(&self) -> DiagnosticMessage { + fn msg(&self) -> DiagMessage { self.msg.clone() } } @@ -448,7 +448,7 @@ pub struct BuiltinUnpermittedTypeInitSub { } impl AddToDiagnostic for BuiltinUnpermittedTypeInitSub { - fn add_to_diagnostic_with>( + fn add_to_diagnostic_with>( self, diag: &mut Diag<'_, G>, _f: F, @@ -503,7 +503,7 @@ pub struct BuiltinClashingExternSub<'a> { } impl AddToDiagnostic for BuiltinClashingExternSub<'_> { - fn add_to_diagnostic_with>( + fn add_to_diagnostic_with>( self, diag: &mut Diag<'_, G>, _f: F, @@ -785,7 +785,7 @@ pub struct HiddenUnicodeCodepointsDiagLabels { } impl AddToDiagnostic for HiddenUnicodeCodepointsDiagLabels { - fn add_to_diagnostic_with>( + fn add_to_diagnostic_with>( self, diag: &mut Diag<'_, G>, _f: F, @@ -803,7 +803,7 @@ pub enum HiddenUnicodeCodepointsDiagSub { // Used because of multiple multipart_suggestion and note impl AddToDiagnostic for HiddenUnicodeCodepointsDiagSub { - fn add_to_diagnostic_with>( + fn add_to_diagnostic_with>( self, diag: &mut Diag<'_, G>, _f: F, @@ -951,7 +951,7 @@ pub struct NonBindingLetSub { } impl AddToDiagnostic for NonBindingLetSub { - fn add_to_diagnostic_with>( + fn add_to_diagnostic_with>( self, diag: &mut Diag<'_, G>, _f: F, @@ -1179,7 +1179,7 @@ impl<'a> DecorateLint<'a, ()> for NonFmtPanicUnused { } } - fn msg(&self) -> DiagnosticMessage { + fn msg(&self) -> DiagMessage { fluent::lint_non_fmt_panic_unused } } @@ -1237,7 +1237,7 @@ pub enum NonSnakeCaseDiagSub { } impl AddToDiagnostic for NonSnakeCaseDiagSub { - fn add_to_diagnostic_with>( + fn add_to_diagnostic_with>( self, diag: &mut Diag<'_, G>, _f: F, @@ -1403,7 +1403,7 @@ impl<'a> DecorateLint<'a, ()> for DropTraitConstraintsDiag<'_> { diag.arg("needs_drop", self.tcx.def_path_str(self.def_id)); } - fn msg(&self) -> DiagnosticMessage { + fn msg(&self) -> DiagMessage { fluent::lint_drop_trait_constraints } } @@ -1419,7 +1419,7 @@ impl<'a> DecorateLint<'a, ()> for DropGlue<'_> { diag.arg("needs_drop", self.tcx.def_path_str(self.def_id)); } - fn msg(&self) -> DiagnosticMessage { + fn msg(&self) -> DiagMessage { fluent::lint_drop_glue } } @@ -1479,7 +1479,7 @@ pub enum OverflowingBinHexSign { } impl AddToDiagnostic for OverflowingBinHexSign { - fn add_to_diagnostic_with>( + fn add_to_diagnostic_with>( self, diag: &mut Diag<'_, G>, _f: F, @@ -1683,12 +1683,12 @@ pub struct ImproperCTypes<'a> { pub ty: Ty<'a>, pub desc: &'a str, pub label: Span, - pub help: Option, - pub note: DiagnosticMessage, + pub help: Option, + pub note: DiagMessage, pub span_note: Option, } -// Used because of the complexity of Option, DiagnosticMessage, and Option +// Used because of the complexity of Option, DiagMessage, and Option impl<'a> DecorateLint<'a, ()> for ImproperCTypes<'_> { fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { diag.arg("ty", self.ty); @@ -1703,7 +1703,7 @@ impl<'a> DecorateLint<'a, ()> for ImproperCTypes<'_> { } } - fn msg(&self) -> DiagnosticMessage { + fn msg(&self) -> DiagMessage { fluent::lint_improper_ctypes } } @@ -1846,7 +1846,7 @@ impl<'a> DecorateLint<'a, ()> for UnusedDef<'_, '_> { } } - fn msg(&self) -> DiagnosticMessage { + fn msg(&self) -> DiagMessage { fluent::lint_unused_def } } @@ -1923,7 +1923,7 @@ impl<'a> DecorateLint<'a, ()> for AsyncFnInTraitDiag { } } - fn msg(&self) -> DiagnosticMessage { + fn msg(&self) -> DiagMessage { fluent::lint_async_fn_in_trait } } diff --git a/compiler/rustc_lint/src/non_ascii_idents.rs b/compiler/rustc_lint/src/non_ascii_idents.rs index 5e66ade035774..79bc78ae55a8d 100644 --- a/compiler/rustc_lint/src/non_ascii_idents.rs +++ b/compiler/rustc_lint/src/non_ascii_idents.rs @@ -172,7 +172,7 @@ impl EarlyLintPass for NonAsciiIdents { } let mut has_non_ascii_idents = false; - let symbols = cx.sess().parse_sess.symbol_gallery.symbols.lock(); + let symbols = cx.sess().psess.symbol_gallery.symbols.lock(); // Sort by `Span` so that error messages make sense with respect to the // order of identifier locations in the code. diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs index ebef77f687972..a2d07fff5067c 100644 --- a/compiler/rustc_lint/src/non_fmt_panic.rs +++ b/compiler/rustc_lint/src/non_fmt_panic.rs @@ -231,7 +231,7 @@ fn check_panic_str<'tcx>( let fmt_span = arg.span.source_callsite(); - let (snippet, style) = match cx.sess().parse_sess.source_map().span_to_snippet(fmt_span) { + let (snippet, style) = match cx.sess().psess.source_map().span_to_snippet(fmt_span) { Ok(snippet) => { // Count the number of `#`s between the `r` and `"`. let style = snippet.strip_prefix('r').and_then(|s| s.find('"')); @@ -282,7 +282,7 @@ fn check_panic_str<'tcx>( /// Given the span of `some_macro!(args);`, gives the span of `(` and `)`, /// and the type of (opening) delimiter used. fn find_delimiters(cx: &LateContext<'_>, span: Span) -> Option<(Span, Span, char)> { - let snippet = cx.sess().parse_sess.source_map().span_to_snippet(span).ok()?; + let snippet = cx.sess().psess.source_map().span_to_snippet(span).ok()?; let (open, open_ch) = snippet.char_indices().find(|&(_, c)| "([{".contains(c))?; let close = snippet.rfind(|c| ")]}".contains(c))?; Some(( diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index 6cb6fd1cbd550..a4fd5a7c45f97 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -14,6 +14,7 @@ declare_lint! { /// ### Example /// /// ```rust + /// #![warn(non_local_definitions)] /// trait MyTrait {} /// struct MyStruct; /// @@ -36,7 +37,7 @@ declare_lint! { /// All nested bodies (functions, enum discriminant, array length, consts) (expect for /// `const _: Ty = { ... }` in top-level module, which is still undecided) are checked. pub NON_LOCAL_DEFINITIONS, - Warn, + Allow, "checks for non-local definitions", report_in_external_macro } diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index a87e2410b3d8e..5d36a8b3d0e9c 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -14,7 +14,7 @@ use crate::{LateContext, LateLintPass, LintContext}; use rustc_ast as ast; use rustc_attr as attr; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::DiagnosticMessage; +use rustc_errors::DiagMessage; use rustc_hir as hir; use rustc_hir::{is_range_literal, Expr, ExprKind, Node}; use rustc_middle::ty::layout::{IntegerExt, LayoutOf, SizeSkeleton}; @@ -959,7 +959,7 @@ struct ImproperCTypesVisitor<'a, 'tcx> { enum FfiResult<'tcx> { FfiSafe, FfiPhantom(Ty<'tcx>), - FfiUnsafe { ty: Ty<'tcx>, reason: DiagnosticMessage, help: Option }, + FfiUnsafe { ty: Ty<'tcx>, reason: DiagMessage, help: Option }, } pub(crate) fn nonnull_optimization_guaranteed<'tcx>( @@ -1446,8 +1446,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { &mut self, ty: Ty<'tcx>, sp: Span, - note: DiagnosticMessage, - help: Option, + note: DiagMessage, + help: Option, ) { let lint = match self.mode { CItemKind::Declaration => IMPROPER_CTYPES, @@ -1474,9 +1474,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { fn check_for_opaque_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool { struct ProhibitOpaqueTypes; impl<'tcx> ty::visit::TypeVisitor> for ProhibitOpaqueTypes { - type BreakTy = Ty<'tcx>; + type Result = ControlFlow>; - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { if !ty.has_opaque_types() { return ControlFlow::Continue(()); } @@ -1620,9 +1620,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } impl<'vis, 'a, 'tcx> ty::visit::TypeVisitor> for FnPtrFinder<'vis, 'a, 'tcx> { - type BreakTy = Ty<'tcx>; + type Result = ControlFlow>; - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { if let ty::FnPtr(sig) = ty.kind() && !self.visitor.is_internal_abi(sig.abi()) { diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 3481c66da702e..f84d1c6c2d0aa 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -20,6 +20,7 @@ use rustc_span::symbol::Symbol; use rustc_span::symbol::{kw, sym}; use rustc_span::{BytePos, Span}; use std::iter; +use std::ops::ControlFlow; declare_lint! { /// The `unused_must_use` lint detects unused result of a type flagged as @@ -753,21 +754,18 @@ trait UnusedDelimLint { // fn f(){(print!(á // ``` use rustc_ast::visit::{walk_expr, Visitor}; - struct ErrExprVisitor { - has_error: bool, - } + struct ErrExprVisitor; impl<'ast> Visitor<'ast> for ErrExprVisitor { - fn visit_expr(&mut self, expr: &'ast ast::Expr) { + type Result = ControlFlow<()>; + fn visit_expr(&mut self, expr: &'ast ast::Expr) -> ControlFlow<()> { if let ExprKind::Err(_) = expr.kind { - self.has_error = true; - return; + ControlFlow::Break(()) + } else { + walk_expr(self, expr) } - walk_expr(self, expr) } } - let mut visitor = ErrExprVisitor { has_error: false }; - visitor.visit_expr(value); - if visitor.has_error { + if ErrExprVisitor.visit_expr(value).is_break() { return; } let spans = match value.kind { diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 94f8bbe2437f8..f2560b35aa2e1 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -67,6 +67,7 @@ declare_lint_pass! { MISSING_FRAGMENT_SPECIFIER, MUST_NOT_SUSPEND, NAMED_ARGUMENTS_USED_POSITIONALLY, + NON_CONTIGUOUS_RANGE_ENDPOINTS, NON_EXHAUSTIVE_OMITTED_PATTERNS, ORDER_DEPENDENT_TRAIT_OBJECTS, OVERLAPPING_RANGE_ENDPOINTS, @@ -812,6 +813,36 @@ declare_lint! { "detects range patterns with overlapping endpoints" } +declare_lint! { + /// The `non_contiguous_range_endpoints` lint detects likely off-by-one errors when using + /// exclusive [range patterns]. + /// + /// [range patterns]: https://doc.rust-lang.org/nightly/reference/patterns.html#range-patterns + /// + /// ### Example + /// + /// ```rust + /// # #![feature(exclusive_range_pattern)] + /// let x = 123u32; + /// match x { + /// 0..100 => { println!("small"); } + /// 101..1000 => { println!("large"); } + /// _ => { println!("larger"); } + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// It is likely a mistake to have range patterns in a match expression that miss out a single + /// number. Check that the beginning and end values are what you expect, and keep in mind that + /// with `..=` the right bound is inclusive, and with `..` it is exclusive. + pub NON_CONTIGUOUS_RANGE_ENDPOINTS, + Warn, + "detects off-by-one errors with exclusive range patterns" +} + declare_lint! { /// The `bindings_with_variant_name` lint detects pattern bindings with /// the same name as one of the matched variants. diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 198008d4d0db6..7f200a7b623d6 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -8,7 +8,7 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::stable_hasher::{ HashStable, StableCompare, StableHasher, ToStableHashKey, }; -use rustc_error_messages::{DiagnosticMessage, MultiSpan}; +use rustc_error_messages::{DiagMessage, MultiSpan}; use rustc_hir::HashStableContext; use rustc_hir::HirId; use rustc_span::edition::Edition; @@ -569,7 +569,7 @@ pub struct AmbiguityErrorDiag { // This could be a closure, but then implementing derive trait // becomes hacky (and it gets allocated). #[derive(Debug)] -pub enum BuiltinLintDiagnostics { +pub enum BuiltinLintDiag { Normal, AbsPathWithModule(Span), ProcMacroDeriveResolutionFallback(Span), @@ -674,7 +674,7 @@ pub struct BufferedEarlyLint { pub span: MultiSpan, /// The lint message. - pub msg: DiagnosticMessage, + pub msg: DiagMessage, /// The `NodeId` of the AST node that generated the lint. pub node_id: NodeId, @@ -684,7 +684,7 @@ pub struct BufferedEarlyLint { pub lint_id: LintId, /// Customization of the `Diag<'_>` for the lint. - pub diagnostic: BuiltinLintDiagnostics, + pub diagnostic: BuiltinLintDiag, } #[derive(Default, Debug)] @@ -703,8 +703,8 @@ impl LintBuffer { lint: &'static Lint, node_id: NodeId, span: MultiSpan, - msg: impl Into, - diagnostic: BuiltinLintDiagnostics, + msg: impl Into, + diagnostic: BuiltinLintDiag, ) { let lint_id = LintId::of(lint); let msg = msg.into(); @@ -721,9 +721,9 @@ impl LintBuffer { lint: &'static Lint, id: NodeId, sp: impl Into, - msg: impl Into, + msg: impl Into, ) { - self.add_lint(lint, id, sp.into(), msg, BuiltinLintDiagnostics::Normal) + self.add_lint(lint, id, sp.into(), msg, BuiltinLintDiag::Normal) } pub fn buffer_lint_with_diagnostic( @@ -731,8 +731,8 @@ impl LintBuffer { lint: &'static Lint, id: NodeId, sp: impl Into, - msg: impl Into, - diagnostic: BuiltinLintDiagnostics, + msg: impl Into, + diagnostic: BuiltinLintDiag, ) { self.add_lint(lint, id, sp.into(), msg, diagnostic) } diff --git a/compiler/rustc_llvm/Cargo.toml b/compiler/rustc_llvm/Cargo.toml index 6598f1db86dac..c206380a06ff3 100644 --- a/compiler/rustc_llvm/Cargo.toml +++ b/compiler/rustc_llvm/Cargo.toml @@ -8,12 +8,7 @@ edition = "2021" libc = "0.2.73" # tidy-alphabetical-end -# FIXME: updating cc past 1.0.79 breaks libstd bootstrapping, pin -# to the last working version here so `cargo update` doesn't cause the -# a higher version to be selected -# https://github.com/rust-lang/cc-rs/issues/913 -# 1.0.{84, 85} fix this but have been yanked [build-dependencies] # tidy-alphabetical-start -cc = "=1.0.79" +cc = "1.0.90" # tidy-alphabetical-end diff --git a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp index 627be99751343..60789b07e54ea 100644 --- a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp @@ -120,7 +120,7 @@ extern "C" void LLVMRustCoverageWriteFilenamesSectionToBuffer( } auto FilenamesWriter = coverage::CoverageFilenamesSectionWriter(ArrayRef(FilenameRefs)); - RawRustStringOstream OS(BufferOut); + auto OS = RawRustStringOstream(BufferOut); FilenamesWriter.write(OS); } @@ -160,7 +160,7 @@ extern "C" void LLVMRustCoverageWriteMappingToBuffer( ArrayRef(VirtualFileMappingIDs, NumVirtualFileMappingIDs), Expressions, MappingRegions); - RawRustStringOstream OS(BufferOut); + auto OS = RawRustStringOstream(BufferOut); CoverageMappingWriter.write(OS); } @@ -168,23 +168,23 @@ extern "C" LLVMValueRef LLVMRustCoverageCreatePGOFuncNameVar( LLVMValueRef F, const char *FuncName, size_t FuncNameLen) { - StringRef FuncNameRef(FuncName, FuncNameLen); + auto FuncNameRef = StringRef(FuncName, FuncNameLen); return wrap(createPGOFuncNameVar(*cast(unwrap(F)), FuncNameRef)); } extern "C" uint64_t LLVMRustCoverageHashByteArray( const char *Bytes, size_t NumBytes) { - StringRef StrRef(Bytes, NumBytes); + auto StrRef = StringRef(Bytes, NumBytes); return IndexedInstrProf::ComputeHash(StrRef); } static void WriteSectionNameToString(LLVMModuleRef M, InstrProfSectKind SK, RustStringRef Str) { - Triple TargetTriple(unwrap(M)->getTargetTriple()); + auto TargetTriple = Triple(unwrap(M)->getTargetTriple()); auto name = getInstrProfSectionName(SK, TargetTriple.getObjectFormat()); - RawRustStringOstream OS(Str); + auto OS = RawRustStringOstream(Str); OS << name; } @@ -200,7 +200,7 @@ extern "C" void LLVMRustCoverageWriteFuncSectionNameToString(LLVMModuleRef M, extern "C" void LLVMRustCoverageWriteMappingVarNameToString(RustStringRef Str) { auto name = getCoverageMappingVarName(); - RawRustStringOstream OS(Str); + auto OS = RawRustStringOstream(Str); OS << name; } diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 4ec784e259058..f6253068eaa63 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -77,9 +77,9 @@ extern "C" void LLVMRustTimeTraceProfilerFinishThread() { } extern "C" void LLVMRustTimeTraceProfilerFinish(const char* FileName) { - StringRef FN(FileName); + auto FN = StringRef(FileName); std::error_code EC; - raw_fd_ostream OS(FN, EC, sys::fs::CD_CreateAlways); + auto OS = raw_fd_ostream(FN, EC, sys::fs::CD_CreateAlways); timeTraceProfilerWrite(OS); timeTraceProfilerCleanup(); @@ -424,7 +424,7 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( auto CM = fromRust(RustCM); std::string Error; - Triple Trip(Triple::normalize(TripleStr)); + auto Trip = Triple(Triple::normalize(TripleStr)); const llvm::Target *TheTarget = TargetRegistry::lookupTarget(Trip.getTriple(), Error); if (TheTarget == nullptr) { @@ -451,14 +451,30 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( Options.ObjectFilenameForDebug = OutputObjFile; } if (!strcmp("zlib", DebugInfoCompression) && llvm::compression::zlib::isAvailable()) { +#if LLVM_VERSION_GE(19, 0) + Options.MCOptions.CompressDebugSections = DebugCompressionType::Zlib; +#else Options.CompressDebugSections = DebugCompressionType::Zlib; +#endif } else if (!strcmp("zstd", DebugInfoCompression) && llvm::compression::zstd::isAvailable()) { +#if LLVM_VERSION_GE(19, 0) + Options.MCOptions.CompressDebugSections = DebugCompressionType::Zstd; +#else Options.CompressDebugSections = DebugCompressionType::Zstd; +#endif } else if (!strcmp("none", DebugInfoCompression)) { +#if LLVM_VERSION_GE(19, 0) + Options.MCOptions.CompressDebugSections = DebugCompressionType::None; +#else Options.CompressDebugSections = DebugCompressionType::None; +#endif } +#if LLVM_VERSION_GE(19, 0) + Options.MCOptions.X86RelaxRelocations = RelaxELFRelocations; +#else Options.RelaxELFRelocations = RelaxELFRelocations; +#endif Options.UseInitArray = UseInitArray; #if LLVM_VERSION_LT(17, 0) @@ -537,8 +553,8 @@ extern "C" void LLVMRustDisposeTargetMachine(LLVMTargetMachineRef TM) { // TargetLibraryInfo pass, so we use this method to do so. extern "C" void LLVMRustAddLibraryInfo(LLVMPassManagerRef PMR, LLVMModuleRef M, bool DisableSimplifyLibCalls) { - Triple TargetTriple(unwrap(M)->getTargetTriple()); - TargetLibraryInfoImpl TLII(TargetTriple); + auto TargetTriple = Triple(unwrap(M)->getTargetTriple()); + auto TLII = TargetLibraryInfoImpl(TargetTriple); if (DisableSimplifyLibCalls) TLII.disableAllFunctions(); unwrap(PMR)->add(new TargetLibraryInfoWrapperPass(TLII)); @@ -589,7 +605,7 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR, std::string ErrorInfo; std::error_code EC; - raw_fd_ostream OS(Path, EC, sys::fs::OF_None); + auto OS = raw_fd_ostream(Path, EC, sys::fs::OF_None); if (EC) ErrorInfo = EC.message(); if (ErrorInfo != "") { @@ -597,9 +613,9 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR, return LLVMRustResult::Failure; } - buffer_ostream BOS(OS); + auto BOS = buffer_ostream(OS); if (DwoPath) { - raw_fd_ostream DOS(DwoPath, EC, sys::fs::OF_None); + auto DOS = raw_fd_ostream(DwoPath, EC, sys::fs::OF_None); EC.clear(); if (EC) ErrorInfo = EC.message(); @@ -607,7 +623,7 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR, LLVMRustSetLastError(ErrorInfo.c_str()); return LLVMRustResult::Failure; } - buffer_ostream DBOS(DOS); + auto DBOS = buffer_ostream(DOS); unwrap(Target)->addPassesToEmitFile(*PM, BOS, &DBOS, FileType, false); PM->run(*unwrap(M)); } else { @@ -796,7 +812,7 @@ LLVMRustOptimize( DebugInfoForProfiling); } - PassBuilder PB(TM, PTO, PGOOpt, &PIC); + auto PB = PassBuilder(TM, PTO, PGOOpt, &PIC); LoopAnalysisManager LAM; FunctionAnalysisManager FAM; CGSCCAnalysisManager CGAM; @@ -1112,7 +1128,7 @@ extern "C" LLVMRustResult LLVMRustPrintModule(LLVMModuleRef M, const char *Path, DemangleFn Demangle) { std::string ErrorInfo; std::error_code EC; - raw_fd_ostream OS(Path, EC, sys::fs::OF_None); + auto OS = raw_fd_ostream(Path, EC, sys::fs::OF_None); if (EC) ErrorInfo = EC.message(); if (ErrorInfo != "") { @@ -1120,8 +1136,8 @@ LLVMRustPrintModule(LLVMModuleRef M, const char *Path, DemangleFn Demangle) { return LLVMRustResult::Failure; } - RustAssemblyAnnotationWriter AAW(Demangle); - formatted_raw_ostream FOS(OS); + auto AAW = RustAssemblyAnnotationWriter(Demangle); + auto FOS = formatted_raw_ostream(OS); unwrap(M)->print(FOS, &AAW); return LLVMRustResult::Success; @@ -1281,8 +1297,8 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, // Load each module's summary and merge it into one combined index for (int i = 0; i < num_modules; i++) { auto module = &modules[i]; - StringRef buffer(module->data, module->len); - MemoryBufferRef mem_buffer(buffer, module->identifier); + auto buffer = StringRef(module->data, module->len); + auto mem_buffer = MemoryBufferRef(buffer, module->identifier); Ret->ModuleMap[module->identifier] = mem_buffer; @@ -1485,7 +1501,7 @@ LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M, return MOrErr; }; bool ClearDSOLocal = clearDSOLocalOnDeclarations(Mod, Target); - FunctionImporter Importer(Data->Index, Loader, ClearDSOLocal); + auto Importer = FunctionImporter(Data->Index, Loader, ClearDSOLocal); Expected Result = Importer.importFunctions(Mod, ImportList); if (!Result) { LLVMRustSetLastError(toString(Result.takeError()).c_str()); @@ -1510,7 +1526,7 @@ extern "C" LLVMRustThinLTOBuffer* LLVMRustThinLTOBufferCreate(LLVMModuleRef M, bool is_thin) { auto Ret = std::make_unique(); { - raw_string_ostream OS(Ret->data); + auto OS = raw_string_ostream(Ret->data); { if (is_thin) { PassBuilder PB; @@ -1557,8 +1573,8 @@ LLVMRustParseBitcodeForLTO(LLVMContextRef Context, const char *data, size_t len, const char *identifier) { - StringRef Data(data, len); - MemoryBufferRef Buffer(Data, identifier); + auto Data = StringRef(data, len); + auto Buffer = MemoryBufferRef(Data, identifier); unwrap(Context)->enableDebugTypeODRUniquing(); Expected> SrcOrError = parseBitcodeFile(Buffer, *unwrap(Context)); @@ -1576,8 +1592,8 @@ extern "C" const char *LLVMRustGetSliceFromObjectDataByName(const char *data, const char *name, size_t *out_len) { *out_len = 0; - StringRef Data(data, len); - MemoryBufferRef Buffer(Data, ""); // The id is unused. + auto Data = StringRef(data, len); + auto Buffer = MemoryBufferRef(Data, ""); // The id is unused. file_magic Type = identify_magic(Buffer.getBuffer()); Expected> ObjFileOrError = object::ObjectFile::createObjectFile(Buffer, Type); diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index cb7cce4da0d5e..3e998d428ee9a 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -66,12 +66,22 @@ static LLVM_THREAD_LOCAL char *LastError; static void FatalErrorHandler(void *UserData, const char* Reason, bool GenCrashDiag) { - // Do the same thing that the default error handler does. - std::cerr << "LLVM ERROR: " << Reason << std::endl; + // Once upon a time we emitted "LLVM ERROR:" specifically to mimic LLVM. Then, + // we developed crater and other tools which only expose logs, not error codes. + // Use a more greppable prefix that will still match the "LLVM ERROR:" prefix. + std::cerr << "rustc-LLVM ERROR: " << Reason << std::endl; // Since this error handler exits the process, we have to run any cleanup that // LLVM would run after handling the error. This might change with an LLVM // upgrade. + // + // In practice, this will do nothing, because the only cleanup LLVM does is + // to remove all files that were registered with it via a frontend calling + // one of the `createOutputFile` family of functions in LLVM and passing true + // to RemoveFileOnSignal, something that rustc does not do. However, it would + // be... inadvisable to suddenly stop running these handlers, if LLVM gets + // "interesting" ideas in the future about what cleanup should be done. + // We might even find it useful for generating less artifacts. sys::RunInterruptHandlers(); exit(101); @@ -109,7 +119,7 @@ extern "C" void LLVMRustSetNormalizedTarget(LLVMModuleRef M, extern "C" const char *LLVMRustPrintPassTimings(size_t *Len) { std::string buf; - raw_string_ostream SS(buf); + auto SS = raw_string_ostream(buf); TimerGroup::printAll(SS); SS.flush(); *Len = buf.length(); @@ -120,7 +130,7 @@ extern "C" const char *LLVMRustPrintPassTimings(size_t *Len) { extern "C" const char *LLVMRustPrintStatistics(size_t *Len) { std::string buf; - raw_string_ostream SS(buf); + auto SS = raw_string_ostream(buf); llvm::PrintStatistics(SS); SS.flush(); *Len = buf.length(); @@ -174,7 +184,7 @@ extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M, extern "C" LLVMValueRef LLVMRustGetOrInsertGlobal(LLVMModuleRef M, const char *Name, size_t NameLen, LLVMTypeRef Ty) { Module *Mod = unwrap(M); - StringRef NameRef(Name, NameLen); + auto NameRef = StringRef(Name, NameLen); // We don't use Module::getOrInsertGlobal because that returns a Constant*, // which may either be the real GlobalVariable*, or a constant bitcast of it @@ -285,7 +295,7 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) { template static inline void AddAttributes(T *t, unsigned Index, LLVMAttributeRef *Attrs, size_t AttrsLen) { AttributeList PAL = t->getAttributes(); - AttrBuilder B(t->getContext()); + auto B = AttrBuilder(t->getContext()); for (LLVMAttributeRef Attr : ArrayRef(Attrs, AttrsLen)) B.addAttribute(unwrap(Attr)); AttributeList PALNew = PAL.addAttributesAtIndex(t->getContext(), Index, B); @@ -1195,13 +1205,13 @@ extern "C" int64_t LLVMRustDIBuilderCreateOpLLVMFragment() { } extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Ty, RustStringRef Str) { - RawRustStringOstream OS(Str); + auto OS = RawRustStringOstream(Str); unwrap(Ty)->print(OS); } extern "C" void LLVMRustWriteValueToString(LLVMValueRef V, RustStringRef Str) { - RawRustStringOstream OS(Str); + auto OS = RawRustStringOstream(Str); if (!V) { OS << "(null)"; } else { @@ -1224,7 +1234,7 @@ extern "C" LLVMTypeRef LLVMRustArrayType(LLVMTypeRef ElementTy, DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Twine, LLVMTwineRef) extern "C" void LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef Str) { - RawRustStringOstream OS(Str); + auto OS = RawRustStringOstream(Str); unwrap(T)->print(OS); } @@ -1236,11 +1246,11 @@ extern "C" void LLVMRustUnpackOptimizationDiagnostic( llvm::DiagnosticInfoOptimizationBase *Opt = static_cast(unwrap(DI)); - RawRustStringOstream PassNameOS(PassNameOut); + auto PassNameOS = RawRustStringOstream(PassNameOut); PassNameOS << Opt->getPassName(); *FunctionOut = wrap(&Opt->getFunction()); - RawRustStringOstream FilenameOS(FilenameOut); + auto FilenameOS = RawRustStringOstream(FilenameOut); DiagnosticLocation loc = Opt->getLocation(); if (loc.isValid()) { *Line = loc.getLine(); @@ -1248,7 +1258,7 @@ extern "C" void LLVMRustUnpackOptimizationDiagnostic( FilenameOS << loc.getAbsolutePath(); } - RawRustStringOstream MessageOS(MessageOut); + auto MessageOS = RawRustStringOstream(MessageOut); MessageOS << Opt->getMsg(); } @@ -1291,8 +1301,8 @@ LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI, extern "C" void LLVMRustWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef DI, RustStringRef Str) { - RawRustStringOstream OS(Str); - DiagnosticPrinterRawOStream DP(OS); + auto OS = RawRustStringOstream(Str); + auto DP = DiagnosticPrinterRawOStream(OS); unwrap(DI)->print(DP); } @@ -1406,7 +1416,7 @@ extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) { default: { std::string error; - llvm::raw_string_ostream stream(error); + auto stream = llvm::raw_string_ostream(error); stream << "Rust does not support the TypeID: " << unwrap(Ty)->getTypeID() << " for the type: " << *unwrap(Ty); stream.flush(); @@ -1432,7 +1442,7 @@ extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef, unsigned* RangesOut, size_t* NumRanges) { SMDiagnostic& D = *unwrap(DRef); - RawRustStringOstream MessageOS(MessageOut); + auto MessageOS = RawRustStringOstream(MessageOut); MessageOS << D.getMessage(); switch (D.getKind()) { @@ -1539,6 +1549,31 @@ LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn, Name)); } +extern "C" LLVMValueRef +LLVMRustBuildCallBr(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn, + LLVMBasicBlockRef DefaultDest, + LLVMBasicBlockRef *IndirectDests, unsigned NumIndirectDests, + LLVMValueRef *Args, unsigned NumArgs, + OperandBundleDef **OpBundles, unsigned NumOpBundles, + const char *Name) { + Value *Callee = unwrap(Fn); + FunctionType *FTy = unwrap(Ty); + + // FIXME: Is there a way around this? + std::vector IndirectDestsUnwrapped; + IndirectDestsUnwrapped.reserve(NumIndirectDests); + for (unsigned i = 0; i < NumIndirectDests; ++i) { + IndirectDestsUnwrapped.push_back(unwrap(IndirectDests[i])); + } + + return wrap(unwrap(B)->CreateCallBr( + FTy, Callee, unwrap(DefaultDest), + ArrayRef(IndirectDestsUnwrapped), + ArrayRef(unwrap(Args), NumArgs), + ArrayRef(*OpBundles, NumOpBundles), + Name)); +} + extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B, LLVMBasicBlockRef BB) { auto Point = unwrap(BB)->getFirstInsertionPt(); @@ -1547,7 +1582,7 @@ extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B, extern "C" void LLVMRustSetComdat(LLVMModuleRef M, LLVMValueRef V, const char *Name, size_t NameLen) { - Triple TargetTriple(unwrap(M)->getTargetTriple()); + Triple TargetTriple = Triple(unwrap(M)->getTargetTriple()); GlobalObject *GV = unwrap(V); if (TargetTriple.supportsCOMDAT()) { StringRef NameRef(Name, NameLen); @@ -1711,7 +1746,7 @@ extern "C" LLVMRustModuleBuffer* LLVMRustModuleBufferCreate(LLVMModuleRef M) { auto Ret = std::make_unique(); { - raw_string_ostream OS(Ret->data); + auto OS = raw_string_ostream(Ret->data); WriteBitcodeToFile(*unwrap(M), OS); } return Ret.release(); @@ -1741,8 +1776,8 @@ LLVMRustModuleCost(LLVMModuleRef M) { extern "C" void LLVMRustModuleInstructionStats(LLVMModuleRef M, RustStringRef Str) { - RawRustStringOstream OS(Str); - llvm::json::OStream JOS(OS); + auto OS = RawRustStringOstream(Str); + auto JOS = llvm::json::OStream(OS); auto Module = unwrap(M); JOS.object([&] { @@ -1857,7 +1892,7 @@ extern "C" LLVMRustResult LLVMRustWriteImportLibrary( MinGW); if (Error) { std::string errorString; - llvm::raw_string_ostream stream(errorString); + auto stream = llvm::raw_string_ostream(errorString); stream << Error; stream.flush(); LLVMRustSetLastError(errorString.c_str()); @@ -2041,7 +2076,7 @@ extern "C" void LLVMRustContextConfigureDiagnosticHandler( } extern "C" void LLVMRustGetMangledName(LLVMValueRef V, RustStringRef Str) { - RawRustStringOstream OS(Str); + auto OS = RawRustStringOstream(Str); GlobalValue *GV = unwrap(V); Mangler().getNameWithPrefix(OS, GV, true); } diff --git a/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp index 91f84692df8f5..ee8239ef8e79d 100644 --- a/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp @@ -11,6 +11,7 @@ #include "llvm/ADT/SmallString.h" #include "llvm/IR/LLVMContext.h" #include "llvm/Object/ObjectFile.h" +#include using namespace llvm; using namespace llvm::sys; @@ -42,7 +43,7 @@ extern "C" void *LLVMRustGetSymbols( MemoryBuffer::getMemBuffer(StringRef(BufPtr, BufLen), StringRef("LLVMRustGetSymbolsObject"), false); SmallString<0> SymNameBuf; - raw_svector_ostream SymName(SymNameBuf); + auto SymName = raw_svector_ostream(SymNameBuf); // In the scenario when LLVMContext is populated SymbolicFile will contain a // reference to it, thus SymbolicFile should be destroyed first. @@ -60,7 +61,7 @@ extern "C" void *LLVMRustGetSymbols( if (!ObjOrErr) { Error E = ObjOrErr.takeError(); SmallString<0> ErrorBuf; - raw_svector_ostream Error(ErrorBuf); + auto Error = raw_svector_ostream(ErrorBuf); Error << E << '\0'; return ErrorCallback(Error.str().data()); } @@ -70,7 +71,7 @@ extern "C" void *LLVMRustGetSymbols( if (!ObjOrErr) { Error E = ObjOrErr.takeError(); SmallString<0> ErrorBuf; - raw_svector_ostream Error(ErrorBuf); + auto Error = raw_svector_ostream(ErrorBuf); Error << E << '\0'; return ErrorCallback(Error.str().data()); } @@ -83,7 +84,7 @@ extern "C" void *LLVMRustGetSymbols( continue; if (Error E = S.printName(SymName)) { SmallString<0> ErrorBuf; - raw_svector_ostream Error(ErrorBuf); + auto Error = raw_svector_ostream(ErrorBuf); Error << E << '\0'; return ErrorCallback(Error.str().data()); } diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs index 5659569c6450c..a1a7b19642b93 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs @@ -165,7 +165,7 @@ impl<'a> LintDiagnosticDerive<'a> { #implementation; } - fn msg(&self) -> rustc_errors::DiagnosticMessage { + fn msg(&self) -> rustc_errors::DiagMessage { #msg } } diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index 6cbebcc7320d1..ef326106404d5 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -93,7 +93,7 @@ impl SubdiagnosticDeriveBuilder { #f: __F ) where __G: rustc_errors::EmissionGuarantee, - __F: rustc_errors::SubdiagnosticMessageOp<__G>, + __F: rustc_errors::SubdiagMessageOp<__G>, { #implementation } diff --git a/compiler/rustc_macros/src/type_visitable.rs b/compiler/rustc_macros/src/type_visitable.rs index c8430380345b4..94e86e0e246fe 100644 --- a/compiler/rustc_macros/src/type_visitable.rs +++ b/compiler/rustc_macros/src/type_visitable.rs @@ -34,7 +34,14 @@ pub fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2: s.add_bounds(synstructure::AddBounds::Generics); let body_visit = s.each(|bind| { quote! { - ::rustc_middle::ty::visit::TypeVisitable::visit_with(#bind, __visitor)?; + match ::rustc_ast_ir::visit::VisitorResult::branch( + ::rustc_middle::ty::visit::TypeVisitable::visit_with(#bind, __visitor) + ) { + ::core::ops::ControlFlow::Continue(()) => {}, + ::core::ops::ControlFlow::Break(r) => { + return ::rustc_ast_ir::visit::VisitorResult::from_residual(r); + }, + } } }); s.bind_with(|_| synstructure::BindStyle::Move); @@ -45,9 +52,9 @@ pub fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2: fn visit_with<__V: ::rustc_middle::ty::visit::TypeVisitor<::rustc_middle::ty::TyCtxt<'tcx>>>( &self, __visitor: &mut __V - ) -> ::std::ops::ControlFlow<__V::BreakTy> { + ) -> __V::Result { match *self { #body_visit } - ::std::ops::ControlFlow::Continue(()) + <__V::Result as ::rustc_ast_ir::visit::VisitorResult>::output() } }, ) diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index f65fe1a29c7cc..72757d90e4238 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -947,6 +947,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } } + #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn report_unused_deps(&mut self, krate: &ast::Crate) { // Make a point span rather than covering the whole file let span = krate.spans.inner_span.shrink_to_lo(); @@ -971,7 +972,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { continue; } - self.sess.parse_sess.buffer_lint( + self.sess.psess.buffer_lint( lint::builtin::UNUSED_CRATE_DEPENDENCIES, span, ast::CRATE_NODE_ID, @@ -1132,7 +1133,13 @@ fn load_dylib(path: &Path, max_attempts: usize) -> Result { // Only try to recover from this specific error. if !matches!(err, libloading::Error::LoadLibraryExW { .. }) { - return Err(err.to_string()); + let err = format_dlopen_err(&err); + // We include the path of the dylib in the error ourselves, so + // if it's in the error, we strip it. + if let Some(err) = err.strip_prefix(&format!(": {}", path.display())) { + return Err(err.to_string()); + } + return Err(err); } last_error = Some(err); diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 90e68a6b5b916..dcccace12b00a 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -1077,7 +1077,7 @@ impl CrateError { crate_rejections, }); } else { - dcx.emit_err(errors::CannotFindCrate { + let error = errors::CannotFindCrate { span, crate_name, add_info, @@ -1091,11 +1091,18 @@ impl CrateError { profiler_runtime: Symbol::intern(&sess.opts.unstable_opts.profiler_runtime), locator_triple: locator.triple, is_ui_testing: sess.opts.unstable_opts.ui_testing, - }); + }; + // The diagnostic for missing core is very good, but it is followed by a lot of + // other diagnostics that do not add information. + if missing_core { + dcx.emit_fatal(error); + } else { + dcx.emit_err(error); + } } } CrateError::NotFound(crate_name) => { - dcx.emit_err(errors::CannotFindCrate { + let error = errors::CannotFindCrate { span, crate_name, add_info: String::new(), @@ -1105,7 +1112,14 @@ impl CrateError { profiler_runtime: Symbol::intern(&sess.opts.unstable_opts.profiler_runtime), locator_triple: sess.opts.target_triple.clone(), is_ui_testing: sess.opts.unstable_opts.ui_testing, - }); + }; + // The diagnostic for missing core is very good, but it is followed by a lot of + // other diagnostics that do not add information. + if missing_core { + dcx.emit_fatal(error); + } else { + dcx.emit_err(error); + } } } } diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index cdcc586b09e70..baa2e1ff60215 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -93,6 +93,7 @@ struct Collector<'tcx> { } impl<'tcx> Collector<'tcx> { + #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn process_module(&mut self, module: &ForeignModule) { let ForeignModule { def_id, abi, ref foreign_items } = *module; let def_id = def_id.expect_local(); diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index e7c80639a0d7c..da384007c22c2 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -420,7 +420,7 @@ impl<'a, 'tcx> Decodable> for ExpnIndex { impl<'a, 'tcx> SpanDecoder for DecodeContext<'a, 'tcx> { fn decode_attr_id(&mut self) -> rustc_span::AttrId { let sess = self.sess.expect("can't decode AttrId without Session"); - sess.parse_sess.attr_id_generator.mk_attr_id() + sess.psess.attr_id_generator.mk_attr_id() } fn decode_crate_num(&mut self) -> CrateNum { @@ -504,7 +504,11 @@ impl<'a, 'tcx> SpanDecoder for DecodeContext<'a, 'tcx> { let data = if tag.kind() == SpanKind::Indirect { // Skip past the tag we just peek'd. self.read_u8(); - let offset_or_position = self.read_usize(); + // indirect tag lengths are safe to access, since they're (0, 8) + let bytes_needed = tag.length().unwrap().0 as usize; + let mut total = [0u8; usize::BITS as usize / 8]; + total[..bytes_needed].copy_from_slice(self.read_raw_bytes(bytes_needed)); + let offset_or_position = usize::from_le_bytes(total); let position = if tag.is_relative_offset() { start - offset_or_position } else { @@ -1749,7 +1753,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { self.root.tables.attr_flags.get(self, index) } - fn get_intrinsic(self, index: DefIndex) -> Option { + fn get_intrinsic(self, index: DefIndex) -> Option { self.root.tables.intrinsic.get(self, index).map(|d| d.decode(self)) } diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 2f507b258fe7e..1c59af5158981 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -356,7 +356,7 @@ provide! { tcx, def_id, other, cdata, cdata.get_stability_implications(tcx).iter().copied().collect() } stripped_cfg_items => { cdata.get_stripped_cfg_items(cdata.cnum, tcx) } - intrinsic => { cdata.get_intrinsic(def_id.index) } + intrinsic_raw => { cdata.get_intrinsic(def_id.index) } defined_lang_items => { cdata.get_lang_items(tcx) } diagnostic_items => { cdata.get_diagnostic_items() } missing_lang_items => { cdata.get_missing_lang_items(tcx) } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index fdb2b4f202415..6e9cbfdcfee28 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -172,11 +172,19 @@ impl<'a, 'tcx> SpanEncoder for EncodeContext<'a, 'tcx> { // previously saved offset must be smaller than the current position. let offset = self.opaque.position() - last_location; if offset < last_location { - SpanTag::indirect(true).encode(self); - offset.encode(self); + let needed = bytes_needed(offset); + SpanTag::indirect(true, needed as u8).encode(self); + self.opaque.write_with(|dest| { + *dest = offset.to_le_bytes(); + needed + }); } else { - SpanTag::indirect(false).encode(self); - last_location.encode(self); + let needed = bytes_needed(last_location); + SpanTag::indirect(false, needed as u8).encode(self); + self.opaque.write_with(|dest| { + *dest = last_location.to_le_bytes(); + needed + }); } } Entry::Vacant(v) => { @@ -212,6 +220,10 @@ impl<'a, 'tcx> SpanEncoder for EncodeContext<'a, 'tcx> { } } +fn bytes_needed(n: usize) -> usize { + (usize::BITS - n.leading_zeros()).div_ceil(u8::BITS) as usize +} + impl<'a, 'tcx> Encodable> for SpanData { fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) { // Don't serialize any `SyntaxContext`s from a proc-macro crate, @@ -1053,11 +1065,14 @@ fn should_encode_mir( // Full-fledged functions + closures DefKind::AssocFn | DefKind::Fn | DefKind::Closure => { let generics = tcx.generics_of(def_id); - let opt = tcx.sess.opts.unstable_opts.always_encode_mir + let mut opt = tcx.sess.opts.unstable_opts.always_encode_mir || (tcx.sess.opts.output_types.should_codegen() && reachable_set.contains(&def_id) && (generics.requires_monomorphization(tcx) || tcx.cross_crate_inlinable(def_id))); + if let Some(intrinsic) = tcx.intrinsic(def_id) { + opt &= !intrinsic.must_be_overridden; + } // The function has a `const` modifier or is in a `#[const_trait]`. let is_const_fn = tcx.is_const_fn_raw(def_id.to_def_id()) || tcx.is_const_default_method(def_id.to_def_id()); @@ -1409,9 +1424,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if let DefKind::Fn | DefKind::AssocFn = def_kind { self.tables.asyncness.set_some(def_id.index, tcx.asyncness(def_id)); record_array!(self.tables.fn_arg_names[def_id] <- tcx.fn_arg_names(def_id)); - if let Some(name) = tcx.intrinsic(def_id) { - record!(self.tables.intrinsic[def_id] <- name); - } + } + if let Some(name) = tcx.intrinsic(def_id) { + record!(self.tables.intrinsic[def_id] <- name); } if let DefKind::TyParam = def_kind { let default = self.tcx.object_lifetime_default(def_id); @@ -1789,7 +1804,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let stability = tcx.lookup_stability(CRATE_DEF_ID); let macros = self.lazy_array(tcx.resolutions(()).proc_macros.iter().map(|p| p.local_def_index)); - for (i, span) in self.tcx.sess.parse_sess.proc_macro_quoted_spans() { + for (i, span) in self.tcx.sess.psess.proc_macro_quoted_spans() { let span = self.lazy(span); self.tables.proc_macro_quoted_spans.set_some(i, span); } @@ -1978,9 +1993,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if of_trait && let Some(header) = tcx.impl_trait_header(def_id) { record!(self.tables.impl_trait_header[def_id] <- header); - let trait_ref = header.map_bound(|h| h.trait_ref); - let trait_ref = trait_ref.instantiate_identity(); + let trait_ref = header.trait_ref.instantiate_identity(); let simplified_self_ty = fast_reject::simplify_type( self.tcx, trait_ref.self_ty(), diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 9c0e8029571d3..8aa31ef564f55 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -375,7 +375,7 @@ macro_rules! define_tables { define_tables! { - defaulted: - intrinsic: Table>>, + intrinsic: Table>>, is_macro_rules: Table, is_type_alias_impl_trait: Table, type_alias_is_lazy: Table, @@ -423,7 +423,7 @@ define_tables! { variances_of: Table>, fn_sig: Table>>>, codegen_fn_attrs: Table>, - impl_trait_header: Table>>>, + impl_trait_header: Table>>, const_param_default: Table>>>, object_lifetime_default: Table>, optimized_mir: Table>>, @@ -530,11 +530,13 @@ impl SpanTag { SpanTag(data) } - fn indirect(relative: bool) -> SpanTag { + fn indirect(relative: bool, length_bytes: u8) -> SpanTag { let mut tag = SpanTag(SpanKind::Indirect as u8); if relative { tag.0 |= 0b100; } + assert!(length_bytes <= 8); + tag.0 |= length_bytes << 3; tag } diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs index 0f6ec656932ce..0d3cffd204770 100644 --- a/compiler/rustc_middle/src/error.rs +++ b/compiler/rustc_middle/src/error.rs @@ -1,6 +1,6 @@ use std::fmt; -use rustc_errors::{codes::*, DiagArgName, DiagArgValue, DiagnosticMessage}; +use rustc_errors::{codes::*, DiagArgName, DiagArgValue, DiagMessage}; use rustc_macros::Diagnostic; use rustc_span::{Span, Symbol}; @@ -93,16 +93,16 @@ pub(super) struct ConstNotUsedTraitAlias { } pub struct CustomSubdiagnostic<'a> { - pub msg: fn() -> DiagnosticMessage, + pub msg: fn() -> DiagMessage, pub add_args: Box, } impl<'a> CustomSubdiagnostic<'a> { - pub fn label(x: fn() -> DiagnosticMessage) -> Self { + pub fn label(x: fn() -> DiagMessage) -> Self { Self::label_and_then(x, |_| {}) } pub fn label_and_then( - msg: fn() -> DiagnosticMessage, + msg: fn() -> DiagMessage, f: F, ) -> Self { Self { msg, add_args: Box::new(move |x| f(x)) } diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index db27e2bd6301b..4960369a0a7a9 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -3,8 +3,7 @@ use crate::middle::debugger_visualizer::DebuggerVisualizerFile; use crate::query::LocalCrate; use crate::ty::TyCtxt; use rustc_ast as ast; -use rustc_ast::visit::VisitorResult; -use rustc_ast::walk_list; +use rustc_ast::visit::{walk_list, VisitorResult}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::svh::Svh; diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 6a3522553c451..d8d6899f05704 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -2,7 +2,7 @@ use std::cmp; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sorted_map::SortedMap; -use rustc_errors::{Diag, DiagnosticMessage, MultiSpan}; +use rustc_errors::{Diag, DiagMessage, MultiSpan}; use rustc_hir::{HirId, ItemLocalId}; use rustc_session::lint::{ builtin::{self, FORBIDDEN_LINT_GROUPS}, @@ -268,7 +268,7 @@ pub fn lint_level( level: Level, src: LintLevelSource, span: Option, - msg: impl Into, + msg: impl Into, decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>), ) { // Avoid codegen bloat from monomorphization by immediately doing dyn dispatch of `decorate` to @@ -280,7 +280,7 @@ pub fn lint_level( level: Level, src: LintLevelSource, span: Option, - msg: impl Into, + msg: impl Into, decorate: Box FnOnce(&'b mut Diag<'a, ()>)>, ) { // Check for future incompatibility lints and issue a stronger warning. diff --git a/compiler/rustc_middle/src/macros.rs b/compiler/rustc_middle/src/macros.rs index 26ca90db018e6..0ee97a6bed037 100644 --- a/compiler/rustc_middle/src/macros.rs +++ b/compiler/rustc_middle/src/macros.rs @@ -85,9 +85,9 @@ macro_rules! TrivialTypeTraversalImpls { fn visit_with>>( &self, _: &mut F) - -> ::std::ops::ControlFlow + -> F::Result { - ::std::ops::ControlFlow::Continue(()) + ::output() } } )+ diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index 31f986403ab9d..c393287da95c9 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -16,7 +16,7 @@ use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdMap}; use rustc_hir::{self as hir, HirId}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_session::lint::builtin::{DEPRECATED, DEPRECATED_IN_FUTURE, SOFT_UNSTABLE}; -use rustc_session::lint::{BuiltinLintDiagnostics, Level, Lint, LintBuffer}; +use rustc_session::lint::{BuiltinLintDiag, Level, Lint, LintBuffer}; use rustc_session::parse::feature_err_issue; use rustc_session::Session; use rustc_span::symbol::{sym, Symbol}; @@ -199,7 +199,7 @@ pub fn early_report_deprecation( return; } - let diag = BuiltinLintDiagnostics::DeprecatedMacro(suggestion, span); + let diag = BuiltinLintDiag::DeprecatedMacro(suggestion, span); lint_buffer.buffer_lint_with_diagnostic(lint, node_id, span, message, diag); } @@ -269,7 +269,7 @@ fn suggestion_for_allocator_api( if feature == sym::allocator_api { if let Some(trait_) = tcx.opt_parent(def_id) { if tcx.is_diagnostic_item(sym::Vec, trait_) { - let sm = tcx.sess.parse_sess.source_map(); + let sm = tcx.sess.psess.source_map(); let inner_types = sm.span_extend_to_prev_char(span, '<', true); if let Ok(snippet) = sm.span_to_snippet(inner_types) { return Some(( diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index b85354e10f978..aea88c4588be1 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -6,9 +6,7 @@ use crate::ty::{layout, tls, Ty, TyCtxt, ValTree}; use rustc_ast_ir::Mutability; use rustc_data_structures::sync::Lock; -use rustc_errors::{ - DiagArgName, DiagArgValue, DiagnosticMessage, ErrorGuaranteed, IntoDiagnosticArg, -}; +use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, ErrorGuaranteed, IntoDiagnosticArg}; use rustc_macros::HashStable; use rustc_session::CtfeBacktrace; use rustc_span::{def_id::DefId, Span, DUMMY_SP}; @@ -489,7 +487,7 @@ pub enum ResourceExhaustionInfo { /// A trait for machine-specific errors (or other "machine stop" conditions). pub trait MachineStopType: Any + fmt::Debug + Send { /// The diagnostic message for this error - fn diagnostic_message(&self) -> DiagnosticMessage; + fn diagnostic_message(&self) -> DiagMessage; /// Add diagnostic arguments by passing name and value pairs to `adder`, which are passed to /// fluent for formatting the translated diagnostic message. fn add_args(self: Box, adder: &mut dyn FnMut(DiagArgName, DiagArgValue)); diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 5ce2e26a0bce3..0221bc6c36383 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -14,9 +14,7 @@ use crate::ty::{AdtDef, InstanceDef, UserTypeAnnotationIndex}; use crate::ty::{GenericArg, GenericArgsRef}; use rustc_data_structures::captures::Captures; -use rustc_errors::{ - DiagArgName, DiagArgValue, DiagnosticMessage, ErrorGuaranteed, IntoDiagnosticArg, -}; +use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, ErrorGuaranteed, IntoDiagnosticArg}; use rustc_hir::def::{CtorKind, Namespace}; use rustc_hir::def_id::{DefId, CRATE_DEF_ID}; use rustc_hir::{self, CoroutineDesugaring, CoroutineKind, ImplicitSelfKind}; @@ -1718,13 +1716,13 @@ mod size_asserts { use super::*; use rustc_data_structures::static_assert_size; // tidy-alphabetical-start - static_assert_size!(BasicBlockData<'_>, 136); + static_assert_size!(BasicBlockData<'_>, 144); static_assert_size!(LocalDecl<'_>, 40); static_assert_size!(SourceScopeData<'_>, 72); static_assert_size!(Statement<'_>, 32); static_assert_size!(StatementKind<'_>, 16); - static_assert_size!(Terminator<'_>, 104); - static_assert_size!(TerminatorKind<'_>, 88); + static_assert_size!(Terminator<'_>, 112); + static_assert_size!(TerminatorKind<'_>, 96); static_assert_size!(VarDebugInfo<'_>, 88); // tidy-alphabetical-end } diff --git a/compiler/rustc_middle/src/mir/patch.rs b/compiler/rustc_middle/src/mir/patch.rs index b81e9fa1aab64..334122970178e 100644 --- a/compiler/rustc_middle/src/mir/patch.rs +++ b/compiler/rustc_middle/src/mir/patch.rs @@ -11,6 +11,8 @@ pub struct MirPatch<'tcx> { resume_block: Option, // Only for unreachable in cleanup path. unreachable_cleanup_block: Option, + // Only for unreachable not in cleanup path. + unreachable_no_cleanup_block: Option, // Cached block for UnwindTerminate (with reason) terminate_block: Option<(BasicBlock, UnwindTerminateReason)>, body_span: Span, @@ -27,6 +29,7 @@ impl<'tcx> MirPatch<'tcx> { next_local: body.local_decls.len(), resume_block: None, unreachable_cleanup_block: None, + unreachable_no_cleanup_block: None, terminate_block: None, body_span: body.span, }; @@ -43,9 +46,12 @@ impl<'tcx> MirPatch<'tcx> { // Check if we already have an unreachable block if matches!(block.terminator().kind, TerminatorKind::Unreachable) && block.statements.is_empty() - && block.is_cleanup { - result.unreachable_cleanup_block = Some(bb); + if block.is_cleanup { + result.unreachable_cleanup_block = Some(bb); + } else { + result.unreachable_no_cleanup_block = Some(bb); + } continue; } @@ -95,6 +101,23 @@ impl<'tcx> MirPatch<'tcx> { bb } + pub fn unreachable_no_cleanup_block(&mut self) -> BasicBlock { + if let Some(bb) = self.unreachable_no_cleanup_block { + return bb; + } + + let bb = self.new_block(BasicBlockData { + statements: vec![], + terminator: Some(Terminator { + source_info: SourceInfo::outermost(self.body_span), + kind: TerminatorKind::Unreachable, + }), + is_cleanup: false, + }); + self.unreachable_no_cleanup_block = Some(bb); + bb + } + pub fn terminate_block(&mut self, reason: UnwindTerminateReason) -> BasicBlock { if let Some((cached_bb, cached_reason)) = self.terminate_block && reason == cached_reason diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 5638b575b319c..e058302af312c 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -7,7 +7,7 @@ use std::path::{Path, PathBuf}; use crate::mir::interpret::ConstAllocation; use super::graphviz::write_mir_fn_graphviz; -use rustc_ast::InlineAsmTemplatePiece; +use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_middle::mir::interpret::{ alloc_range, read_target_uint, AllocBytes, AllocId, Allocation, GlobalAlloc, Pointer, Provenance, @@ -830,6 +830,9 @@ impl<'tcx> TerminatorKind<'tcx> { InlineAsmOperand::SymStatic { def_id } => { write!(fmt, "sym_static {def_id:?}")?; } + InlineAsmOperand::Label { target_index } => { + write!(fmt, "label {target_index}")?; + } } } write!(fmt, ", options({options:?}))") @@ -868,16 +871,19 @@ impl<'tcx> TerminatorKind<'tcx> { vec!["real".into(), "unwind".into()] } FalseUnwind { unwind: _, .. } => vec!["real".into()], - InlineAsm { destination: Some(_), unwind: UnwindAction::Cleanup(_), .. } => { - vec!["return".into(), "unwind".into()] - } - InlineAsm { destination: Some(_), unwind: _, .. } => { - vec!["return".into()] - } - InlineAsm { destination: None, unwind: UnwindAction::Cleanup(_), .. } => { - vec!["unwind".into()] + InlineAsm { options, ref targets, unwind, .. } => { + let mut vec = Vec::with_capacity(targets.len() + 1); + if !options.contains(InlineAsmOptions::NORETURN) { + vec.push("return".into()); + } + vec.resize(targets.len(), "label".into()); + + if let UnwindAction::Cleanup(_) = unwind { + vec.push("unwind".into()); + } + + vec } - InlineAsm { destination: None, unwind: _, .. } => vec![], } } } diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 5c9857b9c53d8..f188923f87618 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -793,9 +793,10 @@ pub enum TerminatorKind<'tcx> { /// used to map assembler errors back to the line in the source code. line_spans: &'tcx [Span], - /// Destination block after the inline assembly returns, unless it is - /// diverging (InlineAsmOptions::NORETURN). - destination: Option, + /// Valid targets for the inline assembly. + /// The first element is the fallthrough destination, unless + /// InlineAsmOptions::NORETURN is set. + targets: Vec, /// Action to be taken if the inline assembly unwinds. This is present /// if and only if InlineAsmOptions::MAY_UNWIND is set. @@ -918,6 +919,10 @@ pub enum InlineAsmOperand<'tcx> { SymStatic { def_id: DefId, }, + Label { + /// This represents the index into the `targets` array in `TerminatorKind::InlineAsm`. + target_index: usize, + }, } /// Type for MIR `Assert` terminator error messages. diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index 4c7df0a7ae219..a4a4df55c4848 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -74,6 +74,17 @@ impl SwitchTargets { pub fn target_for_value(&self, value: u128) -> BasicBlock { self.iter().find_map(|(v, t)| (v == value).then_some(t)).unwrap_or_else(|| self.otherwise()) } + + /// Adds a new target to the switch. But You cannot add an already present value. + #[inline] + pub fn add_target(&mut self, value: u128, bb: BasicBlock) { + let value = Pu128(value); + if self.values.contains(&value) { + bug!("target value {:?} already present", value); + } + self.values.push(value); + self.targets.insert(self.targets.len() - 1, bb); + } } pub struct SwitchTargetsIter<'a> { @@ -251,7 +262,7 @@ impl AssertKind { /// `AssertKind::description` and the lang items mentioned in its docs). /// Note that we deliberately show more details here than we do at runtime, such as the actual /// numbers that overflowed -- it is much easier to do so here than at runtime. - pub fn diagnostic_message(&self) -> DiagnosticMessage { + pub fn diagnostic_message(&self) -> DiagMessage { use crate::fluent_generated::*; use AssertKind::*; @@ -336,8 +347,7 @@ pub struct Terminator<'tcx> { } pub type Successors<'a> = impl DoubleEndedIterator + 'a; -pub type SuccessorsMut<'a> = - iter::Chain, slice::IterMut<'a, BasicBlock>>; +pub type SuccessorsMut<'a> = impl DoubleEndedIterator + 'a; impl<'tcx> Terminator<'tcx> { #[inline] @@ -371,40 +381,36 @@ impl<'tcx> TerminatorKind<'tcx> { pub fn successors(&self) -> Successors<'_> { use self::TerminatorKind::*; match *self { - Call { target: Some(t), unwind: UnwindAction::Cleanup(ref u), .. } - | Yield { resume: t, drop: Some(ref u), .. } - | Drop { target: t, unwind: UnwindAction::Cleanup(ref u), .. } - | Assert { target: t, unwind: UnwindAction::Cleanup(ref u), .. } - | FalseUnwind { real_target: t, unwind: UnwindAction::Cleanup(ref u) } - | InlineAsm { destination: Some(t), unwind: UnwindAction::Cleanup(ref u), .. } => { - Some(t).into_iter().chain(slice::from_ref(u).into_iter().copied()) - } - Goto { target: t } - | Call { target: None, unwind: UnwindAction::Cleanup(t), .. } - | Call { target: Some(t), unwind: _, .. } - | Yield { resume: t, drop: None, .. } - | Drop { target: t, unwind: _, .. } - | Assert { target: t, unwind: _, .. } - | FalseUnwind { real_target: t, unwind: _ } - | InlineAsm { destination: None, unwind: UnwindAction::Cleanup(t), .. } - | InlineAsm { destination: Some(t), unwind: _, .. } => { - Some(t).into_iter().chain((&[]).into_iter().copied()) + Call { target: Some(ref t), unwind: UnwindAction::Cleanup(u), .. } + | Yield { resume: ref t, drop: Some(u), .. } + | Drop { target: ref t, unwind: UnwindAction::Cleanup(u), .. } + | Assert { target: ref t, unwind: UnwindAction::Cleanup(u), .. } + | FalseUnwind { real_target: ref t, unwind: UnwindAction::Cleanup(u) } => { + slice::from_ref(t).into_iter().copied().chain(Some(u)) + } + Goto { target: ref t } + | Call { target: None, unwind: UnwindAction::Cleanup(ref t), .. } + | Call { target: Some(ref t), unwind: _, .. } + | Yield { resume: ref t, drop: None, .. } + | Drop { target: ref t, unwind: _, .. } + | Assert { target: ref t, unwind: _, .. } + | FalseUnwind { real_target: ref t, unwind: _ } => { + slice::from_ref(t).into_iter().copied().chain(None) } UnwindResume | UnwindTerminate(_) | CoroutineDrop | Return | Unreachable - | Call { target: None, unwind: _, .. } - | InlineAsm { destination: None, unwind: _, .. } => { - None.into_iter().chain((&[]).into_iter().copied()) + | Call { target: None, unwind: _, .. } => (&[]).into_iter().copied().chain(None), + InlineAsm { ref targets, unwind: UnwindAction::Cleanup(u), .. } => { + targets.iter().copied().chain(Some(u)) } - SwitchInt { ref targets, .. } => { - None.into_iter().chain(targets.targets.iter().copied()) + InlineAsm { ref targets, unwind: _, .. } => targets.iter().copied().chain(None), + SwitchInt { ref targets, .. } => targets.targets.iter().copied().chain(None), + FalseEdge { ref real_target, imaginary_target } => { + slice::from_ref(real_target).into_iter().copied().chain(Some(imaginary_target)) } - FalseEdge { real_target, ref imaginary_target } => Some(real_target) - .into_iter() - .chain(slice::from_ref(imaginary_target).into_iter().copied()), } } @@ -416,33 +422,31 @@ impl<'tcx> TerminatorKind<'tcx> { | Yield { resume: ref mut t, drop: Some(ref mut u), .. } | Drop { target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u), .. } | Assert { target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u), .. } - | FalseUnwind { real_target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u) } - | InlineAsm { - destination: Some(ref mut t), - unwind: UnwindAction::Cleanup(ref mut u), - .. - } => Some(t).into_iter().chain(slice::from_mut(u)), + | FalseUnwind { real_target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u) } => { + slice::from_mut(t).into_iter().chain(Some(u)) + } Goto { target: ref mut t } | Call { target: None, unwind: UnwindAction::Cleanup(ref mut t), .. } | Call { target: Some(ref mut t), unwind: _, .. } | Yield { resume: ref mut t, drop: None, .. } | Drop { target: ref mut t, unwind: _, .. } | Assert { target: ref mut t, unwind: _, .. } - | FalseUnwind { real_target: ref mut t, unwind: _ } - | InlineAsm { destination: None, unwind: UnwindAction::Cleanup(ref mut t), .. } - | InlineAsm { destination: Some(ref mut t), unwind: _, .. } => { - Some(t).into_iter().chain(&mut []) + | FalseUnwind { real_target: ref mut t, unwind: _ } => { + slice::from_mut(t).into_iter().chain(None) } UnwindResume | UnwindTerminate(_) | CoroutineDrop | Return | Unreachable - | Call { target: None, unwind: _, .. } - | InlineAsm { destination: None, unwind: _, .. } => None.into_iter().chain(&mut []), - SwitchInt { ref mut targets, .. } => None.into_iter().chain(&mut targets.targets), + | Call { target: None, unwind: _, .. } => (&mut []).into_iter().chain(None), + InlineAsm { ref mut targets, unwind: UnwindAction::Cleanup(ref mut u), .. } => { + targets.iter_mut().chain(Some(u)) + } + InlineAsm { ref mut targets, unwind: _, .. } => targets.iter_mut().chain(None), + SwitchInt { ref mut targets, .. } => targets.targets.iter_mut().chain(None), FalseEdge { ref mut real_target, ref mut imaginary_target } => { - Some(real_target).into_iter().chain(slice::from_mut(imaginary_target)) + slice::from_mut(real_target).into_iter().chain(Some(imaginary_target)) } } } @@ -514,7 +518,7 @@ pub enum TerminatorEdges<'mir, 'tcx> { Double(BasicBlock, BasicBlock), /// Special action for `Yield`, `Call` and `InlineAsm` terminators. AssignOnReturn { - return_: Option, + return_: &'mir [BasicBlock], /// The cleanup block, if it exists. cleanup: Option, place: CallReturnPlaces<'mir, 'tcx>, @@ -578,31 +582,37 @@ impl<'tcx> TerminatorKind<'tcx> { TerminatorEdges::Double(real_target, imaginary_target) } - Yield { resume: target, drop, resume_arg, value: _ } => { + Yield { resume: ref target, drop, resume_arg, value: _ } => { TerminatorEdges::AssignOnReturn { - return_: Some(target), + return_: slice::from_ref(target), cleanup: drop, place: CallReturnPlaces::Yield(resume_arg), } } - Call { unwind, destination, target, func: _, args: _, fn_span: _, call_source: _ } => { - TerminatorEdges::AssignOnReturn { - return_: target, - cleanup: unwind.cleanup_block(), - place: CallReturnPlaces::Call(destination), - } - } + Call { + unwind, + destination, + ref target, + func: _, + args: _, + fn_span: _, + call_source: _, + } => TerminatorEdges::AssignOnReturn { + return_: target.as_ref().map(slice::from_ref).unwrap_or_default(), + cleanup: unwind.cleanup_block(), + place: CallReturnPlaces::Call(destination), + }, InlineAsm { template: _, ref operands, options: _, line_spans: _, - destination, + ref targets, unwind, } => TerminatorEdges::AssignOnReturn { - return_: destination, + return_: targets, cleanup: unwind.cleanup_block(), place: CallReturnPlaces::InlineAsm(operands), }, diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 2c5ca82a4cd39..845b17175505d 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -565,7 +565,7 @@ macro_rules! make_mir_visitor { operands, options: _, line_spans: _, - destination: _, + targets: _, unwind: _, } => { for op in operands { @@ -595,7 +595,8 @@ macro_rules! make_mir_visitor { self.visit_constant(value, location); } InlineAsmOperand::Out { place: None, .. } - | InlineAsmOperand::SymStatic { def_id: _ } => {} + | InlineAsmOperand::SymStatic { def_id: _ } + | InlineAsmOperand::Label { target_index: _ } => {} } } } diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 2cdcdcb1492b0..33ee3371605ae 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -177,8 +177,8 @@ impl EraseType for Option> { type Result = [u8; size_of::>>()]; } -impl EraseType for Option>> { - type Result = [u8; size_of::>>>()]; +impl EraseType for Option> { + type Result = [u8; size_of::>>()]; } impl EraseType for Option>> { @@ -241,7 +241,7 @@ trivial! { Option, Option, Option, - Option, + Option, Result<(), rustc_errors::ErrorGuaranteed>, Result<(), rustc_middle::traits::query::NoSolution>, Result, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index e87bc581e6eab..332ebdbdd944c 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -125,12 +125,11 @@ rustc_queries! { } query resolutions(_: ()) -> &'tcx ty::ResolverGlobalCtxt { - feedable no_hash desc { "getting the resolver outputs" } } - query resolver_for_lowering(_: ()) -> &'tcx Steal<(ty::ResolverAstLowering, Lrc)> { + query resolver_for_lowering_raw(_: ()) -> (&'tcx Steal<(ty::ResolverAstLowering, Lrc)>, &'tcx ty::ResolverGlobalCtxt) { eval_always no_hash desc { "getting the resolver for lowering" } @@ -344,15 +343,6 @@ rustc_queries! { } } - query impl_trait_in_assoc_types_defined_by( - key: LocalDefId - ) -> &'tcx ty::List { - desc { - |tcx| "computing the opaque types defined by `{}`", - tcx.def_path_str(key.to_def_id()) - } - } - /// Returns the list of bounds that can be used for /// `SelectionCandidate::ProjectionCandidate(_)` and /// `ProjectionTyCandidate::TraitDef`. @@ -772,6 +762,7 @@ rustc_queries! { desc { |tcx| "computing the variances of `{}`", tcx.def_path_str(def_id) } cache_on_disk_if { def_id.is_local() } separate_provide_extern + cycle_delay_bug } /// Maps from thee `DefId` of a type to its (inferred) outlives. @@ -835,7 +826,7 @@ rustc_queries! { /// creates and returns the associated items that correspond to each impl trait in return position /// of the implemented trait. query associated_types_for_impl_traits_in_associated_fn(fn_def_id: DefId) -> &'tcx [DefId] { - desc { |tcx| "creating associated items for impl trait in trait returned by `{}`", tcx.def_path_str(fn_def_id) } + desc { |tcx| "creating associated items for opaque types returned by `{}`", tcx.def_path_str(fn_def_id) } cache_on_disk_if { fn_def_id.is_local() } separate_provide_extern } @@ -843,13 +834,13 @@ rustc_queries! { /// Given an impl trait in trait `opaque_ty_def_id`, create and return the corresponding /// associated item. query associated_type_for_impl_trait_in_trait(opaque_ty_def_id: LocalDefId) -> LocalDefId { - desc { |tcx| "creates the associated item corresponding to the opaque type `{}`", tcx.def_path_str(opaque_ty_def_id.to_def_id()) } + desc { |tcx| "creating the associated item corresponding to the opaque type `{}`", tcx.def_path_str(opaque_ty_def_id.to_def_id()) } cache_on_disk_if { true } } /// Given an `impl_id`, return the trait it implements along with some header information. /// Return `None` if this is an inherent impl. - query impl_trait_header(impl_id: DefId) -> Option>> { + query impl_trait_header(impl_id: DefId) -> Option> { desc { |tcx| "computing trait implemented by `{}`", tcx.def_path_str(impl_id) } cache_on_disk_if { impl_id.is_local() } separate_provide_extern @@ -964,20 +955,11 @@ rustc_queries! { desc { |tcx| "checking deathness of variables in {}", describe_as_module(key, tcx) } } - query check_mod_impl_wf(key: LocalModDefId) -> Result<(), ErrorGuaranteed> { - desc { |tcx| "checking that impls are well-formed in {}", describe_as_module(key, tcx) } - ensure_forwards_result_if_red - } - query check_mod_type_wf(key: LocalModDefId) -> Result<(), ErrorGuaranteed> { desc { |tcx| "checking that types are well-formed in {}", describe_as_module(key, tcx) } ensure_forwards_result_if_red } - query collect_mod_item_types(key: LocalModDefId) { - desc { |tcx| "collecting item types in {}", describe_as_module(key, tcx) } - } - /// Caches `CoerceUnsized` kinds for impls on custom types. query coerce_unsized_info(key: DefId) -> Result { desc { |tcx| "computing CoerceUnsized info for `{}`", tcx.def_path_str(key) } @@ -1760,7 +1742,7 @@ rustc_queries! { separate_provide_extern } /// Whether the function is an intrinsic - query intrinsic(def_id: DefId) -> Option { + query intrinsic_raw(def_id: DefId) -> Option { desc { |tcx| "fetch intrinsic name if `{}` is an intrinsic", tcx.def_path_str(def_id) } separate_provide_extern } @@ -2230,7 +2212,6 @@ rustc_queries! { /// Should not be called for the local crate before the resolver outputs are created, as it /// is only fed there. query stripped_cfg_items(cnum: CrateNum) -> &'tcx [StrippedCfgItem] { - feedable desc { "getting cfg-ed out item names" } separate_provide_extern } diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 65875ff3f9a86..913d0072c2990 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -565,6 +565,9 @@ pub enum InlineAsmOperand<'tcx> { SymStatic { def_id: DefId, }, + Label { + block: BlockId, + }, } #[derive(Copy, Clone, Debug, PartialEq, HashStable)] diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index 4847a7bea91d7..5952c296fb642 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -162,6 +162,7 @@ pub fn walk_expr<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>( | Const { value: _, span: _ } | SymFn { value: _, span: _ } | SymStatic { def_id: _ } => {} + Label { block } => visitor.visit_block(&visitor.thir()[*block]), } } } diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs index 0dc6512601121..95139b50cb89e 100644 --- a/compiler/rustc_middle/src/traits/solve.rs +++ b/compiler/rustc_middle/src/traits/solve.rs @@ -1,6 +1,6 @@ -use std::ops::ControlFlow; - +use rustc_ast_ir::try_visit; use rustc_data_structures::intern::Interned; +use rustc_span::def_id::DefId; use crate::infer::canonical::{CanonicalVarValues, QueryRegionConstraints}; use crate::traits::query::NoSolution; @@ -9,7 +9,6 @@ use crate::ty::{ self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor, }; -use rustc_span::def_id::DefId; use super::BuiltinImplSource; @@ -196,13 +195,9 @@ impl<'tcx> TypeFoldable> for ExternalConstraints<'tcx> { } impl<'tcx> TypeVisitable> for ExternalConstraints<'tcx> { - fn visit_with>>( - &self, - visitor: &mut V, - ) -> std::ops::ControlFlow { - self.region_constraints.visit_with(visitor)?; - self.opaque_types.visit_with(visitor)?; - ControlFlow::Continue(()) + fn visit_with>>(&self, visitor: &mut V) -> V::Result { + try_visit!(self.region_constraints.visit_with(visitor)); + self.opaque_types.visit_with(visitor) } } @@ -235,10 +230,7 @@ impl<'tcx> TypeFoldable> for PredefinedOpaques<'tcx> { } impl<'tcx> TypeVisitable> for PredefinedOpaques<'tcx> { - fn visit_with>>( - &self, - visitor: &mut V, - ) -> std::ops::ControlFlow { + fn visit_with>>(&self, visitor: &mut V) -> V::Result { self.opaque_types.visit_with(visitor) } } diff --git a/compiler/rustc_middle/src/traits/solve/inspect/format.rs b/compiler/rustc_middle/src/traits/solve/inspect/format.rs index 89c5eb517e565..8d3109a7b284c 100644 --- a/compiler/rustc_middle/src/traits/solve/inspect/format.rs +++ b/compiler/rustc_middle/src/traits/solve/inspect/format.rs @@ -4,22 +4,31 @@ pub(super) struct ProofTreeFormatter<'a, 'b> { f: &'a mut (dyn Write + 'b), } +enum IndentorState { + StartWithNewline, + OnNewline, + Inline, +} + /// A formatter which adds 4 spaces of indentation to its input before /// passing it on to its nested formatter. /// /// We can use this for arbitrary levels of indentation by nesting it. struct Indentor<'a, 'b> { f: &'a mut (dyn Write + 'b), - on_newline: bool, + state: IndentorState, } impl Write for Indentor<'_, '_> { fn write_str(&mut self, s: &str) -> std::fmt::Result { for line in s.split_inclusive('\n') { - if self.on_newline { - self.f.write_str(" ")?; + match self.state { + IndentorState::StartWithNewline => self.f.write_str("\n ")?, + IndentorState::OnNewline => self.f.write_str(" ")?, + IndentorState::Inline => {} } - self.on_newline = line.ends_with('\n'); + self.state = + if line.ends_with('\n') { IndentorState::OnNewline } else { IndentorState::Inline }; self.f.write_str(line)?; } @@ -32,11 +41,15 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> { ProofTreeFormatter { f } } - fn nested(&mut self, func: F) -> R + fn nested(&mut self, func: F) -> std::fmt::Result where - F: FnOnce(&mut ProofTreeFormatter<'_, '_>) -> R, + F: FnOnce(&mut ProofTreeFormatter<'_, '_>) -> std::fmt::Result, { - func(&mut ProofTreeFormatter { f: &mut Indentor { f: self.f, on_newline: true } }) + write!(self.f, " {{")?; + func(&mut ProofTreeFormatter { + f: &mut Indentor { f: self.f, state: IndentorState::StartWithNewline }, + })?; + writeln!(self.f, "}}") } pub(super) fn format_goal_evaluation(&mut self, eval: &GoalEvaluation<'_>) -> std::fmt::Result { @@ -47,7 +60,7 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> { IsNormalizesToHack::Yes => "NORMALIZES-TO HACK GOAL", }, }; - writeln!(self.f, "{}: {:?}", goal_text, eval.uncanonicalized_goal)?; + write!(self.f, "{}: {:?}", goal_text, eval.uncanonicalized_goal)?; self.nested(|this| this.format_canonical_goal_evaluation(&eval.evaluation)) } @@ -69,7 +82,7 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> { } CanonicalGoalEvaluationKind::Evaluation { revisions } => { for (n, step) in revisions.iter().enumerate() { - writeln!(self.f, "REVISION {n}")?; + write!(self.f, "REVISION {n}")?; self.nested(|this| this.format_evaluation_step(step))?; } writeln!(self.f, "RESULT: {:?}", eval.result) @@ -88,25 +101,25 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> { pub(super) fn format_probe(&mut self, probe: &Probe<'_>) -> std::fmt::Result { match &probe.kind { ProbeKind::Root { result } => { - writeln!(self.f, "ROOT RESULT: {result:?}") + write!(self.f, "ROOT RESULT: {result:?}") } ProbeKind::NormalizedSelfTyAssembly => { - writeln!(self.f, "NORMALIZING SELF TY FOR ASSEMBLY:") + write!(self.f, "NORMALIZING SELF TY FOR ASSEMBLY:") } ProbeKind::UnsizeAssembly => { - writeln!(self.f, "ASSEMBLING CANDIDATES FOR UNSIZING:") + write!(self.f, "ASSEMBLING CANDIDATES FOR UNSIZING:") } ProbeKind::UpcastProjectionCompatibility => { - writeln!(self.f, "PROBING FOR PROJECTION COMPATIBILITY FOR UPCASTING:") + write!(self.f, "PROBING FOR PROJECTION COMPATIBILITY FOR UPCASTING:") } ProbeKind::CommitIfOk => { - writeln!(self.f, "COMMIT_IF_OK:") + write!(self.f, "COMMIT_IF_OK:") } ProbeKind::MiscCandidate { name, result } => { - writeln!(self.f, "CANDIDATE {name}: {result:?}") + write!(self.f, "CANDIDATE {name}: {result:?}") } ProbeKind::TraitCandidate { source, result } => { - writeln!(self.f, "CANDIDATE {source:?}: {result:?}") + write!(self.f, "CANDIDATE {source:?}: {result:?}") } }?; @@ -137,7 +150,7 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> { writeln!(self.f, "TRY_EVALUATE_ADDED_GOALS: {:?}", added_goals_evaluation.result)?; for (n, iterations) in added_goals_evaluation.evaluations.iter().enumerate() { - writeln!(self.f, "ITERATION {n}")?; + write!(self.f, "ITERATION {n}")?; self.nested(|this| { for goal_evaluation in iterations { this.format_goal_evaluation(goal_evaluation)?; diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 5e4d899f51768..5b62c0bf931af 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -175,7 +175,20 @@ impl<'tcx> Const<'tcx> { let reported = tcx.dcx().span_delayed_bug(span, msg); Const::new_error(tcx, reported, ty) } +} +impl<'tcx> rustc_type_ir::new::Const> for Const<'tcx> { + fn new_anon_bound( + tcx: TyCtxt<'tcx>, + debruijn: ty::DebruijnIndex, + var: ty::BoundVar, + ty: Ty<'tcx>, + ) -> Self { + Const::new_bound(tcx, debruijn, var, ty) + } +} + +impl<'tcx> Const<'tcx> { /// Literals and const generic parameters are eagerly converted to a constant, everything else /// becomes `Unevaluated`. #[instrument(skip(tcx), level = "debug")] diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index b2a7f5599b643..f947832d28c34 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -39,11 +39,11 @@ use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::steal::Steal; -use rustc_data_structures::sync::{self, FreezeReadGuard, Lock, WorkerLocal}; +use rustc_data_structures::sync::{self, FreezeReadGuard, Lock, Lrc, WorkerLocal}; #[cfg(parallel_compiler)] use rustc_data_structures::sync::{DynSend, DynSync}; use rustc_data_structures::unord::UnordSet; -use rustc_errors::{DecorateLint, Diag, DiagCtxt, DiagnosticMessage, ErrorGuaranteed, MultiSpan}; +use rustc_errors::{DecorateLint, Diag, DiagCtxt, DiagMessage, ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; @@ -60,7 +60,7 @@ use rustc_session::config::CrateType; use rustc_session::cstore::{CrateStoreDyn, Untracked}; use rustc_session::lint::Lint; use rustc_session::{Limit, MetadataKind, Session}; -use rustc_span::def_id::{DefPathHash, StableCrateId}; +use rustc_span::def_id::{DefPathHash, StableCrateId, CRATE_DEF_ID}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{FieldIdx, Layout, LayoutS, TargetDataLayout, VariantIdx}; @@ -74,6 +74,7 @@ use std::cmp::Ordering; use std::fmt; use std::hash::{Hash, Hasher}; use std::iter; +use std::marker::PhantomData; use std::mem; use std::ops::{Bound, Deref}; @@ -130,27 +131,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> { fn mk_canonical_var_infos(self, infos: &[ty::CanonicalVarInfo]) -> Self::CanonicalVars { self.mk_canonical_var_infos(infos) } - - fn mk_bound_ty(self, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self::Ty { - Ty::new_bound(self, debruijn, ty::BoundTy { var, kind: ty::BoundTyKind::Anon }) - } - - fn mk_bound_region(self, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self::Region { - Region::new_bound( - self, - debruijn, - ty::BoundRegion { var, kind: ty::BoundRegionKind::BrAnon }, - ) - } - - fn mk_bound_const( - self, - debruijn: ty::DebruijnIndex, - var: ty::BoundVar, - ty: Self::Ty, - ) -> Self::Const { - Const::new_bound(self, debruijn, var, ty) - } } type InternedSet<'tcx, T> = ShardedHashMap, ()>; @@ -519,14 +499,55 @@ pub struct TyCtxtFeed<'tcx, KEY: Copy> { key: KEY, } +/// Never return a `Feed` from a query. Only queries that create a `DefId` are +/// allowed to feed queries for that `DefId`. +impl !HashStable for TyCtxtFeed<'_, KEY> {} + +/// The same as `TyCtxtFeed`, but does not contain a `TyCtxt`. +/// Use this to pass around when you have a `TyCtxt` elsewhere. +/// Just an optimization to save space and not store hundreds of +/// `TyCtxtFeed` in the resolver. +#[derive(Copy, Clone)] +pub struct Feed<'tcx, KEY: Copy> { + _tcx: PhantomData>, + // Do not allow direct access, as downstream code must not mutate this field. + key: KEY, +} + +/// Never return a `Feed` from a query. Only queries that create a `DefId` are +/// allowed to feed queries for that `DefId`. +impl !HashStable for Feed<'_, KEY> {} + +impl fmt::Debug for Feed<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.key.fmt(f) + } +} + +/// Some workarounds to use cases that cannot use `create_def`. +/// Do not add new ways to create `TyCtxtFeed` without consulting +/// with T-compiler and making an analysis about why your addition +/// does not cause incremental compilation issues. impl<'tcx> TyCtxt<'tcx> { + /// Can only be fed before queries are run, and is thus exempt from any + /// incremental issues. Do not use except for the initial query feeding. pub fn feed_unit_query(self) -> TyCtxtFeed<'tcx, ()> { + self.dep_graph.assert_ignored(); TyCtxtFeed { tcx: self, key: () } } + + /// Can only be fed before queries are run, and is thus exempt from any + /// incremental issues. Do not use except for the initial query feeding. pub fn feed_local_crate(self) -> TyCtxtFeed<'tcx, CrateNum> { + self.dep_graph.assert_ignored(); TyCtxtFeed { tcx: self, key: LOCAL_CRATE } } - pub fn feed_local_def_id(self, key: LocalDefId) -> TyCtxtFeed<'tcx, LocalDefId> { + + /// Only used in the resolver to register the `CRATE_DEF_ID` `DefId` and feed + /// some queries for it. It will panic if used twice. + pub fn create_local_crate_def_id(self, span: Span) -> TyCtxtFeed<'tcx, LocalDefId> { + let key = self.untracked().source_span.push(span); + assert_eq!(key, CRATE_DEF_ID); TyCtxtFeed { tcx: self, key } } @@ -544,6 +565,23 @@ impl<'tcx, KEY: Copy> TyCtxtFeed<'tcx, KEY> { pub fn key(&self) -> KEY { self.key } + + #[inline(always)] + pub fn downgrade(self) -> Feed<'tcx, KEY> { + Feed { _tcx: PhantomData, key: self.key } + } +} + +impl<'tcx, KEY: Copy> Feed<'tcx, KEY> { + #[inline(always)] + pub fn key(&self) -> KEY { + self.key + } + + #[inline(always)] + pub fn upgrade(self, tcx: TyCtxt<'tcx>) -> TyCtxtFeed<'tcx, KEY> { + TyCtxtFeed { tcx, key: self.key } + } } impl<'tcx> TyCtxtFeed<'tcx, LocalDefId> { @@ -1088,7 +1126,7 @@ impl<'tcx> TyCtxt<'tcx> { // needs to be re-evaluated. self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE); - let feed = self.feed_local_def_id(def_id); + let feed = TyCtxtFeed { tcx: self, key: def_id }; feed.def_kind(def_kind); // Unique types created for closures participate in type privacy checking. // They have visibilities inherited from the module they are defined in. @@ -1216,7 +1254,7 @@ impl<'tcx> TyCtxt<'tcx> { if self.def_kind(scope) == DefKind::OpaqueTy { // Lifetime params of opaque types are synthetic and thus irrelevant to // diagnostics. Map them back to their origin! - region = self.map_rpit_lifetime_to_fn_lifetime(def_id); + region = self.map_opaque_lifetime_to_parent_lifetime(def_id); continue; } break (scope, ty::BrNamed(def_id.into(), self.item_name(def_id.into()))); @@ -2118,7 +2156,7 @@ impl<'tcx> TyCtxt<'tcx> { lint: &'static Lint, hir_id: HirId, span: impl Into, - msg: impl Into, + msg: impl Into, decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>), ) { let (level, src) = self.lint_level_at_node(lint, hir_id); @@ -2148,7 +2186,7 @@ impl<'tcx> TyCtxt<'tcx> { self, lint: &'static Lint, id: HirId, - msg: impl Into, + msg: impl Into, decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>), ) { let (level, src) = self.lint_level_at_node(lint, id); @@ -2181,31 +2219,31 @@ impl<'tcx> TyCtxt<'tcx> { ) } - /// Given the def-id of an early-bound lifetime on an RPIT corresponding to + /// Given the def-id of an early-bound lifetime on an opaque corresponding to /// a duplicated captured lifetime, map it back to the early- or late-bound /// lifetime of the function from which it originally as captured. If it is /// a late-bound lifetime, this will represent the liberated (`ReLateParam`) lifetime /// of the signature. // FIXME(RPITIT): if we ever synthesize new lifetimes for RPITITs and not just // re-use the generics of the opaque, this function will need to be tweaked slightly. - pub fn map_rpit_lifetime_to_fn_lifetime( + pub fn map_opaque_lifetime_to_parent_lifetime( self, - mut rpit_lifetime_param_def_id: LocalDefId, + mut opaque_lifetime_param_def_id: LocalDefId, ) -> ty::Region<'tcx> { debug_assert!( - matches!(self.def_kind(rpit_lifetime_param_def_id), DefKind::LifetimeParam), - "{rpit_lifetime_param_def_id:?} is a {}", - self.def_descr(rpit_lifetime_param_def_id.to_def_id()) + matches!(self.def_kind(opaque_lifetime_param_def_id), DefKind::LifetimeParam), + "{opaque_lifetime_param_def_id:?} is a {}", + self.def_descr(opaque_lifetime_param_def_id.to_def_id()) ); loop { - let parent = self.local_parent(rpit_lifetime_param_def_id); + let parent = self.local_parent(opaque_lifetime_param_def_id); let hir::OpaqueTy { lifetime_mapping, .. } = self.hir_node_by_def_id(parent).expect_item().expect_opaque_ty(); let Some((lifetime, _)) = lifetime_mapping .iter() - .find(|(_, duplicated_param)| *duplicated_param == rpit_lifetime_param_def_id) + .find(|(_, duplicated_param)| *duplicated_param == opaque_lifetime_param_def_id) else { bug!("duplicated lifetime param should be present"); }; @@ -2218,7 +2256,7 @@ impl<'tcx> TyCtxt<'tcx> { // of the opaque we mapped from. Continue mapping. if matches!(self.def_kind(new_parent), DefKind::OpaqueTy) { debug_assert_eq!(self.parent(parent.to_def_id()), new_parent); - rpit_lifetime_param_def_id = ebv.expect_local(); + opaque_lifetime_param_def_id = ebv.expect_local(); continue; } @@ -2296,6 +2334,14 @@ impl<'tcx> TyCtxt<'tcx> { ) } + pub fn intrinsic(self, def_id: impl IntoQueryParam + Copy) -> Option { + match self.def_kind(def_id) { + DefKind::Fn | DefKind::AssocFn => {} + _ => return None, + } + self.intrinsic_raw(def_id) + } + pub fn local_def_id_to_hir_id(self, local_def_id: LocalDefId) -> HirId { self.opt_local_def_id_to_hir_id(local_def_id).unwrap() } @@ -2325,18 +2371,21 @@ impl<'tcx> TyCtxt<'tcx> { self.resolutions(()).module_children.get(&def_id).map_or(&[], |v| &v[..]) } + pub fn resolver_for_lowering(self) -> &'tcx Steal<(ty::ResolverAstLowering, Lrc)> { + self.resolver_for_lowering_raw(()).0 + } + /// Given an `impl_id`, return the trait it implements. /// Return `None` if this is an inherent impl. pub fn impl_trait_ref( self, def_id: impl IntoQueryParam, ) -> Option>> { - Some(self.impl_trait_header(def_id)?.map_bound(|h| h.trait_ref)) + Some(self.impl_trait_header(def_id)?.trait_ref) } pub fn impl_polarity(self, def_id: impl IntoQueryParam) -> ty::ImplPolarity { - self.impl_trait_header(def_id) - .map_or(ty::ImplPolarity::Positive, |h| h.skip_binder().polarity) + self.impl_trait_header(def_id).map_or(ty::ImplPolarity::Positive, |h| h.polarity) } } diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 712fbf2444053..2506456f1fb11 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -482,9 +482,9 @@ pub struct IsSuggestableVisitor<'tcx> { } impl<'tcx> TypeVisitor> for IsSuggestableVisitor<'tcx> { - type BreakTy = (); + type Result = ControlFlow<()>; - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { match *t.kind() { Infer(InferTy::TyVar(_)) if self.infer_suggestable => {} @@ -536,7 +536,7 @@ impl<'tcx> TypeVisitor> for IsSuggestableVisitor<'tcx> { t.super_visit_with(self) } - fn visit_const(&mut self, c: Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, c: Const<'tcx>) -> Self::Result { match c.kind() { ConstKind::Infer(InferConst::Var(_)) if self.infer_suggestable => {} diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index c87ef870a084e..8079ad121ad9e 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -6,6 +6,8 @@ use crate::ty::sty::{ClosureArgs, CoroutineArgs, CoroutineClosureArgs, InlineCon use crate::ty::visit::{TypeVisitable, TypeVisitableExt, TypeVisitor}; use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt}; +use rustc_ast_ir::visit::VisitorResult; +use rustc_ast_ir::walk_visitable_list; use rustc_data_structures::intern::Interned; use rustc_errors::{DiagArgValue, IntoDiagnosticArg}; use rustc_hir::def_id::DefId; @@ -19,7 +21,7 @@ use std::cmp::Ordering; use std::marker::PhantomData; use std::mem; use std::num::NonZero; -use std::ops::{ControlFlow, Deref}; +use std::ops::Deref; use std::ptr::NonNull; /// An entity in the Rust type system, which can be one of @@ -240,7 +242,7 @@ impl<'tcx> TypeFoldable> for GenericArg<'tcx> { } impl<'tcx> TypeVisitable> for GenericArg<'tcx> { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>>(&self, visitor: &mut V) -> V::Result { match self.unpack() { GenericArgKind::Lifetime(lt) => lt.visit_with(visitor), GenericArgKind::Type(ty) => ty.visit_with(visitor), @@ -554,8 +556,9 @@ impl<'tcx> TypeFoldable> for &'tcx ty::List> { impl<'tcx, T: TypeVisitable>> TypeVisitable> for &'tcx ty::List { #[inline] - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { - self.iter().try_for_each(|t| t.visit_with(visitor)) + fn visit_with>>(&self, visitor: &mut V) -> V::Result { + walk_visitable_list!(visitor, self.iter()); + V::Result::output() } } diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 260d0885089ef..9fc8d418f5b25 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -694,6 +694,7 @@ impl<'tcx> Instance<'tcx> { } #[inline(always)] + // Keep me in sync with try_instantiate_mir_and_normalize_erasing_regions pub fn instantiate_mir_and_normalize_erasing_regions( &self, tcx: TyCtxt<'tcx>, @@ -701,16 +702,17 @@ impl<'tcx> Instance<'tcx> { v: EarlyBinder, ) -> T where - T: TypeFoldable> + Clone, + T: TypeFoldable>, { if let Some(args) = self.args_for_mir_body() { tcx.instantiate_and_normalize_erasing_regions(args, param_env, v) } else { - tcx.normalize_erasing_regions(param_env, v.skip_binder()) + tcx.normalize_erasing_regions(param_env, v.instantiate_identity()) } } #[inline(always)] + // Keep me in sync with instantiate_mir_and_normalize_erasing_regions pub fn try_instantiate_mir_and_normalize_erasing_regions( &self, tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_middle/src/ty/intrinsic.rs b/compiler/rustc_middle/src/ty/intrinsic.rs new file mode 100644 index 0000000000000..18d08ed23a5e5 --- /dev/null +++ b/compiler/rustc_middle/src/ty/intrinsic.rs @@ -0,0 +1,17 @@ +use rustc_span::{def_id::DefId, Symbol}; + +use super::TyCtxt; + +#[derive(Copy, Clone, Debug, Decodable, Encodable, HashStable)] +pub struct IntrinsicDef { + pub name: Symbol, + /// Whether the intrinsic has no meaningful body and all backends need to shim all calls to it. + pub must_be_overridden: bool, +} + +impl TyCtxt<'_> { + pub fn is_intrinsic(self, def_id: DefId, name: Symbol) -> bool { + let Some(i) = self.intrinsic(def_id) else { return false }; + i.name == name + } +} diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 529d847bfb06a..b1bfd2f1105a8 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -3,7 +3,7 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::query::TyCtxtAt; use crate::ty::normalize_erasing_regions::NormalizationError; use crate::ty::{self, ConstKind, Ty, TyCtxt, TypeVisitableExt}; -use rustc_error_messages::DiagnosticMessage; +use rustc_error_messages::DiagMessage; use rustc_errors::{ Diag, DiagArgValue, DiagCtxt, EmissionGuarantee, IntoDiagnostic, IntoDiagnosticArg, Level, }; @@ -17,6 +17,7 @@ use rustc_target::abi::call::FnAbi; use rustc_target::abi::*; use rustc_target::spec::{abi::Abi as SpecAbi, HasTargetSpec, PanicStrategy, Target}; +use std::borrow::Cow; use std::cmp; use std::fmt; use std::num::NonZero; @@ -205,7 +206,7 @@ pub enum LayoutError<'tcx> { } impl<'tcx> LayoutError<'tcx> { - pub fn diagnostic_message(&self) -> DiagnosticMessage { + pub fn diagnostic_message(&self) -> DiagMessage { use crate::fluent_generated::*; use LayoutError::*; match self { @@ -268,7 +269,7 @@ pub struct LayoutCx<'tcx, C> { impl<'tcx> LayoutCalculator for LayoutCx<'tcx, TyCtxt<'tcx>> { type TargetDataLayoutRef = &'tcx TargetDataLayout; - fn delayed_bug(&self, txt: String) { + fn delayed_bug(&self, txt: impl Into>) { self.tcx.dcx().delayed_bug(txt); } @@ -969,6 +970,8 @@ where } } + /// Compute the information for the pointer stored at the given offset inside this type. + /// This will recurse into fields of ADTs to find the inner pointer. fn ty_and_layout_pointee_info_at( this: TyAndLayout<'tcx>, cx: &C, @@ -1068,15 +1071,17 @@ where } } - // FIXME(eddyb) This should be for `ptr::Unique`, not `Box`. + // Fixup info for the first field of a `Box`. Recursive traversal will have found + // the raw pointer, so size and align are set to the boxed type, but `pointee.safe` + // will still be `None`. if let Some(ref mut pointee) = result { - if let ty::Adt(def, _) = this.ty.kind() { - if def.is_box() && offset.bytes() == 0 { - let optimize = tcx.sess.opts.optimize != OptLevel::No; - pointee.safe = Some(PointerKind::Box { - unpin: optimize && this.ty.boxed_ty().is_unpin(tcx, cx.param_env()), - }); - } + if offset.bytes() == 0 && this.ty.is_box() { + debug_assert!(pointee.safe.is_none()); + let optimize = tcx.sess.opts.optimize != OptLevel::No; + pointee.safe = Some(PointerKind::Box { + unpin: optimize && this.ty.boxed_ty().is_unpin(tcx, cx.param_env()), + global: this.ty.is_box_global(tcx), + }); } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index f005a24050442..5c2d3973d61dd 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -30,9 +30,11 @@ pub use adt::*; pub use assoc::*; pub use generic_args::*; pub use generics::*; +pub use intrinsic::IntrinsicDef; use rustc_ast as ast; +use rustc_ast::expand::StrippedCfgItem; use rustc_ast::node_id::NodeMap; -pub use rustc_ast_ir::{Movability, Mutability}; +pub use rustc_ast_ir::{try_visit, Movability, Mutability}; use rustc_attr as attr; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::intern::Interned; @@ -63,7 +65,6 @@ use std::hash::{Hash, Hasher}; use std::marker::PhantomData; use std::mem; use std::num::NonZero; -use std::ops::ControlFlow; use std::ptr::NonNull; use std::{fmt, str}; @@ -85,7 +86,8 @@ pub use self::consts::{ Const, ConstData, ConstInt, ConstKind, Expr, ScalarInt, UnevaluatedConst, ValTree, }; pub use self::context::{ - tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed, + tls, CtxtInterners, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, + TyCtxtFeed, }; pub use self::instance::{Instance, InstanceDef, ShortInstance, UnusedGenericParams}; pub use self::list::List; @@ -149,6 +151,7 @@ mod generic_args; mod generics; mod impls_ty; mod instance; +mod intrinsic; mod list; mod opaque_types; mod parameterized; @@ -188,6 +191,7 @@ pub struct ResolverGlobalCtxt { pub doc_link_resolutions: FxHashMap, pub doc_link_traits_in_scope: FxHashMap>, pub all_macro_rules: FxHashMap>, + pub stripped_cfg_items: Steal>, } /// Resolutions that should only be used for lowering. @@ -249,9 +253,9 @@ pub struct ImplHeader<'tcx> { pub predicates: Vec>, } -#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, TyEncodable, TyDecodable, HashStable)] +#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)] pub struct ImplTraitHeader<'tcx> { - pub trait_ref: ty::TraitRef<'tcx>, + pub trait_ref: ty::EarlyBinder>, pub polarity: ImplPolarity, pub unsafety: hir::Unsafety, } @@ -597,7 +601,7 @@ impl<'tcx> TypeFoldable> for Term<'tcx> { } impl<'tcx> TypeVisitable> for Term<'tcx> { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>>(&self, visitor: &mut V) -> V::Result { self.unpack().visit_with(visitor) } } @@ -1041,8 +1045,8 @@ impl<'tcx> TypeFoldable> for ParamEnv<'tcx> { } impl<'tcx> TypeVisitable> for ParamEnv<'tcx> { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { - self.caller_bounds().visit_with(visitor)?; + fn visit_with>>(&self, visitor: &mut V) -> V::Result { + try_visit!(self.caller_bounds().visit_with(visitor)); self.reveal().visit_with(visitor) } } @@ -1623,12 +1627,15 @@ impl<'tcx> TyCtxt<'tcx> { def_id1: DefId, def_id2: DefId, ) -> Option { - let impl1 = self.impl_trait_header(def_id1).unwrap().instantiate_identity(); - let impl2 = self.impl_trait_header(def_id2).unwrap().instantiate_identity(); + let impl1 = self.impl_trait_header(def_id1).unwrap(); + let impl2 = self.impl_trait_header(def_id2).unwrap(); + + let trait_ref1 = impl1.trait_ref.skip_binder(); + let trait_ref2 = impl2.trait_ref.skip_binder(); // If either trait impl references an error, they're allowed to overlap, // as one of them essentially doesn't exist. - if impl1.references_error() || impl2.references_error() { + if trait_ref1.references_error() || trait_ref2.references_error() { return Some(ImplOverlapKind::Permitted { marker: false }); } @@ -1649,7 +1656,7 @@ impl<'tcx> TyCtxt<'tcx> { let is_marker_overlap = { let is_marker_impl = |trait_ref: TraitRef<'_>| -> bool { self.trait_def(trait_ref.def_id).is_marker }; - is_marker_impl(impl1.trait_ref) && is_marker_impl(impl2.trait_ref) + is_marker_impl(trait_ref1) && is_marker_impl(trait_ref2) }; if is_marker_overlap { @@ -1933,18 +1940,6 @@ impl<'tcx> TyCtxt<'tcx> { matches!(self.trait_of_item(def_id), Some(trait_id) if self.has_attr(trait_id, sym::const_trait)) } - /// Returns the `DefId` of the item within which the `impl Trait` is declared. - /// For type-alias-impl-trait this is the `type` alias. - /// For impl-trait-in-assoc-type this is the assoc type. - /// For return-position-impl-trait this is the function. - pub fn impl_trait_parent(self, mut def_id: LocalDefId) -> LocalDefId { - // Find the surrounding item (type alias or assoc type) - while let DefKind::OpaqueTy = self.def_kind(def_id) { - def_id = self.local_parent(def_id); - } - def_id - } - pub fn impl_method_has_trait_impl_trait_tys(self, def_id: DefId) -> bool { if self.def_kind(def_id) != DefKind::AssocFn { return false; diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index 22f0574d61483..571c6e918dcbe 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -75,6 +75,7 @@ trivially_parameterized_over_tcx! { ty::Visibility, ty::adjustment::CoerceUnsizedInfo, ty::fast_reject::SimplifiedType, + ty::IntrinsicDef, rustc_ast::Attribute, rustc_ast::DelimArgs, rustc_ast::expand::StrippedCfgItem, diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 540803d953016..c8c9afa7f4d05 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -27,7 +27,7 @@ use std::cell::Cell; use std::collections::BTreeMap; use std::fmt::{self, Write as _}; use std::iter; -use std::ops::{ControlFlow, Deref, DerefMut}; +use std::ops::{Deref, DerefMut}; // `pretty` is a separate module only for organization. use super::*; @@ -2667,9 +2667,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { } impl<'tcx> ty::visit::TypeVisitor> for RegionNameCollector<'tcx> { - type BreakTy = (); - - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, r: ty::Region<'tcx>) { trace!("address: {:p}", r.0.0); // Collect all named lifetimes. These allow us to prevent duplication @@ -2678,18 +2676,14 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { if let Some(name) = r.get_name() { self.used_region_names.insert(name); } - - ControlFlow::Continue(()) } // We collect types in order to prevent really large types from compiling for // a really long time. See issue #83150 for why this is necessary. - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) { let not_previously_inserted = self.type_collector.insert(ty); if not_previously_inserted { ty.super_visit_with(self) - } else { - ControlFlow::Continue(()) } } } diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs index 51a4a9f411c02..7abc3cd283888 100644 --- a/compiler/rustc_middle/src/ty/region.rs +++ b/compiler/rustc_middle/src/ty/region.rs @@ -136,6 +136,12 @@ impl<'tcx> Region<'tcx> { } } +impl<'tcx> rustc_type_ir::new::Region> for Region<'tcx> { + fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self { + Region::new_bound(tcx, debruijn, ty::BoundRegion { var, kind: ty::BoundRegionKind::BrAnon }) + } +} + /// Region utilities impl<'tcx> Region<'tcx> { pub fn kind(self) -> RegionKind<'tcx> { diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index c6805ba932357..c8fb11673cf89 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -8,13 +8,14 @@ use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable}; use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer}; use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; use crate::ty::{self, AliasTy, InferConst, Lift, Term, TermKind, Ty, TyCtxt}; +use rustc_ast_ir::try_visit; +use rustc_ast_ir::visit::VisitorResult; use rustc_hir::def::Namespace; use rustc_span::source_map::Spanned; use rustc_target::abi::TyAndLayout; use rustc_type_ir::{ConstKind, DebugWithInfcx, InferCtxtLike, WithInfcx}; use std::fmt::{self, Debug}; -use std::ops::ControlFlow; use super::print::PrettyPrinter; use super::{GenericArg, GenericArgKind, Region}; @@ -482,11 +483,8 @@ impl<'a, 'tcx> Lift<'tcx> for Term<'a> { // Traversal implementations. impl<'tcx> TypeVisitable> for ty::AdtDef<'tcx> { - fn visit_with>>( - &self, - _visitor: &mut V, - ) -> ControlFlow { - ControlFlow::Continue(()) + fn visit_with>>(&self, _visitor: &mut V) -> V::Result { + V::Result::output() } } @@ -500,7 +498,7 @@ impl<'tcx, T: TypeFoldable>> TypeFoldable> for ty::Bin } impl<'tcx, T: TypeVisitable>> TypeVisitable> for ty::Binder<'tcx, T> { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>>(&self, visitor: &mut V) -> V::Result { visitor.visit_binder(self) } } @@ -517,10 +515,7 @@ impl<'tcx, T: TypeFoldable>> TypeSuperFoldable> for ty impl<'tcx, T: TypeVisitable>> TypeSuperVisitable> for ty::Binder<'tcx, T> { - fn super_visit_with>>( - &self, - visitor: &mut V, - ) -> ControlFlow { + fn super_visit_with>>(&self, visitor: &mut V) -> V::Result { self.as_ref().skip_binder().visit_with(visitor) } } @@ -553,7 +548,7 @@ impl<'tcx> TypeFoldable> for Ty<'tcx> { } impl<'tcx> TypeVisitable> for Ty<'tcx> { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>>(&self, visitor: &mut V) -> V::Result { visitor.visit_ty(*self) } } @@ -609,27 +604,24 @@ impl<'tcx> TypeSuperFoldable> for Ty<'tcx> { } impl<'tcx> TypeSuperVisitable> for Ty<'tcx> { - fn super_visit_with>>( - &self, - visitor: &mut V, - ) -> ControlFlow { + fn super_visit_with>>(&self, visitor: &mut V) -> V::Result { match self.kind() { ty::RawPtr(ref tm) => tm.visit_with(visitor), ty::Array(typ, sz) => { - typ.visit_with(visitor)?; + try_visit!(typ.visit_with(visitor)); sz.visit_with(visitor) } ty::Slice(typ) => typ.visit_with(visitor), ty::Adt(_, args) => args.visit_with(visitor), ty::Dynamic(ref trait_ty, ref reg, _) => { - trait_ty.visit_with(visitor)?; + try_visit!(trait_ty.visit_with(visitor)); reg.visit_with(visitor) } ty::Tuple(ts) => ts.visit_with(visitor), ty::FnDef(_, args) => args.visit_with(visitor), ty::FnPtr(ref f) => f.visit_with(visitor), ty::Ref(r, ty, _) => { - r.visit_with(visitor)?; + try_visit!(r.visit_with(visitor)); ty.visit_with(visitor) } ty::Coroutine(_did, ref args) => args.visit_with(visitor), @@ -650,7 +642,7 @@ impl<'tcx> TypeSuperVisitable> for Ty<'tcx> { | ty::Placeholder(..) | ty::Param(..) | ty::Never - | ty::Foreign(..) => ControlFlow::Continue(()), + | ty::Foreign(..) => V::Result::output(), } } } @@ -665,7 +657,7 @@ impl<'tcx> TypeFoldable> for ty::Region<'tcx> { } impl<'tcx> TypeVisitable> for ty::Region<'tcx> { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>>(&self, visitor: &mut V) -> V::Result { visitor.visit_region(*self) } } @@ -690,13 +682,13 @@ impl<'tcx> TypeFoldable> for ty::Clause<'tcx> { } impl<'tcx> TypeVisitable> for ty::Predicate<'tcx> { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>>(&self, visitor: &mut V) -> V::Result { visitor.visit_predicate(*self) } } impl<'tcx> TypeVisitable> for ty::Clause<'tcx> { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>>(&self, visitor: &mut V) -> V::Result { visitor.visit_predicate(self.as_predicate()) } } @@ -712,10 +704,7 @@ impl<'tcx> TypeSuperFoldable> for ty::Predicate<'tcx> { } impl<'tcx> TypeSuperVisitable> for ty::Predicate<'tcx> { - fn super_visit_with>>( - &self, - visitor: &mut V, - ) -> ControlFlow { + fn super_visit_with>>(&self, visitor: &mut V) -> V::Result { self.kind().visit_with(visitor) } } @@ -739,7 +728,7 @@ impl<'tcx> TypeFoldable> for ty::Const<'tcx> { } impl<'tcx> TypeVisitable> for ty::Const<'tcx> { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>>(&self, visitor: &mut V) -> V::Result { visitor.visit_const(*self) } } @@ -771,16 +760,13 @@ impl<'tcx> TypeSuperFoldable> for ty::Const<'tcx> { } impl<'tcx> TypeSuperVisitable> for ty::Const<'tcx> { - fn super_visit_with>>( - &self, - visitor: &mut V, - ) -> ControlFlow { - self.ty().visit_with(visitor)?; + fn super_visit_with>>(&self, visitor: &mut V) -> V::Result { + try_visit!(self.ty().visit_with(visitor)); match self.kind() { ConstKind::Param(p) => p.visit_with(visitor), ConstKind::Infer(i) => i.visit_with(visitor), ConstKind::Bound(d, b) => { - d.visit_with(visitor)?; + try_visit!(d.visit_with(visitor)); b.visit_with(visitor) } ConstKind::Placeholder(p) => p.visit_with(visitor), @@ -802,25 +788,19 @@ impl<'tcx> TypeFoldable> for InferConst { } impl<'tcx> TypeVisitable> for InferConst { - fn visit_with>>( - &self, - _visitor: &mut V, - ) -> ControlFlow { - ControlFlow::Continue(()) + fn visit_with>>(&self, _visitor: &mut V) -> V::Result { + V::Result::output() } } impl<'tcx> TypeSuperVisitable> for ty::UnevaluatedConst<'tcx> { - fn super_visit_with>>( - &self, - visitor: &mut V, - ) -> ControlFlow { + fn super_visit_with>>(&self, visitor: &mut V) -> V::Result { self.args.visit_with(visitor) } } impl<'tcx> TypeVisitable> for TyAndLayout<'tcx, Ty<'tcx>> { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>>(&self, visitor: &mut V) -> V::Result { visitor.visit_ty(self.ty) } } @@ -828,10 +808,9 @@ impl<'tcx> TypeVisitable> for TyAndLayout<'tcx, Ty<'tcx>> { impl<'tcx, T: TypeVisitable> + Debug + Clone> TypeVisitable> for Spanned { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { - self.node.visit_with(visitor)?; - self.span.visit_with(visitor)?; - ControlFlow::Continue(()) + fn visit_with>>(&self, visitor: &mut V) -> V::Result { + try_visit!(self.node.visit_with(visitor)); + self.span.visit_with(visitor) } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 53690cc58111f..427c0f04bd11e 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -13,9 +13,7 @@ use crate::ty::{GenericArg, GenericArgs, GenericArgsRef}; use crate::ty::{List, ParamEnv}; use hir::def::DefKind; use rustc_data_structures::captures::Captures; -use rustc_errors::{ - DiagArgValue, DiagnosticMessage, ErrorGuaranteed, IntoDiagnosticArg, MultiSpan, -}; +use rustc_errors::{DiagArgValue, ErrorGuaranteed, IntoDiagnosticArg, MultiSpan}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::LangItem; @@ -1426,7 +1424,8 @@ impl From for BoundTy { /// Constructors for `Ty` impl<'tcx> Ty<'tcx> { - // Avoid this in favour of more specific `new_*` methods, where possible. + /// Avoid using this in favour of more specific `new_*` methods, where possible. + /// The more specific methods will often optimize their creation. #[allow(rustc::usage_of_ty_tykind)] #[inline] pub fn new(tcx: TyCtxt<'tcx>, st: TyKind<'tcx>) -> Ty<'tcx> { @@ -1544,7 +1543,7 @@ impl<'tcx> Ty<'tcx> { pub fn new_error_with_message>( tcx: TyCtxt<'tcx>, span: S, - msg: impl Into, + msg: impl Into>, ) -> Ty<'tcx> { let reported = tcx.dcx().span_delayed_bug(span, msg); Ty::new(tcx, Error(reported)) @@ -1813,6 +1812,12 @@ impl<'tcx> Ty<'tcx> { } } +impl<'tcx> rustc_type_ir::new::Ty> for Ty<'tcx> { + fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self { + Ty::new_bound(tcx, debruijn, ty::BoundTy { var, kind: ty::BoundTyKind::Anon }) + } +} + /// Type utilities impl<'tcx> Ty<'tcx> { #[inline(always)] @@ -1994,6 +1999,27 @@ impl<'tcx> Ty<'tcx> { } } + /// Tests whether this is a Box using the global allocator. + #[inline] + pub fn is_box_global(self, tcx: TyCtxt<'tcx>) -> bool { + match self.kind() { + Adt(def, args) if def.is_box() => { + let Some(alloc) = args.get(1) else { + // Single-argument Box is always global. (for "minicore" tests) + return true; + }; + if let Some(alloc_adt) = alloc.expect_ty().ty_adt_def() { + let global_alloc = tcx.require_lang_item(LangItem::GlobalAlloc, None); + alloc_adt.did() == global_alloc + } else { + // Allocator is not an ADT... + false + } + } + _ => false, + } + } + /// Panics if called on any type other than `Box`. pub fn boxed_ty(self) -> Ty<'tcx> { match self.kind() { @@ -2108,9 +2134,9 @@ impl<'tcx> Ty<'tcx> { struct ContainsTyVisitor<'tcx>(Ty<'tcx>); impl<'tcx> TypeVisitor> for ContainsTyVisitor<'tcx> { - type BreakTy = (); + type Result = ControlFlow<()>; - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { if self.0 == t { ControlFlow::Break(()) } else { t.super_visit_with(self) } } } @@ -2126,9 +2152,9 @@ impl<'tcx> Ty<'tcx> { struct ContainsClosureVisitor; impl<'tcx> TypeVisitor> for ContainsClosureVisitor { - type BreakTy = (); + type Result = ControlFlow<()>; - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { if let ty::Closure(..) = t.kind() { ControlFlow::Break(()) } else { diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 5ead620927cd9..4bb0d2c7d1c2b 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -19,7 +19,7 @@ use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; use rustc_index::bit_set::GrowableBitSet; use rustc_macros::HashStable; use rustc_session::Limit; -use rustc_span::{sym, Symbol}; +use rustc_span::sym; use rustc_target::abi::{Integer, IntegerType, Primitive, Size}; use rustc_target::spec::abi::Abi; use smallvec::SmallVec; @@ -1641,12 +1641,15 @@ pub fn is_doc_notable_trait(tcx: TyCtxt<'_>, def_id: DefId) -> bool { .any(|items| items.iter().any(|item| item.has_name(sym::notable_trait))) } -/// Determines whether an item is an intrinsic by Abi. or by whether it has a `rustc_intrinsic` attribute -pub fn intrinsic(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option { +/// Determines whether an item is an intrinsic (which may be via Abi or via the `rustc_intrinsic` attribute) +pub fn intrinsic_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option { if matches!(tcx.fn_sig(def_id).skip_binder().abi(), Abi::RustIntrinsic) || tcx.has_attr(def_id, sym::rustc_intrinsic) { - Some(tcx.item_name(def_id.into())) + Some(ty::IntrinsicDef { + name: tcx.item_name(def_id.into()), + must_be_overridden: tcx.has_attr(def_id, sym::rustc_intrinsic_must_be_overridden), + }) } else { None } @@ -1657,7 +1660,7 @@ pub fn provide(providers: &mut Providers) { reveal_opaque_types_in_bounds, is_doc_hidden, is_doc_notable_trait, - intrinsic, + intrinsic_raw, ..*providers } } diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index 59d09c3dc7821..218567bbd59e8 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -64,19 +64,19 @@ impl<'tcx> TyCtxt<'tcx> { where F: FnMut(ty::Region<'tcx>) -> bool, { - type BreakTy = (); + type Result = ControlFlow<()>; fn visit_binder>>( &mut self, t: &Binder<'tcx, T>, - ) -> ControlFlow { + ) -> Self::Result { self.outer_index.shift_in(1); let result = t.super_visit_with(self); self.outer_index.shift_out(1); result } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result { match *r { ty::ReBound(debruijn, _) if debruijn < self.outer_index => { ControlFlow::Continue(()) @@ -91,7 +91,7 @@ impl<'tcx> TyCtxt<'tcx> { } } - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { // We're only interested in types involving regions if ty.flags().intersects(TypeFlags::HAS_FREE_REGIONS) { ty.super_visit_with(self) @@ -140,8 +140,7 @@ impl<'tcx> TyCtxt<'tcx> { let mut collector = LateBoundRegionsCollector::new(just_constrained); let value = value.skip_binder(); let value = if just_constrained { self.expand_weak_alias_tys(value) } else { value }; - let result = value.visit_with(&mut collector); - assert!(result.is_continue()); // should never have stopped early + value.visit_with(&mut collector); collector.regions } } @@ -165,19 +164,19 @@ impl<'tcx> ValidateBoundVars<'tcx> { } impl<'tcx> TypeVisitor> for ValidateBoundVars<'tcx> { - type BreakTy = (); + type Result = ControlFlow<()>; fn visit_binder>>( &mut self, t: &Binder<'tcx, T>, - ) -> ControlFlow { + ) -> Self::Result { self.binder_index.shift_in(1); let result = t.super_visit_with(self); self.binder_index.shift_out(1); result } - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { if t.outer_exclusive_binder() < self.binder_index || !self.visited.insert((self.binder_index, t)) { @@ -211,7 +210,7 @@ impl<'tcx> TypeVisitor> for ValidateBoundVars<'tcx> { t.super_visit_with(self) } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result { match *r { ty::ReBound(index, br) if index == self.binder_index => { if self.bound_vars.len() <= br.var.as_usize() { @@ -266,23 +265,19 @@ impl LateBoundRegionsCollector { } impl<'tcx> TypeVisitor> for LateBoundRegionsCollector { - fn visit_binder>>( - &mut self, - t: &Binder<'tcx, T>, - ) -> ControlFlow { + fn visit_binder>>(&mut self, t: &Binder<'tcx, T>) { self.current_index.shift_in(1); - let result = t.super_visit_with(self); + t.super_visit_with(self); self.current_index.shift_out(1); - result } - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) { if self.just_constrained { match t.kind() { // If we are only looking for "constrained" regions, we have to ignore the // inputs to a projection as they may not appear in the normalized form. ty::Alias(ty::Projection | ty::Inherent | ty::Opaque, _) => { - return ControlFlow::Continue(()); + return; } // All weak alias types should've been expanded beforehand. ty::Alias(ty::Weak, _) => bug!("unexpected weak alias type"), @@ -293,26 +288,25 @@ impl<'tcx> TypeVisitor> for LateBoundRegionsCollector { t.super_visit_with(self) } - fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, c: ty::Const<'tcx>) { // if we are only looking for "constrained" region, we have to // ignore the inputs of an unevaluated const, as they may not appear // in the normalized form if self.just_constrained { if let ty::ConstKind::Unevaluated(..) = c.kind() { - return ControlFlow::Continue(()); + return; } } c.super_visit_with(self) } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, r: ty::Region<'tcx>) { if let ty::ReBound(debruijn, br) = *r { if debruijn == self.current_index { self.regions.insert(br.kind); } } - ControlFlow::Continue(()) } } @@ -332,7 +326,7 @@ impl MaxUniverse { } impl<'tcx> TypeVisitor> for MaxUniverse { - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) { if let ty::Placeholder(placeholder) = t.kind() { self.max_universe = ty::UniverseIndex::from_u32( self.max_universe.as_u32().max(placeholder.universe.as_u32()), @@ -342,7 +336,7 @@ impl<'tcx> TypeVisitor> for MaxUniverse { t.super_visit_with(self) } - fn visit_const(&mut self, c: ty::consts::Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, c: ty::consts::Const<'tcx>) { if let ty::ConstKind::Placeholder(placeholder) = c.kind() { self.max_universe = ty::UniverseIndex::from_u32( self.max_universe.as_u32().max(placeholder.universe.as_u32()), @@ -352,13 +346,11 @@ impl<'tcx> TypeVisitor> for MaxUniverse { c.super_visit_with(self) } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, r: ty::Region<'tcx>) { if let ty::RePlaceholder(placeholder) = *r { self.max_universe = ty::UniverseIndex::from_u32( self.max_universe.as_u32().max(placeholder.universe.as_u32()), ); } - - ControlFlow::Continue(()) } } diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs index 27b48f46e75a2..f7a3879a7d40c 100644 --- a/compiler/rustc_middle/src/values.rs +++ b/compiler/rustc_middle/src/values.rs @@ -131,6 +131,27 @@ impl<'tcx> Value> for ty::EarlyBinder> } } +impl<'tcx> Value> for &[ty::Variance] { + fn from_cycle_error( + tcx: TyCtxt<'tcx>, + cycle_error: &CycleError, + _guar: ErrorGuaranteed, + ) -> Self { + if let Some(frame) = cycle_error.cycle.get(0) + && frame.query.dep_kind == dep_kinds::variances_of + && let Some(def_id) = frame.query.def_id + { + let n = tcx.generics_of(def_id).params.len(); + vec![ty::Variance::Bivariant; n].leak() + } else { + span_bug!( + cycle_error.usage.as_ref().unwrap().0, + "only `variances_of` returns `&[ty::Variance]`" + ); + } + } +} + // Take a cycle of `Q` and try `try_cycle` on every permutation, falling back to `otherwise`. fn search_for_cycle_permutation( cycle: &[Q], diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index f2cf6fe613c33..b4eeeccc127b4 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -58,52 +58,60 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.thir[scrutinee].span, ), ExprKind::If { cond, then, else_opt, if_then_scope } => { - let then_blk; let then_span = this.thir[then].span; let then_source_info = this.source_info(then_span); let condition_scope = this.local_scope(); - let mut else_blk = unpack!( - then_blk = this.in_scope( - (if_then_scope, then_source_info), - LintLevel::Inherited, - |this| { - let source_info = if this.is_let(cond) { - let variable_scope = - this.new_source_scope(then_span, LintLevel::Inherited, None); - this.source_scope = variable_scope; - SourceInfo { span: then_span, scope: variable_scope } - } else { - this.source_info(then_span) - }; - let (then_block, else_block) = - this.in_if_then_scope(condition_scope, then_span, |this| { - let then_blk = unpack!(this.then_else_break( - block, - cond, - Some(condition_scope), - condition_scope, - source_info, - true, - )); - - this.expr_into_dest(destination, then_blk, then) - }); - then_block.and(else_block) - }, - ) + let then_and_else_blocks = this.in_scope( + (if_then_scope, then_source_info), + LintLevel::Inherited, + |this| { + // FIXME: Does this need extra logic to handle let-chains? + let source_info = if this.is_let(cond) { + let variable_scope = + this.new_source_scope(then_span, LintLevel::Inherited, None); + this.source_scope = variable_scope; + SourceInfo { span: then_span, scope: variable_scope } + } else { + this.source_info(then_span) + }; + + // Lower the condition, and have it branch into `then` and `else` blocks. + let (then_block, else_block) = + this.in_if_then_scope(condition_scope, then_span, |this| { + let then_blk = unpack!(this.then_else_break( + block, + cond, + Some(condition_scope), // Temp scope + source_info, + true, // Declare `let` bindings normally + )); + + // Lower the `then` arm into its block. + this.expr_into_dest(destination, then_blk, then) + }); + + // Pack `(then_block, else_block)` into `BlockAnd`. + then_block.and(else_block) + }, ); - else_blk = if let Some(else_opt) = else_opt { - unpack!(this.expr_into_dest(destination, else_blk, else_opt)) + // Unpack `BlockAnd` into `(then_blk, else_blk)`. + let (then_blk, mut else_blk); + else_blk = unpack!(then_blk = then_and_else_blocks); + + // If there is an `else` arm, lower it into `else_blk`. + if let Some(else_expr) = else_opt { + unpack!(else_blk = this.expr_into_dest(destination, else_blk, else_expr)); } else { - // Body of the `if` expression without an `else` clause must return `()`, thus - // we implicitly generate an `else {}` if it is not specified. + // There is no `else` arm, so we know both arms have type `()`. + // Generate the implicit `else {}` by assigning unit. let correct_si = this.source_info(expr_span.shrink_to_hi()); this.cfg.push_assign_unit(else_blk, correct_si, destination, this.tcx); - else_blk - }; + } + // The `then` and `else` arms have been lowered into their respective + // blocks, so make both of them meet up in a new block. let join_block = this.cfg.start_new_block(); this.cfg.goto(then_blk, source_info, join_block); this.cfg.goto(else_blk, source_info, join_block); @@ -146,9 +154,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.then_else_break( block, lhs, - Some(condition_scope), - condition_scope, + Some(condition_scope), // Temp scope source_info, + // This flag controls how inner `let` expressions are lowered, + // but either way there shouldn't be any of those in here. true, ) }); @@ -374,6 +383,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { line_spans, }) => { use rustc_middle::{mir, thir}; + + let destination_block = this.cfg.start_new_block(); + let mut targets = if options.contains(InlineAsmOptions::NORETURN) { + vec![] + } else { + vec![destination_block] + }; + let operands = operands .into_iter() .map(|op| match *op { @@ -429,14 +446,28 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { thir::InlineAsmOperand::SymStatic { def_id } => { mir::InlineAsmOperand::SymStatic { def_id } } + thir::InlineAsmOperand::Label { block } => { + let target = this.cfg.start_new_block(); + let target_index = targets.len(); + targets.push(target); + + let tmp = this.get_unit_temp(); + let target = unpack!(this.ast_block(tmp, target, block, source_info)); + this.cfg.terminate( + target, + source_info, + TerminatorKind::Goto { target: destination_block }, + ); + + mir::InlineAsmOperand::Label { target_index } + } }) .collect(); - if !options.contains(InlineAsmOptions::NORETURN) { + if !expr.ty.is_never() { this.cfg.push_assign_unit(block, source_info, destination, this.tcx); } - let destination_block = this.cfg.start_new_block(); this.cfg.terminate( block, source_info, @@ -445,11 +476,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { operands, options, line_spans, - destination: if options.contains(InlineAsmOptions::NORETURN) { - None - } else { - Some(destination_block) - }, + targets, unwind: if options.contains(InlineAsmOptions::MAY_UNWIND) { UnwindAction::Continue } else { diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index a6273b92e5d69..31591983101f3 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -30,21 +30,46 @@ mod util; use std::borrow::Borrow; use std::mem; +/// Arguments to [`Builder::then_else_break_inner`] that are usually forwarded +/// to recursive invocations. +#[derive(Clone, Copy)] +struct ThenElseArgs { + /// Used as the temp scope for lowering `expr`. If absent (for match guards), + /// `self.local_scope()` is used. + temp_scope_override: Option, + variable_source_info: SourceInfo, + /// Forwarded to [`Builder::lower_let_expr`] when lowering [`ExprKind::Let`]. + /// When false (for match guards), `let` bindings won't be declared. + declare_let_bindings: bool, +} + impl<'a, 'tcx> Builder<'a, 'tcx> { /// Lowers a condition in a way that ensures that variables bound in any let /// expressions are definitely initialized in the if body. /// - /// If `declare_bindings` is false then variables created in `let` + /// If `declare_let_bindings` is false then variables created in `let` /// expressions will not be declared. This is for if let guards on arms with /// an or pattern, where the guard is lowered multiple times. pub(crate) fn then_else_break( &mut self, - mut block: BasicBlock, + block: BasicBlock, expr_id: ExprId, temp_scope_override: Option, - break_scope: region::Scope, variable_source_info: SourceInfo, - declare_bindings: bool, + declare_let_bindings: bool, + ) -> BlockAnd<()> { + self.then_else_break_inner( + block, + expr_id, + ThenElseArgs { temp_scope_override, variable_source_info, declare_let_bindings }, + ) + } + + fn then_else_break_inner( + &mut self, + block: BasicBlock, // Block that the condition and branch will be lowered into + expr_id: ExprId, // Condition expression to lower + args: ThenElseArgs, ) -> BlockAnd<()> { let this = self; let expr = &this.thir[expr_id]; @@ -52,54 +77,32 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { match expr.kind { ExprKind::LogicalOp { op: LogicalOp::And, lhs, rhs } => { - let lhs_then_block = unpack!(this.then_else_break( - block, - lhs, - temp_scope_override, - break_scope, - variable_source_info, - declare_bindings, - )); - - let rhs_then_block = unpack!(this.then_else_break( - lhs_then_block, - rhs, - temp_scope_override, - break_scope, - variable_source_info, - declare_bindings, - )); - + let lhs_then_block = unpack!(this.then_else_break_inner(block, lhs, args)); + let rhs_then_block = unpack!(this.then_else_break_inner(lhs_then_block, rhs, args)); rhs_then_block.unit() } ExprKind::LogicalOp { op: LogicalOp::Or, lhs, rhs } => { let local_scope = this.local_scope(); let (lhs_success_block, failure_block) = this.in_if_then_scope(local_scope, expr_span, |this| { - this.then_else_break( + this.then_else_break_inner( block, lhs, - temp_scope_override, - local_scope, - variable_source_info, - true, + ThenElseArgs { declare_let_bindings: true, ..args }, ) }); - let rhs_success_block = unpack!(this.then_else_break( + let rhs_success_block = unpack!(this.then_else_break_inner( failure_block, rhs, - temp_scope_override, - break_scope, - variable_source_info, - true, + ThenElseArgs { declare_let_bindings: true, ..args }, )); // Make the LHS and RHS success arms converge to a common block. // (We can't just make LHS goto RHS, because `rhs_success_block` // might contain statements that we don't want on the LHS path.) let success_block = this.cfg.start_new_block(); - this.cfg.goto(lhs_success_block, variable_source_info, success_block); - this.cfg.goto(rhs_success_block, variable_source_info, success_block); + this.cfg.goto(lhs_success_block, args.variable_source_info, success_block); + this.cfg.goto(rhs_success_block, args.variable_source_info, success_block); success_block.unit() } ExprKind::Unary { op: UnOp::Not, arg } => { @@ -111,50 +114,33 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if this.tcx.sess.instrument_coverage() { this.cfg.push_coverage_span_marker(block, this.source_info(expr_span)); } - this.then_else_break( + this.then_else_break_inner( block, arg, - temp_scope_override, - local_scope, - variable_source_info, - true, + ThenElseArgs { declare_let_bindings: true, ..args }, ) }); - this.break_for_else(success_block, break_scope, variable_source_info); + this.break_for_else(success_block, args.variable_source_info); failure_block.unit() } ExprKind::Scope { region_scope, lint_level, value } => { let region_scope = (region_scope, this.source_info(expr_span)); this.in_scope(region_scope, lint_level, |this| { - this.then_else_break( - block, - value, - temp_scope_override, - break_scope, - variable_source_info, - declare_bindings, - ) + this.then_else_break_inner(block, value, args) }) } - ExprKind::Use { source } => this.then_else_break( - block, - source, - temp_scope_override, - break_scope, - variable_source_info, - declare_bindings, - ), + ExprKind::Use { source } => this.then_else_break_inner(block, source, args), ExprKind::Let { expr, ref pat } => this.lower_let_expr( block, expr, pat, - break_scope, - Some(variable_source_info.scope), - variable_source_info.span, - declare_bindings, + Some(args.variable_source_info.scope), + args.variable_source_info.span, + args.declare_let_bindings, ), _ => { - let temp_scope = temp_scope_override.unwrap_or_else(|| this.local_scope()); + let mut block = block; + let temp_scope = args.temp_scope_override.unwrap_or_else(|| this.local_scope()); let mutability = Mutability::Mut; let place = unpack!(block = this.as_temp(block, Some(temp_scope), expr_id, mutability)); @@ -166,7 +152,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let source_info = this.source_info(expr_span); this.cfg.terminate(block, source_info, term); - this.break_for_else(else_block, break_scope, source_info); + this.break_for_else(else_block, source_info); then_block.unit() } @@ -1907,7 +1893,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { mut block: BasicBlock, expr_id: ExprId, pat: &Pat<'tcx>, - else_target: region::Scope, source_scope: Option, span: Span, declare_bindings: bool, @@ -1929,7 +1914,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let expr_place = expr_place_builder.try_to_place(self); let opt_expr_place = expr_place.as_ref().map(|place| (Some(place), expr_span)); let otherwise_post_guard_block = otherwise_candidate.pre_binding_block.unwrap(); - self.break_for_else(otherwise_post_guard_block, else_target, self.source_info(expr_span)); + self.break_for_else(otherwise_post_guard_block, self.source_info(expr_span)); if declare_bindings { self.declare_bindings(source_scope, pat.span.to(span), pat, None, opt_expr_place); @@ -2105,10 +2090,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.then_else_break( block, guard, - None, - match_scope, + None, // Use `self.local_scope()` as the temp scope this.source_info(arm.span), - false, + false, // For guards, `let` bindings are declared separately ) }); @@ -2439,7 +2423,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { None, true, ); - this.break_for_else(failure, *let_else_scope, this.source_info(initializer_span)); + this.break_for_else(failure, this.source_info(initializer_span)); matching.unit() }); matching.and(failure) diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index 04740a9629152..961502566baaa 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -683,20 +683,23 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.cfg.start_new_block().unit() } - pub(crate) fn break_for_else( - &mut self, - block: BasicBlock, - target: region::Scope, - source_info: SourceInfo, - ) { - let scope_index = self.scopes.scope_index(target, source_info.span); + /// Sets up the drops for breaking from `block` due to an `if` condition + /// that turned out to be false. + /// + /// Must be called in the context of [`Builder::in_if_then_scope`], so that + /// there is an if-then scope to tell us what the target scope is. + pub(crate) fn break_for_else(&mut self, block: BasicBlock, source_info: SourceInfo) { let if_then_scope = self .scopes .if_then_scope - .as_mut() + .as_ref() .unwrap_or_else(|| span_bug!(source_info.span, "no if-then scope found")); - assert_eq!(if_then_scope.region_scope, target, "breaking to incorrect scope"); + let target = if_then_scope.region_scope; + let scope_index = self.scopes.scope_index(target, source_info.span); + + // Upgrade `if_then_scope` to `&mut`. + let if_then_scope = self.scopes.if_then_scope.as_mut().expect("upgrading & to &mut"); let mut drop_idx = ROOT_NODE; let drops = &mut if_then_scope.else_drops; diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index d889f89f281f3..9a298a13eb665 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -2,7 +2,7 @@ use crate::fluent_generated as fluent; use rustc_errors::DiagArgValue; use rustc_errors::{ codes::*, AddToDiagnostic, Applicability, Diag, DiagCtxt, EmissionGuarantee, IntoDiagnostic, - Level, MultiSpan, SubdiagnosticMessageOp, + Level, MultiSpan, SubdiagMessageOp, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{self, Ty}; @@ -420,7 +420,7 @@ pub struct UnsafeNotInheritedLintNote { } impl AddToDiagnostic for UnsafeNotInheritedLintNote { - fn add_to_diagnostic_with>( + fn add_to_diagnostic_with>( self, diag: &mut Diag<'_, G>, _f: F, @@ -868,7 +868,7 @@ pub struct Variant { } impl<'tcx> AddToDiagnostic for AdtDefinedHere<'tcx> { - fn add_to_diagnostic_with>( + fn add_to_diagnostic_with>( self, diag: &mut Diag<'_, G>, _f: F, diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs index 3f2b7c482a67f..2c817d605af2a 100644 --- a/compiler/rustc_mir_build/src/lints.rs +++ b/compiler/rustc_mir_build/src/lints.rs @@ -199,9 +199,10 @@ impl<'mir, 'tcx, C: TerminatorClassifier<'tcx>> TriColorVisitor ControlFlow::Break(NonRecursive), - // A diverging InlineAsm is treated as non-recursing - TerminatorKind::InlineAsm { destination, .. } => { - if destination.is_some() { + // A InlineAsm without targets (diverging and contains no labels) + // is treated as non-recursing. + TerminatorKind::InlineAsm { ref targets, .. } => { + if !targets.is_empty() { ControlFlow::Continue(()) } else { ControlFlow::Break(NonRecursive) diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 62762168cf420..2318e84292b83 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -656,6 +656,9 @@ impl<'tcx> Cx<'tcx> { hir::InlineAsmOperand::SymStatic { path: _, def_id } => { InlineAsmOperand::SymStatic { def_id } } + hir::InlineAsmOperand::Label { block } => { + InlineAsmOperand::Label { block: self.mirror_block(block) } + } }) .collect(), options: asm.options, diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs index 267ea3aa3e12c..d53704f89e79e 100644 --- a/compiler/rustc_mir_build/src/thir/print.rs +++ b/compiler/rustc_mir_build/src/thir/print.rs @@ -889,6 +889,12 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { print_indented!(self, format!("def_id: {:?}", def_id), depth_lvl + 1); print_indented!(self, "}", depth_lvl + 1); } + InlineAsmOperand::Label { block } => { + print_indented!(self, "InlineAsmOperand::Block {", depth_lvl); + print_indented!(self, "block:", depth_lvl + 1); + self.print_block(*block, depth_lvl + 2); + print_indented!(self, "}", depth_lvl + 1); + } } } } diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs index 4c3fadf487b3c..f57e8b8bd6f97 100644 --- a/compiler/rustc_mir_dataflow/src/framework/direction.rs +++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs @@ -242,9 +242,9 @@ impl Direction for Backward { propagate(pred, &tmp); } - mir::TerminatorKind::InlineAsm { - destination: Some(dest), ref operands, .. - } if dest == bb => { + mir::TerminatorKind::InlineAsm { ref targets, ref operands, .. } + if targets.contains(&bb) => + { let mut tmp = exit_state.clone(); analysis.apply_call_return_effect( &mut tmp, @@ -491,9 +491,12 @@ impl Direction for Forward { if let Some(cleanup) = cleanup { propagate(cleanup, exit_state); } - if let Some(return_) = return_ { + + if !return_.is_empty() { analysis.apply_call_return_effect(exit_state, bb, place); - propagate(return_, exit_state); + for &target in return_ { + propagate(target, exit_state); + } } } TerminatorEdges::SwitchInt { targets, discr } => { diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs index 0270e059a5821..a827f6a8dbd9d 100644 --- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs +++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs @@ -299,7 +299,9 @@ where })?; } - mir::TerminatorKind::InlineAsm { destination: Some(_), ref operands, .. } => { + mir::TerminatorKind::InlineAsm { ref targets, ref operands, .. } + if !targets.is_empty() => + { self.write_row(w, "", "(on successful return)", |this, w, fmt| { let state_on_unwind = this.results.get().clone(); this.results.apply_custom_effect(|analysis, state| { diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs index 595c2ff5bf7fa..29169c31263bd 100644 --- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs @@ -271,7 +271,8 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> { InlineAsmOperand::In { .. } | InlineAsmOperand::Const { .. } | InlineAsmOperand::SymFn { .. } - | InlineAsmOperand::SymStatic { .. } => {} + | InlineAsmOperand::SymStatic { .. } + | InlineAsmOperand::Label { .. } => {} } } } diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index c6ec1b5aee454..db48ecd702bdb 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -491,7 +491,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { ref operands, options: _, line_spans: _, - destination: _, + targets: _, unwind: _, } => { for op in operands { @@ -515,7 +515,8 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { } InlineAsmOperand::Const { value: _ } | InlineAsmOperand::SymFn { value: _ } - | InlineAsmOperand::SymStatic { def_id: _ } => {} + | InlineAsmOperand::SymStatic { def_id: _ } + | InlineAsmOperand::Label { target_index: _ } => {} } } } diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs index 1575f31e75e0e..d7e3c91b875f8 100644 --- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs +++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs @@ -202,7 +202,7 @@ impl PeekCall { &terminator.kind { if let ty::FnDef(def_id, fn_args) = *func.const_.ty().kind() { - if tcx.intrinsic(def_id)? != sym::rustc_peek { + if tcx.intrinsic(def_id)?.name != sym::rustc_peek { return None; } diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs index c97192435ce48..ed8c4d8283d98 100644 --- a/compiler/rustc_mir_transform/src/coverage/graph.rs +++ b/compiler/rustc_mir_transform/src/coverage/graph.rs @@ -349,12 +349,20 @@ fn bcb_filtered_successors<'a, 'tcx>(terminator: &'a Terminator<'tcx>) -> Covera | FalseUnwind { real_target: target, .. } | Goto { target } => CoverageSuccessors::Chainable(target), - // These terminators can normally be chained, except when they have no + // A call terminator can normally be chained, except when they have no // successor because they are known to diverge. - Call { target: maybe_target, .. } | InlineAsm { destination: maybe_target, .. } => { - match maybe_target { - Some(target) => CoverageSuccessors::Chainable(target), - None => CoverageSuccessors::NotChainable(&[]), + Call { target: maybe_target, .. } => match maybe_target { + Some(target) => CoverageSuccessors::Chainable(target), + None => CoverageSuccessors::NotChainable(&[]), + }, + + // An inline asm terminator can normally be chained, except when it diverges or uses asm + // goto. + InlineAsm { ref targets, .. } => { + if targets.len() == 1 { + CoverageSuccessors::Chainable(targets[0]) + } else { + CoverageSuccessors::NotChainable(targets) } } diff --git a/compiler/rustc_mir_transform/src/coverage/tests.rs b/compiler/rustc_mir_transform/src/coverage/tests.rs index d9a3c0cb162f3..569998de35e0b 100644 --- a/compiler/rustc_mir_transform/src/coverage/tests.rs +++ b/compiler/rustc_mir_transform/src/coverage/tests.rs @@ -88,7 +88,6 @@ impl<'tcx> MockBlocks<'tcx> { | TerminatorKind::FalseEdge { real_target: ref mut target, .. } | TerminatorKind::FalseUnwind { real_target: ref mut target, .. } | TerminatorKind::Goto { ref mut target } - | TerminatorKind::InlineAsm { destination: Some(ref mut target), .. } | TerminatorKind::Yield { resume: ref mut target, .. } => *target = to_block, ref invalid => bug!("Invalid from_block: {:?}", invalid), } @@ -185,10 +184,12 @@ fn debug_basic_blocks(mir_body: &Body<'_>) -> String { | TerminatorKind::FalseEdge { real_target: target, .. } | TerminatorKind::FalseUnwind { real_target: target, .. } | TerminatorKind::Goto { target } - | TerminatorKind::InlineAsm { destination: Some(target), .. } | TerminatorKind::Yield { resume: target, .. } => { format!("{}{:?}:{} -> {:?}", sp, bb, kind.name(), target) } + TerminatorKind::InlineAsm { targets, .. } => { + format!("{}{:?}:{} -> {:?}", sp, bb, kind.name(), targets) + } TerminatorKind::SwitchInt { targets, .. } => { format!("{}{:?}:{} -> {:?}", sp, bb, kind.name(), targets) } diff --git a/compiler/rustc_mir_transform/src/cross_crate_inline.rs b/compiler/rustc_mir_transform/src/cross_crate_inline.rs index 483fd753e7077..07e6ecccaa42c 100644 --- a/compiler/rustc_mir_transform/src/cross_crate_inline.rs +++ b/compiler/rustc_mir_transform/src/cross_crate_inline.rs @@ -23,6 +23,10 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { return false; } + if tcx.intrinsic(def_id).is_some_and(|i| i.must_be_overridden) { + return false; + } + // This just reproduces the logic from Instance::requires_inline. match tcx.def_kind(def_id) { DefKind::Ctor(..) | DefKind::Closure => return true, diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 6e635529d9667..19109735d4871 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -36,7 +36,7 @@ pub(crate) macro throw_machine_stop_str($($tt:tt)*) {{ } impl rustc_middle::mir::interpret::MachineStopType for Zst { - fn diagnostic_message(&self) -> rustc_errors::DiagnosticMessage { + fn diagnostic_message(&self) -> rustc_errors::DiagMessage { self.to_string().into() } @@ -929,7 +929,7 @@ impl<'mir, 'tcx: 'mir> rustc_const_eval::interpret::Machine<'mir, 'tcx> for Dumm _instance: ty::Instance<'tcx>, _abi: rustc_target::spec::abi::Abi, _args: &[rustc_const_eval::interpret::FnArg<'tcx, Self::Provenance>], - _destination: &rustc_const_eval::interpret::PlaceTy<'tcx, Self::Provenance>, + _destination: &rustc_const_eval::interpret::MPlaceTy<'tcx, Self::Provenance>, _target: Option, _unwind: UnwindAction, ) -> interpret::InterpResult<'tcx, Option<(&'mir Body<'tcx>, ty::Instance<'tcx>)>> { @@ -947,7 +947,7 @@ impl<'mir, 'tcx: 'mir> rustc_const_eval::interpret::Machine<'mir, 'tcx> for Dumm _ecx: &mut InterpCx<'mir, 'tcx, Self>, _instance: ty::Instance<'tcx>, _args: &[rustc_const_eval::interpret::OpTy<'tcx, Self::Provenance>], - _destination: &rustc_const_eval::interpret::PlaceTy<'tcx, Self::Provenance>, + _destination: &rustc_const_eval::interpret::MPlaceTy<'tcx, Self::Provenance>, _target: Option, _unwind: UnwindAction, ) -> interpret::InterpResult<'tcx> { diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index 2c8201b1903e6..10fea09531a65 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -648,7 +648,8 @@ impl WriteInfo { } InlineAsmOperand::Const { .. } | InlineAsmOperand::SymFn { .. } - | InlineAsmOperand::SymStatic { .. } => (), + | InlineAsmOperand::SymStatic { .. } + | InlineAsmOperand::Label { .. } => {} } } } diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index f3eff247bc705..80e9172bbe124 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -1,7 +1,7 @@ use std::borrow::Cow; use rustc_errors::{ - codes::*, Applicability, DecorateLint, Diag, DiagArgValue, DiagCtxt, DiagnosticMessage, + codes::*, Applicability, DecorateLint, Diag, DiagArgValue, DiagCtxt, DiagMessage, EmissionGuarantee, IntoDiagnostic, Level, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; @@ -149,7 +149,7 @@ impl RequiresUnsafeDetail { } } - fn label(&self) -> DiagnosticMessage { + fn label(&self) -> DiagMessage { use UnsafetyViolationDetails::*; match self.violation { CallToUnsafeFunction => fluent::mir_transform_call_to_unsafe_label, @@ -199,7 +199,7 @@ impl<'a> DecorateLint<'a, ()> for UnsafeOpInUnsafeFn { } } - fn msg(&self) -> DiagnosticMessage { + fn msg(&self) -> DiagMessage { fluent::mir_transform_unsafe_op_in_unsafe_fn } } @@ -224,7 +224,7 @@ impl<'a, P: std::fmt::Debug> DecorateLint<'a, ()> for AssertLint

{ diag.span_label(self.span, message); } - fn msg(&self) -> DiagnosticMessage { + fn msg(&self) -> DiagMessage { match self.lint_kind { AssertLintKind::ArithmeticOverflow => fluent::mir_transform_arithmetic_overflow, AssertLintKind::UnconditionalPanic => fluent::mir_transform_operation_will_panic, @@ -281,7 +281,7 @@ impl<'a> DecorateLint<'a, ()> for MustNotSupend<'_, '_> { diag.arg("post", self.post); } - fn msg(&self) -> rustc_errors::DiagnosticMessage { + fn msg(&self) -> rustc_errors::DiagMessage { fluent::mir_transform_must_not_suspend } } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 36546a03cdfc5..f6a0945c22297 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -1036,8 +1036,8 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> { { bug!("False unwinds should have been removed before inlining") } - TerminatorKind::InlineAsm { ref mut destination, ref mut unwind, .. } => { - if let Some(ref mut tgt) = *destination { + TerminatorKind::InlineAsm { ref mut targets, ref mut unwind, .. } => { + for tgt in targets.iter_mut() { *tgt = self.map_block(*tgt); } *unwind = self.map_unwind(*unwind); diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index 73102a5f026d9..6b33d81c1c412 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -323,8 +323,8 @@ fn resolve_rust_intrinsic<'tcx>( func_ty: Ty<'tcx>, ) -> Option<(Symbol, GenericArgsRef<'tcx>)> { if let ty::FnDef(def_id, args) = *func_ty.kind() { - let name = tcx.intrinsic(def_id)?; - return Some((name, args)); + let intrinsic = tcx.intrinsic(def_id)?; + return Some((intrinsic.name, args)); } None } diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 945c3c662a604..cd9b98e4f32cd 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -160,7 +160,7 @@ fn remap_mir_for_const_eval_select<'tcx>( fn_span, .. } if let ty::FnDef(def_id, _) = *const_.ty().kind() - && matches!(tcx.intrinsic(def_id), Some(sym::const_eval_select)) => + && tcx.is_intrinsic(def_id, sym::const_eval_select) => { let [tupled_args, called_in_const, called_at_rt]: [_; 3] = std::mem::take(args).try_into().unwrap(); @@ -632,6 +632,12 @@ fn optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> &Body<'_> { } fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> { + if tcx.intrinsic(did).is_some_and(|i| i.must_be_overridden) { + span_bug!( + tcx.def_span(did), + "this intrinsic must be overridden by the codegen backend, it has no meaningful body", + ) + } if tcx.is_constructor(did.to_def_id()) { // There's no reason to run all of the MIR passes on constructors when // we can just output the MIR we want directly. This also saves const diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index a0af902c4e109..f317c025e966c 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -14,9 +14,9 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { if let TerminatorKind::Call { func, args, destination, target, .. } = &mut terminator.kind && let ty::FnDef(def_id, generic_args) = *func.ty(local_decls, tcx).kind() - && let Some(intrinsic_name) = tcx.intrinsic(def_id) + && let Some(intrinsic) = tcx.intrinsic(def_id) { - match intrinsic_name { + match intrinsic.name { sym::unreachable => { terminator.kind = TerminatorKind::Unreachable; } @@ -105,7 +105,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { lhs = args.next().unwrap(); rhs = args.next().unwrap(); } - let bin_op = match intrinsic_name { + let bin_op = match intrinsic.name { sym::wrapping_add => BinOp::Add, sym::wrapping_sub => BinOp::Sub, sym::wrapping_mul => BinOp::Mul, @@ -136,7 +136,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { lhs = args.next().unwrap(); rhs = args.next().unwrap(); } - let bin_op = match intrinsic_name { + let bin_op = match intrinsic.name { sym::add_with_overflow => BinOp::Add, sym::sub_with_overflow => BinOp::Sub, sym::mul_with_overflow => BinOp::Mul, @@ -155,7 +155,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { sym::size_of | sym::min_align_of => { if let Some(target) = *target { let tp_ty = generic_args.type_at(0); - let null_op = match intrinsic_name { + let null_op = match intrinsic.name { sym::size_of => NullOp::SizeOf, sym::min_align_of => NullOp::AlignOf, _ => bug!("unexpected intrinsic"), diff --git a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs index e68d37f4c701e..57fe46ad75aee 100644 --- a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs +++ b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs @@ -2,8 +2,10 @@ use crate::MirPass; use rustc_data_structures::fx::FxHashSet; +use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::{ - BasicBlockData, Body, Local, Operand, Rvalue, StatementKind, Terminator, TerminatorKind, + BasicBlock, BasicBlockData, BasicBlocks, Body, Local, Operand, Rvalue, StatementKind, + TerminatorKind, }; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{Ty, TyCtxt}; @@ -77,7 +79,8 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { trace!("UninhabitedEnumBranching starting for {:?}", body.source); - let mut removable_switchs = Vec::new(); + let mut unreachable_targets = Vec::new(); + let mut patch = MirPatch::new(body); for (bb, bb_data) in body.basic_blocks.iter_enumerated() { trace!("processing block {:?}", bb); @@ -92,46 +95,73 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching { tcx.param_env_reveal_all_normalized(body.source.def_id()).and(discriminant_ty), ); - let allowed_variants = if let Ok(layout) = layout { + let mut allowed_variants = if let Ok(layout) = layout { variant_discriminants(&layout, discriminant_ty, tcx) + } else if let Some(variant_range) = discriminant_ty.variant_range(tcx) { + variant_range + .map(|variant| { + discriminant_ty.discriminant_for_variant(tcx, variant).unwrap().val + }) + .collect() } else { continue; }; trace!("allowed_variants = {:?}", allowed_variants); - let terminator = bb_data.terminator(); - let TerminatorKind::SwitchInt { targets, .. } = &terminator.kind else { bug!() }; + unreachable_targets.clear(); + let TerminatorKind::SwitchInt { targets, discr } = &bb_data.terminator().kind else { + bug!() + }; - let mut reachable_count = 0; for (index, (val, _)) in targets.iter().enumerate() { - if allowed_variants.contains(&val) { - reachable_count += 1; - } else { - removable_switchs.push((bb, index)); + if !allowed_variants.remove(&val) { + unreachable_targets.push(index); + } + } + let otherwise_is_empty_unreachable = + body.basic_blocks[targets.otherwise()].is_empty_unreachable(); + // After resolving https://github.com/llvm/llvm-project/issues/78578, + // we can remove the limit on the number of successors. + fn check_successors(basic_blocks: &BasicBlocks<'_>, bb: BasicBlock) -> bool { + let mut successors = basic_blocks[bb].terminator().successors(); + let Some(first_successor) = successors.next() else { return true }; + if successors.next().is_some() { + return true; } + if let TerminatorKind::SwitchInt { .. } = + &basic_blocks[first_successor].terminator().kind + { + return false; + }; + true } + let otherwise_is_last_variant = !otherwise_is_empty_unreachable + && allowed_variants.len() == 1 + && check_successors(&body.basic_blocks, targets.otherwise()); + let replace_otherwise_to_unreachable = otherwise_is_last_variant + || !otherwise_is_empty_unreachable && allowed_variants.is_empty(); - if reachable_count == allowed_variants.len() { - removable_switchs.push((bb, targets.iter().count())); + if unreachable_targets.is_empty() && !replace_otherwise_to_unreachable { + continue; } - } - if removable_switchs.is_empty() { - return; + let unreachable_block = patch.unreachable_no_cleanup_block(); + let mut targets = targets.clone(); + if replace_otherwise_to_unreachable { + if otherwise_is_last_variant { + #[allow(rustc::potential_query_instability)] + let last_variant = *allowed_variants.iter().next().unwrap(); + targets.add_target(last_variant, targets.otherwise()); + } + unreachable_targets.push(targets.iter().count()); + } + for index in unreachable_targets.iter() { + targets.all_targets_mut()[*index] = unreachable_block; + } + patch.patch_terminator(bb, TerminatorKind::SwitchInt { targets, discr: discr.clone() }); } - let new_block = BasicBlockData::new(Some(Terminator { - source_info: body.basic_blocks[removable_switchs[0].0].terminator().source_info, - kind: TerminatorKind::Unreachable, - })); - let unreachable_block = body.basic_blocks.as_mut().push(new_block); - - for (bb, index) in removable_switchs { - let bb = &mut body.basic_blocks.as_mut()[bb]; - let terminator = bb.terminator_mut(); - let TerminatorKind::SwitchInt { targets, .. } = &mut terminator.kind else { bug!() }; - targets.all_targets_mut()[index] = unreachable_block; - } + patch.apply(body); } } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 5593de607844d..32f823a5ac68f 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -446,7 +446,8 @@ fn collect_items_rec<'tcx>( hir::InlineAsmOperand::In { .. } | hir::InlineAsmOperand::Out { .. } | hir::InlineAsmOperand::InOut { .. } - | hir::InlineAsmOperand::SplitInOut { .. } => { + | hir::InlineAsmOperand::SplitInOut { .. } + | hir::InlineAsmOperand::Label { .. } => { span_bug!(*op_sp, "invalid operand type for global_asm!") } } @@ -1019,6 +1020,11 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) -> return false; } + if tcx.intrinsic(def_id).is_some_and(|i| i.must_be_overridden) { + // These are implemented by backends directly and have no meaningful body. + return false; + } + if def_id.is_local() { // Local items cannot be referred to locally without monomorphizing them locally. return true; @@ -1356,7 +1362,7 @@ fn create_mono_items_for_default_impls<'tcx>( return; }; - if matches!(impl_.skip_binder().polarity, ty::ImplPolarity::Negative) { + if matches!(impl_.polarity, ty::ImplPolarity::Negative) { return; } @@ -1380,7 +1386,7 @@ fn create_mono_items_for_default_impls<'tcx>( } }; let impl_args = GenericArgs::for_item(tcx, item.owner_id.to_def_id(), only_region_params); - let trait_ref = impl_.instantiate(tcx, impl_args).trait_ref; + let trait_ref = impl_.trait_ref.instantiate(tcx, impl_args); // Unlike 'lazy' monomorphization that begins by collecting items transitively // called by `main` or other global items, when eagerly monomorphizing impl diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs index fb42532e247af..1070d1a1380d8 100644 --- a/compiler/rustc_monomorphize/src/polymorphize.rs +++ b/compiler/rustc_monomorphize/src/polymorphize.rs @@ -18,7 +18,6 @@ use rustc_middle::ty::{ GenericArgsRef, Ty, TyCtxt, UnusedGenericParams, }; use rustc_span::symbol::sym; -use std::ops::ControlFlow; use crate::errors::UnusedGenericParamsHint; @@ -291,31 +290,29 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { impl<'a, 'tcx> TypeVisitor> for MarkUsedGenericParams<'a, 'tcx> { #[instrument(level = "debug", skip(self))] - fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, c: ty::Const<'tcx>) { if !c.has_non_region_param() { - return ControlFlow::Continue(()); + return; } match c.kind() { ty::ConstKind::Param(param) => { debug!(?param); self.unused_parameters.mark_used(param.index); - ControlFlow::Continue(()) } ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args }) if matches!(self.tcx.def_kind(def), DefKind::AnonConst) => { self.visit_child_body(def, args); - ControlFlow::Continue(()) } _ => c.super_visit_with(self), } } #[instrument(level = "debug", skip(self))] - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) { if !ty.has_non_region_param() { - return ControlFlow::Continue(()); + return; } match *ty.kind() { @@ -323,18 +320,16 @@ impl<'a, 'tcx> TypeVisitor> for MarkUsedGenericParams<'a, 'tcx> { debug!(?def_id); // Avoid cycle errors with coroutines. if def_id == self.def_id { - return ControlFlow::Continue(()); + return; } // Consider any generic parameters used by any closures/coroutines as used in the // parent. self.visit_child_body(def_id, args); - ControlFlow::Continue(()) } ty::Param(param) => { debug!(?param); self.unused_parameters.mark_used(param.index); - ControlFlow::Continue(()) } _ => ty.super_visit_with(self), } diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs index 7b73e2aebf039..95b3006666202 100644 --- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs @@ -1,6 +1,7 @@ use std::cmp::Ordering; use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; +use rustc_type_ir::new::{Const, Region, Ty}; use rustc_type_ir::visit::TypeVisitableExt; use rustc_type_ir::{ self as ty, Canonical, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind, ConstTy, @@ -293,7 +294,7 @@ impl, I: Interner> TypeFolder var }); - self.interner().mk_bound_region(self.binder_index, var) + Region::new_anon_bound(self.interner(), self.binder_index, var) } fn fold_ty(&mut self, t: I::Ty) -> I::Ty @@ -375,7 +376,7 @@ impl, I: Interner> TypeFolder }), ); - self.interner().mk_bound_ty(self.binder_index, var) + Ty::new_anon_bound(self.interner(), self.binder_index, var) } fn fold_const(&mut self, c: I::Const) -> I::Const @@ -435,6 +436,6 @@ impl, I: Interner> TypeFolder }), ); - self.interner().mk_bound_const(self.binder_index, var, c.ty()) + Const::new_anon_bound(self.interner(), self.binder_index, var, c.ty()) } } diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 91dbf0321d2c6..c72b7e2cfa727 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -4,7 +4,7 @@ use rustc_ast::token::Token; use rustc_ast::{Path, Visibility}; use rustc_errors::{ codes::*, AddToDiagnostic, Applicability, Diag, DiagCtxt, EmissionGuarantee, IntoDiagnostic, - Level, SubdiagnosticMessageOp, + Level, SubdiagMessageOp, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_session::errors::ExprParenthesesNeeded; @@ -1467,7 +1467,7 @@ pub(crate) struct FnTraitMissingParen { } impl AddToDiagnostic for FnTraitMissingParen { - fn add_to_diagnostic_with>( + fn add_to_diagnostic_with>( self, diag: &mut Diag<'_, G>, _: F, diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 4cfd061ebd921..f57945a52df37 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -14,7 +14,7 @@ use rustc_lexer::{Cursor, LiteralKind}; use rustc_session::lint::builtin::{ RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, TEXT_DIRECTION_CODEPOINT_IN_COMMENT, }; -use rustc_session::lint::BuiltinLintDiagnostics; +use rustc_session::lint::BuiltinLintDiag; use rustc_session::parse::ParseSess; use rustc_span::symbol::Symbol; use rustc_span::{edition::Edition, BytePos, Pos, Span}; @@ -42,12 +42,12 @@ pub struct UnmatchedDelim { pub candidate_span: Option, } -pub(crate) fn parse_token_trees<'sess, 'src>( - sess: &'sess ParseSess, +pub(crate) fn parse_token_trees<'psess, 'src>( + psess: &'psess ParseSess, mut src: &'src str, mut start_pos: BytePos, override_span: Option, -) -> Result>> { +) -> Result>> { // Skip `#!`, if present. if let Some(shebang_len) = rustc_lexer::strip_shebang(src) { src = &src[shebang_len..]; @@ -56,7 +56,7 @@ pub(crate) fn parse_token_trees<'sess, 'src>( let cursor = Cursor::new(src); let string_reader = StringReader { - sess, + psess, start_pos, pos: start_pos, src, @@ -75,7 +75,7 @@ pub(crate) fn parse_token_trees<'sess, 'src>( let mut buffer = Vec::with_capacity(1); for unmatched in unmatched_delims { - if let Some(err) = make_unclosed_delims_error(unmatched, sess) { + if let Some(err) = make_unclosed_delims_error(unmatched, psess) { buffer.push(err); } } @@ -90,8 +90,8 @@ pub(crate) fn parse_token_trees<'sess, 'src>( } } -struct StringReader<'sess, 'src> { - sess: &'sess ParseSess, +struct StringReader<'psess, 'src> { + psess: &'psess ParseSess, /// Initial position, read-only. start_pos: BytePos, /// The absolute offset within the source_map of the current character. @@ -107,9 +107,9 @@ struct StringReader<'sess, 'src> { nbsp_is_whitespace: bool, } -impl<'sess, 'src> StringReader<'sess, 'src> { - pub fn dcx(&self) -> &'sess DiagCtxt { - &self.sess.dcx +impl<'psess, 'src> StringReader<'psess, 'src> { + pub fn dcx(&self) -> &'psess DiagCtxt { + &self.psess.dcx } fn mk_sp(&self, lo: BytePos, hi: BytePos) -> Span { @@ -176,11 +176,11 @@ impl<'sess, 'src> StringReader<'sess, 'src> { rustc_lexer::TokenKind::RawIdent => { let sym = nfc_normalize(self.str_from(start + BytePos(2))); let span = self.mk_sp(start, self.pos); - self.sess.symbol_gallery.insert(sym, span); + self.psess.symbol_gallery.insert(sym, span); if !sym.can_be_raw() { self.dcx().emit_err(errors::CannotBeRawIdent { span, ident: sym }); } - self.sess.raw_identifier_spans.push(span); + self.psess.raw_identifier_spans.push(span); token::Ident(sym, IdentIsRaw::Yes) } rustc_lexer::TokenKind::UnknownPrefix => { @@ -199,7 +199,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> { { let sym = nfc_normalize(self.str_from(start)); let span = self.mk_sp(start, self.pos); - self.sess.bad_unicode_identifiers.borrow_mut().entry(sym).or_default() + self.psess.bad_unicode_identifiers.borrow_mut().entry(sym).or_default() .push(span); token::Ident(sym, IdentIsRaw::No) } @@ -230,7 +230,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> { let suffix = if suffix_start < self.pos { let string = self.str_from(suffix_start); if string == "_" { - self.sess + self.psess .dcx .emit_err(errors::UnderscoreLiteralSuffix { span: self.mk_sp(suffix_start, self.pos) }); None @@ -338,7 +338,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> { fn ident(&self, start: BytePos) -> TokenKind { let sym = nfc_normalize(self.str_from(start)); let span = self.mk_sp(start, self.pos); - self.sess.symbol_gallery.insert(sym, span); + self.psess.symbol_gallery.insert(sym, span); token::Ident(sym, IdentIsRaw::No) } @@ -350,12 +350,12 @@ impl<'sess, 'src> StringReader<'sess, 'src> { let content = self.str_from(content_start); if contains_text_flow_control_chars(content) { let span = self.mk_sp(start, self.pos); - self.sess.buffer_lint_with_diagnostic( + self.psess.buffer_lint_with_diagnostic( TEXT_DIRECTION_CODEPOINT_IN_COMMENT, span, ast::CRATE_NODE_ID, "unicode codepoint changing visible direction of text present in comment", - BuiltinLintDiagnostics::UnicodeTextFlow(span, content.to_string()), + BuiltinLintDiag::UnicodeTextFlow(span, content.to_string()), ); } } @@ -566,7 +566,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> { } fn report_non_started_raw_string(&self, start: BytePos, bad_char: char) -> ! { - self.sess + self.psess .dcx .struct_span_fatal( self.mk_sp(start, self.pos), @@ -680,12 +680,12 @@ impl<'sess, 'src> StringReader<'sess, 'src> { self.dcx().emit_err(errors::UnknownPrefix { span: prefix_span, prefix, sugg }); } else { // Before Rust 2021, only emit a lint for migration. - self.sess.buffer_lint_with_diagnostic( + self.psess.buffer_lint_with_diagnostic( RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, prefix_span, ast::CRATE_NODE_ID, format!("prefix `{prefix}` is unknown"), - BuiltinLintDiagnostics::ReservedPrefix(prefix_span), + BuiltinLintDiag::ReservedPrefix(prefix_span), ); } } diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs index c9ff2d58e2c56..a506f98bf3a53 100644 --- a/compiler/rustc_parse/src/lexer/tokentrees.rs +++ b/compiler/rustc_parse/src/lexer/tokentrees.rs @@ -8,18 +8,18 @@ use rustc_ast_pretty::pprust::token_to_string; use rustc_errors::{Applicability, PErr}; use rustc_span::symbol::kw; -pub(super) struct TokenTreesReader<'sess, 'src> { - string_reader: StringReader<'sess, 'src>, +pub(super) struct TokenTreesReader<'psess, 'src> { + string_reader: StringReader<'psess, 'src>, /// The "next" token, which has been obtained from the `StringReader` but /// not yet handled by the `TokenTreesReader`. token: Token, diag_info: TokenTreeDiagInfo, } -impl<'sess, 'src> TokenTreesReader<'sess, 'src> { +impl<'psess, 'src> TokenTreesReader<'psess, 'src> { pub(super) fn parse_all_token_trees( - string_reader: StringReader<'sess, 'src>, - ) -> (TokenStream, Result<(), Vec>>, Vec) { + string_reader: StringReader<'psess, 'src>, + ) -> (TokenStream, Result<(), Vec>>, Vec) { let mut tt_reader = TokenTreesReader { string_reader, token: Token::dummy(), @@ -35,7 +35,7 @@ impl<'sess, 'src> TokenTreesReader<'sess, 'src> { fn parse_token_trees( &mut self, is_delimited: bool, - ) -> (Spacing, TokenStream, Result<(), Vec>>) { + ) -> (Spacing, TokenStream, Result<(), Vec>>) { // Move past the opening delimiter. let (_, open_spacing) = self.bump(false); @@ -71,9 +71,9 @@ impl<'sess, 'src> TokenTreesReader<'sess, 'src> { } } - fn eof_err(&mut self) -> PErr<'sess> { + fn eof_err(&mut self) -> PErr<'psess> { let msg = "this file contains an unclosed delimiter"; - let mut err = self.string_reader.sess.dcx.struct_span_err(self.token.span, msg); + let mut err = self.string_reader.psess.dcx.struct_span_err(self.token.span, msg); for &(_, sp) in &self.diag_info.open_braces { err.span_label(sp, "unclosed delimiter"); self.diag_info.unmatched_delims.push(UnmatchedDelim { @@ -89,7 +89,7 @@ impl<'sess, 'src> TokenTreesReader<'sess, 'src> { report_suspicious_mismatch_block( &mut err, &self.diag_info, - self.string_reader.sess.source_map(), + self.string_reader.psess.source_map(), *delim, ) } @@ -99,7 +99,7 @@ impl<'sess, 'src> TokenTreesReader<'sess, 'src> { fn parse_token_tree_open_delim( &mut self, open_delim: Delimiter, - ) -> Result>> { + ) -> Result>> { // The span for beginning of the delimited section let pre_span = self.token.span; @@ -115,7 +115,7 @@ impl<'sess, 'src> TokenTreesReader<'sess, 'src> { // Expand to cover the entire delimited token tree let delim_span = DelimSpan::from_pair(pre_span, self.token.span); - let sm = self.string_reader.sess.source_map(); + let sm = self.string_reader.psess.source_map(); let close_spacing = match self.token.kind { // Correct delimiter. @@ -232,11 +232,11 @@ impl<'sess, 'src> TokenTreesReader<'sess, 'src> { fn unclosed_delim_err( &mut self, tts: TokenStream, - mut errs: Vec>, - ) -> Vec> { + mut errs: Vec>, + ) -> Vec> { // If there are unclosed delims, see if there are diff markers and if so, point them // out instead of complaining about the unclosed delims. - let mut parser = crate::stream_to_parser(self.string_reader.sess, tts, None); + let mut parser = crate::stream_to_parser(self.string_reader.psess, tts, None); let mut diff_errs = vec![]; // Suggest removing a `{` we think appears in an `if`/`while` condition // We want to suggest removing a `{` only if we think we're in an `if`/`while` condition, but @@ -289,17 +289,17 @@ impl<'sess, 'src> TokenTreesReader<'sess, 'src> { return errs; } - fn close_delim_err(&mut self, delim: Delimiter) -> PErr<'sess> { + fn close_delim_err(&mut self, delim: Delimiter) -> PErr<'psess> { // An unexpected closing delimiter (i.e., there is no // matching opening delimiter). let token_str = token_to_string(&self.token); let msg = format!("unexpected closing delimiter: `{token_str}`"); - let mut err = self.string_reader.sess.dcx.struct_span_err(self.token.span, msg); + let mut err = self.string_reader.psess.dcx.struct_span_err(self.token.span, msg); report_suspicious_mismatch_block( &mut err, &self.diag_info, - self.string_reader.sess.source_map(), + self.string_reader.psess.source_map(), delim, ); err.span_label(self.token.span, "unexpected closing delimiter"); diff --git a/compiler/rustc_parse/src/lexer/unicode_chars.rs b/compiler/rustc_parse/src/lexer/unicode_chars.rs index 3b4e05332fac9..6b055fc844ae1 100644 --- a/compiler/rustc_parse/src/lexer/unicode_chars.rs +++ b/compiler/rustc_parse/src/lexer/unicode_chars.rs @@ -350,7 +350,7 @@ pub(super) fn check_for_substitution( let Some((_, ascii_name, token)) = ASCII_ARRAY.iter().find(|&&(s, _, _)| s == ascii_str) else { let msg = format!("substitution character not found for '{ch}'"); - reader.sess.dcx.span_bug(span, msg); + reader.psess.dcx.span_bug(span, msg); }; // special help suggestion for "directed" double quotes diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 53bcb35101e2e..a46372d368f42 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -57,84 +57,84 @@ macro_rules! panictry_buffer { }}; } -pub fn parse_crate_from_file<'a>(input: &Path, sess: &'a ParseSess) -> PResult<'a, ast::Crate> { - let mut parser = new_parser_from_file(sess, input, None); +pub fn parse_crate_from_file<'a>(input: &Path, psess: &'a ParseSess) -> PResult<'a, ast::Crate> { + let mut parser = new_parser_from_file(psess, input, None); parser.parse_crate_mod() } pub fn parse_crate_attrs_from_file<'a>( input: &Path, - sess: &'a ParseSess, + psess: &'a ParseSess, ) -> PResult<'a, ast::AttrVec> { - let mut parser = new_parser_from_file(sess, input, None); + let mut parser = new_parser_from_file(psess, input, None); parser.parse_inner_attributes() } pub fn parse_crate_from_source_str( name: FileName, source: String, - sess: &ParseSess, + psess: &ParseSess, ) -> PResult<'_, ast::Crate> { - new_parser_from_source_str(sess, name, source).parse_crate_mod() + new_parser_from_source_str(psess, name, source).parse_crate_mod() } pub fn parse_crate_attrs_from_source_str( name: FileName, source: String, - sess: &ParseSess, + psess: &ParseSess, ) -> PResult<'_, ast::AttrVec> { - new_parser_from_source_str(sess, name, source).parse_inner_attributes() + new_parser_from_source_str(psess, name, source).parse_inner_attributes() } pub fn parse_stream_from_source_str( name: FileName, source: String, - sess: &ParseSess, + psess: &ParseSess, override_span: Option, ) -> TokenStream { - source_file_to_stream(sess, sess.source_map().new_source_file(name, source), override_span) + source_file_to_stream(psess, psess.source_map().new_source_file(name, source), override_span) } /// Creates a new parser from a source string. -pub fn new_parser_from_source_str(sess: &ParseSess, name: FileName, source: String) -> Parser<'_> { - panictry_buffer!(maybe_new_parser_from_source_str(sess, name, source)) +pub fn new_parser_from_source_str(psess: &ParseSess, name: FileName, source: String) -> Parser<'_> { + panictry_buffer!(maybe_new_parser_from_source_str(psess, name, source)) } /// Creates a new parser from a source string. Returns any buffered errors from lexing the initial /// token stream; these must be consumed via `emit`, `cancel`, etc., otherwise a panic will occur /// when they are dropped. pub fn maybe_new_parser_from_source_str( - sess: &ParseSess, + psess: &ParseSess, name: FileName, source: String, ) -> Result, Vec>> { - maybe_source_file_to_parser(sess, sess.source_map().new_source_file(name, source)) + maybe_source_file_to_parser(psess, psess.source_map().new_source_file(name, source)) } /// Creates a new parser, aborting if the file doesn't exist. If a span is given, that is used on /// an error as the source of the problem. -pub fn new_parser_from_file<'a>(sess: &'a ParseSess, path: &Path, sp: Option) -> Parser<'a> { - let source_file = sess.source_map().load_file(path).unwrap_or_else(|e| { +pub fn new_parser_from_file<'a>(psess: &'a ParseSess, path: &Path, sp: Option) -> Parser<'a> { + let source_file = psess.source_map().load_file(path).unwrap_or_else(|e| { let msg = format!("couldn't read {}: {}", path.display(), e); - let mut err = sess.dcx.struct_fatal(msg); + let mut err = psess.dcx.struct_fatal(msg); if let Some(sp) = sp { err.span(sp); } err.emit(); }); - panictry_buffer!(maybe_source_file_to_parser(sess, source_file)) + panictry_buffer!(maybe_source_file_to_parser(psess, source_file)) } /// Given a session and a `source_file`, return a parser. Returns any buffered errors from lexing /// the initial token stream. fn maybe_source_file_to_parser( - sess: &ParseSess, + psess: &ParseSess, source_file: Lrc, ) -> Result, Vec>> { let end_pos = source_file.end_position(); - let stream = maybe_file_to_stream(sess, source_file, None)?; - let mut parser = stream_to_parser(sess, stream, None); + let stream = maybe_file_to_stream(psess, source_file, None)?; + let mut parser = stream_to_parser(psess, stream, None); if parser.token == token::Eof { parser.token.span = Span::new(end_pos, end_pos, parser.token.span.ctxt(), None); } @@ -146,47 +146,47 @@ fn maybe_source_file_to_parser( /// Given a `source_file`, produces a sequence of token trees. pub fn source_file_to_stream( - sess: &ParseSess, + psess: &ParseSess, source_file: Lrc, override_span: Option, ) -> TokenStream { - panictry_buffer!(maybe_file_to_stream(sess, source_file, override_span)) + panictry_buffer!(maybe_file_to_stream(psess, source_file, override_span)) } /// Given a source file, produces a sequence of token trees. Returns any buffered errors from /// parsing the token stream. -fn maybe_file_to_stream<'sess>( - sess: &'sess ParseSess, +fn maybe_file_to_stream<'psess>( + psess: &'psess ParseSess, source_file: Lrc, override_span: Option, -) -> Result>> { +) -> Result>> { let src = source_file.src.as_ref().unwrap_or_else(|| { - sess.dcx.bug(format!( + psess.dcx.bug(format!( "cannot lex `source_file` without source: {}", - sess.source_map().filename_for_diagnostics(&source_file.name) + psess.source_map().filename_for_diagnostics(&source_file.name) )); }); - lexer::parse_token_trees(sess, src.as_str(), source_file.start_pos, override_span) + lexer::parse_token_trees(psess, src.as_str(), source_file.start_pos, override_span) } /// Given a stream and the `ParseSess`, produces a parser. pub fn stream_to_parser<'a>( - sess: &'a ParseSess, + psess: &'a ParseSess, stream: TokenStream, subparser_name: Option<&'static str>, ) -> Parser<'a> { - Parser::new(sess, stream, subparser_name) + Parser::new(psess, stream, subparser_name) } /// Runs the given subparser `f` on the tokens of the given `attr`'s item. pub fn parse_in<'a, T>( - sess: &'a ParseSess, + psess: &'a ParseSess, tts: TokenStream, name: &'static str, mut f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>, ) -> PResult<'a, T> { - let mut parser = Parser::new(sess, tts, Some(name)); + let mut parser = Parser::new(psess, tts, Some(name)); let result = f(&mut parser)?; if parser.token != token::Eof { parser.unexpected()?; @@ -194,28 +194,28 @@ pub fn parse_in<'a, T>( Ok(result) } -pub fn fake_token_stream_for_item(sess: &ParseSess, item: &ast::Item) -> TokenStream { +pub fn fake_token_stream_for_item(psess: &ParseSess, item: &ast::Item) -> TokenStream { let source = pprust::item_to_string(item); let filename = FileName::macro_expansion_source_code(&source); - parse_stream_from_source_str(filename, source, sess, Some(item.span)) + parse_stream_from_source_str(filename, source, psess, Some(item.span)) } -pub fn fake_token_stream_for_crate(sess: &ParseSess, krate: &ast::Crate) -> TokenStream { +pub fn fake_token_stream_for_crate(psess: &ParseSess, krate: &ast::Crate) -> TokenStream { let source = pprust::crate_to_string_for_macros(krate); let filename = FileName::macro_expansion_source_code(&source); - parse_stream_from_source_str(filename, source, sess, Some(krate.spans.inner_span)) + parse_stream_from_source_str(filename, source, psess, Some(krate.spans.inner_span)) } pub fn parse_cfg_attr( attr: &Attribute, - parse_sess: &ParseSess, + psess: &ParseSess, ) -> Option<(MetaItem, Vec<(AttrItem, Span)>)> { match attr.get_normal_item().args { ast::AttrArgs::Delimited(ast::DelimArgs { dspan, delim, ref tokens }) if !tokens.is_empty() => { - crate::validate_attr::check_cfg_attr_bad_delim(parse_sess, dspan, delim); - match parse_in(parse_sess, tokens.clone(), "`cfg_attr` input", |p| p.parse_cfg_attr()) { + crate::validate_attr::check_cfg_attr_bad_delim(psess, dspan, delim); + match parse_in(psess, tokens.clone(), "`cfg_attr` input", |p| p.parse_cfg_attr()) { Ok(r) => return Some(r), Err(e) => { e.with_help(format!("the valid syntax is `{CFG_ATTR_GRAMMAR_HELP}`")) @@ -224,7 +224,7 @@ pub fn parse_cfg_attr( } } } - _ => error_malformed_cfg_attr_missing(attr.span, parse_sess), + _ => error_malformed_cfg_attr_missing(attr.span, psess), } None } @@ -234,6 +234,6 @@ const CFG_ATTR_NOTE_REF: &str = "for more information, visit \ "; -fn error_malformed_cfg_attr_missing(span: Span, parse_sess: &ParseSess) { - parse_sess.dcx.emit_err(errors::MalformedCfgAttr { span, sugg: CFG_ATTR_GRAMMAR_HELP }); +fn error_malformed_cfg_attr_missing(span: Span, psess: &ParseSess) { + psess.dcx.emit_err(errors::MalformedCfgAttr { span, sugg: CFG_ATTR_GRAMMAR_HELP }); } diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 685af6546f5f5..eb9a10f4bdab1 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -85,7 +85,7 @@ impl<'a> Parser<'a> { // Always make an outer attribute - this allows us to recover from a misplaced // inner attribute. Some(attr::mk_doc_comment( - &self.sess.attr_id_generator, + &self.psess.attr_id_generator, comment_kind, ast::AttrStyle::Outer, data, @@ -135,7 +135,7 @@ impl<'a> Parser<'a> { this.error_on_forbidden_inner_attr(attr_sp, inner_parse_policy); } - Ok(attr::mk_attr_from_item(&self.sess.attr_id_generator, item, None, style, attr_sp)) + Ok(attr::mk_attr_from_item(&self.psess.attr_id_generator, item, None, style, attr_sp)) }) } @@ -288,7 +288,7 @@ impl<'a> Parser<'a> { if attr_style == ast::AttrStyle::Inner { self.bump(); Some(attr::mk_doc_comment( - &self.sess.attr_id_generator, + &self.psess.attr_id_generator, comment_kind, attr_style, data, diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs index 2307f4cfffae6..a1dd7d6f67345 100644 --- a/compiler/rustc_parse/src/parser/attr_wrapper.rs +++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs @@ -40,8 +40,8 @@ impl AttrWrapper { AttrWrapper { attrs: AttrVec::new(), start_pos: usize::MAX } } - pub(crate) fn take_for_recovery(self, sess: &ParseSess) -> AttrVec { - sess.dcx.span_delayed_bug( + pub(crate) fn take_for_recovery(self, psess: &ParseSess) -> AttrVec { + psess.dcx.span_delayed_bug( self.attrs.get(0).map(|attr| attr.span).unwrap_or(DUMMY_SP), "AttrVec is taken for recovery but no error is produced", ); diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 2a8cb74337b53..2f7ac7d3a12e5 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -242,7 +242,7 @@ impl<'a> DerefMut for SnapshotParser<'a> { impl<'a> Parser<'a> { pub fn dcx(&self) -> &'a DiagCtxt { - &self.sess.dcx + &self.psess.dcx } /// Replace `self` with `snapshot.parser`. @@ -257,7 +257,7 @@ impl<'a> Parser<'a> { } pub(super) fn span_to_snippet(&self, span: Span) -> Result { - self.sess.source_map().span_to_snippet(span) + self.psess.source_map().span_to_snippet(span) } /// Emits an error with suggestions if an identifier was expected but not found. @@ -364,7 +364,7 @@ impl<'a> Parser<'a> { if !self.look_ahead(1, |t| *t == token::Lt) && let Ok(snippet) = - self.sess.source_map().span_to_snippet(generic.span) + self.psess.source_map().span_to_snippet(generic.span) { err.multipart_suggestion_verbose( format!("place the generic parameter name after the {ident_name} name"), @@ -489,7 +489,7 @@ impl<'a> Parser<'a> { expected.sort_by_cached_key(|x| x.to_string()); expected.dedup(); - let sm = self.sess.source_map(); + let sm = self.psess.source_map(); // Special-case "expected `;`" errors. if expected.contains(&TokenType::Token(token::Semi)) { @@ -822,7 +822,7 @@ impl<'a> Parser<'a> { // #[cfg(..)] // other_expr // So we suggest using `if cfg!(..) { expr } else if cfg!(..) { other_expr }`. - let margin = self.sess.source_map().span_to_margin(next_expr.span).unwrap_or(0); + let margin = self.psess.source_map().span_to_margin(next_expr.span).unwrap_or(0); let sugg = vec![ (attr.span.with_hi(segment.span().hi()), "if cfg!".to_string()), (args_span.shrink_to_hi().with_hi(attr.span.hi()), " {".to_string()), @@ -850,7 +850,7 @@ impl<'a> Parser<'a> { } fn check_too_many_raw_str_terminators(&mut self, err: &mut Diag<'_>) -> bool { - let sm = self.sess.source_map(); + let sm = self.psess.source_map(); match (&self.prev_token.kind, &self.token.kind) { ( TokenKind::Literal(Lit { @@ -935,7 +935,7 @@ impl<'a> Parser<'a> { // expand `before` so that we take care of module path such as: // `foo::Bar { ... } ` // we expect to suggest `(foo::Bar { ... })` instead of `foo::(Bar { ... })` - let sm = self.sess.source_map(); + let sm = self.psess.source_map(); let before = maybe_struct_name.span.shrink_to_lo(); if let Ok(extend_before) = sm.span_extend_prev_while(before, |t| { t.is_alphanumeric() || t == ':' || t == '_' @@ -1872,7 +1872,7 @@ impl<'a> Parser<'a> { ); let mut err = self.dcx().struct_span_err(sp, msg); let label_exp = format!("expected `{token_str}`"); - let sm = self.sess.source_map(); + let sm = self.psess.source_map(); if !sm.is_multiline(prev_sp.until(sp)) { // When the spans are in the same line, it means that the only content // between them is whitespace, point only at the found token. @@ -1893,7 +1893,7 @@ impl<'a> Parser<'a> { pub(super) fn recover_colon_as_semi(&mut self) -> bool { let line_idx = |span: Span| { - self.sess + self.psess .source_map() .span_to_lines(span) .ok() @@ -1906,7 +1906,7 @@ impl<'a> Parser<'a> { { self.dcx().emit_err(ColonAsSemi { span: self.token.span, - type_ascription: self.sess.unstable_features.is_nightly_build().then_some(()), + type_ascription: self.psess.unstable_features.is_nightly_build().then_some(()), }); self.bump(); return true; @@ -2357,8 +2357,8 @@ impl<'a> Parser<'a> { ), }; let mut err = self.dcx().struct_span_err(span, msg); - let sp = self.sess.source_map().start_point(self.token.span); - if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&sp) { + let sp = self.psess.source_map().start_point(self.token.span); + if let Some(sp) = self.psess.ambiguous_block_expr_parse.borrow().get(&sp) { err.subdiagnostic(self.dcx(), ExprParenthesesNeeded::surrounding(*sp)); } err.span_label(span, "expected expression"); @@ -2539,7 +2539,7 @@ impl<'a> Parser<'a> { }; let ident = param.ident.to_string(); - let sugg = match (ty_generics, self.sess.source_map().span_to_snippet(param.span())) { + let sugg = match (ty_generics, self.psess.source_map().span_to_snippet(param.span())) { (Some(Generics { params, span: impl_generics, .. }), Ok(snippet)) => { Some(match ¶ms[..] { [] => UnexpectedConstParamDeclarationSugg::AddParam { diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 54771cccd75a1..7a34bc7890c98 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -13,13 +13,14 @@ use ast::mut_visit::{noop_visit_expr, MutVisitor}; use ast::token::IdentIsRaw; use ast::{CoroutineKind, ForLoopKind, GenBlockKind, Pat, Path, PathSegment}; use core::mem; +use core::ops::ControlFlow; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Token, TokenKind}; use rustc_ast::tokenstream::Spacing; use rustc_ast::util::case::Case; use rustc_ast::util::classify; use rustc_ast::util::parser::{prec_let_scrutinee_needs_par, AssocOp, Fixity}; -use rustc_ast::visit::Visitor; +use rustc_ast::visit::{walk_expr, Visitor}; use rustc_ast::{self as ast, AttrStyle, AttrVec, CaptureBy, ExprField, UnOp, DUMMY_NODE_ID}; use rustc_ast::{AnonConst, BinOp, BinOpKind, FnDecl, FnRetTy, MacCall, Param, Ty, TyKind}; use rustc_ast::{Arm, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits}; @@ -31,7 +32,7 @@ use rustc_lexer::unescape::unescape_char; use rustc_macros::Subdiagnostic; use rustc_session::errors::{report_lit_error, ExprParenthesesNeeded}; use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP; -use rustc_session::lint::BuiltinLintDiagnostics; +use rustc_session::lint::BuiltinLintDiag; use rustc_span::source_map::{self, Spanned}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{BytePos, ErrorGuaranteed, Pos, Span}; @@ -403,8 +404,8 @@ impl<'a> Parser<'a> { // suggestions based on the assumption that double-refs are rarely intentional, // and closures are distinct enough that they don't get mixed up with their // return value. - let sp = self.sess.source_map().start_point(self.token.span); - self.sess.ambiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span); + let sp = self.psess.source_map().start_point(self.token.span); + self.psess.ambiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span); false } (true, Some(op)) if !op.can_continue_expr_unambiguously() => false, @@ -608,7 +609,7 @@ impl<'a> Parser<'a> { }; // a block on the LHS might have been intended to be an expression instead - if let Some(sp) = this.sess.ambiguous_block_expr_parse.borrow().get(&lo) { + if let Some(sp) = this.psess.ambiguous_block_expr_parse.borrow().get(&lo) { err.add_parentheses = Some(ExprParenthesesNeeded::surrounding(*sp)); } else { err.remove_plus = Some(lo); @@ -666,7 +667,7 @@ impl<'a> Parser<'a> { fn parse_expr_box(&mut self, box_kw: Span) -> PResult<'a, (Span, ExprKind)> { let (span, _) = self.parse_expr_prefix_common(box_kw)?; let inner_span = span.with_lo(box_kw.hi()); - let code = self.sess.source_map().span_to_snippet(inner_span).unwrap(); + let code = self.psess.source_map().span_to_snippet(inner_span).unwrap(); let guar = self.dcx().emit_err(errors::BoxSyntaxRemoved { span: span, code: code.trim() }); Ok((span, ExprKind::Err(guar))) } @@ -700,7 +701,7 @@ impl<'a> Parser<'a> { // Span the `not` plus trailing whitespace to avoid // trailing whitespace after the `!` in our suggestion sub: sub_diag( - self.sess.source_map().span_until_non_whitespace(lo.to(negated_token.span)), + self.psess.source_map().span_until_non_whitespace(lo.to(negated_token.span)), ), }); @@ -915,7 +916,7 @@ impl<'a> Parser<'a> { let found_raw = self.eat_keyword(kw::Raw); assert!(found_raw); let mutability = self.parse_const_or_mut().unwrap(); - self.sess.gated_spans.gate(sym::raw_ref_op, lo.to(self.prev_token.span)); + self.psess.gated_spans.gate(sym::raw_ref_op, lo.to(self.prev_token.span)); (ast::BorrowKind::Raw, mutability) } else { // `mut?` @@ -1013,7 +1014,7 @@ impl<'a> Parser<'a> { fn error_unexpected_after_dot(&self) { let actual = pprust::token_to_string(&self.token); let span = self.token.span; - let sm = self.sess.source_map(); + let sm = self.psess.source_map(); let (span, actual) = match (&self.token.kind, self.subparser_name) { (token::Eof, Some(_)) if let Ok(actual) = sm.span_to_snippet(sm.next_point(span)) => { (span.shrink_to_hi(), actual.into()) @@ -1434,7 +1435,7 @@ impl<'a> Parser<'a> { this.parse_expr_closure().map_err(|mut err| { // If the input is something like `if a { 1 } else { 2 } | if a { 3 } else { 4 }` // then suggest parens around the lhs. - if let Some(sp) = this.sess.ambiguous_block_expr_parse.borrow().get(&lo) { + if let Some(sp) = this.psess.ambiguous_block_expr_parse.borrow().get(&lo) { err.subdiagnostic(this.dcx(), ExprParenthesesNeeded::surrounding(*sp)); } err @@ -1634,7 +1635,7 @@ impl<'a> Parser<'a> { && let Some(expr) = self.maybe_parse_struct_expr(&qself, &path) { if qself.is_some() { - self.sess.gated_spans.gate(sym::more_qualified_paths, path.span); + self.psess.gated_spans.gate(sym::more_qualified_paths, path.span); } return expr; } else { @@ -1703,19 +1704,20 @@ impl<'a> Parser<'a> { let span = expr.span; let found_labeled_breaks = { - struct FindLabeledBreaksVisitor(bool); + struct FindLabeledBreaksVisitor; impl<'ast> Visitor<'ast> for FindLabeledBreaksVisitor { - fn visit_expr_post(&mut self, ex: &'ast Expr) { + type Result = ControlFlow<()>; + fn visit_expr(&mut self, ex: &'ast Expr) -> ControlFlow<()> { if let ExprKind::Break(Some(_label), _) = ex.kind { - self.0 = true; + ControlFlow::Break(()) + } else { + walk_expr(self, ex) } } } - let mut vis = FindLabeledBreaksVisitor(false); - vis.visit_expr(&expr); - vis.0 + FindLabeledBreaksVisitor.visit_expr(&expr).is_break() }; // Suggestion involves adding a labeled block. @@ -1821,7 +1823,7 @@ impl<'a> Parser<'a> { let kind = ExprKind::Yeet(self.parse_expr_opt()?); let span = lo.to(self.prev_token.span); - self.sess.gated_spans.gate(sym::yeet_expr, span); + self.psess.gated_spans.gate(sym::yeet_expr, span); let expr = self.mk_expr(span, kind); self.maybe_recover_from_bad_qpath(expr) } @@ -1831,7 +1833,7 @@ impl<'a> Parser<'a> { let lo = self.prev_token.span; let kind = ExprKind::Become(self.parse_expr()?); let span = lo.to(self.prev_token.span); - self.sess.gated_spans.gate(sym::explicit_tail_calls, span); + self.psess.gated_spans.gate(sym::explicit_tail_calls, span); let expr = self.mk_expr(span, kind); self.maybe_recover_from_bad_qpath(expr) } @@ -1875,12 +1877,12 @@ impl<'a> Parser<'a> { | ExprKind::Block(_, None) ) { - self.sess.buffer_lint_with_diagnostic( + self.psess.buffer_lint_with_diagnostic( BREAK_WITH_LABEL_AND_LOOP, lo.to(expr.span), ast::CRATE_NODE_ID, "this labeled break expression is easy to confuse with an unlabeled break with a labeled value expression", - BuiltinLintDiagnostics::BreakWithLabelAndLoop(expr.span), + BuiltinLintDiag::BreakWithLabelAndLoop(expr.span), ); } @@ -1926,7 +1928,7 @@ impl<'a> Parser<'a> { let lo = self.prev_token.span; let kind = ExprKind::Yield(self.parse_expr_opt()?); let span = lo.to(self.prev_token.span); - self.sess.gated_spans.gate(sym::yield_expr, span); + self.psess.gated_spans.gate(sym::yield_expr, span); let expr = self.mk_expr(span, kind); self.maybe_recover_from_bad_qpath(expr) } @@ -1955,7 +1957,7 @@ impl<'a> Parser<'a> { let err = self.dcx().create_err(errors::ExpectedBuiltinIdent { span: self.token.span }); return Err(err); }; - self.sess.gated_spans.gate(sym::builtin_syntax, ident.span); + self.psess.gated_spans.gate(sym::builtin_syntax, ident.span); self.bump(); self.expect(&TokenKind::OpenDelim(Delimiter::Parenthesis))?; @@ -2143,7 +2145,7 @@ impl<'a> Parser<'a> { Err(err) => { let span = token.uninterpolated_span(); self.bump(); - let guar = report_lit_error(self.sess, err, lit, span); + let guar = report_lit_error(self.psess, err, lit, span); // Pack possible quotes and prefixes from the original literal into // the error literal's symbol so they can be pretty-printed faithfully. let suffixless_lit = token::Lit::new(lit.kind, lit.symbol, None); @@ -2236,7 +2238,7 @@ impl<'a> Parser<'a> { } if self.token.kind == token::Comma { - if !self.sess.source_map().is_multiline(prev_span.until(self.token.span)) { + if !self.psess.source_map().is_multiline(prev_span.until(self.token.span)) { return Ok(()); } let mut snapshot = self.create_snapshot_for_diagnostic(); @@ -2312,7 +2314,7 @@ impl<'a> Parser<'a> { let lifetime_defs = self.parse_late_bound_lifetime_defs()?; let span = lo.to(self.prev_token.span); - self.sess.gated_spans.gate(sym::closure_lifetime_binder, span); + self.psess.gated_spans.gate(sym::closure_lifetime_binder, span); ClosureBinder::For { span, generic_params: lifetime_defs } } else { @@ -2354,12 +2356,12 @@ impl<'a> Parser<'a> { match coroutine_kind { Some(CoroutineKind::Async { span, .. }) => { // Feature-gate `async ||` closures. - self.sess.gated_spans.gate(sym::async_closure, span); + self.psess.gated_spans.gate(sym::async_closure, span); } Some(CoroutineKind::Gen { span, .. }) | Some(CoroutineKind::AsyncGen { span, .. }) => { // Feature-gate `gen ||` and `async gen ||` closures. // FIXME(gen_blocks): This perhaps should be a different gate. - self.sess.gated_spans.gate(sym::gen_blocks, span); + self.psess.gated_spans.gate(sym::gen_blocks, span); } None => {} } @@ -2502,7 +2504,7 @@ impl<'a> Parser<'a> { ExprKind::Block(_, None) => { let guar = this.dcx().emit_err(errors::IfExpressionMissingCondition { if_span: lo.with_neighbor(cond.span).shrink_to_hi(), - block_span: self.sess.source_map().start_point(cond_span), + block_span: self.psess.source_map().start_point(cond_span), }); std::mem::replace(&mut cond, this.mk_expr_err(cond_span.shrink_to_hi(), guar)) } @@ -2594,7 +2596,7 @@ impl<'a> Parser<'a> { if let ExprKind::Let(_, _, _, None) = cond.kind { // Remove the last feature gating of a `let` expression since it's stable. - self.sess.gated_spans.ungate_last(sym::let_chains, cond.span); + self.psess.gated_spans.ungate_last(sym::let_chains, cond.span); } Ok(cond) @@ -2690,7 +2692,7 @@ impl<'a> Parser<'a> { attrs: AttrWrapper, ) { if !attrs.is_empty() - && let [x0 @ xn] | [x0, .., xn] = &*attrs.take_for_recovery(self.sess) + && let [x0 @ xn] | [x0, .., xn] = &*attrs.take_for_recovery(self.psess) { let attributes = x0.span.to(xn.span); let last = xn.span; @@ -2787,7 +2789,7 @@ impl<'a> Parser<'a> { self.token.uninterpolated_span().at_least_rust_2018() && self.eat_keyword(kw::Await); if is_await { - self.sess.gated_spans.gate(sym::async_for_loop, self.prev_token.span); + self.psess.gated_spans.gate(sym::async_for_loop, self.prev_token.span); } let kind = if is_await { ForLoopKind::ForAwait } else { ForLoopKind::For }; @@ -3048,7 +3050,7 @@ impl<'a> Parser<'a> { |x| { // Don't gate twice if !pat.contains_never_pattern() { - this.sess.gated_spans.gate(sym::never_patterns, pat.span); + this.psess.gated_spans.gate(sym::never_patterns, pat.span); } x }, @@ -3103,7 +3105,7 @@ impl<'a> Parser<'a> { this.expect_one_of(&[token::Comma], &[token::CloseDelim(Delimiter::Brace)]) .map_err(|mut err| { if this.token == token::FatArrow { - let sm = this.sess.source_map(); + let sm = this.psess.source_map(); if let Ok(expr_lines) = sm.span_to_lines(expr_span) && let Ok(arm_start_lines) = sm.span_to_lines(arm_start_span) && arm_start_lines.lines[0].end_col @@ -3227,10 +3229,10 @@ impl<'a> Parser<'a> { if has_let_expr { if does_not_have_bin_op { // Remove the last feature gating of a `let` expression since it's stable. - self.sess.gated_spans.ungate_last(sym::let_chains, cond.span); + self.psess.gated_spans.ungate_last(sym::let_chains, cond.span); } let span = if_span.to(cond.span); - self.sess.gated_spans.gate(sym::if_let_guard, span); + self.psess.gated_spans.gate(sym::if_let_guard, span); } Ok(Some(cond)) } @@ -3321,7 +3323,7 @@ impl<'a> Parser<'a> { Err(self.dcx().create_err(errors::CatchAfterTry { span: self.prev_token.span })) } else { let span = span_lo.to(body.span); - self.sess.gated_spans.gate(sym::try_blocks, span); + self.psess.gated_spans.gate(sym::try_blocks, span); Ok(self.mk_expr_with_attrs(span, ExprKind::TryBlock(body), attrs)) } } @@ -3359,7 +3361,7 @@ impl<'a> Parser<'a> { // `async` blocks are stable } GenBlockKind::Gen | GenBlockKind::AsyncGen => { - self.sess.gated_spans.gate(sym::gen_blocks, lo.to(self.prev_token.span)); + self.psess.gated_spans.gate(sym::gen_blocks, lo.to(self.prev_token.span)); } } let capture_clause = self.parse_capture_clause()?; @@ -3876,7 +3878,7 @@ impl MutVisitor for CondChecker<'_> { comparison: self.comparison, })); } else { - self.parser.sess.gated_spans.gate(sym::let_chains, span); + self.parser.psess.gated_spans.gate(sym::let_chains, span); } } ExprKind::Binary(Spanned { node: BinOpKind::And, .. }, _, _) => { diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index e059e7074910a..263b2a9064356 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -420,7 +420,7 @@ impl<'a> Parser<'a> { type_err.cancel(); let body_sp = pred_lo.to(snapshot.prev_token.span); - let map = self.sess.source_map(); + let map = self.psess.source_map(); self.dcx().emit_err(WhereClauseBeforeTupleStructBody { span: where_sp, diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index d8587f1340a1a..79492fe62ed97 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -563,7 +563,7 @@ impl<'a> Parser<'a> { let constness = self.parse_constness(Case::Sensitive); if let Const::Yes(span) = constness { - self.sess.gated_spans.gate(sym::const_trait_impl, span); + self.psess.gated_spans.gate(sym::const_trait_impl, span); } // Parse stray `impl async Trait` @@ -699,7 +699,7 @@ impl<'a> Parser<'a> { None }; let span = span.to(self.prev_token.span); - self.sess.gated_spans.gate(sym::fn_delegation, span); + self.psess.gated_spans.gate(sym::fn_delegation, span); let ident = path.segments.last().map(|seg| seg.ident).unwrap_or(Ident::empty()); Ok(( @@ -859,7 +859,7 @@ impl<'a> Parser<'a> { let unsafety = self.parse_unsafety(Case::Sensitive); // Parse optional `auto` prefix. let is_auto = if self.eat_keyword(kw::Auto) { - self.sess.gated_spans.gate(sym::auto_traits, self.prev_token.span); + self.psess.gated_spans.gate(sym::auto_traits, self.prev_token.span); IsAuto::Yes } else { IsAuto::No @@ -894,7 +894,7 @@ impl<'a> Parser<'a> { self.dcx().emit_err(errors::TraitAliasCannotBeUnsafe { span: whole_span }); } - self.sess.gated_spans.gate(sym::trait_alias, whole_span); + self.psess.gated_spans.gate(sym::trait_alias, whole_span); Ok((ident, ItemKind::TraitAlias(generics, bounds))) } else { @@ -1209,7 +1209,7 @@ impl<'a> Parser<'a> { fn error_bad_item_kind(&self, span: Span, kind: &ItemKind, ctx: &'static str) -> Option { // FIXME(#100717): needs variant for each `ItemKind` (instead of using `ItemKind::descr()`) - let span = self.sess.source_map().guess_head_span(span); + let span = self.psess.source_map().guess_head_span(span); let descr = kind.descr(); self.dcx().emit_err(errors::BadItemKind { span, descr, ctx }); None @@ -1332,7 +1332,7 @@ impl<'a> Parser<'a> { // Check the span for emptiness instead of the list of parameters in order to correctly // recognize and subsequently flag empty parameter lists (`<>`) as unstable. if !generics.span.is_empty() { - self.sess.gated_spans.gate(sym::generic_const_items, generics.span); + self.psess.gated_spans.gate(sym::generic_const_items, generics.span); } // Parse the type of a constant item. That is, the `":" $ty` fragment. @@ -1366,7 +1366,7 @@ impl<'a> Parser<'a> { name: ident.span, body: expr.span, sugg: if !after_where_clause.has_where_token { - self.sess.source_map().span_to_snippet(expr.span).ok().map(|body| { + self.psess.source_map().span_to_snippet(expr.span).ok().map(|body| { errors::WhereClauseBeforeConstBodySugg { left: before_where_clause.span.shrink_to_lo(), snippet: body, @@ -1401,7 +1401,7 @@ impl<'a> Parser<'a> { }; if where_clause.has_where_token { - self.sess.gated_spans.gate(sym::generic_const_items, where_clause.span); + self.psess.gated_spans.gate(sym::generic_const_items, where_clause.span); } generics.where_clause = where_clause; @@ -1898,7 +1898,7 @@ impl<'a> Parser<'a> { fn expect_field_ty_separator(&mut self) -> PResult<'a, ()> { if let Err(err) = self.expect(&token::Colon) { - let sm = self.sess.source_map(); + let sm = self.psess.source_map(); let eq_typo = self.token.kind == token::Eq && self.look_ahead(1, |t| t.is_path_start()); let semi_typo = self.token.kind == token::Semi && self.look_ahead(1, |t| { @@ -1970,7 +1970,7 @@ impl<'a> Parser<'a> { fn parse_field_ident(&mut self, adt_ty: &str, lo: Span) -> PResult<'a, Ident> { let (ident, is_raw) = self.ident_or_err(true)?; if ident.name == kw::Underscore { - self.sess.gated_spans.gate(sym::unnamed_fields, lo); + self.psess.gated_spans.gate(sym::unnamed_fields, lo); } else if matches!(is_raw, IdentIsRaw::No) && ident.is_reserved() { let snapshot = self.create_snapshot_for_diagnostic(); let err = if self.check_fn_front_matter(false, Case::Sensitive) { @@ -2080,7 +2080,7 @@ impl<'a> Parser<'a> { return self.unexpected(); }; - self.sess.gated_spans.gate(sym::decl_macro, lo.to(self.prev_token.span)); + self.psess.gated_spans.gate(sym::decl_macro, lo.to(self.prev_token.span)); Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, macro_rules: false }))) } @@ -2460,7 +2460,7 @@ impl<'a> Parser<'a> { match coroutine_kind { Some(CoroutineKind::Gen { span, .. }) | Some(CoroutineKind::AsyncGen { span, .. }) => { - self.sess.gated_spans.gate(sym::gen_blocks, span); + self.psess.gated_spans.gate(sym::gen_blocks, span); } Some(CoroutineKind::Async { .. }) | None => {} } diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 8542ea6231038..12879dc429bc9 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -128,7 +128,7 @@ pub enum Recovery { #[derive(Clone)] pub struct Parser<'a> { - pub sess: &'a ParseSess, + pub psess: &'a ParseSess, /// The current token. pub token: Token, /// The spacing for the current token. @@ -414,12 +414,12 @@ pub(super) fn token_descr(token: &Token) -> String { impl<'a> Parser<'a> { pub fn new( - sess: &'a ParseSess, + psess: &'a ParseSess, stream: TokenStream, subparser_name: Option<&'static str>, ) -> Self { let mut parser = Parser { - sess, + psess, token: Token::dummy(), token_spacing: Spacing::Alone, prev_token: Token::dummy(), @@ -714,7 +714,7 @@ impl<'a> Parser<'a> { } match self.token.kind.break_two_token_op() { Some((first, second)) if first == expected => { - let first_span = self.sess.source_map().start_point(self.token.span); + let first_span = self.psess.source_map().start_point(self.token.span); let second_span = self.token.span.with_lo(first_span.hi()); self.token = Token::new(first, first_span); // Keep track of this token - if we end token capturing now, @@ -1213,7 +1213,7 @@ impl<'a> Parser<'a> { fn parse_closure_constness(&mut self) -> Const { let constness = self.parse_constness_(Case::Sensitive, true); if let Const::Yes(span) = constness { - self.sess.gated_spans.gate(sym::const_closures, span); + self.psess.gated_spans.gate(sym::const_closures, span); } constness } @@ -1234,9 +1234,9 @@ impl<'a> Parser<'a> { /// Parses inline const expressions. fn parse_const_block(&mut self, span: Span, pat: bool) -> PResult<'a, P> { if pat { - self.sess.gated_spans.gate(sym::inline_const_pat, span); + self.psess.gated_spans.gate(sym::inline_const_pat, span); } else { - self.sess.gated_spans.gate(sym::inline_const, span); + self.psess.gated_spans.gate(sym::inline_const, span); } self.eat_keyword(kw::Const); let (attrs, blk) = self.parse_inner_attrs_and_block()?; @@ -1521,7 +1521,7 @@ impl<'a> Parser<'a> { pub(crate) fn make_unclosed_delims_error( unmatched: UnmatchedDelim, - sess: &ParseSess, + psess: &ParseSess, ) -> Option> { // `None` here means an `Eof` was found. We already emit those errors elsewhere, we add them to // `unmatched_delims` only for error recovery in the `Parser`. @@ -1530,7 +1530,7 @@ pub(crate) fn make_unclosed_delims_error( if let Some(sp) = unmatched.unclosed_span { spans.push(sp); }; - let err = sess.dcx.create_err(MismatchedClosingDelimiter { + let err = psess.dcx.create_err(MismatchedClosingDelimiter { spans, delimiter: pprust::token_kind_to_string(&token::CloseDelim(found_delim)).to_string(), unmatched: unmatched.found_span, diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 7aeab6488a5ea..88ae1b5420fe7 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -470,7 +470,7 @@ impl<'a> Parser<'a> { self.parse_pat_range_to(form)? // `..=X`, `...X`, or `..X`. } else if self.eat(&token::Not) { // Parse `!` - self.sess.gated_spans.gate(sym::never_patterns, self.prev_token.span); + self.psess.gated_spans.gate(sym::never_patterns, self.prev_token.span); PatKind::Never } else if self.eat_keyword(kw::Underscore) { // Parse `_` @@ -843,8 +843,8 @@ impl<'a> Parser<'a> { let mut err = self.dcx().struct_span_err(self.token.span, msg); err.span_label(self.token.span, format!("expected {expected}")); - let sp = self.sess.source_map().start_point(self.token.span); - if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&sp) { + let sp = self.psess.source_map().start_point(self.token.span); + if let Some(sp) = self.psess.ambiguous_block_expr_parse.borrow().get(&sp) { err.subdiagnostic(self.dcx(), ExprParenthesesNeeded::surrounding(*sp)); } @@ -1067,7 +1067,7 @@ impl<'a> Parser<'a> { fn parse_pat_struct(&mut self, qself: Option>, path: Path) -> PResult<'a, PatKind> { if qself.is_some() { // Feature gate the use of qualified paths in patterns - self.sess.gated_spans.gate(sym::more_qualified_paths, path.span); + self.psess.gated_spans.gate(sym::more_qualified_paths, path.span); } self.bump(); let (fields, etc) = self.parse_pat_fields().unwrap_or_else(|mut e| { @@ -1096,7 +1096,7 @@ impl<'a> Parser<'a> { ) })?; if qself.is_some() { - self.sess.gated_spans.gate(sym::more_qualified_paths, path.span); + self.psess.gated_spans.gate(sym::more_qualified_paths, path.span); } Ok(PatKind::TupleStruct(qself, path, fields)) } @@ -1143,7 +1143,7 @@ impl<'a> Parser<'a> { Ok(PatKind::Ident(BindingAnnotation::NONE, Ident::new(kw::Box, box_span), sub)) } else { let pat = self.parse_pat_with_range_pat(false, None, None)?; - self.sess.gated_spans.gate(sym::box_patterns, box_span.to(self.prev_token.span)); + self.psess.gated_spans.gate(sym::box_patterns, box_span.to(self.prev_token.span)); Ok(PatKind::Box(pat)) } } @@ -1192,15 +1192,15 @@ impl<'a> Parser<'a> { .look_ahead(1, |t| if *t == token::Comma { Some(t.clone()) } else { None }) { let nw_span = self - .sess + .psess .source_map() .span_extend_to_line(comma_tok.span) .trim_start(comma_tok.span.shrink_to_lo()) - .map(|s| self.sess.source_map().span_until_non_whitespace(s)); + .map(|s| self.psess.source_map().span_until_non_whitespace(s)); first_etc_and_maybe_comma_span = nw_span.map(|s| etc_sp.to(s)); } else { first_etc_and_maybe_comma_span = - Some(self.sess.source_map().span_until_non_whitespace(etc_sp)); + Some(self.psess.source_map().span_until_non_whitespace(etc_sp)); } } @@ -1218,7 +1218,8 @@ impl<'a> Parser<'a> { let mut comma_sp = None; if self.token == token::Comma { // Issue #49257 - let nw_span = self.sess.source_map().span_until_non_whitespace(self.token.span); + let nw_span = + self.psess.source_map().span_until_non_whitespace(self.token.span); etc_sp = etc_sp.to(nw_span); err.span_label( etc_sp, diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 6e7bbe7e06d42..545db5138a3ab 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -250,7 +250,7 @@ impl<'a> Parser<'a> { self.dcx().emit_err(PathSingleColon { span: self.prev_token.span, type_ascription: self - .sess + .psess .unstable_features .is_nightly_build() .then_some(()), @@ -322,7 +322,7 @@ impl<'a> Parser<'a> { err = self.dcx().create_err(PathSingleColon { span: self.token.span, type_ascription: self - .sess + .psess .unstable_features .is_nightly_build() .then_some(()), @@ -638,9 +638,9 @@ impl<'a> Parser<'a> { && args.inputs.is_empty() && matches!(args.output, ast::FnRetTy::Default(..)) { - self.sess.gated_spans.gate(sym::return_type_notation, span); + self.psess.gated_spans.gate(sym::return_type_notation, span); } else { - self.sess.gated_spans.gate(sym::associated_type_bounds, span); + self.psess.gated_spans.gate(sym::associated_type_bounds, span); } } let constraint = @@ -675,7 +675,7 @@ impl<'a> Parser<'a> { let term = match arg { Some(GenericArg::Type(ty)) => ty.into(), Some(GenericArg::Const(c)) => { - self.sess.gated_spans.gate(sym::associated_const_equality, span); + self.psess.gated_spans.gate(sym::associated_const_equality, span); c.into() } Some(GenericArg::Lifetime(lt)) => { @@ -691,7 +691,7 @@ impl<'a> Parser<'a> { .struct_span_err(after_eq.to(before_next), "missing type to the right of `=`"); if matches!(self.token.kind, token::Comma | token::Gt) { err.span_suggestion( - self.sess.source_map().next_point(eq).to(before_next), + self.psess.source_map().next_point(eq).to(before_next), "to constrain the associated type, add a type after `=`", " TheType", Applicability::HasPlaceholders, diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 65c0f7d49c153..73f5829adec64 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -230,7 +230,7 @@ impl<'a> Parser<'a> { /// Also error if the previous token was a doc comment. fn error_outer_attrs(&self, attrs: AttrWrapper) { if !attrs.is_empty() - && let attrs @ [.., last] = &*attrs.take_for_recovery(self.sess) + && let attrs @ [.., last] = &*attrs.take_for_recovery(self.psess) { if last.is_doc_comment() { self.dcx().emit_err(errors::DocCommentDoesNotDocumentAnything { @@ -448,7 +448,7 @@ impl<'a> Parser<'a> { } /// Parses a block. No inner attributes are allowed. - pub(super) fn parse_block(&mut self) -> PResult<'a, P> { + pub fn parse_block(&mut self) -> PResult<'a, P> { let (attrs, block) = self.parse_inner_attrs_and_block()?; if let [.., last] = &*attrs { self.error_on_forbidden_inner_attr( @@ -494,7 +494,7 @@ impl<'a> Parser<'a> { // Do not suggest `if foo println!("") {;}` (as would be seen in test for #46836). Ok(Some(Stmt { kind: StmtKind::Empty, .. })) => {} Ok(Some(stmt)) => { - let stmt_own_line = self.sess.source_map().is_line_before_span_empty(sp); + let stmt_own_line = self.psess.source_map().is_line_before_span_empty(sp); let stmt_span = if stmt_own_line && self.eat(&token::Semi) { // Expand the span to include the semicolon. stmt.span.with_hi(self.prev_token.span.hi()) @@ -613,7 +613,7 @@ impl<'a> Parser<'a> { Applicability::MaybeIncorrect, ); } - if self.sess.unstable_features.is_nightly_build() { + if self.psess.unstable_features.is_nightly_build() { // FIXME(Nilstrieb): Remove this again after a few months. err.note("type ascription syntax has been removed, see issue #101728 "); } @@ -787,13 +787,17 @@ impl<'a> Parser<'a> { let suggest_eq = if self.token.kind == token::Dot && let _ = self.bump() && let mut snapshot = self.create_snapshot_for_diagnostic() - && let Ok(_) = snapshot.parse_dot_suffix_expr( - colon_sp, - self.mk_expr_err( + && let Ok(_) = snapshot + .parse_dot_suffix_expr( colon_sp, - self.dcx().delayed_bug("error during `:` -> `=` recovery"), - ), - ) { + self.mk_expr_err( + colon_sp, + self.dcx() + .delayed_bug("error during `:` -> `=` recovery"), + ), + ) + .map_err(Diag::cancel) + { true } else if let Some(op) = self.check_assoc_op() && op.node.can_continue_expr_unambiguously() diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index e3fe535bd5f8d..2385c18c0891c 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -397,7 +397,7 @@ impl<'a> Parser<'a> { let (fields, _recovered) = self.parse_record_struct_body(if is_union { "union" } else { "struct" }, lo, false)?; let span = lo.to(self.prev_token.span); - self.sess.gated_spans.gate(sym::unnamed_fields, span); + self.psess.gated_spans.gate(sym::unnamed_fields, span); let id = ast::DUMMY_NODE_ID; let kind = if is_union { TyKind::AnonUnion(id, fields) } else { TyKind::AnonStruct(id, fields) }; @@ -694,7 +694,7 @@ impl<'a> Parser<'a> { // parse dyn* types let syntax = if self.eat(&TokenKind::BinOp(token::Star)) { - self.sess.gated_spans.gate(sym::dyn_star, lo.to(self.prev_token.span)); + self.psess.gated_spans.gate(sym::dyn_star, lo.to(self.prev_token.span)); TraitObjectSyntax::DynStar } else { TraitObjectSyntax::Dyn @@ -874,10 +874,10 @@ impl<'a> Parser<'a> { let tilde = self.prev_token.span; self.expect_keyword(kw::Const)?; let span = tilde.to(self.prev_token.span); - self.sess.gated_spans.gate(sym::const_trait_impl, span); + self.psess.gated_spans.gate(sym::const_trait_impl, span); BoundConstness::Maybe(span) } else if self.eat_keyword(kw::Const) { - self.sess.gated_spans.gate(sym::const_trait_impl, self.prev_token.span); + self.psess.gated_spans.gate(sym::const_trait_impl, self.prev_token.span); BoundConstness::Always(self.prev_token.span) } else { BoundConstness::Never @@ -886,7 +886,7 @@ impl<'a> Parser<'a> { let asyncness = if self.token.uninterpolated_span().at_least_rust_2018() && self.eat_keyword(kw::Async) { - self.sess.gated_spans.gate(sym::async_closure, self.prev_token.span); + self.psess.gated_spans.gate(sym::async_closure, self.prev_token.span); BoundAsyncness::Async(self.prev_token.span) } else if self.may_recover() && self.token.uninterpolated_span().is_rust_2015() @@ -897,7 +897,7 @@ impl<'a> Parser<'a> { span: self.prev_token.span, help: HelpUseLatestEdition::new(), }); - self.sess.gated_spans.gate(sym::async_closure, self.prev_token.span); + self.psess.gated_spans.gate(sym::async_closure, self.prev_token.span); BoundAsyncness::Async(self.prev_token.span) } else { BoundAsyncness::Normal @@ -906,7 +906,7 @@ impl<'a> Parser<'a> { let polarity = if self.eat(&token::Question) { BoundPolarity::Maybe(self.prev_token.span) } else if self.eat(&token::Not) { - self.sess.gated_spans.gate(sym::negative_bounds, self.prev_token.span); + self.psess.gated_spans.gate(sym::negative_bounds, self.prev_token.span); BoundPolarity::Negative(self.prev_token.span) } else { BoundPolarity::Positive diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index 73c92708eb39c..f88edf29dcebe 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -13,7 +13,7 @@ use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT; use rustc_session::parse::ParseSess; use rustc_span::{sym, Span, Symbol}; -pub fn check_attr(sess: &ParseSess, attr: &Attribute) { +pub fn check_attr(psess: &ParseSess, attr: &Attribute) { if attr.is_doc_comment() { return; } @@ -24,11 +24,11 @@ pub fn check_attr(sess: &ParseSess, attr: &Attribute) { match attr_info { // `rustc_dummy` doesn't have any restrictions specific to built-in attributes. Some(BuiltinAttribute { name, template, .. }) if *name != sym::rustc_dummy => { - check_builtin_attribute(sess, attr, *name, *template) + check_builtin_attribute(psess, attr, *name, *template) } _ if let AttrArgs::Eq(..) = attr.get_normal_item().args => { // All key-value attributes are restricted to meta-item syntax. - parse_meta(sess, attr) + parse_meta(psess, attr) .map_err(|err| { err.emit(); }) @@ -38,7 +38,7 @@ pub fn check_attr(sess: &ParseSess, attr: &Attribute) { } } -pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, MetaItem> { +pub fn parse_meta<'a>(psess: &'a ParseSess, attr: &Attribute) -> PResult<'a, MetaItem> { let item = attr.get_normal_item(); Ok(MetaItem { span: attr.span, @@ -46,8 +46,9 @@ pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Meta kind: match &item.args { AttrArgs::Empty => MetaItemKind::Word, AttrArgs::Delimited(DelimArgs { dspan, delim, tokens }) => { - check_meta_bad_delim(sess, *dspan, *delim); - let nmis = parse_in(sess, tokens.clone(), "meta list", |p| p.parse_meta_seq_top())?; + check_meta_bad_delim(psess, *dspan, *delim); + let nmis = + parse_in(psess, tokens.clone(), "meta list", |p| p.parse_meta_seq_top())?; MetaItemKind::List(nmis) } AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => { @@ -56,7 +57,7 @@ pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Meta let res = match res { Ok(lit) => { if token_lit.suffix.is_some() { - let mut err = sess.dcx.struct_span_err( + let mut err = psess.dcx.struct_span_err( expr.span, "suffixed literals are not allowed in attributes", ); @@ -70,7 +71,7 @@ pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Meta } } Err(err) => { - let guar = report_lit_error(sess, err, token_lit, expr.span); + let guar = report_lit_error(psess, err, token_lit, expr.span); let lit = ast::MetaItemLit { symbol: token_lit.symbol, suffix: token_lit.suffix, @@ -89,7 +90,7 @@ pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Meta // the error because an earlier error will have already // been reported. let msg = "attribute value must be a literal"; - let mut err = sess.dcx.struct_span_err(expr.span, msg); + let mut err = psess.dcx.struct_span_err(expr.span, msg); if let ast::ExprKind::Err(_) = expr.kind { err.downgrade_to_delayed_bug(); } @@ -101,21 +102,21 @@ pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Meta }) } -pub fn check_meta_bad_delim(sess: &ParseSess, span: DelimSpan, delim: Delimiter) { +pub fn check_meta_bad_delim(psess: &ParseSess, span: DelimSpan, delim: Delimiter) { if let Delimiter::Parenthesis = delim { return; } - sess.dcx.emit_err(errors::MetaBadDelim { + psess.dcx.emit_err(errors::MetaBadDelim { span: span.entire(), sugg: errors::MetaBadDelimSugg { open: span.open, close: span.close }, }); } -pub fn check_cfg_attr_bad_delim(sess: &ParseSess, span: DelimSpan, delim: Delimiter) { +pub fn check_cfg_attr_bad_delim(psess: &ParseSess, span: DelimSpan, delim: Delimiter) { if let Delimiter::Parenthesis = delim { return; } - sess.dcx.emit_err(errors::CfgAttrBadDelim { + psess.dcx.emit_err(errors::CfgAttrBadDelim { span: span.entire(), sugg: errors::MetaBadDelimSugg { open: span.open, close: span.close }, }); @@ -132,13 +133,13 @@ fn is_attr_template_compatible(template: &AttributeTemplate, meta: &ast::MetaIte } pub fn check_builtin_attribute( - sess: &ParseSess, + psess: &ParseSess, attr: &Attribute, name: Symbol, template: AttributeTemplate, ) { - match parse_meta(sess, attr) { - Ok(meta) => check_builtin_meta_item(sess, &meta, attr.style, name, template), + match parse_meta(psess, attr) { + Ok(meta) => check_builtin_meta_item(psess, &meta, attr.style, name, template), Err(err) => { err.emit(); } @@ -146,7 +147,7 @@ pub fn check_builtin_attribute( } pub fn check_builtin_meta_item( - sess: &ParseSess, + psess: &ParseSess, meta: &MetaItem, style: ast::AttrStyle, name: Symbol, @@ -157,12 +158,12 @@ pub fn check_builtin_meta_item( let should_skip = |name| name == sym::cfg; if !should_skip(name) && !is_attr_template_compatible(&template, &meta.kind) { - emit_malformed_attribute(sess, style, meta.span, name, template); + emit_malformed_attribute(psess, style, meta.span, name, template); } } fn emit_malformed_attribute( - sess: &ParseSess, + psess: &ParseSess, style: ast::AttrStyle, span: Span, name: Symbol, @@ -204,9 +205,10 @@ fn emit_malformed_attribute( } suggestions.sort(); if should_warn(name) { - sess.buffer_lint(ILL_FORMED_ATTRIBUTE_INPUT, span, ast::CRATE_NODE_ID, msg); + psess.buffer_lint(ILL_FORMED_ATTRIBUTE_INPUT, span, ast::CRATE_NODE_ID, msg); } else { - sess.dcx + psess + .dcx .struct_span_err(span, error_msg) .with_span_suggestions( span, @@ -223,12 +225,12 @@ fn emit_malformed_attribute( } pub fn emit_fatal_malformed_builtin_attribute( - sess: &ParseSess, + psess: &ParseSess, attr: &Attribute, name: Symbol, ) -> ! { let template = BUILTIN_ATTRIBUTE_MAP.get(&name).expect("builtin attr defined").template; - emit_malformed_attribute(sess, attr.style, attr.span, name, template); + emit_malformed_attribute(psess, attr.style, attr.span, name, template); // This is fatal, otherwise it will likely cause a cascade of other errors // (and an error here is expected to be very rare). FatalError.raise() diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 04c0cf7436e2b..a99db9cb8cc58 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1074,6 +1074,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { /// of one item. Read the documentation of [`check_doc_inline`] for more information. /// /// [`check_doc_inline`]: Self::check_doc_inline + #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn check_doc_attrs( &self, attr: &Attribute, @@ -1756,6 +1757,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } /// Checks if the `#[repr]` attributes on `item` are valid. + #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn check_repr( &self, attrs: &[Attribute], @@ -2328,6 +2330,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { let hir_sig = tcx.hir().fn_sig_by_hir_id(hir_id); if let Some(hir_sig) = hir_sig { + #[allow(rustc::diagnostic_outside_of_impl)] // FIXME match terr { TypeError::ArgumentMutability(idx) | TypeError::ArgumentSorts(_, idx) => { if let Some(ty) = hir_sig.decl.inputs.get(idx) { diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs index 02792491f5ed0..30a65d69c4ef8 100644 --- a/compiler/rustc_passes/src/check_const.rs +++ b/compiler/rustc_passes/src/check_const.rs @@ -77,6 +77,7 @@ impl<'tcx> CheckConstVisitor<'tcx> { } /// Emits an error when an unsupported expression is found in a const context. + #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn const_check_violated(&self, expr: NonConstExpr, span: Span) { let Self { tcx, def_id, const_kind } = *self; diff --git a/compiler/rustc_passes/src/debugger_visualizer.rs b/compiler/rustc_passes/src/debugger_visualizer.rs index 4bfe6be549377..96893e585491f 100644 --- a/compiler/rustc_passes/src/debugger_visualizer.rs +++ b/compiler/rustc_passes/src/debugger_visualizer.rs @@ -87,7 +87,7 @@ impl<'ast> rustc_ast::visit::Visitor<'ast> for DebuggerVisualizerCollector<'_> { /// Traverses and collects the debugger visualizers for a specific crate. fn debugger_visualizers(tcx: TyCtxt<'_>, _: LocalCrate) -> Vec { - let resolver_and_krate = tcx.resolver_for_lowering(()).borrow(); + let resolver_and_krate = tcx.resolver_for_lowering().borrow(); let krate = &*resolver_and_krate.1; let mut visitor = DebuggerVisualizerCollector { sess: tcx.sess, visualizers: Vec::new() }; diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs index 97c70e327f0fe..5246389248e9f 100644 --- a/compiler/rustc_passes/src/entry.rs +++ b/compiler/rustc_passes/src/entry.rs @@ -114,6 +114,7 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) { } } +#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId, EntryFnType)> { if let Some((def_id, _)) = visitor.start_fn { Some((def_id.to_def_id(), EntryFnType::Start)) diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 5f412bde2eec1..69104a30495bc 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -7,7 +7,7 @@ use crate::fluent_generated as fluent; use rustc_ast::Label; use rustc_errors::{ codes::*, AddToDiagnostic, Applicability, Diag, DiagCtxt, DiagSymbolList, EmissionGuarantee, - IntoDiagnostic, Level, MultiSpan, SubdiagnosticMessageOp, + IntoDiagnostic, Level, MultiSpan, SubdiagMessageOp, }; use rustc_hir::{self as hir, ExprKind, Target}; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; @@ -1752,7 +1752,7 @@ pub struct UnusedVariableStringInterp { } impl AddToDiagnostic for UnusedVariableStringInterp { - fn add_to_diagnostic_with>( + fn add_to_diagnostic_with>( self, diag: &mut Diag<'_, G>, _f: F, diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs index 02f56ecb10b57..dd6c116695784 100644 --- a/compiler/rustc_passes/src/hir_id_validator.rs +++ b/compiler/rustc_passes/src/hir_id_validator.rs @@ -1,38 +1,26 @@ use rustc_data_structures::sync::Lock; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; -use rustc_hir::intravisit; -use rustc_hir::{HirId, ItemLocalId}; +use rustc_hir::{intravisit, HirId, ItemLocalId}; use rustc_index::bit_set::GrowableBitSet; use rustc_middle::hir::nested_filter; use rustc_middle::ty::TyCtxt; pub fn check_crate(tcx: TyCtxt<'_>) { - if tcx.sess.opts.unstable_opts.hir_stats { - crate::hir_stats::print_hir_stats(tcx); - } - - #[cfg(debug_assertions)] - { - let errors = Lock::new(Vec::new()); + let errors = Lock::new(Vec::new()); - tcx.hir().par_for_each_module(|module_id| { - let mut v = HirIdValidator { - tcx, - owner: None, - hir_ids_seen: Default::default(), - errors: &errors, - }; + tcx.hir().par_for_each_module(|module_id| { + let mut v = + HirIdValidator { tcx, owner: None, hir_ids_seen: Default::default(), errors: &errors }; - tcx.hir().visit_item_likes_in_module(module_id, &mut v); - }); + tcx.hir().visit_item_likes_in_module(module_id, &mut v); + }); - let errors = errors.into_inner(); + let errors = errors.into_inner(); - if !errors.is_empty() { - let message = errors.iter().fold(String::new(), |s1, s2| s1 + "\n" + s2); - tcx.dcx().delayed_bug(message); - } + if !errors.is_empty() { + let message = errors.iter().fold(String::new(), |s1, s2| s1 + "\n" + s2); + tcx.dcx().delayed_bug(message); } } @@ -90,7 +78,7 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> { self.error(|| { format!( "ItemLocalIds not assigned densely in {pretty_owner}. \ - Max ItemLocalId = {max}, missing IDs = {missing_items:#?}; seen IDs = {seen_items:#?}" + Max ItemLocalId = {max}, missing IDs = {missing_items:#?}; seen IDs = {seen_items:#?}" ) }); } diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index d3e3e183845ee..d1368267224a7 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -243,7 +243,7 @@ impl<'ast, 'tcx> LanguageItemCollector<'ast, 'tcx> { /// Traverses and collects all the lang items in all crates. fn get_lang_items(tcx: TyCtxt<'_>, (): ()) -> LanguageItems { - let resolver = tcx.resolver_for_lowering(()).borrow(); + let resolver = tcx.resolver_for_lowering().borrow(); let (resolver, krate) = &*resolver; // Initialize the collector. diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index 7227b185f4d3b..e03052bcfede8 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -28,6 +28,7 @@ mod debugger_visualizer; mod diagnostic_items; pub mod entry; mod errors; +#[cfg(debug_assertions)] pub mod hir_id_validator; pub mod hir_stats; mod lang_items; diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 487407014d178..e5033e1f51f23 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -86,7 +86,6 @@ use crate::errors; use self::LiveNodeKind::*; use self::VarKind::*; -use rustc_ast::InlineAsmOptions; use rustc_data_structures::fx::FxIndexMap; use rustc_hir as hir; use rustc_hir::def::*; @@ -416,6 +415,12 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> { self.add_live_node_for_node(expr.hir_id, ExprNode(expr.span, expr.hir_id)); } + // Inline assembly may contain labels. + hir::ExprKind::InlineAsm(asm) if asm.contains_label() => { + self.add_live_node_for_node(expr.hir_id, ExprNode(expr.span, expr.hir_id)); + intravisit::walk_expr(self, expr); + } + // otherwise, live nodes are not required: hir::ExprKind::Index(..) | hir::ExprKind::Field(..) @@ -1045,20 +1050,53 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { | hir::ExprKind::Repeat(ref e, _) => self.propagate_through_expr(e, succ), hir::ExprKind::InlineAsm(asm) => { + // + // (inputs) + // | + // v + // (outputs) + // / \ + // | | + // v v + // (labels)(fallthrough) + // | | + // v v + // ( succ / exit_ln ) + // Handle non-returning asm - let mut succ = if asm.options.contains(InlineAsmOptions::NORETURN) { - self.exit_ln - } else { - succ - }; + let mut succ = + if self.typeck_results.expr_ty(expr).is_never() { self.exit_ln } else { succ }; + + // Do a first pass for labels only + if asm.contains_label() { + let ln = self.live_node(expr.hir_id, expr.span); + self.init_from_succ(ln, succ); + for (op, _op_sp) in asm.operands.iter().rev() { + match op { + hir::InlineAsmOperand::Label { block } => { + let label_ln = self.propagate_through_block(block, succ); + self.merge_from_succ(ln, label_ln); + } + hir::InlineAsmOperand::In { .. } + | hir::InlineAsmOperand::Out { .. } + | hir::InlineAsmOperand::InOut { .. } + | hir::InlineAsmOperand::SplitInOut { .. } + | hir::InlineAsmOperand::Const { .. } + | hir::InlineAsmOperand::SymFn { .. } + | hir::InlineAsmOperand::SymStatic { .. } => {} + } + } + succ = ln; + } - // Do a first pass for writing outputs only + // Do a second pass for writing outputs only for (op, _op_sp) in asm.operands.iter().rev() { match op { hir::InlineAsmOperand::In { .. } | hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::SymFn { .. } - | hir::InlineAsmOperand::SymStatic { .. } => {} + | hir::InlineAsmOperand::SymStatic { .. } + | hir::InlineAsmOperand::Label { .. } => {} hir::InlineAsmOperand::Out { expr, .. } => { if let Some(expr) = expr { succ = self.write_place(expr, succ, ACC_WRITE); @@ -1075,7 +1113,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } } - // Then do a second pass for inputs + // Then do a third pass for inputs for (op, _op_sp) in asm.operands.iter().rev() { match op { hir::InlineAsmOperand::In { expr, .. } => { @@ -1097,7 +1135,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::SymFn { .. } - | hir::InlineAsmOperand::SymStatic { .. } => {} + | hir::InlineAsmOperand::SymStatic { .. } + | hir::InlineAsmOperand::Label { .. } => {} } } succ diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs index 0455d6d4acba3..27c9c1306e6ac 100644 --- a/compiler/rustc_passes/src/naked_functions.rs +++ b/compiler/rustc_passes/src/naked_functions.rs @@ -237,7 +237,8 @@ impl<'tcx> CheckInlineAssembly<'tcx> { InlineAsmOperand::In { .. } | InlineAsmOperand::Out { .. } | InlineAsmOperand::InOut { .. } - | InlineAsmOperand::SplitInOut { .. } => Some(op_sp), + | InlineAsmOperand::SplitInOut { .. } + | InlineAsmOperand::Label { .. } => Some(op_sp), }) .collect(); if !unsupported_operands.is_empty() { diff --git a/compiler/rustc_pattern_analysis/messages.ftl b/compiler/rustc_pattern_analysis/messages.ftl index 827928f97d7cb..41a1d958f1094 100644 --- a/compiler/rustc_pattern_analysis/messages.ftl +++ b/compiler/rustc_pattern_analysis/messages.ftl @@ -1,3 +1,11 @@ +pattern_analysis_excluside_range_missing_gap = multiple ranges are one apart + .label = this range doesn't match `{$gap}` because `..` is an exclusive range + .suggestion = use an inclusive range instead + +pattern_analysis_excluside_range_missing_max = exclusive range missing `{$max}` + .label = this range doesn't match `{$max}` because `..` is an exclusive range + .suggestion = use an inclusive range instead + pattern_analysis_non_exhaustive_omitted_pattern = some variants are not matched explicitly .help = ensure that all variants are matched explicitly by adding the suggested match arms .note = the matched value is of type `{$scrut_ty}` and the `non_exhaustive_omitted_patterns` attribute was found diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs index 767227619b04b..69e294e47a561 100644 --- a/compiler/rustc_pattern_analysis/src/constructor.rs +++ b/compiler/rustc_pattern_analysis/src/constructor.rs @@ -192,7 +192,7 @@ impl fmt::Display for RangeEnd { #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] pub enum MaybeInfiniteInt { NegInfinity, - /// Encoded value. DO NOT CONSTRUCT BY HAND; use `new_finite`. + /// Encoded value. DO NOT CONSTRUCT BY HAND; use `new_finite_{int,uint}`. #[non_exhaustive] Finite(u128), /// The integer after `u128::MAX`. We need it to represent `x..=u128::MAX` as an exclusive range. @@ -229,25 +229,22 @@ impl MaybeInfiniteInt { } /// Note: this will not turn a finite value into an infinite one or vice-versa. - pub fn minus_one(self) -> Self { + pub fn minus_one(self) -> Option { match self { - Finite(n) => match n.checked_sub(1) { - Some(m) => Finite(m), - None => panic!("Called `MaybeInfiniteInt::minus_one` on 0"), - }, - JustAfterMax => Finite(u128::MAX), - x => x, + Finite(n) => n.checked_sub(1).map(Finite), + JustAfterMax => Some(Finite(u128::MAX)), + x => Some(x), } } /// Note: this will not turn a finite value into an infinite one or vice-versa. - pub fn plus_one(self) -> Self { + pub fn plus_one(self) -> Option { match self { Finite(n) => match n.checked_add(1) { - Some(m) => Finite(m), - None => JustAfterMax, + Some(m) => Some(Finite(m)), + None => Some(JustAfterMax), }, - JustAfterMax => panic!("Called `MaybeInfiniteInt::plus_one` on u128::MAX+1"), - x => x, + JustAfterMax => None, + x => Some(x), } } } @@ -268,18 +265,24 @@ impl IntRange { pub fn is_singleton(&self) -> bool { // Since `lo` and `hi` can't be the same `Infinity` and `plus_one` never changes from finite // to infinite, this correctly only detects ranges that contain exacly one `Finite(x)`. - self.lo.plus_one() == self.hi + self.lo.plus_one() == Some(self.hi) } + /// Construct a singleton range. + /// `x` must be a `Finite(_)` value. #[inline] pub fn from_singleton(x: MaybeInfiniteInt) -> IntRange { - IntRange { lo: x, hi: x.plus_one() } + // `unwrap()` is ok on a finite value + IntRange { lo: x, hi: x.plus_one().unwrap() } } + /// Construct a range with these boundaries. + /// `lo` must not be `PosInfinity` or `JustAfterMax`. `hi` must not be `NegInfinity`. + /// If `end` is `Included`, `hi` must also not be `JustAfterMax`. #[inline] pub fn from_range(lo: MaybeInfiniteInt, mut hi: MaybeInfiniteInt, end: RangeEnd) -> IntRange { if end == RangeEnd::Included { - hi = hi.plus_one(); + hi = hi.plus_one().unwrap(); } if lo >= hi { // This should have been caught earlier by E0030. diff --git a/compiler/rustc_pattern_analysis/src/errors.rs b/compiler/rustc_pattern_analysis/src/errors.rs index 2d592b35159dd..e471b8abd7357 100644 --- a/compiler/rustc_pattern_analysis/src/errors.rs +++ b/compiler/rustc_pattern_analysis/src/errors.rs @@ -1,4 +1,4 @@ -use rustc_errors::{AddToDiagnostic, Diag, EmissionGuarantee, SubdiagnosticMessageOp}; +use rustc_errors::{AddToDiagnostic, Diag, EmissionGuarantee, SubdiagMessageOp}; use rustc_macros::{LintDiagnostic, Subdiagnostic}; use rustc_middle::thir::Pat; use rustc_middle::ty::Ty; @@ -62,7 +62,7 @@ pub struct Overlap<'tcx> { } impl<'tcx> AddToDiagnostic for Overlap<'tcx> { - fn add_to_diagnostic_with>( + fn add_to_diagnostic_with>( self, diag: &mut Diag<'_, G>, _: F, @@ -76,6 +76,57 @@ impl<'tcx> AddToDiagnostic for Overlap<'tcx> { } } +#[derive(LintDiagnostic)] +#[diag(pattern_analysis_excluside_range_missing_max)] +pub struct ExclusiveRangeMissingMax<'tcx> { + #[label] + #[suggestion(code = "{suggestion}", applicability = "maybe-incorrect")] + /// This is an exclusive range that looks like `lo..max` (i.e. doesn't match `max`). + pub first_range: Span, + /// Suggest `lo..=max` instead. + pub suggestion: String, + pub max: Pat<'tcx>, +} + +#[derive(LintDiagnostic)] +#[diag(pattern_analysis_excluside_range_missing_gap)] +pub struct ExclusiveRangeMissingGap<'tcx> { + #[label] + #[suggestion(code = "{suggestion}", applicability = "maybe-incorrect")] + /// This is an exclusive range that looks like `lo..gap` (i.e. doesn't match `gap`). + pub first_range: Span, + pub gap: Pat<'tcx>, + /// Suggest `lo..=gap` instead. + pub suggestion: String, + #[subdiagnostic] + /// All these ranges skipped over `gap` which we think is probably a mistake. + pub gap_with: Vec>, +} + +pub struct GappedRange<'tcx> { + pub span: Span, + pub gap: Pat<'tcx>, + pub first_range: Pat<'tcx>, +} + +impl<'tcx> AddToDiagnostic for GappedRange<'tcx> { + fn add_to_diagnostic_with>( + self, + diag: &mut Diag<'_, G>, + _: F, + ) { + let GappedRange { span, gap, first_range } = self; + + // FIXME(mejrs) unfortunately `#[derive(LintDiagnostic)]` + // does not support `#[subdiagnostic(eager)]`... + let message = format!( + "this could appear to continue range `{first_range}`, but `{gap}` isn't matched by \ + either of them" + ); + diag.span_label(span, message); + } +} + #[derive(LintDiagnostic)] #[diag(pattern_analysis_non_exhaustive_omitted_pattern)] #[help] diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index 4b0955699fc39..f632eaf7ea4f6 100644 --- a/compiler/rustc_pattern_analysis/src/lib.rs +++ b/compiler/rustc_pattern_analysis/src/lib.rs @@ -70,14 +70,8 @@ use rustc_middle::ty::Ty; use rustc_span::ErrorGuaranteed; use crate::constructor::{Constructor, ConstructorSet, IntRange}; -#[cfg(feature = "rustc")] -use crate::lints::lint_nonexhaustive_missing_variants; use crate::pat::DeconstructedPat; use crate::pat_column::PatternColumn; -#[cfg(feature = "rustc")] -use crate::rustc::RustcMatchCheckCtxt; -#[cfg(feature = "rustc")] -use crate::usefulness::{compute_match_usefulness, ValidityConstraint}; pub trait Captures<'a> {} impl<'a, T: ?Sized> Captures<'a> for T {} @@ -145,6 +139,18 @@ pub trait TypeCx: Sized + fmt::Debug { /// The maximum pattern complexity limit was reached. fn complexity_exceeded(&self) -> Result<(), Self::Error>; + + /// Lint that there is a gap `gap` between `pat` and all of `gapped_with` such that the gap is + /// not matched by another range. If `gapped_with` is empty, then `gap` is `T::MAX`. We only + /// detect singleton gaps. + /// The default implementation does nothing. + fn lint_non_contiguous_range_endpoints( + &self, + _pat: &DeconstructedPat, + _gap: IntRange, + _gapped_with: &[&DeconstructedPat], + ) { + } } /// The arm of a match expression. @@ -167,11 +173,14 @@ impl<'p, Cx: TypeCx> Copy for MatchArm<'p, Cx> {} /// useful, and runs some lints. #[cfg(feature = "rustc")] pub fn analyze_match<'p, 'tcx>( - tycx: &RustcMatchCheckCtxt<'p, 'tcx>, + tycx: &rustc::RustcMatchCheckCtxt<'p, 'tcx>, arms: &[rustc::MatchArm<'p, 'tcx>], scrut_ty: Ty<'tcx>, pattern_complexity_limit: Option, ) -> Result, ErrorGuaranteed> { + use lints::lint_nonexhaustive_missing_variants; + use usefulness::{compute_match_usefulness, ValidityConstraint}; + let scrut_ty = tycx.reveal_opaque_ty(scrut_ty); let scrut_validity = ValidityConstraint::from_bool(tycx.known_valid_scrutinee); let report = diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index 5f5bfa7154a74..0085f0ab6566b 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -8,7 +8,7 @@ use rustc_index::{Idx, IndexVec}; use rustc_middle::middle::stability::EvalResult; use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::{self, Const}; -use rustc_middle::thir::{FieldPat, Pat, PatKind, PatRange, PatRangeBoundary}; +use rustc_middle::thir::{self, FieldPat, Pat, PatKind, PatRange, PatRangeBoundary}; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{self, FieldDef, OpaqueTypeKey, Ty, TyCtxt, TypeVisitableExt, VariantDef}; use rustc_session::lint; @@ -718,12 +718,12 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { let value = mir::Const::from_ty_const(c, cx.tcx); lo = PatRangeBoundary::Finite(value); } - let hi = if matches!(range.hi, Finite(0)) { + let hi = if let Some(hi) = range.hi.minus_one() { + hi + } else { // The range encodes `..ty::MIN`, so we can't convert it to an inclusive range. end = rustc_hir::RangeEnd::Excluded; range.hi - } else { - range.hi.minus_one() }; let hi = cx.hoist_pat_range_bdy(hi, ty); PatKind::Range(Box::new(PatRange { lo, hi, end, ty: ty.inner() })) @@ -900,6 +900,70 @@ impl<'p, 'tcx: 'p> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> { let span = self.whole_match_span.unwrap_or(self.scrut_span); Err(self.tcx.dcx().span_err(span, "reached pattern complexity limit")) } + + fn lint_non_contiguous_range_endpoints( + &self, + pat: &crate::pat::DeconstructedPat, + gap: IntRange, + gapped_with: &[&crate::pat::DeconstructedPat], + ) { + let Some(&thir_pat) = pat.data() else { return }; + let thir::PatKind::Range(range) = &thir_pat.kind else { return }; + // Only lint when the left range is an exclusive range. + if range.end != rustc_hir::RangeEnd::Excluded { + return; + } + // `pat` is an exclusive range like `lo..gap`. `gapped_with` contains ranges that start with + // `gap+1`. + let suggested_range: thir::Pat<'_> = { + // Suggest `lo..=gap` instead. + let mut suggested_range = thir_pat.clone(); + let thir::PatKind::Range(range) = &mut suggested_range.kind else { unreachable!() }; + range.end = rustc_hir::RangeEnd::Included; + suggested_range + }; + let gap_as_pat = self.hoist_pat_range(&gap, *pat.ty()); + if gapped_with.is_empty() { + // If `gapped_with` is empty, `gap == T::MAX`. + self.tcx.emit_node_span_lint( + lint::builtin::NON_CONTIGUOUS_RANGE_ENDPOINTS, + self.match_lint_level, + thir_pat.span, + errors::ExclusiveRangeMissingMax { + // Point at this range. + first_range: thir_pat.span, + // That's the gap that isn't covered. + max: gap_as_pat.clone(), + // Suggest `lo..=max` instead. + suggestion: suggested_range.to_string(), + }, + ); + } else { + self.tcx.emit_node_span_lint( + lint::builtin::NON_CONTIGUOUS_RANGE_ENDPOINTS, + self.match_lint_level, + thir_pat.span, + errors::ExclusiveRangeMissingGap { + // Point at this range. + first_range: thir_pat.span, + // That's the gap that isn't covered. + gap: gap_as_pat.clone(), + // Suggest `lo..=gap` instead. + suggestion: suggested_range.to_string(), + // All these ranges skipped over `gap` which we think is probably a + // mistake. + gap_with: gapped_with + .iter() + .map(|pat| errors::GappedRange { + span: pat.data().unwrap().span, + gap: gap_as_pat.clone(), + first_range: thir_pat.clone(), + }) + .collect(), + }, + ); + } + } } /// Recursively expand this pattern into its subpatterns. Only useful for or-patterns. diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index 0261768d91616..a067bf1f0c23e 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -1001,19 +1001,26 @@ impl<'p, Cx: TypeCx> PatStack<'p, Cx> { /// Only call if `ctor.is_covered_by(self.head().ctor())` is true. fn pop_head_constructor( &self, + cx: &Cx, ctor: &Constructor, ctor_arity: usize, ctor_is_relevant: bool, - ) -> PatStack<'p, Cx> { + ) -> Result, Cx::Error> { // We pop the head pattern and push the new fields extracted from the arguments of // `self.head()`. let mut new_pats = self.head().specialize(ctor, ctor_arity); + if new_pats.len() != ctor_arity { + return Err(cx.bug(format_args!( + "uncaught type error: pattern {:?} has inconsistent arity (expected arity {ctor_arity})", + self.head().as_pat().unwrap() + ))); + } new_pats.extend_from_slice(&self.pats[1..]); // `ctor` is relevant for this row if it is the actual constructor of this row, or if the // row has a wildcard and `ctor` is relevant for wildcards. let ctor_is_relevant = !matches!(self.head().ctor(), Constructor::Wildcard) || ctor_is_relevant; - PatStack { pats: new_pats, relevant: self.relevant && ctor_is_relevant } + Ok(PatStack { pats: new_pats, relevant: self.relevant && ctor_is_relevant }) } } @@ -1083,18 +1090,19 @@ impl<'p, Cx: TypeCx> MatrixRow<'p, Cx> { /// Only call if `ctor.is_covered_by(self.head().ctor())` is true. fn pop_head_constructor( &self, + cx: &Cx, ctor: &Constructor, ctor_arity: usize, ctor_is_relevant: bool, parent_row: usize, - ) -> MatrixRow<'p, Cx> { - MatrixRow { - pats: self.pats.pop_head_constructor(ctor, ctor_arity, ctor_is_relevant), + ) -> Result, Cx::Error> { + Ok(MatrixRow { + pats: self.pats.pop_head_constructor(cx, ctor, ctor_arity, ctor_is_relevant)?, parent_row, is_under_guard: self.is_under_guard, useful: false, intersects: BitSet::new_empty(0), // Initialized in `Matrix::expand_and_push`. - } + }) } } @@ -1217,7 +1225,7 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> { }; for (i, row) in self.rows().enumerate() { if ctor.is_covered_by(pcx.cx, row.head().ctor())? { - let new_row = row.pop_head_constructor(ctor, arity, ctor_is_relevant, i); + let new_row = row.pop_head_constructor(pcx.cx, ctor, arity, ctor_is_relevant, i)?; matrix.expand_and_push(new_row); } } @@ -1481,7 +1489,7 @@ impl WitnessMatrix { /// We can however get false negatives because exhaustiveness does not explore all cases. See the /// section on relevancy at the top of the file. fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>( - mcx: &mut UsefulnessCtxt<'_, Cx>, + cx: &Cx, overlap_range: IntRange, matrix: &Matrix<'p, Cx>, specialized_matrix: &Matrix<'p, Cx>, @@ -1514,11 +1522,11 @@ fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>( .map(|&(_, pat)| pat) .collect(); if !overlaps_with.is_empty() { - mcx.tycx.lint_overlapping_range_endpoints(pat, overlap_range, &overlaps_with); + cx.lint_overlapping_range_endpoints(pat, overlap_range, &overlaps_with); } } suffixes.push((child_row_id, pat)) - } else if this_range.hi == overlap.plus_one() { + } else if Some(this_range.hi) == overlap.plus_one() { // `this_range` looks like `this_range.lo..=overlap`; it overlaps with any // ranges that look like `overlap..=hi`. if !suffixes.is_empty() { @@ -1530,7 +1538,7 @@ fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>( .map(|&(_, pat)| pat) .collect(); if !overlaps_with.is_empty() { - mcx.tycx.lint_overlapping_range_endpoints(pat, overlap_range, &overlaps_with); + cx.lint_overlapping_range_endpoints(pat, overlap_range, &overlaps_with); } } prefixes.push((child_row_id, pat)) @@ -1538,6 +1546,33 @@ fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>( } } +/// Collect ranges that have a singleton gap between them. +fn collect_non_contiguous_range_endpoints<'p, Cx: TypeCx>( + cx: &Cx, + gap_range: &IntRange, + matrix: &Matrix<'p, Cx>, +) { + let gap = gap_range.lo; + // Ranges that look like `lo..gap`. + let mut onebefore: SmallVec<[_; 1]> = Default::default(); + // Ranges that start on `gap+1` or singletons `gap+1`. + let mut oneafter: SmallVec<[_; 1]> = Default::default(); + // Look through the column for ranges near the gap. + for pat in matrix.heads() { + let PatOrWild::Pat(pat) = pat else { continue }; + let Constructor::IntRange(this_range) = pat.ctor() else { continue }; + if gap == this_range.hi { + onebefore.push(pat) + } else if gap.plus_one() == Some(this_range.lo) { + oneafter.push(pat) + } + } + + for pat_before in onebefore { + cx.lint_non_contiguous_range_endpoints(pat_before, *gap_range, oneafter.as_slice()); + } +} + /// The core of the algorithm. /// /// This recursively computes witnesses of the non-exhaustiveness of `matrix` (if any). Also tracks @@ -1618,13 +1653,24 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( && spec_matrix.rows.len() >= 2 && spec_matrix.rows.iter().any(|row| !row.intersects.is_empty()) { - collect_overlapping_range_endpoints(mcx, overlap_range, matrix, &spec_matrix); + collect_overlapping_range_endpoints(mcx.tycx, overlap_range, matrix, &spec_matrix); } } matrix.unspecialize(spec_matrix); } + // Detect singleton gaps between ranges. + if missing_ctors.iter().any(|c| matches!(c, Constructor::IntRange(..))) { + for missing in &missing_ctors { + if let Constructor::IntRange(gap) = missing { + if gap.is_singleton() { + collect_non_contiguous_range_endpoints(mcx.tycx, gap, matrix); + } + } + } + } + // Record usefulness in the patterns. for row in matrix.rows() { if row.useful { diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 9d8a9f5fce3e4..fe3598616817b 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -11,6 +11,7 @@ extern crate tracing; mod errors; +use rustc_ast::visit::{try_visit, VisitorResult}; use rustc_ast::MacroDef; use rustc_attr as attr; use rustc_data_structures::fx::FxHashSet; @@ -67,17 +68,13 @@ impl<'tcx> fmt::Display for LazyDefPathStr<'tcx> { /// manually. Second, it doesn't visit some type components like signatures of fn types, or traits /// in `impl Trait`, see individual comments in `DefIdVisitorSkeleton::visit_ty`. trait DefIdVisitor<'tcx> { - type BreakTy = (); + type Result: VisitorResult = (); const SHALLOW: bool = false; const SKIP_ASSOC_TYS: bool = false; fn tcx(&self) -> TyCtxt<'tcx>; - fn visit_def_id( - &mut self, - def_id: DefId, - kind: &str, - descr: &dyn fmt::Display, - ) -> ControlFlow; + fn visit_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) + -> Self::Result; /// Not overridden, but used to actually visit types and traits. fn skeleton(&mut self) -> DefIdVisitorSkeleton<'_, 'tcx, Self> { @@ -87,25 +84,16 @@ trait DefIdVisitor<'tcx> { dummy: Default::default(), } } - fn visit( - &mut self, - ty_fragment: impl TypeVisitable>, - ) -> ControlFlow { + fn visit(&mut self, ty_fragment: impl TypeVisitable>) -> Self::Result { ty_fragment.visit_with(&mut self.skeleton()) } - fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow { + fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> Self::Result { self.skeleton().visit_trait(trait_ref) } - fn visit_predicates( - &mut self, - predicates: ty::GenericPredicates<'tcx>, - ) -> ControlFlow { + fn visit_predicates(&mut self, predicates: ty::GenericPredicates<'tcx>) -> Self::Result { self.skeleton().visit_clauses(predicates.predicates) } - fn visit_clauses( - &mut self, - clauses: &[(ty::Clause<'tcx>, Span)], - ) -> ControlFlow { + fn visit_clauses(&mut self, clauses: &[(ty::Clause<'tcx>, Span)]) -> Self::Result { self.skeleton().visit_clauses(clauses) } } @@ -120,36 +108,42 @@ impl<'tcx, V> DefIdVisitorSkeleton<'_, 'tcx, V> where V: DefIdVisitor<'tcx> + ?Sized, { - fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow { + fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> V::Result { let TraitRef { def_id, args, .. } = trait_ref; - self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref.print_only_trait_path())?; - if V::SHALLOW { ControlFlow::Continue(()) } else { args.visit_with(self) } + try_visit!(self.def_id_visitor.visit_def_id( + def_id, + "trait", + &trait_ref.print_only_trait_path() + )); + if V::SHALLOW { V::Result::output() } else { args.visit_with(self) } } - fn visit_projection_ty(&mut self, projection: ty::AliasTy<'tcx>) -> ControlFlow { + fn visit_projection_ty(&mut self, projection: ty::AliasTy<'tcx>) -> V::Result { let tcx = self.def_id_visitor.tcx(); let (trait_ref, assoc_args) = projection.trait_ref_and_own_args(tcx); - self.visit_trait(trait_ref)?; + try_visit!(self.visit_trait(trait_ref)); if V::SHALLOW { - ControlFlow::Continue(()) + V::Result::output() } else { - assoc_args.iter().try_for_each(|arg| arg.visit_with(self)) + V::Result::from_branch( + assoc_args.iter().try_for_each(|arg| arg.visit_with(self).branch()), + ) } } - fn visit_clause(&mut self, clause: ty::Clause<'tcx>) -> ControlFlow { + fn visit_clause(&mut self, clause: ty::Clause<'tcx>) -> V::Result { match clause.kind().skip_binder() { ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity: _ }) => { self.visit_trait(trait_ref) } ty::ClauseKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => { - term.visit_with(self)?; + try_visit!(term.visit_with(self)); self.visit_projection_ty(projection_ty) } ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, _region)) => ty.visit_with(self), - ty::ClauseKind::RegionOutlives(..) => ControlFlow::Continue(()), + ty::ClauseKind::RegionOutlives(..) => V::Result::output(), ty::ClauseKind::ConstArgHasType(ct, ty) => { - ct.visit_with(self)?; + try_visit!(ct.visit_with(self)); ty.visit_with(self) } ty::ClauseKind::ConstEvaluatable(ct) => ct.visit_with(self), @@ -157,8 +151,11 @@ where } } - fn visit_clauses(&mut self, clauses: &[(ty::Clause<'tcx>, Span)]) -> ControlFlow { - clauses.into_iter().try_for_each(|&(clause, _span)| self.visit_clause(clause)) + fn visit_clauses(&mut self, clauses: &[(ty::Clause<'tcx>, Span)]) -> V::Result { + for &(clause, _) in clauses { + try_visit!(self.visit_clause(clause)); + } + V::Result::output() } } @@ -166,13 +163,13 @@ impl<'tcx, V> TypeVisitor> for DefIdVisitorSkeleton<'_, 'tcx, V> where V: DefIdVisitor<'tcx> + ?Sized, { - type BreakTy = V::BreakTy; + type Result = V::Result; - fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow { + fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> Self::Result { self.visit_clause(p.as_clause().unwrap()) } - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { let tcx = self.def_id_visitor.tcx(); // GenericArgs are not visited here because they are visited below // in `super_visit_with`. @@ -183,16 +180,16 @@ where | ty::Closure(def_id, ..) | ty::CoroutineClosure(def_id, ..) | ty::Coroutine(def_id, ..) => { - self.def_id_visitor.visit_def_id(def_id, "type", &ty)?; + try_visit!(self.def_id_visitor.visit_def_id(def_id, "type", &ty)); if V::SHALLOW { - return ControlFlow::Continue(()); + return V::Result::output(); } // Default type visitor doesn't visit signatures of fn types. // Something like `fn() -> Priv {my_func}` is considered a private type even if // `my_func` is public, so we need to visit signatures. if let ty::FnDef(..) = ty.kind() { // FIXME: this should probably use `args` from `FnDef` - tcx.fn_sig(def_id).instantiate_identity().visit_with(self)?; + try_visit!(tcx.fn_sig(def_id).instantiate_identity().visit_with(self)); } // Inherent static methods don't have self type in args. // Something like `fn() {my_method}` type of the method @@ -200,7 +197,9 @@ where // so we need to visit the self type additionally. if let Some(assoc_item) = tcx.opt_associated_item(def_id) { if let Some(impl_def_id) = assoc_item.impl_container(tcx) { - tcx.type_of(impl_def_id).instantiate_identity().visit_with(self)?; + try_visit!( + tcx.type_of(impl_def_id).instantiate_identity().visit_with(self) + ); } } } @@ -211,10 +210,10 @@ where // as visible/reachable even if `Type` is private. // Ideally, associated types should be instantiated in the same way as // free type aliases, but this isn't done yet. - return ControlFlow::Continue(()); + return V::Result::output(); } - self.def_id_visitor.visit_def_id( + try_visit!(self.def_id_visitor.visit_def_id( data.def_id, match kind { ty::Inherent | ty::Projection => "associated type", @@ -222,15 +221,17 @@ where ty::Opaque => unreachable!(), }, &LazyDefPathStr { def_id: data.def_id, tcx }, - )?; + )); // This will also visit args if necessary, so we don't need to recurse. return if V::SHALLOW { - ControlFlow::Continue(()) + V::Result::output() } else if kind == ty::Projection { self.visit_projection_ty(data) } else { - data.args.iter().try_for_each(|arg| arg.visit_with(self)) + V::Result::from_branch( + data.args.iter().try_for_each(|arg| arg.visit_with(self).branch()), + ) }; } ty::Dynamic(predicates, ..) => { @@ -245,7 +246,7 @@ where } }; let ty::ExistentialTraitRef { def_id, args: _ } = trait_ref; - self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref)?; + try_visit!(self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref)); } } ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => { @@ -258,7 +259,7 @@ where // through the trait list (default type visitor doesn't visit those traits). // All traits in the list are considered the "primary" part of the type // and are visited by shallow visitors. - self.visit_clauses(tcx.explicit_item_bounds(def_id).skip_binder())?; + try_visit!(self.visit_clauses(tcx.explicit_item_bounds(def_id).skip_binder())); } } // These types don't have their own def-ids (but may have subcomponents @@ -285,10 +286,10 @@ where } } - if V::SHALLOW { ControlFlow::Continue(()) } else { ty.super_visit_with(self) } + if V::SHALLOW { V::Result::output() } else { ty.super_visit_with(self) } } - fn visit_const(&mut self, c: Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, c: Const<'tcx>) -> Self::Result { let tcx = self.def_id_visitor.tcx(); tcx.expand_abstract_consts(c).super_visit_with(self) } @@ -316,16 +317,10 @@ impl<'a, 'tcx, VL: VisibilityLike, const SHALLOW: bool> DefIdVisitor<'tcx> fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } - fn visit_def_id( - &mut self, - def_id: DefId, - _kind: &str, - _descr: &dyn fmt::Display, - ) -> ControlFlow { + fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display) { if let Some(def_id) = def_id.as_local() { self.min = VL::new_min(self, def_id); } - ControlFlow::Continue(()) } } @@ -836,12 +831,7 @@ impl<'tcx> DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx> fn tcx(&self) -> TyCtxt<'tcx> { self.ev.tcx } - fn visit_def_id( - &mut self, - def_id: DefId, - _kind: &str, - _descr: &dyn fmt::Display, - ) -> ControlFlow { + fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display) { if let Some(def_id) = def_id.as_local() { // All effective visibilities except `reachable_through_impl_trait` are limited to // nominal visibility. If any type or trait is leaked farther than that, it will @@ -850,7 +840,6 @@ impl<'tcx> DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx> .then(|| self.ev.tcx.local_visibility(def_id)); self.ev.update_eff_vis(def_id, self.effective_vis, max_vis, self.level); } - ControlFlow::Continue(()) } } @@ -1076,8 +1065,8 @@ impl<'tcx> TypePrivacyVisitor<'tcx> { } impl<'tcx> rustc_ty_utils::sig_types::SpannedTypeVisitor<'tcx> for TypePrivacyVisitor<'tcx> { - type BreakTy = (); - fn visit(&mut self, span: Span, value: impl TypeVisitable>) -> ControlFlow<()> { + type Result = ControlFlow<()>; + fn visit(&mut self, span: Span, value: impl TypeVisitable>) -> Self::Result { self.span = span; value.visit_with(&mut self.skeleton()) } @@ -1233,6 +1222,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { } impl<'tcx> DefIdVisitor<'tcx> for TypePrivacyVisitor<'tcx> { + type Result = ControlFlow<()>; fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -1241,7 +1231,7 @@ impl<'tcx> DefIdVisitor<'tcx> for TypePrivacyVisitor<'tcx> { def_id: DefId, kind: &str, descr: &dyn fmt::Display, - ) -> ControlFlow { + ) -> Self::Result { if self.check_def_id(def_id, kind, descr) { ControlFlow::Break(()) } else { @@ -1407,6 +1397,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> { } impl<'tcx> DefIdVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'tcx> { + type Result = ControlFlow<()>; fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -1415,7 +1406,7 @@ impl<'tcx> DefIdVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'tcx> { def_id: DefId, kind: &str, descr: &dyn fmt::Display, - ) -> ControlFlow { + ) -> Self::Result { if self.check_def_id(def_id, kind, descr) { ControlFlow::Break(()) } else { diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 1b546bf9103d8..b06d75be3902d 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -17,6 +17,7 @@ use rustc_middle::dep_graph::{ use rustc_middle::query::on_disk_cache::AbsoluteBytePos; use rustc_middle::query::on_disk_cache::{CacheDecoder, CacheEncoder, EncodedDepNodeIndex}; use rustc_middle::query::Key; +use rustc_middle::ty::print::with_reduced_queries; use rustc_middle::ty::tls::{self, ImplicitCtxt}; use rustc_middle::ty::{self, TyCtxt}; use rustc_query_system::dep_graph::{DepNodeParams, HasDepContext}; @@ -304,6 +305,10 @@ pub(crate) fn create_query_frame< kind: DepKind, name: &'static str, ) -> QueryStackFrame { + // If reduced queries are requested, we may be printing a query stack due + // to a panic. Avoid using `default_span` and `def_kind` in that case. + let reduce_queries = with_reduced_queries(); + // Avoid calling queries while formatting the description let description = ty::print::with_no_queries!(do_describe(tcx, key)); let description = if tcx.sess.verbose_internals() { @@ -311,7 +316,7 @@ pub(crate) fn create_query_frame< } else { description }; - let span = if kind == dep_graph::dep_kinds::def_span { + let span = if kind == dep_graph::dep_kinds::def_span || reduce_queries { // The `def_span` query is used to calculate `default_span`, // so exit to avoid infinite recursion. None @@ -319,7 +324,7 @@ pub(crate) fn create_query_frame< Some(key.default_span(tcx)) }; let def_id = key.key_as_def_id(); - let def_kind = if kind == dep_graph::dep_kinds::def_kind { + let def_kind = if kind == dep_graph::dep_kinds::def_kind || reduce_queries { // Try to avoid infinite recursion. None } else { diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 40517407ee6a1..3d9848395a20b 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -285,9 +285,8 @@ where let lock = query.query_state(qcx).active.get_shard_by_value(&key).lock(); match lock.get(&key) { - Some(QueryResult::Poisoned) => { - panic!("query '{}' not cached due to poisoning", query.name()) - } + // The query we waited on panicked. Continue unwinding here. + Some(QueryResult::Poisoned) => FatalError.raise(), _ => panic!( "query '{}' result must be in the cache or the query must be poisoned after a wait", query.name() diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 1c4aeefcbcfd0..dd18ab7d9d23e 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -25,6 +25,7 @@ use rustc_hir::def::{self, *}; use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID}; use rustc_metadata::creader::LoadedMacro; use rustc_middle::metadata::ModChild; +use rustc_middle::ty::Feed; use rustc_middle::{bug, ty}; use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; @@ -407,7 +408,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { // Top level use tree reuses the item's id and list stems reuse their parent // use tree's ids, so in both cases their visibilities are already filled. if nested && !list_stem { - self.r.feed_visibility(self.r.local_def_id(id), vis); + self.r.feed_visibility(self.r.feed(id), vis); } let mut prefix_iter = parent_prefix @@ -632,7 +633,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { &mut self, fields: &[ast::FieldDef], ident: Ident, - def_id: LocalDefId, + feed: Feed<'tcx, LocalDefId>, adt_res: Res, adt_vis: ty::Visibility, adt_span: Span, @@ -643,7 +644,8 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { // Define a name in the type namespace if it is not anonymous. self.r.define(parent, ident, TypeNS, (adt_res, adt_vis, adt_span, expansion)); - self.r.feed_visibility(def_id, adt_vis); + self.r.feed_visibility(feed, adt_vis); + let def_id = feed.key(); // Record field names for error reporting. self.insert_field_def_ids(def_id, fields); @@ -653,14 +655,15 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { match &field.ty.kind { ast::TyKind::AnonStruct(id, nested_fields) | ast::TyKind::AnonUnion(id, nested_fields) => { - let local_def_id = self.r.local_def_id(*id); + let feed = self.r.feed(*id); + let local_def_id = feed.key(); let def_id = local_def_id.to_def_id(); let def_kind = self.r.tcx.def_kind(local_def_id); let res = Res::Def(def_kind, def_id); self.build_reduced_graph_for_struct_variant( &nested_fields, Ident::empty(), - local_def_id, + feed, res, // Anonymous adts inherit visibility from their parent adts. adt_vis, @@ -680,12 +683,13 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { let ident = item.ident; let sp = item.span; let vis = self.resolve_visibility(&item.vis); - let local_def_id = self.r.local_def_id(item.id); + let feed = self.r.feed(item.id); + let local_def_id = feed.key(); let def_id = local_def_id.to_def_id(); let def_kind = self.r.tcx.def_kind(def_id); let res = Res::Def(def_kind, def_id); - self.r.feed_visibility(local_def_id, vis); + self.r.feed_visibility(feed, vis); match item.kind { ItemKind::Use(ref use_tree) => { @@ -762,7 +766,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { self.build_reduced_graph_for_struct_variant( vdata.fields(), ident, - local_def_id, + feed, res, vis, sp, @@ -795,10 +799,11 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { } ret_fields.push(field_vis.to_def_id()); } - let ctor_def_id = self.r.local_def_id(ctor_node_id); + let feed = self.r.feed(ctor_node_id); + let ctor_def_id = feed.key(); let ctor_res = self.res(ctor_def_id); self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, sp, expansion)); - self.r.feed_visibility(ctor_def_id, ctor_vis); + self.r.feed_visibility(feed, ctor_vis); // We need the field visibility spans also for the constructor for E0603. self.insert_field_visibilities_local(ctor_def_id.to_def_id(), vdata.fields()); @@ -812,7 +817,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { self.build_reduced_graph_for_struct_variant( vdata.fields(), ident, - local_def_id, + feed, res, vis, sp, @@ -919,7 +924,8 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { /// Constructs the reduced graph for one foreign item. fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem) { - let local_def_id = self.r.local_def_id(item.id); + let feed = self.r.feed(item.id); + let local_def_id = feed.key(); let def_id = local_def_id.to_def_id(); let ns = match item.kind { ForeignItemKind::Fn(..) => ValueNS, @@ -931,7 +937,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { let expansion = self.parent_scope.expansion; let vis = self.resolve_visibility(&item.vis); self.r.define(parent, item.ident, ns, (self.res(def_id), vis, item.span, expansion)); - self.r.feed_visibility(local_def_id, vis); + self.r.feed_visibility(feed, vis); } fn build_reduced_graph_for_block(&mut self, block: &Block) { @@ -1218,7 +1224,8 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { fn define_macro(&mut self, item: &ast::Item) -> MacroRulesScopeRef<'a> { let parent_scope = self.parent_scope; let expansion = parent_scope.expansion; - let def_id = self.r.local_def_id(item.id); + let feed = self.r.feed(item.id); + let def_id = feed.key(); let (res, ident, span, macro_rules) = match &item.kind { ItemKind::MacroDef(def) => (self.res(def_id), item.ident, item.span, def.macro_rules), ItemKind::Fn(..) => match self.proc_macro_stub(item) { @@ -1269,7 +1276,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { self.r.check_reserved_macro_name(ident, res); self.insert_unused_macro(ident, def_id, item.id); } - self.r.feed_visibility(def_id, vis); + self.r.feed_visibility(feed, vis); let scope = self.r.arenas.alloc_macro_rules_scope(MacroRulesScope::Binding( self.r.arenas.alloc_macro_rules_binding(MacroRulesBinding { parent_macro_rules_scope: parent_scope.macro_rules, @@ -1293,7 +1300,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { self.insert_unused_macro(ident, def_id, item.id); } self.r.define(module, ident, MacroNS, (res, vis, span, expansion)); - self.r.feed_visibility(def_id, vis); + self.r.feed_visibility(feed, vis); self.parent_scope.macro_rules } } @@ -1385,7 +1392,8 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { } let vis = self.resolve_visibility(&item.vis); - let local_def_id = self.r.local_def_id(item.id); + let feed = self.r.feed(item.id); + let local_def_id = feed.key(); let def_id = local_def_id.to_def_id(); if !(ctxt == AssocCtxt::Impl @@ -1395,7 +1403,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { // Trait impl item visibility is inherited from its trait when not specified // explicitly. In that case we cannot determine it here in early resolve, // so we leave a hole in the visibility table to be filled later. - self.r.feed_visibility(local_def_id, vis); + self.r.feed_visibility(feed, vis); } if ctxt == AssocCtxt::Trait { @@ -1469,7 +1477,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { self.visit_invoc(sf.id); } else { let vis = self.resolve_visibility(&sf.vis); - self.r.feed_visibility(self.r.local_def_id(sf.id), vis); + self.r.feed_visibility(self.r.feed(sf.id), vis); visit::walk_field_def(self, sf); } } @@ -1487,10 +1495,11 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { let ident = variant.ident; // Define a name in the type namespace. - let def_id = self.r.local_def_id(variant.id); + let feed = self.r.feed(variant.id); + let def_id = feed.key(); let vis = self.resolve_visibility(&variant.vis); self.r.define(parent, ident, TypeNS, (self.res(def_id), vis, variant.span, expn_id)); - self.r.feed_visibility(def_id, vis); + self.r.feed_visibility(feed, vis); // If the variant is marked as non_exhaustive then lower the visibility to within the crate. let ctor_vis = @@ -1502,10 +1511,11 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { // Define a constructor name in the value namespace. if let Some(ctor_node_id) = variant.data.ctor_node_id() { - let ctor_def_id = self.r.local_def_id(ctor_node_id); + let feed = self.r.feed(ctor_node_id); + let ctor_def_id = feed.key(); let ctor_res = self.res(ctor_def_id); self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, variant.span, expn_id)); - self.r.feed_visibility(ctor_def_id, ctor_vis); + self.r.feed_visibility(feed, ctor_vis); } // Record field names for error reporting. diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index 37cc50f694385..bf1ea2e270932 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -35,7 +35,7 @@ use rustc_data_structures::unord::UnordSet; use rustc_errors::{pluralize, MultiSpan}; use rustc_hir::def::{DefKind, Res}; use rustc_session::lint::builtin::{MACRO_USE_EXTERN_CRATE, UNUSED_EXTERN_CRATES, UNUSED_IMPORTS}; -use rustc_session::lint::BuiltinLintDiagnostics; +use rustc_session::lint::BuiltinLintDiag; use rustc_span::symbol::{kw, Ident}; use rustc_span::{Span, DUMMY_SP}; @@ -137,6 +137,81 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> { self.check_import_as_underscore(item, *id); } } + + fn report_unused_extern_crate_items( + &mut self, + maybe_unused_extern_crates: FxHashMap, + ) { + let tcx = self.r.tcx(); + for extern_crate in &self.extern_crate_items { + let warn_if_unused = !extern_crate.ident.name.as_str().starts_with('_'); + + // If the crate is fully unused, we suggest removing it altogether. + // We do this in any edition. + if warn_if_unused { + if let Some(&span) = maybe_unused_extern_crates.get(&extern_crate.id) { + self.r.lint_buffer.buffer_lint_with_diagnostic( + UNUSED_EXTERN_CRATES, + extern_crate.id, + span, + "unused extern crate", + BuiltinLintDiag::UnusedExternCrate { + removal_span: extern_crate.span_with_attributes, + }, + ); + continue; + } + } + + // If we are not in Rust 2018 edition, then we don't make any further + // suggestions. + if !tcx.sess.at_least_rust_2018() { + continue; + } + + // If the extern crate has any attributes, they may have funky + // semantics we can't faithfully represent using `use` (most + // notably `#[macro_use]`). Ignore it. + if extern_crate.has_attrs { + continue; + } + + // If the extern crate is renamed, then we cannot suggest replacing it with a use as this + // would not insert the new name into the prelude, where other imports in the crate may be + // expecting it. + if extern_crate.renames { + continue; + } + + // If the extern crate isn't in the extern prelude, + // there is no way it can be written as a `use`. + if !self + .r + .extern_prelude + .get(&extern_crate.ident) + .is_some_and(|entry| !entry.introduced_by_item) + { + continue; + } + + let vis_span = extern_crate + .vis_span + .find_ancestor_inside(extern_crate.span) + .unwrap_or(extern_crate.vis_span); + let ident_span = extern_crate + .ident + .span + .find_ancestor_inside(extern_crate.span) + .unwrap_or(extern_crate.ident.span); + self.r.lint_buffer.buffer_lint_with_diagnostic( + UNUSED_EXTERN_CRATES, + extern_crate.id, + extern_crate.span, + "`extern crate` is not idiomatic in the new edition", + BuiltinLintDiag::ExternCrateNotIdiomatic { vis_span, ident_span }, + ); + } + } } impl<'a, 'b, 'tcx> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b, 'tcx> { @@ -335,6 +410,8 @@ impl Resolver<'_, '_> { }; visit::walk_crate(&mut visitor, krate); + visitor.report_unused_extern_crate_items(maybe_unused_extern_crates); + for unused in visitor.unused_imports.values() { let mut fixes = Vec::new(); let spans = match calc_unused_spans(unused, &unused.use_tree, unused.use_tree_id) { @@ -412,76 +489,7 @@ impl Resolver<'_, '_> { unused.use_tree_id, ms, msg, - BuiltinLintDiagnostics::UnusedImports(fix_msg.into(), fixes, test_module_span), - ); - } - - for extern_crate in visitor.extern_crate_items { - let warn_if_unused = !extern_crate.ident.name.as_str().starts_with('_'); - - // If the crate is fully unused, we suggest removing it altogether. - // We do this in any edition. - if warn_if_unused { - if let Some(&span) = maybe_unused_extern_crates.get(&extern_crate.id) { - visitor.r.lint_buffer.buffer_lint_with_diagnostic( - UNUSED_EXTERN_CRATES, - extern_crate.id, - span, - "unused extern crate", - BuiltinLintDiagnostics::UnusedExternCrate { - removal_span: extern_crate.span_with_attributes, - }, - ); - continue; - } - } - - // If we are not in Rust 2018 edition, then we don't make any further - // suggestions. - if !tcx.sess.at_least_rust_2018() { - continue; - } - - // If the extern crate has any attributes, they may have funky - // semantics we can't faithfully represent using `use` (most - // notably `#[macro_use]`). Ignore it. - if extern_crate.has_attrs { - continue; - } - - // If the extern crate is renamed, then we cannot suggest replacing it with a use as this - // would not insert the new name into the prelude, where other imports in the crate may be - // expecting it. - if extern_crate.renames { - continue; - } - - // If the extern crate isn't in the extern prelude, - // there is no way it can be written as a `use`. - if !visitor - .r - .extern_prelude - .get(&extern_crate.ident) - .is_some_and(|entry| !entry.introduced_by_item) - { - continue; - } - - let vis_span = extern_crate - .vis_span - .find_ancestor_inside(extern_crate.span) - .unwrap_or(extern_crate.vis_span); - let ident_span = extern_crate - .ident - .span - .find_ancestor_inside(extern_crate.span) - .unwrap_or(extern_crate.ident.span); - visitor.r.lint_buffer.buffer_lint_with_diagnostic( - UNUSED_EXTERN_CRATES, - extern_crate.id, - extern_crate.span, - "`extern crate` is not idiomatic in the new edition", - BuiltinLintDiagnostics::ExternCrateNotIdiomatic { vis_span, ident_span }, + BuiltinLintDiag::UnusedImports(fix_msg.into(), fixes, test_module_span), ); } diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 12bf462a6fdfd..bb3b902c0de64 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -38,14 +38,16 @@ impl<'a, 'b, 'tcx> DefCollector<'a, 'b, 'tcx> { "create_def(node_id={:?}, def_kind={:?}, parent_def={:?})", node_id, def_kind, parent_def ); - self.resolver.create_def( - parent_def, - node_id, - name, - def_kind, - self.expansion.to_expn_id(), - span.with_parent(None), - ) + self.resolver + .create_def( + parent_def, + node_id, + name, + def_kind, + self.expansion.to_expn_id(), + span.with_parent(None), + ) + .def_id() } fn with_parent(&mut self, parent_def: LocalDefId, f: F) { diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index dc7dfa04d18f2..0bb2a69ae9926 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -19,7 +19,7 @@ use rustc_middle::ty::TyCtxt; use rustc_session::lint::builtin::ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE; use rustc_session::lint::builtin::AMBIGUOUS_GLOB_IMPORTS; use rustc_session::lint::builtin::MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS; -use rustc_session::lint::{AmbiguityErrorDiag, BuiltinLintDiagnostics}; +use rustc_session::lint::{AmbiguityErrorDiag, BuiltinLintDiag}; use rustc_session::Session; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::edition::Edition; @@ -138,7 +138,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { CRATE_NODE_ID, span_use, msg, - BuiltinLintDiagnostics::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def), + BuiltinLintDiag::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def), ); } @@ -153,7 +153,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { import.root_id, ambiguity_error.ident.span, diag.msg.to_string(), - BuiltinLintDiagnostics::AmbiguousGlobImports { diag }, + BuiltinLintDiag::AmbiguousGlobImports { diag }, ); } else { let mut err = struct_span_code_err!(self.dcx(), diag.span, E0659, "{}", &diag.msg); @@ -188,7 +188,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &candidates, if instead { Instead::Yes } else { Instead::No }, found_use, - DiagnosticMode::Normal, + DiagMode::Normal, path, "", ); @@ -525,7 +525,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - let diag = BuiltinLintDiagnostics::AbsPathWithModule(root_span); + let diag = BuiltinLintDiag::AbsPathWithModule(root_span); self.lint_buffer.buffer_lint_with_diagnostic( ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, node_id, @@ -723,7 +723,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &import_suggestions, Instead::No, FoundUse::Yes, - DiagnosticMode::Pattern, + DiagMode::Pattern, vec![], "", ); @@ -1444,7 +1444,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &import_suggestions, Instead::No, found_use, - DiagnosticMode::Normal, + DiagMode::Normal, vec![], "", ); @@ -1736,7 +1736,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } fn report_privacy_error(&mut self, privacy_error: &PrivacyError<'a>) { - let PrivacyError { ident, binding, outermost_res, parent_scope, dedup_span } = + let PrivacyError { ident, binding, outermost_res, parent_scope, single_nested, dedup_span } = *privacy_error; let res = binding.res(); @@ -1775,7 +1775,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &import_suggestions, Instead::Yes, FoundUse::Yes, - DiagnosticMode::Import, + DiagMode::Import { append: single_nested }, vec![], "", ); @@ -2696,12 +2696,16 @@ enum FoundUse { } /// Whether a binding is part of a pattern or a use statement. Used for diagnostics. -pub(crate) enum DiagnosticMode { +pub(crate) enum DiagMode { Normal, /// The binding is part of a pattern Pattern, /// The binding is part of a use statement - Import, + Import { + /// `true` mean add the tips afterward for case `use a::{b,c}`, + /// rather than replacing within. + append: bool, + }, } pub(crate) fn import_candidates( @@ -2710,7 +2714,7 @@ pub(crate) fn import_candidates( // This is `None` if all placement locations are inside expansions use_placement_span: Option, candidates: &[ImportSuggestion], - mode: DiagnosticMode, + mode: DiagMode, append: &str, ) { show_candidates( @@ -2726,6 +2730,8 @@ pub(crate) fn import_candidates( ); } +type PathString<'a> = (String, &'a str, Option, &'a Option, bool); + /// When an entity with a given name is not available in scope, we search for /// entities with that name in all crates. This method allows outputting the /// results of this search in a programmer-friendly way. If any entities are @@ -2738,7 +2744,7 @@ fn show_candidates( candidates: &[ImportSuggestion], instead: Instead, found_use: FoundUse, - mode: DiagnosticMode, + mode: DiagMode, path: Vec, append: &str, ) -> bool { @@ -2746,10 +2752,8 @@ fn show_candidates( return false; } - let mut accessible_path_strings: Vec<(String, &str, Option, &Option, bool)> = - Vec::new(); - let mut inaccessible_path_strings: Vec<(String, &str, Option, &Option, bool)> = - Vec::new(); + let mut accessible_path_strings: Vec> = Vec::new(); + let mut inaccessible_path_strings: Vec> = Vec::new(); candidates.iter().for_each(|c| { if c.accessible { @@ -2799,7 +2803,7 @@ fn show_candidates( }; let instead = if let Instead::Yes = instead { " instead" } else { "" }; - let mut msg = if let DiagnosticMode::Pattern = mode { + let mut msg = if let DiagMode::Pattern = mode { format!( "if you meant to match on {kind}{instead}{name}, use the full path in the pattern", ) @@ -2811,9 +2815,18 @@ fn show_candidates( err.note(note.clone()); } + let append_candidates = |msg: &mut String, accessible_path_strings: Vec>| { + msg.push(':'); + + for candidate in accessible_path_strings { + msg.push('\n'); + msg.push_str(&candidate.0); + } + }; + if let Some(span) = use_placement_span { let (add_use, trailing) = match mode { - DiagnosticMode::Pattern => { + DiagMode::Pattern => { err.span_suggestions( span, msg, @@ -2822,14 +2835,14 @@ fn show_candidates( ); return true; } - DiagnosticMode::Import => ("", ""), - DiagnosticMode::Normal => ("use ", ";\n"), + DiagMode::Import { .. } => ("", ""), + DiagMode::Normal => ("use ", ";\n"), }; for candidate in &mut accessible_path_strings { // produce an additional newline to separate the new use statement // from the directly following item. let additional_newline = if let FoundUse::No = found_use - && let DiagnosticMode::Normal = mode + && let DiagMode::Normal = mode { "\n" } else { @@ -2839,13 +2852,22 @@ fn show_candidates( format!("{add_use}{}{append}{trailing}{additional_newline}", &candidate.0); } - err.span_suggestions_with_style( - span, - msg, - accessible_path_strings.into_iter().map(|a| a.0), - Applicability::MaybeIncorrect, - SuggestionStyle::ShowAlways, - ); + match mode { + DiagMode::Import { append: true, .. } => { + append_candidates(&mut msg, accessible_path_strings); + err.span_help(span, msg); + } + _ => { + err.span_suggestions_with_style( + span, + msg, + accessible_path_strings.into_iter().map(|a| a.0), + Applicability::MaybeIncorrect, + SuggestionStyle::ShowAlways, + ); + } + } + if let [first, .., last] = &path[..] { let sp = first.ident.span.until(last.ident.span); // Our suggestion is empty, so make sure the span is not empty (or we'd ICE). @@ -2860,26 +2882,17 @@ fn show_candidates( } } } else { - msg.push(':'); - - for candidate in accessible_path_strings { - msg.push('\n'); - msg.push_str(&candidate.0); - } - + append_candidates(&mut msg, accessible_path_strings); err.help(msg); } true - } else if !(inaccessible_path_strings.is_empty() || matches!(mode, DiagnosticMode::Import)) { - let prefix = if let DiagnosticMode::Pattern = mode { - "you might have meant to match on " - } else { - "" - }; + } else if !(inaccessible_path_strings.is_empty() || matches!(mode, DiagMode::Import { .. })) { + let prefix = + if let DiagMode::Pattern = mode { "you might have meant to match on " } else { "" }; if let [(name, descr, def_id, note, _)] = &inaccessible_path_strings[..] { let msg = format!( "{prefix}{descr} `{name}`{} exists but is inaccessible", - if let DiagnosticMode::Pattern = mode { ", which" } else { "" } + if let DiagMode::Pattern = mode { ", which" } else { "" } ); if let Some(local_def_id) = def_id.and_then(|did| did.as_local()) { diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index c17ea00ec8094..6518d9735ae52 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -4,7 +4,7 @@ use rustc_hir::def::{DefKind, Namespace, NonMacroAttrKind, PartialRes, PerNS}; use rustc_middle::bug; use rustc_middle::ty; use rustc_session::lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK; -use rustc_session::lint::BuiltinLintDiagnostics; +use rustc_session::lint::BuiltinLintDiag; use rustc_span::def_id::LocalDefId; use rustc_span::hygiene::{ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContext}; use rustc_span::symbol::{kw, Ident}; @@ -530,7 +530,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ns.descr(), ident ), - BuiltinLintDiagnostics::ProcMacroDeriveResolutionFallback( + BuiltinLintDiag::ProcMacroDeriveResolutionFallback( orig_ident.span, ), ); @@ -868,7 +868,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { .into_iter() .find_map(|binding| if binding == ignore_binding { None } else { binding }); - if let Some(Finalize { path_span, report_private, used, .. }) = finalize { + if let Some(Finalize { path_span, report_private, used, root_span, .. }) = finalize { let Some(binding) = binding else { return Err((Determined, Weak::No)); }; @@ -881,6 +881,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { dedup_span: path_span, outermost_res: None, parent_scope: *parent_scope, + single_nested: path_span != root_span, }); } else { return Err((Determined, Weak::No)); diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 9bfca0f179880..ea08041f2aadd 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -1,6 +1,6 @@ //! A bunch of methods and structures more or less related to resolving imports. -use crate::diagnostics::{import_candidates, DiagnosticMode, Suggestion}; +use crate::diagnostics::{import_candidates, DiagMode, Suggestion}; use crate::errors::{ CannotBeReexportedCratePublic, CannotBeReexportedCratePublicNS, CannotBeReexportedPrivate, CannotBeReexportedPrivateNS, CannotDetermineImportResolution, CannotGlobImportAllCrates, @@ -8,8 +8,8 @@ use crate::errors::{ ItemsInTraitsAreNotImportable, }; use crate::Determinacy::{self, *}; -use crate::Namespace::*; use crate::{module_to_string, names_to_string, ImportSuggestion}; +use crate::{AmbiguityError, Namespace::*}; use crate::{AmbiguityKind, BindingKey, ResolutionError, Resolver, Segment}; use crate::{Finalize, Module, ModuleOrUniformRoot, ParentScope, PerNS, ScopeSet}; use crate::{NameBinding, NameBindingData, NameBindingKind, PathResult, Used}; @@ -27,7 +27,7 @@ use rustc_session::lint::builtin::{ AMBIGUOUS_GLOB_REEXPORTS, HIDDEN_GLOB_REEXPORTS, PUB_USE_OF_PRIVATE_EXTERN_CRATE, UNUSED_IMPORTS, }; -use rustc_session::lint::BuiltinLintDiagnostics; +use rustc_session::lint::BuiltinLintDiag; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::hygiene::LocalExpnId; use rustc_span::symbol::{kw, Ident, Symbol}; @@ -538,7 +538,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { .chain(indeterminate_imports.iter().map(|i| (true, i))) { let unresolved_import_error = self.finalize_import(*import); - // If this import is unresolved then create a dummy import // resolution for it so that later resolve stages won't complain. self.import_dummy_binding(*import, is_indeterminate); @@ -618,7 +617,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { import.root_id, import.root_span, "ambiguous glob re-exports", - BuiltinLintDiagnostics::AmbiguousGlobReexports { + BuiltinLintDiag::AmbiguousGlobReexports { name: key.ident.to_string(), namespace: key.ns.descr().to_string(), first_reexport_span: import.root_span, @@ -654,7 +653,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { binding_id, binding.span, "private item shadows public glob re-export", - BuiltinLintDiagnostics::HiddenGlobReexports { + BuiltinLintDiag::HiddenGlobReexports { name: key.ident.name.to_string(), namespace: key.ns.descr().to_owned(), glob_reexport_span: glob_binding.span, @@ -716,7 +715,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut diag, Some(err.span), candidates, - DiagnosticMode::Import, + DiagMode::Import { append: false }, (source != target) .then(|| format!(" as {target}")) .as_deref() @@ -728,7 +727,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut diag, None, candidates, - DiagnosticMode::Normal, + DiagMode::Normal, (source != target) .then(|| format!(" as {target}")) .as_deref() @@ -856,7 +855,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ImportKind::Single { target_bindings, .. } => target_bindings[TypeNS].get(), _ => None, }; - let prev_ambiguity_errors_len = self.ambiguity_errors.len(); + let ambiguity_errors_len = + |errors: &Vec>| errors.iter().filter(|error| !error.warning).count(); + let prev_ambiguity_errors_len = ambiguity_errors_len(&self.ambiguity_errors); let finalize = Finalize::with_root_span(import.root_id, import.span, import.root_span); // We'll provide more context to the privacy errors later, up to `len`. @@ -870,7 +871,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ignore_binding, ); - let no_ambiguity = self.ambiguity_errors.len() == prev_ambiguity_errors_len; + let no_ambiguity = + ambiguity_errors_len(&self.ambiguity_errors) == prev_ambiguity_errors_len; import.vis.set(orig_vis); let module = match path_res { PathResult::Module(module) => { @@ -1006,7 +1008,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { id, import.span, msg, - BuiltinLintDiagnostics::RedundantImportVisibility { + BuiltinLintDiag::RedundantImportVisibility { max_vis: max_vis.to_string(def_id, self.tcx), span: import.span, }, @@ -1334,9 +1336,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } let mut is_redundant = true; - let mut redundant_span = PerNS { value_ns: None, type_ns: None, macro_ns: None }; - self.per_ns(|this, ns| { if is_redundant && let Ok(binding) = source_bindings[ns].get() { if binding.res() == Res::Err { @@ -1373,7 +1373,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { id, import.span, format!("the item `{source}` is imported redundantly"), - BuiltinLintDiagnostics::RedundantImport(redundant_spans, source), + BuiltinLintDiag::RedundantImport(redundant_spans, source), ); } } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 85db8ba8618e1..d2aea0056b394 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -13,7 +13,7 @@ use crate::{Module, ModuleOrUniformRoot, NameBinding, ParentScope, PathResult}; use crate::{ResolutionError, Resolver, Segment, UseError}; use rustc_ast::ptr::P; -use rustc_ast::visit::{AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; +use rustc_ast::visit::{walk_list, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; use rustc_ast::*; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_errors::{ @@ -581,7 +581,7 @@ impl MaybeExported<'_> { } #[derive(Default)] -struct DiagnosticMetadata<'ast> { +struct DiagMetadata<'ast> { /// The current trait's associated items' ident, used for diagnostic suggestions. current_trait_assoc_items: Option<&'ast [P]>, @@ -674,7 +674,7 @@ struct LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { current_trait_ref: Option<(Module<'a>, TraitRef)>, /// Fields used to add information to diagnostic errors. - diagnostic_metadata: Box>, + diag_metadata: Box>, /// State used to know whether to ignore resolution errors for function bodies. /// @@ -694,12 +694,12 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, // as they do not correspond to actual code. } fn visit_item(&mut self, item: &'ast Item) { - let prev = replace(&mut self.diagnostic_metadata.current_item, Some(item)); + let prev = replace(&mut self.diag_metadata.current_item, Some(item)); // Always report errors in items we just entered. let old_ignore = replace(&mut self.in_func_body, false); self.with_lifetime_rib(LifetimeRibKind::Item, |this| this.resolve_item(item)); self.in_func_body = old_ignore; - self.diagnostic_metadata.current_item = prev; + self.diag_metadata.current_item = prev; } fn visit_arm(&mut self, arm: &'ast Arm) { self.resolve_arm(arm); @@ -716,10 +716,10 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, self.resolve_expr(expr, None); } fn visit_pat(&mut self, p: &'ast Pat) { - let prev = self.diagnostic_metadata.current_pat; - self.diagnostic_metadata.current_pat = Some(p); + let prev = self.diag_metadata.current_pat; + self.diag_metadata.current_pat = Some(p); visit::walk_pat(self, p); - self.diagnostic_metadata.current_pat = prev; + self.diag_metadata.current_pat = prev; } fn visit_local(&mut self, local: &'ast Local) { let local_spans = match local.pat.kind { @@ -731,13 +731,13 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, local.kind.init().map(|init| init.span), )), }; - let original = replace(&mut self.diagnostic_metadata.current_let_binding, local_spans); + let original = replace(&mut self.diag_metadata.current_let_binding, local_spans); self.resolve_local(local); - self.diagnostic_metadata.current_let_binding = original; + self.diag_metadata.current_let_binding = original; } fn visit_ty(&mut self, ty: &'ast Ty) { - let prev = self.diagnostic_metadata.current_trait_object; - let prev_ty = self.diagnostic_metadata.current_type_path; + let prev = self.diag_metadata.current_trait_object; + let prev_ty = self.diag_metadata.current_type_path; match &ty.kind { TyKind::Ref(None, _) => { // Elided lifetime in reference: we resolve as if there was some lifetime `'_` with @@ -748,7 +748,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, visit::walk_ty(self, ty); } TyKind::Path(qself, path) => { - self.diagnostic_metadata.current_type_path = Some(ty); + self.diag_metadata.current_type_path = Some(ty); self.smart_resolve_path(ty.id, qself, path, PathSource::Type); // Check whether we should interpret this as a bare trait object. @@ -795,7 +795,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, self.lifetime_elision_candidates = candidates; } TyKind::TraitObject(bounds, ..) => { - self.diagnostic_metadata.current_trait_object = Some(&bounds[..]); + self.diag_metadata.current_trait_object = Some(&bounds[..]); visit::walk_ty(self, ty) } TyKind::BareFn(bare_fn) => { @@ -842,8 +842,8 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, } _ => visit::walk_ty(self, ty), } - self.diagnostic_metadata.current_trait_object = prev; - self.diagnostic_metadata.current_type_path = prev_ty; + self.diag_metadata.current_trait_object = prev; + self.diag_metadata.current_type_path = prev_ty; } fn visit_poly_trait_ref(&mut self, tref: &'ast PolyTraitRef) { let span = tref.span.shrink_to_lo().to(tref.trait_ref.path.span.shrink_to_lo()); @@ -906,7 +906,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, } } fn visit_fn(&mut self, fn_kind: FnKind<'ast>, sp: Span, fn_id: NodeId) { - let previous_value = self.diagnostic_metadata.current_function; + let previous_value = self.diag_metadata.current_function; match fn_kind { // Bail if the function is foreign, and thus cannot validly have // a body, or if there's no body for some other reason. @@ -939,7 +939,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, return; } FnKind::Fn(..) => { - self.diagnostic_metadata.current_function = Some((fn_kind, sp)); + self.diag_metadata.current_function = Some((fn_kind, sp)); } // Do not update `current_function` for closures: it suggests `self` parameters. FnKind::Closure(..) => {} @@ -1040,17 +1040,14 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, } }) }); - self.diagnostic_metadata.current_function = previous_value; + self.diag_metadata.current_function = previous_value; } fn visit_lifetime(&mut self, lifetime: &'ast Lifetime, use_ctxt: visit::LifetimeCtxt) { self.resolve_lifetime(lifetime, use_ctxt) } fn visit_generics(&mut self, generics: &'ast Generics) { - self.visit_generic_params( - &generics.params, - self.diagnostic_metadata.current_self_item.is_some(), - ); + self.visit_generic_params(&generics.params, self.diag_metadata.current_self_item.is_some()); for p in &generics.where_clause.predicates { self.visit_where_predicate(p); } @@ -1062,7 +1059,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, ClosureBinder::For { generic_params, .. } => { self.visit_generic_params( generic_params, - self.diagnostic_metadata.current_self_item.is_some(), + self.diag_metadata.current_self_item.is_some(), ); } } @@ -1070,7 +1067,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, fn visit_generic_arg(&mut self, arg: &'ast GenericArg) { debug!("visit_generic_arg({:?})", arg); - let prev = replace(&mut self.diagnostic_metadata.currently_processing_generic_args, true); + let prev = replace(&mut self.diag_metadata.currently_processing_generic_args, true); match arg { GenericArg::Type(ref ty) => { // We parse const arguments as path types as we cannot distinguish them during @@ -1101,7 +1098,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, }, ); - self.diagnostic_metadata.currently_processing_generic_args = prev; + self.diag_metadata.currently_processing_generic_args = prev; return; } } @@ -1114,7 +1111,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, self.resolve_anon_const(ct, AnonConstKind::ConstArg(IsRepeatExpr::No)) } } - self.diagnostic_metadata.currently_processing_generic_args = prev; + self.diag_metadata.currently_processing_generic_args = prev; } fn visit_assoc_constraint(&mut self, constraint: &'ast AssocConstraint) { @@ -1192,8 +1189,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, fn visit_where_predicate(&mut self, p: &'ast WherePredicate) { debug!("visit_where_predicate {:?}", p); - let previous_value = - replace(&mut self.diagnostic_metadata.current_where_predicate, Some(p)); + let previous_value = replace(&mut self.diag_metadata.current_where_predicate, Some(p)); self.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| { if let WherePredicate::BoundPredicate(WhereBoundPredicate { ref bounded_ty, @@ -1224,7 +1220,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, visit::walk_where_predicate(this, p); } }); - self.diagnostic_metadata.current_where_predicate = previous_value; + self.diag_metadata.current_where_predicate = previous_value; } fn visit_inline_asm(&mut self, asm: &'ast InlineAsm) { @@ -1246,6 +1242,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, self.resolve_anon_const(anon_const, AnonConstKind::InlineConst); } InlineAsmOperand::Sym { sym } => self.visit_inline_asm_sym(sym), + InlineAsmOperand::Label { block } => self.visit_block(block), } } } @@ -1297,7 +1294,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { lifetime_ribs: Vec::new(), lifetime_elision_candidates: None, current_trait_ref: None, - diagnostic_metadata: Default::default(), + diag_metadata: Default::default(), // errors at module scope should always be reported in_func_body: false, lifetime_uses: Default::default(), @@ -1660,7 +1657,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { node_id, lifetime.ident.span, msg, - lint::BuiltinLintDiagnostics::AssociatedConstElidedLifetime { + lint::BuiltinLintDiag::AssociatedConstElidedLifetime { elided, span: lifetime.ident.span, }, @@ -1707,7 +1704,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { return; } LifetimeRibKind::ElisionFailure => { - self.diagnostic_metadata.current_elision_failures.push(missing_lifetime); + self.diag_metadata.current_elision_failures.push(missing_lifetime); self.record_lifetime_res(lifetime.id, LifetimeRes::Error, elision_candidate); return; } @@ -1911,7 +1908,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { break; } LifetimeRibKind::ElisionFailure => { - self.diagnostic_metadata.current_elision_failures.push(missing_lifetime); + self.diag_metadata.current_elision_failures.push(missing_lifetime); for id in node_ids { self.record_lifetime_res( id, @@ -1950,7 +1947,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { segment_id, elided_lifetime_span, "hidden lifetime parameters in types are deprecated", - lint::BuiltinLintDiagnostics::ElidedLifetimesInPaths( + lint::BuiltinLintDiag::ElidedLifetimesInPaths( expected_lifetimes, path_span, !segment.has_generic_args, @@ -2003,7 +2000,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { let elision_lifetime = self.resolve_fn_params(has_self, inputs); debug!(?elision_lifetime); - let outer_failures = take(&mut self.diagnostic_metadata.current_elision_failures); + let outer_failures = take(&mut self.diag_metadata.current_elision_failures); let output_rib = if let Ok(res) = elision_lifetime.as_ref() { self.r.lifetime_elision_allowed.insert(fn_id); LifetimeRibKind::Elided(*res) @@ -2012,7 +2009,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { }; self.with_lifetime_rib(output_rib, |this| visit::walk_fn_ret_ty(this, output_ty)); let elision_failures = - replace(&mut self.diagnostic_metadata.current_elision_failures, outer_failures); + replace(&mut self.diag_metadata.current_elision_failures, outer_failures); if !elision_failures.is_empty() { let Err(failure_info) = elision_lifetime else { bug!() }; self.report_missing_lifetime_specifiers(elision_failures, Some(failure_info)); @@ -2187,7 +2184,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } let impl_self = self - .diagnostic_metadata + .diag_metadata .current_self_type .as_ref() .and_then(|ty| { @@ -2385,7 +2382,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { items: ref impl_items, .. }) => { - self.diagnostic_metadata.current_impl_items = Some(impl_items); + self.diag_metadata.current_impl_items = Some(impl_items); self.resolve_implementation( &item.attrs, generics, @@ -2394,7 +2391,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { item.id, impl_items, ); - self.diagnostic_metadata.current_impl_items = None; + self.diag_metadata.current_impl_items = None; } ItemKind::Trait(box Trait { ref generics, ref bounds, ref items, .. }) => { @@ -2597,10 +2594,19 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { let span = *entry.get(); let err = ResolutionError::NameAlreadyUsedInParameterList(ident.name, span); self.report_error(param.ident.span, err); - if let GenericParamKind::Lifetime = param.kind { - // Record lifetime res, so lowering knows there is something fishy. - self.record_lifetime_param(param.id, LifetimeRes::Error); - } + let rib = match param.kind { + GenericParamKind::Lifetime => { + // Record lifetime res, so lowering knows there is something fishy. + self.record_lifetime_param(param.id, LifetimeRes::Error); + continue; + } + GenericParamKind::Type { .. } => &mut function_type_rib, + GenericParamKind::Const { .. } => &mut function_value_rib, + }; + + // Taint the resolution in case of errors to prevent follow up errors in typeck + self.r.record_partial_res(param.id, PartialRes::new(Res::Err)); + rib.bindings.insert(ident, Res::Err); continue; } Entry::Vacant(entry) => { @@ -2744,24 +2750,23 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { fn with_current_self_type(&mut self, self_type: &Ty, f: impl FnOnce(&mut Self) -> T) -> T { // Handle nested impls (inside fn bodies) let previous_value = - replace(&mut self.diagnostic_metadata.current_self_type, Some(self_type.clone())); + replace(&mut self.diag_metadata.current_self_type, Some(self_type.clone())); let result = f(self); - self.diagnostic_metadata.current_self_type = previous_value; + self.diag_metadata.current_self_type = previous_value; result } fn with_current_self_item(&mut self, self_item: &Item, f: impl FnOnce(&mut Self) -> T) -> T { - let previous_value = - replace(&mut self.diagnostic_metadata.current_self_item, Some(self_item.id)); + let previous_value = replace(&mut self.diag_metadata.current_self_item, Some(self_item.id)); let result = f(self); - self.diagnostic_metadata.current_self_item = previous_value; + self.diag_metadata.current_self_item = previous_value; result } /// When evaluating a `trait` use its associated types' idents for suggestions in E0412. fn resolve_trait_items(&mut self, trait_items: &'ast [P]) { let trait_assoc_items = - replace(&mut self.diagnostic_metadata.current_trait_assoc_items, Some(trait_items)); + replace(&mut self.diag_metadata.current_trait_assoc_items, Some(trait_items)); let walk_assoc_item = |this: &mut Self, generics: &Generics, kind, item: &'ast AssocItem| { @@ -2818,7 +2823,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { }; } - self.diagnostic_metadata.current_trait_assoc_items = trait_assoc_items; + self.diag_metadata.current_trait_assoc_items = trait_assoc_items; } /// This is called to resolve a trait reference from an `impl` (i.e., `impl Trait for Foo`). @@ -2832,7 +2837,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { let mut new_id = None; if let Some(trait_ref) = opt_trait_ref { let path: Vec<_> = Segment::from_path(&trait_ref.path); - self.diagnostic_metadata.currently_processing_impl_trait = + self.diag_metadata.currently_processing_impl_trait = Some((trait_ref.clone(), self_type.clone())); let res = self.smart_resolve_path_fragment( &None, @@ -2841,7 +2846,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { Finalize::new(trait_ref.ref_id, trait_ref.path.span), RecordPartialRes::Yes, ); - self.diagnostic_metadata.currently_processing_impl_trait = None; + self.diag_metadata.currently_processing_impl_trait = None; if let Some(def_id) = res.expect_full_res().opt_def_id() { new_id = Some(def_id); new_val = Some((self.r.expect_module(def_id), trait_ref.clone())); @@ -3117,7 +3122,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ); rustc_middle::ty::Visibility::Public }; - this.r.feed_visibility(this.r.local_def_id(id), vis); + this.r.feed_visibility(this.r.feed(id), vis); }; let Some(binding) = binding else { @@ -3737,7 +3742,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { let def_id = this.parent_scope.module.nearest_parent_mod(); let instead = res.is_some(); - let suggestion = if let Some((start, end)) = this.diagnostic_metadata.in_range + let suggestion = if let Some((start, end)) = this.diag_metadata.in_range && path[0].ident.span.lo() == end.span.lo() { let mut sugg = "."; @@ -3890,7 +3895,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ) { Ok(Some(partial_res)) if let Some(res) = partial_res.full_res() => { // if we also have an associated type that matches the ident, stash a suggestion - if let Some(items) = self.diagnostic_metadata.current_trait_assoc_items + if let Some(items) = self.diag_metadata.current_trait_assoc_items && let [Segment { ident, .. }] = path && items.iter().any(|item| { item.ident == *ident && matches!(item.kind, AssocItemKind::Type(_)) @@ -3958,6 +3963,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // Avoid recording definition of `A::B` in `::B::C`. self.r.record_partial_res(node_id, partial_res); self.resolve_elided_lifetimes_in_path(partial_res, path, source, path_span); + self.lint_unused_qualifications(path, ns, finalize); } partial_res @@ -4150,46 +4156,13 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { PathResult::Indeterminate => bug!("indeterminate path result in resolve_qpath"), }; - if path.iter().all(|seg| !seg.ident.span.from_expansion()) { - let end_pos = - path.iter().position(|seg| seg.has_generic_args).map_or(path.len(), |pos| pos + 1); - let unqualified = - path[..end_pos].iter().enumerate().skip(1).rev().find_map(|(i, seg)| { - // Preserve the current namespace for the final path segment, but use the type - // namespace for all preceding segments - // - // e.g. for `std::env::args` check the `ValueNS` for `args` but the `TypeNS` for - // `std` and `env` - // - // If the final path segment is beyond `end_pos` all the segments to check will - // use the type namespace - let ns = if i + 1 == path.len() { ns } else { TypeNS }; - let res = self.r.partial_res_map.get(&seg.id?)?.full_res()?; - let binding = self.resolve_ident_in_lexical_scope(seg.ident, ns, None, None)?; - - (res == binding.res()).then_some(seg) - }); - - if let Some(unqualified) = unqualified { - self.r.lint_buffer.buffer_lint_with_diagnostic( - lint::builtin::UNUSED_QUALIFICATIONS, - finalize.node_id, - finalize.path_span, - "unnecessary qualification", - lint::BuiltinLintDiagnostics::UnusedQualifications { - removal_span: finalize.path_span.until(unqualified.ident.span), - }, - ); - } - } - Ok(Some(result)) } fn with_resolved_label(&mut self, label: Option

(ptr: *const P) { + unsafe { transmute::<*const i32, usize>(&42i32) }; + unsafe { transmute::(issue_12402) }; + let _ = unsafe { transmute::<_, usize>(ptr) }; +} diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs index 92eb765e5f94e..cd1607b4c1999 100644 --- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs +++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs @@ -82,3 +82,10 @@ fn issue_10449() { let _x: u8 = unsafe { *std::mem::transmute::(f) }; } + +// Pointers cannot be cast to integers in const contexts +const fn issue_12402

(ptr: *const P) { + unsafe { transmute::<*const i32, usize>(&42i32) }; + unsafe { transmute::(issue_12402) }; + let _ = unsafe { transmute::<_, usize>(ptr) }; +} diff --git a/src/tools/clippy/tests/ui/type_complexity.rs b/src/tools/clippy/tests/ui/type_complexity.rs index be28ee2da0cd4..b057dc4e89f26 100644 --- a/src/tools/clippy/tests/ui/type_complexity.rs +++ b/src/tools/clippy/tests/ui/type_complexity.rs @@ -1,3 +1,5 @@ +//@compile-flags: -Zdeduplicate-diagnostics=yes + #![warn(clippy::all)] #![allow(unused, clippy::needless_pass_by_value, clippy::vec_box, clippy::useless_vec)] #![feature(associated_type_defaults)] diff --git a/src/tools/clippy/tests/ui/type_complexity.stderr b/src/tools/clippy/tests/ui/type_complexity.stderr index 9e27899e4f904..bfbab8647e85c 100644 --- a/src/tools/clippy/tests/ui/type_complexity.stderr +++ b/src/tools/clippy/tests/ui/type_complexity.stderr @@ -1,5 +1,5 @@ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:7:12 + --> tests/ui/type_complexity.rs:9:12 | LL | const CST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,85 +8,85 @@ LL | const CST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); = help: to override `-D warnings` add `#[allow(clippy::type_complexity)]` error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:10:12 + --> tests/ui/type_complexity.rs:12:12 | LL | static ST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:14:8 + --> tests/ui/type_complexity.rs:16:8 | LL | f: Vec>>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:18:11 + --> tests/ui/type_complexity.rs:20:11 | LL | struct Ts(Vec>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:22:11 + --> tests/ui/type_complexity.rs:24:11 | LL | Tuple(Vec>>), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:24:17 + --> tests/ui/type_complexity.rs:26:17 | LL | Struct { f: Vec>> }, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:29:14 + --> tests/ui/type_complexity.rs:31:14 | LL | const A: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:31:30 + --> tests/ui/type_complexity.rs:33:30 | LL | fn impl_method(&self, p: Vec>>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:36:14 + --> tests/ui/type_complexity.rs:38:14 | LL | const A: Vec>>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:38:14 + --> tests/ui/type_complexity.rs:40:14 | LL | type B = Vec>>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:40:25 + --> tests/ui/type_complexity.rs:42:25 | LL | fn method(&self, p: Vec>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:42:29 + --> tests/ui/type_complexity.rs:44:29 | LL | fn def_method(&self, p: Vec>>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:55:15 + --> tests/ui/type_complexity.rs:57:15 | LL | fn test1() -> Vec>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:60:14 + --> tests/ui/type_complexity.rs:62:14 | LL | fn test2(_x: Vec>>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:64:13 + --> tests/ui/type_complexity.rs:66:13 | LL | let _y: Vec>> = vec![]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/unknown_attribute.rs b/src/tools/clippy/tests/ui/unknown_attribute.rs index 932f284d5b713..3241742b5d464 100644 --- a/src/tools/clippy/tests/ui/unknown_attribute.rs +++ b/src/tools/clippy/tests/ui/unknown_attribute.rs @@ -1,3 +1,5 @@ +//@compile-flags: -Zdeduplicate-diagnostics=yes + #[clippy::unknown] //~^ ERROR: usage of unknown attribute #[clippy::cognitive_complexity = "1"] diff --git a/src/tools/clippy/tests/ui/unknown_attribute.stderr b/src/tools/clippy/tests/ui/unknown_attribute.stderr index d1f8eeb51aeac..b306abe0a9d1f 100644 --- a/src/tools/clippy/tests/ui/unknown_attribute.stderr +++ b/src/tools/clippy/tests/ui/unknown_attribute.stderr @@ -1,5 +1,5 @@ error: usage of unknown attribute - --> tests/ui/unknown_attribute.rs:1:11 + --> tests/ui/unknown_attribute.rs:3:11 | LL | #[clippy::unknown] | ^^^^^^^ diff --git a/src/tools/clippy/tests/ui/unnecessary_cast.fixed b/src/tools/clippy/tests/ui/unnecessary_cast.fixed index f52d325033987..288541362cddb 100644 --- a/src/tools/clippy/tests/ui/unnecessary_cast.fixed +++ b/src/tools/clippy/tests/ui/unnecessary_cast.fixed @@ -221,4 +221,10 @@ mod fixable { fn issue_9603() { let _: f32 = -0x400 as f32; } + + // Issue #11968: The suggestion for this lint removes the parentheses and leave the code as + // `*x.pow(2)` which tries to dereference the return value rather than `x`. + fn issue_11968(x: &usize) -> usize { + { *x }.pow(2) + } } diff --git a/src/tools/clippy/tests/ui/unnecessary_cast.rs b/src/tools/clippy/tests/ui/unnecessary_cast.rs index dfd8b454e6cca..eef3a42e35149 100644 --- a/src/tools/clippy/tests/ui/unnecessary_cast.rs +++ b/src/tools/clippy/tests/ui/unnecessary_cast.rs @@ -221,4 +221,10 @@ mod fixable { fn issue_9603() { let _: f32 = -0x400 as f32; } + + // Issue #11968: The suggestion for this lint removes the parentheses and leave the code as + // `*x.pow(2)` which tries to dereference the return value rather than `x`. + fn issue_11968(x: &usize) -> usize { + (*x as usize).pow(2) + } } diff --git a/src/tools/clippy/tests/ui/unnecessary_cast.stderr b/src/tools/clippy/tests/ui/unnecessary_cast.stderr index 935bb71da32bd..80fd5c13d8185 100644 --- a/src/tools/clippy/tests/ui/unnecessary_cast.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_cast.stderr @@ -241,5 +241,11 @@ error: casting to the same type is unnecessary (`f32` -> `f32`) LL | let _num = foo() as f32; | ^^^^^^^^^^^^ help: try: `foo()` -error: aborting due to 40 previous errors +error: casting to the same type is unnecessary (`usize` -> `usize`) + --> tests/ui/unnecessary_cast.rs:228:9 + | +LL | (*x as usize).pow(2) + | ^^^^^^^^^^^^^ help: try: `{ *x }` + +error: aborting due to 41 previous errors diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 8c50bcd5b613e..06d8f099c33fa 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -451,6 +451,15 @@ impl Config { self.target_cfg().panic == PanicStrategy::Unwind } + pub fn has_threads(&self) -> bool { + // Wasm targets don't have threads unless `-threads` is in the target + // name, such as `wasm32-wasip1-threads`. + if self.target.starts_with("wasm") { + return self.target.contains("threads"); + } + true + } + pub fn has_asm_support(&self) -> bool { static ASM_SUPPORTED_ARCHS: &[&str] = &[ "x86", "x86_64", "arm", "aarch64", "riscv32", diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 6de445a57830f..f15761354f7ab 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -787,6 +787,7 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[ "needs-sanitizer-shadow-call-stack", "needs-sanitizer-support", "needs-sanitizer-thread", + "needs-threads", "needs-unwind", "needs-xray", "no-prefer-dynamic", diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs index 3978658815053..d7c74038aea04 100644 --- a/src/tools/compiletest/src/header/needs.rs +++ b/src/tools/compiletest/src/header/needs.rs @@ -84,6 +84,11 @@ pub(super) fn handle_needs( condition: config.run_enabled(), ignore_reason: "ignored when running the resulting test binaries is disabled", }, + Need { + name: "needs-threads", + condition: config.has_threads(), + ignore_reason: "ignored on targets without threading support", + }, Need { name: "needs-unwind", condition: config.can_unwind(), diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index a01f71a68763b..815ac3839df82 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -533,6 +533,16 @@ fn wasm_special() { ("wasm32-wasi", "wasm32", true), ("wasm32-wasi", "wasm32-bare", false), ("wasm32-wasi", "wasi", true), + // NB: the wasm32-wasip1 target is new so this isn't tested for + // the bootstrap compiler. + #[cfg(not(bootstrap))] + ("wasm32-wasip1", "emscripten", false), + #[cfg(not(bootstrap))] + ("wasm32-wasip1", "wasm32", true), + #[cfg(not(bootstrap))] + ("wasm32-wasip1", "wasm32-bare", false), + #[cfg(not(bootstrap))] + ("wasm32-wasip1", "wasi", true), ("wasm64-unknown-unknown", "emscripten", false), ("wasm64-unknown-unknown", "wasm32", false), ("wasm64-unknown-unknown", "wasm32-bare", false), @@ -582,3 +592,23 @@ fn ignore_mode() { assert!(!check_ignore(&config, &format!("//@ ignore-mode-{other}"))); } } + +#[test] +fn threads_support() { + let threads = [ + ("x86_64-unknown-linux-gnu", true), + ("aarch64-apple-darwin", true), + ("wasm32-unknown-unknown", false), + ("wasm64-unknown-unknown", false), + #[cfg(not(bootstrap))] + ("wasm32-wasip1", false), + #[cfg(not(bootstrap))] + ("wasm32-wasip1-threads", true), + ("wasm32-wasi-preview1-threads", true), + ]; + for (target, has_threads) in threads { + let config = cfg().target(target).build(); + assert_eq!(config.has_threads(), has_threads); + assert_eq!(check_ignore(&config, "//@ needs-threads"), !has_threads) + } +} diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index 2f37a64576e4e..a9b5aa5f1efcc 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -342,6 +342,8 @@ fn main() { // (`install_ice_hook` might change `RUST_BACKTRACE`.) let env_snapshot = env::vars_os().collect::>(); + let args = rustc_driver::args::raw_args(&early_dcx).unwrap_or_else(|_| std::process::exit(rustc_driver::EXIT_FAILURE)); + // If the environment asks us to actually be rustc, then do that. if let Some(crate_kind) = env::var_os("MIRI_BE_RUSTC") { // Earliest rustc setup. @@ -359,7 +361,7 @@ fn main() { // We cannot use `rustc_driver::main` as we need to adjust the CLI arguments. run_compiler( - env::args().collect(), + args, target_crate, &mut MiriBeRustCompilerCalls { target_crate }, using_internal_features, @@ -382,7 +384,7 @@ fn main() { // If user has explicitly enabled/disabled isolation let mut isolation_enabled: Option = None; - for arg in env::args() { + for arg in args { if rustc_args.is_empty() { // Very first arg: binary name. rustc_args.push(arg); diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs index de0ed879b3666..4683965159d73 100644 --- a/src/tools/miri/src/diagnostics.rs +++ b/src/tools/miri/src/diagnostics.rs @@ -1,7 +1,7 @@ use std::fmt::{self, Write}; use std::num::NonZero; -use rustc_errors::{Diag, DiagnosticMessage, Level}; +use rustc_errors::{Diag, DiagMessage, Level}; use rustc_span::{SpanData, Symbol, DUMMY_SP}; use rustc_target::abi::{Align, Size}; @@ -95,7 +95,7 @@ impl fmt::Debug for TerminationInfo { } impl MachineStopType for TerminationInfo { - fn diagnostic_message(&self) -> DiagnosticMessage { + fn diagnostic_message(&self) -> DiagMessage { self.to_string().into() } fn add_args( diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 65260254ae25f..9e4b5fe8ad780 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -381,7 +381,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { f: ty::Instance<'tcx>, caller_abi: Abi, args: &[Immediate], - dest: Option<&PlaceTy<'tcx, Provenance>>, + dest: Option<&MPlaceTy<'tcx, Provenance>>, stack_pop: StackPopCleanup, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index d40f1c4525fc2..19d02c6f74620 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -8,7 +8,6 @@ use std::fmt; use std::path::Path; use std::process; -use either::Either; use rand::rngs::StdRng; use rand::Rng; use rand::SeedableRng; @@ -950,7 +949,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { instance: ty::Instance<'tcx>, abi: Abi, args: &[FnArg<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ret: Option, unwind: mir::UnwindAction, ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> { @@ -962,7 +961,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { // to run extra MIR), and Ok(Some(body)) if we found MIR to run for the // foreign function // Any needed call to `goto_block` will be performed by `emulate_foreign_item`. - let args = ecx.copy_fn_args(args)?; // FIXME: Should `InPlace` arguments be reset to uninit? + let args = ecx.copy_fn_args(args); // FIXME: Should `InPlace` arguments be reset to uninit? let link_name = ecx.item_link_name(instance.def_id()); return ecx.emulate_foreign_item(link_name, abi, &args, dest, ret, unwind); } @@ -977,11 +976,11 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { fn_val: DynSym, abi: Abi, args: &[FnArg<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ret: Option, unwind: mir::UnwindAction, ) -> InterpResult<'tcx> { - let args = ecx.copy_fn_args(args)?; // FIXME: Should `InPlace` arguments be reset to uninit? + let args = ecx.copy_fn_args(args); // FIXME: Should `InPlace` arguments be reset to uninit? ecx.emulate_dyn_sym(fn_val, abi, &args, dest, ret, unwind) } @@ -990,7 +989,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { ecx: &mut MiriInterpCx<'mir, 'tcx>, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ret: Option, unwind: mir::UnwindAction, ) -> InterpResult<'tcx> { @@ -1334,18 +1333,12 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { fn protect_in_place_function_argument( ecx: &mut InterpCx<'mir, 'tcx, Self>, - place: &PlaceTy<'tcx, Provenance>, + place: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx> { // If we have a borrow tracker, we also have it set up protection so that all reads *and // writes* during this call are insta-UB. let protected_place = if ecx.machine.borrow_tracker.is_some() { - // Have to do `to_op` first because a `Place::Local` doesn't imply the local doesn't have an address. - if let Either::Left(place) = ecx.place_to_op(place)?.as_mplace_or_imm() { - ecx.protect_place(&place)?.into() - } else { - // Locals that don't have their address taken are as protected as they can ever be. - place.clone() - } + ecx.protect_place(&place)?.into() } else { // No borrow tracker. place.clone() diff --git a/src/tools/miri/src/shims/backtrace.rs b/src/tools/miri/src/shims/backtrace.rs index 48dafc40c621c..abfa7143a73f6 100644 --- a/src/tools/miri/src/shims/backtrace.rs +++ b/src/tools/miri/src/shims/backtrace.rs @@ -12,7 +12,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { abi: Abi, link_name: Symbol, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); let [flags] = this.check_shim(abi, Abi::Rust, link_name, args)?; @@ -32,7 +32,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { abi: Abi, link_name: Symbol, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); let tcx = this.tcx; @@ -145,7 +145,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { abi: Abi, link_name: Symbol, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); let [ptr, flags] = this.check_shim(abi, Abi::Rust, link_name, args)?; @@ -174,7 +174,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // `lo.col` is 0-based - add 1 to make it 1-based for the caller. let colno: u32 = u32::try_from(lo.col.0.saturating_add(1)).unwrap_or(0); - let dest = this.force_allocation(dest)?; if let ty::Adt(adt, _) = dest.layout.ty.kind() { if !adt.repr().c() { throw_ub_format!( @@ -191,29 +190,29 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let filename_alloc = this.allocate_str(&filename, MiriMemoryKind::Rust.into(), Mutability::Mut)?; - this.write_immediate(name_alloc.to_ref(this), &this.project_field(&dest, 0)?)?; - this.write_immediate(filename_alloc.to_ref(this), &this.project_field(&dest, 1)?)?; + this.write_immediate(name_alloc.to_ref(this), &this.project_field(dest, 0)?)?; + this.write_immediate(filename_alloc.to_ref(this), &this.project_field(dest, 1)?)?; } 1 => { this.write_scalar( Scalar::from_target_usize(name.len().try_into().unwrap(), this), - &this.project_field(&dest, 0)?, + &this.project_field(dest, 0)?, )?; this.write_scalar( Scalar::from_target_usize(filename.len().try_into().unwrap(), this), - &this.project_field(&dest, 1)?, + &this.project_field(dest, 1)?, )?; } _ => throw_unsup_format!("unknown `miri_resolve_frame` flags {}", flags), } - this.write_scalar(Scalar::from_u32(lineno), &this.project_field(&dest, 2)?)?; - this.write_scalar(Scalar::from_u32(colno), &this.project_field(&dest, 3)?)?; + this.write_scalar(Scalar::from_u32(lineno), &this.project_field(dest, 2)?)?; + this.write_scalar(Scalar::from_u32(colno), &this.project_field(dest, 3)?)?; // Support a 4-field struct for now - this is deprecated // and slated for removal. if num_fields == 5 { - this.write_pointer(fn_ptr, &this.project_field(&dest, 4)?)?; + this.write_pointer(fn_ptr, &this.project_field(dest, 4)?)?; } Ok(()) diff --git a/src/tools/miri/src/shims/ffi_support.rs b/src/tools/miri/src/shims/ffi_support.rs index e628c44a86788..6da119e5fa8fb 100644 --- a/src/tools/miri/src/shims/ffi_support.rs +++ b/src/tools/miri/src/shims/ffi_support.rs @@ -70,7 +70,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn call_external_c_and_store_return<'a>( &mut self, link_name: Symbol, - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ptr: CodePtr, libffi_args: Vec>, ) -> InterpResult<'tcx, ()> { @@ -205,7 +205,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn call_external_c_fct( &mut self, link_name: Symbol, - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, args: &[OpTy<'tcx, Provenance>], ) -> InterpResult<'tcx, bool> { // Get the pointer to the function in the shared object file if it exists. diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 4ae607e98da8a..a25d377f3a722 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -57,7 +57,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ret: Option, unwind: mir::UnwindAction, ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> { @@ -123,7 +123,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // Second: functions that return immediately. match this.emulate_foreign_item_inner(link_name, abi, args, dest)? { EmulateForeignItemResult::NeedsJumping => { - trace!("{:?}", this.dump_place(dest)); + trace!("{:?}", this.dump_place(&dest.clone().into())); this.go_to_block(ret); } EmulateForeignItemResult::AlreadyJumped => (), @@ -149,7 +149,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { sym: DynSym, abi: Abi, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ret: Option, unwind: mir::UnwindAction, ) -> InterpResult<'tcx> { @@ -401,7 +401,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); @@ -1085,7 +1085,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let (op, op_len) = this.operand_to_simd(op)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, op_len); diff --git a/src/tools/miri/src/shims/intrinsics/atomic.rs b/src/tools/miri/src/shims/intrinsics/atomic.rs index 4d7f6a6b4e0e2..865886a7fc151 100644 --- a/src/tools/miri/src/shims/intrinsics/atomic.rs +++ b/src/tools/miri/src/shims/intrinsics/atomic.rs @@ -18,7 +18,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { &mut self, intrinsic_name: &str, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); @@ -124,7 +124,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { fn atomic_load( &mut self, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, atomic: AtomicReadOrd, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); @@ -181,7 +181,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { fn atomic_rmw_op( &mut self, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, atomic_op: AtomicOp, atomic: AtomicRwOrd, ) -> InterpResult<'tcx> { @@ -223,7 +223,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { fn atomic_exchange( &mut self, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, atomic: AtomicRwOrd, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); @@ -240,7 +240,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { fn atomic_compare_exchange_impl( &mut self, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, success: AtomicRwOrd, fail: AtomicReadOrd, can_fail_spuriously: bool, @@ -269,7 +269,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { fn atomic_compare_exchange( &mut self, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, success: AtomicRwOrd, fail: AtomicReadOrd, ) -> InterpResult<'tcx> { @@ -279,7 +279,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { fn atomic_compare_exchange_weak( &mut self, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, success: AtomicRwOrd, fail: AtomicReadOrd, ) -> InterpResult<'tcx> { diff --git a/src/tools/miri/src/shims/intrinsics/mod.rs b/src/tools/miri/src/shims/intrinsics/mod.rs index b67d588dbc9be..46f0c771cb51c 100644 --- a/src/tools/miri/src/shims/intrinsics/mod.rs +++ b/src/tools/miri/src/shims/intrinsics/mod.rs @@ -23,7 +23,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { &mut self, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ret: Option, _unwind: mir::UnwindAction, ) -> InterpResult<'tcx> { @@ -61,7 +61,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // The rest jumps to `ret` immediately. this.emulate_intrinsic_by_name(intrinsic_name, instance.args, args, dest)?; - trace!("{:?}", this.dump_place(dest)); + trace!("{:?}", this.dump_place(&dest.clone().into())); this.go_to_block(ret); Ok(()) } @@ -72,7 +72,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { intrinsic_name: &str, generic_args: ty::GenericArgsRef<'tcx>, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); diff --git a/src/tools/miri/src/shims/intrinsics/simd.rs b/src/tools/miri/src/shims/intrinsics/simd.rs index bb18fba5c98aa..ddddcdcebd2af 100644 --- a/src/tools/miri/src/shims/intrinsics/simd.rs +++ b/src/tools/miri/src/shims/intrinsics/simd.rs @@ -21,7 +21,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { intrinsic_name: &str, generic_args: ty::GenericArgsRef<'tcx>, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); match intrinsic_name { @@ -40,7 +40,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { => { let [op] = check_arg_count(args)?; let (op, op_len) = this.operand_to_simd(op)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, op_len); @@ -167,7 +167,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let [left, right] = check_arg_count(args)?; let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, left_len); assert_eq!(dest_len, right_len); @@ -255,7 +255,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let (a, a_len) = this.operand_to_simd(a)?; let (b, b_len) = this.operand_to_simd(b)?; let (c, c_len) = this.operand_to_simd(c)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, a_len); assert_eq!(dest_len, b_len); @@ -390,7 +390,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let (mask, mask_len) = this.operand_to_simd(mask)?; let (yes, yes_len) = this.operand_to_simd(yes)?; let (no, no_len) = this.operand_to_simd(no)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, mask_len); assert_eq!(dest_len, yes_len); @@ -411,7 +411,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let [mask, yes, no] = check_arg_count(args)?; let (yes, yes_len) = this.operand_to_simd(yes)?; let (no, no_len) = this.operand_to_simd(no)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; let bitmask_len = dest_len.next_multiple_of(8); // The mask must be an integer or an array. @@ -487,7 +487,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "cast" | "as" | "cast_ptr" | "expose_addr" | "from_exposed_addr" => { let [op] = check_arg_count(args)?; let (op, op_len) = this.operand_to_simd(op)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, op_len); @@ -545,7 +545,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let [left, right] = check_arg_count(args)?; let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; let index = generic_args[2] .expect_const() @@ -582,7 +582,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let [left, right, index] = check_arg_count(args)?; let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; // `index` is an array, not a SIMD type let ty::Array(_, index_len) = index.layout.ty.kind() else { @@ -623,7 +623,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let (passthru, passthru_len) = this.operand_to_simd(passthru)?; let (ptrs, ptrs_len) = this.operand_to_simd(ptrs)?; let (mask, mask_len) = this.operand_to_simd(mask)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, passthru_len); assert_eq!(dest_len, ptrs_len); @@ -669,7 +669,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let (mask, mask_len) = this.operand_to_simd(mask)?; let ptr = this.read_pointer(ptr)?; let (default, default_len) = this.operand_to_simd(default)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, mask_len); assert_eq!(dest_len, default_len); diff --git a/src/tools/miri/src/shims/panic.rs b/src/tools/miri/src/shims/panic.rs index 65b5838cd1437..34b6481dd387d 100644 --- a/src/tools/miri/src/shims/panic.rs +++ b/src/tools/miri/src/shims/panic.rs @@ -28,7 +28,7 @@ pub struct CatchUnwindData<'tcx> { /// The `data` argument for that callback. data: Scalar, /// The return place from the original call to `try`. - dest: PlaceTy<'tcx, Provenance>, + dest: MPlaceTy<'tcx, Provenance>, /// The return block from the original call to `try`. ret: mir::BasicBlock, } @@ -72,7 +72,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn handle_catch_unwind( &mut self, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ret: mir::BasicBlock, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index b5cd18396a286..4ceda80935047 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -44,7 +44,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); diff --git a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs index 64094ac307d2a..6814e0d428325 100644 --- a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs @@ -17,7 +17,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); match link_name.as_str() { diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs index b9215129674b0..d13ada0f4cf00 100644 --- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs @@ -24,7 +24,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); @@ -228,7 +228,7 @@ fn getrandom<'tcx>( ptr: &OpTy<'tcx, Provenance>, len: &OpTy<'tcx, Provenance>, flags: &OpTy<'tcx, Provenance>, - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx> { let ptr = this.read_pointer(ptr)?; let len = this.read_target_usize(len)?; diff --git a/src/tools/miri/src/shims/unix/linux/sync.rs b/src/tools/miri/src/shims/unix/linux/sync.rs index 66105391c475a..ed27066aa6a0f 100644 --- a/src/tools/miri/src/shims/unix/linux/sync.rs +++ b/src/tools/miri/src/shims/unix/linux/sync.rs @@ -8,7 +8,7 @@ use crate::*; pub fn futex<'tcx>( this: &mut MiriInterpCx<'_, 'tcx>, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx> { // The amount of arguments used depends on the type of futex operation. // The full futex syscall takes six arguments (excluding the syscall @@ -179,7 +179,7 @@ pub fn futex<'tcx>( struct Callback<'tcx> { thread: ThreadId, addr_usize: u64, - dest: PlaceTy<'tcx, Provenance>, + dest: MPlaceTy<'tcx, Provenance>, } impl<'tcx> VisitProvenance for Callback<'tcx> { diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs index ecc07e28a2988..3af01eb44d8a4 100644 --- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs @@ -17,7 +17,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs index 054e9719b34a4..dd301f9ee6d36 100644 --- a/src/tools/miri/src/shims/unix/sync.rs +++ b/src/tools/miri/src/shims/unix/sync.rs @@ -843,7 +843,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { cond_op: &OpTy<'tcx, Provenance>, mutex_op: &OpTy<'tcx, Provenance>, abstime_op: &OpTy<'tcx, Provenance>, - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); @@ -883,7 +883,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { active_thread: ThreadId, mutex_id: MutexId, id: CondvarId, - dest: PlaceTy<'tcx, Provenance>, + dest: MPlaceTy<'tcx, Provenance>, } impl<'tcx> VisitProvenance for Callback<'tcx> { diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs index 734737a86dd58..9e0baf86cbcf6 100644 --- a/src/tools/miri/src/shims/windows/foreign_items.rs +++ b/src/tools/miri/src/shims/windows/foreign_items.rs @@ -27,7 +27,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); @@ -366,6 +366,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.WakeByAddressSingle(ptr_op)?; } + "WakeByAddressAll" => { + let [ptr_op] = + this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; + + this.WakeByAddressAll(ptr_op)?; + } // Dynamic symbol loading "GetProcAddress" => { diff --git a/src/tools/miri/src/shims/windows/sync.rs b/src/tools/miri/src/shims/windows/sync.rs index 2b9801fea68e6..c0a79e959a6be 100644 --- a/src/tools/miri/src/shims/windows/sync.rs +++ b/src/tools/miri/src/shims/windows/sync.rs @@ -201,7 +201,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // When we are woken up, set the `pending` flag accordingly. struct Callback<'tcx> { init_once_id: InitOnceId, - pending_place: PlaceTy<'tcx, Provenance>, + pending_place: MPlaceTy<'tcx, Provenance>, } impl<'tcx> VisitProvenance for Callback<'tcx> { @@ -290,7 +290,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { compare_op: &OpTy<'tcx, Provenance>, size_op: &OpTy<'tcx, Provenance>, timeout_op: &OpTy<'tcx, Provenance>, - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); @@ -334,7 +334,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { struct Callback<'tcx> { thread: ThreadId, addr: u64, - dest: PlaceTy<'tcx, Provenance>, + dest: MPlaceTy<'tcx, Provenance>, } impl<'tcx> VisitProvenance for Callback<'tcx> { @@ -384,6 +384,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { Ok(()) } + fn WakeByAddressAll(&mut self, ptr_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx> { + let this = self.eval_context_mut(); + + let ptr = this.read_pointer(ptr_op)?; + + // See the Linux futex implementation for why this fence exists. + this.atomic_fence(AtomicFenceOrd::SeqCst)?; + + while let Some(thread) = this.futex_wake(ptr.addr().bytes(), u32::MAX) { + this.unblock_thread(thread); + this.unregister_timeout_callback_if_exists(thread); + } + + Ok(()) + } fn SleepConditionVariableSRW( &mut self, @@ -391,7 +406,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { lock_op: &OpTy<'tcx, Provenance>, timeout_op: &OpTy<'tcx, Provenance>, flags_op: &OpTy<'tcx, Provenance>, - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); @@ -438,7 +453,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { condvar_id: CondvarId, lock_id: RwLockId, mode: RwLockMode, - dest: PlaceTy<'tcx, Provenance>, + dest: MPlaceTy<'tcx, Provenance>, } impl<'tcx> VisitProvenance for Callback<'tcx> { diff --git a/src/tools/miri/src/shims/x86/aesni.rs b/src/tools/miri/src/shims/x86/aesni.rs index fb0b701512708..6c090d877ea3e 100644 --- a/src/tools/miri/src/shims/x86/aesni.rs +++ b/src/tools/miri/src/shims/x86/aesni.rs @@ -15,7 +15,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); this.expect_target_feature_for_intrinsic(link_name, "aes")?; @@ -138,7 +138,7 @@ fn aes_round<'tcx>( this: &mut crate::MiriInterpCx<'_, 'tcx>, state: &OpTy<'tcx, Provenance>, key: &OpTy<'tcx, Provenance>, - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, f: impl Fn(u128, u128) -> u128, ) -> InterpResult<'tcx, ()> { assert_eq!(dest.layout.size, state.layout.size); diff --git a/src/tools/miri/src/shims/x86/avx.rs b/src/tools/miri/src/shims/x86/avx.rs index 65de1607595be..23c78647b9c46 100644 --- a/src/tools/miri/src/shims/x86/avx.rs +++ b/src/tools/miri/src/shims/x86/avx.rs @@ -21,7 +21,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); this.expect_target_feature_for_intrinsic(link_name, "avx")?; @@ -164,7 +164,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let (data, data_len) = this.operand_to_simd(data)?; let (control, control_len) = this.operand_to_simd(control)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, data_len); assert_eq!(dest_len, control_len); @@ -199,7 +199,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let (data, data_len) = this.operand_to_simd(data)?; let (control, control_len) = this.operand_to_simd(control)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, data_len); assert_eq!(dest_len, control_len); @@ -354,10 +354,10 @@ fn mask_load<'tcx>( this: &mut crate::MiriInterpCx<'_, 'tcx>, ptr: &OpTy<'tcx, Provenance>, mask: &OpTy<'tcx, Provenance>, - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, ()> { let (mask, mask_len) = this.operand_to_simd(mask)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, mask_len); diff --git a/src/tools/miri/src/shims/x86/mod.rs b/src/tools/miri/src/shims/x86/mod.rs index 9cfee20014fc1..7cd397625dca6 100644 --- a/src/tools/miri/src/shims/x86/mod.rs +++ b/src/tools/miri/src/shims/x86/mod.rs @@ -29,7 +29,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); // Prefix should have already been checked. @@ -286,11 +286,11 @@ fn bin_op_simd_float_first<'tcx, F: rustc_apfloat::Float>( which: FloatBinOp, left: &OpTy<'tcx, Provenance>, right: &OpTy<'tcx, Provenance>, - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, ()> { let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, left_len); assert_eq!(dest_len, right_len); @@ -317,11 +317,11 @@ fn bin_op_simd_float_all<'tcx, F: rustc_apfloat::Float>( which: FloatBinOp, left: &OpTy<'tcx, Provenance>, right: &OpTy<'tcx, Provenance>, - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, ()> { let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, left_len); assert_eq!(dest_len, right_len); @@ -414,10 +414,10 @@ fn unary_op_ss<'tcx>( this: &mut crate::MiriInterpCx<'_, 'tcx>, which: FloatUnaryOp, op: &OpTy<'tcx, Provenance>, - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, ()> { let (op, op_len) = this.operand_to_simd(op)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, op_len); @@ -437,10 +437,10 @@ fn unary_op_ps<'tcx>( this: &mut crate::MiriInterpCx<'_, 'tcx>, which: FloatUnaryOp, op: &OpTy<'tcx, Provenance>, - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, ()> { let (op, op_len) = this.operand_to_simd(op)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, op_len); @@ -462,11 +462,11 @@ fn round_first<'tcx, F: rustc_apfloat::Float>( left: &OpTy<'tcx, Provenance>, right: &OpTy<'tcx, Provenance>, rounding: &OpTy<'tcx, Provenance>, - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, ()> { let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, left_len); assert_eq!(dest_len, right_len); @@ -492,10 +492,10 @@ fn round_all<'tcx, F: rustc_apfloat::Float>( this: &mut crate::MiriInterpCx<'_, 'tcx>, op: &OpTy<'tcx, Provenance>, rounding: &OpTy<'tcx, Provenance>, - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, ()> { let (op, op_len) = this.operand_to_simd(op)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, op_len); @@ -544,10 +544,10 @@ fn convert_float_to_int<'tcx>( this: &mut crate::MiriInterpCx<'_, 'tcx>, op: &OpTy<'tcx, Provenance>, rnd: rustc_apfloat::Round, - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, ()> { let (op, op_len) = this.operand_to_simd(op)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; // Output must be *signed* integers. assert!(matches!(dest.layout.field(this, 0).ty.kind(), ty::Int(_))); @@ -587,7 +587,7 @@ fn split_simd_to_128bit_chunks<'tcx>( this: &mut crate::MiriInterpCx<'_, 'tcx>, left: &OpTy<'tcx, Provenance>, right: &OpTy<'tcx, Provenance>, - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult< 'tcx, (u64, u64, MPlaceTy<'tcx, Provenance>, MPlaceTy<'tcx, Provenance>, MPlaceTy<'tcx, Provenance>), @@ -597,7 +597,7 @@ fn split_simd_to_128bit_chunks<'tcx>( let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, left_len); assert_eq!(dest_len, right_len); @@ -636,7 +636,7 @@ fn horizontal_bin_op<'tcx>( saturating: bool, left: &OpTy<'tcx, Provenance>, right: &OpTy<'tcx, Provenance>, - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, ()> { let (num_chunks, items_per_chunk, left, right, dest) = split_simd_to_128bit_chunks(this, left, right, dest)?; @@ -684,7 +684,7 @@ fn conditional_dot_product<'tcx>( left: &OpTy<'tcx, Provenance>, right: &OpTy<'tcx, Provenance>, imm: &OpTy<'tcx, Provenance>, - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, ()> { let (num_chunks, items_per_chunk, left, right, dest) = split_simd_to_128bit_chunks(this, left, right, dest)?; diff --git a/src/tools/miri/src/shims/x86/sse.rs b/src/tools/miri/src/shims/x86/sse.rs index da0db92738faf..b8c0dfb1c7f02 100644 --- a/src/tools/miri/src/shims/x86/sse.rs +++ b/src/tools/miri/src/shims/x86/sse.rs @@ -19,7 +19,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); this.expect_target_feature_for_intrinsic(link_name, "sse")?; @@ -198,7 +198,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let (left, left_len) = this.operand_to_simd(left)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, left_len); diff --git a/src/tools/miri/src/shims/x86/sse2.rs b/src/tools/miri/src/shims/x86/sse2.rs index b34b93e373900..18ff5d809e322 100644 --- a/src/tools/miri/src/shims/x86/sse2.rs +++ b/src/tools/miri/src/shims/x86/sse2.rs @@ -17,7 +17,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); this.expect_target_feature_for_intrinsic(link_name, "sse2")?; @@ -46,7 +46,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(left_len, right_len); assert_eq!(dest_len.checked_mul(2).unwrap(), left_len); @@ -85,7 +85,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; // left and right are u8x16, dest is u64x2 assert_eq!(left_len, right_len); @@ -122,7 +122,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, left_len); assert_eq!(dest_len, right_len); @@ -172,7 +172,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, left_len); assert_eq!(dest_len, right_len); @@ -223,7 +223,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, left_len); assert_eq!(dest_len, right_len); @@ -306,7 +306,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; // left and right are i16x8, dest is i8x16 assert_eq!(left_len, 8); @@ -337,7 +337,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; // left and right are i16x8, dest is u8x16 assert_eq!(left_len, 8); @@ -367,7 +367,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; // left and right are i32x4, dest is i16x8 assert_eq!(left_len, 4); @@ -430,7 +430,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let (op, op_len) = this.operand_to_simd(op)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, op_len); @@ -449,7 +449,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let (op, op_len) = this.operand_to_simd(op)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, op_len); @@ -563,7 +563,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let (left, left_len) = this.operand_to_simd(left)?; let (right, _) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, left_len); diff --git a/src/tools/miri/src/shims/x86/sse3.rs b/src/tools/miri/src/shims/x86/sse3.rs index 99a7a4f2f88ab..5ac30dca79a2f 100644 --- a/src/tools/miri/src/shims/x86/sse3.rs +++ b/src/tools/miri/src/shims/x86/sse3.rs @@ -15,7 +15,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); this.expect_target_feature_for_intrinsic(link_name, "sse3")?; diff --git a/src/tools/miri/src/shims/x86/sse41.rs b/src/tools/miri/src/shims/x86/sse41.rs index 32b1fe43c5837..16a82eed99b07 100644 --- a/src/tools/miri/src/shims/x86/sse41.rs +++ b/src/tools/miri/src/shims/x86/sse41.rs @@ -14,7 +14,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); this.expect_target_feature_for_intrinsic(link_name, "sse4.1")?; @@ -34,7 +34,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, left_len); assert_eq!(dest_len, right_len); @@ -70,7 +70,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(left_len, right_len); assert_eq!(dest_len, left_len.checked_mul(2).unwrap()); @@ -142,7 +142,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let (op, op_len) = this.operand_to_simd(op)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; // Find minimum let mut min_value = u16::MAX; @@ -178,7 +178,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(left_len, right_len); assert_eq!(left_len, dest_len.checked_mul(2).unwrap()); diff --git a/src/tools/miri/src/shims/x86/ssse3.rs b/src/tools/miri/src/shims/x86/ssse3.rs index 724150fd2fe2d..dd5d064b20fe2 100644 --- a/src/tools/miri/src/shims/x86/ssse3.rs +++ b/src/tools/miri/src/shims/x86/ssse3.rs @@ -15,7 +15,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); this.expect_target_feature_for_intrinsic(link_name, "ssse3")?; @@ -29,7 +29,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let (op, op_len) = this.operand_to_simd(op)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(op_len, dest_len); @@ -52,7 +52,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, left_len); assert_eq!(dest_len, right_len); @@ -102,7 +102,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(left_len, right_len); assert_eq!(dest_len.checked_mul(2).unwrap(), left_len); @@ -138,7 +138,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, left_len); assert_eq!(dest_len, right_len); @@ -172,7 +172,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, left_len); assert_eq!(dest_len, right_len); diff --git a/src/tools/miri/tests/compiletest.rs b/src/tools/miri/tests/compiletest.rs index 9f46772456518..db0768848fd37 100644 --- a/src/tools/miri/tests/compiletest.rs +++ b/src/tools/miri/tests/compiletest.rs @@ -81,8 +81,10 @@ fn test_config(target: &str, path: &str, mode: Mode, with_dependencies: bool) -> // Add a test env var to do environment communication tests. program.envs.push(("MIRI_ENV_VAR_TEST".into(), Some("0".into()))); + // Let the tests know where to store temp files (they might run for a different target, which can make this hard to find). - program.envs.push(("MIRI_TEMP".into(), Some(env::temp_dir().into()))); + let miri_temp = env::var_os("MIRI_TEMP").unwrap_or_else(|| env::temp_dir().into()); + program.envs.push(("MIRI_TEMP".into(), Some(miri_temp))); let mut config = Config { target: Some(target.to_owned()), diff --git a/src/tools/miri/tests/pass/shims/fs.rs b/src/tools/miri/tests/pass/shims/fs.rs index 6ba39c1f563f9..304a178dc3404 100644 --- a/src/tools/miri/tests/pass/shims/fs.rs +++ b/src/tools/miri/tests/pass/shims/fs.rs @@ -1,6 +1,10 @@ //@ignore-target-windows: File handling is not implemented yet //@compile-flags: -Zmiri-disable-isolation +// If this test is failing for you locally, you can try +// 1. Deleting the files `/tmp/miri_*` +// 2. Setting `MIRI_TEMP` or `TMPDIR` to a different directory, without the `miri_*` files + #![feature(io_error_more)] #![feature(io_error_uncategorized)] diff --git a/src/tools/opt-dist/src/utils/artifact_size.rs b/src/tools/opt-dist/src/utils/artifact_size.rs index eb1f6bcf21df8..b6c453fb40bd3 100644 --- a/src/tools/opt-dist/src/utils/artifact_size.rs +++ b/src/tools/opt-dist/src/utils/artifact_size.rs @@ -16,7 +16,7 @@ pub fn print_binary_sizes(env: &Environment) -> anyhow::Result<()> { let root = env.build_artifacts().join("stage2"); let mut files = get_files_from_dir(&root.join("bin"), None)?; - files.extend(get_files_from_dir(&root.join("lib"), Some(".so"))?); + files.extend(get_files_from_dir(&root.join("lib"), None)?); files.sort_unstable(); let items: Vec<_> = files diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs index be1c8d9094bfb..a1be60180838c 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs @@ -1,5 +1,6 @@ //! Compute the binary representation of a type +use std::borrow::Cow; use std::fmt; use base_db::salsa::Cycle; @@ -114,8 +115,8 @@ struct LayoutCx<'a> { impl<'a> LayoutCalculator for LayoutCx<'a> { type TargetDataLayoutRef = &'a TargetDataLayout; - fn delayed_bug(&self, txt: String) { - never!("{}", txt); + fn delayed_bug(&self, txt: impl Into>) { + never!("{}", txt.into()); } fn current_data_layout(&self) -> &'a TargetDataLayout { diff --git a/src/tools/rustfmt/src/comment.rs b/src/tools/rustfmt/src/comment.rs index f7cd7cefb3d69..7d1b0384431be 100644 --- a/src/tools/rustfmt/src/comment.rs +++ b/src/tools/rustfmt/src/comment.rs @@ -1721,10 +1721,10 @@ pub(crate) fn recover_comment_removed( // We missed some comments. Warn and keep the original text. if context.config.error_on_unformatted() { context.report.append( - context.parse_sess.span_to_filename(span), + context.psess.span_to_filename(span), vec![FormattingError::from_span( span, - context.parse_sess, + context.psess, ErrorKind::LostComment, )], ); diff --git a/src/tools/rustfmt/src/formatting.rs b/src/tools/rustfmt/src/formatting.rs index 1c64921b1a68d..3bcb4d15184a1 100644 --- a/src/tools/rustfmt/src/formatting.rs +++ b/src/tools/rustfmt/src/formatting.rs @@ -79,7 +79,7 @@ fn should_skip_module( // FIXME(calebcartwright) - we need to determine how we'll handle the // `format_generated_files` option with stdin based input. if !input_is_stdin && !config.format_generated_files() { - let source_file = context.parse_session.span_to_file_contents(module.span); + let source_file = context.psess.span_to_file_contents(module.span); let src = source_file.src.as_ref().expect("SourceFile without src"); if is_generated_file(src) { @@ -109,8 +109,8 @@ fn format_project( let main_file = input.file_name(); let input_is_stdin = main_file == FileName::Stdin; - let parse_session = ParseSess::new(config)?; - if config.skip_children() && parse_session.ignore_file(&main_file) { + let psess = ParseSess::new(config)?; + if config.skip_children() && psess.ignore_file(&main_file) { return Ok(FormatReport::new()); } @@ -118,7 +118,7 @@ fn format_project( let mut report = FormatReport::new(); let directory_ownership = input.to_directory_ownership(); - let krate = match Parser::parse_crate(input, &parse_session) { + let krate = match Parser::parse_crate(input, &psess) { Ok(krate) => krate, // Surface parse error via Session (errors are merged there from report) Err(e) => { @@ -131,9 +131,9 @@ fn format_project( } }; - let mut context = FormatContext::new(&krate, report, parse_session, config, handler); + let mut context = FormatContext::new(&krate, report, psess, config, handler); let files = modules::ModResolver::new( - &context.parse_session, + &context.psess, directory_ownership.unwrap_or(DirectoryOwnership::UnownedViaBlock), !input_is_stdin && !config.skip_children(), ) @@ -148,16 +148,11 @@ fn format_project( timer = timer.done_parsing(); // Suppress error output if we have to do any further parsing. - context.parse_session.set_silent_emitter(); + context.psess.set_silent_emitter(); for (path, module) in files { if input_is_stdin && contains_skip(module.attrs()) { - return echo_back_stdin( - context - .parse_session - .snippet_provider(module.span) - .entire_snippet(), - ); + return echo_back_stdin(context.psess.snippet_provider(module.span).entire_snippet()); } should_emit_verbose(input_is_stdin, config, || println!("Formatting {}", path)); context.format_file(path, &module, is_macro_def)?; @@ -179,7 +174,7 @@ fn format_project( struct FormatContext<'a, T: FormatHandler> { krate: &'a ast::Crate, report: FormatReport, - parse_session: ParseSess, + psess: ParseSess, config: &'a Config, handler: &'a mut T, } @@ -188,21 +183,21 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { fn new( krate: &'a ast::Crate, report: FormatReport, - parse_session: ParseSess, + psess: ParseSess, config: &'a Config, handler: &'a mut T, ) -> Self { FormatContext { krate, report, - parse_session, + psess, config, handler, } } fn ignore_file(&self, path: &FileName) -> bool { - self.parse_session.ignore_file(path) + self.psess.ignore_file(path) } // Formats a single file/module. @@ -212,9 +207,9 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { module: &Module<'_>, is_macro_def: bool, ) -> Result<(), ErrorKind> { - let snippet_provider = self.parse_session.snippet_provider(module.span); - let mut visitor = FmtVisitor::from_parse_sess( - &self.parse_session, + let snippet_provider = self.psess.snippet_provider(module.span); + let mut visitor = FmtVisitor::from_psess( + &self.psess, self.config, &snippet_provider, self.report.clone(), @@ -257,7 +252,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { .add_non_formatted_ranges(visitor.skipped_range.borrow().clone()); self.handler.handle_formatted_file( - &self.parse_session, + &self.psess, path, visitor.buffer.to_owned(), &mut self.report, @@ -269,7 +264,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { trait FormatHandler { fn handle_formatted_file( &mut self, - parse_session: &ParseSess, + psess: &ParseSess, path: FileName, result: String, report: &mut FormatReport, @@ -280,14 +275,14 @@ impl<'b, T: Write + 'b> FormatHandler for Session<'b, T> { // Called for each formatted file. fn handle_formatted_file( &mut self, - parse_session: &ParseSess, + psess: &ParseSess, path: FileName, result: String, report: &mut FormatReport, ) -> Result<(), ErrorKind> { if let Some(ref mut out) = self.out { match source_file::write_file( - Some(parse_session), + Some(psess), &path, &result, out, @@ -318,17 +313,13 @@ pub(crate) struct FormattingError { } impl FormattingError { - pub(crate) fn from_span( - span: Span, - parse_sess: &ParseSess, - kind: ErrorKind, - ) -> FormattingError { + pub(crate) fn from_span(span: Span, psess: &ParseSess, kind: ErrorKind) -> FormattingError { FormattingError { - line: parse_sess.line_of_byte_pos(span.lo()), + line: psess.line_of_byte_pos(span.lo()), is_comment: kind.is_comment(), kind, is_string: false, - line_buffer: parse_sess.span_to_first_line_string(span), + line_buffer: psess.span_to_first_line_string(span), } } diff --git a/src/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs index b4c58d2fefb10..8d77d2b32542d 100644 --- a/src/tools/rustfmt/src/macros.rs +++ b/src/tools/rustfmt/src/macros.rs @@ -136,8 +136,8 @@ fn return_macro_parse_failure_fallback( } context.skipped_range.borrow_mut().push(( - context.parse_sess.line_of_byte_pos(span.lo()), - context.parse_sess.line_of_byte_pos(span.hi()), + context.psess.line_of_byte_pos(span.lo()), + context.psess.line_of_byte_pos(span.hi()), )); // Return the snippet unmodified if the macro is not block-like diff --git a/src/tools/rustfmt/src/missed_spans.rs b/src/tools/rustfmt/src/missed_spans.rs index 28edcb784b40e..b1a7769c21bf4 100644 --- a/src/tools/rustfmt/src/missed_spans.rs +++ b/src/tools/rustfmt/src/missed_spans.rs @@ -91,7 +91,7 @@ impl<'a> FmtVisitor<'a> { assert!( start < end, "Request to format inverted span: {}", - self.parse_sess.span_to_debug_info(mk_sp(start, end)), + self.psess.span_to_debug_info(mk_sp(start, end)), ); self.last_pos = end; @@ -166,8 +166,8 @@ impl<'a> FmtVisitor<'a> { // Trim whitespace from the right hand side of each line. // Annoyingly, the library functions for splitting by lines etc. are not // quite right, so we must do it ourselves. - let line = self.parse_sess.line_of_byte_pos(span.lo()); - let file_name = &self.parse_sess.span_to_filename(span); + let line = self.psess.line_of_byte_pos(span.lo()); + let file_name = &self.psess.span_to_filename(span); let mut status = SnippetStatus::new(line); let snippet = &*transform_missing_snippet(self.config, old_snippet); diff --git a/src/tools/rustfmt/src/modules.rs b/src/tools/rustfmt/src/modules.rs index af9a154a6aea6..0590f28ee0521 100644 --- a/src/tools/rustfmt/src/modules.rs +++ b/src/tools/rustfmt/src/modules.rs @@ -57,8 +57,8 @@ impl<'a> Module<'a> { } /// Maps each module to the corresponding file. -pub(crate) struct ModResolver<'ast, 'sess> { - parse_sess: &'sess ParseSess, +pub(crate) struct ModResolver<'ast, 'psess> { + psess: &'psess ParseSess, directory: Directory, file_map: FileModMap<'ast>, recursive: bool, @@ -99,10 +99,10 @@ enum SubModKind<'a, 'ast> { Internal(&'a ast::Item), } -impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { +impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> { /// Creates a new `ModResolver`. pub(crate) fn new( - parse_sess: &'sess ParseSess, + psess: &'psess ParseSess, directory_ownership: DirectoryOwnership, recursive: bool, ) -> Self { @@ -112,7 +112,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { ownership: directory_ownership, }, file_map: BTreeMap::new(), - parse_sess, + psess, recursive, } } @@ -122,7 +122,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { mut self, krate: &'ast ast::Crate, ) -> Result, ModuleResolutionError> { - let root_filename = self.parse_sess.span_to_filename(krate.spans.inner_span); + let root_filename = self.psess.span_to_filename(krate.spans.inner_span); self.directory.path = match root_filename { FileName::Real(ref p) => p.parent().unwrap_or(Path::new("")).to_path_buf(), _ => PathBuf::new(), @@ -133,7 +133,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { self.visit_mod_from_ast(&krate.items)?; } - let snippet_provider = self.parse_sess.snippet_provider(krate.spans.inner_span); + let snippet_provider = self.psess.snippet_provider(krate.spans.inner_span); self.file_map.insert( root_filename, @@ -149,7 +149,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { /// Visit `cfg_if` macro and look for module declarations. fn visit_cfg_if(&mut self, item: Cow<'ast, ast::Item>) -> Result<(), ModuleResolutionError> { - let mut visitor = visitor::CfgIfVisitor::new(self.parse_sess); + let mut visitor = visitor::CfgIfVisitor::new(self.psess); visitor.visit_item(&item); for module_item in visitor.mods() { if let ast::ItemKind::Mod(_, ref sub_mod_kind) = module_item.item.kind { @@ -338,10 +338,10 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { DirectoryOwnership::UnownedViaBlock => None, }; if let Some(path) = Parser::submod_path_from_attr(attrs, &self.directory.path) { - if self.parse_sess.is_file_parsed(&path) { + if self.psess.is_file_parsed(&path) { return Ok(None); } - return match Parser::parse_file_as_module(self.parse_sess, &path, sub_mod.span) { + return match Parser::parse_file_as_module(self.psess, &path, sub_mod.span) { Ok((ref attrs, _, _)) if contains_skip(attrs) => Ok(None), Ok((attrs, items, span)) => Ok(Some(SubModKind::External( path, @@ -368,7 +368,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { let mut mods_outside_ast = self.find_mods_outside_of_ast(attrs, sub_mod); match self - .parse_sess + .psess .default_submod_path(mod_name, relative, &self.directory.path) { Ok(ModulePathSuccess { @@ -380,7 +380,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { let should_insert = !mods_outside_ast .iter() .any(|(outside_path, _, _)| outside_path == &file_path); - if self.parse_sess.is_file_parsed(&file_path) { + if self.psess.is_file_parsed(&file_path) { if outside_mods_empty { return Ok(None); } else { @@ -390,7 +390,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { return Ok(Some(SubModKind::MultiExternal(mods_outside_ast))); } } - match Parser::parse_file_as_module(self.parse_sess, &file_path, sub_mod.span) { + match Parser::parse_file_as_module(self.psess, &file_path, sub_mod.span) { Ok((ref attrs, _, _)) if contains_skip(attrs) => Ok(None), Ok((attrs, items, span)) if outside_mods_empty => { Ok(Some(SubModKind::External( @@ -517,7 +517,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { if !actual_path.exists() { continue; } - if self.parse_sess.is_file_parsed(&actual_path) { + if self.psess.is_file_parsed(&actual_path) { // If the specified file is already parsed, then we just use that. result.push(( actual_path, @@ -527,7 +527,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { continue; } let (attrs, items, span) = - match Parser::parse_file_as_module(self.parse_sess, &actual_path, sub_mod.span) { + match Parser::parse_file_as_module(self.psess, &actual_path, sub_mod.span) { Ok((ref attrs, _, _)) if contains_skip(attrs) => continue, Ok(m) => m, Err(..) => continue, diff --git a/src/tools/rustfmt/src/modules/visitor.rs b/src/tools/rustfmt/src/modules/visitor.rs index 48431693332a6..3e05b6d0c5d49 100644 --- a/src/tools/rustfmt/src/modules/visitor.rs +++ b/src/tools/rustfmt/src/modules/visitor.rs @@ -12,15 +12,15 @@ pub(crate) struct ModItem { /// Traverse `cfg_if!` macro and fetch modules. pub(crate) struct CfgIfVisitor<'a> { - parse_sess: &'a ParseSess, + psess: &'a ParseSess, mods: Vec, } impl<'a> CfgIfVisitor<'a> { - pub(crate) fn new(parse_sess: &'a ParseSess) -> CfgIfVisitor<'a> { + pub(crate) fn new(psess: &'a ParseSess) -> CfgIfVisitor<'a> { CfgIfVisitor { mods: vec![], - parse_sess, + psess, } } @@ -62,7 +62,7 @@ impl<'a, 'ast: 'a> CfgIfVisitor<'a> { } }; - let items = parse_cfg_if(self.parse_sess, mac)?; + let items = parse_cfg_if(self.psess, mac)?; self.mods .append(&mut items.into_iter().map(|item| ModItem { item }).collect()); diff --git a/src/tools/rustfmt/src/parse/macros/asm.rs b/src/tools/rustfmt/src/parse/macros/asm.rs index 01edfab36547c..6373d0251f896 100644 --- a/src/tools/rustfmt/src/parse/macros/asm.rs +++ b/src/tools/rustfmt/src/parse/macros/asm.rs @@ -7,5 +7,5 @@ use crate::rewrite::RewriteContext; pub(crate) fn parse_asm(context: &RewriteContext<'_>, mac: &ast::MacCall) -> Option { let ts = mac.args.tokens.clone(); let mut parser = super::build_parser(context, ts); - parse_asm_args(&mut parser, context.parse_sess.inner(), mac.span(), false).ok() + parse_asm_args(&mut parser, mac.span(), false).ok() } diff --git a/src/tools/rustfmt/src/parse/macros/cfg_if.rs b/src/tools/rustfmt/src/parse/macros/cfg_if.rs index bafef7b0f4620..5fc988e431935 100644 --- a/src/tools/rustfmt/src/parse/macros/cfg_if.rs +++ b/src/tools/rustfmt/src/parse/macros/cfg_if.rs @@ -9,10 +9,10 @@ use crate::parse::macros::build_stream_parser; use crate::parse::session::ParseSess; pub(crate) fn parse_cfg_if<'a>( - sess: &'a ParseSess, + psess: &'a ParseSess, mac: &'a ast::MacCall, ) -> Result, &'static str> { - match catch_unwind(AssertUnwindSafe(|| parse_cfg_if_inner(sess, mac))) { + match catch_unwind(AssertUnwindSafe(|| parse_cfg_if_inner(psess, mac))) { Ok(Ok(items)) => Ok(items), Ok(err @ Err(_)) => err, Err(..) => Err("failed to parse cfg_if!"), @@ -20,11 +20,11 @@ pub(crate) fn parse_cfg_if<'a>( } fn parse_cfg_if_inner<'a>( - sess: &'a ParseSess, + psess: &'a ParseSess, mac: &'a ast::MacCall, ) -> Result, &'static str> { let ts = mac.args.tokens.clone(); - let mut parser = build_stream_parser(sess.inner(), ts); + let mut parser = build_stream_parser(psess.inner(), ts); let mut items = vec![]; let mut process_if_cfg = true; @@ -67,7 +67,7 @@ fn parse_cfg_if_inner<'a>( Ok(None) => continue, Err(err) => { err.cancel(); - parser.sess.dcx.reset_err_count(); + parser.psess.dcx.reset_err_count(); return Err( "Expected item inside cfg_if block, but failed to parse it as an item", ); diff --git a/src/tools/rustfmt/src/parse/macros/lazy_static.rs b/src/tools/rustfmt/src/parse/macros/lazy_static.rs index 8b1dc6694d6f5..badd956995007 100644 --- a/src/tools/rustfmt/src/parse/macros/lazy_static.rs +++ b/src/tools/rustfmt/src/parse/macros/lazy_static.rs @@ -16,8 +16,8 @@ pub(crate) fn parse_lazy_static( ($method:ident $(,)* $($arg:expr),* $(,)*) => { match parser.$method($($arg,)*) { Ok(val) => { - if parser.sess.dcx.has_errors().is_some() { - parser.sess.dcx.reset_err_count(); + if parser.psess.dcx.has_errors().is_some() { + parser.psess.dcx.reset_err_count(); return None; } else { val @@ -25,7 +25,7 @@ pub(crate) fn parse_lazy_static( } Err(err) => { err.cancel(); - parser.sess.dcx.reset_err_count(); + parser.psess.dcx.reset_err_count(); return None; } } diff --git a/src/tools/rustfmt/src/parse/macros/mod.rs b/src/tools/rustfmt/src/parse/macros/mod.rs index a9f9ea1826ae5..3cf133c647cc4 100644 --- a/src/tools/rustfmt/src/parse/macros/mod.rs +++ b/src/tools/rustfmt/src/parse/macros/mod.rs @@ -14,12 +14,12 @@ pub(crate) mod asm; pub(crate) mod cfg_if; pub(crate) mod lazy_static; -fn build_stream_parser<'a>(sess: &'a ParseSess, tokens: TokenStream) -> Parser<'a> { - stream_to_parser(sess, tokens, MACRO_ARGUMENTS).recovery(Recovery::Forbidden) +fn build_stream_parser<'a>(psess: &'a ParseSess, tokens: TokenStream) -> Parser<'a> { + stream_to_parser(psess, tokens, MACRO_ARGUMENTS).recovery(Recovery::Forbidden) } fn build_parser<'a>(context: &RewriteContext<'a>, tokens: TokenStream) -> Parser<'a> { - build_stream_parser(context.parse_sess.inner(), tokens) + build_stream_parser(context.psess.inner(), tokens) } fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { @@ -29,8 +29,8 @@ fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { if Parser::nonterminal_may_begin_with($nt_kind, &cloned_parser.token) { match $try_parse(&mut cloned_parser) { Ok(x) => { - if parser.sess.dcx.has_errors().is_some() { - parser.sess.dcx.reset_err_count(); + if parser.psess.dcx.has_errors().is_some() { + parser.psess.dcx.reset_err_count(); } else { // Parsing succeeded. *parser = cloned_parser; @@ -39,7 +39,7 @@ fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { } Err(e) => { e.cancel(); - parser.sess.dcx.reset_err_count(); + parser.psess.dcx.reset_err_count(); } } } diff --git a/src/tools/rustfmt/src/parse/parser.rs b/src/tools/rustfmt/src/parse/parser.rs index 19b0dada08f33..5dcdca1d9538d 100644 --- a/src/tools/rustfmt/src/parse/parser.rs +++ b/src/tools/rustfmt/src/parse/parser.rs @@ -29,7 +29,7 @@ pub(crate) struct Parser<'a> { /// A builder for the `Parser`. #[derive(Default)] pub(crate) struct ParserBuilder<'a> { - sess: Option<&'a ParseSess>, + psess: Option<&'a ParseSess>, input: Option, } @@ -39,20 +39,20 @@ impl<'a> ParserBuilder<'a> { self } - pub(crate) fn sess(mut self, sess: &'a ParseSess) -> ParserBuilder<'a> { - self.sess = Some(sess); + pub(crate) fn psess(mut self, psess: &'a ParseSess) -> ParserBuilder<'a> { + self.psess = Some(psess); self } pub(crate) fn build(self) -> Result, ParserError> { - let sess = self.sess.ok_or(ParserError::NoParseSess)?; + let psess = self.psess.ok_or(ParserError::NoParseSess)?; let input = self.input.ok_or(ParserError::NoInput)?; - let parser = match Self::parser(sess.inner(), input) { + let parser = match Self::parser(psess.inner(), input) { Ok(p) => p, Err(db) => { if let Some(diagnostics) = db { - sess.emit_diagnostics(diagnostics); + psess.emit_diagnostics(diagnostics); return Err(ParserError::ParserCreationError); } return Err(ParserError::ParsePanicError); @@ -63,16 +63,16 @@ impl<'a> ParserBuilder<'a> { } fn parser( - sess: &'a rustc_session::parse::ParseSess, + psess: &'a rustc_session::parse::ParseSess, input: Input, ) -> Result, Option>>> { match input { Input::File(ref file) => catch_unwind(AssertUnwindSafe(move || { - new_parser_from_file(sess, file, None) + new_parser_from_file(psess, file, None) })) .map_err(|_| None), Input::Text(text) => rustc_parse::maybe_new_parser_from_source_str( - sess, + psess, rustc_span::FileName::Custom("stdin".to_owned()), text, ) @@ -106,27 +106,27 @@ impl<'a> Parser<'a> { } pub(crate) fn parse_file_as_module( - sess: &'a ParseSess, + psess: &'a ParseSess, path: &Path, span: Span, ) -> Result<(ast::AttrVec, ThinVec>, Span), ParserError> { let result = catch_unwind(AssertUnwindSafe(|| { - let mut parser = new_parser_from_file(sess.inner(), path, Some(span)); + let mut parser = new_parser_from_file(psess.inner(), path, Some(span)); match parser.parse_mod(&TokenKind::Eof) { Ok((a, i, spans)) => Some((a, i, spans.inner_span)), Err(e) => { e.emit(); - if sess.can_reset_errors() { - sess.reset_errors(); + if psess.can_reset_errors() { + psess.reset_errors(); } None } } })); match result { - Ok(Some(m)) if !sess.has_errors() => Ok(m), - Ok(Some(m)) if sess.can_reset_errors() => { - sess.reset_errors(); + Ok(Some(m)) if !psess.has_errors() => Ok(m), + Ok(Some(m)) if psess.can_reset_errors() => { + psess.reset_errors(); Ok(m) } Ok(_) => Err(ParserError::ParseError), @@ -137,25 +137,25 @@ impl<'a> Parser<'a> { pub(crate) fn parse_crate( input: Input, - sess: &'a ParseSess, + psess: &'a ParseSess, ) -> Result { - let krate = Parser::parse_crate_inner(input, sess)?; - if !sess.has_errors() { + let krate = Parser::parse_crate_inner(input, psess)?; + if !psess.has_errors() { return Ok(krate); } - if sess.can_reset_errors() { - sess.reset_errors(); + if psess.can_reset_errors() { + psess.reset_errors(); return Ok(krate); } Err(ParserError::ParseError) } - fn parse_crate_inner(input: Input, sess: &'a ParseSess) -> Result { + fn parse_crate_inner(input: Input, psess: &'a ParseSess) -> Result { ParserBuilder::default() .input(input) - .sess(sess) + .psess(psess) .build()? .parse_crate_mod() } diff --git a/src/tools/rustfmt/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs index d6386a9504db7..cb46e65999df6 100644 --- a/src/tools/rustfmt/src/parse/session.rs +++ b/src/tools/rustfmt/src/parse/session.rs @@ -1,9 +1,8 @@ -use std::borrow::Cow; use std::path::Path; use std::sync::atomic::{AtomicBool, Ordering}; use rustc_data_structures::sync::{IntoDynSyncSend, Lrc}; -use rustc_errors::emitter::{stderr_destination, DynEmitter, Emitter, HumanEmitter}; +use rustc_errors::emitter::{stderr_destination, DynEmitter, Emitter, HumanEmitter, SilentEmitter}; use rustc_errors::translation::Translate; use rustc_errors::{ColorConfig, Diag, DiagCtxt, DiagInner, Level as DiagnosticLevel}; use rustc_session::parse::ParseSess as RawParseSess; @@ -23,46 +22,11 @@ use crate::{Config, ErrorKind, FileName}; /// ParseSess holds structs necessary for constructing a parser. pub(crate) struct ParseSess { - parse_sess: RawParseSess, + raw_psess: RawParseSess, ignore_path_set: Lrc, can_reset_errors: Lrc, } -/// Emitter which discards every error. -struct SilentEmitter; - -impl Translate for SilentEmitter { - fn fluent_bundle(&self) -> Option<&Lrc> { - None - } - - fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle { - panic!("silent emitter attempted to translate a diagnostic"); - } - - // Override `translate_message` for the silent emitter because eager translation of - // subdiagnostics result in a call to this. - fn translate_message<'a>( - &'a self, - message: &'a rustc_errors::DiagnosticMessage, - _: &'a rustc_errors::translation::FluentArgs<'_>, - ) -> Result, rustc_errors::error::TranslateError<'_>> { - rustc_errors::emitter::silent_translate(message) - } -} - -impl Emitter for SilentEmitter { - fn source_map(&self) -> Option<&Lrc> { - None - } - - fn emit_diagnostic(&mut self, _diag: DiagInner) {} -} - -fn silent_emitter() -> Box { - Box::new(SilentEmitter {}) -} - /// Emit errors against every files expect ones specified in the `ignore_path_set`. struct SilentOnIgnoredFilesEmitter { ignore_path_set: IntoDynSyncSend>, @@ -143,17 +107,23 @@ fn default_dcx( ColorConfig::Never }; - let emitter = if hide_parse_errors { - silent_emitter() + let fallback_bundle = rustc_errors::fallback_fluent_bundle( + rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), + false, + ); + let emitter = Box::new( + HumanEmitter::new(stderr_destination(emit_color), fallback_bundle.clone()) + .sm(Some(source_map.clone())), + ); + + let emitter: Box = if hide_parse_errors { + Box::new(SilentEmitter { + fallback_bundle, + fatal_dcx: DiagCtxt::new(emitter), + fatal_note: None, + }) } else { - let fallback_bundle = rustc_errors::fallback_fluent_bundle( - rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), - false, - ); - Box::new( - HumanEmitter::new(stderr_destination(emit_color), fallback_bundle) - .sm(Some(source_map.clone())), - ) + emitter }; DiagCtxt::new(Box::new(SilentOnIgnoredFilesEmitter { has_non_ignorable_parser_errors: false, @@ -180,10 +150,10 @@ impl ParseSess { config.hide_parse_errors(), config.color(), ); - let parse_sess = RawParseSess::with_dcx(dcx, source_map); + let raw_psess = RawParseSess::with_dcx(dcx, source_map); Ok(ParseSess { - parse_sess, + raw_psess, ignore_path_set, can_reset_errors, }) @@ -202,14 +172,14 @@ impl ParseSess { relative: Option, dir_path: &Path, ) -> Result> { - rustc_expand::module::default_submod_path(&self.parse_sess, id, relative, dir_path).or_else( + rustc_expand::module::default_submod_path(&self.raw_psess, id, relative, dir_path).or_else( |e| { // If resloving a module relative to {dir_path}/{symbol} fails because a file // could not be found, then try to resolve the module relative to {dir_path}. // If we still can't find the module after searching for it in {dir_path}, // surface the original error. if matches!(e, ModError::FileNotFound(..)) && relative.is_some() { - rustc_expand::module::default_submod_path(&self.parse_sess, id, None, dir_path) + rustc_expand::module::default_submod_path(&self.raw_psess, id, None, dir_path) .map_err(|_| e) } else { Err(e) @@ -219,7 +189,7 @@ impl ParseSess { } pub(crate) fn is_file_parsed(&self, path: &Path) -> bool { - self.parse_sess + self.raw_psess .source_map() .get_source_file(&rustc_span::FileName::Real( rustc_span::RealFileName::LocalPath(path.to_path_buf()), @@ -232,21 +202,28 @@ impl ParseSess { } pub(crate) fn set_silent_emitter(&mut self) { - self.parse_sess.dcx = DiagCtxt::new(silent_emitter()); + // Ideally this invocation wouldn't be necessary and the fallback bundle in + // `self.parse_sess.dcx` could be used, but the lock in `DiagCtxt` prevents this. + // See `::fallback_fluent_bundle`. + let fallback_bundle = rustc_errors::fallback_fluent_bundle( + rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), + false, + ); + self.raw_psess.dcx.make_silent(fallback_bundle, None); } pub(crate) fn span_to_filename(&self, span: Span) -> FileName { - self.parse_sess.source_map().span_to_filename(span).into() + self.raw_psess.source_map().span_to_filename(span).into() } pub(crate) fn span_to_file_contents(&self, span: Span) -> Lrc { - self.parse_sess + self.raw_psess .source_map() .lookup_source_file(span.data().lo) } pub(crate) fn span_to_first_line_string(&self, span: Span) -> String { - let file_lines = self.parse_sess.source_map().span_to_lines(span).ok(); + let file_lines = self.raw_psess.source_map().span_to_lines(span).ok(); match file_lines { Some(fl) => fl @@ -258,7 +235,7 @@ impl ParseSess { } pub(crate) fn line_of_byte_pos(&self, pos: BytePos) -> usize { - self.parse_sess.source_map().lookup_char_pos(pos).line + self.raw_psess.source_map().lookup_char_pos(pos).line } // TODO(calebcartwright): Preemptive, currently unused addition @@ -271,15 +248,15 @@ impl ParseSess { } pub(crate) fn span_to_debug_info(&self, span: Span) -> String { - self.parse_sess.source_map().span_to_diagnostic_string(span) + self.raw_psess.source_map().span_to_diagnostic_string(span) } pub(crate) fn inner(&self) -> &RawParseSess { - &self.parse_sess + &self.raw_psess } pub(crate) fn snippet_provider(&self, span: Span) -> SnippetProvider { - let source_file = self.parse_sess.source_map().lookup_char_pos(span.lo()).file; + let source_file = self.raw_psess.source_map().lookup_char_pos(span.lo()).file; SnippetProvider::new( source_file.start_pos, source_file.end_position(), @@ -288,7 +265,7 @@ impl ParseSess { } pub(crate) fn get_original_snippet(&self, file_name: &FileName) -> Option> { - self.parse_sess + self.raw_psess .source_map() .get_source_file(&file_name.into()) .and_then(|source_file| source_file.src.clone()) @@ -308,23 +285,23 @@ impl ParseSess { } pub(super) fn has_errors(&self) -> bool { - self.parse_sess.dcx.has_errors().is_some() + self.raw_psess.dcx.has_errors().is_some() } pub(super) fn reset_errors(&self) { - self.parse_sess.dcx.reset_err_count(); + self.raw_psess.dcx.reset_err_count(); } } impl LineRangeUtils for ParseSess { fn lookup_line_range(&self, span: Span) -> LineRange { let snippet = self - .parse_sess + .raw_psess .source_map() .span_to_snippet(span) .unwrap_or_default(); - let lo = self.parse_sess.source_map().lookup_line(span.lo()).unwrap(); - let hi = self.parse_sess.source_map().lookup_line(span.hi()).unwrap(); + let lo = self.raw_psess.source_map().lookup_line(span.lo()).unwrap(); + let hi = self.raw_psess.source_map().lookup_line(span.hi()).unwrap(); debug_assert_eq!( lo.sf.name, hi.sf.name, @@ -383,6 +360,7 @@ mod tests { } fn build_diagnostic(level: DiagnosticLevel, span: Option) -> DiagInner { + #[allow(rustc::untranslatable_diagnostic)] // no translation needed for empty string let mut diag = DiagInner::new(level, ""); diag.messages.clear(); if let Some(span) = span { diff --git a/src/tools/rustfmt/src/reorder.rs b/src/tools/rustfmt/src/reorder.rs index 3e14f9f1272f4..fdbed939af542 100644 --- a/src/tools/rustfmt/src/reorder.rs +++ b/src/tools/rustfmt/src/reorder.rs @@ -263,13 +263,13 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { item_kind: ReorderableItemKind, in_group: bool, ) -> usize { - let mut last = self.parse_sess.lookup_line_range(items[0].span()); + let mut last = self.psess.lookup_line_range(items[0].span()); let item_length = items .iter() .take_while(|ppi| { item_kind.is_same_item_kind(&***ppi) && (!in_group || { - let current = self.parse_sess.lookup_line_range(ppi.span()); + let current = self.psess.lookup_line_range(ppi.span()); let in_same_group = current.lo < last.hi + 2; last = current; in_same_group diff --git a/src/tools/rustfmt/src/rewrite.rs b/src/tools/rustfmt/src/rewrite.rs index 4a3bd129d16f5..e2498a3500a0f 100644 --- a/src/tools/rustfmt/src/rewrite.rs +++ b/src/tools/rustfmt/src/rewrite.rs @@ -26,7 +26,7 @@ impl Rewrite for ptr::P { #[derive(Clone)] pub(crate) struct RewriteContext<'a> { - pub(crate) parse_sess: &'a ParseSess, + pub(crate) psess: &'a ParseSess, pub(crate) config: &'a Config, pub(crate) inside_macro: Rc>, // Force block indent style even if we are using visual indent style. diff --git a/src/tools/rustfmt/src/source_file.rs b/src/tools/rustfmt/src/source_file.rs index 512a8593c27cd..6376bc49b69f3 100644 --- a/src/tools/rustfmt/src/source_file.rs +++ b/src/tools/rustfmt/src/source_file.rs @@ -49,7 +49,7 @@ where } pub(crate) fn write_file( - parse_sess: Option<&ParseSess>, + psess: Option<&ParseSess>, filename: &FileName, formatted_text: &str, out: &mut T, @@ -90,7 +90,7 @@ where let original_text = if newline_style != NewlineStyle::Auto && *filename != FileName::Stdin { Lrc::new(fs::read_to_string(ensure_real_path(filename))?) } else { - match parse_sess.and_then(|sess| sess.get_original_snippet(filename)) { + match psess.and_then(|psess| psess.get_original_snippet(filename)) { Some(ori) => ori, None => Lrc::new(fs::read_to_string(ensure_real_path(filename))?), } diff --git a/src/tools/rustfmt/src/utils.rs b/src/tools/rustfmt/src/utils.rs index d4218cff75aaa..b91d9b47cb63b 100644 --- a/src/tools/rustfmt/src/utils.rs +++ b/src/tools/rustfmt/src/utils.rs @@ -362,7 +362,7 @@ macro_rules! out_of_file_lines_range { && !$self .config .file_lines() - .intersects(&$self.parse_sess.lookup_line_range($span)) + .intersects(&$self.psess.lookup_line_range($span)) }; } diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs index bc5accefd92b8..47f772b485daf 100644 --- a/src/tools/rustfmt/src/visitor.rs +++ b/src/tools/rustfmt/src/visitor.rs @@ -71,7 +71,7 @@ impl SnippetProvider { pub(crate) struct FmtVisitor<'a> { parent_context: Option<&'a RewriteContext<'a>>, - pub(crate) parse_sess: &'a ParseSess, + pub(crate) psess: &'a ParseSess, pub(crate) buffer: String, pub(crate) last_pos: BytePos, // FIXME: use an RAII util or closure for indenting @@ -113,10 +113,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } fn visit_stmt(&mut self, stmt: &Stmt<'_>, include_empty_semi: bool) { - debug!( - "visit_stmt: {}", - self.parse_sess.span_to_debug_info(stmt.span()) - ); + debug!("visit_stmt: {}", self.psess.span_to_debug_info(stmt.span())); if stmt.is_empty() { // If the statement is empty, just skip over it. Before that, make sure any comment @@ -217,10 +214,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { inner_attrs: Option<&[ast::Attribute]>, has_braces: bool, ) { - debug!( - "visit_block: {}", - self.parse_sess.span_to_debug_info(b.span), - ); + debug!("visit_block: {}", self.psess.span_to_debug_info(b.span)); // Check if this block has braces. let brace_compensation = BytePos(if has_braces { 1 } else { 0 }); @@ -744,10 +738,10 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { // do not take into account the lines with attributes as part of the skipped range let attrs_end = attrs .iter() - .map(|attr| self.parse_sess.line_of_byte_pos(attr.span.hi())) + .map(|attr| self.psess.line_of_byte_pos(attr.span.hi())) .max() .unwrap_or(1); - let first_line = self.parse_sess.line_of_byte_pos(main_span.lo()); + let first_line = self.psess.line_of_byte_pos(main_span.lo()); // Statement can start after some newlines and/or spaces // or it can be on the same line as the last attribute. // So here we need to take a minimum between the two. @@ -758,8 +752,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } pub(crate) fn from_context(ctx: &'a RewriteContext<'_>) -> FmtVisitor<'a> { - let mut visitor = FmtVisitor::from_parse_sess( - ctx.parse_sess, + let mut visitor = FmtVisitor::from_psess( + ctx.psess, ctx.config, ctx.snippet_provider, ctx.report.clone(), @@ -769,8 +763,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { visitor } - pub(crate) fn from_parse_sess( - parse_session: &'a ParseSess, + pub(crate) fn from_psess( + psess: &'a ParseSess, config: &'a Config, snippet_provider: &'a SnippetProvider, report: FormatReport, @@ -786,7 +780,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { skip_context.macros.extend(macro_names); FmtVisitor { parent_context: None, - parse_sess: parse_session, + psess, buffer: String::with_capacity(snippet_provider.big_snippet.len() * 2), last_pos: BytePos(0), block_indent: Indent::empty(), @@ -814,12 +808,12 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { pub(crate) fn visit_attrs(&mut self, attrs: &[ast::Attribute], style: ast::AttrStyle) -> bool { for attr in attrs { if attr.has_name(depr_skip_annotation()) { - let file_name = self.parse_sess.span_to_filename(attr.span); + let file_name = self.psess.span_to_filename(attr.span); self.report.append( file_name, vec![FormattingError::from_span( attr.span, - self.parse_sess, + self.psess, ErrorKind::DeprecatedAttr, )], ); @@ -828,12 +822,12 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ast::AttrKind::Normal(ref normal) if self.is_unknown_rustfmt_attr(&normal.item.path.segments) => { - let file_name = self.parse_sess.span_to_filename(attr.span); + let file_name = self.psess.span_to_filename(attr.span); self.report.append( file_name, vec![FormattingError::from_span( attr.span, - self.parse_sess, + self.psess, ErrorKind::BadAttr, )], ); @@ -1007,7 +1001,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { pub(crate) fn get_context(&self) -> RewriteContext<'_> { RewriteContext { - parse_sess: self.parse_sess, + psess: self.psess, config: self.config, inside_macro: Rc::new(Cell::new(false)), use_block: Cell::new(false), diff --git a/src/tools/rustfmt/tests/rustfmt/main.rs b/src/tools/rustfmt/tests/rustfmt/main.rs index 7dcf7c8416eec..e66fad1e7fa7b 100644 --- a/src/tools/rustfmt/tests/rustfmt/main.rs +++ b/src/tools/rustfmt/tests/rustfmt/main.rs @@ -176,7 +176,7 @@ fn rustfmt_emits_error_on_line_overflow_true() { #[test] #[allow(non_snake_case)] fn dont_emit_ICE() { - let files = ["tests/target/issue_5728.rs", "tests/target/issue_5729.rs"]; + let files = ["tests/target/issue_5728.rs", "tests/target/issue_5729.rs", "tests/target/issue_6082.rs"]; for file in files { let args = [file]; diff --git a/src/tools/rustfmt/tests/target/issue_6082.rs b/src/tools/rustfmt/tests/target/issue_6082.rs new file mode 100644 index 0000000000000..58e512c710e98 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue_6082.rs @@ -0,0 +1,5 @@ +macro_rules! test { + ($T:ident, $b:lifetime) => { + Box<$T<$b>> + }; +} diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index cd3976ea6575d..91bbf5041ff58 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -183,8 +183,8 @@ "ui/async-await/issue-67651.rs", "ui/async-await/issue-67765-async-diagnostic.rs", "ui/async-await/issue-68112.rs", -"ui/async-await/issue-68523.rs", "ui/async-await/issue-68523-start.rs", +"ui/async-await/issue-68523.rs", "ui/async-await/issue-69446-fnmut-capture.rs", "ui/async-await/issue-70594.rs", "ui/async-await/issue-70818.rs", @@ -342,8 +342,8 @@ "ui/borrowck/issue-52967-edition-2018-needs-two-phase-borrows.rs", "ui/borrowck/issue-53432-nested-closure-outlives-borrowed-value.rs", "ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.rs", -"ui/borrowck/issue-54499-field-mutation-of-moved-out.rs", "ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.rs", +"ui/borrowck/issue-54499-field-mutation-of-moved-out.rs", "ui/borrowck/issue-54499-field-mutation-of-never-init.rs", "ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.rs", "ui/borrowck/issue-55492-borrowck-migrate-scans-parents.rs", @@ -360,9 +360,9 @@ "ui/borrowck/issue-71546.rs", "ui/borrowck/issue-7573.rs", "ui/borrowck/issue-80772.rs", +"ui/borrowck/issue-81365-1.rs", "ui/borrowck/issue-81365-10.rs", "ui/borrowck/issue-81365-11.rs", -"ui/borrowck/issue-81365-1.rs", "ui/borrowck/issue-81365-2.rs", "ui/borrowck/issue-81365-3.rs", "ui/borrowck/issue-81365-4.rs", @@ -392,6 +392,9 @@ "ui/borrowck/issue-95079-missing-move-in-nested-closure.rs", "ui/box/issue-82446.rs", "ui/box/issue-95036.rs", +"ui/c-variadic/issue-32201.rs", +"ui/c-variadic/issue-86053-1.rs", +"ui/c-variadic/issue-86053-2.rs", "ui/cast/issue-106883-is-empty.rs", "ui/cast/issue-10991.rs", "ui/cast/issue-17444.rs", @@ -399,19 +402,19 @@ "ui/cast/issue-85586.rs", "ui/cast/issue-88621.rs", "ui/cast/issue-89497.rs", +"ui/closure-expected-type/issue-24421.rs", "ui/closure_context/issue-26046-fn-mut.rs", "ui/closure_context/issue-26046-fn-once.rs", "ui/closure_context/issue-42065.rs", -"ui/closure-expected-type/issue-24421.rs", "ui/closures/2229_closure_analysis/issue-118144.rs", "ui/closures/2229_closure_analysis/issue-87378.rs", "ui/closures/2229_closure_analysis/issue-87987.rs", "ui/closures/2229_closure_analysis/issue-88118-2.rs", -"ui/closures/2229_closure_analysis/issue_88118.rs", "ui/closures/2229_closure_analysis/issue-88476.rs", "ui/closures/2229_closure_analysis/issue-89606.rs", "ui/closures/2229_closure_analysis/issue-90465.rs", "ui/closures/2229_closure_analysis/issue-92724-needsdrop-query-cycle.rs", +"ui/closures/2229_closure_analysis/issue_88118.rs", "ui/closures/2229_closure_analysis/match/issue-87097.rs", "ui/closures/2229_closure_analysis/match/issue-87426.rs", "ui/closures/2229_closure_analysis/match/issue-87988.rs", @@ -644,8 +647,8 @@ "ui/const-generics/issues/issue-99641.rs", "ui/const-generics/parser-error-recovery/issue-89013-no-assoc.rs", "ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs", -"ui/const-generics/parser-error-recovery/issue-89013.rs", "ui/const-generics/parser-error-recovery/issue-89013-type.rs", +"ui/const-generics/parser-error-recovery/issue-89013.rs", "ui/const-generics/type-dependent/issue-61936.rs", "ui/const-generics/type-dependent/issue-63695.rs", "ui/const-generics/type-dependent/issue-67144-1.rs", @@ -689,13 +692,13 @@ "ui/consts/const-eval/issue-91827-extern-types-field-offset.rs", "ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier-2.rs", "ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.rs", +"ui/consts/const-mut-refs/issue-76510.rs", "ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.rs", "ui/consts/const_in_pattern/issue-44333.rs", "ui/consts/const_in_pattern/issue-53708.rs", "ui/consts/const_in_pattern/issue-62614.rs", "ui/consts/const_in_pattern/issue-65466.rs", "ui/consts/const_in_pattern/issue-73431.rs", -"ui/consts/const-mut-refs/issue-76510.rs", "ui/consts/control-flow/issue-46843.rs", "ui/consts/control-flow/issue-50577.rs", "ui/consts/extra-const-ub/issue-100771.rs", @@ -714,9 +717,9 @@ "ui/consts/issue-17074.rs", "ui/consts/issue-17458.rs", "ui/consts/issue-17718-borrow-interior.rs", -"ui/consts/issue-17718-constants-not-static.rs", "ui/consts/issue-17718-const-bad-values.rs", "ui/consts/issue-17718-const-borrow.rs", +"ui/consts/issue-17718-constants-not-static.rs", "ui/consts/issue-17718-references.rs", "ui/consts/issue-17718.rs", "ui/consts/issue-17756.rs", @@ -841,9 +844,6 @@ "ui/coroutine/issue-91477.rs", "ui/coroutine/issue-93161.rs", "ui/cross-crate/issue-64872/issue-64872.rs", -"ui/c-variadic/issue-32201.rs", -"ui/c-variadic/issue-86053-1.rs", -"ui/c-variadic/issue-86053-2.rs", "ui/cycle-trait/issue-12511.rs", "ui/debuginfo/issue-105386-debuginfo-ub.rs", "ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs", @@ -902,15 +902,6 @@ "ui/did_you_mean/issue-56028-there-is-an-enum-variant.rs", "ui/did_you_mean/issue-87830-try-brackets-for-arrays.rs", "ui/drop/auxiliary/issue-10028.rs", -"ui/dropck/issue-24805-dropck-itemless.rs", -"ui/dropck/issue-28498-ugeh-with-lifetime-param.rs", -"ui/dropck/issue-28498-ugeh-with-passed-to-fn.rs", -"ui/dropck/issue-28498-ugeh-with-trait-bound.rs", -"ui/dropck/issue-29844.rs", -"ui/dropck/issue-34053.rs", -"ui/dropck/issue-38868.rs", -"ui/dropck/issue-54943-1.rs", -"ui/dropck/issue-54943-2.rs", "ui/drop/issue-100276.rs", "ui/drop/issue-10028.rs", "ui/drop/issue-103107.rs", @@ -929,6 +920,15 @@ "ui/drop/issue-90752-raw-ptr-shenanigans.rs", "ui/drop/issue-90752.rs", "ui/drop/issue-979.rs", +"ui/dropck/issue-24805-dropck-itemless.rs", +"ui/dropck/issue-28498-ugeh-with-lifetime-param.rs", +"ui/dropck/issue-28498-ugeh-with-passed-to-fn.rs", +"ui/dropck/issue-28498-ugeh-with-trait-bound.rs", +"ui/dropck/issue-29844.rs", +"ui/dropck/issue-34053.rs", +"ui/dropck/issue-38868.rs", +"ui/dropck/issue-54943-1.rs", +"ui/dropck/issue-54943-2.rs", "ui/dst/issue-113447.rs", "ui/dst/issue-90528-unsizing-not-suggestion-110063.rs", "ui/dst/issue-90528-unsizing-suggestion-1.rs", @@ -1014,14 +1014,14 @@ "ui/fn/issue-3904.rs", "ui/fn/issue-39259.rs", "ui/fn/issue-80179.rs", -"ui/foreign/issue-74120-lowering-of-ffi-block-bodies.rs", -"ui/foreign/issue-91370-foreign-fn-block-impl.rs", -"ui/foreign/issue-99276-same-type-lifetimes.rs", -"ui/for/issue-20605.rs", "ui/for-loop-while/issue-1257.rs", "ui/for-loop-while/issue-2216.rs", "ui/for-loop-while/issue-51345.rs", "ui/for-loop-while/issue-69841.rs", +"ui/for/issue-20605.rs", +"ui/foreign/issue-74120-lowering-of-ffi-block-bodies.rs", +"ui/foreign/issue-91370-foreign-fn-block-impl.rs", +"ui/foreign/issue-99276-same-type-lifetimes.rs", "ui/function-pointer/issue-102289.rs", "ui/functions-closures/closure-expected-type/issue-38714.rs", "ui/generic-associated-types/bugs/issue-100013.rs", @@ -1084,8 +1084,8 @@ "ui/generic-associated-types/issue-87258_b.rs", "ui/generic-associated-types/issue-87429-2.rs", "ui/generic-associated-types/issue-87429-associated-type-default.rs", -"ui/generic-associated-types/issue-87429.rs", "ui/generic-associated-types/issue-87429-specialization.rs", +"ui/generic-associated-types/issue-87429.rs", "ui/generic-associated-types/issue-87748.rs", "ui/generic-associated-types/issue-87750.rs", "ui/generic-associated-types/issue-88287.rs", @@ -1095,9 +1095,9 @@ "ui/generic-associated-types/issue-88595.rs", "ui/generic-associated-types/issue-89008.rs", "ui/generic-associated-types/issue-89352.rs", -"ui/generic-associated-types/issue-90014.rs", -"ui/generic-associated-types/issue-90014-tait2.rs", "ui/generic-associated-types/issue-90014-tait.rs", +"ui/generic-associated-types/issue-90014-tait2.rs", +"ui/generic-associated-types/issue-90014.rs", "ui/generic-associated-types/issue-90729.rs", "ui/generic-associated-types/issue-91139.rs", "ui/generic-associated-types/issue-91883.rs", @@ -1119,8 +1119,8 @@ "ui/generics/issue-333.rs", "ui/generics/issue-59508-1.rs", "ui/generics/issue-59508.rs", -"ui/generics/issue-61631-default-type-param-cannot-reference-self.rs", "ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.rs", +"ui/generics/issue-61631-default-type-param-cannot-reference-self.rs", "ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.rs", "ui/generics/issue-79605.rs", "ui/generics/issue-80512-param-reordering-with-defaults.rs", @@ -1179,9 +1179,6 @@ "ui/hygiene/issue-47312.rs", "ui/hygiene/issue-61574-const-parameters.rs", "ui/hygiene/issue-77523-def-site-async-await.rs", -"ui/implied-bounds/issue-100690.rs", -"ui/implied-bounds/issue-101951.rs", -"ui/implied-bounds/issue-110161.rs", "ui/impl-trait/explicit-generic-args-with-impl-trait/issue-87718.rs", "ui/impl-trait/in-trait/issue-102140.rs", "ui/impl-trait/in-trait/issue-102301.rs", @@ -1261,6 +1258,9 @@ "ui/impl-trait/issues/issue-92305.rs", "ui/impl-trait/issues/issue-93788.rs", "ui/impl-trait/issues/issue-99348-impl-compatibility.rs", +"ui/implied-bounds/issue-100690.rs", +"ui/implied-bounds/issue-101951.rs", +"ui/implied-bounds/issue-110161.rs", "ui/imports/auxiliary/issue-114682-2-extern.rs", "ui/imports/auxiliary/issue-114682-3-extern.rs", "ui/imports/auxiliary/issue-114682-4-extern.rs", @@ -1368,8 +1368,8 @@ "ui/inference/need_type_info/issue-107745-avoid-expr-from-macro-expansion.rs", "ui/inference/need_type_info/issue-109905.rs", "ui/inference/need_type_info/issue-113264-incorrect-impl-trait-in-path-suggestion.rs", -"ui/infinite/issue-41731-infinite-macro-println.rs", "ui/infinite/issue-41731-infinite-macro-print.rs", +"ui/infinite/issue-41731-infinite-macro-println.rs", "ui/intrinsics/issue-28575.rs", "ui/intrinsics/issue-84297-reifying-copy.rs", "ui/invalid/issue-114435-layout-type-err.rs", @@ -1386,8 +1386,8 @@ "ui/issues/auxiliary/issue-11508.rs", "ui/issues/auxiliary/issue-11529.rs", "ui/issues/auxiliary/issue-11680.rs", -"ui/issues/auxiliary/issue-12133-dylib2.rs", "ui/issues/auxiliary/issue-12133-dylib.rs", +"ui/issues/auxiliary/issue-12133-dylib2.rs", "ui/issues/auxiliary/issue-12133-rlib.rs", "ui/issues/auxiliary/issue-12612-1.rs", "ui/issues/auxiliary/issue-12612-2.rs", @@ -1554,8 +1554,8 @@ "ui/issues/issue-13497-2.rs", "ui/issues/issue-13497.rs", "ui/issues/issue-13507-2.rs", -"ui/issues/issue-13620.rs", "ui/issues/issue-1362.rs", +"ui/issues/issue-13620.rs", "ui/issues/issue-13665.rs", "ui/issues/issue-13703.rs", "ui/issues/issue-13763.rs", @@ -1649,8 +1649,8 @@ "ui/issues/issue-16819.rs", "ui/issues/issue-16922-rpass.rs", "ui/issues/issue-16939.rs", -"ui/issues/issue-16966.rs", "ui/issues/issue-1696.rs", +"ui/issues/issue-16966.rs", "ui/issues/issue-16994.rs", "ui/issues/issue-17001.rs", "ui/issues/issue-17033.rs", @@ -1729,8 +1729,8 @@ "ui/issues/issue-18952.rs", "ui/issues/issue-18959.rs", "ui/issues/issue-18988.rs", -"ui/issues/issue-19001.rs", "ui/issues/issue-1900.rs", +"ui/issues/issue-19001.rs", "ui/issues/issue-19037.rs", "ui/issues/issue-19086.rs", "ui/issues/issue-19097.rs", @@ -1826,8 +1826,8 @@ "ui/issues/issue-21622.rs", "ui/issues/issue-21634.rs", "ui/issues/issue-21655.rs", -"ui/issues/issue-21701.rs", "ui/issues/issue-2170-exe.rs", +"ui/issues/issue-21701.rs", "ui/issues/issue-21763.rs", "ui/issues/issue-21891.rs", "ui/issues/issue-2190-1.rs", @@ -1863,15 +1863,15 @@ "ui/issues/issue-22777.rs", "ui/issues/issue-22781.rs", "ui/issues/issue-22789.rs", -"ui/issues/issue-22814.rs", "ui/issues/issue-2281-part1.rs", +"ui/issues/issue-22814.rs", "ui/issues/issue-2284.rs", "ui/issues/issue-22864-1.rs", "ui/issues/issue-22864-2.rs", "ui/issues/issue-22872.rs", "ui/issues/issue-22874.rs", -"ui/issues/issue-22886.rs", "ui/issues/issue-2288.rs", +"ui/issues/issue-22886.rs", "ui/issues/issue-22894.rs", "ui/issues/issue-22933-1.rs", "ui/issues/issue-22933-2.rs", @@ -1884,9 +1884,9 @@ "ui/issues/issue-23073.rs", "ui/issues/issue-2311-2.rs", "ui/issues/issue-2311.rs", +"ui/issues/issue-2312.rs", "ui/issues/issue-23122-1.rs", "ui/issues/issue-23122-2.rs", -"ui/issues/issue-2312.rs", "ui/issues/issue-2316-c.rs", "ui/issues/issue-23173.rs", "ui/issues/issue-23189.rs", @@ -1917,8 +1917,8 @@ "ui/issues/issue-23649-2.rs", "ui/issues/issue-23649-3.rs", "ui/issues/issue-23699.rs", -"ui/issues/issue-23808.rs", "ui/issues/issue-2380-b.rs", +"ui/issues/issue-23808.rs", "ui/issues/issue-2383.rs", "ui/issues/issue-23891.rs", "ui/issues/issue-23898.rs", @@ -1981,8 +1981,8 @@ "ui/issues/issue-25746-bool-transmute.rs", "ui/issues/issue-25757.rs", "ui/issues/issue-25810.rs", -"ui/issues/issue-25901.rs", "ui/issues/issue-2590.rs", +"ui/issues/issue-25901.rs", "ui/issues/issue-26056.rs", "ui/issues/issue-26093.rs", "ui/issues/issue-26095.rs", @@ -2041,10 +2041,10 @@ "ui/issues/issue-28433.rs", "ui/issues/issue-28472.rs", "ui/issues/issue-2848.rs", +"ui/issues/issue-2849.rs", "ui/issues/issue-28498-must-work-ex1.rs", "ui/issues/issue-28498-must-work-ex2.rs", "ui/issues/issue-28498-ugeh-ex1.rs", -"ui/issues/issue-2849.rs", "ui/issues/issue-28550.rs", "ui/issues/issue-28561.rs", "ui/issues/issue-28568.rs", @@ -2062,8 +2062,8 @@ "ui/issues/issue-28999.rs", "ui/issues/issue-29030.rs", "ui/issues/issue-29037.rs", -"ui/issues/issue-29048.rs", "ui/issues/issue-2904.rs", +"ui/issues/issue-29048.rs", "ui/issues/issue-29053.rs", "ui/issues/issue-29071-2.rs", "ui/issues/issue-29071.rs", @@ -2075,8 +2075,8 @@ "ui/issues/issue-2935.rs", "ui/issues/issue-29466.rs", "ui/issues/issue-29485.rs", -"ui/issues/issue-29516.rs", "ui/issues/issue-2951.rs", +"ui/issues/issue-29516.rs", "ui/issues/issue-29522.rs", "ui/issues/issue-29540.rs", "ui/issues/issue-29663.rs", @@ -2101,10 +2101,10 @@ "ui/issues/issue-30255.rs", "ui/issues/issue-3026.rs", "ui/issues/issue-3029.rs", -"ui/issues/issue-30371.rs", "ui/issues/issue-3037.rs", -"ui/issues/issue-30380.rs", +"ui/issues/issue-30371.rs", "ui/issues/issue-3038.rs", +"ui/issues/issue-30380.rs", "ui/issues/issue-3052.rs", "ui/issues/issue-30530.rs", "ui/issues/issue-30589.rs", @@ -2226,8 +2226,8 @@ "ui/issues/issue-37131.rs", "ui/issues/issue-37311-type-length-limit/issue-37311.rs", "ui/issues/issue-37510.rs", -"ui/issues/issue-37534.rs", "ui/issues/issue-3753.rs", +"ui/issues/issue-37534.rs", "ui/issues/issue-37576.rs", "ui/issues/issue-3763.rs", "ui/issues/issue-37665.rs", @@ -2254,8 +2254,8 @@ "ui/issues/issue-3888-2.rs", "ui/issues/issue-38919.rs", "ui/issues/issue-38942.rs", -"ui/issues/issue-38954.rs", "ui/issues/issue-3895.rs", +"ui/issues/issue-38954.rs", "ui/issues/issue-38987.rs", "ui/issues/issue-39089.rs", "ui/issues/issue-39175.rs", @@ -2265,8 +2265,8 @@ "ui/issues/issue-39687.rs", "ui/issues/issue-39709.rs", "ui/issues/issue-3979-2.rs", -"ui/issues/issue-3979.rs", "ui/issues/issue-3979-xcrate.rs", +"ui/issues/issue-3979.rs", "ui/issues/issue-39808.rs", "ui/issues/issue-39827.rs", "ui/issues/issue-39848.rs", @@ -2341,9 +2341,9 @@ "ui/issues/issue-43250.rs", "ui/issues/issue-43291.rs", "ui/issues/issue-4333.rs", +"ui/issues/issue-4335.rs", "ui/issues/issue-43355.rs", "ui/issues/issue-43357.rs", -"ui/issues/issue-4335.rs", "ui/issues/issue-43420-no-over-suggest.rs", "ui/issues/issue-43424.rs", "ui/issues/issue-43431.rs", @@ -2372,8 +2372,8 @@ "ui/issues/issue-44851.rs", "ui/issues/issue-4517.rs", "ui/issues/issue-4541.rs", -"ui/issues/issue-45425.rs", "ui/issues/issue-4542.rs", +"ui/issues/issue-45425.rs", "ui/issues/issue-4545.rs", "ui/issues/issue-45510.rs", "ui/issues/issue-45562.rs", @@ -2402,8 +2402,8 @@ "ui/issues/issue-47309.rs", "ui/issues/issue-4734.rs", "ui/issues/issue-4735.rs", -"ui/issues/issue-47364.rs", "ui/issues/issue-4736.rs", +"ui/issues/issue-47364.rs", "ui/issues/issue-47377.rs", "ui/issues/issue-47380.rs", "ui/issues/issue-47486.rs", @@ -2412,8 +2412,8 @@ "ui/issues/issue-47638.rs", "ui/issues/issue-47673.rs", "ui/issues/issue-47703-1.rs", -"ui/issues/issue-47703.rs", "ui/issues/issue-47703-tuple.rs", +"ui/issues/issue-47703.rs", "ui/issues/issue-47715.rs", "ui/issues/issue-47722.rs", "ui/issues/issue-48006.rs", @@ -2561,8 +2561,8 @@ "ui/issues/issue-59756.rs", "ui/issues/issue-5988.rs", "ui/issues/issue-5997-outer-generic-parameter/issue-5997-enum.rs", -"ui/issues/issue-5997-outer-generic-parameter/issue-5997.rs", "ui/issues/issue-5997-outer-generic-parameter/issue-5997-struct.rs", +"ui/issues/issue-5997-outer-generic-parameter/issue-5997.rs", "ui/issues/issue-60218.rs", "ui/issues/issue-60622.rs", "ui/issues/issue-60989.rs", @@ -2837,8 +2837,8 @@ "ui/lint/unused/issue-103320-must-use-ops.rs", "ui/lint/unused/issue-104397.rs", "ui/lint/unused/issue-105061-array-lint.rs", -"ui/lint/unused/issue-105061.rs", "ui/lint/unused/issue-105061-should-lint.rs", +"ui/lint/unused/issue-105061.rs", "ui/lint/unused/issue-117142-invalid-remove-parens.rs", "ui/lint/unused/issue-117284-arg-in-macro.rs", "ui/lint/unused/issue-119383-if-let-guard.rs", @@ -2862,8 +2862,8 @@ "ui/lint/use-redundant/issue-92904.rs", "ui/loops/issue-43162.rs", "ui/loops/issue-50576.rs", -"ui/loops/issue-69225-layout-repeated-checked-add.rs", "ui/loops/issue-69225-SCEVAddExpr-wrap-flag.rs", +"ui/loops/issue-69225-layout-repeated-checked-add.rs", "ui/loops/issue-82916.rs", "ui/lowering/issue-121108.rs", "ui/lowering/issue-96847.rs", @@ -3016,7 +3016,6 @@ "ui/mir/issue-29227.rs", "ui/mir/issue-46845.rs", "ui/mir/issue-60390.rs", -"ui/mir/issue66339.rs", "ui/mir/issue-66851.rs", "ui/mir/issue-66930.rs", "ui/mir/issue-67639-normalization-ice.rs", @@ -3043,6 +3042,7 @@ "ui/mir/issue-92893.rs", "ui/mir/issue-99852.rs", "ui/mir/issue-99866.rs", +"ui/mir/issue66339.rs", "ui/mir/validate/issue-95978-validator-lifetime-comparison.rs", "ui/mismatched_types/issue-106182.rs", "ui/mismatched_types/issue-112036.rs", @@ -3053,10 +3053,10 @@ "ui/mismatched_types/issue-26480.rs", "ui/mismatched_types/issue-35030.rs", "ui/mismatched_types/issue-36053-2.rs", -"ui/mismatched_types/issue-38371.rs", "ui/mismatched_types/issue-38371-unfixable.rs", -"ui/mismatched_types/issue-47706.rs", +"ui/mismatched_types/issue-38371.rs", "ui/mismatched_types/issue-47706-trait.rs", +"ui/mismatched_types/issue-47706.rs", "ui/mismatched_types/issue-74918-missing-lifetime.rs", "ui/mismatched_types/issue-75361-mismatched-impl.rs", "ui/mismatched_types/issue-84976.rs", @@ -3414,8 +3414,8 @@ "ui/parser/issues/issue-73568-lifetime-after-mut.rs", "ui/parser/issues/issue-75599.rs", "ui/parser/issues/issue-76437-async.rs", -"ui/parser/issues/issue-76437-const-async.rs", "ui/parser/issues/issue-76437-const-async-unsafe.rs", +"ui/parser/issues/issue-76437-const-async.rs", "ui/parser/issues/issue-76437-const.rs", "ui/parser/issues/issue-76437-pub-crate-unsafe.rs", "ui/parser/issues/issue-76437-unsafe.rs", @@ -3561,16 +3561,10 @@ "ui/privacy/issue-57264-2.rs", "ui/privacy/issue-75062-fieldless-tuple-struct.rs", "ui/privacy/issue-75906.rs", -"ui/privacy/issue-75907_b.rs", "ui/privacy/issue-75907.rs", +"ui/privacy/issue-75907_b.rs", "ui/privacy/issue-79593.rs", "ui/privacy/issue-92755.rs", -"ui/process/issue-13304.rs", -"ui/process/issue-14456.rs", -"ui/process/issue-14940.rs", -"ui/process/issue-16272.rs", -"ui/process/issue-20091.rs", -"ui/process/issue-30490.rs", "ui/proc-macro/auxiliary/issue-104884.rs", "ui/proc-macro/auxiliary/issue-107113.rs", "ui/proc-macro/auxiliary/issue-118809.rs", @@ -3619,8 +3613,14 @@ "ui/proc-macro/issue-86781-bad-inner-doc.rs", "ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.rs", "ui/proc-macro/issue-91800.rs", -"ui/ptr_ops/issue-80309.rs", +"ui/process/issue-13304.rs", +"ui/process/issue-14456.rs", +"ui/process/issue-14940.rs", +"ui/process/issue-16272.rs", +"ui/process/issue-20091.rs", +"ui/process/issue-30490.rs", "ui/ptr_ops/issue-80309-safe.rs", +"ui/ptr_ops/issue-80309.rs", "ui/pub/issue-33174-restricted-type-in-public-interface.rs", "ui/query-system/issue-83479.rs", "ui/range/issue-54505-no-literals.rs", @@ -3698,8 +3698,8 @@ "ui/resolve/issue-21221-3.rs", "ui/resolve/issue-21221-4.rs", "ui/resolve/issue-22692.rs", -"ui/resolve/issue-23305.rs", "ui/resolve/issue-2330.rs", +"ui/resolve/issue-23305.rs", "ui/resolve/issue-2356.rs", "ui/resolve/issue-23716.rs", "ui/resolve/issue-24968.rs", @@ -3820,10 +3820,6 @@ "ui/span/issue-25199.rs", "ui/span/issue-26656.rs", "ui/span/issue-27522.rs", -"ui/span/issue28498-reject-ex1.rs", -"ui/span/issue28498-reject-lifetime-param.rs", -"ui/span/issue28498-reject-passed-to-fn.rs", -"ui/span/issue28498-reject-trait-bound.rs", "ui/span/issue-29106.rs", "ui/span/issue-29595.rs", "ui/span/issue-33884.rs", @@ -3838,6 +3834,10 @@ "ui/span/issue-43927-non-ADT-derive.rs", "ui/span/issue-71363.rs", "ui/span/issue-81800.rs", +"ui/span/issue28498-reject-ex1.rs", +"ui/span/issue28498-reject-lifetime-param.rs", +"ui/span/issue28498-reject-passed-to-fn.rs", +"ui/span/issue28498-reject-trait-bound.rs", "ui/specialization/issue-111232.rs", "ui/specialization/issue-33017.rs", "ui/specialization/issue-35376.rs", @@ -4124,8 +4124,8 @@ "ui/traits/object/issue-44454-3.rs", "ui/traits/suggest-dereferences/issue-39029.rs", "ui/traits/suggest-dereferences/issue-62530.rs", -"ui/traits/trait-upcasting/issue-11515.rs", "ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs", +"ui/traits/trait-upcasting/issue-11515.rs", "ui/traits/vtable/issue-91807.rs", "ui/traits/vtable/issue-97381.rs", "ui/transmutability/arrays/issue-103783-array-length.rs", @@ -4163,8 +4163,8 @@ "ui/type-alias-impl-trait/issue-58951.rs", "ui/type-alias-impl-trait/issue-60371.rs", "ui/type-alias-impl-trait/issue-60407.rs", -"ui/type-alias-impl-trait/issue-60564.rs", "ui/type-alias-impl-trait/issue-60564-working.rs", +"ui/type-alias-impl-trait/issue-60564.rs", "ui/type-alias-impl-trait/issue-60662.rs", "ui/type-alias-impl-trait/issue-62000-associate-impl-trait-lifetimes.rs", "ui/type-alias-impl-trait/issue-63263-closure-return.rs", @@ -4208,10 +4208,26 @@ "ui/type-alias/issue-62263-self-in-atb.rs", "ui/type-alias/issue-62305-self-assoc-ty.rs", "ui/type-alias/issue-62364-self-ty-arg.rs", +"ui/type-inference/issue-113283-alllocator-trait-eq.rs", +"ui/type-inference/issue-30225.rs", "ui/type/ascription/issue-34255-1.rs", "ui/type/ascription/issue-47666.rs", "ui/type/ascription/issue-54516.rs", "ui/type/ascription/issue-60933.rs", +"ui/type/issue-100584.rs", +"ui/type/issue-101866.rs", +"ui/type/issue-102598.rs", +"ui/type/issue-103271.rs", +"ui/type/issue-58355.rs", +"ui/type/issue-67690-type-alias-bound-diagnostic-crash.rs", +"ui/type/issue-91268.rs", +"ui/type/issue-94187-verbose-type-name.rs", +"ui/type/type-check/issue-116967-cannot-coerce-returned-result.rs", +"ui/type/type-check/issue-22897.rs", +"ui/type/type-check/issue-40294.rs", +"ui/type/type-check/issue-41314.rs", +"ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.rs", +"ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.rs", "ui/typeck/auxiliary/issue-29181.rs", "ui/typeck/auxiliary/issue-36708.rs", "ui/typeck/auxiliary/issue-81943-lib.rs", @@ -4316,25 +4332,9 @@ "ui/typeck/issue-96738.rs", "ui/typeck/issue-98260.rs", "ui/typeck/issue-98982.rs", -"ui/type-inference/issue-113283-alllocator-trait-eq.rs", -"ui/type-inference/issue-30225.rs", -"ui/type/issue-100584.rs", -"ui/type/issue-101866.rs", -"ui/type/issue-102598.rs", -"ui/type/issue-103271.rs", -"ui/type/issue-58355.rs", -"ui/type/issue-67690-type-alias-bound-diagnostic-crash.rs", -"ui/type/issue-91268.rs", -"ui/type/issue-94187-verbose-type-name.rs", "ui/typeof/issue-100183.rs", "ui/typeof/issue-29184.rs", "ui/typeof/issue-42060.rs", -"ui/type/type-check/issue-116967-cannot-coerce-returned-result.rs", -"ui/type/type-check/issue-22897.rs", -"ui/type/type-check/issue-40294.rs", -"ui/type/type-check/issue-41314.rs", -"ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.rs", -"ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.rs", "ui/unboxed-closures/issue-18652.rs", "ui/unboxed-closures/issue-18661.rs", "ui/unboxed-closures/issue-30906.rs", @@ -4355,6 +4355,11 @@ "ui/unsafe/issue-47412.rs", "ui/unsafe/issue-85435-unsafe-op-in-let-under-unsafe-under-closure.rs", "ui/unsafe/issue-87414-query-cycle.rs", +"ui/unsized-locals/issue-30276-feature-flagged.rs", +"ui/unsized-locals/issue-30276.rs", +"ui/unsized-locals/issue-50940-with-feature.rs", +"ui/unsized-locals/issue-50940.rs", +"ui/unsized-locals/issue-67981.rs", "ui/unsized/issue-115203.rs", "ui/unsized/issue-115809.rs", "ui/unsized/issue-30355.rs", @@ -4367,11 +4372,6 @@ "ui/unsized/issue-91801.rs", "ui/unsized/issue-91803.rs", "ui/unsized/issue-97732.rs", -"ui/unsized-locals/issue-30276-feature-flagged.rs", -"ui/unsized-locals/issue-30276.rs", -"ui/unsized-locals/issue-50940.rs", -"ui/unsized-locals/issue-50940-with-feature.rs", -"ui/unsized-locals/issue-67981.rs", "ui/use/issue-18986.rs", "ui/use/issue-60976-extern-use-primitive-type.rs", "ui/wf/issue-103573.rs", diff --git a/src/tools/tidy/src/tests_revision_unpaired_stdout_stderr.rs b/src/tools/tidy/src/tests_revision_unpaired_stdout_stderr.rs index 394f95e9144d2..a0773c85bef5e 100644 --- a/src/tools/tidy/src/tests_revision_unpaired_stdout_stderr.rs +++ b/src/tools/tidy/src/tests_revision_unpaired_stdout_stderr.rs @@ -84,10 +84,16 @@ pub fn check(tests_path: impl AsRef, bad: &mut bool) { } }); - let Some((test_name, _)) = test.to_str().map(|s| s.split_once('.')).flatten() else { + let Some(test_name) = test.file_stem().map(OsStr::to_str).flatten() else { continue; }; + assert!( + !test_name.contains('.'), + "test name cannot contain dots '.': `{}`", + test.display() + ); + test_info.insert(test_name.to_string(), (test, expected_revisions)); } @@ -98,14 +104,20 @@ pub fn check(tests_path: impl AsRef, bad: &mut bool) { for sibling in files_under_inspection.iter().filter(|f| { f.extension().map(OsStr::to_str).flatten().is_some_and(|ext| EXTENSIONS.contains(&ext)) }) { - let filename_components = sibling.to_str().unwrap().split('.').collect::>(); - let file_prefix = filename_components[0]; + let Some(filename) = sibling.file_name().map(OsStr::to_str).flatten() else { + continue; + }; + + let filename_components = filename.split('.').collect::>(); + let [file_prefix, ..] = &filename_components[..] else { + continue; + }; - let Some((test_path, expected_revisions)) = test_info.get(file_prefix) else { + let Some((test_path, expected_revisions)) = test_info.get(*file_prefix) else { continue; }; - match filename_components[..] { + match &filename_components[..] { // Cannot have a revision component, skip. [] | [_] => return, [_, _] if !expected_revisions.is_empty() => { @@ -120,9 +132,9 @@ pub fn check(tests_path: impl AsRef, bad: &mut bool) { [_, _] => return, [_, found_revision, .., extension] => { if !IGNORES.contains(&found_revision) - && !expected_revisions.contains(found_revision) + && !expected_revisions.contains(*found_revision) // This is from `//@ stderr-per-bitwidth` - && !(extension == "stderr" && ["32bit", "64bit"].contains(&found_revision)) + && !(*extension == "stderr" && ["32bit", "64bit"].contains(&found_revision)) { // Found some unexpected revision-esque component that is not a known // compare-mode or expected revision. diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index a9c5be913ba1e..39b14adfea413 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -18,7 +18,7 @@ const ENTRY_LIMIT: usize = 900; // FIXME: The following limits should be reduced eventually. const ISSUES_ENTRY_LIMIT: usize = 1750; -const ROOT_ENTRY_LIMIT: usize = 872; +const ROOT_ENTRY_LIMIT: usize = 866; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ "rs", // test source files @@ -34,8 +34,8 @@ const EXTENSION_EXCEPTION_PATHS: &[&str] = &[ "tests/ui/asm/named-asm-labels.s", // loading an external asm file to test named labels lint "tests/ui/codegen/mismatched-data-layout.json", // testing mismatched data layout w/ custom targets "tests/ui/check-cfg/my-awesome-platform.json", // testing custom targets with cfgs - "tests/ui/commandline-argfile-badutf8.args", // passing args via a file - "tests/ui/commandline-argfile.args", // passing args via a file + "tests/ui/argfile/commandline-argfile-badutf8.args", // passing args via a file + "tests/ui/argfile/commandline-argfile.args", // passing args via a file "tests/ui/crate-loading/auxiliary/libfoo.rlib", // testing loading a manually created rlib "tests/ui/include-macros/data.bin", // testing including data with the include macros "tests/ui/include-macros/file.txt", // testing including data with the include macros @@ -104,9 +104,18 @@ pub fn check(path: &Path, bless: bool, bad: &mut bool) { // the list of files in ui tests that are allowed to start with `issue-XXXX` // BTreeSet because we would like a stable ordering so --bless works - let allowed_issue_names = BTreeSet::from( - include!("issues.txt").map(|path| path.replace("/", std::path::MAIN_SEPARATOR_STR)), - ); + let issues_list = + include!("issues.txt").map(|path| path.replace("/", std::path::MAIN_SEPARATOR_STR)); + let issues: Vec = Vec::from(issues_list.clone()); + let is_sorted = issues.windows(2).all(|w| w[0] < w[1]); + if !is_sorted && !bless { + tidy_error!( + bad, + "`src/tools/tidy/src/issues.txt` is not in order, mostly because you modified it manually, + please only update it with command `x test tidy --bless`" + ); + } + let allowed_issue_names = BTreeSet::from(issues_list); let mut remaining_issue_names: BTreeSet = allowed_issue_names.clone(); @@ -190,7 +199,11 @@ pub fn check(path: &Path, bless: bool, bad: &mut bool) { let blessed_issues_path = tidy_src.join("issues_blessed.txt"); let mut blessed_issues_txt = fs::File::create(&blessed_issues_path).unwrap(); blessed_issues_txt.write(issues_txt_header.as_bytes()).unwrap(); - for filename in allowed_issue_names.difference(&remaining_issue_names) { + // If we changed paths to use the OS separator, reassert Unix chauvinism for blessing. + for filename in allowed_issue_names + .difference(&remaining_issue_names) + .map(|s| s.replace(std::path::MAIN_SEPARATOR_STR, "/")) + { write!(blessed_issues_txt, "\"{filename}\",\n").unwrap(); } write!(blessed_issues_txt, "]\n").unwrap(); diff --git a/tests/assembly/stack-protector/stack-protector-target-support.rs b/tests/assembly/stack-protector/stack-protector-target-support.rs index 5fa93b3617ed9..df8a0dce40b2e 100644 --- a/tests/assembly/stack-protector/stack-protector-target-support.rs +++ b/tests/assembly/stack-protector/stack-protector-target-support.rs @@ -149,7 +149,7 @@ //@ [r71] needs-llvm-components: webassembly //@ [r72] compile-flags:--target wasm32-unknown-unknown //@ [r72] needs-llvm-components: webassembly -//@ [r73] compile-flags:--target wasm32-wasi +//@ [r73] compile-flags:--target wasm32-wasip1 //@ [r73] needs-llvm-components: webassembly //@ [r74] compile-flags:--target wasm32-wasi-preview1-threads //@ [r74] needs-llvm-components: webassembly diff --git a/tests/assembly/targets/targets-elf.rs b/tests/assembly/targets/targets-elf.rs index 4051957c22253..b0f8ebd5920b5 100644 --- a/tests/assembly/targets/targets-elf.rs +++ b/tests/assembly/targets/targets-elf.rs @@ -234,6 +234,9 @@ //@ revisions: loongarch64_unknown_linux_gnu //@ [loongarch64_unknown_linux_gnu] compile-flags: --target loongarch64-unknown-linux-gnu //@ [loongarch64_unknown_linux_gnu] needs-llvm-components: loongarch +//@ revisions: loongarch64_unknown_linux_musl +//@ [loongarch64_unknown_linux_musl] compile-flags: --target loongarch64-unknown-linux-musl +//@ [loongarch64_unknown_linux_musl] needs-llvm-components: loongarch //@ revisions: loongarch64_unknown_none //@ [loongarch64_unknown_none] compile-flags: --target loongarch64-unknown-none //@ [loongarch64_unknown_none] needs-llvm-components: loongarch @@ -486,6 +489,9 @@ //@ revisions: wasm32_wasi //@ [wasm32_wasi] compile-flags: --target wasm32-wasi //@ [wasm32_wasi] needs-llvm-components: webassembly +//@ revisions: wasm32_wasip1 +//@ [wasm32_wasip1] compile-flags: --target wasm32-wasip1 +//@ [wasm32_wasip1] needs-llvm-components: webassembly //@ revisions: wasm32_wasi_preview1_threads //@ [wasm32_wasi_preview1_threads] compile-flags: --target wasm32-wasi-preview1-threads //@ [wasm32_wasi_preview1_threads] needs-llvm-components: webassembly diff --git a/tests/assembly/targets/targets-pe.rs b/tests/assembly/targets/targets-pe.rs index 63b07ee4d1a9d..6415aee6fae90 100644 --- a/tests/assembly/targets/targets-pe.rs +++ b/tests/assembly/targets/targets-pe.rs @@ -12,6 +12,9 @@ //@ revisions: aarch64_uwp_windows_msvc //@ [aarch64_uwp_windows_msvc] compile-flags: --target aarch64-uwp-windows-msvc //@ [aarch64_uwp_windows_msvc] needs-llvm-components: aarch64 +//@ revisions: arm64ec_pc_windows_msvc +//@ [arm64ec_pc_windows_msvc] compile-flags: --target arm64ec-pc-windows-msvc +//@ [arm64ec_pc_windows_msvc] needs-llvm-components: aarch64 //@ revisions: avr_unknown_gnu_atmega328 //@ [avr_unknown_gnu_atmega328] compile-flags: --target avr-unknown-gnu-atmega328 //@ [avr_unknown_gnu_atmega328] needs-llvm-components: avr diff --git a/tests/codegen/asm-goto.rs b/tests/codegen/asm-goto.rs new file mode 100644 index 0000000000000..e522d0da5b405 --- /dev/null +++ b/tests/codegen/asm-goto.rs @@ -0,0 +1,51 @@ +//@ compile-flags: -O +//@ only-x86_64 + +#![crate_type = "rlib"] +#![feature(asm_goto)] + +use std::arch::asm; + +#[no_mangle] +pub extern "C" fn panicky() {} + +struct Foo; + +impl Drop for Foo { + fn drop(&mut self) { + println!(); + } +} + +// CHECK-LABEL: @asm_goto +#[no_mangle] +pub unsafe fn asm_goto() { + // CHECK: callbr void asm sideeffect alignstack inteldialect " + // CHECK-NEXT: to label %[[FALLTHROUGHBB:[a-b0-9]+]] [label %[[JUMPBB:[a-b0-9]+]]] + asm!("jmp {}", label {}); +} + +// CHECK-LABEL: @asm_goto_with_outputs +#[no_mangle] +pub unsafe fn asm_goto_with_outputs() -> u64 { + let out: u64; + // CHECK: [[RES:%[0-9]+]] = callbr i64 asm sideeffect alignstack inteldialect " + // CHECK-NEXT: to label %[[FALLTHROUGHBB:[a-b0-9]+]] [label %[[JUMPBB:[a-b0-9]+]]] + asm!("{} /* {} */", out(reg) out, label { return 1; }); + // CHECK: [[JUMPBB]]: + // CHECK-NEXT: [[RET:%.+]] = phi i64 [ [[RES]], %[[FALLTHROUGHBB]] ], [ 1, %start ] + // CHECK-NEXT: ret i64 [[RET]] + out +} + +// CHECK-LABEL: @asm_goto_noreturn +#[no_mangle] +pub unsafe fn asm_goto_noreturn() -> u64 { + let out: u64; + // CHECK: callbr void asm sideeffect alignstack inteldialect " + // CHECK-NEXT: to label %unreachable [label %[[JUMPBB:[a-b0-9]+]]] + asm!("jmp {}", label { return 1; }, options(noreturn)); + // CHECK: [[JUMPBB]]: + // CHECK-NEXT: ret i64 1 + out +} diff --git a/tests/codegen/cffi/c-variadic.rs b/tests/codegen/cffi/c-variadic.rs index 74aed36a8a1a5..914d1623ed230 100644 --- a/tests/codegen/cffi/c-variadic.rs +++ b/tests/codegen/cffi/c-variadic.rs @@ -1,4 +1,4 @@ -//@ ignore-wasm32-bare compiled with panic=abort by default +//@ needs-unwind //@ compile-flags: -C no-prepopulate-passes -Copt-level=0 // diff --git a/tests/codegen/dst-offset.rs b/tests/codegen/dst-offset.rs new file mode 100644 index 0000000000000..f0157e5a10646 --- /dev/null +++ b/tests/codegen/dst-offset.rs @@ -0,0 +1,84 @@ +//! This file tests that we correctly generate GEP instructions for DST +//! field offsets. +//@ compile-flags: -C no-prepopulate-passes -Copt-level=0 + +#![crate_type = "lib"] + +#![feature(extern_types)] + +use std::ptr::addr_of; + +// Hack to get the correct type for usize +// CHECK: @helper([[USIZE:i[0-9]+]] %_1) +#[no_mangle] +pub fn helper(_: usize) { +} + +struct Dst { + x: u32, + y: u8, + z: T, +} + +// CHECK: @dst_dyn_trait_offset(ptr align {{[0-9]+}} [[DATA_PTR:%.+]], ptr align {{[0-9]+}} [[VTABLE_PTR:%.+]]) +#[no_mangle] +pub fn dst_dyn_trait_offset(s: &Dst) -> &dyn Drop { +// The alignment of dyn trait is unknown, so we compute the offset based on align from the vtable. + +// CHECK: [[SIZE_PTR:%[0-9]+]] = getelementptr inbounds {{.+}} [[VTABLE_PTR]] +// CHECK: load [[USIZE]], ptr [[SIZE_PTR]] +// CHECK: [[ALIGN_PTR:%[0-9]+]] = getelementptr inbounds {{.+}} [[VTABLE_PTR]] +// CHECK: load [[USIZE]], ptr [[ALIGN_PTR]] + +// CHECK: getelementptr inbounds i8, ptr [[DATA_PTR]] +// CHECK-NEXT: insertvalue +// CHECK-NEXT: insertvalue +// CHECK-NEXT: ret + &s.z +} + +// CHECK-LABEL: @dst_slice_offset +#[no_mangle] +pub fn dst_slice_offset(s: &Dst<[u16]>) -> &[u16] { +// The alignment of [u16] is known, so we generate a GEP directly. + +// CHECK: start: +// CHECK-NEXT: getelementptr inbounds i8, {{.+}}, [[USIZE]] 6 +// CHECK-NEXT: insertvalue +// CHECK-NEXT: insertvalue +// CHECK-NEXT: ret + &s.z +} + +#[repr(packed)] +struct PackedDstSlice { + x: u32, + y: u8, + z: [u16], +} + +// CHECK-LABEL: @packed_dst_slice_offset +#[no_mangle] +pub fn packed_dst_slice_offset(s: &PackedDstSlice) -> *const [u16] { +// The alignment of [u16] is known, so we generate a GEP directly. + +// CHECK: start: +// CHECK-NEXT: getelementptr inbounds i8, {{.+}}, [[USIZE]] 5 +// CHECK-NEXT: insertvalue +// CHECK-NEXT: insertvalue +// CHECK-NEXT: ret + addr_of!(s.z) +} + +extern { + pub type Extern; +} + +// CHECK-LABEL: @dst_extern +#[no_mangle] +pub fn dst_extern(s: &Dst) -> &Extern { +// Computing the alignment of an extern type is currently unsupported and just panics. + +// CHECK: call void @{{.+}}panic + &s.z +} diff --git a/tests/codegen/enum/uninhabited_enum_default_branch.rs b/tests/codegen/enum/uninhabited_enum_default_branch.rs new file mode 100644 index 0000000000000..5f318f18dec68 --- /dev/null +++ b/tests/codegen/enum/uninhabited_enum_default_branch.rs @@ -0,0 +1,24 @@ +//@ compile-flags: -O + +#![crate_type = "lib"] + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +pub struct Int(u32); + +const A: Int = Int(201); +const B: Int = Int(270); +const C: Int = Int(153); + +// CHECK-LABEL: @foo( +// CHECK-SAME: [[TMP0:%.*]]) +// CHECK-NEXT: start: +// CHECK-NEXT: [[TMP1:%.*]] = add i32 [[TMP0]], -201 +// CHECK-NEXT: icmp ult i32 [[TMP1]], 70 +// CHECK-NEXT: icmp eq i32 [[TMP0]], 153 +// CHECK-NEXT: [[SPEC_SELECT:%.*]] = or i1 +// CHECK-NEXT: ret i1 [[SPEC_SELECT]] +#[no_mangle] +pub fn foo(x: Int) -> bool { + (x >= A && x <= B) + || x == C +} diff --git a/tests/codegen/function-arguments.rs b/tests/codegen/function-arguments.rs index b75c188f51a9b..e6e2f64571497 100644 --- a/tests/codegen/function-arguments.rs +++ b/tests/codegen/function-arguments.rs @@ -2,6 +2,7 @@ #![crate_type = "lib"] #![feature(dyn_star)] #![feature(generic_nonzero)] +#![feature(allocator_api)] use std::mem::MaybeUninit; use std::num::NonZero; @@ -182,6 +183,15 @@ pub fn _box(x: Box) -> Box { x } +// With a custom allocator, it should *not* have `noalias`. (See +// for why.) The second argument is the allocator, +// which is a reference here that still carries `noalias` as usual. +// CHECK: @_box_custom(ptr noundef nonnull align 4 %x.0, ptr noalias noundef nonnull readonly align 1 %x.1) +#[no_mangle] +pub fn _box_custom(x: Box) { + drop(x) +} + // CHECK: noundef nonnull align 4 ptr @notunpin_box(ptr noundef nonnull align 4 %x) #[no_mangle] pub fn notunpin_box(x: Box) -> Box { diff --git a/tests/codegen/zst-offset.rs b/tests/codegen/zst-offset.rs index 65d9cf39c4c61..b623d492d9d69 100644 --- a/tests/codegen/zst-offset.rs +++ b/tests/codegen/zst-offset.rs @@ -13,7 +13,7 @@ pub fn helper(_: usize) { // CHECK-LABEL: @scalar_layout #[no_mangle] pub fn scalar_layout(s: &(u64, ())) { -// CHECK: getelementptr i8, {{.+}}, [[USIZE]] 8 +// CHECK: getelementptr inbounds i8, {{.+}}, [[USIZE]] 8 let x = &s.1; witness(&x); // keep variable in an alloca } @@ -22,7 +22,7 @@ pub fn scalar_layout(s: &(u64, ())) { // CHECK-LABEL: @scalarpair_layout #[no_mangle] pub fn scalarpair_layout(s: &(u64, u32, ())) { -// CHECK: getelementptr i8, {{.+}}, [[USIZE]] 12 +// CHECK: getelementptr inbounds i8, {{.+}}, [[USIZE]] 12 let x = &s.2; witness(&x); // keep variable in an alloca } @@ -34,7 +34,7 @@ pub struct U64x4(u64, u64, u64, u64); // CHECK-LABEL: @vector_layout #[no_mangle] pub fn vector_layout(s: &(U64x4, ())) { -// CHECK: getelementptr i8, {{.+}}, [[USIZE]] 32 +// CHECK: getelementptr inbounds i8, {{.+}}, [[USIZE]] 32 let x = &s.1; witness(&x); // keep variable in an alloca } diff --git a/tests/debuginfo/mutex.rs b/tests/debuginfo/mutex.rs index 1201da0dd7b86..affc1558ffa94 100644 --- a/tests/debuginfo/mutex.rs +++ b/tests/debuginfo/mutex.rs @@ -10,7 +10,7 @@ // // cdb-command:dx m,d // cdb-check:m,d [Type: std::sync::mutex::Mutex] -// cdb-check: [...] inner [Type: std::sys::locks::mutex::windows::Mutex] +// cdb-check: [...] inner [Type: std::sys::locks::mutex::futex::Mutex] // cdb-check: [...] poison [Type: std::sync::poison::Flag] // cdb-check: [...] data : 0 [Type: core::cell::UnsafeCell] diff --git a/tests/debuginfo/rwlock-read.rs b/tests/debuginfo/rwlock-read.rs index 7abbfd70ffb1c..76dbc73a1e940 100644 --- a/tests/debuginfo/rwlock-read.rs +++ b/tests/debuginfo/rwlock-read.rs @@ -16,7 +16,7 @@ // cdb-command:dx r // cdb-check:r [Type: std::sync::rwlock::RwLockReadGuard] // cdb-check: [...] data : NonNull([...]: 0) [Type: core::ptr::non_null::NonNull] -// cdb-check: [...] inner_lock : [...] [Type: std::sys::locks::rwlock::windows::RwLock *] +// cdb-check: [...] inner_lock : [...] [Type: std::sys::locks::rwlock::futex::RwLock *] #[allow(unused_variables)] diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff index 080478ea88419..bd346af6d16e4 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff @@ -69,7 +69,7 @@ StorageLive(_6); _6 = ((*_1).4: std::option::Option); _7 = discriminant(_6); - switchInt(move _7) -> [1: bb4, otherwise: bb6]; + switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb9]; } bb4: { @@ -135,5 +135,9 @@ StorageDead(_6); return; } + + bb9: { + unreachable; + } } diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff index ff8933fca8b2c..422cbeaa224ea 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff @@ -69,7 +69,7 @@ StorageLive(_6); _6 = ((*_1).4: std::option::Option); _7 = discriminant(_6); - switchInt(move _7) -> [1: bb4, otherwise: bb6]; + switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb9]; } bb4: { @@ -135,5 +135,9 @@ StorageDead(_6); return; } + + bb9: { + unreachable; + } } diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir index f7be8b75db7b8..bc12002490a16 100644 --- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir @@ -33,13 +33,13 @@ fn num_to_digit(_1: char) -> u32 { _3 = &_2; StorageLive(_4); _4 = discriminant(_2); - StorageDead(_3); - StorageDead(_2); - switchInt(move _4) -> [1: bb2, otherwise: bb7]; + switchInt(move _4) -> [1: bb2, 0: bb6, otherwise: bb8]; } bb2: { StorageDead(_4); + StorageDead(_3); + StorageDead(_2); StorageLive(_5); _5 = char::methods::::to_digit(move _1, const 8_u32) -> [return: bb3, unwind unreachable]; } @@ -47,7 +47,7 @@ fn num_to_digit(_1: char) -> u32 { bb3: { StorageLive(_6); _6 = discriminant(_5); - switchInt(move _6) -> [0: bb4, 1: bb5, otherwise: bb6]; + switchInt(move _6) -> [0: bb4, 1: bb5, otherwise: bb8]; } bb4: { @@ -58,20 +58,22 @@ fn num_to_digit(_1: char) -> u32 { _0 = move ((_5 as Some).0: u32); StorageDead(_6); StorageDead(_5); - goto -> bb8; + goto -> bb7; } bb6: { - unreachable; + StorageDead(_4); + StorageDead(_3); + StorageDead(_2); + _0 = const 0_u32; + goto -> bb7; } bb7: { - StorageDead(_4); - _0 = const 0_u32; - goto -> bb8; + return; } bb8: { - return; + unreachable; } } diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir index e76fe992ac7d3..6c7e10a45250a 100644 --- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir @@ -33,13 +33,13 @@ fn num_to_digit(_1: char) -> u32 { _3 = &_2; StorageLive(_4); _4 = discriminant(_2); - StorageDead(_3); - StorageDead(_2); - switchInt(move _4) -> [1: bb2, otherwise: bb7]; + switchInt(move _4) -> [1: bb2, 0: bb6, otherwise: bb8]; } bb2: { StorageDead(_4); + StorageDead(_3); + StorageDead(_2); StorageLive(_5); _5 = char::methods::::to_digit(move _1, const 8_u32) -> [return: bb3, unwind continue]; } @@ -47,7 +47,7 @@ fn num_to_digit(_1: char) -> u32 { bb3: { StorageLive(_6); _6 = discriminant(_5); - switchInt(move _6) -> [0: bb4, 1: bb5, otherwise: bb6]; + switchInt(move _6) -> [0: bb4, 1: bb5, otherwise: bb8]; } bb4: { @@ -58,20 +58,22 @@ fn num_to_digit(_1: char) -> u32 { _0 = move ((_5 as Some).0: u32); StorageDead(_6); StorageDead(_5); - goto -> bb8; + goto -> bb7; } bb6: { - unreachable; + StorageDead(_4); + StorageDead(_3); + StorageDead(_2); + _0 = const 0_u32; + goto -> bb7; } bb7: { - StorageDead(_4); - _0 = const 0_u32; - goto -> bb8; + return; } bb8: { - return; + unreachable; } } diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff index 5c586fbc2fc41..84181462f6732 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff @@ -58,16 +58,20 @@ + _2 = const Option::::None; StorageLive(_10); - _10 = discriminant(_2); -- switchInt(move _10) -> [0: bb1, 1: bb2, otherwise: bb6]; +- switchInt(move _10) -> [0: bb2, 1: bb3, otherwise: bb1]; + _10 = const 0_isize; -+ switchInt(const 0_isize) -> [0: bb1, 1: bb2, otherwise: bb6]; ++ switchInt(const 0_isize) -> [0: bb2, 1: bb3, otherwise: bb1]; } bb1: { - _11 = option::unwrap_failed() -> unwind unreachable; + unreachable; } bb2: { + _11 = option::unwrap_failed() -> unwind unreachable; + } + + bb3: { - _1 = move ((_2 as Some).0: std::alloc::Layout); + _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}; StorageDead(_10); @@ -82,21 +86,21 @@ + _7 = const {ALLOC1: &std::alloc::Global}; StorageLive(_8); - _8 = _1; -- _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb3, unwind unreachable]; +- _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb4, unwind unreachable]; + _8 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}; -+ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb3, unwind unreachable]; ++ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb4, unwind unreachable]; } - bb3: { + bb4: { StorageDead(_8); StorageDead(_7); StorageLive(_12); StorageLive(_15); _12 = discriminant(_6); - switchInt(move _12) -> [0: bb5, 1: bb4, otherwise: bb6]; + switchInt(move _12) -> [0: bb6, 1: bb5, otherwise: bb1]; } - bb4: { + bb5: { _15 = const "called `Result::unwrap()` on an `Err` value"; StorageLive(_16); StorageLive(_17); @@ -106,7 +110,7 @@ _14 = result::unwrap_failed(move _15, move _16) -> unwind unreachable; } - bb5: { + bb6: { _5 = move ((_6 as Ok).0: std::ptr::NonNull<[u8]>); StorageDead(_15); StorageDead(_12); @@ -127,10 +131,6 @@ + nop; return; } - - bb6: { - unreachable; - } } + + ALLOC0 (size: 8, align: 4) { diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff index bfb2319dac15a..820d02e26cd01 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff @@ -43,9 +43,9 @@ + _2 = const Option::::None; StorageLive(_10); - _10 = discriminant(_2); -- switchInt(move _10) -> [0: bb2, 1: bb3, otherwise: bb5]; +- switchInt(move _10) -> [0: bb3, 1: bb4, otherwise: bb2]; + _10 = const 0_isize; -+ switchInt(const 0_isize) -> [0: bb2, 1: bb3, otherwise: bb5]; ++ switchInt(const 0_isize) -> [0: bb3, 1: bb4, otherwise: bb2]; } bb1: { @@ -68,10 +68,14 @@ } bb2: { - _11 = option::unwrap_failed() -> unwind continue; + unreachable; } bb3: { + _11 = option::unwrap_failed() -> unwind continue; + } + + bb4: { - _1 = move ((_2 as Some).0: std::alloc::Layout); + _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}; StorageDead(_10); @@ -86,20 +90,16 @@ + _7 = const {ALLOC1: &std::alloc::Global}; StorageLive(_8); - _8 = _1; -- _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb4, unwind continue]; +- _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb5, unwind continue]; + _8 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}; -+ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb4, unwind continue]; ++ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb5, unwind continue]; } - bb4: { + bb5: { StorageDead(_8); StorageDead(_7); _5 = Result::, std::alloc::AllocError>::unwrap(move _6) -> [return: bb1, unwind continue]; } - - bb5: { - unreachable; - } } + + ALLOC0 (size: 8, align: 4) { diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff index ce55a8265e580..f478f7cb9038c 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff @@ -58,16 +58,20 @@ + _2 = const Option::::None; StorageLive(_10); - _10 = discriminant(_2); -- switchInt(move _10) -> [0: bb1, 1: bb2, otherwise: bb6]; +- switchInt(move _10) -> [0: bb2, 1: bb3, otherwise: bb1]; + _10 = const 0_isize; -+ switchInt(const 0_isize) -> [0: bb1, 1: bb2, otherwise: bb6]; ++ switchInt(const 0_isize) -> [0: bb2, 1: bb3, otherwise: bb1]; } bb1: { - _11 = option::unwrap_failed() -> unwind unreachable; + unreachable; } bb2: { + _11 = option::unwrap_failed() -> unwind unreachable; + } + + bb3: { - _1 = move ((_2 as Some).0: std::alloc::Layout); + _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}; StorageDead(_10); @@ -82,21 +86,21 @@ + _7 = const {ALLOC1: &std::alloc::Global}; StorageLive(_8); - _8 = _1; -- _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb3, unwind unreachable]; +- _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb4, unwind unreachable]; + _8 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}; -+ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb3, unwind unreachable]; ++ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb4, unwind unreachable]; } - bb3: { + bb4: { StorageDead(_8); StorageDead(_7); StorageLive(_12); StorageLive(_15); _12 = discriminant(_6); - switchInt(move _12) -> [0: bb5, 1: bb4, otherwise: bb6]; + switchInt(move _12) -> [0: bb6, 1: bb5, otherwise: bb1]; } - bb4: { + bb5: { _15 = const "called `Result::unwrap()` on an `Err` value"; StorageLive(_16); StorageLive(_17); @@ -106,7 +110,7 @@ _14 = result::unwrap_failed(move _15, move _16) -> unwind unreachable; } - bb5: { + bb6: { _5 = move ((_6 as Ok).0: std::ptr::NonNull<[u8]>); StorageDead(_15); StorageDead(_12); @@ -127,10 +131,6 @@ + nop; return; } - - bb6: { - unreachable; - } } + + ALLOC0 (size: 16, align: 8) { diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff index ddf4223bb491a..1fba8b5059a4c 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff @@ -43,9 +43,9 @@ + _2 = const Option::::None; StorageLive(_10); - _10 = discriminant(_2); -- switchInt(move _10) -> [0: bb2, 1: bb3, otherwise: bb5]; +- switchInt(move _10) -> [0: bb3, 1: bb4, otherwise: bb2]; + _10 = const 0_isize; -+ switchInt(const 0_isize) -> [0: bb2, 1: bb3, otherwise: bb5]; ++ switchInt(const 0_isize) -> [0: bb3, 1: bb4, otherwise: bb2]; } bb1: { @@ -68,10 +68,14 @@ } bb2: { - _11 = option::unwrap_failed() -> unwind continue; + unreachable; } bb3: { + _11 = option::unwrap_failed() -> unwind continue; + } + + bb4: { - _1 = move ((_2 as Some).0: std::alloc::Layout); + _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}; StorageDead(_10); @@ -86,20 +90,16 @@ + _7 = const {ALLOC1: &std::alloc::Global}; StorageLive(_8); - _8 = _1; -- _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb4, unwind continue]; +- _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb5, unwind continue]; + _8 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}; -+ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb4, unwind continue]; ++ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb5, unwind continue]; } - bb4: { + bb5: { StorageDead(_8); StorageDead(_7); _5 = Result::, std::alloc::AllocError>::unwrap(move _6) -> [return: bb1, unwind continue]; } - - bb5: { - unreachable; - } } + + ALLOC0 (size: 16, align: 8) { diff --git a/tests/mir-opt/separate_const_switch.identity.JumpThreading.diff b/tests/mir-opt/separate_const_switch.identity.JumpThreading.diff index ab3d91ab91887..d0abebff214d3 100644 --- a/tests/mir-opt/separate_const_switch.identity.JumpThreading.diff +++ b/tests/mir-opt/separate_const_switch.identity.JumpThreading.diff @@ -52,17 +52,21 @@ StorageLive(_9); StorageLive(_10); _8 = discriminant(_1); - switchInt(move _8) -> [0: bb5, 1: bb4, otherwise: bb6]; + switchInt(move _8) -> [0: bb6, 1: bb5, otherwise: bb1]; } bb1: { + unreachable; + } + + bb2: { _7 = ((_2 as Continue).0: i32); _0 = Result::::Ok(_7); StorageDead(_2); return; } - bb2: { + bb3: { _5 = ((_2 as Break).0: std::result::Result); StorageLive(_6); _6 = _5; @@ -73,34 +77,30 @@ return; } - bb3: { + bb4: { StorageDead(_10); StorageDead(_9); StorageDead(_8); StorageDead(_3); _4 = discriminant(_2); -- switchInt(move _4) -> [0: bb1, 1: bb2, otherwise: bb6]; -+ goto -> bb1; +- switchInt(move _4) -> [0: bb2, 1: bb3, otherwise: bb1]; ++ goto -> bb2; } - bb4: { + bb5: { _10 = ((_1 as Err).0: i32); StorageLive(_11); _11 = Result::::Err(_10); _2 = ControlFlow::, i32>::Break(move _11); StorageDead(_11); -- goto -> bb3; +- goto -> bb4; + goto -> bb7; } - bb5: { + bb6: { _9 = ((_1 as Ok).0: i32); _2 = ControlFlow::, i32>::Continue(_9); - goto -> bb3; - } - - bb6: { - unreachable; + goto -> bb4; + } + + bb7: { @@ -109,7 +109,7 @@ + StorageDead(_8); + StorageDead(_3); + _4 = discriminant(_2); -+ goto -> bb2; ++ goto -> bb3; } } diff --git a/tests/mir-opt/separate_const_switch.too_complex.JumpThreading.diff b/tests/mir-opt/separate_const_switch.too_complex.JumpThreading.diff index 1ac527e9338a1..f749586299221 100644 --- a/tests/mir-opt/separate_const_switch.too_complex.JumpThreading.diff +++ b/tests/mir-opt/separate_const_switch.too_complex.JumpThreading.diff @@ -27,54 +27,54 @@ bb0: { StorageLive(_2); _3 = discriminant(_1); - switchInt(move _3) -> [0: bb2, 1: bb1, otherwise: bb7]; + switchInt(move _3) -> [0: bb3, 1: bb2, otherwise: bb1]; } bb1: { + unreachable; + } + + bb2: { _5 = ((_1 as Err).0: usize); _2 = ControlFlow::::Break(_5); -- goto -> bb3; +- goto -> bb4; + goto -> bb8; } - bb2: { + bb3: { _4 = ((_1 as Ok).0: i32); _2 = ControlFlow::::Continue(_4); - goto -> bb3; + goto -> bb4; } - bb3: { + bb4: { _6 = discriminant(_2); -- switchInt(move _6) -> [0: bb5, 1: bb4, otherwise: bb7]; -+ goto -> bb5; +- switchInt(move _6) -> [0: bb6, 1: bb5, otherwise: bb1]; ++ goto -> bb6; } - bb4: { + bb5: { StorageLive(_8); _8 = ((_2 as Break).0: usize); _0 = const Option::::None; StorageDead(_8); - goto -> bb6; + goto -> bb7; } - bb5: { + bb6: { _7 = ((_2 as Continue).0: i32); _0 = Option::::Some(_7); - goto -> bb6; + goto -> bb7; } - bb6: { + bb7: { StorageDead(_2); return; - } - - bb7: { - unreachable; + } + + bb8: { + _6 = discriminant(_2); -+ goto -> bb4; ++ goto -> bb5; } } diff --git a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff index 1566d7197acd8..c520a159f47b2 100644 --- a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff +++ b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff @@ -23,12 +23,12 @@ StorageDead(_3); StorageDead(_2); _5 = discriminant((_1.0: std::option::Option)); - switchInt(move _5) -> [1: bb1, otherwise: bb3]; + switchInt(move _5) -> [1: bb1, 0: bb3, otherwise: bb5]; } bb1: { _4 = discriminant((_1.1: std::option::Option)); - switchInt(move _4) -> [0: bb2, otherwise: bb3]; + switchInt(move _4) -> [0: bb2, 1: bb3, otherwise: bb5]; } bb2: { @@ -46,5 +46,9 @@ StorageDead(_1); return; } + + bb5: { + unreachable; + } } diff --git a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff index ba5262b0ee143..686581591fc4e 100644 --- a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff +++ b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff @@ -23,12 +23,12 @@ StorageDead(_3); StorageDead(_2); _5 = discriminant((_1.0: std::option::Option)); - switchInt(move _5) -> [1: bb1, otherwise: bb3]; + switchInt(move _5) -> [1: bb1, 0: bb3, otherwise: bb5]; } bb1: { _4 = discriminant((_1.1: std::option::Option)); - switchInt(move _4) -> [0: bb2, otherwise: bb3]; + switchInt(move _4) -> [0: bb2, 1: bb3, otherwise: bb5]; } bb2: { @@ -46,5 +46,9 @@ StorageDead(_1); return; } + + bb5: { + unreachable; + } } diff --git a/tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.diff b/tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-abort.diff similarity index 91% rename from tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.diff rename to tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-abort.diff index 5a3544f85387b..1b7517c8d0107 100644 --- a/tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.diff +++ b/tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-abort.diff @@ -31,7 +31,7 @@ _4 = &(_1.1: Test3); _5 = discriminant((*_4)); - switchInt(move _5) -> [0: bb3, 1: bb4, 2: bb5, 3: bb2, otherwise: bb1]; -+ switchInt(move _5) -> [0: bb12, 1: bb12, 2: bb5, 3: bb2, otherwise: bb12]; ++ switchInt(move _5) -> [0: bb1, 1: bb1, 2: bb5, 3: bb2, otherwise: bb1]; } bb1: { @@ -73,7 +73,7 @@ StorageLive(_9); _10 = discriminant((_1.1: Test3)); - switchInt(move _10) -> [0: bb8, 1: bb9, 2: bb10, 3: bb7, otherwise: bb1]; -+ switchInt(move _10) -> [0: bb12, 1: bb12, 2: bb10, 3: bb7, otherwise: bb12]; ++ switchInt(move _10) -> [0: bb1, 1: bb1, 2: bb10, 3: bb7, otherwise: bb1]; } bb7: { @@ -110,10 +110,6 @@ _0 = const (); StorageDead(_1); return; -+ } -+ -+ bb12: { -+ unreachable; } } diff --git a/tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-unwind.diff new file mode 100644 index 0000000000000..1b7517c8d0107 --- /dev/null +++ b/tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-unwind.diff @@ -0,0 +1,115 @@ +- // MIR for `byref` before UninhabitedEnumBranching ++ // MIR for `byref` after UninhabitedEnumBranching + + fn byref() -> () { + let mut _0: (); + let _1: Plop; + let mut _2: Test3; + let _3: &str; + let mut _4: &Test3; + let mut _5: isize; + let _6: &str; + let _7: &str; + let _8: &str; + let _9: &str; + let mut _10: isize; + let _11: &str; + let _12: &str; + let _13: &str; + scope 1 { + debug plop => _1; + } + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test3::C; + _1 = Plop { xx: const 51_u32, test3: move _2 }; + StorageDead(_2); + StorageLive(_3); + StorageLive(_4); + _4 = &(_1.1: Test3); + _5 = discriminant((*_4)); +- switchInt(move _5) -> [0: bb3, 1: bb4, 2: bb5, 3: bb2, otherwise: bb1]; ++ switchInt(move _5) -> [0: bb1, 1: bb1, 2: bb5, 3: bb2, otherwise: bb1]; + } + + bb1: { + unreachable; + } + + bb2: { + StorageLive(_8); + _8 = const "D"; + _3 = &(*_8); + StorageDead(_8); + goto -> bb6; + } + + bb3: { + _3 = const "A(Empty)"; + goto -> bb6; + } + + bb4: { + StorageLive(_6); + _6 = const "B(Empty)"; + _3 = &(*_6); + StorageDead(_6); + goto -> bb6; + } + + bb5: { + StorageLive(_7); + _7 = const "C"; + _3 = &(*_7); + StorageDead(_7); + goto -> bb6; + } + + bb6: { + StorageDead(_4); + StorageDead(_3); + StorageLive(_9); + _10 = discriminant((_1.1: Test3)); +- switchInt(move _10) -> [0: bb8, 1: bb9, 2: bb10, 3: bb7, otherwise: bb1]; ++ switchInt(move _10) -> [0: bb1, 1: bb1, 2: bb10, 3: bb7, otherwise: bb1]; + } + + bb7: { + StorageLive(_13); + _13 = const "D"; + _9 = &(*_13); + StorageDead(_13); + goto -> bb11; + } + + bb8: { + _9 = const "A(Empty)"; + goto -> bb11; + } + + bb9: { + StorageLive(_11); + _11 = const "B(Empty)"; + _9 = &(*_11); + StorageDead(_11); + goto -> bb11; + } + + bb10: { + StorageLive(_12); + _12 = const "C"; + _9 = &(*_12); + StorageDead(_12); + goto -> bb11; + } + + bb11: { + StorageDead(_9); + _0 = const (); + StorageDead(_1); + return; + } + } + diff --git a/tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.diff b/tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-abort.diff similarity index 82% rename from tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.diff rename to tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-abort.diff index 121374553ed87..f9a43480917e6 100644 --- a/tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.diff +++ b/tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-abort.diff @@ -13,8 +13,7 @@ StorageLive(_2); _2 = Test2::D; _3 = discriminant(_2); -- switchInt(move _3) -> [4: bb3, 5: bb2, otherwise: bb1]; -+ switchInt(move _3) -> [4: bb3, 5: bb2, otherwise: bb5]; + switchInt(move _3) -> [4: bb3, 5: bb2, otherwise: bb1]; } bb1: { @@ -39,10 +38,6 @@ StorageDead(_1); _0 = const (); return; -+ } -+ -+ bb5: { -+ unreachable; } } diff --git a/tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-unwind.diff new file mode 100644 index 0000000000000..f9a43480917e6 --- /dev/null +++ b/tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-unwind.diff @@ -0,0 +1,43 @@ +- // MIR for `custom_discriminant` before UninhabitedEnumBranching ++ // MIR for `custom_discriminant` after UninhabitedEnumBranching + + fn custom_discriminant() -> () { + let mut _0: (); + let _1: &str; + let mut _2: Test2; + let mut _3: isize; + let _4: &str; + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test2::D; + _3 = discriminant(_2); + switchInt(move _3) -> [4: bb3, 5: bb2, otherwise: bb1]; + } + + bb1: { + unreachable; + } + + bb2: { + StorageLive(_4); + _4 = const "E"; + _1 = &(*_4); + StorageDead(_4); + goto -> bb4; + } + + bb3: { + _1 = const "D"; + goto -> bb4; + } + + bb4: { + StorageDead(_2); + StorageDead(_1); + _0 = const (); + return; + } + } + diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-abort.diff new file mode 100644 index 0000000000000..383fde4d787b9 --- /dev/null +++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-abort.diff @@ -0,0 +1,53 @@ +- // MIR for `otherwise_t1` before UninhabitedEnumBranching ++ // MIR for `otherwise_t1` after UninhabitedEnumBranching + + fn otherwise_t1() -> () { + let mut _0: (); + let _1: &str; + let mut _2: Test1; + let mut _3: isize; + let _4: &str; + let _5: &str; + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test1::C; + _3 = discriminant(_2); +- switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1]; ++ switchInt(move _3) -> [0: bb5, 1: bb5, 2: bb1, otherwise: bb5]; + } + + bb1: { + StorageLive(_5); + _5 = const "C"; + _1 = &(*_5); + StorageDead(_5); + goto -> bb4; + } + + bb2: { + _1 = const "A(Empty)"; + goto -> bb4; + } + + bb3: { + StorageLive(_4); + _4 = const "B(Empty)"; + _1 = &(*_4); + StorageDead(_4); + goto -> bb4; + } + + bb4: { + StorageDead(_2); + StorageDead(_1); + _0 = const (); + return; ++ } ++ ++ bb5: { ++ unreachable; + } + } + diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-unwind.diff new file mode 100644 index 0000000000000..383fde4d787b9 --- /dev/null +++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-unwind.diff @@ -0,0 +1,53 @@ +- // MIR for `otherwise_t1` before UninhabitedEnumBranching ++ // MIR for `otherwise_t1` after UninhabitedEnumBranching + + fn otherwise_t1() -> () { + let mut _0: (); + let _1: &str; + let mut _2: Test1; + let mut _3: isize; + let _4: &str; + let _5: &str; + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test1::C; + _3 = discriminant(_2); +- switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1]; ++ switchInt(move _3) -> [0: bb5, 1: bb5, 2: bb1, otherwise: bb5]; + } + + bb1: { + StorageLive(_5); + _5 = const "C"; + _1 = &(*_5); + StorageDead(_5); + goto -> bb4; + } + + bb2: { + _1 = const "A(Empty)"; + goto -> bb4; + } + + bb3: { + StorageLive(_4); + _4 = const "B(Empty)"; + _1 = &(*_4); + StorageDead(_4); + goto -> bb4; + } + + bb4: { + StorageDead(_2); + StorageDead(_1); + _0 = const (); + return; ++ } ++ ++ bb5: { ++ unreachable; + } + } + diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-abort.diff new file mode 100644 index 0000000000000..3a2dc19db71cd --- /dev/null +++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-abort.diff @@ -0,0 +1,44 @@ +- // MIR for `otherwise_t2` before UninhabitedEnumBranching ++ // MIR for `otherwise_t2` after UninhabitedEnumBranching + + fn otherwise_t2() -> () { + let mut _0: (); + let _1: &str; + let mut _2: Test2; + let mut _3: isize; + let _4: &str; + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test2::D; + _3 = discriminant(_2); +- switchInt(move _3) -> [4: bb2, otherwise: bb1]; ++ switchInt(move _3) -> [4: bb2, 5: bb1, otherwise: bb4]; + } + + bb1: { + StorageLive(_4); + _4 = const "E"; + _1 = &(*_4); + StorageDead(_4); + goto -> bb3; + } + + bb2: { + _1 = const "D"; + goto -> bb3; + } + + bb3: { + StorageDead(_2); + StorageDead(_1); + _0 = const (); + return; ++ } ++ ++ bb4: { ++ unreachable; + } + } + diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-unwind.diff new file mode 100644 index 0000000000000..3a2dc19db71cd --- /dev/null +++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-unwind.diff @@ -0,0 +1,44 @@ +- // MIR for `otherwise_t2` before UninhabitedEnumBranching ++ // MIR for `otherwise_t2` after UninhabitedEnumBranching + + fn otherwise_t2() -> () { + let mut _0: (); + let _1: &str; + let mut _2: Test2; + let mut _3: isize; + let _4: &str; + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test2::D; + _3 = discriminant(_2); +- switchInt(move _3) -> [4: bb2, otherwise: bb1]; ++ switchInt(move _3) -> [4: bb2, 5: bb1, otherwise: bb4]; + } + + bb1: { + StorageLive(_4); + _4 = const "E"; + _1 = &(*_4); + StorageDead(_4); + goto -> bb3; + } + + bb2: { + _1 = const "D"; + goto -> bb3; + } + + bb3: { + StorageDead(_2); + StorageDead(_1); + _0 = const (); + return; ++ } ++ ++ bb4: { ++ unreachable; + } + } + diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-abort.diff new file mode 100644 index 0000000000000..5dc1e2b73f6a4 --- /dev/null +++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-abort.diff @@ -0,0 +1,53 @@ +- // MIR for `otherwise_t3` before UninhabitedEnumBranching ++ // MIR for `otherwise_t3` after UninhabitedEnumBranching + + fn otherwise_t3() -> () { + let mut _0: (); + let _1: &str; + let mut _2: Test3; + let mut _3: isize; + let _4: &str; + let _5: &str; + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test3::C; + _3 = discriminant(_2); +- switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1]; ++ switchInt(move _3) -> [0: bb5, 1: bb5, otherwise: bb1]; + } + + bb1: { + StorageLive(_5); + _5 = const "C"; + _1 = &(*_5); + StorageDead(_5); + goto -> bb4; + } + + bb2: { + _1 = const "A(Empty)"; + goto -> bb4; + } + + bb3: { + StorageLive(_4); + _4 = const "B(Empty)"; + _1 = &(*_4); + StorageDead(_4); + goto -> bb4; + } + + bb4: { + StorageDead(_2); + StorageDead(_1); + _0 = const (); + return; ++ } ++ ++ bb5: { ++ unreachable; + } + } + diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-unwind.diff new file mode 100644 index 0000000000000..5dc1e2b73f6a4 --- /dev/null +++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-unwind.diff @@ -0,0 +1,53 @@ +- // MIR for `otherwise_t3` before UninhabitedEnumBranching ++ // MIR for `otherwise_t3` after UninhabitedEnumBranching + + fn otherwise_t3() -> () { + let mut _0: (); + let _1: &str; + let mut _2: Test3; + let mut _3: isize; + let _4: &str; + let _5: &str; + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test3::C; + _3 = discriminant(_2); +- switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1]; ++ switchInt(move _3) -> [0: bb5, 1: bb5, otherwise: bb1]; + } + + bb1: { + StorageLive(_5); + _5 = const "C"; + _1 = &(*_5); + StorageDead(_5); + goto -> bb4; + } + + bb2: { + _1 = const "A(Empty)"; + goto -> bb4; + } + + bb3: { + StorageLive(_4); + _4 = const "B(Empty)"; + _1 = &(*_4); + StorageDead(_4); + goto -> bb4; + } + + bb4: { + StorageDead(_2); + StorageDead(_1); + _0 = const (); + return; ++ } ++ ++ bb5: { ++ unreachable; + } + } + diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-abort.diff new file mode 100644 index 0000000000000..1352dda49715b --- /dev/null +++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-abort.diff @@ -0,0 +1,48 @@ +- // MIR for `otherwise_t4` before UninhabitedEnumBranching ++ // MIR for `otherwise_t4` after UninhabitedEnumBranching + + fn otherwise_t4() -> () { + let mut _0: (); + let _1: &str; + let mut _2: Test4; + let mut _3: isize; + let _4: &str; + let _5: &str; + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test4::C; + _3 = discriminant(_2); + switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1]; + } + + bb1: { + StorageLive(_5); + _5 = const "CD"; + _1 = &(*_5); + StorageDead(_5); + goto -> bb4; + } + + bb2: { + _1 = const "A(i32)"; + goto -> bb4; + } + + bb3: { + StorageLive(_4); + _4 = const "B(i32)"; + _1 = &(*_4); + StorageDead(_4); + goto -> bb4; + } + + bb4: { + StorageDead(_2); + StorageDead(_1); + _0 = const (); + return; + } + } + diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-unwind.diff new file mode 100644 index 0000000000000..1352dda49715b --- /dev/null +++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-unwind.diff @@ -0,0 +1,48 @@ +- // MIR for `otherwise_t4` before UninhabitedEnumBranching ++ // MIR for `otherwise_t4` after UninhabitedEnumBranching + + fn otherwise_t4() -> () { + let mut _0: (); + let _1: &str; + let mut _2: Test4; + let mut _3: isize; + let _4: &str; + let _5: &str; + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test4::C; + _3 = discriminant(_2); + switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1]; + } + + bb1: { + StorageLive(_5); + _5 = const "CD"; + _1 = &(*_5); + StorageDead(_5); + goto -> bb4; + } + + bb2: { + _1 = const "A(i32)"; + goto -> bb4; + } + + bb3: { + StorageLive(_4); + _4 = const "B(i32)"; + _1 = &(*_4); + StorageDead(_4); + goto -> bb4; + } + + bb4: { + StorageDead(_2); + StorageDead(_1); + _0 = const (); + return; + } + } + diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff new file mode 100644 index 0000000000000..40dd961fbac4d --- /dev/null +++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff @@ -0,0 +1,62 @@ +- // MIR for `otherwise_t4_uninhabited_default` before UninhabitedEnumBranching ++ // MIR for `otherwise_t4_uninhabited_default` after UninhabitedEnumBranching + + fn otherwise_t4_uninhabited_default() -> () { + let mut _0: (); + let _1: &str; + let mut _2: Test4; + let mut _3: isize; + let _4: &str; + let _5: &str; + let _6: &str; + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test4::C; + _3 = discriminant(_2); +- switchInt(move _3) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb1]; ++ switchInt(move _3) -> [0: bb2, 1: bb3, 2: bb4, 3: bb1, otherwise: bb6]; + } + + bb1: { + StorageLive(_6); + _6 = const "D"; + _1 = &(*_6); + StorageDead(_6); + goto -> bb5; + } + + bb2: { + _1 = const "A(i32)"; + goto -> bb5; + } + + bb3: { + StorageLive(_4); + _4 = const "B(i32)"; + _1 = &(*_4); + StorageDead(_4); + goto -> bb5; + } + + bb4: { + StorageLive(_5); + _5 = const "C"; + _1 = &(*_5); + StorageDead(_5); + goto -> bb5; + } + + bb5: { + StorageDead(_2); + StorageDead(_1); + _0 = const (); + return; ++ } ++ ++ bb6: { ++ unreachable; + } + } + diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff new file mode 100644 index 0000000000000..40dd961fbac4d --- /dev/null +++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff @@ -0,0 +1,62 @@ +- // MIR for `otherwise_t4_uninhabited_default` before UninhabitedEnumBranching ++ // MIR for `otherwise_t4_uninhabited_default` after UninhabitedEnumBranching + + fn otherwise_t4_uninhabited_default() -> () { + let mut _0: (); + let _1: &str; + let mut _2: Test4; + let mut _3: isize; + let _4: &str; + let _5: &str; + let _6: &str; + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test4::C; + _3 = discriminant(_2); +- switchInt(move _3) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb1]; ++ switchInt(move _3) -> [0: bb2, 1: bb3, 2: bb4, 3: bb1, otherwise: bb6]; + } + + bb1: { + StorageLive(_6); + _6 = const "D"; + _1 = &(*_6); + StorageDead(_6); + goto -> bb5; + } + + bb2: { + _1 = const "A(i32)"; + goto -> bb5; + } + + bb3: { + StorageLive(_4); + _4 = const "B(i32)"; + _1 = &(*_4); + StorageDead(_4); + goto -> bb5; + } + + bb4: { + StorageLive(_5); + _5 = const "C"; + _1 = &(*_5); + StorageDead(_5); + goto -> bb5; + } + + bb5: { + StorageDead(_2); + StorageDead(_1); + _0 = const (); + return; ++ } ++ ++ bb6: { ++ unreachable; + } + } + diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-abort.diff new file mode 100644 index 0000000000000..ac39f6be6c634 --- /dev/null +++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-abort.diff @@ -0,0 +1,75 @@ +- // MIR for `otherwise_t4_uninhabited_default_2` before UninhabitedEnumBranching ++ // MIR for `otherwise_t4_uninhabited_default_2` after UninhabitedEnumBranching + + fn otherwise_t4_uninhabited_default_2() -> () { + let mut _0: (); + let _1: &str; + let mut _2: Test4; + let mut _3: isize; + let _4: &str; + let _5: &str; + let _6: &str; + let _7: &str; + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test4::C; + _3 = discriminant(_2); +- switchInt(move _3) -> [0: bb2, 1: bb5, 2: bb6, otherwise: bb1]; ++ switchInt(move _3) -> [0: bb2, 1: bb5, 2: bb6, 3: bb1, otherwise: bb8]; + } + + bb1: { + StorageLive(_7); + _7 = const "A(other)D"; + _1 = &(*_7); + StorageDead(_7); + goto -> bb7; + } + + bb2: { + switchInt(((_2 as A).0: i32)) -> [1: bb3, 2: bb4, otherwise: bb1]; + } + + bb3: { + _1 = const "A(1)"; + goto -> bb7; + } + + bb4: { + StorageLive(_4); + _4 = const "A(2)"; + _1 = &(*_4); + StorageDead(_4); + goto -> bb7; + } + + bb5: { + StorageLive(_5); + _5 = const "B(i32)"; + _1 = &(*_5); + StorageDead(_5); + goto -> bb7; + } + + bb6: { + StorageLive(_6); + _6 = const "C"; + _1 = &(*_6); + StorageDead(_6); + goto -> bb7; + } + + bb7: { + StorageDead(_2); + StorageDead(_1); + _0 = const (); + return; ++ } ++ ++ bb8: { ++ unreachable; + } + } + diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-unwind.diff new file mode 100644 index 0000000000000..ac39f6be6c634 --- /dev/null +++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-unwind.diff @@ -0,0 +1,75 @@ +- // MIR for `otherwise_t4_uninhabited_default_2` before UninhabitedEnumBranching ++ // MIR for `otherwise_t4_uninhabited_default_2` after UninhabitedEnumBranching + + fn otherwise_t4_uninhabited_default_2() -> () { + let mut _0: (); + let _1: &str; + let mut _2: Test4; + let mut _3: isize; + let _4: &str; + let _5: &str; + let _6: &str; + let _7: &str; + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test4::C; + _3 = discriminant(_2); +- switchInt(move _3) -> [0: bb2, 1: bb5, 2: bb6, otherwise: bb1]; ++ switchInt(move _3) -> [0: bb2, 1: bb5, 2: bb6, 3: bb1, otherwise: bb8]; + } + + bb1: { + StorageLive(_7); + _7 = const "A(other)D"; + _1 = &(*_7); + StorageDead(_7); + goto -> bb7; + } + + bb2: { + switchInt(((_2 as A).0: i32)) -> [1: bb3, 2: bb4, otherwise: bb1]; + } + + bb3: { + _1 = const "A(1)"; + goto -> bb7; + } + + bb4: { + StorageLive(_4); + _4 = const "A(2)"; + _1 = &(*_4); + StorageDead(_4); + goto -> bb7; + } + + bb5: { + StorageLive(_5); + _5 = const "B(i32)"; + _1 = &(*_5); + StorageDead(_5); + goto -> bb7; + } + + bb6: { + StorageLive(_6); + _6 = const "C"; + _1 = &(*_6); + StorageDead(_6); + goto -> bb7; + } + + bb7: { + StorageDead(_2); + StorageDead(_1); + _0 = const (); + return; ++ } ++ ++ bb8: { ++ unreachable; + } + } + diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff new file mode 100644 index 0000000000000..8180428a6f459 --- /dev/null +++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff @@ -0,0 +1,66 @@ +- // MIR for `otherwise_t5_uninhabited_default` before UninhabitedEnumBranching ++ // MIR for `otherwise_t5_uninhabited_default` after UninhabitedEnumBranching + + fn otherwise_t5_uninhabited_default() -> () { + let mut _0: (); + let _1: &str; + let mut _2: Test5; + let mut _3: i8; + let _4: &str; + let _5: &str; + let _6: &str; + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test5::::C; + _3 = discriminant(_2); +- switchInt(move _3) -> [255: bb2, 0: bb3, 5: bb4, otherwise: bb1]; ++ switchInt(move _3) -> [255: bb2, 0: bb3, 5: bb4, 3: bb1, otherwise: bb7]; + } + + bb1: { + StorageLive(_6); + _6 = const "D"; + _1 = &(*_6); + StorageDead(_6); + goto -> bb5; + } + + bb2: { + _1 = const "A(T)"; + goto -> bb5; + } + + bb3: { + StorageLive(_4); + _4 = const "B(T)"; + _1 = &(*_4); + StorageDead(_4); + goto -> bb5; + } + + bb4: { + StorageLive(_5); + _5 = const "C"; + _1 = &(*_5); + StorageDead(_5); + goto -> bb5; + } + + bb5: { + drop(_2) -> [return: bb6, unwind unreachable]; + } + + bb6: { + StorageDead(_2); + StorageDead(_1); + _0 = const (); + return; ++ } ++ ++ bb7: { ++ unreachable; + } + } + diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff new file mode 100644 index 0000000000000..b13d5816aed9d --- /dev/null +++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff @@ -0,0 +1,70 @@ +- // MIR for `otherwise_t5_uninhabited_default` before UninhabitedEnumBranching ++ // MIR for `otherwise_t5_uninhabited_default` after UninhabitedEnumBranching + + fn otherwise_t5_uninhabited_default() -> () { + let mut _0: (); + let _1: &str; + let mut _2: Test5; + let mut _3: i8; + let _4: &str; + let _5: &str; + let _6: &str; + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test5::::C; + _3 = discriminant(_2); +- switchInt(move _3) -> [255: bb2, 0: bb3, 5: bb4, otherwise: bb1]; ++ switchInt(move _3) -> [255: bb2, 0: bb3, 5: bb4, 3: bb1, otherwise: bb8]; + } + + bb1: { + StorageLive(_6); + _6 = const "D"; + _1 = &(*_6); + StorageDead(_6); + goto -> bb5; + } + + bb2: { + _1 = const "A(T)"; + goto -> bb5; + } + + bb3: { + StorageLive(_4); + _4 = const "B(T)"; + _1 = &(*_4); + StorageDead(_4); + goto -> bb5; + } + + bb4: { + StorageLive(_5); + _5 = const "C"; + _1 = &(*_5); + StorageDead(_5); + goto -> bb5; + } + + bb5: { + drop(_2) -> [return: bb6, unwind: bb7]; + } + + bb6: { + StorageDead(_2); + StorageDead(_1); + _0 = const (); + return; + } + + bb7 (cleanup): { + resume; ++ } ++ ++ bb8: { ++ unreachable; + } + } + diff --git a/tests/mir-opt/uninhabited_enum_branching.rs b/tests/mir-opt/uninhabited_enum_branching.rs index 08eca57afc630..6de001be9791e 100644 --- a/tests/mir-opt/uninhabited_enum_branching.rs +++ b/tests/mir-opt/uninhabited_enum_branching.rs @@ -1,4 +1,6 @@ //@ unit-test: UninhabitedEnumBranching +// EMIT_MIR_FOR_EACH_PANIC_STRATEGY + enum Empty {} // test matching an enum with uninhabited variants @@ -23,6 +25,21 @@ enum Test3 { D, } +enum Test4 { + A(i32), + B(i32), + C, + D, +} + +#[repr(i8)] +enum Test5 { + A(T) = -1, + B(T) = 0, + C = 5, + D = 3, +} + struct Plop { xx: u32, test3: Test3, @@ -46,8 +63,8 @@ fn simple() { fn custom_discriminant() { // CHECK-LABEL: fn custom_discriminant( // CHECK: [[discr:_.*]] = discriminant( - // CHECK: switchInt(move [[discr]]) -> [4: bb3, 5: bb2, otherwise: bb5]; - // CHECK: bb5: { + // CHECK: switchInt(move [[discr]]) -> [4: bb3, 5: bb2, otherwise: [[unreachable:bb.*]]]; + // CHECK: [[unreachable]]: { // CHECK-NEXT: unreachable; match Test2::D { Test2::D => "D", @@ -55,6 +72,111 @@ fn custom_discriminant() { }; } +// EMIT_MIR uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.diff +fn otherwise_t1() { + // CHECK-LABEL: fn otherwise_t1( + // CHECK: [[discr:_.*]] = discriminant( + // CHECK: switchInt(move [[discr]]) -> [0: bb5, 1: bb5, 2: bb1, otherwise: [[unreachable:bb.*]]]; + // CHECK: [[unreachable]]: { + // CHECK-NEXT: unreachable; + match Test1::C { + Test1::A(_) => "A(Empty)", + Test1::B(_) => "B(Empty)", + _ => "C", + }; +} + +// EMIT_MIR uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.diff +fn otherwise_t2() { + // CHECK-LABEL: fn otherwise_t2( + // CHECK: [[discr:_.*]] = discriminant( + // CHECK: switchInt(move [[discr]]) -> [4: bb2, 5: bb1, otherwise: [[unreachable:bb.*]]]; + // CHECK: [[unreachable]]: { + // CHECK-NEXT: unreachable; + match Test2::D { + Test2::D => "D", + _ => "E", + }; +} + +// EMIT_MIR uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.diff +fn otherwise_t3() { + // CHECK-LABEL: fn otherwise_t3( + // CHECK: [[discr:_.*]] = discriminant( + // CHECK: switchInt(move [[discr]]) -> [0: bb5, 1: bb5, otherwise: bb1]; + // CHECK: bb1: { + // CHECK-NOT: unreachable; + // CHECK: } + // CHECK: bb5: { + // CHECK-NEXT: unreachable; + match Test3::C { + Test3::A(_) => "A(Empty)", + Test3::B(_) => "B(Empty)", + _ => "C", + }; +} + +// EMIT_MIR uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.diff +fn otherwise_t4_uninhabited_default() { + // CHECK-LABEL: fn otherwise_t4_uninhabited_default( + // CHECK: [[discr:_.*]] = discriminant( + // CHECK: switchInt(move [[discr]]) -> [0: bb2, 1: bb3, 2: bb4, 3: bb1, otherwise: [[unreachable:bb.*]]]; + // CHECK: [[unreachable]]: { + // CHECK-NEXT: unreachable; + match Test4::C { + Test4::A(_) => "A(i32)", + Test4::B(_) => "B(i32)", + Test4::C => "C", + _ => "D", + }; +} + +// EMIT_MIR uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.diff +fn otherwise_t4_uninhabited_default_2() { + // CHECK-LABEL: fn otherwise_t4_uninhabited_default_2( + // CHECK: [[discr:_.*]] = discriminant( + // CHECK: switchInt(move [[discr]]) -> [0: bb2, 1: bb5, 2: bb6, 3: bb1, otherwise: [[unreachable:bb.*]]]; + // CHECK: [[unreachable]]: { + // CHECK-NEXT: unreachable; + match Test4::C { + Test4::A(1) => "A(1)", + Test4::A(2) => "A(2)", + Test4::B(_) => "B(i32)", + Test4::C => "C", + _ => "A(other)D", + }; +} + +// EMIT_MIR uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.diff +fn otherwise_t4() { + // CHECK-LABEL: fn otherwise_t4( + // CHECK: [[discr:_.*]] = discriminant( + // CHECK: switchInt(move [[discr]]) -> [0: bb2, 1: bb3, otherwise: [[unreachable:bb.*]]]; + // CHECK: [[unreachable]]: { + // CHECK-NOT: unreachable; + // CHECK: } + match Test4::C { + Test4::A(_) => "A(i32)", + Test4::B(_) => "B(i32)", + _ => "CD", + }; +} + +// EMIT_MIR uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.diff +fn otherwise_t5_uninhabited_default() { + // CHECK-LABEL: fn otherwise_t5_uninhabited_default( + // CHECK: [[discr:_.*]] = discriminant( + // CHECK: switchInt(move [[discr]]) -> [255: bb2, 0: bb3, 5: bb4, 3: bb1, otherwise: [[unreachable:bb.*]]]; + // CHECK: [[unreachable]]: { + // CHECK-NEXT: unreachable; + match Test5::::C { + Test5::A(_) => "A(T)", + Test5::B(_) => "B(T)", + Test5::C => "C", + _ => "D", + }; +} + // EMIT_MIR uninhabited_enum_branching.byref.UninhabitedEnumBranching.diff fn byref() { // CHECK-LABEL: fn byref( @@ -69,6 +191,9 @@ fn byref() { Test3::D => "D", }; + // CHECK: [[unreachable]]: { + // CHECK-NEXT: unreachable; + // CHECK: [[discr:_.*]] = discriminant( // CHECK: switchInt(move [[discr]]) -> [0: [[unreachable]], 1: [[unreachable]], 2: bb10, 3: bb7, otherwise: [[unreachable]]]; match plop.test3 { @@ -77,13 +202,17 @@ fn byref() { Test3::C => "C", Test3::D => "D", }; - - // CHECK: [[unreachable]]: { - // CHECK-NEXT: unreachable; } fn main() { simple(); custom_discriminant(); + otherwise_t1(); + otherwise_t2(); + otherwise_t3(); + otherwise_t4_uninhabited_default(); + otherwise_t4_uninhabited_default_2(); + otherwise_t4(); + otherwise_t5_uninhabited_default::(); byref(); } diff --git a/tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.diff b/tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-abort.diff similarity index 89% rename from tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.diff rename to tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-abort.diff index 6ce61e1528748..674d3a25504a9 100644 --- a/tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.diff +++ b/tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-abort.diff @@ -15,7 +15,7 @@ _2 = Test1::C; _3 = discriminant(_2); - switchInt(move _3) -> [0: bb3, 1: bb4, 2: bb2, otherwise: bb1]; -+ switchInt(move _3) -> [0: bb6, 1: bb6, 2: bb2, otherwise: bb6]; ++ switchInt(move _3) -> [0: bb1, 1: bb1, 2: bb2, otherwise: bb1]; } bb1: { @@ -48,10 +48,6 @@ StorageDead(_1); _0 = const (); return; -+ } -+ -+ bb6: { -+ unreachable; } } diff --git a/tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-unwind.diff new file mode 100644 index 0000000000000..674d3a25504a9 --- /dev/null +++ b/tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-unwind.diff @@ -0,0 +1,53 @@ +- // MIR for `simple` before UninhabitedEnumBranching ++ // MIR for `simple` after UninhabitedEnumBranching + + fn simple() -> () { + let mut _0: (); + let _1: &str; + let mut _2: Test1; + let mut _3: isize; + let _4: &str; + let _5: &str; + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test1::C; + _3 = discriminant(_2); +- switchInt(move _3) -> [0: bb3, 1: bb4, 2: bb2, otherwise: bb1]; ++ switchInt(move _3) -> [0: bb1, 1: bb1, 2: bb2, otherwise: bb1]; + } + + bb1: { + unreachable; + } + + bb2: { + StorageLive(_5); + _5 = const "C"; + _1 = &(*_5); + StorageDead(_5); + goto -> bb5; + } + + bb3: { + _1 = const "A(Empty)"; + goto -> bb5; + } + + bb4: { + StorageLive(_4); + _4 = const "B(Empty)"; + _1 = &(*_4); + StorageDead(_4); + goto -> bb5; + } + + bb5: { + StorageDead(_2); + StorageDead(_1); + _0 = const (); + return; + } + } + diff --git a/tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff b/tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff index 79948139f888d..28a8c251d956a 100644 --- a/tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff +++ b/tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff @@ -9,7 +9,7 @@ bb0: { _2 = discriminant(_1); - switchInt(move _2) -> [0: bb2, 1: bb3, otherwise: bb1]; -+ switchInt(move _2) -> [0: bb5, 1: bb3, otherwise: bb1]; ++ switchInt(move _2) -> [0: bb5, 1: bb3, 2: bb1, otherwise: bb5]; } bb1: { diff --git a/tests/run-make-fulldeps/issue-19371/foo.rs b/tests/run-make-fulldeps/issue-19371/foo.rs index a0bbe3851e82f..327c99a02c6fe 100644 --- a/tests/run-make-fulldeps/issue-19371/foo.rs +++ b/tests/run-make-fulldeps/issue-19371/foo.rs @@ -56,7 +56,7 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf) { file_loader: None, locale_resources: &[], lint_caps: Default::default(), - parse_sess_created: None, + psess_created: None, hash_untracked_state: None, register_lints: None, override_queries: None, diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx_global_asm.checks b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx_global_asm.checks index d4a3d4479014c..1d8fc96ad50cd 100644 --- a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx_global_asm.checks +++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx_global_asm.checks @@ -1,2 +1,7 @@ CHECK: cmake_plus_one_cxx_global_asm -CHECK: lfence +CHECK-NEXT: movl +CHECK-NEXT: lfence +CHECK-NEXT: incl +CHECK-NEXT: shlq $0x0, (%rsp) +CHECK-NEXT: lfence +CHECK-NEXT: retq diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/print.with_frame_pointers.checks b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/print.with_frame_pointers.checks new file mode 100644 index 0000000000000..485e20e3111f7 --- /dev/null +++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/print.with_frame_pointers.checks @@ -0,0 +1,7 @@ +CHECK: print +CHECK: lfence +CHECK: popq +CHECK: popq +CHECK-NEXT: popq [[REGISTER:%[a-z]+]] +CHECK-NEXT: lfence +CHECK-NEXT: jmpq *[[REGISTER]] diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/print.checks b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/print.without_frame_pointers.checks similarity index 100% rename from tests/run-make/x86_64-fortanix-unknown-sgx-lvi/print.checks rename to tests/run-make/x86_64-fortanix-unknown-sgx-lvi/print.without_frame_pointers.checks diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh index 04a34724518e8..a36ad916bebe3 100644 --- a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh +++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh @@ -34,8 +34,9 @@ function check { ${enclave} > ${asm} ${filecheck} --input-file ${asm} ${checks} - if [ "${func_re}" != "rust_plus_one_global_asm" && - "${func_re}" != "cmake_plus_one_c_global_asm" ]; then + if [ "${func_re}" != "rust_plus_one_global_asm" ] && + [ "${func_re}" != "cmake_plus_one_c_global_asm" ] && + [ "${func_re}" != "cmake_plus_one_cxx_global_asm" ]; then # The assembler cannot avoid explicit `ret` instructions. Sequences # of `shlq $0x0, (%rsp); lfence; retq` are used instead. # https://www.intel.com/content/www/us/en/developer/articles/technical/ @@ -48,7 +49,8 @@ build check "unw_getcontext" unw_getcontext.checks check "__libunwind_Registers_x86_64_jumpto" jumpto.checks -check 'std::io::stdio::_print::[[:alnum:]]+' print.checks +check 'std::io::stdio::_print::[[:alnum:]]+' print.with_frame_pointers.checks || + check 'std::io::stdio::_print::[[:alnum:]]+' print.without_frame_pointers.checks check rust_plus_one_global_asm rust_plus_one_global_asm.checks check cc_plus_one_c cc_plus_one_c.checks diff --git a/tests/rustdoc-ui/argfile/commandline-argfile-badutf8-windows.rs b/tests/rustdoc-ui/argfile/commandline-argfile-badutf8-windows.rs new file mode 100644 index 0000000000000..eba17ca6f7e92 --- /dev/null +++ b/tests/rustdoc-ui/argfile/commandline-argfile-badutf8-windows.rs @@ -0,0 +1,17 @@ +// Check to see if we can get parameters from an @argsfile file +// +// Path replacement in .stderr files (i.e. `$DIR`) doesn't handle mixed path +// separators. This test uses backslash as the path separator for the command +// line arguments and is only run on windows. +// +//@ only-windows +//@ compile-flags: --cfg cmdline_set @{{src-base}}\argfile\commandline-argfile-badutf8.args + +#[cfg(not(cmdline_set))] +compile_error!("cmdline_set not set"); + +#[cfg(not(unbroken))] +compile_error!("unbroken not set"); + +fn main() { +} diff --git a/tests/rustdoc-ui/argfile/commandline-argfile-badutf8-windows.stderr b/tests/rustdoc-ui/argfile/commandline-argfile-badutf8-windows.stderr new file mode 100644 index 0000000000000..b4c0d4c20d75f --- /dev/null +++ b/tests/rustdoc-ui/argfile/commandline-argfile-badutf8-windows.stderr @@ -0,0 +1,2 @@ +error: failed to load argument file: UTF-8 error in $DIR/commandline-argfile-badutf8.args + diff --git a/tests/rustdoc-ui/commandline-argfile-badutf8.args b/tests/rustdoc-ui/argfile/commandline-argfile-badutf8.args similarity index 100% rename from tests/rustdoc-ui/commandline-argfile-badutf8.args rename to tests/rustdoc-ui/argfile/commandline-argfile-badutf8.args diff --git a/tests/rustdoc-ui/argfile/commandline-argfile-badutf8.rs b/tests/rustdoc-ui/argfile/commandline-argfile-badutf8.rs new file mode 100644 index 0000000000000..1b2e52af762f1 --- /dev/null +++ b/tests/rustdoc-ui/argfile/commandline-argfile-badutf8.rs @@ -0,0 +1,18 @@ +// Check to see if we can get parameters from an @argsfile file +// +// Path replacement in .stderr files (i.e. `$DIR`) doesn't handle mixed path +// separators. We have a duplicated version of this test that uses backslash as +// the path separator for the command line arguments that is only run on +// windows. +// +//@ ignore-windows +//@ compile-flags: --cfg cmdline_set @{{src-base}}/argfile/commandline-argfile-badutf8.args + +#[cfg(not(cmdline_set))] +compile_error!("cmdline_set not set"); + +#[cfg(not(unbroken))] +compile_error!("unbroken not set"); + +fn main() { +} diff --git a/tests/rustdoc-ui/argfile/commandline-argfile-badutf8.stderr b/tests/rustdoc-ui/argfile/commandline-argfile-badutf8.stderr new file mode 100644 index 0000000000000..b4c0d4c20d75f --- /dev/null +++ b/tests/rustdoc-ui/argfile/commandline-argfile-badutf8.stderr @@ -0,0 +1,2 @@ +error: failed to load argument file: UTF-8 error in $DIR/commandline-argfile-badutf8.args + diff --git a/tests/rustdoc-ui/commandline-argfile-missing.rs b/tests/rustdoc-ui/argfile/commandline-argfile-missing-windows.rs similarity index 55% rename from tests/rustdoc-ui/commandline-argfile-missing.rs rename to tests/rustdoc-ui/argfile/commandline-argfile-missing-windows.rs index bb9644d66ce10..24cfd25ccadb9 100644 --- a/tests/rustdoc-ui/commandline-argfile-missing.rs +++ b/tests/rustdoc-ui/argfile/commandline-argfile-missing-windows.rs @@ -1,8 +1,13 @@ // Check to see if we can get parameters from an @argsfile file // +// Path replacement in .stderr files (i.e. `$DIR`) doesn't handle mixed path +// separators. This test uses backslash as the path separator for the command +// line arguments and is only run on windows. +// +//@ only-windows //@ normalize-stderr-test: "os error \d+" -> "os error $$ERR" //@ normalize-stderr-test: "commandline-argfile-missing.args:[^(]*" -> "commandline-argfile-missing.args: $$FILE_MISSING " -//@ compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-missing.args +//@ compile-flags: --cfg cmdline_set @{{src-base}}\argfile\commandline-argfile-missing.args #[cfg(not(cmdline_set))] compile_error!("cmdline_set not set"); diff --git a/tests/rustdoc-ui/argfile/commandline-argfile-missing-windows.stderr b/tests/rustdoc-ui/argfile/commandline-argfile-missing-windows.stderr new file mode 100644 index 0000000000000..28a20debf1cca --- /dev/null +++ b/tests/rustdoc-ui/argfile/commandline-argfile-missing-windows.stderr @@ -0,0 +1,2 @@ +error: failed to load argument file: IO error: $DIR/commandline-argfile-missing.args: $FILE_MISSING (os error $ERR) + diff --git a/tests/rustdoc-ui/argfile/commandline-argfile-missing.rs b/tests/rustdoc-ui/argfile/commandline-argfile-missing.rs new file mode 100644 index 0000000000000..fe6a849b0c8b6 --- /dev/null +++ b/tests/rustdoc-ui/argfile/commandline-argfile-missing.rs @@ -0,0 +1,20 @@ +// Check to see if we can get parameters from an @argsfile file +// +// Path replacement in .stderr files (i.e. `$DIR`) doesn't handle mixed path +// separators. We have a duplicated version of this test that uses backslash as +// the path separator for the command line arguments that is only run on +// windows. +// +//@ ignore-windows +//@ normalize-stderr-test: "os error \d+" -> "os error $$ERR" +//@ normalize-stderr-test: "commandline-argfile-missing.args:[^(]*" -> "commandline-argfile-missing.args: $$FILE_MISSING " +//@ compile-flags: --cfg cmdline_set @{{src-base}}/argfile/commandline-argfile-missing.args + +#[cfg(not(cmdline_set))] +compile_error!("cmdline_set not set"); + +#[cfg(not(unbroken))] +compile_error!("unbroken not set"); + +fn main() { +} diff --git a/tests/rustdoc-ui/argfile/commandline-argfile-missing.stderr b/tests/rustdoc-ui/argfile/commandline-argfile-missing.stderr new file mode 100644 index 0000000000000..28a20debf1cca --- /dev/null +++ b/tests/rustdoc-ui/argfile/commandline-argfile-missing.stderr @@ -0,0 +1,2 @@ +error: failed to load argument file: IO error: $DIR/commandline-argfile-missing.args: $FILE_MISSING (os error $ERR) + diff --git a/tests/rustdoc-ui/argfile/commandline-argfile-multiple-windows.rs b/tests/rustdoc-ui/argfile/commandline-argfile-multiple-windows.rs new file mode 100644 index 0000000000000..84c050d84e25b --- /dev/null +++ b/tests/rustdoc-ui/argfile/commandline-argfile-multiple-windows.rs @@ -0,0 +1,20 @@ +// Check to see if we can get parameters from an @argsfile file +// +// Path replacement in .stderr files (i.e. `$DIR`) doesn't handle mixed path +// separators. This test uses backslash as the path separator for the command +// line arguments and is only run on windows. +// +//@ only-windows +//@ normalize-stderr-test: "os error \d+" -> "os error $$ERR" +//@ normalize-stderr-test: "commandline-argfile-missing.args:[^(]*" -> "commandline-argfile-missing.args: $$FILE_MISSING " +//@ normalize-stderr-test: "commandline-argfile-missing2.args:[^(]*" -> "commandline-argfile-missing2.args: $$FILE_MISSING " +//@ compile-flags: --cfg cmdline_set @{{src-base}}\argfile\commandline-argfile-missing.args @{{src-base}}\argfile\commandline-argfile-badutf8.args @{{src-base}}\argfile\commandline-argfile-missing2.args + +#[cfg(not(cmdline_set))] +compile_error!("cmdline_set not set"); + +#[cfg(not(unbroken))] +compile_error!("unbroken not set"); + +fn main() { +} diff --git a/tests/rustdoc-ui/argfile/commandline-argfile-multiple-windows.stderr b/tests/rustdoc-ui/argfile/commandline-argfile-multiple-windows.stderr new file mode 100644 index 0000000000000..ad3b445c958fd --- /dev/null +++ b/tests/rustdoc-ui/argfile/commandline-argfile-multiple-windows.stderr @@ -0,0 +1,6 @@ +error: failed to load argument file: IO error: $DIR/commandline-argfile-missing.args: $FILE_MISSING (os error $ERR) + +error: failed to load argument file: UTF-8 error in $DIR/commandline-argfile-badutf8.args + +error: failed to load argument file: IO error: $DIR/commandline-argfile-missing2.args: $FILE_MISSING (os error $ERR) + diff --git a/tests/rustdoc-ui/argfile/commandline-argfile-multiple.rs b/tests/rustdoc-ui/argfile/commandline-argfile-multiple.rs new file mode 100644 index 0000000000000..f658ee34fbb08 --- /dev/null +++ b/tests/rustdoc-ui/argfile/commandline-argfile-multiple.rs @@ -0,0 +1,21 @@ +// Check to see if we can get parameters from an @argsfile file +// +// Path replacement in .stderr files (i.e. `$DIR`) doesn't handle mixed path +// separators. We have a duplicated version of this test that uses backslash as +// the path separator for the command line arguments that is only run on +// windows. +// +//@ ignore-windows +//@ normalize-stderr-test: "os error \d+" -> "os error $$ERR" +//@ normalize-stderr-test: "commandline-argfile-missing.args:[^(]*" -> "commandline-argfile-missing.args: $$FILE_MISSING " +//@ normalize-stderr-test: "commandline-argfile-missing2.args:[^(]*" -> "commandline-argfile-missing2.args: $$FILE_MISSING " +//@ compile-flags: --cfg cmdline_set @{{src-base}}/argfile/commandline-argfile-missing.args @{{src-base}}/argfile/commandline-argfile-badutf8.args @{{src-base}}/argfile/commandline-argfile-missing2.args + +#[cfg(not(cmdline_set))] +compile_error!("cmdline_set not set"); + +#[cfg(not(unbroken))] +compile_error!("unbroken not set"); + +fn main() { +} diff --git a/tests/rustdoc-ui/argfile/commandline-argfile-multiple.stderr b/tests/rustdoc-ui/argfile/commandline-argfile-multiple.stderr new file mode 100644 index 0000000000000..ad3b445c958fd --- /dev/null +++ b/tests/rustdoc-ui/argfile/commandline-argfile-multiple.stderr @@ -0,0 +1,6 @@ +error: failed to load argument file: IO error: $DIR/commandline-argfile-missing.args: $FILE_MISSING (os error $ERR) + +error: failed to load argument file: UTF-8 error in $DIR/commandline-argfile-badutf8.args + +error: failed to load argument file: IO error: $DIR/commandline-argfile-missing2.args: $FILE_MISSING (os error $ERR) + diff --git a/tests/rustdoc-ui/commandline-argfile.args b/tests/rustdoc-ui/argfile/commandline-argfile.args similarity index 100% rename from tests/rustdoc-ui/commandline-argfile.args rename to tests/rustdoc-ui/argfile/commandline-argfile.args diff --git a/tests/rustdoc-ui/commandline-argfile.rs b/tests/rustdoc-ui/argfile/commandline-argfile.rs similarity index 72% rename from tests/rustdoc-ui/commandline-argfile.rs rename to tests/rustdoc-ui/argfile/commandline-argfile.rs index d71bc72562b75..b0b314f53ceb7 100644 --- a/tests/rustdoc-ui/commandline-argfile.rs +++ b/tests/rustdoc-ui/argfile/commandline-argfile.rs @@ -1,7 +1,7 @@ // Check to see if we can get parameters from an @argsfile file // //@ check-pass -//@ compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile.args +//@ compile-flags: --cfg cmdline_set @{{src-base}}/argfile/commandline-argfile.args #[cfg(not(cmdline_set))] compile_error!("cmdline_set not set"); diff --git a/tests/rustdoc-ui/commandline-argfile-badutf8.rs b/tests/rustdoc-ui/commandline-argfile-badutf8.rs deleted file mode 100644 index b3a19fa62741d..0000000000000 --- a/tests/rustdoc-ui/commandline-argfile-badutf8.rs +++ /dev/null @@ -1,12 +0,0 @@ -// Check to see if we can get parameters from an @argsfile file -// -//@ compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-badutf8.args - -#[cfg(not(cmdline_set))] -compile_error!("cmdline_set not set"); - -#[cfg(not(unbroken))] -compile_error!("unbroken not set"); - -fn main() { -} diff --git a/tests/rustdoc-ui/commandline-argfile-badutf8.stderr b/tests/rustdoc-ui/commandline-argfile-badutf8.stderr deleted file mode 100644 index 9af6fc0a518df..0000000000000 --- a/tests/rustdoc-ui/commandline-argfile-badutf8.stderr +++ /dev/null @@ -1,2 +0,0 @@ -error: Failed to load argument file: Utf8 error in $DIR/commandline-argfile-badutf8.args - diff --git a/tests/rustdoc-ui/commandline-argfile-missing.stderr b/tests/rustdoc-ui/commandline-argfile-missing.stderr deleted file mode 100644 index 179ad83100419..0000000000000 --- a/tests/rustdoc-ui/commandline-argfile-missing.stderr +++ /dev/null @@ -1,2 +0,0 @@ -error: Failed to load argument file: IO Error: $DIR/commandline-argfile-missing.args: $FILE_MISSING (os error $ERR) - diff --git a/tests/rustdoc-ui/issue-110629-private-type-cycle-dyn.stderr b/tests/rustdoc-ui/issue-110629-private-type-cycle-dyn.stderr index d056dde00ea01..9394b019e11e0 100644 --- a/tests/rustdoc-ui/issue-110629-private-type-cycle-dyn.stderr +++ b/tests/rustdoc-ui/issue-110629-private-type-cycle-dyn.stderr @@ -8,17 +8,11 @@ LL | type Bar<'a, 'b> = Box>>; = note: type aliases cannot be recursive = help: consider using a struct, enum, or union instead to break the cycle = help: see for more information -note: cycle used when collecting item types in top-level module +note: cycle used when checking that `Bar` is well-formed --> $DIR/issue-110629-private-type-cycle-dyn.rs:1:1 | -LL | / type Bar<'a, 'b> = Box>>; -LL | | -LL | | -LL | | fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> { -... | -LL | | assert!(bar(&meh) == bar(&muh)); -LL | | } - | |_^ +LL | type Bar<'a, 'b> = Box>>; + | ^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/issues/issue-105742.stderr b/tests/rustdoc-ui/issues/issue-105742.stderr index d5a9031075f8d..0f01bc59759d1 100644 --- a/tests/rustdoc-ui/issues/issue-105742.stderr +++ b/tests/rustdoc-ui/issues/issue-105742.stderr @@ -464,38 +464,6 @@ help: add missing generic argument LL | Output = ::Item> as SVec>::Item, | +++ -error[E0107]: missing generics for associated type `SVec::Item` - --> $DIR/issue-105742.rs:61:38 - | -LL | fn len(&self) -> ::Item; - | ^^^^ expected 1 lifetime argument - | -note: associated type defined here, with 1 lifetime parameter: `'a` - --> $DIR/issue-105742.rs:59:10 - | -LL | type Item<'a, T>; - | ^^^^ -- -help: add missing lifetime argument - | -LL | fn len(&self) -> ::Item<'_>; - | ++++ - -error[E0107]: missing generics for associated type `SVec::Item` - --> $DIR/issue-105742.rs:61:38 - | -LL | fn len(&self) -> ::Item; - | ^^^^ expected 1 generic argument - | -note: associated type defined here, with 1 generic parameter: `T` - --> $DIR/issue-105742.rs:59:10 - | -LL | type Item<'a, T>; - | ^^^^ - -help: add missing generic argument - | -LL | fn len(&self) -> ::Item; - | +++ - error[E0107]: missing generics for associated type `SVec::Item` --> $DIR/issue-105742.rs:15:21 | @@ -632,6 +600,38 @@ help: add missing generic argument LL | Output = ::Item> as SVec>::Item, | +++ +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:61:38 + | +LL | fn len(&self) -> ::Item; + | ^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-105742.rs:59:10 + | +LL | type Item<'a, T>; + | ^^^^ -- +help: add missing lifetime argument + | +LL | fn len(&self) -> ::Item<'_>; + | ++++ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:61:38 + | +LL | fn len(&self) -> ::Item; + | ^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/issue-105742.rs:59:10 + | +LL | type Item<'a, T>; + | ^^^^ - +help: add missing generic argument + | +LL | fn len(&self) -> ::Item; + | +++ + error: aborting due to 37 previous errors Some errors have detailed explanations: E0038, E0107. diff --git a/tests/rustdoc-ui/not-wf-ambiguous-normalization.rs b/tests/rustdoc-ui/not-wf-ambiguous-normalization.rs index 16e2c7d60b834..9f7d6db5d26e9 100644 --- a/tests/rustdoc-ui/not-wf-ambiguous-normalization.rs +++ b/tests/rustdoc-ui/not-wf-ambiguous-normalization.rs @@ -12,7 +12,7 @@ struct DefaultAllocator; // `::Buffer` to be ambiguous, // which caused an ICE with `-Znormalize-docs`. impl Allocator for DefaultAllocator { - //~^ ERROR: type annotations needed + //~^ ERROR: the type parameter `T` is not constrained type Buffer = (); } diff --git a/tests/rustdoc-ui/not-wf-ambiguous-normalization.stderr b/tests/rustdoc-ui/not-wf-ambiguous-normalization.stderr index 01034018e22df..55ab144b92419 100644 --- a/tests/rustdoc-ui/not-wf-ambiguous-normalization.stderr +++ b/tests/rustdoc-ui/not-wf-ambiguous-normalization.stderr @@ -1,9 +1,9 @@ -error[E0282]: type annotations needed - --> $DIR/not-wf-ambiguous-normalization.rs:14:23 +error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates + --> $DIR/not-wf-ambiguous-normalization.rs:14:6 | LL | impl Allocator for DefaultAllocator { - | ^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T` + | ^ unconstrained type parameter error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/rustdoc/invalid.crate.name.rs b/tests/rustdoc/invalid$crate$name.rs similarity index 100% rename from tests/rustdoc/invalid.crate.name.rs rename to tests/rustdoc/invalid$crate$name.rs diff --git a/tests/ui-fulldeps/fluent-messages/test.rs b/tests/ui-fulldeps/fluent-messages/test.rs index 2316a5334696d..2cd22b99e8377 100644 --- a/tests/ui-fulldeps/fluent-messages/test.rs +++ b/tests/ui-fulldeps/fluent-messages/test.rs @@ -5,15 +5,15 @@ extern crate rustc_errors; extern crate rustc_fluent_macro; -/// Copy of the relevant `DiagnosticMessage` variant constructed by `fluent_messages` as it -/// expects `crate::DiagnosticMessage` to exist. -pub enum DiagnosticMessage { +/// Copy of the relevant `DiagMessage` variant constructed by `fluent_messages` as it +/// expects `crate::DiagMessage` to exist. +pub enum DiagMessage { FluentIdentifier(std::borrow::Cow<'static, str>, Option>), } -/// Copy of the relevant `SubdiagnosticMessage` variant constructed by `fluent_messages` as it -/// expects `crate::SubdiagnosticMessage` to exist. -pub enum SubdiagnosticMessage { +/// Copy of the relevant `SubdiagMessage` variant constructed by `fluent_messages` as it +/// expects `crate::SubdiagMessage` to exist. +pub enum SubdiagMessage { FluentAttr(std::borrow::Cow<'static, str>), } diff --git a/tests/ui-fulldeps/internal-lints/diagnostics.rs b/tests/ui-fulldeps/internal-lints/diagnostics.rs index 8dcc34d4f6002..f73fdc0882ff9 100644 --- a/tests/ui-fulldeps/internal-lints/diagnostics.rs +++ b/tests/ui-fulldeps/internal-lints/diagnostics.rs @@ -1,4 +1,5 @@ //@ compile-flags: -Z unstable-options +//@ ignore-stage1 #![crate_type = "lib"] #![feature(rustc_attrs)] @@ -13,8 +14,8 @@ extern crate rustc_session; extern crate rustc_span; use rustc_errors::{ - AddToDiagnostic, Diag, EmissionGuarantee, DiagCtxt, IntoDiagnostic, Level, - SubdiagnosticMessageOp, + AddToDiagnostic, DecorateLint, Diag, DiagCtxt, DiagInner, DiagMessage, EmissionGuarantee, + IntoDiagnostic, Level, SubdiagMessageOp, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::Span; @@ -55,7 +56,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for TranslatableInIntoDiagn pub struct UntranslatableInAddToDiagnostic; impl AddToDiagnostic for UntranslatableInAddToDiagnostic { - fn add_to_diagnostic_with>( + fn add_to_diagnostic_with>( self, diag: &mut Diag<'_, G>, f: F, @@ -68,7 +69,7 @@ impl AddToDiagnostic for UntranslatableInAddToDiagnostic { pub struct TranslatableInAddToDiagnostic; impl AddToDiagnostic for TranslatableInAddToDiagnostic { - fn add_to_diagnostic_with>( + fn add_to_diagnostic_with>( self, diag: &mut Diag<'_, G>, f: F, @@ -77,6 +78,31 @@ impl AddToDiagnostic for TranslatableInAddToDiagnostic { } } +pub struct UntranslatableInDecorateLint; + +impl<'a> DecorateLint<'a, ()> for UntranslatableInDecorateLint { + fn decorate_lint<'b, >(self, diag: &'b mut Diag<'a, ()>) { + diag.note("untranslatable diagnostic"); + //~^ ERROR diagnostics should be created using translatable messages + } + + fn msg(&self) -> DiagMessage { + unreachable!(); + } +} + +pub struct TranslatableInDecorateLint; + +impl<'a> DecorateLint<'a, ()> for TranslatableInDecorateLint { + fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { + diag.note(crate::fluent_generated::no_crate_note); + } + + fn msg(&self) -> DiagMessage { + unreachable!(); + } +} + pub fn make_diagnostics<'a>(dcx: &'a DiagCtxt) { let _diag = dcx.struct_err(crate::fluent_generated::no_crate_example); //~^ ERROR diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls @@ -86,9 +112,11 @@ pub fn make_diagnostics<'a>(dcx: &'a DiagCtxt) { //~^^ ERROR diagnostics should be created using translatable messages } -// Check that `rustc_lint_diagnostics`-annotated functions aren't themselves linted. +// Check that `rustc_lint_diagnostics`-annotated functions aren't themselves linted for +// `diagnostic_outside_of_impl`. #[rustc_lint_diagnostics] pub fn skipped_because_of_annotation<'a>(dcx: &'a DiagCtxt) { + #[allow(rustc::untranslatable_diagnostic)] let _diag = dcx.struct_err("untranslatable diagnostic"); // okay! } diff --git a/tests/ui-fulldeps/internal-lints/diagnostics.stderr b/tests/ui-fulldeps/internal-lints/diagnostics.stderr index 1b1ad7d5892c7..b8fbee1ff009c 100644 --- a/tests/ui-fulldeps/internal-lints/diagnostics.stderr +++ b/tests/ui-fulldeps/internal-lints/diagnostics.stderr @@ -1,44 +1,50 @@ error: diagnostics should be created using translatable messages - --> $DIR/diagnostics.rs:42:9 + --> $DIR/diagnostics.rs:43:9 | LL | Diag::new(dcx, level, "untranslatable diagnostic") | ^^^^^^^^^ | note: the lint level is defined here - --> $DIR/diagnostics.rs:6:9 + --> $DIR/diagnostics.rs:7:9 | LL | #![deny(rustc::untranslatable_diagnostic)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostics should be created using translatable messages - --> $DIR/diagnostics.rs:63:14 + --> $DIR/diagnostics.rs:64:14 + | +LL | diag.note("untranslatable diagnostic"); + | ^^^^ + +error: diagnostics should be created using translatable messages + --> $DIR/diagnostics.rs:85:14 | LL | diag.note("untranslatable diagnostic"); | ^^^^ error: diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls - --> $DIR/diagnostics.rs:81:21 + --> $DIR/diagnostics.rs:107:21 | LL | let _diag = dcx.struct_err(crate::fluent_generated::no_crate_example); | ^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/diagnostics.rs:7:9 + --> $DIR/diagnostics.rs:8:9 | LL | #![deny(rustc::diagnostic_outside_of_impl)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls - --> $DIR/diagnostics.rs:84:21 + --> $DIR/diagnostics.rs:110:21 | LL | let _diag = dcx.struct_err("untranslatable diagnostic"); | ^^^^^^^^^^ error: diagnostics should be created using translatable messages - --> $DIR/diagnostics.rs:84:21 + --> $DIR/diagnostics.rs:110:21 | LL | let _diag = dcx.struct_err("untranslatable diagnostic"); | ^^^^^^^^^^ -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors diff --git a/tests/ui-fulldeps/mod_dir_path_canonicalized.rs b/tests/ui-fulldeps/mod_dir_path_canonicalized.rs index 8ffc4669ee27a..ef70e64ed7e91 100644 --- a/tests/ui-fulldeps/mod_dir_path_canonicalized.rs +++ b/tests/ui-fulldeps/mod_dir_path_canonicalized.rs @@ -18,7 +18,6 @@ extern crate rustc_driver; use rustc_parse::new_parser_from_file; use rustc_session::parse::ParseSess; -use rustc_span::source_map::FilePathMapping; use std::path::Path; #[path = "mod_dir_simple/test.rs"] @@ -31,13 +30,10 @@ pub fn main() { } fn parse() { - let parse_session = ParseSess::new( - vec![rustc_parse::DEFAULT_LOCALE_RESOURCE], - FilePathMapping::empty() - ); + let psess = ParseSess::new(vec![rustc_parse::DEFAULT_LOCALE_RESOURCE]); let path = Path::new(file!()); let path = path.canonicalize().unwrap(); - let mut parser = new_parser_from_file(&parse_session, &path, None); + let mut parser = new_parser_from_file(&psess, &path, None); let _ = parser.parse_crate_mod(); } diff --git a/tests/ui-fulldeps/pprust-expr-roundtrip.rs b/tests/ui-fulldeps/pprust-expr-roundtrip.rs index e1c326c6a9155..475a69f4ad098 100644 --- a/tests/ui-fulldeps/pprust-expr-roundtrip.rs +++ b/tests/ui-fulldeps/pprust-expr-roundtrip.rs @@ -38,16 +38,16 @@ use rustc_ast::*; use rustc_ast_pretty::pprust; use rustc_parse::new_parser_from_source_str; use rustc_session::parse::ParseSess; -use rustc_span::source_map::{FilePathMapping, Spanned}; +use rustc_span::source_map::Spanned; use rustc_span::symbol::Ident; use rustc_span::{FileName, DUMMY_SP}; use thin_vec::{thin_vec, ThinVec}; -fn parse_expr(ps: &ParseSess, src: &str) -> Option> { +fn parse_expr(psess: &ParseSess, src: &str) -> Option> { let src_as_string = src.to_string(); let mut p = - new_parser_from_source_str(ps, FileName::Custom(src_as_string.clone()), src_as_string); + new_parser_from_source_str(psess, FileName::Custom(src_as_string.clone()), src_as_string); p.parse_expr().map_err(|e| e.cancel()).ok() } @@ -225,7 +225,7 @@ fn main() { } fn run() { - let ps = ParseSess::new(vec![rustc_parse::DEFAULT_LOCALE_RESOURCE], FilePathMapping::empty()); + let psess = ParseSess::new(vec![rustc_parse::DEFAULT_LOCALE_RESOURCE]); iter_exprs(2, &mut |mut e| { // If the pretty printer is correct, then `parse(print(e))` should be identical to `e`, @@ -234,7 +234,7 @@ fn run() { println!("printed: {}", printed); // Ignore expressions with chained comparisons that fail to parse - if let Some(mut parsed) = parse_expr(&ps, &printed) { + if let Some(mut parsed) = parse_expr(&psess, &printed) { // We want to know if `parsed` is structurally identical to `e`, ignoring trivial // differences like placement of `Paren`s or the exact ranges of node spans. // Unfortunately, there is no easy way to make this comparison. Instead, we add `Paren`s diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.rs index 90bea03ffd5e1..40df9cc5dcadd 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.rs +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.rs @@ -19,7 +19,7 @@ extern crate rustc_macros; extern crate rustc_session; extern crate rustc_span; -use rustc_errors::{Applicability, DiagnosticMessage, SubdiagnosticMessage}; +use rustc_errors::{Applicability, DiagMessage, SubdiagMessage}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::Span; diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs index f2f42f054817d..1107097239441 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs @@ -25,7 +25,7 @@ extern crate rustc_middle; use rustc_middle::ty::Ty; extern crate rustc_errors; -use rustc_errors::{Applicability, DiagnosticMessage, ErrCode, MultiSpan, SubdiagnosticMessage}; +use rustc_errors::{Applicability, DiagMessage, ErrCode, MultiSpan, SubdiagMessage}; extern crate rustc_session; diff --git a/tests/ui-fulldeps/session-diagnostic/invalid-variable.rs b/tests/ui-fulldeps/session-diagnostic/invalid-variable.rs index ba529e42e7866..cbe9e3f4ef4c1 100644 --- a/tests/ui-fulldeps/session-diagnostic/invalid-variable.rs +++ b/tests/ui-fulldeps/session-diagnostic/invalid-variable.rs @@ -10,7 +10,7 @@ extern crate rustc_fluent_macro; extern crate rustc_macros; extern crate rustc_errors; use rustc_macros::Diagnostic; -use rustc_errors::{SubdiagnosticMessage, DiagnosticMessage}; +use rustc_errors::{DiagMessage, SubdiagMessage}; extern crate rustc_session; rustc_fluent_macro::fluent_messages! { "./example.ftl" } diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs index 15e3b212d9048..163af7ff0e214 100644 --- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs +++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs @@ -17,7 +17,7 @@ extern crate rustc_macros; extern crate rustc_session; extern crate rustc_span; -use rustc_errors::{Applicability, DiagnosticMessage, SubdiagnosticMessage}; +use rustc_errors::{Applicability, DiagMessage, SubdiagMessage}; use rustc_macros::Subdiagnostic; use rustc_span::Span; diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs index fcf31aa970cd0..3ee4542810c65 100644 --- a/tests/ui/abi/compatibility.rs +++ b/tests/ui/abi/compatibility.rs @@ -39,13 +39,13 @@ //@ revisions: loongarch64 //@[loongarch64] compile-flags: --target loongarch64-unknown-linux-gnu //@[loongarch64] needs-llvm-components: loongarch -//@[loongarch64] min-llvm-version: 17 +//@[loongarch64] min-llvm-version: 18 //@ revisions: wasm //@[wasm] compile-flags: --target wasm32-unknown-unknown //@[wasm] needs-llvm-components: webassembly -//@ revisions: wasi -//@[wasi] compile-flags: --target wasm32-wasi -//@[wasi] needs-llvm-components: webassembly +//@ revisions: wasip1 +//@[wasip1] compile-flags: --target wasm32-wasip1 +//@[wasip1] needs-llvm-components: webassembly //@ revisions: bpf //@[bpf] compile-flags: --target bpfeb-unknown-none //@[bpf] needs-llvm-components: bpf @@ -160,6 +160,7 @@ mod prelude { pub _marker: PhantomData, } + #[lang = "global_alloc_ty"] pub struct Global; #[lang = "owned_box"] diff --git a/tests/ui/abi/extern/extern-call-deep2.rs b/tests/ui/abi/extern/extern-call-deep2.rs index 80c492e302216..c021bc223482d 100644 --- a/tests/ui/abi/extern/extern-call-deep2.rs +++ b/tests/ui/abi/extern/extern-call-deep2.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_must_use)] -//@ ignore-emscripten no threads support +//@ needs-threads #![feature(rustc_private)] extern crate libc; diff --git a/tests/ui/abi/extern/extern-call-scrub.rs b/tests/ui/abi/extern/extern-call-scrub.rs index 873f5d2e7748f..7edf8975ad816 100644 --- a/tests/ui/abi/extern/extern-call-scrub.rs +++ b/tests/ui/abi/extern/extern-call-scrub.rs @@ -4,7 +4,7 @@ // make sure the stack pointers are maintained properly in both // directions -//@ ignore-emscripten no threads support +//@ needs-threads #![feature(rustc_private)] extern crate libc; diff --git a/tests/ui/abi/foreign/foreign-call-no-runtime.rs b/tests/ui/abi/foreign/foreign-call-no-runtime.rs index 7f847d55721c3..42d8d7b1d2596 100644 --- a/tests/ui/abi/foreign/foreign-call-no-runtime.rs +++ b/tests/ui/abi/foreign/foreign-call-no-runtime.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ ignore-emscripten no threads support +//@ needs-threads #![feature(rustc_private)] diff --git a/tests/ui/argfile/commandline-argfile-badutf8-windows.rs b/tests/ui/argfile/commandline-argfile-badutf8-windows.rs new file mode 100644 index 0000000000000..eba17ca6f7e92 --- /dev/null +++ b/tests/ui/argfile/commandline-argfile-badutf8-windows.rs @@ -0,0 +1,17 @@ +// Check to see if we can get parameters from an @argsfile file +// +// Path replacement in .stderr files (i.e. `$DIR`) doesn't handle mixed path +// separators. This test uses backslash as the path separator for the command +// line arguments and is only run on windows. +// +//@ only-windows +//@ compile-flags: --cfg cmdline_set @{{src-base}}\argfile\commandline-argfile-badutf8.args + +#[cfg(not(cmdline_set))] +compile_error!("cmdline_set not set"); + +#[cfg(not(unbroken))] +compile_error!("unbroken not set"); + +fn main() { +} diff --git a/tests/ui/argfile/commandline-argfile-badutf8-windows.stderr b/tests/ui/argfile/commandline-argfile-badutf8-windows.stderr new file mode 100644 index 0000000000000..b4c0d4c20d75f --- /dev/null +++ b/tests/ui/argfile/commandline-argfile-badutf8-windows.stderr @@ -0,0 +1,2 @@ +error: failed to load argument file: UTF-8 error in $DIR/commandline-argfile-badutf8.args + diff --git a/tests/ui/commandline-argfile-badutf8.args b/tests/ui/argfile/commandline-argfile-badutf8.args similarity index 100% rename from tests/ui/commandline-argfile-badutf8.args rename to tests/ui/argfile/commandline-argfile-badutf8.args diff --git a/tests/ui/argfile/commandline-argfile-badutf8.rs b/tests/ui/argfile/commandline-argfile-badutf8.rs new file mode 100644 index 0000000000000..1b2e52af762f1 --- /dev/null +++ b/tests/ui/argfile/commandline-argfile-badutf8.rs @@ -0,0 +1,18 @@ +// Check to see if we can get parameters from an @argsfile file +// +// Path replacement in .stderr files (i.e. `$DIR`) doesn't handle mixed path +// separators. We have a duplicated version of this test that uses backslash as +// the path separator for the command line arguments that is only run on +// windows. +// +//@ ignore-windows +//@ compile-flags: --cfg cmdline_set @{{src-base}}/argfile/commandline-argfile-badutf8.args + +#[cfg(not(cmdline_set))] +compile_error!("cmdline_set not set"); + +#[cfg(not(unbroken))] +compile_error!("unbroken not set"); + +fn main() { +} diff --git a/tests/ui/argfile/commandline-argfile-badutf8.stderr b/tests/ui/argfile/commandline-argfile-badutf8.stderr new file mode 100644 index 0000000000000..b4c0d4c20d75f --- /dev/null +++ b/tests/ui/argfile/commandline-argfile-badutf8.stderr @@ -0,0 +1,2 @@ +error: failed to load argument file: UTF-8 error in $DIR/commandline-argfile-badutf8.args + diff --git a/tests/ui/commandline-argfile-missing.rs b/tests/ui/argfile/commandline-argfile-missing-windows.rs similarity index 55% rename from tests/ui/commandline-argfile-missing.rs rename to tests/ui/argfile/commandline-argfile-missing-windows.rs index bb9644d66ce10..24cfd25ccadb9 100644 --- a/tests/ui/commandline-argfile-missing.rs +++ b/tests/ui/argfile/commandline-argfile-missing-windows.rs @@ -1,8 +1,13 @@ // Check to see if we can get parameters from an @argsfile file // +// Path replacement in .stderr files (i.e. `$DIR`) doesn't handle mixed path +// separators. This test uses backslash as the path separator for the command +// line arguments and is only run on windows. +// +//@ only-windows //@ normalize-stderr-test: "os error \d+" -> "os error $$ERR" //@ normalize-stderr-test: "commandline-argfile-missing.args:[^(]*" -> "commandline-argfile-missing.args: $$FILE_MISSING " -//@ compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-missing.args +//@ compile-flags: --cfg cmdline_set @{{src-base}}\argfile\commandline-argfile-missing.args #[cfg(not(cmdline_set))] compile_error!("cmdline_set not set"); diff --git a/tests/ui/argfile/commandline-argfile-missing-windows.stderr b/tests/ui/argfile/commandline-argfile-missing-windows.stderr new file mode 100644 index 0000000000000..28a20debf1cca --- /dev/null +++ b/tests/ui/argfile/commandline-argfile-missing-windows.stderr @@ -0,0 +1,2 @@ +error: failed to load argument file: IO error: $DIR/commandline-argfile-missing.args: $FILE_MISSING (os error $ERR) + diff --git a/tests/ui/argfile/commandline-argfile-missing.rs b/tests/ui/argfile/commandline-argfile-missing.rs new file mode 100644 index 0000000000000..fe6a849b0c8b6 --- /dev/null +++ b/tests/ui/argfile/commandline-argfile-missing.rs @@ -0,0 +1,20 @@ +// Check to see if we can get parameters from an @argsfile file +// +// Path replacement in .stderr files (i.e. `$DIR`) doesn't handle mixed path +// separators. We have a duplicated version of this test that uses backslash as +// the path separator for the command line arguments that is only run on +// windows. +// +//@ ignore-windows +//@ normalize-stderr-test: "os error \d+" -> "os error $$ERR" +//@ normalize-stderr-test: "commandline-argfile-missing.args:[^(]*" -> "commandline-argfile-missing.args: $$FILE_MISSING " +//@ compile-flags: --cfg cmdline_set @{{src-base}}/argfile/commandline-argfile-missing.args + +#[cfg(not(cmdline_set))] +compile_error!("cmdline_set not set"); + +#[cfg(not(unbroken))] +compile_error!("unbroken not set"); + +fn main() { +} diff --git a/tests/ui/argfile/commandline-argfile-missing.stderr b/tests/ui/argfile/commandline-argfile-missing.stderr new file mode 100644 index 0000000000000..28a20debf1cca --- /dev/null +++ b/tests/ui/argfile/commandline-argfile-missing.stderr @@ -0,0 +1,2 @@ +error: failed to load argument file: IO error: $DIR/commandline-argfile-missing.args: $FILE_MISSING (os error $ERR) + diff --git a/tests/ui/argfile/commandline-argfile-multiple-windows.rs b/tests/ui/argfile/commandline-argfile-multiple-windows.rs new file mode 100644 index 0000000000000..84c050d84e25b --- /dev/null +++ b/tests/ui/argfile/commandline-argfile-multiple-windows.rs @@ -0,0 +1,20 @@ +// Check to see if we can get parameters from an @argsfile file +// +// Path replacement in .stderr files (i.e. `$DIR`) doesn't handle mixed path +// separators. This test uses backslash as the path separator for the command +// line arguments and is only run on windows. +// +//@ only-windows +//@ normalize-stderr-test: "os error \d+" -> "os error $$ERR" +//@ normalize-stderr-test: "commandline-argfile-missing.args:[^(]*" -> "commandline-argfile-missing.args: $$FILE_MISSING " +//@ normalize-stderr-test: "commandline-argfile-missing2.args:[^(]*" -> "commandline-argfile-missing2.args: $$FILE_MISSING " +//@ compile-flags: --cfg cmdline_set @{{src-base}}\argfile\commandline-argfile-missing.args @{{src-base}}\argfile\commandline-argfile-badutf8.args @{{src-base}}\argfile\commandline-argfile-missing2.args + +#[cfg(not(cmdline_set))] +compile_error!("cmdline_set not set"); + +#[cfg(not(unbroken))] +compile_error!("unbroken not set"); + +fn main() { +} diff --git a/tests/ui/argfile/commandline-argfile-multiple-windows.stderr b/tests/ui/argfile/commandline-argfile-multiple-windows.stderr new file mode 100644 index 0000000000000..ad3b445c958fd --- /dev/null +++ b/tests/ui/argfile/commandline-argfile-multiple-windows.stderr @@ -0,0 +1,6 @@ +error: failed to load argument file: IO error: $DIR/commandline-argfile-missing.args: $FILE_MISSING (os error $ERR) + +error: failed to load argument file: UTF-8 error in $DIR/commandline-argfile-badutf8.args + +error: failed to load argument file: IO error: $DIR/commandline-argfile-missing2.args: $FILE_MISSING (os error $ERR) + diff --git a/tests/ui/argfile/commandline-argfile-multiple.rs b/tests/ui/argfile/commandline-argfile-multiple.rs new file mode 100644 index 0000000000000..f658ee34fbb08 --- /dev/null +++ b/tests/ui/argfile/commandline-argfile-multiple.rs @@ -0,0 +1,21 @@ +// Check to see if we can get parameters from an @argsfile file +// +// Path replacement in .stderr files (i.e. `$DIR`) doesn't handle mixed path +// separators. We have a duplicated version of this test that uses backslash as +// the path separator for the command line arguments that is only run on +// windows. +// +//@ ignore-windows +//@ normalize-stderr-test: "os error \d+" -> "os error $$ERR" +//@ normalize-stderr-test: "commandline-argfile-missing.args:[^(]*" -> "commandline-argfile-missing.args: $$FILE_MISSING " +//@ normalize-stderr-test: "commandline-argfile-missing2.args:[^(]*" -> "commandline-argfile-missing2.args: $$FILE_MISSING " +//@ compile-flags: --cfg cmdline_set @{{src-base}}/argfile/commandline-argfile-missing.args @{{src-base}}/argfile/commandline-argfile-badutf8.args @{{src-base}}/argfile/commandline-argfile-missing2.args + +#[cfg(not(cmdline_set))] +compile_error!("cmdline_set not set"); + +#[cfg(not(unbroken))] +compile_error!("unbroken not set"); + +fn main() { +} diff --git a/tests/ui/argfile/commandline-argfile-multiple.stderr b/tests/ui/argfile/commandline-argfile-multiple.stderr new file mode 100644 index 0000000000000..ad3b445c958fd --- /dev/null +++ b/tests/ui/argfile/commandline-argfile-multiple.stderr @@ -0,0 +1,6 @@ +error: failed to load argument file: IO error: $DIR/commandline-argfile-missing.args: $FILE_MISSING (os error $ERR) + +error: failed to load argument file: UTF-8 error in $DIR/commandline-argfile-badutf8.args + +error: failed to load argument file: IO error: $DIR/commandline-argfile-missing2.args: $FILE_MISSING (os error $ERR) + diff --git a/tests/ui/commandline-argfile.args b/tests/ui/argfile/commandline-argfile.args similarity index 100% rename from tests/ui/commandline-argfile.args rename to tests/ui/argfile/commandline-argfile.args diff --git a/tests/ui/commandline-argfile.rs b/tests/ui/argfile/commandline-argfile.rs similarity index 72% rename from tests/ui/commandline-argfile.rs rename to tests/ui/argfile/commandline-argfile.rs index 8577312a3c406..387a8d033b3cd 100644 --- a/tests/ui/commandline-argfile.rs +++ b/tests/ui/argfile/commandline-argfile.rs @@ -1,7 +1,7 @@ // Check to see if we can get parameters from an @argsfile file // //@ build-pass -//@ compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile.args +//@ compile-flags: --cfg cmdline_set @{{src-base}}/argfile/commandline-argfile.args #[cfg(not(cmdline_set))] compile_error!("cmdline_set not set"); diff --git a/tests/ui/asm/aarch64/parse-error.stderr b/tests/ui/asm/aarch64/parse-error.stderr index 46984a1fe1ca0..539c134472fda 100644 --- a/tests/ui/asm/aarch64/parse-error.stderr +++ b/tests/ui/asm/aarch64/parse-error.stderr @@ -130,17 +130,17 @@ LL | asm!("{1}", in("x0") foo, const bar); | | | explicit register argument -error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `""` +error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `label`, `lateout`, `options`, `out`, or `sym`, found `""` --> $DIR/parse-error.rs:66:29 | LL | asm!("", options(), ""); - | ^^ expected one of 9 possible tokens + | ^^ expected one of 10 possible tokens -error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `"{}"` +error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `label`, `lateout`, `options`, `out`, or `sym`, found `"{}"` --> $DIR/parse-error.rs:68:33 | LL | asm!("{}", in(reg) foo, "{}", out(reg) foo); - | ^^^^ expected one of 9 possible tokens + | ^^^^ expected one of 10 possible tokens error: asm template must be a string literal --> $DIR/parse-error.rs:70:14 diff --git a/tests/ui/asm/parse-error.rs b/tests/ui/asm/parse-error.rs index 6f32293511bf6..a0251c6763ba4 100644 --- a/tests/ui/asm/parse-error.rs +++ b/tests/ui/asm/parse-error.rs @@ -142,3 +142,5 @@ global_asm!(format!("{{{}}}", 0), const FOO); //~^ ERROR asm template must be a string literal global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR); //~^ ERROR asm template must be a string literal +global_asm!("{}", label {}); +//~^ ERROR expected operand, options, or additional template string diff --git a/tests/ui/asm/parse-error.stderr b/tests/ui/asm/parse-error.stderr index 075d28e176ad8..80ee5191dbbe9 100644 --- a/tests/ui/asm/parse-error.stderr +++ b/tests/ui/asm/parse-error.stderr @@ -176,17 +176,17 @@ LL | asm!("{a}", a = const foo, a = const bar); | = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"` -error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `""` +error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `label`, `lateout`, `options`, `out`, or `sym`, found `""` --> $DIR/parse-error.rs:82:29 | LL | asm!("", options(), ""); - | ^^ expected one of 9 possible tokens + | ^^ expected one of 10 possible tokens -error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `"{}"` +error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `label`, `lateout`, `options`, `out`, or `sym`, found `"{}"` --> $DIR/parse-error.rs:84:33 | LL | asm!("{}", in(reg) foo, "{}", out(reg) foo); - | ^^^^ expected one of 9 possible tokens + | ^^^^ expected one of 10 possible tokens error: asm template must be a string literal --> $DIR/parse-error.rs:86:14 @@ -362,6 +362,12 @@ LL | global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR); | = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) +error: expected operand, options, or additional template string + --> $DIR/parse-error.rs:145:19 + | +LL | global_asm!("{}", label {}); + | ^^^^^^^^ expected operand, options, or additional template string + error[E0435]: attempt to use a non-constant value in a constant --> $DIR/parse-error.rs:39:37 | @@ -407,6 +413,6 @@ LL | let mut bar = 0; LL | asm!("{a}", a = const foo, a = const bar); | ^^^ non-constant value -error: aborting due to 63 previous errors +error: aborting due to 64 previous errors For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/asm/x86_64/bad-options.rs b/tests/ui/asm/x86_64/bad-options.rs index a6d5022ecf130..f9cc13cfc5a8b 100644 --- a/tests/ui/asm/x86_64/bad-options.rs +++ b/tests/ui/asm/x86_64/bad-options.rs @@ -1,5 +1,7 @@ //@ only-x86_64 +#![feature(asm_unwind, asm_goto)] + use std::arch::{asm, global_asm}; fn main() { @@ -14,6 +16,8 @@ fn main() { //~^ ERROR asm with the `pure` option must have at least one output asm!("{}", out(reg) foo, options(noreturn)); //~^ ERROR asm outputs are not allowed with the `noreturn` option + asm!("{}", label {}, options(may_unwind)); + //~^ ERROR asm labels are not allowed with the `may_unwind` option } unsafe { diff --git a/tests/ui/asm/x86_64/bad-options.stderr b/tests/ui/asm/x86_64/bad-options.stderr index e2351840eef21..aa167e7913c3e 100644 --- a/tests/ui/asm/x86_64/bad-options.stderr +++ b/tests/ui/asm/x86_64/bad-options.stderr @@ -1,35 +1,41 @@ error: the `nomem` and `readonly` options are mutually exclusive - --> $DIR/bad-options.rs:8:18 + --> $DIR/bad-options.rs:10:18 | LL | asm!("", options(nomem, readonly)); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: the `pure` and `noreturn` options are mutually exclusive - --> $DIR/bad-options.rs:10:18 + --> $DIR/bad-options.rs:12:18 | LL | asm!("", options(pure, nomem, noreturn)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: asm with the `pure` option must have at least one output - --> $DIR/bad-options.rs:10:18 + --> $DIR/bad-options.rs:12:18 | LL | asm!("", options(pure, nomem, noreturn)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: asm with the `pure` option must have at least one output - --> $DIR/bad-options.rs:13:33 + --> $DIR/bad-options.rs:15:33 | LL | asm!("{}", in(reg) foo, options(pure, nomem)); | ^^^^^^^^^^^^^^^^^^^^ error: asm outputs are not allowed with the `noreturn` option - --> $DIR/bad-options.rs:15:20 + --> $DIR/bad-options.rs:17:20 | LL | asm!("{}", out(reg) foo, options(noreturn)); | ^^^^^^^^^^^^ +error: asm labels are not allowed with the `may_unwind` option + --> $DIR/bad-options.rs:19:20 + | +LL | asm!("{}", label {}, options(may_unwind)); + | ^^^^^^^^ + error: asm with `clobber_abi` must specify explicit registers for outputs - --> $DIR/bad-options.rs:22:20 + --> $DIR/bad-options.rs:26:20 | LL | asm!("{}", out(reg) foo, clobber_abi("C")); | ^^^^^^^^^^^^ ---------------- clobber_abi @@ -37,7 +43,7 @@ LL | asm!("{}", out(reg) foo, clobber_abi("C")); | generic outputs error: asm with `clobber_abi` must specify explicit registers for outputs - --> $DIR/bad-options.rs:24:20 + --> $DIR/bad-options.rs:28:20 | LL | asm!("{}", out(reg) foo, clobber_abi("C"), clobber_abi("C")); | ^^^^^^^^^^^^ ---------------- ---------------- clobber_abi @@ -46,43 +52,43 @@ LL | asm!("{}", out(reg) foo, clobber_abi("C"), clobber_abi("C")); | generic outputs error: expected one of `)`, `att_syntax`, or `raw`, found `nomem` - --> $DIR/bad-options.rs:31:25 + --> $DIR/bad-options.rs:35:25 | LL | global_asm!("", options(nomem)); | ^^^^^ expected one of `)`, `att_syntax`, or `raw` error: expected one of `)`, `att_syntax`, or `raw`, found `readonly` - --> $DIR/bad-options.rs:33:25 + --> $DIR/bad-options.rs:37:25 | LL | global_asm!("", options(readonly)); | ^^^^^^^^ expected one of `)`, `att_syntax`, or `raw` error: expected one of `)`, `att_syntax`, or `raw`, found `noreturn` - --> $DIR/bad-options.rs:35:25 + --> $DIR/bad-options.rs:39:25 | LL | global_asm!("", options(noreturn)); | ^^^^^^^^ expected one of `)`, `att_syntax`, or `raw` error: expected one of `)`, `att_syntax`, or `raw`, found `pure` - --> $DIR/bad-options.rs:37:25 + --> $DIR/bad-options.rs:41:25 | LL | global_asm!("", options(pure)); | ^^^^ expected one of `)`, `att_syntax`, or `raw` error: expected one of `)`, `att_syntax`, or `raw`, found `nostack` - --> $DIR/bad-options.rs:39:25 + --> $DIR/bad-options.rs:43:25 | LL | global_asm!("", options(nostack)); | ^^^^^^^ expected one of `)`, `att_syntax`, or `raw` error: expected one of `)`, `att_syntax`, or `raw`, found `preserves_flags` - --> $DIR/bad-options.rs:41:25 + --> $DIR/bad-options.rs:45:25 | LL | global_asm!("", options(preserves_flags)); | ^^^^^^^^^^^^^^^ expected one of `)`, `att_syntax`, or `raw` error: invalid ABI for `clobber_abi` - --> $DIR/bad-options.rs:20:18 + --> $DIR/bad-options.rs:24:18 | LL | asm!("", clobber_abi("foo")); | ^^^^^^^^^^^^^^^^^^ @@ -90,12 +96,12 @@ LL | asm!("", clobber_abi("foo")); = note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, `sysv64` error: `C` ABI specified multiple times - --> $DIR/bad-options.rs:24:52 + --> $DIR/bad-options.rs:28:52 | LL | asm!("{}", out(reg) foo, clobber_abi("C"), clobber_abi("C")); | ---------------- ^^^^^^^^^^^^^^^^ | | | previously specified here -error: aborting due to 15 previous errors +error: aborting due to 16 previous errors diff --git a/tests/ui/asm/x86_64/goto.mirunsafeck.stderr b/tests/ui/asm/x86_64/goto.mirunsafeck.stderr new file mode 100644 index 0000000000000..fe189c14f0a7c --- /dev/null +++ b/tests/ui/asm/x86_64/goto.mirunsafeck.stderr @@ -0,0 +1,23 @@ +warning: unreachable statement + --> $DIR/goto.rs:99:9 + | +LL | / asm!( +LL | | "jmp {}", +LL | | label { +LL | | return; +LL | | }, +LL | | options(noreturn) +LL | | ); + | |_________- any code following this expression is unreachable +LL | unreachable!(); + | ^^^^^^^^^^^^^^ unreachable statement + | +note: the lint level is defined here + --> $DIR/goto.rs:89:8 + | +LL | #[warn(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + = note: this warning originates in the macro `unreachable` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: 1 warning emitted + diff --git a/tests/ui/asm/x86_64/goto.rs b/tests/ui/asm/x86_64/goto.rs new file mode 100644 index 0000000000000..6a567efbb2c7e --- /dev/null +++ b/tests/ui/asm/x86_64/goto.rs @@ -0,0 +1,111 @@ +//@ only-x86_64 +//@ run-pass +//@ needs-asm-support +//@ revisions: mirunsafeck thirunsafeck +//@ [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![deny(unreachable_code)] +#![feature(asm_goto)] + +use std::arch::asm; + +fn goto_fallthough() { + unsafe { + asm!( + "/* {} */", + label { + unreachable!(); + } + ) + } +} + +fn goto_jump() { + unsafe { + let mut value = false; + asm!( + "jmp {}", + label { + value = true; + } + ); + assert!(value); + } +} + +// asm goto with outputs cause miscompilation in LLVM. UB can be triggered +// when outputs are used inside the label block when optimisation is enabled. +// See: https://github.com/llvm/llvm-project/issues/74483 +/* +fn goto_out_fallthrough() { + unsafe { + let mut out: usize; + asm!( + "lea {}, [{} + 1]", + "/* {} */", + out(reg) out, + in(reg) 0x12345678usize, + label { + unreachable!(); + } + ); + assert_eq!(out, 0x12345679); + } +} + +fn goto_out_jump() { + unsafe { + let mut value = false; + let mut out: usize; + asm!( + "lea {}, [{} + 1]", + "jmp {}", + out(reg) out, + in(reg) 0x12345678usize, + label { + value = true; + assert_eq!(out, 0x12345679); + } + ); + assert!(value); + } +} +*/ + +fn goto_noreturn() { + unsafe { + let a; + asm!( + "jmp {}", + label { + a = 1; + }, + options(noreturn) + ); + assert_eq!(a, 1); + } +} + +#[warn(unreachable_code)] +fn goto_noreturn_diverge() { + unsafe { + asm!( + "jmp {}", + label { + return; + }, + options(noreturn) + ); + unreachable!(); + //~^ WARN unreachable statement + } +} + +fn main() { + goto_fallthough(); + goto_jump(); + // goto_out_fallthrough(); + // goto_out_jump(); + goto_noreturn(); + goto_noreturn_diverge(); +} diff --git a/tests/ui/asm/x86_64/goto.thirunsafeck.stderr b/tests/ui/asm/x86_64/goto.thirunsafeck.stderr new file mode 100644 index 0000000000000..fe189c14f0a7c --- /dev/null +++ b/tests/ui/asm/x86_64/goto.thirunsafeck.stderr @@ -0,0 +1,23 @@ +warning: unreachable statement + --> $DIR/goto.rs:99:9 + | +LL | / asm!( +LL | | "jmp {}", +LL | | label { +LL | | return; +LL | | }, +LL | | options(noreturn) +LL | | ); + | |_________- any code following this expression is unreachable +LL | unreachable!(); + | ^^^^^^^^^^^^^^ unreachable statement + | +note: the lint level is defined here + --> $DIR/goto.rs:89:8 + | +LL | #[warn(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + = note: this warning originates in the macro `unreachable` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: 1 warning emitted + diff --git a/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.stderr b/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.stderr index a2ad4cbde01ca..a495e94bd9ab3 100644 --- a/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.stderr +++ b/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.stderr @@ -26,17 +26,11 @@ note: ...which requires computing normalized predicates of `Foo`... LL | struct Foo { | ^^^^^^^^^^ = note: ...which again requires computing predicates of `Foo`, completing the cycle -note: cycle used when collecting item types in top-level module - --> $DIR/cycle-iat-inside-of-adt.rs:3:1 +note: cycle used when checking that `Foo` is well-formed + --> $DIR/cycle-iat-inside-of-adt.rs:7:1 | -LL | / #![feature(inherent_associated_types)] -LL | | #![allow(incomplete_features)] -LL | | // FIXME(inherent_associated_types): This should pass. -LL | | -... | -LL | | -LL | | fn main() {} - | |____________^ +LL | struct Foo { + | ^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error: aborting due to 1 previous error diff --git a/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-where-predicate.stderr b/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-where-predicate.stderr index b3d55fea14b5a..e7292c08ebd0c 100644 --- a/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-where-predicate.stderr +++ b/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-where-predicate.stderr @@ -20,19 +20,23 @@ note: ...which requires computing normalized predicates of `user`... LL | fn user() where S::P: std::fmt::Debug {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which again requires computing predicates of `user`, completing the cycle -note: cycle used when collecting item types in top-level module - --> $DIR/cycle-iat-inside-of-where-predicate.rs:3:1 - | -LL | / #![feature(inherent_associated_types)] -LL | | #![allow(incomplete_features)] -LL | | -LL | | // FIXME(inherent_associated_types): This shouldn't lead to a cycle error. -... | -LL | | -LL | | fn main() {} - | |____________^ +note: cycle used when checking that `user` is well-formed + --> $DIR/cycle-iat-inside-of-where-predicate.rs:8:1 + | +LL | fn user() where S::P: std::fmt::Debug {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to 1 previous error +error[E0392]: type parameter `T` is never used + --> $DIR/cycle-iat-inside-of-where-predicate.rs:10:10 + | +LL | struct S; + | ^ unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0391`. +Some errors have detailed explanations: E0391, E0392. +For more information about an error, try `rustc --explain E0391`. diff --git a/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr b/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr index b8366b15a8ae4..72d3f5c6d4d42 100644 --- a/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr +++ b/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr @@ -20,16 +20,6 @@ help: add missing generic argument LL | impl Windows { | +++ -error[E0658]: inherent associated types are unstable - --> $DIR/issue-109071.rs:8:5 - | -LL | type Item = &[T]; - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #8995 for more information - = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error[E0223]: ambiguous associated type --> $DIR/issue-109071.rs:15:22 | @@ -43,6 +33,16 @@ LL | fn T() -> Option< as IntoAsyncIterator>::Item> {} LL | fn T() -> Option< as IntoIterator>::Item> {} | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +error[E0658]: inherent associated types are unstable + --> $DIR/issue-109071.rs:8:5 + | +LL | type Item = &[T]; + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #8995 for more information + = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + error: aborting due to 4 previous errors Some errors have detailed explanations: E0107, E0223, E0637, E0658. diff --git a/tests/ui/associated-type-bounds/duplicate.stderr b/tests/ui/associated-type-bounds/duplicate.stderr index 9816d11a40a8b..6345ef4b79860 100644 --- a/tests/ui/associated-type-bounds/duplicate.stderr +++ b/tests/ui/associated-type-bounds/duplicate.stderr @@ -198,6 +198,17 @@ LL | fn FRPIT1() -> impl Iterator { | | | `Item` bound here first +error[E0282]: type annotations needed + --> $DIR/duplicate.rs:136:5 + | +LL | iter::empty() + | ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `empty` + | +help: consider specifying the generic argument + | +LL | iter::empty::() + | +++++ + error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified --> $DIR/duplicate.rs:139:42 | @@ -206,6 +217,17 @@ LL | fn FRPIT2() -> impl Iterator { | | | `Item` bound here first +error[E0282]: type annotations needed + --> $DIR/duplicate.rs:141:5 + | +LL | iter::empty() + | ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `empty` + | +help: consider specifying the generic argument + | +LL | iter::empty::() + | +++++ + error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified --> $DIR/duplicate.rs:144:45 | @@ -214,6 +236,17 @@ LL | fn FRPIT3() -> impl Iterator { | | | `Item` bound here first +error[E0282]: type annotations needed + --> $DIR/duplicate.rs:146:5 + | +LL | iter::empty() + | ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `empty` + | +help: consider specifying the generic argument + | +LL | iter::empty::() + | +++++ + error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified --> $DIR/duplicate.rs:149:40 | @@ -376,6 +409,16 @@ LL | trait TRS1: Iterator {} | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified + --> $DIR/duplicate.rs:197:34 + | +LL | trait TRS1: Iterator {} + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified --> $DIR/duplicate.rs:201:34 | @@ -394,6 +437,16 @@ LL | trait TRS2: Iterator {} | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified + --> $DIR/duplicate.rs:201:34 + | +LL | trait TRS2: Iterator {} + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified --> $DIR/duplicate.rs:205:37 | @@ -412,6 +465,16 @@ LL | trait TRS3: Iterator {} | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified + --> $DIR/duplicate.rs:205:37 + | +LL | trait TRS3: Iterator {} + | ------------- ^^^^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified --> $DIR/duplicate.rs:211:29 | @@ -454,6 +517,16 @@ LL | Self: Iterator, | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified + --> $DIR/duplicate.rs:229:32 + | +LL | Self: Iterator, + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified --> $DIR/duplicate.rs:237:32 | @@ -472,6 +545,16 @@ LL | Self: Iterator, | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified + --> $DIR/duplicate.rs:237:32 + | +LL | Self: Iterator, + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified --> $DIR/duplicate.rs:245:35 | @@ -490,6 +573,16 @@ LL | Self: Iterator, | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified + --> $DIR/duplicate.rs:245:35 + | +LL | Self: Iterator, + | ------------- ^^^^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified --> $DIR/duplicate.rs:252:34 | @@ -514,99 +607,6 @@ LL | type A: Iterator; | | | `Item` bound here first -error[E0282]: type annotations needed - --> $DIR/duplicate.rs:136:5 - | -LL | iter::empty() - | ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `empty` - | -help: consider specifying the generic argument - | -LL | iter::empty::() - | +++++ - -error[E0282]: type annotations needed - --> $DIR/duplicate.rs:141:5 - | -LL | iter::empty() - | ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `empty` - | -help: consider specifying the generic argument - | -LL | iter::empty::() - | +++++ - -error[E0282]: type annotations needed - --> $DIR/duplicate.rs:146:5 - | -LL | iter::empty() - | ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `empty` - | -help: consider specifying the generic argument - | -LL | iter::empty::() - | +++++ - -error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified - --> $DIR/duplicate.rs:197:34 - | -LL | trait TRS1: Iterator {} - | ---------- ^^^^^^^^^^ re-bound here - | | - | `Item` bound here first - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified - --> $DIR/duplicate.rs:201:34 - | -LL | trait TRS2: Iterator {} - | ---------- ^^^^^^^^^^ re-bound here - | | - | `Item` bound here first - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified - --> $DIR/duplicate.rs:205:37 - | -LL | trait TRS3: Iterator {} - | ------------- ^^^^^^^^^^^^^ re-bound here - | | - | `Item` bound here first - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified - --> $DIR/duplicate.rs:229:32 - | -LL | Self: Iterator, - | ---------- ^^^^^^^^^^ re-bound here - | | - | `Item` bound here first - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified - --> $DIR/duplicate.rs:237:32 - | -LL | Self: Iterator, - | ---------- ^^^^^^^^^^ re-bound here - | | - | `Item` bound here first - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified - --> $DIR/duplicate.rs:245:35 - | -LL | Self: Iterator, - | ------------- ^^^^^^^^^^^^^ re-bound here - | | - | `Item` bound here first - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - error: aborting due to 72 previous errors Some errors have detailed explanations: E0282, E0719. diff --git a/tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr b/tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr index 2a308f83731fa..03d72f2ae2c6e 100644 --- a/tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr +++ b/tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr @@ -1,11 +1,8 @@ -error[E0191]: the value of the associated types `Item`, `Item`, `IntoIter` and `IntoIter` in `IntoIterator` must be specified +error[E0191]: the value of the associated types `Item` and `IntoIter` in `IntoIterator` must be specified --> $DIR/overlaping-bound-suggestion.rs:7:13 | LL | inner: >::IntoIterator as Item>::Core, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | | - | | associated types `Item`, `IntoIter` must be specified - | associated types `Item`, `IntoIter` must be specified + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: specify the associated types: `IntoIterator, Item = Type, IntoIter = Type>` error[E0223]: ambiguous associated type --> $DIR/overlaping-bound-suggestion.rs:7:13 diff --git a/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr b/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr index d361643f024d1..c5260adbed43a 100644 --- a/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr +++ b/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr @@ -9,6 +9,23 @@ help: if there were a type named `Example` that implemented `Get`, you could use LL | fn get(x: T, y: U) -> ::Value {} | ~~~~~~~~~~~~~~~~~~~~~~~ +error[E0223]: ambiguous associated type + --> $DIR/associated-types-in-ambiguous-context.rs:13:23 + | +LL | fn grab(&self) -> Grab::Value; + | ^^^^^^^^^^^ help: use fully-qualified syntax: `::Value` + +error[E0223]: ambiguous associated type + --> $DIR/associated-types-in-ambiguous-context.rs:16:22 + | +LL | fn get(&self) -> Get::Value; + | ^^^^^^^^^^ + | +help: if there were a type named `Example` that implemented `Get`, you could use the fully-qualified path + | +LL | fn get(&self) -> ::Value; + | ~~~~~~~~~~~~~~~~~~~~~~~ + error[E0223]: ambiguous associated type --> $DIR/associated-types-in-ambiguous-context.rs:22:17 | @@ -33,23 +50,6 @@ LL | type X = ::Target; | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ and N other candidates -error[E0223]: ambiguous associated type - --> $DIR/associated-types-in-ambiguous-context.rs:13:23 - | -LL | fn grab(&self) -> Grab::Value; - | ^^^^^^^^^^^ help: use fully-qualified syntax: `::Value` - -error[E0223]: ambiguous associated type - --> $DIR/associated-types-in-ambiguous-context.rs:16:22 - | -LL | fn get(&self) -> Get::Value; - | ^^^^^^^^^^ - | -help: if there were a type named `Example` that implemented `Get`, you could use the fully-qualified path - | -LL | fn get(&self) -> ::Value; - | ~~~~~~~~~~~~~~~~~~~~~~~ - error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/associated-types/hr-associated-type-projection-1.rs b/tests/ui/associated-types/hr-associated-type-projection-1.rs index 3df3f68ab1eed..d7fc5d122c3ec 100644 --- a/tests/ui/associated-types/hr-associated-type-projection-1.rs +++ b/tests/ui/associated-types/hr-associated-type-projection-1.rs @@ -11,8 +11,8 @@ where } impl UnsafeCopy<'_, T> for T { - //~^ type mismatch resolving `::Target == T` type Item = T; + //~^ type mismatch resolving `::Target == T` } pub fn main() { diff --git a/tests/ui/associated-types/hr-associated-type-projection-1.stderr b/tests/ui/associated-types/hr-associated-type-projection-1.stderr index 65221718ee661..b871bb51ae313 100644 --- a/tests/ui/associated-types/hr-associated-type-projection-1.stderr +++ b/tests/ui/associated-types/hr-associated-type-projection-1.stderr @@ -1,10 +1,10 @@ error[E0271]: type mismatch resolving `::Target == T` - --> $DIR/hr-associated-type-projection-1.rs:13:33 + --> $DIR/hr-associated-type-projection-1.rs:14:17 | LL | impl UnsafeCopy<'_, T> for T { - | - ^^^^^^^^^^^^^^^^^ expected type parameter `T`, found associated type - | | - | expected this type parameter + | - expected this type parameter +LL | type Item = T; + | ^ expected type parameter `T`, found associated type | = note: expected type parameter `T` found associated type `::Target` diff --git a/tests/ui/associated-types/issue-38821.stderr b/tests/ui/associated-types/issue-38821.stderr index acf6bb2810c99..f1c8f83e30c8f 100644 --- a/tests/ui/associated-types/issue-38821.stderr +++ b/tests/ui/associated-types/issue-38821.stderr @@ -1,22 +1,3 @@ -error[E0277]: the trait bound `::SqlType: NotNull` is not satisfied - --> $DIR/issue-38821.rs:23:17 - | -LL | #[derive(Debug, Copy, Clone)] - | ^^^^ the trait `NotNull` is not implemented for `::SqlType`, which is required by `::SqlType: IntoNullable` - | -note: required for `::SqlType` to implement `IntoNullable` - --> $DIR/issue-38821.rs:9:18 - | -LL | impl IntoNullable for T { - | ------- ^^^^^^^^^^^^ ^ - | | - | unsatisfied trait bound introduced here - = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider further restricting the associated type - | -LL | Expr: Expression::Nullable>, ::SqlType: NotNull, - | +++++++++++++++++++++++++++++++++++++++ - error[E0277]: the trait bound `::SqlType: NotNull` is not satisfied --> $DIR/issue-38821.rs:40:1 | @@ -129,6 +110,25 @@ LL | impl IntoNullable for T { = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) +error[E0277]: the trait bound `::SqlType: NotNull` is not satisfied + --> $DIR/issue-38821.rs:23:17 + | +LL | #[derive(Debug, Copy, Clone)] + | ^^^^ the trait `NotNull` is not implemented for `::SqlType`, which is required by `::SqlType: IntoNullable` + | +note: required for `::SqlType` to implement `IntoNullable` + --> $DIR/issue-38821.rs:9:18 + | +LL | impl IntoNullable for T { + | ------- ^^^^^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider further restricting the associated type + | +LL | Expr: Expression::Nullable>, ::SqlType: NotNull, + | +++++++++++++++++++++++++++++++++++++++ + error[E0277]: the trait bound `::SqlType: NotNull` is not satisfied --> $DIR/issue-38821.rs:23:17 | diff --git a/tests/ui/associated-types/substs-ppaux.normal.stderr b/tests/ui/associated-types/substs-ppaux.normal.stderr index 93118616f02c7..a2647f6683531 100644 --- a/tests/ui/associated-types/substs-ppaux.normal.stderr +++ b/tests/ui/associated-types/substs-ppaux.normal.stderr @@ -70,13 +70,12 @@ help: use parentheses to call this function LL | let x: () = foo::<'static>(); | ++ -error[E0277]: the size for values of type `str` cannot be known at compilation time +error[E0277]: the trait bound `str: Foo<'_, '_, u8>` is not satisfied --> $DIR/substs-ppaux.rs:49:6 | LL | >::bar; - | ^^^ doesn't have a size known at compile-time + | ^^^ the trait `Sized` is not implemented for `str`, which is required by `str: Foo<'_, '_, u8>` | - = help: the trait `Sized` is not implemented for `str`, which is required by `str: Foo<'_, '_, u8>` note: required for `str` to implement `Foo<'_, '_, u8>` --> $DIR/substs-ppaux.rs:11:17 | diff --git a/tests/ui/associated-types/substs-ppaux.rs b/tests/ui/associated-types/substs-ppaux.rs index d32cdd2465863..077ca764e241f 100644 --- a/tests/ui/associated-types/substs-ppaux.rs +++ b/tests/ui/associated-types/substs-ppaux.rs @@ -47,6 +47,6 @@ fn foo<'z>() where &'z (): Sized { //[normal]~| found fn item `fn() {foo::<'static>}` >::bar; - //[verbose]~^ ERROR the size for values of type - //[normal]~^^ ERROR the size for values of type + //[verbose]~^ ERROR the trait bound `str: Foo<'?0, '?1, u8>` is not satisfied + //[normal]~^^ ERROR the trait bound `str: Foo<'_, '_, u8>` is not satisfied } diff --git a/tests/ui/associated-types/substs-ppaux.verbose.stderr b/tests/ui/associated-types/substs-ppaux.verbose.stderr index 13d3156fb8018..d32f44ccd6412 100644 --- a/tests/ui/associated-types/substs-ppaux.verbose.stderr +++ b/tests/ui/associated-types/substs-ppaux.verbose.stderr @@ -70,13 +70,12 @@ help: use parentheses to call this function LL | let x: () = foo::<'static>(); | ++ -error[E0277]: the size for values of type `str` cannot be known at compilation time +error[E0277]: the trait bound `str: Foo<'?0, '?1, u8>` is not satisfied --> $DIR/substs-ppaux.rs:49:6 | LL | >::bar; - | ^^^ doesn't have a size known at compile-time + | ^^^ the trait `Sized` is not implemented for `str`, which is required by `str: Foo<'?0, '?1, u8>` | - = help: the trait `Sized` is not implemented for `str`, which is required by `str: Foo<'?0, '?1, u8>` note: required for `str` to implement `Foo<'?0, '?1, u8>` --> $DIR/substs-ppaux.rs:11:17 | diff --git a/tests/ui/async-await/async-closures/signature-deduction.rs b/tests/ui/async-await/async-closures/signature-deduction.rs new file mode 100644 index 0000000000000..031dab1029658 --- /dev/null +++ b/tests/ui/async-await/async-closures/signature-deduction.rs @@ -0,0 +1,10 @@ +//@ check-pass +//@ edition: 2021 + +#![feature(async_closure)] + +async fn foo(x: impl async Fn(&str) -> &str) {} + +fn main() { + foo(async |x| x); +} diff --git a/tests/ui/async-await/async-error-span.stderr b/tests/ui/async-await/async-error-span.stderr index 2ec968ffc0307..44f1583f4cc33 100644 --- a/tests/ui/async-await/async-error-span.stderr +++ b/tests/ui/async-await/async-error-span.stderr @@ -5,7 +5,6 @@ LL | fn get_future() -> impl Future { | ^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not a future | = help: the trait `Future` is not implemented for `()` - = note: () must be a future or must implement `IntoFuture` to be awaited error[E0282]: type annotations needed --> $DIR/async-error-span.rs:13:9 diff --git a/tests/ui/async-await/async-outside-of-await-issue-121096.rs b/tests/ui/async-await/async-outside-of-await-issue-121096.rs new file mode 100644 index 0000000000000..e3999035ef91f --- /dev/null +++ b/tests/ui/async-await/async-outside-of-await-issue-121096.rs @@ -0,0 +1,9 @@ +//@ edition:2021 + +fn main() { + async { + use std::ops::Add; + let _ = 1.add(3); + }.await + //~^ ERROR `await` is only allowed inside `async` functions and blocks +} diff --git a/tests/ui/async-await/async-outside-of-await-issue-121096.stderr b/tests/ui/async-await/async-outside-of-await-issue-121096.stderr new file mode 100644 index 0000000000000..b0677a83864e0 --- /dev/null +++ b/tests/ui/async-await/async-outside-of-await-issue-121096.stderr @@ -0,0 +1,12 @@ +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> $DIR/async-outside-of-await-issue-121096.rs:7:7 + | +LL | fn main() { + | ---- this is not `async` +... +LL | }.await + | ^^^^^ only allowed inside `async` functions and blocks + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0728`. diff --git a/tests/ui/async-await/coroutine-not-future.stderr b/tests/ui/async-await/coroutine-not-future.stderr index 130c5ef526b39..580217fb4f821 100644 --- a/tests/ui/async-await/coroutine-not-future.stderr +++ b/tests/ui/async-await/coroutine-not-future.stderr @@ -49,7 +49,6 @@ LL | takes_future(returns_coroutine()); | required by a bound introduced by this call | = help: the trait `Future` is not implemented for `impl Coroutine` - = note: impl Coroutine must be a future or must implement `IntoFuture` to be awaited note: required by a bound in `takes_future` --> $DIR/coroutine-not-future.rs:17:26 | @@ -69,7 +68,6 @@ LL | | }); | |_____^ `{coroutine@$DIR/coroutine-not-future.rs:41:18: 41:23}` is not a future | = help: the trait `Future` is not implemented for `{coroutine@$DIR/coroutine-not-future.rs:41:18: 41:23}` - = note: {coroutine@$DIR/coroutine-not-future.rs:41:18: 41:23} must be a future or must implement `IntoFuture` to be awaited note: required by a bound in `takes_future` --> $DIR/coroutine-not-future.rs:17:26 | diff --git a/tests/ui/auto-traits/typeck-default-trait-impl-precedence.rs b/tests/ui/auto-traits/typeck-default-trait-impl-precedence.rs index 2bbe82270bd06..5baa4f10c448a 100644 --- a/tests/ui/auto-traits/typeck-default-trait-impl-precedence.rs +++ b/tests/ui/auto-traits/typeck-default-trait-impl-precedence.rs @@ -17,5 +17,5 @@ impl Signed for i32 { } fn main() { is_defaulted::<&'static i32>(); is_defaulted::<&'static u32>(); - //~^ ERROR `u32: Signed` is not satisfied + //~^ ERROR the trait bound `&'static u32: Defaulted` is not satisfied } diff --git a/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr b/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr index e699422ae2b86..47bb1a059be5a 100644 --- a/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr +++ b/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr @@ -1,8 +1,8 @@ -error[E0277]: the trait bound `u32: Signed` is not satisfied +error[E0277]: the trait bound `&'static u32: Defaulted` is not satisfied --> $DIR/typeck-default-trait-impl-precedence.rs:19:20 | LL | is_defaulted::<&'static u32>(); - | ^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32`, which is required by `&'static u32: Defaulted` + | ^^^^^^^^^^^^ the trait `Signed` is not implemented for `&'static u32`, which is required by `&'static u32: Defaulted` | note: required for `&'static u32` to implement `Defaulted` --> $DIR/typeck-default-trait-impl-precedence.rs:10:19 diff --git a/tests/ui/box/unit/unique-send-2.rs b/tests/ui/box/unit/unique-send-2.rs index 20474fee4d8d5..d3cbeefab3766 100644 --- a/tests/ui/box/unit/unique-send-2.rs +++ b/tests/ui/box/unit/unique-send-2.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_must_use)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::sync::mpsc::{channel, Sender}; use std::thread; diff --git a/tests/ui/check-cfg/mix.rs b/tests/ui/check-cfg/mix.rs index ba30bc1e69b50..69156ab67635e 100644 --- a/tests/ui/check-cfg/mix.rs +++ b/tests/ui/check-cfg/mix.rs @@ -74,6 +74,8 @@ fn test_cfg_macro() { //~^ WARNING unexpected `cfg` condition value //~| WARNING unexpected `cfg` condition value //~| WARNING unexpected `cfg` condition value + cfg!(target_feature = "zebra"); + //~^ WARNING unexpected `cfg` condition value } fn main() {} diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr index 77643f227d9d0..007f9de033147 100644 --- a/tests/ui/check-cfg/mix.stderr +++ b/tests/ui/check-cfg/mix.stderr @@ -245,5 +245,14 @@ LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); = help: to expect this configuration use `--check-cfg=cfg(feature, values("zebra"))` = note: see for more information about checking conditional configuration -warning: 26 warnings emitted +warning: unexpected `cfg` condition value: `zebra` + --> $DIR/mix.rs:77:10 + | +LL | cfg!(target_feature = "zebra"); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512er`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512pf`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, `bmi2` and 187 more + = note: see for more information about checking conditional configuration + +warning: 27 warnings emitted diff --git a/tests/ui/check-cfg/well-known-values.rs b/tests/ui/check-cfg/well-known-values.rs index 859a36c604c6f..fa062a3fe2eae 100644 --- a/tests/ui/check-cfg/well-known-values.rs +++ b/tests/ui/check-cfg/well-known-values.rs @@ -6,6 +6,7 @@ // //@ check-pass //@ compile-flags: --check-cfg=cfg() -Z unstable-options +//@ compile-flags: -Zcheck-cfg-all-expected #![feature(cfg_overflow_checks)] #![feature(cfg_relocation_model)] diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index 01fc3f83f162b..cf18503b74bb9 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:25:5 + --> $DIR/well-known-values.rs:26:5 | LL | clippy = "_UNEXPECTED_VALUE", | ^^^^^^---------------------- @@ -11,7 +11,7 @@ LL | clippy = "_UNEXPECTED_VALUE", = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:27:5 + --> $DIR/well-known-values.rs:28:5 | LL | debug_assertions = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^---------------------- @@ -22,7 +22,7 @@ LL | debug_assertions = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:29:5 + --> $DIR/well-known-values.rs:30:5 | LL | doc = "_UNEXPECTED_VALUE", | ^^^---------------------- @@ -33,7 +33,7 @@ LL | doc = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:31:5 + --> $DIR/well-known-values.rs:32:5 | LL | doctest = "_UNEXPECTED_VALUE", | ^^^^^^^---------------------- @@ -44,7 +44,7 @@ LL | doctest = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:33:5 + --> $DIR/well-known-values.rs:34:5 | LL | miri = "_UNEXPECTED_VALUE", | ^^^^---------------------- @@ -55,7 +55,7 @@ LL | miri = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:35:5 + --> $DIR/well-known-values.rs:36:5 | LL | overflow_checks = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^---------------------- @@ -66,7 +66,7 @@ LL | overflow_checks = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:37:5 + --> $DIR/well-known-values.rs:38:5 | LL | panic = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -75,7 +75,7 @@ LL | panic = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:39:5 + --> $DIR/well-known-values.rs:40:5 | LL | proc_macro = "_UNEXPECTED_VALUE", | ^^^^^^^^^^---------------------- @@ -86,7 +86,7 @@ LL | proc_macro = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:41:5 + --> $DIR/well-known-values.rs:42:5 | LL | relocation_model = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -95,7 +95,7 @@ LL | relocation_model = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:43:5 + --> $DIR/well-known-values.rs:44:5 | LL | sanitize = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -104,7 +104,7 @@ LL | sanitize = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:45:5 + --> $DIR/well-known-values.rs:46:5 | LL | target_abi = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -113,16 +113,16 @@ LL | target_abi = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:47:5 + --> $DIR/well-known-values.rs:48:5 | LL | target_arch = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_arch` are: `aarch64`, `arm`, `avr`, `bpf`, `csky`, `hexagon`, `loongarch64`, `m68k`, `mips`, `mips32r6`, `mips64`, `mips64r6`, `msp430`, `nvptx64`, `powerpc`, `powerpc64`, `riscv32`, `riscv64`, `s390x`, `sparc`, `sparc64`, `wasm32`, `wasm64`, `x86`, `x86_64` + = note: expected values for `target_arch` are: `aarch64`, `arm`, `arm64ec`, `avr`, `bpf`, `csky`, `hexagon`, `loongarch64`, `m68k`, `mips`, `mips32r6`, `mips64`, `mips64r6`, `msp430`, `nvptx64`, `powerpc`, `powerpc64`, `riscv32`, `riscv64`, `s390x`, `sparc`, `sparc64`, `wasm32`, `wasm64`, `x86`, `x86_64` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:49:5 + --> $DIR/well-known-values.rs:50:5 | LL | target_endian = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -131,7 +131,7 @@ LL | target_endian = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:51:5 + --> $DIR/well-known-values.rs:52:5 | LL | target_env = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -140,7 +140,7 @@ LL | target_env = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:53:5 + --> $DIR/well-known-values.rs:54:5 | LL | target_family = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -149,16 +149,16 @@ LL | target_family = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:55:5 + --> $DIR/well-known-values.rs:56:5 | LL | target_feature = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512er`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512pf`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `f`, `f16c`, `f32mm`, `f64mm`, `fast-unaligned-access`, `fcma`, `fdivdu`, `fhm`, `flagm`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lsx`, `lvz`, `lzcnt`, `m`, `mclass`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sign-ext`, `simd128`, `sm4`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `sve`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, `zkt` + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512er`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512pf`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `f`, `f16c`, `f32mm`, `f64mm`, `fast-unaligned-access`, `fcma`, `fdivdu`, `fhm`, `flagm`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lsx`, `lvz`, `lzcnt`, `m`, `mclass`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sign-ext`, `simd128`, `sm4`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `sve`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, `zkt` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:57:5 + --> $DIR/well-known-values.rs:58:5 | LL | target_has_atomic = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -167,7 +167,7 @@ LL | target_has_atomic = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:59:5 + --> $DIR/well-known-values.rs:60:5 | LL | target_has_atomic_equal_alignment = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -176,7 +176,7 @@ LL | target_has_atomic_equal_alignment = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:61:5 + --> $DIR/well-known-values.rs:62:5 | LL | target_has_atomic_load_store = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -185,7 +185,7 @@ LL | target_has_atomic_load_store = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:63:5 + --> $DIR/well-known-values.rs:64:5 | LL | target_os = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -194,7 +194,7 @@ LL | target_os = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:65:5 + --> $DIR/well-known-values.rs:66:5 | LL | target_pointer_width = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -203,7 +203,7 @@ LL | target_pointer_width = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:67:5 + --> $DIR/well-known-values.rs:68:5 | LL | target_thread_local = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^---------------------- @@ -214,7 +214,7 @@ LL | target_thread_local = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:69:5 + --> $DIR/well-known-values.rs:70:5 | LL | target_vendor = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -223,7 +223,7 @@ LL | target_vendor = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:71:5 + --> $DIR/well-known-values.rs:72:5 | LL | test = "_UNEXPECTED_VALUE", | ^^^^---------------------- @@ -234,7 +234,7 @@ LL | test = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:73:5 + --> $DIR/well-known-values.rs:74:5 | LL | unix = "_UNEXPECTED_VALUE", | ^^^^---------------------- @@ -245,7 +245,7 @@ LL | unix = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:75:5 + --> $DIR/well-known-values.rs:76:5 | LL | windows = "_UNEXPECTED_VALUE", | ^^^^^^^---------------------- @@ -256,7 +256,7 @@ LL | windows = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `linuz` - --> $DIR/well-known-values.rs:81:7 + --> $DIR/well-known-values.rs:82:7 | LL | #[cfg(target_os = "linuz")] // testing that we suggest `linux` | ^^^^^^^^^^^^------- diff --git a/tests/ui/closures/issue-78720.rs b/tests/ui/closures/issue-78720.rs index 0e1f78ae3c69b..0c4f337ba57b8 100644 --- a/tests/ui/closures/issue-78720.rs +++ b/tests/ui/closures/issue-78720.rs @@ -1,7 +1,7 @@ fn server() -> impl { -//~^ ERROR at least one trait must be specified + //~^ ERROR at least one trait must be specified + //~| ERROR type annotations needed ().map2(|| "") - //~^ ERROR type annotations needed } trait FilterBase2 { diff --git a/tests/ui/closures/issue-78720.stderr b/tests/ui/closures/issue-78720.stderr index d8d3811af5a74..2f57c7616f121 100644 --- a/tests/ui/closures/issue-78720.stderr +++ b/tests/ui/closures/issue-78720.stderr @@ -23,10 +23,10 @@ LL | struct Map2 { | +++ error[E0282]: type annotations needed - --> $DIR/issue-78720.rs:3:5 + --> $DIR/issue-78720.rs:1:16 | -LL | ().map2(|| "") - | ^^^^^^^^^^^^^^ cannot infer type +LL | fn server() -> impl { + | ^^^^ cannot infer type error[E0308]: mismatched types --> $DIR/issue-78720.rs:8:39 diff --git a/tests/ui/codegen/duplicated-path-in-error.rs b/tests/ui/codegen/duplicated-path-in-error.rs new file mode 100644 index 0000000000000..cff20dd9bd639 --- /dev/null +++ b/tests/ui/codegen/duplicated-path-in-error.rs @@ -0,0 +1,7 @@ +//@ only-linux +//@ compile-flags: -Zcodegen-backend=/non-existing-one.so + +// This test ensures that the error of the "not found dylib" doesn't duplicate +// the path of the dylib. + +fn main() {} diff --git a/tests/ui/codegen/duplicated-path-in-error.stderr b/tests/ui/codegen/duplicated-path-in-error.stderr new file mode 100644 index 0000000000000..d0d34e2f93468 --- /dev/null +++ b/tests/ui/codegen/duplicated-path-in-error.stderr @@ -0,0 +1,2 @@ +error: couldn't load codegen backend /non-existing-one.so: cannot open shared object file: No such file or directory + diff --git a/tests/ui/codegen/init-large-type.rs b/tests/ui/codegen/init-large-type.rs index 34b40693ab12c..b9fc6612e1687 100644 --- a/tests/ui/codegen/init-large-type.rs +++ b/tests/ui/codegen/init-large-type.rs @@ -7,8 +7,7 @@ // optimisation. //@ pretty-expanded FIXME #23616 -//@ ignore-emscripten no threads support - +//@ needs-threads #![feature(intrinsics)] use std::{mem, thread}; diff --git a/tests/ui/codegen/issue-28950.rs b/tests/ui/codegen/issue-28950.rs index 8e55172af6d73..0a706c588d564 100644 --- a/tests/ui/codegen/issue-28950.rs +++ b/tests/ui/codegen/issue-28950.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ ignore-emscripten no threads +//@ needs-threads //@ compile-flags: -O // Tests that the `vec!` macro does not overflow the stack when it is diff --git a/tests/ui/coherence/coherence-orphan.stderr b/tests/ui/coherence/coherence-orphan.stderr index b1bb75bfe5162..48843f7cd1818 100644 --- a/tests/ui/coherence/coherence-orphan.stderr +++ b/tests/ui/coherence/coherence-orphan.stderr @@ -10,17 +10,6 @@ LL | impl TheTrait for isize {} | = note: define and implement a trait or new type instead -error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate - --> $DIR/coherence-orphan.rs:20:1 - | -LL | impl !Send for Vec {} - | ^^^^^^^^^^^^^^^---------- - | | | - | | `Vec` is not defined in the current crate - | impl doesn't use only types from inside the current crate - | - = note: define and implement a trait or new type instead - error[E0046]: not all trait items implemented, missing: `the_fn` --> $DIR/coherence-orphan.rs:10:1 | @@ -45,6 +34,17 @@ LL | impl TheTrait for TheType {} | = help: implement the missing item: `fn the_fn(&self) { todo!() }` +error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate + --> $DIR/coherence-orphan.rs:20:1 + | +LL | impl !Send for Vec {} + | ^^^^^^^^^^^^^^^---------- + | | | + | | `Vec` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + error: aborting due to 5 previous errors Some errors have detailed explanations: E0046, E0117. diff --git a/tests/ui/command/need-crate-arg-ignore-tidy.x.rs b/tests/ui/command/need-crate-arg-ignore-tidy$x.rs similarity index 100% rename from tests/ui/command/need-crate-arg-ignore-tidy.x.rs rename to tests/ui/command/need-crate-arg-ignore-tidy$x.rs diff --git a/tests/ui/command/need-crate-arg-ignore-tidy.x.stderr b/tests/ui/command/need-crate-arg-ignore-tidy$x.stderr similarity index 68% rename from tests/ui/command/need-crate-arg-ignore-tidy.x.stderr rename to tests/ui/command/need-crate-arg-ignore-tidy$x.stderr index 89f7210c048e1..28f6d31b1ce59 100644 --- a/tests/ui/command/need-crate-arg-ignore-tidy.x.stderr +++ b/tests/ui/command/need-crate-arg-ignore-tidy$x.stderr @@ -1,4 +1,4 @@ -error: invalid character `'.'` in crate name: `need_crate_arg_ignore_tidy.x` +error: invalid character `'$'` in crate name: `need_crate_arg_ignore_tidy$x` | = help: you can either pass `--crate-name` on the command line or add `#![crate_name="…"]` to set the crate name diff --git a/tests/ui/commandline-argfile-badutf8.rs b/tests/ui/commandline-argfile-badutf8.rs deleted file mode 100644 index b3a19fa62741d..0000000000000 --- a/tests/ui/commandline-argfile-badutf8.rs +++ /dev/null @@ -1,12 +0,0 @@ -// Check to see if we can get parameters from an @argsfile file -// -//@ compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-badutf8.args - -#[cfg(not(cmdline_set))] -compile_error!("cmdline_set not set"); - -#[cfg(not(unbroken))] -compile_error!("unbroken not set"); - -fn main() { -} diff --git a/tests/ui/commandline-argfile-badutf8.stderr b/tests/ui/commandline-argfile-badutf8.stderr deleted file mode 100644 index 9af6fc0a518df..0000000000000 --- a/tests/ui/commandline-argfile-badutf8.stderr +++ /dev/null @@ -1,2 +0,0 @@ -error: Failed to load argument file: Utf8 error in $DIR/commandline-argfile-badutf8.args - diff --git a/tests/ui/commandline-argfile-missing.stderr b/tests/ui/commandline-argfile-missing.stderr deleted file mode 100644 index 179ad83100419..0000000000000 --- a/tests/ui/commandline-argfile-missing.stderr +++ /dev/null @@ -1,2 +0,0 @@ -error: Failed to load argument file: IO Error: $DIR/commandline-argfile-missing.args: $FILE_MISSING (os error $ERR) - diff --git a/tests/ui/const-generics/generic_arg_infer/in-signature.stderr b/tests/ui/const-generics/generic_arg_infer/in-signature.stderr index b32018a6a2d22..fcac95732d12e 100644 --- a/tests/ui/const-generics/generic_arg_infer/in-signature.stderr +++ b/tests/ui/const-generics/generic_arg_infer/in-signature.stderr @@ -74,26 +74,6 @@ LL | static TY_STATIC_MIXED: Bar<_, _> = Bar::(0); | not allowed in type signatures | help: replace with the correct type: `Bar` -error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants - --> $DIR/in-signature.rs:35:21 - | -LL | const ARR: [u8; _]; - | ^ not allowed in type signatures - -error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants - --> $DIR/in-signature.rs:39:25 - | -LL | const ARR: Bar; - | ^ not allowed in type signatures - -error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants - --> $DIR/in-signature.rs:43:20 - | -LL | const ARR: Bar<_, _>; - | ^ ^ not allowed in type signatures - | | - | not allowed in type signatures - error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types --> $DIR/in-signature.rs:51:23 | @@ -114,6 +94,26 @@ LL | type Assoc = Bar<_, _>; | | | not allowed in type signatures +error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants + --> $DIR/in-signature.rs:35:21 + | +LL | const ARR: [u8; _]; + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants + --> $DIR/in-signature.rs:39:25 + | +LL | const ARR: Bar; + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants + --> $DIR/in-signature.rs:43:20 + | +LL | const ARR: Bar<_, _>; + | ^ ^ not allowed in type signatures + | | + | not allowed in type signatures + error: aborting due to 15 previous errors For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/issue_114151.rs b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/issue_114151.rs index 6256000b4919b..9cdb4158d2b35 100644 --- a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/issue_114151.rs +++ b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/issue_114151.rs @@ -20,6 +20,7 @@ where //~^^^ ERROR: function takes 1 generic argument but 2 generic arguments were supplied //~^^^^ ERROR: unconstrained generic constant //~^^^^^ ERROR: unconstrained generic constant `{const expr}` + //~^^^^^^ ERROR: unconstrained generic constant `{const expr}` } fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/issue_114151.stderr b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/issue_114151.stderr index 6001d8247876a..14c58f8d0da7f 100644 --- a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/issue_114151.stderr +++ b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/issue_114151.stderr @@ -58,7 +58,15 @@ error: unconstrained generic constant `{const expr}` LL | foo::<_, L>([(); L + 1 + L]); | ^^^^^^^^^^^ -error: aborting due to 5 previous errors +error: unconstrained generic constant `{const expr}` + --> $DIR/issue_114151.rs:17:5 + | +LL | foo::<_, L>([(); L + 1 + L]); + | ^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 6 previous errors Some errors have detailed explanations: E0107, E0308. For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/const-generics/issues/issue-68366.full.stderr b/tests/ui/const-generics/issues/issue-68366.full.stderr index ca9eb801dfce7..dc20af7731068 100644 --- a/tests/ui/const-generics/issues/issue-68366.full.stderr +++ b/tests/ui/const-generics/issues/issue-68366.full.stderr @@ -1,5 +1,14 @@ +error: `Option` is forbidden as the type of a const generic parameter + --> $DIR/issue-68366.rs:9:25 + | +LL | struct Collatz>; + | ^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types + error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates - --> $DIR/issue-68366.rs:11:7 + --> $DIR/issue-68366.rs:12:7 | LL | impl Collatz<{Some(N)}> {} | ^^^^^^^^^^^^^^ unconstrained const parameter @@ -8,7 +17,7 @@ LL | impl Collatz<{Some(N)}> {} = note: proving the result of expressions other than the parameter are unique is not supported error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates - --> $DIR/issue-68366.rs:17:6 + --> $DIR/issue-68366.rs:19:6 | LL | impl Foo {} | ^^^^^^^^^^^^^^ unconstrained const parameter @@ -16,6 +25,17 @@ LL | impl Foo {} = note: expressions using a const parameter must map each value to a distinct output value = note: proving the result of expressions other than the parameter are unique is not supported -error: aborting due to 2 previous errors +error: overly complex generic constant + --> $DIR/issue-68366.rs:12:31 + | +LL | impl Collatz<{Some(N)}> {} + | ^-------^ + | | + | struct/enum construction is not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/const-generics/issues/issue-68366.min.stderr b/tests/ui/const-generics/issues/issue-68366.min.stderr index ecf24a356deef..78e49f46e1a4b 100644 --- a/tests/ui/const-generics/issues/issue-68366.min.stderr +++ b/tests/ui/const-generics/issues/issue-68366.min.stderr @@ -1,5 +1,5 @@ error: generic parameters may not be used in const operations - --> $DIR/issue-68366.rs:11:37 + --> $DIR/issue-68366.rs:12:37 | LL | impl Collatz<{Some(N)}> {} | ^ cannot perform const operation using `N` @@ -7,8 +7,17 @@ LL | impl Collatz<{Some(N)}> {} = help: const parameters may only be used as standalone arguments, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions +error: `Option` is forbidden as the type of a const generic parameter + --> $DIR/issue-68366.rs:9:25 + | +LL | struct Collatz>; + | ^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types + error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates - --> $DIR/issue-68366.rs:11:7 + --> $DIR/issue-68366.rs:12:7 | LL | impl Collatz<{Some(N)}> {} | ^^^^^^^^^^^^^^ unconstrained const parameter @@ -17,7 +26,7 @@ LL | impl Collatz<{Some(N)}> {} = note: proving the result of expressions other than the parameter are unique is not supported error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates - --> $DIR/issue-68366.rs:17:6 + --> $DIR/issue-68366.rs:19:6 | LL | impl Foo {} | ^^^^^^^^^^^^^^ unconstrained const parameter @@ -25,6 +34,6 @@ LL | impl Foo {} = note: expressions using a const parameter must map each value to a distinct output value = note: proving the result of expressions other than the parameter are unique is not supported -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/const-generics/issues/issue-68366.rs b/tests/ui/const-generics/issues/issue-68366.rs index d3e57a021a682..d9d5e21857b13 100644 --- a/tests/ui/const-generics/issues/issue-68366.rs +++ b/tests/ui/const-generics/issues/issue-68366.rs @@ -7,10 +7,12 @@ #![cfg_attr(full, allow(incomplete_features))] struct Collatz>; +//~^ ERROR: `Option` is forbidden impl Collatz<{Some(N)}> {} //~^ ERROR the const parameter //[min]~^^ generic parameters may not be used in const operations +//[full]~^^^ ERROR overly complex struct Foo; diff --git a/tests/ui/const-generics/issues/issue-71202.rs b/tests/ui/const-generics/issues/issue-71202.rs index 57fd72b12846e..0f955414d843e 100644 --- a/tests/ui/const-generics/issues/issue-71202.rs +++ b/tests/ui/const-generics/issues/issue-71202.rs @@ -25,7 +25,7 @@ impl DataHolder { } >::VALUE - } as usize] = []; + } as usize] = []; //~ ERROR unconstrained generic constant } fn main() {} diff --git a/tests/ui/const-generics/issues/issue-71202.stderr b/tests/ui/const-generics/issues/issue-71202.stderr index 2aa9e344067bf..437b808c893c2 100644 --- a/tests/ui/const-generics/issues/issue-71202.stderr +++ b/tests/ui/const-generics/issues/issue-71202.stderr @@ -29,5 +29,30 @@ LL | | } as usize] = []; >::VALUE } as usize]:` -error: aborting due to 1 previous error +error: unconstrained generic constant + --> $DIR/issue-71202.rs:28:19 + | +LL | } as usize] = []; + | ^^ + | + = help: try adding a `where` bound using this expression: `where [(); 1 - { + trait NotCopy { + const VALUE: bool = false; + } + + impl<__Type: ?Sized> NotCopy for __Type {} + + struct IsCopy<__Type: ?Sized>(PhantomData<__Type>); + + impl<__Type> IsCopy<__Type> + where + __Type: Sized + Copy, + { + const VALUE: bool = true; + } + + >::VALUE + } as usize]:` + +error: aborting due to 2 previous errors diff --git a/tests/ui/consts/const-eval/infinite_loop.stderr b/tests/ui/consts/const-eval/infinite_loop.eval_limit.stderr similarity index 91% rename from tests/ui/consts/const-eval/infinite_loop.stderr rename to tests/ui/consts/const-eval/infinite_loop.eval_limit.stderr index 37cd94bf7b7c7..d664ae8832325 100644 --- a/tests/ui/consts/const-eval/infinite_loop.stderr +++ b/tests/ui/consts/const-eval/infinite_loop.eval_limit.stderr @@ -1,5 +1,5 @@ error: constant evaluation is taking a long time - --> $DIR/infinite_loop.rs:12:9 + --> $DIR/infinite_loop.rs:15:9 | LL | / while n != 0 { LL | | @@ -10,7 +10,7 @@ LL | | } = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. If your compilation actually takes a long time, you can safely allow the lint. help: the constant being evaluated - --> $DIR/infinite_loop.rs:10:18 + --> $DIR/infinite_loop.rs:13:18 | LL | let s = [(); { | __________________^ diff --git a/tests/ui/consts/const-eval/infinite_loop.no_ice.stderr b/tests/ui/consts/const-eval/infinite_loop.no_ice.stderr new file mode 100644 index 0000000000000..d664ae8832325 --- /dev/null +++ b/tests/ui/consts/const-eval/infinite_loop.no_ice.stderr @@ -0,0 +1,27 @@ +error: constant evaluation is taking a long time + --> $DIR/infinite_loop.rs:15:9 + | +LL | / while n != 0 { +LL | | +LL | | n = if n % 2 == 0 { n / 2 } else { 3 * n + 1 }; +LL | | } + | |_________^ + | + = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. + If your compilation actually takes a long time, you can safely allow the lint. +help: the constant being evaluated + --> $DIR/infinite_loop.rs:13:18 + | +LL | let s = [(); { + | __________________^ +LL | | let mut n = 113383; // #20 in https://oeis.org/A006884 +LL | | while n != 0 { +LL | | +... | +LL | | n +LL | | }]; + | |_____^ + = note: `#[deny(long_running_const_eval)]` on by default + +error: aborting due to 1 previous error + diff --git a/tests/ui/consts/const-eval/infinite_loop.rs b/tests/ui/consts/const-eval/infinite_loop.rs index 44456f1ce47d9..f8cb79b63db55 100644 --- a/tests/ui/consts/const-eval/infinite_loop.rs +++ b/tests/ui/consts/const-eval/infinite_loop.rs @@ -1,8 +1,11 @@ //! This test tests two things at once: //! 1. we error if a const evaluation hits the deny-by-default lint limit //! 2. we do not ICE on invalid follow-up code +//! 3. no ICE when run with `-Z unstable-options` (issue 122177) -//@ compile-flags: -Z tiny-const-eval-limit +//@revisions: eval_limit no_ice +//@[no_ice] compile-flags: -Z tiny-const-eval-limit -Z unstable-options +//@[eval_limit] compile-flags: -Z tiny-const-eval-limit fn main() { // Tests the Collatz conjecture with an incorrect base case (0 instead of 1). diff --git a/tests/ui/consts/different-fn-ptr-binders-during-ctfe.rs b/tests/ui/consts/different-fn-ptr-binders-during-ctfe.rs new file mode 100644 index 0000000000000..b378542e5730c --- /dev/null +++ b/tests/ui/consts/different-fn-ptr-binders-during-ctfe.rs @@ -0,0 +1,6 @@ +const fn cmp(x: fn(&'static ()), y: for<'a> fn(&'a ())) -> bool { + x == y + //~^ ERROR pointers cannot be reliably compared during const eval +} + +fn main() {} diff --git a/tests/ui/consts/different-fn-ptr-binders-during-ctfe.stderr b/tests/ui/consts/different-fn-ptr-binders-during-ctfe.stderr new file mode 100644 index 0000000000000..43a7b9ce66ce0 --- /dev/null +++ b/tests/ui/consts/different-fn-ptr-binders-during-ctfe.stderr @@ -0,0 +1,10 @@ +error: pointers cannot be reliably compared during const eval + --> $DIR/different-fn-ptr-binders-during-ctfe.rs:2:5 + | +LL | x == y + | ^^^^^^ + | + = note: see issue #53020 for more information + +error: aborting due to 1 previous error + diff --git a/tests/ui/consts/issue-103790.stderr b/tests/ui/consts/issue-103790.stderr index 55bc9675401b1..abe7366483b05 100644 --- a/tests/ui/consts/issue-103790.stderr +++ b/tests/ui/consts/issue-103790.stderr @@ -48,17 +48,11 @@ note: ...which requires computing type of `S::S`... LL | struct S; | ^ = note: ...which again requires computing type of `S`, completing the cycle -note: cycle used when collecting item types in top-level module - --> $DIR/issue-103790.rs:1:1 +note: cycle used when checking that `S` is well-formed + --> $DIR/issue-103790.rs:4:1 | -LL | / #![feature(generic_const_exprs)] -LL | | #![allow(incomplete_features)] -LL | | -LL | | struct S; -... | -LL | | -LL | | fn main() {} - | |____________^ +LL | struct S; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error: `()` is forbidden as the type of a const generic parameter diff --git a/tests/ui/consts/issue-36163.stderr b/tests/ui/consts/issue-36163.stderr index de70a457f16f2..8a7a0981f4154 100644 --- a/tests/ui/consts/issue-36163.stderr +++ b/tests/ui/consts/issue-36163.stderr @@ -20,17 +20,11 @@ note: ...which requires const-evaluating + checking `A`... LL | const A: isize = Foo::B as isize; | ^^^^^^^^^^^^^^^ = note: ...which again requires simplifying constant for the type system `Foo::B::{constant#0}`, completing the cycle -note: cycle used when collecting item types in top-level module - --> $DIR/issue-36163.rs:1:1 +note: cycle used when checking that `Foo` is well-formed + --> $DIR/issue-36163.rs:3:1 | -LL | / const A: isize = Foo::B as isize; -LL | | -LL | | enum Foo { -LL | | B = A, -LL | | } -LL | | -LL | | fn main() {} - | |____________^ +LL | enum Foo { + | ^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error: aborting due to 1 previous error diff --git a/tests/ui/coroutine/gen_block_is_no_future.stderr b/tests/ui/coroutine/gen_block_is_no_future.stderr index f9e23e45b4435..fb2f2ba559775 100644 --- a/tests/ui/coroutine/gen_block_is_no_future.stderr +++ b/tests/ui/coroutine/gen_block_is_no_future.stderr @@ -5,7 +5,6 @@ LL | fn foo() -> impl std::future::Future { | ^^^^^^^^^^^^^^^^^^^^^^^^ `{gen block@$DIR/gen_block_is_no_future.rs:5:5: 5:21}` is not a future | = help: the trait `Future` is not implemented for `{gen block@$DIR/gen_block_is_no_future.rs:5:5: 5:21}` - = note: {gen block@$DIR/gen_block_is_no_future.rs:5:5: 5:21} must be a future or must implement `IntoFuture` to be awaited error: aborting due to 1 previous error diff --git a/tests/ui/coroutine/smoke.rs b/tests/ui/coroutine/smoke.rs index 0ed56982c9b74..17d98a52a1c49 100644 --- a/tests/ui/coroutine/smoke.rs +++ b/tests/ui/coroutine/smoke.rs @@ -3,7 +3,7 @@ //@ revisions: default nomiropt //@[nomiropt]compile-flags: -Z mir-opt-level=0 -//@ ignore-emscripten no threads support +//@ needs-threads //@ compile-flags: --test #![feature(coroutines, coroutine_trait)] diff --git a/tests/ui/crate-loading/missing-std.stderr b/tests/ui/crate-loading/missing-std.stderr index 70bcae1e0edd0..3eb6c2946d354 100644 --- a/tests/ui/crate-loading/missing-std.stderr +++ b/tests/ui/crate-loading/missing-std.stderr @@ -8,8 +8,6 @@ LL | extern crate core; = help: consider downloading the target with `rustup target add x86_64-unknown-uefi` = help: consider building the standard library from source with `cargo build -Zbuild-std` -error: requires `sized` lang_item - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0463`. diff --git a/tests/ui/cross-crate/cci_capture_clause.rs b/tests/ui/cross-crate/cci_capture_clause.rs index 99736ad185de4..73e1020d7cfcb 100644 --- a/tests/ui/cross-crate/cci_capture_clause.rs +++ b/tests/ui/cross-crate/cci_capture_clause.rs @@ -5,7 +5,7 @@ // that use capture clauses. //@ pretty-expanded FIXME #23616 -//@ ignore-emscripten no threads support +//@ needs-threads extern crate cci_capture_clause; diff --git a/tests/ui/cycle-trait/cycle-trait-default-type-trait.stderr b/tests/ui/cycle-trait/cycle-trait-default-type-trait.stderr index e8be9b0b91350..c0b935567f814 100644 --- a/tests/ui/cycle-trait/cycle-trait-default-type-trait.stderr +++ b/tests/ui/cycle-trait/cycle-trait-default-type-trait.stderr @@ -5,15 +5,11 @@ LL | trait Foo> { | ^^^ | = note: ...which immediately requires computing type of `Foo::X` again -note: cycle used when collecting item types in top-level module +note: cycle used when checking that `Foo` is well-formed --> $DIR/cycle-trait-default-type-trait.rs:4:1 | -LL | / trait Foo> { -LL | | -LL | | } -LL | | -LL | | fn main() { } - | |_____________^ +LL | trait Foo> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error: aborting due to 1 previous error diff --git a/tests/ui/cycle-trait/cycle-trait-supertrait-direct.stderr b/tests/ui/cycle-trait/cycle-trait-supertrait-direct.stderr index 8645b4ebccf51..2e11a59c3a492 100644 --- a/tests/ui/cycle-trait/cycle-trait-supertrait-direct.stderr +++ b/tests/ui/cycle-trait/cycle-trait-supertrait-direct.stderr @@ -5,7 +5,7 @@ LL | trait Chromosome: Chromosome { | ^^^^^^^^^^ | = note: ...which immediately requires computing the super predicates of `Chromosome` again -note: cycle used when collecting item types in top-level module +note: cycle used when checking that `Chromosome` is well-formed --> $DIR/cycle-trait-supertrait-direct.rs:3:1 | LL | / trait Chromosome: Chromosome { diff --git a/tests/ui/cycle-trait/issue-12511.stderr b/tests/ui/cycle-trait/issue-12511.stderr index bc56b9904f5a7..0246bf219831a 100644 --- a/tests/ui/cycle-trait/issue-12511.stderr +++ b/tests/ui/cycle-trait/issue-12511.stderr @@ -10,7 +10,7 @@ note: ...which requires computing the super predicates of `T2`... LL | trait T2 : T1 { | ^^ = note: ...which again requires computing the super predicates of `T1`, completing the cycle -note: cycle used when collecting item types in top-level module +note: cycle used when checking that `T1` is well-formed --> $DIR/issue-12511.rs:1:1 | LL | / trait T1 : T2 { diff --git a/tests/ui/delegation/not-supported.stderr b/tests/ui/delegation/not-supported.stderr index f235767d50afc..324b79f3c535a 100644 --- a/tests/ui/delegation/not-supported.stderr +++ b/tests/ui/delegation/not-supported.stderr @@ -70,14 +70,14 @@ LL | fn foo(&self, x: i32) -> i32 { x } LL | reuse Trait::foo; | ^^^ -error: delegation with early bound generics is not supported yet +error[E0049]: method `foo2` has 0 type parameters but its trait declaration has 1 type parameter --> $DIR/not-supported.rs:49:22 | LL | fn foo2(&self, x: T) -> T { x } - | ---------------------------- callee defined here + | - expected 1 type parameter ... LL | reuse Trait::foo2 { &self.0 } - | ^^^^ + | ^^^^ found 0 type parameters error: delegation with early bound generics is not supported yet --> $DIR/not-supported.rs:52:29 @@ -88,6 +88,15 @@ LL | fn foo3<'a: 'a>(_: &'a u32) {} LL | reuse ::foo3; | ^^^^ +error[E0195]: lifetime parameters or bounds on method `foo3` do not match the trait declaration + --> $DIR/not-supported.rs:52:29 + | +LL | fn foo3<'a: 'a>(_: &'a u32) {} + | -------- lifetimes in impl do not match this method in trait +... +LL | reuse ::foo3; + | ^^^^ lifetimes do not match method in trait + error: delegation with early bound generics is not supported yet --> $DIR/not-supported.rs:59:22 | @@ -97,6 +106,15 @@ LL | fn foo(&self, x: i32) -> i32 { x } LL | reuse Trait::foo { &self.0 } | ^^^ +error: delegation with early bound generics is not supported yet + --> $DIR/not-supported.rs:49:22 + | +LL | fn foo2(&self, x: T) -> T { x } + | ---------------------------- callee defined here +... +LL | reuse Trait::foo2 { &self.0 } + | ^^^^ + error: delegation with early bound generics is not supported yet --> $DIR/not-supported.rs:74:21 | @@ -160,24 +178,6 @@ LL | pub reuse to_reuse2::foo; LL | reuse to_reuse1::foo; | ^^^ -error[E0049]: method `foo2` has 0 type parameters but its trait declaration has 1 type parameter - --> $DIR/not-supported.rs:49:22 - | -LL | fn foo2(&self, x: T) -> T { x } - | - expected 1 type parameter -... -LL | reuse Trait::foo2 { &self.0 } - | ^^^^ found 0 type parameters - -error[E0195]: lifetime parameters or bounds on method `foo3` do not match the trait declaration - --> $DIR/not-supported.rs:52:29 - | -LL | fn foo3<'a: 'a>(_: &'a u32) {} - | -------- lifetimes in impl do not match this method in trait -... -LL | reuse ::foo3; - | ^^^^ lifetimes do not match method in trait - error: aborting due to 19 previous errors; 1 warning emitted Some errors have detailed explanations: E0049, E0195. diff --git a/tests/ui/diagnostic_namespace/existing_proc_macros.rs b/tests/ui/diagnostic_namespace/existing_proc_macros.rs index 2bc58aea8fc2c..014ec46f1b981 100644 --- a/tests/ui/diagnostic_namespace/existing_proc_macros.rs +++ b/tests/ui/diagnostic_namespace/existing_proc_macros.rs @@ -1,4 +1,3 @@ -#![feature(diagnostic_namespace)] //@ check-pass //@ aux-build:proc-macro-helper.rs diff --git a/tests/ui/diagnostic_namespace/feature-gate-diagnostic_namespace.rs b/tests/ui/diagnostic_namespace/feature-gate-diagnostic_namespace.rs deleted file mode 100644 index b08e291621fdc..0000000000000 --- a/tests/ui/diagnostic_namespace/feature-gate-diagnostic_namespace.rs +++ /dev/null @@ -1,13 +0,0 @@ -#[diagnostic::non_existing_attribute] -//~^ERROR `#[diagnostic]` attribute name space is experimental [E0658] -//~|WARNING unknown diagnostic attribute [unknown_or_malformed_diagnostic_attributes] -pub trait Bar { -} - -#[diagnostic::non_existing_attribute(with_option = "foo")] -//~^ERROR `#[diagnostic]` attribute name space is experimental [E0658] -//~|WARNING unknown diagnostic attribute [unknown_or_malformed_diagnostic_attributes] -struct Foo; - -fn main() { -} diff --git a/tests/ui/diagnostic_namespace/feature-gate-diagnostic_namespace.stderr b/tests/ui/diagnostic_namespace/feature-gate-diagnostic_namespace.stderr deleted file mode 100644 index 38424c13d8613..0000000000000 --- a/tests/ui/diagnostic_namespace/feature-gate-diagnostic_namespace.stderr +++ /dev/null @@ -1,37 +0,0 @@ -error[E0658]: `#[diagnostic]` attribute name space is experimental - --> $DIR/feature-gate-diagnostic_namespace.rs:1:3 - | -LL | #[diagnostic::non_existing_attribute] - | ^^^^^^^^^^ - | - = note: see issue #111996 for more information - = help: add `#![feature(diagnostic_namespace)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: `#[diagnostic]` attribute name space is experimental - --> $DIR/feature-gate-diagnostic_namespace.rs:7:3 - | -LL | #[diagnostic::non_existing_attribute(with_option = "foo")] - | ^^^^^^^^^^ - | - = note: see issue #111996 for more information - = help: add `#![feature(diagnostic_namespace)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -warning: unknown diagnostic attribute - --> $DIR/feature-gate-diagnostic_namespace.rs:1:15 - | -LL | #[diagnostic::non_existing_attribute] - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default - -warning: unknown diagnostic attribute - --> $DIR/feature-gate-diagnostic_namespace.rs:7:15 - | -LL | #[diagnostic::non_existing_attribute(with_option = "foo")] - | ^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors; 2 warnings emitted - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.rs b/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.rs index 95465701bf858..f6957b1448d18 100644 --- a/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.rs +++ b/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.rs @@ -1,4 +1,3 @@ -#![feature(diagnostic_namespace)] //@ check-pass #[diagnostic::non_existing_attribute] //~^WARN unknown diagnostic attribute diff --git a/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.stderr b/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.stderr index 753077b365e8f..c073ec9b103f6 100644 --- a/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.stderr +++ b/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.stderr @@ -1,5 +1,5 @@ warning: unknown diagnostic attribute - --> $DIR/non_existing_attributes_accepted.rs:3:15 + --> $DIR/non_existing_attributes_accepted.rs:2:15 | LL | #[diagnostic::non_existing_attribute] | ^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | #[diagnostic::non_existing_attribute] = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default warning: unknown diagnostic attribute - --> $DIR/non_existing_attributes_accepted.rs:8:15 + --> $DIR/non_existing_attributes_accepted.rs:7:15 | LL | #[diagnostic::non_existing_attribute(with_option = "foo")] | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/auxiliary/other.rs b/tests/ui/diagnostic_namespace/on_unimplemented/auxiliary/other.rs index 884bab2800a5b..512ef6330e5ec 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/auxiliary/other.rs +++ b/tests/ui/diagnostic_namespace/on_unimplemented/auxiliary/other.rs @@ -1,5 +1,3 @@ -#![feature(diagnostic_namespace)] - #[diagnostic::on_unimplemented( message = "Message", note = "Note", diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs index eb985c062f3dd..30a85ff21992d 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs +++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs @@ -1,5 +1,3 @@ -#![feature(diagnostic_namespace)] - #[diagnostic::on_unimplemented( on(_Self = "&str"), //~^WARN malformed `on_unimplemented` attribute diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr index 75a701f0b5f65..e34b917f67e10 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr +++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr @@ -1,5 +1,5 @@ warning: `#[diagnostic::on_unimplemented]` can only be applied to trait definitions - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:24:1 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:22:1 | LL | #[diagnostic::on_unimplemented(message = "Not allowed to apply it on a impl")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | #[diagnostic::on_unimplemented(message = "Not allowed to apply it on a impl = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:4:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:2:5 | LL | on(_Self = "&str"), | ^^^^^^^^^^^^^^^^^^ invalid option found here @@ -15,7 +15,7 @@ LL | on(_Self = "&str"), = help: only `message`, `note` and `label` are allowed as options warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:10:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:8:5 | LL | parent_label = "in this scope", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here @@ -23,7 +23,7 @@ LL | parent_label = "in this scope", = help: only `message`, `note` and `label` are allowed as options warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:13:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:11:5 | LL | append_const_msg | ^^^^^^^^^^^^^^^^ invalid option found here @@ -31,7 +31,7 @@ LL | append_const_msg = help: only `message`, `note` and `label` are allowed as options warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:19:32 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:17:32 | LL | #[diagnostic::on_unimplemented = "Message"] | ^^^^^^^^^^^ invalid option found here @@ -39,7 +39,7 @@ LL | #[diagnostic::on_unimplemented = "Message"] = help: only `message`, `note` and `label` are allowed as options warning: there is no parameter `from_desugaring` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5 | LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -47,7 +47,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", = help: expect either a generic argument name or `{Self}` as format argument warning: there is no parameter `direct` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5 | LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -55,7 +55,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", = help: expect either a generic argument name or `{Self}` as format argument warning: there is no parameter `cause` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5 | LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -63,7 +63,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", = help: expect either a generic argument name or `{Self}` as format argument warning: there is no parameter `integral` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5 | LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -71,7 +71,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", = help: expect either a generic argument name or `{Self}` as format argument warning: there is no parameter `integer` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5 | LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -79,7 +79,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", = help: expect either a generic argument name or `{Self}` as format argument warning: there is no parameter `float` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5 | LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -87,7 +87,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" = help: expect either a generic argument name or `{Self}` as format argument warning: there is no parameter `_Self` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5 | LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -95,7 +95,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" = help: expect either a generic argument name or `{Self}` as format argument warning: there is no parameter `crate_local` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5 | LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -103,7 +103,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" = help: expect either a generic argument name or `{Self}` as format argument warning: there is no parameter `Trait` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5 | LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -111,7 +111,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" = help: expect either a generic argument name or `{Self}` as format argument warning: there is no parameter `ItemContext` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5 | LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -119,7 +119,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" = help: expect either a generic argument name or `{Self}` as format argument warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:4:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:2:5 | LL | on(_Self = "&str"), | ^^^^^^^^^^^^^^^^^^ invalid option found here @@ -128,7 +128,7 @@ LL | on(_Self = "&str"), = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:10:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:8:5 | LL | parent_label = "in this scope", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here @@ -137,7 +137,7 @@ LL | parent_label = "in this scope", = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:13:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:11:5 | LL | append_const_msg | ^^^^^^^^^^^^^^^^ invalid option found here @@ -146,7 +146,7 @@ LL | append_const_msg = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: trait has `()` and `i32` as params - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:61:15 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:59:15 | LL | takes_foo(()); | --------- ^^ trait has `()` and `i32` as params @@ -156,18 +156,18 @@ LL | takes_foo(()); = help: the trait `Foo` is not implemented for `()` = note: trait has `()` and `i32` as params help: this trait has no implementations, consider adding one - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:17:1 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:15:1 | LL | trait Foo {} | ^^^^^^^^^^^^ note: required by a bound in `takes_foo` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:56:22 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:54:22 | LL | fn takes_foo(_: impl Foo) {} | ^^^^^^^^ required by this bound in `takes_foo` warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:19:32 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:17:32 | LL | #[diagnostic::on_unimplemented = "Message"] | ^^^^^^^^^^^ invalid option found here @@ -176,7 +176,7 @@ LL | #[diagnostic::on_unimplemented = "Message"] = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `(): Bar` is not satisfied - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:63:15 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:61:15 | LL | takes_bar(()); | --------- ^^ the trait `Bar` is not implemented for `()` @@ -185,13 +185,13 @@ LL | takes_bar(()); | = help: the trait `Bar` is implemented for `i32` note: required by a bound in `takes_bar` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:57:22 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:55:22 | LL | fn takes_bar(_: impl Bar) {} | ^^^ required by this bound in `takes_bar` warning: there is no parameter `from_desugaring` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5 | LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -200,7 +200,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: there is no parameter `direct` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5 | LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -209,7 +209,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: there is no parameter `cause` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5 | LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -218,7 +218,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: there is no parameter `integral` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5 | LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -227,7 +227,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: there is no parameter `integer` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5 | LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -236,7 +236,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: there is no parameter `float` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5 | LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -245,7 +245,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: there is no parameter `_Self` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5 | LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -254,7 +254,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: there is no parameter `crate_local` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5 | LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -263,7 +263,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: there is no parameter `Trait` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5 | LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -272,7 +272,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: there is no parameter `ItemContext` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5 | LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -281,7 +281,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: {from_desugaring}{direct}{cause}{integral}{integer} - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:65:15 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:63:15 | LL | takes_baz(()); | --------- ^^ {float}{_Self}{crate_local}{Trait}{ItemContext} @@ -290,12 +290,12 @@ LL | takes_baz(()); | = help: the trait `Baz` is not implemented for `()` help: this trait has no implementations, consider adding one - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:54:1 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:52:1 | LL | trait Baz {} | ^^^^^^^^^ note: required by a bound in `takes_baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:58:22 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:56:22 | LL | fn takes_baz(_: impl Baz) {} | ^^^ required by this bound in `takes_baz` diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs index 12fe988170ac1..b4234066bb19a 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs +++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs @@ -1,5 +1,3 @@ -#![feature(diagnostic_namespace)] - #[diagnostic::on_unimplemented(unsupported = "foo")] //~^WARN malformed `on_unimplemented` attribute //~|WARN malformed `on_unimplemented` attribute diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr index 11263580b15e2..dc0c194823696 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr +++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr @@ -1,5 +1,5 @@ warning: `#[diagnostic::on_unimplemented]` can only be applied to trait definitions - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:8:1 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:6:1 | LL | #[diagnostic::on_unimplemented(message = "Baz")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | #[diagnostic::on_unimplemented(message = "Baz")] = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:3:32 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:1:32 | LL | #[diagnostic::on_unimplemented(unsupported = "foo")] | ^^^^^^^^^^^^^^^^^^^ invalid option found here @@ -15,7 +15,7 @@ LL | #[diagnostic::on_unimplemented(unsupported = "foo")] = help: only `message`, `note` and `label` are allowed as options warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:12:50 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:10:50 | LL | #[diagnostic::on_unimplemented(message = "Boom", unsupported = "Bar")] | ^^^^^^^^^^^^^^^^^^^ invalid option found here @@ -23,7 +23,7 @@ LL | #[diagnostic::on_unimplemented(message = "Boom", unsupported = "Bar")] = help: only `message`, `note` and `label` are allowed as options warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:17:50 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:15:50 | LL | #[diagnostic::on_unimplemented(message = "Boom", on(_Self = "i32", message = "whatever"))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here @@ -31,7 +31,7 @@ LL | #[diagnostic::on_unimplemented(message = "Boom", on(_Self = "i32", message = help: only `message`, `note` and `label` are allowed as options warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:22:32 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:20:32 | LL | #[diagnostic::on_unimplemented = "boom"] | ^^^^^^^^ invalid option found here @@ -39,7 +39,7 @@ LL | #[diagnostic::on_unimplemented = "boom"] = help: only `message`, `note` and `label` are allowed as options warning: missing options for `on_unimplemented` attribute - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:26:1 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:24:1 | LL | #[diagnostic::on_unimplemented] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -47,7 +47,7 @@ LL | #[diagnostic::on_unimplemented] = help: at least one of the `message`, `note` and `label` options are expected warning: there is no parameter `DoesNotExist` on trait `Test` - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:31:32 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:29:32 | LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -55,7 +55,7 @@ LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")] = help: expect either a generic argument name or `{Self}` as format argument warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:3:32 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:1:32 | LL | #[diagnostic::on_unimplemented(unsupported = "foo")] | ^^^^^^^^^^^^^^^^^^^ invalid option found here @@ -64,7 +64,7 @@ LL | #[diagnostic::on_unimplemented(unsupported = "foo")] = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `i32: Foo` is not satisfied - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:43:14 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:41:14 | LL | take_foo(1_i32); | -------- ^^^^^ the trait `Foo` is not implemented for `i32` @@ -72,18 +72,18 @@ LL | take_foo(1_i32); | required by a bound introduced by this call | help: this trait has no implementations, consider adding one - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:6:1 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:4:1 | LL | trait Foo {} | ^^^^^^^^^ note: required by a bound in `take_foo` - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:36:21 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:34:21 | LL | fn take_foo(_: impl Foo) {} | ^^^ required by this bound in `take_foo` warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:12:50 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:10:50 | LL | #[diagnostic::on_unimplemented(message = "Boom", unsupported = "Bar")] | ^^^^^^^^^^^^^^^^^^^ invalid option found here @@ -92,7 +92,7 @@ LL | #[diagnostic::on_unimplemented(message = "Boom", unsupported = "Bar")] = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: Boom - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:45:14 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:43:14 | LL | take_baz(1_i32); | -------- ^^^^^ the trait `Baz` is not implemented for `i32` @@ -100,18 +100,18 @@ LL | take_baz(1_i32); | required by a bound introduced by this call | help: this trait has no implementations, consider adding one - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:15:1 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:13:1 | LL | trait Baz {} | ^^^^^^^^^ note: required by a bound in `take_baz` - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:37:21 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:35:21 | LL | fn take_baz(_: impl Baz) {} | ^^^ required by this bound in `take_baz` warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:17:50 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:15:50 | LL | #[diagnostic::on_unimplemented(message = "Boom", on(_Self = "i32", message = "whatever"))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here @@ -120,7 +120,7 @@ LL | #[diagnostic::on_unimplemented(message = "Boom", on(_Self = "i32", message = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: Boom - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:47:15 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:45:15 | LL | take_boom(1_i32); | --------- ^^^^^ the trait `Boom` is not implemented for `i32` @@ -128,18 +128,18 @@ LL | take_boom(1_i32); | required by a bound introduced by this call | help: this trait has no implementations, consider adding one - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:20:1 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:18:1 | LL | trait Boom {} | ^^^^^^^^^^ note: required by a bound in `take_boom` - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:38:22 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:36:22 | LL | fn take_boom(_: impl Boom) {} | ^^^^ required by this bound in `take_boom` warning: missing options for `on_unimplemented` attribute - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:26:1 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:24:1 | LL | #[diagnostic::on_unimplemented] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -148,7 +148,7 @@ LL | #[diagnostic::on_unimplemented] = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `i32: Whatever` is not satisfied - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:49:19 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:47:19 | LL | take_whatever(1_i32); | ------------- ^^^^^ the trait `Whatever` is not implemented for `i32` @@ -156,18 +156,18 @@ LL | take_whatever(1_i32); | required by a bound introduced by this call | help: this trait has no implementations, consider adding one - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:29:1 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:27:1 | LL | trait Whatever {} | ^^^^^^^^^^^^^^ note: required by a bound in `take_whatever` - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:39:26 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:37:26 | LL | fn take_whatever(_: impl Whatever) {} | ^^^^^^^^ required by this bound in `take_whatever` warning: there is no parameter `DoesNotExist` on trait `Test` - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:31:32 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:29:32 | LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -176,7 +176,7 @@ LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")] = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: {DoesNotExist} - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:51:15 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:49:15 | LL | take_test(()); | --------- ^^ the trait `Test` is not implemented for `()` @@ -184,12 +184,12 @@ LL | take_test(()); | required by a bound introduced by this call | help: this trait has no implementations, consider adding one - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:34:1 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:32:1 | LL | trait Test {} | ^^^^^^^^^^ note: required by a bound in `take_test` - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:40:22 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:38:22 | LL | fn take_test(_: impl Test) {} | ^^^^ required by this bound in `take_test` diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/feature-gate-diagnostic_on_unimplemented.rs b/tests/ui/diagnostic_namespace/on_unimplemented/feature-gate-diagnostic_on_unimplemented.rs deleted file mode 100644 index 609a840c118c6..0000000000000 --- a/tests/ui/diagnostic_namespace/on_unimplemented/feature-gate-diagnostic_on_unimplemented.rs +++ /dev/null @@ -1,7 +0,0 @@ -#[diagnostic::on_unimplemented(message = "Foo")] -//~^ERROR `#[diagnostic]` attribute name space is experimental [E0658] -pub trait Bar { -} - -fn main() { -} diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/feature-gate-diagnostic_on_unimplemented.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/feature-gate-diagnostic_on_unimplemented.stderr deleted file mode 100644 index 719322fa0f55e..0000000000000 --- a/tests/ui/diagnostic_namespace/on_unimplemented/feature-gate-diagnostic_on_unimplemented.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0658]: `#[diagnostic]` attribute name space is experimental - --> $DIR/feature-gate-diagnostic_on_unimplemented.rs:1:3 - | -LL | #[diagnostic::on_unimplemented(message = "Foo")] - | ^^^^^^^^^^ - | - = note: see issue #111996 for more information - = help: add `#![feature(diagnostic_namespace)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.rs b/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.rs index 0893f29c4a3b4..5b25fb234bc52 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.rs +++ b/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.rs @@ -1,5 +1,3 @@ -#![feature(diagnostic_namespace)] - #[diagnostic::on_unimplemented( if(Self = "()"), //~^WARN malformed `on_unimplemented` attribute diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.stderr index e00846da77be5..56d125e20e5c4 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.stderr +++ b/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.stderr @@ -1,5 +1,5 @@ warning: malformed `on_unimplemented` attribute - --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:4:5 + --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:2:5 | LL | if(Self = "()"), | ^^^^^^^^^^^^^^^ invalid option found here @@ -8,7 +8,7 @@ LL | if(Self = "()"), = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default warning: `message` is ignored due to previous definition of `message` - --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:10:32 + --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:8:32 | LL | message = "custom message", | -------------------------- `message` is first declared here @@ -17,7 +17,7 @@ LL | #[diagnostic::on_unimplemented(message = "fallback!!")] | ^^^^^^^^^^^^^^^^^^^^^^ `message` is already declared here warning: malformed `on_unimplemented` attribute - --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:4:5 + --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:2:5 | LL | if(Self = "()"), | ^^^^^^^^^^^^^^^ invalid option found here @@ -26,7 +26,7 @@ LL | if(Self = "()"), = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: `message` is ignored due to previous definition of `message` - --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:10:32 + --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:8:32 | LL | message = "custom message", | -------------------------- `message` is first declared here @@ -37,7 +37,7 @@ LL | #[diagnostic::on_unimplemented(message = "fallback!!")] = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: custom message - --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:20:15 + --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:18:15 | LL | takes_foo(()); | --------- ^^ fallback label @@ -48,12 +48,12 @@ LL | takes_foo(()); = note: custom note = note: fallback note help: this trait has no implementations, consider adding one - --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:15:1 + --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:13:1 | LL | trait Foo {} | ^^^^^^^^^ note: required by a bound in `takes_foo` - --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:17:22 + --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:15:22 | LL | fn takes_foo(_: impl Foo) {} | ^^^ required by this bound in `takes_foo` diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.rs b/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.rs index 34cdb99c754b1..a5982f6492ca5 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.rs +++ b/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.rs @@ -1,5 +1,3 @@ -#![feature(diagnostic_namespace)] - #[diagnostic::on_unimplemented(message = "Foo", label = "Bar", note = "Baz", note = "Boom")] trait Foo {} diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.stderr index c72321d4617f0..93a0d0b3f4132 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.stderr +++ b/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.stderr @@ -1,5 +1,5 @@ error[E0277]: Foo - --> $DIR/multiple_notes.rs:14:15 + --> $DIR/multiple_notes.rs:12:15 | LL | takes_foo(()); | --------- ^^ Bar @@ -10,18 +10,18 @@ LL | takes_foo(()); = note: Baz = note: Boom help: this trait has no implementations, consider adding one - --> $DIR/multiple_notes.rs:4:1 + --> $DIR/multiple_notes.rs:2:1 | LL | trait Foo {} | ^^^^^^^^^ note: required by a bound in `takes_foo` - --> $DIR/multiple_notes.rs:10:22 + --> $DIR/multiple_notes.rs:8:22 | LL | fn takes_foo(_: impl Foo) {} | ^^^ required by this bound in `takes_foo` error[E0277]: Bar - --> $DIR/multiple_notes.rs:16:15 + --> $DIR/multiple_notes.rs:14:15 | LL | takes_bar(()); | --------- ^^ Foo @@ -32,12 +32,12 @@ LL | takes_bar(()); = note: Baz = note: Baz2 help: this trait has no implementations, consider adding one - --> $DIR/multiple_notes.rs:8:1 + --> $DIR/multiple_notes.rs:6:1 | LL | trait Bar {} | ^^^^^^^^^ note: required by a bound in `takes_bar` - --> $DIR/multiple_notes.rs:11:22 + --> $DIR/multiple_notes.rs:9:22 | LL | fn takes_bar(_: impl Bar) {} | ^^^ required by this bound in `takes_bar` diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.rs b/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.rs index 797edbc9ec564..7ca0312775964 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.rs +++ b/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.rs @@ -1,5 +1,3 @@ -#![feature(diagnostic_namespace)] - #[diagnostic::on_unimplemented(message = "Foo", label = "Bar", note = "Baz")] trait Foo {} diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.stderr index de57f7044bffe..6b17f40c6dd16 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.stderr +++ b/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.stderr @@ -1,5 +1,5 @@ error[E0277]: Foo - --> $DIR/on_unimplemented_simple.rs:9:15 + --> $DIR/on_unimplemented_simple.rs:7:15 | LL | takes_foo(()); | --------- ^^ Bar @@ -9,12 +9,12 @@ LL | takes_foo(()); = help: the trait `Foo` is not implemented for `()` = note: Baz help: this trait has no implementations, consider adding one - --> $DIR/on_unimplemented_simple.rs:4:1 + --> $DIR/on_unimplemented_simple.rs:2:1 | LL | trait Foo {} | ^^^^^^^^^ note: required by a bound in `takes_foo` - --> $DIR/on_unimplemented_simple.rs:6:22 + --> $DIR/on_unimplemented_simple.rs:4:22 | LL | fn takes_foo(_: impl Foo) {} | ^^^ required by this bound in `takes_foo` diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.rs b/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.rs index a7becd2f88f6d..8c0b81504177f 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.rs +++ b/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.rs @@ -1,5 +1,3 @@ -#![feature(diagnostic_namespace)] - #[diagnostic::on_unimplemented( message = "first message", label = "first label", diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.stderr index d30754dcf10d0..43ab6bf25a1a2 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.stderr +++ b/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.stderr @@ -1,5 +1,5 @@ warning: `message` is ignored due to previous definition of `message` - --> $DIR/report_warning_on_duplicated_options.rs:9:5 + --> $DIR/report_warning_on_duplicated_options.rs:7:5 | LL | message = "first message", | ------------------------- `message` is first declared here @@ -10,7 +10,7 @@ LL | message = "second message", = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default warning: `label` is ignored due to previous definition of `label` - --> $DIR/report_warning_on_duplicated_options.rs:12:5 + --> $DIR/report_warning_on_duplicated_options.rs:10:5 | LL | label = "first label", | --------------------- `label` is first declared here @@ -19,7 +19,7 @@ LL | label = "second label", | ^^^^^^^^^^^^^^^^^^^^^^ `label` is already declared here warning: `message` is ignored due to previous definition of `message` - --> $DIR/report_warning_on_duplicated_options.rs:9:5 + --> $DIR/report_warning_on_duplicated_options.rs:7:5 | LL | message = "first message", | ------------------------- `message` is first declared here @@ -30,7 +30,7 @@ LL | message = "second message", = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: `label` is ignored due to previous definition of `label` - --> $DIR/report_warning_on_duplicated_options.rs:12:5 + --> $DIR/report_warning_on_duplicated_options.rs:10:5 | LL | label = "first label", | --------------------- `label` is first declared here @@ -41,7 +41,7 @@ LL | label = "second label", = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: first message - --> $DIR/report_warning_on_duplicated_options.rs:23:15 + --> $DIR/report_warning_on_duplicated_options.rs:21:15 | LL | takes_foo(()); | --------- ^^ first label @@ -52,12 +52,12 @@ LL | takes_foo(()); = note: custom note = note: second note help: this trait has no implementations, consider adding one - --> $DIR/report_warning_on_duplicated_options.rs:17:1 + --> $DIR/report_warning_on_duplicated_options.rs:15:1 | LL | trait Foo {} | ^^^^^^^^^ note: required by a bound in `takes_foo` - --> $DIR/report_warning_on_duplicated_options.rs:20:22 + --> $DIR/report_warning_on_duplicated_options.rs:18:22 | LL | fn takes_foo(_: impl Foo) {} | ^^^ required by this bound in `takes_foo` diff --git a/tests/ui/diagnostic_namespace/requires_path.rs b/tests/ui/diagnostic_namespace/requires_path.rs index e8d6ca73ad0cf..4f3a1319cafff 100644 --- a/tests/ui/diagnostic_namespace/requires_path.rs +++ b/tests/ui/diagnostic_namespace/requires_path.rs @@ -1,5 +1,3 @@ -#![feature(diagnostic_namespace)] - #[diagnostic] //~^ERROR cannot find attribute `diagnostic` in this scope pub struct Bar; diff --git a/tests/ui/diagnostic_namespace/requires_path.stderr b/tests/ui/diagnostic_namespace/requires_path.stderr index 5d07d3a22d50e..e02aacac8c1a7 100644 --- a/tests/ui/diagnostic_namespace/requires_path.stderr +++ b/tests/ui/diagnostic_namespace/requires_path.stderr @@ -1,5 +1,5 @@ error: cannot find attribute `diagnostic` in this scope - --> $DIR/requires_path.rs:3:3 + --> $DIR/requires_path.rs:1:3 | LL | #[diagnostic] | ^^^^^^^^^^ diff --git a/tests/ui/did_you_mean/bad-assoc-ty.stderr b/tests/ui/did_you_mean/bad-assoc-ty.stderr index dc93762c9b19f..b349332bcb9c3 100644 --- a/tests/ui/did_you_mean/bad-assoc-ty.stderr +++ b/tests/ui/did_you_mean/bad-assoc-ty.stderr @@ -272,6 +272,17 @@ help: use type parameters instead LL | struct L(F) where F: Fn() -> T; | +++ ~ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/bad-assoc-ty.rs:82:38 + | +LL | fn foo(_: F) where F: Fn() -> _ {} + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn foo(_: F) where F: Fn() -> T {} + | +++ ~ + error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs --> $DIR/bad-assoc-ty.rs:62:30 | @@ -305,28 +316,6 @@ help: use type parameters instead LL | union O where F: Fn() -> T { | +++ ~ -error[E0121]: the placeholder `_` is not allowed within types on item signatures for traits - --> $DIR/bad-assoc-ty.rs:77:29 - | -LL | trait P where F: Fn() -> _ { - | ^ not allowed in type signatures - | -help: use type parameters instead - | -LL | trait P where F: Fn() -> T { - | +++ ~ - -error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions - --> $DIR/bad-assoc-ty.rs:82:38 - | -LL | fn foo(_: F) where F: Fn() -> _ {} - | ^ not allowed in type signatures - | -help: use type parameters instead - | -LL | fn foo(_: F) where F: Fn() -> T {} - | +++ ~ - error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union --> $DIR/bad-assoc-ty.rs:73:5 | @@ -339,6 +328,17 @@ help: wrap the field type in `ManuallyDrop<...>` LL | foo: std::mem::ManuallyDrop, | +++++++++++++++++++++++ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for traits + --> $DIR/bad-assoc-ty.rs:77:29 + | +LL | trait P where F: Fn() -> _ { + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | trait P where F: Fn() -> T { + | +++ ~ + error: aborting due to 29 previous errors; 1 warning emitted Some errors have detailed explanations: E0121, E0223, E0740. diff --git a/tests/ui/duplicate/duplicate-type-parameter.rs b/tests/ui/duplicate/duplicate-type-parameter.rs index 2751b3c8dc0ac..c2064b423f194 100644 --- a/tests/ui/duplicate/duplicate-type-parameter.rs +++ b/tests/ui/duplicate/duplicate-type-parameter.rs @@ -23,7 +23,6 @@ trait Qux {} impl Qux for Option {} //~^ ERROR the name `T` is already used -//~^^ ERROR the type parameter `T` is not constrained fn main() { } diff --git a/tests/ui/duplicate/duplicate-type-parameter.stderr b/tests/ui/duplicate/duplicate-type-parameter.stderr index 628f898d5c879..f23f2460a8acf 100644 --- a/tests/ui/duplicate/duplicate-type-parameter.stderr +++ b/tests/ui/duplicate/duplicate-type-parameter.stderr @@ -54,13 +54,6 @@ LL | impl Qux for Option {} | | | first use of `T` -error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates - --> $DIR/duplicate-type-parameter.rs:24:8 - | -LL | impl Qux for Option {} - | ^ unconstrained type parameter - -error: aborting due to 8 previous errors +error: aborting due to 7 previous errors -Some errors have detailed explanations: E0207, E0403. -For more information about an error, try `rustc --explain E0207`. +For more information about this error, try `rustc --explain E0403`. diff --git a/tests/ui/error-codes/E0374.stderr b/tests/ui/error-codes/E0374.stderr index 77f351b28ef24..71eec4c16fd34 100644 --- a/tests/ui/error-codes/E0374.stderr +++ b/tests/ui/error-codes/E0374.stderr @@ -1,3 +1,11 @@ +error[E0392]: type parameter `T` is never used + --> $DIR/E0374.rs:4:12 + | +LL | struct Foo { + | ^ unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + error[E0374]: the trait `CoerceUnsized` may only be implemented for a coercion between structures --> $DIR/E0374.rs:8:1 | @@ -7,14 +15,6 @@ LL | | where T: CoerceUnsized {} | = note: expected a single field to be coerced, none found -error[E0392]: type parameter `T` is never used - --> $DIR/E0374.rs:4:12 - | -LL | struct Foo { - | ^ unused type parameter - | - = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` - error: aborting due to 2 previous errors Some errors have detailed explanations: E0374, E0392. diff --git a/tests/ui/error-codes/E0375.stderr b/tests/ui/error-codes/E0375.stderr index d5340022d68ce..af720bd40e7e3 100644 --- a/tests/ui/error-codes/E0375.stderr +++ b/tests/ui/error-codes/E0375.stderr @@ -1,12 +1,3 @@ -error[E0375]: implementing the trait `CoerceUnsized` requires multiple coercions - --> $DIR/E0375.rs:10:12 - | -LL | impl CoerceUnsized> for Foo {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ requires multiple coercions - | - = note: `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced - = note: currently, 2 fields need coercions: `b` (`T` to `U`), `c` (`U` to `T`) - error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/E0375.rs:6:8 | @@ -32,6 +23,15 @@ help: the `Box` type always has a statically known size and allocates its conten LL | b: Box, | ++++ + +error[E0375]: implementing the trait `CoerceUnsized` requires multiple coercions + --> $DIR/E0375.rs:10:12 + | +LL | impl CoerceUnsized> for Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ requires multiple coercions + | + = note: `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced + = note: currently, 2 fields need coercions: `b` (`T` to `U`), `c` (`U` to `T`) + error: aborting due to 2 previous errors Some errors have detailed explanations: E0277, E0375. diff --git a/tests/ui/error-codes/E0657.rs b/tests/ui/error-codes/E0657.rs index cb11de13f73c6..212c1d9e581a2 100644 --- a/tests/ui/error-codes/E0657.rs +++ b/tests/ui/error-codes/E0657.rs @@ -8,7 +8,7 @@ impl Id for T {} fn free_fn_capture_hrtb_in_impl_trait() -> Box Id>> - //~^ ERROR `impl Trait` can only capture lifetimes bound at the fn or impl level [E0657] + //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type { Box::new(()) } @@ -17,7 +17,7 @@ struct Foo; impl Foo { fn impl_fn_capture_hrtb_in_impl_trait() -> Box Id>> - //~^ ERROR `impl Trait` can only capture lifetimes bound at the fn or impl level + //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type { Box::new(()) } diff --git a/tests/ui/error-codes/E0657.stderr b/tests/ui/error-codes/E0657.stderr index df76b45a5891f..c539007cdcf19 100644 --- a/tests/ui/error-codes/E0657.stderr +++ b/tests/ui/error-codes/E0657.stderr @@ -1,14 +1,26 @@ -error[E0657]: `impl Trait` can only capture lifetimes bound at the fn or impl level +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from `dyn` type --> $DIR/E0657.rs:10:31 | LL | -> Box Id>> | ^^ + | +note: lifetime declared here + --> $DIR/E0657.rs:10:16 + | +LL | -> Box Id>> + | ^^ -error[E0657]: `impl Trait` can only capture lifetimes bound at the fn or impl level +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from `dyn` type --> $DIR/E0657.rs:19:35 | LL | -> Box Id>> | ^^ + | +note: lifetime declared here + --> $DIR/E0657.rs:19:20 + | +LL | -> Box Id>> + | ^^ error: aborting due to 2 previous errors diff --git a/tests/ui/error-codes/E0719.stderr b/tests/ui/error-codes/E0719.stderr index f048a8aabd449..7e8329db1f48f 100644 --- a/tests/ui/error-codes/E0719.stderr +++ b/tests/ui/error-codes/E0719.stderr @@ -16,14 +16,6 @@ LL | trait Foo: Iterator {} | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified - --> $DIR/E0719.rs:8:42 - | -LL | fn test() -> Box> { - | --------- ^^^^^^^^^^^ re-bound here - | | - | `Item` bound here first - error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified --> $DIR/E0719.rs:1:33 | @@ -34,6 +26,14 @@ LL | trait Foo: Iterator {} | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified + --> $DIR/E0719.rs:8:42 + | +LL | fn test() -> Box> { + | --------- ^^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified --> $DIR/E0719.rs:14:38 | diff --git a/tests/ui/feature-gates/feature-gate-asm_goto.rs b/tests/ui/feature-gates/feature-gate-asm_goto.rs new file mode 100644 index 0000000000000..beac4590349f6 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-asm_goto.rs @@ -0,0 +1,10 @@ +//@ only-x86_64 + +use std::arch::asm; + +fn main() { + unsafe { + asm!("jmp {}", label {}); + //~^ ERROR label operands for inline assembly are unstable + } +} diff --git a/tests/ui/feature-gates/feature-gate-asm_goto.stderr b/tests/ui/feature-gates/feature-gate-asm_goto.stderr new file mode 100644 index 0000000000000..62fd1a320d3c0 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-asm_goto.stderr @@ -0,0 +1,13 @@ +error[E0658]: label operands for inline assembly are unstable + --> $DIR/feature-gate-asm_goto.rs:7:24 + | +LL | asm!("jmp {}", label {}); + | ^^^^^^^^ + | + = note: see issue #119364 for more information + = help: add `#![feature(asm_goto)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-impl_trait_in_assoc_type.stderr b/tests/ui/feature-gates/feature-gate-impl_trait_in_assoc_type.stderr index 7dfd79c728641..d8a85c8838d4d 100644 --- a/tests/ui/feature-gates/feature-gate-impl_trait_in_assoc_type.stderr +++ b/tests/ui/feature-gates/feature-gate-impl_trait_in_assoc_type.stderr @@ -18,6 +18,14 @@ LL | type Bop = impl std::fmt::Debug; = help: add `#![feature(impl_trait_in_assoc_type)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +error: unconstrained opaque type + --> $DIR/feature-gate-impl_trait_in_assoc_type.rs:6:16 + | +LL | type Bar = impl std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: `Bar` must be used in combination with a concrete type within the same impl + error[E0658]: inherent associated types are unstable --> $DIR/feature-gate-impl_trait_in_assoc_type.rs:14:5 | @@ -28,14 +36,6 @@ LL | type Bop = impl std::fmt::Debug; = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: unconstrained opaque type - --> $DIR/feature-gate-impl_trait_in_assoc_type.rs:6:16 - | -LL | type Bar = impl std::fmt::Debug; - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: `Bar` must be used in combination with a concrete type within the same impl - error: unconstrained opaque type --> $DIR/feature-gate-impl_trait_in_assoc_type.rs:14:16 | diff --git a/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr b/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr index 7fc726409ce40..5e62221628d26 100644 --- a/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr +++ b/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr @@ -74,7 +74,6 @@ LL | fn use_for() where i32: Iterator { | ^^^^^^^^^^^^^ `i32` is not an iterator | = help: the trait `Iterator` is not implemented for `i32` - = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable diff --git a/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr b/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr index 5d598ec2969fc..c3f161469e308 100644 --- a/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr +++ b/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr @@ -56,26 +56,6 @@ LL | impl Fn<()> for Foo { | = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable -error[E0183]: manual implementations of `FnOnce` are experimental - --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:18:6 - | -LL | impl FnOnce() for Foo1 { - | ^^^^^^^^ manual implementations of `FnOnce` are experimental - | - = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable - -error[E0229]: associated type bindings are not allowed here - --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:18:6 - | -LL | impl FnOnce() for Foo1 { - | ^^^^^^^^ associated type not allowed here - | -help: parenthesized trait syntax expands to `FnOnce<(), Output=()>` - --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:18:6 - | -LL | impl FnOnce() for Foo1 { - | ^^^^^^^^ - error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:26:6 | @@ -94,24 +74,6 @@ LL | impl FnMut<()> for Bar { | = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable -error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change - --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:35:6 - | -LL | impl FnOnce<()> for Baz { - | ^^^^^^^^^^ - | - = note: see issue #29625 for more information - = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0183]: manual implementations of `FnOnce` are experimental - --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:35:6 - | -LL | impl FnOnce<()> for Baz { - | ^^^^^^^^^^ manual implementations of `FnOnce` are experimental - | - = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable - error[E0277]: expected a `FnMut()` closure, found `Foo` --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:9:17 | @@ -135,6 +97,44 @@ LL | extern "rust-call" fn call(self, args: ()) -> () {} = note: expected signature `extern "rust-call" fn(&Foo, ()) -> _` found signature `extern "rust-call" fn(Foo, ())` +error[E0183]: manual implementations of `FnOnce` are experimental + --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:18:6 + | +LL | impl FnOnce() for Foo1 { + | ^^^^^^^^ manual implementations of `FnOnce` are experimental + | + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + +error[E0229]: associated type bindings are not allowed here + --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:18:6 + | +LL | impl FnOnce() for Foo1 { + | ^^^^^^^^ associated type not allowed here + | +help: parenthesized trait syntax expands to `FnOnce<(), Output=()>` + --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:18:6 + | +LL | impl FnOnce() for Foo1 { + | ^^^^^^^^ + +error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change + --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:35:6 + | +LL | impl FnOnce<()> for Baz { + | ^^^^^^^^^^ + | + = note: see issue #29625 for more information + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0183]: manual implementations of `FnOnce` are experimental + --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:35:6 + | +LL | impl FnOnce<()> for Baz { + | ^^^^^^^^^^ manual implementations of `FnOnce` are experimental + | + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + error[E0046]: not all trait items implemented, missing: `Output` --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:18:1 | diff --git a/tests/ui/for/issue-20605.current.stderr b/tests/ui/for/issue-20605.current.stderr index c8d39afdeb957..9e706601ef507 100644 --- a/tests/ui/for/issue-20605.current.stderr +++ b/tests/ui/for/issue-20605.current.stderr @@ -1,4 +1,4 @@ -error[E0277]: the size for values of type `dyn Iterator` cannot be known at compilation time +error[E0277]: `dyn Iterator` is not an iterator --> $DIR/issue-20605.rs:5:17 | LL | for item in *things { *item = 0 } diff --git a/tests/ui/for/issue-20605.next.stderr b/tests/ui/for/issue-20605.next.stderr index a44faa5491d3d..f9c3848476c88 100644 --- a/tests/ui/for/issue-20605.next.stderr +++ b/tests/ui/for/issue-20605.next.stderr @@ -1,8 +1,10 @@ -error[E0277]: the trait bound `dyn Iterator: IntoIterator` is not satisfied +error[E0277]: `dyn Iterator` is not an iterator --> $DIR/issue-20605.rs:5:17 | LL | for item in *things { *item = 0 } - | ^^^^^^^ the trait `IntoIterator` is not implemented for `dyn Iterator` + | ^^^^^^^ `dyn Iterator` is not an iterator + | + = help: the trait `IntoIterator` is not implemented for `dyn Iterator` error: the type ` as IntoIterator>::IntoIter` is not well-formed --> $DIR/issue-20605.rs:5:17 diff --git a/tests/ui/for/issue-20605.rs b/tests/ui/for/issue-20605.rs index 4a9f62b6612ae..1c01de967ccc8 100644 --- a/tests/ui/for/issue-20605.rs +++ b/tests/ui/for/issue-20605.rs @@ -3,8 +3,8 @@ fn changer<'a>(mut things: Box>) { for item in *things { *item = 0 } - //[current]~^ ERROR the size for values of type - //[next]~^^ ERROR the trait bound `dyn Iterator: IntoIterator` is not satisfied + //[current]~^ ERROR `dyn Iterator` is not an iterator + //[next]~^^ ERROR `dyn Iterator` is not an iterator //[next]~| ERROR the type ` as IntoIterator>::IntoIter` is not well-formed //[next]~| ERROR the type `&mut as IntoIterator>::IntoIter` is not well-formed //[next]~| ERROR the type `Option<< as IntoIterator>::IntoIter as Iterator>::Item>` is not well-formed diff --git a/tests/ui/generic-associated-types/bugs/issue-87735.stderr b/tests/ui/generic-associated-types/bugs/issue-87735.stderr index b80e3e798bd41..d80050652389d 100644 --- a/tests/ui/generic-associated-types/bugs/issue-87735.stderr +++ b/tests/ui/generic-associated-types/bugs/issue-87735.stderr @@ -4,6 +4,91 @@ error[E0207]: the type parameter `U` is not constrained by the impl trait, self LL | impl<'b, T, U> AsRef2 for Foo | ^ unconstrained type parameter -error: aborting due to 1 previous error +error[E0309]: the parameter type `U` may not live long enough + --> $DIR/issue-87735.rs:34:21 + | +LL | type Output<'a> = FooRef<'a, U> where Self: 'a; + | -- ^^^^^^^^^^^^^ ...so that the type `U` will meet its required lifetime bounds... + | | + | the parameter type `U` must be valid for the lifetime `'a` as defined here... + | +note: ...that is required by this bound + --> $DIR/issue-87735.rs:23:22 + | +LL | struct FooRef<'a, U>(&'a [U]); + | ^^^^^^^ +help: consider adding an explicit lifetime bound + | +LL | type Output<'a> = FooRef<'a, U> where Self: 'a, U: 'a; + | +++++++ + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/issue-87735.rs:31:15 + | +LL | impl<'b, T, U> AsRef2 for Foo + | -- the parameter type `T` must be valid for the lifetime `'b` as defined here... +... +LL | T: AsRef2 = &'b [U]>, + | ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds... + | +note: ...that is required by this bound + --> $DIR/issue-87735.rs:7:31 + | +LL | type Output<'a> where Self: 'a; + | ^^ +help: consider adding an explicit lifetime bound + | +LL | T: AsRef2 = &'b [U]> + 'b, + | ++++ + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/issue-87735.rs:36:31 + | +LL | impl<'b, T, U> AsRef2 for Foo + | -- the parameter type `T` must be valid for the lifetime `'b` as defined here... +... +LL | fn as_ref2<'a>(&'a self) -> Self::Output<'a> { + | ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds... + | +note: ...that is required by this bound + --> $DIR/issue-87735.rs:7:31 + | +LL | type Output<'a> where Self: 'a; + | ^^ +help: consider adding an explicit lifetime bound + | +LL | T: AsRef2 = &'b [U]> + 'b, + | ++++ + +error: lifetime may not live long enough + --> $DIR/issue-87735.rs:37:5 + | +LL | impl<'b, T, U> AsRef2 for Foo + | -- lifetime `'b` defined here +... +LL | fn as_ref2<'a>(&'a self) -> Self::Output<'a> { + | -- lifetime `'a` defined here +LL | FooRef(self.0.as_ref2()) + | ^^^^^^^^^^^^^^^^^^^^^^^^ method was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/issue-87735.rs:37:12 + | +LL | impl<'b, T, U> AsRef2 for Foo + | -- lifetime `'b` defined here +... +LL | fn as_ref2<'a>(&'a self) -> Self::Output<'a> { + | -- lifetime `'a` defined here +LL | FooRef(self.0.as_ref2()) + | ^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` + +help: `'b` and `'a` must be the same: replace one with the other + +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0207`. +Some errors have detailed explanations: E0207, E0309. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/generic-associated-types/bugs/issue-88526.stderr b/tests/ui/generic-associated-types/bugs/issue-88526.stderr index ba87ac9185d30..5da3e3ff64ab9 100644 --- a/tests/ui/generic-associated-types/bugs/issue-88526.stderr +++ b/tests/ui/generic-associated-types/bugs/issue-88526.stderr @@ -4,6 +4,20 @@ error[E0207]: the type parameter `I` is not constrained by the impl trait, self LL | impl<'q, Q, I, F> A for TestB | ^ unconstrained type parameter -error: aborting due to 1 previous error +error[E0309]: the parameter type `F` may not live long enough + --> $DIR/issue-88526.rs:16:18 + | +LL | type I<'a> = &'a F; + | -- ^^^^^ ...so that the reference type `&'a F` does not outlive the data it points at + | | + | the parameter type `F` must be valid for the lifetime `'a` as defined here... + | +help: consider adding an explicit lifetime bound + | +LL | type I<'a> = &'a F where F: 'a; + | +++++++++++ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0207`. +Some errors have detailed explanations: E0207, E0309. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr b/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr index 8589d008a6b89..65854ed71587b 100644 --- a/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr +++ b/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr @@ -1,3 +1,23 @@ +error[E0049]: method `foo` has 1 type parameter but its trait declaration has 0 type parameters + --> $DIR/gat-trait-path-missing-lifetime.rs:8:10 + | +LL | fn foo<'a>(t : Self::Y<'a>) -> Self::Y<'a> { t } + | -- expected 0 type parameters +... +LL | fn foo<'a, T1: X>(t : T1) -> T1::Y<'a> { + | ^^ ^^ + | | + | found 1 type parameter + +error[E0046]: not all trait items implemented, missing: `Y` + --> $DIR/gat-trait-path-missing-lifetime.rs:7:1 + | +LL | type Y<'a>; + | ---------- `Y` from trait +... +LL | impl X for T { + | ^^^^^^^^^^^^^^^ missing `Y` in implementation + error[E0107]: missing generics for associated type `X::Y` --> $DIR/gat-trait-path-missing-lifetime.rs:8:20 | @@ -31,26 +51,6 @@ help: add missing lifetime argument LL | fn foo<'a, T1: X = T1>>(t : T1) -> T1::Y<'a> { | ++++ -error[E0049]: method `foo` has 1 type parameter but its trait declaration has 0 type parameters - --> $DIR/gat-trait-path-missing-lifetime.rs:8:10 - | -LL | fn foo<'a>(t : Self::Y<'a>) -> Self::Y<'a> { t } - | -- expected 0 type parameters -... -LL | fn foo<'a, T1: X>(t : T1) -> T1::Y<'a> { - | ^^ ^^ - | | - | found 1 type parameter - -error[E0046]: not all trait items implemented, missing: `Y` - --> $DIR/gat-trait-path-missing-lifetime.rs:7:1 - | -LL | type Y<'a>; - | ---------- `Y` from trait -... -LL | impl X for T { - | ^^^^^^^^^^^^^^^ missing `Y` in implementation - error: lifetime may not live long enough --> $DIR/gat-trait-path-missing-lifetime.rs:8:3 | diff --git a/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr b/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr index bad2ae9c9183c..fcd3e7d9aace8 100644 --- a/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr +++ b/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr @@ -53,22 +53,6 @@ note: associated type defined here, with 0 generic parameters LL | type Y<'a>; | ^ -error[E0107]: associated type takes 1 lifetime argument but 0 lifetime arguments were supplied - --> $DIR/gat-trait-path-parenthesised-args.rs:18:27 - | -LL | fn bar<'a>(arg: Box>) {} - | ^ expected 1 lifetime argument - | -note: associated type defined here, with 1 lifetime parameter: `'a` - --> $DIR/gat-trait-path-parenthesised-args.rs:2:8 - | -LL | type Y<'a>; - | ^ -- -help: add missing lifetime argument - | -LL | fn bar<'a>(arg: Box>) {} - | ++ - error[E0107]: associated type takes 1 lifetime argument but 0 lifetime arguments were supplied --> $DIR/gat-trait-path-parenthesised-args.rs:5:27 | @@ -154,6 +138,22 @@ LL | type Y<'a>; | ^ ...because it contains the generic associated type `Y` = help: consider moving `Y` to another trait +error[E0107]: associated type takes 1 lifetime argument but 0 lifetime arguments were supplied + --> $DIR/gat-trait-path-parenthesised-args.rs:18:27 + | +LL | fn bar<'a>(arg: Box>) {} + | ^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/gat-trait-path-parenthesised-args.rs:2:8 + | +LL | type Y<'a>; + | ^ -- +help: add missing lifetime argument + | +LL | fn bar<'a>(arg: Box>) {} + | ++ + error[E0107]: associated type takes 1 lifetime argument but 0 lifetime arguments were supplied --> $DIR/gat-trait-path-parenthesised-args.rs:18:27 | diff --git a/tests/ui/generic-associated-types/issue-80433.stderr b/tests/ui/generic-associated-types/issue-80433.stderr index 2bbf87ff1ff4f..1ca080f5df26b 100644 --- a/tests/ui/generic-associated-types/issue-80433.stderr +++ b/tests/ui/generic-associated-types/issue-80433.stderr @@ -1,3 +1,14 @@ +error: missing required bound on `Output` + --> $DIR/issue-80433.rs:7:5 + | +LL | type Output<'a>; + | ^^^^^^^^^^^^^^^- + | | + | help: add the required where clause: `where Self: 'a` + | + = note: this bound is currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 for more information + error[E0107]: missing generics for associated type `TestMut::Output` --> $DIR/issue-80433.rs:21:47 | @@ -14,17 +25,6 @@ help: add missing lifetime argument LL | fn test_simpler<'a>(dst: &'a mut impl TestMut = &'a mut f32>) | ++++ -error: missing required bound on `Output` - --> $DIR/issue-80433.rs:7:5 - | -LL | type Output<'a>; - | ^^^^^^^^^^^^^^^- - | | - | help: add the required where clause: `where Self: 'a` - | - = note: this bound is currently required to ensure that impls have maximum flexibility - = note: we are soliciting feedback, see issue #87479 for more information - error[E0499]: cannot borrow `*dst` as mutable more than once at a time --> $DIR/issue-80433.rs:25:10 | diff --git a/tests/ui/generic-associated-types/missing_lifetime_args.stderr b/tests/ui/generic-associated-types/missing_lifetime_args.stderr index 5980c60c51c6a..18c2d8c7eedf2 100644 --- a/tests/ui/generic-associated-types/missing_lifetime_args.stderr +++ b/tests/ui/generic-associated-types/missing_lifetime_args.stderr @@ -14,42 +14,6 @@ help: add missing lifetime arguments LL | fn foo<'c, 'd>(_arg: Box = (&'c u32, &'d u32)>>) {} | ++++++++ -error[E0107]: struct takes 3 lifetime arguments but 2 lifetime arguments were supplied - --> $DIR/missing_lifetime_args.rs:17:26 - | -LL | fn bar<'a, 'b, 'c>(_arg: Foo<'a, 'b>) {} - | ^^^ -- -- supplied 2 lifetime arguments - | | - | expected 3 lifetime arguments - | -note: struct defined here, with 3 lifetime parameters: `'a`, `'b`, `'c` - --> $DIR/missing_lifetime_args.rs:5:8 - | -LL | struct Foo<'a, 'b, 'c> { - | ^^^ -- -- -- -help: add missing lifetime argument - | -LL | fn bar<'a, 'b, 'c>(_arg: Foo<'a, 'b, 'a>) {} - | ++++ - -error[E0107]: struct takes 3 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/missing_lifetime_args.rs:20:16 - | -LL | fn f<'a>(_arg: Foo<'a>) {} - | ^^^ -- supplied 1 lifetime argument - | | - | expected 3 lifetime arguments - | -note: struct defined here, with 3 lifetime parameters: `'a`, `'b`, `'c` - --> $DIR/missing_lifetime_args.rs:5:8 - | -LL | struct Foo<'a, 'b, 'c> { - | ^^^ -- -- -- -help: add missing lifetime arguments - | -LL | fn f<'a>(_arg: Foo<'a, 'a, 'a>) {} - | ++++++++ - error[E0107]: missing generics for associated type `X::Y` --> $DIR/missing_lifetime_args.rs:11:32 | @@ -99,6 +63,42 @@ LL | type Y<'a, 'b>; | ^ ...because it contains the generic associated type `Y` = help: consider moving `Y` to another trait +error[E0107]: struct takes 3 lifetime arguments but 2 lifetime arguments were supplied + --> $DIR/missing_lifetime_args.rs:17:26 + | +LL | fn bar<'a, 'b, 'c>(_arg: Foo<'a, 'b>) {} + | ^^^ -- -- supplied 2 lifetime arguments + | | + | expected 3 lifetime arguments + | +note: struct defined here, with 3 lifetime parameters: `'a`, `'b`, `'c` + --> $DIR/missing_lifetime_args.rs:5:8 + | +LL | struct Foo<'a, 'b, 'c> { + | ^^^ -- -- -- +help: add missing lifetime argument + | +LL | fn bar<'a, 'b, 'c>(_arg: Foo<'a, 'b, 'a>) {} + | ++++ + +error[E0107]: struct takes 3 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/missing_lifetime_args.rs:20:16 + | +LL | fn f<'a>(_arg: Foo<'a>) {} + | ^^^ -- supplied 1 lifetime argument + | | + | expected 3 lifetime arguments + | +note: struct defined here, with 3 lifetime parameters: `'a`, `'b`, `'c` + --> $DIR/missing_lifetime_args.rs:5:8 + | +LL | struct Foo<'a, 'b, 'c> { + | ^^^ -- -- -- +help: add missing lifetime arguments + | +LL | fn f<'a>(_arg: Foo<'a, 'a, 'a>) {} + | ++++++++ + error: aborting due to 6 previous errors Some errors have detailed explanations: E0038, E0107. diff --git a/tests/ui/generic-associated-types/unknown-lifetime-ice-119827.rs b/tests/ui/generic-associated-types/unknown-lifetime-ice-119827.rs index cd3acf9bc41b1..f74d7cf281116 100644 --- a/tests/ui/generic-associated-types/unknown-lifetime-ice-119827.rs +++ b/tests/ui/generic-associated-types/unknown-lifetime-ice-119827.rs @@ -1,16 +1,10 @@ trait Foo { + //~^ ERROR cycle detected type Context<'c> where Self: 'c; } impl Foo for Box {} -//~^ ERROR `Foo` cannot be made into an object -//~| ERROR `Foo` cannot be made into an object -//~| ERROR cycle detected -//~| ERROR cycle detected -//~| ERROR cycle detected -//~| ERROR the trait bound `Box<(dyn Foo + 'static)>: Foo` is not satisfied -//~| ERROR not all trait items implemented fn main() {} diff --git a/tests/ui/generic-associated-types/unknown-lifetime-ice-119827.stderr b/tests/ui/generic-associated-types/unknown-lifetime-ice-119827.stderr index 8e6b69f7461d9..29b226f16cb28 100644 --- a/tests/ui/generic-associated-types/unknown-lifetime-ice-119827.stderr +++ b/tests/ui/generic-associated-types/unknown-lifetime-ice-119827.stderr @@ -1,119 +1,22 @@ -error[E0391]: cycle detected when computing type of `` - --> $DIR/unknown-lifetime-ice-119827.rs:7:1 - | -LL | impl Foo for Box {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: ...which requires finding trait impls of `Foo`... +error[E0391]: cycle detected when finding trait impls of `Foo` --> $DIR/unknown-lifetime-ice-119827.rs:1:1 | LL | trait Foo { | ^^^^^^^^^ - = note: ...which again requires computing type of ``, completing the cycle -note: cycle used when collecting item types in top-level module - --> $DIR/unknown-lifetime-ice-119827.rs:1:1 | -LL | / trait Foo { -LL | | type Context<'c> -LL | | where -LL | | Self: 'c; -... | -LL | | -LL | | fn main() {} - | |____________^ - = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information - -error[E0391]: cycle detected when computing type of `` - --> $DIR/unknown-lifetime-ice-119827.rs:7:1 +note: ...which requires computing type of ``... + --> $DIR/unknown-lifetime-ice-119827.rs:8:1 | LL | impl Foo for Box {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: ...which immediately requires computing type of `` again -note: cycle used when collecting item types in top-level module + = note: ...which again requires finding trait impls of `Foo`, completing the cycle +note: cycle used when checking that `Foo` is well-formed --> $DIR/unknown-lifetime-ice-119827.rs:1:1 | -LL | / trait Foo { -LL | | type Context<'c> -LL | | where -LL | | Self: 'c; -... | -LL | | -LL | | fn main() {} - | |____________^ - = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information - -error[E0391]: cycle detected when computing type of `` - --> $DIR/unknown-lifetime-ice-119827.rs:7:1 - | -LL | impl Foo for Box {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: ...which immediately requires computing type of `` again -note: cycle used when collecting item types in top-level module - --> $DIR/unknown-lifetime-ice-119827.rs:1:1 - | -LL | / trait Foo { -LL | | type Context<'c> -LL | | where -LL | | Self: 'c; -... | -LL | | -LL | | fn main() {} - | |____________^ - = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/unknown-lifetime-ice-119827.rs:7:22 - | -LL | impl Foo for Box {} - | ^^^ `Foo` cannot be made into an object - | -note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/unknown-lifetime-ice-119827.rs:2:10 - | -LL | trait Foo { - | --- this trait cannot be made into an object... -LL | type Context<'c> - | ^^^^^^^ ...because it contains the generic associated type `Context` - = help: consider moving `Context` to another trait - = help: only type `{type error}` implements the trait, consider using it directly instead - -error[E0277]: the trait bound `Box<(dyn Foo + 'static)>: Foo` is not satisfied - --> $DIR/unknown-lifetime-ice-119827.rs:7:14 - | -LL | impl Foo for Box {} - | ^^^^^^^^^^^^ the trait `Foo` is not implemented for `Box<(dyn Foo + 'static)>` - | - = help: the trait `Foo` is implemented for `Box<(dyn Foo + 'static)>` - -error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/unknown-lifetime-ice-119827.rs:7:14 - | -LL | impl Foo for Box {} - | ^^^^^^^^^^^^ `Foo` cannot be made into an object - | -note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/unknown-lifetime-ice-119827.rs:2:10 - | LL | trait Foo { - | --- this trait cannot be made into an object... -LL | type Context<'c> - | ^^^^^^^ ...because it contains the generic associated type `Context` - = help: consider moving `Context` to another trait - = help: only type `std::boxed::Box<(dyn Foo + 'static)>` implements the trait, consider using it directly instead - -error[E0046]: not all trait items implemented, missing: `Context` - --> $DIR/unknown-lifetime-ice-119827.rs:7:1 - | -LL | type Context<'c> - | ---------------- `Context` from trait -... -LL | impl Foo for Box {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ missing `Context` in implementation + | ^^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to 7 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0038, E0046, E0277, E0391. -For more information about an error, try `rustc --explain E0038`. +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs index 33b99259dfec9..9d067229b6de8 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs @@ -1,6 +1,7 @@ // Test various non-exhaustive matches for `X..`, `..=X` and `..X` ranges. #![feature(exclusive_range_pattern)] +#![allow(non_contiguous_range_endpoints)] fn main() {} diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr b/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr index 1e68235303b2e..6b20a820b7302 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: `_` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:14:8 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:15:8 | LL | m!(0f32, f32::NEG_INFINITY..); | ^^^^ pattern `_` not covered @@ -11,7 +11,7 @@ LL | match $s { $($t)+ => {}, _ => todo!() } | ++++++++++++++ error[E0004]: non-exhaustive patterns: `_` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:15:8 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:16:8 | LL | m!(0f32, ..f32::INFINITY); | ^^^^ pattern `_` not covered @@ -23,7 +23,7 @@ LL | match $s { $($t)+ => {}, _ => todo!() } | ++++++++++++++ error[E0004]: non-exhaustive patterns: `'\u{10ffff}'` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:24:8 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:25:8 | LL | m!('a', ..core::char::MAX); | ^^^ pattern `'\u{10ffff}'` not covered @@ -35,7 +35,7 @@ LL | match $s { $($t)+ => {}, '\u{10ffff}' => todo!() } | +++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `'\u{10fffe}'..='\u{10ffff}'` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:25:8 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:26:8 | LL | m!('a', ..ALMOST_MAX); | ^^^ pattern `'\u{10fffe}'..='\u{10ffff}'` not covered @@ -47,7 +47,7 @@ LL | match $s { $($t)+ => {}, '\u{10fffe}'..='\u{10ffff}' => todo!() } | ++++++++++++++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `'\0'` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:26:8 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:27:8 | LL | m!('a', ALMOST_MIN..); | ^^^ pattern `'\0'` not covered @@ -59,7 +59,7 @@ LL | match $s { $($t)+ => {}, '\0' => todo!() } | +++++++++++++++++ error[E0004]: non-exhaustive patterns: `'\u{10ffff}'` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:27:8 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:28:8 | LL | m!('a', ..=ALMOST_MAX); | ^^^ pattern `'\u{10ffff}'` not covered @@ -71,7 +71,7 @@ LL | match $s { $($t)+ => {}, '\u{10ffff}' => todo!() } | +++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `'b'` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:28:8 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:29:8 | LL | m!('a', ..=VAL | VAL_2..); | ^^^ pattern `'b'` not covered @@ -83,7 +83,7 @@ LL | match $s { $($t)+ => {}, 'b' => todo!() } | ++++++++++++++++ error[E0004]: non-exhaustive patterns: `'b'` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:29:8 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:30:8 | LL | m!('a', ..VAL_1 | VAL_2..); | ^^^ pattern `'b'` not covered @@ -95,7 +95,7 @@ LL | match $s { $($t)+ => {}, 'b' => todo!() } | ++++++++++++++++ error[E0004]: non-exhaustive patterns: `u8::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:39:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:40:12 | LL | m!(0, ..u8::MAX); | ^ pattern `u8::MAX` not covered @@ -107,7 +107,7 @@ LL | match $s { $($t)+ => {}, u8::MAX => todo!() } | ++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `254_u8..=u8::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:40:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:41:12 | LL | m!(0, ..ALMOST_MAX); | ^ pattern `254_u8..=u8::MAX` not covered @@ -119,7 +119,7 @@ LL | match $s { $($t)+ => {}, 254_u8..=u8::MAX => todo!() } | +++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `0_u8` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:41:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:42:12 | LL | m!(0, ALMOST_MIN..); | ^ pattern `0_u8` not covered @@ -131,7 +131,7 @@ LL | match $s { $($t)+ => {}, 0_u8 => todo!() } | +++++++++++++++++ error[E0004]: non-exhaustive patterns: `u8::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:42:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:43:12 | LL | m!(0, ..=ALMOST_MAX); | ^ pattern `u8::MAX` not covered @@ -143,7 +143,7 @@ LL | match $s { $($t)+ => {}, u8::MAX => todo!() } | ++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_u8` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:43:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:44:12 | LL | m!(0, ..=VAL | VAL_2..); | ^ pattern `43_u8` not covered @@ -155,7 +155,7 @@ LL | match $s { $($t)+ => {}, 43_u8 => todo!() } | ++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_u8` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:44:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:45:12 | LL | m!(0, ..VAL_1 | VAL_2..); | ^ pattern `43_u8` not covered @@ -167,7 +167,7 @@ LL | match $s { $($t)+ => {}, 43_u8 => todo!() } | ++++++++++++++++++ error[E0004]: non-exhaustive patterns: `u16::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:52:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:53:12 | LL | m!(0, ..u16::MAX); | ^ pattern `u16::MAX` not covered @@ -179,7 +179,7 @@ LL | match $s { $($t)+ => {}, u16::MAX => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `65534_u16..=u16::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:53:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:54:12 | LL | m!(0, ..ALMOST_MAX); | ^ pattern `65534_u16..=u16::MAX` not covered @@ -191,7 +191,7 @@ LL | match $s { $($t)+ => {}, 65534_u16..=u16::MAX => todo!() } | +++++++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `0_u16` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:54:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:55:12 | LL | m!(0, ALMOST_MIN..); | ^ pattern `0_u16` not covered @@ -203,7 +203,7 @@ LL | match $s { $($t)+ => {}, 0_u16 => todo!() } | ++++++++++++++++++ error[E0004]: non-exhaustive patterns: `u16::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:55:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:56:12 | LL | m!(0, ..=ALMOST_MAX); | ^ pattern `u16::MAX` not covered @@ -215,7 +215,7 @@ LL | match $s { $($t)+ => {}, u16::MAX => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_u16` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:56:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:57:12 | LL | m!(0, ..=VAL | VAL_2..); | ^ pattern `43_u16` not covered @@ -227,7 +227,7 @@ LL | match $s { $($t)+ => {}, 43_u16 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_u16` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:57:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:58:12 | LL | m!(0, ..VAL_1 | VAL_2..); | ^ pattern `43_u16` not covered @@ -239,7 +239,7 @@ LL | match $s { $($t)+ => {}, 43_u16 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `u32::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:65:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:66:12 | LL | m!(0, ..u32::MAX); | ^ pattern `u32::MAX` not covered @@ -251,7 +251,7 @@ LL | match $s { $($t)+ => {}, u32::MAX => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `4294967294_u32..=u32::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:66:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:67:12 | LL | m!(0, ..ALMOST_MAX); | ^ pattern `4294967294_u32..=u32::MAX` not covered @@ -263,7 +263,7 @@ LL | match $s { $($t)+ => {}, 4294967294_u32..=u32::MAX => todo!() } | ++++++++++++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `0_u32` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:67:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:68:12 | LL | m!(0, ALMOST_MIN..); | ^ pattern `0_u32` not covered @@ -275,7 +275,7 @@ LL | match $s { $($t)+ => {}, 0_u32 => todo!() } | ++++++++++++++++++ error[E0004]: non-exhaustive patterns: `u32::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:68:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:69:12 | LL | m!(0, ..=ALMOST_MAX); | ^ pattern `u32::MAX` not covered @@ -287,7 +287,7 @@ LL | match $s { $($t)+ => {}, u32::MAX => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_u32` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:69:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:70:12 | LL | m!(0, ..=VAL | VAL_2..); | ^ pattern `43_u32` not covered @@ -299,7 +299,7 @@ LL | match $s { $($t)+ => {}, 43_u32 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_u32` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:70:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:71:12 | LL | m!(0, ..VAL_1 | VAL_2..); | ^ pattern `43_u32` not covered @@ -311,7 +311,7 @@ LL | match $s { $($t)+ => {}, 43_u32 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `u64::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:78:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:79:12 | LL | m!(0, ..u64::MAX); | ^ pattern `u64::MAX` not covered @@ -323,7 +323,7 @@ LL | match $s { $($t)+ => {}, u64::MAX => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `18446744073709551614_u64..=u64::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:79:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:80:12 | LL | m!(0, ..ALMOST_MAX); | ^ pattern `18446744073709551614_u64..=u64::MAX` not covered @@ -335,7 +335,7 @@ LL | match $s { $($t)+ => {}, 18446744073709551614_u64..=u64::MAX => tod | ++++++++++++++++++++++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `0_u64` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:80:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:81:12 | LL | m!(0, ALMOST_MIN..); | ^ pattern `0_u64` not covered @@ -347,7 +347,7 @@ LL | match $s { $($t)+ => {}, 0_u64 => todo!() } | ++++++++++++++++++ error[E0004]: non-exhaustive patterns: `u64::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:81:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:82:12 | LL | m!(0, ..=ALMOST_MAX); | ^ pattern `u64::MAX` not covered @@ -359,7 +359,7 @@ LL | match $s { $($t)+ => {}, u64::MAX => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_u64` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:82:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:83:12 | LL | m!(0, ..=VAL | VAL_2..); | ^ pattern `43_u64` not covered @@ -371,7 +371,7 @@ LL | match $s { $($t)+ => {}, 43_u64 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_u64` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:83:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:84:12 | LL | m!(0, ..VAL_1 | VAL_2..); | ^ pattern `43_u64` not covered @@ -383,7 +383,7 @@ LL | match $s { $($t)+ => {}, 43_u64 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `u128::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:91:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:92:12 | LL | m!(0, ..u128::MAX); | ^ pattern `u128::MAX` not covered @@ -395,7 +395,7 @@ LL | match $s { $($t)+ => {}, u128::MAX => todo!() } | ++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `340282366920938463463374607431768211454_u128..=u128::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:92:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:93:12 | LL | m!(0, ..ALMOST_MAX); | ^ pattern `340282366920938463463374607431768211454_u128..=u128::MAX` not covered @@ -407,7 +407,7 @@ LL | match $s { $($t)+ => {}, 340282366920938463463374607431768211454_u1 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `0_u128` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:93:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:94:12 | LL | m!(0, ALMOST_MIN..); | ^ pattern `0_u128` not covered @@ -419,7 +419,7 @@ LL | match $s { $($t)+ => {}, 0_u128 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `u128::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:94:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:95:12 | LL | m!(0, ..=ALMOST_MAX); | ^ pattern `u128::MAX` not covered @@ -431,7 +431,7 @@ LL | match $s { $($t)+ => {}, u128::MAX => todo!() } | ++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_u128` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:95:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:96:12 | LL | m!(0, ..=VAL | VAL_2..); | ^ pattern `43_u128` not covered @@ -443,7 +443,7 @@ LL | match $s { $($t)+ => {}, 43_u128 => todo!() } | ++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_u128` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:96:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:97:12 | LL | m!(0, ..VAL_1 | VAL_2..); | ^ pattern `43_u128` not covered @@ -455,7 +455,7 @@ LL | match $s { $($t)+ => {}, 43_u128 => todo!() } | ++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i8::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:107:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:108:12 | LL | m!(0, ..i8::MAX); | ^ pattern `i8::MAX` not covered @@ -467,7 +467,7 @@ LL | match $s { $($t)+ => {}, i8::MAX => todo!() } | ++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `126_i8..=i8::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:108:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:109:12 | LL | m!(0, ..ALMOST_MAX); | ^ pattern `126_i8..=i8::MAX` not covered @@ -479,7 +479,7 @@ LL | match $s { $($t)+ => {}, 126_i8..=i8::MAX => todo!() } | +++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i8::MIN` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:109:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:110:12 | LL | m!(0, ALMOST_MIN..); | ^ pattern `i8::MIN` not covered @@ -491,7 +491,7 @@ LL | match $s { $($t)+ => {}, i8::MIN => todo!() } | ++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i8::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:110:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:111:12 | LL | m!(0, ..=ALMOST_MAX); | ^ pattern `i8::MAX` not covered @@ -503,7 +503,7 @@ LL | match $s { $($t)+ => {}, i8::MAX => todo!() } | ++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_i8` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:111:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:112:12 | LL | m!(0, ..=VAL | VAL_2..); | ^ pattern `43_i8` not covered @@ -515,7 +515,7 @@ LL | match $s { $($t)+ => {}, 43_i8 => todo!() } | ++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_i8` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:112:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:113:12 | LL | m!(0, ..VAL_1 | VAL_2..); | ^ pattern `43_i8` not covered @@ -527,7 +527,7 @@ LL | match $s { $($t)+ => {}, 43_i8 => todo!() } | ++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i16::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:120:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:121:12 | LL | m!(0, ..i16::MAX); | ^ pattern `i16::MAX` not covered @@ -539,7 +539,7 @@ LL | match $s { $($t)+ => {}, i16::MAX => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `32766_i16..=i16::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:121:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:122:12 | LL | m!(0, ..ALMOST_MAX); | ^ pattern `32766_i16..=i16::MAX` not covered @@ -551,7 +551,7 @@ LL | match $s { $($t)+ => {}, 32766_i16..=i16::MAX => todo!() } | +++++++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i16::MIN` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:122:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:123:12 | LL | m!(0, ALMOST_MIN..); | ^ pattern `i16::MIN` not covered @@ -563,7 +563,7 @@ LL | match $s { $($t)+ => {}, i16::MIN => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i16::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:123:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:124:12 | LL | m!(0, ..=ALMOST_MAX); | ^ pattern `i16::MAX` not covered @@ -575,7 +575,7 @@ LL | match $s { $($t)+ => {}, i16::MAX => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_i16` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:124:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:125:12 | LL | m!(0, ..=VAL | VAL_2..); | ^ pattern `43_i16` not covered @@ -587,7 +587,7 @@ LL | match $s { $($t)+ => {}, 43_i16 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_i16` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:125:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:126:12 | LL | m!(0, ..VAL_1 | VAL_2..); | ^ pattern `43_i16` not covered @@ -599,7 +599,7 @@ LL | match $s { $($t)+ => {}, 43_i16 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i32::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:133:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:134:12 | LL | m!(0, ..i32::MAX); | ^ pattern `i32::MAX` not covered @@ -611,7 +611,7 @@ LL | match $s { $($t)+ => {}, i32::MAX => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `2147483646_i32..=i32::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:134:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:135:12 | LL | m!(0, ..ALMOST_MAX); | ^ pattern `2147483646_i32..=i32::MAX` not covered @@ -623,7 +623,7 @@ LL | match $s { $($t)+ => {}, 2147483646_i32..=i32::MAX => todo!() } | ++++++++++++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i32::MIN` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:135:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:136:12 | LL | m!(0, ALMOST_MIN..); | ^ pattern `i32::MIN` not covered @@ -635,7 +635,7 @@ LL | match $s { $($t)+ => {}, i32::MIN => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i32::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:136:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:137:12 | LL | m!(0, ..=ALMOST_MAX); | ^ pattern `i32::MAX` not covered @@ -647,7 +647,7 @@ LL | match $s { $($t)+ => {}, i32::MAX => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_i32` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:137:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:138:12 | LL | m!(0, ..=VAL | VAL_2..); | ^ pattern `43_i32` not covered @@ -659,7 +659,7 @@ LL | match $s { $($t)+ => {}, 43_i32 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_i32` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:138:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:139:12 | LL | m!(0, ..VAL_1 | VAL_2..); | ^ pattern `43_i32` not covered @@ -671,7 +671,7 @@ LL | match $s { $($t)+ => {}, 43_i32 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i64::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:146:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:147:12 | LL | m!(0, ..i64::MAX); | ^ pattern `i64::MAX` not covered @@ -683,7 +683,7 @@ LL | match $s { $($t)+ => {}, i64::MAX => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `9223372036854775806_i64..=i64::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:147:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:148:12 | LL | m!(0, ..ALMOST_MAX); | ^ pattern `9223372036854775806_i64..=i64::MAX` not covered @@ -695,7 +695,7 @@ LL | match $s { $($t)+ => {}, 9223372036854775806_i64..=i64::MAX => todo | +++++++++++++++++++++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i64::MIN` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:148:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:149:12 | LL | m!(0, ALMOST_MIN..); | ^ pattern `i64::MIN` not covered @@ -707,7 +707,7 @@ LL | match $s { $($t)+ => {}, i64::MIN => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i64::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:149:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:150:12 | LL | m!(0, ..=ALMOST_MAX); | ^ pattern `i64::MAX` not covered @@ -719,7 +719,7 @@ LL | match $s { $($t)+ => {}, i64::MAX => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_i64` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:150:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:151:12 | LL | m!(0, ..=VAL | VAL_2..); | ^ pattern `43_i64` not covered @@ -731,7 +731,7 @@ LL | match $s { $($t)+ => {}, 43_i64 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_i64` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:151:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:152:12 | LL | m!(0, ..VAL_1 | VAL_2..); | ^ pattern `43_i64` not covered @@ -743,7 +743,7 @@ LL | match $s { $($t)+ => {}, 43_i64 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i128::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:159:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:160:12 | LL | m!(0, ..i128::MAX); | ^ pattern `i128::MAX` not covered @@ -755,7 +755,7 @@ LL | match $s { $($t)+ => {}, i128::MAX => todo!() } | ++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `170141183460469231731687303715884105726_i128..=i128::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:160:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:161:12 | LL | m!(0, ..ALMOST_MAX); | ^ pattern `170141183460469231731687303715884105726_i128..=i128::MAX` not covered @@ -767,7 +767,7 @@ LL | match $s { $($t)+ => {}, 170141183460469231731687303715884105726_i1 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i128::MIN` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:161:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:162:12 | LL | m!(0, ALMOST_MIN..); | ^ pattern `i128::MIN` not covered @@ -779,7 +779,7 @@ LL | match $s { $($t)+ => {}, i128::MIN => todo!() } | ++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i128::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:162:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:163:12 | LL | m!(0, ..=ALMOST_MAX); | ^ pattern `i128::MAX` not covered @@ -791,7 +791,7 @@ LL | match $s { $($t)+ => {}, i128::MAX => todo!() } | ++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_i128` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:163:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:164:12 | LL | m!(0, ..=VAL | VAL_2..); | ^ pattern `43_i128` not covered @@ -803,7 +803,7 @@ LL | match $s { $($t)+ => {}, 43_i128 => todo!() } | ++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_i128` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:164:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:165:12 | LL | m!(0, ..VAL_1 | VAL_2..); | ^ pattern `43_i128` not covered diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions0.rs b/tests/ui/half-open-range-patterns/range_pat_interactions0.rs index 7a82f9ce89a86..53b6b89ed1662 100644 --- a/tests/ui/half-open-range-patterns/range_pat_interactions0.rs +++ b/tests/ui/half-open-range-patterns/range_pat_interactions0.rs @@ -1,4 +1,5 @@ //@ run-pass +#![allow(non_contiguous_range_endpoints)] #![feature(exclusive_range_pattern)] #![feature(inline_const_pat)] diff --git a/tests/ui/hashmap/hashmap-memory.rs b/tests/ui/hashmap/hashmap-memory.rs index 0b1e09f53446c..6db5d2e7bef35 100644 --- a/tests/ui/hashmap/hashmap-memory.rs +++ b/tests/ui/hashmap/hashmap-memory.rs @@ -4,7 +4,7 @@ #![allow(non_camel_case_types)] #![allow(dead_code)] #![allow(unused_mut)] -//@ ignore-emscripten No support for threads +//@ needs-threads /** A somewhat reduced test case to expose some Valgrind issues. diff --git a/tests/ui/impl-trait/impl-fn-hrtb-bounds.rs b/tests/ui/impl-trait/impl-fn-hrtb-bounds.rs index 06c3d9ad434e4..a9ea657f10e2c 100644 --- a/tests/ui/impl-trait/impl-fn-hrtb-bounds.rs +++ b/tests/ui/impl-trait/impl-fn-hrtb-bounds.rs @@ -2,19 +2,19 @@ use std::fmt::Debug; fn a() -> impl Fn(&u8) -> (impl Debug + '_) { - //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` |x| x //~^ ERROR lifetime may not live long enough } fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) { - //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` |x| x //~^ ERROR lifetime may not live long enough } fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) { - //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` |x| x //~^ ERROR lifetime may not live long enough } diff --git a/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr b/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr index ebab994049314..bdb099619b76f 100644 --- a/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr +++ b/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr @@ -10,7 +10,7 @@ help: consider using the `'static` lifetime, but this is uncommon unless you're LL | fn d() -> impl Fn() -> (impl Debug + 'static) { | ~~~~~~~ -error: higher kinded lifetime bounds on nested opaque types are not supported yet +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` --> $DIR/impl-fn-hrtb-bounds.rs:4:41 | LL | fn a() -> impl Fn(&u8) -> (impl Debug + '_) { @@ -22,7 +22,16 @@ note: lifetime declared here LL | fn a() -> impl Fn(&u8) -> (impl Debug + '_) { | ^ -error: higher kinded lifetime bounds on nested opaque types are not supported yet +error: lifetime may not live long enough + --> $DIR/impl-fn-hrtb-bounds.rs:6:9 + | +LL | |x| x + | -- ^ returning this value requires that `'1` must outlive `'2` + | || + | |return type of closure is impl Debug + '2 + | has type `&'1 u8` + +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` --> $DIR/impl-fn-hrtb-bounds.rs:10:52 | LL | fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) { @@ -34,7 +43,16 @@ note: lifetime declared here LL | fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) { | ^^ -error: higher kinded lifetime bounds on nested opaque types are not supported yet +error: lifetime may not live long enough + --> $DIR/impl-fn-hrtb-bounds.rs:12:9 + | +LL | |x| x + | -- ^ returning this value requires that `'1` must outlive `'2` + | || + | |return type of closure is impl Debug + '2 + | has type `&'1 u8` + +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` --> $DIR/impl-fn-hrtb-bounds.rs:16:52 | LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) { @@ -46,24 +64,6 @@ note: lifetime declared here LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) { | ^^ -error: lifetime may not live long enough - --> $DIR/impl-fn-hrtb-bounds.rs:6:9 - | -LL | |x| x - | -- ^ returning this value requires that `'1` must outlive `'2` - | || - | |return type of closure is impl Debug + '2 - | has type `&'1 u8` - -error: lifetime may not live long enough - --> $DIR/impl-fn-hrtb-bounds.rs:12:9 - | -LL | |x| x - | -- ^ returning this value requires that `'1` must outlive `'2` - | || - | |return type of closure is impl Debug + '2 - | has type `&'1 u8` - error: lifetime may not live long enough --> $DIR/impl-fn-hrtb-bounds.rs:18:9 | @@ -75,4 +75,5 @@ LL | |x| x error: aborting due to 7 previous errors -For more information about this error, try `rustc --explain E0106`. +Some errors have detailed explanations: E0106, E0657. +For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/impl-trait/impl-fn-parsing-ambiguities.rs b/tests/ui/impl-trait/impl-fn-parsing-ambiguities.rs index a4a1f1dcee120..ef9d87335097f 100644 --- a/tests/ui/impl-trait/impl-fn-parsing-ambiguities.rs +++ b/tests/ui/impl-trait/impl-fn-parsing-ambiguities.rs @@ -3,7 +3,7 @@ use std::fmt::Debug; fn a() -> impl Fn(&u8) -> impl Debug + '_ { //~^ ERROR ambiguous `+` in a type - //~| ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + //~| ERROR cannot capture higher-ranked lifetime from outer `impl Trait` |x| x //~^ ERROR lifetime may not live long enough } diff --git a/tests/ui/impl-trait/impl-fn-parsing-ambiguities.stderr b/tests/ui/impl-trait/impl-fn-parsing-ambiguities.stderr index e18e89700b4e9..3881b37a0cbf4 100644 --- a/tests/ui/impl-trait/impl-fn-parsing-ambiguities.stderr +++ b/tests/ui/impl-trait/impl-fn-parsing-ambiguities.stderr @@ -10,7 +10,7 @@ error: ambiguous `+` in a type LL | fn b() -> impl Fn() -> impl Debug + Send { | ^^^^^^^^^^^^^^^^^ help: use parentheses to disambiguate: `(impl Debug + Send)` -error: higher kinded lifetime bounds on nested opaque types are not supported yet +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` --> $DIR/impl-fn-parsing-ambiguities.rs:4:40 | LL | fn a() -> impl Fn(&u8) -> impl Debug + '_ { @@ -33,3 +33,4 @@ LL | |x| x error: aborting due to 4 previous errors +For more information about this error, try `rustc --explain E0657`. diff --git a/tests/ui/impl-trait/implicit-capture-late.stderr b/tests/ui/impl-trait/implicit-capture-late.stderr index 2fb5ebb65418c..080750f849767 100644 --- a/tests/ui/impl-trait/implicit-capture-late.stderr +++ b/tests/ui/impl-trait/implicit-capture-late.stderr @@ -1,4 +1,10 @@ -error[E0657]: `impl Trait` can only capture lifetimes bound at the fn or impl level +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from `dyn` type + --> $DIR/implicit-capture-late.rs:10:55 + | +LL | fn foo(x: Vec) -> Box Deref> { + | ^^^^^^^^^^^ `impl Trait` implicitly captures all lifetimes in scope + | +note: lifetime declared here --> $DIR/implicit-capture-late.rs:10:36 | LL | fn foo(x: Vec) -> Box Deref> { diff --git a/tests/ui/impl-trait/in-trait/opaque-and-lifetime-mismatch.rs b/tests/ui/impl-trait/in-trait/opaque-and-lifetime-mismatch.rs new file mode 100644 index 0000000000000..6f0dbd752b0c2 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/opaque-and-lifetime-mismatch.rs @@ -0,0 +1,18 @@ +struct Wrapper<'rom>(T); +//~^ ERROR cannot find type `T` in this scope + +trait Foo { + fn bar() -> Wrapper; + //~^ ERROR missing lifetime specifier + //~| ERROR struct takes 0 generic arguments but 1 generic argument was supplied +} + +impl Foo for () { + fn bar() -> i32 { + //~^ ERROR method `bar` has an incompatible type for trait + //~| ERROR method `bar` has an incompatible return type for trait + 0 + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/opaque-and-lifetime-mismatch.stderr b/tests/ui/impl-trait/in-trait/opaque-and-lifetime-mismatch.stderr new file mode 100644 index 0000000000000..d30557c8a7bc2 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/opaque-and-lifetime-mismatch.stderr @@ -0,0 +1,67 @@ +error[E0106]: missing lifetime specifier + --> $DIR/opaque-and-lifetime-mismatch.rs:5:24 + | +LL | fn bar() -> Wrapper; + | ^ 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 bar() -> Wrapper<'static, impl Sized>; + | ++++++++ + +error[E0412]: cannot find type `T` in this scope + --> $DIR/opaque-and-lifetime-mismatch.rs:1:22 + | +LL | struct Wrapper<'rom>(T); + | ^ not found in this scope + | +help: you might be missing a type parameter + | +LL | struct Wrapper<'rom, T>(T); + | +++ + +error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/opaque-and-lifetime-mismatch.rs:5:17 + | +LL | fn bar() -> Wrapper; + | ^^^^^^^ ---------- help: remove this generic argument + | | + | expected 0 generic arguments + | +note: struct defined here, with 0 generic parameters + --> $DIR/opaque-and-lifetime-mismatch.rs:1:8 + | +LL | struct Wrapper<'rom>(T); + | ^^^^^^^ + +error[E0053]: method `bar` has an incompatible return type for trait + --> $DIR/opaque-and-lifetime-mismatch.rs:11:17 + | +LL | fn bar() -> i32 { + | ^^^ + | | + | expected `Wrapper<'static>`, found `i32` + | return type in trait + +error[E0053]: method `bar` has an incompatible type for trait + --> $DIR/opaque-and-lifetime-mismatch.rs:11:17 + | +LL | fn bar() -> i32 { + | ^^^ + | | + | expected `Wrapper<'static>`, found `i32` + | help: change the output type to match the trait: `Wrapper<'static>` + | +note: type in trait + --> $DIR/opaque-and-lifetime-mismatch.rs:5:17 + | +LL | fn bar() -> Wrapper; + | ^^^^^^^^^^^^^^^^^^^ + = note: expected signature `fn() -> Wrapper<'static>` + found signature `fn() -> i32` + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0053, E0106, E0107, E0412. +For more information about an error, try `rustc --explain E0053`. diff --git a/tests/ui/impl-trait/in-trait/rpitit-cycle-in-generics-of.rs b/tests/ui/impl-trait/in-trait/rpitit-cycle-in-generics-of.rs new file mode 100644 index 0000000000000..882497d1015d3 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/rpitit-cycle-in-generics-of.rs @@ -0,0 +1,18 @@ +//@ check-pass + +// Check that we don't hit a query cycle when: +// 1. Computing generics_of, which requires... +// 2. Calling resolve_bound_vars, which requires... +// 3. Calling associated_items, which requires... +// 4. Calling associated_type_for_impl_trait_in_trait, which requires... +// 5. Computing generics_of, which cycles. + +pub trait Foo<'a> { + type Assoc; + + fn demo(other: T) -> impl Foo<'a, Assoc = Self::Assoc> + where + T: Foo<'a, Assoc = ()>; +} + +fn main() {} diff --git a/tests/ui/impl-trait/issues/issue-54895.rs b/tests/ui/impl-trait/issues/issue-54895.rs index 8d7a1d56f8320..13c0038ce4340 100644 --- a/tests/ui/impl-trait/issues/issue-54895.rs +++ b/tests/ui/impl-trait/issues/issue-54895.rs @@ -13,7 +13,7 @@ impl<'a> Trait<'a> for X { } fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> { - //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` X(()) } diff --git a/tests/ui/impl-trait/issues/issue-54895.stderr b/tests/ui/impl-trait/issues/issue-54895.stderr index 999ffd5214154..64b425328e3ab 100644 --- a/tests/ui/impl-trait/issues/issue-54895.stderr +++ b/tests/ui/impl-trait/issues/issue-54895.stderr @@ -1,4 +1,4 @@ -error: higher kinded lifetime bounds on nested opaque types are not supported yet +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` --> $DIR/issue-54895.rs:15:53 | LL | fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> { @@ -12,3 +12,4 @@ LL | fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> { error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0657`. diff --git a/tests/ui/impl-trait/issues/issue-67830.rs b/tests/ui/impl-trait/issues/issue-67830.rs index 6dc8935c77708..939eca82a8f6d 100644 --- a/tests/ui/impl-trait/issues/issue-67830.rs +++ b/tests/ui/impl-trait/issues/issue-67830.rs @@ -19,7 +19,7 @@ where struct A; fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> { - //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` Wrap(|a| Some(a).into_iter()) //~^ ERROR implementation of `FnOnce` is not general enough //~| ERROR implementation of `FnOnce` is not general enough diff --git a/tests/ui/impl-trait/issues/issue-67830.stderr b/tests/ui/impl-trait/issues/issue-67830.stderr index 546198b8a1037..ef513a40cf39f 100644 --- a/tests/ui/impl-trait/issues/issue-67830.stderr +++ b/tests/ui/impl-trait/issues/issue-67830.stderr @@ -1,4 +1,4 @@ -error: higher kinded lifetime bounds on nested opaque types are not supported yet +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` --> $DIR/issue-67830.rs:21:62 | LL | fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> { @@ -31,3 +31,4 @@ LL | Wrap(|a| Some(a).into_iter()) error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0657`. diff --git a/tests/ui/impl-trait/issues/issue-83919.stderr b/tests/ui/impl-trait/issues/issue-83919.stderr index 200257235feae..b0bd6ed116bca 100644 --- a/tests/ui/impl-trait/issues/issue-83919.stderr +++ b/tests/ui/impl-trait/issues/issue-83919.stderr @@ -5,7 +5,6 @@ LL | fn get_fut(&self) -> Self::Fut { | ^^^^^^^^^ `{integer}` is not a future | = help: the trait `Future` is not implemented for `{integer}` - = note: {integer} must be a future or must implement `IntoFuture` to be awaited error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/issues/issue-86800.rs b/tests/ui/impl-trait/issues/issue-86800.rs index ae6e198c2ad46..172ab04f58df4 100644 --- a/tests/ui/impl-trait/issues/issue-86800.rs +++ b/tests/ui/impl-trait/issues/issue-86800.rs @@ -1,12 +1,6 @@ #![feature(type_alias_impl_trait)] //@ edition:2021 -//@ compile-flags:-Z treat-err-as-bug=2 -//@ error-pattern: due to `-Z treat-err-as-bug=2 -//@ failure-status:101 -//@ normalize-stderr-test ".*note: .*\n\n" -> "" -//@ normalize-stderr-test "thread 'rustc' panicked.*:\n.*\n" -> "" -//@ rustc-env:RUST_BACKTRACE=0 use std::future::Future; @@ -29,6 +23,7 @@ struct Context { type TransactionResult = Result; type TransactionFuture<'__, O> = impl '__ + Future>; +//~^ ERROR unconstrained opaque type fn execute_transaction_fut<'f, F, O>( f: F, @@ -37,6 +32,7 @@ where F: FnOnce(&mut dyn Transaction) -> TransactionFuture<'_, O> + 'f { f + //~^ ERROR expected generic lifetime parameter, found `'_` } impl Context { @@ -44,6 +40,7 @@ impl Context { &self, f: impl FnOnce(&mut dyn Transaction) -> TransactionFuture<'_, O> ) -> TransactionResult { + //~^ ERROR expected generic lifetime parameter, found `'_` let mut conn = Connection {}; let mut transaction = TestTransaction { conn: &mut conn }; f(&mut transaction).await diff --git a/tests/ui/impl-trait/issues/issue-86800.stderr b/tests/ui/impl-trait/issues/issue-86800.stderr index 7af4846a9593f..146d2f67942be 100644 --- a/tests/ui/impl-trait/issues/issue-86800.stderr +++ b/tests/ui/impl-trait/issues/issue-86800.stderr @@ -1,11 +1,13 @@ error: unconstrained opaque type - --> $DIR/issue-86800.rs:31:34 + --> $DIR/issue-86800.rs:25:34 | LL | type TransactionFuture<'__, O> = impl '__ + Future>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -error: internal compiler error[E0792]: expected generic lifetime parameter, found `'_` - --> $DIR/issue-86800.rs:39:5 + = note: `TransactionFuture` must be used in combination with a concrete type within the same module + +error[E0792]: expected generic lifetime parameter, found `'_` + --> $DIR/issue-86800.rs:34:5 | LL | type TransactionFuture<'__, O> = impl '__ + Future>; | --- this generic parameter must be used with a generic lifetime parameter @@ -13,9 +15,20 @@ LL | type TransactionFuture<'__, O> = impl '__ + Future $DIR/issue-86800.rs:42:5 + | +LL | type TransactionFuture<'__, O> = impl '__ + Future>; + | --- this generic parameter must be used with a generic lifetime parameter +... +LL | / { +LL | | +LL | | let mut conn = Connection {}; +LL | | let mut transaction = TestTransaction { conn: &mut conn }; +LL | | f(&mut transaction).await +LL | | } + | |_____^ + +error: aborting due to 3 previous errors -query stack during panic: -#0 [mir_borrowck] borrow-checking `execute_transaction_fut` -#1 [type_of_opaque] computing type of opaque `execute_transaction_fut::{opaque#0}` -end of query stack +For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/impl-trait/issues/issue-87340.rs b/tests/ui/impl-trait/issues/issue-87340.rs index 705a4addcb704..b1baaaa6ba5c1 100644 --- a/tests/ui/impl-trait/issues/issue-87340.rs +++ b/tests/ui/impl-trait/issues/issue-87340.rs @@ -9,6 +9,8 @@ impl X for () { //~^ ERROR `T` is not constrained by the impl trait, self type, or predicates type I = impl Sized; fn f() -> Self::I {} + //~^ ERROR type annotations needed + //~| ERROR type annotations needed } fn main() {} diff --git a/tests/ui/impl-trait/issues/issue-87340.stderr b/tests/ui/impl-trait/issues/issue-87340.stderr index 8513cb2881e1f..1be4087be4242 100644 --- a/tests/ui/impl-trait/issues/issue-87340.stderr +++ b/tests/ui/impl-trait/issues/issue-87340.stderr @@ -4,6 +4,19 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self LL | impl X for () { | ^ unconstrained type parameter -error: aborting due to 1 previous error +error[E0282]: type annotations needed + --> $DIR/issue-87340.rs:11:23 + | +LL | fn f() -> Self::I {} + | ^^ cannot infer type for type parameter `T` + +error[E0282]: type annotations needed + --> $DIR/issue-87340.rs:11:15 + | +LL | fn f() -> Self::I {} + | ^^^^^^^ cannot infer type for type parameter `T` + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0207`. +Some errors have detailed explanations: E0207, E0282. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/impl-trait/issues/issue-88236-2.rs b/tests/ui/impl-trait/issues/issue-88236-2.rs index f4354d1b2aef0..7ff08d8174f8e 100644 --- a/tests/ui/impl-trait/issues/issue-88236-2.rs +++ b/tests/ui/impl-trait/issues/issue-88236-2.rs @@ -13,17 +13,17 @@ impl<'a> Hrtb<'a> for &'a () { } fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {} -//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet +//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> { - //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` &() //~^ ERROR implementation of `Hrtb` is not general enough //~| ERROR implementation of `Hrtb` is not general enough } fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> { - //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` x //~^ ERROR implementation of `Hrtb` is not general enough //~| ERROR implementation of `Hrtb` is not general enough diff --git a/tests/ui/impl-trait/issues/issue-88236-2.stderr b/tests/ui/impl-trait/issues/issue-88236-2.stderr index 1e63338d6d195..09fd58056a561 100644 --- a/tests/ui/impl-trait/issues/issue-88236-2.stderr +++ b/tests/ui/impl-trait/issues/issue-88236-2.stderr @@ -1,4 +1,4 @@ -error: higher kinded lifetime bounds on nested opaque types are not supported yet +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` --> $DIR/issue-88236-2.rs:15:61 | LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {} @@ -10,7 +10,7 @@ note: lifetime declared here LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {} | ^^ -error: higher kinded lifetime bounds on nested opaque types are not supported yet +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` --> $DIR/issue-88236-2.rs:18:80 | LL | fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> { @@ -22,18 +22,6 @@ note: lifetime declared here LL | fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> { | ^^ -error: higher kinded lifetime bounds on nested opaque types are not supported yet - --> $DIR/issue-88236-2.rs:25:78 - | -LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> { - | ^^ - | -note: lifetime declared here - --> $DIR/issue-88236-2.rs:25:45 - | -LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> { - | ^^ - error: implementation of `Hrtb` is not general enough --> $DIR/issue-88236-2.rs:20:5 | @@ -52,6 +40,18 @@ LL | &() = note: `Hrtb<'a>` would have to be implemented for the type `&()` = note: ...but `Hrtb<'0>` is actually implemented for the type `&'0 ()`, for some specific lifetime `'0` +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` + --> $DIR/issue-88236-2.rs:25:78 + | +LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> { + | ^^ + | +note: lifetime declared here + --> $DIR/issue-88236-2.rs:25:45 + | +LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> { + | ^^ + error: lifetime may not live long enough --> $DIR/issue-88236-2.rs:27:5 | @@ -90,3 +90,4 @@ LL | x error: aborting due to 8 previous errors +For more information about this error, try `rustc --explain E0657`. diff --git a/tests/ui/impl-trait/issues/issue-88236.rs b/tests/ui/impl-trait/issues/issue-88236.rs index 36d12417354a2..e782a87657346 100644 --- a/tests/ui/impl-trait/issues/issue-88236.rs +++ b/tests/ui/impl-trait/issues/issue-88236.rs @@ -13,6 +13,6 @@ impl<'a> Hrtb<'a> for &'a () { } fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {} -//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet +//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` fn main() {} diff --git a/tests/ui/impl-trait/issues/issue-88236.stderr b/tests/ui/impl-trait/issues/issue-88236.stderr index 6cf1a42d6a997..5dee5f88c89f2 100644 --- a/tests/ui/impl-trait/issues/issue-88236.stderr +++ b/tests/ui/impl-trait/issues/issue-88236.stderr @@ -1,4 +1,4 @@ -error: higher kinded lifetime bounds on nested opaque types are not supported yet +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` --> $DIR/issue-88236.rs:15:61 | LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {} @@ -12,3 +12,4 @@ LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {} error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0657`. diff --git a/tests/ui/impl-trait/nested-rpit-hrtb.rs b/tests/ui/impl-trait/nested-rpit-hrtb.rs index a3eca741daad9..c10bfbfe4dc1a 100644 --- a/tests/ui/impl-trait/nested-rpit-hrtb.rs +++ b/tests/ui/impl-trait/nested-rpit-hrtb.rs @@ -23,18 +23,18 @@ impl Qux<'_> for () {} // This is not supported. fn one_hrtb_outlives() -> impl for<'a> Foo<'a, Assoc = impl Sized + 'a> {} -//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet +//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` // This is not supported. fn one_hrtb_trait_param() -> impl for<'a> Foo<'a, Assoc = impl Qux<'a>> {} -//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet +//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` fn one_hrtb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'a> {} -//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet +//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` //~| ERROR implementation of `Bar` is not general enough fn one_hrtb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl Qux<'a>> {} -//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet +//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` //~| ERROR: the trait bound `for<'a> &'a (): Qux<'_>` is not satisfied // This should resolve. diff --git a/tests/ui/impl-trait/nested-rpit-hrtb.stderr b/tests/ui/impl-trait/nested-rpit-hrtb.stderr index 0e0f76874e3af..2779694a51711 100644 --- a/tests/ui/impl-trait/nested-rpit-hrtb.stderr +++ b/tests/ui/impl-trait/nested-rpit-hrtb.stderr @@ -29,7 +29,7 @@ help: consider introducing lifetime `'b` here LL | fn two_htrb_outlives_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Sized + 'b> {} | ++++ -error: higher kinded lifetime bounds on nested opaque types are not supported yet +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` --> $DIR/nested-rpit-hrtb.rs:25:69 | LL | fn one_hrtb_outlives() -> impl for<'a> Foo<'a, Assoc = impl Sized + 'a> {} @@ -41,7 +41,7 @@ note: lifetime declared here LL | fn one_hrtb_outlives() -> impl for<'a> Foo<'a, Assoc = impl Sized + 'a> {} | ^^ -error: higher kinded lifetime bounds on nested opaque types are not supported yet +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` --> $DIR/nested-rpit-hrtb.rs:29:68 | LL | fn one_hrtb_trait_param() -> impl for<'a> Foo<'a, Assoc = impl Qux<'a>> {} @@ -53,7 +53,7 @@ note: lifetime declared here LL | fn one_hrtb_trait_param() -> impl for<'a> Foo<'a, Assoc = impl Qux<'a>> {} | ^^ -error: higher kinded lifetime bounds on nested opaque types are not supported yet +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` --> $DIR/nested-rpit-hrtb.rs:32:74 | LL | fn one_hrtb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'a> {} @@ -65,7 +65,16 @@ note: lifetime declared here LL | fn one_hrtb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'a> {} | ^^ -error: higher kinded lifetime bounds on nested opaque types are not supported yet +error: implementation of `Bar` is not general enough + --> $DIR/nested-rpit-hrtb.rs:32:78 + | +LL | fn one_hrtb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'a> {} + | ^^ implementation of `Bar` is not general enough + | + = note: `()` must implement `Bar<'a>` + = note: ...but it actually implements `Bar<'0>`, for some specific lifetime `'0` + +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` --> $DIR/nested-rpit-hrtb.rs:36:73 | LL | fn one_hrtb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl Qux<'a>> {} @@ -77,15 +86,6 @@ note: lifetime declared here LL | fn one_hrtb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl Qux<'a>> {} | ^^ -error: implementation of `Bar` is not general enough - --> $DIR/nested-rpit-hrtb.rs:32:78 - | -LL | fn one_hrtb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'a> {} - | ^^ implementation of `Bar` is not general enough - | - = note: `()` must implement `Bar<'a>` - = note: ...but it actually implements `Bar<'0>`, for some specific lifetime `'0` - error[E0277]: the trait bound `for<'a> &'a (): Qux<'_>` is not satisfied --> $DIR/nested-rpit-hrtb.rs:36:64 | @@ -133,5 +133,5 @@ LL | fn two_htrb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Si error: aborting due to 12 previous errors -Some errors have detailed explanations: E0261, E0277. +Some errors have detailed explanations: E0261, E0277, E0657. For more information about an error, try `rustc --explain E0261`. diff --git a/tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr b/tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr index fee3b86034af1..4a5e4bfe94b56 100644 --- a/tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr +++ b/tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr @@ -1,9 +1,9 @@ error[E0282]: type annotations needed - --> $DIR/recursive-coroutine-boxed.rs:10:23 + --> $DIR/recursive-coroutine-boxed.rs:11:23 | LL | let mut gen = Box::pin(foo()); | ^^^^^^^^ cannot infer type of the type parameter `T` declared on the struct `Box` -... +LL | LL | let mut r = gen.as_mut().resume(()); | ------ type must be known at this point | @@ -13,10 +13,10 @@ LL | let mut gen = Box::::pin(foo()); | +++++ error[E0282]: type annotations needed - --> $DIR/recursive-coroutine-boxed.rs:10:32 + --> $DIR/recursive-coroutine-boxed.rs:8:13 | -LL | let mut gen = Box::pin(foo()); - | ^^^^^ cannot infer type for opaque type `impl Coroutine` +LL | fn foo() -> impl Coroutine { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for opaque type `impl Coroutine` error: aborting due to 2 previous errors diff --git a/tests/ui/impl-trait/recursive-coroutine-boxed.rs b/tests/ui/impl-trait/recursive-coroutine-boxed.rs index a42ae68f28e97..8f0bbb400cff0 100644 --- a/tests/ui/impl-trait/recursive-coroutine-boxed.rs +++ b/tests/ui/impl-trait/recursive-coroutine-boxed.rs @@ -6,10 +6,10 @@ use std::ops::{Coroutine, CoroutineState}; fn foo() -> impl Coroutine { + //[next]~^ ERROR type annotations needed || { let mut gen = Box::pin(foo()); //[next]~^ ERROR type annotations needed - //[next]~| ERROR type annotations needed let mut r = gen.as_mut().resume(()); while let CoroutineState::Yielded(v) = r { yield v; diff --git a/tests/ui/impl-trait/wf-check-hidden-type.rs b/tests/ui/impl-trait/wf-check-hidden-type.rs new file mode 100644 index 0000000000000..c3b1182a98f48 --- /dev/null +++ b/tests/ui/impl-trait/wf-check-hidden-type.rs @@ -0,0 +1,20 @@ +//! Regression test for #114728. + +trait Extend<'a, 'b> { + fn extend(self, _: &'a str) -> &'b str; +} + +impl<'a, 'b> Extend<'a, 'b> for Option<&'b &'a ()> { + fn extend(self, s: &'a str) -> &'b str { + s + } +} + +fn boom<'a, 'b>() -> impl Extend<'a, 'b> { + None::<&'_ &'_ ()> //~ ERROR lifetime may not live long enough +} + +fn main() { + let y = boom().extend(&String::from("temporary")); + println!("{}", y); +} diff --git a/tests/ui/impl-trait/wf-check-hidden-type.stderr b/tests/ui/impl-trait/wf-check-hidden-type.stderr new file mode 100644 index 0000000000000..86ba7aff54ada --- /dev/null +++ b/tests/ui/impl-trait/wf-check-hidden-type.stderr @@ -0,0 +1,14 @@ +error: lifetime may not live long enough + --> $DIR/wf-check-hidden-type.rs:14:5 + | +LL | fn boom<'a, 'b>() -> impl Extend<'a, 'b> { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | None::<&'_ &'_ ()> + | ^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to 1 previous error + diff --git a/tests/ui/impl-trait/where-allowed.stderr b/tests/ui/impl-trait/where-allowed.stderr index c4bdd484fdbd3..bffe0447f8bb4 100644 --- a/tests/ui/impl-trait/where-allowed.stderr +++ b/tests/ui/impl-trait/where-allowed.stderr @@ -342,33 +342,6 @@ LL | let _in_return_in_local_variable = || -> impl Fn() { || {} }; | = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions - --> $DIR/where-allowed.rs:239:7 - | -LL | impl T {} - | ^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #36887 - = note: `#[deny(invalid_type_param_default)]` on by default - -error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions - --> $DIR/where-allowed.rs:246:36 - | -LL | fn in_method_generic_param_default(_: T) {} - | ^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #36887 - -error[E0118]: no nominal type found for inherent implementation - --> $DIR/where-allowed.rs:239:1 - | -LL | impl T {} - | ^^^^^^^^^^^^^^^^^^^^^^^ impl requires a nominal type - | - = note: either implement a trait on it or create a newtype to wrap it instead - error[E0283]: type annotations needed --> $DIR/where-allowed.rs:46:57 | @@ -389,6 +362,24 @@ LL | fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { pani - impl Fn for Box where Args: Tuple, F: Fn, A: Allocator, F: ?Sized; +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/where-allowed.rs:239:7 + | +LL | impl T {} + | ^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #36887 + = note: `#[deny(invalid_type_param_default)]` on by default + +error[E0118]: no nominal type found for inherent implementation + --> $DIR/where-allowed.rs:239:1 + | +LL | impl T {} + | ^^^^^^^^^^^^^^^^^^^^^^^ impl requires a nominal type + | + = note: either implement a trait on it or create a newtype to wrap it instead + error[E0599]: no function or associated item named `into_vec` found for slice `[_]` in the current scope --> $DIR/where-allowed.rs:81:5 | @@ -428,6 +419,15 @@ LL | type Out = impl Debug; | = note: `Out` must be used in combination with a concrete type within the same impl +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/where-allowed.rs:246:36 + | +LL | fn in_method_generic_param_default(_: T) {} + | ^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #36887 + error: aborting due to 50 previous errors Some errors have detailed explanations: E0053, E0118, E0283, E0562, E0599, E0658, E0666. diff --git a/tests/ui/impl-unused-tps.stderr b/tests/ui/impl-unused-tps.stderr index 93215326c2fe3..af427cb5f3e3c 100644 --- a/tests/ui/impl-unused-tps.stderr +++ b/tests/ui/impl-unused-tps.stderr @@ -1,3 +1,25 @@ +error[E0119]: conflicting implementations of trait `Foo<_>` for type `[isize; 0]` + --> $DIR/impl-unused-tps.rs:27:1 + | +LL | impl Foo for [isize;0] { + | ---------------------------- first implementation here +... +LL | impl Foo for U { + | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `[isize; 0]` + +error[E0275]: overflow evaluating the requirement `([isize; 0], _): Sized` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`impl_unused_tps`) +note: required for `([isize; 0], _)` to implement `Bar` + --> $DIR/impl-unused-tps.rs:31:11 + | +LL | impl Bar for T { + | - ^^^ ^ + | | + | unsatisfied trait bound introduced here + = note: 126 redundant requirements hidden + = note: required for `([isize; 0], _)` to implement `Bar` + error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates --> $DIR/impl-unused-tps.rs:15:8 | @@ -28,28 +50,6 @@ error[E0207]: the type parameter `V` is not constrained by the impl trait, self LL | impl Foo for T | ^ unconstrained type parameter -error[E0119]: conflicting implementations of trait `Foo<_>` for type `[isize; 0]` - --> $DIR/impl-unused-tps.rs:27:1 - | -LL | impl Foo for [isize;0] { - | ---------------------------- first implementation here -... -LL | impl Foo for U { - | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `[isize; 0]` - -error[E0275]: overflow evaluating the requirement `([isize; 0], _): Sized` - | - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`impl_unused_tps`) -note: required for `([isize; 0], _)` to implement `Bar` - --> $DIR/impl-unused-tps.rs:31:11 - | -LL | impl Bar for T { - | - ^^^ ^ - | | - | unsatisfied trait bound introduced here - = note: 126 redundant requirements hidden - = note: required for `([isize; 0], _)` to implement `Bar` - error: aborting due to 7 previous errors Some errors have detailed explanations: E0119, E0207, E0275. diff --git a/tests/ui/imports/append-import-suggestion.rs b/tests/ui/imports/append-import-suggestion.rs new file mode 100644 index 0000000000000..6b75804b86fcb --- /dev/null +++ b/tests/ui/imports/append-import-suggestion.rs @@ -0,0 +1,16 @@ +// https://github.com/rust-lang/rust/issues/114884 + +mod mod1 { + pub trait TraitA {} +} + +mod mod2 { + mod sub_mod { + use super::super::mod1::TraitA; + } +} + +use mod2::{sub_mod::TraitA}; +//~^ ERROR: module `sub_mod` is private + +fn main() {} diff --git a/tests/ui/imports/append-import-suggestion.stderr b/tests/ui/imports/append-import-suggestion.stderr new file mode 100644 index 0000000000000..6d7b657f3d128 --- /dev/null +++ b/tests/ui/imports/append-import-suggestion.stderr @@ -0,0 +1,21 @@ +error[E0603]: module `sub_mod` is private + --> $DIR/append-import-suggestion.rs:13:12 + | +LL | use mod2::{sub_mod::TraitA}; + | ^^^^^^^ private module + | +help: consider importing this trait instead: + mod1::TraitA + --> $DIR/append-import-suggestion.rs:13:12 + | +LL | use mod2::{sub_mod::TraitA}; + | ^^^^^^^^^^^^^^^ +note: the module `sub_mod` is defined here + --> $DIR/append-import-suggestion.rs:8:5 + | +LL | mod sub_mod { + | ^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/imports/auxiliary/aux-issue-121915.rs b/tests/ui/imports/auxiliary/aux-issue-121915.rs new file mode 100644 index 0000000000000..7f9f5bda79ffd --- /dev/null +++ b/tests/ui/imports/auxiliary/aux-issue-121915.rs @@ -0,0 +1 @@ +pub fn item() {} diff --git a/tests/ui/imports/redundant-import-issue-121915-2015.rs b/tests/ui/imports/redundant-import-issue-121915-2015.rs new file mode 100644 index 0000000000000..d41d190bb58c4 --- /dev/null +++ b/tests/ui/imports/redundant-import-issue-121915-2015.rs @@ -0,0 +1,11 @@ +//@ compile-flags: --extern aux_issue_121915 --edition 2015 +//@ aux-build: aux-issue-121915.rs + +extern crate aux_issue_121915; + +#[deny(unused_imports)] +fn main() { + use aux_issue_121915; + //~^ ERROR the item `aux_issue_121915` is imported redundantly + aux_issue_121915::item(); +} diff --git a/tests/ui/imports/redundant-import-issue-121915-2015.stderr b/tests/ui/imports/redundant-import-issue-121915-2015.stderr new file mode 100644 index 0000000000000..174ed4fb96b11 --- /dev/null +++ b/tests/ui/imports/redundant-import-issue-121915-2015.stderr @@ -0,0 +1,17 @@ +error: the item `aux_issue_121915` is imported redundantly + --> $DIR/redundant-import-issue-121915-2015.rs:8:9 + | +LL | extern crate aux_issue_121915; + | ------------------------------ the item `aux_issue_121915` is already imported here +... +LL | use aux_issue_121915; + | ^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/redundant-import-issue-121915-2015.rs:6:8 + | +LL | #[deny(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/imports/redundant-import-issue-121915.rs b/tests/ui/imports/redundant-import-issue-121915.rs new file mode 100644 index 0000000000000..237acc4af2565 --- /dev/null +++ b/tests/ui/imports/redundant-import-issue-121915.rs @@ -0,0 +1,9 @@ +//@ compile-flags: --extern aux_issue_121915 --edition 2018 +//@ aux-build: aux-issue-121915.rs + +#[deny(unused_imports)] +fn main() { + use aux_issue_121915; + //~^ ERROR the item `aux_issue_121915` is imported redundantly + aux_issue_121915::item(); +} diff --git a/tests/ui/imports/redundant-import-issue-121915.stderr b/tests/ui/imports/redundant-import-issue-121915.stderr new file mode 100644 index 0000000000000..0047d7c34207c --- /dev/null +++ b/tests/ui/imports/redundant-import-issue-121915.stderr @@ -0,0 +1,14 @@ +error: the item `aux_issue_121915` is imported redundantly + --> $DIR/redundant-import-issue-121915.rs:6:9 + | +LL | use aux_issue_121915; + | ^^^^^^^^^^^^^^^^ the item `aux_issue_121915` is already defined by prelude + | +note: the lint level is defined here + --> $DIR/redundant-import-issue-121915.rs:4:8 + | +LL | #[deny(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/imports/suggest-remove-issue-121315.rs b/tests/ui/imports/suggest-remove-issue-121315.rs new file mode 100644 index 0000000000000..63533480ec127 --- /dev/null +++ b/tests/ui/imports/suggest-remove-issue-121315.rs @@ -0,0 +1,40 @@ +//@ compile-flags: --edition 2021 +#![deny(unused_imports)] +#![allow(dead_code)] + +fn test0() { + // Test remove FlatUnused + use std::convert::TryFrom; + //~^ ERROR the item `TryFrom` is imported redundantly + let _ = u32::try_from(5i32); +} + +fn test1() { + // FIXME(yukang) Test remove NestedFullUnused + use std::convert::{TryFrom, TryInto}; + //~^ ERROR the item `TryFrom` is imported redundantly + //~| ERROR the item `TryInto` is imported redundantly + + let _ = u32::try_from(5i32); + let _a: i32 = u32::try_into(5u32).unwrap(); +} + +fn test2() { + // FIXME(yukang): Test remove both redundant and unused + use std::convert::{AsMut, Into}; + //~^ ERROR unused import: `AsMut` + //~| ERROR the item `Into` is imported redundantly + + let _a: u32 = (5u8).into(); +} + +fn test3() { + // Test remove NestedPartialUnused + use std::convert::{From, Infallible}; + //~^ ERROR unused import: `From` + + trait MyTrait {} + impl MyTrait for fn() -> Infallible {} +} + +fn main() {} diff --git a/tests/ui/imports/suggest-remove-issue-121315.stderr b/tests/ui/imports/suggest-remove-issue-121315.stderr new file mode 100644 index 0000000000000..dbd742f6c781f --- /dev/null +++ b/tests/ui/imports/suggest-remove-issue-121315.stderr @@ -0,0 +1,56 @@ +error: the item `TryFrom` is imported redundantly + --> $DIR/suggest-remove-issue-121315.rs:7:9 + | +LL | use std::convert::TryFrom; + | ^^^^^^^^^^^^^^^^^^^^^ + --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL + | + = note: the item `TryFrom` is already defined here + | +note: the lint level is defined here + --> $DIR/suggest-remove-issue-121315.rs:2:9 + | +LL | #![deny(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: the item `TryFrom` is imported redundantly + --> $DIR/suggest-remove-issue-121315.rs:14:24 + | +LL | use std::convert::{TryFrom, TryInto}; + | ^^^^^^^ + --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL + | + = note: the item `TryFrom` is already defined here + +error: the item `TryInto` is imported redundantly + --> $DIR/suggest-remove-issue-121315.rs:14:33 + | +LL | use std::convert::{TryFrom, TryInto}; + | ^^^^^^^ + --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL + | + = note: the item `TryInto` is already defined here + +error: unused import: `AsMut` + --> $DIR/suggest-remove-issue-121315.rs:24:24 + | +LL | use std::convert::{AsMut, Into}; + | ^^^^^ + +error: the item `Into` is imported redundantly + --> $DIR/suggest-remove-issue-121315.rs:24:31 + | +LL | use std::convert::{AsMut, Into}; + | ^^^^ + --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL + | + = note: the item `Into` is already defined here + +error: unused import: `From` + --> $DIR/suggest-remove-issue-121315.rs:33:24 + | +LL | use std::convert::{From, Infallible}; + | ^^^^ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/imports/unresolved-seg-after-ambiguous.rs b/tests/ui/imports/unresolved-seg-after-ambiguous.rs new file mode 100644 index 0000000000000..dcabc528a85ed --- /dev/null +++ b/tests/ui/imports/unresolved-seg-after-ambiguous.rs @@ -0,0 +1,24 @@ +mod a { + mod b { + mod c { + pub struct E; + } + + mod d { + #[derive(Debug)] + pub struct E; + } + + pub use self::d::*; + pub use self::c::*; + } + + pub use self::b::*; +} + +use self::a::E::in_exist; +//~^ ERROR: unresolved import `self::a::E` +//~| WARNING: `E` is ambiguous +//~| WARNING: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +fn main() {} diff --git a/tests/ui/imports/unresolved-seg-after-ambiguous.stderr b/tests/ui/imports/unresolved-seg-after-ambiguous.stderr new file mode 100644 index 0000000000000..9e0efd4a75f84 --- /dev/null +++ b/tests/ui/imports/unresolved-seg-after-ambiguous.stderr @@ -0,0 +1,32 @@ +error[E0432]: unresolved import `self::a::E` + --> $DIR/unresolved-seg-after-ambiguous.rs:19:14 + | +LL | use self::a::E::in_exist; + | ^ `E` is a struct, not a module + +warning: `E` is ambiguous + --> $DIR/unresolved-seg-after-ambiguous.rs:19:14 + | +LL | use self::a::E::in_exist; + | ^ ambiguous name + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #114095 + = note: ambiguous because of multiple glob imports of a name in the same module +note: `E` could refer to the struct imported here + --> $DIR/unresolved-seg-after-ambiguous.rs:13:17 + | +LL | pub use self::c::*; + | ^^^^^^^^^^ + = help: consider adding an explicit import of `E` to disambiguate +note: `E` could also refer to the struct imported here + --> $DIR/unresolved-seg-after-ambiguous.rs:12:17 + | +LL | pub use self::d::*; + | ^^^^^^^^^^ + = help: consider adding an explicit import of `E` to disambiguate + = note: `#[warn(ambiguous_glob_imports)]` on by default + +error: aborting due to 1 previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/infinite/infinite-trait-alias-recursion.stderr b/tests/ui/infinite/infinite-trait-alias-recursion.stderr index 220d81031ac22..b3980cb935efe 100644 --- a/tests/ui/infinite/infinite-trait-alias-recursion.stderr +++ b/tests/ui/infinite/infinite-trait-alias-recursion.stderr @@ -16,7 +16,7 @@ LL | trait T3 = T1 + T3; | ^^ = note: ...which again requires computing the super predicates of `T1`, completing the cycle = note: trait aliases cannot be recursive -note: cycle used when collecting item types in top-level module +note: cycle used when checking that `T1` is well-formed --> $DIR/infinite-trait-alias-recursion.rs:3:1 | LL | trait T1 = T2; diff --git a/tests/ui/infinite/infinite-type-alias-mutual-recursion.gated.stderr b/tests/ui/infinite/infinite-type-alias-mutual-recursion.gated.stderr index 57ca1b24d2a38..ab1bcc44cb8b0 100644 --- a/tests/ui/infinite/infinite-type-alias-mutual-recursion.gated.stderr +++ b/tests/ui/infinite/infinite-type-alias-mutual-recursion.gated.stderr @@ -18,17 +18,11 @@ LL | type X3 = X1; = note: type aliases cannot be recursive = help: consider using a struct, enum, or union instead to break the cycle = help: see for more information -note: cycle used when collecting item types in top-level module - --> $DIR/infinite-type-alias-mutual-recursion.rs:3:1 +note: cycle used when checking that `X1` is well-formed + --> $DIR/infinite-type-alias-mutual-recursion.rs:6:1 | -LL | / #![cfg_attr(feature, feature(lazy_type_alias))] -LL | | #![allow(incomplete_features)] -LL | | -LL | | type X1 = X2; -... | -LL | | -LL | | fn main() {} - | |____________^ +LL | type X1 = X2; + | ^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error: aborting due to 1 previous error diff --git a/tests/ui/infinite/infinite-vec-type-recursion.gated.stderr b/tests/ui/infinite/infinite-vec-type-recursion.gated.stderr index efafc9b75cdbf..43364892bb53a 100644 --- a/tests/ui/infinite/infinite-vec-type-recursion.gated.stderr +++ b/tests/ui/infinite/infinite-vec-type-recursion.gated.stderr @@ -8,17 +8,11 @@ LL | type X = Vec; = note: type aliases cannot be recursive = help: consider using a struct, enum, or union instead to break the cycle = help: see for more information -note: cycle used when collecting item types in top-level module - --> $DIR/infinite-vec-type-recursion.rs:3:1 +note: cycle used when checking that `X` is well-formed + --> $DIR/infinite-vec-type-recursion.rs:6:1 | -LL | / #![cfg_attr(feature, feature(lazy_type_alias))] -LL | | #![allow(incomplete_features)] -LL | | -LL | | type X = Vec; -... | -LL | | #[rustfmt::skip] -LL | | fn main() { let b: X = Vec::new(); } - | |____________________________________^ +LL | type X = Vec; + | ^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error: aborting due to 1 previous error diff --git a/tests/ui/instrument-coverage/bad-value.bad.stderr b/tests/ui/instrument-coverage/bad-value.bad.stderr index b867d169dae5b..0411a1f98a3ee 100644 --- a/tests/ui/instrument-coverage/bad-value.bad.stderr +++ b/tests/ui/instrument-coverage/bad-value.bad.stderr @@ -1,2 +1,2 @@ -error: incorrect value `bad-value` for codegen option `instrument-coverage` - `all` (default), `branch`, `except-unused-generics`, `except-unused-functions`, or `off` was expected +error: incorrect value `bad-value` for codegen option `instrument-coverage` - either a boolean (`yes`, `no`, `on`, `off`, etc) or (unstable) one of `branch`, `except-unused-generics`, `except-unused-functions` was expected diff --git a/tests/ui/instrument-coverage/bad-value.blank.stderr b/tests/ui/instrument-coverage/bad-value.blank.stderr index e7122fb61cdfc..b3a8e7cf94784 100644 --- a/tests/ui/instrument-coverage/bad-value.blank.stderr +++ b/tests/ui/instrument-coverage/bad-value.blank.stderr @@ -1,2 +1,2 @@ -error: incorrect value `` for codegen option `instrument-coverage` - `all` (default), `branch`, `except-unused-generics`, `except-unused-functions`, or `off` was expected +error: incorrect value `` for codegen option `instrument-coverage` - either a boolean (`yes`, `no`, `on`, `off`, etc) or (unstable) one of `branch`, `except-unused-generics`, `except-unused-functions` was expected diff --git a/tests/ui/intrinsics/always-gets-overridden.rs b/tests/ui/intrinsics/always-gets-overridden.rs new file mode 100644 index 0000000000000..ad2c2be4daa48 --- /dev/null +++ b/tests/ui/intrinsics/always-gets-overridden.rs @@ -0,0 +1,20 @@ +//! Check that `vtable_size` gets overridden by llvm backend even if there is no +//! `rustc_intrinsic_must_be_overridden` attribute on this usage. +#![feature(rustc_attrs)] +//@run-pass + +#[rustc_intrinsic] +pub unsafe fn vtable_size(_ptr: *const ()) -> usize { + panic!(); +} + +trait Trait {} +impl Trait for () {} + +fn main() { + let x: &dyn Trait = &(); + unsafe { + let (_data, vtable): (*const (), *const ()) = core::mem::transmute(x); + assert_eq!(vtable_size(vtable), 0); + } +} diff --git a/tests/ui/intrinsics/const-eval-select-backtrace.rs b/tests/ui/intrinsics/const-eval-select-backtrace.rs index d6b1c865bdfc7..ea4374f5d328e 100644 --- a/tests/ui/intrinsics/const-eval-select-backtrace.rs +++ b/tests/ui/intrinsics/const-eval-select-backtrace.rs @@ -12,8 +12,5 @@ fn uhoh() { const fn c() {} fn main() { - // safety: this is unsound and just used to test - unsafe { - std::intrinsics::const_eval_select((), c, uhoh); - } + std::intrinsics::const_eval_select((), c, uhoh); } diff --git a/tests/ui/intrinsics/const-eval-select-backtrace.run.stderr b/tests/ui/intrinsics/const-eval-select-backtrace.run.stderr index 3f196bd8abc39..8f38d54146b88 100644 --- a/tests/ui/intrinsics/const-eval-select-backtrace.run.stderr +++ b/tests/ui/intrinsics/const-eval-select-backtrace.run.stderr @@ -1,3 +1,3 @@ -thread 'main' panicked at $DIR/const-eval-select-backtrace.rs:17:9: +thread 'main' panicked at $DIR/const-eval-select-backtrace.rs:15:5: Aaah! note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/tests/ui/intrinsics/const-eval-select-stability.rs b/tests/ui/intrinsics/const-eval-select-stability.rs index f9554decec16b..575bc0cadda1b 100644 --- a/tests/ui/intrinsics/const-eval-select-stability.rs +++ b/tests/ui/intrinsics/const-eval-select-stability.rs @@ -13,7 +13,7 @@ const fn nothing(){} #[stable(since = "1.0", feature = "hey")] #[rustc_const_stable(since = "1.0", feature = "const_hey")] -pub const unsafe fn hey() { +pub const fn hey() { const_eval_select((), nothing, log); //~^ ERROR `const_eval_select` is not yet stable as a const fn } diff --git a/tests/ui/intrinsics/const-eval-select-x86_64.rs b/tests/ui/intrinsics/const-eval-select-x86_64.rs index 5ba7a443d0bb9..c17be2ddaca39 100644 --- a/tests/ui/intrinsics/const-eval-select-x86_64.rs +++ b/tests/ui/intrinsics/const-eval-select-x86_64.rs @@ -22,9 +22,7 @@ fn eq_rt(x: [i32; 4], y: [i32; 4]) -> bool { } const fn eq(x: [i32; 4], y: [i32; 4]) -> bool { - unsafe { - const_eval_select((x, y), eq_ct, eq_rt) - } + const_eval_select((x, y), eq_ct, eq_rt) } fn main() { diff --git a/tests/ui/intrinsics/const-eval-select.rs b/tests/ui/intrinsics/const-eval-select.rs index 353105cb0a163..66d83585fcec8 100644 --- a/tests/ui/intrinsics/const-eval-select.rs +++ b/tests/ui/intrinsics/const-eval-select.rs @@ -13,9 +13,9 @@ fn no() -> bool { false } -// not a sound use case; testing only +// not allowed on stable; testing only const fn is_const_eval() -> bool { - unsafe { const_eval_select((), yes, no) } + const_eval_select((), yes, no) } fn main() { diff --git a/tests/ui/intrinsics/not-overridden.rs b/tests/ui/intrinsics/not-overridden.rs new file mode 100644 index 0000000000000..d6655b51905ae --- /dev/null +++ b/tests/ui/intrinsics/not-overridden.rs @@ -0,0 +1,18 @@ +//! Check that intrinsics that do not get overridden, but are marked as such, +//! cause an error instead of silently invoking the body. +#![feature(rustc_attrs, effects)] +//@ build-fail +//@ failure-status:101 +//@ normalize-stderr-test ".*note: .*\n\n" -> "" +//@ normalize-stderr-test "thread 'rustc' panicked.*:\n.*\n" -> "" +//@ normalize-stderr-test "internal compiler error:.*: intrinsic const_deallocate " -> "" +//@ rustc-env:RUST_BACKTRACE=0 + +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {} + +fn main() { + unsafe { const_deallocate(std::ptr::null_mut(), 0, 0) } + //~^ ERROR: must be overridden +} diff --git a/tests/ui/intrinsics/not-overridden.stderr b/tests/ui/intrinsics/not-overridden.stderr new file mode 100644 index 0000000000000..9b8849cea1ced --- /dev/null +++ b/tests/ui/intrinsics/not-overridden.stderr @@ -0,0 +1,10 @@ +error: must be overridden by codegen backend, but isn't + --> $DIR/not-overridden.rs:16:14 + | +LL | unsafe { const_deallocate(std::ptr::null_mut(), 0, 0) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +query stack during panic: +end of query stack +error: aborting due to 1 previous error + diff --git a/tests/ui/issues-71798.stderr b/tests/ui/issues-71798.stderr index 829d0a02ec90b..52dd14ccb0a14 100644 --- a/tests/ui/issues-71798.stderr +++ b/tests/ui/issues-71798.stderr @@ -14,7 +14,6 @@ LL | *x | -- return type was inferred to be `u32` here | = help: the trait `Future` is not implemented for `u32` - = note: u32 must be a future or must implement `IntoFuture` to be awaited error: aborting due to 2 previous errors diff --git a/tests/ui/issues/issue-16560.rs b/tests/ui/issues/issue-16560.rs index 37b536e644d86..d9a7aa9101d3f 100644 --- a/tests/ui/issues/issue-16560.rs +++ b/tests/ui/issues/issue-16560.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_variables)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; use std::mem; diff --git a/tests/ui/issues/issue-20831-debruijn.stderr b/tests/ui/issues/issue-20831-debruijn.stderr index 7d1e19b7e4759..60721f001b738 100644 --- a/tests/ui/issues/issue-20831-debruijn.stderr +++ b/tests/ui/issues/issue-20831-debruijn.stderr @@ -4,11 +4,11 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` d LL | fn subscribe(&mut self, t : Box::Output> + 'a>) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the anonymous lifetime defined here... - --> $DIR/issue-20831-debruijn.rs:28:58 +note: first, the lifetime cannot outlive the anonymous lifetime as defined here... + --> $DIR/issue-20831-debruijn.rs:28:18 | LL | fn subscribe(&mut self, t : Box::Output> + 'a>) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^ note: ...but the lifetime must also be valid for the lifetime `'a` as defined here... --> $DIR/issue-20831-debruijn.rs:26:6 | diff --git a/tests/ui/issues/issue-21291.rs b/tests/ui/issues/issue-21291.rs index 357d5520028fb..06f50ac6996df 100644 --- a/tests/ui/issues/issue-21291.rs +++ b/tests/ui/issues/issue-21291.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ ignore-emscripten no threads support +//@ needs-threads // Regression test for unwrapping the result of `join`, issue #21291 diff --git a/tests/ui/issues/issue-22864-2.rs b/tests/ui/issues/issue-22864-2.rs index 1b702f4f509c3..d98dbeda46b5d 100644 --- a/tests/ui/issues/issue-22864-2.rs +++ b/tests/ui/issues/issue-22864-2.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ ignore-emscripten no threads support +//@ needs-threads pub fn main() { let f = || || 0; diff --git a/tests/ui/issues/issue-23302-enum-infinite-recursion/issue-23302-1.stderr b/tests/ui/issues/issue-23302-enum-infinite-recursion/issue-23302-1.stderr index 53131f9130d9c..234060ab5c897 100644 --- a/tests/ui/issues/issue-23302-enum-infinite-recursion/issue-23302-1.stderr +++ b/tests/ui/issues/issue-23302-enum-infinite-recursion/issue-23302-1.stderr @@ -10,15 +10,11 @@ note: ...which requires const-evaluating + checking `X::A::{constant#0}`... LL | A = X::A as isize, | ^^^^^^^^^^^^^ = note: ...which again requires simplifying constant for the type system `X::A::{constant#0}`, completing the cycle -note: cycle used when collecting item types in top-level module +note: cycle used when checking that `X` is well-formed --> $DIR/issue-23302-1.rs:3:1 | -LL | / enum X { -LL | | A = X::A as isize, -LL | | } -LL | | -LL | | fn main() { } - | |_____________^ +LL | enum X { + | ^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-23302-enum-infinite-recursion/issue-23302-2.stderr b/tests/ui/issues/issue-23302-enum-infinite-recursion/issue-23302-2.stderr index d55d88762be43..9bd95239c8335 100644 --- a/tests/ui/issues/issue-23302-enum-infinite-recursion/issue-23302-2.stderr +++ b/tests/ui/issues/issue-23302-enum-infinite-recursion/issue-23302-2.stderr @@ -10,16 +10,11 @@ note: ...which requires const-evaluating + checking `Y::A::{constant#0}`... LL | A = Y::B as isize, | ^^^^^^^^^^^^^ = note: ...which again requires simplifying constant for the type system `Y::A::{constant#0}`, completing the cycle -note: cycle used when collecting item types in top-level module +note: cycle used when checking that `Y` is well-formed --> $DIR/issue-23302-2.rs:3:1 | -LL | / enum Y { -LL | | A = Y::B as isize, -LL | | B, -LL | | } -LL | | -LL | | fn main() { } - | |_____________^ +LL | enum Y { + | ^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-29861.rs b/tests/ui/issues/issue-29861.rs index 58f8eb5362c2e..875c168185feb 100644 --- a/tests/ui/issues/issue-29861.rs +++ b/tests/ui/issues/issue-29861.rs @@ -14,6 +14,7 @@ impl<'a, T: 'a> MakeRef2 for T { } fn foo() -> ::Ref2 { &String::from("foo") } +//~^ ERROR temporary value dropped while borrowed fn main() { println!("{}", foo()); diff --git a/tests/ui/issues/issue-29861.stderr b/tests/ui/issues/issue-29861.stderr index e7860c19eaa45..a25cbf0515d84 100644 --- a/tests/ui/issues/issue-29861.stderr +++ b/tests/ui/issues/issue-29861.stderr @@ -4,6 +4,18 @@ error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, LL | impl<'a, T: 'a> MakeRef2 for T { | ^^ unconstrained lifetime parameter -error: aborting due to 1 previous error +error[E0716]: temporary value dropped while borrowed + --> $DIR/issue-29861.rs:16:43 + | +LL | fn foo() -> ::Ref2 { &String::from("foo") } + | ^^^^^^^^^^^^^^^^^^^ -- borrow later used here + | | | + | | temporary value is freed at the end of this statement + | creates a temporary value which is freed while still in use + | + = note: consider using a `let` binding to create a longer lived value + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0207`. +Some errors have detailed explanations: E0207, E0716. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/issues/issue-33941.rs b/tests/ui/issues/issue-33941.rs index 0ad7cbe8efc41..7b5be30834b9d 100644 --- a/tests/ui/issues/issue-33941.rs +++ b/tests/ui/issues/issue-33941.rs @@ -5,5 +5,4 @@ use std::collections::HashMap; fn main() { for _ in HashMap::new().iter().cloned() {} //~ ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` //~^ ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` - //~| ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` } diff --git a/tests/ui/issues/issue-33941.stderr b/tests/ui/issues/issue-33941.stderr index e7f4a4fa004ce..f1b6b6ba17edc 100644 --- a/tests/ui/issues/issue-33941.stderr +++ b/tests/ui/issues/issue-33941.stderr @@ -27,16 +27,6 @@ LL | for _ in HashMap::new().iter().cloned() {} = note: required for `Cloned>` to implement `Iterator` = note: required for `Cloned>` to implement `IntoIterator` -error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` - --> $DIR/issue-33941.rs:6:14 - | -LL | for _ in HashMap::new().iter().cloned() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(&_, &_)`, found `&_` - | - = note: expected tuple `(&_, &_)` - found reference `&_` - = note: required for `Cloned>` to implement `Iterator` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/issues/issue-34373.stderr b/tests/ui/issues/issue-34373.stderr index 13667cd920e9b..784fe935bf8ae 100644 --- a/tests/ui/issues/issue-34373.stderr +++ b/tests/ui/issues/issue-34373.stderr @@ -10,17 +10,11 @@ note: ...which requires expanding type alias `DefaultFoo`... LL | type DefaultFoo = Foo; | ^^^ = note: ...which again requires computing type of `Foo::T`, completing the cycle -note: cycle used when collecting item types in top-level module - --> $DIR/issue-34373.rs:1:1 - | -LL | / #![allow(warnings)] -LL | | -LL | | trait Trait { -LL | | fn foo(_: T) {} -... | -LL | | fn main() { -LL | | } - | |_^ +note: cycle used when checking that `Foo` is well-formed + --> $DIR/issue-34373.rs:7:1 + | +LL | pub struct Foo>>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error[E0038]: the trait `Trait` cannot be made into an object diff --git a/tests/ui/issues/issue-37131.stderr b/tests/ui/issues/issue-37131.stderr index 9ecae3e7a2b24..588696f354184 100644 --- a/tests/ui/issues/issue-37131.stderr +++ b/tests/ui/issues/issue-37131.stderr @@ -4,8 +4,6 @@ error[E0463]: can't find crate for `std` = help: consider downloading the target with `rustup target add thumbv6m-none-eabi` = help: consider building the standard library from source with `cargo build -Zbuild-std` -error: requires `sized` lang_item - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0463`. diff --git a/tests/ui/issues/issue-49851/compiler-builtins-error.rs b/tests/ui/issues/issue-49851/compiler-builtins-error.rs index 3b62cc73f93d6..db45d040f7914 100644 --- a/tests/ui/issues/issue-49851/compiler-builtins-error.rs +++ b/tests/ui/issues/issue-49851/compiler-builtins-error.rs @@ -1,5 +1,4 @@ //~ ERROR can't find crate for `core` -//~^ ERROR can't find crate for `compiler_builtins` //@ compile-flags: --target thumbv7em-none-eabihf //@ needs-llvm-components: arm @@ -8,6 +7,5 @@ #![no_std] extern crate cortex_m; -//~^ ERROR can't find crate for `cortex_m` fn main() {} diff --git a/tests/ui/issues/issue-49851/compiler-builtins-error.stderr b/tests/ui/issues/issue-49851/compiler-builtins-error.stderr index fcfa2bf119cff..1cd65a1b68c88 100644 --- a/tests/ui/issues/issue-49851/compiler-builtins-error.stderr +++ b/tests/ui/issues/issue-49851/compiler-builtins-error.stderr @@ -4,16 +4,6 @@ error[E0463]: can't find crate for `core` = help: consider downloading the target with `rustup target add thumbv7em-none-eabihf` = help: consider building the standard library from source with `cargo build -Zbuild-std` -error[E0463]: can't find crate for `compiler_builtins` - -error[E0463]: can't find crate for `cortex_m` - --> $DIR/compiler-builtins-error.rs:10:1 - | -LL | extern crate cortex_m; - | ^^^^^^^^^^^^^^^^^^^^^^ can't find crate - -error: requires `sized` lang_item - -error: aborting due to 4 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0463`. diff --git a/tests/ui/issues/issue-59020.rs b/tests/ui/issues/issue-59020.rs index 5692afe811e83..2a34ba52b8831 100644 --- a/tests/ui/issues/issue-59020.rs +++ b/tests/ui/issues/issue-59020.rs @@ -1,6 +1,6 @@ //@ edition:2018 //@ run-pass -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; use std::time::Duration; diff --git a/tests/ui/iterators/bound.stderr b/tests/ui/iterators/bound.stderr index e5ed19f3731ca..915f0496716e9 100644 --- a/tests/ui/iterators/bound.stderr +++ b/tests/ui/iterators/bound.stderr @@ -5,7 +5,6 @@ LL | struct T(S); | ^^^^^ `u8` is not an iterator | = help: the trait `Iterator` is not implemented for `u8` - = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` note: required by a bound in `S` --> $DIR/bound.rs:1:13 | diff --git a/tests/ui/iterators/vec-on-unimplemented.fixed b/tests/ui/iterators/vec-on-unimplemented.fixed new file mode 100644 index 0000000000000..cc46bd67f9a8e --- /dev/null +++ b/tests/ui/iterators/vec-on-unimplemented.fixed @@ -0,0 +1,5 @@ +//@ run-rustfix +fn main() { + let _ = vec![true, false].into_iter().map(|v| !v).collect::>(); + //~^ ERROR no method named `map` found for struct `Vec` in the current scope +} diff --git a/tests/ui/iterators/vec-on-unimplemented.rs b/tests/ui/iterators/vec-on-unimplemented.rs index 42b5d36bfad4a..7367fd4c9cd78 100644 --- a/tests/ui/iterators/vec-on-unimplemented.rs +++ b/tests/ui/iterators/vec-on-unimplemented.rs @@ -1,4 +1,5 @@ +//@ run-rustfix fn main() { - vec![true, false].map(|v| !v).collect::>(); - //~^ ERROR `Vec` is not an iterator + let _ = vec![true, false].map(|v| !v).collect::>(); + //~^ ERROR no method named `map` found for struct `Vec` in the current scope } diff --git a/tests/ui/iterators/vec-on-unimplemented.stderr b/tests/ui/iterators/vec-on-unimplemented.stderr index 29b19d5e3b45b..d6f4bfa1cdebe 100644 --- a/tests/ui/iterators/vec-on-unimplemented.stderr +++ b/tests/ui/iterators/vec-on-unimplemented.stderr @@ -1,14 +1,13 @@ -error[E0599]: `Vec` is not an iterator - --> $DIR/vec-on-unimplemented.rs:2:23 +error[E0599]: no method named `map` found for struct `Vec` in the current scope + --> $DIR/vec-on-unimplemented.rs:3:31 | -LL | vec![true, false].map(|v| !v).collect::>(); - | ^^^ `Vec` is not an iterator; try calling `.into_iter()` or `.iter()` +LL | let _ = vec![true, false].map(|v| !v).collect::>(); + | ^^^ `Vec` is not an iterator | - = note: the following trait bounds were not satisfied: - `Vec: Iterator` - which is required by `&mut Vec: Iterator` - `[bool]: Iterator` - which is required by `&mut [bool]: Iterator` +help: call `.into_iter()` first + | +LL | let _ = vec![true, false].into_iter().map(|v| !v).collect::>(); + | ++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/kindck/kindck-impl-type-params-2.rs b/tests/ui/kindck/kindck-impl-type-params-2.rs index 8950fc51e643c..8b0771985dc3f 100644 --- a/tests/ui/kindck/kindck-impl-type-params-2.rs +++ b/tests/ui/kindck/kindck-impl-type-params-2.rs @@ -11,5 +11,5 @@ fn take_param(foo: &T) { } fn main() { let x: Box<_> = Box::new(3); take_param(&x); - //~^ ERROR the trait bound `Box<{integer}>: Copy` is not satisfied + //~^ ERROR the trait bound `Box<{integer}>: Foo` is not satisfied } diff --git a/tests/ui/kindck/kindck-impl-type-params-2.stderr b/tests/ui/kindck/kindck-impl-type-params-2.stderr index 46c0bda95352f..a7d169d3ac4ae 100644 --- a/tests/ui/kindck/kindck-impl-type-params-2.stderr +++ b/tests/ui/kindck/kindck-impl-type-params-2.stderr @@ -1,4 +1,4 @@ -error[E0277]: the trait bound `Box<{integer}>: Copy` is not satisfied +error[E0277]: the trait bound `Box<{integer}>: Foo` is not satisfied --> $DIR/kindck-impl-type-params-2.rs:13:16 | LL | take_param(&x); diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr b/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr index a85815d8cc498..979525ff40735 100644 --- a/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr +++ b/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr @@ -1,4 +1,4 @@ -error[E0277]: the trait bound `Box<{integer}>: Copy` is not satisfied +error[E0277]: the trait bound `Box<{integer}>: Foo` is not satisfied --> $DIR/kindck-inherited-copy-bound.rs:21:16 | LL | take_param(&x); diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr b/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr index 687660fe7eea3..30f90b88160e5 100644 --- a/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr +++ b/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr @@ -1,4 +1,4 @@ -error[E0277]: the trait bound `Box<{integer}>: Copy` is not satisfied +error[E0277]: the trait bound `Box<{integer}>: Foo` is not satisfied --> $DIR/kindck-inherited-copy-bound.rs:21:16 | LL | take_param(&x); diff --git a/tests/ui/kindck/kindck-send-object.rs b/tests/ui/kindck/kindck-send-object.rs index 6411e688b4aa6..f5d44246efe5a 100644 --- a/tests/ui/kindck/kindck-send-object.rs +++ b/tests/ui/kindck/kindck-send-object.rs @@ -10,7 +10,7 @@ trait Message : Send { } fn object_ref_with_static_bound_not_ok() { assert_send::<&'static (dyn Dummy + 'static)>(); - //~^ ERROR `(dyn Dummy + 'static)` cannot be shared between threads safely [E0277] + //~^ ERROR `&'static (dyn Dummy + 'static)` cannot be sent between threads safely [E0277] } fn box_object_with_no_bound_not_ok<'a>() { diff --git a/tests/ui/kindck/kindck-send-object.stderr b/tests/ui/kindck/kindck-send-object.stderr index 0fc9cb14c7d46..9f1ff4f3644cc 100644 --- a/tests/ui/kindck/kindck-send-object.stderr +++ b/tests/ui/kindck/kindck-send-object.stderr @@ -1,10 +1,10 @@ -error[E0277]: `(dyn Dummy + 'static)` cannot be shared between threads safely +error[E0277]: `&'static (dyn Dummy + 'static)` cannot be sent between threads safely --> $DIR/kindck-send-object.rs:12:19 | LL | assert_send::<&'static (dyn Dummy + 'static)>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'static)` cannot be shared between threads safely + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&'static (dyn Dummy + 'static)` cannot be sent between threads safely | - = help: the trait `Sync` is not implemented for `(dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send` + = help: the trait `Sync` is not implemented for `&'static (dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send` = note: required for `&'static (dyn Dummy + 'static)` to implement `Send` note: required by a bound in `assert_send` --> $DIR/kindck-send-object.rs:5:18 diff --git a/tests/ui/kindck/kindck-send-object1.rs b/tests/ui/kindck/kindck-send-object1.rs index 0ce3995dccc9a..76a9fc6019abc 100644 --- a/tests/ui/kindck/kindck-send-object1.rs +++ b/tests/ui/kindck/kindck-send-object1.rs @@ -8,7 +8,7 @@ trait Dummy { } // careful with object types, who knows what they close over... fn test51<'a>() { assert_send::<&'a dyn Dummy>(); - //~^ ERROR `(dyn Dummy + 'a)` cannot be shared between threads safely [E0277] + //~^ ERROR `&'a (dyn Dummy + 'a)` cannot be sent between threads safely [E0277] } fn test52<'a>() { assert_send::<&'a (dyn Dummy + Sync)>(); diff --git a/tests/ui/kindck/kindck-send-object1.stderr b/tests/ui/kindck/kindck-send-object1.stderr index 39343b9993b5a..f2aa814676fc3 100644 --- a/tests/ui/kindck/kindck-send-object1.stderr +++ b/tests/ui/kindck/kindck-send-object1.stderr @@ -1,10 +1,10 @@ -error[E0277]: `(dyn Dummy + 'a)` cannot be shared between threads safely +error[E0277]: `&'a (dyn Dummy + 'a)` cannot be sent between threads safely --> $DIR/kindck-send-object1.rs:10:19 | LL | assert_send::<&'a dyn Dummy>(); - | ^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be shared between threads safely + | ^^^^^^^^^^^^^ `&'a (dyn Dummy + 'a)` cannot be sent between threads safely | - = help: the trait `Sync` is not implemented for `(dyn Dummy + 'a)`, which is required by `&'a (dyn Dummy + 'a): Send` + = help: the trait `Sync` is not implemented for `&'a (dyn Dummy + 'a)`, which is required by `&'a (dyn Dummy + 'a): Send` = note: required for `&'a (dyn Dummy + 'a)` to implement `Send` note: required by a bound in `assert_send` --> $DIR/kindck-send-object1.rs:5:18 diff --git a/tests/ui/kindck/kindck-send-object2.rs b/tests/ui/kindck/kindck-send-object2.rs index b797588e446d6..d37074e657462 100644 --- a/tests/ui/kindck/kindck-send-object2.rs +++ b/tests/ui/kindck/kindck-send-object2.rs @@ -5,7 +5,7 @@ trait Dummy { } fn test50() { assert_send::<&'static dyn Dummy>(); - //~^ ERROR `(dyn Dummy + 'static)` cannot be shared between threads safely [E0277] + //~^ ERROR `&'static (dyn Dummy + 'static)` cannot be sent between threads safely [E0277] } fn test53() { diff --git a/tests/ui/kindck/kindck-send-object2.stderr b/tests/ui/kindck/kindck-send-object2.stderr index 758a517e12885..cd4d74360f867 100644 --- a/tests/ui/kindck/kindck-send-object2.stderr +++ b/tests/ui/kindck/kindck-send-object2.stderr @@ -1,10 +1,10 @@ -error[E0277]: `(dyn Dummy + 'static)` cannot be shared between threads safely +error[E0277]: `&'static (dyn Dummy + 'static)` cannot be sent between threads safely --> $DIR/kindck-send-object2.rs:7:19 | LL | assert_send::<&'static dyn Dummy>(); - | ^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'static)` cannot be shared between threads safely + | ^^^^^^^^^^^^^^^^^^ `&'static (dyn Dummy + 'static)` cannot be sent between threads safely | - = help: the trait `Sync` is not implemented for `(dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send` + = help: the trait `Sync` is not implemented for `&'static (dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send` = note: required for `&'static (dyn Dummy + 'static)` to implement `Send` note: required by a bound in `assert_send` --> $DIR/kindck-send-object2.rs:3:18 diff --git a/tests/ui/layout/issue-84108.rs b/tests/ui/layout/issue-84108.rs index 44d6ac8db72f0..425da65b9905a 100644 --- a/tests/ui/layout/issue-84108.rs +++ b/tests/ui/layout/issue-84108.rs @@ -11,4 +11,5 @@ const BAR: (&Path, [u8], usize) = ("hello", [], 42); static BAZ: ([u8], usize) = ([], 0); //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time +//~| ERROR the size for values of type `[u8]` cannot be known at compilation time //~| ERROR mismatched types diff --git a/tests/ui/layout/issue-84108.stderr b/tests/ui/layout/issue-84108.stderr index 58bddb069fc7d..6c168cc5fa84c 100644 --- a/tests/ui/layout/issue-84108.stderr +++ b/tests/ui/layout/issue-84108.stderr @@ -29,6 +29,16 @@ LL | static BAZ: ([u8], usize) = ([], 0); = help: the trait `Sized` is not implemented for `[u8]` = note: only the last element of a tuple may have a dynamically sized type +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/issue-84108.rs:12:13 + | +LL | static BAZ: ([u8], usize) = ([], 0); + | ^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: only the last element of a tuple may have a dynamically sized type + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error[E0308]: mismatched types --> $DIR/issue-84108.rs:12:30 | @@ -38,7 +48,7 @@ LL | static BAZ: ([u8], usize) = ([], 0); = note: expected slice `[u8]` found array `[_; 0]` -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors Some errors have detailed explanations: E0277, E0308, E0412. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/lazy-type-alias/unconstrained-params-in-impl-due-to-overflow.rs b/tests/ui/lazy-type-alias/unconstrained-params-in-impl-due-to-overflow.rs index eceefa719ec80..7bc91ef426b6c 100644 --- a/tests/ui/lazy-type-alias/unconstrained-params-in-impl-due-to-overflow.rs +++ b/tests/ui/lazy-type-alias/unconstrained-params-in-impl-due-to-overflow.rs @@ -3,6 +3,6 @@ impl Loop {} //~ ERROR the type parameter `T` is not constrained -type Loop = Loop; +type Loop = Loop; //~ ERROR overflow fn main() {} diff --git a/tests/ui/lazy-type-alias/unconstrained-params-in-impl-due-to-overflow.stderr b/tests/ui/lazy-type-alias/unconstrained-params-in-impl-due-to-overflow.stderr index b65c84226ce93..bcffa02ddd424 100644 --- a/tests/ui/lazy-type-alias/unconstrained-params-in-impl-due-to-overflow.stderr +++ b/tests/ui/lazy-type-alias/unconstrained-params-in-impl-due-to-overflow.stderr @@ -4,6 +4,15 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self LL | impl Loop {} | ^ unconstrained type parameter -error: aborting due to 1 previous error +error[E0275]: overflow normalizing the type alias `Loop` + --> $DIR/unconstrained-params-in-impl-due-to-overflow.rs:6:16 + | +LL | type Loop = Loop; + | ^^^^^^^ + | + = note: in case this is a recursive type alias, consider using a struct, enum, or union instead + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0207`. +Some errors have detailed explanations: E0207, E0275. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/lifetimes/issue-76168-hr-outlives-3.rs b/tests/ui/lifetimes/issue-76168-hr-outlives-3.rs index 03913869503c5..85eeb5d4c901e 100644 --- a/tests/ui/lifetimes/issue-76168-hr-outlives-3.rs +++ b/tests/ui/lifetimes/issue-76168-hr-outlives-3.rs @@ -6,6 +6,7 @@ use std::future::Future; async fn wrapper(f: F) //~^ ERROR: expected a `FnOnce(&'a mut i32)` closure, found `i32` //~| ERROR: expected a `FnOnce(&'a mut i32)` closure, found `i32` +//~| ERROR: expected a `FnOnce(&'a mut i32)` closure, found `i32` where F:, for<'a> >::Output: Future + 'a, diff --git a/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr b/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr index 89ebdb57f3c31..578ba149baf3f 100644 --- a/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr +++ b/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr @@ -4,6 +4,7 @@ error[E0277]: expected a `FnOnce(&'a mut i32)` closure, found `i32` LL | / async fn wrapper(f: F) LL | | LL | | +LL | | LL | | where LL | | F:, LL | | for<'a> >::Output: Future + 'a, @@ -20,7 +21,21 @@ LL | async fn wrapper(f: F) = help: the trait `for<'a> FnOnce<(&'a mut i32,)>` is not implemented for `i32` error[E0277]: expected a `FnOnce(&'a mut i32)` closure, found `i32` - --> $DIR/issue-76168-hr-outlives-3.rs:12:1 + --> $DIR/issue-76168-hr-outlives-3.rs:6:1 + | +LL | / async fn wrapper(f: F) +LL | | +LL | | +LL | | +LL | | where +LL | | F:, +LL | | for<'a> >::Output: Future + 'a, + | |__________________________________________________________________________^ expected an `FnOnce(&'a mut i32)` closure, found `i32` + | + = help: the trait `for<'a> FnOnce<(&'a mut i32,)>` is not implemented for `i32` + +error[E0277]: expected a `FnOnce(&'a mut i32)` closure, found `i32` + --> $DIR/issue-76168-hr-outlives-3.rs:13:1 | LL | / { LL | | @@ -31,6 +46,6 @@ LL | | } | = help: the trait `for<'a> FnOnce<(&'a mut i32,)>` is not implemented for `i32` -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/lifetimes/issue-95023.stderr b/tests/ui/lifetimes/issue-95023.stderr index 0c67d7328f2bc..c4285dbf4bdbb 100644 --- a/tests/ui/lifetimes/issue-95023.stderr +++ b/tests/ui/lifetimes/issue-95023.stderr @@ -32,12 +32,6 @@ help: parenthesized trait syntax expands to `Fn<(&isize,), Output=()>` LL | impl Fn(&isize) for Error { | ^^^^^^^^^^ -error[E0220]: associated type `B` not found for `Self` - --> $DIR/issue-95023.rs:8:44 - | -LL | fn foo(&self) -> Self::B<{ N }>; - | ^ help: `Self` has the following associated type: `Output` - error[E0277]: expected a `FnMut(&isize)` closure, found `Error` --> $DIR/issue-95023.rs:3:21 | @@ -56,6 +50,12 @@ LL | impl Fn(&isize) for Error { | = help: implement the missing item: `fn call(&self, _: (&isize,)) -> >::Output { todo!() }` +error[E0220]: associated type `B` not found for `Self` + --> $DIR/issue-95023.rs:8:44 + | +LL | fn foo(&self) -> Self::B<{ N }>; + | ^ help: `Self` has the following associated type: `Output` + error[E0220]: associated type `B` not found for `Self` --> $DIR/issue-95023.rs:8:44 | diff --git a/tests/ui/lifetimes/missing-lifetime-in-alias.stderr b/tests/ui/lifetimes/missing-lifetime-in-alias.stderr index 9183e6302eefc..b868d4b15a1aa 100644 --- a/tests/ui/lifetimes/missing-lifetime-in-alias.stderr +++ b/tests/ui/lifetimes/missing-lifetime-in-alias.stderr @@ -25,22 +25,6 @@ help: consider using one of the available lifetimes here LL | type C<'a, 'b> = as Trait<'lifetime>>::Bar; | +++++++++++ -error[E0107]: missing generics for associated type `Trait::Bar` - --> $DIR/missing-lifetime-in-alias.rs:27:36 - | -LL | type C<'a, 'b> = as Trait>::Bar; - | ^^^ expected 1 lifetime argument - | -note: associated type defined here, with 1 lifetime parameter: `'b` - --> $DIR/missing-lifetime-in-alias.rs:4:10 - | -LL | type Bar<'b> - | ^^^ -- -help: add missing lifetime argument - | -LL | type C<'a, 'b> = as Trait>::Bar<'a>; - | ++++ - error[E0477]: the type `Impl<'a>` does not fulfill the required lifetime --> $DIR/missing-lifetime-in-alias.rs:16:20 | @@ -60,6 +44,22 @@ help: copy the `where` clause predicates from the trait LL | type Bar<'b> = &'b () where Self: 'b; | ++++++++++++++ +error[E0107]: missing generics for associated type `Trait::Bar` + --> $DIR/missing-lifetime-in-alias.rs:27:36 + | +LL | type C<'a, 'b> = as Trait>::Bar; + | ^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'b` + --> $DIR/missing-lifetime-in-alias.rs:4:10 + | +LL | type Bar<'b> + | ^^^ -- +help: add missing lifetime argument + | +LL | type C<'a, 'b> = as Trait>::Bar<'a>; + | ++++ + error: aborting due to 4 previous errors Some errors have detailed explanations: E0106, E0107, E0477. diff --git a/tests/ui/linkage-attr/common-linkage-non-zero-init.stderr b/tests/ui/linkage-attr/common-linkage-non-zero-init.stderr index 667bb3ec130ed..93015bb2bac12 100644 --- a/tests/ui/linkage-attr/common-linkage-non-zero-init.stderr +++ b/tests/ui/linkage-attr/common-linkage-non-zero-init.stderr @@ -1,3 +1,3 @@ 'common' global must have a zero initializer! ptr @TEST -LLVM ERROR: Broken module found, compilation aborted! +rustc-LLVM ERROR: Broken module found, compilation aborted! diff --git a/tests/ui/lint/lint-qualification.fixed b/tests/ui/lint/lint-qualification.fixed index ab450f8b7347d..2b1f8b591752a 100644 --- a/tests/ui/lint/lint-qualification.fixed +++ b/tests/ui/lint/lint-qualification.fixed @@ -24,6 +24,9 @@ fn main() { use std::fmt; let _: fmt::Result = Ok(()); //~ ERROR: unnecessary qualification + let _ = ::default(); // issue #121999 + //~^ ERROR: unnecessary qualification + macro_rules! m { ($a:ident, $b:ident) => { $crate::foo::bar(); // issue #37357 ::foo::bar(); // issue #38682 diff --git a/tests/ui/lint/lint-qualification.rs b/tests/ui/lint/lint-qualification.rs index 84a36f509eb9e..002fdbf7724a7 100644 --- a/tests/ui/lint/lint-qualification.rs +++ b/tests/ui/lint/lint-qualification.rs @@ -24,6 +24,9 @@ fn main() { use std::fmt; let _: std::fmt::Result = Ok(()); //~ ERROR: unnecessary qualification + let _ = ::default(); // issue #121999 + //~^ ERROR: unnecessary qualification + macro_rules! m { ($a:ident, $b:ident) => { $crate::foo::bar(); // issue #37357 ::foo::bar(); // issue #38682 diff --git a/tests/ui/lint/lint-qualification.stderr b/tests/ui/lint/lint-qualification.stderr index 45e1525f4bf8c..8dddcf23f7575 100644 --- a/tests/ui/lint/lint-qualification.stderr +++ b/tests/ui/lint/lint-qualification.stderr @@ -87,5 +87,17 @@ LL - let _: std::fmt::Result = Ok(()); LL + let _: fmt::Result = Ok(()); | -error: aborting due to 7 previous errors +error: unnecessary qualification + --> $DIR/lint-qualification.rs:27:13 + | +LL | let _ = ::default(); // issue #121999 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the unnecessary path segments + | +LL - let _ = ::default(); // issue #121999 +LL + let _ = ::default(); // issue #121999 + | + +error: aborting due to 8 previous errors diff --git a/tests/ui/lint/non_local_definitions.rs b/tests/ui/lint/non_local_definitions.rs index c9aaa04934631..bbcc81898713c 100644 --- a/tests/ui/lint/non_local_definitions.rs +++ b/tests/ui/lint/non_local_definitions.rs @@ -4,6 +4,7 @@ //@ rustc-env:CARGO=/usr/bin/cargo #![feature(inline_const)] +#![warn(non_local_definitions)] extern crate non_local_macro; diff --git a/tests/ui/lint/non_local_definitions.stderr b/tests/ui/lint/non_local_definitions.stderr index f9f29ec63a805..b9583ae983f34 100644 --- a/tests/ui/lint/non_local_definitions.stderr +++ b/tests/ui/lint/non_local_definitions.stderr @@ -1,5 +1,5 @@ warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:36:5 + --> $DIR/non_local_definitions.rs:37:5 | LL | const Z: () = { | - help: use a const-anon item to suppress this lint: `_` @@ -11,10 +11,14 @@ LL | impl Uto for &Test {} = note: an `impl` definition is non-local if it is nested inside an item and neither the type nor the trait are at the same nesting level as the `impl` block = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue - = note: `#[warn(non_local_definitions)]` on by default +note: the lint level is defined here + --> $DIR/non_local_definitions.rs:7:9 + | +LL | #![warn(non_local_definitions)] + | ^^^^^^^^^^^^^^^^^^^^^ warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:46:5 + --> $DIR/non_local_definitions.rs:47:5 | LL | impl Uto for *mut Test {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +29,7 @@ LL | impl Uto for *mut Test {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:54:9 + --> $DIR/non_local_definitions.rs:55:9 | LL | impl Uto for Test {} | ^^^^^^^^^^^^^^^^^^^^ @@ -36,7 +40,7 @@ LL | impl Uto for Test {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:63:5 + --> $DIR/non_local_definitions.rs:64:5 | LL | impl Uto2 for Test {} | ^^^^^^^^^^^^^^^^^^^^^ @@ -47,7 +51,7 @@ LL | impl Uto2 for Test {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:71:5 + --> $DIR/non_local_definitions.rs:72:5 | LL | impl Uto3 for Test {} | ^^^^^^^^^^^^^^^^^^^^^ @@ -58,7 +62,7 @@ LL | impl Uto3 for Test {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `macro_rules!` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:75:5 + --> $DIR/non_local_definitions.rs:76:5 | LL | macro_rules! m0 { () => { } }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -69,7 +73,7 @@ LL | macro_rules! m0 { () => { } }; = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `macro_rules!` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:87:5 + --> $DIR/non_local_definitions.rs:88:5 | LL | macro_rules! m { () => { } }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -80,7 +84,7 @@ LL | macro_rules! m { () => { } }; = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:90:5 + --> $DIR/non_local_definitions.rs:91:5 | LL | / impl Test { LL | | @@ -94,7 +98,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:96:9 + --> $DIR/non_local_definitions.rs:97:9 | LL | / impl Test { LL | | @@ -108,7 +112,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:105:9 + --> $DIR/non_local_definitions.rs:106:9 | LL | / impl Test { LL | | @@ -122,7 +126,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:114:9 + --> $DIR/non_local_definitions.rs:115:9 | LL | / impl Test { LL | | @@ -136,7 +140,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:122:5 + --> $DIR/non_local_definitions.rs:123:5 | LL | / impl Display for Test { LL | | @@ -152,7 +156,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:129:5 + --> $DIR/non_local_definitions.rs:130:5 | LL | impl dyn Uto5 {} | ^^^^^^^^^^^^^^^^ @@ -163,7 +167,7 @@ LL | impl dyn Uto5 {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:132:5 + --> $DIR/non_local_definitions.rs:133:5 | LL | impl Uto5 for Vec { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -174,7 +178,7 @@ LL | impl Uto5 for Vec { } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:135:5 + --> $DIR/non_local_definitions.rs:136:5 | LL | impl Uto5 for &dyn Uto5 {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -185,7 +189,7 @@ LL | impl Uto5 for &dyn Uto5 {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:138:5 + --> $DIR/non_local_definitions.rs:139:5 | LL | impl Uto5 for *mut Test {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -196,7 +200,7 @@ LL | impl Uto5 for *mut Test {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:141:5 + --> $DIR/non_local_definitions.rs:142:5 | LL | impl Uto5 for *mut [Test] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -207,7 +211,7 @@ LL | impl Uto5 for *mut [Test] {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:144:5 + --> $DIR/non_local_definitions.rs:145:5 | LL | impl Uto5 for [Test; 8] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -218,7 +222,7 @@ LL | impl Uto5 for [Test; 8] {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:147:5 + --> $DIR/non_local_definitions.rs:148:5 | LL | impl Uto5 for (Test,) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -229,7 +233,7 @@ LL | impl Uto5 for (Test,) {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:150:5 + --> $DIR/non_local_definitions.rs:151:5 | LL | impl Uto5 for fn(Test) -> () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -240,7 +244,7 @@ LL | impl Uto5 for fn(Test) -> () {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:153:5 + --> $DIR/non_local_definitions.rs:154:5 | LL | impl Uto5 for fn() -> Test {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -251,7 +255,7 @@ LL | impl Uto5 for fn() -> Test {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:157:9 + --> $DIR/non_local_definitions.rs:158:9 | LL | impl Uto5 for Test {} | ^^^^^^^^^^^^^^^^^^^^^ @@ -262,7 +266,7 @@ LL | impl Uto5 for Test {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:164:9 + --> $DIR/non_local_definitions.rs:165:9 | LL | impl Uto5 for &Test {} | ^^^^^^^^^^^^^^^^^^^^^^ @@ -273,7 +277,7 @@ LL | impl Uto5 for &Test {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:171:9 + --> $DIR/non_local_definitions.rs:172:9 | LL | impl Uto5 for &(Test,) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -284,7 +288,7 @@ LL | impl Uto5 for &(Test,) {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:178:9 + --> $DIR/non_local_definitions.rs:179:9 | LL | impl Uto5 for &(Test,Test) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -295,7 +299,7 @@ LL | impl Uto5 for &(Test,Test) {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:186:5 + --> $DIR/non_local_definitions.rs:187:5 | LL | impl Uto5 for *mut InsideMain {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -306,7 +310,7 @@ LL | impl Uto5 for *mut InsideMain {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:188:5 + --> $DIR/non_local_definitions.rs:189:5 | LL | impl Uto5 for *mut [InsideMain] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -317,7 +321,7 @@ LL | impl Uto5 for *mut [InsideMain] {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:190:5 + --> $DIR/non_local_definitions.rs:191:5 | LL | impl Uto5 for [InsideMain; 8] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -328,7 +332,7 @@ LL | impl Uto5 for [InsideMain; 8] {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:192:5 + --> $DIR/non_local_definitions.rs:193:5 | LL | impl Uto5 for (InsideMain,) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -339,7 +343,7 @@ LL | impl Uto5 for (InsideMain,) {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:194:5 + --> $DIR/non_local_definitions.rs:195:5 | LL | impl Uto5 for fn(InsideMain) -> () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -350,7 +354,7 @@ LL | impl Uto5 for fn(InsideMain) -> () {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:196:5 + --> $DIR/non_local_definitions.rs:197:5 | LL | impl Uto5 for fn() -> InsideMain {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -361,7 +365,7 @@ LL | impl Uto5 for fn() -> InsideMain {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:210:9 + --> $DIR/non_local_definitions.rs:211:9 | LL | / impl Display for InsideMain { LL | | @@ -377,7 +381,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:217:9 + --> $DIR/non_local_definitions.rs:218:9 | LL | / impl InsideMain { LL | | @@ -394,7 +398,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `macro_rules!` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:221:17 + --> $DIR/non_local_definitions.rs:222:17 | LL | macro_rules! m2 { () => { } }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -405,7 +409,7 @@ LL | macro_rules! m2 { () => { } }; = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:231:5 + --> $DIR/non_local_definitions.rs:232:5 | LL | impl Uto3 for Vec { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -416,7 +420,7 @@ LL | impl Uto3 for Vec { } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:240:5 + --> $DIR/non_local_definitions.rs:241:5 | LL | impl Uto7 for Test where Local: std::any::Any {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -427,7 +431,7 @@ LL | impl Uto7 for Test where Local: std::any::Any {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:243:5 + --> $DIR/non_local_definitions.rs:244:5 | LL | impl Uto8 for T {} | ^^^^^^^^^^^^^^^^^^^^^ @@ -438,7 +442,7 @@ LL | impl Uto8 for T {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:252:5 + --> $DIR/non_local_definitions.rs:253:5 | LL | / impl Default for UwU { LL | | @@ -454,7 +458,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:263:5 + --> $DIR/non_local_definitions.rs:264:5 | LL | / impl From for () { LL | | @@ -470,7 +474,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:272:5 + --> $DIR/non_local_definitions.rs:273:5 | LL | / impl AsRef for () { LL | | @@ -484,7 +488,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:283:5 + --> $DIR/non_local_definitions.rs:284:5 | LL | / impl PartialEq for G { LL | | @@ -500,7 +504,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:300:5 + --> $DIR/non_local_definitions.rs:301:5 | LL | / impl PartialEq for &Dog { LL | | @@ -516,7 +520,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:307:5 + --> $DIR/non_local_definitions.rs:308:5 | LL | / impl PartialEq<()> for Dog { LL | | @@ -532,7 +536,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:314:5 + --> $DIR/non_local_definitions.rs:315:5 | LL | / impl PartialEq<()> for &Dog { LL | | @@ -548,7 +552,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:321:5 + --> $DIR/non_local_definitions.rs:322:5 | LL | / impl PartialEq for () { LL | | @@ -564,7 +568,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:343:5 + --> $DIR/non_local_definitions.rs:344:5 | LL | / impl From>> for () { LL | | @@ -580,7 +584,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:350:5 + --> $DIR/non_local_definitions.rs:351:5 | LL | / impl From<()> for Wrap { LL | | @@ -596,7 +600,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:363:13 + --> $DIR/non_local_definitions.rs:364:13 | LL | impl MacroTrait for OutsideStruct {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -611,7 +615,7 @@ LL | m!(); = note: this warning originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:373:1 + --> $DIR/non_local_definitions.rs:374:1 | LL | non_local_macro::non_local_impl!(CargoUpdate); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -624,7 +628,7 @@ LL | non_local_macro::non_local_impl!(CargoUpdate); = note: this warning originates in the macro `non_local_macro::non_local_impl` (in Nightly builds, run with -Z macro-backtrace for more info) warning: non-local `macro_rules!` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:376:1 + --> $DIR/non_local_definitions.rs:377:1 | LL | non_local_macro::non_local_macro_rules!(my_macro); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/use-redundant/use-redundant-issue-71450.rs b/tests/ui/lint/use-redundant/use-redundant-issue-71450.rs new file mode 100644 index 0000000000000..d0fb3454d3f2b --- /dev/null +++ b/tests/ui/lint/use-redundant/use-redundant-issue-71450.rs @@ -0,0 +1,45 @@ +//@ check-pass + +#![warn(unused_imports)] + +mod foo { + use std::fmt; + + pub struct String; + + impl String { + pub fn new() -> String { + String{} + } + } + + impl fmt::Display for String { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "String") + } + } +} + +fn main() { + + { + use std::string::String; //~ WARNING the item `String` is imported redundantly + // 'String' from 'std::string::String'. + let s = String::new(); + println!("{}", s); + } + + { + // 'String' from 'std::string::String'. + let s = String::new(); + println!("{}", s); + } + + { + use foo::*; + // 'String' from 'foo::String'. + let s = String::new(); + println!("{}", s); + } + +} diff --git a/tests/ui/lint/use-redundant/use-redundant-issue-71450.stderr b/tests/ui/lint/use-redundant/use-redundant-issue-71450.stderr new file mode 100644 index 0000000000000..b8832a3178371 --- /dev/null +++ b/tests/ui/lint/use-redundant/use-redundant-issue-71450.stderr @@ -0,0 +1,17 @@ +warning: the item `String` is imported redundantly + --> $DIR/use-redundant-issue-71450.rs:26:13 + | +LL | use std::string::String; + | ^^^^^^^^^^^^^^^^^^^ + --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL + | + = note: the item `String` is already defined here + | +note: the lint level is defined here + --> $DIR/use-redundant-issue-71450.rs:3:9 + | +LL | #![warn(unused_imports)] + | ^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/lint/use-redundant/use-redundant-issue-78894.rs b/tests/ui/lint/use-redundant/use-redundant-issue-78894.rs new file mode 100644 index 0000000000000..09c87bc37a630 --- /dev/null +++ b/tests/ui/lint/use-redundant/use-redundant-issue-78894.rs @@ -0,0 +1,48 @@ +//@ check-pass +//@ edition:2018 + +#![warn(unused_imports)] + +mod foo { + macro_rules! foo1 { + () => (); + } + + pub(crate) use foo1; +} + +fn main () +{ + bar!(); + + macro_rules! bar { + () => (); + } + + use bar; + + mod m { + bar1!(); + + macro_rules! bar1 { + () => (); + } + + use bar1; + } + + { + foo::foo1!(); + } + + { + use foo::foo1; + foo1!(); + } + + { + use foo::foo1; //~ WARNING unused import: `foo::foo1` + foo::foo1!(); + } + +} diff --git a/tests/ui/lint/use-redundant/use-redundant-issue-78894.stderr b/tests/ui/lint/use-redundant/use-redundant-issue-78894.stderr new file mode 100644 index 0000000000000..78dfe364223d4 --- /dev/null +++ b/tests/ui/lint/use-redundant/use-redundant-issue-78894.stderr @@ -0,0 +1,14 @@ +warning: unused import: `foo::foo1` + --> $DIR/use-redundant-issue-78894.rs:44:13 + | +LL | use foo::foo1; + | ^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/use-redundant-issue-78894.rs:4:9 + | +LL | #![warn(unused_imports)] + | ^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/logging-only-prints-once.rs b/tests/ui/logging-only-prints-once.rs index 75ef0a274ee48..5377d5eeae2bc 100644 --- a/tests/ui/logging-only-prints-once.rs +++ b/tests/ui/logging-only-prints-once.rs @@ -1,6 +1,6 @@ //@ run-pass //@ ignore-windows -//@ ignore-emscripten no threads support +//@ needs-threads use std::cell::Cell; use std::fmt; diff --git a/tests/ui/lto/lto-still-runs-thread-dtors.rs b/tests/ui/lto/lto-still-runs-thread-dtors.rs index a93d7cf35cc75..504923a93c279 100644 --- a/tests/ui/lto/lto-still-runs-thread-dtors.rs +++ b/tests/ui/lto/lto-still-runs-thread-dtors.rs @@ -1,7 +1,7 @@ //@ run-pass //@ compile-flags: -C lto //@ no-prefer-dynamic -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; diff --git a/tests/ui/macros/macro-with-braces-in-expr-position.rs b/tests/ui/macros/macro-with-braces-in-expr-position.rs index febfa7241f214..4607349e96368 100644 --- a/tests/ui/macros/macro-with-braces-in-expr-position.rs +++ b/tests/ui/macros/macro-with-braces-in-expr-position.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_must_use)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; diff --git a/tests/ui/marker_trait_attr/override-item-on-marker-trait.stderr b/tests/ui/marker_trait_attr/override-item-on-marker-trait.stderr index 92a54cff7f5fa..ab86df9c8a5b2 100644 --- a/tests/ui/marker_trait_attr/override-item-on-marker-trait.stderr +++ b/tests/ui/marker_trait_attr/override-item-on-marker-trait.stderr @@ -1,15 +1,3 @@ -error[E0715]: impls for marker traits cannot contain items - --> $DIR/override-item-on-marker-trait.rs:12:1 - | -LL | impl Marker for OverrideConst { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0715]: impls for marker traits cannot contain items - --> $DIR/override-item-on-marker-trait.rs:18:1 - | -LL | impl Marker for OverrideFn { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0714]: marker traits cannot have associated items --> $DIR/override-item-on-marker-trait.rs:5:5 | @@ -22,6 +10,18 @@ error[E0714]: marker traits cannot have associated items LL | fn do_something() {} | ^^^^^^^^^^^^^^^^^ +error[E0715]: impls for marker traits cannot contain items + --> $DIR/override-item-on-marker-trait.rs:12:1 + | +LL | impl Marker for OverrideConst { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0715]: impls for marker traits cannot contain items + --> $DIR/override-item-on-marker-trait.rs:18:1 + | +LL | impl Marker for OverrideFn { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + error: aborting due to 4 previous errors Some errors have detailed explanations: E0714, E0715. diff --git a/tests/ui/match/issue-18060.rs b/tests/ui/match/issue-18060.rs index daba393a3fa3d..9d480ba6b8bbb 100644 --- a/tests/ui/match/issue-18060.rs +++ b/tests/ui/match/issue-18060.rs @@ -1,6 +1,7 @@ //@ run-pass // Regression test for #18060: match arms were matching in the wrong order. +#[allow(non_contiguous_range_endpoints)] fn main() { assert_eq!(2, match (1, 3) { (0, 2..=5) => 1, (1, 3) => 2, (_, 2..=5) => 3, (_, _) => 4 }); assert_eq!(2, match (1, 3) { (1, 3) => 2, (_, 2..=5) => 3, (_, _) => 4 }); diff --git a/tests/ui/meta/dir.with.dots/test.rs b/tests/ui/meta/dir.with.dots/test.rs new file mode 100644 index 0000000000000..4d663e994f52b --- /dev/null +++ b/tests/ui/meta/dir.with.dots/test.rs @@ -0,0 +1,7 @@ +// Regression test for . +// Check that `tests_revision_unpaired_stdout_stderr` don't accidentally get confused by +// paths containing periods. + +//@ check-pass + +fn main() {} diff --git a/tests/ui/methods/issues/issue-94581.fixed b/tests/ui/methods/issues/issue-94581.fixed new file mode 100644 index 0000000000000..ff2bbeba27cbb --- /dev/null +++ b/tests/ui/methods/issues/issue-94581.fixed @@ -0,0 +1,8 @@ +//@ run-rustfix +fn get_slice() -> &'static [i32] { + &[1, 2, 3, 4] +} + +fn main() { + let _sqsum: i32 = get_slice().into_iter().map(|i| i * i).sum(); //~ ERROR [E0599] +} diff --git a/tests/ui/methods/issues/issue-94581.rs b/tests/ui/methods/issues/issue-94581.rs index df393e91db084..535d3249eb910 100644 --- a/tests/ui/methods/issues/issue-94581.rs +++ b/tests/ui/methods/issues/issue-94581.rs @@ -1,7 +1,8 @@ +//@ run-rustfix fn get_slice() -> &'static [i32] { &[1, 2, 3, 4] } fn main() { - let sqsum = get_slice().map(|i| i * i).sum(); //~ ERROR [E0599] + let _sqsum: i32 = get_slice().map(|i| i * i).sum(); //~ ERROR [E0599] } diff --git a/tests/ui/methods/issues/issue-94581.stderr b/tests/ui/methods/issues/issue-94581.stderr index ae7446d483352..d04d6ca5e3cd3 100644 --- a/tests/ui/methods/issues/issue-94581.stderr +++ b/tests/ui/methods/issues/issue-94581.stderr @@ -1,14 +1,13 @@ -error[E0599]: `&'static [i32]` is not an iterator - --> $DIR/issue-94581.rs:6:29 +error[E0599]: no method named `map` found for reference `&'static [i32]` in the current scope + --> $DIR/issue-94581.rs:7:35 | -LL | let sqsum = get_slice().map(|i| i * i).sum(); - | ^^^ `&'static [i32]` is not an iterator; try calling `.iter()` +LL | let _sqsum: i32 = get_slice().map(|i| i * i).sum(); + | ^^^ `&'static [i32]` is not an iterator | - = note: the following trait bounds were not satisfied: - `&'static [i32]: Iterator` - which is required by `&mut &'static [i32]: Iterator` - `[i32]: Iterator` - which is required by `&mut [i32]: Iterator` +help: call `.into_iter()` first + | +LL | let _sqsum: i32 = get_slice().into_iter().map(|i| i * i).sum(); + | ++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/mir/mir_match_test.rs b/tests/ui/mir/mir_match_test.rs index 925e1e6ab3d47..0da8522f2181a 100644 --- a/tests/ui/mir/mir_match_test.rs +++ b/tests/ui/mir/mir_match_test.rs @@ -1,5 +1,6 @@ #![feature(exclusive_range_pattern)] #![allow(overlapping_range_endpoints)] +#![allow(non_contiguous_range_endpoints)] //@ run-pass diff --git a/tests/ui/moves/moves-based-on-type-capture-clause.rs b/tests/ui/moves/moves-based-on-type-capture-clause.rs index baf52ffb5154c..46759f6646818 100644 --- a/tests/ui/moves/moves-based-on-type-capture-clause.rs +++ b/tests/ui/moves/moves-based-on-type-capture-clause.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_must_use)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; diff --git a/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr b/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr index e7fcdbd0c9c53..6beb04e5b9372 100644 --- a/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr +++ b/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr @@ -1,21 +1,3 @@ -error[E0038]: the trait `Baz` cannot be made into an object - --> $DIR/object-safety-supertrait-mentions-Self.rs:16:31 - | -LL | fn make_baz(t: &T) -> &dyn Baz { - | ^^^^^^^ `Baz` cannot be made into an object - | -note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-supertrait-mentions-Self.rs:8:13 - | -LL | trait Baz : Bar { - | --- ^^^^^^^^^ ...because it uses `Self` as a type parameter - | | - | this trait cannot be made into an object... -help: consider using an opaque type instead - | -LL | fn make_baz(t: &T) -> &impl Baz { - | ~~~~ - error[E0277]: the size for values of type `Self` cannot be known at compilation time --> $DIR/object-safety-supertrait-mentions-Self.rs:8:13 | @@ -36,6 +18,24 @@ help: consider relaxing the implicit `Sized` restriction LL | trait Bar { | ++++++++ +error[E0038]: the trait `Baz` cannot be made into an object + --> $DIR/object-safety-supertrait-mentions-Self.rs:16:31 + | +LL | fn make_baz(t: &T) -> &dyn Baz { + | ^^^^^^^ `Baz` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-supertrait-mentions-Self.rs:8:13 + | +LL | trait Baz : Bar { + | --- ^^^^^^^^^ ...because it uses `Self` as a type parameter + | | + | this trait cannot be made into an object... +help: consider using an opaque type instead + | +LL | fn make_baz(t: &T) -> &impl Baz { + | ~~~~ + error: aborting due to 2 previous errors Some errors have detailed explanations: E0038, E0277. diff --git a/tests/ui/panics/default-backtrace-ice.stderr b/tests/ui/panics/default-backtrace-ice.stderr index 9d27cb22ae942..82b61e43f4494 100644 --- a/tests/ui/panics/default-backtrace-ice.stderr +++ b/tests/ui/panics/default-backtrace-ice.stderr @@ -21,5 +21,5 @@ error: the compiler unexpectedly panicked. this is a bug. query stack during panic: -#0 [resolver_for_lowering] getting the resolver for lowering +#0 [resolver_for_lowering_raw] getting the resolver for lowering end of query stack diff --git a/tests/ui/panics/panic-handler-chain.rs b/tests/ui/panics/panic-handler-chain.rs index eb23849f3ac83..fea71ad9ec4e3 100644 --- a/tests/ui/panics/panic-handler-chain.rs +++ b/tests/ui/panics/panic-handler-chain.rs @@ -1,9 +1,8 @@ //@ run-pass //@ needs-unwind +//@ needs-threads #![allow(stable_features)] -//@ ignore-emscripten no threads support - #![feature(std_panic)] use std::sync::atomic::{AtomicUsize, Ordering}; diff --git a/tests/ui/panics/panic-task-name-none.rs b/tests/ui/panics/panic-task-name-none.rs index 7eb974bde4c55..8695771ff5eaa 100644 --- a/tests/ui/panics/panic-task-name-none.rs +++ b/tests/ui/panics/panic-task-name-none.rs @@ -1,7 +1,7 @@ //@ run-fail //@ error-pattern:thread '' panicked //@ error-pattern:test -//@ ignore-emscripten Needs threads +//@ needs-threads use std::thread; diff --git a/tests/ui/panics/panic-task-name-owned.rs b/tests/ui/panics/panic-task-name-owned.rs index 9a680676dc0fe..42ae33b5d351b 100644 --- a/tests/ui/panics/panic-task-name-owned.rs +++ b/tests/ui/panics/panic-task-name-owned.rs @@ -1,7 +1,7 @@ //@ run-fail //@ error-pattern:thread 'owned name' panicked //@ error-pattern:test -//@ ignore-emscripten Needs threads. +//@ needs-threads use std::thread::Builder; diff --git a/tests/ui/parser/impl-item-type-no-body-semantic-fail.stderr b/tests/ui/parser/impl-item-type-no-body-semantic-fail.stderr index 1c71cdacd89b6..29b0b25a564d9 100644 --- a/tests/ui/parser/impl-item-type-no-body-semantic-fail.stderr +++ b/tests/ui/parser/impl-item-type-no-body-semantic-fail.stderr @@ -82,15 +82,6 @@ LL | type W where Self: Eq; = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0592]: duplicate definitions with name `W` - --> $DIR/impl-item-type-no-body-semantic-fail.rs:18:5 - | -LL | type W: Ord where Self: Eq; - | ------ other definition for `W` -... -LL | type W where Self: Eq; - | ^^^^^^ duplicate definitions for `W` - error[E0277]: the trait bound `X: Eq` is not satisfied --> $DIR/impl-item-type-no-body-semantic-fail.rs:13:23 | @@ -119,6 +110,15 @@ LL + #[derive(Eq)] LL | struct X; | +error[E0592]: duplicate definitions with name `W` + --> $DIR/impl-item-type-no-body-semantic-fail.rs:18:5 + | +LL | type W: Ord where Self: Eq; + | ------ other definition for `W` +... +LL | type W where Self: Eq; + | ^^^^^^ duplicate definitions for `W` + error: aborting due to 13 previous errors Some errors have detailed explanations: E0277, E0592, E0658. diff --git a/tests/ui/parser/impls-nested-within-anon-consts-semantic.rs b/tests/ui/parser/impls-nested-within-anon-consts-semantic.rs new file mode 100644 index 0000000000000..36a7825cec8f1 --- /dev/null +++ b/tests/ui/parser/impls-nested-within-anon-consts-semantic.rs @@ -0,0 +1,35 @@ +// Regression test for issue #89342 and for part of #119924. +//@ check-pass + +struct Expr; + +trait Trait0 { + fn required(_: Expr<{ + struct Type; + + impl Type { + // This visibility qualifier used to get rejected. + pub fn perform() {} + } + + 0 + }>); +} + +trait Trait1 {} + +impl Trait1 for () +where + [(); { + struct Type; + + impl Type { + // This visibility qualifier used to get rejected. + pub const STORE: Self = Self; + } + + 0 + }]: +{} + +fn main() {} diff --git a/tests/ui/parser/impls-nested-within-fns-semantic-0.rs b/tests/ui/parser/impls-nested-within-fns-semantic-0.rs new file mode 100644 index 0000000000000..107380d33c70a --- /dev/null +++ b/tests/ui/parser/impls-nested-within-fns-semantic-0.rs @@ -0,0 +1,15 @@ +// Regression test for #121607 and for part of issue #119924. +//@ check-pass + +trait Trait { + fn provided() { + pub struct Type; + + impl Type { + // This visibility qualifier used to get rejected. + pub fn perform() {} + } + } +} + +fn main() {} diff --git a/tests/ui/parser/impls-nested-within-fns-semantic-1.rs b/tests/ui/parser/impls-nested-within-fns-semantic-1.rs new file mode 100644 index 0000000000000..43530e41a66c1 --- /dev/null +++ b/tests/ui/parser/impls-nested-within-fns-semantic-1.rs @@ -0,0 +1,22 @@ +// Regression test for part of issue #119924. +//@ check-pass + +#![feature(const_trait_impl, effects)] + +#[const_trait] +trait Trait { + fn required(); +} + +impl const Trait for () { + fn required() { + pub struct Type; + + impl Type { + // This visibility qualifier used to get rejected. + pub fn perform() {} + } + } +} + +fn main() {} diff --git a/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.rs b/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.rs index ed4de58cd23ce..521eb6a818b0c 100644 --- a/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.rs +++ b/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.rs @@ -1,3 +1,10 @@ +#![allow(unused)] + +fn test_122112() { + // Make sure we don't ICE if parsing in recovery fails + let _: std::env::temp_dir().join(&self, push: Box); //~ ERROR expected one of +} + fn main() { let _: std::env::temp_dir().join("foo"); //~ ERROR expected one of } diff --git a/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.stderr b/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.stderr index d03f3ae02830b..15c27bb9451b6 100644 --- a/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.stderr +++ b/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.stderr @@ -1,5 +1,13 @@ error: expected one of `!`, `+`, `->`, `::`, `;`, or `=`, found `.` - --> $DIR/recover-colon-instead-of-eq-in-local.rs:2:32 + --> $DIR/recover-colon-instead-of-eq-in-local.rs:5:32 + | +LL | let _: std::env::temp_dir().join(&self, push: Box); + | - ^ expected one of `!`, `+`, `->`, `::`, `;`, or `=` + | | + | while parsing the type for `_` + +error: expected one of `!`, `+`, `->`, `::`, `;`, or `=`, found `.` + --> $DIR/recover-colon-instead-of-eq-in-local.rs:9:32 | LL | let _: std::env::temp_dir().join("foo"); | - ^ expected one of `!`, `+`, `->`, `::`, `;`, or `=` @@ -7,5 +15,5 @@ LL | let _: std::env::temp_dir().join("foo"); | while parsing the type for `_` | help: use `=` if you meant to assign -error: aborting due to 1 previous error +error: aborting due to 2 previous errors diff --git a/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.rs b/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.rs index 0f5f49c4ca473..07156d9a08a34 100644 --- a/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.rs +++ b/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.rs @@ -1,5 +1,6 @@ #![feature(exclusive_range_pattern)] #![allow(overlapping_range_endpoints)] +#![allow(non_contiguous_range_endpoints)] #![deny(unreachable_patterns)] macro_rules! m { diff --git a/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr b/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr index b585de2062913..90d0fd7483a99 100644 --- a/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr +++ b/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: `u8::MAX` not covered - --> $DIR/exhaustiveness.rs:47:8 + --> $DIR/exhaustiveness.rs:48:8 | LL | m!(0u8, 0..255); | ^^^ pattern `u8::MAX` not covered @@ -11,7 +11,7 @@ LL | match $s { $($t)+ => {}, u8::MAX => todo!() } | ++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `u8::MAX` not covered - --> $DIR/exhaustiveness.rs:48:8 + --> $DIR/exhaustiveness.rs:49:8 | LL | m!(0u8, 0..=254); | ^^^ pattern `u8::MAX` not covered @@ -23,7 +23,7 @@ LL | match $s { $($t)+ => {}, u8::MAX => todo!() } | ++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `0_u8` not covered - --> $DIR/exhaustiveness.rs:49:8 + --> $DIR/exhaustiveness.rs:50:8 | LL | m!(0u8, 1..=255); | ^^^ pattern `0_u8` not covered @@ -35,7 +35,7 @@ LL | match $s { $($t)+ => {}, 0_u8 => todo!() } | +++++++++++++++++ error[E0004]: non-exhaustive patterns: `42_u8` not covered - --> $DIR/exhaustiveness.rs:50:8 + --> $DIR/exhaustiveness.rs:51:8 | LL | m!(0u8, 0..42 | 43..=255); | ^^^ pattern `42_u8` not covered @@ -47,7 +47,7 @@ LL | match $s { $($t)+ => {}, 42_u8 => todo!() } | ++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i8::MAX` not covered - --> $DIR/exhaustiveness.rs:51:8 + --> $DIR/exhaustiveness.rs:52:8 | LL | m!(0i8, -128..127); | ^^^ pattern `i8::MAX` not covered @@ -59,7 +59,7 @@ LL | match $s { $($t)+ => {}, i8::MAX => todo!() } | ++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i8::MAX` not covered - --> $DIR/exhaustiveness.rs:52:8 + --> $DIR/exhaustiveness.rs:53:8 | LL | m!(0i8, -128..=126); | ^^^ pattern `i8::MAX` not covered @@ -71,7 +71,7 @@ LL | match $s { $($t)+ => {}, i8::MAX => todo!() } | ++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i8::MIN` not covered - --> $DIR/exhaustiveness.rs:53:8 + --> $DIR/exhaustiveness.rs:54:8 | LL | m!(0i8, -127..=127); | ^^^ pattern `i8::MIN` not covered @@ -83,7 +83,7 @@ LL | match $s { $($t)+ => {}, i8::MIN => todo!() } | ++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `0_i8` not covered - --> $DIR/exhaustiveness.rs:54:11 + --> $DIR/exhaustiveness.rs:55:11 | LL | match 0i8 { | ^^^ pattern `0_i8` not covered @@ -96,7 +96,7 @@ LL + 0_i8 => todo!() | error[E0004]: non-exhaustive patterns: `u128::MAX` not covered - --> $DIR/exhaustiveness.rs:59:8 + --> $DIR/exhaustiveness.rs:60:8 | LL | m!(0u128, 0..=ALMOST_MAX); | ^^^^^ pattern `u128::MAX` not covered @@ -108,7 +108,7 @@ LL | match $s { $($t)+ => {}, u128::MAX => todo!() } | ++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `5_u128..=u128::MAX` not covered - --> $DIR/exhaustiveness.rs:60:8 + --> $DIR/exhaustiveness.rs:61:8 | LL | m!(0u128, 0..=4); | ^^^^^ pattern `5_u128..=u128::MAX` not covered @@ -120,7 +120,7 @@ LL | match $s { $($t)+ => {}, 5_u128..=u128::MAX => todo!() } | +++++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `0_u128` not covered - --> $DIR/exhaustiveness.rs:61:8 + --> $DIR/exhaustiveness.rs:62:8 | LL | m!(0u128, 1..=u128::MAX); | ^^^^^ pattern `0_u128` not covered @@ -132,7 +132,7 @@ LL | match $s { $($t)+ => {}, 0_u128 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `(126_u8..=127_u8, false)` not covered - --> $DIR/exhaustiveness.rs:69:11 + --> $DIR/exhaustiveness.rs:70:11 | LL | match (0u8, true) { | ^^^^^^^^^^^ pattern `(126_u8..=127_u8, false)` not covered diff --git a/tests/ui/pattern/usefulness/integer-ranges/gap_between_ranges.rs b/tests/ui/pattern/usefulness/integer-ranges/gap_between_ranges.rs new file mode 100644 index 0000000000000..78849d7e14325 --- /dev/null +++ b/tests/ui/pattern/usefulness/integer-ranges/gap_between_ranges.rs @@ -0,0 +1,117 @@ +#![feature(exclusive_range_pattern)] +#![deny(non_contiguous_range_endpoints)] + +macro_rules! m { + ($s:expr, $t1:pat, $t2:pat) => { + match $s { + $t1 => {} + $t2 => {} + _ => {} + } + }; +} + +fn main() { + match 0u8 { + 20..30 => {} //~ ERROR multiple ranges are one apart + 31..=40 => {} + _ => {} + } + match 0u8 { + 20..30 => {} //~ ERROR multiple ranges are one apart + 31 => {} + _ => {} + } + + m!(0u8, 20..30, 31..=40); //~ ERROR multiple ranges are one apart + m!(0u8, 31..=40, 20..30); //~ ERROR multiple ranges are one apart + m!(0u8, 20..30, 29..=40); //~ WARN multiple patterns overlap on their endpoints + m!(0u8, 20..30, 30..=40); + m!(0u8, 20..30, 31..=40); //~ ERROR multiple ranges are one apart + m!(0u8, 20..30, 32..=40); + m!(0u8, 20..30, 31..=32); //~ ERROR multiple ranges are one apart + // Don't lint two singletons. + m!(0u8, 30, 32); + // Don't lint on the equivalent inclusive range + m!(0u8, 20..=29, 31..=40); + // Don't lint if the lower one is a singleton. + m!(0u8, 30, 32..=40); + + // Catch the `lo..MAX` case. + match 0u8 { + 0..255 => {} //~ ERROR exclusive range missing `u8::MAX` + _ => {} + } + // Except for `usize`, since `0..=usize::MAX` isn't exhaustive either. + match 0usize { + 0..usize::MAX => {} + _ => {} + } + + // Don't lint if the gap is caught by another range. + match 0u8 { + 0..10 => {} + 11..20 => {} + 10 => {} + _ => {} + } + match 0u8 { + 0..10 => {} + 11..20 => {} + 5..15 => {} + _ => {} + } + match 0u8 { + 0..255 => {} + 255 => {} + } + + // Test multiple at once + match 0u8 { + 0..10 => {} //~ ERROR multiple ranges are one apart + 11..20 => {} + 11..30 => {} + _ => {} + } + match 0u8 { + 0..10 => {} //~ ERROR multiple ranges are one apart + 11..20 => {} //~ ERROR multiple ranges are one apart + 21..30 => {} + _ => {} + } + match 0u8 { + 00..20 => {} //~ ERROR multiple ranges are one apart + 10..20 => {} //~ ERROR multiple ranges are one apart + 21..30 => {} + 21..40 => {} + _ => {} + } + + // Test nested + match (0u8, true) { + (0..10, true) => {} //~ ERROR multiple ranges are one apart + (11..20, true) => {} + _ => {} + } + match (true, 0u8) { + (true, 0..10) => {} //~ ERROR multiple ranges are one apart + (true, 11..20) => {} + _ => {} + } + // Asymmetry due to how exhaustiveness is computed. + match (0u8, true) { + (0..10, true) => {} //~ ERROR multiple ranges are one apart + (11..20, false) => {} + _ => {} + } + match (true, 0u8) { + (true, 0..10) => {} + (false, 11..20) => {} + _ => {} + } + match Some(0u8) { + Some(0..10) => {} //~ ERROR multiple ranges are one apart + Some(11..20) => {} + _ => {} + } +} diff --git a/tests/ui/pattern/usefulness/integer-ranges/gap_between_ranges.stderr b/tests/ui/pattern/usefulness/integer-ranges/gap_between_ranges.stderr new file mode 100644 index 0000000000000..e5c2d788ba4ef --- /dev/null +++ b/tests/ui/pattern/usefulness/integer-ranges/gap_between_ranges.stderr @@ -0,0 +1,193 @@ +error: multiple ranges are one apart + --> $DIR/gap_between_ranges.rs:16:9 + | +LL | 20..30 => {} + | ^^^^^^ + | | + | this range doesn't match `30_u8` because `..` is an exclusive range + | help: use an inclusive range instead: `20_u8..=30_u8` +LL | 31..=40 => {} + | ------- this could appear to continue range `20_u8..30_u8`, but `30_u8` isn't matched by either of them + | +note: the lint level is defined here + --> $DIR/gap_between_ranges.rs:2:9 + | +LL | #![deny(non_contiguous_range_endpoints)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: multiple ranges are one apart + --> $DIR/gap_between_ranges.rs:21:9 + | +LL | 20..30 => {} + | ^^^^^^ + | | + | this range doesn't match `30_u8` because `..` is an exclusive range + | help: use an inclusive range instead: `20_u8..=30_u8` +LL | 31 => {} + | -- this could appear to continue range `20_u8..30_u8`, but `30_u8` isn't matched by either of them + +error: multiple ranges are one apart + --> $DIR/gap_between_ranges.rs:26:13 + | +LL | m!(0u8, 20..30, 31..=40); + | ^^^^^^ ------- this could appear to continue range `20_u8..30_u8`, but `30_u8` isn't matched by either of them + | | + | this range doesn't match `30_u8` because `..` is an exclusive range + | help: use an inclusive range instead: `20_u8..=30_u8` + +error: multiple ranges are one apart + --> $DIR/gap_between_ranges.rs:27:22 + | +LL | m!(0u8, 31..=40, 20..30); + | ------- ^^^^^^ + | | | + | | this range doesn't match `30_u8` because `..` is an exclusive range + | | help: use an inclusive range instead: `20_u8..=30_u8` + | this could appear to continue range `20_u8..30_u8`, but `30_u8` isn't matched by either of them + +warning: multiple patterns overlap on their endpoints + --> $DIR/gap_between_ranges.rs:28:21 + | +LL | m!(0u8, 20..30, 29..=40); + | ------ ^^^^^^^ ... with this range + | | + | this range overlaps on `29_u8`... + | + = note: you likely meant to write mutually exclusive ranges + = note: `#[warn(overlapping_range_endpoints)]` on by default + +error: multiple ranges are one apart + --> $DIR/gap_between_ranges.rs:30:13 + | +LL | m!(0u8, 20..30, 31..=40); + | ^^^^^^ ------- this could appear to continue range `20_u8..30_u8`, but `30_u8` isn't matched by either of them + | | + | this range doesn't match `30_u8` because `..` is an exclusive range + | help: use an inclusive range instead: `20_u8..=30_u8` + +error: multiple ranges are one apart + --> $DIR/gap_between_ranges.rs:32:13 + | +LL | m!(0u8, 20..30, 31..=32); + | ^^^^^^ ------- this could appear to continue range `20_u8..30_u8`, but `30_u8` isn't matched by either of them + | | + | this range doesn't match `30_u8` because `..` is an exclusive range + | help: use an inclusive range instead: `20_u8..=30_u8` + +error: exclusive range missing `u8::MAX` + --> $DIR/gap_between_ranges.rs:42:9 + | +LL | 0..255 => {} + | ^^^^^^ + | | + | this range doesn't match `u8::MAX` because `..` is an exclusive range + | help: use an inclusive range instead: `0_u8..=u8::MAX` + +error: multiple ranges are one apart + --> $DIR/gap_between_ranges.rs:71:9 + | +LL | 0..10 => {} + | ^^^^^ + | | + | this range doesn't match `10_u8` because `..` is an exclusive range + | help: use an inclusive range instead: `0_u8..=10_u8` +LL | 11..20 => {} + | ------ this could appear to continue range `0_u8..10_u8`, but `10_u8` isn't matched by either of them +LL | 11..30 => {} + | ------ this could appear to continue range `0_u8..10_u8`, but `10_u8` isn't matched by either of them + +error: multiple ranges are one apart + --> $DIR/gap_between_ranges.rs:77:9 + | +LL | 0..10 => {} + | ^^^^^ + | | + | this range doesn't match `10_u8` because `..` is an exclusive range + | help: use an inclusive range instead: `0_u8..=10_u8` +LL | 11..20 => {} + | ------ this could appear to continue range `0_u8..10_u8`, but `10_u8` isn't matched by either of them + +error: multiple ranges are one apart + --> $DIR/gap_between_ranges.rs:78:9 + | +LL | 11..20 => {} + | ^^^^^^ + | | + | this range doesn't match `20_u8` because `..` is an exclusive range + | help: use an inclusive range instead: `11_u8..=20_u8` +LL | 21..30 => {} + | ------ this could appear to continue range `11_u8..20_u8`, but `20_u8` isn't matched by either of them + +error: multiple ranges are one apart + --> $DIR/gap_between_ranges.rs:83:9 + | +LL | 00..20 => {} + | ^^^^^^ + | | + | this range doesn't match `20_u8` because `..` is an exclusive range + | help: use an inclusive range instead: `0_u8..=20_u8` +LL | 10..20 => {} +LL | 21..30 => {} + | ------ this could appear to continue range `0_u8..20_u8`, but `20_u8` isn't matched by either of them +LL | 21..40 => {} + | ------ this could appear to continue range `0_u8..20_u8`, but `20_u8` isn't matched by either of them + +error: multiple ranges are one apart + --> $DIR/gap_between_ranges.rs:84:9 + | +LL | 10..20 => {} + | ^^^^^^ + | | + | this range doesn't match `20_u8` because `..` is an exclusive range + | help: use an inclusive range instead: `10_u8..=20_u8` +LL | 21..30 => {} + | ------ this could appear to continue range `10_u8..20_u8`, but `20_u8` isn't matched by either of them +LL | 21..40 => {} + | ------ this could appear to continue range `10_u8..20_u8`, but `20_u8` isn't matched by either of them + +error: multiple ranges are one apart + --> $DIR/gap_between_ranges.rs:92:10 + | +LL | (0..10, true) => {} + | ^^^^^ + | | + | this range doesn't match `10_u8` because `..` is an exclusive range + | help: use an inclusive range instead: `0_u8..=10_u8` +LL | (11..20, true) => {} + | ------ this could appear to continue range `0_u8..10_u8`, but `10_u8` isn't matched by either of them + +error: multiple ranges are one apart + --> $DIR/gap_between_ranges.rs:97:16 + | +LL | (true, 0..10) => {} + | ^^^^^ + | | + | this range doesn't match `10_u8` because `..` is an exclusive range + | help: use an inclusive range instead: `0_u8..=10_u8` +LL | (true, 11..20) => {} + | ------ this could appear to continue range `0_u8..10_u8`, but `10_u8` isn't matched by either of them + +error: multiple ranges are one apart + --> $DIR/gap_between_ranges.rs:103:10 + | +LL | (0..10, true) => {} + | ^^^^^ + | | + | this range doesn't match `10_u8` because `..` is an exclusive range + | help: use an inclusive range instead: `0_u8..=10_u8` +LL | (11..20, false) => {} + | ------ this could appear to continue range `0_u8..10_u8`, but `10_u8` isn't matched by either of them + +error: multiple ranges are one apart + --> $DIR/gap_between_ranges.rs:113:14 + | +LL | Some(0..10) => {} + | ^^^^^ + | | + | this range doesn't match `10_u8` because `..` is an exclusive range + | help: use an inclusive range instead: `0_u8..=10_u8` +LL | Some(11..20) => {} + | ------ this could appear to continue range `0_u8..10_u8`, but `10_u8` isn't matched by either of them + +error: aborting due to 16 previous errors; 1 warning emitted + diff --git a/tests/ui/pattern/usefulness/integer-ranges/reachability.rs b/tests/ui/pattern/usefulness/integer-ranges/reachability.rs index 247fdd91572cd..13b84e2c44bc1 100644 --- a/tests/ui/pattern/usefulness/integer-ranges/reachability.rs +++ b/tests/ui/pattern/usefulness/integer-ranges/reachability.rs @@ -1,5 +1,6 @@ #![feature(exclusive_range_pattern)] #![allow(overlapping_range_endpoints)] +#![allow(non_contiguous_range_endpoints)] #![deny(unreachable_patterns)] macro_rules! m { diff --git a/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr b/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr index c5b028d2038c3..0f52dfd83b9cb 100644 --- a/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr +++ b/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr @@ -1,137 +1,137 @@ error: unreachable pattern - --> $DIR/reachability.rs:18:17 + --> $DIR/reachability.rs:19:17 | LL | m!(0u8, 42, 42); | ^^ | note: the lint level is defined here - --> $DIR/reachability.rs:3:9 + --> $DIR/reachability.rs:4:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/reachability.rs:22:22 + --> $DIR/reachability.rs:23:22 | LL | m!(0u8, 20..=30, 20); | ^^ error: unreachable pattern - --> $DIR/reachability.rs:23:22 + --> $DIR/reachability.rs:24:22 | LL | m!(0u8, 20..=30, 21); | ^^ error: unreachable pattern - --> $DIR/reachability.rs:24:22 + --> $DIR/reachability.rs:25:22 | LL | m!(0u8, 20..=30, 25); | ^^ error: unreachable pattern - --> $DIR/reachability.rs:25:22 + --> $DIR/reachability.rs:26:22 | LL | m!(0u8, 20..=30, 29); | ^^ error: unreachable pattern - --> $DIR/reachability.rs:26:22 + --> $DIR/reachability.rs:27:22 | LL | m!(0u8, 20..=30, 30); | ^^ error: unreachable pattern - --> $DIR/reachability.rs:29:21 + --> $DIR/reachability.rs:30:21 | LL | m!(0u8, 20..30, 20); | ^^ error: unreachable pattern - --> $DIR/reachability.rs:30:21 + --> $DIR/reachability.rs:31:21 | LL | m!(0u8, 20..30, 21); | ^^ error: unreachable pattern - --> $DIR/reachability.rs:31:21 + --> $DIR/reachability.rs:32:21 | LL | m!(0u8, 20..30, 25); | ^^ error: unreachable pattern - --> $DIR/reachability.rs:32:21 + --> $DIR/reachability.rs:33:21 | LL | m!(0u8, 20..30, 29); | ^^ error: unreachable pattern - --> $DIR/reachability.rs:36:22 + --> $DIR/reachability.rs:37:22 | LL | m!(0u8, 20..=30, 20..=30); | ^^^^^^^ error: unreachable pattern - --> $DIR/reachability.rs:37:22 + --> $DIR/reachability.rs:38:22 | LL | m!(0u8, 20.. 30, 20.. 30); | ^^^^^^^ error: unreachable pattern - --> $DIR/reachability.rs:38:22 + --> $DIR/reachability.rs:39:22 | LL | m!(0u8, 20..=30, 20.. 30); | ^^^^^^^ error: unreachable pattern - --> $DIR/reachability.rs:40:22 + --> $DIR/reachability.rs:41:22 | LL | m!(0u8, 20..=30, 21..=30); | ^^^^^^^ error: unreachable pattern - --> $DIR/reachability.rs:41:22 + --> $DIR/reachability.rs:42:22 | LL | m!(0u8, 20..=30, 20..=29); | ^^^^^^^ error: unreachable pattern - --> $DIR/reachability.rs:43:24 + --> $DIR/reachability.rs:44:24 | LL | m!('a', 'A'..='z', 'a'..='z'); | ^^^^^^^^^ error: unreachable pattern - --> $DIR/reachability.rs:50:9 + --> $DIR/reachability.rs:51:9 | LL | 5..=8 => {}, | ^^^^^ error: unreachable pattern - --> $DIR/reachability.rs:56:9 + --> $DIR/reachability.rs:57:9 | LL | 5..15 => {}, | ^^^^^ error: unreachable pattern - --> $DIR/reachability.rs:63:9 + --> $DIR/reachability.rs:64:9 | LL | 5..25 => {}, | ^^^^^ error: unreachable pattern - --> $DIR/reachability.rs:71:9 + --> $DIR/reachability.rs:72:9 | LL | 5..25 => {}, | ^^^^^ error: unreachable pattern - --> $DIR/reachability.rs:77:9 + --> $DIR/reachability.rs:78:9 | LL | 5..15 => {}, | ^^^^^ error: unreachable pattern - --> $DIR/reachability.rs:84:9 + --> $DIR/reachability.rs:85:9 | LL | _ => {}, | - matches any value @@ -139,19 +139,19 @@ LL | '\u{D7FF}'..='\u{E000}' => {}, | ^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern error: unreachable pattern - --> $DIR/reachability.rs:89:9 + --> $DIR/reachability.rs:90:9 | LL | '\u{D7FF}'..='\u{E000}' => {}, | ^^^^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/reachability.rs:105:9 + --> $DIR/reachability.rs:106:9 | LL | &FOO => {} | ^^^^ error: unreachable pattern - --> $DIR/reachability.rs:106:9 + --> $DIR/reachability.rs:107:9 | LL | BAR => {} | ^^^ diff --git a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs index 8567d812e4fb2..29793e9f7347d 100644 --- a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs +++ b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs @@ -14,7 +14,7 @@ struct PriorityQueueEntry { //~^ ERROR can't compare `PriorityQueue` with `PriorityQueue` //~| ERROR the trait bound `PriorityQueue: Eq` is not satisfied //~| ERROR can't compare `T` with `T` -//~| ERROR `BinaryHeap>` is not an iterator +//~| ERROR no method named `cmp` found for struct `BinaryHeap>` //~| ERROR no field `height` on type `&PriorityQueue` struct PriorityQueue(BinaryHeap>); diff --git a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr index 6fa639877d3b1..0fe560afcb5d3 100644 --- a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr +++ b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr @@ -46,15 +46,12 @@ LL | struct PriorityQueue(BinaryHeap>); = help: the trait `PartialOrd<_>` is not implemented for `BinaryHeap>` = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0599]: `BinaryHeap>` is not an iterator +error[E0599]: no method named `cmp` found for struct `BinaryHeap>` in the current scope --> $DIR/issue-104884-trait-impl-sugg-err.rs:13:22 | LL | #[derive(PartialOrd, AddImpl)] | ^^^^^^^ `BinaryHeap>` is not an iterator | - = note: the following trait bounds were not satisfied: - `BinaryHeap>: Iterator` - which is required by `&mut BinaryHeap>: Iterator` = note: this error originates in the derive macro `AddImpl` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0609]: no field `height` on type `&PriorityQueue` diff --git a/tests/ui/proc-macro/nested-macro-rules.rs b/tests/ui/proc-macro/nested-macro-rules.rs index 0dce3c408c203..2f0d85c4bbf88 100644 --- a/tests/ui/proc-macro/nested-macro-rules.rs +++ b/tests/ui/proc-macro/nested-macro-rules.rs @@ -5,6 +5,8 @@ //@ edition:2018 #![no_std] // Don't load unnecessary hygiene information from std +#![warn(non_local_definitions)] + extern crate std; extern crate nested_macro_rules; diff --git a/tests/ui/proc-macro/nested-macro-rules.stderr b/tests/ui/proc-macro/nested-macro-rules.stderr index 111be8827714f..270e9161b0330 100644 --- a/tests/ui/proc-macro/nested-macro-rules.stderr +++ b/tests/ui/proc-macro/nested-macro-rules.stderr @@ -12,7 +12,7 @@ LL | | } LL | | } | |_________^ | - ::: $DIR/nested-macro-rules.rs:21:5 + ::: $DIR/nested-macro-rules.rs:23:5 | LL | nested_macro_rules::outer_macro!(SecondStruct, SecondAttrStruct); | ---------------------------------------------------------------- in this macro invocation @@ -21,7 +21,11 @@ LL | nested_macro_rules::outer_macro!(SecondStruct, SecondAttrStruct); = note: a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue - = note: `#[warn(non_local_definitions)]` on by default +note: the lint level is defined here + --> $DIR/nested-macro-rules.rs:8:9 + | +LL | #![warn(non_local_definitions)] + | ^^^^^^^^^^^^^^^^^^^^^ warning: 1 warning emitted diff --git a/tests/ui/proc-macro/nested-macro-rules.stdout b/tests/ui/proc-macro/nested-macro-rules.stdout index 829cfdc0c33f5..5b678554b9e0f 100644 --- a/tests/ui/proc-macro/nested-macro-rules.stdout +++ b/tests/ui/proc-macro/nested-macro-rules.stdout @@ -25,7 +25,7 @@ PRINT-BANG INPUT (DISPLAY): SecondStruct PRINT-BANG INPUT (DEBUG): TokenStream [ Ident { ident: "SecondStruct", - span: $DIR/nested-macro-rules.rs:21:38: 21:50 (#15), + span: $DIR/nested-macro-rules.rs:23:38: 23:50 (#15), }, ] PRINT-ATTR INPUT (DISPLAY): struct SecondAttrStruct {} @@ -36,7 +36,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ }, Ident { ident: "SecondAttrStruct", - span: $DIR/nested-macro-rules.rs:21:52: 21:68 (#15), + span: $DIR/nested-macro-rules.rs:23:52: 23:68 (#15), }, Group { delimiter: Brace, diff --git a/tests/ui/process-termination/process-termination-blocking-io.rs b/tests/ui/process-termination/process-termination-blocking-io.rs index c21edff25cf7c..f725a95894162 100644 --- a/tests/ui/process-termination/process-termination-blocking-io.rs +++ b/tests/ui/process-termination/process-termination-blocking-io.rs @@ -2,7 +2,7 @@ // https://github.com/fortanix/rust-sgx/issues/109 //@ run-pass -//@ ignore-emscripten no threads support +//@ needs-threads use std::{net::TcpListener, sync::mpsc, thread}; diff --git a/tests/ui/process-termination/process-termination-simple.rs b/tests/ui/process-termination/process-termination-simple.rs index 63eb2c747068b..8f5f185b7f9b9 100644 --- a/tests/ui/process-termination/process-termination-simple.rs +++ b/tests/ui/process-termination/process-termination-simple.rs @@ -1,7 +1,7 @@ // program should terminate when std::process::exit is called from any thread //@ run-pass -//@ ignore-emscripten no threads support +//@ needs-threads use std::{process, thread}; diff --git a/tests/ui/resolve/auxiliary/proc_macro_generate_packed.rs b/tests/ui/resolve/auxiliary/proc_macro_generate_packed.rs new file mode 100644 index 0000000000000..c0b24706dcba6 --- /dev/null +++ b/tests/ui/resolve/auxiliary/proc_macro_generate_packed.rs @@ -0,0 +1,27 @@ +//@ force-host +//@ no-prefer-dynamic +//@ compile-flags: --crate-type proc-macro + +extern crate proc_macro; + +use proc_macro::*; + +#[proc_macro_attribute] +pub fn proc_macro_attribute_that_generates_repr_packed( + _attr: TokenStream, + item: TokenStream, +) -> TokenStream { + let repr = vec![TokenTree::Ident(Ident::new("packed", Span::call_site()))].into_iter(); + let attr = vec![ + TokenTree::Ident(Ident::new("repr", Span::call_site())), + TokenTree::Group(Group::new(Delimiter::Parenthesis, repr.collect())), + ] + .into_iter(); + vec![ + TokenTree::Punct(Punct::new('#', Spacing::Alone)), + TokenTree::Group(Group::new(Delimiter::Bracket, attr.collect())), + ] + .into_iter() + .chain(item) + .collect() +} diff --git a/tests/ui/resolve/multiple_definitions_attribute_merging.rs b/tests/ui/resolve/multiple_definitions_attribute_merging.rs new file mode 100644 index 0000000000000..523717861e1ba --- /dev/null +++ b/tests/ui/resolve/multiple_definitions_attribute_merging.rs @@ -0,0 +1,19 @@ +//! This test ICEs because the `repr(packed)` attributes +//! end up on the `Dealigned` struct's attribute list, but the +//! derive didn't see that. + +//@known-bug: #120873 +//@ failure-status: 101 +//@ normalize-stderr-test "note: .*\n\n" -> "" +//@ normalize-stderr-test "thread 'rustc' panicked.*\n" -> "" +//@ normalize-stderr-test "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: " +//@ rustc-env:RUST_BACKTRACE=0 + +#[repr(packed)] +struct Dealigned(u8, T); + +#[derive(PartialEq)] +#[repr(C)] +struct Dealigned(u8, T); + +fn main() {} diff --git a/tests/ui/resolve/multiple_definitions_attribute_merging.stderr b/tests/ui/resolve/multiple_definitions_attribute_merging.stderr new file mode 100644 index 0000000000000..b2d20af883abb --- /dev/null +++ b/tests/ui/resolve/multiple_definitions_attribute_merging.stderr @@ -0,0 +1,26 @@ +error[E0428]: the name `Dealigned` is defined multiple times + --> $DIR/multiple_definitions_attribute_merging.rs:17:1 + | +LL | struct Dealigned(u8, T); + | --------------------------- previous definition of the type `Dealigned` here +... +LL | struct Dealigned(u8, T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Dealigned` redefined here + | + = error: internal compiler error: compiler/rustc_mir_transform/src/check_packed_ref.rs:LL:CC: builtin derive created an unaligned reference + --> $DIR/multiple_definitions_attribute_merging.rs:17:25 + | +LL | #[derive(PartialEq)] + | --------- in this derive macro expansion +LL | #[repr(C)] +LL | struct Dealigned(u8, T); + | ^ + | + = Box +query stack during panic: +#0 [mir_const] preparing `::eq` for borrow checking +#1 [mir_promoted] promoting constants in MIR for `::eq` +end of query stack +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/resolve/proc_macro_generated_packed.rs b/tests/ui/resolve/proc_macro_generated_packed.rs new file mode 100644 index 0000000000000..34a7e4db6030d --- /dev/null +++ b/tests/ui/resolve/proc_macro_generated_packed.rs @@ -0,0 +1,20 @@ +//! This test ICEs because the `repr(packed)` attribute +//! was generated by a proc macro, so `#[derive]` didn't see it. + +//@aux-build: proc_macro_generate_packed.rs +//@known-bug: #120873 +//@ failure-status: 101 +//@ normalize-stderr-test "note: .*\n\n" -> "" +//@ normalize-stderr-test "thread 'rustc' panicked.*\n" -> "" +//@ normalize-stderr-test "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: " +//@ rustc-env:RUST_BACKTRACE=0 + +extern crate proc_macro_generate_packed; +use proc_macro_generate_packed::proc_macro_attribute_that_generates_repr_packed; + +#[derive(PartialEq)] +#[repr(C)] +#[proc_macro_attribute_that_generates_repr_packed] +struct Dealigned(u8, T); + +fn main() {} diff --git a/tests/ui/resolve/proc_macro_generated_packed.stderr b/tests/ui/resolve/proc_macro_generated_packed.stderr new file mode 100644 index 0000000000000..507e5867c904b --- /dev/null +++ b/tests/ui/resolve/proc_macro_generated_packed.stderr @@ -0,0 +1,16 @@ +error: internal compiler error: compiler/rustc_mir_transform/src/check_packed_ref.rs:LL:CC: builtin derive created an unaligned reference + --> $DIR/proc_macro_generated_packed.rs:18:25 + | +LL | #[derive(PartialEq)] + | --------- in this derive macro expansion +... +LL | struct Dealigned(u8, T); + | ^ + | + = Box +query stack during panic: +#0 [mir_const] preparing `::eq` for borrow checking +#1 [mir_promoted] promoting constants in MIR for `::eq` +end of query stack +error: aborting due to 1 previous error + diff --git a/tests/ui/resolve/resolve-self-in-impl.stderr b/tests/ui/resolve/resolve-self-in-impl.stderr index 183a17171f7fc..62cfdb4dc78c1 100644 --- a/tests/ui/resolve/resolve-self-in-impl.stderr +++ b/tests/ui/resolve/resolve-self-in-impl.stderr @@ -14,6 +14,20 @@ LL | impl Tr for S {} | = note: replace `Self` with a different type +error[E0391]: cycle detected when computing trait implemented by `` + --> $DIR/resolve-self-in-impl.rs:19:1 + | +LL | impl Tr for S {} + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: ...which immediately requires computing trait implemented by `` again +note: cycle used when building specialization graph of trait `Tr` + --> $DIR/resolve-self-in-impl.rs:4:1 + | +LL | trait Tr { + | ^^^^^^^^^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + error: `Self` is not valid in the self type of an impl block --> $DIR/resolve-self-in-impl.rs:16:6 | @@ -38,26 +52,6 @@ LL | impl (Self, Self) {} | = note: replace `Self` with a different type -error[E0391]: cycle detected when computing trait implemented by `` - --> $DIR/resolve-self-in-impl.rs:19:1 - | -LL | impl Tr for S {} - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: ...which immediately requires computing trait implemented by `` again -note: cycle used when collecting item types in top-level module - --> $DIR/resolve-self-in-impl.rs:1:1 - | -LL | / #![feature(associated_type_defaults)] -LL | | -LL | | struct S(T); -LL | | trait Tr { -... | -LL | | -LL | | fn main() {} - | |____________^ - = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information - error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.stderr index eb0f18edd3401..00efbb52f159b 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.stderr +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.stderr @@ -1,5 +1,5 @@ error: `#[target_feature(..)]` cannot be applied to safe trait method - --> $DIR/trait-impl.rs:22:5 + --> $DIR/trait-impl.rs:13:5 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot be applied to safe trait method @@ -8,7 +8,7 @@ LL | fn foo(&self) {} | ------------- not an `unsafe` function error: `#[target_feature(..)]` cannot be applied to safe trait method - --> $DIR/trait-impl.rs:13:5 + --> $DIR/trait-impl.rs:22:5 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot be applied to safe trait method diff --git a/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.rs b/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.rs index 5053c115b4537..c9dc1c6e6498b 100644 --- a/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.rs +++ b/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.rs @@ -17,5 +17,5 @@ fn stuff(_: T) {} fn main() { stuff(1u8); - //~^ the trait bound `u8: Foo` is not satisfied + //~^ the trait bound `u8: Bar` is not satisfied } diff --git a/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr b/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr index 99d318a793364..284dacf7000bd 100644 --- a/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr +++ b/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr @@ -1,4 +1,4 @@ -error[E0277]: the trait bound `u8: Foo` is not satisfied +error[E0277]: the trait bound `u8: Bar` is not satisfied --> $DIR/feature-gate-do_not_recommend.rs:19:11 | LL | stuff(1u8); diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.stderr index 8f374bc4d8f27..e45c1a1f46fb6 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.stderr @@ -13,6 +13,15 @@ LL | impl const Default for A { = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change +error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates + --> $DIR/derive-const-use.rs:7:6 + | +LL | impl const Default for A { + | ^^^^^ unconstrained const parameter + | + = note: expressions using a const parameter must map each value to a distinct output value + = note: proving the result of expressions other than the parameter are unique is not supported + error: const `impl` for trait `Default` which is not marked with `#[const_trait]` --> $DIR/derive-const-use.rs:15:16 | @@ -24,20 +33,23 @@ LL | #[derive_const(Default, PartialEq)] = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates - --> $DIR/derive-const-use.rs:7:6 - | -LL | impl const Default for A { - | ^^^^^ unconstrained const parameter | = note: expressions using a const parameter must map each value to a distinct output value = note: proving the result of expressions other than the parameter are unique is not supported -error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates +error[E0308]: mismatched types + --> $DIR/derive-const-use.rs:16:14 | - = note: expressions using a const parameter must map each value to a distinct output value - = note: proving the result of expressions other than the parameter are unique is not supported +LL | #[derive_const(Default, PartialEq)] + | --------- in this derive macro expansion +LL | pub struct S((), A); + | ^^ expected `host`, found `true` + | + = note: expected constant `host` + found constant `true` + = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors -Some errors have detailed explanations: E0207, E0635. +Some errors have detailed explanations: E0207, E0308, E0635. For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs index 5ee38078a2950..1b380c989fa4a 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs @@ -511,6 +511,7 @@ const fn drop(_: T) {} extern "rust-intrinsic" { #[rustc_const_stable(feature = "const_eval_select", since = "1.0.0")] + #[rustc_safe_intrinsic] fn const_eval_select( arg: ARG, called_in_const: F, @@ -525,5 +526,5 @@ fn test_const_eval_select() { const fn const_fn() {} fn rt_fn() {} - unsafe { const_eval_select((), const_fn, rt_fn); } + const_eval_select((), const_fn, rt_fn); } diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.rs index 97e89f96fe1b0..7bead45b35ab7 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.rs @@ -8,6 +8,8 @@ impl const dyn T { //~^ ERROR inherent impls cannot be `const` //~| ERROR the const parameter `host` is not constrained by the impl trait, self type, or pub const fn new() -> std::sync::Mutex {} + //~^ ERROR mismatched types + //~| ERROR cannot be known at compilation time } fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.stderr index 11577d9ec1d0f..3ff1efb59883d 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.stderr @@ -17,6 +17,29 @@ LL | impl const dyn T { = note: expressions using a const parameter must map each value to a distinct output value = note: proving the result of expressions other than the parameter are unique is not supported -error: aborting due to 2 previous errors +error[E0308]: mismatched types + --> $DIR/span-bug-issue-121418.rs:10:27 + | +LL | pub const fn new() -> std::sync::Mutex {} + | --- ^^^^^^^^^^^^^^^^^^^^^^^ expected `Mutex`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + | + = note: expected struct `Mutex<(dyn T + 'static)>` + found unit type `()` + +error[E0277]: the size for values of type `(dyn T + 'static)` cannot be known at compilation time + --> $DIR/span-bug-issue-121418.rs:10:27 + | +LL | pub const fn new() -> std::sync::Mutex {} + | ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `Mutex<(dyn T + 'static)>`, the trait `Sized` is not implemented for `(dyn T + 'static)`, which is required by `Mutex<(dyn T + 'static)>: Sized` +note: required because it appears within the type `Mutex<(dyn T + 'static)>` + --> $SRC_DIR/std/src/sync/mutex.rs:LL:COL + = note: the return type of a function must have a statically known size + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0207`. +Some errors have detailed explanations: E0207, E0277, E0308. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr index 2c63c0217aba1..77aee6a8bb8f8 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr @@ -24,12 +24,6 @@ LL | trait Bar: ~const Foo {} | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:18:24 - | -LL | const fn foo(x: &T) { - | ^^^ - error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/super-traits-fail-3.rs:12:19 | @@ -38,5 +32,11 @@ LL | trait Bar: ~const Foo {} | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/super-traits-fail-3.rs:18:24 + | +LL | const fn foo(x: &T) { + | ^^^ + error: aborting due to 5 previous errors diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr index 92a9c347a075e..8151b9aaa23de 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr @@ -262,16 +262,6 @@ LL | const CONSTANT: () = (); = help: add `#![feature(generic_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: inherent associated types are unstable - --> $DIR/tilde-const-invalid-places.rs:44:5 - | -LL | type Type = (); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #8995 for more information - = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error[E0392]: type parameter `T` is never used --> $DIR/tilde-const-invalid-places.rs:11:19 | @@ -304,6 +294,16 @@ note: required by a bound in `NonConstTrait::Type` LL | type Type: ~const Trait; | ^^^^^^^^^^^^ required by this bound in `NonConstTrait::Type` +error[E0658]: inherent associated types are unstable + --> $DIR/tilde-const-invalid-places.rs:44:5 + | +LL | type Type = (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #8995 for more information + = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + error: aborting due to 30 previous errors Some errors have detailed explanations: E0275, E0392, E0658, E0740. diff --git a/tests/ui/shell-argfiles/shell-argfiles-badquotes-windows.stderr b/tests/ui/shell-argfiles/shell-argfiles-badquotes-windows.stderr index 14adb1f740abb..dc219c153f781 100644 --- a/tests/ui/shell-argfiles/shell-argfiles-badquotes-windows.stderr +++ b/tests/ui/shell-argfiles/shell-argfiles-badquotes-windows.stderr @@ -1,2 +1,2 @@ -error: Failed to load argument file: Invalid shell-style arguments in $DIR/shell-argfiles-badquotes.args +error: failed to load argument file: invalid shell-style arguments in $DIR/shell-argfiles-badquotes.args diff --git a/tests/ui/shell-argfiles/shell-argfiles-badquotes.stderr b/tests/ui/shell-argfiles/shell-argfiles-badquotes.stderr index 14adb1f740abb..dc219c153f781 100644 --- a/tests/ui/shell-argfiles/shell-argfiles-badquotes.stderr +++ b/tests/ui/shell-argfiles/shell-argfiles-badquotes.stderr @@ -1,2 +1,2 @@ -error: Failed to load argument file: Invalid shell-style arguments in $DIR/shell-argfiles-badquotes.args +error: failed to load argument file: invalid shell-style arguments in $DIR/shell-argfiles-badquotes.args diff --git a/tests/ui/span/issue-35987.rs b/tests/ui/span/issue-35987.rs index 3a6e6ffe24910..d52a3793af971 100644 --- a/tests/ui/span/issue-35987.rs +++ b/tests/ui/span/issue-35987.rs @@ -7,6 +7,7 @@ impl Add for Foo { type Output = usize; fn add(self, rhs: Self) -> Self::Output { + //~^ ERROR ambiguous associated type unimplemented!(); } } diff --git a/tests/ui/span/issue-35987.stderr b/tests/ui/span/issue-35987.stderr index d3014f276fd84..36c59137b3125 100644 --- a/tests/ui/span/issue-35987.stderr +++ b/tests/ui/span/issue-35987.stderr @@ -9,6 +9,20 @@ LL | impl Add for Foo { | | | found this type parameter -error: aborting due to 1 previous error +error[E0223]: ambiguous associated type + --> $DIR/issue-35987.rs:9:32 + | +LL | fn add(self, rhs: Self) -> Self::Output { + | ^^^^^^^^^^^^ + | +help: use fully-qualified syntax + | +LL | fn add(self, rhs: Self) -> as BitOr>::Output { + | ~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | fn add(self, rhs: Self) -> as IntoFuture>::Output { + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0404`. +Some errors have detailed explanations: E0223, E0404. +For more information about an error, try `rustc --explain E0223`. diff --git a/tests/ui/structs-enums/ivec-tag.rs b/tests/ui/structs-enums/ivec-tag.rs index 9185a0cbb6e93..2a0b6dd1ed482 100644 --- a/tests/ui/structs-enums/ivec-tag.rs +++ b/tests/ui/structs-enums/ivec-tag.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_must_use)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; use std::sync::mpsc::{channel, Sender}; diff --git a/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr index ec9826819c0e5..05e087fd9f9a6 100644 --- a/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr +++ b/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr @@ -7,7 +7,6 @@ LL | bar(foo); | required by a bound introduced by this call | = help: the trait `Future` is not implemented for fn item `fn() -> impl Future {foo}` - = note: fn() -> impl Future {foo} must be a future or must implement `IntoFuture` to be awaited note: required by a bound in `bar` --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:7:16 | @@ -27,7 +26,6 @@ LL | bar(async_closure); | required by a bound introduced by this call | = help: the trait `Future` is not implemented for `{async closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}` - = note: {async closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33} must be a future or must implement `IntoFuture` to be awaited note: required by a bound in `bar` --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:7:16 | diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr index a7d636b63bd27..61a2925f582b2 100644 --- a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr +++ b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr @@ -150,6 +150,14 @@ help: consider introducing a named lifetime parameter LL | fn g<'a>(mut x: impl Iterator) -> Option<&()> { x.next() } | ++++ ++ +error: lifetime may not live long enough + --> $DIR/impl-trait-missing-lifetime-gated.rs:19:67 + | +LL | async fn i(mut x: impl Iterator) -> Option<&()> { x.next() } + | ----------------------------------------------------------- ^^^^^^^^ returning this value requires that `'1` must outlive `'static` + | | + | return type `impl Future>` contains a lifetime `'1` + error[E0658]: anonymous lifetimes in `impl Trait` are unstable --> $DIR/impl-trait-missing-lifetime-gated.rs:25:35 | @@ -176,6 +184,14 @@ help: consider introducing a named lifetime parameter LL | fn g<'a>(mut x: impl Iterator) -> Option<&'_ ()> { x.next() } | ++++ ~~ +error: lifetime may not live long enough + --> $DIR/impl-trait-missing-lifetime-gated.rs:38:73 + | +LL | async fn i(mut x: impl Iterator) -> Option<&'_ ()> { x.next() } + | ----------------------------------------------------------------- ^^^^^^^^ returning this value requires that `'1` must outlive `'static` + | | + | return type `impl Future>` contains a lifetime `'1` + error[E0658]: anonymous lifetimes in `impl Trait` are unstable --> $DIR/impl-trait-missing-lifetime-gated.rs:46:18 | @@ -228,22 +244,6 @@ help: consider introducing a named lifetime parameter LL | fn g<'a>(mut x: impl Foo<'a, ()>) -> Option<&()> { x.next() } | ++++ +++ -error: lifetime may not live long enough - --> $DIR/impl-trait-missing-lifetime-gated.rs:19:67 - | -LL | async fn i(mut x: impl Iterator) -> Option<&()> { x.next() } - | ----------------------------------------------------------- ^^^^^^^^ returning this value requires that `'1` must outlive `'static` - | | - | return type `impl Future>` contains a lifetime `'1` - -error: lifetime may not live long enough - --> $DIR/impl-trait-missing-lifetime-gated.rs:38:73 - | -LL | async fn i(mut x: impl Iterator) -> Option<&'_ ()> { x.next() } - | ----------------------------------------------------------------- ^^^^^^^^ returning this value requires that `'1` must outlive `'static` - | | - | return type `impl Future>` contains a lifetime `'1` - error: aborting due to 16 previous errors Some errors have detailed explanations: E0106, E0658. diff --git a/tests/ui/suggestions/issue-104961.fixed b/tests/ui/suggestions/issue-104961.fixed index a4047def341e8..5def21b506e1c 100644 --- a/tests/ui/suggestions/issue-104961.fixed +++ b/tests/ui/suggestions/issue-104961.fixed @@ -2,12 +2,12 @@ fn foo(x: &str) -> bool { x.starts_with(&("hi".to_string() + " you")) - //~^ ERROR expected a `FnMut(char)` closure, found `String` + //~^ ERROR the trait bound `String: Pattern<'_>` is not satisfied [E0277] } fn foo2(x: &str) -> bool { x.starts_with(&"hi".to_string()) - //~^ ERROR expected a `FnMut(char)` closure, found `String` + //~^ ERROR the trait bound `String: Pattern<'_>` is not satisfied [E0277] } fn main() { diff --git a/tests/ui/suggestions/issue-104961.rs b/tests/ui/suggestions/issue-104961.rs index 9d02f570c84c5..a09b8a887114c 100644 --- a/tests/ui/suggestions/issue-104961.rs +++ b/tests/ui/suggestions/issue-104961.rs @@ -2,12 +2,12 @@ fn foo(x: &str) -> bool { x.starts_with("hi".to_string() + " you") - //~^ ERROR expected a `FnMut(char)` closure, found `String` + //~^ ERROR the trait bound `String: Pattern<'_>` is not satisfied [E0277] } fn foo2(x: &str) -> bool { x.starts_with("hi".to_string()) - //~^ ERROR expected a `FnMut(char)` closure, found `String` + //~^ ERROR the trait bound `String: Pattern<'_>` is not satisfied [E0277] } fn main() { diff --git a/tests/ui/suggestions/issue-104961.stderr b/tests/ui/suggestions/issue-104961.stderr index 7e795a74c9000..3c5f86817f3a4 100644 --- a/tests/ui/suggestions/issue-104961.stderr +++ b/tests/ui/suggestions/issue-104961.stderr @@ -1,4 +1,4 @@ -error[E0277]: expected a `FnMut(char)` closure, found `String` +error[E0277]: the trait bound `String: Pattern<'_>` is not satisfied --> $DIR/issue-104961.rs:4:19 | LL | x.starts_with("hi".to_string() + " you") @@ -6,7 +6,6 @@ LL | x.starts_with("hi".to_string() + " you") | | | required by a bound introduced by this call | - = note: the trait bound `String: Pattern<'_>` is not satisfied = note: required for `String` to implement `Pattern<'_>` note: required by a bound in `core::str::::starts_with` --> $SRC_DIR/core/src/str/mod.rs:LL:COL @@ -15,7 +14,7 @@ help: consider borrowing here LL | x.starts_with(&("hi".to_string() + " you")) | ++ + -error[E0277]: expected a `FnMut(char)` closure, found `String` +error[E0277]: the trait bound `String: Pattern<'_>` is not satisfied --> $DIR/issue-104961.rs:9:19 | LL | x.starts_with("hi".to_string()) @@ -23,7 +22,6 @@ LL | x.starts_with("hi".to_string()) | | | required by a bound introduced by this call | - = note: the trait bound `String: Pattern<'_>` is not satisfied = note: required for `String` to implement `Pattern<'_>` note: required by a bound in `core::str::::starts_with` --> $SRC_DIR/core/src/str/mod.rs:LL:COL diff --git a/tests/ui/suggestions/issue-62843.stderr b/tests/ui/suggestions/issue-62843.stderr index f3a9f6b7913aa..84ab4a0edd39c 100644 --- a/tests/ui/suggestions/issue-62843.stderr +++ b/tests/ui/suggestions/issue-62843.stderr @@ -1,4 +1,4 @@ -error[E0277]: expected a `FnMut(char)` closure, found `String` +error[E0277]: the trait bound `String: Pattern<'_>` is not satisfied --> $DIR/issue-62843.rs:4:32 | LL | println!("{:?}", line.find(pattern)); @@ -6,7 +6,6 @@ LL | println!("{:?}", line.find(pattern)); | | | required by a bound introduced by this call | - = note: the trait bound `String: Pattern<'_>` is not satisfied = note: required for `String` to implement `Pattern<'_>` note: required by a bound in `core::str::::find` --> $SRC_DIR/core/src/str/mod.rs:LL:COL diff --git a/tests/ui/suggestions/slice-issue-87994.rs b/tests/ui/suggestions/slice-issue-87994.rs index ecb7f54ea250a..5a2574fff8af8 100644 --- a/tests/ui/suggestions/slice-issue-87994.rs +++ b/tests/ui/suggestions/slice-issue-87994.rs @@ -1,16 +1,16 @@ fn main() { let v = vec![1i32, 2, 3]; for _ in v[1..] { - //~^ ERROR [i32]` is not an iterator [E0277] - //~^^ ERROR known at compilation time + //~^ ERROR `[i32]` is not an iterator [E0277] + //~| ERROR `[i32]` is not an iterator [E0277] } struct K { n: i32, } let mut v2 = vec![K { n: 1 }, K { n: 1 }, K { n: 1 }]; for i2 in v2[1..] { - //~^ ERROR [K]` is not an iterator [E0277] - //~^^ ERROR known at compilation time + //~^ ERROR `[K]` is not an iterator [E0277] + //~| ERROR `[K]` is not an iterator [E0277] i2.n = 2; } } diff --git a/tests/ui/suggestions/slice-issue-87994.stderr b/tests/ui/suggestions/slice-issue-87994.stderr index 656f71eb8773e..22ad5d352120d 100644 --- a/tests/ui/suggestions/slice-issue-87994.stderr +++ b/tests/ui/suggestions/slice-issue-87994.stderr @@ -13,7 +13,7 @@ LL | for _ in &v[1..] { LL | for _ in &mut v[1..] { | ++++ -error[E0277]: the size for values of type `[i32]` cannot be known at compilation time +error[E0277]: `[i32]` is not an iterator --> $DIR/slice-issue-87994.rs:3:12 | LL | for _ in v[1..] { @@ -21,6 +21,7 @@ LL | for _ in v[1..] { | = note: the trait bound `[i32]: IntoIterator` is not satisfied = note: required for `[i32]` to implement `IntoIterator` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider borrowing here | LL | for _ in &v[1..] { @@ -43,7 +44,7 @@ LL | for i2 in &v2[1..] { LL | for i2 in &mut v2[1..] { | ++++ -error[E0277]: the size for values of type `[K]` cannot be known at compilation time +error[E0277]: `[K]` is not an iterator --> $DIR/slice-issue-87994.rs:11:13 | LL | for i2 in v2[1..] { @@ -51,6 +52,7 @@ LL | for i2 in v2[1..] { | = note: the trait bound `[K]: IntoIterator` is not satisfied = note: required for `[K]` to implement `IntoIterator` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider borrowing here | LL | for i2 in &v2[1..] { diff --git a/tests/ui/suggestions/suggest-blanket-impl-local-trait.stderr b/tests/ui/suggestions/suggest-blanket-impl-local-trait.stderr index 398caa98b84db..769f3bd64f320 100644 --- a/tests/ui/suggestions/suggest-blanket-impl-local-trait.stderr +++ b/tests/ui/suggestions/suggest-blanket-impl-local-trait.stderr @@ -1,40 +1,3 @@ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/suggest-blanket-impl-local-trait.rs:13:24 - | -LL | impl LocalTraitTwo for LocalTraitOne {} - | ^^^^^^^^^^^^^ - | -help: add `dyn` keyword before this trait - | -LL | impl LocalTraitTwo for dyn LocalTraitOne {} - | +++ -help: alternatively use a blanket implementation to implement `LocalTraitTwo` for all types that also implement `LocalTraitOne` - | -LL | impl LocalTraitTwo for T {} - | ++++++++++++++++++ ~ - -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/suggest-blanket-impl-local-trait.rs:18:23 - | -LL | impl fmt::Display for LocalTraitOne { - | ^^^^^^^^^^^^^ - | -help: add `dyn` keyword before this trait - | -LL | impl fmt::Display for dyn LocalTraitOne { - | +++ - -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/suggest-blanket-impl-local-trait.rs:26:23 - | -LL | impl fmt::Display for LocalTraitTwo + Send { - | ^^^^^^^^^^^^^^^^^^^^ - | -help: add `dyn` keyword before this trait - | -LL | impl fmt::Display for dyn LocalTraitTwo + Send { - | +++ - error[E0782]: trait objects must include the `dyn` keyword --> $DIR/suggest-blanket-impl-local-trait.rs:34:24 | @@ -65,6 +28,21 @@ help: alternatively use a blanket implementation to implement `LocalTraitOne` fo LL | impl LocalTraitOne for T {} | ++++++++++++++++++++++++ ~ +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-blanket-impl-local-trait.rs:13:24 + | +LL | impl LocalTraitTwo for LocalTraitOne {} + | ^^^^^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL | impl LocalTraitTwo for dyn LocalTraitOne {} + | +++ +help: alternatively use a blanket implementation to implement `LocalTraitTwo` for all types that also implement `LocalTraitOne` + | +LL | impl LocalTraitTwo for T {} + | ++++++++++++++++++ ~ + error[E0782]: trait objects must include the `dyn` keyword --> $DIR/suggest-blanket-impl-local-trait.rs:46:29 | @@ -80,6 +58,28 @@ help: alternatively use a blanket implementation to implement `GenericTrait` LL | impl GenericTrait for T {} | ++++++++++++++++++ ~ +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-blanket-impl-local-trait.rs:18:23 + | +LL | impl fmt::Display for LocalTraitOne { + | ^^^^^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL | impl fmt::Display for dyn LocalTraitOne { + | +++ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-blanket-impl-local-trait.rs:26:23 + | +LL | impl fmt::Display for LocalTraitTwo + Send { + | ^^^^^^^^^^^^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL | impl fmt::Display for dyn LocalTraitTwo + Send { + | +++ + error[E0782]: trait objects must include the `dyn` keyword --> $DIR/suggest-blanket-impl-local-trait.rs:53:35 | diff --git a/tests/ui/suggestions/suggest-remove-refs-5.stderr b/tests/ui/suggestions/suggest-remove-refs-5.stderr index 6b2f330e1a36d..3b6994b45d109 100644 --- a/tests/ui/suggestions/suggest-remove-refs-5.stderr +++ b/tests/ui/suggestions/suggest-remove-refs-5.stderr @@ -1,10 +1,10 @@ -error[E0277]: `Vec` is not an iterator +error[E0277]: `&mut &mut &mut &mut Vec` is not an iterator --> $DIR/suggest-remove-refs-5.rs:4:14 | LL | for _ in &mut &mut v {} - | ^^^^^^^^^^^ `Vec` is not an iterator; try calling `.into_iter()` or `.iter()` + | ^^^^^^^^^^^ `&mut &mut &mut &mut Vec` is not an iterator | - = help: the trait `Iterator` is not implemented for `Vec`, which is required by `&mut &mut &mut &mut Vec: IntoIterator` + = help: the trait `Iterator` is not implemented for `&mut &mut &mut &mut Vec`, which is required by `&mut &mut &mut &mut Vec: IntoIterator` = note: required for `&mut Vec` to implement `Iterator` = note: 3 redundant requirements hidden = note: required for `&mut &mut &mut &mut Vec` to implement `Iterator` @@ -15,13 +15,13 @@ LL ~ let v = &mut Vec::::new(); LL ~ for _ in v {} | -error[E0277]: `[u8; 1]` is not an iterator +error[E0277]: `&mut &mut &mut [u8; 1]` is not an iterator --> $DIR/suggest-remove-refs-5.rs:7:14 | LL | for _ in &mut v {} - | ^^^^^^ `[u8; 1]` is not an iterator; try calling `.into_iter()` or `.iter()` + | ^^^^^^ `&mut &mut &mut [u8; 1]` is not an iterator | - = help: the trait `Iterator` is not implemented for `[u8; 1]`, which is required by `&mut &mut &mut [u8; 1]: IntoIterator` + = help: the trait `Iterator` is not implemented for `&mut &mut &mut [u8; 1]`, which is required by `&mut &mut &mut [u8; 1]: IntoIterator` = note: required for `&mut [u8; 1]` to implement `Iterator` = note: 2 redundant requirements hidden = note: required for `&mut &mut &mut [u8; 1]` to implement `Iterator` diff --git a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.rs b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.rs index c4384bce3a9b8..a5ab8be7f45a7 100644 --- a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.rs +++ b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.rs @@ -3,9 +3,12 @@ pub trait Trait<'a, T> {} pub struct Struct; +//~^ ERROR `T` is never used pub enum Enum {} +//~^ ERROR `T` is never used pub union Union { + //~^ ERROR `T` is never used f1: usize, } @@ -15,8 +18,10 @@ impl<'a, T> Struct for Trait<'a, T> {} impl<'a, T> Enum for Trait<'a, T> {} //~^ ERROR expected trait, found enum `Enum` +//~| ERROR trait objects must include the `dyn` keyword impl<'a, T> Union for Trait<'a, T> {} //~^ ERROR expected trait, found union `Union` +//~| ERROR trait objects must include the `dyn` keyword fn main() {} diff --git a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.stderr b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.stderr index 87e7164362091..2893370570d24 100644 --- a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.stderr +++ b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.stderr @@ -1,5 +1,5 @@ error[E0404]: expected trait, found struct `Struct` - --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:12:13 + --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:15:13 | LL | impl<'a, T> Struct for Trait<'a, T> {} | ^^^^^^^^^ not a trait @@ -10,7 +10,7 @@ LL | impl<'a, T> Trait<'a, T> for Struct {} | ~~~~~~~~~~~~ ~~~~~~~~~ error[E0404]: expected trait, found enum `Enum` - --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:16:13 + --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:19:13 | LL | impl<'a, T> Enum for Trait<'a, T> {} | ^^^^^^^ not a trait @@ -21,7 +21,7 @@ LL | impl<'a, T> Trait<'a, T> for Enum {} | ~~~~~~~~~~~~ ~~~~~~~ error[E0404]: expected trait, found union `Union` - --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:19:13 + --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:23:13 | LL | impl<'a, T> Union for Trait<'a, T> {} | ^^^^^^^^ not a trait @@ -31,8 +31,35 @@ help: `impl` items mention the trait being implemented first and the type it is LL | impl<'a, T> Trait<'a, T> for Union {} | ~~~~~~~~~~~~ ~~~~~~~~ +error[E0392]: type parameter `T` is never used + --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:5:19 + | +LL | pub struct Struct; + | ^ unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + +error[E0392]: type parameter `T` is never used + --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:7:15 + | +LL | pub enum Enum {} + | ^ unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + +error[E0392]: type parameter `T` is never used + --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:10:17 + | +LL | pub union Union { + | ^ unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:12:27 + --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:15:27 | LL | impl<'a, T> Struct for Trait<'a, T> {} | ^^^^^^^^^^^^ @@ -42,7 +69,29 @@ help: add `dyn` keyword before this trait LL | impl<'a, T> Struct for dyn Trait<'a, T> {} | +++ -error: aborting due to 4 previous errors +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:19:25 + | +LL | impl<'a, T> Enum for Trait<'a, T> {} + | ^^^^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL | impl<'a, T> Enum for dyn Trait<'a, T> {} + | +++ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:23:26 + | +LL | impl<'a, T> Union for Trait<'a, T> {} + | ^^^^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL | impl<'a, T> Union for dyn Trait<'a, T> {} + | +++ + +error: aborting due to 9 previous errors -Some errors have detailed explanations: E0404, E0782. -For more information about an error, try `rustc --explain E0404`. +Some errors have detailed explanations: E0392, E0404, E0782. +For more information about an error, try `rustc --explain E0392`. diff --git a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait.rs b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait.rs index 947bc2c79654b..951e7313f0a58 100644 --- a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait.rs +++ b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait.rs @@ -1,9 +1,12 @@ pub trait Trait<'a, T> {} pub struct Struct; +//~^ ERROR `T` is never used pub enum Enum {} +//~^ ERROR `T` is never used pub union Union { + //~^ ERROR `T` is never used f1: usize, } @@ -14,8 +17,12 @@ impl<'a, T> Struct for Trait<'a, T> {} impl<'a, T> Enum for Trait<'a, T> {} //~^ ERROR expected trait, found enum `Enum` +//~| WARNING trait objects without an explicit `dyn` are deprecated +//~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! impl<'a, T> Union for Trait<'a, T> {} //~^ ERROR expected trait, found union `Union` +//~| WARNING trait objects without an explicit `dyn` are deprecated +//~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! fn main() {} diff --git a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait.stderr b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait.stderr index 0098814f81e78..5d805d97a4358 100644 --- a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait.stderr +++ b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait.stderr @@ -1,5 +1,5 @@ error[E0404]: expected trait, found struct `Struct` - --> $DIR/suggest-swapping-self-ty-and-trait.rs:10:13 + --> $DIR/suggest-swapping-self-ty-and-trait.rs:13:13 | LL | impl<'a, T> Struct for Trait<'a, T> {} | ^^^^^^^^^ not a trait @@ -10,7 +10,7 @@ LL | impl<'a, T> Trait<'a, T> for Struct {} | ~~~~~~~~~~~~ ~~~~~~~~~ error[E0404]: expected trait, found enum `Enum` - --> $DIR/suggest-swapping-self-ty-and-trait.rs:15:13 + --> $DIR/suggest-swapping-self-ty-and-trait.rs:18:13 | LL | impl<'a, T> Enum for Trait<'a, T> {} | ^^^^^^^ not a trait @@ -21,7 +21,7 @@ LL | impl<'a, T> Trait<'a, T> for Enum {} | ~~~~~~~~~~~~ ~~~~~~~ error[E0404]: expected trait, found union `Union` - --> $DIR/suggest-swapping-self-ty-and-trait.rs:18:13 + --> $DIR/suggest-swapping-self-ty-and-trait.rs:23:13 | LL | impl<'a, T> Union for Trait<'a, T> {} | ^^^^^^^^ not a trait @@ -31,8 +31,35 @@ help: `impl` items mention the trait being implemented first and the type it is LL | impl<'a, T> Trait<'a, T> for Union {} | ~~~~~~~~~~~~ ~~~~~~~~ +error[E0392]: type parameter `T` is never used + --> $DIR/suggest-swapping-self-ty-and-trait.rs:3:19 + | +LL | pub struct Struct; + | ^ unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + +error[E0392]: type parameter `T` is never used + --> $DIR/suggest-swapping-self-ty-and-trait.rs:5:15 + | +LL | pub enum Enum {} + | ^ unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + +error[E0392]: type parameter `T` is never used + --> $DIR/suggest-swapping-self-ty-and-trait.rs:8:17 + | +LL | pub union Union { + | ^ unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/suggest-swapping-self-ty-and-trait.rs:10:27 + --> $DIR/suggest-swapping-self-ty-and-trait.rs:13:27 | LL | impl<'a, T> Struct for Trait<'a, T> {} | ^^^^^^^^^^^^ @@ -45,6 +72,33 @@ help: if this is an object-safe trait, use `dyn` LL | impl<'a, T> Struct for dyn Trait<'a, T> {} | +++ -error: aborting due to 3 previous errors; 1 warning emitted +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/suggest-swapping-self-ty-and-trait.rs:18:25 + | +LL | impl<'a, T> Enum for Trait<'a, T> {} + | ^^^^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: if this is an object-safe trait, use `dyn` + | +LL | impl<'a, T> Enum for dyn Trait<'a, T> {} + | +++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/suggest-swapping-self-ty-and-trait.rs:23:26 + | +LL | impl<'a, T> Union for Trait<'a, T> {} + | ^^^^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: if this is an object-safe trait, use `dyn` + | +LL | impl<'a, T> Union for dyn Trait<'a, T> {} + | +++ + +error: aborting due to 6 previous errors; 3 warnings emitted -For more information about this error, try `rustc --explain E0404`. +Some errors have detailed explanations: E0392, E0404. +For more information about an error, try `rustc --explain E0392`. diff --git a/tests/ui/tag-type-args.stderr b/tests/ui/tag-type-args.stderr index a1136f61cc52f..def13832e1ae0 100644 --- a/tests/ui/tag-type-args.stderr +++ b/tests/ui/tag-type-args.stderr @@ -1,3 +1,12 @@ +error[E0392]: type parameter `T` is never used + --> $DIR/tag-type-args.rs:1:11 + | +LL | enum Quux { Bar } + | ^ unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + error[E0107]: missing generics for enum `Quux` --> $DIR/tag-type-args.rs:4:11 | @@ -14,15 +23,6 @@ help: add missing generic argument LL | fn foo(c: Quux) { assert!((false)); } | +++ -error[E0392]: type parameter `T` is never used - --> $DIR/tag-type-args.rs:1:11 - | -LL | enum Quux { Bar } - | ^ unused type parameter - | - = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead - error: aborting due to 2 previous errors Some errors have detailed explanations: E0107, E0392. diff --git a/tests/ui/target-feature/invalid-attribute.stderr b/tests/ui/target-feature/invalid-attribute.stderr index 278b9ad5003a6..bf48911edec5f 100644 --- a/tests/ui/target-feature/invalid-attribute.stderr +++ b/tests/ui/target-feature/invalid-attribute.stderr @@ -183,6 +183,15 @@ error: cannot use `#[inline(always)]` with `#[target_feature]` LL | #[inline(always)] | ^^^^^^^^^^^^^^^^^ +error[E0046]: not all trait items implemented, missing: `foo` + --> $DIR/invalid-attribute.rs:88:1 + | +LL | impl Quux for u8 {} + | ^^^^^^^^^^^^^^^^ missing `foo` in implementation +... +LL | fn foo(); + | --------- `foo` from trait + error[E0658]: `#[target_feature(..)]` can only be applied to `unsafe` functions --> $DIR/invalid-attribute.rs:103:5 | @@ -196,15 +205,6 @@ LL | fn foo() {} = help: add `#![feature(target_feature_11)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0046]: not all trait items implemented, missing: `foo` - --> $DIR/invalid-attribute.rs:88:1 - | -LL | impl Quux for u8 {} - | ^^^^^^^^^^^^^^^^ missing `foo` in implementation -... -LL | fn foo(); - | --------- `foo` from trait - error: aborting due to 23 previous errors Some errors have detailed explanations: E0046, E0658. diff --git a/tests/ui/test-attrs/terse.rs b/tests/ui/test-attrs/terse.rs new file mode 100644 index 0000000000000..ab9d5cc19bd6c --- /dev/null +++ b/tests/ui/test-attrs/terse.rs @@ -0,0 +1,125 @@ +//@ compile-flags: --test +//@ run-fail +//@ run-flags: --test-threads=1 --quiet +//@ check-run-results +//@ exec-env:RUST_BACKTRACE=0 +//@ normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME" +//@ ignore-emscripten no threads support +//@ needs-unwind + +#[test] +fn abc() { + panic!(); +} + +#[test] +fn foo() { + panic!(); +} + +#[test] +fn foo2() { + panic!(); +} + +// run a whole bunch of tests so we can see what happens when we go over 88 columns +#[test] fn f0() {} +#[test] fn f1() {} +#[test] fn f2() {} +#[test] fn f3() {} +#[test] fn f4() {} +#[test] fn f5() {} +#[test] fn f6() {} +#[test] fn f7() {} +#[test] fn f8() {} +#[test] fn f9() {} +#[test] fn f10() {} +#[test] fn f11() {} +#[test] fn f12() {} +#[test] fn f13() {} +#[test] fn f14() {} +#[test] fn f15() {} +#[test] fn f16() {} +#[test] fn f17() {} +#[test] fn f18() {} +#[test] fn f19() {} +#[test] fn f20() {} +#[test] fn f21() {} +#[test] fn f22() {} +#[test] fn f23() {} +#[test] fn f24() {} +#[test] fn f25() {} +#[test] fn f26() {} +#[test] fn f27() {} +#[test] fn f28() {} +#[test] fn f29() {} +#[test] fn f30() {} +#[test] fn f31() {} +#[test] fn f32() {} +#[test] fn f33() {} +#[test] fn f34() {} +#[test] fn f35() {} +#[test] fn f36() {} +#[test] fn f37() {} +#[test] fn f38() {} +#[test] fn f39() {} +#[test] fn f40() {} +#[test] fn f41() {} +#[test] fn f42() {} +#[test] fn f43() {} +#[test] fn f44() {} +#[test] fn f45() {} +#[test] fn f46() {} +#[test] fn f47() {} +#[test] fn f48() {} +#[test] fn f49() {} +#[test] fn f50() {} +#[test] fn f51() {} +#[test] fn f52() {} +#[test] fn f53() {} +#[test] fn f54() {} +#[test] fn f55() {} +#[test] fn f56() {} +#[test] fn f57() {} +#[test] fn f58() {} +#[test] fn f59() {} +#[test] fn f60() {} +#[test] fn f61() {} +#[test] fn f62() {} +#[test] fn f63() {} +#[test] fn f64() {} +#[test] fn f65() {} +#[test] fn f66() {} +#[test] fn f67() {} +#[test] fn f68() {} +#[test] fn f69() {} +#[test] fn f70() {} +#[test] fn f71() {} +#[test] fn f72() {} +#[test] fn f73() {} +#[test] fn f74() {} +#[test] fn f75() {} +#[test] fn f76() {} +#[test] fn f77() {} +#[test] fn f78() {} +#[test] fn f79() {} +#[test] fn f80() {} +#[test] fn f81() {} +#[test] fn f82() {} +#[test] fn f83() {} +#[test] fn f84() {} +#[test] fn f85() {} +#[test] fn f86() {} +#[test] fn f87() {} +#[test] fn f88() {} +#[test] fn f89() {} +#[test] fn f90() {} +#[test] fn f91() {} +#[test] fn f92() {} +#[test] fn f93() {} +#[test] fn f94() {} +#[test] fn f95() {} +#[test] fn f96() {} +#[test] fn f97() {} +#[test] fn f98() {} +#[test] fn f99() {} diff --git a/tests/ui/test-attrs/terse.run.stdout b/tests/ui/test-attrs/terse.run.stdout new file mode 100644 index 0000000000000..2b361361ae888 --- /dev/null +++ b/tests/ui/test-attrs/terse.run.stdout @@ -0,0 +1,31 @@ + +running 103 tests +abc --- FAILED +....................................................................................... 88/103 +............. 101/103 +foo --- FAILED +foo2 --- FAILED + +failures: + +---- abc stdout ---- +thread 'abc' panicked at $DIR/terse.rs:12:5: +explicit panic +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace + +---- foo stdout ---- +thread 'foo' panicked at $DIR/terse.rs:17:5: +explicit panic + +---- foo2 stdout ---- +thread 'foo2' panicked at $DIR/terse.rs:22:5: +explicit panic + + +failures: + abc + foo + foo2 + +test result: FAILED. 100 passed; 3 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/tests/ui/test-attrs/test-filter-multiple.rs b/tests/ui/test-attrs/test-filter-multiple.rs index 0347ce457ae66..05fc022834aea 100644 --- a/tests/ui/test-attrs/test-filter-multiple.rs +++ b/tests/ui/test-attrs/test-filter-multiple.rs @@ -3,7 +3,7 @@ //@ run-flags: --test-threads=1 test1 test2 //@ check-run-results //@ normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME" -//@ ignore-emscripten no threads support +//@ needs-threads #[test] fn test1() {} diff --git a/tests/ui/test-attrs/test-type.rs b/tests/ui/test-attrs/test-type.rs index 8f75ff309e0ea..7db7e31d01daa 100644 --- a/tests/ui/test-attrs/test-type.rs +++ b/tests/ui/test-attrs/test-type.rs @@ -2,7 +2,7 @@ //@ run-flags: --test-threads=1 //@ check-run-results //@ normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME" -//@ ignore-emscripten no threads support +//@ needs-threads //@ run-pass #[test] diff --git a/tests/ui/thread-local/tls.rs b/tests/ui/thread-local/tls.rs index 17096319d237c..fa6a722b291d7 100644 --- a/tests/ui/thread-local/tls.rs +++ b/tests/ui/thread-local/tls.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ ignore-emscripten no threads support +//@ needs-threads //@ compile-flags: -O //@ ignore-nto Doesn't work without emulated TLS enabled (in LLVM) diff --git a/tests/ui/threads-sendsync/child-outlives-parent.rs b/tests/ui/threads-sendsync/child-outlives-parent.rs index 2fb4a6f637a2b..213fd008cd3de 100644 --- a/tests/ui/threads-sendsync/child-outlives-parent.rs +++ b/tests/ui/threads-sendsync/child-outlives-parent.rs @@ -2,7 +2,7 @@ // Reported as issue #126, child leaks the string. //@ pretty-expanded FIXME #23616 -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; diff --git a/tests/ui/threads-sendsync/clone-with-exterior.rs b/tests/ui/threads-sendsync/clone-with-exterior.rs index 58529e4a7887c..67790367e27e4 100644 --- a/tests/ui/threads-sendsync/clone-with-exterior.rs +++ b/tests/ui/threads-sendsync/clone-with-exterior.rs @@ -1,7 +1,7 @@ //@ run-pass #![allow(unused_must_use)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; diff --git a/tests/ui/threads-sendsync/comm.rs b/tests/ui/threads-sendsync/comm.rs index 589859e60a66a..0c37fda8a3931 100644 --- a/tests/ui/threads-sendsync/comm.rs +++ b/tests/ui/threads-sendsync/comm.rs @@ -1,13 +1,13 @@ //@ run-pass #![allow(unused_must_use)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; use std::sync::mpsc::{channel, Sender}; pub fn main() { let (tx, rx) = channel(); - let t = thread::spawn(move|| { child(&tx) }); + let t = thread::spawn(move || { child(&tx) }); let y = rx.recv().unwrap(); println!("received"); println!("{}", y); diff --git a/tests/ui/threads-sendsync/eprint-on-tls-drop.rs b/tests/ui/threads-sendsync/eprint-on-tls-drop.rs index 3ff9fb10f2419..82abf21df3f41 100644 --- a/tests/ui/threads-sendsync/eprint-on-tls-drop.rs +++ b/tests/ui/threads-sendsync/eprint-on-tls-drop.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ ignore-emscripten no processes +//@ needs-threads //@ ignore-sgx no processes use std::cell::RefCell; diff --git a/tests/ui/threads-sendsync/issue-24313.rs b/tests/ui/threads-sendsync/issue-24313.rs index 17e027520c15f..1ea862f1e7d6b 100644 --- a/tests/ui/threads-sendsync/issue-24313.rs +++ b/tests/ui/threads-sendsync/issue-24313.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ ignore-emscripten no threads +//@ needs-threads //@ ignore-sgx no processes use std::thread; diff --git a/tests/ui/threads-sendsync/issue-29488.rs b/tests/ui/threads-sendsync/issue-29488.rs index c848e7b50bb73..fbbd6b02a067d 100644 --- a/tests/ui/threads-sendsync/issue-29488.rs +++ b/tests/ui/threads-sendsync/issue-29488.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; diff --git a/tests/ui/threads-sendsync/issue-43733-2.rs b/tests/ui/threads-sendsync/issue-43733-2.rs index 5a9ee015cb9dd..372ebf2cff97f 100644 --- a/tests/ui/threads-sendsync/issue-43733-2.rs +++ b/tests/ui/threads-sendsync/issue-43733-2.rs @@ -1,4 +1,4 @@ -//@ ignore-wasm32 +//@ needs-threads //@ dont-check-compiler-stderr #![feature(cfg_target_thread_local, thread_local_internals)] diff --git a/tests/ui/threads-sendsync/issue-43733.rs b/tests/ui/threads-sendsync/issue-43733.rs index 12207f4e6aa02..c90f60887cfd2 100644 --- a/tests/ui/threads-sendsync/issue-43733.rs +++ b/tests/ui/threads-sendsync/issue-43733.rs @@ -1,4 +1,4 @@ -//@ ignore-wasm32 +//@ needs-threads #![feature(thread_local)] #![feature(cfg_target_thread_local, thread_local_internals)] diff --git a/tests/ui/threads-sendsync/issue-4446.rs b/tests/ui/threads-sendsync/issue-4446.rs index b5e3a20ccde1e..aa2de51974b37 100644 --- a/tests/ui/threads-sendsync/issue-4446.rs +++ b/tests/ui/threads-sendsync/issue-4446.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ ignore-emscripten no threads support +//@ needs-threads use std::sync::mpsc::channel; use std::thread; diff --git a/tests/ui/threads-sendsync/issue-4448.rs b/tests/ui/threads-sendsync/issue-4448.rs index 0f3bf65c441f0..b8324a8c43fb5 100644 --- a/tests/ui/threads-sendsync/issue-4448.rs +++ b/tests/ui/threads-sendsync/issue-4448.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ ignore-emscripten no threads support +//@ needs-threads use std::sync::mpsc::channel; use std::thread; diff --git a/tests/ui/threads-sendsync/issue-8827.rs b/tests/ui/threads-sendsync/issue-8827.rs index b7deef0f34dd1..fa07a4ebc7d6d 100644 --- a/tests/ui/threads-sendsync/issue-8827.rs +++ b/tests/ui/threads-sendsync/issue-8827.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; use std::sync::mpsc::{channel, Receiver}; diff --git a/tests/ui/threads-sendsync/issue-9396.rs b/tests/ui/threads-sendsync/issue-9396.rs index 6228f4ba706b7..6b5907e5c1d09 100644 --- a/tests/ui/threads-sendsync/issue-9396.rs +++ b/tests/ui/threads-sendsync/issue-9396.rs @@ -1,7 +1,7 @@ //@ run-pass #![allow(unused_must_use)] #![allow(deprecated)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::sync::mpsc::{TryRecvError, channel}; use std::thread; diff --git a/tests/ui/threads-sendsync/mpsc_stress.rs b/tests/ui/threads-sendsync/mpsc_stress.rs index 68c401512817c..f5354c60bfce9 100644 --- a/tests/ui/threads-sendsync/mpsc_stress.rs +++ b/tests/ui/threads-sendsync/mpsc_stress.rs @@ -1,6 +1,6 @@ //@ run-pass //@ compile-flags:--test -//@ ignore-emscripten +//@ needs-threads use std::sync::mpsc::channel; use std::sync::mpsc::TryRecvError; diff --git a/tests/ui/threads-sendsync/send-resource.rs b/tests/ui/threads-sendsync/send-resource.rs index 32910c5f7d177..3e1532b3132ee 100644 --- a/tests/ui/threads-sendsync/send-resource.rs +++ b/tests/ui/threads-sendsync/send-resource.rs @@ -4,7 +4,7 @@ #![allow(non_camel_case_types)] //@ pretty-expanded FIXME #23616 -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; use std::sync::mpsc::channel; diff --git a/tests/ui/threads-sendsync/sendfn-spawn-with-fn-arg.rs b/tests/ui/threads-sendsync/sendfn-spawn-with-fn-arg.rs index 5306d69a7d2cc..63cf3ff40490d 100644 --- a/tests/ui/threads-sendsync/sendfn-spawn-with-fn-arg.rs +++ b/tests/ui/threads-sendsync/sendfn-spawn-with-fn-arg.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; diff --git a/tests/ui/threads-sendsync/spawn-fn.rs b/tests/ui/threads-sendsync/spawn-fn.rs index 863c22f70d6be..e4d83b53f3cfa 100644 --- a/tests/ui/threads-sendsync/spawn-fn.rs +++ b/tests/ui/threads-sendsync/spawn-fn.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_must_use)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; diff --git a/tests/ui/threads-sendsync/spawn-types.rs b/tests/ui/threads-sendsync/spawn-types.rs index 9c1b6550d9b1e..2a7a9e2f49732 100644 --- a/tests/ui/threads-sendsync/spawn-types.rs +++ b/tests/ui/threads-sendsync/spawn-types.rs @@ -1,7 +1,7 @@ //@ run-pass #![allow(non_camel_case_types)] -//@ ignore-emscripten no threads support +//@ needs-threads /* Make sure we can spawn tasks that take different types of diff --git a/tests/ui/threads-sendsync/spawn.rs b/tests/ui/threads-sendsync/spawn.rs index 2c06fc2837f34..c7b344b9f7581 100644 --- a/tests/ui/threads-sendsync/spawn.rs +++ b/tests/ui/threads-sendsync/spawn.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; diff --git a/tests/ui/threads-sendsync/spawn2.rs b/tests/ui/threads-sendsync/spawn2.rs index cfe907ea6d9a3..8278fec1885b9 100644 --- a/tests/ui/threads-sendsync/spawn2.rs +++ b/tests/ui/threads-sendsync/spawn2.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; diff --git a/tests/ui/threads-sendsync/spawning-with-debug.rs b/tests/ui/threads-sendsync/spawning-with-debug.rs index 58f1743527c88..90a81c1e53bcb 100644 --- a/tests/ui/threads-sendsync/spawning-with-debug.rs +++ b/tests/ui/threads-sendsync/spawning-with-debug.rs @@ -3,7 +3,7 @@ #![allow(unused_mut)] //@ ignore-windows //@ exec-env:RUST_LOG=debug -//@ ignore-emscripten no threads support +//@ needs-threads // regression test for issue #10405, make sure we don't call println! too soon. diff --git a/tests/ui/threads-sendsync/task-comm-0.rs b/tests/ui/threads-sendsync/task-comm-0.rs index 06ce739b8e597..50f2b59189481 100644 --- a/tests/ui/threads-sendsync/task-comm-0.rs +++ b/tests/ui/threads-sendsync/task-comm-0.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_must_use)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; use std::sync::mpsc::{channel, Sender}; diff --git a/tests/ui/threads-sendsync/task-comm-1.rs b/tests/ui/threads-sendsync/task-comm-1.rs index 77ca940e947b9..41592bd916b4e 100644 --- a/tests/ui/threads-sendsync/task-comm-1.rs +++ b/tests/ui/threads-sendsync/task-comm-1.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_must_use)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; diff --git a/tests/ui/threads-sendsync/task-comm-10.rs b/tests/ui/threads-sendsync/task-comm-10.rs index 6f043b64a092e..844652c0dde49 100644 --- a/tests/ui/threads-sendsync/task-comm-10.rs +++ b/tests/ui/threads-sendsync/task-comm-10.rs @@ -1,7 +1,7 @@ //@ run-pass #![allow(unused_must_use)] #![allow(unused_mut)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; use std::sync::mpsc::{channel, Sender}; diff --git a/tests/ui/threads-sendsync/task-comm-11.rs b/tests/ui/threads-sendsync/task-comm-11.rs index 51f134344354c..199082fda96de 100644 --- a/tests/ui/threads-sendsync/task-comm-11.rs +++ b/tests/ui/threads-sendsync/task-comm-11.rs @@ -1,7 +1,7 @@ //@ run-pass #![allow(unused_must_use)] //@ pretty-expanded FIXME #23616 -//@ ignore-emscripten no threads support +//@ needs-threads use std::sync::mpsc::{channel, Sender}; use std::thread; diff --git a/tests/ui/threads-sendsync/task-comm-12.rs b/tests/ui/threads-sendsync/task-comm-12.rs index cb1fb774f1073..7be7ec4c988b1 100644 --- a/tests/ui/threads-sendsync/task-comm-12.rs +++ b/tests/ui/threads-sendsync/task-comm-12.rs @@ -1,7 +1,7 @@ //@ run-pass #![allow(unused_must_use)] #![allow(unused_mut)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; diff --git a/tests/ui/threads-sendsync/task-comm-13.rs b/tests/ui/threads-sendsync/task-comm-13.rs index 6b5384e3f08a8..414e6e0db76da 100644 --- a/tests/ui/threads-sendsync/task-comm-13.rs +++ b/tests/ui/threads-sendsync/task-comm-13.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_variables)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::sync::mpsc::{channel, Sender}; use std::thread; diff --git a/tests/ui/threads-sendsync/task-comm-14.rs b/tests/ui/threads-sendsync/task-comm-14.rs index 65cc750a7c39e..54deb221294ae 100644 --- a/tests/ui/threads-sendsync/task-comm-14.rs +++ b/tests/ui/threads-sendsync/task-comm-14.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_parens)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::sync::mpsc::{channel, Sender}; use std::thread; diff --git a/tests/ui/threads-sendsync/task-comm-15.rs b/tests/ui/threads-sendsync/task-comm-15.rs index 844a18b61589a..f487bf3cc84b3 100644 --- a/tests/ui/threads-sendsync/task-comm-15.rs +++ b/tests/ui/threads-sendsync/task-comm-15.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_must_use)] -//@ ignore-emscripten no threads support +//@ needs-threads //@ pretty-expanded FIXME #23616 use std::sync::mpsc::{channel, Sender}; diff --git a/tests/ui/threads-sendsync/task-comm-17.rs b/tests/ui/threads-sendsync/task-comm-17.rs index 14ef4dd3edecc..687322d4dc963 100644 --- a/tests/ui/threads-sendsync/task-comm-17.rs +++ b/tests/ui/threads-sendsync/task-comm-17.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_must_use)] -//@ ignore-emscripten no threads support +//@ needs-threads //@ pretty-expanded FIXME #23616 // Issue #922 diff --git a/tests/ui/threads-sendsync/task-comm-3.rs b/tests/ui/threads-sendsync/task-comm-3.rs index 1f2a6406d79bd..26f3eaf9dc6c4 100644 --- a/tests/ui/threads-sendsync/task-comm-3.rs +++ b/tests/ui/threads-sendsync/task-comm-3.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_must_use)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; use std::sync::mpsc::{channel, Sender}; diff --git a/tests/ui/threads-sendsync/task-comm-7.rs b/tests/ui/threads-sendsync/task-comm-7.rs index f6e77986e16c3..d9b322daa66bf 100644 --- a/tests/ui/threads-sendsync/task-comm-7.rs +++ b/tests/ui/threads-sendsync/task-comm-7.rs @@ -1,7 +1,7 @@ //@ run-pass #![allow(unused_must_use)] #![allow(unused_assignments)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::sync::mpsc::{channel, Sender}; use std::thread; diff --git a/tests/ui/threads-sendsync/task-comm-9.rs b/tests/ui/threads-sendsync/task-comm-9.rs index f8fe680e5e013..3e617e4a40c28 100644 --- a/tests/ui/threads-sendsync/task-comm-9.rs +++ b/tests/ui/threads-sendsync/task-comm-9.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_must_use)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; use std::sync::mpsc::{channel, Sender}; diff --git a/tests/ui/threads-sendsync/task-life-0.rs b/tests/ui/threads-sendsync/task-life-0.rs index a4652197afc7e..d3eca5d371fb8 100644 --- a/tests/ui/threads-sendsync/task-life-0.rs +++ b/tests/ui/threads-sendsync/task-life-0.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_must_use)] -//@ ignore-emscripten no threads support +//@ needs-threads //@ pretty-expanded FIXME #23616 use std::thread; diff --git a/tests/ui/threads-sendsync/task-spawn-barefn.rs b/tests/ui/threads-sendsync/task-spawn-barefn.rs index 2c957878c95f6..a97e92206e206 100644 --- a/tests/ui/threads-sendsync/task-spawn-barefn.rs +++ b/tests/ui/threads-sendsync/task-spawn-barefn.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:Ensure that the child thread runs by panicking -//@ ignore-emscripten Needs threads. +//@ needs-threads use std::thread; diff --git a/tests/ui/threads-sendsync/task-spawn-move-and-copy.rs b/tests/ui/threads-sendsync/task-spawn-move-and-copy.rs index 442955421d83e..ea1c6a9b1081b 100644 --- a/tests/ui/threads-sendsync/task-spawn-move-and-copy.rs +++ b/tests/ui/threads-sendsync/task-spawn-move-and-copy.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_must_use)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; use std::sync::mpsc::channel; diff --git a/tests/ui/threads-sendsync/task-stderr.rs b/tests/ui/threads-sendsync/task-stderr.rs index 0f215a2b763ac..cad10c7a7922c 100644 --- a/tests/ui/threads-sendsync/task-stderr.rs +++ b/tests/ui/threads-sendsync/task-stderr.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ ignore-emscripten no threads support +//@ needs-threads //@ needs-unwind #![feature(internal_output_capture)] diff --git a/tests/ui/threads-sendsync/tcp-stress.rs b/tests/ui/threads-sendsync/tcp-stress.rs index 488cab4014085..429a465731408 100644 --- a/tests/ui/threads-sendsync/tcp-stress.rs +++ b/tests/ui/threads-sendsync/tcp-stress.rs @@ -1,6 +1,6 @@ //@ run-pass //@ ignore-android needs extra network permissions -//@ ignore-emscripten no threads or sockets support +//@ needs-threads //@ ignore-netbsd system ulimit (Too many open files) //@ ignore-openbsd system ulimit (Too many open files) diff --git a/tests/ui/threads-sendsync/test-tasks-invalid-value.rs b/tests/ui/threads-sendsync/test-tasks-invalid-value.rs index 4b38b9ce2c9bc..127086743ca82 100644 --- a/tests/ui/threads-sendsync/test-tasks-invalid-value.rs +++ b/tests/ui/threads-sendsync/test-tasks-invalid-value.rs @@ -5,7 +5,7 @@ //@ error-pattern:should be a positive integer //@ compile-flags: --test //@ exec-env:RUST_TEST_THREADS=foo -//@ ignore-emscripten +//@ needs-threads #[test] fn do_nothing() {} diff --git a/tests/ui/threads-sendsync/threads.rs b/tests/ui/threads-sendsync/threads.rs index 7b7e52abab459..f3ed7890364b5 100644 --- a/tests/ui/threads-sendsync/threads.rs +++ b/tests/ui/threads-sendsync/threads.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_must_use)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; diff --git a/tests/ui/threads-sendsync/tls-dtors-are-run-in-a-static-binary.rs b/tests/ui/threads-sendsync/tls-dtors-are-run-in-a-static-binary.rs index 66fd6169db0e5..8417665941232 100644 --- a/tests/ui/threads-sendsync/tls-dtors-are-run-in-a-static-binary.rs +++ b/tests/ui/threads-sendsync/tls-dtors-are-run-in-a-static-binary.rs @@ -1,6 +1,6 @@ //@ run-pass //@ no-prefer-dynamic -//@ ignore-emscripten no threads support +//@ needs-threads static mut HIT: bool = false; diff --git a/tests/ui/threads-sendsync/tls-init-on-init.rs b/tests/ui/threads-sendsync/tls-init-on-init.rs index ba5e4698e63dd..fd764669e7f61 100644 --- a/tests/ui/threads-sendsync/tls-init-on-init.rs +++ b/tests/ui/threads-sendsync/tls-init-on-init.rs @@ -1,7 +1,7 @@ //@ run-pass #![allow(stable_features)] -//@ ignore-emscripten no threads support +//@ needs-threads #![feature(thread_local_try_with)] diff --git a/tests/ui/threads-sendsync/tls-try-with.rs b/tests/ui/threads-sendsync/tls-try-with.rs index d9af1caf74117..72cee219a0abd 100644 --- a/tests/ui/threads-sendsync/tls-try-with.rs +++ b/tests/ui/threads-sendsync/tls-try-with.rs @@ -1,7 +1,7 @@ //@ run-pass #![allow(stable_features)] -//@ ignore-emscripten no threads support +//@ needs-threads #![feature(thread_local_try_with)] diff --git a/tests/ui/threads-sendsync/unwind-resource.rs b/tests/ui/threads-sendsync/unwind-resource.rs index ea9e0c7514ce1..3b1ab57b46e3e 100644 --- a/tests/ui/threads-sendsync/unwind-resource.rs +++ b/tests/ui/threads-sendsync/unwind-resource.rs @@ -2,7 +2,7 @@ //@ needs-unwind #![allow(non_camel_case_types)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::sync::mpsc::{channel, Sender}; use std::thread; diff --git a/tests/ui/threads-sendsync/yield.rs b/tests/ui/threads-sendsync/yield.rs index 4d89b10af9578..99d14bd92eaa5 100644 --- a/tests/ui/threads-sendsync/yield.rs +++ b/tests/ui/threads-sendsync/yield.rs @@ -2,7 +2,7 @@ #![allow(unused_must_use)] #![allow(unused_mut)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; diff --git a/tests/ui/threads-sendsync/yield1.rs b/tests/ui/threads-sendsync/yield1.rs index b003a70f47eee..c965d2fc3033e 100644 --- a/tests/ui/threads-sendsync/yield1.rs +++ b/tests/ui/threads-sendsync/yield1.rs @@ -2,7 +2,7 @@ #![allow(unused_must_use)] #![allow(unused_mut)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; diff --git a/tests/ui/trait-bounds/ice-unsized-tuple-const-issue-121443.rs b/tests/ui/trait-bounds/ice-unsized-tuple-const-issue-121443.rs new file mode 100644 index 0000000000000..c3a2ab82adc6a --- /dev/null +++ b/tests/ui/trait-bounds/ice-unsized-tuple-const-issue-121443.rs @@ -0,0 +1,16 @@ +// Regression test for #121443 +// Checks that no ICE occurs upon encountering +// a tuple with unsized element that is not +// the last element + +type Fn = dyn FnOnce() -> u8; + +const TEST: Fn = some_fn; +//~^ ERROR cannot find value `some_fn` in this scope +//~| ERROR the size for values of type `(dyn FnOnce() -> u8 + 'static)` cannot be known at compilation time +//~| ERROR the size for values of type `(dyn FnOnce() -> u8 + 'static)` cannot be known at compilation time +const TEST2: (Fn, u8) = (TEST, 0); +//~^ ERROR the size for values of type `(dyn FnOnce() -> u8 + 'static)` cannot be known at compilation time +//~| ERROR the size for values of type `(dyn FnOnce() -> u8 + 'static)` cannot be known at compilation time + +fn main() {} diff --git a/tests/ui/trait-bounds/ice-unsized-tuple-const-issue-121443.stderr b/tests/ui/trait-bounds/ice-unsized-tuple-const-issue-121443.stderr new file mode 100644 index 0000000000000..0e92979ccd507 --- /dev/null +++ b/tests/ui/trait-bounds/ice-unsized-tuple-const-issue-121443.stderr @@ -0,0 +1,45 @@ +error[E0425]: cannot find value `some_fn` in this scope + --> $DIR/ice-unsized-tuple-const-issue-121443.rs:8:18 + | +LL | const TEST: Fn = some_fn; + | ^^^^^^^ not found in this scope + +error[E0277]: the size for values of type `(dyn FnOnce() -> u8 + 'static)` cannot be known at compilation time + --> $DIR/ice-unsized-tuple-const-issue-121443.rs:8:13 + | +LL | const TEST: Fn = some_fn; + | ^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn FnOnce() -> u8 + 'static)` + +error[E0277]: the size for values of type `(dyn FnOnce() -> u8 + 'static)` cannot be known at compilation time + --> $DIR/ice-unsized-tuple-const-issue-121443.rs:8:18 + | +LL | const TEST: Fn = some_fn; + | ^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn FnOnce() -> u8 + 'static)` + = note: constant expressions must have a statically known size + +error[E0277]: the size for values of type `(dyn FnOnce() -> u8 + 'static)` cannot be known at compilation time + --> $DIR/ice-unsized-tuple-const-issue-121443.rs:12:14 + | +LL | const TEST2: (Fn, u8) = (TEST, 0); + | ^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn FnOnce() -> u8 + 'static)` + = note: only the last element of a tuple may have a dynamically sized type + +error[E0277]: the size for values of type `(dyn FnOnce() -> u8 + 'static)` cannot be known at compilation time + --> $DIR/ice-unsized-tuple-const-issue-121443.rs:12:25 + | +LL | const TEST2: (Fn, u8) = (TEST, 0); + | ^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn FnOnce() -> u8 + 'static)` + = note: only the last element of a tuple may have a dynamically sized type + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0277, E0425. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/trait-bounds/super-assoc-mismatch.rs b/tests/ui/trait-bounds/super-assoc-mismatch.rs new file mode 100644 index 0000000000000..97dfec80e3167 --- /dev/null +++ b/tests/ui/trait-bounds/super-assoc-mismatch.rs @@ -0,0 +1,60 @@ +trait Super { + type Assoc; +} +impl Super for () { + type Assoc = u8; +} +trait Sub: Super {} + +trait BoundOnSelf: Sub {} +impl BoundOnSelf for () {} +//~^ ERROR the trait bound `(): Sub` is not satisfied + +trait BoundOnParam {} +impl BoundOnParam<()> for () {} +//~^ ERROR the trait bound `(): Sub` is not satisfied + +trait BoundOnAssoc { + type Assoc: Sub; +} +impl BoundOnAssoc for () { + type Assoc = (); + //~^ ERROR the trait bound `(): Sub` is not satisfied +} + +trait BoundOnGat where Self::Assoc: Sub { + type Assoc; +} +impl BoundOnGat for u8 { + type Assoc = (); + //~^ ERROR the trait bound `(): Sub` is not satisfied +} + +fn trivial_bound() where (): Sub {} +//~^ ERROR the trait bound `(): Sub` is not satisfied + +// The following is an edge case where the unsatisfied projection predicate +// `<::Assoc1<()> as SuperGeneric>::Assoc == ::Assoc2` +// contains both associated types of `MultiAssoc`. To suppress the error about the unsatisfied +// super projection, the error's span must be equal to the span of the unsatisfied trait error. +trait SuperGeneric { + type Assoc; +} +trait SubGeneric: SuperGeneric {} +trait MultiAssoc +where + Self::Assoc1<()>: SubGeneric +{ + type Assoc1; + type Assoc2; +} +impl SuperGeneric for () { + type Assoc = u8; +} +impl MultiAssoc for u8 { + type Assoc1 = (); + //~^ ERROR the trait bound `(): SubGeneric` is not satisfied + type Assoc2 = u16; +} + +fn main() {} diff --git a/tests/ui/trait-bounds/super-assoc-mismatch.stderr b/tests/ui/trait-bounds/super-assoc-mismatch.stderr new file mode 100644 index 0000000000000..47535776348b9 --- /dev/null +++ b/tests/ui/trait-bounds/super-assoc-mismatch.stderr @@ -0,0 +1,105 @@ +error[E0277]: the trait bound `(): Sub` is not satisfied + --> $DIR/super-assoc-mismatch.rs:10:22 + | +LL | impl BoundOnSelf for () {} + | ^^ the trait `Sub` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/super-assoc-mismatch.rs:7:1 + | +LL | trait Sub: Super {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `BoundOnSelf` + --> $DIR/super-assoc-mismatch.rs:9:20 + | +LL | trait BoundOnSelf: Sub {} + | ^^^ required by this bound in `BoundOnSelf` + +error[E0277]: the trait bound `(): Sub` is not satisfied + --> $DIR/super-assoc-mismatch.rs:14:27 + | +LL | impl BoundOnParam<()> for () {} + | ^^ the trait `Sub` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/super-assoc-mismatch.rs:7:1 + | +LL | trait Sub: Super {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `BoundOnParam` + --> $DIR/super-assoc-mismatch.rs:13:23 + | +LL | trait BoundOnParam {} + | ^^^ required by this bound in `BoundOnParam` + +error[E0277]: the trait bound `(): Sub` is not satisfied + --> $DIR/super-assoc-mismatch.rs:21:18 + | +LL | type Assoc = (); + | ^^ the trait `Sub` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/super-assoc-mismatch.rs:7:1 + | +LL | trait Sub: Super {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `BoundOnAssoc::Assoc` + --> $DIR/super-assoc-mismatch.rs:18:17 + | +LL | type Assoc: Sub; + | ^^^ required by this bound in `BoundOnAssoc::Assoc` + +error[E0277]: the trait bound `(): Sub` is not satisfied + --> $DIR/super-assoc-mismatch.rs:29:21 + | +LL | type Assoc = (); + | ^^ the trait `Sub` is not implemented for `()`, which is required by `::Assoc: Sub` + | +help: this trait has no implementations, consider adding one + --> $DIR/super-assoc-mismatch.rs:7:1 + | +LL | trait Sub: Super {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `BoundOnGat` + --> $DIR/super-assoc-mismatch.rs:25:41 + | +LL | trait BoundOnGat where Self::Assoc: Sub { + | ^^^ required by this bound in `BoundOnGat` + +error[E0277]: the trait bound `(): Sub` is not satisfied + --> $DIR/super-assoc-mismatch.rs:33:26 + | +LL | fn trivial_bound() where (): Sub {} + | ^^^^^^^ the trait `Sub` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/super-assoc-mismatch.rs:7:1 + | +LL | trait Sub: Super {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + +error[E0277]: the trait bound `(): SubGeneric` is not satisfied + --> $DIR/super-assoc-mismatch.rs:55:22 + | +LL | type Assoc1 = (); + | ^^ the trait `SubGeneric` is not implemented for `()`, which is required by `::Assoc1<()>: SubGeneric<::Assoc2>` + | +help: this trait has no implementations, consider adding one + --> $DIR/super-assoc-mismatch.rs:43:1 + | +LL | trait SubGeneric: SuperGeneric {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `MultiAssoc` + --> $DIR/super-assoc-mismatch.rs:46:23 + | +LL | trait MultiAssoc + | ---------- required by a bound in this trait +LL | where +LL | Self::Assoc1<()>: SubGeneric + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `MultiAssoc` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/alias/cross-crate.rs b/tests/ui/traits/alias/cross-crate.rs index 207216f73bf9f..376819485482e 100644 --- a/tests/ui/traits/alias/cross-crate.rs +++ b/tests/ui/traits/alias/cross-crate.rs @@ -12,6 +12,6 @@ fn use_alias() {} fn main() { use_alias::(); use_alias::>(); - //~^ ERROR `Rc` cannot be sent between threads safely [E0277] - //~^^ ERROR `Rc` cannot be shared between threads safely [E0277] + //~^ ERROR the trait bound `Rc: SendSync` is not satisfied [E0277] + //~| ERROR the trait bound `Rc: SendSync` is not satisfied [E0277] } diff --git a/tests/ui/traits/alias/cross-crate.stderr b/tests/ui/traits/alias/cross-crate.stderr index fd614b4bcd58a..52eb7e44f44fe 100644 --- a/tests/ui/traits/alias/cross-crate.stderr +++ b/tests/ui/traits/alias/cross-crate.stderr @@ -1,10 +1,9 @@ -error[E0277]: `Rc` cannot be sent between threads safely +error[E0277]: the trait bound `Rc: SendSync` is not satisfied --> $DIR/cross-crate.rs:14:17 | LL | use_alias::>(); - | ^^^^^^^ `Rc` cannot be sent between threads safely + | ^^^^^^^ the trait `Send` is not implemented for `Rc`, which is required by `Rc: SendSync` | - = help: the trait `Send` is not implemented for `Rc`, which is required by `Rc: SendSync` = note: required for `Rc` to implement `SendSync` note: required by a bound in `use_alias` --> $DIR/cross-crate.rs:10:17 @@ -12,13 +11,12 @@ note: required by a bound in `use_alias` LL | fn use_alias() {} | ^^^^^^^^ required by this bound in `use_alias` -error[E0277]: `Rc` cannot be shared between threads safely +error[E0277]: the trait bound `Rc: SendSync` is not satisfied --> $DIR/cross-crate.rs:14:17 | LL | use_alias::>(); - | ^^^^^^^ `Rc` cannot be shared between threads safely + | ^^^^^^^ the trait `Sync` is not implemented for `Rc`, which is required by `Rc: SendSync` | - = help: the trait `Sync` is not implemented for `Rc`, which is required by `Rc: SendSync` = note: required for `Rc` to implement `SendSync` note: required by a bound in `use_alias` --> $DIR/cross-crate.rs:10:17 diff --git a/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.rs b/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.rs index d254c0ae3ef92..bffa856bbeebb 100644 --- a/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.rs +++ b/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.rs @@ -7,5 +7,5 @@ trait IteratorAlias = Iterator; fn f(_: impl IteratorAlias) {} fn main() { - f(()) //~ `()` is not an iterator + f(()) //~ ERROR the trait bound `(): IteratorAlias` is not satisfied } diff --git a/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr b/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr index 1e4f4cb70463c..c73c2f680329c 100644 --- a/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr +++ b/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr @@ -1,12 +1,11 @@ -error[E0277]: `()` is not an iterator +error[E0277]: the trait bound `(): IteratorAlias` is not satisfied --> $DIR/issue-108072-unmet-trait-alias-bound.rs:10:7 | LL | f(()) - | - ^^ `()` is not an iterator + | - ^^ the trait `Iterator` is not implemented for `()`, which is required by `(): IteratorAlias` | | | required by a bound introduced by this call | - = help: the trait `Iterator` is not implemented for `()`, which is required by `(): IteratorAlias` = note: required for `()` to implement `IteratorAlias` note: required by a bound in `f` --> $DIR/issue-108072-unmet-trait-alias-bound.rs:7:14 diff --git a/tests/ui/traits/alias/only-require-assocs-from-supertraits.rs b/tests/ui/traits/alias/only-require-assocs-from-supertraits.rs new file mode 100644 index 0000000000000..35149fdfba084 --- /dev/null +++ b/tests/ui/traits/alias/only-require-assocs-from-supertraits.rs @@ -0,0 +1,16 @@ +//@ check-pass + +#![feature(trait_alias)] + +trait Foo {} +trait Bar { type Assoc; } + +trait Alias = Foo; + +// Check that an alias only requires us to specify the associated types +// of the principal's supertraits. For example, we shouldn't require +// specifying the type `Assoc` on trait `Bar` just because we have some +// `T: Bar` where clause on the alias... because that makes no sense. +fn use_alias(x: &dyn Alias) {} + +fn main() {} diff --git a/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.rs b/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.rs index 52ecbcc9e2cb3..7d71fcdd15813 100644 --- a/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.rs +++ b/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.rs @@ -20,6 +20,7 @@ impl Trait for () {} fn func>(t: T) -> impl Trait<(), i32> { //~^ ERROR trait takes 1 generic argument but 2 generic arguments were supplied //~| ERROR trait takes 1 generic argument but 2 generic arguments were supplied +//~| ERROR type annotations needed 3 } diff --git a/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.stderr b/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.stderr index e7ceb7372bfca..f4ede4190fc7a 100644 --- a/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.stderr +++ b/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.stderr @@ -1,3 +1,9 @@ +error[E0207]: the type parameter `S` is not constrained by the impl trait, self type, or predicates + --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:9:9 + | +LL | impl Trait for i32 { + | ^ unconstrained type parameter + error[E0107]: trait takes 1 generic argument but 2 generic arguments were supplied --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:15:12 | @@ -10,6 +16,12 @@ note: trait defined here, with 1 generic parameter: `T` LL | pub trait Trait { | ^^^^^ - +error[E0207]: the type parameter `S` is not constrained by the impl trait, self type, or predicates + --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:15:9 + | +LL | impl Trait for () {} + | ^ unconstrained type parameter + error[E0107]: trait takes 1 generic argument but 2 generic arguments were supplied --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:20:12 | @@ -42,8 +54,14 @@ help: replace the generic bound with the associated type LL | fn func>(t: T) -> impl Trait<(), Assoc = i32> { | +++++++ +error[E0282]: type annotations needed + --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:20:41 + | +LL | fn func>(t: T) -> impl Trait<(), i32> { + | ^^^^^^^^^^^^^^^^^^^ cannot infer type + error[E0107]: trait takes 1 generic argument but 2 generic arguments were supplied - --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:26:18 + --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:27:18 | LL | struct Struct> { | ^^^^^ expected 1 generic argument @@ -59,7 +77,7 @@ LL | struct Struct> { | +++++++ error[E0107]: trait takes 1 generic argument but 2 generic arguments were supplied - --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:31:23 + --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:32:23 | LL | trait AnotherTrait> {} | ^^^^^ expected 1 generic argument @@ -75,7 +93,7 @@ LL | trait AnotherTrait> {} | +++++++ error[E0107]: trait takes 1 generic argument but 2 generic arguments were supplied - --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:34:9 + --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:35:9 | LL | impl> Struct {} | ^^^^^ expected 1 generic argument @@ -91,7 +109,7 @@ LL | impl> Struct {} | +++++++ error[E0107]: struct takes 1 generic argument but 2 generic arguments were supplied - --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:40:58 + --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:41:58 | LL | impl, U> YetAnotherTrait for Struct {} | ^^^^^^ - help: remove this generic argument @@ -99,24 +117,12 @@ LL | impl, U> YetAnotherTrait for Struct {} | expected 1 generic argument | note: struct defined here, with 1 generic parameter: `T` - --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:26:8 + --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:27:8 | LL | struct Struct> { | ^^^^^^ - -error[E0207]: the type parameter `S` is not constrained by the impl trait, self type, or predicates - --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:9:9 - | -LL | impl Trait for i32 { - | ^ unconstrained type parameter - -error[E0207]: the type parameter `S` is not constrained by the impl trait, self type, or predicates - --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:15:9 - | -LL | impl Trait for () {} - | ^ unconstrained type parameter - -error: aborting due to 9 previous errors +error: aborting due to 10 previous errors -Some errors have detailed explanations: E0107, E0207. +Some errors have detailed explanations: E0107, E0207, E0282. For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/traits/bound/in-arc.rs b/tests/ui/traits/bound/in-arc.rs index 40a6115e8381e..2616ad84ff874 100644 --- a/tests/ui/traits/bound/in-arc.rs +++ b/tests/ui/traits/bound/in-arc.rs @@ -3,7 +3,7 @@ // Tests that a heterogeneous list of existential `dyn` types can be put inside an Arc // and shared between threads as long as all types fulfill Send. -//@ ignore-emscripten no threads support +//@ needs-threads use std::sync::Arc; use std::sync::mpsc::channel; diff --git a/tests/ui/traits/bound/on-structs-and-enums-static.rs b/tests/ui/traits/bound/on-structs-and-enums-static.rs index 066416cb362a3..d734893dd7c96 100644 --- a/tests/ui/traits/bound/on-structs-and-enums-static.rs +++ b/tests/ui/traits/bound/on-structs-and-enums-static.rs @@ -8,6 +8,7 @@ struct Foo { static X: Foo = Foo { //~^ ERROR E0277 +//~| ERROR E0277 x: 1, //~ ERROR: E0277 }; diff --git a/tests/ui/traits/bound/on-structs-and-enums-static.stderr b/tests/ui/traits/bound/on-structs-and-enums-static.stderr index 28bbe00c58218..42ebcc07571f1 100644 --- a/tests/ui/traits/bound/on-structs-and-enums-static.stderr +++ b/tests/ui/traits/bound/on-structs-and-enums-static.stderr @@ -16,7 +16,25 @@ LL | struct Foo { | ^^^^^ required by this bound in `Foo` error[E0277]: the trait bound `usize: Trait` is not satisfied - --> $DIR/on-structs-and-enums-static.rs:11:8 + --> $DIR/on-structs-and-enums-static.rs:9:11 + | +LL | static X: Foo = Foo { + | ^^^^^^^^^^ the trait `Trait` is not implemented for `usize` + | +help: this trait has no implementations, consider adding one + --> $DIR/on-structs-and-enums-static.rs:1:1 + | +LL | trait Trait { + | ^^^^^^^^^^^ +note: required by a bound in `Foo` + --> $DIR/on-structs-and-enums-static.rs:5:14 + | +LL | struct Foo { + | ^^^^^ required by this bound in `Foo` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0277]: the trait bound `usize: Trait` is not satisfied + --> $DIR/on-structs-and-enums-static.rs:12:8 | LL | x: 1, | ^ the trait `Trait` is not implemented for `usize` @@ -32,6 +50,6 @@ note: required by a bound in `Foo` LL | struct Foo { | ^^^^^ required by this bound in `Foo` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr b/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr index 629ccac49c56a..17fced307ed1f 100644 --- a/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr +++ b/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr @@ -6,7 +6,7 @@ LL | auto trait Magic: Copy {} | | | auto traits cannot have super traits or lifetime bounds -error[E0277]: the trait bound `NoClone: Copy` is not satisfied +error[E0277]: the trait bound `NoClone: Magic` is not satisfied --> $DIR/supertrait-auto-trait.rs:16:23 | LL | let (a, b) = copy(NoClone); diff --git a/tests/ui/traits/issue-105231.rs b/tests/ui/traits/issue-105231.rs index 74c7afd6b9edb..89b2da4452a5c 100644 --- a/tests/ui/traits/issue-105231.rs +++ b/tests/ui/traits/issue-105231.rs @@ -1,7 +1,9 @@ //~ ERROR overflow evaluating the requirement `A>>>>>>: Send` struct A(B); //~^ ERROR recursive types `A` and `B` have infinite size +//~| ERROR `T` is never used struct B(A>); +//~^ ERROR `T` is never used trait Foo {} impl Foo for T where T: Send {} impl Foo for B {} diff --git a/tests/ui/traits/issue-105231.stderr b/tests/ui/traits/issue-105231.stderr index fe20c47c57a80..6467a438375c9 100644 --- a/tests/ui/traits/issue-105231.stderr +++ b/tests/ui/traits/issue-105231.stderr @@ -3,7 +3,7 @@ error[E0072]: recursive types `A` and `B` have infinite size | LL | struct A(B); | ^^^^^^^^^^^ ---- recursive without indirection -LL | +... LL | struct B(A>); | ^^^^^^^^^^^ ------- recursive without indirection | @@ -11,19 +11,38 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle | LL ~ struct A(Box>); LL | +LL | LL ~ struct B(Box>>); | +error[E0392]: type parameter `T` is never used + --> $DIR/issue-105231.rs:2:10 + | +LL | struct A(B); + | ^ unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + +error[E0392]: type parameter `T` is never used + --> $DIR/issue-105231.rs:5:10 + | +LL | struct B(A>); + | ^ unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + error[E0275]: overflow evaluating the requirement `A>>>>>>: Send` | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_105231`) note: required because it appears within the type `B>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` - --> $DIR/issue-105231.rs:4:8 + --> $DIR/issue-105231.rs:5:8 | LL | struct B(A>); | ^ -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0072, E0275. +Some errors have detailed explanations: E0072, E0275, E0392. For more information about an error, try `rustc --explain E0072`. diff --git a/tests/ui/traits/issue-28576.stderr b/tests/ui/traits/issue-28576.stderr index 653ce05d28574..7e0f52bc4fe09 100644 --- a/tests/ui/traits/issue-28576.stderr +++ b/tests/ui/traits/issue-28576.stderr @@ -1,3 +1,23 @@ +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/issue-28576.rs:5:16 + | +LL | pub trait Bar: Foo { + | ^^^^^^^^^^^^^ doesn't have a size known at compile-time + | +note: required by an implicit `Sized` bound in `Foo` + --> $DIR/issue-28576.rs:1:15 + | +LL | pub trait Foo { + | ^^^^^^^^ required by the implicit `Sized` requirement on this type parameter in `Foo` +help: consider further restricting `Self` + | +LL | pub trait Bar: Foo + Sized { + | +++++++ +help: consider relaxing the implicit `Sized` restriction + | +LL | pub trait Foo { + | ++++++++ + error[E0038]: the trait `Bar` cannot be made into an object --> $DIR/issue-28576.rs:9:12 | @@ -19,26 +39,6 @@ help: consider using an opaque type instead LL | impl Bar | ~~~~ -error[E0277]: the size for values of type `Self` cannot be known at compilation time - --> $DIR/issue-28576.rs:5:16 - | -LL | pub trait Bar: Foo { - | ^^^^^^^^^^^^^ doesn't have a size known at compile-time - | -note: required by an implicit `Sized` bound in `Foo` - --> $DIR/issue-28576.rs:1:15 - | -LL | pub trait Foo { - | ^^^^^^^^ required by the implicit `Sized` requirement on this type parameter in `Foo` -help: consider further restricting `Self` - | -LL | pub trait Bar: Foo + Sized { - | +++++++ -help: consider relaxing the implicit `Sized` restriction - | -LL | pub trait Foo { - | ++++++++ - error[E0277]: the size for values of type `Self` cannot be known at compilation time --> $DIR/issue-28576.rs:5:16 | diff --git a/tests/ui/traits/issue-50480.stderr b/tests/ui/traits/issue-50480.stderr index 6c019f59b0992..330b23b5755d7 100644 --- a/tests/ui/traits/issue-50480.stderr +++ b/tests/ui/traits/issue-50480.stderr @@ -60,6 +60,14 @@ error[E0412]: cannot find type `NotDefined` in this scope LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); | ^^^^^^^^^^ not found in this scope +error[E0277]: `i32` is not an iterator + --> $DIR/issue-50480.rs:3:27 + | +LL | struct Foo(N, NotDefined, ::Item, Vec, String); + | ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator + | + = help: the trait `Iterator` is not implemented for `i32` + error[E0204]: the trait `Copy` cannot be implemented for this type --> $DIR/issue-50480.rs:1:17 | @@ -86,15 +94,6 @@ LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); | = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0277]: `i32` is not an iterator - --> $DIR/issue-50480.rs:3:27 - | -LL | struct Foo(N, NotDefined, ::Item, Vec, String); - | ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator - | - = help: the trait `Iterator` is not implemented for `i32` - = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` - error[E0277]: `i32` is not an iterator --> $DIR/issue-50480.rs:14:33 | @@ -102,7 +101,6 @@ LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); | ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator | = help: the trait `Iterator` is not implemented for `i32` - = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` error[E0277]: `i32` is not an iterator --> $DIR/issue-50480.rs:3:28 @@ -111,7 +109,6 @@ LL | struct Foo(N, NotDefined, ::Item, Vec, String); | ^^^ `i32` is not an iterator | = help: the trait `Iterator` is not implemented for `i32` - = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` error[E0277]: `i32` is not an iterator --> $DIR/issue-50480.rs:11:10 @@ -120,7 +117,6 @@ LL | #[derive(Clone, Copy)] | ^^^^^ `i32` is not an iterator | = help: the trait `Iterator` is not implemented for `i32` - = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: `i32` is not an iterator @@ -133,7 +129,6 @@ LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); | ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator | = help: the trait `Iterator` is not implemented for `i32` - = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 13 previous errors diff --git a/tests/ui/traits/next-solver/assembly/param-env-alias-bound-conflict.rs b/tests/ui/traits/next-solver/assembly/param-env-alias-bound-conflict.rs new file mode 100644 index 0000000000000..ddda1a71d7ee4 --- /dev/null +++ b/tests/ui/traits/next-solver/assembly/param-env-alias-bound-conflict.rs @@ -0,0 +1,26 @@ +//@ compile-flags: -Znext-solver +//@ check-pass + +// Regression test for #119607. + +pub trait IntoFoo { + type Item; + type IntoIter: Foo; + + fn into_iter(self) -> Self::IntoIter; +} + +pub trait Foo { + type Item; + + fn next(self) -> Option; +} + +pub fn foo<'a, Iter1, Elem1>(a: &'a Iter1) +where + &'a Iter1: IntoFoo, +{ + a.into_iter().next(); +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr index a04fa1ab8a177..39d453e8035e8 100644 --- a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr +++ b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr @@ -1,15 +1,3 @@ -error[E0119]: conflicting implementations of trait `Trait` - --> $DIR/trait_ref_is_knowable-norm-overflow.rs:18:1 - | -LL | impl Trait for T {} - | ------------------------- first implementation here -LL | struct LocalTy; -LL | impl Trait for ::Assoc {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation - | - = note: overflow evaluating the requirement `_ == ::Assoc` - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`trait_ref_is_knowable_norm_overflow`) - error[E0275]: overflow evaluating the requirement `::Assoc: Sized` --> $DIR/trait_ref_is_knowable-norm-overflow.rs:10:18 | @@ -27,6 +15,18 @@ help: consider relaxing the implicit `Sized` restriction LL | type Assoc: ?Sized; | ++++++++ +error[E0119]: conflicting implementations of trait `Trait` + --> $DIR/trait_ref_is_knowable-norm-overflow.rs:18:1 + | +LL | impl Trait for T {} + | ------------------------- first implementation here +LL | struct LocalTy; +LL | impl Trait for ::Assoc {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation + | + = note: overflow evaluating the requirement `_ == ::Assoc` + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`trait_ref_is_knowable_norm_overflow`) + error: aborting due to 2 previous errors Some errors have detailed explanations: E0119, E0275. diff --git a/tests/ui/traits/next-solver/env-shadows-impls/param-env-impl-conflict.rs b/tests/ui/traits/next-solver/env-shadows-impls/param-env-impl-conflict.rs new file mode 100644 index 0000000000000..1b9e9866cd60e --- /dev/null +++ b/tests/ui/traits/next-solver/env-shadows-impls/param-env-impl-conflict.rs @@ -0,0 +1,23 @@ +//@ compile-flags: -Znext-solver +//@ check-pass + +// Regression test for #119608. + +pub trait Foo {} + +pub trait Bar { + type Assoc; +} + +impl Bar for T { + type Assoc = T; +} + +pub fn foo(_input: ::Assoc) +where + I: Bar, + ::Assoc: Foo, +{ +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.stderr b/tests/ui/traits/next-solver/issue-118950-root-region.stderr index 931c46c688727..45ff9f763cd10 100644 --- a/tests/ui/traits/next-solver/issue-118950-root-region.stderr +++ b/tests/ui/traits/next-solver/issue-118950-root-region.stderr @@ -13,6 +13,12 @@ LL | #![feature(lazy_type_alias)] = note: see issue #112792 for more information = note: `#[warn(incomplete_features)]` on by default +error: the type `<*const T as ToUnit<'a>>::Unit` is not well-formed + --> $DIR/issue-118950-root-region.rs:14:21 + | +LL | type Assoc<'a, T> = <*const T as ToUnit<'a>>::Unit; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), 'a) }), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) } WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), 'a) }), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) } WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), 'a) }), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) } @@ -26,12 +32,6 @@ LL | LL | impl Overlap fn(Assoc<'a, T>)> for T where Missing: Overlap {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `fn(_)` -error: the type `<*const T as ToUnit<'a>>::Unit` is not well-formed - --> $DIR/issue-118950-root-region.rs:14:21 - | -LL | type Assoc<'a, T> = <*const T as ToUnit<'a>>::Unit; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error: aborting due to 3 previous errors; 1 warning emitted Some errors have detailed explanations: E0119, E0412. diff --git a/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.stderr b/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.stderr index 3a4415ed23aca..6c259621466d3 100644 --- a/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.stderr +++ b/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.stderr @@ -21,6 +21,20 @@ help: consider adding an explicit lifetime bound LL | for F: 'a, !1_"F": 'a | ~~~~~~~~~~~~ -error: aborting due to 1 previous error; 1 warning emitted +error[E0309]: the placeholder type `!2_"F"` may not live long enough + --> $DIR/type-match-with-late-bound.rs:11:1 + | +LL | async fn walk2<'a, T: 'a>(_: T) + | -- the placeholder type `!2_"F"` must be valid for the lifetime `'a` as defined here... +... +LL | {} + | ^^ ...so that the type `F` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound + | +LL | for F: 'a, !2_"F": 'a + | ~~~~~~~~~~~~ + +error: aborting due to 2 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/traits/suggest-dereferences/root-obligation.fixed b/tests/ui/traits/suggest-dereferences/root-obligation.fixed index eecd52304ff66..072296c6b154d 100644 --- a/tests/ui/traits/suggest-dereferences/root-obligation.fixed +++ b/tests/ui/traits/suggest-dereferences/root-obligation.fixed @@ -4,7 +4,7 @@ fn get_vowel_count(string: &str) -> usize { string .chars() .filter(|c| "aeiou".contains(*c)) - //~^ ERROR expected a `Fn(char)` closure, found `char` + //~^ ERROR the trait bound `&char: Pattern<'_>` is not satisfied .count() } diff --git a/tests/ui/traits/suggest-dereferences/root-obligation.rs b/tests/ui/traits/suggest-dereferences/root-obligation.rs index d58193f121382..e7025fe082541 100644 --- a/tests/ui/traits/suggest-dereferences/root-obligation.rs +++ b/tests/ui/traits/suggest-dereferences/root-obligation.rs @@ -4,7 +4,7 @@ fn get_vowel_count(string: &str) -> usize { string .chars() .filter(|c| "aeiou".contains(c)) - //~^ ERROR expected a `Fn(char)` closure, found `char` + //~^ ERROR the trait bound `&char: Pattern<'_>` is not satisfied .count() } diff --git a/tests/ui/traits/suggest-dereferences/root-obligation.stderr b/tests/ui/traits/suggest-dereferences/root-obligation.stderr index a41330373be1a..56f95e207158a 100644 --- a/tests/ui/traits/suggest-dereferences/root-obligation.stderr +++ b/tests/ui/traits/suggest-dereferences/root-obligation.stderr @@ -1,12 +1,11 @@ -error[E0277]: expected a `Fn(char)` closure, found `char` +error[E0277]: the trait bound `&char: Pattern<'_>` is not satisfied --> $DIR/root-obligation.rs:6:38 | LL | .filter(|c| "aeiou".contains(c)) - | -------- ^ expected an `Fn(char)` closure, found `char` + | -------- ^ the trait `Fn<(char,)>` is not implemented for `&char`, which is required by `&char: Pattern<'_>` | | | required by a bound introduced by this call | - = help: the trait `Fn<(char,)>` is not implemented for `char`, which is required by `&char: Pattern<'_>` = note: required for `&char` to implement `FnOnce<(char,)>` = note: required for `&char` to implement `Pattern<'_>` note: required by a bound in `core::str::::contains` diff --git a/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.rs b/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.rs index 511e41562b220..6211c7fac4158 100644 --- a/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.rs +++ b/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.rs @@ -1,5 +1,6 @@ trait A: B + A {} //~^ ERROR cycle detected when computing the super predicates of `A` [E0391] +//~| ERROR cycle detected when computing the implied predicates of `A` [E0391] trait B {} diff --git a/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr b/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr index 85c05bd05db1f..b9988e2e6d336 100644 --- a/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr +++ b/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr @@ -5,13 +5,27 @@ LL | trait A: B + A {} | ^ | = note: ...which immediately requires computing the super predicates of `A` again -note: cycle used when collecting item types in top-level module +note: cycle used when checking that `A` is well-formed --> $DIR/cyclic-trait-resolution.rs:1:1 | LL | trait A: B + A {} | ^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to 1 previous error +error[E0391]: cycle detected when computing the implied predicates of `A` + --> $DIR/cyclic-trait-resolution.rs:1:14 + | +LL | trait A: B + A {} + | ^ + | + = note: ...which immediately requires computing the implied predicates of `A` again +note: cycle used when checking that `` is well-formed + --> $DIR/cyclic-trait-resolution.rs:7:1 + | +LL | impl A for () {} + | ^^^^^^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/type-alias-enum-variants/self-in-enum-definition.stderr b/tests/ui/type-alias-enum-variants/self-in-enum-definition.stderr index 7f80c3cfaba44..df466609a1246 100644 --- a/tests/ui/type-alias-enum-variants/self-in-enum-definition.stderr +++ b/tests/ui/type-alias-enum-variants/self-in-enum-definition.stderr @@ -46,17 +46,11 @@ LL | V3 = Self::V1 {} as u8 + 2, | ^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires computing layout of `Alpha`... = note: ...which again requires simplifying constant for the type system `Alpha::V3::{constant#0}`, completing the cycle -note: cycle used when collecting item types in top-level module - --> $DIR/self-in-enum-definition.rs:1:1 +note: cycle used when checking that `Alpha` is well-formed + --> $DIR/self-in-enum-definition.rs:2:1 | -LL | / #[repr(u8)] -LL | | enum Alpha { -LL | | V1 = 41, -LL | | V2 = Self::V1 as u8 + 1, // OK; See #50072. -... | -LL | | -LL | | fn main() {} - | |____________^ +LL | enum Alpha { + | ^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.rs b/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.rs index 7c7c68ad60afe..f62dccff58d0d 100644 --- a/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.rs +++ b/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.rs @@ -20,6 +20,7 @@ impl<'a, I> UnwrapItemsExt for I { fn unwrap_items(self) -> Self::Iter { MyStruct {} + //~^ ERROR expected generic lifetime parameter } } diff --git a/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr b/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr index 089c3e4fd8ab2..e6b94c525ff23 100644 --- a/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr +++ b/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr @@ -4,6 +4,16 @@ error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, LL | impl<'a, I> UnwrapItemsExt for I { | ^^ unconstrained lifetime parameter -error: aborting due to 1 previous error +error[E0792]: expected generic lifetime parameter, found `'_` + --> $DIR/assoc-type-lifetime-unconstrained.rs:22:9 + | +LL | impl<'a, I> UnwrapItemsExt for I { + | -- this generic parameter must be used with a generic lifetime parameter +... +LL | MyStruct {} + | ^^^^^^^^^^^ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0207`. +Some errors have detailed explanations: E0207, E0792. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/type-alias-impl-trait/escaping-bound-var.rs b/tests/ui/type-alias-impl-trait/escaping-bound-var.rs index bf27e76db2b4d..1ff200680be5e 100644 --- a/tests/ui/type-alias-impl-trait/escaping-bound-var.rs +++ b/tests/ui/type-alias-impl-trait/escaping-bound-var.rs @@ -7,7 +7,7 @@ pub trait Trait<'a> { trait Test<'a> {} pub type Foo = impl for<'a> Trait<'a, Assoc = impl Test<'a>>; -//~^ ERROR cannot capture late-bound lifetime in type alias impl trait +//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` impl Trait<'_> for () { type Assoc = (); diff --git a/tests/ui/type-alias-impl-trait/escaping-bound-var.stderr b/tests/ui/type-alias-impl-trait/escaping-bound-var.stderr index 7dce067d39c68..09f6fba79cfdf 100644 --- a/tests/ui/type-alias-impl-trait/escaping-bound-var.stderr +++ b/tests/ui/type-alias-impl-trait/escaping-bound-var.stderr @@ -1,8 +1,15 @@ -error: cannot capture late-bound lifetime in type alias impl trait - --> $DIR/escaping-bound-var.rs:9:57 +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` + --> $DIR/escaping-bound-var.rs:9:47 | LL | pub type Foo = impl for<'a> Trait<'a, Assoc = impl Test<'a>>; - | -- lifetime defined here ^^ + | ^^^^^^^^^^^^^ `impl Trait` implicitly captures all lifetimes in scope + | +note: lifetime declared here + --> $DIR/escaping-bound-var.rs:9:25 + | +LL | pub type Foo = impl for<'a> Trait<'a, Assoc = impl Test<'a>>; + | ^^ error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0657`. diff --git a/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.rs b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.rs index 4c881dd133086..3117060cef0d2 100644 --- a/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.rs +++ b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.rs @@ -15,7 +15,7 @@ impl Trait for Bar { type Assoc = impl std::fmt::Debug; fn foo() -> Foo { Foo { field: () } - //~^ ERROR: item constrains opaque type that is not in its signature + //~^ ERROR: mismatched types } } diff --git a/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.stderr b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.stderr index 5c53dfa3a7500..4910e794e8d6e 100644 --- a/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.stderr +++ b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.stderr @@ -1,11 +1,15 @@ -error: item constrains opaque type that is not in its signature +error[E0308]: mismatched types --> $DIR/hidden_behind_struct_field2.rs:17:22 | +LL | type Assoc = impl std::fmt::Debug; + | -------------------- the expected opaque type +LL | fn foo() -> Foo { LL | Foo { field: () } - | ^^ + | ^^ expected opaque type, found `()` | - = note: this item must mention the opaque type in its signature in order to be able to register hidden types -note: this item must mention the opaque type in its signature in order to be able to register hidden types + = note: expected opaque type `::Assoc` + found unit type `()` +note: this item must have the opaque type in its signature in order to be able to register hidden types --> $DIR/hidden_behind_struct_field2.rs:16:8 | LL | fn foo() -> Foo { @@ -13,3 +17,4 @@ LL | fn foo() -> Foo { error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/hidden_behind_struct_field3.rs b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field3.rs new file mode 100644 index 0000000000000..c1f135994121e --- /dev/null +++ b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field3.rs @@ -0,0 +1,28 @@ +//! This test demonstrates a bug where we accidentally +//! detected opaque types in struct fields, but only if nested +//! in projections of another opaque type. + +#![feature(impl_trait_in_assoc_type)] + +struct Bar; + +trait Trait: Sized { + type Assoc2; + type Assoc; + fn foo() -> Self::Assoc; +} + +impl Trait for Bar { + type Assoc2 = impl std::fmt::Debug; + type Assoc = impl Iterator; + fn foo() -> Self::Assoc { + vec![Foo { field: () }].into_iter() + //~^ ERROR mismatched types + } +} + +struct Foo { + field: ::Assoc2, +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/hidden_behind_struct_field3.stderr b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field3.stderr new file mode 100644 index 0000000000000..f10ccc0029973 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field3.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/hidden_behind_struct_field3.rs:19:27 + | +LL | type Assoc2 = impl std::fmt::Debug; + | -------------------- the expected opaque type +... +LL | vec![Foo { field: () }].into_iter() + | ^^ expected opaque type, found `()` + | + = note: expected opaque type `::Assoc2` + found unit type `()` +note: this item must have the opaque type in its signature in order to be able to register hidden types + --> $DIR/hidden_behind_struct_field3.rs:18:8 + | +LL | fn foo() -> Self::Assoc { + | ^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.rs b/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.rs index 1824ff5e2fb82..fcac83500ec4f 100644 --- a/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.rs +++ b/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.rs @@ -12,6 +12,8 @@ impl X for () { //~^ ERROR the type parameter `T` is not constrained type I = impl Sized; fn f() -> Self::I {} + //~^ ERROR type annotations needed + //~| ERROR type annotations needed } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr b/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr index 137a4db81b563..bb0e11d314c33 100644 --- a/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr +++ b/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr @@ -4,6 +4,19 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self LL | impl X for () { | ^ unconstrained type parameter -error: aborting due to 1 previous error +error[E0282]: type annotations needed + --> $DIR/impl-with-unconstrained-param.rs:14:23 + | +LL | fn f() -> Self::I {} + | ^^ cannot infer type for type parameter `T` + +error[E0282]: type annotations needed + --> $DIR/impl-with-unconstrained-param.rs:14:15 + | +LL | fn f() -> Self::I {} + | ^^^^^^^ cannot infer type for type parameter `T` + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0207`. +Some errors have detailed explanations: E0207, E0282. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/type-alias-impl-trait/issue-74244.rs b/tests/ui/type-alias-impl-trait/issue-74244.rs index bb4104b3d2519..ce8a38a3361f8 100644 --- a/tests/ui/type-alias-impl-trait/issue-74244.rs +++ b/tests/ui/type-alias-impl-trait/issue-74244.rs @@ -14,6 +14,7 @@ impl Allocator for DefaultAllocator { type A = impl Fn(::Buffer); fn foo() -> A { + //~^ ERROR: type annotations needed |_| () } diff --git a/tests/ui/type-alias-impl-trait/issue-74244.stderr b/tests/ui/type-alias-impl-trait/issue-74244.stderr index f5ca56bacccf6..d2b50ffd86b59 100644 --- a/tests/ui/type-alias-impl-trait/issue-74244.stderr +++ b/tests/ui/type-alias-impl-trait/issue-74244.stderr @@ -4,6 +4,13 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self LL | impl Allocator for DefaultAllocator { | ^ unconstrained type parameter -error: aborting due to 1 previous error +error[E0282]: type annotations needed + --> $DIR/issue-74244.rs:16:13 + | +LL | fn foo() -> A { + | ^ cannot infer type for type parameter `T` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0207`. +Some errors have detailed explanations: E0207, E0282. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/type-alias-impl-trait/issue-74761-2.rs b/tests/ui/type-alias-impl-trait/issue-74761-2.rs index f582592e9bcc8..e556025adee6e 100644 --- a/tests/ui/type-alias-impl-trait/issue-74761-2.rs +++ b/tests/ui/type-alias-impl-trait/issue-74761-2.rs @@ -10,6 +10,7 @@ impl<'a, 'b> A for () { type B = impl core::fmt::Debug; fn f(&self) -> Self::B {} + //~^ ERROR expected generic lifetime parameter } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-74761-2.stderr b/tests/ui/type-alias-impl-trait/issue-74761-2.stderr index f15d0a069ca8a..26babc29000c0 100644 --- a/tests/ui/type-alias-impl-trait/issue-74761-2.stderr +++ b/tests/ui/type-alias-impl-trait/issue-74761-2.stderr @@ -10,6 +10,16 @@ error[E0207]: the lifetime parameter `'b` is not constrained by the impl trait, LL | impl<'a, 'b> A for () { | ^^ unconstrained lifetime parameter -error: aborting due to 2 previous errors +error[E0792]: expected generic lifetime parameter, found `'_` + --> $DIR/issue-74761-2.rs:12:28 + | +LL | impl<'a, 'b> A for () { + | -- this generic parameter must be used with a generic lifetime parameter +... +LL | fn f(&self) -> Self::B {} + | ^^ + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0207`. +Some errors have detailed explanations: E0207, E0792. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/type-alias-impl-trait/issue-74761.rs b/tests/ui/type-alias-impl-trait/issue-74761.rs index f582592e9bcc8..e556025adee6e 100644 --- a/tests/ui/type-alias-impl-trait/issue-74761.rs +++ b/tests/ui/type-alias-impl-trait/issue-74761.rs @@ -10,6 +10,7 @@ impl<'a, 'b> A for () { type B = impl core::fmt::Debug; fn f(&self) -> Self::B {} + //~^ ERROR expected generic lifetime parameter } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-74761.stderr b/tests/ui/type-alias-impl-trait/issue-74761.stderr index 1d016fe070f9c..a4826c293467e 100644 --- a/tests/ui/type-alias-impl-trait/issue-74761.stderr +++ b/tests/ui/type-alias-impl-trait/issue-74761.stderr @@ -10,6 +10,16 @@ error[E0207]: the lifetime parameter `'b` is not constrained by the impl trait, LL | impl<'a, 'b> A for () { | ^^ unconstrained lifetime parameter -error: aborting due to 2 previous errors +error[E0792]: expected generic lifetime parameter, found `'_` + --> $DIR/issue-74761.rs:12:28 + | +LL | impl<'a, 'b> A for () { + | -- this generic parameter must be used with a generic lifetime parameter +... +LL | fn f(&self) -> Self::B {} + | ^^ + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0207`. +Some errors have detailed explanations: E0207, E0792. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/type-alias-impl-trait/issue-90400-2.stderr b/tests/ui/type-alias-impl-trait/issue-90400-2.stderr index 5e978e97d6b50..b4b78f8175fa2 100644 --- a/tests/ui/type-alias-impl-trait/issue-90400-2.stderr +++ b/tests/ui/type-alias-impl-trait/issue-90400-2.stderr @@ -2,15 +2,13 @@ error[E0277]: the trait bound `B: Bar` is not satisfied --> $DIR/issue-90400-2.rs:25:9 | LL | MyBaz(bar) - | ^^^^^^^^^^ the trait `Bar` is not implemented for `B`, which is required by `MyBaz: Baz` + | ^^^^^^^^^^ the trait `Bar` is not implemented for `B` | -note: required for `MyBaz` to implement `Baz` - --> $DIR/issue-90400-2.rs:30:14 +note: required by a bound in `MyBaz` + --> $DIR/issue-90400-2.rs:29:17 | -LL | impl Baz for MyBaz { - | --- ^^^ ^^^^^^^^ - | | - | unsatisfied trait bound introduced here +LL | struct MyBaz(B); + | ^^^ required by this bound in `MyBaz` help: consider restricting type parameter `B` | LL | type FooFn = impl Baz; diff --git a/tests/ui/type-alias-impl-trait/self-referential.rs b/tests/ui/type-alias-impl-trait/self-referential.rs index 3090f7733d24d..2bd450e6c8609 100644 --- a/tests/ui/type-alias-impl-trait/self-referential.rs +++ b/tests/ui/type-alias-impl-trait/self-referential.rs @@ -12,14 +12,14 @@ fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> { type Foo<'a, 'b> = (i32, impl PartialEq> + std::fmt::Debug); fn foo<'a, 'b>(i: &'a i32) -> Foo<'a, 'b> { - //~^ ERROR can't compare `&i32` with `(i32, Foo<'a, 'b>::{opaque#0})` + //~^ ERROR can't compare `&i32` with `(i32, Foo<'a, 'b>::{opaque#0}<'a, 'b>)` (42, i) } type Moo<'a, 'b> = (i32, impl PartialEq> + std::fmt::Debug); fn moo<'a, 'b>(i: &'a i32) -> Moo<'a, 'b> { - //~^ ERROR can't compare `&i32` with `(i32, Moo<'b, 'a>::{opaque#0})` + //~^ ERROR can't compare `&i32` with `(i32, Moo<'b, 'a>::{opaque#0}<'b, 'a>)` (42, i) } diff --git a/tests/ui/type-alias-impl-trait/self-referential.stderr b/tests/ui/type-alias-impl-trait/self-referential.stderr index 27506b8d06f80..396237c78980c 100644 --- a/tests/ui/type-alias-impl-trait/self-referential.stderr +++ b/tests/ui/type-alias-impl-trait/self-referential.stderr @@ -10,28 +10,28 @@ LL | i = help: the trait `PartialEq>` is not implemented for `&i32` = help: the trait `PartialEq` is implemented for `i32` -error[E0277]: can't compare `&i32` with `(i32, Foo<'a, 'b>::{opaque#0})` +error[E0277]: can't compare `&i32` with `(i32, Foo<'a, 'b>::{opaque#0}<'a, 'b>)` --> $DIR/self-referential.rs:14:31 | LL | fn foo<'a, 'b>(i: &'a i32) -> Foo<'a, 'b> { - | ^^^^^^^^^^^ no implementation for `&i32 == (i32, Foo<'a, 'b>::{opaque#0})` + | ^^^^^^^^^^^ no implementation for `&i32 == (i32, Foo<'a, 'b>::{opaque#0}<'a, 'b>)` LL | LL | (42, i) | ------- return type was inferred to be `(i32, &i32)` here | - = help: the trait `PartialEq<(i32, Foo<'a, 'b>::{opaque#0})>` is not implemented for `&i32` + = help: the trait `PartialEq<(i32, Foo<'a, 'b>::{opaque#0}<'a, 'b>)>` is not implemented for `&i32` = help: the trait `PartialEq` is implemented for `i32` -error[E0277]: can't compare `&i32` with `(i32, Moo<'b, 'a>::{opaque#0})` +error[E0277]: can't compare `&i32` with `(i32, Moo<'b, 'a>::{opaque#0}<'b, 'a>)` --> $DIR/self-referential.rs:21:31 | LL | fn moo<'a, 'b>(i: &'a i32) -> Moo<'a, 'b> { - | ^^^^^^^^^^^ no implementation for `&i32 == (i32, Moo<'b, 'a>::{opaque#0})` + | ^^^^^^^^^^^ no implementation for `&i32 == (i32, Moo<'b, 'a>::{opaque#0}<'b, 'a>)` LL | LL | (42, i) | ------- return type was inferred to be `(i32, &i32)` here | - = help: the trait `PartialEq<(i32, Moo<'b, 'a>::{opaque#0})>` is not implemented for `&i32` + = help: the trait `PartialEq<(i32, Moo<'b, 'a>::{opaque#0}<'b, 'a>)>` is not implemented for `&i32` = help: the trait `PartialEq` is implemented for `i32` error: aborting due to 3 previous errors diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.rs index 296a3f3e30072..b232097fdb332 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.rs +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.rs @@ -12,6 +12,7 @@ impl<'a, I: Iterator> Trait for (i32, I) { type Associated = (i32, impl Iterator); fn into(self) -> Self::Associated { (0_i32, [0_i32].iter().copied()) + //~^ ERROR: expected generic lifetime parameter, found `'_` } } diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.stderr index cff2695304ae2..5f9c56f1ca9d0 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.stderr +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.stderr @@ -4,6 +4,16 @@ error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, LL | impl<'a, I: Iterator> Trait for (i32, I) { | ^^ unconstrained lifetime parameter -error: aborting due to 1 previous error +error[E0792]: expected generic lifetime parameter, found `'_` + --> $DIR/type-alias-impl-trait-unconstrained-lifetime.rs:14:9 + | +LL | impl<'a, I: Iterator> Trait for (i32, I) { + | -- this generic parameter must be used with a generic lifetime parameter +... +LL | (0_i32, [0_i32].iter().copied()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0207`. +Some errors have detailed explanations: E0207, E0792. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/type-alias-impl-trait/variance.rs b/tests/ui/type-alias-impl-trait/variance.rs index e92cf2513e731..4b9fa67fd64c7 100644 --- a/tests/ui/type-alias-impl-trait/variance.rs +++ b/tests/ui/type-alias-impl-trait/variance.rs @@ -5,17 +5,22 @@ trait Captures<'a> {} impl Captures<'_> for T {} -type NotCapturedEarly<'a> = impl Sized; //~ [o] +type NotCapturedEarly<'a> = impl Sized; //~ [*, o] +//~^ ERROR: unconstrained opaque type -type CapturedEarly<'a> = impl Sized + Captures<'a>; //~ [o] +type CapturedEarly<'a> = impl Sized + Captures<'a>; //~ [*, o] +//~^ ERROR: unconstrained opaque type -// TAIT does *not* capture `'b` -type NotCapturedLate<'a> = dyn for<'b> Iterator; //~ [o] +type NotCapturedLate<'a> = dyn for<'b> Iterator; //~ [*, o, o] +//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type +//~| ERROR: unconstrained opaque type -// TAIT does *not* capture `'b` -type Captured<'a> = dyn for<'b> Iterator>; //~ [o] +type Captured<'a> = dyn for<'b> Iterator>; //~ [*, o, o] +//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type +//~| ERROR: unconstrained opaque type -type Bar<'a, 'b: 'b, T> = impl Sized; //~ ERROR [o, o, o] +type Bar<'a, 'b: 'b, T> = impl Sized; //~ ERROR [*, *, o, o, o] +//~^ ERROR: unconstrained opaque type trait Foo<'i> { type ImplicitCapture<'a>; @@ -26,19 +31,25 @@ trait Foo<'i> { } impl<'i> Foo<'i> for &'i () { - type ImplicitCapture<'a> = impl Sized; //~ [o, o] + type ImplicitCapture<'a> = impl Sized; //~ [*, *, o, o] + //~^ ERROR: unconstrained opaque type - type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ [o, o] + type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ [*, *, o, o] + //~^ ERROR: unconstrained opaque type - type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ [o, o] + type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ [*, *, o, o] + //~^ ERROR: unconstrained opaque type } impl<'i> Foo<'i> for () { - type ImplicitCapture<'a> = impl Sized; //~ [o, o] + type ImplicitCapture<'a> = impl Sized; //~ [*, *, o, o] + //~^ ERROR: unconstrained opaque type - type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ [o, o] + type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ [*, *, o, o] + //~^ ERROR: unconstrained opaque type - type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ [o, o] + type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ [*, *, o, o] + //~^ ERROR: unconstrained opaque type } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/variance.stderr b/tests/ui/type-alias-impl-trait/variance.stderr index 1794447c89a20..1aaf36223b7f5 100644 --- a/tests/ui/type-alias-impl-trait/variance.stderr +++ b/tests/ui/type-alias-impl-trait/variance.stderr @@ -1,68 +1,181 @@ -error: [o] +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from `dyn` type + --> $DIR/variance.rs:14:56 + | +LL | type NotCapturedLate<'a> = dyn for<'b> Iterator; + | ^^^^^^^^^^ `impl Trait` implicitly captures all lifetimes in scope + | +note: lifetime declared here + --> $DIR/variance.rs:14:36 + | +LL | type NotCapturedLate<'a> = dyn for<'b> Iterator; + | ^^ + +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from `dyn` type + --> $DIR/variance.rs:18:49 + | +LL | type Captured<'a> = dyn for<'b> Iterator>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ `impl Trait` implicitly captures all lifetimes in scope + | +note: lifetime declared here + --> $DIR/variance.rs:18:29 + | +LL | type Captured<'a> = dyn for<'b> Iterator>; + | ^^ + +error: unconstrained opaque type + --> $DIR/variance.rs:8:29 + | +LL | type NotCapturedEarly<'a> = impl Sized; + | ^^^^^^^^^^ + | + = note: `NotCapturedEarly` must be used in combination with a concrete type within the same module + +error: unconstrained opaque type + --> $DIR/variance.rs:11:26 + | +LL | type CapturedEarly<'a> = impl Sized + Captures<'a>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `CapturedEarly` must be used in combination with a concrete type within the same module + +error: unconstrained opaque type + --> $DIR/variance.rs:14:56 + | +LL | type NotCapturedLate<'a> = dyn for<'b> Iterator; + | ^^^^^^^^^^ + | + = note: `NotCapturedLate` must be used in combination with a concrete type within the same module + +error: unconstrained opaque type + --> $DIR/variance.rs:18:49 + | +LL | type Captured<'a> = dyn for<'b> Iterator>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `Captured` must be used in combination with a concrete type within the same module + +error: unconstrained opaque type + --> $DIR/variance.rs:22:27 + | +LL | type Bar<'a, 'b: 'b, T> = impl Sized; + | ^^^^^^^^^^ + | + = note: `Bar` must be used in combination with a concrete type within the same module + +error: unconstrained opaque type + --> $DIR/variance.rs:34:32 + | +LL | type ImplicitCapture<'a> = impl Sized; + | ^^^^^^^^^^ + | + = note: `ImplicitCapture` must be used in combination with a concrete type within the same impl + +error: unconstrained opaque type + --> $DIR/variance.rs:37:42 + | +LL | type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `ExplicitCaptureFromHeader` must be used in combination with a concrete type within the same impl + +error: unconstrained opaque type + --> $DIR/variance.rs:40:39 + | +LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `ExplicitCaptureFromGat` must be used in combination with a concrete type within the same impl + +error: unconstrained opaque type + --> $DIR/variance.rs:45:32 + | +LL | type ImplicitCapture<'a> = impl Sized; + | ^^^^^^^^^^ + | + = note: `ImplicitCapture` must be used in combination with a concrete type within the same impl + +error: unconstrained opaque type + --> $DIR/variance.rs:48:42 + | +LL | type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `ExplicitCaptureFromHeader` must be used in combination with a concrete type within the same impl + +error: unconstrained opaque type + --> $DIR/variance.rs:51:39 + | +LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `ExplicitCaptureFromGat` must be used in combination with a concrete type within the same impl + +error: [*, o] --> $DIR/variance.rs:8:29 | LL | type NotCapturedEarly<'a> = impl Sized; | ^^^^^^^^^^ -error: [o] - --> $DIR/variance.rs:10:26 +error: [*, o] + --> $DIR/variance.rs:11:26 | LL | type CapturedEarly<'a> = impl Sized + Captures<'a>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [o] - --> $DIR/variance.rs:13:56 +error: [*, o, o] + --> $DIR/variance.rs:14:56 | LL | type NotCapturedLate<'a> = dyn for<'b> Iterator; | ^^^^^^^^^^ -error: [o] - --> $DIR/variance.rs:16:49 +error: [*, o, o] + --> $DIR/variance.rs:18:49 | LL | type Captured<'a> = dyn for<'b> Iterator>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [o, o, o] - --> $DIR/variance.rs:18:27 +error: [*, *, o, o, o] + --> $DIR/variance.rs:22:27 | LL | type Bar<'a, 'b: 'b, T> = impl Sized; | ^^^^^^^^^^ -error: [o, o] - --> $DIR/variance.rs:29:32 +error: [*, *, o, o] + --> $DIR/variance.rs:34:32 | LL | type ImplicitCapture<'a> = impl Sized; | ^^^^^^^^^^ -error: [o, o] - --> $DIR/variance.rs:31:42 +error: [*, *, o, o] + --> $DIR/variance.rs:37:42 | LL | type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [o, o] - --> $DIR/variance.rs:33:39 +error: [*, *, o, o] + --> $DIR/variance.rs:40:39 | LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [o, o] - --> $DIR/variance.rs:37:32 +error: [*, *, o, o] + --> $DIR/variance.rs:45:32 | LL | type ImplicitCapture<'a> = impl Sized; | ^^^^^^^^^^ -error: [o, o] - --> $DIR/variance.rs:39:42 +error: [*, *, o, o] + --> $DIR/variance.rs:48:42 | LL | type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [o, o] - --> $DIR/variance.rs:41:39 +error: [*, *, o, o] + --> $DIR/variance.rs:51:39 | LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 11 previous errors +error: aborting due to 24 previous errors +For more information about this error, try `rustc --explain E0657`. diff --git a/tests/ui/type-alias-impl-trait/wf-check-definition-site.rs b/tests/ui/type-alias-impl-trait/wf-check-definition-site.rs new file mode 100644 index 0000000000000..19dd4c1793677 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/wf-check-definition-site.rs @@ -0,0 +1,40 @@ +//@ check-pass + +// Regression test for #114572, We were inferring an ill-formed type: +// +// `Opaque<'a> = Static<&'a str>`, vs +// `Opaque<'a> = Static<&'static str>`. +// +// The hidden type of the opaque ends up as `Static<'?0 str>`. When +// computing member constraints we end up choosing `'a` for `?0` unless +// `?0` is already required to outlive `'a`. We achieve this by checking +// that `Static<'?0 str>` is well-formed. +#![feature(type_alias_impl_trait)] + +struct Static(T); + +type OpaqueRet<'a> = impl Sized + 'a; +fn test_return<'a>(msg: Static<&'static u8>) -> OpaqueRet<'a> { + msg +} + +fn test_rpit<'a>(msg: Static<&'static u8>) -> impl Sized + 'a { + msg +} + +type OpaqueAssign<'a> = impl Sized + 'a; +fn test_assign<'a>(msg: Static<&'static u8>) -> Option> { + let _: OpaqueAssign<'a> = msg; + None +} + +// `OpaqueRef<'a, T> = Ref<'a, T>`, vs +// `OpaqueRef<'a, T> = Ref<'static, T>`. +trait RefAt<'a>: 'a {} +struct Ref<'a, T: RefAt<'a>>(&'a T); +type OpaqueRef<'a, T: RefAt<'static>> = impl Sized + 'a; +fn test_trait<'a, T: RefAt<'static>>(msg: Ref<'static, T>) -> OpaqueRef<'a, T> { + msg +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/wf-nested.fail.stderr b/tests/ui/type-alias-impl-trait/wf-nested.fail.stderr index 17c1f8897bf0c..79b726f83dde0 100644 --- a/tests/ui/type-alias-impl-trait/wf-nested.fail.stderr +++ b/tests/ui/type-alias-impl-trait/wf-nested.fail.stderr @@ -1,21 +1,16 @@ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/wf-nested.rs:57:27 + --> $DIR/wf-nested.rs:64:38 | -LL | type InnerOpaque = impl Sized; - | ^^^^^^^^^^ - | | - | the parameter type `T` must be valid for the static lifetime... - | ...so that the type `T` will meet its required lifetime bounds... +LL | fn define() -> OuterOpaque {} + | ^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds | -note: ...that is required by this bound - --> $DIR/wf-nested.rs:12:20 - | -LL | struct IsStatic(T); - | ^^^^^^^ help: consider adding an explicit lifetime bound | -LL | type InnerOpaque = impl Sized; - | +++++++++ +LL | fn define() -> OuterOpaque {} + | +++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/wf-nested.pass.stderr b/tests/ui/type-alias-impl-trait/wf-nested.pass.stderr new file mode 100644 index 0000000000000..b61b69d8e407e --- /dev/null +++ b/tests/ui/type-alias-impl-trait/wf-nested.pass.stderr @@ -0,0 +1,31 @@ +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/wf-nested.rs:34:38 + | +LL | fn define() -> OuterOpaque {} + | ^^ + | | + | 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 | fn define() -> OuterOpaque {} + | +++++++++ + +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/wf-nested.rs:37:69 + | +LL | fn define_rpit() -> impl Trait<&'static T, Out = impl Sized> {} + | ^^ + | | + | 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 | fn define_rpit() -> impl Trait<&'static T, Out = impl Sized> {} + | +++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr b/tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr index f5d3a218542cd..dbd3a1394f89b 100644 --- a/tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr +++ b/tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr @@ -1,5 +1,19 @@ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/wf-nested.rs:46:17 + --> $DIR/wf-nested.rs:46:38 + | +LL | fn define() -> OuterOpaque {} + | ^^ + | | + | 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 | fn define() -> OuterOpaque {} + | +++++++++ + +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/wf-nested.rs:51:17 | LL | let _ = outer.get(); | ^^^^^^^^^^^ @@ -13,7 +27,7 @@ LL | fn test() { | +++++++++ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/wf-nested.rs:46:17 + --> $DIR/wf-nested.rs:51:17 | LL | let _ = outer.get(); | ^^^^^^^^^^^ @@ -27,6 +41,6 @@ help: consider adding an explicit lifetime bound LL | fn test() { | +++++++++ -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/type-alias-impl-trait/wf-nested.rs b/tests/ui/type-alias-impl-trait/wf-nested.rs index 1fc93a3cd2793..56c524c6db066 100644 --- a/tests/ui/type-alias-impl-trait/wf-nested.rs +++ b/tests/ui/type-alias-impl-trait/wf-nested.rs @@ -1,12 +1,8 @@ // Well-formedness of nested opaque types, i.e. `impl Sized` in -// `type Outer = impl Trait`. -// See the comments below. -// -//@ revisions: pass pass_sound fail -//@ [pass] check-pass -//@ [pass_sound] check-fail -//@ [fail] check-fail - +// `type Outer = impl Trait`. We check that +// the nested type is well-formed, even though this would also +// be implied by the item bounds of the opaque being +// well-formed. See the comments below. #![feature(type_alias_impl_trait)] struct IsStatic(T); @@ -23,40 +19,26 @@ impl Trait<&'static T> for () { type Out = IsStatic; } -// The hidden type for `impl Sized` is `IsStatic`, which requires `T: 'static`. -// We know it is well-formed because it can *only* be referenced as a projection: -// as Trait<&'static T>>::Out`. -// So any instantiation of the type already requires proving `T: 'static`. -#[cfg(pass)] -mod pass { - use super::*; - type OuterOpaque = impl Trait<&'static T, Out = impl Sized>; - fn define() -> OuterOpaque {} -} - -// Test the soundness of `pass` - We should require `T: 'static` at the use site. -#[cfg(pass_sound)] -mod pass_sound { - use super::*; - type OuterOpaque = impl Trait<&'static T, Out = impl Sized>; - fn define() -> OuterOpaque {} - - fn test() { - let outer = define::(); - let _ = outer.get(); - //[pass_sound]~^ ERROR `T` may not live long enough - //[pass_sound]~| ERROR `T` may not live long enough - } -} -// Similar to `pass` but here `impl Sized` can be referenced directly as -// InnerOpaque, so we require an explicit bound `T: 'static`. -#[cfg(fail)] -mod fail { - use super::*; - type InnerOpaque = impl Sized; //[fail]~ ERROR `T` may not live long enough - type OuterOpaque = impl Trait<&'static T, Out = InnerOpaque>; - fn define() -> OuterOpaque {} -} +// We could theoretically allow this (and previously did), as even +// though the nested opaque is not well-formed, it can only be +// used by normalizing the projection +// as Trait<&'static T>>::Out +// Assuming that we check that this projection is well-formed, the wf +// of the nested opaque is implied. +type OuterOpaque1 = impl Trait<&'static T, Out = impl Sized>; +fn define() -> OuterOpaque1 {} +//~^ ERROR `T` may not live long enough + +fn define_rpit() -> impl Trait<&'static T, Out = impl Sized> {} +//~^ ERROR the parameter type `T` may not live long enough + +// Similar to `define` but here `impl Sized` can be referenced directly as +// InnerOpaque, so the `'static` bound is definitely required for +// soundness. +type InnerOpaque = impl Sized; +type OuterOpaque2 = impl Trait<&'static T, Out = InnerOpaque>; +fn define_nested_rpit() -> OuterOpaque2 {} +//~^ ERROR the parameter type `T` may not live long enough fn main() {} diff --git a/tests/ui/type-alias-impl-trait/wf-nested.stderr b/tests/ui/type-alias-impl-trait/wf-nested.stderr new file mode 100644 index 0000000000000..6d50e11c5da84 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/wf-nested.stderr @@ -0,0 +1,45 @@ +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/wf-nested.rs:30:35 + | +LL | fn define() -> OuterOpaque1 {} + | ^^ + | | + | 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 | fn define() -> OuterOpaque1 {} + | +++++++++ + +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/wf-nested.rs:33:65 + | +LL | fn define_rpit() -> impl Trait<&'static T, Out = impl Sized> {} + | ^^ + | | + | 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 | fn define_rpit() -> impl Trait<&'static T, Out = impl Sized> {} + | +++++++++ + +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/wf-nested.rs:41:47 + | +LL | fn define_nested_rpit() -> OuterOpaque2 {} + | ^^ + | | + | 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 | fn define_nested_rpit() -> OuterOpaque2 {} + | +++++++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/typeck/issue-13853-5.rs b/tests/ui/typeck/issue-13853-5.rs index 2afdf95aacf42..fc97c6c67d687 100644 --- a/tests/ui/typeck/issue-13853-5.rs +++ b/tests/ui/typeck/issue-13853-5.rs @@ -7,6 +7,7 @@ trait Deserializable { impl<'a, T: Deserializable> Deserializable for &'a str { //~^ ERROR type parameter `T` is not constrained fn deserialize_token>(_x: D, _y: &'a str) -> &'a str { + //~^ ERROR mismatched types } } diff --git a/tests/ui/typeck/issue-13853-5.stderr b/tests/ui/typeck/issue-13853-5.stderr index 1eead9563286c..388d5ec746ce6 100644 --- a/tests/ui/typeck/issue-13853-5.stderr +++ b/tests/ui/typeck/issue-13853-5.stderr @@ -4,6 +4,22 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self LL | impl<'a, T: Deserializable> Deserializable for &'a str { | ^ unconstrained type parameter -error: aborting due to 1 previous error +error[E0308]: mismatched types + --> $DIR/issue-13853-5.rs:9:70 + | +LL | fn deserialize_token>(_x: D, _y: &'a str) -> &'a str { + | ----------------- ^^^^^^^ expected `&str`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + | +help: consider returning the local binding `_y` + | +LL ~ fn deserialize_token>(_x: D, _y: &'a str) -> &'a str { +LL + _y +LL ~ + | + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0207`. +Some errors have detailed explanations: E0207, E0308. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/typeck/type-placeholder-fn-in-const.stderr b/tests/ui/typeck/type-placeholder-fn-in-const.stderr index 302359d2500c9..92b47bd4781c5 100644 --- a/tests/ui/typeck/type-placeholder-fn-in-const.stderr +++ b/tests/ui/typeck/type-placeholder-fn-in-const.stderr @@ -1,25 +1,25 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions - --> $DIR/type-placeholder-fn-in-const.rs:4:25 + --> $DIR/type-placeholder-fn-in-const.rs:10:25 | -LL | const TEST: fn() -> _; +LL | const TEST: fn() -> _ = 42; | ^ not allowed in type signatures -error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/type-placeholder-fn-in-const.rs:4:25 | LL | const TEST: fn() -> _; | ^ not allowed in type signatures -error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions +error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants --> $DIR/type-placeholder-fn-in-const.rs:10:25 | LL | const TEST: fn() -> _ = 42; | ^ not allowed in type signatures error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants - --> $DIR/type-placeholder-fn-in-const.rs:10:25 + --> $DIR/type-placeholder-fn-in-const.rs:4:25 | -LL | const TEST: fn() -> _ = 42; +LL | const TEST: fn() -> _; | ^ not allowed in type signatures error: aborting due to 4 previous errors diff --git a/tests/ui/typeck/typeck-builtin-bound-type-parameters.stderr b/tests/ui/typeck/typeck-builtin-bound-type-parameters.stderr index 1dc1d46aa71ad..9a9b2a68dbed9 100644 --- a/tests/ui/typeck/typeck-builtin-bound-type-parameters.stderr +++ b/tests/ui/typeck/typeck-builtin-bound-type-parameters.stderr @@ -24,6 +24,16 @@ LL | trait Trait: Copy {} | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/typeck-builtin-bound-type-parameters.rs:4:14 + | +LL | trait Trait: Copy {} + | ^^^^---------- help: remove these generics + | | + | expected 0 generic arguments + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied --> $DIR/typeck-builtin-bound-type-parameters.rs:9:21 | @@ -56,16 +66,6 @@ LL | fn foo2<'a, T:Copy<'a, U>, U>(x: T) {} | | | expected 0 generic arguments -error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/typeck-builtin-bound-type-parameters.rs:4:14 - | -LL | trait Trait: Copy {} - | ^^^^---------- help: remove these generics - | | - | expected 0 generic arguments - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - error: aborting due to 8 previous errors For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/typeck/typeck_type_placeholder_item.stderr b/tests/ui/typeck/typeck_type_placeholder_item.stderr index c102926fcf562..e8f1de1ad04cd 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item.stderr +++ b/tests/ui/typeck/typeck_type_placeholder_item.stderr @@ -169,6 +169,28 @@ LL | unsafe fn test12(x: *const usize) -> *const *const _ { | | not allowed in type signatures | help: replace with the correct return type: `*const *const usize` +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:59:24 + | +LL | fn clone(&self) -> _ { Test9 } + | ^ not allowed in type signatures + | +help: try replacing `_` with the type in the corresponding trait method signature + | +LL | fn clone(&self) -> Test9 { Test9 } + | ~~~~~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:62:37 + | +LL | fn clone_from(&mut self, other: _) { *self = Test9; } + | ^ not allowed in type signatures + | +help: try replacing `_` with the type in the corresponding trait method signature + | +LL | fn clone_from(&mut self, other: &Test9) { *self = Test9; } + | ~~~~~~ + error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs --> $DIR/typeck_type_placeholder_item.rs:67:8 | @@ -294,6 +316,28 @@ help: use type parameters instead LL | fn fn_test8(_f: fn() -> T) { } | +++ ~ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:115:28 + | +LL | fn clone(&self) -> _ { FnTest9 } + | ^ not allowed in type signatures + | +help: try replacing `_` with the type in the corresponding trait method signature + | +LL | fn clone(&self) -> FnTest9 { FnTest9 } + | ~~~~~~~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:118:41 + | +LL | fn clone_from(&mut self, other: _) { *self = FnTest9; } + | ^ not allowed in type signatures + | +help: try replacing `_` with the type in the corresponding trait method signature + | +LL | fn clone_from(&mut self, other: &FnTest9) { *self = FnTest9; } + | ~~~~~~~~ + error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs --> $DIR/typeck_type_placeholder_item.rs:123:12 | @@ -346,6 +390,76 @@ LL | fn fn_test13(x: _) -> (i32, _) { (x, x) } | | not allowed in type signatures | help: replace with the correct return type: `(i32, i32)` +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:140:31 + | +LL | fn method_test1(&self, x: _); + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn method_test1(&self, x: T); + | +++ ~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:142:31 + | +LL | fn method_test2(&self, x: _) -> _; + | ^ ^ not allowed in type signatures + | | + | not allowed in type signatures + | +help: use type parameters instead + | +LL | fn method_test2(&self, x: T) -> T; + | +++ ~ ~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:144:31 + | +LL | fn method_test3(&self) -> _; + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn method_test3(&self) -> T; + | +++ ~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:146:26 + | +LL | fn assoc_fn_test1(x: _); + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn assoc_fn_test1(x: T); + | +++ ~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:148:26 + | +LL | fn assoc_fn_test2(x: _) -> _; + | ^ ^ not allowed in type signatures + | | + | not allowed in type signatures + | +help: use type parameters instead + | +LL | fn assoc_fn_test2(x: T) -> T; + | +++ ~ ~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:150:28 + | +LL | fn assoc_fn_test3() -> _; + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn assoc_fn_test3() -> T; + | +++ ~ + error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs --> $DIR/typeck_type_placeholder_item.rs:154:21 | @@ -410,6 +524,28 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures LL | type Y = impl Trait<_>; | ^ not allowed in type signatures +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:44:27 + | +LL | fn test10(&self, _x : _) { } + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn test10(&self, _x : T) { } + | +++ ~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:110:34 + | +LL | fn fn_test10(&self, _x : _) { } + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn fn_test10(&self, _x : T) { } + | +++ ~ + error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:217:31 | @@ -428,6 +564,39 @@ LL | const _: Option<_> = map(value); | not allowed in type signatures | help: replace with the correct type: `Option` +error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants + --> $DIR/typeck_type_placeholder_item.rs:206:14 + | +LL | const C: _; + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants + --> $DIR/typeck_type_placeholder_item.rs:209:14 + | +LL | const D: _ = 42; + | ^ + | | + | not allowed in type signatures + | help: replace with the correct type: `i32` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants + --> $DIR/typeck_type_placeholder_item.rs:194:14 + | +LL | const D: _ = 42; + | ^ + | | + | not allowed in type signatures + | help: replace with the correct type: `i32` + +error[E0046]: not all trait items implemented, missing: `F` + --> $DIR/typeck_type_placeholder_item.rs:200:1 + | +LL | type F: std::ops::Fn(_); + | ----------------------- `F` from trait +... +LL | impl Qux for Struct { + | ^^^^^^^^^^^^^^^^^^^ missing `F` in implementation + error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:225:31 | @@ -449,103 +618,6 @@ note: however, the inferred type `Map, {closure@typeck_type_pl LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions - --> $DIR/typeck_type_placeholder_item.rs:140:31 - | -LL | fn method_test1(&self, x: _); - | ^ not allowed in type signatures - | -help: use type parameters instead - | -LL | fn method_test1(&self, x: T); - | +++ ~ - -error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions - --> $DIR/typeck_type_placeholder_item.rs:142:31 - | -LL | fn method_test2(&self, x: _) -> _; - | ^ ^ not allowed in type signatures - | | - | not allowed in type signatures - | -help: use type parameters instead - | -LL | fn method_test2(&self, x: T) -> T; - | +++ ~ ~ - -error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions - --> $DIR/typeck_type_placeholder_item.rs:144:31 - | -LL | fn method_test3(&self) -> _; - | ^ not allowed in type signatures - | -help: use type parameters instead - | -LL | fn method_test3(&self) -> T; - | +++ ~ - -error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions - --> $DIR/typeck_type_placeholder_item.rs:146:26 - | -LL | fn assoc_fn_test1(x: _); - | ^ not allowed in type signatures - | -help: use type parameters instead - | -LL | fn assoc_fn_test1(x: T); - | +++ ~ - -error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions - --> $DIR/typeck_type_placeholder_item.rs:148:26 - | -LL | fn assoc_fn_test2(x: _) -> _; - | ^ ^ not allowed in type signatures - | | - | not allowed in type signatures - | -help: use type parameters instead - | -LL | fn assoc_fn_test2(x: T) -> T; - | +++ ~ ~ - -error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions - --> $DIR/typeck_type_placeholder_item.rs:150:28 - | -LL | fn assoc_fn_test3() -> _; - | ^ not allowed in type signatures - | -help: use type parameters instead - | -LL | fn assoc_fn_test3() -> T; - | +++ ~ - -error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types - --> $DIR/typeck_type_placeholder_item.rs:190:14 - | -LL | type B = _; - | ^ not allowed in type signatures - -error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants - --> $DIR/typeck_type_placeholder_item.rs:192:14 - | -LL | const C: _; - | ^ not allowed in type signatures - -error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants - --> $DIR/typeck_type_placeholder_item.rs:194:14 - | -LL | const D: _ = 42; - | ^ - | | - | not allowed in type signatures - | help: replace with the correct type: `i32` - -error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types - --> $DIR/typeck_type_placeholder_item.rs:197:26 - | -LL | type F: std::ops::Fn(_); - | ^ not allowed in type signatures - error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:41:24 | @@ -555,39 +627,6 @@ LL | fn test9(&self) -> _ { () } | not allowed in type signatures | help: replace with the correct return type: `()` -error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions - --> $DIR/typeck_type_placeholder_item.rs:44:27 - | -LL | fn test10(&self, _x : _) { } - | ^ not allowed in type signatures - | -help: use type parameters instead - | -LL | fn test10(&self, _x : T) { } - | +++ ~ - -error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions - --> $DIR/typeck_type_placeholder_item.rs:59:24 - | -LL | fn clone(&self) -> _ { Test9 } - | ^ not allowed in type signatures - | -help: try replacing `_` with the type in the corresponding trait method signature - | -LL | fn clone(&self) -> Test9 { Test9 } - | ~~~~~ - -error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions - --> $DIR/typeck_type_placeholder_item.rs:62:37 - | -LL | fn clone_from(&mut self, other: _) { *self = Test9; } - | ^ not allowed in type signatures - | -help: try replacing `_` with the type in the corresponding trait method signature - | -LL | fn clone_from(&mut self, other: &Test9) { *self = Test9; } - | ~~~~~~ - error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:107:31 | @@ -597,39 +636,6 @@ LL | fn fn_test9(&self) -> _ { () } | not allowed in type signatures | help: replace with the correct return type: `()` -error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions - --> $DIR/typeck_type_placeholder_item.rs:110:34 - | -LL | fn fn_test10(&self, _x : _) { } - | ^ not allowed in type signatures - | -help: use type parameters instead - | -LL | fn fn_test10(&self, _x : T) { } - | +++ ~ - -error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions - --> $DIR/typeck_type_placeholder_item.rs:115:28 - | -LL | fn clone(&self) -> _ { FnTest9 } - | ^ not allowed in type signatures - | -help: try replacing `_` with the type in the corresponding trait method signature - | -LL | fn clone(&self) -> FnTest9 { FnTest9 } - | ~~~~~~~ - -error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions - --> $DIR/typeck_type_placeholder_item.rs:118:41 - | -LL | fn clone_from(&mut self, other: _) { *self = FnTest9; } - | ^ not allowed in type signatures - | -help: try replacing `_` with the type in the corresponding trait method signature - | -LL | fn clone_from(&mut self, other: &FnTest9) { *self = FnTest9; } - | ~~~~~~~~ - error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types --> $DIR/typeck_type_placeholder_item.rs:202:14 | @@ -642,29 +648,23 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures LL | type B = _; | ^ not allowed in type signatures -error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants - --> $DIR/typeck_type_placeholder_item.rs:206:14 +error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types + --> $DIR/typeck_type_placeholder_item.rs:190:14 | -LL | const C: _; +LL | type B = _; | ^ not allowed in type signatures error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants - --> $DIR/typeck_type_placeholder_item.rs:209:14 + --> $DIR/typeck_type_placeholder_item.rs:192:14 | -LL | const D: _ = 42; - | ^ - | | - | not allowed in type signatures - | help: replace with the correct type: `i32` +LL | const C: _; + | ^ not allowed in type signatures -error[E0046]: not all trait items implemented, missing: `F` - --> $DIR/typeck_type_placeholder_item.rs:200:1 +error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types + --> $DIR/typeck_type_placeholder_item.rs:197:26 | LL | type F: std::ops::Fn(_); - | ----------------------- `F` from trait -... -LL | impl Qux for Struct { - | ^^^^^^^^^^^^^^^^^^^ missing `F` in implementation + | ^ not allowed in type signatures error[E0015]: cannot call non-const fn ` as Iterator>::filter::<{closure@$DIR/typeck_type_placeholder_item.rs:230:29: 230:32}>` in constants --> $DIR/typeck_type_placeholder_item.rs:230:22 diff --git a/tests/ui/typeck/typeck_type_placeholder_item_help.stderr b/tests/ui/typeck/typeck_type_placeholder_item_help.stderr index b0d4ed8272be9..32585e2937b77 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item_help.stderr +++ b/tests/ui/typeck/typeck_type_placeholder_item_help.stderr @@ -38,18 +38,18 @@ LL | const TEST4: fn() -> _ = 42; | ^ not allowed in type signatures error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants - --> $DIR/typeck_type_placeholder_item_help.rs:18:18 + --> $DIR/typeck_type_placeholder_item_help.rs:25:18 | -LL | const TEST5: _ = 42; +LL | const TEST6: _ = 13; | ^ | | | not allowed in type signatures | help: replace with the correct type: `i32` error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants - --> $DIR/typeck_type_placeholder_item_help.rs:25:18 + --> $DIR/typeck_type_placeholder_item_help.rs:18:18 | -LL | const TEST6: _ = 13; +LL | const TEST5: _ = 42; | ^ | | | not allowed in type signatures diff --git a/tests/ui/union/unnamed-fields/unnamed-enum-field-issue-121757.rs b/tests/ui/union/unnamed-fields/unnamed-enum-field-issue-121757.rs new file mode 100644 index 0000000000000..5d15ec4cffdb9 --- /dev/null +++ b/tests/ui/union/unnamed-fields/unnamed-enum-field-issue-121757.rs @@ -0,0 +1,25 @@ +type NodeId = u32; +struct Type<'a>(std::marker::PhantomData::<&'a ()>); + +type Ast<'ast> = &'ast AstStructure<'ast>; + +struct AstStructure<'ast> { +//~^ ERROR struct with unnamed fields must have `#[repr(C)]` representation + id: NodeId, + _: AstKind<'ast> +//~^ ERROR unnamed fields are not yet fully implemented [E0658] +//~^^ ERROR unnamed fields can only have struct or union types +} + +enum AstKind<'ast> { + ExprInt, + ExprLambda(Ast<'ast>), +} + +fn compute_types<'tcx,'ast>(ast: Ast<'ast>) -> Type<'tcx> +{ + match ast.kind {} +//~^ ERROR no field `kind` on type `&'ast AstStructure<'ast>` [E0609] +} + +fn main() {} diff --git a/tests/ui/union/unnamed-fields/unnamed-enum-field-issue-121757.stderr b/tests/ui/union/unnamed-fields/unnamed-enum-field-issue-121757.stderr new file mode 100644 index 0000000000000..4ea910202de98 --- /dev/null +++ b/tests/ui/union/unnamed-fields/unnamed-enum-field-issue-121757.stderr @@ -0,0 +1,45 @@ +error[E0658]: unnamed fields are not yet fully implemented + --> $DIR/unnamed-enum-field-issue-121757.rs:9:5 + | +LL | _: AstKind<'ast> + | ^ + | + = note: see issue #49804 for more information + = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: struct with unnamed fields must have `#[repr(C)]` representation + --> $DIR/unnamed-enum-field-issue-121757.rs:6:1 + | +LL | struct AstStructure<'ast> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ struct `AstStructure` defined here + | +note: unnamed field defined here + --> $DIR/unnamed-enum-field-issue-121757.rs:9:5 + | +LL | _: AstKind<'ast> + | ^^^^^^^^^^^^^^^^ +help: add `#[repr(C)]` to this struct + | +LL + #[repr(C)] +LL | struct AstStructure<'ast> { + | + +error: unnamed fields can only have struct or union types + --> $DIR/unnamed-enum-field-issue-121757.rs:9:5 + | +LL | _: AstKind<'ast> + | ^^^^^^^^^^^^^^^^ + +error[E0609]: no field `kind` on type `&'ast AstStructure<'ast>` + --> $DIR/unnamed-enum-field-issue-121757.rs:21:15 + | +LL | match ast.kind {} + | ^^^^ unknown field + | + = note: available fields are: `id`, `_` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0609, E0658. +For more information about an error, try `rustc --explain E0609`. diff --git a/tests/ui/variance/variance-associated-consts.rs b/tests/ui/variance/variance-associated-consts.rs index da55bc96244f2..6a44a94df3fdd 100644 --- a/tests/ui/variance/variance-associated-consts.rs +++ b/tests/ui/variance/variance-associated-consts.rs @@ -12,6 +12,7 @@ trait Trait { #[rustc_variance] struct Foo { //~ ERROR [o] field: [u8; ::Const] + //~^ ERROR: unconstrained generic constant } fn main() { } diff --git a/tests/ui/variance/variance-associated-consts.stderr b/tests/ui/variance/variance-associated-consts.stderr index e25f0879add0a..f41574ca3a37b 100644 --- a/tests/ui/variance/variance-associated-consts.stderr +++ b/tests/ui/variance/variance-associated-consts.stderr @@ -1,8 +1,16 @@ +error: unconstrained generic constant + --> $DIR/variance-associated-consts.rs:14:12 + | +LL | field: [u8; ::Const] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); ::Const]:` + error: [o] --> $DIR/variance-associated-consts.rs:13:1 | LL | struct Foo { | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error: aborting due to 2 previous errors diff --git a/tests/ui/variance/variance-regions-direct.rs b/tests/ui/variance/variance-regions-direct.rs index 39ea77a8aa21a..f1763c403f1a1 100644 --- a/tests/ui/variance/variance-regions-direct.rs +++ b/tests/ui/variance/variance-regions-direct.rs @@ -50,6 +50,7 @@ struct Test6<'a, 'b:'a> { //~ ERROR [+, o] #[rustc_variance] struct Test7<'a> { //~ ERROR [*] + //~^ ERROR: `'a` is never used x: isize } diff --git a/tests/ui/variance/variance-regions-direct.stderr b/tests/ui/variance/variance-regions-direct.stderr index c55730296f1c5..edfc888f65667 100644 --- a/tests/ui/variance/variance-regions-direct.stderr +++ b/tests/ui/variance/variance-regions-direct.stderr @@ -1,3 +1,11 @@ +error[E0392]: lifetime parameter `'a` is never used + --> $DIR/variance-regions-direct.rs:52:14 + | +LL | struct Test7<'a> { + | ^^ unused lifetime parameter + | + = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` + error: [+, +, +] --> $DIR/variance-regions-direct.rs:9:1 | @@ -35,10 +43,11 @@ LL | struct Test7<'a> { | ^^^^^^^^^^^^^^^^ error: [-, +, o] - --> $DIR/variance-regions-direct.rs:59:1 + --> $DIR/variance-regions-direct.rs:60:1 | LL | enum Test8<'a, 'b, 'c:'b> { | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 7 previous errors +error: aborting due to 8 previous errors +For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/variance/variance-regions-indirect.rs b/tests/ui/variance/variance-regions-indirect.rs index 0d00535fef11b..31e25641d8c3a 100644 --- a/tests/ui/variance/variance-regions-indirect.rs +++ b/tests/ui/variance/variance-regions-indirect.rs @@ -6,6 +6,7 @@ #[rustc_variance] enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR [-, +, o, *] + //~^ ERROR: `'d` is never used Test8A(extern "Rust" fn(&'a isize)), Test8B(&'b [isize]), Test8C(&'b mut &'c str), @@ -13,16 +14,19 @@ enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR [-, +, o, *] #[rustc_variance] struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR [*, o, +, -] + //~^ ERROR: `'w` is never used f: Base<'z, 'y, 'x, 'w> } #[rustc_variance] // Combine - and + to yield o struct Derived2<'a, 'b:'a, 'c> { //~ ERROR [o, o, *] + //~^ ERROR: `'c` is never used f: Base<'a, 'a, 'b, 'c> } #[rustc_variance] // Combine + and o to yield o (just pay attention to 'a here) struct Derived3<'a:'b, 'b, 'c> { //~ ERROR [o, +, *] + //~^ ERROR: `'c` is never used f: Base<'a, 'b, 'a, 'c> } diff --git a/tests/ui/variance/variance-regions-indirect.stderr b/tests/ui/variance/variance-regions-indirect.stderr index edf2626d5984f..901ec0c6a762b 100644 --- a/tests/ui/variance/variance-regions-indirect.stderr +++ b/tests/ui/variance/variance-regions-indirect.stderr @@ -1,3 +1,35 @@ +error[E0392]: lifetime parameter `'d` is never used + --> $DIR/variance-regions-indirect.rs:8:26 + | +LL | enum Base<'a, 'b, 'c:'b, 'd> { + | ^^ unused lifetime parameter + | + = help: consider removing `'d`, referring to it in a field, or using a marker such as `PhantomData` + +error[E0392]: lifetime parameter `'w` is never used + --> $DIR/variance-regions-indirect.rs:16:17 + | +LL | struct Derived1<'w, 'x:'y, 'y, 'z> { + | ^^ unused lifetime parameter + | + = help: consider removing `'w`, referring to it in a field, or using a marker such as `PhantomData` + +error[E0392]: lifetime parameter `'c` is never used + --> $DIR/variance-regions-indirect.rs:22:28 + | +LL | struct Derived2<'a, 'b:'a, 'c> { + | ^^ unused lifetime parameter + | + = help: consider removing `'c`, referring to it in a field, or using a marker such as `PhantomData` + +error[E0392]: lifetime parameter `'c` is never used + --> $DIR/variance-regions-indirect.rs:28:28 + | +LL | struct Derived3<'a:'b, 'b, 'c> { + | ^^ unused lifetime parameter + | + = help: consider removing `'c`, referring to it in a field, or using a marker such as `PhantomData` + error: [-, +, o, *] --> $DIR/variance-regions-indirect.rs:8:1 | @@ -5,28 +37,29 @@ LL | enum Base<'a, 'b, 'c:'b, 'd> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: [*, o, +, -] - --> $DIR/variance-regions-indirect.rs:15:1 + --> $DIR/variance-regions-indirect.rs:16:1 | LL | struct Derived1<'w, 'x:'y, 'y, 'z> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: [o, o, *] - --> $DIR/variance-regions-indirect.rs:20:1 + --> $DIR/variance-regions-indirect.rs:22:1 | LL | struct Derived2<'a, 'b:'a, 'c> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: [o, +, *] - --> $DIR/variance-regions-indirect.rs:25:1 + --> $DIR/variance-regions-indirect.rs:28:1 | LL | struct Derived3<'a:'b, 'b, 'c> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: [-, +, o] - --> $DIR/variance-regions-indirect.rs:30:1 + --> $DIR/variance-regions-indirect.rs:34:1 | LL | struct Derived4<'a, 'b, 'c:'b> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 5 previous errors +error: aborting due to 9 previous errors +For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/variance/variance-trait-bounds.rs b/tests/ui/variance/variance-trait-bounds.rs index ad5334602a2de..25a01b160ddd1 100644 --- a/tests/ui/variance/variance-trait-bounds.rs +++ b/tests/ui/variance/variance-trait-bounds.rs @@ -19,16 +19,19 @@ struct TestStruct> { //~ ERROR [+, +] #[rustc_variance] enum TestEnum> { //~ ERROR [*, +] + //~^ ERROR: `U` is never used Foo(T) } #[rustc_variance] struct TestContraStruct> { //~ ERROR [*, +] + //~^ ERROR: `U` is never used t: T } #[rustc_variance] struct TestBox+Setter> { //~ ERROR [*, +] + //~^ ERROR: `U` is never used t: T } diff --git a/tests/ui/variance/variance-trait-bounds.stderr b/tests/ui/variance/variance-trait-bounds.stderr index 5a73e541c3a17..95ed18c1ad2bf 100644 --- a/tests/ui/variance/variance-trait-bounds.stderr +++ b/tests/ui/variance/variance-trait-bounds.stderr @@ -1,3 +1,30 @@ +error[E0392]: type parameter `U` is never used + --> $DIR/variance-trait-bounds.rs:21:15 + | +LL | enum TestEnum> { + | ^ unused type parameter + | + = help: consider removing `U`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `U` to be a const parameter, use `const U: /* Type */` instead + +error[E0392]: type parameter `U` is never used + --> $DIR/variance-trait-bounds.rs:27:25 + | +LL | struct TestContraStruct> { + | ^ unused type parameter + | + = help: consider removing `U`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `U` to be a const parameter, use `const U: /* Type */` instead + +error[E0392]: type parameter `U` is never used + --> $DIR/variance-trait-bounds.rs:33:16 + | +LL | struct TestBox+Setter> { + | ^ unused type parameter + | + = help: consider removing `U`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `U` to be a const parameter, use `const U: /* Type */` instead + error: [+, +] --> $DIR/variance-trait-bounds.rs:16:1 | @@ -11,16 +38,17 @@ LL | enum TestEnum> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: [*, +] - --> $DIR/variance-trait-bounds.rs:26:1 + --> $DIR/variance-trait-bounds.rs:27:1 | LL | struct TestContraStruct> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: [*, +] - --> $DIR/variance-trait-bounds.rs:31:1 + --> $DIR/variance-trait-bounds.rs:33:1 | LL | struct TestBox+Setter> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: aborting due to 7 previous errors +For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/wf/wf-const-type.rs b/tests/ui/wf/wf-const-type.rs index 64b0d9c8de797..3b770b4b91633 100644 --- a/tests/ui/wf/wf-const-type.rs +++ b/tests/ui/wf/wf-const-type.rs @@ -10,6 +10,7 @@ struct NotCopy; const FOO: IsCopy> = IsCopy { t: None }; //~^ ERROR E0277 //~| ERROR E0277 +//~| ERROR E0277 fn main() { } diff --git a/tests/ui/wf/wf-const-type.stderr b/tests/ui/wf/wf-const-type.stderr index d5e0f7672a6f3..d73642729ea75 100644 --- a/tests/ui/wf/wf-const-type.stderr +++ b/tests/ui/wf/wf-const-type.stderr @@ -16,6 +16,25 @@ LL + #[derive(Copy)] LL | struct NotCopy; | +error[E0277]: the trait bound `NotCopy: Copy` is not satisfied + --> $DIR/wf-const-type.rs:10:12 + | +LL | const FOO: IsCopy> = IsCopy { t: None }; + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NotCopy`, which is required by `Option: Copy` + | + = note: required for `Option` to implement `Copy` +note: required by a bound in `IsCopy` + --> $DIR/wf-const-type.rs:7:17 + | +LL | struct IsCopy { t: T } + | ^^^^ required by this bound in `IsCopy` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider annotating `NotCopy` with `#[derive(Copy)]` + | +LL + #[derive(Copy)] +LL | struct NotCopy; + | + error[E0277]: the trait bound `NotCopy: Copy` is not satisfied --> $DIR/wf-const-type.rs:10:50 | @@ -34,6 +53,6 @@ LL + #[derive(Copy)] LL | struct NotCopy; | -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-static-type.rs b/tests/ui/wf/wf-static-type.rs index f454fe30e7750..1980c5de40c80 100644 --- a/tests/ui/wf/wf-static-type.rs +++ b/tests/ui/wf/wf-static-type.rs @@ -10,6 +10,7 @@ struct NotCopy; static FOO: IsCopy> = IsCopy { t: None }; //~^ ERROR E0277 //~| ERROR E0277 +//~| ERROR E0277 fn main() { } diff --git a/tests/ui/wf/wf-static-type.stderr b/tests/ui/wf/wf-static-type.stderr index 481173b8a269c..36234f3fd1766 100644 --- a/tests/ui/wf/wf-static-type.stderr +++ b/tests/ui/wf/wf-static-type.stderr @@ -16,6 +16,25 @@ LL + #[derive(Copy)] LL | struct NotCopy; | +error[E0277]: the trait bound `NotCopy: Copy` is not satisfied + --> $DIR/wf-static-type.rs:10:13 + | +LL | static FOO: IsCopy> = IsCopy { t: None }; + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NotCopy`, which is required by `Option: Copy` + | + = note: required for `Option` to implement `Copy` +note: required by a bound in `IsCopy` + --> $DIR/wf-static-type.rs:7:17 + | +LL | struct IsCopy { t: T } + | ^^^^ required by this bound in `IsCopy` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider annotating `NotCopy` with `#[derive(Copy)]` + | +LL + #[derive(Copy)] +LL | struct NotCopy; + | + error[E0277]: the trait bound `NotCopy: Copy` is not satisfied --> $DIR/wf-static-type.rs:10:51 | @@ -34,6 +53,6 @@ LL + #[derive(Copy)] LL | struct NotCopy; | -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`.