diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 5ccf0eaf02bd4..b5d8614804812 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1779,7 +1779,7 @@ pub enum ExprKind { Lit(token::Lit), /// A cast (e.g., `foo as f64`). Cast(Box, Box), - /// A type ascription (e.g., `builtin # type_ascribe(42, usize)`). + /// A type ascription (e.g., `k#type_ascribe(42, usize)`). /// /// Usually not written directly in user code but /// indirectly via the macro `type_ascribe!(...)`. @@ -1871,7 +1871,7 @@ pub enum ExprKind { /// Output of the `asm!()` macro. InlineAsm(Box), - /// An `offset_of` expression (e.g., `builtin # offset_of(Struct, field)`). + /// An `offset_of` expression (e.g., `k#offset_of(Struct, field)`). /// /// Usually not written directly in user code but /// indirectly via the macro `core::mem::offset_of!(...)`. @@ -2570,7 +2570,7 @@ pub enum TyKind { /// Pattern types like `pattern_type!(u32 is 1..=)`, which is the same as `NonZero`, /// just as part of the type system. Pat(Box, Box), - /// A `field_of` expression (e.g., `builtin # field_of(Struct, field)`). + /// A `field_of` expression (e.g., `k#field_of(Struct, field)`). /// /// Usually not written directly in user code but indirectly via the macro /// `core::field::field_of!(...)`. diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 20079dd039f6f..4ec5fe2a8bd84 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -313,6 +313,8 @@ pub fn ident_can_begin_expr(name: Symbol, span: Span, kind: IdentKind) -> bool { // WARNING: Take care when modifying this function! It will change the stable(!) set of // tokens that are allowed to match an `expr` nonterminal which is user observable. + // NOTE: We don't care about forced keywords that are gated behind `internal_syntax`. + let ident_token = Token::new(Ident(name, kind), span); // FIXME: Remove `box` from this list given we officially no longer support box expressions @@ -350,6 +352,8 @@ fn ident_can_begin_type(name: Symbol, span: Span, kind: IdentKind) -> bool { // WARNING: Take care when modifying this function! It will change the stable(!) set of // tokens that are allowed to match an `ty` nonterminal which is user observable. + // NOTE: We don't care about forced keywords that are gated behind `internal_syntax`. + let ident_token = Token::new(Ident(name, kind), span); !ident_token.is_reserved_ident() @@ -936,6 +940,10 @@ impl Token { self.non_raw_ident().is_some_and(|id| id.name == kw) } + pub fn is_forced_keyword(&self, kw: Symbol) -> bool { + self.ident().is_some_and(|(id, kind)| kind == IdentKind::ForcedKeyword && id.name == kw) + } + /// Returns `true` if the token is a given keyword, `kw` or if `case` is `Insensitive` and this /// token is an identifier equal to `kw` ignoring the case. pub fn is_keyword_case(&self, kw: Symbol, case: Case) -> bool { diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index bc0604cf96e95..862d4736ca33c 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -431,7 +431,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { // tidy-alphabetical-start gate_all!(async_for_loop, "`for await` loops are experimental"); - gate_all!(builtin_syntax, "`builtin #` syntax is unstable"); gate_all!(const_block_items, "const block items are experimental"); gate_all!(const_closures, "const closures are experimental"); gate_all!(const_trait_impl, "const trait impls are experimental"); @@ -452,6 +451,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { gate_all!(global_registration, "global registration is experimental"); gate_all!(guard_patterns, "guard patterns are experimental", "consider using match arm guards"); gate_all!(impl_restriction, "`impl` restrictions are experimental"); + gate_all!(internal_syntax, "this syntax is internal"); gate_all!(more_qualified_paths, "usage of qualified paths in this context is experimental"); gate_all!(move_expr, "`move(expr)` syntax is experimental"); gate_all!(mut_ref, "mutable by-reference bindings are experimental"); diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index a082300bb47ed..a5dbaf81376c1 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1442,7 +1442,7 @@ impl<'a> State<'a> { self.print_ty_pat(pat); } ast::TyKind::FieldOf(ty, variant, field) => { - self.word("builtin # field_of"); + self.word("k#field_of"); self.popen(); let ib = self.ibox(0); self.print_type(ty); @@ -2012,6 +2012,11 @@ impl<'a> State<'a> { self.pclose(); } PatKind::Deref(inner) => { + // FIXME(deref_patterns, internal_syntax, forced_keywords, clippy): + // This should render `k#deref(...)` but unfortunately Clippy uses `pat_to_string` + // for the suggestions of its lint `unnested_or_patterns`. Smh fix Clippy to not + // rely on AST pretty printing `deref!(…)` for `Deref` patterns and please don't + // think about adding a flag to AST pretty to control the output. self.word("deref!"); self.popen(); self.print_pat(inner); diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index d6e8f69dbfa03..51e3988577827 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -497,7 +497,7 @@ impl<'a> State<'a> { self.print_type(ty); } ast::ExprKind::Type(expr, ty) => { - self.word("builtin # type_ascribe"); + self.word("k#type_ascribe"); self.popen(); let ib = self.ibox(0); self.print_expr(expr, FixupContext::default()); @@ -777,12 +777,12 @@ impl<'a> State<'a> { self.print_expr(result, fixup.rightmost_subexpression()); } ast::ExprKind::InlineAsm(a) => { - // FIXME: Print `builtin # asm` once macro `asm` uses `builtin_syntax`. + // FIXME: Print `k#asm` once macro `asm` uses `internal_syntax`. self.word(format!("{}!", a.asm_macro.macro_name())); self.print_inline_asm(a); } ast::ExprKind::FormatArgs(fmt) => { - // FIXME: Print `builtin # format_args` once macro `format_args` uses `builtin_syntax`. + // FIXME: Print `k#format_args` once macro `format_args` uses `internal_syntax`. self.word("format_args!"); self.popen(); let ib = self.ibox(0); @@ -795,7 +795,7 @@ impl<'a> State<'a> { self.pclose(); } ast::ExprKind::OffsetOf(container, fields) => { - self.word("builtin # offset_of"); + self.word("k#offset_of"); self.popen(); let ib = self.ibox(0); self.print_type(container); @@ -855,10 +855,9 @@ impl<'a> State<'a> { self.print_block_with_attrs(blk, attrs, cb, ib) } ast::ExprKind::UnsafeBinderCast(kind, expr, ty) => { - self.word("builtin # "); match kind { - ast::UnsafeBinderCastKind::Wrap => self.word("wrap_binder"), - ast::UnsafeBinderCastKind::Unwrap => self.word("unwrap_binder"), + ast::UnsafeBinderCastKind::Wrap => self.word("k#wrap_binder"), + ast::UnsafeBinderCastKind::Unwrap => self.word("k#unwrap_binder"), } self.popen(); let ib = self.ibox(0); diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index 6ce34cecc7e97..84d620b9b5250 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -288,7 +288,7 @@ impl<'a> State<'a> { self.bclose(item.span, empty, cb); } ast::ItemKind::GlobalAsm(asm) => { - // FIXME: Print `builtin # global_asm` once macro `global_asm` uses `builtin_syntax`. + // FIXME: Print `k#global_asm` once macro `global_asm` uses `internal_syntax`. let (cb, ib) = self.head(visibility_qualified(&item.vis, "global_asm!")); self.print_inline_asm(asm); self.word(";"); diff --git a/compiler/rustc_attr_ir/src/lang_items.rs b/compiler/rustc_attr_ir/src/lang_items.rs index d715a6d3af8c5..56fb1a4b6c865 100644 --- a/compiler/rustc_attr_ir/src/lang_items.rs +++ b/compiler/rustc_attr_ir/src/lang_items.rs @@ -163,7 +163,7 @@ language_item_table! { Unsize, sym::unsize, unsize_trait, Target::Trait, GenericRequirement::Minimum(1); AlignOf, sym::mem_align_const, align_const, Target::AssocConst(AssocCtxt::Trait), GenericRequirement::Exact(0); SizeOf, sym::mem_size_const, size_const, Target::AssocConst(AssocCtxt::Trait), GenericRequirement::Exact(0); - OffsetOf, sym::offset_of, offset_of, Target::Fn, GenericRequirement::Exact(1); + OffsetOf, kw::OffsetOf, offset_of, Target::Fn, GenericRequirement::Exact(1); /// Trait injected by `#[derive(PartialEq)]`, (i.e. "Partial EQ"). StructuralPeq, sym::structural_peq, structural_peq_trait, Target::Trait, GenericRequirement::None; Copy, sym::copy, copy_trait, Target::Trait, GenericRequirement::Exact(0); @@ -239,7 +239,7 @@ language_item_table! { Complex, sym::complex, complex, Target::Struct, GenericRequirement::Exact(1); PpcF128, sym::ppcf128, ppcf128, Target::Struct, GenericRequirement::None; - Deref, sym::deref, deref_trait, Target::Trait, GenericRequirement::Exact(0); + Deref, kw::Deref, deref_trait, Target::Trait, GenericRequirement::Exact(0); DerefMut, sym::deref_mut, deref_mut_trait, Target::Trait, GenericRequirement::Exact(0); DerefPure, sym::deref_pure, deref_pure_trait, Target::Trait, GenericRequirement::Exact(0); DerefTarget, sym::deref_target, deref_target, Target::AssocTy(AssocCtxt::Trait), GenericRequirement::None; diff --git a/compiler/rustc_attr_parsing/src/attributes/lint.rs b/compiler/rustc_attr_parsing/src/attributes/lint.rs index e0607c49124d9..938de1a8597ab 100644 --- a/compiler/rustc_attr_parsing/src/attributes/lint.rs +++ b/compiler/rustc_attr_parsing/src/attributes/lint.rs @@ -8,6 +8,7 @@ use thin_vec::ThinVec; use crate::attributes::{AcceptMapping, AttributeParser, AttributeStability}; use crate::context::{AcceptContext, ExpectStringLiteral, FinalizeContext}; +use crate::diagnostics::{MalformedLintAttributeInput, MalformedLintAttributeInputHelp}; use crate::parser::{ArgParser, MetaItemOrLitParser}; use crate::target_checking::AllowedTargets; use crate::target_checking::Policy::{Allow, Warn}; @@ -36,9 +37,11 @@ impl LintParser { let p = parsers.last()?.meta_item()?; let nv = p.args().as_name_value()?; if !p.path().word_is(sym::reason) { - cx.emit_err(diagnostics::MalformedAttribute { + // FIXME: We should recommend `reason` here + cx.emit_err(MalformedLintAttributeInput { span: p.span(), - kind: diagnostics::MalformedAttributeKind::BadAttributeArgument(p.span()), + help: MalformedLintAttributeInputHelp::Other { kind: kind.sym() }, + kind: kind.sym(), }); } else { parsers = &parsers[..(parsers.len() - 1)]; @@ -78,26 +81,28 @@ impl LintParser { nv.expect_string_literal(cx); } ArgParser::NameValue(_) | ArgParser::List(_) => { - cx.emit_err(diagnostics::MalformedAttribute { + cx.emit_err(MalformedLintAttributeInput { span: p.span(), - kind: diagnostics::MalformedAttributeKind::BadAttributeArgument( - item.span(), - ), + help: MalformedLintAttributeInputHelp::Other { + kind: kind.sym(), + }, + kind: kind.sym(), }); } } } MetaItemOrLitParser::Lit(lit) => { - cx.emit_err(diagnostics::BadAttributeLit { + cx.emit_err(MalformedLintAttributeInput { span: item.span(), help: if lit.kind.is_str() { - diagnostics::BadAttributeLitHelp::StrLit { + MalformedLintAttributeInputHelp::StrLit { sym: lit.symbol, kind: kind.sym(), } } else { - diagnostics::BadAttributeLitHelp::Other { kind: kind.sym() } + MalformedLintAttributeInputHelp::Other { kind: kind.sym() } }, + kind: kind.sym(), }); } } diff --git a/compiler/rustc_attr_parsing/src/diagnostics.rs b/compiler/rustc_attr_parsing/src/diagnostics.rs index 127b0e4f14de8..d33c52fb061c8 100644 --- a/compiler/rustc_attr_parsing/src/diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/diagnostics.rs @@ -2196,24 +2196,23 @@ pub(crate) struct MalformedAttribute { #[derive(Subdiagnostic)] pub(crate) enum MalformedAttributeKind { - #[label("bad attribute argument")] - BadAttributeArgument(#[primary_span] Span), #[label("reason in lint attribute must come last")] ReasonMustComeLast(#[primary_span] Span), } #[derive(Diagnostic)] -#[diag("expected a lint, found literal")] -pub(crate) struct BadAttributeLit { +#[diag("malformed `{$kind}` attribute input")] +pub(crate) struct MalformedLintAttributeInput { #[primary_span] #[label("not the name of a lint")] pub span: Span, + pub kind: Symbol, #[subdiagnostic] - pub help: BadAttributeLitHelp, + pub help: MalformedLintAttributeInputHelp, } #[derive(Subdiagnostic)] -pub(crate) enum BadAttributeLitHelp { +pub(crate) enum MalformedLintAttributeInputHelp { #[help("try using `#[{$kind}({$sym})]`")] StrLit { sym: Symbol, kind: Symbol }, #[help("for example, write `#[{$kind}(dead_code)]` for `dead_code`")] diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 2089f2b2008be..30b8b3682c3b1 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -22,7 +22,6 @@ use tracing::{debug, instrument, trace}; use crate::common::CodegenCx; use crate::diagnostics::SymbolAlreadyDefined; use crate::llvm::{self, Type, Value, const_ptr_auth}; -use crate::type_of::LayoutLlvmExt; use crate::{base, debuginfo}; /// Indicates whether a value originates from a `static`. @@ -200,7 +199,7 @@ fn check_and_apply_linkage<'ll, 'tcx>( let mut should_sign = false; // Declare a symbol `foo`. If `foo` is an extern_weak symbol, we declare // an extern_weak function, otherwise a global with the desired linkage. - let g1 = if matches!(attrs.import_linkage, Some(Linkage::ExternalWeak)) { + let actual_global = if matches!(attrs.import_linkage, Some(Linkage::ExternalWeak)) { // An `extern_weak` function is represented as an `Option`, // we extract the function signature and declare it as an extern_weak function // instead of an extern_weak i8. @@ -224,28 +223,11 @@ fn check_and_apply_linkage<'ll, 'tcx>( } else { cx.declare_global(sym, cx.type_i8()) }; - llvm::set_linkage(g1, base::linkage_to_llvm(linkage)); + llvm::set_linkage(actual_global, base::linkage_to_llvm(linkage)); // Normally this is done in `get_static_inner`, but when as we generate an internal global, // it will apply the dso_local to the internal global instead, so do it here, too. - cx.assume_dso_local(g1, true); - - // Declare an internal global `extern_with_linkage_foo` which - // is initialized with the address of `foo`. If `foo` is - // discarded during linking (for example, if `foo` has weak - // linkage and there are no definitions), then - // `extern_with_linkage_foo` will instead be initialized to - // zero. - let real_name = - format!("_rust_extern_with_linkage_{:016x}_{sym}", cx.tcx.stable_crate_id(LOCAL_CRATE)); - let g2 = cx.define_global(&real_name, llty).unwrap_or_else(|| { - cx.sess().dcx().emit_fatal(SymbolAlreadyDefined { - span: cx.tcx.def_span(def_id), - symbol_name: sym, - }) - }); - llvm::set_linkage(g2, llvm::Linkage::InternalLinkage); - llvm::set_unnamed_address(g2, llvm::UnnamedAddr::Global); + cx.assume_dso_local(actual_global, true); // Sign the function pointer that is used to initialize the global let initializer = if should_sign { @@ -256,18 +238,36 @@ fn check_and_apply_linkage<'ll, 'tcx>( .expect("pointer authentication functions must be available when signing"); const_ptr_auth( - cx.const_bitcast(g1, llty), + actual_global, schema.key as u32, schema.constant_discriminator as u64, None, /* address_diversity */ ) } else { - g1 + actual_global }; - llvm::set_initializer(g2, initializer); - - g2 + // Declare an internal global `extern_with_linkage_foo` which + // is initialized with the address of `foo`. If `foo` is + // discarded during linking (for example, if `foo` has weak + // linkage and there are no definitions), then + // `extern_with_linkage_foo` will instead be initialized to + // zero. + let real_name = + format!("_rust_extern_with_linkage_{:016x}_{sym}", cx.tcx.stable_crate_id(LOCAL_CRATE)); + let pointer_global = + cx.define_global(&real_name, cx.val_ty(initializer)).unwrap_or_else(|| { + cx.sess().dcx().emit_fatal(SymbolAlreadyDefined { + span: cx.tcx.def_span(def_id), + symbol_name: sym, + }) + }); + llvm::set_linkage(pointer_global, llvm::Linkage::InternalLinkage); + llvm::set_unnamed_address(pointer_global, llvm::UnnamedAddr::Global); + + llvm::set_initializer(pointer_global, initializer); + + pointer_global } else if cx.tcx.sess.target.arch == Arch::X86 && common::is_using_dlltool(&cx.tcx.sess.target) && let Some(dllimport) = crate::common::get_dllimport(cx.tcx, def_id, sym) @@ -358,7 +358,7 @@ impl<'ll> CodegenCx<'ll, '_> { } else { let ty = instance.ty(self.tcx, self.typing_env()); trace!(?ty); - self.layout_of(ty).llvm_type(self) + self.type_array(self.type_i8(), self.layout_of(ty).size.bytes()) }; self.get_static_inner(def_id, llty) } diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs index 0cd26ca835971..f9863da230dfb 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs @@ -262,6 +262,12 @@ pub(crate) fn add_global<'ll>(llmod: Module<'ll>, ty: &'ll Type, name_cstr: &CSt } pub(crate) fn set_initializer(llglobal: &Value, constant_val: &Value) { + unsafe { + assert_eq!( + crate::llvm::LLVMGlobalGetValueType(llglobal), + crate::llvm::LLVMTypeOf(constant_val) + ); + } unsafe { LLVMSetInitializer(llglobal, constant_val); } diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index 2d64c63cf9ae4..82bd5584211c0 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -20,7 +20,6 @@ use crate::abi::FnAbiLlvmExt; use crate::builder::Builder; use crate::context::CodegenCx; use crate::diagnostics::SymbolAlreadyDefined; -use crate::type_of::LayoutLlvmExt; use crate::{base, llvm}; impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { @@ -37,7 +36,7 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { // out the llvm type from the actual evaluated initializer. let ty = if nested { self.tcx.types.unit } else { instance.ty(self.tcx, self.typing_env()) }; - let llty = self.layout_of(ty).llvm_type(self); + let llty = self.type_array(self.type_i8(), self.layout_of(ty).size.bytes()); let g = self.define_global(symbol_name, llty).unwrap_or_else(|| { self.sess() diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index c3bace9569dd0..10baf16915d15 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -72,8 +72,13 @@ fn process_builtin_attrs( AttributeKind::Cold => codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD, AttributeKind::ExportName { name, .. } => codegen_fn_attrs.symbol_name = Some(*name), AttributeKind::Inline(inline, span) => { - codegen_fn_attrs.inline = *inline; - interesting_spans.inline = Some(*span); + // On an `async fn` (or similar), inlining hints are meant for the code the user + // wrote, which lives in the body coroutine. The constructor is trivial and left to + // the usual heuristics. + if !constructs_desugared_body_coroutine(tcx, did) { + codegen_fn_attrs.inline = *inline; + interesting_spans.inline = Some(*span); + } } AttributeKind::Naked(_) => codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED, AttributeKind::RustcAlign { align, .. } => codegen_fn_attrs.alignment = Some(*align), @@ -297,9 +302,54 @@ fn process_builtin_attrs( } } + // The body coroutine can't carry attributes of its own, so it takes the ones describing the + // code the user wrote from the `async fn` (or similar) it was desugared from. This makes e.g. + // `#[inline(never)] async fn` affect `Future::poll`. See #129347. + if is_desugared_body_coroutine(tcx, did) { + let parent = tcx.local_parent(did); + // `#[rustc_force_inline]` is already rejected on the parent. Propagating it would only + // cause `CheckForceInline` to report the same attribute again for the coroutine. + if let Some((inline, span)) = find_attr!( + tcx, + parent, + Inline(inline, span) if !matches!(inline, InlineAttr::Force { .. }) => (*inline, *span) + ) { + codegen_fn_attrs.inline = inline; + interesting_spans.inline = Some(span); + } + // Unlike inlining hints, `#[cold]` stays on the constructor as well: calling it is just as + // unlikely, and its call sites are only recognized as cold through that. + if find_attr!(tcx, parent, Cold) { + codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD; + } + } + interesting_spans } +/// Whether `did` is the coroutine holding the body of an `async fn`, `gen fn`, `async gen fn`, or +/// `async` closure, as opposed to one written as an `async {}` block. +fn is_desugared_body_coroutine(tcx: TyCtxt<'_>, did: LocalDefId) -> bool { + matches!( + tcx.coroutine_kind(did), + Some(hir::CoroutineKind::Desugared( + _, + hir::CoroutineSource::Fn | hir::CoroutineSource::Closure + )) + ) +} + +/// Whether `did` is an `async fn`, `gen fn`, `async gen fn`, or `async` closure, i.e. its body +/// does nothing but construct a [desugared body coroutine](is_desugared_body_coroutine). +fn constructs_desugared_body_coroutine(tcx: TyCtxt<'_>, did: LocalDefId) -> bool { + tcx.hir_maybe_body_owned_by(did).is_some_and(|body| { + matches!( + body.value.kind, + hir::ExprKind::Closure(closure) if is_desugared_body_coroutine(tcx, closure.def_id) + ) + }) +} + /// Applies overrides for codegen fn attrs. These often have a specific reason why they're necessary. /// Please comment why when adding a new one! fn apply_overrides(tcx: TyCtxt<'_>, did: LocalDefId, codegen_fn_attrs: &mut CodegenFnAttrs) { @@ -336,7 +386,17 @@ fn apply_overrides(tcx: TyCtxt<'_>, did: LocalDefId, codegen_fn_attrs: &mut Code // its parent function, which effectively inherits the features anyway. Boxing this closure // would result in this closure being compiled without the inherited target features, but this // is probably a poor usage of `#[inline(always)]` and easily avoided by not using the attribute. - if tcx.is_closure_like(did.to_def_id()) && codegen_fn_attrs.inline != InlineAttr::Always { + // + // That reasoning doesn't hold for the body coroutine of an `async fn` or `gen fn`: it is never + // inlined into the function constructing it, yet its body was checked as part of that function. + // It always inherits, so it is compiled with the same features as the function itself. + if tcx.is_closure_like(did.to_def_id()) + && (codegen_fn_attrs.inline != InlineAttr::Always + || matches!( + tcx.coroutine_kind(did), + Some(hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Fn)) + )) + { let owner_id = tcx.parent(did.to_def_id()); if tcx.def_kind(owner_id).has_codegen_attrs() { codegen_fn_attrs diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 941af4a4ab01d..95ca582e011df 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -14,7 +14,7 @@ use rustc_middle::mir::interpret::{CTFE_ALLOC_SALT, read_target_uint, write_targ use rustc_middle::mir::{self, BinOp, ConstValue, NonDivergingIntrinsic}; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{self, FloatTy, ScalarInt, Ty, TyCtxt, TypeVisitableExt}; -use rustc_span::{Symbol, bug, span_bug, sym}; +use rustc_span::{Symbol, bug, kw, span_bug, sym}; use tracing::trace; use super::memory::MemoryKind; @@ -231,7 +231,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let val = layout.align.bytes(); self.write_scalar(Scalar::from_target_usize(val, self), dest)?; } - sym::offset_of => { + kw::OffsetOf => { let tp_ty = instance.args.type_at(0); let variant = self.read_scalar(&args[0])?.to_u32()?; diff --git a/compiler/rustc_error_codes/src/error_codes/E0452.md b/compiler/rustc_error_codes/src/error_codes/E0452.md index 429813a7cdd4e..581687e86974a 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0452.md +++ b/compiler/rustc_error_codes/src/error_codes/E0452.md @@ -3,7 +3,7 @@ An invalid lint attribute has been given. Erroneous code example: ```compile_fail,E0452 -#![allow(foo = "")] // error: malformed lint attribute +#![allow(reason = "", foo)] // error: malformed lint attribute ``` Lint attributes only accept a list of identifiers (where each identifier is a diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 3472180ae26dc..66687cfcbb06e 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -301,8 +301,6 @@ declare_features! ( /// Allows features specific to auto traits. /// Renamed from `optin_builtin_traits`. (unstable, auto_traits, "1.50.0", Some(13231)), - /// Allows builtin # foo() syntax - (internal, builtin_syntax, "1.71.0", Some(110680)), /// Allows `#[doc(notable_trait)]`. /// Renamed from `doc_spotlight`. (unstable, doc_notable_trait, "1.52.0", Some(45040)), @@ -310,6 +308,8 @@ declare_features! ( (unstable, dropck_eyepatch, "1.10.0", Some(34761)), /// Allows using the `#[fundamental]` attribute. (unstable, fundamental, "1.0.0", Some(29635)), + /// Allows internal syntax. + (internal, internal_syntax, "CURRENT_RUSTC_VERSION", Some(110680)), /// Allows using `#[link_name="llvm.*"]`. (internal, link_llvm_intrinsics, "1.0.0", Some(29602)), /// Allows using the `#[linkage = ".."]` attribute. diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 85b666372074a..8b55734d90c8f 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -6,7 +6,7 @@ use rustc_hir as hir; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::{self, Const, Ty, TyCtxt}; use rustc_span::def_id::LocalDefId; -use rustc_span::{Span, Symbol, sym}; +use rustc_span::{Span, Symbol, kw, sym}; use crate::check::check_function_signature; use crate::diagnostics::{UnrecognizedIntrinsicFunction, WrongNumberOfGenericArgumentsToIntrinsic}; @@ -66,6 +66,7 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi // safe extern fns are otherwise unprecedented. // tidy-alphabetical-start + | kw::OffsetOf | sym::abort_immediate | sym::add_with_overflow | sym::aggregate_raw_ptr @@ -141,7 +142,6 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi | sym::needs_drop | sym::offload | sym::offload_get_num_devices - | sym::offset_of | sym::overflow_checks | sym::powf | sym::powi @@ -271,7 +271,7 @@ pub(crate) fn check_intrinsic_type( (1, 0, vec![Ty::new_imm_ptr(tcx, param(0))], tcx.types.usize) } sym::type_id_size_of => (0, 0, vec![type_id_ty()], Ty::new_option(tcx, tcx.types.usize)), - sym::offset_of => (1, 0, vec![tcx.types.u32, tcx.types.u32], tcx.types.usize), + kw::OffsetOf => (1, 0, vec![tcx.types.u32, tcx.types.u32], tcx.types.usize), sym::field_offset => (1, 0, vec![], tcx.types.usize), sym::rustc_peek => (1, 0, vec![param(0)], param(0)), sym::caller_location => (0, 0, vec![], tcx.caller_location_ty()), diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index bf0d64d78d395..02acd8dc58918 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -402,7 +402,9 @@ fn bounds_from_generic_clauses<'tcx>( ty::ClauseKind::Trait(trait_predicate) => { let entry = types.entry(trait_predicate.self_ty()).or_default(); let def_id = trait_predicate.def_id(); - if !tcx.is_default_trait(def_id) && !tcx.is_lang_item(def_id, LangItem::Sized) { + if !tcx.is_implicit_trait(def_id, ty::IncludeSizedImplicitBounds::No) + && !tcx.is_lang_item(def_id, LangItem::Sized) + { // Do not add that restriction to the list if it is a positive requirement. entry.push(trait_predicate.def_id()); } diff --git a/compiler/rustc_hir_analysis/src/collect/clauses_of.rs b/compiler/rustc_hir_analysis/src/collect/clauses_of.rs index ae384a67ee6aa..ba1c1197bee92 100644 --- a/compiler/rustc_hir_analysis/src/collect/clauses_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/clauses_of.rs @@ -7,7 +7,8 @@ use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::ty::{ - self, GenericClauses, ImplTraitInTraitData, Ty, TyCtxt, TypeVisitable, TypeVisitor, Upcast, + self, GenericClauses, ImplTraitInTraitData, IncludeSizedImplicitBounds, Ty, TyCtxt, + TypeVisitable, TypeVisitor, Upcast, }; use rustc_span::{DUMMY_SP, Ident, Span, bug, span_bug}; use tracing::{debug, instrument, trace}; @@ -195,19 +196,13 @@ fn gather_explicit_clauses_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generi PredicateFilter::All, OverlappingAsssocItemConstraints::Allowed, ); - icx.lowerer().add_implicit_sizedness_bounds( - &mut bounds, - tcx.types.self_param, - self_bounds, - ImpliedBoundsContext::TraitDef(def_id), - span, - ); - icx.lowerer().add_default_traits( + icx.lowerer().add_implicit_bounds( &mut bounds, tcx.types.self_param, self_bounds, ImpliedBoundsContext::TraitDef(def_id), span, + IncludeSizedImplicitBounds::Yes, ); clauses.extend(bounds); } @@ -234,19 +229,13 @@ fn gather_explicit_clauses_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generi let param_ty = icx.lowerer().lower_ty_param(param.hir_id); let mut bounds = Vec::new(); // Implicit bounds are added to type params unless a `?Trait` bound is found - icx.lowerer().add_implicit_sizedness_bounds( - &mut bounds, - param_ty, - &[], - ImpliedBoundsContext::TyParam(param.def_id, hir_generics.predicates), - param.span, - ); - icx.lowerer().add_default_traits( + icx.lowerer().add_implicit_bounds( &mut bounds, param_ty, &[], ImpliedBoundsContext::TyParam(param.def_id, hir_generics.predicates), param.span, + IncludeSizedImplicitBounds::Yes, ); trace!(?bounds); clauses.extend(bounds); @@ -690,19 +679,13 @@ pub(super) fn implied_clauses_with_filter<'tcx>( | PredicateFilter::SelfOnly | PredicateFilter::SelfTraitThatDefines(_) | PredicateFilter::SelfAndAssociatedTypeBounds => { - icx.lowerer().add_implicit_sizedness_bounds( - &mut bounds, - self_param_ty, - superbounds, - ImpliedBoundsContext::TraitDef(trait_def_id), - item.span, - ); - icx.lowerer().add_default_traits( + icx.lowerer().add_implicit_bounds( &mut bounds, self_param_ty, superbounds, ImpliedBoundsContext::TraitDef(trait_def_id), item.span, + IncludeSizedImplicitBounds::Yes, ); } //`ConstIfConst` is only interested in `[const]` bounds. @@ -992,19 +975,13 @@ impl<'tcx> ItemCtxt<'tcx> { match param.kind { hir::GenericParamKind::Type { .. } => { let param_ty = self.lowerer().lower_ty_param(param.hir_id); - self.lowerer().add_implicit_sizedness_bounds( - &mut bounds, - param_ty, - &[], - ImpliedBoundsContext::TyParam(param.def_id, hir_generics.predicates), - param.span, - ); - self.lowerer().add_default_traits( + self.lowerer().add_implicit_bounds( &mut bounds, param_ty, &[], ImpliedBoundsContext::TyParam(param.def_id, hir_generics.predicates), param.span, + IncludeSizedImplicitBounds::Yes, ); } hir::GenericParamKind::Lifetime { .. } diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index 5ed5745310f16..131af48cd52bd 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -2,8 +2,8 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_hir as hir; use rustc_infer::traits::util; use rustc_middle::ty::{ - self, GenericArgs, PredicateProxy, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, - TypeVisitableExt, Upcast, shift_vars, + self, GenericArgs, IncludeSizedImplicitBounds, PredicateProxy, Ty, TyCtxt, TypeFoldable, + TypeFolder, TypeSuperFoldable, TypeVisitableExt, Upcast, shift_vars, }; use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::{Span, bug, span_bug}; @@ -54,19 +54,13 @@ fn associated_type_bounds<'tcx>( | PredicateFilter::SelfTraitThatDefines(_) | PredicateFilter::SelfAndAssociatedTypeBounds => { // Implicit bounds are added to associated types unless a `?Trait` bound is found. - icx.lowerer().add_implicit_sizedness_bounds( - &mut bounds, - item_ty, - hir_bounds, - ImpliedBoundsContext::AssociatedTypeOrImplTrait, - span, - ); - icx.lowerer().add_default_traits( + icx.lowerer().add_implicit_bounds( &mut bounds, item_ty, hir_bounds, ImpliedBoundsContext::AssociatedTypeOrImplTrait, span, + IncludeSizedImplicitBounds::Yes, ); // Also collect `where Self::Assoc: Trait` from the parent trait's where clauses. @@ -381,19 +375,13 @@ fn opaque_type_bounds<'tcx>( | PredicateFilter::SelfOnly | PredicateFilter::SelfTraitThatDefines(_) | PredicateFilter::SelfAndAssociatedTypeBounds => { - icx.lowerer().add_implicit_sizedness_bounds( - &mut bounds, - item_ty, - hir_bounds, - ImpliedBoundsContext::AssociatedTypeOrImplTrait, - span, - ); - icx.lowerer().add_default_traits( + icx.lowerer().add_implicit_bounds( &mut bounds, item_ty, hir_bounds, ImpliedBoundsContext::AssociatedTypeOrImplTrait, span, + IncludeSizedImplicitBounds::Yes, ); } //`ConstIfConst` is only interested in `[const]` bounds. diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 0b7df89551da8..88924a9d6a98e 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -10,8 +10,8 @@ use rustc_hir::PolyTraitRef; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_middle::ty::{ - self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, - TypeVisitor, Upcast, + self as ty, IncludeSizedImplicitBounds, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, + TypeVisitable, TypeVisitableExt, TypeVisitor, Upcast, }; use rustc_span::{ErrorGuaranteed, Ident, Span, bug, kw}; use rustc_trait_selection::traits; @@ -138,6 +138,29 @@ fn add_trait_bound<'tcx>( } impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { + /// Adds implicit sizedness, and in the future `Move` and `Forget`, and default trait bounds. + pub(crate) fn add_implicit_bounds( + &self, + bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, + self_ty: Ty<'tcx>, + hir_bounds: &[hir::GenericBound<'_>], + context: ImpliedBoundsContext<'tcx>, + span: Span, + // Sized is treated slightly more specially than the other implicit bounds. + include_sized: IncludeSizedImplicitBounds, + ) { + // Skip adding any default bounds if `#![rustc_no_implicit_bounds]` + if find_attr!(self.tcx(), crate, RustcNoImplicitBounds) { + return; + } + + self.add_default_traits(bounds, self_ty, hir_bounds, context, span); + + if let IncludeSizedImplicitBounds::Yes = include_sized { + self.add_implicit_sizedness_bounds(bounds, self_ty, hir_bounds, context, span); + } + } + /// Adds sizedness bounds to a trait, trait alias, parameter, opaque type or associated type. /// /// - On parameters, opaque type and associated types, add default `Sized` bound if no explicit @@ -146,7 +169,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// bounds are present. /// - On parameters, opaque type, associated types and trait aliases, add a `MetaSized` bound if /// a `?Sized` bound is present. - pub(crate) fn add_implicit_sizedness_bounds( + fn add_implicit_sizedness_bounds( &self, bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, self_ty: Ty<'tcx>, @@ -156,11 +179,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) { let tcx = self.tcx(); - // Skip adding any default bounds if `#![rustc_no_implicit_bounds]` - if find_attr!(tcx, crate, RustcNoImplicitBounds) { - return; - } - let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, span); let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span); @@ -208,7 +226,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } - pub(crate) fn add_default_traits( + fn add_default_traits( &self, bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, self_ty: Ty<'tcx>, @@ -224,7 +242,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// Add a `experimental_default_bounds` bound to the `bounds` if appropriate. /// /// Doesn't add the bound if the HIR bounds contain any of `Trait`, `?Trait` or `!Trait`. - pub(crate) fn add_default_trait( + fn add_default_trait( &self, trait_: LangItem, bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, @@ -244,23 +262,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } if let Some(trait_did) = tcx.lang_items().get(trait_) - && self.should_add_default_traits(trait_did, hir_bounds, context) + && !collect_bounds(hir_bounds, context, trait_did).any() { add_trait_bound(tcx, bounds, self_ty, trait_did, span); } } - /// Returns `true` if default trait bound should be added. - fn should_add_default_traits( - &self, - trait_def_id: DefId, - hir_bounds: &[hir::GenericBound<'_>], - context: ImpliedBoundsContext<'tcx>, - ) -> bool { - let collected = collect_bounds(hir_bounds, context, trait_def_id); - !find_attr!(self.tcx(), crate, RustcNoImplicitBounds) && !collected.any() - } - pub(crate) fn require_bound_to_relax_default_trait( &self, trait_ref: hir::TraitRef<'_>, @@ -269,7 +276,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let tcx = self.tcx(); if let Res::Def(DefKind::Trait, def_id) = trait_ref.path.res - && (tcx.is_lang_item(def_id, LangItem::Sized) || tcx.is_default_trait(def_id)) + && (tcx.is_lang_item(def_id, LangItem::Sized) + || tcx.is_implicit_trait(def_id, IncludeSizedImplicitBounds::No)) { return; } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs index c652174f9ba68..4a763e5b89316 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs @@ -9,8 +9,8 @@ use rustc_hir::{self as hir, HirId}; use rustc_lint_defs::builtin::{BARE_TRAIT_OBJECTS, UNUSED_ASSOCIATED_TYPE_BOUNDS}; use rustc_middle::ty::elaborate::ClauseWithSupertraitSpan; use rustc_middle::ty::{ - self, BottomUpFolder, ExistentialPredicateStableCmpExt as _, Ty, TyCtxt, TypeFoldable, - TypeVisitableExt, Upcast, + self, BottomUpFolder, ExistentialPredicateStableCmpExt as _, IncludeSizedImplicitBounds, Ty, + TyCtxt, TypeFoldable, TypeVisitableExt, Upcast, }; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::{ErrorGuaranteed, Span}; @@ -75,7 +75,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } - self.add_default_traits( + self.add_implicit_bounds( &mut user_written_bounds, dummy_self, &hir_bounds @@ -84,6 +84,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .collect::>(), ImpliedBoundsContext::AssociatedTypeOrImplTrait, span, + IncludeSizedImplicitBounds::No, ); let (mut elaborated_trait_bounds, elaborated_projection_bounds) = diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 5edf50d5cb33b..f15b8c81c51d2 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -15,7 +15,7 @@ //! [^1]: This includes types, lifetimes / regions, constants in type positions, //! trait references and bounds. -mod bounds; +pub(crate) mod bounds; mod cmse; mod dyn_trait; pub mod errors; @@ -43,9 +43,9 @@ use rustc_lint_defs::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; use rustc_macros::{TypeFoldable, TypeVisitable}; use rustc_middle::middle::stability::AllowUnstable; use rustc_middle::ty::{ - self, Const, FnSigKind, GenericArgKind, GenericParamDefKind, LitToConstInput, Ty, TyCtxt, - TypeSuperFoldable, TypeVisitableExt, TypingMode, Unnormalized, Upcast, const_lit_matches_ty, - fold_regions, + self, Const, FnSigKind, GenericArgKind, GenericParamDefKind, IncludeSizedImplicitBounds, + LitToConstInput, Ty, TyCtxt, TypeSuperFoldable, TypeVisitableExt, TypingMode, Unnormalized, + Upcast, const_lit_matches_ty, fold_regions, }; use rustc_session::diagnostics::feature_err; use rustc_span::def_id::{LocalModId, ModId}; @@ -3326,12 +3326,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { PredicateFilter::All, OverlappingAsssocItemConstraints::Allowed, ); - self.add_implicit_sizedness_bounds( + self.add_implicit_bounds( &mut bounds, self_ty, hir_bounds, ImpliedBoundsContext::AssociatedTypeOrImplTrait, hir_ty.span, + IncludeSizedImplicitBounds::Yes, ); self.register_trait_ascription_bounds(bounds, hir_ty.hir_id, hir_ty.span); self_ty diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs index f3cba3a27d69f..7ccd7eb435d03 100644 --- a/compiler/rustc_hir_typeck/src/place_op.rs +++ b/compiler/rustc_hir_typeck/src/place_op.rs @@ -9,7 +9,7 @@ use rustc_middle::ty::adjustment::{ OverloadedDeref, PointerCoercion, }; use rustc_middle::ty::{self, Ty}; -use rustc_span::{Span, span_bug, sym}; +use rustc_span::{Span, kw, span_bug, sym}; use tracing::debug; use crate::method::{MethodCallee, TreatNotYetDefinedOpaques}; @@ -203,7 +203,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!("try_overloaded_place_op({:?},{:?},{:?})", span, base_ty, op); let (Some(imm_tr), imm_op) = (match op { - PlaceOp::Deref => (self.tcx.lang_items().deref_trait(), sym::deref), + PlaceOp::Deref => (self.tcx.lang_items().deref_trait(), kw::Deref), PlaceOp::Index => (self.tcx.lang_items().index_trait(), sym::index), }) else { // Bail if `Deref` or `Index` isn't defined. diff --git a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs index 75552ab759fd5..12b52f4e2801e 100644 --- a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs +++ b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs @@ -1,7 +1,7 @@ use rustc_attr_ir::lang_items::LangItem; use rustc_hir as hir; use rustc_lint_defs::{declare_lint, declare_lint_pass}; -use rustc_middle::ty::Unnormalized; +use rustc_middle::ty::{IncludeSizedImplicitBounds, Unnormalized}; use crate::{LateContext, LateLintPass, LintContext}; @@ -51,7 +51,9 @@ impl<'tcx> LateLintPass<'tcx> for MultipleSupertraitUpcastable { .map(Unnormalized::skip_norm_wip) .filter_map(|(clause, _)| clause.as_trait_clause()) .filter(|pred| !cx.tcx.is_lang_item(pred.def_id(), LangItem::MetaSized)) - .filter(|pred| !cx.tcx.is_default_trait(pred.def_id())); + .filter(|pred| { + !cx.tcx.is_implicit_trait(pred.def_id(), IncludeSizedImplicitBounds::No) + }); if direct_super_traits_iter.count() > 1 { cx.emit_span_lint( MULTIPLE_SUPERTRAIT_UPCASTABLE, diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 3b96713305337..976512fba3f53 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -48,7 +48,8 @@ use rustc_structures::{CrateType, Limit}; use rustc_type_ir::TyKind::*; pub use rustc_type_ir::lift::Lift; use rustc_type_ir::{ - CollectAndApply, PlaceholderType, WithCachedTypeInfo, elaborate, search_graph, + CollectAndApply, IncludeSizedImplicitBounds, PlaceholderType, WithCachedTypeInfo, elaborate, + search_graph, }; use tracing::{debug, instrument}; @@ -955,6 +956,18 @@ impl<'tcx> TyCtxt<'tcx> { self.default_traits().iter().any(|&default_trait| self.is_lang_item(def_id, default_trait)) } + /// Returns true if a trait is an "implicit trait", which is a trait which is added + /// to bounds on generic types automatically by the compiler. + pub fn is_implicit_trait( + self, + def_id: DefId, + including_sized: IncludeSizedImplicitBounds, + ) -> bool { + self.is_default_trait(def_id) + // NOTE: add move and forget here later + || (matches!(including_sized, IncludeSizedImplicitBounds::Yes) && self.is_sizedness_trait(def_id)) + } + pub fn is_sizedness_trait(self, def_id: DefId) -> bool { matches!(self.as_lang_item(def_id), Some(LangItem::Sized | LangItem::MetaSized)) } diff --git a/compiler/rustc_middle/src/ty/context/impl_interner.rs b/compiler/rustc_middle/src/ty/context/impl_interner.rs index eb81ea291759b..c62bdcebec389 100644 --- a/compiler/rustc_middle/src/ty/context/impl_interner.rs +++ b/compiler/rustc_middle/src/ty/context/impl_interner.rs @@ -12,8 +12,8 @@ use rustc_span::{DUMMY_SP, Span, Symbol, bug}; use rustc_type_ir::lang_items::{SolverAdtLangItem, SolverProjectionLangItem, SolverTraitLangItem}; use rustc_type_ir::solve::CanonicalInputData; use rustc_type_ir::{ - BoundVar, CollectAndApply, DebruijnIndex, Interner, RegionVid, TypeFoldable, Unnormalized, - VisitorResult, WithCachedTypeInfo, search_graph, try_visit, + BoundVar, CollectAndApply, DebruijnIndex, IncludeSizedImplicitBounds, Interner, RegionVid, + TypeFoldable, Unnormalized, VisitorResult, WithCachedTypeInfo, search_graph, try_visit, }; use crate::dep_graph::{DepKind, DepNodeIndex}; @@ -527,6 +527,14 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.is_default_trait(def_id) } + fn is_implicit_trait( + self, + def_id: Self::TraitId, + including_sized: IncludeSizedImplicitBounds, + ) -> bool { + self.is_implicit_trait(def_id, including_sized) + } + fn is_sizedness_trait(self, def_id: DefId) -> bool { self.is_sizedness_trait(def_id) } diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 3d560a9f18815..398633cb3311c 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -141,7 +141,7 @@ impl<'tcx> TyCtxt<'tcx> { where T: TypeFoldable>, { - self.instantiate_bound_regions(value, |_| self.lifetimes.re_erased).0 + self.instantiate_bound_regions_uncached(value, |_| self.lifetimes.re_erased) } /// Anonymize all bound variables in `value`, this is mostly used to improve caching. diff --git a/compiler/rustc_mir_build/src/builder/matches/test.rs b/compiler/rustc_mir_build/src/builder/matches/test.rs index d116806fc0b73..a8ae60b4daba7 100644 --- a/compiler/rustc_mir_build/src/builder/matches/test.rs +++ b/compiler/rustc_mir_build/src/builder/matches/test.rs @@ -14,7 +14,7 @@ use rustc_middle::mir::*; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, GenericArg, Ty, TyCtxt}; use rustc_span::def_id::DefId; -use rustc_span::{DUMMY_SP, Span, Spanned, Symbol, bug, sym}; +use rustc_span::{DUMMY_SP, Span, Spanned, Symbol, bug, kw, sym}; use tracing::{debug, instrument}; use crate::builder::Builder; @@ -343,7 +343,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { span: Span, ) { let (trait_item, method) = match mutability { - Mutability::Not => (LangItem::Deref, sym::deref), + Mutability::Not => (LangItem::Deref, kw::Deref), Mutability::Mut => (LangItem::DerefMut, sym::deref_mut), }; let borrow_kind = super::util::ref_pat_borrow_kind(mutability); diff --git a/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs index 569fbd41e1b22..6b159074493f9 100644 --- a/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs @@ -26,13 +26,15 @@ const NEEDS_CANONICAL: TypeFlags = TypeFlags::from_bits( .unwrap(); #[derive(Debug, Clone, Copy)] -enum CanonicalizeInputKind { +enum CanonicalizeInputKind { /// When canonicalizing the `param_env`, we keep `'static` as merging /// trait candidates relies on it when deciding whether a where-bound /// is trivial. ParamEnv, /// When canonicalizing predicates, we don't keep `'static`. - Predicate, + /// `param_env_var_kinds` caches the interned variable kinds to be + /// reused if there are no new vars. + Predicate { param_env_var_kinds: Option }, } /// Whether we're canonicalizing a query input or the query response. @@ -41,8 +43,8 @@ enum CanonicalizeInputKind { /// while canonicalizing the response happens in the context of the /// query. #[derive(Debug, Clone, Copy)] -enum CanonicalizeMode { - Input(CanonicalizeInputKind), +enum CanonicalizeMode { + Input(CanonicalizeInputKind), /// FIXME: We currently return region constraints referring to /// placeholders and inference variables from a binder instantiated /// inside of the query. @@ -68,14 +70,14 @@ pub(super) struct Canonicalizer<'a, D: SolverDelegate, I: Interner delegate: &'a D, // Immutable field. - canonicalize_mode: CanonicalizeMode, + canonicalize_mode: CanonicalizeMode, // Mutable fields. state: Box>, } impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { - fn new(delegate: &'a D, canonicalize_mode: CanonicalizeMode) -> Self { + fn new(delegate: &'a D, canonicalize_mode: CanonicalizeMode) -> Self { Canonicalizer { delegate, canonicalize_mode, state: delegate.obtain_canonicalizer_state() } } @@ -105,15 +107,18 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { if !param_env.has_type_flags(NEEDS_CANONICAL) { let rest_canonicalizer = Canonicalizer::new( delegate, - CanonicalizeMode::Input(CanonicalizeInputKind::Predicate), + CanonicalizeMode::Input(CanonicalizeInputKind::Predicate { + param_env_var_kinds: None, + }), ); return (param_env, rest_canonicalizer); } // Do the `env` canonicalization, and then convert the canonicalizer to `rest` form for - // subsequent use. - let do_env_and_make_rest = || { + // subsequent use, also returning the optionally interned (i.e., uniquely identified) + // canonicalized variable kind list in case cache is used, so it can also be cached. + let do_env_and_make_rest = |intern_var_kinds: bool| { let mut env_canonicalizer = Canonicalizer::new( delegate, CanonicalizeMode::Input(CanonicalizeInputKind::ParamEnv), @@ -133,12 +138,17 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { // // We clear the cache rather than deleting it or replacing it with an empty cache. This // lets the allocated capacity be reused later. - let mut rest_canonicalizer = env_canonicalizer; - rest_canonicalizer.canonicalize_mode = - CanonicalizeMode::Input(CanonicalizeInputKind::Predicate); + let param_env_var_kinds = intern_var_kinds + .then(|| delegate.cx().mk_canonical_var_kinds(&env_canonicalizer.state.var_kinds)); + let mut rest_canonicalizer = Canonicalizer { + canonicalize_mode: CanonicalizeMode::Input(CanonicalizeInputKind::Predicate { + param_env_var_kinds, + }), + ..env_canonicalizer + }; rest_canonicalizer.state.cache.clear(); - (param_env, rest_canonicalizer) + (param_env, rest_canonicalizer, param_env_var_kinds) }; // Check whether we can use the global cache for this param_env. As we only use @@ -153,11 +163,11 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { Entry::Vacant(e) => { // Cache miss. Do `env` canonicalization and get `rest_canonicalizer`, and // fill in the cache entry. - let (param_env, rest_canonicalizer) = do_env_and_make_rest(); + let (param_env, rest_canonicalizer, var_kinds) = do_env_and_make_rest(true); e.insert(CanonicalParamEnvCacheEntry { param_env, variables: rest_canonicalizer.state.variables.clone(), - var_kinds: rest_canonicalizer.state.var_kinds.clone(), + var_kinds: var_kinds.unwrap(), // SAFETY: The iterated elements go straight back into a hashmap. #[allow(rustc::potential_query_instability)] variable_lookup_table: rest_canonicalizer @@ -174,10 +184,12 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { let e = e.get(); let mut rest_canonicalizer = Canonicalizer::new( delegate, - CanonicalizeMode::Input(CanonicalizeInputKind::Predicate), + CanonicalizeMode::Input(CanonicalizeInputKind::Predicate { + param_env_var_kinds: Some(e.var_kinds), + }), ); rest_canonicalizer.state.variables.clone_from(&e.variables); - rest_canonicalizer.state.var_kinds.clone_from(&e.var_kinds); + e.var_kinds.as_slice().clone_into(&mut rest_canonicalizer.state.var_kinds); rest_canonicalizer .state .variable_lookup_table @@ -187,7 +199,8 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { }) } else { // Do `env` canonicalization and get `rest_canonicalizer`. - do_env_and_make_rest() + let (param_env, rest_canonicalizer, _) = do_env_and_make_rest(false); + (param_env, rest_canonicalizer) } } @@ -278,7 +291,7 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { // during canonicalization in the new solver. let max_universe = match self.canonicalize_mode { // All placeholders and vars are canonicalized in the root universe. - CanonicalizeMode::Input { .. } => { + CanonicalizeMode::Input(_) => { debug_assert!( self.state .var_kinds @@ -309,7 +322,15 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { .unwrap_or(ty::UniverseIndex::ROOT) } }; - let var_kinds = self.delegate.cx().mk_canonical_var_kinds(&self.state.var_kinds); + let var_kinds = match self.canonicalize_mode { + CanonicalizeMode::Input(CanonicalizeInputKind::Predicate { + param_env_var_kinds: Some(cached), + }) if cached.len() == self.state.variables.len() => { + debug_assert_eq!(cached.as_slice(), self.state.var_kinds.as_slice()); + cached + } + _ => self.delegate.cx().mk_canonical_var_kinds(&self.state.var_kinds), + }; // We have finished with this canonicalizer and can return its state to the delegate for // later reuse. @@ -330,7 +351,7 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { let sub_root = self.get_or_insert_sub_root(vid); let ui = match self.canonicalize_mode { - CanonicalizeMode::Input { .. } => ty::UniverseIndex::ROOT, + CanonicalizeMode::Input(_) => ty::UniverseIndex::ROOT, CanonicalizeMode::Response { .. } => self .delegate .universe_of_ty(vid) @@ -359,7 +380,7 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { } }, ty::Placeholder(placeholder) => match self.canonicalize_mode { - CanonicalizeMode::Input { .. } => { + CanonicalizeMode::Input(_) => { CanonicalVarKind::PlaceholderTy(PlaceholderType::new_anon( ty::UniverseIndex::ROOT, self.state.variables.len().into(), @@ -368,7 +389,7 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { CanonicalizeMode::Response { .. } => CanonicalVarKind::PlaceholderTy(placeholder), }, ty::Param(_) => match self.canonicalize_mode { - CanonicalizeMode::Input { .. } => { + CanonicalizeMode::Input(_) => { CanonicalVarKind::PlaceholderTy(PlaceholderType::new_anon( ty::UniverseIndex::ROOT, self.state.variables.len().into(), @@ -429,7 +450,7 @@ impl, I: Interner> TypeFolder for Canonicaliz // We don't canonicalize `ReStatic` in the `param_env` as we use it // when checking whether a `ParamEnv` candidate is global. ty::ReStatic => match self.canonicalize_mode { - CanonicalizeMode::Input(CanonicalizeInputKind::Predicate) => { + CanonicalizeMode::Input(CanonicalizeInputKind::Predicate { .. }) => { CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion::new_anon( ty::UniverseIndex::ROOT, self.state.variables.len().into(), @@ -541,7 +562,7 @@ impl, I: Interner> TypeFolder for Canonicaliz ); match self.canonicalize_mode { - CanonicalizeMode::Input { .. } => { + CanonicalizeMode::Input(_) => { CanonicalVarKind::Const(ty::UniverseIndex::ROOT) } CanonicalizeMode::Response { .. } => { @@ -552,7 +573,7 @@ impl, I: Interner> TypeFolder for Canonicaliz ty::InferConst::Fresh(_) => unimplemented!(), }, ty::ConstKind::Placeholder(placeholder) => match self.canonicalize_mode { - CanonicalizeMode::Input { .. } => { + CanonicalizeMode::Input(_) => { CanonicalVarKind::PlaceholderConst(PlaceholderConst::new_anon( ty::UniverseIndex::ROOT, self.state.variables.len().into(), @@ -563,7 +584,7 @@ impl, I: Interner> TypeFolder for Canonicaliz } }, ty::ConstKind::Param(_) => match self.canonicalize_mode { - CanonicalizeMode::Input { .. } => { + CanonicalizeMode::Input(_) => { CanonicalVarKind::PlaceholderConst(PlaceholderConst::new_anon( ty::UniverseIndex::ROOT, self.state.variables.len().into(), @@ -592,7 +613,7 @@ impl, I: Interner> TypeFolder for Canonicaliz match self.canonicalize_mode { CanonicalizeMode::Input(CanonicalizeInputKind::ParamEnv) | CanonicalizeMode::Response { max_input_universe: _ } => {} - CanonicalizeMode::Input(CanonicalizeInputKind::Predicate) => { + CanonicalizeMode::Input(CanonicalizeInputKind::Predicate { .. }) => { panic!("erasing 'static in env") } } diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 5ae19b2eb6935..685897188a6bf 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -10,9 +10,9 @@ use rustc_type_ir::solve::{ QueryResultOrRerunNonErased, RerunNonErased, RerunReason, RerunResultExt, SizedTraitKind, }; use rustc_type_ir::{ - self as ty, ClausePolarity, ExistentialPredicate, FieldInfo, Interner, MayBeErased, Movability, - Region, TraitClause, TraitRef, TypeVisitableExt as _, TypingMode, Unnormalized, Upcast as _, - elaborate, + self as ty, ClausePolarity, ExistentialPredicate, FieldInfo, IncludeSizedImplicitBounds, + Interner, MayBeErased, Movability, Region, TraitClause, TraitRef, TypeVisitableExt as _, + TypingMode, Unnormalized, Upcast as _, elaborate, }; use tracing::{debug, instrument, trace, warn}; @@ -1413,7 +1413,13 @@ where // Backward compatibility for default auto traits. // Test: ui/traits/default_auto_traits/extern-types.rs - ty::Foreign(..) if self.cx().is_default_trait(goal.predicate.def_id()) => check_impls(), + ty::Foreign(..) + if self + .cx() + .is_implicit_trait(goal.predicate.def_id(), IncludeSizedImplicitBounds::No) => + { + check_impls() + } // These types cannot be structurally decomposed into constituent // types, and therefore have no built-in auto impl. diff --git a/compiler/rustc_parse/src/diagnostics.rs b/compiler/rustc_parse/src/diagnostics.rs index ab220cc56a9e0..72947b1c576c8 100644 --- a/compiler/rustc_parse/src/diagnostics.rs +++ b/compiler/rustc_parse/src/diagnostics.rs @@ -4079,21 +4079,6 @@ impl IntoDiagArg for Case { } } -#[derive(Diagnostic)] -#[diag("unknown `builtin #` construct `{$name}`")] -pub(crate) struct UnknownBuiltinConstruct { - #[primary_span] - pub span: Span, - pub name: Ident, -} - -#[derive(Diagnostic)] -#[diag("expected identifier after `builtin #`")] -pub(crate) struct ExpectedBuiltinIdent { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag("static items may not have generic parameters")] pub(crate) struct StaticWithGenerics { diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 84aa391590041..e8c4ee4aae0f2 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1315,8 +1315,6 @@ impl<'a> Parser<'a> { }) } else if this.check(exp!(OpenBracket)) { this.parse_expr_array_or_repeat(exp!(CloseBracket)) - } else if this.is_builtin() { - this.parse_expr_builtin() } else if this.check_path() { this.parse_expr_path_start() } else if this.token.is_keyword(kw::Move) @@ -1385,6 +1383,14 @@ impl<'a> Parser<'a> { return Ok(expr); } Ok(this.mk_expr(this.prev_token.span, ExprKind::Underscore)) + } else if this.eat_forced_keyword_noexpect(kw::OffsetOf) { + this.parse_expr_offset_of(lo) + } else if this.eat_forced_keyword_noexpect(kw::TypeAscribe) { + this.parse_expr_type_ascribe(lo) + } else if this.eat_forced_keyword_noexpect(kw::WrapBinder) { + this.parse_expr_unsafe_binder_cast(lo, UnsafeBinderCastKind::Wrap) + } else if this.eat_forced_keyword_noexpect(kw::UnwrapBinder) { + this.parse_expr_unsafe_binder_cast(lo, UnsafeBinderCastKind::Unwrap) } else if this.token_uninterpolated_span().at_least_rust_2018() { // `Span::at_least_rust_2018()` is somewhat expensive; don't get it repeatedly. let at_async = this.check_keyword(exp!(Async)); @@ -1826,58 +1832,9 @@ impl<'a> Parser<'a> { self.maybe_recover_from_bad_qpath(expr) } - /// Parse `builtin # ident(args,*)`. - fn parse_expr_builtin(&mut self) -> PResult<'a, Box> { - self.parse_builtin(|this, lo, ident| { - Ok(match ident.name { - sym::offset_of => Some(this.parse_expr_offset_of(lo)?), - sym::type_ascribe => Some(this.parse_expr_type_ascribe(lo)?), - sym::wrap_binder => { - Some(this.parse_expr_unsafe_binder_cast(lo, UnsafeBinderCastKind::Wrap)?) - } - sym::unwrap_binder => { - Some(this.parse_expr_unsafe_binder_cast(lo, UnsafeBinderCastKind::Unwrap)?) - } - _ => None, - }) - }) - } - - pub(crate) fn parse_builtin( - &mut self, - parse: impl FnOnce(&mut Parser<'a>, Span, Ident) -> PResult<'a, Option>, - ) -> PResult<'a, T> { - let lo = self.token.span; - - self.bump(); // `builtin` - self.bump(); // `#` - - let Some((ident, IdentKind::Normal)) = self.token.ident() else { - let err = self - .dcx() - .create_err(crate::diagnostics::ExpectedBuiltinIdent { span: self.token.span }); - return Err(err); - }; - self.psess.gated_spans.gate(sym::builtin_syntax, ident.span); - self.bump(); - + pub(crate) fn parse_expr_offset_of(&mut self, lo: Span) -> PResult<'a, Box> { self.expect(exp!(OpenParen))?; - let ret = if let Some(res) = parse(self, lo, ident)? { - Ok(res) - } else { - let err = self.dcx().create_err(crate::diagnostics::UnknownBuiltinConstruct { - span: lo.to(ident.span), - name: ident, - }); - return Err(err); - }; - self.expect(exp!(CloseParen))?; - - ret - } - /// Built-in macro for `offset_of!` expressions. - pub(crate) fn parse_expr_offset_of(&mut self, lo: Span) -> PResult<'a, Box> { let container = self.parse_ty()?; self.expect(exp!(Comma))?; @@ -1900,16 +1857,26 @@ impl<'a> Parser<'a> { } } + // FIXME: Odd not to include the closing paren (contrary to the leading one etc.) but + // it actually "improves" diagnostics slightly by not pointing into the wrapper macros. let span = lo.to(self.token.span); + self.expect(exp!(CloseParen))?; + + self.psess.gated_spans.gate(sym::internal_syntax, lo.to(self.token.span)); + Ok(self.mk_expr(span, ExprKind::OffsetOf(container, fields))) } - /// Built-in macro for type ascription expressions. pub(crate) fn parse_expr_type_ascribe(&mut self, lo: Span) -> PResult<'a, Box> { + self.expect(exp!(OpenParen))?; let expr = self.parse_expr()?; self.expect(exp!(Comma))?; let ty = self.parse_ty()?; + // FIXME: Odd not to include the closing paren (contrary to the leading one etc.) but + // it actually "improves" diagnostics slightly by not pointing into the wrapper macros. let span = lo.to(self.token.span); + self.expect(exp!(CloseParen))?; + self.psess.gated_spans.gate(sym::internal_syntax, lo.to(self.token.span)); Ok(self.mk_expr(span, ExprKind::Type(expr, ty))) } @@ -1918,9 +1885,15 @@ impl<'a> Parser<'a> { lo: Span, kind: UnsafeBinderCastKind, ) -> PResult<'a, Box> { + self.expect(exp!(OpenParen))?; + let expr = self.parse_expr()?; let ty = if self.eat(exp!(Comma)) { Some(self.parse_ty()?) } else { None }; + // FIXME: Odd not to include the closing paren (contrary to the leading one etc.) but + // it actually "improves" diagnostics slightly by not pointing into the wrapper macros. let span = lo.to(self.token.span); + self.expect(exp!(CloseParen))?; + self.psess.gated_spans.gate(sym::internal_syntax, lo.to(self.token.span)); Ok(self.mk_expr(span, ExprKind::UnsafeBinderCast(kind, expr, ty))) } @@ -3423,10 +3396,6 @@ impl<'a> Parser<'a> { Ok(expr) } - pub(crate) fn is_builtin(&self) -> bool { - self.token.is_keyword(kw::Builtin) && self.look_ahead(1, |t| *t == token::Pound) - } - /// Parses a `try {...}` or `try bikeshed Ty {...}` expression (`try` token already eaten). fn parse_try_block(&mut self, span_lo: Span) -> PResult<'a, Box> { let annotation = diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index bc74ff14a1b3a..27646bac1c21e 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -354,9 +354,6 @@ impl<'a> Parser<'a> { // UNION ITEM self.bump(); // `union` self.parse_item_union()? - } else if self.is_builtin() { - // BUILTIN# ITEM - return self.parse_item_builtin(); } else if self.eat_keyword_case(exp!(Macro), case) { // MACROS 2.0 ITEM self.parse_item_decl_macro(lo)? @@ -599,11 +596,6 @@ impl<'a> Parser<'a> { if let Some(err) = err { Err(self.dcx().create_err(err)) } else { Ok(()) } } - fn parse_item_builtin(&mut self) -> PResult<'a, Option> { - // To be expanded - Ok(None) - } - /// Parses an item macro, e.g., `item!();`. fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, MacCall> { let path = self.parse_path(PathStyle::Mod)?; // `foo::bar` diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index fb26ef5e8ace6..a89fd9b6298f3 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -630,6 +630,15 @@ impl<'a> Parser<'a> { if !self.eat_keyword(exp) { self.unexpected() } else { Ok(()) } } + #[must_use] + pub(crate) fn eat_forced_keyword_noexpect(&mut self, kw: Symbol) -> bool { + if self.token.is_forced_keyword(kw) { + self.bump(); + return true; + } + false + } + /// Consume a sequence produced by a metavar expansion, if present. pub fn eat_metavar_seq( &mut self, diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 9fd38aa0f3b8f..422e3cbfd082e 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -801,8 +801,17 @@ impl<'a> Parser<'a> { } else { PatKind::Expr(const_expr) } - } else if self.is_builtin() { - self.parse_pat_builtin()? + } else if self.eat_forced_keyword_noexpect(kw::Deref) { + self.expect(exp!(OpenParen))?; + let pat = ast::PatKind::Deref(Box::new(self.parse_pat_allow_top_guard( + None, + RecoverComma::Yes, + RecoverColon::Yes, + CommaRecoveryMode::LikelyTuple, + )?)); + self.expect(exp!(CloseParen))?; + self.psess.gated_spans.gate(sym::internal_syntax, lo.to(self.token.span)); + pat } // Don't eagerly error on semantically invalid tokens when matching // declarative macros, as the input to those doesn't have to be @@ -1608,23 +1617,6 @@ impl<'a> Parser<'a> { .contains(&self.token.kind) } - fn parse_pat_builtin(&mut self) -> PResult<'a, PatKind> { - self.parse_builtin(|self_, _lo, ident| { - Ok(match ident.name { - // builtin#deref(PAT) - sym::deref => { - Some(ast::PatKind::Deref(Box::new(self_.parse_pat_allow_top_guard( - None, - RecoverComma::Yes, - RecoverColon::Yes, - CommaRecoveryMode::LikelyTuple, - )?))) - } - _ => None, - }) - }) - } - // FIXME: remove this entirely eventually /// Parses the removed `box pat` syntax to provide a more helpful error message. fn parse_pat_box(&mut self) -> PResult<'a, PatKind> { diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 49bcdbbe8fa57..df2df24854ee1 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -126,11 +126,7 @@ impl<'a> Parser<'a> { diagnostics::InvalidVariableDeclarationSub::UseLetNotVar, force_collect, )? - } else if self.check_path() - && !self.token.is_qpath_start() - && !self.is_path_start_item() - && !self.is_builtin() - { + } else if self.check_path() && !self.token.is_qpath_start() && !self.is_path_start_item() { // We have avoided contextual keywords like `union`, items with `crate` visibility, // or `auto trait` items. We aim to parse an arbitrary path `a::b` but not something // that starts like a path (1 token), but it fact not a path. diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index e2187612f5d20..b66d7310dbea5 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -326,8 +326,6 @@ impl<'a> Parser<'a> { self.parse_borrowed_pointee()? } else if self.eat_keyword_noexpect(kw::Typeof) { self.parse_typeof_ty(lo)? - } else if self.is_builtin() { - self.parse_builtin_ty()? } else if self.eat_keyword(exp!(Underscore)) { // A type to be inferred `_` TyKind::Infer @@ -423,6 +421,8 @@ impl<'a> Parser<'a> { && self.look_ahead(1, |tok| tok.kind == token::Lt) { self.parse_unsafe_binder_ty()? + } else if self.eat_forced_keyword_noexpect(kw::FieldOf) { + self.parse_ty_field_of(lo)? } else { let msg = format!("expected type, found {}", super::token_descr(&self.token)); let mut err = self.dcx().struct_span_err(lo, msg); @@ -826,16 +826,9 @@ impl<'a> Parser<'a> { Ok(TyKind::Err(guar)) } - fn parse_builtin_ty(&mut self) -> PResult<'a, TyKind> { - self.parse_builtin(|this, lo, ident| { - Ok(match ident.name { - sym::field_of => Some(this.parse_ty_field_of(lo)?), - _ => None, - }) - }) - } + pub(crate) fn parse_ty_field_of(&mut self, lo: Span) -> PResult<'a, TyKind> { + self.expect(exp!(OpenParen))?; - pub(crate) fn parse_ty_field_of(&mut self, _lo: Span) -> PResult<'a, TyKind> { let container = self.parse_ty()?; self.expect(exp!(Comma))?; @@ -844,30 +837,36 @@ impl<'a> Parser<'a> { if let Err(mut e) = self.expect_one_of(&[], &[exp!(CloseParen)]) { if trailing_comma { - e.note("unexpected third argument to field_of"); + e.note("unexpected third argument to `field_of`"); } else { - e.note("field_of expects dot-separated field and variant names"); + e.note("`field_of` expects dot-separated field and variant names"); } e.emit(); } - // Eat tokens until the macro call ends. + // Eat tokens until the construct ends. if self.may_recover() { while !self.token.kind.is_close_delim_or_eof() { self.bump(); } } + // FIXME: Odd not to include the closing paren (contrary to the leading one etc.) but + // it actually "improves" diagnostics slightly by not pointing into the wrapper macros. + let span = self.token.span; + self.expect(exp!(CloseParen))?; + + self.psess.gated_spans.gate(sym::internal_syntax, lo.to(self.token.span)); + match *fields { - [] => Err(self.dcx().struct_span_err( - self.token.span, - "`field_of!` expects dot-separated field and variant names", - )), + [] => Err(self + .dcx() + .struct_span_err(span, "`field_of` expects dot-separated field and variant names")), [field] => Ok(TyKind::FieldOf(container, None, field)), [variant, field] => Ok(TyKind::FieldOf(container, Some(variant), field)), _ => Err(self.dcx().struct_span_err( fields.iter().map(|f| f.span).collect::>(), - "`field_of!` only supports a single field or a variant with a field", + "`field_of` only supports a single field or a variant with a field", )), } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 6f078fef4892b..6c0a9cab34f8e 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -125,17 +125,22 @@ symbols! { // Matching predicates: `is_weak` // tidy-alphabetical-start Auto: "auto", - Builtin: "builtin", Catch: "catch", ContractEnsures: "contract_ensures", ContractRequires: "contract_requires", Default: "default", + Deref: "deref", + FieldOf: "field_of", MacroRules: "macro_rules", + OffsetOf: "offset_of", Pin: "pin", Raw: "raw", Reuse: "reuse", Safe: "safe", + TypeAscribe: "type_ascribe", Union: "union", + UnwrapBinder: "unwrap_binder", + WrapBinder: "wrap_binder", Yeet: "yeet", // tidy-alphabetical-end } @@ -580,7 +585,6 @@ symbols! { bridge, bswap, built, - builtin_syntax, bundle, c_dash_variadic, c_str_literals, @@ -828,7 +832,6 @@ symbols! { deprecated, deprecated_safe, deprecated_suggestion, - deref, deref_method, deref_mut, deref_patterns, @@ -990,7 +993,6 @@ symbols! { field, field_base, field_init_shorthand, - field_of, field_offset, field_projections, field_representing_type, @@ -1173,6 +1175,7 @@ symbols! { integral, internal_eq_trait_method_impls, internal_features, + internal_syntax, interrupt, into_async_iter_into_iter, into_future, @@ -1507,7 +1510,6 @@ symbols! { offload_kernel, offload_region, offset, - offset_of, offset_of_enum, offset_of_nested, offset_of_slice, @@ -2204,7 +2206,6 @@ symbols! { ty, type_alias_enum_variants, type_alias_impl_trait, - type_ascribe, type_ascription, type_changing_struct_update, type_id, @@ -2333,7 +2334,6 @@ symbols! { unwind_attributes, unwind_safe_trait, unwrap, - unwrap_binder, unwrap_or, update, use_cloned, @@ -2419,7 +2419,6 @@ symbols! { windows, windows_subsystem, with_negative_coherence, - wrap_binder, wrapping_add, wrapping_div, wrapping_mul, diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index a0e1267ed16e1..d4ff3af28ed7f 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -66,8 +66,8 @@ use rustc_middle::traits::PatternOriginExpr; use rustc_middle::ty::error::{ExpectedFound, TypeError, TypeErrorToStringExt}; use rustc_middle::ty::print::{PrintTraitRefExt as _, WrapBinderMode, with_forced_trimmed_paths}; use rustc_middle::ty::{ - self, List, Mutability, ParamEnv, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, - TypeVisitable, TypeVisitableExt, Unnormalized, + self, IsRigid, List, Mutability, ParamEnv, Region, Ty, TyCtxt, TypeFoldable, + TypeSuperVisitable, TypeVisitable, TypeVisitableExt, Unnormalized, }; use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Pos, Span, bug, sym}; use thin_vec::ThinVec; @@ -2479,6 +2479,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { /// with the other type. A TyVar inference type is compatible with any type, and an IntVar or /// FloatVar inference type are compatible with themselves or their concrete types (Int and /// Float types, respectively). When comparing two ADTs, these rules apply recursively. + /// Non-rigid aliases are treated just like TyVar since normalization can be ambiguous here. pub fn same_type_modulo_infer>>(&self, a: T, b: T) -> bool { let (a, b) = self.deeply_resolve_ignoring_regions((a, b)); SameTypeModuloInfer(self).relate(a, b).is_ok() @@ -2528,7 +2529,9 @@ impl<'tcx> TypeRelation> for SameTypeModuloInfer<'_, 'tcx> { ty::Float(_) | ty::Infer(ty::InferTy::FloatVar(_)), ) | (ty::Infer(ty::InferTy::TyVar(_)), _) - | (_, ty::Infer(ty::InferTy::TyVar(_))) => Ok(a), + | (_, ty::Infer(ty::InferTy::TyVar(_))) + | (ty::Alias(IsRigid::No, _), _) + | (_, ty::Alias(IsRigid::No, _)) => Ok(a), (ty::Infer(_), _) | (_, ty::Infer(_)) => Err(TypeError::Mismatch), _ => relate::structurally_relate_tys(self, a, b), } diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index c55c43e18d2bf..be07ff71ccf34 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -33,7 +33,7 @@ use thin_vec::{ThinVec, thin_vec}; use super::inspect::InferCtxtProofTreeExt; use crate::solve::inspect::{self, InspectConfig, ProofTreeVisitor}; -use crate::traits::{EvaluateConstErr, ObligationCause, sizedness_fast_path, specialization_graph}; +use crate::traits::{EvaluateConstErr, ObligationCause, implicit_fast_path, specialization_graph}; #[repr(transparent)] pub struct SolverDelegate<'tcx>(InferCtxt<'tcx>); @@ -178,7 +178,7 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< match self.0.tcx.as_lang_item(trait_pred.def_id()) { Some(LangItem::Sized) | Some(LangItem::MetaSized) => { let predicate = self.deeply_resolve_ignoring_regions(goal.predicate); - if sizedness_fast_path(self.tcx, predicate, goal.param_env) { + if implicit_fast_path(self.tcx, predicate, goal.param_env) { Outcome::TriviallyHolds } else { Outcome::NoFastPath diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 3a1ad2ee5feab..56e80958e6892 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -33,7 +33,7 @@ use crate::infer::InferCtxt; use crate::traits::normalize::normalize_with_depth_to; use crate::traits::project::{PolyProjectionObligation, ProjectionCacheKeyExt as _}; use crate::traits::query::evaluate_obligation::InferCtxtExt; -use crate::traits::{EvaluateConstErr, sizedness_fast_path}; +use crate::traits::{EvaluateConstErr, implicit_fast_path}; pub(crate) type PendingPredicateObligations<'tcx> = ThinVec>; @@ -398,7 +398,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { let infcx = self.selcx.infcx; if !infcx.disable_trait_solver_fast_paths() - && sizedness_fast_path(infcx.tcx, obligation.predicate, obligation.param_env) + && implicit_fast_path(infcx.tcx, obligation.predicate, obligation.param_env) { return ProcessResult::Changed(thin_vec![]); } diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 7076ec99c141c..326710007564c 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -66,7 +66,7 @@ pub use self::specialize::{ pub use self::structural_normalize::StructurallyNormalizeExt; pub use self::util::{ BoundVarReplacer, PlaceholderReplacer, elaborate, expand_trait_aliases, impl_item_is_final, - sizedness_fast_path, supertrait_def_ids, supertraits, transitive_bounds_that_define_assoc_item, + implicit_fast_path, supertrait_def_ids, supertraits, transitive_bounds_that_define_assoc_item, upcast_choices, with_replaced_escaping_bound_vars, }; use crate::error_reporting::InferCtxtErrorExt; diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs index 148f75e0a6308..b8c2a3078e8cb 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs @@ -6,7 +6,7 @@ use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt}; use crate::infer::InferCtxt; use crate::infer::canonical::{CanonicalQueryInput, CanonicalQueryResponse}; -use crate::traits::{ObligationCtxt, sizedness_fast_path}; +use crate::traits::{ObligationCtxt, implicit_fast_path}; impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> { type QueryResponse = (); @@ -15,7 +15,7 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> { infcx: &InferCtxt<'tcx>, key: &ParamEnvAnd<'tcx, Self>, ) -> Option { - if sizedness_fast_path(infcx.tcx, key.value.predicate, key.param_env) { + if implicit_fast_path(infcx.tcx, key.value.predicate, key.param_env) { return Some(()); } diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 8a770bea8468b..0d497fe86cf44 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -15,8 +15,8 @@ use rustc_hir::{self as hir, CoroutineDesugaring, CoroutineKind}; use rustc_infer::traits::{Obligation, PolyTraitObligation, PredicateObligation, SelectionError}; use rustc_middle::ty::fast_reject::DeepRejectCtxt; use rustc_middle::ty::{ - self, ExistentialPredicate, FieldInfo, SizedTraitKind, TraitRef, Ty, TypeVisitableExt, - elaborate, + self, ExistentialPredicate, FieldInfo, IncludeSizedImplicitBounds, SizedTraitKind, TraitRef, + Ty, TypeVisitableExt, elaborate, }; use rustc_span::{DUMMY_SP, bug, span_bug}; use tracing::{debug, instrument, trace}; @@ -782,7 +782,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Backward compatibility for default auto traits. // Test: ui/traits/default_auto_traits/extern-types.rs - if self.tcx().is_default_trait(def_id) { + if self.tcx().is_implicit_trait(def_id, IncludeSizedImplicitBounds::No) { check_impls() } } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index e280184169844..279392221a33c 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -47,7 +47,7 @@ use crate::infer::{InferCtxt, InferOk, TypeFreshener}; use crate::solve::InferCtxtSelectExt as _; use crate::traits::normalize::{normalize_with_depth, normalize_with_depth_to}; use crate::traits::project::{ProjectAndUnifyResult, ProjectionCacheKeyExt}; -use crate::traits::{EvaluateConstErr, ProjectionCacheKey, effects, sizedness_fast_path}; +use crate::traits::{EvaluateConstErr, ProjectionCacheKey, effects, implicit_fast_path}; mod _match; mod candidate_assembly; @@ -537,7 +537,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } if !self.infcx.disable_trait_solver_fast_paths() - && sizedness_fast_path(self.tcx(), obligation.predicate, obligation.param_env) + && implicit_fast_path(self.tcx(), obligation.predicate, obligation.param_env) { return Ok(EvaluatedToOk); } diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index c60ebc4758ead..9cbb53c6f63bd 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -217,7 +217,7 @@ pub fn with_replaced_escaping_bound_vars< } } -pub fn sizedness_fast_path<'tcx>( +pub fn implicit_fast_path<'tcx>( tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tcx>, param_env: ty::ParamEnv<'tcx>, diff --git a/compiler/rustc_traits/src/evaluate_obligation.rs b/compiler/rustc_traits/src/evaluate_obligation.rs index 6bc6543a0a01b..ac5df8b93f482 100644 --- a/compiler/rustc_traits/src/evaluate_obligation.rs +++ b/compiler/rustc_traits/src/evaluate_obligation.rs @@ -5,7 +5,7 @@ use rustc_span::DUMMY_SP; use rustc_trait_selection::traits::query::CanonicalPredicateGoal; use rustc_trait_selection::traits::{ EvaluationResult, Obligation, ObligationCause, OverflowError, SelectionContext, TraitQueryMode, - sizedness_fast_path, + implicit_fast_path, }; use tracing::debug; @@ -24,7 +24,7 @@ fn evaluate_obligation<'tcx>( debug!("evaluate_obligation: goal={:#?}", goal); let ParamEnvAnd { param_env, value: predicate } = goal; - if !tcx.disable_trait_solver_fast_paths() && sizedness_fast_path(tcx, predicate, param_env) { + if !tcx.disable_trait_solver_fast_paths() && implicit_fast_path(tcx, predicate, param_env) { return Ok(EvaluationResult::EvaluatedToOk); } diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs index 7aa3d87328fe7..edcc0082a942f 100644 --- a/compiler/rustc_type_ir/src/canonical.rs +++ b/compiler/rustc_type_ir/src/canonical.rs @@ -317,7 +317,7 @@ pub struct CanonicalParamEnvCacheEntry { pub param_env: I::ParamEnv, pub variables: Vec, pub variable_lookup_table: HashMap, - pub var_kinds: Vec>, + pub var_kinds: I::CanonicalVarKinds, } /// State used and modified by a canonicalizer during canonicalization. To avoid many allocations, diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index be0114b8f3af3..4de18651b3520 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -461,6 +461,12 @@ pub trait Interner: fn is_default_trait(self, def_id: Self::TraitId) -> bool; + fn is_implicit_trait( + self, + def_id: Self::TraitId, + including_sized: IncludeSizedImplicitBounds, + ) -> bool; + fn is_sizedness_trait(self, def_id: Self::TraitId) -> bool; fn as_projection_lang_item( @@ -786,3 +792,8 @@ impl search_graph::Cx for I { self.assert_evaluation_is_concurrent() } } + +pub enum IncludeSizedImplicitBounds { + Yes, + No, +} diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs index 53afc311cc623..e300b94cbc438 100644 --- a/compiler/rustc_type_ir/src/solve/mod.rs +++ b/compiler/rustc_type_ir/src/solve/mod.rs @@ -461,9 +461,8 @@ pub enum CandidatePreferenceMode { impl CandidatePreferenceMode { /// Given `trait_def_id`, which candidate preference mode should be used? pub fn compute(cx: I, trait_id: I::TraitId) -> CandidatePreferenceMode { - let is_sizedness_or_auto_or_default_goal = cx.is_sizedness_trait(trait_id) - || cx.trait_is_auto(trait_id) - || cx.is_default_trait(trait_id); + let is_sizedness_or_auto_or_default_goal = cx.trait_is_auto(trait_id) + || cx.is_implicit_trait(trait_id, ty::IncludeSizedImplicitBounds::Yes); if is_sizedness_or_auto_or_default_goal { CandidatePreferenceMode::Marker } else { diff --git a/library/core/src/field.rs b/library/core/src/field.rs index 5a8ae7759bc1e..b17a78846ce2a 100644 --- a/library/core/src/field.rs +++ b/library/core/src/field.rs @@ -124,7 +124,7 @@ impl Ord /// The container type may be a tuple, `struct`, `union` or `enum`. In the case of an enum, the /// variant must also be specified. Only a single field is supported. #[unstable(feature = "field_projections", issue = "145383")] -#[allow_internal_unstable(field_representing_type_raw, builtin_syntax)] +#[allow_internal_unstable(field_representing_type_raw, internal_syntax)] #[diagnostic::on_unmatched_args( note = "this macro expects a container type and a field path, like `field_of!(Type, field)` or `field_of!(Enum, Variant.field)`" )] @@ -134,7 +134,7 @@ impl Ord // it to `FieldRepresentingType<...>`. Thus stabilizing this requires careful thought about the // completeness of the trait impls for `FieldRepresentingType`. pub macro field_of($Container:ty, $($fields:expr)+ $(,)?) { - builtin # field_of($Container, $($fields)+) + k#field_of($Container, $($fields)+) } /// Type representing a field of a `struct`, `union`, `enum` variant or tuple. diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 36a19f89e58cd..67c216053f7b1 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -129,6 +129,7 @@ #![feature(f128)] #![feature(field_projections)] #![feature(final_associated_functions)] +#![feature(forced_keywords)] #![feature(freeze_impls)] #![feature(fundamental)] #![feature(impl_restriction)] diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 3b378078d3284..789119fb20052 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1907,7 +1907,7 @@ pub(crate) mod builtin { } /// Unstable placeholder for type ascription. - #[allow_internal_unstable(builtin_syntax)] + #[allow_internal_unstable(internal_syntax)] #[unstable( feature = "type_ascription", issue = "101728", @@ -1915,11 +1915,11 @@ pub(crate) mod builtin { )] #[diagnostic::opaque] pub macro type_ascribe($expr:expr, $ty:ty) { - builtin # type_ascribe($expr, $ty) + k#type_ascribe($expr, $ty) } /// Unstable placeholder for deref patterns. - #[allow_internal_unstable(builtin_syntax)] + #[allow_internal_unstable(internal_syntax)] #[unstable( feature = "deref_patterns", issue = "87121", @@ -1927,7 +1927,7 @@ pub(crate) mod builtin { )] #[diagnostic::opaque] pub macro deref($pat:pat) { - builtin # deref($pat) + k#deref($pat) } /// Derive macro generating an impl of the trait `From`. diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index b38557779092c..39b07963fb9a9 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -1664,10 +1664,10 @@ impl SizedTypeProperties for T {} note = "this macro expects a container type and a (nested) field path, like `offset_of!(Type, field)`" )] #[doc(alias = "memoffset")] -#[allow_internal_unstable(builtin_syntax, core_intrinsics)] +#[allow_internal_unstable(core_intrinsics, internal_syntax)] #[diagnostic::opaque] pub macro offset_of($Container:ty, $($fields:expr)+ $(,)?) { - const { builtin # offset_of($Container, $($fields)+) } + const { k#offset_of($Container, $($fields)+) } } /// Create a fresh instance of the inhabited ZST type `T`. diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index b5c4636cbb384..054f44cf94cba 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -393,11 +393,14 @@ impl *const T { /// `count` is in units of **bytes**. /// /// This is purely a convenience for casting to a `u8` pointer and - /// using [offset][pointer::offset] on it. See that method for documentation - /// and safety requirements. + /// using [offset][pointer::offset] on it. /// /// For non-`Sized` pointees this operation changes only the data pointer, /// leaving the metadata untouched. + /// + /// # Safety + /// + /// See [offset][pointer::offset] for documentation and safety requirements. #[must_use] #[inline(always)] #[stable(feature = "pointer_byte_offsets", since = "1.75.0")] @@ -626,11 +629,14 @@ impl *const T { /// units of **bytes**. /// /// This is purely a convenience for casting to a `u8` pointer and - /// using [`offset_from`][pointer::offset_from] on it. See that method for - /// documentation and safety requirements. + /// using [`offset_from`][pointer::offset_from] on it. /// /// For non-`Sized` pointees this operation considers only the data pointers, /// ignoring the metadata. + /// + /// # Safety + /// + /// See [`offset_from`][pointer::offset_from] for documentation and safety requirements. #[inline(always)] #[stable(feature = "pointer_byte_offsets", since = "1.75.0")] #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")] @@ -738,10 +744,13 @@ impl *const T { /// /// This is purely a convenience for casting to a `u8` pointer and /// using [`offset_from_unsigned`][pointer::offset_from_unsigned] on it. - /// See that method for documentation and safety requirements. /// /// For non-`Sized` pointees this operation considers only the data pointers, /// ignoring the metadata. + /// + /// # Safety + /// + /// See [`offset_from_unsigned`][pointer::offset_from_unsigned] for documentation and safety requirements. #[stable(feature = "ptr_sub_ptr", since = "1.87.0")] #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "1.87.0")] #[inline] @@ -875,11 +884,14 @@ impl *const T { /// `count` is in units of bytes. /// /// This is purely a convenience for casting to a `u8` pointer and - /// using [add][pointer::add] on it. See that method for documentation - /// and safety requirements. + /// using [add][pointer::add] on it. /// /// For non-`Sized` pointees this operation changes only the data pointer, /// leaving the metadata untouched. + /// + /// # Safety + /// + /// See [add][pointer::add] for documentation and safety requirements. #[must_use] #[inline(always)] #[stable(feature = "pointer_byte_offsets", since = "1.75.0")] @@ -960,11 +972,14 @@ impl *const T { /// `count` is in units of bytes. /// /// This is purely a convenience for casting to a `u8` pointer and - /// using [sub][pointer::sub] on it. See that method for documentation - /// and safety requirements. + /// using [sub][pointer::sub] on it. /// /// For non-`Sized` pointees this operation changes only the data pointer, /// leaving the metadata untouched. + /// + /// # Safety + /// + /// See [sub][pointer::sub] for documentation and safety requirements. #[must_use] #[inline(always)] #[stable(feature = "pointer_byte_offsets", since = "1.75.0")] @@ -1137,6 +1152,8 @@ impl *const T { /// Reads the value from `self` without moving it. This leaves the /// memory in `self` unchanged. /// + /// # Safety + /// /// See [`ptr::read`] for safety concerns and examples. /// /// [`ptr::read`]: crate::ptr::read() @@ -1159,6 +1176,8 @@ impl *const T { /// to not be elided or reordered by the compiler across other volatile /// operations. /// + /// # Safety + /// /// See [`ptr::read_volatile`] for safety concerns and examples. /// /// [`ptr::read_volatile`]: crate::ptr::read_volatile() @@ -1179,6 +1198,8 @@ impl *const T { /// /// Unlike `read`, the pointer may be unaligned. /// + /// # Safety + /// /// See [`ptr::read_unaligned`] for safety concerns and examples. /// /// [`ptr::read_unaligned`]: crate::ptr::read_unaligned() @@ -1199,6 +1220,8 @@ impl *const T { /// /// NOTE: this has the *same* argument order as [`ptr::copy`]. /// + /// # Safety + /// /// See [`ptr::copy`] for safety concerns and examples. /// /// [`ptr::copy`]: crate::ptr::copy() @@ -1219,6 +1242,8 @@ impl *const T { /// /// NOTE: this has the *same* argument order as [`ptr::copy_nonoverlapping`]. /// + /// # Safety + /// /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples. /// /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping() @@ -1494,6 +1519,8 @@ impl *const [T] { /// Returns a raw pointer to an element or subslice, without doing bounds /// checking. /// + /// # Safety + /// /// Calling this method with an [out-of-bounds index] or when `self` is not dereferenceable /// is *[undefined behavior]* even if the resulting pointer is not used. /// diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 080ee6b61a4ab..926d03892ad0d 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -397,11 +397,14 @@ impl *mut T { /// `count` is in units of **bytes**. /// /// This is purely a convenience for casting to a `u8` pointer and - /// using [offset][pointer::offset] on it. See that method for documentation - /// and safety requirements. + /// using [offset][pointer::offset] on it. /// /// For non-`Sized` pointees this operation changes only the data pointer, /// leaving the metadata untouched. + /// + /// # Safety + /// + /// See [offset][pointer::offset] for documentation and safety requirements. #[must_use] #[inline(always)] #[stable(feature = "pointer_byte_offsets", since = "1.75.0")] @@ -806,11 +809,14 @@ impl *mut T { /// units of **bytes**. /// /// This is purely a convenience for casting to a `u8` pointer and - /// using [`offset_from`][pointer::offset_from] on it. See that method for - /// documentation and safety requirements. + /// using [`offset_from`][pointer::offset_from] on it. /// /// For non-`Sized` pointees this operation considers only the data pointers, /// ignoring the metadata. + /// + /// # Safety + /// + /// See [`offset_from`][pointer::offset_from] for documentation and safety requirements. #[inline(always)] #[stable(feature = "pointer_byte_offsets", since = "1.75.0")] #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")] @@ -897,10 +903,13 @@ impl *mut T { /// /// This is purely a convenience for casting to a `u8` pointer and /// using [`offset_from_unsigned`][pointer::offset_from_unsigned] on it. - /// See that method for documentation and safety requirements. /// /// For non-`Sized` pointees this operation considers only the data pointers, /// ignoring the metadata. + /// + /// # Safety + /// + /// See [`offset_from_unsigned`][pointer::offset_from_unsigned] for documentation and safety requirements. #[stable(feature = "ptr_sub_ptr", since = "1.87.0")] #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "1.87.0")] #[inline] @@ -974,11 +983,14 @@ impl *mut T { /// `count` is in units of bytes. /// /// This is purely a convenience for casting to a `u8` pointer and - /// using [add][pointer::add] on it. See that method for documentation - /// and safety requirements. + /// using [add][pointer::add] on it. /// /// For non-`Sized` pointees this operation changes only the data pointer, /// leaving the metadata untouched. + /// + /// # Safety + /// + /// See [`add`][pointer::add] for documentation and safety requirements. #[must_use] #[inline(always)] #[stable(feature = "pointer_byte_offsets", since = "1.75.0")] @@ -1059,11 +1071,14 @@ impl *mut T { /// `count` is in units of bytes. /// /// This is purely a convenience for casting to a `u8` pointer and - /// using [sub][pointer::sub] on it. See that method for documentation - /// and safety requirements. + /// using [sub][pointer::sub] on it. /// /// For non-`Sized` pointees this operation changes only the data pointer, /// leaving the metadata untouched. + /// + /// # Safety + /// + /// See [`sub`][pointer::sub] for documentation and safety requirements. #[must_use] #[inline(always)] #[stable(feature = "pointer_byte_offsets", since = "1.75.0")] @@ -1230,6 +1245,8 @@ impl *mut T { /// Reads the value from `self` without moving it. This leaves the /// memory in `self` unchanged. /// + /// # Safety + /// /// See [`ptr::read`] for safety concerns and examples. /// /// [`ptr::read`]: crate::ptr::read() @@ -1252,6 +1269,8 @@ impl *mut T { /// to not be elided or reordered by the compiler across other volatile /// operations. /// + /// # Safety + /// /// See [`ptr::read_volatile`] for safety concerns and examples. /// /// [`ptr::read_volatile`]: crate::ptr::read_volatile() @@ -1272,6 +1291,8 @@ impl *mut T { /// /// Unlike `read`, the pointer may be unaligned. /// + /// # Safety + /// /// See [`ptr::read_unaligned`] for safety concerns and examples. /// /// [`ptr::read_unaligned`]: crate::ptr::read_unaligned() @@ -1292,6 +1313,8 @@ impl *mut T { /// /// NOTE: this has the *same* argument order as [`ptr::copy`]. /// + /// # Safety + /// /// See [`ptr::copy`] for safety concerns and examples. /// /// [`ptr::copy`]: crate::ptr::copy() @@ -1312,6 +1335,8 @@ impl *mut T { /// /// NOTE: this has the *same* argument order as [`ptr::copy_nonoverlapping`]. /// + /// # Safety + /// /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples. /// /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping() @@ -1332,6 +1357,8 @@ impl *mut T { /// /// NOTE: this has the *opposite* argument order of [`ptr::copy`]. /// + /// # Safety + /// /// See [`ptr::copy`] for safety concerns and examples. /// /// [`ptr::copy`]: crate::ptr::copy() @@ -1352,6 +1379,8 @@ impl *mut T { /// /// NOTE: this has the *opposite* argument order of [`ptr::copy_nonoverlapping`]. /// + /// # Safety + /// /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples. /// /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping() @@ -1369,6 +1398,8 @@ impl *mut T { /// Executes the destructor (if any) of the pointed-to value. /// + /// # Safety + /// /// See [`ptr::drop_in_place`] for safety concerns and examples. /// /// [`ptr::drop_in_place`]: crate::ptr::drop_in_place() @@ -1387,6 +1418,8 @@ impl *mut T { /// Overwrites a memory location with the given value without reading or /// dropping the old value. /// + /// # Safety + /// /// See [`ptr::write`] for safety concerns and examples. /// /// [`ptr::write`]: crate::ptr::write() @@ -1405,6 +1438,8 @@ impl *mut T { /// Invokes memset on the specified pointer, setting `count * size_of::()` /// bytes of memory starting at `self` to `val`. /// + /// # Safety + /// /// See [`ptr::write_bytes`] for safety concerns and examples. /// /// [`ptr::write_bytes`]: crate::ptr::write_bytes() @@ -1428,6 +1463,8 @@ impl *mut T { /// to not be elided or reordered by the compiler across other volatile /// operations. /// + /// # Safety + /// /// See [`ptr::write_volatile`] for safety concerns and examples. /// /// [`ptr::write_volatile`]: crate::ptr::write_volatile() @@ -1448,6 +1485,8 @@ impl *mut T { /// /// Unlike `write`, the pointer may be unaligned. /// + /// # Safety + /// /// See [`ptr::write_unaligned`] for safety concerns and examples. /// /// [`ptr::write_unaligned`]: crate::ptr::write_unaligned() @@ -1466,6 +1505,8 @@ impl *mut T { /// Replaces the value at `self` with `src`, returning the old /// value, without dropping either. /// + /// # Safety + /// /// See [`ptr::replace`] for safety concerns and examples. /// /// [`ptr::replace`]: crate::ptr::replace() @@ -1484,6 +1525,8 @@ impl *mut T { /// deinitializing either. They may overlap, unlike `mem::swap` which is /// otherwise equivalent. /// + /// # Safety + /// /// See [`ptr::swap`] for safety concerns and examples. /// /// [`ptr::swap`]: crate::ptr::swap() @@ -1873,6 +1916,8 @@ impl *mut [T] { /// Returns a raw pointer to an element or subslice, without doing bounds /// checking. /// + /// # Safety + /// /// Calling this method with an [out-of-bounds index] or when `self` is not dereferenceable /// is *[undefined behavior]* even if the resulting pointer is not used. /// diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 36e4bc2f9286c..bc65d5ea836ac 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -575,11 +575,14 @@ impl NonNull { /// `count` is in units of **bytes**. /// /// This is purely a convenience for casting to a `u8` pointer and - /// using [offset][pointer::offset] on it. See that method for documentation - /// and safety requirements. + /// using [offset][pointer::offset] on it. /// /// For non-`Sized` pointees this operation changes only the data pointer, /// leaving the metadata untouched. + /// + /// # Safety + /// + /// See [offset][pointer::offset] for documentation and safety requirements. #[must_use] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -630,11 +633,14 @@ impl NonNull { /// `count` is in units of bytes. /// /// This is purely a convenience for casting to a `u8` pointer and - /// using [`add`][NonNull::add] on it. See that method for documentation - /// and safety requirements. + /// using [`add`][NonNull::add] on it. /// /// For non-`Sized` pointees this operation changes only the data pointer, /// leaving the metadata untouched. + /// + /// # Safety + /// + /// See [`add`][NonNull::add] for documentation and safety requirements. #[must_use] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -690,11 +696,14 @@ impl NonNull { /// `count` is in units of bytes. /// /// This is purely a convenience for casting to a `u8` pointer and - /// using [`sub`][NonNull::sub] on it. See that method for documentation - /// and safety requirements. + /// using [`sub`][NonNull::sub] on it. /// /// For non-`Sized` pointees this operation changes only the data pointer, /// leaving the metadata untouched. + /// + /// # Safety + /// + /// See [`sub`][NonNull::sub] for documentation and safety requirements. #[must_use] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -809,11 +818,14 @@ impl NonNull { /// units of **bytes**. /// /// This is purely a convenience for casting to a `u8` pointer and - /// using [`offset_from`][NonNull::offset_from] on it. See that method for - /// documentation and safety requirements. + /// using [`offset_from`][NonNull::offset_from] on it. /// /// For non-`Sized` pointees this operation considers only the data pointers, /// ignoring the metadata. + /// + /// # Safety + /// + /// See [`offset_from`][NonNull::offset_from] for documentation and safety requirements. #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[stable(feature = "non_null_convenience", since = "1.80.0")] @@ -902,10 +914,13 @@ impl NonNull { /// /// This is purely a convenience for casting to a `u8` pointer and /// using [`offset_from_unsigned`][NonNull::offset_from_unsigned] on it. - /// See that method for documentation and safety requirements. /// /// For non-`Sized` pointees this operation considers only the data pointers, /// ignoring the metadata. + /// + /// # Safety + /// + /// See [`offset_from_unsigned`][NonNull::offset_from_unsigned] for documentation and safety requirements. #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[stable(feature = "ptr_sub_ptr", since = "1.87.0")] @@ -918,6 +933,8 @@ impl NonNull { /// Reads the value from `self` without moving it. This leaves the /// memory in `self` unchanged. /// + /// # Safety + /// /// See [`ptr::read`] for safety concerns and examples. /// /// [`ptr::read`]: crate::ptr::read() @@ -940,6 +957,8 @@ impl NonNull { /// to not be elided or reordered by the compiler across other volatile /// operations. /// + /// # Safety + /// /// See [`ptr::read_volatile`] for safety concerns and examples. /// /// [`ptr::read_volatile`]: crate::ptr::read_volatile() @@ -960,6 +979,8 @@ impl NonNull { /// /// Unlike `read`, the pointer may be unaligned. /// + /// # Safety + /// /// See [`ptr::read_unaligned`] for safety concerns and examples. /// /// [`ptr::read_unaligned`]: crate::ptr::read_unaligned() @@ -980,6 +1001,8 @@ impl NonNull { /// /// NOTE: this has the *same* argument order as [`ptr::copy`]. /// + /// # Safety + /// /// See [`ptr::copy`] for safety concerns and examples. /// /// [`ptr::copy`]: crate::ptr::copy() @@ -1000,6 +1023,8 @@ impl NonNull { /// /// NOTE: this has the *same* argument order as [`ptr::copy_nonoverlapping`]. /// + /// # Safety + /// /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples. /// /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping() @@ -1020,6 +1045,8 @@ impl NonNull { /// /// NOTE: this has the *opposite* argument order of [`ptr::copy`]. /// + /// # Safety + /// /// See [`ptr::copy`] for safety concerns and examples. /// /// [`ptr::copy`]: crate::ptr::copy() @@ -1040,6 +1067,8 @@ impl NonNull { /// /// NOTE: this has the *opposite* argument order of [`ptr::copy_nonoverlapping`]. /// + /// # Safety + /// /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples. /// /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping() @@ -1057,6 +1086,8 @@ impl NonNull { /// Executes the destructor (if any) of the pointed-to value. /// + /// # Safety + /// /// See [`ptr::drop_in_place`] for safety concerns and examples. /// /// [`ptr::drop_in_place`]: crate::ptr::drop_in_place() @@ -1074,6 +1105,8 @@ impl NonNull { /// Overwrites a memory location with the given value without reading or /// dropping the old value. /// + /// # Safety + /// /// See [`ptr::write`] for safety concerns and examples. /// /// [`ptr::write`]: crate::ptr::write() @@ -1092,6 +1125,8 @@ impl NonNull { /// Invokes memset on the specified pointer, setting `count * size_of::()` /// bytes of memory starting at `self` to `val`. /// + /// # Safety + /// /// See [`ptr::write_bytes`] for safety concerns and examples. /// /// [`ptr::write_bytes`]: crate::ptr::write_bytes() @@ -1115,6 +1150,8 @@ impl NonNull { /// to not be elided or reordered by the compiler across other volatile /// operations. /// + /// # Safety + /// /// See [`ptr::write_volatile`] for safety concerns and examples. /// /// [`ptr::write_volatile`]: crate::ptr::write_volatile() @@ -1135,6 +1172,8 @@ impl NonNull { /// /// Unlike `write`, the pointer may be unaligned. /// + /// # Safety + /// /// See [`ptr::write_unaligned`] for safety concerns and examples. /// /// [`ptr::write_unaligned`]: crate::ptr::write_unaligned() @@ -1153,6 +1192,8 @@ impl NonNull { /// Replaces the value at `self` with `src`, returning the old /// value, without dropping either. /// + /// # Safety + /// /// See [`ptr::replace`] for safety concerns and examples. /// /// [`ptr::replace`]: crate::ptr::replace() @@ -1171,6 +1212,8 @@ impl NonNull { /// deinitializing either. They may overlap, unlike `mem::swap` which is /// otherwise equivalent. /// + /// # Safety + /// /// See [`ptr::swap`] for safety concerns and examples. /// /// [`ptr::swap`]: crate::ptr::swap() @@ -1586,6 +1629,8 @@ impl NonNull<[T]> { /// Returns a raw pointer to an element or subslice, without doing bounds /// checking. /// + /// # Safety + /// /// Calling this method with an [out-of-bounds index] or when `self` is not dereferenceable /// is *[undefined behavior]* even if the resulting pointer is not used. /// diff --git a/library/core/src/unsafe_binder.rs b/library/core/src/unsafe_binder.rs index 3d2a04e95f078..bb7144fc5dddd 100644 --- a/library/core/src/unsafe_binder.rs +++ b/library/core/src/unsafe_binder.rs @@ -1,27 +1,17 @@ //! Operators used to turn types into unsafe binders and back. /// Unwrap an unsafe binder into its underlying type. -#[allow_internal_unstable(builtin_syntax)] +#[allow_internal_unstable(internal_syntax)] #[unstable(feature = "unsafe_binders", issue = "130516")] #[diagnostic::opaque] -pub macro unwrap_binder { - ($expr:expr) => { - builtin # unwrap_binder ( $expr ) - }, - ($expr:expr ; $ty:ty) => { - builtin # unwrap_binder ( $expr, $ty ) - }, +pub macro unwrap_binder($expr:expr $( ; $ty:ty )?) { + k#unwrap_binder($expr $( , $ty )?) } /// Wrap a type into an unsafe binder. -#[allow_internal_unstable(builtin_syntax)] +#[allow_internal_unstable(internal_syntax)] #[unstable(feature = "unsafe_binders", issue = "130516")] #[diagnostic::opaque] -pub macro wrap_binder { - ($expr:expr) => { - builtin # wrap_binder ( $expr ) - }, - ($expr:expr ; $ty:ty) => { - builtin # wrap_binder ( $expr, $ty ) - }, +pub macro wrap_binder($expr:expr $( ; $ty:ty )?) { + k#wrap_binder($expr $( , $ty )?) } diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 8ed3a46bf3189..cd3fc8fda587b 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -287,7 +287,6 @@ #![feature(doc_masked)] #![feature(doc_notable_trait)] #![feature(dropck_eyepatch)] -#![feature(exact_div)] #![feature(f16)] #![feature(f128)] #![feature(ffi_const)] diff --git a/library/std/src/sys/paths/unix.rs b/library/std/src/sys/paths/unix.rs index cee799c36c79b..756c5ec26f127 100644 --- a/library/std/src/sys/paths/unix.rs +++ b/library/std/src/sys/paths/unix.rs @@ -253,37 +253,14 @@ pub fn current_exe() -> io::Result { #[cfg(target_os = "openbsd")] pub fn current_exe() -> io::Result { + let mut path = vec![0u8; libc::PATH_MAX as usize]; unsafe { - let mut mib = [libc::CTL_KERN, libc::KERN_PROC_ARGS, libc::getpid(), libc::KERN_PROC_ARGV]; - let mib = mib.as_mut_ptr(); - - // Determine the required size (in bytes) for the argument array ... - let mut argv_size = 0; - cvt(libc::sysctl(mib, 4, ptr::null_mut(), &mut argv_size, ptr::null_mut(), 0))?; - - // ... allocate a buffer for it ... - let argc = argv_size.div_exact(size_of::<*const libc::c_char>()).unwrap(); - let mut argv = Vec::<*const libc::c_char>::with_capacity(argc); - - // ... and retrieve the argument array. - cvt(libc::sysctl(mib, 4, argv.as_mut_ptr() as *mut _, &mut argv_size, ptr::null_mut(), 0))?; - let argc = argv_size.div_exact(size_of::<*const libc::c_char>()).unwrap(); - argv.set_len(argc); - - if argv[0].is_null() { - return Err(io::const_error!(io::ErrorKind::Uncategorized, "no current exe available")); - } - let argv0 = CStr::from_ptr(argv[0]).to_bytes(); - if argv0.iter().any(|b| *b == b'/') { - // The program name is path-like, so try to canonicalize it. - crate::fs::canonicalize(OsStr::from_bytes(argv0)) - } else { - // The program was probably found in the PATH. Instead of trying to - // find it again (which might not succeed if PATH has changed), just - // return the program name – this function is best-effort anyway. - Ok(PathBuf::from(OsStr::from_bytes(argv0))) - } + cvt(libc::getexecpath(path.as_mut_ptr().cast(), path.len()))?; + // SAFETY: getexecpath(3) NUL-terminates the buffer on success. + let len = CStr::from_ptr(path.as_ptr().cast()).count_bytes(); + path.truncate(len); } + Ok(PathBuf::from(OsString::from_vec(path))) } #[cfg(any( diff --git a/library/std/src/sys/thread_local/guard/aix.rs b/library/std/src/sys/thread_local/guard/aix.rs new file mode 100644 index 0000000000000..9b945456bf790 --- /dev/null +++ b/library/std/src/sys/thread_local/guard/aix.rs @@ -0,0 +1,30 @@ +//! AIX registers thread destructors using `__pt_atexit_np`. +//! Calling it registers a callback that runs on thread termination +//! and upon process exit (for the main thread). + +use crate::cell::Cell; +use crate::sys::thread_local::destructors; + +pub fn enable() { + #[thread_local] + static REGISTERED: Cell = Cell::new(false); + + unsafe extern "C" { + fn __pt_atexit_np(flags: i32, dtor: unsafe extern "C" fn(i32) -> i32) -> i32; + } + + if !REGISTERED.replace(true) { + let ret = unsafe { __pt_atexit_np(0, run_dtors) }; + if ret != 0 { + rtabort!("failed to register thread destructor"); + } + } + + unsafe extern "C" fn run_dtors(_: i32) -> i32 { + unsafe { + destructors::run(); + crate::rt::thread_cleanup(); + } + 0 + } +} diff --git a/library/std/src/sys/thread_local/mod.rs b/library/std/src/sys/thread_local/mod.rs index 5d3c23ce04678..1c137e52d9319 100644 --- a/library/std/src/sys/thread_local/mod.rs +++ b/library/std/src/sys/thread_local/mod.rs @@ -101,6 +101,10 @@ pub(crate) mod guard { mod apple; pub(crate) use apple::enable; } + all(target_thread_local, target_os = "aix") => { + mod aix; + pub(crate) use aix::enable; + } target_os = "windows" => { mod windows; pub(crate) use windows::enable; diff --git a/src/ci/docker/host-x86_64/test-x86_64-gnu-gcc/Dockerfile b/src/ci/docker/host-x86_64/test-x86_64-gnu-gcc/Dockerfile index d248faaabca6c..2a721006bfdc0 100644 --- a/src/ci/docker/host-x86_64/test-x86_64-gnu-gcc/Dockerfile +++ b/src/ci/docker/host-x86_64/test-x86_64-gnu-gcc/Dockerfile @@ -42,7 +42,7 @@ ENV RUST_CONFIGURE_ARGS="--build=x86_64-unknown-linux-gnu \ --set llvm.libzstd=true" ENV SCRIPT="python3 ../x.py \ --stage 2 \ - test tests \ + test tests compiler/rustc_codegen_gcc \ --test-codegen-backend gcc \ --skip tests/coverage \ --skip tests/coverage-run-rustdoc \ diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index dd5e307fdfca5..2dcf3d51fc509 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1821,7 +1821,7 @@ impl PrimitiveType { Char => sym::char, Array => sym::array, Pat => sym::pat, - FieldOf => sym::field_of, + FieldOf => kw::FieldOf, Slice => sym::slice, Tuple => sym::tuple, Unit => sym::unit, diff --git a/src/tools/clippy/clippy_lints/src/methods/should_implement_trait.rs b/src/tools/clippy/clippy_lints/src/methods/should_implement_trait.rs index c233fe3f28ed5..2536ad574239b 100644 --- a/src/tools/clippy/clippy_lints/src/methods/should_implement_trait.rs +++ b/src/tools/clippy/clippy_lints/src/methods/should_implement_trait.rs @@ -112,7 +112,7 @@ const TRAIT_METHODS: [ShouldImplTraitCase; 30] = [ ShouldImplTraitCase::new("std::clone::Clone", sym::clone, 1, SelfKind::Ref, OutType::Any, true, Edition2015), ShouldImplTraitCase::new("std::cmp::Ord", sym::cmp, 2, SelfKind::Ref, OutType::Any, true, Edition2015), ShouldImplTraitCase::new("std::default::Default", kw::Default, 0, SelfKind::No, OutType::Any, true, Edition2015), - ShouldImplTraitCase::new("std::ops::Deref", sym::deref, 1, SelfKind::Ref, OutType::Ref, true, Edition2015), + ShouldImplTraitCase::new("std::ops::Deref", kw::Deref, 1, SelfKind::Ref, OutType::Ref, true, Edition2015), ShouldImplTraitCase::new("std::ops::DerefMut", sym::deref_mut, 1, SelfKind::RefMut, OutType::Ref, true, Edition2015), ShouldImplTraitCase::new("std::ops::Div", sym::div, 2, SelfKind::Value, OutType::Any, true, Edition2015), ShouldImplTraitCase::new("std::ops::Drop", sym::drop, 1, SelfKind::RefMut, OutType::Unit, true, Edition2015), diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index 28c2740444822..6451595449046 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -1015,14 +1015,6 @@ impl Rewrite for ast::Ty { }) } ast::TyKind::CVarArgs => Ok("...".to_owned()), - ast::TyKind::FieldOf(ref ty, ref variant, ref field) => { - let ty = ty.rewrite_result(context, shape)?; - if let Some(variant) = variant { - Ok(format!("builtin # field_of({ty}, {variant}.{field})")) - } else { - Ok(format!("builtin # field_of({ty}, {field})")) - } - } ast::TyKind::UnsafeBinder(ref binder) => { let mut result = String::new(); if binder.generic_params.is_empty() { @@ -1049,7 +1041,10 @@ impl Rewrite for ast::Ty { result.push_str(&rewrite); Ok(result) } - ast::TyKind::Pat(..) | ast::TyKind::View(..) | ast::TyKind::GcaMacro(..) => { + ast::TyKind::FieldOf(..) + | ast::TyKind::GcaMacro(..) + | ast::TyKind::Pat(..) + | ast::TyKind::View(..) => { // These don't normally occur in the AST because macros aren't expanded. However, // rustfmt tries to parse macro arguments when formatting macros, so it's not // totally impossible for rustfmt to come across these nodes when formatting a file. diff --git a/src/tools/rustfmt/tests/target/field-representing-types.rs b/src/tools/rustfmt/tests/target/field-representing-types.rs index a31ccbfb461f2..c5b400c6b3442 100644 --- a/src/tools/rustfmt/tests/target/field-representing-types.rs +++ b/src/tools/rustfmt/tests/target/field-representing-types.rs @@ -1,2 +1,4 @@ -type FRT = builtin # field_of(Type, ident); -type FRT2 = builtin # field_of(Type, ident); +//@ rustfmt-edition: 2021 + +type FRT = k#field_of(Type, ident); +type FRT2 = k#field_of(Type, ident); diff --git a/src/tools/rustfmt/tests/target/issue-6105.rs b/src/tools/rustfmt/tests/target/issue-6105.rs index 1eb0ce89f7812..cb73fc6042e24 100644 --- a/src/tools/rustfmt/tests/target/issue-6105.rs +++ b/src/tools/rustfmt/tests/target/issue-6105.rs @@ -1 +1,3 @@ -const _: () = builtin # offset_of(x, x); +//@ rustfmt-edition: 2021 + +const _: () = k#offset_of(x, x); diff --git a/src/tools/rustfmt/tests/target/issue_6159.rs b/src/tools/rustfmt/tests/target/issue_6159.rs index 49fd539d3ef5a..35047aadcec6b 100644 --- a/src/tools/rustfmt/tests/target/issue_6159.rs +++ b/src/tools/rustfmt/tests/target/issue_6159.rs @@ -1,3 +1,5 @@ +//@ rustfmt-edition: 2021 + fn main() { - builtin # type_ascribe(10, usize) + k#type_ascribe(10, usize) } diff --git a/tests/assembly-llvm/cstring-merging.rs b/tests/assembly-llvm/cstring-merging.rs index 9c1af4ebb4c05..e198a49c52216 100644 --- a/tests/assembly-llvm/cstring-merging.rs +++ b/tests/assembly-llvm/cstring-merging.rs @@ -14,7 +14,7 @@ use std::ffi::CStr; #[unsafe(no_mangle)] static CSTR: &[u8; 4] = b"foo\0"; -// CHECK-NOT: .section +// CHECK: .section .rodata.str1.{{[12]}},"aMS" // CHECK: {{(\.L|\$)}}anon.{{.+}}: // CHECK-NEXT: .{{asciz|string}} "bar" #[unsafe(no_mangle)] diff --git a/tests/assembly-llvm/static-relocation-model.rs b/tests/assembly-llvm/static-relocation-model.rs index a47681f4532a9..66bc992219527 100644 --- a/tests/assembly-llvm/static-relocation-model.rs +++ b/tests/assembly-llvm/static-relocation-model.rs @@ -47,7 +47,8 @@ pub fn peach() -> u8 { // x64: movq EXOCHORDA{{(\(%[a-z0-9]+\))?}}, %[[REG:[a-z0-9]+]] // x64-NEXT: {{movb|movzbl}} (%[[REG]]), %{{[a-z0-9]+}} // A64: adrp [[REG2:[a-z0-9]+]], EXOCHORDA -// A64-NEXT: ldr {{[a-z0-9]+}}, {{\[}}[[REG2]], :lo12:EXOCHORDA] +// A64-NEXT: add [[REG2]], [[REG2]], :lo12:EXOCHORDA +// A64-NEXT: ldr {{[a-z0-9]+}}, {{\[}}[[REG2]]{{\]}} #[no_mangle] pub fn mango() -> u8 { unsafe { *EXOCHORDA } diff --git a/tests/codegen-llvm/async-fn-cold-attr.rs b/tests/codegen-llvm/async-fn-cold-attr.rs new file mode 100644 index 0000000000000..3f4925d9208d4 --- /dev/null +++ b/tests/codegen-llvm/async-fn-cold-attr.rs @@ -0,0 +1,51 @@ +// Checks that `#[cold]` on `async fn`s and async closures applies to the coroutine holding their +// body (i.e. the `Future::poll` implementation), in addition to the function or closure that +// constructs it. +// +//@ edition: 2024 +//@ compile-flags: -Cno-prepopulate-passes -Csymbol-mangling-version=v0 -Zinline-mir=no +#![crate_type = "lib"] +#![feature(stmt_expr_attributes)] + +use std::future::Future; +use std::pin::pin; +use std::task::Context; + +// CHECK: ; async_fn_cold_attr::cold{{$}} +// CHECK-NEXT: ; Function Attrs: cold +// CHECK: ; async_fn_cold_attr::cold::{closure#0} +// CHECK-NEXT: ; Function Attrs: cold +#[cold] +pub async fn cold() {} + +// CHECK: ; async_fn_cold_attr::not_cold::{closure#0} +// CHECK-NEXT: ; Function Attrs: +// CHECK-NOT: cold +// CHECK-SAME: {{$}} +pub async fn not_cold() {} + +pub struct S; + +impl S { + // CHECK: ; ::method{{$}} + // CHECK-NEXT: ; Function Attrs: cold + // CHECK: ; ::method::{closure#0} + // CHECK-NEXT: ; Function Attrs: cold + #[cold] + pub async fn method(&self) {} +} + +// CHECK: ; async_fn_cold_attr::poll_all{{$}} +pub fn poll_all(cx: &mut Context<'_>) { + let _ = pin!(cold()).poll(cx); + let _ = pin!(not_cold()).poll(cx); + let _ = pin!(S.method()).poll(cx); + + // CHECK: ; async_fn_cold_attr::poll_all::{closure#0}{{$}} + // CHECK-NEXT: ; Function Attrs: cold + // CHECK: ; async_fn_cold_attr::poll_all::{closure#0}::{closure#0}:: + // CHECK-NEXT: ; Function Attrs: cold + let closure = #[cold] + async || {}; + let _ = pin!(closure()).poll(cx); +} diff --git a/tests/codegen-llvm/async-fn-inline-always-target-feature.rs b/tests/codegen-llvm/async-fn-inline-always-target-feature.rs new file mode 100644 index 0000000000000..83e635c03a50d --- /dev/null +++ b/tests/codegen-llvm/async-fn-inline-always-target-feature.rs @@ -0,0 +1,32 @@ +// `#[inline(always)]` on an `async fn` applies to its body coroutine (#129347). Unlike a closure +// marked `#[inline(always)]`, that coroutine is never inlined into the function it was written +// in, so it must still inherit that function's `#[target_feature]`s. +// +//@ revisions: x86_64 aarch64 +//@[x86_64] only-x86_64 +//@[aarch64] only-aarch64 +//@ edition: 2024 +//@ compile-flags: -Cno-prepopulate-passes -Csymbol-mangling-version=v0 -Zinline-mir=no +#![crate_type = "lib"] + +use std::future::Future; +use std::pin::pin; +use std::task::{Context, Waker}; + +// CHECK: ; async_fn_inline_always_target_feature::always::{closure#0} +// CHECK-NEXT: ; Function Attrs: +// CHECK-NEXT: define {{.*}} #[[ATTRS:[0-9]+]] +#[inline(always)] +#[cfg_attr(target_arch = "x86_64", target_feature(enable = "avx2"))] +#[cfg_attr(target_arch = "aarch64", target_feature(enable = "sha3"))] +pub async fn always() {} + +#[cfg_attr(target_arch = "x86_64", target_feature(enable = "avx2"))] +#[cfg_attr(target_arch = "aarch64", target_feature(enable = "sha3"))] +pub fn poll_always() { + let mut cx = Context::from_waker(Waker::noop()); + let _ = pin!(always()).poll(&mut cx); +} + +// x86_64: attributes #[[ATTRS]] = {{{.*}}"target-features"="{{[^"]*}}+avx2 +// aarch64: attributes #[[ATTRS]] = {{{.*}}"target-features"="{{[^"]*}}+sha3 diff --git a/tests/codegen-llvm/async-fn-inline-attr.rs b/tests/codegen-llvm/async-fn-inline-attr.rs new file mode 100644 index 0000000000000..d97300dd6046c --- /dev/null +++ b/tests/codegen-llvm/async-fn-inline-attr.rs @@ -0,0 +1,71 @@ +// Checks that inline attributes on `async fn`s and async closures apply to the coroutine holding +// their body (i.e. the `Future::poll` implementation) rather than to the function or closure that +// merely constructs it. See #129347. +// +//@ edition: 2024 +//@ compile-flags: -Cno-prepopulate-passes -Csymbol-mangling-version=v0 -Zinline-mir=no +#![crate_type = "lib"] +#![feature(stmt_expr_attributes)] + +use std::future::Future; +use std::pin::pin; +use std::task::Context; + +// CHECK: ; async_fn_inline_attr::never{{$}} +// CHECK-NEXT: ; Function Attrs: +// CHECK-NOT: noinline +// CHECK-SAME: {{$}} +// CHECK: ; async_fn_inline_attr::never::{closure#0} +// CHECK-NEXT: ; Function Attrs: noinline +#[inline(never)] +pub async fn never() {} + +// CHECK: ; async_fn_inline_attr::always{{$}} +// CHECK-NEXT: ; Function Attrs: +// CHECK-NOT: alwaysinline +// CHECK-SAME: {{$}} +// CHECK: ; async_fn_inline_attr::always::{closure#0} +// CHECK-NEXT: ; Function Attrs: alwaysinline +#[inline(always)] +pub async fn always() {} + +// The body coroutine would get an inline hint regardless, like all closures. +// CHECK: ; async_fn_inline_attr::hint{{$}} +// CHECK-NEXT: ; Function Attrs: +// CHECK-NOT: inlinehint +// CHECK-SAME: {{$}} +// CHECK: ; async_fn_inline_attr::hint::{closure#0} +// CHECK-NEXT: ; Function Attrs: inlinehint +#[inline] +pub async fn hint() {} + +pub struct S; + +impl S { + // CHECK: ; ::method{{$}} + // CHECK-NEXT: ; Function Attrs: + // CHECK-NOT: noinline + // CHECK-SAME: {{$}} + // CHECK: ; ::method::{closure#0} + // CHECK-NEXT: ; Function Attrs: noinline + #[inline(never)] + pub async fn method(&self) {} +} + +// CHECK: ; async_fn_inline_attr::poll_all{{$}} +pub fn poll_all(cx: &mut Context<'_>) { + let _ = pin!(never()).poll(cx); + let _ = pin!(always()).poll(cx); + let _ = pin!(hint()).poll(cx); + let _ = pin!(S.method()).poll(cx); + + // CHECK: ; async_fn_inline_attr::poll_all::{closure#0}{{$}} + // CHECK-NEXT: ; Function Attrs: + // CHECK-NOT: noinline + // CHECK-SAME: {{$}} + // CHECK: ; async_fn_inline_attr::poll_all::{closure#0}::{closure#0}:: + // CHECK-NEXT: ; Function Attrs: noinline + let closure = #[inline(never)] + async || {}; + let _ = pin!(closure()).poll(cx); +} diff --git a/tests/codegen-llvm/debuginfo-generic-closure-env-names.rs b/tests/codegen-llvm/debuginfo-generic-closure-env-names.rs index 64bc58e1df7af..f43566ba88118 100644 --- a/tests/codegen-llvm/debuginfo-generic-closure-env-names.rs +++ b/tests/codegen-llvm/debuginfo-generic-closure-env-names.rs @@ -22,13 +22,13 @@ //@ edition: 2021 // non_generic_closure() -// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}", scope: ![[non_generic_closure_NAMESPACE:[0-9]+]], -// MSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "closure_env$0", scope: ![[non_generic_closure_NAMESPACE:[0-9]+]], -// CHECK: ![[non_generic_closure_NAMESPACE]] = !DINamespace(name: "non_generic_closure" +// NONMSVC-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}", scope: ![[non_generic_closure_NAMESPACE:[0-9]+]], +// MSVC-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "closure_env$0", scope: ![[non_generic_closure_NAMESPACE:[0-9]+]], +// CHECK-DAG: ![[non_generic_closure_NAMESPACE]] = !DINamespace(name: "non_generic_closure" -// CHECK: ![[function_containing_closure_NAMESPACE:[0-9]+]] = !DINamespace(name: "function_containing_closure" -// CHECK: ![[generic_async_function_NAMESPACE:[0-9]+]] = !DINamespace(name: "generic_async_function" -// CHECK: ![[generic_async_block_NAMESPACE:[0-9]+]] = !DINamespace(name: "generic_async_block" +// CHECK-DAG: ![[function_containing_closure_NAMESPACE:[0-9]+]] = !DINamespace(name: "function_containing_closure" +// CHECK-DAG: ![[generic_async_function_NAMESPACE:[0-9]+]] = !DINamespace(name: "generic_async_function" +// CHECK-DAG: ![[generic_async_block_NAMESPACE:[0-9]+]] = !DINamespace(name: "generic_async_block" // function_containing_closure() // NONMSVC-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}", scope: ![[function_containing_closure_NAMESPACE]] diff --git a/tests/codegen-llvm/direct-access-external-data.rs b/tests/codegen-llvm/direct-access-external-data.rs index 43ee290d3a058..135c7e32b4a5d 100644 --- a/tests/codegen-llvm/direct-access-external-data.rs +++ b/tests/codegen-llvm/direct-access-external-data.rs @@ -17,7 +17,7 @@ unsafe extern "C" { // PIE-NOT: dso_local // DIRECT-SAME: dso_local // INDIRECT-NOT: dso_local - // CHECK-SAME: global i32 + // CHECK-SAME: global [4 x i8] safe static VAR: i32; // When "linkage" is used, we generate an indirection global. diff --git a/tests/codegen-llvm/thread-local.rs b/tests/codegen-llvm/thread-local.rs index 70b655fd5cf61..a3584154e079d 100644 --- a/tests/codegen-llvm/thread-local.rs +++ b/tests/codegen-llvm/thread-local.rs @@ -16,8 +16,8 @@ use std::cell::Cell; thread_local!(static A: Cell = const { Cell::new(1) }); -// CHECK: [[TLS_AUX:@.+]] = external thread_local{{.*}} global i64 // CHECK: [[TLS:@.+]] = internal thread_local{{.*}} global +// CHECK: [[TLS_AUX:@.+]] = external thread_local{{.*}} global [8 x i8] // CHECK-LABEL: @get #[no_mangle] diff --git a/tests/crashes/158773.rs b/tests/crashes/158773.rs deleted file mode 100644 index 3020ab6206e4b..0000000000000 --- a/tests/crashes/158773.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ known-bug: #158773 -//@ needs-rustc-debug-assertions -//@ compile-flags: -Znext-solver=globally -trait HasLifetime { - type AtLifetime<'a>; -} - -pub struct ExistentialLifetime(S::AtLifetime<'static>); - -impl ExistentialLifetime { - fn new() -> ExistentialLifetime { - ExistentialLifetime(ExistentialLifetime(())) - } -} - -fn main() {} diff --git a/tests/run-make/dynamic-loading-cdylib/load_and_unload.rs b/tests/run-make/dynamic-loading-cdylib/load_and_unload.rs index eb1baea93dc00..38669eb1a21d7 100644 --- a/tests/run-make/dynamic-loading-cdylib/load_and_unload.rs +++ b/tests/run-make/dynamic-loading-cdylib/load_and_unload.rs @@ -48,6 +48,8 @@ mod libloading { use std::ffi::{c_char, c_int, c_void}; const RTLD_NOW: c_int = 2; + #[cfg(target_os = "aix")] + const RTLD_MEMBER: c_int = 0x00040000; fn cstr_null(s: &str) -> Vec { assert!(!s.as_bytes().contains(&0), "string must not contain interior NUL"); @@ -58,10 +60,17 @@ mod libloading { #[cfg(target_os = "macos")] let filename = cstr_null(&format!("lib{}.dylib", lib_name)); - #[cfg(not(target_os = "macos"))] + #[cfg(target_os = "aix")] + let filename = cstr_null(&format!("./lib{0}.a(lib{0}.so)", lib_name)); + + #[cfg(not(any(target_os = "macos", target_os = "aix")))] let filename = cstr_null(&format!("./lib{}.so", lib_name)); - let handle = unsafe { dlopen(filename.as_ptr(), RTLD_NOW) }; + let flags = RTLD_NOW; + #[cfg(target_os = "aix")] + let flags = flags | RTLD_MEMBER; + + let handle = unsafe { dlopen(filename.as_ptr(), flags) }; if handle.is_null() { None } else { Some(handle) } } diff --git a/tests/run-make/dynamic-loading-cdylib/rmake.rs b/tests/run-make/dynamic-loading-cdylib/rmake.rs index 975722da75d6b..b931863b694a8 100644 --- a/tests/run-make/dynamic-loading-cdylib/rmake.rs +++ b/tests/run-make/dynamic-loading-cdylib/rmake.rs @@ -5,21 +5,29 @@ // - `foo.rs` is a cdylib. // - `load_and_unload.rs` is a binary that loads and unloads the cdylib. // -// This test is ignored on musl hosts because musl's dlclose is a no-op and -// therefore destructors won't run when the library is unloaded. -// See https://wiki.musl-libc.org/functional-differences-from-glibc.html#Unloading-libraries //@ ignore-cross-compile -//@ ignore-musl use run_make_support::{diff, run_with_args, rustc}; +// On musl and AIX, `dlclose` does not invoke TLS destructors upon unloading, +// so only the `load_only` case is tested on those platforms. +// +// Reference for musl: +// https://wiki.musl-libc.org/functional-differences-from-glibc.html#Unloading-libraries + +#[cfg(any(target_env = "musl", target_os = "aix"))] +const TEST_MODES: &[&str] = &["load_only"]; + +#[cfg(not(any(target_env = "musl", target_os = "aix")))] +const TEST_MODES: &[&str] = &["unload", "load_only"]; + fn main() { rustc().input("foo.rs").run(); rustc().crate_type("bin").crate_name("load_and_unload_bin").input("load_and_unload.rs").run(); - for command_arg in ["unload", "load_only"] { + for command_arg in TEST_MODES { let out_raw = run_with_args("load_and_unload_bin", &[command_arg]).stdout_utf8(); #[cfg(windows)] diff --git a/tests/ui/associated-types/dyn-impl-missing-assoc-type-ice-152668.stderr b/tests/ui/associated-types/dyn-impl-missing-assoc-type-ice-152668.stderr index 923972d02b713..f8d9b80ddbf62 100644 --- a/tests/ui/associated-types/dyn-impl-missing-assoc-type-ice-152668.stderr +++ b/tests/ui/associated-types/dyn-impl-missing-assoc-type-ice-152668.stderr @@ -48,6 +48,11 @@ LL | fn sub(self, rhs: Self) -> Self::Output {} found unit type `()` = help: consider constraining the associated type `<(dyn Vector2 + 'static) as Sub>::Output` to `()` or calling a method that returns `<(dyn Vector2 + 'static) as Sub>::Output` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html +note: consider returning one of these bindings + --> $DIR/dyn-impl-missing-assoc-type-ice-152668.rs:10:12 + | +LL | fn sub(self, rhs: Self) -> Self::Output {} + | ^^^^ ^^^ error[E0277]: the size for values of type `(dyn Vector2 + 'static)` cannot be known at compilation time --> $DIR/dyn-impl-missing-assoc-type-ice-152668.rs:10:12 diff --git a/tests/ui/attributes/unsafe/proc-unsafe-attributes.rs b/tests/ui/attributes/unsafe/proc-unsafe-attributes.rs index 33324685a84f4..f84f0bcbd34d4 100644 --- a/tests/ui/attributes/unsafe/proc-unsafe-attributes.rs +++ b/tests/ui/attributes/unsafe/proc-unsafe-attributes.rs @@ -33,9 +33,9 @@ pub fn e() {} //~| ERROR: expected identifier, found keyword `unsafe` //~| ERROR: expected identifier, found keyword `unsafe` //~| ERROR: expected identifier, found keyword `unsafe` -//~| ERROR: malformed lint attribute input -//~| ERROR: malformed lint attribute input -//~| ERROR: malformed lint attribute input +//~| ERROR: malformed +//~| ERROR: malformed +//~| ERROR: malformed pub fn f() {} fn main() {} diff --git a/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr b/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr index 04e8c4d2dd453..cd73156eff453 100644 --- a/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr +++ b/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr @@ -25,11 +25,13 @@ help: escape `unsafe` to use it as an identifier LL | #[unsafe(allow(r#unsafe(dead_code)))] | ++ -error[E0452]: malformed lint attribute input +error: malformed `allow` attribute input --> $DIR/proc-unsafe-attributes.rs:29:16 | LL | #[unsafe(allow(unsafe(dead_code)))] - | ^^^^^^^^^^^^^^^^^ bad attribute argument + | ^^^^^^^^^^^^^^^^^ not the name of a lint + | + = help: for example, write `#[allow(dead_code)]` for `dead_code` error: the `proc_macro` attribute is only usable with crates of the `proc-macro` crate type --> $DIR/proc-unsafe-attributes.rs:1:10 @@ -85,12 +87,13 @@ help: escape `unsafe` to use it as an identifier LL | #[unsafe(allow(r#unsafe(dead_code)))] | ++ -error[E0452]: malformed lint attribute input +error: malformed `allow` attribute input --> $DIR/proc-unsafe-attributes.rs:29:16 | LL | #[unsafe(allow(unsafe(dead_code)))] - | ^^^^^^^^^^^^^^^^^ bad attribute argument + | ^^^^^^^^^^^^^^^^^ not the name of a lint | + = help: for example, write `#[allow(dead_code)]` for `dead_code` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `proc_macro` is not an unsafe attribute @@ -176,15 +179,15 @@ help: escape `unsafe` to use it as an identifier LL | #[unsafe(allow(r#unsafe(dead_code)))] | ++ -error[E0452]: malformed lint attribute input +error: malformed `allow` attribute input --> $DIR/proc-unsafe-attributes.rs:29:16 | LL | #[unsafe(allow(unsafe(dead_code)))] - | ^^^^^^^^^^^^^^^^^ bad attribute argument + | ^^^^^^^^^^^^^^^^^ not the name of a lint | + = help: for example, write `#[allow(dead_code)]` for `dead_code` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 21 previous errors -Some errors have detailed explanations: E0452, E0565. -For more information about an error, try `rustc --explain E0452`. +For more information about this error, try `rustc --explain E0565`. diff --git a/tests/ui/diagnostic-flags/deduplicate-diagnostics.deduplicate.stderr b/tests/ui/diagnostic-flags/deduplicate-diagnostics.deduplicate.stderr index 114c37188a9ef..ff82a449d83ba 100644 --- a/tests/ui/diagnostic-flags/deduplicate-diagnostics.deduplicate.stderr +++ b/tests/ui/diagnostic-flags/deduplicate-diagnostics.deduplicate.stderr @@ -1,4 +1,4 @@ -error: expected a lint, found literal +error: malformed `deny` attribute input --> $DIR/deduplicate-diagnostics.rs:10:8 | LL | #[deny("literal")] diff --git a/tests/ui/diagnostic-flags/deduplicate-diagnostics.duplicate.stderr b/tests/ui/diagnostic-flags/deduplicate-diagnostics.duplicate.stderr index 66d0d94c0e815..3c7ce1686080c 100644 --- a/tests/ui/diagnostic-flags/deduplicate-diagnostics.duplicate.stderr +++ b/tests/ui/diagnostic-flags/deduplicate-diagnostics.duplicate.stderr @@ -1,4 +1,4 @@ -error: expected a lint, found literal +error: malformed `deny` attribute input --> $DIR/deduplicate-diagnostics.rs:10:8 | LL | #[deny("literal")] @@ -20,7 +20,7 @@ LL | #[derive(Unresolved)] | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: expected a lint, found literal +error: malformed `deny` attribute input --> $DIR/deduplicate-diagnostics.rs:10:8 | LL | #[deny("literal")] @@ -29,7 +29,7 @@ LL | #[deny("literal")] = help: try using `#[deny(literal)]` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: expected a lint, found literal +error: malformed `deny` attribute input --> $DIR/deduplicate-diagnostics.rs:10:8 | LL | #[deny("literal")] diff --git a/tests/ui/diagnostic-flags/deduplicate-diagnostics.rs b/tests/ui/diagnostic-flags/deduplicate-diagnostics.rs index b070ec0f7dd93..437ed20acbeb9 100644 --- a/tests/ui/diagnostic-flags/deduplicate-diagnostics.rs +++ b/tests/ui/diagnostic-flags/deduplicate-diagnostics.rs @@ -7,7 +7,7 @@ //[duplicate]~| ERROR cannot find derive macro `Unresolved` in this scope struct S; -#[deny("literal")] //~ ERROR expected a lint, found literal - //[duplicate]~| ERROR expected a lint, found literal - //[duplicate]~| ERROR expected a lint, found literal +#[deny("literal")] //~ ERROR malformed + //[duplicate]~| ERROR malformed + //[duplicate]~| ERROR malformed fn main() {} diff --git a/tests/ui/error-codes/E0452.rs b/tests/ui/error-codes/E0452.rs index 4e5a6c9301467..6a0437df7b14e 100644 --- a/tests/ui/error-codes/E0452.rs +++ b/tests/ui/error-codes/E0452.rs @@ -1,8 +1,8 @@ -#![allow(foo = "")] //~ ERROR E0452 - //~| ERROR E0452 - //~| ERROR E0452 - //~| ERROR E0452 - //~| ERROR E0452 - //~| ERROR E0452 +#![allow(foo = "")] //~ ERROR malformed + //~| ERROR malformed + //~| ERROR malformed + //~| ERROR malformed + //~| ERROR malformed + //~| ERROR malformed fn main() { } diff --git a/tests/ui/error-codes/E0452.stderr b/tests/ui/error-codes/E0452.stderr index c20429e363dda..c34d9a2a01b28 100644 --- a/tests/ui/error-codes/E0452.stderr +++ b/tests/ui/error-codes/E0452.stderr @@ -1,49 +1,55 @@ -error[E0452]: malformed lint attribute input +error: malformed `allow` attribute input --> $DIR/E0452.rs:1:10 | LL | #![allow(foo = "")] - | ^^^^^^^^ bad attribute argument + | ^^^^^^^^ not the name of a lint + | + = help: for example, write `#[allow(dead_code)]` for `dead_code` -error[E0452]: malformed lint attribute input +error: malformed `allow` attribute input --> $DIR/E0452.rs:1:10 | LL | #![allow(foo = "")] - | ^^^^^^^^ bad attribute argument + | ^^^^^^^^ not the name of a lint | + = help: for example, write `#[allow(dead_code)]` for `dead_code` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0452]: malformed lint attribute input +error: malformed `allow` attribute input --> $DIR/E0452.rs:1:10 | LL | #![allow(foo = "")] - | ^^^^^^^^ bad attribute argument + | ^^^^^^^^ not the name of a lint | + = help: for example, write `#[allow(dead_code)]` for `dead_code` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0452]: malformed lint attribute input +error: malformed `allow` attribute input --> $DIR/E0452.rs:1:10 | LL | #![allow(foo = "")] - | ^^^^^^^^ bad attribute argument + | ^^^^^^^^ not the name of a lint | + = help: for example, write `#[allow(dead_code)]` for `dead_code` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0452]: malformed lint attribute input +error: malformed `allow` attribute input --> $DIR/E0452.rs:1:10 | LL | #![allow(foo = "")] - | ^^^^^^^^ bad attribute argument + | ^^^^^^^^ not the name of a lint | + = help: for example, write `#[allow(dead_code)]` for `dead_code` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0452]: malformed lint attribute input +error: malformed `allow` attribute input --> $DIR/E0452.rs:1:10 | LL | #![allow(foo = "")] - | ^^^^^^^^ bad attribute argument + | ^^^^^^^^ not the name of a lint | + = help: for example, write `#[allow(dead_code)]` for `dead_code` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0452`. diff --git a/tests/ui/feature-gates/feature-gate-builtin_syntax.rs b/tests/ui/feature-gates/feature-gate-builtin_syntax.rs deleted file mode 100644 index 832bb5a96bc3d..0000000000000 --- a/tests/ui/feature-gates/feature-gate-builtin_syntax.rs +++ /dev/null @@ -1,7 +0,0 @@ -struct Foo { - v: u8, - w: u8, -} -fn main() { - builtin # offset_of(Foo, v); //~ ERROR `builtin #` syntax is unstable -} diff --git a/tests/ui/feature-gates/feature-gate-internal_syntax.rs b/tests/ui/feature-gates/feature-gate-internal_syntax.rs new file mode 100644 index 0000000000000..5b4293d900923 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-internal_syntax.rs @@ -0,0 +1,10 @@ +//@ edition: 2021.. +#![feature(forced_keywords)] + +struct Foo { + v: u8, + w: u8, +} +fn main() { + k#offset_of(Foo, v); //~ ERROR this syntax is internal +} diff --git a/tests/ui/feature-gates/feature-gate-builtin_syntax.stderr b/tests/ui/feature-gates/feature-gate-internal_syntax.stderr similarity index 56% rename from tests/ui/feature-gates/feature-gate-builtin_syntax.stderr rename to tests/ui/feature-gates/feature-gate-internal_syntax.stderr index 297363b3de711..9db1a51e0d999 100644 --- a/tests/ui/feature-gates/feature-gate-builtin_syntax.stderr +++ b/tests/ui/feature-gates/feature-gate-internal_syntax.stderr @@ -1,11 +1,11 @@ -error[E0658]: `builtin #` syntax is unstable - --> $DIR/feature-gate-builtin_syntax.rs:6:15 +error[E0658]: this syntax is internal + --> $DIR/feature-gate-internal_syntax.rs:9:5 | -LL | builtin # offset_of(Foo, v); - | ^^^^^^^^^ +LL | k#offset_of(Foo, v); + | ^^^^^^^^^^^^^^^^^^^^ | = note: see issue #110680 for more information - = help: add `#![feature(builtin_syntax)]` to the crate attributes to enable + = help: add `#![feature(internal_syntax)]` 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 diff --git a/tests/ui/field_representing_types/invalid.next.stderr b/tests/ui/field_representing_types/invalid.next.stderr index 52872001b4dee..82b2aa81451ab 100644 --- a/tests/ui/field_representing_types/invalid.next.stderr +++ b/tests/ui/field_representing_types/invalid.next.stderr @@ -33,7 +33,7 @@ error: offset_of expects dot-separated field and variant names LL | let _: field_of!(Enum, Variant..field); | ^^^^^^^^^^^^^^ -error: `field_of!` expects dot-separated field and variant names +error: `field_of` expects dot-separated field and variant names --> $DIR/invalid.rs:28:12 | LL | let _: field_of!(Enum, Variant..field); @@ -48,7 +48,7 @@ error: offset_of expects dot-separated field and variant names LL | let _: field_of!(Struct, [42]); | ^^^^ -error: `field_of!` expects dot-separated field and variant names +error: `field_of` expects dot-separated field and variant names --> $DIR/invalid.rs:30:12 | LL | let _: field_of!(Struct, [42]); @@ -57,7 +57,7 @@ LL | let _: field_of!(Struct, [42]); | in this macro invocation | this macro call doesn't expand to a type -error: `field_of!` only supports a single field or a variant with a field +error: `field_of` only supports a single field or a variant with a field --> $DIR/invalid.rs:32:30 | LL | let _: field_of!(Struct, field1.field2.field3); diff --git a/tests/ui/field_representing_types/invalid.old.stderr b/tests/ui/field_representing_types/invalid.old.stderr index 52872001b4dee..82b2aa81451ab 100644 --- a/tests/ui/field_representing_types/invalid.old.stderr +++ b/tests/ui/field_representing_types/invalid.old.stderr @@ -33,7 +33,7 @@ error: offset_of expects dot-separated field and variant names LL | let _: field_of!(Enum, Variant..field); | ^^^^^^^^^^^^^^ -error: `field_of!` expects dot-separated field and variant names +error: `field_of` expects dot-separated field and variant names --> $DIR/invalid.rs:28:12 | LL | let _: field_of!(Enum, Variant..field); @@ -48,7 +48,7 @@ error: offset_of expects dot-separated field and variant names LL | let _: field_of!(Struct, [42]); | ^^^^ -error: `field_of!` expects dot-separated field and variant names +error: `field_of` expects dot-separated field and variant names --> $DIR/invalid.rs:30:12 | LL | let _: field_of!(Struct, [42]); @@ -57,7 +57,7 @@ LL | let _: field_of!(Struct, [42]); | in this macro invocation | this macro call doesn't expand to a type -error: `field_of!` only supports a single field or a variant with a field +error: `field_of` only supports a single field or a variant with a field --> $DIR/invalid.rs:32:30 | LL | let _: field_of!(Struct, field1.field2.field3); diff --git a/tests/ui/field_representing_types/invalid.rs b/tests/ui/field_representing_types/invalid.rs index 0d8c5d563401c..e0ba33dd4eb59 100644 --- a/tests/ui/field_representing_types/invalid.rs +++ b/tests/ui/field_representing_types/invalid.rs @@ -24,10 +24,10 @@ fn main() { let _: field_of!(Struct); //~ ERROR: unexpected end of macro invocation let _: field_of!(Struct,); //~ ERROR: unexpected end of macro invocation let _: field_of!(Struct, field, extra); //~ ERROR: no rules expected `extra` - // FIXME(FRTs): adjust error message to mention `field_of!` & prevent double errors + // FIXME(FRTs): adjust error message to mention `field_of` & prevent double errors let _: field_of!(Enum, Variant..field); //~ ERROR: offset_of expects dot-separated field and variant names - //~^ ERROR: `field_of!` expects dot-separated field and variant names + //~^ ERROR: `field_of` expects dot-separated field and variant names let _: field_of!(Struct, [42]); //~ ERROR: offset_of expects dot-separated field and variant names - //~^ ERROR: `field_of!` expects dot-separated field and variant names - let _: field_of!(Struct, field1.field2.field3); //~ ERROR: `field_of!` only supports a single field or a variant with a field + //~^ ERROR: `field_of` expects dot-separated field and variant names + let _: field_of!(Struct, field1.field2.field3); //~ ERROR: `field_of` only supports a single field or a variant with a field } diff --git a/tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.stderr b/tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.stderr index 4a0991d0eb3cb..8015bc15f510c 100644 --- a/tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.stderr +++ b/tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.stderr @@ -11,6 +11,8 @@ LL | x = foo::<()>; | = note: expected fn item `fn(F) -> F {bar::}` found fn item `fn(()) -> () {foo::<()>}` + = note: different fn items have unique types, even if their signatures are the same + = help: consider casting both fn items to fn pointers using `as fn(Alias(No, Alias { kind: Opaque { def_id: DefId(0:8 ~ fn_def_opaque_coercion_to_fn_ptr[7fda]::F::{opaque#0}) }, args: [], .. })) -> Alias(No, Alias { kind: Opaque { def_id: DefId(0:8 ~ fn_def_opaque_coercion_to_fn_ptr[7fda]::F::{opaque#0}) }, args: [], .. })` error[E0308]: mismatched types --> $DIR/fn_def_opaque_coercion_to_fn_ptr.rs:29:9 @@ -28,6 +30,8 @@ LL | x = foo::; | = note: expected fn item `fn(()) -> () {bar::<()>}` found fn item `fn(I) -> I {foo::}` + = note: different fn items have unique types, even if their signatures are the same + = help: consider casting both fn items to fn pointers using `as fn(())` help: use parentheses to call this function | LL | x = foo::(/* I */); diff --git a/tests/ui/force-inlining/invalid-async-cold.rs b/tests/ui/force-inlining/invalid-async-cold.rs new file mode 100644 index 0000000000000..f0a699ac1caa0 --- /dev/null +++ b/tests/ui/force-inlining/invalid-async-cold.rs @@ -0,0 +1,25 @@ +//@ edition: 2024 +//@ compile-flags: --crate-type=lib +#![allow(internal_features)] +#![feature(gen_blocks)] +#![feature(rustc_attrs)] + +// `#[inline]` on an `async fn` or `gen fn` applies to its body coroutine, but +// `#[rustc_force_inline]` must not: it is already rejected on such functions, +// so it must not also be reported as incompatible with `#[cold]`, which both +// the function and its body coroutine get. + +#[rustc_force_inline] +//~^ ERROR attribute cannot be applied to a `async`, `gen` or `async gen` function +#[cold] +pub async fn async_cold() {} + +#[rustc_force_inline] +//~^ ERROR attribute cannot be applied to a `async`, `gen` or `async gen` function +#[cold] +pub gen fn gen_cold() {} + +pub fn caller() { + let _ = async_cold(); + let _ = gen_cold(); +} diff --git a/tests/ui/force-inlining/invalid-async-cold.stderr b/tests/ui/force-inlining/invalid-async-cold.stderr new file mode 100644 index 0000000000000..cc176458c0c13 --- /dev/null +++ b/tests/ui/force-inlining/invalid-async-cold.stderr @@ -0,0 +1,20 @@ +error: attribute cannot be applied to a `async`, `gen` or `async gen` function + --> $DIR/invalid-async-cold.rs:12:1 + | +LL | #[rustc_force_inline] + | ^^^^^^^^^^^^^^^^^^^^^ +... +LL | pub async fn async_cold() {} + | ------------------------- `async`, `gen` or `async gen` function + +error: attribute cannot be applied to a `async`, `gen` or `async gen` function + --> $DIR/invalid-async-cold.rs:17:1 + | +LL | #[rustc_force_inline] + | ^^^^^^^^^^^^^^^^^^^^^ +... +LL | pub gen fn gen_cold() {} + | --------------------- `async`, `gen` or `async gen` function + +error: aborting due to 2 previous errors + diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr index f9f39e34b658e..7339b9acaea56 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr @@ -6,8 +6,6 @@ LL | call(f, ()); | | | required by a bound introduced by this call | - = note: expected type with signature `for<'a> fn(<_ as ATC<'a>>::Type)` - found type parameter with signature `fn(())` note: required by a bound in `call` --> $DIR/issue-62529-3.rs:9:36 | diff --git a/tests/ui/hygiene/unpretty-debug-lifetimes.rs b/tests/ui/hygiene/unpretty-debug-lifetimes.rs index ee8be21b60d01..5f8a20281ab04 100644 --- a/tests/ui/hygiene/unpretty-debug-lifetimes.rs +++ b/tests/ui/hygiene/unpretty-debug-lifetimes.rs @@ -4,8 +4,15 @@ // Regression test for lifetime hygiene annotations in -Zunpretty=expanded,hygiene // Previously, lifetimes were missing the #N syntax context suffix. -// Don't break whenever Symbol numbering changes -//@ normalize-stdout: "\d+#" -> "0#" +// This test deliberately has no `.stdout` snapshot. The hygiene annotations +// embed `Symbol` indices, whose width feeds into the pretty-printer's line +// breaking, so the layout shifts whenever a `Symbol` gains or loses a digit. +// `normalize-stdout` can't help, because the layout is decided before +// normalization runs. Assert the property this test is about instead: the two +// `'a` share their text but carry different syntax contexts. +//@ dont-check-compiler-stdout +//@ check-stdout +//@ regex-error-pattern: f\s*/\*\s*\d+#0\s*\*/<'a\s*/\*\s*\d+#0\s*\*/,\s*'a\s*/\*\s*\d+#1\s*\*/ #![feature(decl_macro)] #![feature(no_core)] diff --git a/tests/ui/hygiene/unpretty-debug-lifetimes.stdout b/tests/ui/hygiene/unpretty-debug-lifetimes.stdout deleted file mode 100644 index c75cc7b2179d3..0000000000000 --- a/tests/ui/hygiene/unpretty-debug-lifetimes.stdout +++ /dev/null @@ -1,33 +0,0 @@ -//@ check-pass -//@ compile-flags: -Zunpretty=expanded,hygiene - -// Regression test for lifetime hygiene annotations in -Zunpretty=expanded,hygiene -// Previously, lifetimes were missing the #N syntax context suffix. - -// Don't break whenever Symbol numbering changes -//@ normalize-stdout: "\d+#" -> "0#" - -#![feature /* 0#0 */(decl_macro /* 0#0 */)] -#![feature /* 0#0 */(no_core /* 0#0 */)] -#![no_core /* 0#0 */] - -macro lifetime_hygiene - /* - 0#0 - */ { - ($f /* 0#0 */:ident /* 0#0 */<$a /* 0#0 */:lifetime /* 0#0 - */>) => - { fn /* 0#0 */ $f /* 0#0 */<$a /* 0#0 */, 'a /* 0#0 */>() {} } -} -fn f /* 0#0 */<'a /* 0#0 */, 'a /* 0#1 */>() {} - - -/* -Expansions: -crate0::{{expn0}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Root -crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "lifetime_hygiene") - -SyntaxContexts: -#0: parent: #0, outer_mark: (crate0::{{expn0}}, Opaque) -#1: parent: #0, outer_mark: (crate0::{{expn1}}, Opaque) -*/ diff --git a/tests/ui/impl-trait/in-assoc-type.stderr b/tests/ui/impl-trait/in-assoc-type.stderr index 5a8cc40d0276e..1f824bb23f0b7 100644 --- a/tests/ui/impl-trait/in-assoc-type.stderr +++ b/tests/ui/impl-trait/in-assoc-type.stderr @@ -11,6 +11,10 @@ LL | fn foo(&self) -> >::Bar {} | = note: expected opaque type `<() as Foo<()>>::Bar` found unit type `()` +help: consider returning the local binding `self` + | +LL | fn foo(&self) -> >::Bar { self } + | ++++ error: aborting due to 1 previous error diff --git a/tests/ui/lint/lint-attribute-literals.rs b/tests/ui/lint/lint-attribute-literals.rs index 34a4757adec3c..7adec75210108 100644 --- a/tests/ui/lint/lint-attribute-literals.rs +++ b/tests/ui/lint/lint-attribute-literals.rs @@ -1,11 +1,11 @@ // Checks that lint attributes with literals have an explanatory error #[allow("literal")] -//~^ ERROR expected a lint, found literal -//~| ERROR expected a lint, found literal -//~| ERROR expected a lint, found literal +//~^ ERROR malformed +//~| ERROR malformed +//~| ERROR malformed #[deny(1.0)] -//~^ ERROR expected a lint, found literal -//~| ERROR expected a lint, found literal -//~| ERROR expected a lint, found literal +//~^ ERROR malformed +//~| ERROR malformed +//~| ERROR malformed fn main() {} diff --git a/tests/ui/lint/lint-attribute-literals.stderr b/tests/ui/lint/lint-attribute-literals.stderr index 7434f8b5c5d4b..b06eac094f66d 100644 --- a/tests/ui/lint/lint-attribute-literals.stderr +++ b/tests/ui/lint/lint-attribute-literals.stderr @@ -1,4 +1,4 @@ -error: expected a lint, found literal +error: malformed `allow` attribute input --> $DIR/lint-attribute-literals.rs:3:9 | LL | #[allow("literal")] @@ -6,7 +6,7 @@ LL | #[allow("literal")] | = help: try using `#[allow(literal)]` -error: expected a lint, found literal +error: malformed `deny` attribute input --> $DIR/lint-attribute-literals.rs:7:8 | LL | #[deny(1.0)] @@ -14,7 +14,7 @@ LL | #[deny(1.0)] | = help: for example, write `#[deny(dead_code)]` for `dead_code` -error: expected a lint, found literal +error: malformed `allow` attribute input --> $DIR/lint-attribute-literals.rs:3:9 | LL | #[allow("literal")] @@ -23,7 +23,7 @@ LL | #[allow("literal")] = help: try using `#[allow(literal)]` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: expected a lint, found literal +error: malformed `deny` attribute input --> $DIR/lint-attribute-literals.rs:7:8 | LL | #[deny(1.0)] @@ -32,7 +32,7 @@ LL | #[deny(1.0)] = help: for example, write `#[deny(dead_code)]` for `dead_code` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: expected a lint, found literal +error: malformed `allow` attribute input --> $DIR/lint-attribute-literals.rs:3:9 | LL | #[allow("literal")] @@ -41,7 +41,7 @@ LL | #[allow("literal")] = help: try using `#[allow(literal)]` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: expected a lint, found literal +error: malformed `deny` attribute input --> $DIR/lint-attribute-literals.rs:7:8 | LL | #[deny(1.0)] diff --git a/tests/ui/lint/lint-malformed.rs b/tests/ui/lint/lint-malformed.rs index cf5570753d85d..5fd92170363f0 100644 --- a/tests/ui/lint/lint-malformed.rs +++ b/tests/ui/lint/lint-malformed.rs @@ -1,8 +1,8 @@ #![deny = "foo"] //~ ERROR malformed `deny` attribute input -#![allow(bar = "baz")] //~ ERROR malformed lint attribute - //~| ERROR malformed lint attribute - //~| ERROR malformed lint attribute - //~| ERROR malformed lint attribute - //~| ERROR malformed lint attribute - //~| ERROR malformed lint attribute +#![allow(bar = "baz")] //~ ERROR malformed + //~| ERROR malformed + //~| ERROR malformed + //~| ERROR malformed + //~| ERROR malformed + //~| ERROR malformed fn main() { } diff --git a/tests/ui/lint/lint-malformed.stderr b/tests/ui/lint/lint-malformed.stderr index 7be928de86985..ceb7fe105bcd3 100644 --- a/tests/ui/lint/lint-malformed.stderr +++ b/tests/ui/lint/lint-malformed.stderr @@ -1,31 +1,36 @@ -error[E0452]: malformed lint attribute input +error: malformed `allow` attribute input --> $DIR/lint-malformed.rs:2:10 | LL | #![allow(bar = "baz")] - | ^^^^^^^^^^^ bad attribute argument + | ^^^^^^^^^^^ not the name of a lint + | + = help: for example, write `#[allow(dead_code)]` for `dead_code` -error[E0452]: malformed lint attribute input +error: malformed `allow` attribute input --> $DIR/lint-malformed.rs:2:10 | LL | #![allow(bar = "baz")] - | ^^^^^^^^^^^ bad attribute argument + | ^^^^^^^^^^^ not the name of a lint | + = help: for example, write `#[allow(dead_code)]` for `dead_code` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0452]: malformed lint attribute input +error: malformed `allow` attribute input --> $DIR/lint-malformed.rs:2:10 | LL | #![allow(bar = "baz")] - | ^^^^^^^^^^^ bad attribute argument + | ^^^^^^^^^^^ not the name of a lint | + = help: for example, write `#[allow(dead_code)]` for `dead_code` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0452]: malformed lint attribute input +error: malformed `allow` attribute input --> $DIR/lint-malformed.rs:2:10 | LL | #![allow(bar = "baz")] - | ^^^^^^^^^^^ bad attribute argument + | ^^^^^^^^^^^ not the name of a lint | + = help: for example, write `#[allow(dead_code)]` for `dead_code` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0539]: malformed `deny` attribute input @@ -49,23 +54,24 @@ LL - #![deny = "foo"] LL + #![deny(lint1, lint2, lint3, reason = "...")] | -error[E0452]: malformed lint attribute input +error: malformed `allow` attribute input --> $DIR/lint-malformed.rs:2:10 | LL | #![allow(bar = "baz")] - | ^^^^^^^^^^^ bad attribute argument + | ^^^^^^^^^^^ not the name of a lint | + = help: for example, write `#[allow(dead_code)]` for `dead_code` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0452]: malformed lint attribute input +error: malformed `allow` attribute input --> $DIR/lint-malformed.rs:2:10 | LL | #![allow(bar = "baz")] - | ^^^^^^^^^^^ bad attribute argument + | ^^^^^^^^^^^ not the name of a lint | + = help: for example, write `#[allow(dead_code)]` for `dead_code` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 7 previous errors -Some errors have detailed explanations: E0452, E0539. -For more information about an error, try `rustc --explain E0452`. +For more information about this error, try `rustc --explain E0539`. diff --git a/tests/ui/lint/pre-expansion-parsing.rs b/tests/ui/lint/pre-expansion-parsing.rs index 7cfc57ff4e903..11a55beb77d65 100644 --- a/tests/ui/lint/pre-expansion-parsing.rs +++ b/tests/ui/lint/pre-expansion-parsing.rs @@ -3,7 +3,7 @@ #[expect] // OK #[expect[wut]] // OK #[expect(expect)] // OK -#[expect(expect(expect))] //~ ERROR malformed lint attribute input +#[expect(expect(expect))] //~ ERROR malformed #[deny(({!}))] // OK #[expect[helix::]] // OK #[cfg(false)] diff --git a/tests/ui/lint/pre-expansion-parsing.stderr b/tests/ui/lint/pre-expansion-parsing.stderr index ecc8b7017d92d..651fd5d4c8f38 100644 --- a/tests/ui/lint/pre-expansion-parsing.stderr +++ b/tests/ui/lint/pre-expansion-parsing.stderr @@ -1,9 +1,10 @@ -error[E0452]: malformed lint attribute input +error: malformed `expect` attribute input --> $DIR/pre-expansion-parsing.rs:6:10 | LL | #[expect(expect(expect))] - | ^^^^^^^^^^^^^^ bad attribute argument + | ^^^^^^^^^^^^^^ not the name of a lint + | + = help: for example, write `#[expect(dead_code)]` for `dead_code` error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0452`. diff --git a/tests/ui/lint/reasons-erroneous.rs b/tests/ui/lint/reasons-erroneous.rs index 38ad00da64cd7..4a0c458209ee6 100644 --- a/tests/ui/lint/reasons-erroneous.rs +++ b/tests/ui/lint/reasons-erroneous.rs @@ -8,14 +8,14 @@ //~^ ERROR malformed `warn` attribute input //~| NOTE expected a normal string literal, not a byte string literal #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")] -//~^ ERROR malformed lint attribute -//~| NOTE bad attribute argument +//~^ ERROR malformed +//~| NOTE not the name of a lint #![warn(unsafe_code, blerp = "or in league with robbers have reversed the signposts")] -//~^ ERROR malformed lint attribute -//~| NOTE bad attribute argument +//~^ ERROR malformed +//~| NOTE not the name of a lint #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))] -//~^ ERROR malformed lint attribute -//~| NOTE bad attribute argument +//~^ ERROR malformed +//~| NOTE not the name of a lint #![warn(ellipsis_inclusive_range_patterns, reason = "born barren", reason = "a freak growth")] //~^ ERROR malformed lint attribute //~| NOTE reason in lint attribute must come last diff --git a/tests/ui/lint/reasons-erroneous.stderr b/tests/ui/lint/reasons-erroneous.stderr index d771366d6168e..3c52a0d8e25b4 100644 --- a/tests/ui/lint/reasons-erroneous.stderr +++ b/tests/ui/lint/reasons-erroneous.stderr @@ -29,23 +29,29 @@ LL | #![warn(anonymous_parameters, reason = b"consider these, for we have condem | = note: expected a normal string literal, not a byte string literal -error[E0452]: malformed lint attribute input +error: malformed `warn` attribute input --> $DIR/reasons-erroneous.rs:10:29 | LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not the name of a lint + | + = help: for example, write `#[warn(dead_code)]` for `dead_code` -error[E0452]: malformed lint attribute input +error: malformed `warn` attribute input --> $DIR/reasons-erroneous.rs:13:22 | LL | #![warn(unsafe_code, blerp = "or in league with robbers have reversed the signposts")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not the name of a lint + | + = help: for example, write `#[warn(dead_code)]` for `dead_code` -error[E0452]: malformed lint attribute input +error: malformed `warn` attribute input --> $DIR/reasons-erroneous.rs:16:36 | LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not the name of a lint + | + = help: for example, write `#[warn(dead_code)]` for `dead_code` error[E0452]: malformed lint attribute input --> $DIR/reasons-erroneous.rs:19:44 diff --git a/tests/ui/offset-of/offset-of-builtin.rs b/tests/ui/offset-of/offset-of-builtin.rs deleted file mode 100644 index 6664c10f905ef..0000000000000 --- a/tests/ui/offset-of/offset-of-builtin.rs +++ /dev/null @@ -1,32 +0,0 @@ -#![feature(builtin_syntax)] - -// For the exposed macro we already test these errors in the other files, -// but this test helps to make sure the builtin construct also errors. -// This has the same examples as offset-of-arg-count.rs - -fn main() { - builtin # offset_of(NotEnoughArguments); //~ ERROR expected one of -} -fn t1() { - builtin # offset_of(NotEnoughArgumentsWithAComma, ); //~ ERROR expected expression -} -fn t2() { - builtin # offset_of(S, f, too many arguments); //~ ERROR expected `)`, found `too` -} -fn t3() { - builtin # offset_of(S, f); // compiles fine -} -fn t4() { - builtin # offset_of(S, f.); //~ ERROR unexpected token -} -fn t5() { - builtin # offset_of(S, f.,); //~ ERROR unexpected token -} -fn t6() { - builtin # offset_of(S, f..); //~ ERROR offset_of expects dot-separated field and variant names -} -fn t7() { - builtin # offset_of(S, f..,); //~ ERROR offset_of expects dot-separated field and variant names -} - -struct S { f: u8, } diff --git a/tests/ui/offset-of/offset-of-builtin.stderr b/tests/ui/offset-of/offset-of-builtin.stderr deleted file mode 100644 index 5917ee2936361..0000000000000 --- a/tests/ui/offset-of/offset-of-builtin.stderr +++ /dev/null @@ -1,46 +0,0 @@ -error: expected one of `!`, `(`, `+`, `,`, `::`, or `<`, found `)` - --> $DIR/offset-of-builtin.rs:8:43 - | -LL | builtin # offset_of(NotEnoughArguments); - | ^ expected one of `!`, `(`, `+`, `,`, `::`, or `<` - -error: expected expression, found `)` - --> $DIR/offset-of-builtin.rs:11:55 - | -LL | builtin # offset_of(NotEnoughArgumentsWithAComma, ); - | ^ expected expression - -error: expected `)`, found `too` - --> $DIR/offset-of-builtin.rs:14:31 - | -LL | builtin # offset_of(S, f, too many arguments); - | ^^^ expected `)` - | - = note: unexpected third argument to offset_of - -error: unexpected token: `)` - --> $DIR/offset-of-builtin.rs:20:30 - | -LL | builtin # offset_of(S, f.); - | ^ - -error: unexpected token: `,` - --> $DIR/offset-of-builtin.rs:23:30 - | -LL | builtin # offset_of(S, f.,); - | ^ - -error: offset_of expects dot-separated field and variant names - --> $DIR/offset-of-builtin.rs:26:28 - | -LL | builtin # offset_of(S, f..); - | ^^^ - -error: offset_of expects dot-separated field and variant names - --> $DIR/offset-of-builtin.rs:29:28 - | -LL | builtin # offset_of(S, f..,); - | ^^^ - -error: aborting due to 7 previous errors - diff --git a/tests/ui/offset-of/offset-of-tuple-field.rs b/tests/ui/offset-of/offset-of-tuple-field.rs index 02d41f91a2563..755d61d18b739 100644 --- a/tests/ui/offset-of/offset-of-tuple-field.rs +++ b/tests/ui/offset-of/offset-of-tuple-field.rs @@ -1,5 +1,3 @@ -#![feature(builtin_syntax)] - use std::mem::offset_of; fn main() { @@ -9,12 +7,6 @@ fn main() { offset_of!((u8, u8), 1_u8); //~ ERROR no field `1_` //~| ERROR suffixes on a tuple index - builtin # offset_of((u8, u8), 1e2); //~ ERROR no field `1e2` - builtin # offset_of((u8, u8), _0); //~ ERROR no field `_0` - builtin # offset_of((u8, u8), 01); //~ ERROR no field `01` - builtin # offset_of((u8, u8), 1_u8); //~ ERROR no field `1_` - //~| ERROR suffixes on a tuple index - offset_of!(((u8, u16), (u32, u16, u8)), 0.2); //~ ERROR no field `2` offset_of!(((u8, u16), (u32, u16, u8)), 0.1e2); //~ ERROR no field `1e2` offset_of!(((u8, u16), (u32, u16, u8)), 1.2); diff --git a/tests/ui/offset-of/offset-of-tuple-field.stderr b/tests/ui/offset-of/offset-of-tuple-field.stderr index 01622c5fa2da6..052e4b0596fd6 100644 --- a/tests/ui/offset-of/offset-of-tuple-field.stderr +++ b/tests/ui/offset-of/offset-of-tuple-field.stderr @@ -1,17 +1,11 @@ error: suffixes on a tuple index are invalid - --> $DIR/offset-of-tuple-field.rs:15:35 - | -LL | builtin # offset_of((u8, u8), 1_u8); - | ^^^^ invalid suffix `u8` - -error: suffixes on a tuple index are invalid - --> $DIR/offset-of-tuple-field.rs:9:26 + --> $DIR/offset-of-tuple-field.rs:7:26 | LL | offset_of!((u8, u8), 1_u8); | ^^^^ invalid suffix `u8` error[E0609]: no field `_0` on type `(u8, u8)` - --> $DIR/offset-of-tuple-field.rs:6:26 + --> $DIR/offset-of-tuple-field.rs:4:26 | LL | offset_of!((u8, u8), _0); | ^^ @@ -23,7 +17,7 @@ LL + offset_of!((u8, u8), 0); | error[E0609]: no field `01` on type `(u8, u8)` - --> $DIR/offset-of-tuple-field.rs:7:26 + --> $DIR/offset-of-tuple-field.rs:5:26 | LL | offset_of!((u8, u8), 01); | ^^ @@ -31,7 +25,7 @@ LL | offset_of!((u8, u8), 01); = note: available fields are: `0`, `1` error[E0609]: no field `1e2` on type `(u8, u8)` - --> $DIR/offset-of-tuple-field.rs:8:26 + --> $DIR/offset-of-tuple-field.rs:6:26 | LL | offset_of!((u8, u8), 1e2); | ^^^ @@ -39,7 +33,7 @@ LL | offset_of!((u8, u8), 1e2); = note: available fields are: `0`, `1` error[E0609]: no field `1_` on type `(u8, u8)` - --> $DIR/offset-of-tuple-field.rs:9:26 + --> $DIR/offset-of-tuple-field.rs:7:26 | LL | offset_of!((u8, u8), 1_u8); | ^^^^ @@ -50,48 +44,8 @@ LL - offset_of!((u8, u8), 1_u8); LL + offset_of!((u8, u8), 1); | -error[E0609]: no field `1e2` on type `(u8, u8)` - --> $DIR/offset-of-tuple-field.rs:12:35 - | -LL | builtin # offset_of((u8, u8), 1e2); - | ^^^ - | - = note: available fields are: `0`, `1` - -error[E0609]: no field `_0` on type `(u8, u8)` - --> $DIR/offset-of-tuple-field.rs:13:35 - | -LL | builtin # offset_of((u8, u8), _0); - | ^^ - | -help: a field with a similar name exists - | -LL - builtin # offset_of((u8, u8), _0); -LL + builtin # offset_of((u8, u8), 0); - | - -error[E0609]: no field `01` on type `(u8, u8)` - --> $DIR/offset-of-tuple-field.rs:14:35 - | -LL | builtin # offset_of((u8, u8), 01); - | ^^ - | - = note: available fields are: `0`, `1` - -error[E0609]: no field `1_` on type `(u8, u8)` - --> $DIR/offset-of-tuple-field.rs:15:35 - | -LL | builtin # offset_of((u8, u8), 1_u8); - | ^^^^ - | -help: a field with a similar name exists - | -LL - builtin # offset_of((u8, u8), 1_u8); -LL + builtin # offset_of((u8, u8), 1); - | - error[E0609]: no field `2` on type `(u8, u16)` - --> $DIR/offset-of-tuple-field.rs:18:47 + --> $DIR/offset-of-tuple-field.rs:10:47 | LL | offset_of!(((u8, u16), (u32, u16, u8)), 0.2); | ^ @@ -99,7 +53,7 @@ LL | offset_of!(((u8, u16), (u32, u16, u8)), 0.2); = note: available fields are: `0`, `1` error[E0609]: no field `1e2` on type `(u8, u16)` - --> $DIR/offset-of-tuple-field.rs:19:47 + --> $DIR/offset-of-tuple-field.rs:11:47 | LL | offset_of!(((u8, u16), (u32, u16, u8)), 0.1e2); | ^^^ @@ -107,11 +61,11 @@ LL | offset_of!(((u8, u16), (u32, u16, u8)), 0.1e2); = note: available fields are: `0`, `1` error[E0609]: no field `0` on type `u8` - --> $DIR/offset-of-tuple-field.rs:21:49 + --> $DIR/offset-of-tuple-field.rs:13:49 | LL | offset_of!(((u8, u16), (u32, u16, u8)), 1.2.0); | ^ -error: aborting due to 13 previous errors +error: aborting due to 8 previous errors For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/offset-of/offset-of-tuple.rs b/tests/ui/offset-of/offset-of-tuple.rs index ddbaee97b1bb0..be668d9e08946 100644 --- a/tests/ui/offset-of/offset-of-tuple.rs +++ b/tests/ui/offset-of/offset-of-tuple.rs @@ -1,4 +1,5 @@ -#![feature(builtin_syntax)] +//@ edition: 2021.. +#![feature(forced_keywords, internal_syntax)] use std::mem::offset_of; @@ -9,9 +10,9 @@ fn main() { offset_of!((u8, u8), 1 .); //~ ERROR unexpected token: `)` // We need to put these into curly braces, otherwise only one of the // errors will be emitted and the others suppressed. - { builtin # offset_of((u8, u8), +1) }; //~ ERROR leading `+` is not supported - { builtin # offset_of((u8, u8), 1.) }; //~ ERROR offset_of expects dot-separated field and variant names - { builtin # offset_of((u8, u8), 1 .) }; //~ ERROR unexpected token: `)` + { k#offset_of((u8, u8), +1) }; //~ ERROR leading `+` is not supported + { k#offset_of((u8, u8), 1.) }; //~ ERROR offset_of expects dot-separated field and variant names + { k#offset_of((u8, u8), 1 .) }; //~ ERROR unexpected token: `)` } type ComplexTup = (((u8, u8), u8), u8); @@ -26,14 +27,15 @@ fn nested() { offset_of!(ComplexTup, 0.0 . 1.); //~ ERROR unexpected token: `)` offset_of!(ComplexTup, 0.0. 1.); //~ ERROR unexpected token: `)` + // FIXME(fmease): Update comment. // Test for builtin too to ensure that the builtin syntax can also handle these cases // We need to put these into curly braces, otherwise only one of the // errors will be emitted and the others suppressed. - { builtin # offset_of(ComplexTup, 0.0.1.) }; //~ ERROR unexpected token: `)` - { builtin # offset_of(ComplexTup, 0 .0.1.) }; //~ ERROR unexpected token: `)` - { builtin # offset_of(ComplexTup, 0 . 0.1.) }; //~ ERROR unexpected token: `)` - { builtin # offset_of(ComplexTup, 0. 0.1.) }; //~ ERROR unexpected token: `)` - { builtin # offset_of(ComplexTup, 0.0 .1.) }; //~ ERROR unexpected token: `)` - { builtin # offset_of(ComplexTup, 0.0 . 1.) }; //~ ERROR unexpected token: `)` - { builtin # offset_of(ComplexTup, 0.0. 1.) }; //~ ERROR unexpected token: `)` + { k#offset_of(ComplexTup, 0.0.1.) }; //~ ERROR unexpected token: `)` + { k#offset_of(ComplexTup, 0 .0.1.) }; //~ ERROR unexpected token: `)` + { k#offset_of(ComplexTup, 0 . 0.1.) }; //~ ERROR unexpected token: `)` + { k#offset_of(ComplexTup, 0. 0.1.) }; //~ ERROR unexpected token: `)` + { k#offset_of(ComplexTup, 0.0 .1.) }; //~ ERROR unexpected token: `)` + { k#offset_of(ComplexTup, 0.0 . 1.) }; //~ ERROR unexpected token: `)` + { k#offset_of(ComplexTup, 0.0. 1.) }; //~ ERROR unexpected token: `)` } diff --git a/tests/ui/offset-of/offset-of-tuple.stderr b/tests/ui/offset-of/offset-of-tuple.stderr index f90f2db1c6c35..db46373449218 100644 --- a/tests/ui/offset-of/offset-of-tuple.stderr +++ b/tests/ui/offset-of/offset-of-tuple.stderr @@ -1,71 +1,71 @@ error: leading `+` is not supported - --> $DIR/offset-of-tuple.rs:12:37 + --> $DIR/offset-of-tuple.rs:13:29 | -LL | { builtin # offset_of((u8, u8), +1) }; - | ^ unexpected `+` +LL | { k#offset_of((u8, u8), +1) }; + | ^ unexpected `+` | help: try removing the `+` | -LL - { builtin # offset_of((u8, u8), +1) }; -LL + { builtin # offset_of((u8, u8), 1) }; +LL - { k#offset_of((u8, u8), +1) }; +LL + { k#offset_of((u8, u8), 1) }; | error: offset_of expects dot-separated field and variant names - --> $DIR/offset-of-tuple.rs:13:38 + --> $DIR/offset-of-tuple.rs:14:30 | -LL | { builtin # offset_of((u8, u8), 1.) }; - | ^ +LL | { k#offset_of((u8, u8), 1.) }; + | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:14:40 + --> $DIR/offset-of-tuple.rs:15:32 | -LL | { builtin # offset_of((u8, u8), 1 .) }; - | ^ +LL | { k#offset_of((u8, u8), 1 .) }; + | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:32:45 + --> $DIR/offset-of-tuple.rs:34:37 | -LL | { builtin # offset_of(ComplexTup, 0.0.1.) }; - | ^ +LL | { k#offset_of(ComplexTup, 0.0.1.) }; + | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:33:46 + --> $DIR/offset-of-tuple.rs:35:38 | -LL | { builtin # offset_of(ComplexTup, 0 .0.1.) }; - | ^ +LL | { k#offset_of(ComplexTup, 0 .0.1.) }; + | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:34:47 + --> $DIR/offset-of-tuple.rs:36:39 | -LL | { builtin # offset_of(ComplexTup, 0 . 0.1.) }; - | ^ +LL | { k#offset_of(ComplexTup, 0 . 0.1.) }; + | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:35:46 + --> $DIR/offset-of-tuple.rs:37:38 | -LL | { builtin # offset_of(ComplexTup, 0. 0.1.) }; - | ^ +LL | { k#offset_of(ComplexTup, 0. 0.1.) }; + | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:36:46 + --> $DIR/offset-of-tuple.rs:38:38 | -LL | { builtin # offset_of(ComplexTup, 0.0 .1.) }; - | ^ +LL | { k#offset_of(ComplexTup, 0.0 .1.) }; + | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:37:47 + --> $DIR/offset-of-tuple.rs:39:39 | -LL | { builtin # offset_of(ComplexTup, 0.0 . 1.) }; - | ^ +LL | { k#offset_of(ComplexTup, 0.0 . 1.) }; + | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:38:46 + --> $DIR/offset-of-tuple.rs:40:38 | -LL | { builtin # offset_of(ComplexTup, 0.0. 1.) }; - | ^ +LL | { k#offset_of(ComplexTup, 0.0. 1.) }; + | ^ error: no rules expected `+` - --> $DIR/offset-of-tuple.rs:6:26 + --> $DIR/offset-of-tuple.rs:7:26 | LL | offset_of!((u8, u8), +1); | ^ no rules expected this token in macro call @@ -75,61 +75,61 @@ note: while trying to match meta-variable `$fields:expr` = note: this macro expects a container type and a (nested) field path, like `offset_of!(Type, field)` error: offset_of expects dot-separated field and variant names - --> $DIR/offset-of-tuple.rs:7:26 + --> $DIR/offset-of-tuple.rs:8:26 | LL | offset_of!((u8, u8), -1); | ^^ error: offset_of expects dot-separated field and variant names - --> $DIR/offset-of-tuple.rs:8:27 + --> $DIR/offset-of-tuple.rs:9:27 | LL | offset_of!((u8, u8), 1.); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:9:29 + --> $DIR/offset-of-tuple.rs:10:29 | LL | offset_of!((u8, u8), 1 .); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:21:34 + --> $DIR/offset-of-tuple.rs:22:34 | LL | offset_of!(ComplexTup, 0.0.1.); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:22:35 + --> $DIR/offset-of-tuple.rs:23:35 | LL | offset_of!(ComplexTup, 0 .0.1.); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:23:36 + --> $DIR/offset-of-tuple.rs:24:36 | LL | offset_of!(ComplexTup, 0 . 0.1.); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:24:35 + --> $DIR/offset-of-tuple.rs:25:35 | LL | offset_of!(ComplexTup, 0. 0.1.); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:25:35 + --> $DIR/offset-of-tuple.rs:26:35 | LL | offset_of!(ComplexTup, 0.0 .1.); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:26:36 + --> $DIR/offset-of-tuple.rs:27:36 | LL | offset_of!(ComplexTup, 0.0 . 1.); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:27:35 + --> $DIR/offset-of-tuple.rs:28:35 | LL | offset_of!(ComplexTup, 0.0. 1.); | ^ diff --git a/tests/ui/parser/builtin-syntax.rs b/tests/ui/parser/builtin-syntax.rs deleted file mode 100644 index 897dab8ec50ae..0000000000000 --- a/tests/ui/parser/builtin-syntax.rs +++ /dev/null @@ -1,9 +0,0 @@ -#![feature(builtin_syntax)] - -fn main() { - builtin # foobar(); //~ ERROR unknown `builtin #` construct -} - -fn not_identifier() { - builtin # {}(); //~ ERROR expected identifier after -} diff --git a/tests/ui/parser/builtin-syntax.stderr b/tests/ui/parser/builtin-syntax.stderr deleted file mode 100644 index ee3764a62216a..0000000000000 --- a/tests/ui/parser/builtin-syntax.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: unknown `builtin #` construct `foobar` - --> $DIR/builtin-syntax.rs:4:5 - | -LL | builtin # foobar(); - | ^^^^^^^^^^^^^^^^ - -error: expected identifier after `builtin #` - --> $DIR/builtin-syntax.rs:8:15 - | -LL | builtin # {}(); - | ^ - -error: aborting due to 2 previous errors - diff --git a/tests/ui/suggestions/if-then-neeing-semi.stderr b/tests/ui/suggestions/if-then-neeing-semi.stderr index 0556d6c50b1ce..105e2756fb1db 100644 --- a/tests/ui/suggestions/if-then-neeing-semi.stderr +++ b/tests/ui/suggestions/if-then-neeing-semi.stderr @@ -52,12 +52,10 @@ help: consider `await`ing on the `Future` | LL | async_dummy2().await | ++++++ -help: consider removing this semicolon and boxing the expressions +help: consider removing this semicolon | -LL ~ Box::new(async_dummy()) -LL | -LL | } else { -LL ~ Box::new(async_dummy2()) +LL - async_dummy(); +LL + async_dummy() | error[E0308]: `if` and `else` have incompatible types diff --git a/tests/ui/suggestions/match-prev-arm-needing-semi.stderr b/tests/ui/suggestions/match-prev-arm-needing-semi.stderr index f70f6a1e1570b..c468433fd4421 100644 --- a/tests/ui/suggestions/match-prev-arm-needing-semi.stderr +++ b/tests/ui/suggestions/match-prev-arm-needing-semi.stderr @@ -52,12 +52,10 @@ help: consider `await`ing on the `Future` | LL | false => async_dummy2().await, | ++++++ -help: consider removing this semicolon and boxing the expressions +help: consider removing this semicolon | -LL ~ Box::new(async_dummy()) -LL | -LL | } -LL ~ false => Box::new(async_dummy2()), +LL - async_dummy(); +LL + async_dummy() | error[E0308]: `match` arms have incompatible types diff --git a/tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr b/tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr index 03249bd39a8c7..196eafa5bba68 100644 --- a/tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr +++ b/tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr @@ -11,6 +11,10 @@ help: a method is available that returns `>::A` | LL | fn func(&self) -> Self::A; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ consider calling `Trait::func` +help: consider returning the local binding `self` + | +LL | fn funq(&self) -> Self::A { self } + | ++++ error[E0308]: mismatched types --> $DIR/trait-with-missing-associated-type-restriction.rs:14:9 diff --git a/tests/ui/traits/next-solver/normalization-shadowing/is-global-norm-concrete-alias-to-generic.current.stderr b/tests/ui/traits/next-solver/normalization-shadowing/is-global-norm-concrete-alias-to-generic.current.stderr index 0ad8e3444600b..972a42d0f6621 100644 --- a/tests/ui/traits/next-solver/normalization-shadowing/is-global-norm-concrete-alias-to-generic.current.stderr +++ b/tests/ui/traits/next-solver/normalization-shadowing/is-global-norm-concrete-alias-to-generic.current.stderr @@ -13,6 +13,10 @@ LL | x = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html = note: the associated type `<(*const T,) as Id>::This` is defined as `(*const T,)` in the implementation, but the where-bound `(*const T,)` shadows this definition see issue #152409 for more information +help: use a trailing comma to create a tuple with one element + | +LL | (x,) + | + ++ error: aborting due to 1 previous error diff --git a/tests/ui/traits/next-solver/rigid-alias-in-same-type-modulo-infer.next.stderr b/tests/ui/traits/next-solver/rigid-alias-in-same-type-modulo-infer.next.stderr new file mode 100644 index 0000000000000..fe8ef6aff748d --- /dev/null +++ b/tests/ui/traits/next-solver/rigid-alias-in-same-type-modulo-infer.next.stderr @@ -0,0 +1,16 @@ +error[E0271]: type mismatch resolving `::AtLifetime<'static> == ExistentialLifetime<_>` + --> $DIR/rigid-alias-in-same-type-modulo-infer.rs:16:9 + | +LL | ExistentialLifetime(ExistentialLifetime(())) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `ExistentialLifetime<_>`, found associated type + | + = note: expected struct `ExistentialLifetime<_>` + found associated type `::AtLifetime<'static>` +help: consider constraining the associated type `::AtLifetime<'static>` to `ExistentialLifetime<_>` + | +LL | impl = ExistentialLifetime<_>>> ExistentialLifetime { + | ++++++++++++++++++++++++++++++++++++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/next-solver/rigid-alias-in-same-type-modulo-infer.old.stderr b/tests/ui/traits/next-solver/rigid-alias-in-same-type-modulo-infer.old.stderr new file mode 100644 index 0000000000000..fe8ef6aff748d --- /dev/null +++ b/tests/ui/traits/next-solver/rigid-alias-in-same-type-modulo-infer.old.stderr @@ -0,0 +1,16 @@ +error[E0271]: type mismatch resolving `::AtLifetime<'static> == ExistentialLifetime<_>` + --> $DIR/rigid-alias-in-same-type-modulo-infer.rs:16:9 + | +LL | ExistentialLifetime(ExistentialLifetime(())) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `ExistentialLifetime<_>`, found associated type + | + = note: expected struct `ExistentialLifetime<_>` + found associated type `::AtLifetime<'static>` +help: consider constraining the associated type `::AtLifetime<'static>` to `ExistentialLifetime<_>` + | +LL | impl = ExistentialLifetime<_>>> ExistentialLifetime { + | ++++++++++++++++++++++++++++++++++++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/next-solver/rigid-alias-in-same-type-modulo-infer.rs b/tests/ui/traits/next-solver/rigid-alias-in-same-type-modulo-infer.rs new file mode 100644 index 0000000000000..c083234411fe8 --- /dev/null +++ b/tests/ui/traits/next-solver/rigid-alias-in-same-type-modulo-infer.rs @@ -0,0 +1,21 @@ +//! Regression test for . +// Avoids ICE on SameTypeModuloInfer assertion rigidity of two types. +// +//@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +trait HasLifetime { + type AtLifetime<'a>; +} + +pub struct ExistentialLifetime(S::AtLifetime<'static>); + +impl ExistentialLifetime { + fn new() -> ExistentialLifetime { + ExistentialLifetime(ExistentialLifetime(())) + //~^ ERROR: type mismatch resolving `::AtLifetime<'static> == ExistentialLifetime<_>` [E0271] + } +} + +fn main() {} diff --git a/tests/ui/unpretty/exhaustive.expanded.stdout b/tests/ui/unpretty/exhaustive.expanded.stdout index 7eca271aeda13..3551d40dffbfc 100644 --- a/tests/ui/unpretty/exhaustive.expanded.stdout +++ b/tests/ui/unpretty/exhaustive.expanded.stdout @@ -10,12 +10,13 @@ // errors that only occur once we get past the AST. #![feature(auto_traits)] -#![feature(builtin_syntax)] +#![feature(internal_syntax)] #![feature(const_trait_impl)] #![feature(coroutines)] #![feature(decl_macro)] #![feature(deref_patterns)] #![feature(explicit_tail_calls)] +#![feature(forced_keywords)] #![feature(gen_blocks)] #![feature(more_qualified_paths)] #![feature(never_patterns)] @@ -131,7 +132,7 @@ mod expressions { fn expr_cast() { let expr; expr as T; expr as T; } /// ExprKind::Type - fn expr_type() { let expr; builtin # type_ascribe(expr, T); } + fn expr_type() { let expr; k#type_ascribe(expr, T); } /// ExprKind::Let fn expr_let() { @@ -315,7 +316,7 @@ mod expressions { - const { builtin # offset_of(T, field) }; + const { k#offset_of(T, field) }; } /// ExprKind::MacCall fn expr_mac_call() { "..."; "..."; "..."; } diff --git a/tests/ui/unpretty/exhaustive.hir.stderr b/tests/ui/unpretty/exhaustive.hir.stderr index 5ca4b080a95e5..276bc5b5d2573 100644 --- a/tests/ui/unpretty/exhaustive.hir.stderr +++ b/tests/ui/unpretty/exhaustive.hir.stderr @@ -1,17 +1,17 @@ error[E0697]: closures cannot be static - --> $DIR/exhaustive.rs:209:9 + --> $DIR/exhaustive.rs:210:9 | LL | static || value; | ^^^^^^^^^ error[E0697]: closures cannot be static - --> $DIR/exhaustive.rs:210:9 + --> $DIR/exhaustive.rs:211:9 | LL | static move || value; | ^^^^^^^^^^^^^^ error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/exhaustive.rs:239:13 + --> $DIR/exhaustive.rs:240:13 | LL | fn expr_await() { | --------------- this is not `async` @@ -20,19 +20,19 @@ LL | fut.await; | ^^^^^ only allowed inside `async` functions and blocks error: in expressions, `_` can only be used on the left-hand side of an assignment - --> $DIR/exhaustive.rs:290:9 + --> $DIR/exhaustive.rs:291:9 | LL | _; | ^ `_` not allowed here error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/exhaustive.rs:300:9 + --> $DIR/exhaustive.rs:301:9 | LL | x::(); | ^^^^^ only `Fn` traits may use parentheses error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/exhaustive.rs:301:9 + --> $DIR/exhaustive.rs:302:9 | LL | x::(T, T) -> T; | ^^^^^^^^^^^^^^ only `Fn` traits may use parentheses @@ -44,31 +44,31 @@ LL + x:: -> T; | error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/exhaustive.rs:302:9 + --> $DIR/exhaustive.rs:303:9 | LL | crate::() -> ()::expressions::() -> ()::expr_path; | ^^^^^^^^^^^^^^^ only `Fn` traits may use parentheses error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/exhaustive.rs:302:26 + --> $DIR/exhaustive.rs:303:26 | LL | crate::() -> ()::expressions::() -> ()::expr_path; | ^^^^^^^^^^^^^^^^^^^^^ only `Fn` traits may use parentheses error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/exhaustive.rs:305:9 + --> $DIR/exhaustive.rs:306:9 | LL | core::()::marker::()::PhantomData; | ^^^^^^^^ only `Fn` traits may use parentheses error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/exhaustive.rs:305:19 + --> $DIR/exhaustive.rs:306:19 | LL | core::()::marker::()::PhantomData; | ^^^^^^^^^^ only `Fn` traits may use parentheses error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks - --> $DIR/exhaustive.rs:392:9 + --> $DIR/exhaustive.rs:393:9 | LL | yield; | ^^^^^ @@ -79,7 +79,7 @@ LL | #[coroutine] fn expr_yield() { | ++++++++++++ error[E0703]: invalid ABI: found `C++` - --> $DIR/exhaustive.rs:472:23 + --> $DIR/exhaustive.rs:473:23 | LL | unsafe extern "C++" {} | ^^^^^ invalid ABI @@ -87,7 +87,7 @@ LL | unsafe extern "C++" {} = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions error: `..` patterns are not allowed here - --> $DIR/exhaustive.rs:674:13 + --> $DIR/exhaustive.rs:675:13 | LL | let ..; | ^^ @@ -95,13 +95,13 @@ LL | let ..; = note: only allowed in tuple, tuple struct, and slice patterns error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/exhaustive.rs:789:16 + --> $DIR/exhaustive.rs:790:16 | LL | let _: T() -> !; | ^^^^^^^^ only `Fn` traits may use parentheses error[E0562]: `impl Trait` is not allowed in the type of variable bindings - --> $DIR/exhaustive.rs:803:16 + --> $DIR/exhaustive.rs:804:16 | LL | let _: impl Send; | ^^^^^^^^^ @@ -112,7 +112,7 @@ LL | let _: impl Send; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0562]: `impl Trait` is not allowed in the type of variable bindings - --> $DIR/exhaustive.rs:804:16 + --> $DIR/exhaustive.rs:805:16 | LL | let _: impl Send + 'static; | ^^^^^^^^^^^^^^^^^^^ @@ -123,7 +123,7 @@ LL | let _: impl Send + 'static; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0562]: `impl Trait` is not allowed in the type of variable bindings - --> $DIR/exhaustive.rs:805:16 + --> $DIR/exhaustive.rs:806:16 | LL | let _: impl 'static + Send; | ^^^^^^^^^^^^^^^^^^^ @@ -134,7 +134,7 @@ LL | let _: impl 'static + Send; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0562]: `impl Trait` is not allowed in the type of variable bindings - --> $DIR/exhaustive.rs:806:16 + --> $DIR/exhaustive.rs:807:16 | LL | let _: impl ?Sized; | ^^^^^^^^^^^ @@ -145,7 +145,7 @@ LL | let _: impl ?Sized; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0562]: `impl Trait` is not allowed in the type of variable bindings - --> $DIR/exhaustive.rs:807:16 + --> $DIR/exhaustive.rs:808:16 | LL | let _: impl [const] Clone; | ^^^^^^^^^^^^^^^^^^ @@ -156,7 +156,7 @@ LL | let _: impl [const] Clone; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0562]: `impl Trait` is not allowed in the type of variable bindings - --> $DIR/exhaustive.rs:808:16 + --> $DIR/exhaustive.rs:809:16 | LL | let _: impl for<'a> Send; | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unpretty/exhaustive.hir.stdout b/tests/ui/unpretty/exhaustive.hir.stdout index b1c956c2fe9f1..6af4d3b5b81de 100644 --- a/tests/ui/unpretty/exhaustive.hir.stdout +++ b/tests/ui/unpretty/exhaustive.hir.stdout @@ -1,8 +1,9 @@ -#![attr = Feature([auto_traits#0, builtin_syntax#0, const_trait_impl#0, +#![attr = Feature([auto_traits#0, internal_syntax#0, const_trait_impl#0, coroutines#0, decl_macro#0, deref_patterns#0, explicit_tail_calls#0, -gen_blocks#0, more_qualified_paths#0, never_patterns#0, pattern_types#0, -pattern_type_macro#0, prelude_import#0, specialization#0, trace_macros#0, -trait_alias#0, try_blocks#0, try_blocks_heterogeneous#0, yeet_expr#0])] +forced_keywords#0, gen_blocks#0, more_qualified_paths#0, never_patterns#0, +pattern_types#0, pattern_type_macro#0, prelude_import#0, specialization#0, +trace_macros#0, trait_alias#0, try_blocks#0, try_blocks_heterogeneous#0, +yeet_expr#0])] #![attr = LintCheck([LintCheck {lint_name: LintName { tool: None, name: "incomplete_features" }, kind: Allow}, LintCheck {lint_name: LintName { tool: None, name: "unused_attributes" }, diff --git a/tests/ui/unpretty/exhaustive.rs b/tests/ui/unpretty/exhaustive.rs index 03ef63874ac0a..15f684fc3dd72 100644 --- a/tests/ui/unpretty/exhaustive.rs +++ b/tests/ui/unpretty/exhaustive.rs @@ -9,12 +9,13 @@ // errors that only occur once we get past the AST. #![feature(auto_traits)] -#![feature(builtin_syntax)] +#![feature(internal_syntax)] #![feature(const_trait_impl)] #![feature(coroutines)] #![feature(decl_macro)] #![feature(deref_patterns)] #![feature(explicit_tail_calls)] +#![feature(forced_keywords)] #![feature(gen_blocks)] #![feature(more_qualified_paths)] #![feature(never_patterns)] @@ -144,7 +145,7 @@ mod expressions { /// ExprKind::Type fn expr_type() { let expr; - builtin # type_ascribe(expr, T); + k#type_ascribe(expr, T); } /// ExprKind::Let