diff --git a/Cargo.lock b/Cargo.lock index 81f19668c24b..8be13e84596d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -674,7 +674,7 @@ checksum = "fe6d2e5af09e8c8ad56c969f2157a3d4238cebc7c55f0a517728c38f7b200f81" dependencies = [ "serde", "termcolor", - "unicode-width 0.2.1", + "unicode-width 0.1.14", ] [[package]] @@ -1458,9 +1458,9 @@ dependencies = [ [[package]] name = "getopts" -version = "0.2.23" +version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cba6ae63eb948698e300f645f87c70f76630d505f23b8907cf1e193ee85048c1" +checksum = "cfe4fbac503b8d1f88e6676011885f34b7174f46e59956bba534ba83abded4df" dependencies = [ "unicode-width 0.2.1", ] @@ -2167,6 +2167,7 @@ version = "0.1.0" dependencies = [ "html5ever", "regex", + "urlencoding", ] [[package]] @@ -3248,6 +3249,7 @@ dependencies = [ "rustc_driver_impl", "rustc_public", "rustc_public_bridge", + "rustc_windows_rc", "tikv-jemalloc-sys", ] @@ -3623,6 +3625,7 @@ name = "rustc_driver" version = "0.0.0" dependencies = [ "rustc_driver_impl", + "rustc_windows_rc", ] [[package]] @@ -4409,7 +4412,6 @@ dependencies = [ "rustc_middle", "rustc_query_system", "rustc_serialize", - "rustc_session", "rustc_span", "tracing", ] @@ -4681,6 +4683,7 @@ dependencies = [ name = "rustc_type_ir" version = "0.0.0" dependencies = [ + "arrayvec", "bitflags", "derive-where", "ena", @@ -4718,6 +4721,13 @@ dependencies = [ "semver", ] +[[package]] +name = "rustc_windows_rc" +version = "0.0.0" +dependencies = [ + "cc", +] + [[package]] name = "rustdoc" version = "0.0.0" @@ -5518,11 +5528,10 @@ checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ - "cfg-if", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -5825,6 +5834,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + [[package]] name = "utf-8" version = "0.7.6" @@ -5969,9 +5984,9 @@ dependencies = [ [[package]] name = "wasm-component-ld" -version = "0.5.16" +version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14cd35d6cae91109a0ffd207b573cf3c741cab7e921dd376ea7aaf2c52a3408c" +checksum = "1c9208f87cac2332fd80dcf36d54e9163d3446e28301e0c6e424984425738984" dependencies = [ "anyhow", "clap", @@ -5979,9 +5994,9 @@ dependencies = [ "libc", "tempfile", "wasi-preview1-component-adapter-provider", - "wasmparser 0.237.0", + "wasmparser 0.239.0", "wat", - "windows-sys 0.59.0", + "windows-sys 0.60.2", "winsplit", "wit-component", "wit-parser", @@ -6006,24 +6021,24 @@ dependencies = [ [[package]] name = "wasm-encoder" -version = "0.237.0" +version = "0.239.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efe92d1321afa53ffc88a57c497bb7330c3cf84c98ffdba4a4caf6a0684fad3c" +checksum = "5be00faa2b4950c76fe618c409d2c3ea5a3c9422013e079482d78544bb2d184c" dependencies = [ "leb128fmt", - "wasmparser 0.237.0", + "wasmparser 0.239.0", ] [[package]] name = "wasm-metadata" -version = "0.237.0" +version = "0.239.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cc0b0a0c4f35ca6efa7a797671372915d4e9659dba2d59edc6fafc931d19997" +checksum = "20b3ec880a9ac69ccd92fbdbcf46ee833071cf09f82bb005b2327c7ae6025ae2" dependencies = [ "anyhow", "indexmap", - "wasm-encoder 0.237.0", - "wasmparser 0.237.0", + "wasm-encoder 0.239.0", + "wasmparser 0.239.0", ] [[package]] @@ -6048,9 +6063,9 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.237.0" +version = "0.239.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d2a40ca0d2bdf4b0bf36c13a737d0b2c58e4c8aaefe1c57f336dd75369ca250" +checksum = "8c9d90bb93e764f6beabf1d02028c70a2156a6583e63ac4218dd07ef733368b0" dependencies = [ "bitflags", "hashbrown", @@ -6061,22 +6076,22 @@ dependencies = [ [[package]] name = "wast" -version = "237.0.0" +version = "239.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcf66f545acbd55082485cb9a6daab54579cb8628a027162253e8e9f5963c767" +checksum = "9139176fe8a2590e0fb174cdcaf373b224cb93c3dde08e4297c1361d2ba1ea5d" dependencies = [ "bumpalo", "leb128fmt", "memchr", "unicode-width 0.2.1", - "wasm-encoder 0.237.0", + "wasm-encoder 0.239.0", ] [[package]] name = "wat" -version = "1.237.0" +version = "1.239.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27975186f549e4b8d6878b627be732863883c72f7bf4dcf8f96e5f8242f73da9" +checksum = "3e1c941927d34709f255558166f8901a2005f8ab4a9650432e9281b7cc6f3b75" dependencies = [ "wast", ] @@ -6565,9 +6580,9 @@ dependencies = [ [[package]] name = "wit-component" -version = "0.237.0" +version = "0.239.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfb7674f76c10e82fe00b256a9d4ffb2b8d037d42ab8e9a83ebb3be35c9d0bf6" +checksum = "88a866b19dba2c94d706ec58c92a4c62ab63e482b4c935d2a085ac94caecb136" dependencies = [ "anyhow", "bitflags", @@ -6576,17 +6591,17 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "wasm-encoder 0.237.0", + "wasm-encoder 0.239.0", "wasm-metadata", - "wasmparser 0.237.0", + "wasmparser 0.239.0", "wit-parser", ] [[package]] name = "wit-parser" -version = "0.237.0" +version = "0.239.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce2596a5bc7c24cc965b56ad6ff9e32394c4e401764f89620a888519c6e849ab" +checksum = "55c92c939d667b7bf0c6bf2d1f67196529758f99a2a45a3355cc56964fd5315d" dependencies = [ "anyhow", "id-arena", @@ -6597,7 +6612,7 @@ dependencies = [ "serde_derive", "serde_json", "unicode-xid", - "wasmparser 0.237.0", + "wasmparser 0.239.0", ] [[package]] diff --git a/compiler/rustc/Cargo.toml b/compiler/rustc/Cargo.toml index 3ca752354466..e3214d1ab9ce 100644 --- a/compiler/rustc/Cargo.toml +++ b/compiler/rustc/Cargo.toml @@ -33,3 +33,8 @@ llvm = ['rustc_driver_impl/llvm'] max_level_info = ['rustc_driver_impl/max_level_info'] rustc_randomized_layouts = ['rustc_driver_impl/rustc_randomized_layouts'] # tidy-alphabetical-end + +[build-dependencies] +# tidy-alphabetical-start +rustc_windows_rc = { path = "../rustc_windows_rc" } +# tidy-alphabetical-end diff --git a/compiler/rustc/build.rs b/compiler/rustc/build.rs index 8b7d28d2b8aa..9b5def53e3cb 100644 --- a/compiler/rustc/build.rs +++ b/compiler/rustc/build.rs @@ -1,4 +1,6 @@ -use std::env; +use std::{env, path}; + +use rustc_windows_rc::{VersionInfoFileType, compile_windows_resource_file}; fn main() { let target_os = env::var("CARGO_CFG_TARGET_OS"); @@ -13,6 +15,18 @@ fn main() { // Add a manifest file to rustc.exe. fn set_windows_exe_options() { + set_windows_resource(); + set_windows_manifest(); +} + +fn set_windows_resource() { + let stem = path::PathBuf::from("rustc_main_resource"); + let file_description = "rustc"; + let res_file = compile_windows_resource_file(&stem, file_description, VersionInfoFileType::App); + println!("cargo:rustc-link-arg={}", res_file.display()); +} + +fn set_windows_manifest() { static WINDOWS_MANIFEST_FILE: &str = "Windows Manifest.xml"; let mut manifest = env::current_dir().unwrap(); diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 802a6fa32498..3e8fddd9954e 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2284,6 +2284,54 @@ pub struct FnSig { pub span: Span, } +impl FnSig { + /// Return a span encompassing the header, or where to insert it if empty. + pub fn header_span(&self) -> Span { + match self.header.ext { + Extern::Implicit(span) | Extern::Explicit(_, span) => { + return self.span.with_hi(span.hi()); + } + Extern::None => {} + } + + match self.header.safety { + Safety::Unsafe(span) | Safety::Safe(span) => return self.span.with_hi(span.hi()), + Safety::Default => {} + }; + + if let Some(coroutine_kind) = self.header.coroutine_kind { + return self.span.with_hi(coroutine_kind.span().hi()); + } + + if let Const::Yes(span) = self.header.constness { + return self.span.with_hi(span.hi()); + } + + self.span.shrink_to_lo() + } + + /// The span of the header's safety, or where to insert it if empty. + pub fn safety_span(&self) -> Span { + match self.header.safety { + Safety::Unsafe(span) | Safety::Safe(span) => span, + Safety::Default => { + // Insert after the `coroutine_kind` if available. + if let Some(extern_span) = self.header.ext.span() { + return extern_span.shrink_to_lo(); + } + + // Insert right at the front of the signature. + self.header_span().shrink_to_hi() + } + } + } + + /// The span of the header's extern, or where to insert it if empty. + pub fn extern_span(&self) -> Span { + self.header.ext.span().unwrap_or(self.safety_span().shrink_to_hi()) + } +} + /// A constraint on an associated item. /// /// ### Examples @@ -3526,6 +3574,13 @@ impl Extern { None => Extern::Implicit(span), } } + + pub fn span(self) -> Option { + match self { + Extern::None => None, + Extern::Implicit(span) | Extern::Explicit(_, span) => Some(span), + } + } } /// A function header. @@ -3534,12 +3589,12 @@ impl Extern { /// included in this struct (e.g., `async unsafe fn` or `const extern "C" fn`). #[derive(Clone, Copy, Encodable, Decodable, Debug, Walkable)] pub struct FnHeader { - /// Whether this is `unsafe`, or has a default safety. - pub safety: Safety, - /// Whether this is `async`, `gen`, or nothing. - pub coroutine_kind: Option, /// The `const` keyword, if any pub constness: Const, + /// Whether this is `async`, `gen`, or nothing. + pub coroutine_kind: Option, + /// Whether this is `unsafe`, or has a default safety. + pub safety: Safety, /// The `extern` keyword and corresponding ABI string, if any. pub ext: Extern, } @@ -3553,38 +3608,6 @@ impl FnHeader { || matches!(constness, Const::Yes(_)) || !matches!(ext, Extern::None) } - - /// Return a span encompassing the header, or none if all options are default. - pub fn span(&self) -> Option { - fn append(a: &mut Option, b: Span) { - *a = match a { - None => Some(b), - Some(x) => Some(x.to(b)), - } - } - - let mut full_span = None; - - match self.safety { - Safety::Unsafe(span) | Safety::Safe(span) => append(&mut full_span, span), - Safety::Default => {} - }; - - if let Some(coroutine_kind) = self.coroutine_kind { - append(&mut full_span, coroutine_kind.span()); - } - - if let Const::Yes(span) = self.constness { - append(&mut full_span, span); - } - - match self.ext { - Extern::Implicit(span) | Extern::Explicit(_, span) => append(&mut full_span, span), - Extern::None => {} - } - - full_span - } } impl Default for FnHeader { diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 3674814b796c..bb6b25baf013 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -1536,7 +1536,13 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::LangItem::Range } } - (None, Some(..), Closed) => hir::LangItem::RangeToInclusive, + (None, Some(..), Closed) => { + if self.tcx.features().new_range() { + hir::LangItem::RangeToInclusiveCopy + } else { + hir::LangItem::RangeToInclusive + } + } (Some(e1), Some(e2), Closed) => { if self.tcx.features().new_range() { hir::LangItem::RangeInclusiveCopy @@ -1560,13 +1566,26 @@ impl<'hir> LoweringContext<'_, 'hir> { }; let fields = self.arena.alloc_from_iter( - e1.iter().map(|e| (sym::start, e)).chain(e2.iter().map(|e| (sym::end, e))).map( - |(s, e)| { + e1.iter() + .map(|e| (sym::start, e)) + .chain(e2.iter().map(|e| { + ( + if matches!( + lang_item, + hir::LangItem::RangeInclusiveCopy | hir::LangItem::RangeToInclusiveCopy + ) { + sym::last + } else { + sym::end + }, + e, + ) + })) + .map(|(s, e)| { let expr = self.lower_expr(e); let ident = Ident::new(s, self.lower_span(e.span)); self.expr_field(ident, expr, e.span) - }, - ), + }), ); hir::ExprKind::Struct( diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 72f20a95ff02..4e2243e87873 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2101,17 +2101,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { { return; } - if self.tcx.features().more_maybe_bounds() { - return; - } } RelaxedBoundPolicy::Forbidden(reason) => { - if self.tcx.features().more_maybe_bounds() { - return; - } - match reason { RelaxedBoundForbiddenReason::TraitObjectTy => { + if self.tcx.features().more_maybe_bounds() { + return; + } + self.dcx().span_err( span, "relaxed bounds are not permitted in trait object types", @@ -2119,6 +2116,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { return; } RelaxedBoundForbiddenReason::SuperTrait => { + if self.tcx.features().more_maybe_bounds() { + return; + } + let mut diag = self.dcx().struct_span_err( span, "relaxed bounds are not permitted in supertrait bounds", diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index e5f1fcdc4b40..8dcf3e3aa388 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -57,8 +57,6 @@ ast_passes_auto_super_lifetime = auto traits cannot have super traits or lifetim .label = {ast_passes_auto_super_lifetime} .suggestion = remove the super traits or lifetime bounds -ast_passes_bad_c_variadic = defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention - ast_passes_body_in_extern = incorrect `{$kind}` inside `extern` block .cannot_have = cannot have a body .invalid = the invalid body @@ -66,6 +64,19 @@ ast_passes_body_in_extern = incorrect `{$kind}` inside `extern` block ast_passes_bound_in_context = bounds on `type`s in {$ctx} have no effect +ast_passes_c_variadic_associated_function = associated functions cannot have a C variable argument list + +ast_passes_c_variadic_bad_extern = `...` is not supported for `extern "{$abi}"` functions + .label = `extern "{$abi}"` because of this + .help = only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list + +ast_passes_c_variadic_must_be_unsafe = + functions with a C variable argument list must be unsafe + .suggestion = add the `unsafe` keyword to this definition + +ast_passes_c_variadic_no_extern = `...` is not supported for non-extern functions + .help = only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list + ast_passes_const_and_c_variadic = functions cannot be both `const` and C-variadic .const = `const` because of this .variadic = C-variadic because of this @@ -84,6 +95,10 @@ ast_passes_const_without_body = ast_passes_constraint_on_negative_bound = associated type constraints not allowed on negative bounds +ast_passes_coroutine_and_c_variadic = functions cannot be both `{$coroutine_kind}` and C-variadic + .const = `{$coroutine_kind}` because of this + .variadic = C-variadic because of this + ast_passes_equality_in_where = equality constraints are not yet supported in `where` clauses .label = not supported .suggestion = if `{$ident}` is an associated type you're trying to set, use the associated type binding syntax diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 6133cc3548b5..a6ef89b553db 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -492,7 +492,7 @@ impl<'a> AstValidator<'a> { } if !spans.is_empty() { - let header_span = sig.header.span().unwrap_or(sig.span.shrink_to_lo()); + let header_span = sig.header_span(); let suggestion_span = header_span.shrink_to_hi().to(sig.decl.output.span()); let padding = if header_span.is_empty() { "" } else { " " }; @@ -665,46 +665,73 @@ impl<'a> AstValidator<'a> { /// - Non-const /// - Either foreign, or free and `unsafe extern "C"` semantically fn check_c_variadic_type(&self, fk: FnKind<'a>) { - let variadic_spans: Vec<_> = fk - .decl() - .inputs - .iter() - .filter(|arg| matches!(arg.ty.kind, TyKind::CVarArgs)) - .map(|arg| arg.span) - .collect(); + // `...` is already rejected when it is not the final parameter. + let variadic_param = match fk.decl().inputs.last() { + Some(param) if matches!(param.ty.kind, TyKind::CVarArgs) => param, + _ => return, + }; - if variadic_spans.is_empty() { - return; - } + let FnKind::Fn(fn_ctxt, _, Fn { sig, .. }) = fk else { + // Unreachable because the parser already rejects `...` in closures. + unreachable!("C variable argument list cannot be used in closures") + }; - if let Some(header) = fk.header() - && let Const::Yes(const_span) = header.constness - { - let mut spans = variadic_spans.clone(); - spans.push(const_span); + // C-variadics are not yet implemented in const evaluation. + if let Const::Yes(const_span) = sig.header.constness { self.dcx().emit_err(errors::ConstAndCVariadic { - spans, + spans: vec![const_span, variadic_param.span], const_span, - variadic_spans: variadic_spans.clone(), + variadic_span: variadic_param.span, }); } - match (fk.ctxt(), fk.header()) { - (Some(FnCtxt::Foreign), _) => return, - (Some(FnCtxt::Free), Some(header)) => match header.ext { - Extern::Explicit(StrLit { symbol_unescaped: sym::C, .. }, _) - | Extern::Explicit(StrLit { symbol_unescaped: sym::C_dash_unwind, .. }, _) - | Extern::Implicit(_) - if matches!(header.safety, Safety::Unsafe(_)) => - { - return; - } - _ => {} - }, - _ => {} - }; + if let Some(coroutine_kind) = sig.header.coroutine_kind { + self.dcx().emit_err(errors::CoroutineAndCVariadic { + spans: vec![coroutine_kind.span(), variadic_param.span], + coroutine_kind: coroutine_kind.as_str(), + coroutine_span: coroutine_kind.span(), + variadic_span: variadic_param.span, + }); + } - self.dcx().emit_err(errors::BadCVariadic { span: variadic_spans }); + match fn_ctxt { + FnCtxt::Foreign => return, + FnCtxt::Free => match sig.header.ext { + Extern::Implicit(_) => { + if !matches!(sig.header.safety, Safety::Unsafe(_)) { + self.dcx().emit_err(errors::CVariadicMustBeUnsafe { + span: variadic_param.span, + unsafe_span: sig.safety_span(), + }); + } + } + Extern::Explicit(StrLit { symbol_unescaped, .. }, _) => { + if !matches!(symbol_unescaped, sym::C | sym::C_dash_unwind) { + self.dcx().emit_err(errors::CVariadicBadExtern { + span: variadic_param.span, + abi: symbol_unescaped, + extern_span: sig.extern_span(), + }); + } + + if !matches!(sig.header.safety, Safety::Unsafe(_)) { + self.dcx().emit_err(errors::CVariadicMustBeUnsafe { + span: variadic_param.span, + unsafe_span: sig.safety_span(), + }); + } + } + Extern::None => { + let err = errors::CVariadicNoExtern { span: variadic_param.span }; + self.dcx().emit_err(err); + } + }, + FnCtxt::Assoc(_) => { + // For now, C variable argument lists are unsupported in associated functions. + let err = errors::CVariadicAssociatedFunction { span: variadic_param.span }; + self.dcx().emit_err(err); + } + } } fn check_item_named(&self, ident: Ident, kind: &str) { diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index ae8f056cb4e6..ae805042c549 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -319,10 +319,44 @@ pub(crate) struct ExternItemAscii { } #[derive(Diagnostic)] -#[diag(ast_passes_bad_c_variadic)] -pub(crate) struct BadCVariadic { +#[diag(ast_passes_c_variadic_associated_function)] +pub(crate) struct CVariadicAssociatedFunction { #[primary_span] - pub span: Vec, + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_c_variadic_no_extern)] +#[help] +pub(crate) struct CVariadicNoExtern { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_c_variadic_must_be_unsafe)] +pub(crate) struct CVariadicMustBeUnsafe { + #[primary_span] + pub span: Span, + + #[suggestion( + ast_passes_suggestion, + applicability = "maybe-incorrect", + code = "unsafe ", + style = "verbose" + )] + pub unsafe_span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_c_variadic_bad_extern)] +#[help] +pub(crate) struct CVariadicBadExtern { + #[primary_span] + pub span: Span, + pub abi: Symbol, + #[label] + pub extern_span: Span, } #[derive(Diagnostic)] @@ -656,7 +690,19 @@ pub(crate) struct ConstAndCVariadic { #[label(ast_passes_const)] pub const_span: Span, #[label(ast_passes_variadic)] - pub variadic_spans: Vec, + pub variadic_span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_coroutine_and_c_variadic)] +pub(crate) struct CoroutineAndCVariadic { + #[primary_span] + pub spans: Vec, + pub coroutine_kind: &'static str, + #[label(ast_passes_const)] + pub coroutine_span: Span, + #[label(ast_passes_variadic)] + pub variadic_span: Span, } #[derive(Diagnostic)] diff --git a/compiler/rustc_attr_parsing/messages.ftl b/compiler/rustc_attr_parsing/messages.ftl index 7fa1293463cc..839a5d23c3b4 100644 --- a/compiler/rustc_attr_parsing/messages.ftl +++ b/compiler/rustc_attr_parsing/messages.ftl @@ -247,3 +247,7 @@ attr_parsing_raw_dylib_only_windows = attr_parsing_whole_archive_needs_static = linking modifier `whole-archive` is only compatible with `static` linking kind + +attr_parsing_limit_invalid = + `limit` must be a non-negative integer + .label = {$error_str} diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index ffdacff71521..d5d51f2e79ab 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -218,6 +218,7 @@ impl AttributeParser for NakedParser { sym::rustc_std_internal_symbol, // FIXME(#82232, #143834): temporarily renamed to mitigate `#[align]` nameres ambiguity sym::rustc_align, + sym::rustc_align_static, // obviously compatible with self sym::naked, // documentation diff --git a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs index 2fed09b85e87..d23a7ae72f8c 100644 --- a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs +++ b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs @@ -1,6 +1,40 @@ -use rustc_feature::AttributeType; +use std::num::IntErrorKind; + +use rustc_hir::limit::Limit; use super::prelude::*; +use crate::session_diagnostics::LimitInvalid; + +impl AcceptContext<'_, '_, S> { + fn parse_limit_int(&self, nv: &NameValueParser) -> Option { + let Some(limit) = nv.value_as_str() else { + self.expected_string_literal(nv.value_span, Some(nv.value_as_lit())); + return None; + }; + + let error_str = match limit.as_str().parse() { + Ok(i) => return Some(Limit::new(i)), + Err(e) => match e.kind() { + IntErrorKind::PosOverflow => "`limit` is too large", + IntErrorKind::Empty => "`limit` must be a non-negative integer", + IntErrorKind::InvalidDigit => "not a valid integer", + IntErrorKind::NegOverflow => { + panic!( + "`limit` should never negatively overflow since we're parsing into a usize and we'd get Empty instead" + ) + } + IntErrorKind::Zero => { + panic!("zero is a valid `limit` so should have returned Ok() when parsing") + } + kind => panic!("unimplemented IntErrorKind variant: {:?}", kind), + }, + }; + + self.emit_err(LimitInvalid { span: self.attr_span, value_span: nv.value_span, error_str }); + + None + } +} pub(crate) struct CrateNameParser; @@ -11,8 +45,8 @@ impl SingleAttributeParser for CrateNameParser { const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name"); const TYPE: AttributeType = AttributeType::CrateLevel; - // FIXME: crate name is allowed on all targets and ignored, - // even though it should only be valid on crates of course + // because it's a crate-level attribute, we already warn about it. + // Putting target limitations here would give duplicate warnings const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option { @@ -34,3 +68,111 @@ impl SingleAttributeParser for CrateNameParser { }) } } + +pub(crate) struct RecursionLimitParser; + +impl SingleAttributeParser for RecursionLimitParser { + const PATH: &[Symbol] = &[sym::recursion_limit]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; + const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N", "https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute"); + const TYPE: AttributeType = AttributeType::CrateLevel; + + // because it's a crate-level attribute, we already warn about it. + // Putting target limitations here would give duplicate warnings + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option { + let ArgParser::NameValue(nv) = args else { + cx.expected_name_value(cx.attr_span, None); + return None; + }; + + Some(AttributeKind::RecursionLimit { + limit: cx.parse_limit_int(nv)?, + attr_span: cx.attr_span, + limit_span: nv.value_span, + }) + } +} + +pub(crate) struct MoveSizeLimitParser; + +impl SingleAttributeParser for MoveSizeLimitParser { + const PATH: &[Symbol] = &[sym::move_size_limit]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N"); + const TYPE: AttributeType = AttributeType::CrateLevel; + + // because it's a crate-level attribute, we already warn about it. + // Putting target limitations here would give duplicate warnings + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option { + let ArgParser::NameValue(nv) = args else { + cx.expected_name_value(cx.attr_span, None); + return None; + }; + + Some(AttributeKind::MoveSizeLimit { + limit: cx.parse_limit_int(nv)?, + attr_span: cx.attr_span, + limit_span: nv.value_span, + }) + } +} + +pub(crate) struct TypeLengthLimitParser; + +impl SingleAttributeParser for TypeLengthLimitParser { + const PATH: &[Symbol] = &[sym::type_length_limit]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; + const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N"); + const TYPE: AttributeType = AttributeType::CrateLevel; + + // because it's a crate-level attribute, we already warn about it. + // Putting target limitations here would give duplicate warnings + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option { + let ArgParser::NameValue(nv) = args else { + cx.expected_name_value(cx.attr_span, None); + return None; + }; + + Some(AttributeKind::TypeLengthLimit { + limit: cx.parse_limit_int(nv)?, + attr_span: cx.attr_span, + limit_span: nv.value_span, + }) + } +} + +pub(crate) struct PatternComplexityLimitParser; + +impl SingleAttributeParser for PatternComplexityLimitParser { + const PATH: &[Symbol] = &[sym::pattern_complexity_limit]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N"); + const TYPE: AttributeType = AttributeType::CrateLevel; + + // because it's a crate-level attribute, we already warn about it. + // Putting target limitations here would give duplicate warnings + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option { + let ArgParser::NameValue(nv) = args else { + cx.expected_name_value(cx.attr_span, None); + return None; + }; + + Some(AttributeKind::PatternComplexityLimit { + limit: cx.parse_limit_int(nv)?, + attr_span: cx.attr_span, + limit_span: nv.value_span, + }) + } +} diff --git a/compiler/rustc_attr_parsing/src/attributes/prelude.rs b/compiler/rustc_attr_parsing/src/attributes/prelude.rs index 6aef7e7a67be..8f040ffb9d41 100644 --- a/compiler/rustc_attr_parsing/src/attributes/prelude.rs +++ b/compiler/rustc_attr_parsing/src/attributes/prelude.rs @@ -1,8 +1,7 @@ -// templates -#[doc(hidden)] -pub(super) use rustc_feature::{AttributeTemplate, template}; // data structures #[doc(hidden)] +pub(super) use rustc_feature::{AttributeTemplate, AttributeType, template}; +#[doc(hidden)] pub(super) use rustc_hir::attrs::AttributeKind; #[doc(hidden)] pub(super) use rustc_hir::lints::AttributeLintKind; diff --git a/compiler/rustc_attr_parsing/src/attributes/repr.rs b/compiler/rustc_attr_parsing/src/attributes/repr.rs index 23aabd155976..0330e2515c7d 100644 --- a/compiler/rustc_attr_parsing/src/attributes/repr.rs +++ b/compiler/rustc_attr_parsing/src/attributes/repr.rs @@ -331,3 +331,30 @@ impl AttributeParser for AlignParser { Some(AttributeKind::Align { align, span }) } } + +#[derive(Default)] +pub(crate) struct AlignStaticParser(AlignParser); + +impl AlignStaticParser { + const PATH: &'static [Symbol] = &[sym::rustc_align_static]; + const TEMPLATE: AttributeTemplate = AlignParser::TEMPLATE; + + fn parse<'c, S: Stage>( + &mut self, + cx: &'c mut AcceptContext<'_, '_, S>, + args: &'c ArgParser<'_>, + ) { + self.0.parse(cx, args) + } +} + +impl AttributeParser for AlignStaticParser { + const ATTRIBUTES: AcceptMapping = &[(Self::PATH, Self::TEMPLATE, Self::parse)]; + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowList(&[Allow(Target::Static), Allow(Target::ForeignStatic)]); + + fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option { + let (align, span) = self.0.0?; + Some(AttributeKind::Align { align, span }) + } +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 7f5b810f244f..d2b35090135d 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -24,7 +24,10 @@ use crate::attributes::codegen_attrs::{ UsedParser, }; use crate::attributes::confusables::ConfusablesParser; -use crate::attributes::crate_level::CrateNameParser; +use crate::attributes::crate_level::{ + CrateNameParser, MoveSizeLimitParser, PatternComplexityLimitParser, RecursionLimitParser, + TypeLengthLimitParser, +}; use crate::attributes::deprecation::DeprecationParser; use crate::attributes::dummy::DummyParser; use crate::attributes::inline::{InlineParser, RustcForceInlineParser}; @@ -47,7 +50,7 @@ use crate::attributes::proc_macro_attrs::{ ProcMacroAttributeParser, ProcMacroDeriveParser, ProcMacroParser, RustcBuiltinMacroParser, }; use crate::attributes::prototype::CustomMirParser; -use crate::attributes::repr::{AlignParser, ReprParser}; +use crate::attributes::repr::{AlignParser, AlignStaticParser, ReprParser}; use crate::attributes::rustc_internal::{ RustcLayoutScalarValidRangeEnd, RustcLayoutScalarValidRangeStart, RustcObjectLifetimeDefaultParser, @@ -149,6 +152,7 @@ attribute_parsers!( pub(crate) static ATTRIBUTE_PARSERS = [ // tidy-alphabetical-start AlignParser, + AlignStaticParser, BodyStabilityParser, ConfusablesParser, ConstStabilityParser, @@ -181,10 +185,13 @@ attribute_parsers!( Single, Single, Single, + Single, Single, Single, Single, + Single, Single, + Single, Single, Single, Single, @@ -194,6 +201,7 @@ attribute_parsers!( Single, Single, Single, + Single, Single>, Single>, Single>, @@ -346,7 +354,10 @@ impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> { /// must be delayed until after HIR is built. This method will take care of the details of /// that. pub(crate) fn emit_lint(&mut self, lint: AttributeLintKind, span: Span) { - if matches!(self.stage.should_emit(), ShouldEmit::Nothing) { + if !matches!( + self.stage.should_emit(), + ShouldEmit::ErrorsAndLints | ShouldEmit::EarlyFatal { also_emit_lints: true } + ) { return; } let id = self.target_id; @@ -670,20 +681,20 @@ pub enum ShouldEmit { /// /// Only relevant when early parsing, in late parsing equivalent to `ErrorsAndLints`. /// Late parsing is never fatal, and instead tries to emit as many diagnostics as possible. - EarlyFatal, + EarlyFatal { also_emit_lints: bool }, /// The operation will emit errors and lints. /// This is usually what you need. ErrorsAndLints, /// The operation will emit *not* errors and lints. - /// Use this if you are *sure* that this operation will be called at a different time with `ShouldEmit::Emit`. + /// Use this if you are *sure* that this operation will be called at a different time with `ShouldEmit::ErrorsAndLints`. Nothing, } impl ShouldEmit { pub(crate) fn emit_err(&self, diag: Diag<'_>) -> ErrorGuaranteed { match self { - ShouldEmit::EarlyFatal if diag.level() == Level::DelayedBug => diag.emit(), - ShouldEmit::EarlyFatal => diag.upgrade_to_fatal().emit(), + ShouldEmit::EarlyFatal { .. } if diag.level() == Level::DelayedBug => diag.emit(), + ShouldEmit::EarlyFatal { .. } => diag.upgrade_to_fatal().emit(), ShouldEmit::ErrorsAndLints => diag.emit(), ShouldEmit::Nothing => diag.delay_as_bug(), } diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index a9dee23bf6a3..32ea9005a97d 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -930,3 +930,13 @@ pub(crate) struct ImportNameTypeRaw { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(attr_parsing_limit_invalid)] +pub(crate) struct LimitInvalid<'a> { + #[primary_span] + pub span: Span, + #[label] + pub value_span: Span, + pub error_str: &'a str, +} diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 9990f4cb3f2a..f57456949bb5 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -615,7 +615,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { } // Type-test failed. Report the error. - let erased_generic_kind = infcx.tcx.erase_regions(type_test.generic_kind); + let erased_generic_kind = infcx.tcx.erase_and_anonymize_regions(type_test.generic_kind); // Skip duplicate-ish errors. if deduplicate_errors.insert(( diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs index 95c5366a6c8e..0af636aa734c 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs @@ -341,7 +341,7 @@ fn compute_concrete_types_from_defining_uses<'tcx>( // // FIXME(-Znext-solver): This isn't necessary after all. We can remove this check again. if let Some((prev_decl_key, prev_span)) = decls_modulo_regions.insert( - rcx.infcx.tcx.erase_regions(opaque_type_key), + rcx.infcx.tcx.erase_and_anonymize_regions(opaque_type_key), (opaque_type_key, hidden_type.span), ) && let Some((arg1, arg2)) = std::iter::zip( prev_decl_key.iter_captured_args(infcx.tcx).map(|(_, arg)| arg), diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 02be78f90b0d..8c5447fe1e9e 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1892,7 +1892,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { if is_diverging { // The signature in this call can reference region variables, // so erase them before calling a query. - let output_ty = self.tcx().erase_regions(sig.output()); + let output_ty = self.tcx().erase_and_anonymize_regions(sig.output()); if !output_ty .is_privately_uninhabited(self.tcx(), self.infcx.typing_env(self.infcx.param_env)) { @@ -1986,7 +1986,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let op_arg_ty = self.normalize(op_arg_ty, term_location); let category = if call_source.from_hir_call() { - ConstraintCategory::CallArgument(Some(self.infcx.tcx.erase_regions(func_ty))) + ConstraintCategory::CallArgument(Some( + self.infcx.tcx.erase_and_anonymize_regions(func_ty), + )) } else { ConstraintCategory::Boring }; @@ -2120,7 +2122,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // Erase the regions from `ty` to get a global type. The // `Sized` bound in no way depends on precise regions, so this // shouldn't affect `is_sized`. - let erased_ty = tcx.erase_regions(ty); + let erased_ty = tcx.erase_and_anonymize_regions(ty); // FIXME(#132279): Using `Ty::is_sized` causes us to incorrectly handle opaques here. if !erased_ty.is_sized(tcx, self.infcx.typing_env(self.infcx.param_env)) { // in current MIR construction, all non-control-flow rvalue diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 6415e55e0b03..a6c8e7d29cc7 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -565,6 +565,7 @@ fn make_format_args( &used, &args, &pieces, + &invalid_refs, detect_foreign_fmt, str_style, fmt_str, @@ -645,6 +646,7 @@ fn report_missing_placeholders( used: &[bool], args: &FormatArguments, pieces: &[parse::Piece<'_>], + invalid_refs: &[(usize, Option, PositionUsedAs, FormatArgPositionKind)], detect_foreign_fmt: bool, str_style: Option, fmt_str: &str, @@ -762,6 +764,31 @@ fn report_missing_placeholders( diag.span_label(fmt_span, "formatting specifier missing"); } + if !found_foreign && invalid_refs.is_empty() { + // Show example if user didn't use any format specifiers + let show_example = used.iter().all(|used| !used); + + if !show_example { + if unused.len() > 1 { + diag.note(format!("consider adding {} format specifiers", unused.len())); + } + } else { + let original_fmt_str = + if fmt_str.len() >= 1 { &fmt_str[..fmt_str.len() - 1] } else { "" }; + + let msg = if unused.len() == 1 { + "a format specifier".to_string() + } else { + format!("{} format specifiers", unused.len()) + }; + + let sugg = format!("\"{}{}\"", original_fmt_str, "{}".repeat(unused.len())); + let msg = format!("format specifiers use curly braces, consider adding {msg}"); + + diag.span_suggestion_verbose(fmt_span, msg, sugg, Applicability::MaybeIncorrect); + } + } + diag.emit(); } diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs index 37bab5be5421..11b868f81a97 100644 --- a/compiler/rustc_builtin_macros/src/source_util.rs +++ b/compiler/rustc_builtin_macros/src/source_util.rs @@ -1,3 +1,5 @@ +//! The implementation of built-in macros which relate to the file system. + use std::path::{Path, PathBuf}; use std::rc::Rc; use std::sync::Arc; @@ -11,9 +13,11 @@ use rustc_expand::base::{ }; use rustc_expand::module::DirOwnership; use rustc_lint_defs::BuiltinLintDiag; -use rustc_parse::parser::{ForceCollect, Parser}; +use rustc_parse::lexer::StripTokens; +use rustc_parse::parser::ForceCollect; use rustc_parse::{new_parser_from_file, unwrap_or_emit_fatal, utf8_error}; use rustc_session::lint::builtin::INCOMPLETE_INCLUDE; +use rustc_session::parse::ParseSess; use rustc_span::source_map::SourceMap; use rustc_span::{ByteSymbol, Pos, Span, Symbol}; use smallvec::SmallVec; @@ -23,11 +27,7 @@ use crate::util::{ check_zero_tts, get_single_str_from_tts, get_single_str_spanned_from_tts, parse_expr, }; -// These macros all relate to the file system; they either return -// the column/row/filename of the expression, or they include -// a given file into the current one. - -/// line!(): expands to the current line number +/// Expand `line!()` to the current line number. pub(crate) fn expand_line( cx: &mut ExtCtxt<'_>, sp: Span, @@ -42,7 +42,7 @@ pub(crate) fn expand_line( ExpandResult::Ready(MacEager::expr(cx.expr_u32(topmost, loc.line as u32))) } -/* column!(): expands to the current column number */ +/// Expand `column!()` to the current column number. pub(crate) fn expand_column( cx: &mut ExtCtxt<'_>, sp: Span, @@ -57,9 +57,7 @@ pub(crate) fn expand_column( ExpandResult::Ready(MacEager::expr(cx.expr_u32(topmost, loc.col.to_usize() as u32 + 1))) } -/// file!(): expands to the current filename */ -/// The source_file (`loc.file`) contains a bunch more information we could spit -/// out if we wanted. +/// Expand `file!()` to the current filename. pub(crate) fn expand_file( cx: &mut ExtCtxt<'_>, sp: Span, @@ -81,6 +79,7 @@ pub(crate) fn expand_file( ))) } +/// Expand `stringify!($input)`. pub(crate) fn expand_stringify( cx: &mut ExtCtxt<'_>, sp: Span, @@ -91,6 +90,7 @@ pub(crate) fn expand_stringify( ExpandResult::Ready(MacEager::expr(cx.expr_str(sp, Symbol::intern(&s)))) } +/// Expand `module_path!()` to (a textual representation of) the current module path. pub(crate) fn expand_mod( cx: &mut ExtCtxt<'_>, sp: Span, @@ -104,9 +104,9 @@ pub(crate) fn expand_mod( ExpandResult::Ready(MacEager::expr(cx.expr_str(sp, Symbol::intern(&string)))) } -/// include! : parse the given file as an expr -/// This is generally a bad idea because it's going to behave -/// unhygienically. +/// Expand `include!($input)`. +/// +/// This works in item and expression position. Notably, it doesn't work in pattern position. pub(crate) fn expand_include<'cx>( cx: &'cx mut ExtCtxt<'_>, sp: Span, @@ -116,39 +116,48 @@ pub(crate) fn expand_include<'cx>( let ExpandResult::Ready(mac) = get_single_str_from_tts(cx, sp, tts, "include!") else { return ExpandResult::Retry(()); }; - let file = match mac { - Ok(file) => file, + let path = match mac { + Ok(path) => path, Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)), }; // The file will be added to the code map by the parser - let file = match resolve_path(&cx.sess, file.as_str(), sp) { - Ok(f) => f, + let path = match resolve_path(&cx.sess, path.as_str(), sp) { + Ok(path) => path, Err(err) => { let guar = err.emit(); return ExpandResult::Ready(DummyResult::any(sp, guar)); } }; - let p = unwrap_or_emit_fatal(new_parser_from_file(cx.psess(), &file, Some(sp))); // If in the included file we have e.g., `mod bar;`, - // then the path of `bar.rs` should be relative to the directory of `file`. + // then the path of `bar.rs` should be relative to the directory of `path`. // See https://github.com/rust-lang/rust/pull/69838/files#r395217057 for a discussion. // `MacroExpander::fully_expand_fragment` later restores, so "stack discipline" is maintained. - let dir_path = file.parent().unwrap_or(&file).to_owned(); + let dir_path = path.parent().unwrap_or(&path).to_owned(); cx.current_expansion.module = Rc::new(cx.current_expansion.module.with_dir_path(dir_path)); cx.current_expansion.dir_ownership = DirOwnership::Owned { relative: None }; struct ExpandInclude<'a> { - p: Parser<'a>, + psess: &'a ParseSess, + path: PathBuf, node_id: ast::NodeId, + span: Span, } impl<'a> MacResult for ExpandInclude<'a> { - fn make_expr(mut self: Box>) -> Option> { - let expr = parse_expr(&mut self.p).ok()?; - if self.p.token != token::Eof { - self.p.psess.buffer_lint( + fn make_expr(self: Box>) -> Option> { + let mut p = unwrap_or_emit_fatal(new_parser_from_file( + self.psess, + &self.path, + // Don't strip frontmatter for backward compatibility, `---` may be the start of a + // manifold negation. FIXME: Ideally, we wouldn't strip shebangs here either. + StripTokens::Shebang, + Some(self.span), + )); + let expr = parse_expr(&mut p).ok()?; + if p.token != token::Eof { + p.psess.buffer_lint( INCOMPLETE_INCLUDE, - self.p.token.span, + p.token.span, self.node_id, BuiltinLintDiag::IncompleteInclude, ); @@ -156,24 +165,27 @@ pub(crate) fn expand_include<'cx>( Some(expr) } - fn make_items(mut self: Box>) -> Option; 1]>> { + fn make_items(self: Box>) -> Option; 1]>> { + let mut p = unwrap_or_emit_fatal(new_parser_from_file( + self.psess, + &self.path, + StripTokens::ShebangAndFrontmatter, + Some(self.span), + )); let mut ret = SmallVec::new(); loop { - match self.p.parse_item(ForceCollect::No) { + match p.parse_item(ForceCollect::No) { Err(err) => { err.emit(); break; } Ok(Some(item)) => ret.push(item), Ok(None) => { - if self.p.token != token::Eof { - self.p - .dcx() - .create_err(errors::ExpectedItem { - span: self.p.token.span, - token: &pprust::token_to_string(&self.p.token), - }) - .emit(); + if p.token != token::Eof { + p.dcx().emit_err(errors::ExpectedItem { + span: p.token.span, + token: &pprust::token_to_string(&p.token), + }); } break; @@ -184,10 +196,17 @@ pub(crate) fn expand_include<'cx>( } } - ExpandResult::Ready(Box::new(ExpandInclude { p, node_id: cx.current_expansion.lint_node_id })) + ExpandResult::Ready(Box::new(ExpandInclude { + psess: cx.psess(), + path, + node_id: cx.current_expansion.lint_node_id, + span: sp, + })) } -/// `include_str!`: read the given file, insert it as a literal string expr +/// Expand `include_str!($input)` to the content of the UTF-8-encoded file given by path `$input` as a string literal. +/// +/// This works in expression, pattern and statement position. pub(crate) fn expand_include_str( cx: &mut ExtCtxt<'_>, sp: Span, @@ -206,6 +225,7 @@ pub(crate) fn expand_include_str( Ok((bytes, bsp)) => match std::str::from_utf8(&bytes) { Ok(src) => { let interned_src = Symbol::intern(src); + // MacEager converts the expr into a pat if need be. MacEager::expr(cx.expr_str(cx.with_def_site_ctxt(bsp), interned_src)) } Err(utf8err) => { @@ -218,6 +238,9 @@ pub(crate) fn expand_include_str( }) } +/// Expand `include_bytes!($input)` to the content of the file given by path `$input`. +/// +/// This works in expression, pattern and statement position. pub(crate) fn expand_include_bytes( cx: &mut ExtCtxt<'_>, sp: Span, @@ -237,6 +260,7 @@ pub(crate) fn expand_include_bytes( // Don't care about getting the span for the raw bytes, // because the console can't really show them anyway. let expr = cx.expr(sp, ast::ExprKind::IncludedBytes(ByteSymbol::intern(&bytes))); + // MacEager converts the expr into a pat if need be. MacEager::expr(expr) } Err(dummy) => dummy, diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs index 619277eba8b8..7fe8fc122b3c 100644 --- a/compiler/rustc_codegen_gcc/src/consts.rs +++ b/compiler/rustc_codegen_gcc/src/consts.rs @@ -81,6 +81,8 @@ impl<'gcc, 'tcx> StaticCodegenMethods for CodegenCx<'gcc, 'tcx> { if global.to_rvalue().get_type() != val_llty { global.to_rvalue().set_type(val_llty); } + + // NOTE: Alignment from attributes has already been applied to the allocation. set_global_alignment(self, global, alloc.align); global.global_set_initializer_rvalue(value); diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs index 093f902bc3d8..93202483eed8 100644 --- a/compiler/rustc_codegen_gcc/src/type_of.rs +++ b/compiler/rustc_codegen_gcc/src/type_of.rs @@ -240,7 +240,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { // Make sure lifetimes are erased, to avoid generating distinct LLVM // types for Rust types that only differ in the choice of lifetimes. - let normal_ty = cx.tcx.erase_regions(self.ty); + let normal_ty = cx.tcx.erase_and_anonymize_regions(self.ty); let mut defer = None; let ty = if self.ty != normal_ty { diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 9ec7b0f80aee..dc9bb743560d 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -452,6 +452,8 @@ impl<'ll> CodegenCx<'ll, '_> { self.statics_to_rauw.borrow_mut().push((g, new_g)); new_g }; + + // NOTE: Alignment from attributes has already been applied to the allocation. set_global_alignment(self, g, alloc.align); llvm::set_initializer(g, v); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index caa3369f413a..dc3a84b6a151 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -103,16 +103,17 @@ fn build_fixed_size_array_di_node<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, unique_type_id: UniqueTypeId<'tcx>, array_type: Ty<'tcx>, + span: Span, ) -> DINodeCreationResult<'ll> { let ty::Array(element_type, len) = array_type.kind() else { bug!("build_fixed_size_array_di_node() called with non-ty::Array type `{:?}`", array_type) }; - let element_type_di_node = type_di_node(cx, *element_type); + let element_type_di_node = spanned_type_di_node(cx, *element_type, span); return_if_di_node_created_in_meantime!(cx, unique_type_id); - let (size, align) = cx.size_and_align_of(array_type); + let (size, align) = cx.spanned_size_and_align_of(array_type, span); let upper_bound = len .try_to_target_usize(cx.tcx) @@ -447,7 +448,7 @@ pub(crate) fn spanned_type_di_node<'ll, 'tcx>( build_basic_type_di_node(cx, t) } ty::Tuple(elements) if elements.is_empty() => build_basic_type_di_node(cx, t), - ty::Array(..) => build_fixed_size_array_di_node(cx, unique_type_id, t), + ty::Array(..) => build_fixed_size_array_di_node(cx, unique_type_id, t, span), ty::Slice(_) | ty::Str => build_slice_type_di_node(cx, t, unique_type_id), ty::Dynamic(..) => build_dyn_type_di_node(cx, t, unique_type_id), ty::Foreign(..) => build_foreign_type_di_node(cx, t, unique_type_id), @@ -1435,7 +1436,7 @@ fn build_vtable_type_di_node<'ll, 'tcx>( let vtable_entries = if let Some(poly_trait_ref) = poly_trait_ref { let trait_ref = poly_trait_ref.with_self_ty(tcx, ty); - let trait_ref = tcx.erase_regions(trait_ref); + let trait_ref = tcx.erase_and_anonymize_regions(trait_ref); tcx.vtable_entries(trait_ref) } else { @@ -1562,7 +1563,7 @@ pub(crate) fn apply_vcall_visibility_metadata<'ll, 'tcx>( // Unwrap potential addrspacecast let vtable = find_vtable_behind_cast(vtable); let trait_ref_self = trait_ref.with_self_ty(cx.tcx, ty); - let trait_ref_self = cx.tcx.erase_regions(trait_ref_self); + let trait_ref_self = cx.tcx.erase_and_anonymize_regions(trait_ref_self); let trait_def_id = trait_ref_self.def_id; let trait_vis = cx.tcx.visibility(trait_def_id); diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs index 4e7096da502d..84998b5499bd 100644 --- a/compiler/rustc_codegen_llvm/src/type_of.rs +++ b/compiler/rustc_codegen_llvm/src/type_of.rs @@ -7,6 +7,7 @@ use rustc_middle::bug; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_middle::ty::{self, CoroutineArgsExt, Ty, TypeVisitableExt}; +use rustc_span::{DUMMY_SP, Span}; use tracing::debug; use crate::common::*; @@ -149,7 +150,11 @@ impl<'a, 'tcx> CodegenCx<'a, 'tcx> { } pub(crate) fn size_and_align_of(&self, ty: Ty<'tcx>) -> (Size, Align) { - let layout = self.layout_of(ty); + self.spanned_size_and_align_of(ty, DUMMY_SP) + } + + pub(crate) fn spanned_size_and_align_of(&self, ty: Ty<'tcx>, span: Span) -> (Size, Align) { + let layout = self.spanned_layout_of(ty, span); (layout.size, layout.align.abi) } } @@ -226,7 +231,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> { // Make sure lifetimes are erased, to avoid generating distinct LLVM // types for Rust types that only differ in the choice of lifetimes. - let normal_ty = cx.tcx.erase_regions(self.ty); + let normal_ty = cx.tcx.erase_and_anonymize_regions(self.ty); let mut defer = None; let llty = if self.ty != normal_ty { diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 2dfbc5816432..5462163f4ffd 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -9,7 +9,7 @@ ar_archive_writer = "0.5" bitflags = "2.4.1" bstr = "1.11.3" # `cc` updates often break things, so we pin it here. Cargo enforces "max 1 semver-compat version -# per crate", so if you change this, you need to also change it in `rustc_llvm`. +# per crate", so if you change this, you need to also change it in `rustc_llvm` and `rustc_windows_rc`. cc = "=1.2.16" itertools = "0.12" pathdiff = "0.2.0" diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 9681d89ce35f..91ed71ac3e54 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -4,6 +4,7 @@ use either::{Left, Right}; use rustc_abi::{Align, HasDataLayout, Size, TargetDataLayout}; use rustc_errors::DiagCtxtHandle; use rustc_hir::def_id::DefId; +use rustc_hir::limit::Limit; use rustc_middle::mir::interpret::{ErrorHandled, InvalidMetaKind, ReportedErrorInfo}; use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::layout::{ @@ -12,7 +13,6 @@ use rustc_middle::ty::layout::{ }; use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypingEnv, Variance}; use rustc_middle::{mir, span_bug}; -use rustc_session::Limit; use rustc_span::Span; use rustc_target::callconv::FnAbi; use tracing::{debug, trace}; diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 2c1e5087e1c6..ebcdb9461d02 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -953,6 +953,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // # Global allocations if let Some(global_alloc) = self.tcx.try_get_global_alloc(id) { + // NOTE: `static` alignment from attributes has already been applied to the allocation. let (size, align) = global_alloc.size_and_align(*self.tcx, self.typing_env); let mutbl = global_alloc.mutability(*self.tcx, self.typing_env); let kind = match global_alloc { @@ -1501,8 +1502,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // `get_bytes_mut` will clear the provenance, which is correct, // since we don't want to keep any provenance at the target. // This will also error if copying partial provenance is not supported. - let provenance = - src_alloc.provenance().prepare_copy(src_range, dest_offset, num_copies, self); + let provenance = src_alloc + .provenance() + .prepare_copy(src_range, dest_offset, num_copies, self) + .map_err(|e| e.to_interp_error(src_alloc_id))?; // Prepare a copy of the initialization mask. let init = src_alloc.init_mask().prepare_copy(src_range); diff --git a/compiler/rustc_const_eval/src/interpret/traits.rs b/compiler/rustc_const_eval/src/interpret/traits.rs index e4b5c82853a2..870f9a396ae2 100644 --- a/compiler/rustc_const_eval/src/interpret/traits.rs +++ b/compiler/rustc_const_eval/src/interpret/traits.rs @@ -23,7 +23,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ) -> InterpResult<'tcx, Pointer>> { trace!("get_vtable(ty={ty:?}, dyn_ty={dyn_ty:?})"); - let (ty, dyn_ty) = self.tcx.erase_regions((ty, dyn_ty)); + let (ty, dyn_ty) = self.tcx.erase_and_anonymize_regions((ty, dyn_ty)); // All vtables must be monomorphic, bail out otherwise. ensure_monomorphic_enough(*self.tcx, ty)?; @@ -53,8 +53,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ) -> &'tcx [VtblEntry<'tcx>] { if let Some(trait_) = trait_ { let trait_ref = trait_.with_self_ty(*self.tcx, dyn_ty); - let trait_ref = - self.tcx.erase_regions(self.tcx.instantiate_bound_regions_with_erased(trait_ref)); + let trait_ref = self.tcx.erase_and_anonymize_regions( + self.tcx.instantiate_bound_regions_with_erased(trait_ref), + ); self.tcx.vtable_entries(trait_ref) } else { TyCtxt::COMMON_VTABLE_ENTRIES diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs index 72bee3454065..f667823723c0 100644 --- a/compiler/rustc_const_eval/src/interpret/util.rs +++ b/compiler/rustc_const_eval/src/interpret/util.rs @@ -1,6 +1,6 @@ use rustc_hir::def_id::LocalDefId; use rustc_middle::mir; -use rustc_middle::mir::interpret::{AllocInit, Allocation, InterpResult, Pointer}; +use rustc_middle::mir::interpret::{AllocInit, Allocation, GlobalAlloc, InterpResult, Pointer}; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{TyCtxt, TypeVisitable, TypeVisitableExt}; use tracing::debug; @@ -38,7 +38,14 @@ pub(crate) fn create_static_alloc<'tcx>( static_def_id: LocalDefId, layout: TyAndLayout<'tcx>, ) -> InterpResult<'tcx, MPlaceTy<'tcx>> { - let alloc = Allocation::try_new(layout.size, layout.align.abi, AllocInit::Uninit, ())?; + // Inherit size and align from the `GlobalAlloc::Static` so we can avoid duplicating + // the alignment attribute logic. + let (size, align) = + GlobalAlloc::Static(static_def_id.into()).size_and_align(*ecx.tcx, ecx.typing_env); + assert_eq!(size, layout.size); + assert!(align >= layout.align.abi); + + let alloc = Allocation::try_new(size, align, AllocInit::Uninit, ())?; let alloc_id = ecx.tcx.reserve_and_set_static_alloc(static_def_id.into()); assert_eq!(ecx.machine.static_root_ids, None); ecx.machine.static_root_ids = Some((alloc_id, static_def_id)); diff --git a/compiler/rustc_const_eval/src/util/type_name.rs b/compiler/rustc_const_eval/src/util/type_name.rs index 2ae6655901b6..5bcf96abd8cb 100644 --- a/compiler/rustc_const_eval/src/util/type_name.rs +++ b/compiler/rustc_const_eval/src/util/type_name.rs @@ -168,10 +168,11 @@ impl<'tcx> PrettyPrinter<'tcx> for TypeNamePrinter<'tcx> { // Bound regions are always printed (as `'_`), which gives some idea that they are special, // even though the `for` is omitted by the pretty printer. // E.g. `for<'a, 'b> fn(&'a u32, &'b u32)` is printed as "fn(&'_ u32, &'_ u32)". + let kind = region.kind(); match region.kind() { - ty::ReErased | ty::ReEarlyParam(_) => false, + ty::ReErased | ty::ReEarlyParam(_) | ty::ReStatic => false, ty::ReBound(..) => true, - _ => unreachable!(), + _ => panic!("type_name unhandled region: {kind:?}"), } } diff --git a/compiler/rustc_driver/Cargo.toml b/compiler/rustc_driver/Cargo.toml index e3ee83512952..519097198276 100644 --- a/compiler/rustc_driver/Cargo.toml +++ b/compiler/rustc_driver/Cargo.toml @@ -10,3 +10,8 @@ crate-type = ["dylib"] # tidy-alphabetical-start rustc_driver_impl = { path = "../rustc_driver_impl" } # tidy-alphabetical-end + +[build-dependencies] +# tidy-alphabetical-start +rustc_windows_rc = { path = "../rustc_windows_rc" } +# tidy-alphabetical-end diff --git a/compiler/rustc_driver/build.rs b/compiler/rustc_driver/build.rs new file mode 100644 index 000000000000..ba44fe7a86ed --- /dev/null +++ b/compiler/rustc_driver/build.rs @@ -0,0 +1,21 @@ +use std::{env, path}; + +use rustc_windows_rc::{VersionInfoFileType, compile_windows_resource_file}; + +fn main() { + let target_os = env::var("CARGO_CFG_TARGET_OS"); + let target_env = env::var("CARGO_CFG_TARGET_ENV"); + if Ok("windows") == target_os.as_deref() && Ok("msvc") == target_env.as_deref() { + set_windows_dll_options(); + } else { + // Avoid rerunning the build script every time. + println!("cargo:rerun-if-changed=build.rs"); + } +} + +fn set_windows_dll_options() { + let stem = path::PathBuf::from("rustc_driver_resource"); + let file_description = "rustc_driver"; + let res_file = compile_windows_resource_file(&stem, file_description, VersionInfoFileType::Dll); + println!("cargo:rustc-link-arg={}", res_file.display()); +} diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index f3ed60421056..d00a4c358340 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -51,6 +51,7 @@ use rustc_lint::unerased_lint_store; use rustc_metadata::creader::MetadataLoader; use rustc_metadata::locator; use rustc_middle::ty::TyCtxt; +use rustc_parse::lexer::StripTokens; use rustc_parse::{new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal}; use rustc_session::config::{ CG_OPTIONS, CrateType, ErrorOutputType, Input, OptionDesc, OutFileName, OutputType, Sysroot, @@ -1288,10 +1289,15 @@ fn warn_on_confusing_output_filename_flag( fn parse_crate_attrs<'a>(sess: &'a Session) -> PResult<'a, ast::AttrVec> { let mut parser = unwrap_or_emit_fatal(match &sess.io.input { - Input::File(file) => new_parser_from_file(&sess.psess, file, None), - Input::Str { name, input } => { - new_parser_from_source_str(&sess.psess, name.clone(), input.clone()) + Input::File(file) => { + new_parser_from_file(&sess.psess, file, StripTokens::ShebangAndFrontmatter, None) } + Input::Str { name, input } => new_parser_from_source_str( + &sess.psess, + name.clone(), + input.clone(), + StripTokens::ShebangAndFrontmatter, + ), }); parser.parse_inner_attributes() } diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 8ff21509f4a9..88f88f30a8c6 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -18,13 +18,14 @@ use rustc_feature::Features; use rustc_hir as hir; use rustc_hir::attrs::{AttributeKind, CfgEntry, Deprecation}; use rustc_hir::def::MacroKinds; +use rustc_hir::limit::Limit; use rustc_hir::{Stability, find_attr}; use rustc_lint_defs::RegisteredTools; use rustc_parse::MACRO_ARGUMENTS; use rustc_parse::parser::{ForceCollect, Parser}; +use rustc_session::Session; use rustc_session::config::CollapseMacroDebuginfo; use rustc_session::parse::ParseSess; -use rustc_session::{Limit, Session}; use rustc_span::def_id::{CrateNum, DefId, LocalDefId}; use rustc_span::edition::Edition; use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId, MacroKind}; diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index ba9d76970f0c..6eb5cd65846e 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -2,8 +2,8 @@ use std::borrow::Cow; use rustc_ast::ast; use rustc_errors::codes::*; +use rustc_hir::limit::Limit; use rustc_macros::{Diagnostic, Subdiagnostic}; -use rustc_session::Limit; use rustc_span::{Ident, MacroRulesNormalizedIdent, Span, Symbol}; #[derive(Diagnostic)] diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index dbb4a9de9e03..38e057d2776e 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -19,14 +19,15 @@ use rustc_errors::PResult; use rustc_feature::Features; use rustc_hir::Target; use rustc_hir::def::MacroKinds; +use rustc_hir::limit::Limit; use rustc_parse::parser::{ AttemptLocalParseRecovery, CommaRecoveryMode, ForceCollect, Parser, RecoverColon, RecoverComma, token_descr, }; +use rustc_session::Session; use rustc_session::lint::BuiltinLintDiag; use rustc_session::lint::builtin::{UNUSED_ATTRIBUTES, UNUSED_DOC_COMMENTS}; use rustc_session::parse::feature_err; -use rustc_session::{Limit, Session}; use rustc_span::hygiene::SyntaxContext; use rustc_span::{ErrorGuaranteed, FileName, Ident, LocalExpnId, Span, Symbol, sym}; use smallvec::SmallVec; @@ -2529,6 +2530,7 @@ impl ExpansionConfig<'_> { ExpansionConfig { crate_name, features, + // FIXME should this limit be configurable? recursion_limit: Limit::new(1024), trace_mac: false, should_test: false, diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs index 19f3cdbc5491..79ab3cab22ce 100644 --- a/compiler/rustc_expand/src/module.rs +++ b/compiler/rustc_expand/src/module.rs @@ -4,6 +4,7 @@ use std::path::{self, Path, PathBuf}; use rustc_ast::{AttrVec, Attribute, Inline, Item, ModSpans}; use rustc_attr_parsing::validate_attr; use rustc_errors::{Diag, ErrorGuaranteed}; +use rustc_parse::lexer::StripTokens; use rustc_parse::{exp, new_parser_from_file, unwrap_or_emit_fatal}; use rustc_session::Session; use rustc_session::parse::ParseSess; @@ -67,8 +68,12 @@ pub(crate) fn parse_external_mod( } // Actually parse the external file as a module. - let mut parser = - unwrap_or_emit_fatal(new_parser_from_file(&sess.psess, &mp.file_path, Some(span))); + let mut parser = unwrap_or_emit_fatal(new_parser_from_file( + &sess.psess, + &mp.file_path, + StripTokens::ShebangAndFrontmatter, + Some(span), + )); let (inner_attrs, items, inner_span) = parser.parse_mod(exp!(Eof)).map_err(|err| ModError::ParserError(err))?; attrs.extend(inner_attrs); diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 5b1d3d6d35b6..295573f44926 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -8,7 +8,7 @@ use rustc_ast::util::literal::escape_byte_str_symbol; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{Diag, ErrorGuaranteed, MultiSpan, PResult}; -use rustc_parse::lexer::nfc_normalize; +use rustc_parse::lexer::{StripTokens, nfc_normalize}; use rustc_parse::parser::Parser; use rustc_parse::{exp, new_parser_from_source_str, source_str_to_stream, unwrap_or_emit_fatal}; use rustc_proc_macro::bridge::{ @@ -485,8 +485,13 @@ impl server::FreeFunctions for Rustc<'_, '_> { fn literal_from_str(&mut self, s: &str) -> Result, ()> { let name = FileName::proc_macro_source_code(s); - let mut parser = - unwrap_or_emit_fatal(new_parser_from_source_str(self.psess(), name, s.to_owned())); + + let mut parser = unwrap_or_emit_fatal(new_parser_from_source_str( + self.psess(), + name, + s.to_owned(), + StripTokens::Nothing, + )); let first_span = parser.token.span.data(); let minus_present = parser.eat(exp!(Minus)); diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index e81003b18972..129ab7eccb57 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -621,6 +621,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), // FIXME(#82232, #143834): temporarily renamed to mitigate `#[align]` nameres ambiguity gated!(rustc_align, Normal, template!(List: &["alignment"]), DuplicatesOk, EncodeCrossCrate::No, fn_align, experimental!(rustc_align)), + gated!(rustc_align_static, Normal, template!(List: &["alignment"]), DuplicatesOk, EncodeCrossCrate::No, static_align, experimental!(rustc_align_static)), ungated!( unsafe(Edition2024) export_name, Normal, template!(NameValueStr: "name", "https://doc.rust-lang.org/reference/abi.html#the-export_name-attribute"), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 4f35bf63a1a4..93e5588146e1 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -632,6 +632,8 @@ declare_features! ( (unstable, simd_ffi, "1.0.0", Some(27731)), /// Allows specialization of implementations (RFC 1210). (incomplete, specialization, "1.7.0", Some(31844)), + /// Allows using `#[rustc_align_static(...)]` on static items. + (unstable, static_align, "CURRENT_RUSTC_VERSION", Some(146177)), /// Allows attributes on expressions and non-item statements. (unstable, stmt_expr_attributes, "1.6.0", Some(15701)), /// Allows lints part of the strict provenance effort. diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index dd5565d6f909..b4c1b61b9b58 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -14,6 +14,7 @@ pub use rustc_target::spec::SanitizerSet; use thin_vec::ThinVec; use crate::attrs::pretty_printing::PrintAttribute; +use crate::limit::Limit; use crate::{DefaultBodyStability, PartialConstStability, RustcVersion, Stability}; #[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic, PrintAttribute)] @@ -565,6 +566,9 @@ pub enum AttributeKind { /// Represents [`#[may_dangle]`](https://std-dev-guide.rust-lang.org/tricky/may-dangle.html). MayDangle(Span), + /// Represents `#[move_size_limit]` + MoveSizeLimit { attr_span: Span, limit_span: Span, limit: Limit }, + /// Represents `#[must_use]`. MustUse { span: Span, @@ -596,6 +600,9 @@ pub enum AttributeKind { /// Represents `#[path]` Path(Symbol, Span), + /// Represents `#[pattern_complexity_limit]` + PatternComplexityLimit { attr_span: Span, limit_span: Span, limit: Limit }, + /// Represents `#[pointee]` Pointee(Span), @@ -611,6 +618,9 @@ pub enum AttributeKind { /// Represents `#[rustc_pub_transparent]` (used by the `repr_transparent_external_private_fields` lint). PubTransparent(Span), + /// Represents [`#[recursion_limit]`](https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute) + RecursionLimit { attr_span: Span, limit_span: Span, limit: Limit }, + /// Represents [`#[repr]`](https://doc.rust-lang.org/stable/reference/type-layout.html#representations). Repr { reprs: ThinVec<(ReprAttr, Span)>, first_span: Span }, @@ -661,6 +671,9 @@ pub enum AttributeKind { /// Represents `#[type_const]`. TypeConst(Span), + /// Represents `#[type_length_limit]` + TypeLengthLimit { attr_span: Span, limit_span: Span, limit: Limit }, + /// Represents `#[rustc_unsafe_specialization_marker]`. UnsafeSpecializationMarker(Span), diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 3810bb6d0038..0e208be3497a 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -61,6 +61,7 @@ impl AttributeKind { MacroUse { .. } => No, Marker(..) => No, MayDangle(..) => No, + MoveSizeLimit { .. } => No, MustUse { .. } => Yes, Naked(..) => No, NoImplicitPrelude(..) => No, @@ -70,11 +71,13 @@ impl AttributeKind { ParenSugar(..) => No, PassByValue(..) => Yes, Path(..) => No, + PatternComplexityLimit { .. } => No, Pointee(..) => No, ProcMacro(..) => No, ProcMacroAttribute(..) => No, ProcMacroDerive { .. } => No, PubTransparent(..) => Yes, + RecursionLimit { .. } => No, Repr { .. } => No, RustcBuiltinMacro { .. } => Yes, RustcLayoutScalarValidRangeEnd(..) => Yes, @@ -89,6 +92,7 @@ impl AttributeKind { TargetFeature { .. } => No, TrackCaller(..) => Yes, TypeConst(..) => Yes, + TypeLengthLimit { .. } => No, UnsafeSpecializationMarker(..) => No, UnstableFeatureBound(..) => No, Used { .. } => No, diff --git a/compiler/rustc_hir/src/attrs/pretty_printing.rs b/compiler/rustc_hir/src/attrs/pretty_printing.rs index e65de25b4511..d13cd3fd1dab 100644 --- a/compiler/rustc_hir/src/attrs/pretty_printing.rs +++ b/compiler/rustc_hir/src/attrs/pretty_printing.rs @@ -9,6 +9,8 @@ use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol}; use rustc_target::spec::SanitizerSet; use thin_vec::ThinVec; +use crate::limit::Limit; + /// This trait is used to print attributes in `rustc_hir_pretty`. /// /// For structs and enums it can be derived using [`rustc_macros::PrintAttribute`]. @@ -146,7 +148,7 @@ macro_rules! print_tup { print_tup!(A B C D E F G H); print_skip!(Span, (), ErrorGuaranteed); -print_disp!(u16, bool, NonZero); +print_disp!(u16, bool, NonZero, Limit); print_debug!( Symbol, Ident, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index ae03121e5f70..75551fe4c196 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2614,6 +2614,18 @@ impl Expr<'_> { StructTailExpr::None, ), ) + | ( + ExprKind::Struct( + QPath::LangItem(LangItem::RangeToInclusiveCopy, _), + [val1], + StructTailExpr::None, + ), + ExprKind::Struct( + QPath::LangItem(LangItem::RangeToInclusiveCopy, _), + [val2], + StructTailExpr::None, + ), + ) | ( ExprKind::Struct( QPath::LangItem(LangItem::RangeFrom, _), @@ -2705,7 +2717,8 @@ pub fn is_range_literal(expr: &Expr<'_>) -> bool { | LangItem::RangeToInclusive | LangItem::RangeCopy | LangItem::RangeFromCopy - | LangItem::RangeInclusiveCopy, + | LangItem::RangeInclusiveCopy + | LangItem::RangeToInclusiveCopy, .. ) ), diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 0464665b41fc..67d2f15d4147 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -422,6 +422,7 @@ language_item_table! { RangeFromCopy, sym::RangeFromCopy, range_from_copy_struct, Target::Struct, GenericRequirement::None; RangeCopy, sym::RangeCopy, range_copy_struct, Target::Struct, GenericRequirement::None; RangeInclusiveCopy, sym::RangeInclusiveCopy, range_inclusive_copy_struct, Target::Struct, GenericRequirement::None; + RangeToInclusiveCopy, sym::RangeToInclusiveCopy, range_to_inclusive_copy_struct, Target::Struct, GenericRequirement::None; String, sym::String, string, Target::Struct, GenericRequirement::None; CStr, sym::CStr, c_str, Target::Struct, GenericRequirement::None; diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 78fc63753a2e..eb630fc80186 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -25,6 +25,7 @@ mod hir; pub use rustc_hir_id::{self as hir_id, *}; pub mod intravisit; pub mod lang_items; +pub mod limit; pub mod lints; pub mod pat_util; mod stability; diff --git a/compiler/rustc_hir/src/limit.rs b/compiler/rustc_hir/src/limit.rs new file mode 100644 index 000000000000..7e6d23f51bdb --- /dev/null +++ b/compiler/rustc_hir/src/limit.rs @@ -0,0 +1,63 @@ +use std::fmt; +use std::ops::{Div, Mul}; + +use rustc_error_messages::{DiagArgValue, IntoDiagArg}; +use rustc_macros::{Decodable, Encodable, HashStable_Generic}; + +/// New-type wrapper around `usize` for representing limits. Ensures that comparisons against +/// limits are consistent throughout the compiler. +#[derive(Clone, Copy, Debug, HashStable_Generic, Encodable, Decodable)] +pub struct Limit(pub usize); + +impl Limit { + /// Create a new limit from a `usize`. + pub fn new(value: usize) -> Self { + Limit(value) + } + + /// Create a new unlimited limit. + pub fn unlimited() -> Self { + Limit(usize::MAX) + } + + /// Check that `value` is within the limit. Ensures that the same comparisons are used + /// throughout the compiler, as mismatches can cause ICEs, see #72540. + #[inline] + pub fn value_within_limit(&self, value: usize) -> bool { + value <= self.0 + } +} + +impl From for Limit { + fn from(value: usize) -> Self { + Self::new(value) + } +} + +impl fmt::Display for Limit { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} + +impl Div for Limit { + type Output = Limit; + + fn div(self, rhs: usize) -> Self::Output { + Limit::new(self.0 / rhs) + } +} + +impl Mul for Limit { + type Output = Limit; + + fn mul(self, rhs: usize) -> Self::Output { + Limit::new(self.0 * rhs) + } +} + +impl IntoDiagArg for Limit { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { + self.to_string().into_diag_arg(&mut None) + } +} diff --git a/compiler/rustc_hir_analysis/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs index e27e68d36624..e8237471e1b6 100644 --- a/compiler/rustc_hir_analysis/src/autoderef.rs +++ b/compiler/rustc_hir_analysis/src/autoderef.rs @@ -1,7 +1,7 @@ +use rustc_hir::limit::Limit; use rustc_infer::infer::InferCtxt; use rustc_infer::traits::PredicateObligations; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; -use rustc_session::Limit; use rustc_span::def_id::{LOCAL_CRATE, LocalDefId}; use rustc_span::{ErrorGuaranteed, Span}; use rustc_trait_selection::traits::ObligationCtxt; diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index b5c0ca4727cd..e70d5505aae3 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -70,6 +70,7 @@ pub mod intrinsic; mod region; pub mod wfcheck; +use std::borrow::Cow; use std::num::NonZero; pub use check::{check_abi, check_custom_abi}; @@ -85,7 +86,9 @@ use rustc_infer::traits::ObligationCause; use rustc_middle::query::Providers; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::print::with_types_for_signature; -use rustc_middle::ty::{self, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypingMode}; +use rustc_middle::ty::{ + self, GenericArgs, GenericArgsRef, OutlivesPredicate, Region, Ty, TyCtxt, TypingMode, +}; use rustc_middle::{bug, span_bug}; use rustc_session::parse::feature_err; use rustc_span::def_id::CRATE_DEF_ID; @@ -233,8 +236,7 @@ fn missing_items_err( }; // Obtain the level of indentation ending in `sugg_sp`. - let padding = - tcx.sess.source_map().indentation_before(sugg_sp).unwrap_or_else(|| String::new()); + let padding = tcx.sess.source_map().indentation_before(sugg_sp).unwrap_or_else(String::new); let (mut missing_trait_item, mut missing_trait_item_none, mut missing_trait_item_label) = (Vec::new(), Vec::new(), Vec::new()); @@ -331,8 +333,10 @@ fn default_body_is_unstable( fn bounds_from_generic_predicates<'tcx>( tcx: TyCtxt<'tcx>, predicates: impl IntoIterator, Span)>, + assoc: ty::AssocItem, ) -> (String, String) { let mut types: FxIndexMap, Vec> = FxIndexMap::default(); + let mut regions: FxIndexMap, Vec>> = FxIndexMap::default(); let mut projections = vec![]; for (predicate, _) in predicates { debug!("predicate {:?}", predicate); @@ -349,39 +353,75 @@ fn bounds_from_generic_predicates<'tcx>( ty::ClauseKind::Projection(projection_pred) => { projections.push(bound_predicate.rebind(projection_pred)); } + ty::ClauseKind::RegionOutlives(OutlivesPredicate(a, b)) => { + regions.entry(a).or_default().push(b); + } _ => {} } } let mut where_clauses = vec![]; - let mut types_str = vec![]; - for (ty, bounds) in types { - if let ty::Param(_) = ty.kind() { - let mut bounds_str = vec![]; - for bound in bounds { - let mut projections_str = vec![]; - for projection in &projections { - let p = projection.skip_binder(); - if bound == tcx.parent(p.projection_term.def_id) - && p.projection_term.self_ty() == ty - { - let name = tcx.item_name(p.projection_term.def_id); - projections_str.push(format!("{} = {}", name, p.term)); + let generics = tcx.generics_of(assoc.def_id); + let params = generics + .own_params + .iter() + .filter(|p| !p.kind.is_synthetic()) + .map(|p| match tcx.mk_param_from_def(p).kind() { + ty::GenericArgKind::Type(ty) => { + let bounds = + types.get(&ty).map(Cow::Borrowed).unwrap_or_else(|| Cow::Owned(Vec::new())); + let mut bounds_str = vec![]; + for bound in bounds.iter().copied() { + let mut projections_str = vec![]; + for projection in &projections { + let p = projection.skip_binder(); + if bound == tcx.parent(p.projection_term.def_id) + && p.projection_term.self_ty() == ty + { + let name = tcx.item_name(p.projection_term.def_id); + projections_str.push(format!("{} = {}", name, p.term)); + } + } + let bound_def_path = if tcx.is_lang_item(bound, LangItem::MetaSized) { + String::from("?Sized") + } else { + tcx.def_path_str(bound) + }; + if projections_str.is_empty() { + where_clauses.push(format!("{}: {}", ty, bound_def_path)); + } else { + bounds_str.push(format!( + "{}<{}>", + bound_def_path, + projections_str.join(", ") + )); } } - let bound_def_path = tcx.def_path_str(bound); - if projections_str.is_empty() { - where_clauses.push(format!("{}: {}", ty, bound_def_path)); + if bounds_str.is_empty() { + ty.to_string() } else { - bounds_str.push(format!("{}<{}>", bound_def_path, projections_str.join(", "))); + format!("{}: {}", ty, bounds_str.join(" + ")) } } - if bounds_str.is_empty() { - types_str.push(ty.to_string()); - } else { - types_str.push(format!("{}: {}", ty, bounds_str.join(" + "))); + ty::GenericArgKind::Const(ct) => { + format!("const {ct}: {}", tcx.type_of(p.def_id).skip_binder()) } - } else { + ty::GenericArgKind::Lifetime(region) => { + if let Some(v) = regions.get(®ion) + && !v.is_empty() + { + format!( + "{region}: {}", + v.into_iter().map(Region::to_string).collect::>().join(" + ") + ) + } else { + region.to_string() + } + } + }) + .collect::>(); + for (ty, bounds) in types.into_iter() { + if !matches!(ty.kind(), ty::Param(_)) { // Avoid suggesting the following: // fn foo::Bar>(_: T) where T: Trait, ::Bar: Other {} where_clauses.extend( @@ -391,7 +431,7 @@ fn bounds_from_generic_predicates<'tcx>( } let generics = - if types_str.is_empty() { "".to_string() } else { format!("<{}>", types_str.join(", ")) }; + if params.is_empty() { "".to_string() } else { format!("<{}>", params.join(", ")) }; let where_clauses = if where_clauses.is_empty() { "".to_string() @@ -473,10 +513,10 @@ fn fn_sig_suggestion<'tcx>( let output = if !output.is_unit() { format!(" -> {output}") } else { String::new() }; let safety = sig.safety.prefix_str(); - let (generics, where_clauses) = bounds_from_generic_predicates(tcx, predicates); + let (generics, where_clauses) = bounds_from_generic_predicates(tcx, predicates, assoc); // FIXME: this is not entirely correct, as the lifetimes from borrowed params will - // not be present in the `fn` definition, not will we account for renamed + // not be present in the `fn` definition, nor will we account for renamed // lifetimes between the `impl` and the `trait`, but this should be good enough to // fill in a significant portion of the missing code, and other subsequent // suggestions can help the user fix the code. @@ -512,6 +552,7 @@ fn suggestion_signature<'tcx>( let (generics, where_clauses) = bounds_from_generic_predicates( tcx, tcx.predicates_of(assoc.def_id).instantiate_own(tcx, args), + assoc, ); format!("type {}{generics} = /* Type */{where_clauses};", assoc.name()) } diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index e6a1f6d8d8bb..22a9446fd4cf 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1047,7 +1047,7 @@ fn check_type_defn<'tcx>( let needs_drop_copy = || { packed && { let ty = tcx.type_of(variant.tail().did).instantiate_identity(); - let ty = tcx.erase_regions(ty); + let ty = tcx.erase_and_anonymize_regions(ty); assert!(!ty.has_infer()); ty.needs_drop(tcx, wfcx.infcx.typing_env(wfcx.param_env)) } diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index f707196c8163..621431ae2343 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -404,7 +404,7 @@ fn emit_orphan_check_error<'tcx>( of_trait.trait_ref.path.span }; - ty = tcx.erase_regions(ty); + ty = tcx.erase_and_anonymize_regions(ty); let is_foreign = !trait_ref.def_id.is_local() && matches!(is_target_ty, IsFirstInputType::No); diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index b59dc4bd132f..126ffabd448c 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -174,12 +174,6 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen } }; - if let Node::TraitItem(item) = node { - let mut bounds = Vec::new(); - icx.lowerer().add_default_trait_item_bounds(item, &mut bounds); - predicates.extend(bounds); - } - let generics = tcx.generics_of(def_id); // Below we'll consider the bounds on the type parameters (including `Self`) diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 6565ad7cf536..3b6367219b7f 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -6,6 +6,7 @@ use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, DiagSymbolList, Diagnostic, EmissionGuarantee, Level, MultiSpan, }; +use rustc_hir::limit::Limit; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::Ty; use rustc_span::{Ident, Span, Symbol}; @@ -557,7 +558,7 @@ pub(crate) struct AutoDerefReachedRecursionLimit<'a> { #[label] pub span: Span, pub ty: Ty<'a>, - pub suggested_limit: rustc_session::Limit, + pub suggested_limit: Limit, pub crate_name: Symbol, } 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 d14aef8ace46..99dc8e6e5221 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -1,12 +1,13 @@ +use std::assert_matches::assert_matches; use std::ops::ControlFlow; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::struct_span_code_err; use rustc_hir as hir; +use rustc_hir::PolyTraitRef; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; -use rustc_hir::{AmbigArg, PolyTraitRef}; use rustc_middle::bug; use rustc_middle::ty::{ self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, @@ -230,122 +231,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } - /// Checks whether `Self: DefaultAutoTrait` bounds should be added on trait super bounds - /// or associated items. - /// - /// To keep backward compatibility with existing code, `experimental_default_bounds` bounds - /// should be added everywhere, including super bounds. However this causes a huge performance - /// costs. For optimization purposes instead of adding default supertraits, bounds - /// are added to the associated items: - /// - /// ```ignore(illustrative) - /// // Default bounds are generated in the following way: - /// trait Trait { - /// fn foo(&self) where Self: Leak {} - /// } - /// - /// // instead of this: - /// trait Trait: Leak { - /// fn foo(&self) {} - /// } - /// ``` - /// It is not always possible to do this because of backward compatibility: - /// - /// ```ignore(illustrative) - /// pub trait Trait {} - /// pub trait Trait1 : Trait {} - /// //~^ ERROR: `Rhs` requires `DefaultAutoTrait`, but `Self` is not `DefaultAutoTrait` - /// ``` - /// - /// or: - /// - /// ```ignore(illustrative) - /// trait Trait { - /// type Type where Self: Sized; - /// } - /// trait Trait2 : Trait {} - /// //~^ ERROR: `DefaultAutoTrait` required for `Trait2`, by implicit `Self: DefaultAutoTrait` in `Trait::Type` - /// ``` - /// - /// Therefore, `experimental_default_bounds` are still being added to supertraits if - /// the `SelfTyParam` or `AssocItemConstraint` were found in a trait header. - fn requires_default_supertraits( - &self, - hir_bounds: &'tcx [hir::GenericBound<'tcx>], - hir_generics: &'tcx hir::Generics<'tcx>, - ) -> bool { - struct TraitInfoCollector; - - impl<'tcx> hir::intravisit::Visitor<'tcx> for TraitInfoCollector { - type Result = ControlFlow<()>; - - fn visit_assoc_item_constraint( - &mut self, - _constraint: &'tcx hir::AssocItemConstraint<'tcx>, - ) -> Self::Result { - ControlFlow::Break(()) - } - - fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx, AmbigArg>) -> Self::Result { - if matches!( - &t.kind, - hir::TyKind::Path(hir::QPath::Resolved( - _, - hir::Path { res: hir::def::Res::SelfTyParam { .. }, .. }, - )) - ) { - return ControlFlow::Break(()); - } - hir::intravisit::walk_ty(self, t) - } - } - - let mut found = false; - for bound in hir_bounds { - found |= hir::intravisit::walk_param_bound(&mut TraitInfoCollector, bound).is_break(); - } - found |= hir::intravisit::walk_generics(&mut TraitInfoCollector, hir_generics).is_break(); - found - } - - /// Implicitly add `Self: DefaultAutoTrait` clauses on trait associated items if - /// they are not added as super trait bounds to the trait itself. See - /// `requires_default_supertraits` for more information. - pub(crate) fn add_default_trait_item_bounds( - &self, - trait_item: &hir::TraitItem<'tcx>, - bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, - ) { - let tcx = self.tcx(); - if !tcx.sess.opts.unstable_opts.experimental_default_bounds { - return; - } - - let parent = tcx.local_parent(trait_item.hir_id().owner.def_id); - let hir::Node::Item(parent_trait) = tcx.hir_node_by_def_id(parent) else { - unreachable!(); - }; - - let (trait_generics, trait_bounds) = match parent_trait.kind { - hir::ItemKind::Trait(_, _, _, _, generics, supertraits, _) => (generics, supertraits), - hir::ItemKind::TraitAlias(_, generics, supertraits) => (generics, supertraits), - _ => unreachable!(), - }; - - if !self.requires_default_supertraits(trait_bounds, trait_generics) { - let self_ty_where_predicates = (parent, trait_item.generics.predicates); - self.add_default_traits( - bounds, - tcx.types.self_param, - &[], - Some(self_ty_where_predicates), - trait_item.span, - ); - } - } - - /// Lazily sets `experimental_default_bounds` to true on trait super bounds. - /// See `requires_default_supertraits` for more information. + /// Adds `experimental_default_bounds` bounds to the supertrait bounds. pub(crate) fn add_default_super_traits( &self, trait_def_id: LocalDefId, @@ -354,21 +240,21 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { hir_generics: &'tcx hir::Generics<'tcx>, span: Span, ) { - if !self.tcx().sess.opts.unstable_opts.experimental_default_bounds { + assert_matches!(self.tcx().def_kind(trait_def_id), DefKind::Trait | DefKind::TraitAlias); + + // Supertraits for auto trait are unsound according to the unstable book: + // https://doc.rust-lang.org/beta/unstable-book/language-features/auto-traits.html#supertraits + if self.tcx().trait_is_auto(trait_def_id.to_def_id()) { return; } - assert!(matches!(self.tcx().def_kind(trait_def_id), DefKind::Trait | DefKind::TraitAlias)); - if self.requires_default_supertraits(hir_bounds, hir_generics) { - let self_ty_where_predicates = (trait_def_id, hir_generics.predicates); - self.add_default_traits( - bounds, - self.tcx().types.self_param, - hir_bounds, - Some(self_ty_where_predicates), - span, - ); - } + self.add_default_traits( + bounds, + self.tcx().types.self_param, + hir_bounds, + Some((trait_def_id, hir_generics.predicates)), + span, + ); } pub(crate) fn add_default_traits( diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 93b82acf6212..0cf9cb7193f7 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -482,7 +482,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .map(|header| header.trait_ref.instantiate_identity().self_ty()) // We don't care about blanket impls. .filter(|self_ty| !self_ty.has_non_region_param()) - .map(|self_ty| tcx.erase_regions(self_ty).to_string()) + .map(|self_ty| tcx.erase_and_anonymize_regions(self_ty).to_string()) .collect() }; // FIXME: also look at `tcx.generics_of(self.item_def_id()).params` any that diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 3eeb0eac023a..27540fd1a438 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -851,8 +851,8 @@ impl<'a, 'tcx> CastCheck<'tcx> { debug!("check_ptr_ptr_cast m_src={m_src:?} m_dst={m_dst:?}"); // ptr-ptr cast. metadata must match. - let src_kind = fcx.tcx.erase_regions(fcx.pointer_kind(m_src.ty, self.span)?); - let dst_kind = fcx.tcx.erase_regions(fcx.pointer_kind(m_dst.ty, self.span)?); + let src_kind = fcx.tcx.erase_and_anonymize_regions(fcx.pointer_kind(m_src.ty, self.span)?); + let dst_kind = fcx.tcx.erase_and_anonymize_regions(fcx.pointer_kind(m_dst.ty, self.span)?); // We can't cast if target pointer kind is unknown let Some(dst_kind) = dst_kind else { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 74f27e85cba2..7a060cafeab1 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -21,7 +21,6 @@ use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitableExt}; use rustc_session::Session; use rustc_span::{self, DUMMY_SP, ErrorGuaranteed, Ident, Span, sym}; use rustc_trait_selection::error_reporting::TypeErrCtxt; -use rustc_trait_selection::error_reporting::infer::sub_relations::SubRelations; use rustc_trait_selection::traits::{ self, FulfillmentError, ObligationCause, ObligationCauseCode, ObligationCtxt, }; @@ -188,14 +187,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// /// [`InferCtxtErrorExt::err_ctxt`]: rustc_trait_selection::error_reporting::InferCtxtErrorExt::err_ctxt pub(crate) fn err_ctxt(&'a self) -> TypeErrCtxt<'a, 'tcx> { - let mut sub_relations = SubRelations::default(); - sub_relations.add_constraints( - self, - self.fulfillment_cx.borrow_mut().pending_obligations().iter().map(|o| o.predicate), - ); TypeErrCtxt { infcx: &self.infcx, - sub_relations: RefCell::new(sub_relations), typeck_results: Some(self.typeck_results.borrow()), fallback_has_occurred: self.fallback_has_occurred.get(), normalize_fn_sig: Box::new(|fn_sig| { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 84ea2ec0f8a4..d7ddbcc8b53b 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1358,7 +1358,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .infcx .type_implements_trait( clone_trait_def, - [self.tcx.erase_regions(expected_ty)], + [self.tcx.erase_and_anonymize_regions(expected_ty)], self.param_env, ) .must_apply_modulo_regions() diff --git a/compiler/rustc_hir_typeck/src/inline_asm.rs b/compiler/rustc_hir_typeck/src/inline_asm.rs index b59c1752c25a..c0cd23be6909 100644 --- a/compiler/rustc_hir_typeck/src/inline_asm.rs +++ b/compiler/rustc_hir_typeck/src/inline_asm.rs @@ -44,7 +44,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { if ty.has_non_region_infer() { Ty::new_misc_error(self.tcx()) } else { - self.tcx().erase_regions(ty) + self.tcx().erase_and_anonymize_regions(ty) } } diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index ab584eb7c909..52a8eff984b9 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -403,15 +403,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // special handling for this "trivial case" is a good idea. let infcx = &self.infcx; - let (ParamEnvAnd { param_env: _, value: self_ty }, canonical_inference_vars) = + let (ParamEnvAnd { param_env: _, value: self_ty }, var_values) = infcx.instantiate_canonical(span, &query_input.canonical); debug!(?self_ty, ?query_input, "probe_op: Mode::Path"); MethodAutoderefStepsResult { steps: infcx.tcx.arena.alloc_from_iter([CandidateStep { - self_ty: self.make_query_response_ignoring_pending_obligations( - canonical_inference_vars, - self_ty, - ), + self_ty: self + .make_query_response_ignoring_pending_obligations(var_values, self_ty), autoderefs: 0, from_unsafe_deref: false, unsize: false, diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index d75bc9edab20..90301d1b391a 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -802,7 +802,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { format!("unexpected inference variable after writeback: {predicate:?}"), ); } else { - let predicate = self.tcx().erase_regions(predicate); + let predicate = self.tcx().erase_and_anonymize_regions(predicate); if cause.has_infer() || cause.has_placeholders() { // We can't use the the obligation cause as it references // information local to this query. @@ -984,8 +984,8 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { // borrowck, and specifically region constraints will be populated during // MIR typeck which is run on the new body. // - // We're not using `tcx.erase_regions` as that also anonymizes bound variables, - // regressing borrowck diagnostics. + // We're not using `tcx.erase_and_anonymize_regions` as that also + // anonymizes bound variables, regressing borrowck diagnostics. value = fold_regions(tcx, value, |_, _| tcx.lifetimes.re_erased); // Normalize consts in writeback, because GCE doesn't normalize eagerly. diff --git a/compiler/rustc_index/src/idx.rs b/compiler/rustc_index/src/idx.rs index 33f406e21137..9cd7134659c5 100644 --- a/compiler/rustc_index/src/idx.rs +++ b/compiler/rustc_index/src/idx.rs @@ -130,7 +130,22 @@ impl IntoSliceIdx for core::range::RangeFrom { impl IntoSliceIdx for core::range::RangeInclusive { type Output = core::range::RangeInclusive; #[inline] + #[cfg(bootstrap)] fn into_slice_idx(self) -> Self::Output { core::range::RangeInclusive { start: self.start.index(), end: self.end.index() } } + #[inline] + #[cfg(not(bootstrap))] + fn into_slice_idx(self) -> Self::Output { + core::range::RangeInclusive { start: self.start.index(), last: self.last.index() } + } +} + +#[cfg(all(feature = "nightly", not(bootstrap)))] +impl IntoSliceIdx for core::range::RangeToInclusive { + type Output = core::range::RangeToInclusive; + #[inline] + fn into_slice_idx(self) -> Self::Output { + core::range::RangeToInclusive { last: self.last.index() } + } } diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 3ad14dc79d51..3c5e4a91c98c 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -6,6 +6,7 @@ //! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::sso::SsoHashMap; use rustc_index::Idx; use rustc_middle::bug; use rustc_middle::ty::{ @@ -17,7 +18,7 @@ use tracing::debug; use crate::infer::InferCtxt; use crate::infer::canonical::{ - Canonical, CanonicalQueryInput, CanonicalTyVarKind, CanonicalVarKind, OriginalQueryValues, + Canonical, CanonicalQueryInput, CanonicalVarKind, OriginalQueryValues, }; impl<'tcx> InferCtxt<'tcx> { @@ -293,6 +294,13 @@ struct Canonicalizer<'cx, 'tcx> { // Note that indices is only used once `var_values` is big enough to be // heap-allocated. indices: FxHashMap, BoundVar>, + /// Maps each `sub_unification_table_root_var` to the index of the first + /// variable which used it. + /// + /// This means in case two type variables have the same sub relations root, + /// we set the `sub_root` of the second variable to the position of the first. + /// Otherwise the `sub_root` of each type variable is just its own position. + sub_root_lookup_table: SsoHashMap, canonicalize_mode: &'cx dyn CanonicalizeMode, needs_canonical_flags: TypeFlags, @@ -361,10 +369,8 @@ impl<'cx, 'tcx> TypeFolder> for Canonicalizer<'cx, 'tcx> { // FIXME: perf problem described in #55921. ui = ty::UniverseIndex::ROOT; } - self.canonicalize_ty_var( - CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)), - t, - ) + let sub_root = self.get_or_insert_sub_root(vid); + self.canonicalize_ty_var(CanonicalVarKind::Ty { ui, sub_root }, t) } } } @@ -374,7 +380,7 @@ impl<'cx, 'tcx> TypeFolder> for Canonicalizer<'cx, 'tcx> { if nt != t { return self.fold_ty(nt); } else { - self.canonicalize_ty_var(CanonicalVarKind::Ty(CanonicalTyVarKind::Int), t) + self.canonicalize_ty_var(CanonicalVarKind::Int, t) } } ty::Infer(ty::FloatVar(vid)) => { @@ -382,7 +388,7 @@ impl<'cx, 'tcx> TypeFolder> for Canonicalizer<'cx, 'tcx> { if nt != t { return self.fold_ty(nt); } else { - self.canonicalize_ty_var(CanonicalVarKind::Ty(CanonicalTyVarKind::Float), t) + self.canonicalize_ty_var(CanonicalVarKind::Float, t) } } @@ -562,6 +568,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { variables: SmallVec::from_slice(base.variables), query_state, indices: FxHashMap::default(), + sub_root_lookup_table: Default::default(), binder_index: ty::INNERMOST, }; if canonicalizer.query_state.var_values.spilled() { @@ -660,6 +667,13 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { } } + fn get_or_insert_sub_root(&mut self, vid: ty::TyVid) -> ty::BoundVar { + let root_vid = self.infcx.unwrap().sub_unification_table_root_var(vid); + let idx = + *self.sub_root_lookup_table.entry(root_vid).or_insert_with(|| self.variables.len()); + ty::BoundVar::from(idx) + } + /// Replaces the universe indexes used in `var_values` with their index in /// `query_state.universe_map`. This minimizes the maximum universe used in /// the canonicalized value. @@ -679,11 +693,11 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { self.variables .iter() .map(|&kind| match kind { - CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float) => { + CanonicalVarKind::Int | CanonicalVarKind::Float => { return kind; } - CanonicalVarKind::Ty(CanonicalTyVarKind::General(u)) => { - CanonicalVarKind::Ty(CanonicalTyVarKind::General(reverse_universe_map[&u])) + CanonicalVarKind::Ty { ui, sub_root } => { + CanonicalVarKind::Ty { ui: reverse_universe_map[&ui], sub_root } } CanonicalVarKind::Region(u) => CanonicalVarKind::Region(reverse_universe_map[&u]), CanonicalVarKind::Const(u) => CanonicalVarKind::Const(reverse_universe_map[&u]), diff --git a/compiler/rustc_infer/src/infer/canonical/mod.rs b/compiler/rustc_infer/src/infer/canonical/mod.rs index 79a2aa54ef83..f99f228e19d8 100644 --- a/compiler/rustc_infer/src/infer/canonical/mod.rs +++ b/compiler/rustc_infer/src/infer/canonical/mod.rs @@ -24,7 +24,7 @@ pub use instantiate::CanonicalExt; use rustc_index::IndexVec; pub use rustc_middle::infer::canonical::*; -use rustc_middle::ty::{self, GenericArg, List, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, GenericArg, Ty, TyCtxt, TypeFoldable}; use rustc_span::Span; use crate::infer::{InferCtxt, RegionVariableOrigin}; @@ -67,30 +67,12 @@ impl<'tcx> InferCtxt<'tcx> { .chain((1..=canonical.max_universe.as_u32()).map(|_| self.create_next_universe())) .collect(); - let canonical_inference_vars = - self.instantiate_canonical_vars(span, canonical.variables, |ui| universes[ui]); - let result = canonical.instantiate(self.tcx, &canonical_inference_vars); - (result, canonical_inference_vars) - } - - /// Given the "infos" about the canonical variables from some - /// canonical, creates fresh variables with the same - /// characteristics (see `instantiate_canonical_var` for - /// details). You can then use `instantiate` to instantiate the - /// canonical variable with these inference variables. - fn instantiate_canonical_vars( - &self, - span: Span, - variables: &List>, - universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex, - ) -> CanonicalVarValues<'tcx> { - CanonicalVarValues { - var_values: self.tcx.mk_args_from_iter( - variables - .iter() - .map(|kind| self.instantiate_canonical_var(span, kind, &universe_map)), - ), - } + let var_values = + CanonicalVarValues::instantiate(self.tcx, &canonical.variables, |var_values, info| { + self.instantiate_canonical_var(span, info, &var_values, |ui| universes[ui]) + }); + let result = canonical.instantiate(self.tcx, &var_values); + (result, var_values) } /// Given the "info" about a canonical variable, creates a fresh @@ -105,22 +87,28 @@ impl<'tcx> InferCtxt<'tcx> { &self, span: Span, kind: CanonicalVarKind<'tcx>, + previous_var_values: &[GenericArg<'tcx>], universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex, ) -> GenericArg<'tcx> { match kind { - CanonicalVarKind::Ty(ty_kind) => { - let ty = match ty_kind { - CanonicalTyVarKind::General(ui) => { - self.next_ty_var_in_universe(span, universe_map(ui)) + CanonicalVarKind::Ty { ui, sub_root } => { + let vid = self.next_ty_vid_in_universe(span, universe_map(ui)); + // If this inference variable is related to an earlier variable + // via subtyping, we need to add that info to the inference context. + if let Some(prev) = previous_var_values.get(sub_root.as_usize()) { + if let &ty::Infer(ty::TyVar(sub_root)) = prev.expect_ty().kind() { + self.sub_unify_ty_vids_raw(vid, sub_root); + } else { + unreachable!() } - - CanonicalTyVarKind::Int => self.next_int_var(), - - CanonicalTyVarKind::Float => self.next_float_var(), - }; - ty.into() + } + Ty::new_var(self.tcx, vid).into() } + CanonicalVarKind::Int => self.next_int_var().into(), + + CanonicalVarKind::Float => self.next_float_var().into(), + CanonicalVarKind::PlaceholderTy(ty::PlaceholderType { universe, bound }) => { let universe_mapped = universe_map(universe); let placeholder_mapped = ty::PlaceholderType { universe: universe_mapped, bound }; diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 09578598114b..5d1b4be9e57b 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -13,6 +13,7 @@ use std::iter; use rustc_index::{Idx, IndexVec}; use rustc_middle::arena::ArenaAllocatable; use rustc_middle::bug; +use rustc_middle::infer::canonical::CanonicalVarKind; use rustc_middle::ty::{self, BoundVar, GenericArg, GenericArgKind, Ty, TyCtxt, TypeFoldable}; use tracing::{debug, instrument}; @@ -413,26 +414,27 @@ impl<'tcx> InferCtxt<'tcx> { let mut opt_values: IndexVec>> = IndexVec::from_elem_n(None, query_response.variables.len()); - // In terms of our example above, we are iterating over pairs like: - // [(?A, Vec), ('static, '?1), (?B, ?0)] for (original_value, result_value) in iter::zip(&original_values.var_values, result_values) { match result_value.kind() { GenericArgKind::Type(result_value) => { - // e.g., here `result_value` might be `?0` in the example above... - if let ty::Bound(debruijn, b) = *result_value.kind() { - // ...in which case we would set `canonical_vars[0]` to `Some(?U)`. - + // We disable the instantiation guess for inference variables + // and only use it for placeholders. We need to handle the + // `sub_root` of type inference variables which would make this + // more involved. They are also a lot rarer than region variables. + if let ty::Bound(debruijn, b) = *result_value.kind() + && !matches!( + query_response.variables[b.var.as_usize()], + CanonicalVarKind::Ty { .. } + ) + { // We only allow a `ty::INNERMOST` index in generic parameters. assert_eq!(debruijn, ty::INNERMOST); opt_values[b.var] = Some(*original_value); } } GenericArgKind::Lifetime(result_value) => { - // e.g., here `result_value` might be `'?1` in the example above... if let ty::ReBound(debruijn, b) = result_value.kind() { - // ... in which case we would set `canonical_vars[0]` to `Some('static)`. - // We only allow a `ty::INNERMOST` index in generic parameters. assert_eq!(debruijn, ty::INNERMOST); opt_values[b.var] = Some(*original_value); @@ -440,8 +442,6 @@ impl<'tcx> InferCtxt<'tcx> { } GenericArgKind::Const(result_value) => { if let ty::ConstKind::Bound(debruijn, b) = result_value.kind() { - // ...in which case we would set `canonical_vars[0]` to `Some(const X)`. - // We only allow a `ty::INNERMOST` index in generic parameters. assert_eq!(debruijn, ty::INNERMOST); opt_values[b.var] = Some(*original_value); @@ -453,39 +453,36 @@ impl<'tcx> InferCtxt<'tcx> { // Create result arguments: if we found a value for a // given variable in the loop above, use that. Otherwise, use // a fresh inference variable. - let result_args = CanonicalVarValues { - var_values: self.tcx.mk_args_from_iter( - query_response.variables.iter().enumerate().map(|(index, var_kind)| { - if var_kind.universe() != ty::UniverseIndex::ROOT { - // A variable from inside a binder of the query. While ideally these shouldn't - // exist at all, we have to deal with them for now. - self.instantiate_canonical_var(cause.span, var_kind, |u| { - universe_map[u.as_usize()] - }) - } else if var_kind.is_existential() { - match opt_values[BoundVar::new(index)] { - Some(k) => k, - None => self.instantiate_canonical_var(cause.span, var_kind, |u| { - universe_map[u.as_usize()] - }), - } - } else { - // For placeholders which were already part of the input, we simply map this - // universal bound variable back the placeholder of the input. - opt_values[BoundVar::new(index)].expect( - "expected placeholder to be unified with itself during response", - ) - } - }), - ), - }; + let tcx = self.tcx; + let variables = query_response.variables; + let var_values = CanonicalVarValues::instantiate(tcx, variables, |var_values, kind| { + if kind.universe() != ty::UniverseIndex::ROOT { + // A variable from inside a binder of the query. While ideally these shouldn't + // exist at all, we have to deal with them for now. + self.instantiate_canonical_var(cause.span, kind, &var_values, |u| { + universe_map[u.as_usize()] + }) + } else if kind.is_existential() { + match opt_values[BoundVar::new(var_values.len())] { + Some(k) => k, + None => self.instantiate_canonical_var(cause.span, kind, &var_values, |u| { + universe_map[u.as_usize()] + }), + } + } else { + // For placeholders which were already part of the input, we simply map this + // universal bound variable back the placeholder of the input. + opt_values[BoundVar::new(var_values.len())] + .expect("expected placeholder to be unified with itself during response") + } + }); let mut obligations = PredicateObligations::new(); // Carry all newly resolved opaque types to the caller's scope for &(a, b) in &query_response.value.opaque_types { - let a = instantiate_value(self.tcx, &result_args, a); - let b = instantiate_value(self.tcx, &result_args, b); + let a = instantiate_value(self.tcx, &var_values, a); + let b = instantiate_value(self.tcx, &var_values, b); debug!(?a, ?b, "constrain opaque type"); // We use equate here instead of, for example, just registering the // opaque type's hidden value directly, because the hidden type may have been an inference @@ -502,7 +499,7 @@ impl<'tcx> InferCtxt<'tcx> { ); } - Ok(InferOk { value: result_args, obligations }) + Ok(InferOk { value: var_values, obligations }) } /// Given a "guess" at the values for the canonical variables in diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index 8265fccabc96..14cc590720ac 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -59,6 +59,10 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { self.root_var(var) } + fn sub_unification_table_root_var(&self, var: ty::TyVid) -> ty::TyVid { + self.sub_unification_table_root_var(var) + } + fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid { self.root_const_var(var) } @@ -179,6 +183,10 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { self.inner.borrow_mut().type_variables().equate(a, b); } + fn sub_unify_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid) { + self.sub_unify_ty_vids_raw(a, b); + } + fn equate_int_vids_raw(&self, a: ty::IntVid, b: ty::IntVid) { self.inner.borrow_mut().int_unification_table().union(a, b); } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index d105d24bed77..9d3886aff1c1 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -764,6 +764,7 @@ impl<'tcx> InferCtxt<'tcx> { let r_b = self.shallow_resolve(predicate.skip_binder().b); match (r_a.kind(), r_b.kind()) { (&ty::Infer(ty::TyVar(a_vid)), &ty::Infer(ty::TyVar(b_vid))) => { + self.sub_unify_ty_vids_raw(a_vid, b_vid); return Err((a_vid, b_vid)); } _ => {} @@ -1128,6 +1129,14 @@ impl<'tcx> InferCtxt<'tcx> { self.inner.borrow_mut().type_variables().root_var(var) } + pub fn sub_unify_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid) { + self.inner.borrow_mut().type_variables().sub_unify(a, b); + } + + pub fn sub_unification_table_root_var(&self, var: ty::TyVid) -> ty::TyVid { + self.inner.borrow_mut().type_variables().sub_unification_table_root_var(var) + } + pub fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid { self.inner.borrow_mut().const_unification_table().find(var).vid } diff --git a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs index bfdd282d7e11..f06eb58a371c 100644 --- a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs +++ b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs @@ -76,7 +76,7 @@ pub(super) fn can_match_erased_ty<'tcx>( erased_ty: Ty<'tcx>, ) -> bool { assert!(!outlives_predicate.has_escaping_bound_vars()); - let erased_outlives_predicate = tcx.erase_regions(outlives_predicate); + let erased_outlives_predicate = tcx.erase_and_anonymize_regions(outlives_predicate); let outlives_ty = erased_outlives_predicate.skip_binder().0; if outlives_ty == erased_ty { // pointless micro-optimization diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index 69feecfe30a4..f67b99cb3f84 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -96,7 +96,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { &self, alias_ty: ty::AliasTy<'tcx>, ) -> Vec> { - let erased_alias_ty = self.tcx.erase_regions(alias_ty.to_ty(self.tcx)); + let erased_alias_ty = self.tcx.erase_and_anonymize_regions(alias_ty.to_ty(self.tcx)); self.declared_generic_bounds_from_env_for_erased_ty(erased_alias_ty) } @@ -241,7 +241,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { } let p_ty = p.to_ty(tcx); - let erased_p_ty = self.tcx.erase_regions(p_ty); + let erased_p_ty = self.tcx.erase_and_anonymize_regions(p_ty); (erased_p_ty == erased_ty).then_some(ty::Binder::dummy(ty::OutlivesPredicate(p_ty, r))) })); diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index a000bb1123c1..cc41957c110f 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -6,8 +6,8 @@ use rustc_hir::def_id::DefId; use rustc_middle::bug; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::{ - self, AliasRelationDirection, InferConst, MaxUniverse, Term, Ty, TyCtxt, TypeVisitable, - TypeVisitableExt, TypingMode, + self, AliasRelationDirection, InferConst, Term, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, + TypeVisitableExt, TypeVisitor, TypingMode, }; use rustc_span::Span; use tracing::{debug, instrument, warn}; @@ -290,6 +290,45 @@ impl<'tcx> InferCtxt<'tcx> { } } +/// Finds the max universe present +struct MaxUniverse { + max_universe: ty::UniverseIndex, +} + +impl MaxUniverse { + fn new() -> Self { + MaxUniverse { max_universe: ty::UniverseIndex::ROOT } + } + + fn max_universe(self) -> ty::UniverseIndex { + self.max_universe + } +} + +impl<'tcx> TypeVisitor> for MaxUniverse { + fn visit_ty(&mut self, t: Ty<'tcx>) { + if let ty::Placeholder(placeholder) = t.kind() { + self.max_universe = self.max_universe.max(placeholder.universe); + } + + t.super_visit_with(self) + } + + fn visit_const(&mut self, c: ty::Const<'tcx>) { + if let ty::ConstKind::Placeholder(placeholder) = c.kind() { + self.max_universe = self.max_universe.max(placeholder.universe); + } + + c.super_visit_with(self) + } + + fn visit_region(&mut self, r: ty::Region<'tcx>) { + if let ty::RePlaceholder(placeholder) = r.kind() { + self.max_universe = self.max_universe.max(placeholder.universe); + } + } +} + /// The "generalizer" is used when handling inference variables. /// /// The basic strategy for handling a constraint like `?A <: B` is to @@ -519,6 +558,10 @@ impl<'tcx> TypeRelation> for Generalizer<'_, 'tcx> { let origin = inner.type_variables().var_origin(vid); let new_var_id = inner.type_variables().new_var(self.for_universe, origin); + // Record that `vid` and `new_var_id` have to be subtypes + // of each other. This is currently only used for diagnostics. + // To see why, see the docs in the `type_variables` module. + inner.type_variables().sub_unify(vid, new_var_id); // If we're in the new solver and create a new inference // variable inside of an alias we eagerly constrain that // inference variable to prevent unexpected ambiguity errors. diff --git a/compiler/rustc_infer/src/infer/snapshot/undo_log.rs b/compiler/rustc_infer/src/infer/snapshot/undo_log.rs index fcc0ab3af410..22c815fb87c6 100644 --- a/compiler/rustc_infer/src/infer/snapshot/undo_log.rs +++ b/compiler/rustc_infer/src/infer/snapshot/undo_log.rs @@ -20,7 +20,7 @@ pub struct Snapshot<'tcx> { pub(crate) enum UndoLog<'tcx> { DuplicateOpaqueType, OpaqueTypes(OpaqueTypeKey<'tcx>, Option>), - TypeVariables(sv::UndoLog>>), + TypeVariables(type_variable::UndoLog<'tcx>), ConstUnificationTable(sv::UndoLog>>), IntUnificationTable(sv::UndoLog>), FloatUnificationTable(sv::UndoLog>), @@ -49,6 +49,8 @@ impl_from! { RegionConstraintCollector(region_constraints::UndoLog<'tcx>), TypeVariables(sv::UndoLog>>), + TypeVariables(sv::UndoLog>), + TypeVariables(type_variable::UndoLog<'tcx>), IntUnificationTable(sv::UndoLog>), FloatUnificationTable(sv::UndoLog>), diff --git a/compiler/rustc_infer/src/infer/type_variable.rs b/compiler/rustc_infer/src/infer/type_variable.rs index 6f6791804d32..65f77fe8e25f 100644 --- a/compiler/rustc_infer/src/infer/type_variable.rs +++ b/compiler/rustc_infer/src/infer/type_variable.rs @@ -13,12 +13,48 @@ use tracing::debug; use crate::infer::InferCtxtUndoLogs; +/// Represents a single undo-able action that affects a type inference variable. +#[derive(Clone)] +pub(crate) enum UndoLog<'tcx> { + EqRelation(sv::UndoLog>>), + SubRelation(sv::UndoLog>), +} + +/// Convert from a specific kind of undo to the more general UndoLog +impl<'tcx> From>>> for UndoLog<'tcx> { + fn from(l: sv::UndoLog>>) -> Self { + UndoLog::EqRelation(l) + } +} + +/// Convert from a specific kind of undo to the more general UndoLog +impl<'tcx> From>> for UndoLog<'tcx> { + fn from(l: sv::UndoLog>) -> Self { + UndoLog::SubRelation(l) + } +} + impl<'tcx> Rollback>>> for TypeVariableStorage<'tcx> { fn reverse(&mut self, undo: sv::UndoLog>>) { self.eq_relations.reverse(undo) } } +impl<'tcx> Rollback>> for TypeVariableStorage<'tcx> { + fn reverse(&mut self, undo: sv::UndoLog>) { + self.sub_unification_table.reverse(undo) + } +} + +impl<'tcx> Rollback> for TypeVariableStorage<'tcx> { + fn reverse(&mut self, undo: UndoLog<'tcx>) { + match undo { + UndoLog::EqRelation(undo) => self.eq_relations.reverse(undo), + UndoLog::SubRelation(undo) => self.sub_unification_table.reverse(undo), + } + } +} + #[derive(Clone, Default)] pub(crate) struct TypeVariableStorage<'tcx> { /// The origins of each type variable. @@ -27,6 +63,25 @@ pub(crate) struct TypeVariableStorage<'tcx> { /// constraint `?X == ?Y`. This table also stores, for each key, /// the known value. eq_relations: ut::UnificationTableStorage>, + /// Only used by `-Znext-solver` and for diagnostics. Tracks whether + /// type variables are related via subtyping at all, ignoring which of + /// the two is the subtype. + /// + /// When reporting ambiguity errors, we sometimes want to + /// treat all inference vars which are subtypes of each + /// others as if they are equal. For this case we compute + /// the transitive closure of our subtype obligations here. + /// + /// E.g. when encountering ambiguity errors, we want to suggest + /// specifying some method argument or to add a type annotation + /// to a local variable. Because subtyping cannot change the + /// shape of a type, it's fine if the cause of the ambiguity error + /// is only related to the suggested variable via subtyping. + /// + /// Even for something like `let x = returns_arg(); x.method();` the + /// type of `x` is only a supertype of the argument of `returns_arg`. We + /// still want to suggest specifying the type of the argument. + sub_unification_table: ut::UnificationTableStorage, } pub(crate) struct TypeVariableTable<'a, 'tcx> { @@ -102,13 +157,24 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> { self.storage.values[vid].origin } - /// Records that `a == b`, depending on `dir`. + /// Records that `a == b`. /// /// Precondition: neither `a` nor `b` are known. pub(crate) fn equate(&mut self, a: ty::TyVid, b: ty::TyVid) { debug_assert!(self.probe(a).is_unknown()); debug_assert!(self.probe(b).is_unknown()); self.eq_relations().union(a, b); + self.sub_unification_table().union(a, b); + } + + /// Records that `a` and `b` are related via subtyping. We don't track + /// which of the two is the subtype. + /// + /// Precondition: neither `a` nor `b` are known. + pub(crate) fn sub_unify(&mut self, a: ty::TyVid, b: ty::TyVid) { + debug_assert!(self.probe(a).is_unknown()); + debug_assert!(self.probe(b).is_unknown()); + self.sub_unification_table().union(a, b); } /// Instantiates `vid` with the type `ty`. @@ -142,6 +208,10 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> { origin: TypeVariableOrigin, ) -> ty::TyVid { let eq_key = self.eq_relations().new_key(TypeVariableValue::Unknown { universe }); + + let sub_key = self.sub_unification_table().new_key(()); + debug_assert_eq!(eq_key.vid, sub_key.vid); + let index = self.storage.values.push(TypeVariableData { origin }); debug_assert_eq!(eq_key.vid, index); @@ -164,6 +234,18 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> { self.eq_relations().find(vid).vid } + /// Returns the "root" variable of `vid` in the `sub_unification_table` + /// equivalence table. All type variables that have been are related via + /// equality or subtyping will yield the same root variable (per the + /// union-find algorithm), so `sub_unification_table_root_var(a) + /// == sub_unification_table_root_var(b)` implies that: + /// ```text + /// exists X. (a <: X || X <: a) && (b <: X || X <: b) + /// ``` + pub(crate) fn sub_unification_table_root_var(&mut self, vid: ty::TyVid) -> ty::TyVid { + self.sub_unification_table().find(vid).vid + } + /// Retrieves the type to which `vid` has been instantiated, if /// any. pub(crate) fn probe(&mut self, vid: ty::TyVid) -> TypeVariableValue<'tcx> { @@ -181,6 +263,11 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> { self.storage.eq_relations.with_log(self.undo_log) } + #[inline] + fn sub_unification_table(&mut self) -> super::UnificationTable<'_, 'tcx, TyVidSubKey> { + self.storage.sub_unification_table.with_log(self.undo_log) + } + /// Returns a range of the type variables created during the snapshot. pub(crate) fn vars_since_snapshot( &mut self, @@ -243,6 +330,33 @@ impl<'tcx> ut::UnifyKey for TyVidEqKey<'tcx> { } } +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub(crate) struct TyVidSubKey { + vid: ty::TyVid, +} + +impl From for TyVidSubKey { + #[inline] // make this function eligible for inlining - it is quite hot. + fn from(vid: ty::TyVid) -> Self { + TyVidSubKey { vid } + } +} + +impl ut::UnifyKey for TyVidSubKey { + type Value = (); + #[inline] + fn index(&self) -> u32 { + self.vid.as_u32() + } + #[inline] + fn from_index(i: u32) -> TyVidSubKey { + TyVidSubKey { vid: ty::TyVid::from_u32(i) } + } + fn tag() -> &'static str { + "TyVidSubKey" + } +} + impl<'tcx> ut::UnifyValue for TypeVariableValue<'tcx> { type Error = ut::NoError; diff --git a/compiler/rustc_interface/messages.ftl b/compiler/rustc_interface/messages.ftl index 4b9c71d71725..d83b18cbc2df 100644 --- a/compiler/rustc_interface/messages.ftl +++ b/compiler/rustc_interface/messages.ftl @@ -30,10 +30,6 @@ interface_ignoring_out_dir = ignoring --out-dir flag due to -o flag interface_input_file_would_be_overwritten = the input file "{$path}" would be overwritten by the generated executable -interface_limit_invalid = - `limit` must be a non-negative integer - .label = {$error_str} - interface_mixed_bin_crate = cannot mix `bin` crate type with others diff --git a/compiler/rustc_interface/src/errors.rs b/compiler/rustc_interface/src/errors.rs index 6b39b4f18911..d1082eaf6173 100644 --- a/compiler/rustc_interface/src/errors.rs +++ b/compiler/rustc_interface/src/errors.rs @@ -108,13 +108,3 @@ pub(crate) struct AbiRequiredTargetFeature<'a> { pub feature: &'a str, pub enabled: &'a str, } - -#[derive(Diagnostic)] -#[diag(interface_limit_invalid)] -pub(crate) struct LimitInvalid<'a> { - #[primary_span] - pub span: Span, - #[label] - pub value_span: Span, - pub error_str: &'a str, -} diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 4c820b8877b7..b52c5b4cd663 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -13,7 +13,8 @@ use rustc_lint::LintStore; use rustc_middle::ty; use rustc_middle::ty::CurrentGcx; use rustc_middle::util::Providers; -use rustc_parse::new_parser_from_simple_source_str; +use rustc_parse::lexer::StripTokens; +use rustc_parse::new_parser_from_source_str; use rustc_parse::parser::attr::AllowLeadingUnsafe; use rustc_query_impl::QueryCtxt; use rustc_query_system::query::print_query_stack; @@ -68,7 +69,8 @@ pub(crate) fn parse_cfg(dcx: DiagCtxtHandle<'_>, cfgs: Vec) -> Cfg { }; } - match new_parser_from_simple_source_str(&psess, filename, s.to_string()) { + match new_parser_from_source_str(&psess, filename, s.to_string(), StripTokens::Nothing) + { Ok(mut parser) => match parser.parse_meta_item(AllowLeadingUnsafe::No) { Ok(meta_item) if parser.token == token::Eof => { if meta_item.path.segments.len() != 1 { @@ -166,13 +168,15 @@ pub(crate) fn parse_check_cfg(dcx: DiagCtxtHandle<'_>, specs: Vec) -> Ch error!("expected `cfg(name, values(\"value1\", \"value2\", ... \"valueN\"))`") }; - let mut parser = match new_parser_from_simple_source_str(&psess, filename, s.to_string()) { - Ok(parser) => parser, - Err(errs) => { - errs.into_iter().for_each(|err| err.cancel()); - expected_error(); - } - }; + let mut parser = + match new_parser_from_source_str(&psess, filename, s.to_string(), StripTokens::Nothing) + { + Ok(parser) => parser, + Err(errs) => { + errs.into_iter().for_each(|err| err.cancel()); + expected_error(); + } + }; let meta_item = match parser.parse_meta_item(AllowLeadingUnsafe::No) { Ok(meta_item) if parser.token == token::Eof => meta_item, diff --git a/compiler/rustc_interface/src/limits.rs b/compiler/rustc_interface/src/limits.rs index 8f01edec09f3..10e58f32256f 100644 --- a/compiler/rustc_interface/src/limits.rs +++ b/compiler/rustc_interface/src/limits.rs @@ -8,78 +8,32 @@ //! Users can override these limits via an attribute on the crate like //! `#![recursion_limit="22"]`. This pass just looks for those attributes. -use std::num::IntErrorKind; - -use rustc_ast::attr::AttributeExt; -use rustc_middle::bug; +use rustc_hir::attrs::AttributeKind; +use rustc_hir::limit::Limit; +use rustc_hir::{Attribute, find_attr}; use rustc_middle::query::Providers; -use rustc_session::{Limit, Limits, Session}; -use rustc_span::{Symbol, sym}; - -use crate::errors::LimitInvalid; +use rustc_session::Limits; pub(crate) fn provide(providers: &mut Providers) { - providers.limits = |tcx, ()| Limits { - recursion_limit: get_recursion_limit(tcx.hir_krate_attrs(), tcx.sess), - move_size_limit: get_limit( - tcx.hir_krate_attrs(), - tcx.sess, - sym::move_size_limit, - Limit::new(tcx.sess.opts.unstable_opts.move_size_limit.unwrap_or(0)), - ), - type_length_limit: get_limit( - tcx.hir_krate_attrs(), - tcx.sess, - sym::type_length_limit, - Limit::new(2usize.pow(24)), - ), - pattern_complexity_limit: get_limit( - tcx.hir_krate_attrs(), - tcx.sess, - sym::pattern_complexity_limit, - Limit::unlimited(), - ), + providers.limits = |tcx, ()| { + let attrs = tcx.hir_krate_attrs(); + Limits { + recursion_limit: get_recursion_limit(tcx.hir_krate_attrs()), + move_size_limit: + find_attr!(attrs, AttributeKind::MoveSizeLimit { limit, .. } => *limit) + .unwrap_or(Limit::new(tcx.sess.opts.unstable_opts.move_size_limit.unwrap_or(0))), + type_length_limit: + find_attr!(attrs, AttributeKind::TypeLengthLimit { limit, .. } => *limit) + .unwrap_or(Limit::new(2usize.pow(24))), + pattern_complexity_limit: + find_attr!(attrs, AttributeKind::PatternComplexityLimit { limit, .. } => *limit) + .unwrap_or(Limit::unlimited()), + } } } // This one is separate because it must be read prior to macro expansion. -pub(crate) fn get_recursion_limit(krate_attrs: &[impl AttributeExt], sess: &Session) -> Limit { - get_limit(krate_attrs, sess, sym::recursion_limit, Limit::new(128)) -} - -fn get_limit( - krate_attrs: &[impl AttributeExt], - sess: &Session, - name: Symbol, - default: Limit, -) -> Limit { - for attr in krate_attrs { - if !attr.has_name(name) { - continue; - } - - if let Some(sym) = attr.value_str() { - match sym.as_str().parse() { - Ok(n) => return Limit::new(n), - Err(e) => { - let error_str = match e.kind() { - IntErrorKind::PosOverflow => "`limit` is too large", - IntErrorKind::Empty => "`limit` must be a non-negative integer", - IntErrorKind::InvalidDigit => "not a valid integer", - IntErrorKind::NegOverflow => { - bug!("`limit` should never negatively overflow") - } - IntErrorKind::Zero => bug!("zero is a valid `limit`"), - kind => bug!("unimplemented IntErrorKind variant: {:?}", kind), - }; - sess.dcx().emit_err(LimitInvalid { - span: attr.span(), - value_span: attr.value_span().unwrap(), - error_str, - }); - } - } - } - } - default +pub(crate) fn get_recursion_limit(attrs: &[Attribute]) -> Limit { + find_attr!(attrs, AttributeKind::RecursionLimit { limit, .. } => *limit) + .unwrap_or(Limit::new(128)) } diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index ca8c10311fb8..d39219bfd660 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -6,7 +6,7 @@ use std::sync::{Arc, LazyLock, OnceLock}; use std::{env, fs, iter}; use rustc_ast as ast; -use rustc_attr_parsing::{AttributeParser, ShouldEmit, validate_attr}; +use rustc_attr_parsing::{AttributeParser, ShouldEmit}; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::jobserver::Proxy; use rustc_data_structures::steal::Steal; @@ -19,6 +19,7 @@ use rustc_fs_util::try_canonicalize; use rustc_hir::attrs::AttributeKind; use rustc_hir::def_id::{LOCAL_CRATE, StableCrateId, StableCrateIdMap}; use rustc_hir::definitions::Definitions; +use rustc_hir::limit::Limit; use rustc_incremental::setup_dep_graph; use rustc_lint::{BufferedEarlyLint, EarlyCheckNode, LintStore, unerased_lint_store}; use rustc_metadata::EncodedMetadata; @@ -27,15 +28,16 @@ use rustc_middle::arena::Arena; use rustc_middle::dep_graph::DepsType; use rustc_middle::ty::{self, CurrentGcx, GlobalCtxt, RegisteredTools, TyCtxt}; use rustc_middle::util::Providers; +use rustc_parse::lexer::StripTokens; use rustc_parse::{new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal}; use rustc_passes::{abi_test, input_stats, layout_test}; use rustc_resolve::{Resolver, ResolverOutputs}; +use rustc_session::Session; use rustc_session::config::{CrateType, Input, OutFileName, OutputFilenames, OutputType}; use rustc_session::cstore::Untracked; use rustc_session::output::{collect_crate_types, filename_for_input}; use rustc_session::parse::feature_err; use rustc_session::search_paths::PathKind; -use rustc_session::{Limit, Session}; use rustc_span::{ DUMMY_SP, ErrorGuaranteed, ExpnKind, FileName, SourceFileHash, SourceFileHashAlgorithm, Span, Symbol, sym, @@ -51,10 +53,18 @@ pub fn parse<'a>(sess: &'a Session) -> ast::Crate { let mut krate = sess .time("parse_crate", || { let mut parser = unwrap_or_emit_fatal(match &sess.io.input { - Input::File(file) => new_parser_from_file(&sess.psess, file, None), - Input::Str { input, name } => { - new_parser_from_source_str(&sess.psess, name.clone(), input.clone()) - } + Input::File(file) => new_parser_from_file( + &sess.psess, + file, + StripTokens::ShebangAndFrontmatter, + None, + ), + Input::Str { input, name } => new_parser_from_source_str( + &sess.psess, + name.clone(), + input.clone(), + StripTokens::ShebangAndFrontmatter, + ), }); parser.parse_crate_mod() }) @@ -1246,7 +1256,8 @@ pub fn get_crate_name(sess: &Session, krate_attrs: &[ast::Attribute]) -> Symbol // in all code paths that require the crate name very early on, namely before // macro expansion. - let attr_crate_name = parse_crate_name(sess, krate_attrs, ShouldEmit::EarlyFatal); + let attr_crate_name = + parse_crate_name(sess, krate_attrs, ShouldEmit::EarlyFatal { also_emit_lints: true }); let validate = |name, span| { rustc_session::output::validate_crate_name(sess, name, span); @@ -1307,36 +1318,18 @@ pub(crate) fn parse_crate_name( } fn get_recursion_limit(krate_attrs: &[ast::Attribute], sess: &Session) -> Limit { - // We don't permit macro calls inside of the attribute (e.g., #![recursion_limit = `expand!()`]) - // because that would require expanding this while in the middle of expansion, which needs to - // know the limit before expanding. - let _ = validate_and_find_value_str_builtin_attr(sym::recursion_limit, sess, krate_attrs); - crate::limits::get_recursion_limit(krate_attrs, sess) -} - -/// Validate *all* occurrences of the given "[value-str]" built-in attribute and return the first find. -/// -/// This validator is intended for built-in attributes whose value needs to be known very early -/// during compilation (namely, before macro expansion) and it mainly exists to reject macro calls -/// inside of the attributes, such as in `#![name = expand!()]`. Normal attribute validation happens -/// during semantic analysis via [`TyCtxt::check_mod_attrs`] which happens *after* macro expansion -/// when such macro calls (here: `expand`) have already been expanded and we can no longer check for -/// their presence. -/// -/// [value-str]: ast::Attribute::value_str -fn validate_and_find_value_str_builtin_attr( - name: Symbol, - sess: &Session, - krate_attrs: &[ast::Attribute], -) -> Option<(Symbol, Span)> { - let mut result = None; - // Validate *all* relevant attributes, not just the first occurrence. - for attr in ast::attr::filter_by_name(krate_attrs, name) { - let Some(value) = attr.value_str() else { - validate_attr::emit_fatal_malformed_builtin_attribute(&sess.psess, attr, name) - }; - // Choose the first occurrence as our result. - result.get_or_insert((value, attr.span)); - } - result + let attr = AttributeParser::parse_limited_should_emit( + sess, + &krate_attrs, + sym::recursion_limit, + DUMMY_SP, + rustc_ast::node_id::CRATE_NODE_ID, + None, + // errors are fatal here, but lints aren't. + // If things aren't fatal we continue, and will parse this again. + // That makes the same lint trigger again. + // So, no lints here to avoid duplicates. + ShouldEmit::EarlyFatal { also_emit_lints: false }, + ); + crate::limits::get_recursion_limit(attr.as_slice()) } diff --git a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs index 943fcc0801b1..e1c51ff82990 100644 --- a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs +++ b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs @@ -78,7 +78,7 @@ impl<'tcx> LateLintPass<'tcx> for DerefIntoDynSupertrait { { // erase regions in self type for better diagnostic presentation let (self_ty, target_principal, supertrait_principal) = - tcx.erase_regions((self_ty, target_principal, supertrait_principal)); + tcx.erase_and_anonymize_regions((self_ty, target_principal, supertrait_principal)); let label2 = tcx .associated_items(item.owner_id) .find_by_ident_and_kind( diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs index a56b753bda72..9e1fc5981711 100644 --- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs +++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs @@ -176,7 +176,7 @@ fn suggest_question_mark<'tcx>( cause, param_env, // Erase any region vids from the type, which may not be resolved - infcx.tcx.erase_regions(ty), + infcx.tcx.erase_and_anonymize_regions(ty), into_iterator_did, ); diff --git a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs index 5513c703f1d5..93f067d09833 100644 --- a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs +++ b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs @@ -47,7 +47,8 @@ impl<'tcx> LateLintPass<'tcx> for MultipleSupertraitUpcastable { .explicit_super_predicates_of(def_id) .iter_identity_copied() .filter_map(|(pred, _)| pred.as_trait_clause()) - .filter(|pred| !cx.tcx.is_lang_item(pred.def_id(), hir::LangItem::MetaSized)); + .filter(|pred| !cx.tcx.is_lang_item(pred.def_id(), hir::LangItem::MetaSized)) + .filter(|pred| !cx.tcx.is_default_trait(pred.def_id())); if direct_super_traits_iter.count() > 1 { cx.emit_span_lint( MULTIPLE_SUPERTRAIT_UPCASTABLE, diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index a72b802eb5d1..88527fa2e6e7 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -935,7 +935,7 @@ impl<'tcx> LateLintPass<'tcx> for VariantSizeDifferences { fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) { if let hir::ItemKind::Enum(_, _, ref enum_definition) = it.kind { let t = cx.tcx.type_of(it.owner_id).instantiate_identity(); - let ty = cx.tcx.erase_regions(t); + let ty = cx.tcx.erase_and_anonymize_regions(t); let Ok(layout) = cx.layout_of(ty) else { return }; let Variants::Multiple { tag_encoding: TagEncoding::Direct, tag, variants, .. } = &layout.variants diff --git a/compiler/rustc_llvm/Cargo.toml b/compiler/rustc_llvm/Cargo.toml index cd352ce3d0f4..0dfd1b13df50 100644 --- a/compiler/rustc_llvm/Cargo.toml +++ b/compiler/rustc_llvm/Cargo.toml @@ -11,7 +11,7 @@ libc = "0.2.73" [build-dependencies] # tidy-alphabetical-start # `cc` updates often break things, so we pin it here. Cargo enforces "max 1 semver-compat version -# per crate", so if you change this, you need to also change it in `rustc_codegen_ssa`. +# per crate", so if you change this, you need to also change it in `rustc_codegen_ssa` and `rustc_windows_rc`. cc = "=1.2.16" # tidy-alphabetical-end diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs index 225ab8c846d8..9d21d0d22e3e 100644 --- a/compiler/rustc_llvm/build.rs +++ b/compiler/rustc_llvm/build.rs @@ -254,7 +254,10 @@ fn main() { println!("cargo:rustc-link-lib=kstat"); } - if (target.starts_with("arm") && !target.contains("freebsd") && !target.contains("ohos")) + if (target.starts_with("arm") + && !target.starts_with("arm64") + && !target.contains("freebsd") + && !target.contains("ohos")) || target.starts_with("mips-") || target.starts_with("mipsel-") || target.starts_with("powerpc-") diff --git a/compiler/rustc_log/Cargo.toml b/compiler/rustc_log/Cargo.toml index 2332ff9b323b..72f68d685cd3 100644 --- a/compiler/rustc_log/Cargo.toml +++ b/compiler/rustc_log/Cargo.toml @@ -5,13 +5,12 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -# tracing > 0.1.37 have huge binary size / instructions regression -tracing = "=0.1.37" +tracing = "0.1.41" tracing-subscriber = { version = "0.3.3", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] } tracing-tree = "0.3.1" # tidy-alphabetical-end [features] # tidy-alphabetical-start -max_level_info = ['tracing/max_level_info'] +max_level_info = ['tracing/max_level_info', 'tracing/release_max_level_info'] # tidy-alphabetical-end diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs index 7520bc262c6b..dad402ec6961 100644 --- a/compiler/rustc_middle/src/error.rs +++ b/compiler/rustc_middle/src/error.rs @@ -72,7 +72,7 @@ pub enum TypeMismatchReason { #[help] pub(crate) struct RecursionLimitReached<'tcx> { pub ty: Ty<'tcx>, - pub suggested_limit: rustc_session::Limit, + pub suggested_limit: rustc_hir::limit::Limit, } #[derive(Diagnostic)] diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index 4fe4c2dadee1..153605ee7f81 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -27,7 +27,6 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lock; use rustc_macros::{HashStable, TypeFoldable, TypeVisitable}; pub use rustc_type_ir as ir; -pub use rustc_type_ir::CanonicalTyVarKind; use smallvec::SmallVec; use crate::mir::ConstraintCategory; diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 2ea92a39d482..67962813ae43 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -724,6 +724,11 @@ impl Allocation } // If we get here, we have to check per-byte provenance, and join them together. let prov = 'prov: { + if !Prov::OFFSET_IS_ADDR { + // FIXME(#146291): We need to ensure that we don't mix different pointers with + // the same provenance. + return Err(AllocError::ReadPartialPointer(range.start)); + } // Initialize with first fragment. Must have index 0. let Some((mut joint_prov, 0)) = self.provenance.get_byte(range.start, cx) else { break 'prov None; diff --git a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs index dbbd95408c8a..720e58d7aa0e 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs @@ -11,6 +11,7 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use tracing::trace; use super::{AllocRange, CtfeProvenance, Provenance, alloc_range}; +use crate::mir::interpret::{AllocError, AllocResult}; /// Stores the provenance information of pointers stored in memory. #[derive(Clone, PartialEq, Eq, Hash, Debug)] @@ -137,6 +138,11 @@ impl ProvenanceMap { let Some(bytes) = self.bytes.as_deref_mut() else { return true; }; + if !Prov::OFFSET_IS_ADDR { + // FIXME(#146291): We need to ensure that we don't mix different pointers with + // the same provenance. + return false; + } let ptr_size = cx.data_layout().pointer_size(); while let Some((offset, (prov, _))) = bytes.iter().next().copied() { // Check if this fragment starts a pointer. @@ -285,7 +291,7 @@ impl ProvenanceMap { dest: Size, count: u64, cx: &impl HasDataLayout, - ) -> ProvenanceCopy { + ) -> AllocResult> { let shift_offset = move |idx, offset| { // compute offset for current repetition let dest_offset = dest + src.size * idx; // `Size` operations @@ -363,6 +369,12 @@ impl ProvenanceMap { } trace!("byte provenances: {bytes:?}"); + if !bytes.is_empty() && !Prov::OFFSET_IS_ADDR { + // FIXME(#146291): We need to ensure that we don't mix different pointers with + // the same provenance. + return Err(AllocError::ReadPartialPointer(src.start)); + } + // And again a buffer for the new list on the target side. let mut dest_bytes = Vec::with_capacity(bytes.len() * (count as usize)); for i in 0..count { @@ -373,7 +385,7 @@ impl ProvenanceMap { dest_bytes_box = Some(dest_bytes.into_boxed_slice()); } - ProvenanceCopy { dest_ptrs: dest_ptrs_box, dest_bytes: dest_bytes_box } + Ok(ProvenanceCopy { dest_ptrs: dest_ptrs_box, dest_bytes: dest_bytes_box }) } /// Applies a provenance copy. diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index bed99a4ff2ab..9762e0f21da9 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -386,7 +386,16 @@ impl<'tcx> GlobalAlloc<'tcx> { .expect("statics should not have generic parameters"); let layout = tcx.layout_of(typing_env.as_query_input(ty)).unwrap(); assert!(layout.is_sized()); - (layout.size, layout.align.abi) + + // Take over-alignment from attributes into account. + let align = match tcx.codegen_fn_attrs(def_id).alignment { + Some(align_from_attribute) => { + Ord::max(align_from_attribute, layout.align.abi) + } + None => layout.align.abi, + }; + + (layout.size, align) } } GlobalAlloc::Memory(alloc) => { diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index e25f35c59c28..ecf35d9dd6d7 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -41,7 +41,7 @@ impl<'tcx> TyCtxt<'tcx> { let instance = ty::Instance::new_raw(def_id, args); let cid = GlobalId { instance, promoted: None }; let typing_env = ty::TypingEnv::post_analysis(self, def_id); - let inputs = self.erase_regions(typing_env.as_query_input(cid)); + let inputs = self.erase_and_anonymize_regions(typing_env.as_query_input(cid)); self.eval_to_allocation_raw(inputs) } @@ -172,8 +172,9 @@ impl<'tcx> TyCtxt<'tcx> { ) -> EvalToConstValueResult<'tcx> { // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should // improve caching of queries. - let inputs = - self.erase_regions(typing_env.with_post_analysis_normalized(self).as_query_input(cid)); + let inputs = self.erase_and_anonymize_regions( + typing_env.with_post_analysis_normalized(self).as_query_input(cid), + ); if !span.is_dummy() { // The query doesn't know where it is being invoked, so we need to fix the span. self.at(span).eval_to_const_value_raw(inputs).map_err(|e| e.with_span(span)) @@ -192,8 +193,9 @@ impl<'tcx> TyCtxt<'tcx> { ) -> ConstToValTreeResult<'tcx> { // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should // improve caching of queries. - let inputs = - self.erase_regions(typing_env.with_post_analysis_normalized(self).as_query_input(cid)); + let inputs = self.erase_and_anonymize_regions( + typing_env.with_post_analysis_normalized(self).as_query_input(cid), + ); debug!(?inputs); let res = if !span.is_dummy() { // The query doesn't know where it is being invoked, so we need to fix the span. diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index a7d99f513a12..f9d0a5f0a3b6 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -78,8 +78,9 @@ impl<'dis, 'de, 'tcx> MirDumper<'dis, 'de, 'tcx> { pub fn new(tcx: TyCtxt<'tcx>, pass_name: &'static str, body: &Body<'tcx>) -> Option { let dump_enabled = if let Some(ref filters) = tcx.sess.opts.unstable_opts.dump_mir { // see notes on #41697 below - let node_path = - ty::print::with_forced_impl_filename_line!(tcx.def_path_str(body.source.def_id())); + let node_path = ty::print::with_no_trimmed_paths!( + ty::print::with_forced_impl_filename_line!(tcx.def_path_str(body.source.def_id())) + ); filters.split('|').any(|or_filter| { or_filter.split('&').all(|and_filter| { let and_filter_trimmed = and_filter.trim(); @@ -173,9 +174,10 @@ impl<'dis, 'de, 'tcx> MirDumper<'dis, 'de, 'tcx> { // trigger `type_of`, and this can run while we are already attempting to evaluate `type_of`. pub fn dump_mir_to_writer(&self, body: &Body<'tcx>, w: &mut dyn io::Write) -> io::Result<()> { // see notes on #41697 above - let def_path = ty::print::with_forced_impl_filename_line!( - self.tcx().def_path_str(body.source.def_id()) - ); + let def_path = + ty::print::with_no_trimmed_paths!(ty::print::with_forced_impl_filename_line!( + self.tcx().def_path_str(body.source.def_id()) + )); // ignore-tidy-odd-backticks the literal below is fine write!(w, "// MIR for `{def_path}")?; match body.source.promoted { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 874cee54c7c6..2aa32dfa0d82 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -135,7 +135,7 @@ use crate::traits::{ }; use crate::ty::fast_reject::SimplifiedType; use crate::ty::layout::ValidityRequirement; -use crate::ty::print::{PrintTraitRefExt, describe_as_module}; +use crate::ty::print::PrintTraitRefExt; use crate::ty::util::AlwaysRequiresDrop; use crate::ty::{ self, CrateInherentImpls, GenericArg, GenericArgsRef, PseudoCanonicalInput, SizedTraitKind, Ty, @@ -761,9 +761,9 @@ rustc_queries! { } /// Erases regions from `ty` to yield a new type. - /// Normally you would just use `tcx.erase_regions(value)`, + /// Normally you would just use `tcx.erase_and_anonymize_regions(value)`, /// however, which uses this query as a kind of cache. - query erase_regions_ty(ty: Ty<'tcx>) -> Ty<'tcx> { + query erase_and_anonymize_regions_ty(ty: Ty<'tcx>) -> Ty<'tcx> { // This query is not expected to have input -- as a result, it // is not a good candidates for "replay" because it is essentially a // pure function of its input (and hence the expectation is that @@ -2731,3 +2731,12 @@ rustc_queries! { rustc_with_all_queries! { define_callbacks! } rustc_feedable_queries! { define_feedable! } + +fn describe_as_module(def_id: impl Into, tcx: TyCtxt<'_>) -> String { + let def_id = def_id.into(); + if def_id.is_top_level_module() { + "top-level module".to_string() + } else { + format!("module `{}`", tcx.def_path_str(def_id)) + } +} diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs index c9b9ec771b32..463e4c588055 100644 --- a/compiler/rustc_middle/src/ty/abstract_const.rs +++ b/compiler/rustc_middle/src/ty/abstract_const.rs @@ -55,7 +55,7 @@ impl<'tcx> TyCtxt<'tcx> { ty::ConstKind::Unevaluated(uv) => match self.tcx.thir_abstract_const(uv.def) { Err(e) => ty::Const::new_error(self.tcx, e), Ok(Some(bac)) => { - let args = self.tcx.erase_regions(uv.args); + let args = self.tcx.erase_and_anonymize_regions(uv.args); let bac = bac.instantiate(self.tcx, args); return bac.fold_with(self); } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 97c8a0336c21..218ac2cfbc19 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -38,6 +38,7 @@ use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId}; use rustc_hir::definitions::{DefPathData, Definitions, DisambiguatorState}; use rustc_hir::intravisit::VisitorExt; use rustc_hir::lang_items::LangItem; +use rustc_hir::limit::Limit; use rustc_hir::{self as hir, Attribute, HirId, Node, TraitCandidate, find_attr}; use rustc_index::IndexVec; use rustc_macros::{HashStable, TyDecodable, TyEncodable}; @@ -45,14 +46,14 @@ use rustc_query_system::cache::WithDepNode; use rustc_query_system::dep_graph::DepNodeIndex; use rustc_query_system::ich::StableHashingContext; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; +use rustc_session::Session; use rustc_session::config::CrateType; use rustc_session::cstore::{CrateStoreDyn, Untracked}; use rustc_session::lint::Lint; -use rustc_session::{Limit, Session}; use rustc_span::def_id::{CRATE_DEF_ID, DefPathHash, StableCrateId}; use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym}; use rustc_type_ir::TyKind::*; -use rustc_type_ir::lang_items::{SolverLangItem, SolverTraitLangItem}; +use rustc_type_ir::lang_items::{SolverAdtLangItem, SolverLangItem, SolverTraitLangItem}; pub use rustc_type_ir::lift::Lift; use rustc_type_ir::{ CollectAndApply, Interner, TypeFlags, TypeFoldable, WithCachedTypeInfo, elaborate, search_graph, @@ -94,6 +95,13 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type DefId = DefId; type LocalDefId = LocalDefId; type TraitId = DefId; + type ForeignId = DefId; + type FunctionId = DefId; + type ClosureId = DefId; + type CoroutineClosureId = DefId; + type CoroutineId = DefId; + type AdtId = DefId; + type ImplId = DefId; type Span = Span; type GenericArgs = ty::GenericArgsRef<'tcx>; @@ -492,6 +500,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.require_lang_item(solver_trait_lang_item_to_lang_item(lang_item), DUMMY_SP) } + fn require_adt_lang_item(self, lang_item: SolverAdtLangItem) -> DefId { + self.require_lang_item(solver_adt_lang_item_to_lang_item(lang_item), DUMMY_SP) + } + fn is_lang_item(self, def_id: DefId, lang_item: SolverLangItem) -> bool { self.is_lang_item(def_id, solver_lang_item_to_lang_item(lang_item)) } @@ -500,6 +512,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.is_lang_item(def_id, solver_trait_lang_item_to_lang_item(lang_item)) } + fn is_adt_lang_item(self, def_id: DefId, lang_item: SolverAdtLangItem) -> bool { + self.is_lang_item(def_id, solver_adt_lang_item_to_lang_item(lang_item)) + } + fn is_default_trait(self, def_id: DefId) -> bool { self.is_default_trait(def_id) } @@ -512,6 +528,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { lang_item_to_solver_trait_lang_item(self.lang_items().from_def_id(def_id)?) } + fn as_adt_lang_item(self, def_id: DefId) -> Option { + lang_item_to_solver_adt_lang_item(self.lang_items().from_def_id(def_id)?) + } + fn associated_type_def_ids(self, def_id: DefId) -> impl IntoIterator { self.associated_items(def_id) .in_definition_order() @@ -783,6 +803,13 @@ bidirectional_lang_item_map! { DynMetadata, FutureOutput, Metadata, +// tidy-alphabetical-end +} + +bidirectional_lang_item_map! { + SolverAdtLangItem, lang_item_to_solver_adt_lang_item, solver_adt_lang_item_to_lang_item; + +// tidy-alphabetical-start Option, Poll, // tidy-alphabetical-end diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs index f4fead7e9526..74b4adda7fdd 100644 --- a/compiler/rustc_middle/src/ty/erase_regions.rs +++ b/compiler/rustc_middle/src/ty/erase_regions.rs @@ -6,20 +6,20 @@ use crate::ty::{ }; pub(super) fn provide(providers: &mut Providers) { - *providers = Providers { erase_regions_ty, ..*providers }; + *providers = Providers { erase_and_anonymize_regions_ty, ..*providers }; } -fn erase_regions_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { +fn erase_and_anonymize_regions_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { // N.B., use `super_fold_with` here. If we used `fold_with`, it - // could invoke the `erase_regions_ty` query recursively. - ty.super_fold_with(&mut RegionEraserVisitor { tcx }) + // could invoke the `erase_and_anonymize_regions_ty` query recursively. + ty.super_fold_with(&mut RegionEraserAndAnonymizerVisitor { tcx }) } impl<'tcx> TyCtxt<'tcx> { - /// Returns an equivalent value with all free regions removed (note - /// that late-bound regions remain, because they are important for - /// subtyping, but they are anonymized and normalized as well).. - pub fn erase_regions(self, value: T) -> T + /// Returns an equivalent value with all free regions removed and + /// bound regions anonymized. (note that bound regions are important + /// for subtyping and generally type equality so *cannot* be removed) + pub fn erase_and_anonymize_regions(self, value: T) -> T where T: TypeFoldable>, { @@ -27,18 +27,18 @@ impl<'tcx> TyCtxt<'tcx> { if !value.has_type_flags(TypeFlags::HAS_BINDER_VARS | TypeFlags::HAS_FREE_REGIONS) { return value; } - debug!("erase_regions({:?})", value); - let value1 = value.fold_with(&mut RegionEraserVisitor { tcx: self }); - debug!("erase_regions = {:?}", value1); + debug!("erase_and_anonymize_regions({:?})", value); + let value1 = value.fold_with(&mut RegionEraserAndAnonymizerVisitor { tcx: self }); + debug!("erase_and_anonymize_regions = {:?}", value1); value1 } } -struct RegionEraserVisitor<'tcx> { +struct RegionEraserAndAnonymizerVisitor<'tcx> { tcx: TyCtxt<'tcx>, } -impl<'tcx> TypeFolder> for RegionEraserVisitor<'tcx> { +impl<'tcx> TypeFolder> for RegionEraserAndAnonymizerVisitor<'tcx> { fn cx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -49,7 +49,7 @@ impl<'tcx> TypeFolder> for RegionEraserVisitor<'tcx> { } else if ty.has_infer() { ty.super_fold_with(self) } else { - self.tcx.erase_regions_ty(ty) + self.tcx.erase_and_anonymize_regions_ty(ty) } } diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 3f854038651a..66542525d284 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -7,6 +7,7 @@ use std::path::PathBuf; use rustc_errors::pluralize; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind}; +use rustc_hir::limit::Limit; use rustc_macros::extension; pub use rustc_type_ir::error::ExpectedFound; @@ -233,7 +234,7 @@ impl<'tcx> TyCtxt<'tcx> { loop { // Look for the longest properly trimmed path that still fits in length_limit. short = with_forced_trimmed_paths!({ - let mut p = FmtPrinter::new_with_limit(self, ns, rustc_session::Limit(type_limit)); + let mut p = FmtPrinter::new_with_limit(self, ns, Limit(type_limit)); self.lift(t) .expect("could not lift for printing") .print(&mut p) diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 3a51f79f1216..e76993e0542b 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -544,7 +544,9 @@ impl<'tcx> Instance<'tcx> { // All regions in the result of this query are erased, so it's // fine to erase all of the input regions. - tcx.resolve_instance_raw(tcx.erase_regions(typing_env.as_query_input((def_id, args)))) + tcx.resolve_instance_raw( + tcx.erase_and_anonymize_regions(typing_env.as_query_input((def_id, args))), + ) } pub fn expect_resolve( diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index aed94f9aa04d..2114d080dfa4 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -401,7 +401,10 @@ impl<'tcx> SizeSkeleton<'tcx> { match tail.kind() { ty::Param(_) | ty::Alias(ty::Projection | ty::Inherent, _) => { debug_assert!(tail.has_non_region_param()); - Ok(SizeSkeleton::Pointer { non_zero, tail: tcx.erase_regions(tail) }) + Ok(SizeSkeleton::Pointer { + non_zero, + tail: tcx.erase_and_anonymize_regions(tail), + }) } ty::Error(guar) => { // Fixes ICE #124031 diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index e567ba05f61c..da17ec1f9f37 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -109,7 +109,6 @@ pub use self::typeck_results::{ CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, IsIdentity, Rust2024IncompatiblePatInfo, TypeckResults, UserType, UserTypeAnnotationIndex, UserTypeKind, }; -pub use self::visit::*; use crate::error::{OpaqueHiddenTypeMismatch, TypeMismatchReason}; use crate::metadata::ModChild; use crate::middle::privacy::EffectiveVisibilities; diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs index f2a4a5a4ecf7..69c1eb9b3454 100644 --- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs +++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs @@ -51,7 +51,7 @@ impl<'tcx> TyCtxt<'tcx> { // Erase first before we do the real query -- this keeps the // cache from being too polluted. - let value = self.erase_regions(value); + let value = self.erase_and_anonymize_regions(value); debug!(?value); if !value.has_aliases() { @@ -83,7 +83,7 @@ impl<'tcx> TyCtxt<'tcx> { // Erase first before we do the real query -- this keeps the // cache from being too polluted. - let value = self.erase_regions(value); + let value = self.erase_and_anonymize_regions(value); debug!(?value); if !value.has_aliases() { diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs index 59e00f85957e..69dcca54f469 100644 --- a/compiler/rustc_middle/src/ty/predicate.rs +++ b/compiler/rustc_middle/src/ty/predicate.rs @@ -638,21 +638,7 @@ impl<'tcx> Predicate<'tcx> { let predicate = self.kind(); match predicate.skip_binder() { PredicateKind::Clause(ClauseKind::Trait(t)) => Some(predicate.rebind(t)), - PredicateKind::Clause(ClauseKind::Projection(..)) - | PredicateKind::Clause(ClauseKind::HostEffect(..)) - | PredicateKind::Clause(ClauseKind::ConstArgHasType(..)) - | PredicateKind::Clause(ClauseKind::UnstableFeature(_)) - | PredicateKind::NormalizesTo(..) - | PredicateKind::AliasRelate(..) - | PredicateKind::Subtype(..) - | PredicateKind::Coerce(..) - | PredicateKind::Clause(ClauseKind::RegionOutlives(..)) - | PredicateKind::Clause(ClauseKind::WellFormed(..)) - | PredicateKind::DynCompatible(..) - | PredicateKind::Clause(ClauseKind::TypeOutlives(..)) - | PredicateKind::Clause(ClauseKind::ConstEvaluatable(..)) - | PredicateKind::ConstEquate(..) - | PredicateKind::Ambiguous => None, + _ => None, } } @@ -660,21 +646,7 @@ impl<'tcx> Predicate<'tcx> { let predicate = self.kind(); match predicate.skip_binder() { PredicateKind::Clause(ClauseKind::Projection(t)) => Some(predicate.rebind(t)), - PredicateKind::Clause(ClauseKind::Trait(..)) - | PredicateKind::Clause(ClauseKind::HostEffect(..)) - | PredicateKind::Clause(ClauseKind::ConstArgHasType(..)) - | PredicateKind::Clause(ClauseKind::UnstableFeature(_)) - | PredicateKind::NormalizesTo(..) - | PredicateKind::AliasRelate(..) - | PredicateKind::Subtype(..) - | PredicateKind::Coerce(..) - | PredicateKind::Clause(ClauseKind::RegionOutlives(..)) - | PredicateKind::Clause(ClauseKind::WellFormed(..)) - | PredicateKind::DynCompatible(..) - | PredicateKind::Clause(ClauseKind::TypeOutlives(..)) - | PredicateKind::Clause(ClauseKind::ConstEvaluatable(..)) - | PredicateKind::ConstEquate(..) - | PredicateKind::Ambiguous => None, + _ => None, } } diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index 9e6f277ef770..d636e8ef31ff 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -2,7 +2,7 @@ use hir::def::Namespace; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sso::SsoHashSet; use rustc_hir as hir; -use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; +use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; use tracing::{debug, instrument, trace}; @@ -396,16 +396,6 @@ impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::Const<'tcx> { } } -// This is only used by query descriptions -pub fn describe_as_module(def_id: impl Into, tcx: TyCtxt<'_>) -> String { - let def_id = def_id.into(); - if def_id.is_top_level_module() { - "top-level module".to_string() - } else { - format!("module `{}`", tcx.def_path_str(def_id)) - } -} - impl rustc_type_ir::ir_print::IrPrint for TyCtxt<'_> where T: Copy + for<'a, 'tcx> Lift, Lifted: Print<'tcx, FmtPrinter<'a, 'tcx>>>, diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 74caee7336a5..fc821ffdaa68 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -13,8 +13,8 @@ use rustc_hir::LangItem; use rustc_hir::def::{self, CtorKind, DefKind, Namespace}; use rustc_hir::def_id::{DefIdMap, DefIdSet, LOCAL_CRATE, ModDefId}; use rustc_hir::definitions::{DefKey, DefPathDataName}; +use rustc_hir::limit::Limit; use rustc_macros::{Lift, extension}; -use rustc_session::Limit; use rustc_session::cstore::{ExternCrate, ExternCrateSource}; use rustc_span::{FileNameDisplayPreference, Ident, Symbol, kw, sym}; use rustc_type_ir::{Upcast as _, elaborate}; @@ -1436,8 +1436,8 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { // anonymized regions, but the super projections can still // contain named regions. So we erase and anonymize everything // here to compare the types modulo regions below. - let proj = p.tcx().erase_regions(proj); - let super_proj = p.tcx().erase_regions(super_proj); + let proj = p.tcx().erase_and_anonymize_regions(proj); + let super_proj = p.tcx().erase_and_anonymize_regions(super_proj); proj == super_proj }); diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index a7d07adf78f0..96fbdf447912 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -12,9 +12,9 @@ use rustc_hashes::Hash128; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; +use rustc_hir::limit::Limit; use rustc_index::bit_set::GrowableBitSet; use rustc_macros::{HashStable, TyDecodable, TyEncodable, extension}; -use rustc_session::Limit; use rustc_span::sym; use rustc_type_ir::solve::SizedTraitKind; use smallvec::{SmallVec, smallvec}; @@ -131,10 +131,9 @@ impl<'tcx> TyCtxt<'tcx> { /// Creates a hash of the type `Ty` which will be the same no matter what crate /// context it's calculated within. This is used by the `type_id` intrinsic. pub fn type_id_hash(self, ty: Ty<'tcx>) -> Hash128 { - // We want the type_id be independent of the types free regions, so we - // erase them. The erase_regions() call will also anonymize bound - // regions, which is desirable too. - let ty = self.erase_regions(ty); + // We don't have region information, so we erase all free regions. Equal types + // must have the same `TypeId`, so we must anonymize all bound regions as well. + let ty = self.erase_and_anonymize_regions(ty); self.with_stable_hashing_context(|mut hcx| { let mut hasher = StableHasher::new(); @@ -1309,7 +1308,7 @@ impl<'tcx> Ty<'tcx> { debug_assert!(!typing_env.param_env.has_infer()); let query_ty = tcx .try_normalize_erasing_regions(typing_env, query_ty) - .unwrap_or_else(|_| tcx.erase_regions(query_ty)); + .unwrap_or_else(|_| tcx.erase_and_anonymize_regions(query_ty)); tcx.needs_drop_raw(typing_env.as_query_input(query_ty)) } @@ -1346,7 +1345,7 @@ impl<'tcx> Ty<'tcx> { debug_assert!(!typing_env.has_infer()); let query_ty = tcx .try_normalize_erasing_regions(typing_env, query_ty) - .unwrap_or_else(|_| tcx.erase_regions(query_ty)); + .unwrap_or_else(|_| tcx.erase_and_anonymize_regions(query_ty)); tcx.needs_async_drop_raw(typing_env.as_query_input(query_ty)) } diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index 3853a804a920..f0c47f257cc4 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -212,42 +212,3 @@ impl<'tcx> TypeVisitor> for LateBoundRegionsCollector { } } } - -/// Finds the max universe present -pub struct MaxUniverse { - max_universe: ty::UniverseIndex, -} - -impl MaxUniverse { - pub fn new() -> Self { - MaxUniverse { max_universe: ty::UniverseIndex::ROOT } - } - - pub fn max_universe(self) -> ty::UniverseIndex { - self.max_universe - } -} - -impl<'tcx> TypeVisitor> for MaxUniverse { - fn visit_ty(&mut self, t: Ty<'tcx>) { - if let ty::Placeholder(placeholder) = t.kind() { - self.max_universe = self.max_universe.max(placeholder.universe); - } - - t.super_visit_with(self) - } - - fn visit_const(&mut self, c: ty::consts::Const<'tcx>) { - if let ty::ConstKind::Placeholder(placeholder) = c.kind() { - self.max_universe = self.max_universe.max(placeholder.universe); - } - - c.super_visit_with(self) - } - - fn visit_region(&mut self, r: ty::Region<'tcx>) { - if let ty::RePlaceholder(placeholder) = r.kind() { - self.max_universe = self.max_universe.max(placeholder.universe); - } - } -} diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs index 6fc19c82342f..e2f09fdcb4b4 100644 --- a/compiler/rustc_middle/src/ty/vtable.rs +++ b/compiler/rustc_middle/src/ty/vtable.rs @@ -89,7 +89,7 @@ pub(super) fn vtable_allocation_provider<'tcx>( let vtable_entries = if let Some(poly_trait_ref) = poly_trait_ref { let trait_ref = poly_trait_ref.with_self_ty(tcx, ty); - let trait_ref = tcx.erase_regions(trait_ref); + let trait_ref = tcx.erase_and_anonymize_regions(trait_ref); tcx.vtable_entries(trait_ref) } else { diff --git a/compiler/rustc_mir_build/src/check_tail_calls.rs b/compiler/rustc_mir_build/src/check_tail_calls.rs index e0cbe8519edd..d40c77d145f4 100644 --- a/compiler/rustc_mir_build/src/check_tail_calls.rs +++ b/compiler/rustc_mir_build/src/check_tail_calls.rs @@ -64,10 +64,10 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> { "`become` outside of functions should have been disallowed by hir_typeck" ) }; - // While the `caller_sig` does have its regions erased, it does not have its - // binders anonymized. We call `erase_regions` once again to anonymize any binders + // While the `caller_sig` does have its free regions erased, it does not have its + // binders anonymized. We call `erase_and_anonymize_regions` once again to anonymize any binders // within the signature, such as in function pointer or `dyn Trait` args. - let caller_sig = self.tcx.erase_regions(caller_sig); + let caller_sig = self.tcx.erase_and_anonymize_regions(caller_sig); let ExprKind::Scope { value, .. } = call.kind else { span_bug!(call.span, "expected scope, found: {call:?}") diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 81b0e21a5f55..0b9bc018a09b 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -792,10 +792,9 @@ impl<'tcx> ThirBuildCx<'tcx> { let ty = self.typeck_results.node_type(anon_const.hir_id); let did = anon_const.def_id.to_def_id(); let typeck_root_def_id = tcx.typeck_root_def_id(did); - let parent_args = tcx.erase_regions(GenericArgs::identity_for_item( - tcx, - typeck_root_def_id, - )); + let parent_args = tcx.erase_and_anonymize_regions( + GenericArgs::identity_for_item(tcx, typeck_root_def_id), + ); let args = InlineConstArgs::new(tcx, InlineConstArgsParts { parent_args, ty }) .args; @@ -831,8 +830,10 @@ impl<'tcx> ThirBuildCx<'tcx> { let ty = self.typeck_results.node_type(anon_const.hir_id); let did = anon_const.def_id.to_def_id(); let typeck_root_def_id = tcx.typeck_root_def_id(did); - let parent_args = - tcx.erase_regions(GenericArgs::identity_for_item(tcx, typeck_root_def_id)); + let parent_args = tcx.erase_and_anonymize_regions(GenericArgs::identity_for_item( + tcx, + typeck_root_def_id, + )); let args = InlineConstArgs::new(tcx, InlineConstArgsParts { parent_args, ty }).args; ExprKind::ConstBlock { did, args } diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index d46c4678bcf7..6316ccf1b8c5 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -105,9 +105,11 @@ impl<'tcx> ConstToPat<'tcx> { // // FIXME: `const_eval_resolve_for_typeck` should probably just modify the env itself // instead of having this logic here - let typing_env = - self.tcx.erase_regions(self.typing_env).with_post_analysis_normalized(self.tcx); - let uv = self.tcx.erase_regions(uv); + let typing_env = self + .tcx + .erase_and_anonymize_regions(self.typing_env) + .with_post_analysis_normalized(self.tcx); + let uv = self.tcx.erase_and_anonymize_regions(uv); // try to resolve e.g. associated constants to their definition on an impl, and then // evaluate the const. diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 9a00831dc012..bf5ec8f459e6 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -891,7 +891,7 @@ pub fn iter_fields<'tcx>( let field_ty = f_def.ty(tcx, args); let field_ty = tcx .try_normalize_erasing_regions(typing_env, field_ty) - .unwrap_or_else(|_| tcx.erase_regions(field_ty)); + .unwrap_or_else(|_| tcx.erase_and_anonymize_regions(field_ty)); f(variant, f_index.into(), field_ty); } } diff --git a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs index 92ee80eaa353..be4f84d64d03 100644 --- a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs +++ b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs @@ -32,8 +32,8 @@ impl<'a, 'tcx> MutVisitor<'tcx> for SubTypeChecker<'a, 'tcx> { let mut rval_ty = rvalue.ty(self.local_decls, self.tcx); // Not erasing this causes `Free Regions` errors in validator, // when rval is `ReStatic`. - rval_ty = self.tcx.erase_regions(rval_ty); - place_ty = self.tcx.erase_regions(place_ty); + rval_ty = self.tcx.erase_and_anonymize_regions(rval_ty); + place_ty = self.tcx.erase_and_anonymize_regions(place_ty); if place_ty != rval_ty { let temp = self .patcher diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index f867c130efb9..bf6aa800d20f 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -1644,6 +1644,11 @@ impl<'tcx> VnState<'_, 'tcx> { let place = Place { local, projection: self.tcx.mk_place_elems(projection.as_slice()) }; return Some(place); + } else if projection.last() == Some(&PlaceElem::Deref) { + // `Deref` can only be the first projection in a place. + // If we are here, we failed to find a local, and we already have a `Deref`. + // Trying to add projections will only result in an ill-formed place. + return None; } else if let Value::Projection(pointer, proj) = *self.get(index) && (allow_complex_projection || proj.is_stable_offset()) && let Some(proj) = self.try_as_place_elem(self.ty(index), proj, loc) diff --git a/compiler/rustc_mir_transform/src/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs index 7f9234d1dc89..25a9baffe582 100644 --- a/compiler/rustc_mir_transform/src/inline/cycle.rs +++ b/compiler/rustc_mir_transform/src/inline/cycle.rs @@ -2,9 +2,9 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::unord::UnordSet; use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::limit::Limit; use rustc_middle::mir::TerminatorKind; use rustc_middle::ty::{self, GenericArgsRef, InstanceKind, TyCtxt, TypeVisitableExt}; -use rustc_session::Limit; use rustc_span::sym; use tracing::{instrument, trace}; diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index 462ddfa3dd3c..9ea2eb4f25d9 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -875,7 +875,8 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { let mut promoted_operand = |ty, span| { promoted.span = span; promoted.local_decls[RETURN_PLACE] = LocalDecl::new(ty, span); - let args = tcx.erase_regions(GenericArgs::identity_for_item(tcx, def)); + let args = + tcx.erase_and_anonymize_regions(GenericArgs::identity_for_item(tcx, def)); let uneval = mir::UnevaluatedConst { def, args, promoted: Some(next_promoted_index) }; diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index cffeb6f98075..378d71cb1fcd 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -217,6 +217,7 @@ use rustc_hir::attrs::InlineAttr; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId}; use rustc_hir::lang_items::LangItem; +use rustc_hir::limit::Limit; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::interpret::{AllocId, ErrorHandled, GlobalAlloc, Scalar}; use rustc_middle::mir::mono::{CollectionMode, InstantiationMode, MonoItem}; @@ -231,7 +232,6 @@ use rustc_middle::ty::{ }; use rustc_middle::util::Providers; use rustc_middle::{bug, span_bug}; -use rustc_session::Limit; use rustc_session::config::{DebugInfo, EntryFnType}; use rustc_span::source_map::{Spanned, dummy_spanned, respan}; use rustc_span::{DUMMY_SP, Span}; @@ -1558,7 +1558,7 @@ impl<'v> RootCollector<'_, 'v> { ty::Closure(def_id, args) | ty::Coroutine(def_id, args) | ty::CoroutineClosure(def_id, args) => { - Instance::new_raw(def_id, self.tcx.erase_regions(args)) + Instance::new_raw(def_id, self.tcx.erase_and_anonymize_regions(args)) } _ => unreachable!(), }; diff --git a/compiler/rustc_monomorphize/src/mono_checks/move_check.rs b/compiler/rustc_monomorphize/src/mono_checks/move_check.rs index 7251ef478c6f..0adf1b089b53 100644 --- a/compiler/rustc_monomorphize/src/mono_checks/move_check.rs +++ b/compiler/rustc_monomorphize/src/mono_checks/move_check.rs @@ -1,10 +1,10 @@ use rustc_abi::Size; use rustc_data_structures::fx::FxIndexSet; use rustc_hir::def_id::DefId; +use rustc_hir::limit::Limit; use rustc_middle::mir::visit::Visitor as MirVisitor; use rustc_middle::mir::{self, Location, traversal}; use rustc_middle::ty::{self, AssocTag, Instance, Ty, TyCtxt, TypeFoldable}; -use rustc_session::Limit; use rustc_session::lint::builtin::LARGE_ASSIGNMENTS; use rustc_span::source_map::Spanned; use rustc_span::{Ident, Span, sym}; diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs index da05c49756ff..a8f2b4e8db66 100644 --- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs @@ -2,9 +2,8 @@ use rustc_type_ir::data_structures::{HashMap, ensure_sufficient_stack}; use rustc_type_ir::inherent::*; use rustc_type_ir::solve::{Goal, QueryInput}; use rustc_type_ir::{ - self as ty, Canonical, CanonicalParamEnvCacheEntry, CanonicalTyVarKind, CanonicalVarKind, - Flags, InferCtxtLike, Interner, TypeFlags, TypeFoldable, TypeFolder, TypeSuperFoldable, - TypeVisitableExt, + self as ty, Canonical, CanonicalParamEnvCacheEntry, CanonicalVarKind, Flags, InferCtxtLike, + Interner, TypeFlags, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, }; use crate::delegate::SolverDelegate; @@ -68,6 +67,13 @@ pub struct Canonicalizer<'a, D: SolverDelegate, I: Interner> { variables: &'a mut Vec, var_kinds: Vec>, variable_lookup_table: HashMap, + /// Maps each `sub_unification_table_root_var` to the index of the first + /// variable which used it. + /// + /// This means in case two type variables have the same sub relations root, + /// we set the `sub_root` of the second variable to the position of the first. + /// Otherwise the `sub_root` of each type variable is just its own position. + sub_root_lookup_table: HashMap, binder_index: ty::DebruijnIndex, /// We only use the debruijn index during lookup. We don't need to @@ -89,6 +95,7 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { variables, variable_lookup_table: Default::default(), + sub_root_lookup_table: Default::default(), var_kinds: Vec::new(), binder_index: ty::INNERMOST, @@ -133,6 +140,7 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { variables: &mut variables, variable_lookup_table: Default::default(), + sub_root_lookup_table: Default::default(), var_kinds: Vec::new(), binder_index: ty::INNERMOST, @@ -140,6 +148,7 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { }; let param_env = param_env.fold_with(&mut env_canonicalizer); debug_assert_eq!(env_canonicalizer.binder_index, ty::INNERMOST); + debug_assert!(env_canonicalizer.sub_root_lookup_table.is_empty()); CanonicalParamEnvCacheEntry { param_env, variable_lookup_table: env_canonicalizer.variable_lookup_table, @@ -165,6 +174,7 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { variables, variable_lookup_table: Default::default(), + sub_root_lookup_table: Default::default(), var_kinds: Vec::new(), binder_index: ty::INNERMOST, @@ -172,6 +182,7 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { }; let param_env = param_env.fold_with(&mut env_canonicalizer); debug_assert_eq!(env_canonicalizer.binder_index, ty::INNERMOST); + debug_assert!(env_canonicalizer.sub_root_lookup_table.is_empty()); (param_env, env_canonicalizer.variable_lookup_table, env_canonicalizer.var_kinds) } } @@ -200,6 +211,7 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { variables, variable_lookup_table, + sub_root_lookup_table: Default::default(), var_kinds, binder_index: ty::INNERMOST, @@ -266,6 +278,13 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { ty::BoundVar::from(idx) } + fn get_or_insert_sub_root(&mut self, vid: ty::TyVid) -> ty::BoundVar { + let root_vid = self.delegate.sub_unification_table_root_var(vid); + let idx = + *self.sub_root_lookup_table.entry(root_vid).or_insert_with(|| self.variables.len()); + ty::BoundVar::from(idx) + } + fn finalize(self) -> (ty::UniverseIndex, I::CanonicalVarKinds) { let mut var_kinds = self.var_kinds; // See the rustc-dev-guide section about how we deal with universes @@ -313,18 +332,15 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { "ty vid should have been resolved fully before canonicalization" ); - match self.canonicalize_mode { - CanonicalizeMode::Input { .. } => CanonicalVarKind::Ty( - CanonicalTyVarKind::General(ty::UniverseIndex::ROOT), - ), - CanonicalizeMode::Response { .. } => { - CanonicalVarKind::Ty(CanonicalTyVarKind::General( - self.delegate.universe_of_ty(vid).unwrap_or_else(|| { - panic!("ty var should have been resolved: {t:?}") - }), - )) - } - } + let sub_root = self.get_or_insert_sub_root(vid); + let ui = match self.canonicalize_mode { + CanonicalizeMode::Input { .. } => ty::UniverseIndex::ROOT, + CanonicalizeMode::Response { .. } => self + .delegate + .universe_of_ty(vid) + .unwrap_or_else(|| panic!("ty var should have been resolved: {t:?}")), + }; + CanonicalVarKind::Ty { ui, sub_root } } ty::IntVar(vid) => { debug_assert_eq!( @@ -332,7 +348,7 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { t, "ty vid should have been resolved fully before canonicalization" ); - CanonicalVarKind::Ty(CanonicalTyVarKind::Int) + CanonicalVarKind::Int } ty::FloatVar(vid) => { debug_assert_eq!( @@ -340,7 +356,7 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { t, "ty vid should have been resolved fully before canonicalization" ); - CanonicalVarKind::Ty(CanonicalTyVarKind::Float) + CanonicalVarKind::Float } ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => { panic!("fresh vars not expected in canonicalization") diff --git a/compiler/rustc_next_trait_solver/src/coherence.rs b/compiler/rustc_next_trait_solver/src/coherence.rs index 79219b34e290..b949deb11926 100644 --- a/compiler/rustc_next_trait_solver/src/coherence.rs +++ b/compiler/rustc_next_trait_solver/src/coherence.rs @@ -435,7 +435,21 @@ where } } ty::Error(_) => ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)), - ty::Closure(did, ..) | ty::CoroutineClosure(did, ..) | ty::Coroutine(did, ..) => { + ty::Closure(did, ..) => { + if self.def_id_is_local(did) { + ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)) + } else { + self.found_non_local_ty(ty) + } + } + ty::CoroutineClosure(did, ..) => { + if self.def_id_is_local(did) { + ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)) + } else { + self.found_non_local_ty(ty) + } + } + ty::Coroutine(did, ..) => { if self.def_id_is_local(did) { ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)) } else { diff --git a/compiler/rustc_next_trait_solver/src/delegate.rs b/compiler/rustc_next_trait_solver/src/delegate.rs index 7b932010d498..41c2e5f60ec3 100644 --- a/compiler/rustc_next_trait_solver/src/delegate.rs +++ b/compiler/rustc_next_trait_solver/src/delegate.rs @@ -57,12 +57,14 @@ pub trait SolverDelegate: Deref + Sized { where V: TypeFoldable; - fn instantiate_canonical_var_with_infer( + fn instantiate_canonical_var( &self, kind: ty::CanonicalVarKind, span: ::Span, + var_values: &[::GenericArg], universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex, ) -> ::GenericArg; + fn add_item_bounds_for_hidden_type( &self, def_id: ::DefId, @@ -76,7 +78,7 @@ pub trait SolverDelegate: Deref + Sized { &self, goal_trait_ref: ty::TraitRef, trait_assoc_def_id: ::DefId, - impl_def_id: ::DefId, + impl_def_id: ::ImplId, ) -> Result< Option<::DefId>, ::ErrorGuaranteed, diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index be7e4dd4cdaf..e3cf0330b14a 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -186,7 +186,7 @@ where fn consider_impl_candidate( ecx: &mut EvalCtxt<'_, D>, goal: Goal, - impl_def_id: I::DefId, + impl_def_id: I::ImplId, ) -> Result, NoSolution>; /// If the predicate contained an error, we want to avoid emitting unnecessary trait diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index 7c5940828daa..f6eab286ba70 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -605,7 +605,7 @@ fn coroutine_closure_to_certain_coroutine( cx: I, goal_kind: ty::ClosureKind, goal_region: I::Region, - def_id: I::DefId, + def_id: I::CoroutineClosureId, args: ty::CoroutineClosureArgs, sig: ty::CoroutineClosureSignature, ) -> I::Ty { @@ -629,7 +629,7 @@ fn coroutine_closure_to_ambiguous_coroutine( cx: I, goal_kind: ty::ClosureKind, goal_region: I::Region, - def_id: I::DefId, + def_id: I::CoroutineClosureId, args: ty::CoroutineClosureArgs, sig: ty::CoroutineClosureSignature, ) -> I::Ty { @@ -664,7 +664,7 @@ fn coroutine_closure_to_ambiguous_coroutine( pub(in crate::solve) fn extract_fn_def_from_const_callable( cx: I, self_ty: I::Ty, -) -> Result<(ty::Binder, I::DefId, I::GenericArgs), NoSolution> { +) -> Result<(ty::Binder, I::FunctionId, I::GenericArgs), NoSolution> { match self_ty.kind() { ty::FnDef(def_id, args) => { let sig = cx.fn_sig(def_id); diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs index 229345065b19..6646857a1368 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -123,7 +123,7 @@ where fn consider_impl_candidate( ecx: &mut EvalCtxt<'_, D>, goal: Goal, - impl_def_id: I::DefId, + impl_def_id: I::ImplId, ) -> Result, NoSolution> { let cx = ecx.cx(); @@ -152,20 +152,20 @@ where } ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| { - let impl_args = ecx.fresh_args_for_item(impl_def_id); + let impl_args = ecx.fresh_args_for_item(impl_def_id.into()); ecx.record_impl_args(impl_args); let impl_trait_ref = impl_trait_ref.instantiate(cx, impl_args); ecx.eq(goal.param_env, goal.predicate.trait_ref, impl_trait_ref)?; let where_clause_bounds = cx - .predicates_of(impl_def_id) + .predicates_of(impl_def_id.into()) .iter_instantiated(cx, impl_args) .map(|pred| goal.with(cx, pred)); ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds); // For this impl to be `const`, we need to check its `[const]` bounds too. let const_conditions = cx - .const_conditions(impl_def_id) + .const_conditions(impl_def_id.into()) .iter_instantiated(cx, impl_args) .map(|bound_trait_ref| { goal.with( @@ -240,7 +240,7 @@ where ty::TraitRef::new(cx, cx.require_trait_lang_item(SolverTraitLangItem::Sized), [output]) }); let requirements = cx - .const_conditions(def_id) + .const_conditions(def_id.into()) .iter_instantiated(cx, args) .map(|trait_ref| { ( diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs index 6f9f40673847..169832ca5fbd 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs @@ -16,7 +16,8 @@ use rustc_type_ir::data_structures::HashSet; use rustc_type_ir::inherent::*; use rustc_type_ir::relate::solver_relating::RelateExt; use rustc_type_ir::{ - self as ty, Canonical, CanonicalVarValues, InferCtxtLike, Interner, TypeFoldable, + self as ty, Canonical, CanonicalVarKind, CanonicalVarValues, InferCtxtLike, Interner, + TypeFoldable, }; use tracing::{debug, instrument, trace}; @@ -336,7 +337,16 @@ where { match result_value.kind() { ty::GenericArgKind::Type(t) => { - if let ty::Bound(debruijn, b) = t.kind() { + // We disable the instantiation guess for inference variables + // and only use it for placeholders. We need to handle the + // `sub_root` of type inference variables which would make this + // more involved. They are also a lot rarer than region variables. + if let ty::Bound(debruijn, b) = t.kind() + && !matches!( + response.variables.get(b.var().as_usize()).unwrap(), + CanonicalVarKind::Ty { .. } + ) + { assert_eq!(debruijn, ty::INNERMOST); opt_values[b.var()] = Some(*original_value); } @@ -355,39 +365,33 @@ where } } } - - let var_values = delegate.cx().mk_args_from_iter( - response.variables.iter().enumerate().map(|(index, var_kind)| { - if var_kind.universe() != ty::UniverseIndex::ROOT { - // A variable from inside a binder of the query. While ideally these shouldn't - // exist at all (see the FIXME at the start of this method), we have to deal with - // them for now. - delegate.instantiate_canonical_var_with_infer(var_kind, span, |idx| { - prev_universe + idx.index() - }) - } else if var_kind.is_existential() { - // As an optimization we sometimes avoid creating a new inference variable here. - // - // All new inference variables we create start out in the current universe of the caller. - // This is conceptually wrong as these inference variables would be able to name - // more placeholders then they should be able to. However the inference variables have - // to "come from somewhere", so by equating them with the original values of the caller - // later on, we pull them down into their correct universe again. - if let Some(v) = opt_values[ty::BoundVar::from_usize(index)] { - v - } else { - delegate - .instantiate_canonical_var_with_infer(var_kind, span, |_| prev_universe) - } + CanonicalVarValues::instantiate(delegate.cx(), response.variables, |var_values, kind| { + if kind.universe() != ty::UniverseIndex::ROOT { + // A variable from inside a binder of the query. While ideally these shouldn't + // exist at all (see the FIXME at the start of this method), we have to deal with + // them for now. + delegate.instantiate_canonical_var(kind, span, &var_values, |idx| { + prev_universe + idx.index() + }) + } else if kind.is_existential() { + // As an optimization we sometimes avoid creating a new inference variable here. + // + // All new inference variables we create start out in the current universe of the caller. + // This is conceptually wrong as these inference variables would be able to name + // more placeholders then they should be able to. However the inference variables have + // to "come from somewhere", so by equating them with the original values of the caller + // later on, we pull them down into their correct universe again. + if let Some(v) = opt_values[ty::BoundVar::from_usize(var_values.len())] { + v } else { - // For placeholders which were already part of the input, we simply map this - // universal bound variable back the placeholder of the input. - original_values[var_kind.expect_placeholder_index()] + delegate.instantiate_canonical_var(kind, span, &var_values, |_| prev_universe) } - }), - ); - - CanonicalVarValues { var_values } + } else { + // For placeholders which were already part of the input, we simply map this + // universal bound variable back the placeholder of the input. + original_values[kind.expect_placeholder_index()] + } + }) } /// Unify the `original_values` with the `var_values` returned by the canonical query.. diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 443aebbdb4d6..5cd597d4fe6b 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -900,6 +900,10 @@ where && goal.param_env.visit_with(&mut visitor).is_continue() } + pub(super) fn sub_unify_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid) { + self.delegate.sub_unify_ty_vids_raw(a, b) + } + #[instrument(level = "trace", skip(self, param_env), ret)] pub(super) fn eq>( &mut self, @@ -1092,7 +1096,7 @@ where &self, goal_trait_ref: ty::TraitRef, trait_assoc_def_id: I::DefId, - impl_def_id: I::DefId, + impl_def_id: I::ImplId, ) -> Result, I::ErrorGuaranteed> { self.delegate.fetch_eligible_assoc_item(goal_trait_ref, trait_assoc_def_id, impl_def_id) } diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index 85f9d852d959..db3460c4ff67 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -119,11 +119,15 @@ where #[instrument(level = "trace", skip(self))] fn compute_subtype_goal(&mut self, goal: Goal>) -> QueryResult { - if goal.predicate.a.is_ty_var() && goal.predicate.b.is_ty_var() { - self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) - } else { - self.sub(goal.param_env, goal.predicate.a, goal.predicate.b)?; - self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + match (goal.predicate.a.kind(), goal.predicate.b.kind()) { + (ty::Infer(ty::TyVar(a_vid)), ty::Infer(ty::TyVar(b_vid))) => { + self.sub_unify_ty_vids_raw(a_vid, b_vid); + self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) + } + _ => { + self.sub(goal.param_env, goal.predicate.a, goal.predicate.b)?; + self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + } } } @@ -414,6 +418,11 @@ pub struct GoalEvaluation { pub has_changed: HasChanged, /// If the [`Certainty`] was `Maybe`, then keep track of whether the goal has changed /// before rerunning it. + /// + /// We knowingly ignore the `sub_root` of our inference variables here. This means we + /// may not reevaluate a goal even though a change to the `sub_root` could cause a goal + /// to make progress. Tracking them adds additional complexity for an incredibly minor + /// type inference improvement. We could look into properly handling this in the future. pub stalled_on: Option>, } diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index cfdf2007391a..6e6be829f521 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -5,7 +5,7 @@ mod opaque_types; use rustc_type_ir::fast_reject::DeepRejectCtxt; use rustc_type_ir::inherent::*; -use rustc_type_ir::lang_items::{SolverLangItem, SolverTraitLangItem}; +use rustc_type_ir::lang_items::{SolverAdtLangItem, SolverLangItem, SolverTraitLangItem}; use rustc_type_ir::solve::SizedTraitKind; use rustc_type_ir::{self as ty, Interner, NormalizesTo, PredicateKind, Upcast as _}; use tracing::instrument; @@ -193,7 +193,7 @@ where fn consider_impl_candidate( ecx: &mut EvalCtxt<'_, D>, goal: Goal>, - impl_def_id: I::DefId, + impl_def_id: I::ImplId, ) -> Result, NoSolution> { let cx = ecx.cx(); @@ -217,13 +217,13 @@ where }; ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| { - let impl_args = ecx.fresh_args_for_item(impl_def_id); + let impl_args = ecx.fresh_args_for_item(impl_def_id.into()); let impl_trait_ref = impl_trait_ref.instantiate(cx, impl_args); ecx.eq(goal.param_env, goal_trait_ref, impl_trait_ref)?; let where_clause_bounds = cx - .predicates_of(impl_def_id) + .predicates_of(impl_def_id.into()) .iter_instantiated(cx, impl_args) .map(|pred| goal.with(cx, pred)); ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds); @@ -824,10 +824,10 @@ where // coroutine yield ty `Poll>`. let wrapped_expected_ty = Ty::new_adt( cx, - cx.adt_def(cx.require_lang_item(SolverLangItem::Poll)), + cx.adt_def(cx.require_adt_lang_item(SolverAdtLangItem::Poll)), cx.mk_args(&[Ty::new_adt( cx, - cx.adt_def(cx.require_lang_item(SolverLangItem::Option)), + cx.adt_def(cx.require_adt_lang_item(SolverAdtLangItem::Option)), cx.mk_args(&[expected_ty.into()]), ) .into()]), @@ -979,7 +979,7 @@ where fn translate_args( &mut self, goal: Goal>, - impl_def_id: I::DefId, + impl_def_id: I::ImplId, impl_args: I::GenericArgs, impl_trait_ref: rustc_type_ir::TraitRef, target_container_def_id: I::DefId, @@ -988,14 +988,15 @@ where Ok(if target_container_def_id == impl_trait_ref.def_id.into() { // Default value from the trait definition. No need to rebase. goal.predicate.alias.args - } else if target_container_def_id == impl_def_id { + } else if target_container_def_id == impl_def_id.into() { // Same impl, no need to fully translate, just a rebase from // the trait is sufficient. goal.predicate.alias.args.rebase_onto(cx, impl_trait_ref.def_id.into(), impl_args) } else { let target_args = self.fresh_args_for_item(target_container_def_id); - let target_trait_ref = - cx.impl_trait_ref(target_container_def_id).instantiate(cx, target_args); + let target_trait_ref = cx + .impl_trait_ref(target_container_def_id.try_into().unwrap()) + .instantiate(cx, target_args); // Relate source impl to target impl by equating trait refs. self.eq(goal.param_env, impl_trait_ref, target_trait_ref)?; // Also add predicates since they may be needed to constrain the 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 cdcfebf29090..3e720a47f32e 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -54,7 +54,7 @@ where fn consider_impl_candidate( ecx: &mut EvalCtxt<'_, D>, goal: Goal>, - impl_def_id: I::DefId, + impl_def_id: I::ImplId, ) -> Result, NoSolution> { let cx = ecx.cx(); @@ -91,13 +91,13 @@ where }; ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| { - let impl_args = ecx.fresh_args_for_item(impl_def_id); + let impl_args = ecx.fresh_args_for_item(impl_def_id.into()); ecx.record_impl_args(impl_args); let impl_trait_ref = impl_trait_ref.instantiate(cx, impl_args); ecx.eq(goal.param_env, goal.predicate.trait_ref, impl_trait_ref)?; let where_clause_bounds = cx - .predicates_of(impl_def_id) + .predicates_of(impl_def_id.into()) .iter_instantiated(cx, impl_args) .map(|pred| goal.with(cx, pred)); ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds); diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 77dd313d9b8e..72cd75f6d894 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -479,9 +479,6 @@ parse_invalid_identifier_with_leading_number = identifiers cannot start with a n parse_invalid_literal_suffix_on_tuple_index = suffixes on a tuple index are invalid .label = invalid suffix `{$suffix}` - .tuple_exception_line_1 = `{$suffix}` is *temporarily* accepted on tuple index fields as it was incorrectly accepted on stable for a few releases - .tuple_exception_line_2 = on proc macros, you'll want to use `syn::Index::from` or `proc_macro::Literal::*_unsuffixed` for code that will desugar to tuple field access - .tuple_exception_line_3 = see issue #60210 for more information parse_invalid_logical_operator = `{$incorrect}` is not a logical operator .note = unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 797d4830c2ff..00ca5acd84d5 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1017,10 +1017,6 @@ pub(crate) struct InvalidLiteralSuffixOnTupleIndex { #[label] pub span: Span, pub suffix: Symbol, - #[help(parse_tuple_exception_line_1)] - #[help(parse_tuple_exception_line_2)] - #[help(parse_tuple_exception_line_3)] - pub exception: bool, } #[derive(Diagnostic)] diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index f5f081efc495..51019db7c00e 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -45,7 +45,7 @@ pub(crate) struct UnmatchedDelim { } /// Which tokens should be stripped before lexing the tokens. -pub(crate) enum StripTokens { +pub enum StripTokens { /// Strip both shebang and frontmatter. ShebangAndFrontmatter, /// Strip the shebang but not frontmatter. diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index d8792d7af4c3..88b67d792deb 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -54,29 +54,18 @@ pub fn unwrap_or_emit_fatal(expr: Result>>) -> T { } } -/// Creates a new parser from a source string. On failure, the errors must be consumed via -/// `unwrap_or_emit_fatal`, `emit`, `cancel`, etc., otherwise a panic will occur when they are -/// dropped. +/// Creates a new parser from a source string. +/// +/// On failure, the errors must be consumed via `unwrap_or_emit_fatal`, `emit`, `cancel`, +/// etc., otherwise a panic will occur when they are dropped. pub fn new_parser_from_source_str( psess: &ParseSess, name: FileName, source: String, + strip_tokens: StripTokens, ) -> Result, Vec>> { let source_file = psess.source_map().new_source_file(name, source); - new_parser_from_source_file(psess, source_file, StripTokens::ShebangAndFrontmatter) -} - -/// Creates a new parser from a simple (no shebang, no frontmatter) source string. -/// -/// On failure, the errors must be consumed via `unwrap_or_emit_fatal`, `emit`, `cancel`, -/// etc., otherwise a panic will occur when they are dropped. -pub fn new_parser_from_simple_source_str( - psess: &ParseSess, - name: FileName, - source: String, -) -> Result, Vec>> { - let source_file = psess.source_map().new_source_file(name, source); - new_parser_from_source_file(psess, source_file, StripTokens::Nothing) + new_parser_from_source_file(psess, source_file, strip_tokens) } /// Creates a new parser from a filename. On failure, the errors must be consumed via @@ -87,6 +76,7 @@ pub fn new_parser_from_simple_source_str( pub fn new_parser_from_file<'a>( psess: &'a ParseSess, path: &Path, + strip_tokens: StripTokens, sp: Option, ) -> Result, Vec>> { let sm = psess.source_map(); @@ -110,7 +100,7 @@ pub fn new_parser_from_file<'a>( } err.emit(); }); - new_parser_from_source_file(psess, source_file, StripTokens::ShebangAndFrontmatter) + new_parser_from_source_file(psess, source_file, strip_tokens) } pub fn utf8_error( @@ -172,6 +162,9 @@ fn new_parser_from_source_file( Ok(parser) } +/// Given a source string, produces a sequence of token trees. +/// +/// NOTE: This only strips shebangs, not frontmatter! pub fn source_str_to_stream( psess: &ParseSess, name: FileName, @@ -179,13 +172,16 @@ pub fn source_str_to_stream( override_span: Option, ) -> Result>> { let source_file = psess.source_map().new_source_file(name, source); - // used mainly for `proc_macro` and the likes, not for our parsing purposes, so don't parse - // frontmatters as frontmatters, but for compatibility reason still strip the shebang + // FIXME(frontmatter): Consider stripping frontmatter in a future edition. We can't strip them + // in the current edition since that would be breaking. + // See also . + // Alternatively, stop stripping shebangs here, too, if T-lang and crater approve. source_file_to_stream(psess, source_file, override_span, StripTokens::Shebang) } -/// Given a source file, produces a sequence of token trees. Returns any buffered errors from -/// parsing the token stream. +/// Given a source file, produces a sequence of token trees. +/// +/// Returns any buffered errors from parsing the token stream. fn source_file_to_stream<'psess>( psess: &'psess ParseSess, source_file: Arc, diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 4c02547357ef..81a5d48d94e8 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1163,7 +1163,10 @@ impl<'a> Parser<'a> { suffix, }) => { if let Some(suffix) = suffix { - self.expect_no_tuple_index_suffix(current.span, suffix); + self.dcx().emit_err(errors::InvalidLiteralSuffixOnTupleIndex { + span: current.span, + suffix, + }); } match self.break_up_float(symbol, current.span) { // 1e2 @@ -1239,7 +1242,8 @@ impl<'a> Parser<'a> { suffix: Option, ) -> Box { if let Some(suffix) = suffix { - self.expect_no_tuple_index_suffix(ident_span, suffix); + self.dcx() + .emit_err(errors::InvalidLiteralSuffixOnTupleIndex { span: ident_span, suffix }); } self.mk_expr(lo.to(ident_span), ExprKind::Field(base, Ident::new(field, ident_span))) } @@ -2225,24 +2229,6 @@ impl<'a> Parser<'a> { }) } - pub(super) fn expect_no_tuple_index_suffix(&self, span: Span, suffix: Symbol) { - if [sym::i32, sym::u32, sym::isize, sym::usize].contains(&suffix) { - // #59553: warn instead of reject out of hand to allow the fix to percolate - // through the ecosystem when people fix their macros - self.dcx().emit_warn(errors::InvalidLiteralSuffixOnTupleIndex { - span, - suffix, - exception: true, - }); - } else { - self.dcx().emit_err(errors::InvalidLiteralSuffixOnTupleIndex { - span, - suffix, - exception: false, - }); - } - } - /// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`). /// Keep this in sync with `Token::can_begin_literal_maybe_minus`. pub fn parse_literal_maybe_minus(&mut self) -> PResult<'a, Box> { diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 3bbca622975c..ed4069dae933 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1335,7 +1335,10 @@ impl<'a> Parser<'a> { if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) = self.token.kind { if let Some(suffix) = suffix { - self.expect_no_tuple_index_suffix(self.token.span, suffix); + self.dcx().emit_err(errors::InvalidLiteralSuffixOnTupleIndex { + span: self.token.span, + suffix, + }); } self.bump(); Ok(Ident::new(symbol, self.prev_token.span)) diff --git a/compiler/rustc_parse/src/parser/tests.rs b/compiler/rustc_parse/src/parser/tests.rs index a6e7266e71b4..e645fb47b9ec 100644 --- a/compiler/rustc_parse/src/parser/tests.rs +++ b/compiler/rustc_parse/src/parser/tests.rs @@ -22,6 +22,7 @@ use rustc_span::{ }; use termcolor::WriteColor; +use crate::lexer::StripTokens; use crate::parser::{ForceCollect, Parser}; use crate::{new_parser_from_source_str, source_str_to_stream, unwrap_or_emit_fatal}; @@ -35,6 +36,7 @@ fn string_to_parser(psess: &ParseSess, source_str: String) -> Parser<'_> { psess, PathBuf::from("bogofile").into(), source_str, + StripTokens::Nothing, )) } @@ -2240,7 +2242,7 @@ fn parse_item_from_source_str( source: String, psess: &ParseSess, ) -> PResult<'_, Option>> { - unwrap_or_emit_fatal(new_parser_from_source_str(psess, name, source)) + unwrap_or_emit_fatal(new_parser_from_source_str(psess, name, source, StripTokens::Nothing)) .parse_item(ForceCollect::No) } @@ -2520,7 +2522,8 @@ fn ttdelim_span() { source: String, psess: &ParseSess, ) -> PResult<'_, Box> { - unwrap_or_emit_fatal(new_parser_from_source_str(psess, name, source)).parse_expr() + unwrap_or_emit_fatal(new_parser_from_source_str(psess, name, source, StripTokens::Nothing)) + .parse_expr() } create_default_session_globals_then(|| { diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index afd08319738d..ab7885905a6e 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -501,6 +501,10 @@ passes_repr_align_should_be_align = `#[repr(align(...))]` is not supported on {$item} .help = use `#[rustc_align(...)]` instead +passes_repr_align_should_be_align_static = + `#[repr(align(...))]` is not supported on {$item} + .help = use `#[rustc_align_static(...)]` instead + passes_repr_conflicting = conflicting representation hints diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 2cd4830b5d93..38a6b4b16c93 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -270,6 +270,10 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::Linkage(..) | AttributeKind::MustUse { .. } | AttributeKind::CrateName { .. } + | AttributeKind::RecursionLimit { .. } + | AttributeKind::MoveSizeLimit { .. } + | AttributeKind::TypeLengthLimit { .. } + | AttributeKind::PatternComplexityLimit { .. } ) => { /* do nothing */ } Attribute::Unparsed(attr_item) => { style = Some(attr_item.style); @@ -1602,12 +1606,18 @@ impl<'tcx> CheckAttrVisitor<'tcx> { ReprAttr::ReprAlign(align) => { match target { Target::Struct | Target::Union | Target::Enum => {} - Target::Fn | Target::Method(_) => { + Target::Fn | Target::Method(_) if self.tcx.features().fn_align() => { self.dcx().emit_err(errors::ReprAlignShouldBeAlign { span: *repr_span, item: target.plural_name(), }); } + Target::Static if self.tcx.features().static_align() => { + self.dcx().emit_err(errors::ReprAlignShouldBeAlignStatic { + span: *repr_span, + item: target.plural_name(), + }); + } _ => { self.dcx().emit_err(errors::AttrApplication::StructEnumUnion { hint_span: *repr_span, diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 23dcabef1a17..2da4b6f52cf2 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1609,6 +1609,15 @@ pub(crate) struct ReprAlignShouldBeAlign { pub item: &'static str, } +#[derive(Diagnostic)] +#[diag(passes_repr_align_should_be_align_static)] +pub(crate) struct ReprAlignShouldBeAlignStatic { + #[primary_span] + #[help] + pub span: Span, + pub item: &'static str, +} + #[derive(Diagnostic)] #[diag(passes_custom_mir_phase_requires_dialect)] pub(crate) struct CustomMirPhaseRequiresDialect { diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml index e5cceacf15da..257785b10c8b 100644 --- a/compiler/rustc_query_impl/Cargo.toml +++ b/compiler/rustc_query_impl/Cargo.toml @@ -13,7 +13,6 @@ rustc_index = { path = "../rustc_index" } rustc_middle = { path = "../rustc_middle" } rustc_query_system = { path = "../rustc_query_system" } rustc_serialize = { path = "../rustc_serialize" } -rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 55549cba737e..4e601a6c5944 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -9,6 +9,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{DynSend, DynSync}; use rustc_data_structures::unord::UnordMap; use rustc_hashes::Hash64; +use rustc_hir::limit::Limit; use rustc_index::Idx; use rustc_middle::bug; use rustc_middle::dep_graph::{ @@ -31,7 +32,6 @@ use rustc_query_system::query::{ }; use rustc_query_system::{QueryOverflow, QueryOverflowNote}; use rustc_serialize::{Decodable, Encodable}; -use rustc_session::Limit; use rustc_span::def_id::LOCAL_CRATE; use crate::QueryConfigRestored; diff --git a/compiler/rustc_query_system/src/error.rs b/compiler/rustc_query_system/src/error.rs index 5108ecaeea3a..2778b24e7741 100644 --- a/compiler/rustc_query_system/src/error.rs +++ b/compiler/rustc_query_system/src/error.rs @@ -1,6 +1,6 @@ use rustc_errors::codes::*; +use rustc_hir::limit::Limit; use rustc_macros::{Diagnostic, Subdiagnostic}; -use rustc_session::Limit; use rustc_span::{Span, Symbol}; #[derive(Subdiagnostic)] diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 96767d054398..3525c7c1d1a9 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1,10 +1,9 @@ use std::any::Any; -use std::ops::{Div, Mul}; use std::path::{Path, PathBuf}; use std::str::FromStr; use std::sync::Arc; use std::sync::atomic::AtomicBool; -use std::{env, fmt, io}; +use std::{env, io}; use rand::{RngCore, rng}; use rustc_ast::NodeId; @@ -25,6 +24,7 @@ use rustc_errors::{ Diag, DiagCtxt, DiagCtxtHandle, DiagMessage, Diagnostic, ErrorGuaranteed, FatalAbort, LintEmitter, TerminalUrl, fallback_fluent_bundle, }; +use rustc_hir::limit::Limit; use rustc_macros::HashStable_Generic; pub use rustc_span::def_id::StableCrateId; use rustc_span::edition::Edition; @@ -62,64 +62,6 @@ pub enum CtfeBacktrace { Immediate, } -/// New-type wrapper around `usize` for representing limits. Ensures that comparisons against -/// limits are consistent throughout the compiler. -#[derive(Clone, Copy, Debug, HashStable_Generic)] -pub struct Limit(pub usize); - -impl Limit { - /// Create a new limit from a `usize`. - pub fn new(value: usize) -> Self { - Limit(value) - } - - /// Create a new unlimited limit. - pub fn unlimited() -> Self { - Limit(usize::MAX) - } - - /// Check that `value` is within the limit. Ensures that the same comparisons are used - /// throughout the compiler, as mismatches can cause ICEs, see #72540. - #[inline] - pub fn value_within_limit(&self, value: usize) -> bool { - value <= self.0 - } -} - -impl From for Limit { - fn from(value: usize) -> Self { - Self::new(value) - } -} - -impl fmt::Display for Limit { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.0.fmt(f) - } -} - -impl Div for Limit { - type Output = Limit; - - fn div(self, rhs: usize) -> Self::Output { - Limit::new(self.0 / rhs) - } -} - -impl Mul for Limit { - type Output = Limit; - - fn mul(self, rhs: usize) -> Self::Output { - Limit::new(self.0 * rhs) - } -} - -impl rustc_errors::IntoDiagArg for Limit { - fn into_diag_arg(self, _: &mut Option) -> rustc_errors::DiagArgValue { - self.to_string().into_diag_arg(&mut None) - } -} - #[derive(Clone, Copy, Debug, HashStable_Generic)] pub struct Limits { /// The maximum recursion limit for potentially infinitely recursive diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index e5108d8b7e92..aedeb0e14ed2 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -21,18 +21,17 @@ mod tests; // The proc macro code for this is in `compiler/rustc_macros/src/symbols.rs`. symbols! { - // This list includes things that are definitely keywords (e.g. `if`), - // a few things that are definitely not keywords (e.g. the empty symbol, - // `{{root}}`) and things where there is disagreement between people and/or - // documents (such as the Rust Reference) about whether it is a keyword - // (e.g. `_`). + // This list includes things that are definitely keywords (e.g. `if`), a + // few things that are definitely not keywords (e.g. `{{root}}`) and things + // where there is disagreement between people and/or documents (such as the + // Rust Reference) about whether it is a keyword (e.g. `_`). // // If you modify this list, adjust any relevant `Symbol::{is,can_be}_*` // predicates and `used_keywords`. Also consider adding new keywords to the // `ui/parser/raw/raw-idents.rs` test. Keywords { - // Special reserved identifiers used internally for elided lifetimes, - // unnamed method parameters, crate root module, error recovery etc. + // Special reserved identifiers used internally for unnamed method + // parameters, crate root module, etc. // Matching predicates: `is_special`/`is_reserved` // // tidy-alphabetical-start @@ -326,6 +325,7 @@ symbols! { RangeSub, RangeTo, RangeToInclusive, + RangeToInclusiveCopy, Rc, RcWeak, Ready, @@ -1280,6 +1280,7 @@ symbols! { lang, lang_items, large_assignments, + last, lateout, lazy_normalization_consts, lazy_type_alias, @@ -1846,6 +1847,7 @@ symbols! { rustc_abi, // FIXME(#82232, #143834): temporary name to mitigate `#[align]` nameres ambiguity rustc_align, + rustc_align_static, rustc_allocator, rustc_allocator_zeroed, rustc_allocator_zeroed_variant, @@ -2097,6 +2099,7 @@ symbols! { staged_api, start, state, + static_align, static_in_const, static_nobundle, static_recursion, diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index 4d9741f1d11c..95a7ec61868d 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -54,7 +54,7 @@ pub(super) fn mangle<'tcx>( // Erase regions because they may not be deterministic when hashed // and should not matter anyhow. - let instance_ty = tcx.erase_regions(instance_ty); + let instance_ty = tcx.erase_and_anonymize_regions(instance_ty); let hash = get_symbol_hash(tcx, instance, instance_ty, instantiating_crate); @@ -422,7 +422,10 @@ impl<'tcx> Printer<'tcx> for LegacySymbolMangler<'tcx> { || &args[..generics.count()] == self .tcx - .erase_regions(ty::GenericArgs::identity_for_item(self.tcx, impl_def_id)) + .erase_and_anonymize_regions(ty::GenericArgs::identity_for_item( + self.tcx, + impl_def_id, + )) .as_slice() { ( diff --git a/compiler/rustc_symbol_mangling/src/test.rs b/compiler/rustc_symbol_mangling/src/test.rs index 0c6d1495e39c..50935e7caf33 100644 --- a/compiler/rustc_symbol_mangling/src/test.rs +++ b/compiler/rustc_symbol_mangling/src/test.rs @@ -58,7 +58,7 @@ impl SymbolNamesTest<'_> { let def_id = def_id.to_def_id(); let instance = Instance::new_raw( def_id, - tcx.erase_regions(GenericArgs::identity_for_item(tcx, def_id)), + tcx.erase_and_anonymize_regions(GenericArgs::identity_for_item(tcx, def_id)), ); let mangled = tcx.symbol_name(instance); tcx.dcx().emit_err(TestOutput { diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 0655c2d5e814..1605b4958ba3 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -329,7 +329,10 @@ impl<'tcx> Printer<'tcx> for V0SymbolMangler<'tcx> { || &args[..generics.count()] == self .tcx - .erase_regions(ty::GenericArgs::identity_for_item(self.tcx, impl_def_id)) + .erase_and_anonymize_regions(ty::GenericArgs::identity_for_item( + self.tcx, + impl_def_id, + )) .as_slice() { ( @@ -339,7 +342,7 @@ impl<'tcx> Printer<'tcx> for V0SymbolMangler<'tcx> { ) } else { assert!( - !args.has_non_region_param(), + !args.has_non_region_param() && !args.has_free_regions(), "should not be mangling partially substituted \ polymorphic instance: {impl_def_id:?} {args:?}" ); 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 812e20e43382..d71110521ffa 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -91,7 +91,6 @@ mod suggest; pub mod need_type_info; pub mod nice_region_error; pub mod region; -pub mod sub_relations; /// Makes a valid string literal from a string by escaping special characters (" and \), /// unless they are already escaped. @@ -1617,8 +1616,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { && let Some((e, f)) = values.ty() && let TypeError::ArgumentSorts(..) | TypeError::Sorts(_) = terr { - let e = self.tcx.erase_regions(e); - let f = self.tcx.erase_regions(f); + let e = self.tcx.erase_and_anonymize_regions(e); + let f = self.tcx.erase_and_anonymize_regions(f); let mut expected = with_forced_trimmed_paths!(e.sort_string(self.tcx)); let mut found = with_forced_trimmed_paths!(f.sort_string(self.tcx)); if let ObligationCauseCode::Pattern { span, .. } = cause.code() diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs index ec2287ed5161..edab530590b2 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs @@ -894,7 +894,8 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { use ty::{Infer, TyVar}; match (inner_ty.kind(), target_ty.kind()) { (&Infer(TyVar(a_vid)), &Infer(TyVar(b_vid))) => { - self.tecx.sub_relations.borrow_mut().unified(self.tecx, a_vid, b_vid) + self.tecx.sub_unification_table_root_var(a_vid) + == self.tecx.sub_unification_table_root_var(b_vid) } _ => false, } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs index 40285e5d0e96..e042ce84955e 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs @@ -629,7 +629,11 @@ impl Trait for X { let tcx = self.tcx; // Don't suggest constraining a projection to something containing itself - if self.tcx.erase_regions(values.found).contains(self.tcx.erase_regions(values.expected)) { + if self + .tcx + .erase_and_anonymize_regions(values.found) + .contains(self.tcx.erase_and_anonymize_regions(values.expected)) + { return; } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/sub_relations.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/sub_relations.rs deleted file mode 100644 index ef26a8ff7b86..000000000000 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/sub_relations.rs +++ /dev/null @@ -1,81 +0,0 @@ -use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::undo_log::NoUndo; -use rustc_data_structures::unify as ut; -use rustc_middle::ty; - -use crate::infer::InferCtxt; - -#[derive(Debug, Copy, Clone, PartialEq)] -struct SubId(u32); -impl ut::UnifyKey for SubId { - type Value = (); - #[inline] - fn index(&self) -> u32 { - self.0 - } - #[inline] - fn from_index(i: u32) -> SubId { - SubId(i) - } - fn tag() -> &'static str { - "SubId" - } -} - -/// When reporting ambiguity errors, we sometimes want to -/// treat all inference vars which are subtypes of each -/// others as if they are equal. For this case we compute -/// the transitive closure of our subtype obligations here. -/// -/// E.g. when encountering ambiguity errors, we want to suggest -/// specifying some method argument or to add a type annotation -/// to a local variable. Because subtyping cannot change the -/// shape of a type, it's fine if the cause of the ambiguity error -/// is only related to the suggested variable via subtyping. -/// -/// Even for something like `let x = returns_arg(); x.method();` the -/// type of `x` is only a supertype of the argument of `returns_arg`. We -/// still want to suggest specifying the type of the argument. -#[derive(Default)] -pub struct SubRelations { - map: FxHashMap, - table: ut::UnificationTableStorage, -} - -impl SubRelations { - fn get_id<'tcx>(&mut self, infcx: &InferCtxt<'tcx>, vid: ty::TyVid) -> SubId { - let root_vid = infcx.root_var(vid); - *self.map.entry(root_vid).or_insert_with(|| self.table.with_log(&mut NoUndo).new_key(())) - } - - pub fn add_constraints<'tcx>( - &mut self, - infcx: &InferCtxt<'tcx>, - obls: impl IntoIterator>, - ) { - for p in obls { - let (a, b) = match p.kind().skip_binder() { - ty::PredicateKind::Subtype(ty::SubtypePredicate { a_is_expected: _, a, b }) => { - (a, b) - } - ty::PredicateKind::Coerce(ty::CoercePredicate { a, b }) => (a, b), - _ => continue, - }; - - match (a.kind(), b.kind()) { - (&ty::Infer(ty::TyVar(a_vid)), &ty::Infer(ty::TyVar(b_vid))) => { - let a = self.get_id(infcx, a_vid); - let b = self.get_id(infcx, b_vid); - self.table.with_log(&mut NoUndo).unify_var_var(a, b).unwrap(); - } - _ => continue, - } - } - } - - pub fn unified<'tcx>(&mut self, infcx: &InferCtxt<'tcx>, a: ty::TyVid, b: ty::TyVid) -> bool { - let a = self.get_id(infcx, a); - let b = self.get_id(infcx, b); - self.table.with_log(&mut NoUndo).unioned(a, b) - } -} diff --git a/compiler/rustc_trait_selection/src/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/mod.rs index 82695688ae89..cce20b05c79a 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/mod.rs @@ -7,8 +7,6 @@ use rustc_macros::extension; use rustc_middle::bug; use rustc_middle::ty::{self, Ty}; -use crate::error_reporting::infer::sub_relations; - pub mod infer; pub mod traits; @@ -21,7 +19,6 @@ pub mod traits; /// methods which should not be used during the happy path. pub struct TypeErrCtxt<'a, 'tcx> { pub infcx: &'a InferCtxt<'tcx>, - pub sub_relations: std::cell::RefCell, pub typeck_results: Option>>, pub fallback_has_occurred: bool, @@ -38,7 +35,6 @@ impl<'tcx> InferCtxt<'tcx> { fn err_ctxt(&self) -> TypeErrCtxt<'_, 'tcx> { TypeErrCtxt { infcx: self, - sub_relations: Default::default(), typeck_results: None, fallback_has_occurred: false, normalize_fn_sig: Box::new(|fn_sig| fn_sig), diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index bc984f30472d..c82043f02223 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -75,7 +75,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { { if let Some(cause) = self .tcx - .diagnostic_hir_wf_check((tcx.erase_regions(obligation.predicate), *wf_loc)) + .diagnostic_hir_wf_check((tcx.erase_and_anonymize_regions(obligation.predicate), *wf_loc)) { obligation.cause = cause.clone(); span = obligation.cause.span; @@ -2612,8 +2612,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } // Erase regions because layout code doesn't particularly care about regions. - let trait_pred = - self.tcx.erase_regions(self.tcx.instantiate_bound_regions_with_erased(trait_pred)); + let trait_pred = self.tcx.erase_and_anonymize_regions( + self.tcx.instantiate_bound_regions_with_erased(trait_pred), + ); let src_and_dst = rustc_transmute::Types { dst: trait_pred.trait_ref.args.type_at(0), diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs index c8500b2d9d4a..f794ff632c59 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs @@ -139,10 +139,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { &self, mut errors: Vec>, ) -> ErrorGuaranteed { - self.sub_relations - .borrow_mut() - .add_constraints(self, errors.iter().map(|e| e.obligation.predicate)); - #[derive(Debug)] struct ErrorDescriptor<'tcx> { goal: Goal<'tcx, ty::Predicate<'tcx>>, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs index 4f1f5c330e5f..a0876d8fe759 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs @@ -3,10 +3,10 @@ use std::fmt; use rustc_errors::{Diag, E0275, EmissionGuarantee, ErrorGuaranteed, struct_span_code_err}; use rustc_hir::def::Namespace; use rustc_hir::def_id::LOCAL_CRATE; +use rustc_hir::limit::Limit; use rustc_infer::traits::{Obligation, PredicateObligation}; use rustc_middle::ty::print::{FmtPrinter, Print}; use rustc_middle::ty::{self, TyCtxt, Upcast}; -use rustc_session::Limit; use rustc_span::Span; use tracing::debug; @@ -67,7 +67,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // We don't need to save the type to a file, we will be talking about this type already // in a separate note when we explain the obligation, so it will be available that way. let mut p: FmtPrinter<'_, '_> = - FmtPrinter::new_with_limit(tcx, Namespace::TypeNS, rustc_session::Limit(6)); + FmtPrinter::new_with_limit(tcx, Namespace::TypeNS, Limit(6)); value.print(&mut p).unwrap(); p.into_buffer() } else { diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index f6dbbeb51cab..cb84d583e6e9 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -2442,7 +2442,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // Look for a type inside the coroutine interior that matches the target type to get // a span. - let target_ty_erased = self.tcx.erase_regions(target_ty); + let target_ty_erased = self.tcx.erase_and_anonymize_regions(target_ty); let ty_matches = |ty| -> bool { // Careful: the regions for types that appear in the // coroutine interior are not generally known, so we @@ -2454,10 +2454,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // interior generally contain "bound regions" to // represent regions that are part of the suspended // coroutine frame. Bound regions are preserved by - // `erase_regions` and so we must also call + // `erase_and_anonymize_regions` and so we must also call // `instantiate_bound_regions_with_erased`. let ty_erased = self.tcx.instantiate_bound_regions_with_erased(ty); - let ty_erased = self.tcx.erase_regions(ty_erased); + let ty_erased = self.tcx.erase_and_anonymize_regions(ty_erased); let eq = ty_erased == target_ty_erased; debug!(?ty_erased, ?target_ty_erased, ?eq); eq diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index 7c6b7b14ecbe..4c50c44b8418 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -184,10 +184,9 @@ impl<'tcx> InferCtxtBuilder<'tcx> { R: Debug + TypeFoldable>, Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>, { - let (infcx, key, canonical_inference_vars) = - self.build_with_canonical(DUMMY_SP, canonical_key); + let (infcx, key, var_values) = self.build_with_canonical(DUMMY_SP, canonical_key); let ocx = ObligationCtxt::new(&infcx); let value = operation(&ocx, key)?; - ocx.make_canonicalized_query_response(canonical_inference_vars, value) + ocx.make_canonicalized_query_response(var_values, value) } } diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index e6a2761db5a9..b6bdf1067a35 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -126,13 +126,12 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< } ty::PredicateKind::Subtype(ty::SubtypePredicate { a, b, .. }) | ty::PredicateKind::Coerce(ty::CoercePredicate { a, b }) => { - if self.shallow_resolve(a).is_ty_var() && self.shallow_resolve(b).is_ty_var() { - // FIXME: We also need to register a subtype relation between these vars - // when those are added, and if they aren't in the same sub root then - // we should mark this goal as `has_changed`. - Some(Certainty::AMBIGUOUS) - } else { - None + match (self.shallow_resolve(a).kind(), self.shallow_resolve(b).kind()) { + (&ty::Infer(ty::TyVar(a_vid)), &ty::Infer(ty::TyVar(b_vid))) => { + self.sub_unify_ty_vids_raw(a_vid, b_vid); + Some(Certainty::AMBIGUOUS) + } + _ => None, } } ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, _)) => { @@ -238,13 +237,14 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< canonical.instantiate(self.tcx, &values) } - fn instantiate_canonical_var_with_infer( + fn instantiate_canonical_var( &self, kind: CanonicalVarKind<'tcx>, span: Span, + var_values: &[ty::GenericArg<'tcx>], universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex, ) -> ty::GenericArg<'tcx> { - self.0.instantiate_canonical_var(span, kind, universe_map) + self.0.instantiate_canonical_var(span, kind, var_values, universe_map) } fn add_item_bounds_for_hidden_type( @@ -300,7 +300,7 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< ) -> Result { // Erase regions because we compute layouts in `rustc_transmute`, // which will ICE for region vars. - let (dst, src) = self.tcx.erase_regions((dst, src)); + let (dst, src) = self.tcx.erase_and_anonymize_regions((dst, src)); let Some(assume) = rustc_transmute::Assume::from_const(self.tcx, assume) else { return Err(NoSolution); diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index 4b493c95d593..bcd11d6918d9 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -759,7 +759,7 @@ impl<'tcx> TypeVisitor> for IllegalSelfTypeVisitor<'tcx> { )), ) .map(|trait_ref| { - self.tcx.erase_regions( + self.tcx.erase_and_anonymize_regions( self.tcx.instantiate_bound_regions_with_erased(trait_ref), ) }) diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index a9fb16b8000a..6fefac436994 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -576,7 +576,7 @@ pub fn try_evaluate_const<'tcx>( let args = replace_param_and_infer_args_with_placeholder(tcx, uv.args); let typing_env = infcx - .typing_env(tcx.erase_regions(param_env)) + .typing_env(tcx.erase_and_anonymize_regions(param_env)) .with_post_analysis_normalized(tcx); (args, typing_env) } @@ -589,7 +589,7 @@ pub fn try_evaluate_const<'tcx>( } } else { let typing_env = infcx - .typing_env(tcx.erase_regions(param_env)) + .typing_env(tcx.erase_and_anonymize_regions(param_env)) .with_post_analysis_normalized(tcx); (uv.args, typing_env) } @@ -634,14 +634,14 @@ pub fn try_evaluate_const<'tcx>( } let typing_env = infcx - .typing_env(tcx.erase_regions(param_env)) + .typing_env(tcx.erase_and_anonymize_regions(param_env)) .with_post_analysis_normalized(tcx); (uv.args, typing_env) } }; let uv = ty::UnevaluatedConst::new(uv.def, args); - let erased_uv = tcx.erase_regions(uv); + let erased_uv = tcx.erase_and_anonymize_regions(uv); use rustc_middle::mir::interpret::ErrorHandled; // FIXME: `def_span` will point at the definition of this const; ideally, we'd point at diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs index de4045328997..945ca7c37758 100644 --- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs +++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs @@ -350,7 +350,9 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>( // Note that we don't care about whether the resume type has any drops since this is // redundant; there is no storage for the resume type, so if it is actually stored // in the interior, we'll already detect the need for a drop by checking the interior. - let typing_env = tcx.erase_regions(typing_env); + // + // FIXME(@lcnr): Why do we erase regions in the env here? Seems odd + let typing_env = tcx.erase_and_anonymize_regions(typing_env); let needs_drop = tcx.mir_coroutine_witnesses(def_id).is_some_and(|witness| { witness.field_tys.iter().any(|field| field.ty.needs_drop(tcx, typing_env)) }); diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs index 7dd3c59edd05..4b05e2cc3811 100644 --- a/compiler/rustc_traits/src/codegen.rs +++ b/compiler/rustc_traits/src/codegen.rs @@ -73,7 +73,7 @@ pub(crate) fn codegen_select_candidate<'tcx>( } let impl_source = infcx.resolve_vars_if_possible(impl_source); - let impl_source = tcx.erase_regions(impl_source); + let impl_source = tcx.erase_and_anonymize_regions(impl_source); if impl_source.has_non_region_infer() { // Unused generic types or consts on an impl get replaced with inference vars, // but never resolved, causing the return value of a query to contain inference diff --git a/compiler/rustc_traits/src/evaluate_obligation.rs b/compiler/rustc_traits/src/evaluate_obligation.rs index 819b8e3231ce..8f72bdf09726 100644 --- a/compiler/rustc_traits/src/evaluate_obligation.rs +++ b/compiler/rustc_traits/src/evaluate_obligation.rs @@ -19,7 +19,7 @@ fn evaluate_obligation<'tcx>( ) -> Result { assert!(!tcx.next_trait_solver_globally()); debug!("evaluate_obligation(canonical_goal={:#?})", canonical_goal); - let (ref infcx, goal, _canonical_inference_vars) = + let (ref infcx, goal, _var_values) = tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &canonical_goal); debug!("evaluate_obligation: goal={:#?}", goal); let ParamEnvAnd { param_env, value: predicate } = goal; diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs index c1b848a2e79d..c98b56abe9c1 100644 --- a/compiler/rustc_traits/src/normalize_erasing_regions.rs +++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs @@ -41,7 +41,7 @@ fn try_normalize_after_erasing_regions<'tcx, T: TypeFoldable> + Par // fresh `InferCtxt`. If this assert does trigger, it will give // us a test case. debug_assert_eq!(normalized_value, resolved_value); - let erased = infcx.tcx.erase_regions(resolved_value); + let erased = infcx.tcx.erase_and_anonymize_regions(resolved_value); debug_assert!(!erased.has_infer(), "{erased:?}"); Ok(erased) } diff --git a/compiler/rustc_transmute/src/layout/mod.rs b/compiler/rustc_transmute/src/layout/mod.rs index acbce258f39b..4e548ff8fe20 100644 --- a/compiler/rustc_transmute/src/layout/mod.rs +++ b/compiler/rustc_transmute/src/layout/mod.rs @@ -163,7 +163,7 @@ pub mod rustc { ty: Ty<'tcx>, ) -> Result, &'tcx LayoutError<'tcx>> { use rustc_middle::ty::layout::LayoutOf; - let ty = cx.tcx().erase_regions(ty); + let ty = cx.tcx().erase_and_anonymize_regions(ty); cx.layout_of(ty).map(|tl| tl.layout) } } diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs index 3f83b4d50aad..d7ea26a2ab1d 100644 --- a/compiler/rustc_transmute/src/layout/tree.rs +++ b/compiler/rustc_transmute/src/layout/tree.rs @@ -426,24 +426,23 @@ pub(crate) mod rustc { assert!(def.is_enum()); // Computes the layout of a variant. - let layout_of_variant = - |index, encoding: Option>| -> Result { - let variant_layout = ty_variant(cx, (ty, layout), index); - if variant_layout.is_uninhabited() { - return Ok(Self::uninhabited()); - } - let tag = cx.tcx().tag_for_variant( - cx.typing_env.as_query_input((cx.tcx().erase_regions(ty), index)), - ); - let variant_def = Def::Variant(def.variant(index)); - Self::from_variant( - variant_def, - tag.map(|tag| (tag, index, encoding.unwrap())), - (ty, variant_layout), - layout.size, - cx, - ) - }; + let layout_of_variant = |index, encoding: Option<_>| -> Result { + let variant_layout = ty_variant(cx, (ty, layout), index); + if variant_layout.is_uninhabited() { + return Ok(Self::uninhabited()); + } + let tag = cx.tcx().tag_for_variant( + cx.typing_env.as_query_input((cx.tcx().erase_and_anonymize_regions(ty), index)), + ); + let variant_def = Def::Variant(def.variant(index)); + Self::from_variant( + variant_def, + tag.map(|tag| (tag, index, encoding.unwrap())), + (ty, variant_layout), + layout.size, + cx, + ) + }; match layout.variants() { Variants::Empty => Ok(Self::uninhabited()), @@ -634,7 +633,7 @@ pub(crate) mod rustc { (ty, layout): (Ty<'tcx>, Layout<'tcx>), i: VariantIdx, ) -> Layout<'tcx> { - let ty = cx.tcx().erase_regions(ty); + let ty = cx.tcx().erase_and_anonymize_regions(ty); TyAndLayout { ty, layout }.for_variant(&cx, i).layout } } diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 5c3f7d491a57..e28ebaabc0a1 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -176,7 +176,7 @@ fn resolve_associated_item<'tcx>( args, leaf_def.defining_node, ); - let args = infcx.tcx.erase_regions(args); + let args = infcx.tcx.erase_and_anonymize_regions(args); // HACK: We may have overlapping `dyn Trait` built-in impls and // user-provided blanket impls. Detect that case here, and return @@ -222,7 +222,7 @@ fn resolve_associated_item<'tcx>( return Err(guar); } - let args = tcx.erase_regions(args); + let args = tcx.erase_and_anonymize_regions(args); // We check that the impl item is compatible with the trait item // because otherwise we may ICE in const eval due to type mismatches, @@ -279,7 +279,7 @@ fn resolve_associated_item<'tcx>( assert_eq!(name, sym::clone_from); // Use the default `fn clone_from` from `trait Clone`. - let args = tcx.erase_regions(rcvr_args); + let args = tcx.erase_and_anonymize_regions(rcvr_args); Some(ty::Instance::new_raw(trait_item_id, args)) } } else if tcx.is_lang_item(trait_ref.def_id, LangItem::FnPtrTrait) { @@ -380,7 +380,7 @@ fn resolve_associated_item<'tcx>( } else if tcx.is_lang_item(trait_ref.def_id, LangItem::TransmuteTrait) { let name = tcx.item_name(trait_item_id); assert_eq!(name, sym::transmute); - let args = tcx.erase_regions(rcvr_args); + let args = tcx.erase_and_anonymize_regions(rcvr_args); Some(ty::Instance::new_raw(trait_item_id, args)) } else { Instance::try_resolve_item_for_coroutine(tcx, trait_item_id, trait_id, rcvr_args) diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index 13d56889bd12..0ef435b1a0e2 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -2,11 +2,11 @@ use rustc_data_structures::fx::FxHashSet; use rustc_hir::def_id::DefId; +use rustc_hir::limit::Limit; use rustc_middle::bug; use rustc_middle::query::Providers; use rustc_middle::ty::util::{AlwaysRequiresDrop, needs_drop_components}; use rustc_middle::ty::{self, EarlyBinder, GenericArgsRef, Ty, TyCtxt}; -use rustc_session::Limit; use rustc_span::sym; use tracing::{debug, instrument}; diff --git a/compiler/rustc_type_ir/Cargo.toml b/compiler/rustc_type_ir/Cargo.toml index d55e9b3b1be8..6ccddb17ff22 100644 --- a/compiler/rustc_type_ir/Cargo.toml +++ b/compiler/rustc_type_ir/Cargo.toml @@ -5,6 +5,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start +arrayvec = { version = "0.7", default-features = false } bitflags = "2.4.1" derive-where = "1.2.7" ena = "0.14.3" diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs index de2a9186e7c9..ecf3ae4f8b2c 100644 --- a/compiler/rustc_type_ir/src/canonical.rs +++ b/compiler/rustc_type_ir/src/canonical.rs @@ -1,7 +1,7 @@ use std::fmt; -use std::hash::Hash; use std::ops::Index; +use arrayvec::ArrayVec; use derive_where::derive_where; #[cfg(feature = "nightly")] use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext}; @@ -91,8 +91,18 @@ impl fmt::Display for Canonical { derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext) )] pub enum CanonicalVarKind { - /// Some kind of type inference variable. - Ty(CanonicalTyVarKind), + /// General type variable `?T` that can be unified with arbitrary types. + /// + /// We also store the index of the first type variable which is sub-unified + /// with this one. If there is no inference variable related to this one, + /// its `sub_root` just points to itself. + Ty { ui: UniverseIndex, sub_root: ty::BoundVar }, + + /// Integral type variable `?I` (that can only be unified with integral types). + Int, + + /// Floating-point type variable `?F` (that can only be unified with float types). + Float, /// A "placeholder" that represents "any type". PlaceholderTy(I::PlaceholderTy), @@ -117,15 +127,13 @@ impl Eq for CanonicalVarKind {} impl CanonicalVarKind { pub fn universe(self) -> UniverseIndex { match self { - CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)) => ui, + CanonicalVarKind::Ty { ui, sub_root: _ } => ui, CanonicalVarKind::Region(ui) => ui, CanonicalVarKind::Const(ui) => ui, CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.universe(), CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.universe(), CanonicalVarKind::PlaceholderConst(placeholder) => placeholder.universe(), - CanonicalVarKind::Ty(CanonicalTyVarKind::Float | CanonicalTyVarKind::Int) => { - UniverseIndex::ROOT - } + CanonicalVarKind::Float | CanonicalVarKind::Int => UniverseIndex::ROOT, } } @@ -135,9 +143,7 @@ impl CanonicalVarKind { /// the updated universe is not the root. pub fn with_updated_universe(self, ui: UniverseIndex) -> CanonicalVarKind { match self { - CanonicalVarKind::Ty(CanonicalTyVarKind::General(_)) => { - CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)) - } + CanonicalVarKind::Ty { ui: _, sub_root } => CanonicalVarKind::Ty { ui, sub_root }, CanonicalVarKind::Region(_) => CanonicalVarKind::Region(ui), CanonicalVarKind::Const(_) => CanonicalVarKind::Const(ui), @@ -150,7 +156,7 @@ impl CanonicalVarKind { CanonicalVarKind::PlaceholderConst(placeholder) => { CanonicalVarKind::PlaceholderConst(placeholder.with_updated_universe(ui)) } - CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float) => { + CanonicalVarKind::Int | CanonicalVarKind::Float => { assert_eq!(ui, UniverseIndex::ROOT); self } @@ -159,19 +165,23 @@ impl CanonicalVarKind { pub fn is_existential(self) -> bool { match self { - CanonicalVarKind::Ty(_) => true, - CanonicalVarKind::PlaceholderTy(_) => false, - CanonicalVarKind::Region(_) => true, - CanonicalVarKind::PlaceholderRegion(..) => false, - CanonicalVarKind::Const(_) => true, - CanonicalVarKind::PlaceholderConst(_) => false, + CanonicalVarKind::Ty { .. } + | CanonicalVarKind::Int + | CanonicalVarKind::Float + | CanonicalVarKind::Region(_) + | CanonicalVarKind::Const(_) => true, + CanonicalVarKind::PlaceholderTy(_) + | CanonicalVarKind::PlaceholderRegion(..) + | CanonicalVarKind::PlaceholderConst(_) => false, } } pub fn is_region(self) -> bool { match self { CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => true, - CanonicalVarKind::Ty(_) + CanonicalVarKind::Ty { .. } + | CanonicalVarKind::Int + | CanonicalVarKind::Float | CanonicalVarKind::PlaceholderTy(_) | CanonicalVarKind::Const(_) | CanonicalVarKind::PlaceholderConst(_) => false, @@ -180,7 +190,11 @@ impl CanonicalVarKind { pub fn expect_placeholder_index(self) -> usize { match self { - CanonicalVarKind::Ty(_) | CanonicalVarKind::Region(_) | CanonicalVarKind::Const(_) => { + CanonicalVarKind::Ty { .. } + | CanonicalVarKind::Int + | CanonicalVarKind::Float + | CanonicalVarKind::Region(_) + | CanonicalVarKind::Const(_) => { panic!("expected placeholder: {self:?}") } @@ -191,27 +205,6 @@ impl CanonicalVarKind { } } -/// Rust actually has more than one category of type variables; -/// notably, the type variables we create for literals (e.g., 22 or -/// 22.) can only be instantiated with integral/float types (e.g., -/// usize or f32). In order to faithfully reproduce a type, we need to -/// know what set of types a given type variable can be unified with. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -#[cfg_attr( - feature = "nightly", - derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext) -)] -pub enum CanonicalTyVarKind { - /// General type variable `?T` that can be unified with arbitrary types. - General(UniverseIndex), - - /// Integral type variable `?I` (that can only be unified with integral types). - Int, - - /// Floating-point type variable `?F` (that can only be unified with float types). - Float, -} - /// A set of values corresponding to the canonical variables from some /// `Canonical`. You can give these values to /// `canonical_value.instantiate` to instantiate them into the canonical @@ -287,7 +280,10 @@ impl CanonicalVarValues { var_values: cx.mk_args_from_iter(infos.iter().enumerate().map( |(i, kind)| -> I::GenericArg { match kind { - CanonicalVarKind::Ty(_) | CanonicalVarKind::PlaceholderTy(_) => { + CanonicalVarKind::Ty { .. } + | CanonicalVarKind::Int + | CanonicalVarKind::Float + | CanonicalVarKind::PlaceholderTy(_) => { Ty::new_anon_bound(cx, ty::INNERMOST, ty::BoundVar::from_usize(i)) .into() } @@ -311,6 +307,37 @@ impl CanonicalVarValues { CanonicalVarValues { var_values: Default::default() } } + pub fn instantiate( + cx: I, + variables: I::CanonicalVarKinds, + mut f: impl FnMut(&[I::GenericArg], CanonicalVarKind) -> I::GenericArg, + ) -> CanonicalVarValues { + // Instantiating `CanonicalVarValues` is really hot, but limited to less than + // 4 most of the time. Avoid creating a `Vec` here. + if variables.len() <= 4 { + let mut var_values = ArrayVec::<_, 4>::new(); + for info in variables.iter() { + var_values.push(f(&var_values, info)); + } + CanonicalVarValues { var_values: cx.mk_args(&var_values) } + } else { + CanonicalVarValues::instantiate_cold(cx, variables, f) + } + } + + #[cold] + fn instantiate_cold( + cx: I, + variables: I::CanonicalVarKinds, + mut f: impl FnMut(&[I::GenericArg], CanonicalVarKind) -> I::GenericArg, + ) -> CanonicalVarValues { + let mut var_values = Vec::with_capacity(variables.len()); + for info in variables.iter() { + var_values.push(f(&var_values, info)); + } + CanonicalVarValues { var_values: cx.mk_args(&var_values) } + } + #[inline] pub fn len(&self) -> usize { self.var_values.len() diff --git a/compiler/rustc_type_ir/src/fast_reject.rs b/compiler/rustc_type_ir/src/fast_reject.rs index 5a05630e1bd1..ed6416a7f55f 100644 --- a/compiler/rustc_type_ir/src/fast_reject.rs +++ b/compiler/rustc_type_ir/src/fast_reject.rs @@ -122,7 +122,7 @@ pub fn simplify_type( ty::Int(int_type) => Some(SimplifiedType::Int(int_type)), ty::Uint(uint_type) => Some(SimplifiedType::Uint(uint_type)), ty::Float(float_type) => Some(SimplifiedType::Float(float_type)), - ty::Adt(def, _) => Some(SimplifiedType::Adt(def.def_id())), + ty::Adt(def, _) => Some(SimplifiedType::Adt(def.def_id().into())), ty::Str => Some(SimplifiedType::Str), ty::Array(..) => Some(SimplifiedType::Array), ty::Slice(..) => Some(SimplifiedType::Slice), @@ -135,11 +135,11 @@ pub fn simplify_type( _ => Some(SimplifiedType::MarkerTraitObject), }, ty::Ref(_, _, mutbl) => Some(SimplifiedType::Ref(mutbl)), - ty::FnDef(def_id, _) | ty::Closure(def_id, _) | ty::CoroutineClosure(def_id, _) => { - Some(SimplifiedType::Closure(def_id)) - } - ty::Coroutine(def_id, _) => Some(SimplifiedType::Coroutine(def_id)), - ty::CoroutineWitness(def_id, _) => Some(SimplifiedType::CoroutineWitness(def_id)), + ty::FnDef(def_id, _) => Some(SimplifiedType::Closure(def_id.into())), + ty::Closure(def_id, _) => Some(SimplifiedType::Closure(def_id.into())), + ty::CoroutineClosure(def_id, _) => Some(SimplifiedType::Closure(def_id.into())), + ty::Coroutine(def_id, _) => Some(SimplifiedType::Coroutine(def_id.into())), + ty::CoroutineWitness(def_id, _) => Some(SimplifiedType::CoroutineWitness(def_id.into())), ty::Never => Some(SimplifiedType::Never), ty::Tuple(tys) => Some(SimplifiedType::Tuple(tys.len())), ty::FnPtr(sig_tys, _hdr) => { @@ -161,7 +161,7 @@ pub fn simplify_type( } TreatParams::AsRigid | TreatParams::InstantiateWithInfer => None, }, - ty::Foreign(def_id) => Some(SimplifiedType::Foreign(def_id)), + ty::Foreign(def_id) => Some(SimplifiedType::Foreign(def_id.into())), ty::Error(_) => Some(SimplifiedType::Error), ty::Bound(..) | ty::Infer(_) => None, } diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index b4462294700a..56962b4597b8 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -158,6 +158,7 @@ pub trait InferCtxtLike: Sized { fn universe_of_ct(&self, ct: ty::ConstVid) -> Option; fn root_ty_var(&self, var: ty::TyVid) -> ty::TyVid; + fn sub_unification_table_root_var(&self, var: ty::TyVid) -> ty::TyVid; fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid; fn opportunistic_resolve_ty_var(&self, vid: ty::TyVid) -> ::Ty; @@ -197,6 +198,7 @@ pub trait InferCtxtLike: Sized { ) -> U; fn equate_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid); + fn sub_unify_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid); fn equate_int_vids_raw(&self, a: ty::IntVid, b: ty::IntVid); fn equate_float_vids_raw(&self, a: ty::FloatVid, b: ty::FloatVid); fn equate_const_vids_raw(&self, a: ty::ConstVid, b: ty::ConstVid); diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 64063b1a3650..ecfc05a6e20e 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -74,7 +74,7 @@ pub trait Ty>: fn new_adt(interner: I, adt_def: I::AdtDef, args: I::GenericArgs) -> Self; - fn new_foreign(interner: I, def_id: I::DefId) -> Self; + fn new_foreign(interner: I, def_id: I::ForeignId) -> Self; fn new_dynamic( interner: I, @@ -83,17 +83,21 @@ pub trait Ty>: kind: ty::DynKind, ) -> Self; - fn new_coroutine(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self; + fn new_coroutine(interner: I, def_id: I::CoroutineId, args: I::GenericArgs) -> Self; - fn new_coroutine_closure(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self; + fn new_coroutine_closure( + interner: I, + def_id: I::CoroutineClosureId, + args: I::GenericArgs, + ) -> Self; - fn new_closure(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self; + fn new_closure(interner: I, def_id: I::ClosureId, args: I::GenericArgs) -> Self; - fn new_coroutine_witness(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self; + fn new_coroutine_witness(interner: I, def_id: I::CoroutineId, args: I::GenericArgs) -> Self; fn new_coroutine_witness_for_coroutine( interner: I, - def_id: I::DefId, + def_id: I::CoroutineId, coroutine_args: I::GenericArgs, ) -> Self; @@ -112,7 +116,7 @@ pub trait Ty>: It: Iterator, T: CollectAndApply; - fn new_fn_def(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self; + fn new_fn_def(interner: I, def_id: I::FunctionId, args: I::GenericArgs) -> Self; fn new_fn_ptr(interner: I, sig: ty::Binder>) -> Self; @@ -599,7 +603,7 @@ pub trait ParamLike: Copy + Debug + Hash + Eq { } pub trait AdtDef: Copy + Debug + Hash + Eq { - fn def_id(self) -> I::DefId; + fn def_id(self) -> I::AdtId; fn is_struct(self) -> bool; @@ -646,6 +650,16 @@ pub trait DefId: Copy + Debug + Hash + Eq + TypeFoldable { fn as_local(self) -> Option; } +pub trait SpecificDefId: + DefId + Into + TryFrom +{ +} + +impl + Into + TryFrom> + SpecificDefId for T +{ +} + pub trait BoundExistentialPredicates: Copy + Debug + Hash + Eq + Relate + SliceLike>> { diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 3355c0c2104d..3a83b1739ffa 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -9,7 +9,7 @@ use rustc_index::bit_set::DenseBitSet; use crate::fold::TypeFoldable; use crate::inherent::*; use crate::ir_print::IrPrint; -use crate::lang_items::{SolverLangItem, SolverTraitLangItem}; +use crate::lang_items::{SolverAdtLangItem, SolverLangItem, SolverTraitLangItem}; use crate::relate::Relate; use crate::solve::{ CanonicalInput, ExternalConstraintsData, PredefinedOpaquesData, QueryResult, inspect, @@ -41,13 +41,20 @@ pub trait Interner: type DefId: DefId; type LocalDefId: Copy + Debug + Hash + Eq + Into + TypeFoldable; - /// A `DefId` of a trait. - /// - /// In rustc this is just a `DefId`, but rust-analyzer uses different types for different items. - /// - /// Note: The `TryFrom` always succeeds (in rustc), so don't use it to check if some `DefId` - /// is a trait! - type TraitId: DefId + Into + TryFrom; + // Various more specific `DefId`s. + // + // rustc just defines them all to be `DefId`, but rust-analyzer uses different types so this is convenient for it. + // + // Note: The `TryFrom` always succeeds (in rustc), so don't use it to check if some `DefId` + // is of some specific type! + type TraitId: SpecificDefId; + type ForeignId: SpecificDefId; + type FunctionId: SpecificDefId; + type ClosureId: SpecificDefId; + type CoroutineClosureId: SpecificDefId; + type CoroutineId: SpecificDefId; + type AdtId: SpecificDefId; + type ImplId: SpecificDefId; type Span: Span; type GenericArgs: GenericArgs; @@ -199,7 +206,7 @@ pub trait Interner: -> ty::EarlyBinder; type AdtDef: AdtDef; - fn adt_def(self, adt_def_id: Self::DefId) -> Self::AdtDef; + fn adt_def(self, adt_def_id: Self::AdtId) -> Self::AdtDef; fn alias_ty_kind(self, alias: ty::AliasTy) -> ty::AliasTyKind; @@ -240,17 +247,17 @@ pub trait Interner: fn coroutine_hidden_types( self, - def_id: Self::DefId, + def_id: Self::CoroutineId, ) -> ty::EarlyBinder>>; fn fn_sig( self, - def_id: Self::DefId, + def_id: Self::FunctionId, ) -> ty::EarlyBinder>>; - fn coroutine_movability(self, def_id: Self::DefId) -> Movability; + fn coroutine_movability(self, def_id: Self::CoroutineId) -> Movability; - fn coroutine_for_closure(self, def_id: Self::DefId) -> Self::DefId; + fn coroutine_for_closure(self, def_id: Self::CoroutineClosureId) -> Self::CoroutineId; fn generics_require_sized_self(self, def_id: Self::DefId) -> bool; @@ -293,11 +300,11 @@ pub trait Interner: /// and filtering them to the outlives predicates. This is purely for performance. fn impl_super_outlives( self, - impl_def_id: Self::DefId, + impl_def_id: Self::ImplId, ) -> ty::EarlyBinder>; - fn impl_is_const(self, def_id: Self::DefId) -> bool; - fn fn_is_const(self, def_id: Self::DefId) -> bool; + fn impl_is_const(self, def_id: Self::ImplId) -> bool; + fn fn_is_const(self, def_id: Self::FunctionId) -> bool; fn alias_has_const_conditions(self, def_id: Self::DefId) -> bool; fn const_conditions( self, @@ -308,42 +315,49 @@ pub trait Interner: def_id: Self::DefId, ) -> ty::EarlyBinder>>>; - fn impl_self_is_guaranteed_unsized(self, def_id: Self::DefId) -> bool; + fn impl_self_is_guaranteed_unsized(self, def_id: Self::ImplId) -> bool; - fn has_target_features(self, def_id: Self::DefId) -> bool; + fn has_target_features(self, def_id: Self::FunctionId) -> bool; fn require_lang_item(self, lang_item: SolverLangItem) -> Self::DefId; fn require_trait_lang_item(self, lang_item: SolverTraitLangItem) -> Self::TraitId; + fn require_adt_lang_item(self, lang_item: SolverAdtLangItem) -> Self::AdtId; + fn is_lang_item(self, def_id: Self::DefId, lang_item: SolverLangItem) -> bool; fn is_trait_lang_item(self, def_id: Self::TraitId, lang_item: SolverTraitLangItem) -> bool; + fn is_adt_lang_item(self, def_id: Self::AdtId, lang_item: SolverAdtLangItem) -> bool; + fn is_default_trait(self, def_id: Self::TraitId) -> bool; fn as_lang_item(self, def_id: Self::DefId) -> Option; fn as_trait_lang_item(self, def_id: Self::TraitId) -> Option; + fn as_adt_lang_item(self, def_id: Self::AdtId) -> Option; + fn associated_type_def_ids(self, def_id: Self::DefId) -> impl IntoIterator; fn for_each_relevant_impl( self, trait_def_id: Self::TraitId, self_ty: Self::Ty, - f: impl FnMut(Self::DefId), + f: impl FnMut(Self::ImplId), ); fn has_item_definition(self, def_id: Self::DefId) -> bool; - fn impl_specializes(self, impl_def_id: Self::DefId, victim_def_id: Self::DefId) -> bool; + fn impl_specializes(self, impl_def_id: Self::ImplId, victim_def_id: Self::ImplId) -> bool; - fn impl_is_default(self, impl_def_id: Self::DefId) -> bool; + fn impl_is_default(self, impl_def_id: Self::ImplId) -> bool; - fn impl_trait_ref(self, impl_def_id: Self::DefId) -> ty::EarlyBinder>; + fn impl_trait_ref(self, impl_def_id: Self::ImplId) + -> ty::EarlyBinder>; - fn impl_polarity(self, impl_def_id: Self::DefId) -> ty::ImplPolarity; + fn impl_polarity(self, impl_def_id: Self::ImplId) -> ty::ImplPolarity; fn trait_is_auto(self, trait_def_id: Self::TraitId) -> bool; @@ -364,13 +378,13 @@ pub trait Interner: fn delay_bug(self, msg: impl ToString) -> Self::ErrorGuaranteed; - fn is_general_coroutine(self, coroutine_def_id: Self::DefId) -> bool; - fn coroutine_is_async(self, coroutine_def_id: Self::DefId) -> bool; - fn coroutine_is_gen(self, coroutine_def_id: Self::DefId) -> bool; - fn coroutine_is_async_gen(self, coroutine_def_id: Self::DefId) -> bool; + fn is_general_coroutine(self, coroutine_def_id: Self::CoroutineId) -> bool; + fn coroutine_is_async(self, coroutine_def_id: Self::CoroutineId) -> bool; + fn coroutine_is_gen(self, coroutine_def_id: Self::CoroutineId) -> bool; + fn coroutine_is_async_gen(self, coroutine_def_id: Self::CoroutineId) -> bool; type UnsizingParams: Deref>; - fn unsizing_params_for_adt(self, adt_def_id: Self::DefId) -> Self::UnsizingParams; + fn unsizing_params_for_adt(self, adt_def_id: Self::AdtId) -> Self::UnsizingParams; fn anonymize_bound_vars>( self, diff --git a/compiler/rustc_type_ir/src/lang_items.rs b/compiler/rustc_type_ir/src/lang_items.rs index 31f8f5be588f..5f503d8b912e 100644 --- a/compiler/rustc_type_ir/src/lang_items.rs +++ b/compiler/rustc_type_ir/src/lang_items.rs @@ -11,6 +11,11 @@ pub enum SolverLangItem { DynMetadata, FutureOutput, Metadata, + // tidy-alphabetical-end +} + +pub enum SolverAdtLangItem { + // tidy-alphabetical-start Option, Poll, // tidy-alphabetical-end diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs index 223230fde9e7..690a5f65e084 100644 --- a/compiler/rustc_type_ir/src/relate.rs +++ b/compiler/rustc_type_ir/src/relate.rs @@ -405,7 +405,7 @@ pub fn structurally_relate_tys>( Ok(if a_args.is_empty() { a } else { - let args = relation.relate_item_args(a_def.def_id(), a_args, b_args)?; + let args = relation.relate_item_args(a_def.def_id().into(), a_args, b_args)?; if args == a_args { a } else { Ty::new_adt(cx, a_def, args) } }) } @@ -524,7 +524,7 @@ pub fn structurally_relate_tys>( Ok(if a_args.is_empty() { a } else { - let args = relation.relate_item_args(a_def_id, a_args, b_args)?; + let args = relation.relate_item_args(a_def_id.into(), a_args, b_args)?; if args == a_args { a } else { Ty::new_fn_def(cx, a_def_id, args) } }) } diff --git a/compiler/rustc_type_ir/src/search_graph/mod.rs b/compiler/rustc_type_ir/src/search_graph/mod.rs index dbbc0c217d7d..8f8f019510fe 100644 --- a/compiler/rustc_type_ir/src/search_graph/mod.rs +++ b/compiler/rustc_type_ir/src/search_graph/mod.rs @@ -1262,7 +1262,7 @@ impl, X: Cx> SearchGraph { encountered_overflow |= stack_entry.encountered_overflow; debug_assert_eq!(stack_entry.input, input); - // If the current goal is not the root of a cycle, we are done. + // If the current goal is not a cycle head, we are done. // // There are no provisional cache entries which depend on this goal. let Some(usages) = stack_entry.usages else { @@ -1278,7 +1278,7 @@ impl, X: Cx> SearchGraph { // // Check whether we reached a fixpoint, either because the final result // is equal to the provisional result of the previous iteration, or because - // this was only the root of either coinductive or inductive cycles, and the + // this was only the head of either coinductive or inductive cycles, and the // final result is equal to the initial response for that case. if self.reached_fixpoint(cx, &stack_entry, usages, result) { self.rebase_provisional_cache_entries(&stack_entry, |_, result| result); diff --git a/compiler/rustc_type_ir/src/search_graph/stack.rs b/compiler/rustc_type_ir/src/search_graph/stack.rs index 3fd8e2bd16e4..8348666be412 100644 --- a/compiler/rustc_type_ir/src/search_graph/stack.rs +++ b/compiler/rustc_type_ir/src/search_graph/stack.rs @@ -13,7 +13,7 @@ rustc_index::newtype_index! { pub(super) struct StackDepth {} } -/// Stack entries of the evaluation stack. Its fields tend to be lazily +/// Stack entries of the evaluation stack. Its fields tend to be lazily updated /// when popping a child goal or completely immutable. #[derive_where(Debug; X: Cx)] pub(super) struct StackEntry { @@ -42,7 +42,7 @@ pub(super) struct StackEntry { /// Whether evaluating this goal encountered overflow. Lazily updated. pub encountered_overflow: bool, - /// Whether and how this goal has been used as the root of a cycle. Lazily updated. + /// Whether and how this goal has been used as a cycle head. Lazily updated. pub usages: Option, /// We want to be able to ignore head usages if they happen inside of candidates diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs index b6d362d77c44..b48a8f46ebef 100644 --- a/compiler/rustc_type_ir/src/solve/mod.rs +++ b/compiler/rustc_type_ir/src/solve/mod.rs @@ -136,7 +136,7 @@ pub enum CandidateSource { /// let y = x.clone(); /// } /// ``` - Impl(I::DefId), + Impl(I::ImplId), /// A builtin impl generated by the compiler. When adding a new special /// trait, try to use actual impls whenever possible. Builtin impls should /// only be used in cases where the impl cannot be manually be written. diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index bde506ffd938..225d85f79c3d 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -101,7 +101,7 @@ pub enum TyKind { Adt(I::AdtDef, I::GenericArgs), /// An unsized FFI type that is opaque to Rust. Written as `extern type T`. - Foreign(I::DefId), + Foreign(I::ForeignId), /// The pointee of a string slice. Written as `str`. Str, @@ -137,7 +137,7 @@ pub enum TyKind { /// fn foo() -> i32 { 1 } /// let bar = foo; // bar: fn() -> i32 {foo} /// ``` - FnDef(I::DefId, I::GenericArgs), + FnDef(I::FunctionId, I::GenericArgs), /// A pointer to a function. Written as `fn() -> i32`. /// @@ -172,21 +172,21 @@ pub enum TyKind { /// Closure args contain both the - potentially instantiated - generic parameters /// of its parent and some synthetic parameters. See the documentation for /// `ClosureArgs` for more details. - Closure(I::DefId, I::GenericArgs), + Closure(I::ClosureId, I::GenericArgs), /// The anonymous type of a closure. Used to represent the type of `async |a| a`. /// /// Coroutine-closure args contain both the - potentially instantiated - generic /// parameters of its parent and some synthetic parameters. See the documentation /// for `CoroutineClosureArgs` for more details. - CoroutineClosure(I::DefId, I::GenericArgs), + CoroutineClosure(I::CoroutineClosureId, I::GenericArgs), /// The anonymous type of a coroutine. Used to represent the type of /// `|a| yield a`. /// /// For more info about coroutine args, visit the documentation for /// `CoroutineArgs`. - Coroutine(I::DefId, I::GenericArgs), + Coroutine(I::CoroutineId, I::GenericArgs), /// A type representing the types stored inside a coroutine. /// This should only appear as part of the `CoroutineArgs`. @@ -211,7 +211,7 @@ pub enum TyKind { /// } /// # ; /// ``` - CoroutineWitness(I::DefId, I::GenericArgs), + CoroutineWitness(I::CoroutineId, I::GenericArgs), /// The never type `!`. Never, diff --git a/compiler/rustc_type_ir/src/ty_kind/closure.rs b/compiler/rustc_type_ir/src/ty_kind/closure.rs index a2e16d917a9e..3a6d1acfa8d9 100644 --- a/compiler/rustc_type_ir/src/ty_kind/closure.rs +++ b/compiler/rustc_type_ir/src/ty_kind/closure.rs @@ -391,7 +391,7 @@ impl CoroutineClosureSignature { cx: I, parent_args: I::GenericArgsSlice, coroutine_kind_ty: I::Ty, - coroutine_def_id: I::DefId, + coroutine_def_id: I::CoroutineId, tupled_upvars_ty: I::Ty, ) -> I::Ty { let coroutine_args = ty::CoroutineArgs::new( @@ -418,7 +418,7 @@ impl CoroutineClosureSignature { self, cx: I, parent_args: I::GenericArgsSlice, - coroutine_def_id: I::DefId, + coroutine_def_id: I::CoroutineId, goal_kind: ty::ClosureKind, env_region: I::Region, closure_tupled_upvars_ty: I::Ty, diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs index 5104484e9c43..6e62e1031a96 100644 --- a/compiler/rustc_type_ir/src/visit.rs +++ b/compiler/rustc_type_ir/src/visit.rs @@ -398,9 +398,9 @@ impl std::fmt::Debug for HasTypeFlagsVisitor { // looks, particular for `Ty`/`Predicate` where it's just a field access. // // N.B. The only case where this isn't totally true is binders, which also -// add `HAS_{RE,TY,CT}_LATE_BOUND` flag depending on the *bound variables* that +// add `HAS_BINDER_VARS` flag depending on the *bound variables* that // are present, regardless of whether those bound variables are used. This -// is important for anonymization of binders in `TyCtxt::erase_regions`. We +// is important for anonymization of binders in `TyCtxt::erase_and_anonymize_regions`. We // specifically detect this case in `visit_binder`. impl TypeVisitor for HasTypeFlagsVisitor { type Result = ControlFlow; diff --git a/compiler/rustc_windows_rc/Cargo.toml b/compiler/rustc_windows_rc/Cargo.toml new file mode 100644 index 000000000000..080acd35c38c --- /dev/null +++ b/compiler/rustc_windows_rc/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "rustc_windows_rc" +version = "0.0.0" +edition = "2024" + +[dependencies] +#tidy-alphabetical-start +# `cc` updates often break things, so we pin it here. Cargo enforces "max 1 semver-compat version +# per crate", so if you change this, you need to also change it in `rustc_llvm` and `rustc_codegen_ssa`. +cc = "=1.2.16" +#tidy-alphabetical-end diff --git a/compiler/rustc_windows_rc/rustc.rc.in b/compiler/rustc_windows_rc/rustc.rc.in new file mode 100644 index 000000000000..10a00b9bd4e3 --- /dev/null +++ b/compiler/rustc_windows_rc/rustc.rc.in @@ -0,0 +1,40 @@ +// A template for the rustc_driver and rustc Windows resource files. +// This file is processed by the build script to produce rustc.rc and rustc_driver.rc +// with the appropriate version information filled in. + +// All the strings are in UTF-8 +#pragma code_page(65001) + +#define RUSTC_FILEDESCRIPTION_STR "@RUSTC_FILEDESCRIPTION_STR@" +#define RUSTC_FILETYPE @RUSTC_FILETYPE@ +#define RUSTC_FILEVERSION_QUAD @RUSTC_FILEVERSION_QUAD@ +#define RUSTC_FILEVERSION_STR "@RUSTC_FILEVERSION_STR@" + +#define RUSTC_PRODUCTNAME_STR "@RUSTC_PRODUCTNAME_STR@" +#define RUSTC_PRODUCTVERSION_QUAD @RUSTC_PRODUCTVERSION_QUAD@ +#define RUSTC_PRODUCTVERSION_STR "@RUSTC_PRODUCTVERSION_STR@" + + +1 VERSIONINFO +FILEVERSION RUSTC_FILEVERSION_QUAD +PRODUCTVERSION RUSTC_PRODUCTVERSION_QUAD +FILEOS 0x00040004 +FILETYPE RUSTC_FILETYPE +FILESUBTYPE 0 +FILEFLAGSMASK 0x3f +FILEFLAGS 0x0 +{ + BLOCK "StringFileInfo" + { + BLOCK "000004b0" + { + VALUE "FileDescription", RUSTC_FILEDESCRIPTION_STR + VALUE "FileVersion", RUSTC_FILEVERSION_STR + VALUE "ProductVersion", RUSTC_PRODUCTVERSION_STR + VALUE "ProductName", RUSTC_PRODUCTNAME_STR + } + } + BLOCK "VarFileInfo" { + VALUE "Translation", 0x0, 0x04b0 + } +} diff --git a/compiler/rustc_windows_rc/src/lib.rs b/compiler/rustc_windows_rc/src/lib.rs new file mode 100644 index 000000000000..caa5e5ef2765 --- /dev/null +++ b/compiler/rustc_windows_rc/src/lib.rs @@ -0,0 +1,158 @@ +//! A build script dependency to create a Windows resource file for the compiler +//! +//! Uses values from the `CFG_VERSION` and `CFG_RELEASE` environment variables +//! to set the product and file version information in the Windows resource file. +use std::{env, ffi, fs, path, process}; + +use cc::windows_registry; + +/// The template for the Windows resource file. +const RESOURCE_TEMPLATE: &str = include_str!("../rustc.rc.in"); + +/// A subset of the possible values for the `FILETYPE` field in a Windows resource file +/// +/// See the `dwFileType` member of [VS_FIXEDFILEINFO](https://learn.microsoft.com/en-us/windows/win32/api/verrsrc/ns-verrsrc-vs_fixedfileinfo#members) +#[derive(Debug, Clone, Copy)] +#[repr(u32)] +pub enum VersionInfoFileType { + /// `VFT_APP` - The file is an application. + App = 0x00000001, + /// `VFT_DLL` - The file is a dynamic link library. + Dll = 0x00000002, +} + +/// Create and compile a Windows resource file with the product and file version information for the rust compiler. +/// +/// Returns the path to the compiled resource file +/// +/// Does not emit any cargo directives, the caller is responsible for that. +pub fn compile_windows_resource_file( + file_stem: &path::Path, + file_description: &str, + filetype: VersionInfoFileType, +) -> path::PathBuf { + let mut resources_dir = path::PathBuf::from(env::var_os("OUT_DIR").unwrap()); + resources_dir.push("resources"); + fs::create_dir_all(&resources_dir).unwrap(); + + let resource_compiler = + find_resource_compiler(&env::var("CARGO_CFG_TARGET_ARCH").unwrap()).expect("found rc.exe"); + + let rc_path = resources_dir.join(file_stem.with_extension("rc")); + + write_resource_script_file(&rc_path, file_description, filetype); + + let res_path = resources_dir.join(file_stem.with_extension("res")); + + let status = process::Command::new(resource_compiler) + .arg("/fo") + .arg(&res_path) + .arg(&rc_path) + .status() + .expect("can execute resource compiler"); + assert!(status.success(), "rc.exe failed with status {}", status); + assert!( + res_path.try_exists().unwrap_or(false), + "resource file {} was not created", + res_path.display() + ); + res_path +} + +/// Writes a Windows resource script file for the rust compiler with the product and file version information +/// into `rc_path` +fn write_resource_script_file( + rc_path: &path::Path, + file_description: &str, + filetype: VersionInfoFileType, +) { + let mut resource_script = RESOURCE_TEMPLATE.to_string(); + + // Set the string product and file version to the same thing as `rustc --version` + let descriptive_version = env::var("CFG_VERSION").unwrap_or("unknown".to_string()); + + // Set the product name to "Rust Compiler" or "Rust Compiler (nightly)" etc + let product_name = product_name(env::var("CFG_RELEASE_CHANNEL").unwrap()); + + // For the numeric version we need `major,minor,patch,build`. + // Extract them from `CFG_RELEASE` which is "major.minor.patch" and a "-dev", "-nightly" or similar suffix + let cfg_release = env::var("CFG_RELEASE").unwrap(); + // remove the suffix, if present and parse into [`ResourceVersion`] + let version = parse_version(cfg_release.split("-").next().unwrap_or("0.0.0")) + .expect("valid CFG_RELEASE version"); + + resource_script = resource_script + .replace("@RUSTC_FILEDESCRIPTION_STR@", file_description) + .replace("@RUSTC_FILETYPE@", &format!("{}", filetype as u32)) + .replace("@RUSTC_FILEVERSION_QUAD@", &version.to_quad_string()) + .replace("@RUSTC_FILEVERSION_STR@", &descriptive_version) + .replace("@RUSTC_PRODUCTNAME_STR@", &product_name) + .replace("@RUSTC_PRODUCTVERSION_QUAD@", &version.to_quad_string()) + .replace("@RUSTC_PRODUCTVERSION_STR@", &descriptive_version); + + fs::write(&rc_path, resource_script) + .unwrap_or_else(|_| panic!("failed to write resource file {}", rc_path.display())); +} + +fn product_name(channel: String) -> String { + format!( + "Rust Compiler{}", + if channel == "stable" { "".to_string() } else { format!(" ({})", channel) } + ) +} + +/// Windows resources store versions as four 16-bit integers. +struct ResourceVersion { + major: u16, + minor: u16, + patch: u16, + build: u16, +} + +impl ResourceVersion { + /// Format the version as a comma-separated string of four integers + /// as expected by Windows resource scripts for the `FILEVERSION` and `PRODUCTVERSION` fields. + fn to_quad_string(&self) -> String { + format!("{},{},{},{}", self.major, self.minor, self.patch, self.build) + } +} + +/// Parse a string in the format "major.minor.patch" into a [`ResourceVersion`]. +/// The build is set to 0. +/// Returns `None` if the version string is not in the expected format. +fn parse_version(version: &str) -> Option { + let mut parts = version.split('.'); + let major = parts.next()?.parse::().ok()?; + let minor = parts.next()?.parse::().ok()?; + let patch = parts.next()?.parse::().ok()?; + if parts.next().is_some() { + None + } else { + Some(ResourceVersion { major, minor, patch, build: 0 }) + } +} + +/// Find the Windows SDK resource compiler `rc.exe` for the given architecture or target triple. +/// Returns `None` if the tool could not be found. +fn find_resource_compiler(arch_or_target: &str) -> Option { + find_windows_sdk_tool(arch_or_target, "rc.exe") +} + +/// Find a Windows SDK tool for the given architecture or target triple. +/// Returns `None` if the tool could not be found. +fn find_windows_sdk_tool(arch_or_target: &str, tool_name: &str) -> Option { + // windows_registry::find_tool can only find MSVC tools, not Windows SDK tools, but + // cc does include the Windows SDK tools in the PATH environment of MSVC tools. + + let msvc_linker = windows_registry::find_tool(arch_or_target, "link.exe")?; + let path = &msvc_linker.env().iter().find(|(k, _)| k == "PATH")?.1; + find_tool_in_path(tool_name, path) +} + +/// Find a tool in the directories in a given PATH-like string. +fn find_tool_in_path>(tool_name: &str, path: P) -> Option { + env::split_paths(path.as_ref()).find_map(|p| { + let tool_path = p.join(tool_name); + if tool_path.try_exists().unwrap_or(false) { Some(tool_path) } else { None } + }) +} diff --git a/library/Cargo.lock b/library/Cargo.lock index e601137e0057..e4b3839847b1 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -99,13 +99,12 @@ dependencies = [ [[package]] name = "getopts" -version = "0.2.23" +version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cba6ae63eb948698e300f645f87c70f76630d505f23b8907cf1e193ee85048c1" +checksum = "cfe4fbac503b8d1f88e6676011885f34b7174f46e59956bba534ba83abded4df" dependencies = [ "rustc-std-workspace-core", "rustc-std-workspace-std", - "unicode-width", ] [[package]] @@ -361,16 +360,6 @@ dependencies = [ "std", ] -[[package]] -name = "unicode-width" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" -dependencies = [ - "rustc-std-workspace-core", - "rustc-std-workspace-std", -] - [[package]] name = "unwind" version = "0.0.0" diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs index 22cdd8ecde02..e772ac25a95c 100644 --- a/library/alloc/src/str.rs +++ b/library/alloc/src/str.rs @@ -418,9 +418,8 @@ impl str { } fn case_ignorable_then_cased>(iter: I) -> bool { - use core::unicode::{Case_Ignorable, Cased}; - match iter.skip_while(|&c| Case_Ignorable(c)).next() { - Some(c) => Cased(c), + match iter.skip_while(|&c| c.is_case_ignorable()).next() { + Some(c) => c.is_cased(), None => false, } } diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 3336d028e273..76f54db28707 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -969,7 +969,43 @@ impl char { #[must_use] #[inline] pub(crate) fn is_grapheme_extended(self) -> bool { - unicode::Grapheme_Extend(self) + !self.is_ascii() && unicode::Grapheme_Extend(self) + } + + /// Returns `true` if this `char` has the `Cased` property. + /// + /// `Cased` is described in Chapter 4 (Character Properties) of the [Unicode Standard] and + /// specified in the [Unicode Character Database][ucd] [`DerivedCoreProperties.txt`]. + /// + /// [Unicode Standard]: https://www.unicode.org/versions/latest/ + /// [ucd]: https://www.unicode.org/reports/tr44/ + /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt + #[must_use] + #[inline] + #[doc(hidden)] + #[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] + pub fn is_cased(self) -> bool { + if self.is_ascii() { self.is_ascii_alphabetic() } else { unicode::Cased(self) } + } + + /// Returns `true` if this `char` has the `Case_Ignorable` property. + /// + /// `Case_Ignorable` is described in Chapter 4 (Character Properties) of the [Unicode Standard] and + /// specified in the [Unicode Character Database][ucd] [`DerivedCoreProperties.txt`]. + /// + /// [Unicode Standard]: https://www.unicode.org/versions/latest/ + /// [ucd]: https://www.unicode.org/reports/tr44/ + /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt + #[must_use] + #[inline] + #[doc(hidden)] + #[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] + pub fn is_case_ignorable(self) -> bool { + if self.is_ascii() { + matches!(self, '\'' | '.' | ':' | '^' | '`') + } else { + unicode::Case_Ignorable(self) + } } /// Returns `true` if this `char` has one of the general categories for numbers. diff --git a/library/core/src/default.rs b/library/core/src/default.rs index cc9289307c1d..1cc4fb6e8fdd 100644 --- a/library/core/src/default.rs +++ b/library/core/src/default.rs @@ -33,7 +33,7 @@ use crate::ascii::Char as AsciiChar; /// } /// ``` /// -/// Now, you get all of the default values. Rust implements `Default` for various primitives types. +/// Now, you get all of the default values. Rust implements `Default` for various primitive types. /// /// If you want to override a particular option, but still retain the other defaults: /// diff --git a/library/core/src/iter/traits/accum.rs b/library/core/src/iter/traits/accum.rs index 73122369b41d..3b805139ded1 100644 --- a/library/core/src/iter/traits/accum.rs +++ b/library/core/src/iter/traits/accum.rs @@ -203,7 +203,7 @@ macro_rules! float_sum_product { integer_sum_product! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize } saturating_integer_sum_product! { u8 u16 u32 u64 u128 usize } -float_sum_product! { f32 f64 } +float_sum_product! { f16 f32 f64 f128 } #[stable(feature = "iter_arith_traits_result", since = "1.16.0")] impl Sum> for Result diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index c306011bdda3..86a68e18b0af 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -252,47 +252,16 @@ pub use crate::macros::cfg_select; #[macro_use] mod internal_macros; -#[path = "num/shells/int_macros.rs"] -#[macro_use] -mod int_macros; - -#[rustc_diagnostic_item = "i128_legacy_mod"] -#[path = "num/shells/i128.rs"] -pub mod i128; -#[rustc_diagnostic_item = "i16_legacy_mod"] -#[path = "num/shells/i16.rs"] -pub mod i16; -#[rustc_diagnostic_item = "i32_legacy_mod"] -#[path = "num/shells/i32.rs"] -pub mod i32; -#[rustc_diagnostic_item = "i64_legacy_mod"] -#[path = "num/shells/i64.rs"] -pub mod i64; -#[rustc_diagnostic_item = "i8_legacy_mod"] -#[path = "num/shells/i8.rs"] -pub mod i8; -#[rustc_diagnostic_item = "isize_legacy_mod"] -#[path = "num/shells/isize.rs"] -pub mod isize; - -#[rustc_diagnostic_item = "u128_legacy_mod"] -#[path = "num/shells/u128.rs"] -pub mod u128; -#[rustc_diagnostic_item = "u16_legacy_mod"] -#[path = "num/shells/u16.rs"] -pub mod u16; -#[rustc_diagnostic_item = "u32_legacy_mod"] -#[path = "num/shells/u32.rs"] -pub mod u32; -#[rustc_diagnostic_item = "u64_legacy_mod"] -#[path = "num/shells/u64.rs"] -pub mod u64; -#[rustc_diagnostic_item = "u8_legacy_mod"] -#[path = "num/shells/u8.rs"] -pub mod u8; -#[rustc_diagnostic_item = "usize_legacy_mod"] -#[path = "num/shells/usize.rs"] -pub mod usize; +#[path = "num/shells/legacy_int_modules.rs"] +mod legacy_int_modules; +#[stable(feature = "rust1", since = "1.0.0")] +#[allow(clippy::useless_attribute)] // FIXME false positive (https://github.com/rust-lang/rust-clippy/issues/15636) +#[allow(deprecated_in_future)] +pub use legacy_int_modules::{i8, i16, i32, i64, isize, u8, u16, u32, u64, usize}; +#[stable(feature = "i128", since = "1.26.0")] +#[allow(clippy::useless_attribute)] // FIXME false positive (https://github.com/rust-lang/rust-clippy/issues/15636) +#[allow(deprecated_in_future)] +pub use legacy_int_modules::{i128, u128}; #[path = "num/f128.rs"] pub mod f128; diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index ccf41dfb01dd..3f58fc448aa6 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1017,6 +1017,7 @@ pub(crate) mod builtin { )] #[allow_internal_unstable(fmt_internals)] #[rustc_builtin_macro] + #[doc(hidden)] #[macro_export] macro_rules! format_args_nl { ($fmt:expr) => {{ /* compiler built-in */ }}; diff --git a/library/core/src/num/shells/i128.rs b/library/core/src/num/shells/i128.rs deleted file mode 100644 index b3b3d3b4875a..000000000000 --- a/library/core/src/num/shells/i128.rs +++ /dev/null @@ -1,11 +0,0 @@ -//! Redundant constants module for the [`i128` primitive type][i128]. -//! -//! New code should use the associated constants directly on the primitive type. - -#![stable(feature = "i128", since = "1.26.0")] -#![deprecated( - since = "TBD", - note = "all constants in this module replaced by associated constants on `i128`" -)] - -int_module! { i128, #[stable(feature = "i128", since="1.26.0")] } diff --git a/library/core/src/num/shells/i16.rs b/library/core/src/num/shells/i16.rs deleted file mode 100644 index 70a452e19398..000000000000 --- a/library/core/src/num/shells/i16.rs +++ /dev/null @@ -1,11 +0,0 @@ -//! Redundant constants module for the [`i16` primitive type][i16]. -//! -//! New code should use the associated constants directly on the primitive type. - -#![stable(feature = "rust1", since = "1.0.0")] -#![deprecated( - since = "TBD", - note = "all constants in this module replaced by associated constants on `i16`" -)] - -int_module! { i16 } diff --git a/library/core/src/num/shells/i32.rs b/library/core/src/num/shells/i32.rs deleted file mode 100644 index c30849e2591c..000000000000 --- a/library/core/src/num/shells/i32.rs +++ /dev/null @@ -1,11 +0,0 @@ -//! Redundant constants module for the [`i32` primitive type][i32]. -//! -//! New code should use the associated constants directly on the primitive type. - -#![stable(feature = "rust1", since = "1.0.0")] -#![deprecated( - since = "TBD", - note = "all constants in this module replaced by associated constants on `i32`" -)] - -int_module! { i32 } diff --git a/library/core/src/num/shells/i64.rs b/library/core/src/num/shells/i64.rs deleted file mode 100644 index 77d95d712506..000000000000 --- a/library/core/src/num/shells/i64.rs +++ /dev/null @@ -1,11 +0,0 @@ -//! Redundant constants module for the [`i64` primitive type][i64]. -//! -//! New code should use the associated constants directly on the primitive type. - -#![stable(feature = "rust1", since = "1.0.0")] -#![deprecated( - since = "TBD", - note = "all constants in this module replaced by associated constants on `i64`" -)] - -int_module! { i64 } diff --git a/library/core/src/num/shells/i8.rs b/library/core/src/num/shells/i8.rs deleted file mode 100644 index 516ba8cdef3b..000000000000 --- a/library/core/src/num/shells/i8.rs +++ /dev/null @@ -1,11 +0,0 @@ -//! Redundant constants module for the [`i8` primitive type][i8]. -//! -//! New code should use the associated constants directly on the primitive type. - -#![stable(feature = "rust1", since = "1.0.0")] -#![deprecated( - since = "TBD", - note = "all constants in this module replaced by associated constants on `i8`" -)] - -int_module! { i8 } diff --git a/library/core/src/num/shells/int_macros.rs b/library/core/src/num/shells/int_macros.rs deleted file mode 100644 index 8ae9b7abae3b..000000000000 --- a/library/core/src/num/shells/int_macros.rs +++ /dev/null @@ -1,46 +0,0 @@ -#![doc(hidden)] - -macro_rules! int_module { - ($T:ident) => (int_module!($T, #[stable(feature = "rust1", since = "1.0.0")]);); - ($T:ident, #[$attr:meta]) => ( - #[doc = concat!( - "The smallest value that can be represented by this integer type. Use ", - "[`", stringify!($T), "::MIN", "`] instead." - )] - /// - /// # Examples - /// - /// ```rust - /// // deprecated way - #[doc = concat!("let min = std::", stringify!($T), "::MIN;")] - /// - /// // intended way - #[doc = concat!("let min = ", stringify!($T), "::MIN;")] - /// ``` - /// - #[$attr] - #[deprecated(since = "TBD", note = "replaced by the `MIN` associated constant on this type")] - #[rustc_diagnostic_item = concat!(stringify!($T), "_legacy_const_min")] - pub const MIN: $T = $T::MIN; - - #[doc = concat!( - "The largest value that can be represented by this integer type. Use ", - "[`", stringify!($T), "::MAX", "`] instead." - )] - /// - /// # Examples - /// - /// ```rust - /// // deprecated way - #[doc = concat!("let max = std::", stringify!($T), "::MAX;")] - /// - /// // intended way - #[doc = concat!("let max = ", stringify!($T), "::MAX;")] - /// ``` - /// - #[$attr] - #[deprecated(since = "TBD", note = "replaced by the `MAX` associated constant on this type")] - #[rustc_diagnostic_item = concat!(stringify!($T), "_legacy_const_max")] - pub const MAX: $T = $T::MAX; - ) -} diff --git a/library/core/src/num/shells/isize.rs b/library/core/src/num/shells/isize.rs deleted file mode 100644 index 828f7345bafb..000000000000 --- a/library/core/src/num/shells/isize.rs +++ /dev/null @@ -1,11 +0,0 @@ -//! Redundant constants module for the [`isize` primitive type][isize]. -//! -//! New code should use the associated constants directly on the primitive type. - -#![stable(feature = "rust1", since = "1.0.0")] -#![deprecated( - since = "TBD", - note = "all constants in this module replaced by associated constants on `isize`" -)] - -int_module! { isize } diff --git a/library/core/src/num/shells/legacy_int_modules.rs b/library/core/src/num/shells/legacy_int_modules.rs new file mode 100644 index 000000000000..6b4f25391115 --- /dev/null +++ b/library/core/src/num/shells/legacy_int_modules.rs @@ -0,0 +1,71 @@ +#![doc(hidden)] + +macro_rules! legacy_int_module { + ($T:ident) => (legacy_int_module!($T, #[stable(feature = "rust1", since = "1.0.0")]);); + ($T:ident, #[$attr:meta]) => ( + #[$attr] + #[deprecated( + since = "TBD", + note = "all constants in this module replaced by associated constants on the type" + )] + #[rustc_diagnostic_item = concat!(stringify!($T), "_legacy_mod")] + pub mod $T { + #![doc = concat!("Redundant constants module for the [`", stringify!($T), "` primitive type][", stringify!($T), "].")] + //! + //! New code should use the associated constants directly on the primitive type. + + #[doc = concat!( + "The smallest value that can be represented by this integer type. Use ", + "[`", stringify!($T), "::MIN", "`] instead." + )] + /// + /// # Examples + /// + /// ```rust + /// // deprecated way + #[doc = concat!("let min = std::", stringify!($T), "::MIN;")] + /// + /// // intended way + #[doc = concat!("let min = ", stringify!($T), "::MIN;")] + /// ``` + /// + #[$attr] + #[deprecated(since = "TBD", note = "replaced by the `MIN` associated constant on this type")] + #[rustc_diagnostic_item = concat!(stringify!($T), "_legacy_const_min")] + pub const MIN: $T = $T::MIN; + + #[doc = concat!( + "The largest value that can be represented by this integer type. Use ", + "[`", stringify!($T), "::MAX", "`] instead." + )] + /// + /// # Examples + /// + /// ```rust + /// // deprecated way + #[doc = concat!("let max = std::", stringify!($T), "::MAX;")] + /// + /// // intended way + #[doc = concat!("let max = ", stringify!($T), "::MAX;")] + /// ``` + /// + #[$attr] + #[deprecated(since = "TBD", note = "replaced by the `MAX` associated constant on this type")] + #[rustc_diagnostic_item = concat!(stringify!($T), "_legacy_const_max")] + pub const MAX: $T = $T::MAX; + } + ) +} + +legacy_int_module! { i128, #[stable(feature = "i128", since = "1.26.0")] } +legacy_int_module! { i16 } +legacy_int_module! { i32 } +legacy_int_module! { i64 } +legacy_int_module! { i8 } +legacy_int_module! { isize } +legacy_int_module! { u128, #[stable(feature = "i128", since = "1.26.0")] } +legacy_int_module! { u16 } +legacy_int_module! { u32 } +legacy_int_module! { u64 } +legacy_int_module! { u8 } +legacy_int_module! { usize } diff --git a/library/core/src/num/shells/u128.rs b/library/core/src/num/shells/u128.rs deleted file mode 100644 index b1e30e384352..000000000000 --- a/library/core/src/num/shells/u128.rs +++ /dev/null @@ -1,11 +0,0 @@ -//! Redundant constants module for the [`u128` primitive type][u128]. -//! -//! New code should use the associated constants directly on the primitive type. - -#![stable(feature = "i128", since = "1.26.0")] -#![deprecated( - since = "TBD", - note = "all constants in this module replaced by associated constants on `u128`" -)] - -int_module! { u128, #[stable(feature = "i128", since="1.26.0")] } diff --git a/library/core/src/num/shells/u16.rs b/library/core/src/num/shells/u16.rs deleted file mode 100644 index 7394977e5078..000000000000 --- a/library/core/src/num/shells/u16.rs +++ /dev/null @@ -1,11 +0,0 @@ -//! Redundant constants module for the [`u16` primitive type][u16]. -//! -//! New code should use the associated constants directly on the primitive type. - -#![stable(feature = "rust1", since = "1.0.0")] -#![deprecated( - since = "TBD", - note = "all constants in this module replaced by associated constants on `u16`" -)] - -int_module! { u16 } diff --git a/library/core/src/num/shells/u32.rs b/library/core/src/num/shells/u32.rs deleted file mode 100644 index 4c84274e752e..000000000000 --- a/library/core/src/num/shells/u32.rs +++ /dev/null @@ -1,11 +0,0 @@ -//! Redundant constants module for the [`u32` primitive type][u32]. -//! -//! New code should use the associated constants directly on the primitive type. - -#![stable(feature = "rust1", since = "1.0.0")] -#![deprecated( - since = "TBD", - note = "all constants in this module replaced by associated constants on `u32`" -)] - -int_module! { u32 } diff --git a/library/core/src/num/shells/u64.rs b/library/core/src/num/shells/u64.rs deleted file mode 100644 index 47a95c6820f2..000000000000 --- a/library/core/src/num/shells/u64.rs +++ /dev/null @@ -1,11 +0,0 @@ -//! Redundant constants module for the [`u64` primitive type][u64]. -//! -//! New code should use the associated constants directly on the primitive type. - -#![stable(feature = "rust1", since = "1.0.0")] -#![deprecated( - since = "TBD", - note = "all constants in this module replaced by associated constants on `u64`" -)] - -int_module! { u64 } diff --git a/library/core/src/num/shells/u8.rs b/library/core/src/num/shells/u8.rs deleted file mode 100644 index 360baef72286..000000000000 --- a/library/core/src/num/shells/u8.rs +++ /dev/null @@ -1,11 +0,0 @@ -//! Redundant constants module for the [`u8` primitive type][u8]. -//! -//! New code should use the associated constants directly on the primitive type. - -#![stable(feature = "rust1", since = "1.0.0")] -#![deprecated( - since = "TBD", - note = "all constants in this module replaced by associated constants on `u8`" -)] - -int_module! { u8 } diff --git a/library/core/src/num/shells/usize.rs b/library/core/src/num/shells/usize.rs deleted file mode 100644 index 44c24dfc2cf5..000000000000 --- a/library/core/src/num/shells/usize.rs +++ /dev/null @@ -1,11 +0,0 @@ -//! Redundant constants module for the [`usize` primitive type][usize]. -//! -//! New code should use the associated constants directly on the primitive type. - -#![stable(feature = "rust1", since = "1.0.0")] -#![deprecated( - since = "TBD", - note = "all constants in this module replaced by associated constants on `usize`" -)] - -int_module! { usize } diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 6b94088cb567..625024373ef4 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -1348,6 +1348,40 @@ pub const unsafe fn swap(x: *mut T, y: *mut T) { /// assert_eq!(x, [7, 8, 3, 4]); /// assert_eq!(y, [1, 2, 9]); /// ``` +/// +/// # Const evaluation limitations +/// +/// If this function is invoked during const-evaluation, the current implementation has a small (and +/// rarely relevant) limitation: if `count` is at least 2 and the data pointed to by `x` or `y` +/// contains a pointer that crosses the boundary of two `T`-sized chunks of memory, the function may +/// fail to evaluate (similar to a panic during const-evaluation). This behavior may change in the +/// future. +/// +/// The limitation is illustrated by the following example: +/// +/// ``` +/// use std::mem::size_of; +/// use std::ptr; +/// +/// const { unsafe { +/// const PTR_SIZE: usize = size_of::<*const i32>(); +/// let mut data1 = [0u8; PTR_SIZE]; +/// let mut data2 = [0u8; PTR_SIZE]; +/// // Store a pointer in `data1`. +/// data1.as_mut_ptr().cast::<*const i32>().write_unaligned(&42); +/// // Swap the contents of `data1` and `data2` by swapping `PTR_SIZE` many `u8`-sized chunks. +/// // This call will fail, because the pointer in `data1` crosses the boundary +/// // between several of the 1-byte chunks that are being swapped here. +/// //ptr::swap_nonoverlapping(data1.as_mut_ptr(), data2.as_mut_ptr(), PTR_SIZE); +/// // Swap the contents of `data1` and `data2` by swapping a single chunk of size +/// // `[u8; PTR_SIZE]`. That works, as there is no pointer crossing the boundary between +/// // two chunks. +/// ptr::swap_nonoverlapping(&mut data1, &mut data2, 1); +/// // Read the pointer from `data2` and dereference it. +/// let ptr = data2.as_ptr().cast::<*const i32>().read_unaligned(); +/// assert!(*ptr == 42); +/// } } +/// ``` #[inline] #[stable(feature = "swap_nonoverlapping", since = "1.27.0")] #[rustc_const_stable(feature = "const_swap_nonoverlapping", since = "1.88.0")] @@ -1376,7 +1410,9 @@ pub const unsafe fn swap_nonoverlapping(x: *mut T, y: *mut T, count: usize) { const_eval_select!( @capture[T] { x: *mut T, y: *mut T, count: usize }: if const { - // At compile-time we don't need all the special code below. + // At compile-time we want to always copy this in chunks of `T`, to ensure that if there + // are pointers inside `T` we will copy them in one go rather than trying to copy a part + // of a pointer (which would not work). // SAFETY: Same preconditions as this function unsafe { swap_nonoverlapping_const(x, y, count) } } else { diff --git a/library/core/src/range.rs b/library/core/src/range.rs index 332ae51d8484..8c49123fdaf5 100644 --- a/library/core/src/range.rs +++ b/library/core/src/range.rs @@ -31,9 +31,7 @@ pub use iter::{IterRange, IterRangeFrom, IterRangeInclusive}; #[doc(inline)] pub use crate::iter::Step; #[doc(inline)] -pub use crate::ops::{ - Bound, IntoBounds, OneSidedRange, RangeBounds, RangeFull, RangeTo, RangeToInclusive, -}; +pub use crate::ops::{Bound, IntoBounds, OneSidedRange, RangeBounds, RangeFull, RangeTo}; /// A (half-open) range bounded inclusively below and exclusively above /// (`start..end` in a future edition). @@ -209,20 +207,20 @@ impl const From> for Range { } } -/// A range bounded inclusively below and above (`start..=end`). +/// A range bounded inclusively below and above (`start..=last`). /// -/// The `RangeInclusive` `start..=end` contains all values with `x >= start` -/// and `x <= end`. It is empty unless `start <= end`. +/// The `RangeInclusive` `start..=last` contains all values with `x >= start` +/// and `x <= last`. It is empty unless `start <= last`. /// /// # Examples /// -/// The `start..=end` syntax is a `RangeInclusive`: +/// The `start..=last` syntax is a `RangeInclusive`: /// /// ``` /// #![feature(new_range_api)] /// use core::range::RangeInclusive; /// -/// assert_eq!(RangeInclusive::from(3..=5), RangeInclusive { start: 3, end: 5 }); +/// assert_eq!(RangeInclusive::from(3..=5), RangeInclusive { start: 3, last: 5 }); /// assert_eq!(3 + 4 + 5, RangeInclusive::from(3..=5).into_iter().sum()); /// ``` #[lang = "RangeInclusiveCopy"] @@ -234,7 +232,7 @@ pub struct RangeInclusive { pub start: Idx, /// The upper bound of the range (inclusive). #[unstable(feature = "new_range_api", issue = "125687")] - pub end: Idx, + pub last: Idx, } #[unstable(feature = "new_range_api", issue = "125687")] @@ -242,7 +240,7 @@ impl fmt::Debug for RangeInclusive { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { self.start.fmt(fmt)?; write!(fmt, "..=")?; - self.end.fmt(fmt)?; + self.last.fmt(fmt)?; Ok(()) } } @@ -306,7 +304,7 @@ impl> RangeInclusive { #[unstable(feature = "new_range_api", issue = "125687")] #[inline] pub fn is_empty(&self) -> bool { - !(self.start <= self.end) + !(self.start <= self.last) } } @@ -335,10 +333,10 @@ impl RangeInclusive { impl RangeInclusive { /// Converts to an exclusive `Range` for `SliceIndex` implementations. - /// The caller is responsible for dealing with `end == usize::MAX`. + /// The caller is responsible for dealing with `last == usize::MAX`. #[inline] pub(crate) const fn into_slice_range(self) -> Range { - Range { start: self.start, end: self.end + 1 } + Range { start: self.start, end: self.last + 1 } } } @@ -348,7 +346,7 @@ impl RangeBounds for RangeInclusive { Included(&self.start) } fn end_bound(&self) -> Bound<&T> { - Included(&self.end) + Included(&self.last) } } @@ -364,7 +362,7 @@ impl RangeBounds for RangeInclusive<&T> { Included(self.start) } fn end_bound(&self) -> Bound<&T> { - Included(self.end) + Included(self.last) } } @@ -372,7 +370,7 @@ impl RangeBounds for RangeInclusive<&T> { #[unstable(feature = "new_range_api", issue = "125687")] impl IntoBounds for RangeInclusive { fn into_bounds(self) -> (Bound, Bound) { - (Included(self.start), Included(self.end)) + (Included(self.start), Included(self.last)) } } @@ -381,7 +379,7 @@ impl IntoBounds for RangeInclusive { impl const From> for legacy::RangeInclusive { #[inline] fn from(value: RangeInclusive) -> Self { - Self::new(value.start, value.end) + Self::new(value.start, value.last) } } #[unstable(feature = "new_range_api", issue = "125687")] @@ -394,8 +392,8 @@ impl const From> for RangeInclusive { "attempted to convert from an exhausted `legacy::RangeInclusive` (unspecified behavior)" ); - let (start, end) = value.into_inner(); - RangeInclusive { start, end } + let (start, last) = value.into_inner(); + RangeInclusive { start, last } } } @@ -544,3 +542,107 @@ impl const From> for RangeFrom { Self { start: value.start } } } + +/// A range only bounded inclusively above (`..=last`). +/// +/// The `RangeToInclusive` `..=last` contains all values with `x <= last`. +/// It cannot serve as an [`Iterator`] because it doesn't have a starting point. +/// +/// # Examples +/// +/// The `..=last` syntax is a `RangeToInclusive`: +/// +/// ``` +/// #![feature(new_range_api)] +/// #![feature(new_range)] +/// assert_eq!((..=5), std::range::RangeToInclusive{ last: 5 }); +/// ``` +/// +/// It does not have an [`IntoIterator`] implementation, so you can't use it in a +/// `for` loop directly. This won't compile: +/// +/// ```compile_fail,E0277 +/// // error[E0277]: the trait bound `std::range::RangeToInclusive<{integer}>: +/// // std::iter::Iterator` is not satisfied +/// for i in ..=5 { +/// // ... +/// } +/// ``` +/// +/// When used as a [slicing index], `RangeToInclusive` produces a slice of all +/// array elements up to and including the index indicated by `last`. +/// +/// ``` +/// let arr = [0, 1, 2, 3, 4]; +/// assert_eq!(arr[ .. ], [0, 1, 2, 3, 4]); +/// assert_eq!(arr[ .. 3], [0, 1, 2 ]); +/// assert_eq!(arr[ ..=3], [0, 1, 2, 3 ]); // This is a `RangeToInclusive` +/// assert_eq!(arr[1.. ], [ 1, 2, 3, 4]); +/// assert_eq!(arr[1.. 3], [ 1, 2 ]); +/// assert_eq!(arr[1..=3], [ 1, 2, 3 ]); +/// ``` +/// +/// [slicing index]: crate::slice::SliceIndex +#[lang = "RangeToInclusiveCopy"] +#[doc(alias = "..=")] +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[unstable(feature = "new_range_api", issue = "125687")] +pub struct RangeToInclusive { + /// The upper bound of the range (inclusive) + #[unstable(feature = "new_range_api", issue = "125687")] + pub last: Idx, +} + +#[unstable(feature = "new_range_api", issue = "125687")] +impl fmt::Debug for RangeToInclusive { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(fmt, "..=")?; + self.last.fmt(fmt)?; + Ok(()) + } +} + +impl> RangeToInclusive { + /// Returns `true` if `item` is contained in the range. + /// + /// # Examples + /// + /// ``` + /// assert!( (..=5).contains(&-1_000_000_000)); + /// assert!( (..=5).contains(&5)); + /// assert!(!(..=5).contains(&6)); + /// + /// assert!( (..=1.0).contains(&1.0)); + /// assert!(!(..=1.0).contains(&f32::NAN)); + /// assert!(!(..=f32::NAN).contains(&0.5)); + /// ``` + #[inline] + #[unstable(feature = "new_range_api", issue = "125687")] + pub fn contains(&self, item: &U) -> bool + where + Idx: PartialOrd, + U: ?Sized + PartialOrd, + { + >::contains(self, item) + } +} + +// RangeToInclusive cannot impl From> +// because underflow would be possible with (..0).into() + +#[unstable(feature = "new_range_api", issue = "125687")] +impl RangeBounds for RangeToInclusive { + fn start_bound(&self) -> Bound<&T> { + Unbounded + } + fn end_bound(&self) -> Bound<&T> { + Included(&self.last) + } +} + +#[unstable(feature = "range_into_bounds", issue = "136903")] +impl IntoBounds for RangeToInclusive { + fn into_bounds(self) -> (Bound, Bound) { + (Unbounded, Included(self.last)) + } +} diff --git a/library/core/src/range/iter.rs b/library/core/src/range/iter.rs index 1e261d8c1d93..24efd4a204a5 100644 --- a/library/core/src/range/iter.rs +++ b/library/core/src/range/iter.rs @@ -164,7 +164,7 @@ impl IterRangeInclusive { return None; } - Some(RangeInclusive { start: self.0.start, end: self.0.end }) + Some(RangeInclusive { start: self.0.start, last: self.0.end }) } } diff --git a/library/core/src/range/legacy.rs b/library/core/src/range/legacy.rs index 6723c4903f75..aa11331382dd 100644 --- a/library/core/src/range/legacy.rs +++ b/library/core/src/range/legacy.rs @@ -1,10 +1,10 @@ //! # Legacy range types //! //! The types within this module will be replaced by the types -//! [`Range`], [`RangeInclusive`], and [`RangeFrom`] in the parent +//! [`Range`], [`RangeInclusive`], [`RangeToInclusive`], and [`RangeFrom`] in the parent //! module, [`core::range`]. //! //! The types here are equivalent to those in [`core::ops`]. #[doc(inline)] -pub use crate::ops::{Range, RangeFrom, RangeInclusive}; +pub use crate::ops::{Range, RangeFrom, RangeInclusive, RangeToInclusive}; diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index 8e1bc0bae70a..a8147d745f3a 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -129,6 +129,8 @@ mod private_slice_index { #[unstable(feature = "new_range_api", issue = "125687")] impl Sealed for range::RangeInclusive {} #[unstable(feature = "new_range_api", issue = "125687")] + impl Sealed for range::RangeToInclusive {} + #[unstable(feature = "new_range_api", issue = "125687")] impl Sealed for range::RangeFrom {} impl Sealed for ops::IndexRange {} @@ -788,6 +790,45 @@ unsafe impl const SliceIndex<[T]> for ops::RangeToInclusive { } } +/// The methods `index` and `index_mut` panic if the end of the range is out of bounds. +#[stable(feature = "inclusive_range", since = "1.26.0")] +#[rustc_const_unstable(feature = "const_index", issue = "143775")] +unsafe impl const SliceIndex<[T]> for range::RangeToInclusive { + type Output = [T]; + + #[inline] + fn get(self, slice: &[T]) -> Option<&[T]> { + (0..=self.last).get(slice) + } + + #[inline] + fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> { + (0..=self.last).get_mut(slice) + } + + #[inline] + unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] { + // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. + unsafe { (0..=self.last).get_unchecked(slice) } + } + + #[inline] + unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] { + // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. + unsafe { (0..=self.last).get_unchecked_mut(slice) } + } + + #[inline] + fn index(self, slice: &[T]) -> &[T] { + (0..=self.last).index(slice) + } + + #[inline] + fn index_mut(self, slice: &mut [T]) -> &mut [T] { + (0..=self.last).index_mut(slice) + } +} + /// Performs bounds checking of a range. /// /// This method is similar to [`Index::index`] for slices, but it returns a diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs index 4f228edf78e4..5adae62b7e65 100644 --- a/library/core/src/str/traits.rs +++ b/library/core/src/str/traits.rs @@ -677,11 +677,11 @@ unsafe impl const SliceIndex for range::RangeInclusive { type Output = str; #[inline] fn get(self, slice: &str) -> Option<&Self::Output> { - if self.end == usize::MAX { None } else { self.into_slice_range().get(slice) } + if self.last == usize::MAX { None } else { self.into_slice_range().get(slice) } } #[inline] fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> { - if self.end == usize::MAX { None } else { self.into_slice_range().get_mut(slice) } + if self.last == usize::MAX { None } else { self.into_slice_range().get_mut(slice) } } #[inline] unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output { @@ -695,14 +695,14 @@ unsafe impl const SliceIndex for range::RangeInclusive { } #[inline] fn index(self, slice: &str) -> &Self::Output { - if self.end == usize::MAX { + if self.last == usize::MAX { str_index_overflow_fail(); } self.into_slice_range().index(slice) } #[inline] fn index_mut(self, slice: &mut str) -> &mut Self::Output { - if self.end == usize::MAX { + if self.last == usize::MAX { str_index_overflow_fail(); } self.into_slice_range().index_mut(slice) diff --git a/library/core/src/unicode/unicode_data.rs b/library/core/src/unicode/unicode_data.rs index 0bf2f948e85b..2f53de183f62 100644 --- a/library/core/src/unicode/unicode_data.rs +++ b/library/core/src/unicode/unicode_data.rs @@ -1,16 +1,15 @@ //! This file is generated by `./x run src/tools/unicode-table-generator`; do not edit manually! -// Alphabetic : 1727 bytes, 142759 codepoints in 757 ranges (U+000041 - U+0323B0) using skiplist -// Case_Ignorable : 1053 bytes, 2749 codepoints in 452 ranges (U+000027 - U+0E01F0) using skiplist -// Cased : 407 bytes, 4578 codepoints in 159 ranges (U+000041 - U+01F18A) using skiplist -// Cc : 9 bytes, 65 codepoints in 2 ranges (U+000000 - U+0000A0) using skiplist +// Alphabetic : 1723 bytes, 142707 codepoints in 755 ranges (U+0000AA - U+0323B0) using skiplist +// Case_Ignorable : 1043 bytes, 2744 codepoints in 447 ranges (U+0000A8 - U+0E01F0) using skiplist +// Cased : 403 bytes, 4526 codepoints in 157 ranges (U+0000AA - U+01F18A) using skiplist // Grapheme_Extend : 887 bytes, 2193 codepoints in 375 ranges (U+000300 - U+0E01F0) using skiplist -// Lowercase : 935 bytes, 2569 codepoints in 675 ranges (U+000061 - U+01E944) using bitset -// N : 457 bytes, 1911 codepoints in 144 ranges (U+000030 - U+01FBFA) using skiplist -// Uppercase : 799 bytes, 1978 codepoints in 656 ranges (U+000041 - U+01F18A) using bitset -// White_Space : 256 bytes, 25 codepoints in 10 ranges (U+000009 - U+003001) using cascading +// Lowercase : 933 bytes, 2543 codepoints in 674 ranges (U+0000AA - U+01E944) using bitset +// N : 455 bytes, 1901 codepoints in 143 ranges (U+0000B2 - U+01FBFA) using skiplist +// Uppercase : 797 bytes, 1952 codepoints in 655 ranges (U+0000C0 - U+01F18A) using bitset +// White_Space : 256 bytes, 19 codepoints in 8 ranges (U+000085 - U+003001) using cascading // to_lower : 11484 bytes // to_upper : 13432 bytes -// Total : 31446 bytes +// Total : 31413 bytes #[inline(always)] const fn bitset_search< @@ -148,93 +147,100 @@ pub mod alphabetic { use super::ShortOffsetRunHeader; static SHORT_OFFSET_RUNS: [ShortOffsetRunHeader; 53] = [ - ShortOffsetRunHeader::new(0, 706), ShortOffsetRunHeader::new(16, 4681), - ShortOffsetRunHeader::new(418, 5741), ShortOffsetRunHeader::new(456, 7958), - ShortOffsetRunHeader::new(556, 9398), ShortOffsetRunHeader::new(627, 11264), - ShortOffsetRunHeader::new(629, 12293), ShortOffsetRunHeader::new(667, 13312), - ShortOffsetRunHeader::new(691, 19904), ShortOffsetRunHeader::new(692, 42125), - ShortOffsetRunHeader::new(694, 42509), ShortOffsetRunHeader::new(698, 55204), - ShortOffsetRunHeader::new(788, 63744), ShortOffsetRunHeader::new(793, 64110), - ShortOffsetRunHeader::new(794, 64830), ShortOffsetRunHeader::new(816, 66176), - ShortOffsetRunHeader::new(857, 67383), ShortOffsetRunHeader::new(904, 73440), - ShortOffsetRunHeader::new(1221, 74650), ShortOffsetRunHeader::new(1232, 77712), - ShortOffsetRunHeader::new(1237, 78896), ShortOffsetRunHeader::new(1240, 82939), - ShortOffsetRunHeader::new(1244, 83527), ShortOffsetRunHeader::new(1246, 90368), - ShortOffsetRunHeader::new(1247, 92160), ShortOffsetRunHeader::new(1249, 92729), - ShortOffsetRunHeader::new(1250, 93504), ShortOffsetRunHeader::new(1265, 100344), - ShortOffsetRunHeader::new(1282, 101590), ShortOffsetRunHeader::new(1284, 110576), - ShortOffsetRunHeader::new(1287, 110883), ShortOffsetRunHeader::new(1294, 111356), - ShortOffsetRunHeader::new(1304, 113664), ShortOffsetRunHeader::new(1305, 119808), - ShortOffsetRunHeader::new(1315, 120486), ShortOffsetRunHeader::new(1352, 122624), - ShortOffsetRunHeader::new(1375, 123536), ShortOffsetRunHeader::new(1399, 124112), - ShortOffsetRunHeader::new(1403, 124896), ShortOffsetRunHeader::new(1409, 126464), - ShortOffsetRunHeader::new(1425, 127280), ShortOffsetRunHeader::new(1491, 131072), - ShortOffsetRunHeader::new(1497, 173792), ShortOffsetRunHeader::new(1498, 177978), - ShortOffsetRunHeader::new(1500, 183970), ShortOffsetRunHeader::new(1504, 191457), - ShortOffsetRunHeader::new(1506, 192094), ShortOffsetRunHeader::new(1508, 194560), - ShortOffsetRunHeader::new(1509, 195102), ShortOffsetRunHeader::new(1510, 196608), - ShortOffsetRunHeader::new(1511, 201547), ShortOffsetRunHeader::new(1512, 205744), - ShortOffsetRunHeader::new(1514, 1319856), + ShortOffsetRunHeader::new(0, 706), ShortOffsetRunHeader::new(12, 4681), + ShortOffsetRunHeader::new(414, 5741), ShortOffsetRunHeader::new(452, 7958), + ShortOffsetRunHeader::new(552, 9398), ShortOffsetRunHeader::new(623, 11264), + ShortOffsetRunHeader::new(625, 12293), ShortOffsetRunHeader::new(663, 13312), + ShortOffsetRunHeader::new(687, 19904), ShortOffsetRunHeader::new(688, 42125), + ShortOffsetRunHeader::new(690, 42509), ShortOffsetRunHeader::new(694, 55204), + ShortOffsetRunHeader::new(784, 63744), ShortOffsetRunHeader::new(789, 64110), + ShortOffsetRunHeader::new(790, 64830), ShortOffsetRunHeader::new(812, 66176), + ShortOffsetRunHeader::new(853, 67383), ShortOffsetRunHeader::new(900, 73440), + ShortOffsetRunHeader::new(1217, 74650), ShortOffsetRunHeader::new(1228, 77712), + ShortOffsetRunHeader::new(1233, 78896), ShortOffsetRunHeader::new(1236, 82939), + ShortOffsetRunHeader::new(1240, 83527), ShortOffsetRunHeader::new(1242, 90368), + ShortOffsetRunHeader::new(1243, 92160), ShortOffsetRunHeader::new(1245, 92729), + ShortOffsetRunHeader::new(1246, 93504), ShortOffsetRunHeader::new(1261, 100344), + ShortOffsetRunHeader::new(1278, 101590), ShortOffsetRunHeader::new(1280, 110576), + ShortOffsetRunHeader::new(1283, 110883), ShortOffsetRunHeader::new(1290, 111356), + ShortOffsetRunHeader::new(1300, 113664), ShortOffsetRunHeader::new(1301, 119808), + ShortOffsetRunHeader::new(1311, 120486), ShortOffsetRunHeader::new(1348, 122624), + ShortOffsetRunHeader::new(1371, 123536), ShortOffsetRunHeader::new(1395, 124112), + ShortOffsetRunHeader::new(1399, 124896), ShortOffsetRunHeader::new(1405, 126464), + ShortOffsetRunHeader::new(1421, 127280), ShortOffsetRunHeader::new(1487, 131072), + ShortOffsetRunHeader::new(1493, 173792), ShortOffsetRunHeader::new(1494, 177978), + ShortOffsetRunHeader::new(1496, 183970), ShortOffsetRunHeader::new(1500, 191457), + ShortOffsetRunHeader::new(1502, 192094), ShortOffsetRunHeader::new(1504, 194560), + ShortOffsetRunHeader::new(1505, 195102), ShortOffsetRunHeader::new(1506, 196608), + ShortOffsetRunHeader::new(1507, 201547), ShortOffsetRunHeader::new(1508, 205744), + ShortOffsetRunHeader::new(1510, 1319856), ]; - static OFFSETS: [u8; 1515] = [ - 65, 26, 6, 26, 47, 1, 10, 1, 4, 1, 5, 23, 1, 31, 1, 0, 4, 12, 14, 5, 7, 1, 1, 1, 86, 1, 29, - 18, 1, 2, 2, 4, 1, 1, 6, 1, 1, 3, 1, 1, 1, 20, 1, 83, 1, 139, 8, 166, 1, 38, 2, 1, 6, 41, - 39, 14, 1, 1, 1, 2, 1, 2, 1, 1, 8, 27, 4, 4, 29, 11, 5, 56, 1, 7, 14, 102, 1, 8, 4, 8, 4, 3, - 10, 3, 2, 1, 16, 48, 13, 101, 24, 33, 9, 2, 4, 1, 5, 24, 2, 19, 19, 25, 7, 11, 5, 24, 1, 6, - 8, 1, 8, 42, 10, 12, 3, 7, 6, 76, 1, 16, 1, 3, 4, 15, 13, 19, 1, 8, 2, 2, 2, 22, 1, 7, 1, 1, - 3, 4, 3, 8, 2, 2, 2, 2, 1, 1, 8, 1, 4, 2, 1, 5, 12, 2, 10, 1, 4, 3, 1, 6, 4, 2, 2, 22, 1, 7, - 1, 2, 1, 2, 1, 2, 4, 5, 4, 2, 2, 2, 4, 1, 7, 4, 1, 1, 17, 6, 11, 3, 1, 9, 1, 3, 1, 22, 1, 7, - 1, 2, 1, 5, 3, 9, 1, 3, 1, 2, 3, 1, 15, 4, 21, 4, 4, 3, 1, 8, 2, 2, 2, 22, 1, 7, 1, 2, 1, 5, - 3, 8, 2, 2, 2, 2, 9, 2, 4, 2, 1, 5, 13, 1, 16, 2, 1, 6, 3, 3, 1, 4, 3, 2, 1, 1, 1, 2, 3, 2, - 3, 3, 3, 12, 4, 5, 3, 3, 1, 3, 3, 1, 6, 1, 40, 13, 1, 3, 1, 23, 1, 16, 3, 8, 1, 3, 1, 3, 8, - 2, 1, 3, 2, 1, 2, 4, 28, 4, 1, 8, 1, 3, 1, 23, 1, 10, 1, 5, 3, 8, 1, 3, 1, 3, 8, 2, 6, 2, 1, - 4, 13, 3, 12, 13, 1, 3, 1, 41, 2, 8, 1, 3, 1, 3, 1, 1, 5, 4, 7, 5, 22, 6, 1, 3, 1, 18, 3, - 24, 1, 9, 1, 1, 2, 7, 8, 6, 1, 1, 1, 8, 18, 2, 13, 58, 5, 7, 6, 1, 51, 2, 1, 1, 1, 5, 1, 24, - 1, 1, 1, 19, 1, 3, 2, 5, 1, 1, 6, 1, 14, 4, 32, 1, 63, 8, 1, 36, 4, 19, 4, 16, 1, 36, 67, - 55, 1, 1, 2, 5, 16, 64, 10, 4, 2, 38, 1, 1, 5, 1, 2, 43, 1, 0, 1, 4, 2, 7, 1, 1, 1, 4, 2, - 41, 1, 4, 2, 33, 1, 4, 2, 7, 1, 1, 1, 4, 2, 15, 1, 57, 1, 4, 2, 67, 37, 16, 16, 86, 2, 6, 3, - 0, 2, 17, 1, 26, 5, 75, 3, 11, 7, 20, 11, 21, 12, 20, 12, 13, 1, 3, 1, 2, 12, 52, 2, 19, 14, - 1, 4, 1, 67, 89, 7, 43, 5, 70, 10, 31, 1, 12, 4, 9, 23, 30, 2, 5, 11, 44, 4, 26, 54, 28, 4, - 63, 2, 20, 50, 1, 23, 2, 11, 3, 49, 52, 1, 15, 1, 8, 51, 42, 2, 4, 10, 44, 1, 11, 14, 55, - 22, 3, 10, 36, 2, 11, 5, 43, 2, 3, 41, 4, 1, 6, 1, 2, 3, 1, 5, 192, 19, 34, 11, 0, 2, 6, 2, - 38, 2, 6, 2, 8, 1, 1, 1, 1, 1, 1, 1, 31, 2, 53, 1, 7, 1, 1, 3, 3, 1, 7, 3, 4, 2, 6, 4, 13, - 5, 3, 1, 7, 116, 1, 13, 1, 16, 13, 101, 1, 4, 1, 2, 10, 1, 1, 3, 5, 6, 1, 1, 1, 1, 1, 1, 4, - 1, 11, 2, 4, 5, 5, 4, 1, 17, 41, 0, 52, 0, 229, 6, 4, 3, 2, 12, 38, 1, 1, 5, 1, 2, 56, 7, 1, - 16, 23, 9, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 32, 47, 1, 0, 3, 25, 9, 7, 5, 2, - 5, 4, 86, 6, 3, 1, 90, 1, 4, 5, 43, 1, 94, 17, 32, 48, 16, 0, 0, 64, 0, 67, 46, 2, 0, 3, 16, - 10, 2, 20, 47, 5, 8, 3, 113, 39, 9, 2, 103, 2, 67, 2, 2, 1, 1, 1, 8, 21, 20, 1, 33, 24, 52, - 12, 68, 1, 1, 44, 6, 3, 1, 1, 3, 10, 33, 5, 35, 13, 29, 3, 51, 1, 12, 15, 1, 16, 16, 10, 5, - 1, 55, 9, 14, 18, 23, 3, 69, 1, 1, 1, 1, 24, 3, 2, 16, 2, 4, 11, 6, 2, 6, 2, 6, 9, 7, 1, 7, - 1, 43, 1, 14, 6, 123, 21, 0, 12, 23, 4, 49, 0, 0, 2, 106, 38, 7, 12, 5, 5, 12, 1, 13, 1, 5, - 1, 1, 1, 2, 1, 2, 1, 108, 33, 0, 18, 64, 2, 54, 40, 12, 116, 5, 1, 135, 36, 26, 6, 26, 11, - 89, 3, 6, 2, 6, 2, 6, 2, 3, 35, 12, 1, 26, 1, 19, 1, 2, 1, 15, 2, 14, 34, 123, 69, 53, 0, - 29, 3, 49, 47, 32, 13, 30, 5, 43, 5, 30, 2, 36, 4, 8, 1, 5, 42, 158, 18, 36, 4, 36, 4, 40, - 8, 52, 12, 11, 1, 15, 1, 7, 1, 2, 1, 11, 1, 15, 1, 7, 1, 2, 3, 52, 12, 0, 9, 22, 10, 8, 24, - 6, 1, 42, 1, 9, 69, 6, 2, 1, 1, 44, 1, 2, 3, 1, 2, 23, 10, 23, 9, 31, 65, 19, 1, 2, 10, 22, - 10, 26, 70, 56, 6, 2, 64, 4, 1, 2, 5, 8, 1, 3, 1, 29, 42, 29, 3, 29, 35, 8, 1, 28, 27, 54, - 10, 22, 10, 19, 13, 18, 110, 73, 55, 51, 13, 51, 13, 40, 34, 28, 3, 1, 5, 23, 250, 42, 1, 2, - 3, 2, 16, 3, 55, 1, 3, 29, 10, 1, 8, 22, 42, 18, 46, 21, 27, 23, 9, 70, 43, 5, 10, 57, 9, 1, - 13, 25, 23, 51, 17, 4, 8, 35, 3, 1, 9, 64, 1, 4, 9, 2, 10, 1, 1, 1, 35, 18, 1, 34, 2, 1, 6, - 4, 62, 7, 1, 1, 1, 4, 1, 15, 1, 10, 7, 57, 23, 4, 1, 8, 2, 2, 2, 22, 1, 7, 1, 2, 1, 5, 3, 8, - 2, 2, 2, 2, 3, 1, 6, 1, 5, 7, 28, 10, 1, 1, 2, 1, 1, 38, 1, 10, 1, 1, 2, 1, 1, 4, 1, 2, 3, - 1, 1, 1, 44, 66, 1, 3, 1, 4, 20, 3, 30, 66, 2, 2, 1, 1, 184, 54, 2, 7, 25, 6, 34, 63, 1, 1, - 3, 1, 59, 54, 2, 1, 71, 27, 2, 14, 21, 7, 185, 57, 103, 64, 31, 8, 2, 1, 2, 8, 1, 2, 1, 30, - 1, 2, 2, 2, 2, 4, 93, 8, 2, 46, 2, 6, 1, 1, 1, 2, 27, 51, 2, 10, 17, 72, 5, 1, 18, 73, 199, - 33, 31, 9, 1, 45, 1, 7, 1, 1, 49, 30, 2, 22, 1, 14, 73, 7, 1, 2, 1, 44, 3, 1, 1, 2, 1, 3, 1, - 1, 2, 2, 24, 6, 1, 2, 1, 37, 1, 2, 1, 4, 1, 1, 0, 23, 9, 17, 1, 41, 3, 3, 111, 1, 79, 0, - 102, 111, 17, 196, 0, 97, 15, 0, 17, 6, 25, 0, 5, 0, 0, 47, 0, 0, 7, 31, 17, 79, 17, 30, 18, - 48, 16, 4, 31, 21, 5, 19, 0, 45, 211, 64, 128, 75, 4, 57, 7, 17, 64, 2, 1, 1, 12, 2, 14, 0, - 8, 0, 41, 10, 0, 4, 1, 7, 1, 2, 1, 0, 15, 1, 29, 3, 2, 1, 14, 4, 8, 0, 0, 107, 5, 13, 3, 9, - 7, 10, 4, 1, 0, 85, 1, 71, 1, 2, 2, 1, 2, 2, 2, 4, 1, 12, 1, 1, 1, 7, 1, 65, 1, 4, 2, 8, 1, - 7, 1, 28, 1, 4, 1, 5, 1, 1, 3, 7, 1, 0, 2, 25, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, - 25, 1, 31, 1, 25, 1, 8, 0, 31, 6, 6, 213, 7, 1, 17, 2, 7, 1, 2, 1, 5, 5, 62, 33, 1, 112, 45, - 10, 7, 16, 1, 0, 30, 18, 44, 0, 28, 228, 30, 2, 1, 0, 7, 1, 4, 1, 2, 1, 15, 1, 197, 59, 68, - 3, 1, 3, 1, 0, 4, 1, 27, 1, 2, 1, 1, 2, 1, 1, 10, 1, 4, 1, 1, 1, 1, 6, 1, 4, 1, 1, 1, 1, 1, - 1, 3, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 4, 1, 7, 1, 4, 1, 4, 1, 1, 1, - 10, 1, 17, 5, 3, 1, 5, 1, 17, 0, 26, 6, 26, 6, 26, 0, 0, 32, 0, 6, 222, 2, 0, 14, 0, 15, 0, - 0, 0, 0, 0, 5, 0, 0, + static OFFSETS: [u8; 1511] = [ + 170, 1, 10, 1, 4, 1, 5, 23, 1, 31, 1, 0, 4, 12, 14, 5, 7, 1, 1, 1, 86, 1, 29, 18, 1, 2, 2, + 4, 1, 1, 6, 1, 1, 3, 1, 1, 1, 20, 1, 83, 1, 139, 8, 166, 1, 38, 2, 1, 6, 41, 39, 14, 1, 1, + 1, 2, 1, 2, 1, 1, 8, 27, 4, 4, 29, 11, 5, 56, 1, 7, 14, 102, 1, 8, 4, 8, 4, 3, 10, 3, 2, 1, + 16, 48, 13, 101, 24, 33, 9, 2, 4, 1, 5, 24, 2, 19, 19, 25, 7, 11, 5, 24, 1, 6, 8, 1, 8, 42, + 10, 12, 3, 7, 6, 76, 1, 16, 1, 3, 4, 15, 13, 19, 1, 8, 2, 2, 2, 22, 1, 7, 1, 1, 3, 4, 3, 8, + 2, 2, 2, 2, 1, 1, 8, 1, 4, 2, 1, 5, 12, 2, 10, 1, 4, 3, 1, 6, 4, 2, 2, 22, 1, 7, 1, 2, 1, 2, + 1, 2, 4, 5, 4, 2, 2, 2, 4, 1, 7, 4, 1, 1, 17, 6, 11, 3, 1, 9, 1, 3, 1, 22, 1, 7, 1, 2, 1, 5, + 3, 9, 1, 3, 1, 2, 3, 1, 15, 4, 21, 4, 4, 3, 1, 8, 2, 2, 2, 22, 1, 7, 1, 2, 1, 5, 3, 8, 2, 2, + 2, 2, 9, 2, 4, 2, 1, 5, 13, 1, 16, 2, 1, 6, 3, 3, 1, 4, 3, 2, 1, 1, 1, 2, 3, 2, 3, 3, 3, 12, + 4, 5, 3, 3, 1, 3, 3, 1, 6, 1, 40, 13, 1, 3, 1, 23, 1, 16, 3, 8, 1, 3, 1, 3, 8, 2, 1, 3, 2, + 1, 2, 4, 28, 4, 1, 8, 1, 3, 1, 23, 1, 10, 1, 5, 3, 8, 1, 3, 1, 3, 8, 2, 6, 2, 1, 4, 13, 3, + 12, 13, 1, 3, 1, 41, 2, 8, 1, 3, 1, 3, 1, 1, 5, 4, 7, 5, 22, 6, 1, 3, 1, 18, 3, 24, 1, 9, 1, + 1, 2, 7, 8, 6, 1, 1, 1, 8, 18, 2, 13, 58, 5, 7, 6, 1, 51, 2, 1, 1, 1, 5, 1, 24, 1, 1, 1, 19, + 1, 3, 2, 5, 1, 1, 6, 1, 14, 4, 32, 1, 63, 8, 1, 36, 4, 19, 4, 16, 1, 36, 67, 55, 1, 1, 2, 5, + 16, 64, 10, 4, 2, 38, 1, 1, 5, 1, 2, 43, 1, 0, 1, 4, 2, 7, 1, 1, 1, 4, 2, 41, 1, 4, 2, 33, + 1, 4, 2, 7, 1, 1, 1, 4, 2, 15, 1, 57, 1, 4, 2, 67, 37, 16, 16, 86, 2, 6, 3, 0, 2, 17, 1, 26, + 5, 75, 3, 11, 7, 20, 11, 21, 12, 20, 12, 13, 1, 3, 1, 2, 12, 52, 2, 19, 14, 1, 4, 1, 67, 89, + 7, 43, 5, 70, 10, 31, 1, 12, 4, 9, 23, 30, 2, 5, 11, 44, 4, 26, 54, 28, 4, 63, 2, 20, 50, 1, + 23, 2, 11, 3, 49, 52, 1, 15, 1, 8, 51, 42, 2, 4, 10, 44, 1, 11, 14, 55, 22, 3, 10, 36, 2, + 11, 5, 43, 2, 3, 41, 4, 1, 6, 1, 2, 3, 1, 5, 192, 19, 34, 11, 0, 2, 6, 2, 38, 2, 6, 2, 8, 1, + 1, 1, 1, 1, 1, 1, 31, 2, 53, 1, 7, 1, 1, 3, 3, 1, 7, 3, 4, 2, 6, 4, 13, 5, 3, 1, 7, 116, 1, + 13, 1, 16, 13, 101, 1, 4, 1, 2, 10, 1, 1, 3, 5, 6, 1, 1, 1, 1, 1, 1, 4, 1, 11, 2, 4, 5, 5, + 4, 1, 17, 41, 0, 52, 0, 229, 6, 4, 3, 2, 12, 38, 1, 1, 5, 1, 2, 56, 7, 1, 16, 23, 9, 7, 1, + 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 32, 47, 1, 0, 3, 25, 9, 7, 5, 2, 5, 4, 86, 6, 3, + 1, 90, 1, 4, 5, 43, 1, 94, 17, 32, 48, 16, 0, 0, 64, 0, 67, 46, 2, 0, 3, 16, 10, 2, 20, 47, + 5, 8, 3, 113, 39, 9, 2, 103, 2, 67, 2, 2, 1, 1, 1, 8, 21, 20, 1, 33, 24, 52, 12, 68, 1, 1, + 44, 6, 3, 1, 1, 3, 10, 33, 5, 35, 13, 29, 3, 51, 1, 12, 15, 1, 16, 16, 10, 5, 1, 55, 9, 14, + 18, 23, 3, 69, 1, 1, 1, 1, 24, 3, 2, 16, 2, 4, 11, 6, 2, 6, 2, 6, 9, 7, 1, 7, 1, 43, 1, 14, + 6, 123, 21, 0, 12, 23, 4, 49, 0, 0, 2, 106, 38, 7, 12, 5, 5, 12, 1, 13, 1, 5, 1, 1, 1, 2, 1, + 2, 1, 108, 33, 0, 18, 64, 2, 54, 40, 12, 116, 5, 1, 135, 36, 26, 6, 26, 11, 89, 3, 6, 2, 6, + 2, 6, 2, 3, 35, 12, 1, 26, 1, 19, 1, 2, 1, 15, 2, 14, 34, 123, 69, 53, 0, 29, 3, 49, 47, 32, + 13, 30, 5, 43, 5, 30, 2, 36, 4, 8, 1, 5, 42, 158, 18, 36, 4, 36, 4, 40, 8, 52, 12, 11, 1, + 15, 1, 7, 1, 2, 1, 11, 1, 15, 1, 7, 1, 2, 3, 52, 12, 0, 9, 22, 10, 8, 24, 6, 1, 42, 1, 9, + 69, 6, 2, 1, 1, 44, 1, 2, 3, 1, 2, 23, 10, 23, 9, 31, 65, 19, 1, 2, 10, 22, 10, 26, 70, 56, + 6, 2, 64, 4, 1, 2, 5, 8, 1, 3, 1, 29, 42, 29, 3, 29, 35, 8, 1, 28, 27, 54, 10, 22, 10, 19, + 13, 18, 110, 73, 55, 51, 13, 51, 13, 40, 34, 28, 3, 1, 5, 23, 250, 42, 1, 2, 3, 2, 16, 3, + 55, 1, 3, 29, 10, 1, 8, 22, 42, 18, 46, 21, 27, 23, 9, 70, 43, 5, 10, 57, 9, 1, 13, 25, 23, + 51, 17, 4, 8, 35, 3, 1, 9, 64, 1, 4, 9, 2, 10, 1, 1, 1, 35, 18, 1, 34, 2, 1, 6, 4, 62, 7, 1, + 1, 1, 4, 1, 15, 1, 10, 7, 57, 23, 4, 1, 8, 2, 2, 2, 22, 1, 7, 1, 2, 1, 5, 3, 8, 2, 2, 2, 2, + 3, 1, 6, 1, 5, 7, 28, 10, 1, 1, 2, 1, 1, 38, 1, 10, 1, 1, 2, 1, 1, 4, 1, 2, 3, 1, 1, 1, 44, + 66, 1, 3, 1, 4, 20, 3, 30, 66, 2, 2, 1, 1, 184, 54, 2, 7, 25, 6, 34, 63, 1, 1, 3, 1, 59, 54, + 2, 1, 71, 27, 2, 14, 21, 7, 185, 57, 103, 64, 31, 8, 2, 1, 2, 8, 1, 2, 1, 30, 1, 2, 2, 2, 2, + 4, 93, 8, 2, 46, 2, 6, 1, 1, 1, 2, 27, 51, 2, 10, 17, 72, 5, 1, 18, 73, 199, 33, 31, 9, 1, + 45, 1, 7, 1, 1, 49, 30, 2, 22, 1, 14, 73, 7, 1, 2, 1, 44, 3, 1, 1, 2, 1, 3, 1, 1, 2, 2, 24, + 6, 1, 2, 1, 37, 1, 2, 1, 4, 1, 1, 0, 23, 9, 17, 1, 41, 3, 3, 111, 1, 79, 0, 102, 111, 17, + 196, 0, 97, 15, 0, 17, 6, 25, 0, 5, 0, 0, 47, 0, 0, 7, 31, 17, 79, 17, 30, 18, 48, 16, 4, + 31, 21, 5, 19, 0, 45, 211, 64, 128, 75, 4, 57, 7, 17, 64, 2, 1, 1, 12, 2, 14, 0, 8, 0, 41, + 10, 0, 4, 1, 7, 1, 2, 1, 0, 15, 1, 29, 3, 2, 1, 14, 4, 8, 0, 0, 107, 5, 13, 3, 9, 7, 10, 4, + 1, 0, 85, 1, 71, 1, 2, 2, 1, 2, 2, 2, 4, 1, 12, 1, 1, 1, 7, 1, 65, 1, 4, 2, 8, 1, 7, 1, 28, + 1, 4, 1, 5, 1, 1, 3, 7, 1, 0, 2, 25, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, + 1, 25, 1, 8, 0, 31, 6, 6, 213, 7, 1, 17, 2, 7, 1, 2, 1, 5, 5, 62, 33, 1, 112, 45, 10, 7, 16, + 1, 0, 30, 18, 44, 0, 28, 228, 30, 2, 1, 0, 7, 1, 4, 1, 2, 1, 15, 1, 197, 59, 68, 3, 1, 3, 1, + 0, 4, 1, 27, 1, 2, 1, 1, 2, 1, 1, 10, 1, 4, 1, 1, 1, 1, 6, 1, 4, 1, 1, 1, 1, 1, 1, 3, 1, 2, + 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 4, 1, 7, 1, 4, 1, 4, 1, 1, 1, 10, 1, 17, + 5, 3, 1, 5, 1, 17, 0, 26, 6, 26, 6, 26, 0, 0, 32, 0, 6, 222, 2, 0, 14, 0, 15, 0, 0, 0, 0, 0, + 5, 0, 0, ]; + #[inline] pub fn lookup(c: char) -> bool { + debug_assert!(!c.is_ascii()); + (c as u32) >= 0xaa && lookup_slow(c) + } + + #[inline(never)] + fn lookup_slow(c: char) -> bool { const { assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > char::MAX as u32); let mut i = 0; @@ -254,62 +260,69 @@ pub mod case_ignorable { use super::ShortOffsetRunHeader; static SHORT_OFFSET_RUNS: [ShortOffsetRunHeader; 37] = [ - ShortOffsetRunHeader::new(0, 688), ShortOffsetRunHeader::new(21, 4957), - ShortOffsetRunHeader::new(273, 5906), ShortOffsetRunHeader::new(275, 8125), - ShortOffsetRunHeader::new(385, 11388), ShortOffsetRunHeader::new(419, 12293), - ShortOffsetRunHeader::new(431, 40981), ShortOffsetRunHeader::new(443, 42232), - ShortOffsetRunHeader::new(445, 42508), ShortOffsetRunHeader::new(447, 64286), - ShortOffsetRunHeader::new(543, 65024), ShortOffsetRunHeader::new(547, 66045), - ShortOffsetRunHeader::new(577, 67456), ShortOffsetRunHeader::new(583, 68097), - ShortOffsetRunHeader::new(589, 68900), ShortOffsetRunHeader::new(601, 69291), - ShortOffsetRunHeader::new(609, 71727), ShortOffsetRunHeader::new(733, 71995), - ShortOffsetRunHeader::new(737, 72752), ShortOffsetRunHeader::new(765, 73459), - ShortOffsetRunHeader::new(795, 78896), ShortOffsetRunHeader::new(807, 90398), - ShortOffsetRunHeader::new(811, 92912), ShortOffsetRunHeader::new(815, 93504), - ShortOffsetRunHeader::new(821, 94031), ShortOffsetRunHeader::new(825, 110576), - ShortOffsetRunHeader::new(833, 113821), ShortOffsetRunHeader::new(839, 118528), - ShortOffsetRunHeader::new(843, 119143), ShortOffsetRunHeader::new(847, 121344), - ShortOffsetRunHeader::new(857, 122880), ShortOffsetRunHeader::new(869, 123566), - ShortOffsetRunHeader::new(885, 124139), ShortOffsetRunHeader::new(889, 125136), - ShortOffsetRunHeader::new(893, 127995), ShortOffsetRunHeader::new(897, 917505), - ShortOffsetRunHeader::new(899, 2032112), + ShortOffsetRunHeader::new(0, 688), ShortOffsetRunHeader::new(11, 4957), + ShortOffsetRunHeader::new(263, 5906), ShortOffsetRunHeader::new(265, 8125), + ShortOffsetRunHeader::new(375, 11388), ShortOffsetRunHeader::new(409, 12293), + ShortOffsetRunHeader::new(421, 40981), ShortOffsetRunHeader::new(433, 42232), + ShortOffsetRunHeader::new(435, 42508), ShortOffsetRunHeader::new(437, 64286), + ShortOffsetRunHeader::new(533, 65024), ShortOffsetRunHeader::new(537, 66045), + ShortOffsetRunHeader::new(567, 67456), ShortOffsetRunHeader::new(573, 68097), + ShortOffsetRunHeader::new(579, 68900), ShortOffsetRunHeader::new(591, 69291), + ShortOffsetRunHeader::new(599, 71727), ShortOffsetRunHeader::new(723, 71995), + ShortOffsetRunHeader::new(727, 72752), ShortOffsetRunHeader::new(755, 73459), + ShortOffsetRunHeader::new(785, 78896), ShortOffsetRunHeader::new(797, 90398), + ShortOffsetRunHeader::new(801, 92912), ShortOffsetRunHeader::new(805, 93504), + ShortOffsetRunHeader::new(811, 94031), ShortOffsetRunHeader::new(815, 110576), + ShortOffsetRunHeader::new(823, 113821), ShortOffsetRunHeader::new(829, 118528), + ShortOffsetRunHeader::new(833, 119143), ShortOffsetRunHeader::new(837, 121344), + ShortOffsetRunHeader::new(847, 122880), ShortOffsetRunHeader::new(859, 123566), + ShortOffsetRunHeader::new(875, 124139), ShortOffsetRunHeader::new(879, 125136), + ShortOffsetRunHeader::new(883, 127995), ShortOffsetRunHeader::new(887, 917505), + ShortOffsetRunHeader::new(889, 2032112), ]; - static OFFSETS: [u8; 905] = [ - 39, 1, 6, 1, 11, 1, 35, 1, 1, 1, 71, 1, 4, 1, 1, 1, 4, 1, 2, 2, 0, 192, 4, 2, 4, 1, 9, 2, - 1, 1, 251, 7, 207, 1, 5, 1, 49, 45, 1, 1, 1, 2, 1, 2, 1, 1, 44, 1, 11, 6, 10, 11, 1, 1, 35, - 1, 10, 21, 16, 1, 101, 8, 1, 10, 1, 4, 33, 1, 1, 1, 30, 27, 91, 11, 58, 11, 4, 1, 2, 1, 24, - 24, 43, 3, 44, 1, 7, 2, 5, 9, 41, 58, 55, 1, 1, 1, 4, 8, 4, 1, 3, 7, 10, 2, 13, 1, 15, 1, - 58, 1, 4, 4, 8, 1, 20, 2, 26, 1, 2, 2, 57, 1, 4, 2, 4, 2, 2, 3, 3, 1, 30, 2, 3, 1, 11, 2, - 57, 1, 4, 5, 1, 2, 4, 1, 20, 2, 22, 6, 1, 1, 58, 1, 2, 1, 1, 4, 8, 1, 7, 2, 11, 2, 30, 1, - 61, 1, 12, 1, 50, 1, 3, 1, 55, 1, 1, 3, 5, 3, 1, 4, 7, 2, 11, 2, 29, 1, 58, 1, 2, 1, 6, 1, - 5, 2, 20, 2, 28, 2, 57, 2, 4, 4, 8, 1, 20, 2, 29, 1, 72, 1, 7, 3, 1, 1, 90, 1, 2, 7, 11, 9, - 98, 1, 2, 9, 9, 1, 1, 7, 73, 2, 27, 1, 1, 1, 1, 1, 55, 14, 1, 5, 1, 2, 5, 11, 1, 36, 9, 1, - 102, 4, 1, 6, 1, 2, 2, 2, 25, 2, 4, 3, 16, 4, 13, 1, 2, 2, 6, 1, 15, 1, 94, 1, 0, 3, 0, 3, - 29, 2, 30, 2, 30, 2, 64, 2, 1, 7, 8, 1, 2, 11, 3, 1, 5, 1, 45, 5, 51, 1, 65, 2, 34, 1, 118, - 3, 4, 2, 9, 1, 6, 3, 219, 2, 2, 1, 58, 1, 1, 7, 1, 1, 1, 1, 2, 8, 6, 10, 2, 1, 39, 1, 8, 31, - 49, 4, 48, 1, 1, 5, 1, 1, 5, 1, 40, 9, 12, 2, 32, 4, 2, 2, 1, 3, 56, 1, 1, 2, 3, 1, 1, 3, - 58, 8, 2, 2, 64, 6, 82, 3, 1, 13, 1, 7, 4, 1, 6, 1, 3, 2, 50, 63, 13, 1, 34, 101, 0, 1, 1, - 3, 11, 3, 13, 3, 13, 3, 13, 2, 12, 5, 8, 2, 10, 1, 2, 1, 2, 5, 49, 5, 1, 10, 1, 1, 13, 1, - 16, 13, 51, 33, 0, 2, 113, 3, 125, 1, 15, 1, 96, 32, 47, 1, 0, 1, 36, 4, 3, 5, 5, 1, 93, 6, - 93, 3, 0, 1, 0, 6, 0, 1, 98, 4, 1, 10, 1, 1, 28, 4, 80, 2, 14, 34, 78, 1, 23, 3, 103, 3, 3, - 2, 8, 1, 3, 1, 4, 1, 25, 2, 5, 1, 151, 2, 26, 18, 13, 1, 38, 8, 25, 11, 46, 3, 48, 1, 2, 4, - 2, 2, 17, 1, 21, 2, 66, 6, 2, 2, 2, 2, 12, 1, 8, 1, 35, 1, 11, 1, 51, 1, 1, 3, 2, 2, 5, 2, - 1, 1, 27, 1, 14, 2, 5, 2, 1, 1, 100, 5, 9, 3, 121, 1, 2, 1, 4, 1, 0, 1, 147, 17, 0, 16, 3, - 1, 12, 16, 34, 1, 2, 1, 169, 1, 7, 1, 6, 1, 11, 1, 35, 1, 1, 1, 47, 1, 45, 2, 67, 1, 21, 3, - 0, 1, 226, 1, 149, 5, 0, 6, 1, 42, 1, 9, 0, 3, 1, 2, 5, 4, 40, 3, 4, 1, 165, 2, 0, 4, 38, 1, - 26, 5, 1, 1, 0, 2, 79, 4, 70, 11, 49, 4, 123, 1, 54, 15, 41, 1, 2, 2, 10, 3, 49, 4, 2, 2, 2, - 1, 4, 1, 10, 1, 50, 3, 36, 5, 1, 8, 62, 1, 12, 2, 52, 9, 10, 4, 2, 1, 95, 3, 2, 1, 1, 2, 6, - 1, 2, 1, 157, 1, 3, 8, 21, 2, 57, 2, 3, 1, 37, 7, 3, 5, 70, 6, 13, 1, 1, 1, 1, 1, 14, 2, 85, - 8, 2, 3, 1, 1, 23, 1, 84, 6, 1, 1, 4, 2, 1, 2, 238, 4, 6, 2, 1, 2, 27, 2, 85, 8, 2, 1, 1, 2, - 106, 1, 1, 1, 2, 6, 1, 1, 101, 1, 1, 1, 2, 4, 1, 5, 0, 9, 1, 2, 0, 2, 1, 1, 4, 1, 144, 4, 2, - 2, 4, 1, 32, 10, 40, 6, 2, 4, 8, 1, 9, 6, 2, 3, 46, 13, 1, 2, 0, 7, 1, 6, 1, 1, 82, 22, 2, - 7, 1, 2, 1, 2, 122, 6, 3, 1, 1, 2, 1, 7, 1, 1, 72, 2, 3, 1, 1, 1, 0, 2, 11, 2, 52, 5, 5, 1, - 1, 1, 23, 1, 0, 17, 6, 15, 0, 12, 3, 3, 0, 5, 59, 7, 9, 4, 0, 3, 40, 2, 0, 1, 63, 17, 64, 2, - 1, 2, 0, 4, 1, 7, 1, 2, 0, 2, 1, 4, 0, 46, 2, 23, 0, 3, 9, 16, 2, 7, 30, 4, 148, 3, 0, 55, - 4, 50, 8, 1, 14, 1, 22, 5, 1, 15, 0, 7, 1, 17, 2, 7, 1, 2, 1, 5, 5, 62, 33, 1, 160, 14, 0, - 1, 61, 4, 0, 5, 254, 2, 0, 7, 109, 8, 0, 5, 0, 1, 30, 96, 128, 240, 0, + static OFFSETS: [u8; 895] = [ + 168, 1, 4, 1, 1, 1, 4, 1, 2, 2, 0, 192, 4, 2, 4, 1, 9, 2, 1, 1, 251, 7, 207, 1, 5, 1, 49, + 45, 1, 1, 1, 2, 1, 2, 1, 1, 44, 1, 11, 6, 10, 11, 1, 1, 35, 1, 10, 21, 16, 1, 101, 8, 1, 10, + 1, 4, 33, 1, 1, 1, 30, 27, 91, 11, 58, 11, 4, 1, 2, 1, 24, 24, 43, 3, 44, 1, 7, 2, 5, 9, 41, + 58, 55, 1, 1, 1, 4, 8, 4, 1, 3, 7, 10, 2, 13, 1, 15, 1, 58, 1, 4, 4, 8, 1, 20, 2, 26, 1, 2, + 2, 57, 1, 4, 2, 4, 2, 2, 3, 3, 1, 30, 2, 3, 1, 11, 2, 57, 1, 4, 5, 1, 2, 4, 1, 20, 2, 22, 6, + 1, 1, 58, 1, 2, 1, 1, 4, 8, 1, 7, 2, 11, 2, 30, 1, 61, 1, 12, 1, 50, 1, 3, 1, 55, 1, 1, 3, + 5, 3, 1, 4, 7, 2, 11, 2, 29, 1, 58, 1, 2, 1, 6, 1, 5, 2, 20, 2, 28, 2, 57, 2, 4, 4, 8, 1, + 20, 2, 29, 1, 72, 1, 7, 3, 1, 1, 90, 1, 2, 7, 11, 9, 98, 1, 2, 9, 9, 1, 1, 7, 73, 2, 27, 1, + 1, 1, 1, 1, 55, 14, 1, 5, 1, 2, 5, 11, 1, 36, 9, 1, 102, 4, 1, 6, 1, 2, 2, 2, 25, 2, 4, 3, + 16, 4, 13, 1, 2, 2, 6, 1, 15, 1, 94, 1, 0, 3, 0, 3, 29, 2, 30, 2, 30, 2, 64, 2, 1, 7, 8, 1, + 2, 11, 3, 1, 5, 1, 45, 5, 51, 1, 65, 2, 34, 1, 118, 3, 4, 2, 9, 1, 6, 3, 219, 2, 2, 1, 58, + 1, 1, 7, 1, 1, 1, 1, 2, 8, 6, 10, 2, 1, 39, 1, 8, 31, 49, 4, 48, 1, 1, 5, 1, 1, 5, 1, 40, 9, + 12, 2, 32, 4, 2, 2, 1, 3, 56, 1, 1, 2, 3, 1, 1, 3, 58, 8, 2, 2, 64, 6, 82, 3, 1, 13, 1, 7, + 4, 1, 6, 1, 3, 2, 50, 63, 13, 1, 34, 101, 0, 1, 1, 3, 11, 3, 13, 3, 13, 3, 13, 2, 12, 5, 8, + 2, 10, 1, 2, 1, 2, 5, 49, 5, 1, 10, 1, 1, 13, 1, 16, 13, 51, 33, 0, 2, 113, 3, 125, 1, 15, + 1, 96, 32, 47, 1, 0, 1, 36, 4, 3, 5, 5, 1, 93, 6, 93, 3, 0, 1, 0, 6, 0, 1, 98, 4, 1, 10, 1, + 1, 28, 4, 80, 2, 14, 34, 78, 1, 23, 3, 103, 3, 3, 2, 8, 1, 3, 1, 4, 1, 25, 2, 5, 1, 151, 2, + 26, 18, 13, 1, 38, 8, 25, 11, 46, 3, 48, 1, 2, 4, 2, 2, 17, 1, 21, 2, 66, 6, 2, 2, 2, 2, 12, + 1, 8, 1, 35, 1, 11, 1, 51, 1, 1, 3, 2, 2, 5, 2, 1, 1, 27, 1, 14, 2, 5, 2, 1, 1, 100, 5, 9, + 3, 121, 1, 2, 1, 4, 1, 0, 1, 147, 17, 0, 16, 3, 1, 12, 16, 34, 1, 2, 1, 169, 1, 7, 1, 6, 1, + 11, 1, 35, 1, 1, 1, 47, 1, 45, 2, 67, 1, 21, 3, 0, 1, 226, 1, 149, 5, 0, 6, 1, 42, 1, 9, 0, + 3, 1, 2, 5, 4, 40, 3, 4, 1, 165, 2, 0, 4, 38, 1, 26, 5, 1, 1, 0, 2, 79, 4, 70, 11, 49, 4, + 123, 1, 54, 15, 41, 1, 2, 2, 10, 3, 49, 4, 2, 2, 2, 1, 4, 1, 10, 1, 50, 3, 36, 5, 1, 8, 62, + 1, 12, 2, 52, 9, 10, 4, 2, 1, 95, 3, 2, 1, 1, 2, 6, 1, 2, 1, 157, 1, 3, 8, 21, 2, 57, 2, 3, + 1, 37, 7, 3, 5, 70, 6, 13, 1, 1, 1, 1, 1, 14, 2, 85, 8, 2, 3, 1, 1, 23, 1, 84, 6, 1, 1, 4, + 2, 1, 2, 238, 4, 6, 2, 1, 2, 27, 2, 85, 8, 2, 1, 1, 2, 106, 1, 1, 1, 2, 6, 1, 1, 101, 1, 1, + 1, 2, 4, 1, 5, 0, 9, 1, 2, 0, 2, 1, 1, 4, 1, 144, 4, 2, 2, 4, 1, 32, 10, 40, 6, 2, 4, 8, 1, + 9, 6, 2, 3, 46, 13, 1, 2, 0, 7, 1, 6, 1, 1, 82, 22, 2, 7, 1, 2, 1, 2, 122, 6, 3, 1, 1, 2, 1, + 7, 1, 1, 72, 2, 3, 1, 1, 1, 0, 2, 11, 2, 52, 5, 5, 1, 1, 1, 23, 1, 0, 17, 6, 15, 0, 12, 3, + 3, 0, 5, 59, 7, 9, 4, 0, 3, 40, 2, 0, 1, 63, 17, 64, 2, 1, 2, 0, 4, 1, 7, 1, 2, 0, 2, 1, 4, + 0, 46, 2, 23, 0, 3, 9, 16, 2, 7, 30, 4, 148, 3, 0, 55, 4, 50, 8, 1, 14, 1, 22, 5, 1, 15, 0, + 7, 1, 17, 2, 7, 1, 2, 1, 5, 5, 62, 33, 1, 160, 14, 0, 1, 61, 4, 0, 5, 254, 2, 0, 7, 109, 8, + 0, 5, 0, 1, 30, 96, 128, 240, 0, ]; + #[inline] pub fn lookup(c: char) -> bool { + debug_assert!(!c.is_ascii()); + (c as u32) >= 0xa8 && lookup_slow(c) + } + + #[inline(never)] + fn lookup_slow(c: char) -> bool { const { assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > char::MAX as u32); let mut i = 0; @@ -329,33 +342,40 @@ pub mod cased { use super::ShortOffsetRunHeader; static SHORT_OFFSET_RUNS: [ShortOffsetRunHeader; 22] = [ - ShortOffsetRunHeader::new(0, 4256), ShortOffsetRunHeader::new(55, 5024), - ShortOffsetRunHeader::new(65, 7296), ShortOffsetRunHeader::new(69, 7958), - ShortOffsetRunHeader::new(78, 9398), ShortOffsetRunHeader::new(153, 11264), - ShortOffsetRunHeader::new(155, 42560), ShortOffsetRunHeader::new(167, 43824), - ShortOffsetRunHeader::new(187, 64256), ShortOffsetRunHeader::new(193, 65313), - ShortOffsetRunHeader::new(197, 66560), ShortOffsetRunHeader::new(201, 67456), - ShortOffsetRunHeader::new(223, 68736), ShortOffsetRunHeader::new(231, 71840), - ShortOffsetRunHeader::new(239, 93760), ShortOffsetRunHeader::new(241, 119808), - ShortOffsetRunHeader::new(243, 120486), ShortOffsetRunHeader::new(280, 122624), - ShortOffsetRunHeader::new(303, 122928), ShortOffsetRunHeader::new(309, 125184), - ShortOffsetRunHeader::new(311, 127280), ShortOffsetRunHeader::new(313, 1241482), + ShortOffsetRunHeader::new(0, 4256), ShortOffsetRunHeader::new(51, 5024), + ShortOffsetRunHeader::new(61, 7296), ShortOffsetRunHeader::new(65, 7958), + ShortOffsetRunHeader::new(74, 9398), ShortOffsetRunHeader::new(149, 11264), + ShortOffsetRunHeader::new(151, 42560), ShortOffsetRunHeader::new(163, 43824), + ShortOffsetRunHeader::new(183, 64256), ShortOffsetRunHeader::new(189, 65313), + ShortOffsetRunHeader::new(193, 66560), ShortOffsetRunHeader::new(197, 67456), + ShortOffsetRunHeader::new(219, 68736), ShortOffsetRunHeader::new(227, 71840), + ShortOffsetRunHeader::new(235, 93760), ShortOffsetRunHeader::new(237, 119808), + ShortOffsetRunHeader::new(239, 120486), ShortOffsetRunHeader::new(276, 122624), + ShortOffsetRunHeader::new(299, 122928), ShortOffsetRunHeader::new(305, 125184), + ShortOffsetRunHeader::new(307, 127280), ShortOffsetRunHeader::new(309, 1241482), ]; - static OFFSETS: [u8; 319] = [ - 65, 26, 6, 26, 47, 1, 10, 1, 4, 1, 5, 23, 1, 31, 1, 195, 1, 4, 4, 208, 1, 36, 7, 2, 30, 5, - 96, 1, 42, 4, 2, 2, 2, 4, 1, 1, 6, 1, 1, 3, 1, 1, 1, 20, 1, 83, 1, 139, 8, 166, 1, 38, 9, - 41, 0, 38, 1, 1, 5, 1, 2, 43, 1, 4, 0, 86, 2, 6, 0, 11, 5, 43, 2, 3, 64, 192, 64, 0, 2, 6, - 2, 38, 2, 6, 2, 8, 1, 1, 1, 1, 1, 1, 1, 31, 2, 53, 1, 7, 1, 1, 3, 3, 1, 7, 3, 4, 2, 6, 4, - 13, 5, 3, 1, 7, 116, 1, 13, 1, 16, 13, 101, 1, 4, 1, 2, 10, 1, 1, 3, 5, 6, 1, 1, 1, 1, 1, 1, - 4, 1, 6, 4, 1, 2, 4, 5, 5, 4, 1, 17, 32, 3, 2, 0, 52, 0, 229, 6, 4, 3, 2, 12, 38, 1, 1, 5, - 1, 0, 46, 18, 30, 132, 102, 3, 4, 1, 62, 2, 2, 1, 1, 1, 8, 21, 5, 1, 3, 0, 43, 1, 14, 6, 80, - 0, 7, 12, 5, 0, 26, 6, 26, 0, 80, 96, 36, 4, 36, 116, 11, 1, 15, 1, 7, 1, 2, 1, 11, 1, 15, - 1, 7, 1, 2, 0, 1, 2, 3, 1, 42, 1, 9, 0, 51, 13, 51, 93, 22, 10, 22, 0, 64, 0, 64, 0, 85, 1, - 71, 1, 2, 2, 1, 2, 2, 2, 4, 1, 12, 1, 1, 1, 7, 1, 65, 1, 4, 2, 8, 1, 7, 1, 28, 1, 4, 1, 5, - 1, 1, 3, 7, 1, 0, 2, 25, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, - 8, 0, 10, 1, 20, 6, 6, 0, 62, 0, 68, 0, 26, 6, 26, 6, 26, 0, + static OFFSETS: [u8; 315] = [ + 170, 1, 10, 1, 4, 1, 5, 23, 1, 31, 1, 195, 1, 4, 4, 208, 1, 36, 7, 2, 30, 5, 96, 1, 42, 4, + 2, 2, 2, 4, 1, 1, 6, 1, 1, 3, 1, 1, 1, 20, 1, 83, 1, 139, 8, 166, 1, 38, 9, 41, 0, 38, 1, 1, + 5, 1, 2, 43, 1, 4, 0, 86, 2, 6, 0, 11, 5, 43, 2, 3, 64, 192, 64, 0, 2, 6, 2, 38, 2, 6, 2, 8, + 1, 1, 1, 1, 1, 1, 1, 31, 2, 53, 1, 7, 1, 1, 3, 3, 1, 7, 3, 4, 2, 6, 4, 13, 5, 3, 1, 7, 116, + 1, 13, 1, 16, 13, 101, 1, 4, 1, 2, 10, 1, 1, 3, 5, 6, 1, 1, 1, 1, 1, 1, 4, 1, 6, 4, 1, 2, 4, + 5, 5, 4, 1, 17, 32, 3, 2, 0, 52, 0, 229, 6, 4, 3, 2, 12, 38, 1, 1, 5, 1, 0, 46, 18, 30, 132, + 102, 3, 4, 1, 62, 2, 2, 1, 1, 1, 8, 21, 5, 1, 3, 0, 43, 1, 14, 6, 80, 0, 7, 12, 5, 0, 26, 6, + 26, 0, 80, 96, 36, 4, 36, 116, 11, 1, 15, 1, 7, 1, 2, 1, 11, 1, 15, 1, 7, 1, 2, 0, 1, 2, 3, + 1, 42, 1, 9, 0, 51, 13, 51, 93, 22, 10, 22, 0, 64, 0, 64, 0, 85, 1, 71, 1, 2, 2, 1, 2, 2, 2, + 4, 1, 12, 1, 1, 1, 7, 1, 65, 1, 4, 2, 8, 1, 7, 1, 28, 1, 4, 1, 5, 1, 1, 3, 7, 1, 0, 2, 25, + 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 8, 0, 10, 1, 20, 6, 6, 0, + 62, 0, 68, 0, 26, 6, 26, 6, 26, 0, ]; + #[inline] pub fn lookup(c: char) -> bool { + debug_assert!(!c.is_ascii()); + (c as u32) >= 0xaa && lookup_slow(c) + } + + #[inline(never)] + fn lookup_slow(c: char) -> bool { const { assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > char::MAX as u32); let mut i = 0; @@ -424,6 +444,7 @@ pub mod grapheme_extend { ]; #[inline] pub fn lookup(c: char) -> bool { + debug_assert!(!c.is_ascii()); (c as u32) >= 0x300 && lookup_slow(c) } @@ -446,7 +467,7 @@ pub mod grapheme_extend { #[rustfmt::skip] pub mod lowercase { static BITSET_CHUNKS_MAP: [u8; 123] = [ - 14, 17, 0, 0, 9, 0, 0, 12, 13, 10, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 12, 17, 0, 0, 9, 0, 0, 13, 14, 10, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0, 15, 0, 8, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, @@ -458,37 +479,37 @@ pub mod lowercase { [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 14, 56, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 43, 0, 52, 48, 50, 33], - [0, 0, 0, 0, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 9, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 3, 0, 16, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27], [0, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 34, 17, 23, 53, 54, 49, 47, 7, 35, 42, 0, 28, 12, 31], [0, 0, 46, 0, 56, 56, 56, 0, 22, 22, 69, 22, 36, 25, 24, 37], [0, 5, 70, 0, 29, 15, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 66, 34, 17, 23, 53, 54, 49, 47, 8, 35, 42, 0, 28, 13, 31], - [11, 60, 0, 6, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 32, 0], + [10, 60, 0, 6, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 32, 0], [16, 26, 22, 38, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [16, 51, 2, 21, 68, 9, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [16, 51, 2, 21, 68, 8, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0], [16, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [65, 41, 55, 12, 77, 63, 18, 1, 7, 64, 76, 20, 73, 74, 4, 45], + [65, 41, 55, 11, 66, 63, 18, 13, 1, 64, 76, 20, 73, 74, 4, 45], ]; static BITSET_CANONICAL: [u64; 56] = [ 0b0000000000000000000000000000000000000000000000000000000000000000, - 0b1111111111111111110000000000000000000000000011111111111111111111, + 0b0000111111111111111111111111110000000000000000000000000011111111, 0b1010101010101010101010101010101010101010101010101010100000000010, 0b0000000000000111111111111111111111111111111111111111111111111111, 0b1111111111111111111111000000000000000000000000001111110111111111, 0b1000000000000010000000000000000000000000000000000000000000000000, 0b0000111111111111111111111111111111111111000000000000000000000000, - 0b0000111111111111111111111111110000000000000000000000000011111111, 0b1111111111111111111111111111111111111111111111111010101010000101, 0b1111111111111111111111111111111100000000000000000000000000000000, 0b1111111111111111111111111111110000000000000000000000000000000000, 0b1111111111111111111111110000000000000000000000000000000000000000, 0b1111111111111111111111000000000000000000000000001111111111101111, 0b1111111111111111111100000000000000000000000000010000000000000000, + 0b1111111111111111110000000000000000000000000011111111111111111111, 0b1111111111111111000000111111111111110111111111111111111111111111, 0b1111111111111111000000000000000000000000000000000100001111000000, 0b1111111111111111000000000000000000000000000000000000000000000000, @@ -532,13 +553,15 @@ pub mod lowercase { 0b1110011001010001001011010010101001001110001001000011000100101001, 0b1110101111000000000000000000000000001111111111111111111111111100, ]; - static BITSET_MAPPING: [(u8, u8); 22] = [ - (0, 64), (1, 188), (1, 186), (1, 183), (1, 176), (1, 109), (1, 124), (1, 126), (1, 66), - (1, 70), (1, 77), (2, 146), (2, 144), (2, 83), (3, 93), (3, 147), (3, 133), (4, 12), (4, 6), - (5, 187), (6, 78), (7, 132), + static BITSET_MAPPING: [(u8, u8); 21] = [ + (0, 64), (1, 184), (1, 182), (1, 179), (1, 172), (1, 161), (1, 146), (1, 144), (1, 140), + (1, 136), (1, 132), (2, 146), (2, 144), (2, 83), (3, 93), (3, 147), (3, 133), (4, 12), + (4, 6), (5, 187), (6, 78), ]; pub const fn lookup(c: char) -> bool { + debug_assert!(!c.is_ascii()); + (c as u32) >= 0xaa && super::bitset_search( c as u32, &BITSET_CHUNKS_MAP, @@ -554,43 +577,50 @@ pub mod n { use super::ShortOffsetRunHeader; static SHORT_OFFSET_RUNS: [ShortOffsetRunHeader; 42] = [ - ShortOffsetRunHeader::new(0, 1632), ShortOffsetRunHeader::new(9, 2406), - ShortOffsetRunHeader::new(15, 4160), ShortOffsetRunHeader::new(49, 4969), - ShortOffsetRunHeader::new(53, 5870), ShortOffsetRunHeader::new(55, 6470), - ShortOffsetRunHeader::new(63, 8304), ShortOffsetRunHeader::new(79, 9312), - ShortOffsetRunHeader::new(89, 10102), ShortOffsetRunHeader::new(93, 11517), - ShortOffsetRunHeader::new(95, 12295), ShortOffsetRunHeader::new(97, 12690), - ShortOffsetRunHeader::new(103, 42528), ShortOffsetRunHeader::new(115, 43056), - ShortOffsetRunHeader::new(119, 44016), ShortOffsetRunHeader::new(131, 65296), - ShortOffsetRunHeader::new(133, 65799), ShortOffsetRunHeader::new(135, 66273), - ShortOffsetRunHeader::new(141, 67672), ShortOffsetRunHeader::new(153, 68858), - ShortOffsetRunHeader::new(183, 69216), ShortOffsetRunHeader::new(189, 70736), - ShortOffsetRunHeader::new(209, 71248), ShortOffsetRunHeader::new(213, 71904), - ShortOffsetRunHeader::new(221, 72688), ShortOffsetRunHeader::new(225, 73552), - ShortOffsetRunHeader::new(233, 74752), ShortOffsetRunHeader::new(237, 90416), - ShortOffsetRunHeader::new(239, 92768), ShortOffsetRunHeader::new(241, 93552), - ShortOffsetRunHeader::new(249, 93824), ShortOffsetRunHeader::new(251, 118000), - ShortOffsetRunHeader::new(253, 119488), ShortOffsetRunHeader::new(255, 120782), - ShortOffsetRunHeader::new(261, 123200), ShortOffsetRunHeader::new(263, 123632), - ShortOffsetRunHeader::new(265, 124144), ShortOffsetRunHeader::new(267, 125127), - ShortOffsetRunHeader::new(271, 126065), ShortOffsetRunHeader::new(275, 127232), - ShortOffsetRunHeader::new(285, 130032), ShortOffsetRunHeader::new(287, 1244154), + ShortOffsetRunHeader::new(0, 1632), ShortOffsetRunHeader::new(7, 2406), + ShortOffsetRunHeader::new(13, 4160), ShortOffsetRunHeader::new(47, 4969), + ShortOffsetRunHeader::new(51, 5870), ShortOffsetRunHeader::new(53, 6470), + ShortOffsetRunHeader::new(61, 8304), ShortOffsetRunHeader::new(77, 9312), + ShortOffsetRunHeader::new(87, 10102), ShortOffsetRunHeader::new(91, 11517), + ShortOffsetRunHeader::new(93, 12295), ShortOffsetRunHeader::new(95, 12690), + ShortOffsetRunHeader::new(101, 42528), ShortOffsetRunHeader::new(113, 43056), + ShortOffsetRunHeader::new(117, 44016), ShortOffsetRunHeader::new(129, 65296), + ShortOffsetRunHeader::new(131, 65799), ShortOffsetRunHeader::new(133, 66273), + ShortOffsetRunHeader::new(139, 67672), ShortOffsetRunHeader::new(151, 68858), + ShortOffsetRunHeader::new(181, 69216), ShortOffsetRunHeader::new(187, 70736), + ShortOffsetRunHeader::new(207, 71248), ShortOffsetRunHeader::new(211, 71904), + ShortOffsetRunHeader::new(219, 72688), ShortOffsetRunHeader::new(223, 73552), + ShortOffsetRunHeader::new(231, 74752), ShortOffsetRunHeader::new(235, 90416), + ShortOffsetRunHeader::new(237, 92768), ShortOffsetRunHeader::new(239, 93552), + ShortOffsetRunHeader::new(247, 93824), ShortOffsetRunHeader::new(249, 118000), + ShortOffsetRunHeader::new(251, 119488), ShortOffsetRunHeader::new(253, 120782), + ShortOffsetRunHeader::new(259, 123200), ShortOffsetRunHeader::new(261, 123632), + ShortOffsetRunHeader::new(263, 124144), ShortOffsetRunHeader::new(265, 125127), + ShortOffsetRunHeader::new(269, 126065), ShortOffsetRunHeader::new(273, 127232), + ShortOffsetRunHeader::new(283, 130032), ShortOffsetRunHeader::new(285, 1244154), ]; - static OFFSETS: [u8; 289] = [ - 48, 10, 120, 2, 5, 1, 2, 3, 0, 10, 134, 10, 198, 10, 0, 10, 118, 10, 4, 6, 108, 10, 118, - 10, 118, 10, 2, 6, 110, 13, 115, 10, 8, 7, 103, 10, 104, 7, 7, 19, 109, 10, 96, 10, 118, 10, - 70, 20, 0, 10, 70, 10, 0, 20, 0, 3, 239, 10, 6, 10, 22, 10, 0, 10, 128, 11, 165, 10, 6, 10, - 182, 10, 86, 10, 134, 10, 6, 10, 0, 1, 3, 6, 6, 10, 198, 51, 2, 5, 0, 60, 78, 22, 0, 30, 0, - 1, 0, 1, 25, 9, 14, 3, 0, 4, 138, 10, 30, 8, 1, 15, 32, 10, 39, 15, 0, 10, 188, 10, 0, 6, - 154, 10, 38, 10, 198, 10, 22, 10, 86, 10, 0, 10, 0, 10, 0, 45, 12, 57, 17, 2, 0, 27, 36, 4, - 29, 1, 8, 1, 134, 5, 202, 10, 0, 8, 25, 7, 39, 9, 75, 5, 22, 6, 160, 2, 2, 16, 2, 46, 64, 9, - 52, 2, 30, 3, 75, 5, 104, 8, 24, 8, 41, 7, 0, 6, 48, 10, 6, 10, 0, 31, 158, 10, 42, 4, 112, - 7, 134, 30, 128, 10, 60, 10, 144, 10, 7, 20, 251, 10, 0, 10, 118, 10, 0, 10, 102, 10, 6, 20, - 76, 12, 0, 19, 93, 10, 0, 10, 86, 29, 227, 10, 70, 10, 0, 10, 102, 21, 0, 111, 0, 10, 0, 10, - 86, 10, 134, 10, 1, 7, 0, 10, 0, 23, 0, 10, 0, 20, 12, 20, 108, 25, 0, 50, 0, 10, 0, 10, 0, - 10, 247, 10, 0, 9, 128, 10, 0, 59, 1, 3, 1, 4, 76, 45, 1, 15, 0, 13, 0, 10, 0, + static OFFSETS: [u8; 287] = [ + 178, 2, 5, 1, 2, 3, 0, 10, 134, 10, 198, 10, 0, 10, 118, 10, 4, 6, 108, 10, 118, 10, 118, + 10, 2, 6, 110, 13, 115, 10, 8, 7, 103, 10, 104, 7, 7, 19, 109, 10, 96, 10, 118, 10, 70, 20, + 0, 10, 70, 10, 0, 20, 0, 3, 239, 10, 6, 10, 22, 10, 0, 10, 128, 11, 165, 10, 6, 10, 182, 10, + 86, 10, 134, 10, 6, 10, 0, 1, 3, 6, 6, 10, 198, 51, 2, 5, 0, 60, 78, 22, 0, 30, 0, 1, 0, 1, + 25, 9, 14, 3, 0, 4, 138, 10, 30, 8, 1, 15, 32, 10, 39, 15, 0, 10, 188, 10, 0, 6, 154, 10, + 38, 10, 198, 10, 22, 10, 86, 10, 0, 10, 0, 10, 0, 45, 12, 57, 17, 2, 0, 27, 36, 4, 29, 1, 8, + 1, 134, 5, 202, 10, 0, 8, 25, 7, 39, 9, 75, 5, 22, 6, 160, 2, 2, 16, 2, 46, 64, 9, 52, 2, + 30, 3, 75, 5, 104, 8, 24, 8, 41, 7, 0, 6, 48, 10, 6, 10, 0, 31, 158, 10, 42, 4, 112, 7, 134, + 30, 128, 10, 60, 10, 144, 10, 7, 20, 251, 10, 0, 10, 118, 10, 0, 10, 102, 10, 6, 20, 76, 12, + 0, 19, 93, 10, 0, 10, 86, 29, 227, 10, 70, 10, 0, 10, 102, 21, 0, 111, 0, 10, 0, 10, 86, 10, + 134, 10, 1, 7, 0, 10, 0, 23, 0, 10, 0, 20, 12, 20, 108, 25, 0, 50, 0, 10, 0, 10, 0, 10, 247, + 10, 0, 9, 128, 10, 0, 59, 1, 3, 1, 4, 76, 45, 1, 15, 0, 13, 0, 10, 0, ]; + #[inline] pub fn lookup(c: char) -> bool { + debug_assert!(!c.is_ascii()); + (c as u32) >= 0xb2 && lookup_slow(c) + } + + #[inline(never)] + fn lookup_slow(c: char) -> bool { const { assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > char::MAX as u32); let mut i = 0; @@ -608,34 +638,34 @@ pub mod n { #[rustfmt::skip] pub mod uppercase { static BITSET_CHUNKS_MAP: [u8; 125] = [ - 12, 15, 6, 6, 0, 6, 6, 2, 4, 11, 6, 16, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 5, 6, 14, 6, 10, 6, 6, 1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 13, 6, 6, - 6, 6, 9, 6, 3, + 3, 14, 6, 6, 0, 6, 6, 2, 5, 12, 6, 15, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 9, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 7, 6, 13, 6, 11, 6, 6, 1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 8, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 16, 6, 6, + 6, 6, 10, 6, 4, ]; static BITSET_INDEX_CHUNKS: [[u8; 16]; 17] = [ - [44, 44, 5, 35, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 5, 1], + [44, 44, 5, 35, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 5, 0], [44, 44, 5, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], - [44, 44, 40, 44, 44, 44, 44, 44, 17, 17, 63, 17, 43, 29, 24, 23], + [44, 44, 40, 44, 44, 44, 44, 44, 17, 17, 62, 17, 43, 29, 24, 23], + [44, 44, 44, 32, 36, 21, 22, 15, 13, 34, 44, 44, 44, 11, 30, 39], [44, 44, 44, 44, 9, 8, 45, 44, 44, 44, 44, 44, 44, 44, 44, 44], - [44, 44, 44, 44, 37, 28, 67, 44, 44, 44, 44, 44, 44, 44, 44, 44], - [44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 0, 44, 44, 44], + [44, 44, 44, 44, 37, 28, 66, 44, 44, 44, 44, 44, 44, 44, 44, 44], [44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], - [44, 44, 44, 44, 44, 44, 44, 44, 44, 55, 44, 44, 44, 44, 44, 44], - [44, 44, 44, 44, 44, 44, 44, 44, 44, 62, 61, 44, 20, 14, 16, 4], - [44, 44, 44, 44, 56, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], - [44, 44, 59, 44, 44, 31, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], - [44, 44, 60, 46, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], - [44, 49, 44, 32, 36, 21, 22, 15, 13, 34, 44, 44, 44, 11, 30, 39], - [52, 54, 26, 50, 12, 7, 25, 51, 41, 53, 6, 3, 66, 65, 64, 68], - [57, 44, 9, 47, 44, 42, 33, 44, 44, 44, 44, 44, 44, 44, 44, 44], - [58, 19, 2, 18, 10, 48, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], - [58, 38, 17, 27, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], + [44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 57, 44, 44, 44], + [44, 44, 44, 44, 44, 44, 44, 44, 44, 49, 44, 44, 44, 44, 44, 44], + [44, 44, 44, 44, 44, 44, 44, 44, 44, 61, 60, 44, 20, 14, 16, 4], + [44, 44, 44, 44, 50, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], + [44, 44, 53, 44, 44, 31, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], + [44, 44, 54, 46, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], + [51, 44, 9, 47, 44, 42, 33, 44, 44, 44, 44, 44, 44, 44, 44, 44], + [52, 19, 2, 18, 10, 48, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], + [52, 38, 17, 27, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], + [58, 1, 26, 55, 12, 7, 25, 56, 41, 59, 6, 3, 65, 64, 63, 67], ]; static BITSET_CANONICAL: [u64; 44] = [ - 0b0000011111111111111111111111111000000000000000000000000000000000, 0b0000000000111111111111111111111111111111111111111111111111111111, + 0b1111111111111111111111110000000000000000000000000011111111111111, 0b0101010101010101010101010101010101010101010101010101010000000001, 0b0000011111111111111111111111110000000000000000000000000000000001, 0b0000000000100000000000000000000000010101010000010001101011110101, @@ -679,13 +709,15 @@ pub mod uppercase { 0b1111011111111111000000000000000000000000000000000000000000000000, 0b1111111100000000111111110000000000111111000000001111111100000000, ]; - static BITSET_MAPPING: [(u8, u8); 25] = [ - (0, 187), (0, 177), (0, 171), (0, 167), (0, 164), (0, 32), (0, 47), (0, 51), (0, 121), - (0, 117), (0, 109), (1, 150), (1, 148), (1, 142), (1, 134), (1, 131), (1, 64), (2, 164), - (2, 146), (2, 20), (3, 146), (3, 140), (3, 134), (4, 178), (4, 171), + static BITSET_MAPPING: [(u8, u8); 24] = [ + (0, 182), (0, 74), (0, 166), (0, 162), (0, 159), (0, 150), (0, 148), (0, 142), (0, 134), + (0, 131), (0, 64), (1, 66), (1, 70), (1, 83), (1, 12), (1, 8), (2, 164), (2, 146), (2, 20), + (3, 146), (3, 140), (3, 134), (4, 178), (4, 171), ]; pub const fn lookup(c: char) -> bool { + debug_assert!(!c.is_ascii()); + (c as u32) >= 0xc0 && super::bitset_search( c as u32, &BITSET_CHUNKS_MAP, @@ -699,8 +731,8 @@ pub mod uppercase { #[rustfmt::skip] pub mod white_space { static WHITESPACE_MAP: [u8; 256] = [ - 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -711,6 +743,7 @@ pub mod white_space { ]; #[inline] pub const fn lookup(c: char) -> bool { + debug_assert!(!c.is_ascii()); match c as u32 >> 8 { 0 => WHITESPACE_MAP[c as usize & 0xff] & 1 != 0, 22 => c as u32 == 0x1680, diff --git a/library/coretests/tests/ptr.rs b/library/coretests/tests/ptr.rs index c13fb96a67f9..f8774833d0a5 100644 --- a/library/coretests/tests/ptr.rs +++ b/library/coretests/tests/ptr.rs @@ -936,12 +936,13 @@ fn test_const_swap_ptr() { assert!(*s1.0.ptr == 666); assert!(*s2.0.ptr == 1); - // Swap them back, byte-for-byte + // Swap them back, again as an array. + // FIXME(#146291): we should be swapping back at type `u8` but that currently does not work. unsafe { ptr::swap_nonoverlapping( - ptr::from_mut(&mut s1).cast::(), - ptr::from_mut(&mut s2).cast::(), - size_of::(), + ptr::from_mut(&mut s1).cast::(), + ptr::from_mut(&mut s2).cast::(), + 1, ); } diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index 57a980d6acdb..21e82d43a800 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -95,6 +95,9 @@ impl Error { pub(crate) const ZERO_TIMEOUT: Self = const_error!(ErrorKind::InvalidInput, "cannot set a 0 duration timeout"); + + pub(crate) const NO_ADDRESSES: Self = + const_error!(ErrorKind::InvalidInput, "could not resolve to any addresses"); } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/net/mod.rs b/library/std/src/net/mod.rs index ddd3b68dd2d6..40f1a93e39de 100644 --- a/library/std/src/net/mod.rs +++ b/library/std/src/net/mod.rs @@ -34,7 +34,6 @@ pub use self::tcp::IntoIncoming; pub use self::tcp::{Incoming, TcpListener, TcpStream}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::udp::UdpSocket; -use crate::io::{self, ErrorKind}; mod ip_addr; mod socket_addr; @@ -67,23 +66,3 @@ pub enum Shutdown { #[stable(feature = "rust1", since = "1.0.0")] Both, } - -fn each_addr(addr: A, mut f: F) -> io::Result -where - F: FnMut(io::Result<&SocketAddr>) -> io::Result, -{ - let addrs = match addr.to_socket_addrs() { - Ok(addrs) => addrs, - Err(e) => return f(Err(e)), - }; - let mut last_err = None; - for addr in addrs { - match f(Ok(&addr)) { - Ok(l) => return Ok(l), - Err(e) => last_err = Some(e), - } - } - Err(last_err.unwrap_or_else(|| { - io::const_error!(ErrorKind::InvalidInput, "could not resolve to any addresses") - })) -} diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs index 10685b493194..ae50f531a716 100644 --- a/library/std/src/net/tcp.rs +++ b/library/std/src/net/tcp.rs @@ -167,7 +167,7 @@ impl TcpStream { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn connect(addr: A) -> io::Result { - super::each_addr(addr, net_imp::TcpStream::connect).map(TcpStream) + net_imp::TcpStream::connect(addr).map(TcpStream) } /// Opens a TCP connection to a remote host with a timeout. @@ -782,7 +782,7 @@ impl TcpListener { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn bind(addr: A) -> io::Result { - super::each_addr(addr, net_imp::TcpListener::bind).map(TcpListener) + net_imp::TcpListener::bind(addr).map(TcpListener) } /// Returns the local socket address of this listener. diff --git a/library/std/src/net/tcp/tests.rs b/library/std/src/net/tcp/tests.rs index 03003037b295..7c7ef7b2f701 100644 --- a/library/std/src/net/tcp/tests.rs +++ b/library/std/src/net/tcp/tests.rs @@ -1,5 +1,5 @@ use crate::io::prelude::*; -use crate::io::{BorrowedBuf, IoSlice, IoSliceMut}; +use crate::io::{BorrowedBuf, ErrorKind, IoSlice, IoSliceMut}; use crate::mem::MaybeUninit; use crate::net::test::{next_test_ip4, next_test_ip6}; use crate::net::*; diff --git a/library/std/src/net/udp.rs b/library/std/src/net/udp.rs index a97b3299774b..72e292e3d157 100644 --- a/library/std/src/net/udp.rs +++ b/library/std/src/net/udp.rs @@ -120,7 +120,7 @@ impl UdpSocket { /// [`Ipv4Addr::UNSPECIFIED`] or [`Ipv6Addr::UNSPECIFIED`]. #[stable(feature = "rust1", since = "1.0.0")] pub fn bind(addr: A) -> io::Result { - super::each_addr(addr, net_imp::UdpSocket::bind).map(UdpSocket) + net_imp::UdpSocket::bind(addr).map(UdpSocket) } /// Receives a single datagram message on the socket. On success, returns the number @@ -677,7 +677,7 @@ impl UdpSocket { /// on the platform. #[stable(feature = "net2_mutators", since = "1.9.0")] pub fn connect(&self, addr: A) -> io::Result<()> { - super::each_addr(addr, |addr| self.0.connect(addr)) + self.0.connect(addr) } /// Sends data on the socket to the remote address to which it is connected. diff --git a/library/std/src/net/udp/tests.rs b/library/std/src/net/udp/tests.rs index 91da3135f97c..0638b36c54f9 100644 --- a/library/std/src/net/udp/tests.rs +++ b/library/std/src/net/udp/tests.rs @@ -1,3 +1,4 @@ +use crate::io::ErrorKind; use crate::net::test::{compare_ignore_zoneid, next_test_ip4, next_test_ip6}; use crate::net::*; use crate::sync::mpsc::channel; diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 19663e4a9df6..70ba502d6842 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -3037,6 +3037,14 @@ impl Path { /// /// This is an alias to [`fs::canonicalize`]. /// + /// # Errors + /// + /// This method will return an error in the following situations, but is not + /// limited to just these cases: + /// + /// * `path` does not exist. + /// * A non-final component in path is not a directory. + /// /// # Examples /// /// ```no_run diff --git a/library/std/src/sync/barrier.rs b/library/std/src/sync/barrier.rs index 712ce03f90b0..8988126bd90c 100644 --- a/library/std/src/sync/barrier.rs +++ b/library/std/src/sync/barrier.rs @@ -1,4 +1,5 @@ use crate::fmt; +use crate::panic::RefUnwindSafe; use crate::sync::nonpoison::{Condvar, Mutex}; /// A barrier enables multiple threads to synchronize the beginning @@ -31,6 +32,9 @@ pub struct Barrier { num_threads: usize, } +#[stable(feature = "unwind_safe_lock_refs", since = "1.12.0")] +impl RefUnwindSafe for Barrier {} + // The inner state of a double barrier struct BarrierState { count: usize, diff --git a/library/std/src/sys/net/connection/mod.rs b/library/std/src/sys/net/connection/mod.rs new file mode 100644 index 000000000000..7f9636a8ccfd --- /dev/null +++ b/library/std/src/sys/net/connection/mod.rs @@ -0,0 +1,57 @@ +cfg_select! { + any( + all(target_family = "unix", not(target_os = "l4re")), + target_os = "windows", + target_os = "hermit", + all(target_os = "wasi", target_env = "p2"), + target_os = "solid_asp3", + ) => { + mod socket; + pub use socket::*; + } + all(target_vendor = "fortanix", target_env = "sgx") => { + mod sgx; + pub use sgx::*; + } + all(target_os = "wasi", target_env = "p1") => { + mod wasip1; + pub use wasip1::*; + } + target_os = "xous" => { + mod xous; + pub use xous::*; + } + target_os = "uefi" => { + mod uefi; + pub use uefi::*; + } + _ => { + mod unsupported; + pub use unsupported::*; + } +} + +#[cfg_attr( + // Make sure that this is used on some platforms at least. + not(any(target_os = "linux", target_os = "windows")), + allow(dead_code) +)] +fn each_addr(addr: A, mut f: F) -> crate::io::Result +where + F: FnMut(&crate::net::SocketAddr) -> crate::io::Result, +{ + use crate::io::Error; + + let mut last_err = None; + for addr in addr.to_socket_addrs()? { + match f(&addr) { + Ok(l) => return Ok(l), + Err(e) => last_err = Some(e), + } + } + + match last_err { + Some(err) => Err(err), + None => Err(Error::NO_ADDRESSES), + } +} diff --git a/library/std/src/sys/net/connection/sgx.rs b/library/std/src/sys/net/connection/sgx.rs index 2389fd1bcb6c..9b54571997d0 100644 --- a/library/std/src/sys/net/connection/sgx.rs +++ b/library/std/src/sys/net/connection/sgx.rs @@ -1,3 +1,5 @@ +use crate::error; +use crate::fmt::{self, Write}; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, ToSocketAddrs}; use crate::sync::Arc; @@ -5,7 +7,6 @@ use crate::sys::abi::usercalls; use crate::sys::fd::FileDesc; use crate::sys::{AsInner, FromInner, IntoInner, TryIntoInner, sgx_ineffective, unsupported}; use crate::time::Duration; -use crate::{error, fmt}; const DEFAULT_FAKE_TTL: u32 = 64; @@ -63,18 +64,52 @@ impl fmt::Debug for TcpStream { } } -fn io_err_to_addr(result: io::Result<&SocketAddr>) -> io::Result { - match result { - Ok(saddr) => Ok(saddr.to_string()), - // need to downcast twice because io::Error::into_inner doesn't return the original - // value if the conversion fails - Err(e) => { - if e.get_ref().and_then(|e| e.downcast_ref::()).is_some() { - Ok(e.into_inner().unwrap().downcast::().unwrap().host) - } else { - Err(e) +/// Converts each address in `addr` into a hostname. +/// +/// SGX doesn't support DNS resolution but rather accepts hostnames in +/// the same place as socket addresses. So, to make e.g. +/// ```rust +/// TcpStream::connect("example.com:80")` +/// ``` +/// work, the DNS lookup returns a special error (`NonIpSockAddr`) instead, +/// which contains the hostname being looked up. When `.to_socket_addrs()` +/// fails, we inspect the error and try recover the hostname from it. If that +/// succeeds, we thus continue with the hostname. +/// +/// This is a terrible hack and leads to buggy code. For instance, when users +/// use the result of `.to_socket_addrs()` in their own `ToSocketAddrs` +/// implementation to select from a list of possible URLs, the only URL used +/// will be that of the last item tried. +// FIXME: This is a terrible, terrible hack. Fixing this requires Fortanix to +// add a method for resolving addresses. +fn each_addr(addr: A, mut f: F) -> io::Result +where + F: FnMut(&str) -> io::Result, +{ + match addr.to_socket_addrs() { + Ok(addrs) => { + let mut last_err = None; + let mut encoded = String::new(); + for addr in addrs { + // Format the IP address as a string, reusing the buffer. + encoded.clear(); + write!(encoded, "{}", &addr).unwrap(); + + match f(&encoded) { + Ok(val) => return Ok(val), + Err(err) => last_err = Some(err), + } + } + + match last_err { + Some(err) => Err(err), + None => Err(io::Error::NO_ADDRESSES), } } + Err(err) => match err.get_ref().and_then(|e| e.downcast_ref::()) { + Some(NonIpSockAddr { host }) => f(host), + None => Err(err), + }, } } @@ -86,17 +121,18 @@ fn addr_to_sockaddr(addr: Option<&str>) -> io::Result { } impl TcpStream { - pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result { - let addr = io_err_to_addr(addr)?; - let (fd, local_addr, peer_addr) = usercalls::connect_stream(&addr)?; - Ok(TcpStream { inner: Socket::new(fd, local_addr), peer_addr: Some(peer_addr) }) + pub fn connect(addr: A) -> io::Result { + each_addr(addr, |addr| { + let (fd, local_addr, peer_addr) = usercalls::connect_stream(addr)?; + Ok(TcpStream { inner: Socket::new(fd, local_addr), peer_addr: Some(peer_addr) }) + }) } pub fn connect_timeout(addr: &SocketAddr, dur: Duration) -> io::Result { if dur == Duration::default() { return Err(io::Error::ZERO_TIMEOUT); } - Self::connect(Ok(addr)) // FIXME: ignoring timeout + Self::connect(addr) // FIXME: ignoring timeout } pub fn set_read_timeout(&self, dur: Option) -> io::Result<()> { @@ -247,10 +283,11 @@ impl fmt::Debug for TcpListener { } impl TcpListener { - pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result { - let addr = io_err_to_addr(addr)?; - let (fd, local_addr) = usercalls::bind_stream(&addr)?; - Ok(TcpListener { inner: Socket::new(fd, local_addr) }) + pub fn bind(addr: A) -> io::Result { + each_addr(addr, |addr| { + let (fd, local_addr) = usercalls::bind_stream(addr)?; + Ok(TcpListener { inner: Socket::new(fd, local_addr) }) + }) } pub fn socket_addr(&self) -> io::Result { @@ -316,7 +353,7 @@ impl FromInner for TcpListener { pub struct UdpSocket(!); impl UdpSocket { - pub fn bind(_: io::Result<&SocketAddr>) -> io::Result { + pub fn bind(_: A) -> io::Result { unsupported() } @@ -436,7 +473,7 @@ impl UdpSocket { self.0 } - pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> { + pub fn connect(&self, _: A) -> io::Result<()> { self.0 } } diff --git a/library/std/src/sys/net/connection/socket.rs b/library/std/src/sys/net/connection/socket/mod.rs similarity index 90% rename from library/std/src/sys/net/connection/socket.rs rename to library/std/src/sys/net/connection/socket/mod.rs index aa83ed65d4c2..564f2e3a01f3 100644 --- a/library/std/src/sys/net/connection/socket.rs +++ b/library/std/src/sys/net/connection/socket/mod.rs @@ -3,8 +3,11 @@ mod tests; use crate::ffi::{c_int, c_void}; use crate::io::{self, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut}; -use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, SocketAddrV4, SocketAddrV6}; +use crate::net::{ + Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs, +}; use crate::sys::common::small_c_string::run_with_cstr; +use crate::sys::net::connection::each_addr; use crate::sys_common::{AsInner, FromInner}; use crate::time::Duration; use crate::{cmp, fmt, mem, ptr}; @@ -342,14 +345,15 @@ pub struct TcpStream { } impl TcpStream { - pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result { - let addr = addr?; - + pub fn connect(addr: A) -> io::Result { init(); + return each_addr(addr, inner); - let sock = Socket::new(addr, c::SOCK_STREAM)?; - sock.connect(addr)?; - Ok(TcpStream { inner: sock }) + fn inner(addr: &SocketAddr) -> io::Result { + let sock = Socket::new(addr, c::SOCK_STREAM)?; + sock.connect(addr)?; + Ok(TcpStream { inner: sock }) + } } pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result { @@ -512,48 +516,45 @@ pub struct TcpListener { } impl TcpListener { - pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result { - let addr = addr?; - + pub fn bind(addr: A) -> io::Result { init(); + return each_addr(addr, inner); - let sock = Socket::new(addr, c::SOCK_STREAM)?; + fn inner(addr: &SocketAddr) -> io::Result { + let sock = Socket::new(addr, c::SOCK_STREAM)?; - // On platforms with Berkeley-derived sockets, this allows to quickly - // rebind a socket, without needing to wait for the OS to clean up the - // previous one. - // - // On Windows, this allows rebinding sockets which are actively in use, - // which allows “socket hijacking”, so we explicitly don't set it here. - // https://docs.microsoft.com/en-us/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse - #[cfg(not(windows))] - setsockopt(&sock, c::SOL_SOCKET, c::SO_REUSEADDR, 1 as c_int)?; + // On platforms with Berkeley-derived sockets, this allows to quickly + // rebind a socket, without needing to wait for the OS to clean up the + // previous one. + // + // On Windows, this allows rebinding sockets which are actively in use, + // which allows “socket hijacking”, so we explicitly don't set it here. + // https://docs.microsoft.com/en-us/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse + #[cfg(not(windows))] + setsockopt(&sock, c::SOL_SOCKET, c::SO_REUSEADDR, 1 as c_int)?; - // Bind our new socket - let (addr, len) = socket_addr_to_c(addr); - cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?; + // Bind our new socket + let (addr, len) = socket_addr_to_c(addr); + cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?; - cfg_select! { - target_os = "horizon" => { + let backlog = if cfg!(target_os = "horizon") { // The 3DS doesn't support a big connection backlog. Sometimes // it allows up to about 37, but other times it doesn't even // accept 32. There may be a global limitation causing this. - let backlog = 20; - } - target_os = "haiku" => { + 20 + } else if cfg!(target_os = "haiku") { // Haiku does not support a queue length > 32 // https://github.com/haiku/haiku/blob/979a0bc487864675517fb2fab28f87dc8bf43041/headers/posix/sys/socket.h#L81 - let backlog = 32; - } - _ => { + 32 + } else { // The default for all other platforms - let backlog = 128; - } - } + 128 + }; - // Start listening - cvt(unsafe { c::listen(sock.as_raw(), backlog) })?; - Ok(TcpListener { inner: sock }) + // Start listening + cvt(unsafe { c::listen(sock.as_raw(), backlog) })?; + Ok(TcpListener { inner: sock }) + } } #[inline] @@ -639,15 +640,16 @@ pub struct UdpSocket { } impl UdpSocket { - pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result { - let addr = addr?; - + pub fn bind(addr: A) -> io::Result { init(); + return each_addr(addr, inner); - let sock = Socket::new(addr, c::SOCK_DGRAM)?; - let (addr, len) = socket_addr_to_c(addr); - cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?; - Ok(UdpSocket { inner: sock }) + fn inner(addr: &SocketAddr) -> io::Result { + let sock = Socket::new(addr, c::SOCK_DGRAM)?; + let (addr, len) = socket_addr_to_c(addr); + cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?; + Ok(UdpSocket { inner: sock }) + } } #[inline] @@ -822,9 +824,13 @@ impl UdpSocket { Ok(ret as usize) } - pub fn connect(&self, addr: io::Result<&SocketAddr>) -> io::Result<()> { - let (addr, len) = socket_addr_to_c(addr?); - cvt_r(|| unsafe { c::connect(self.inner.as_raw(), addr.as_ptr(), len) }).map(drop) + pub fn connect(&self, addr: A) -> io::Result<()> { + return each_addr(addr, |addr| inner(self, addr)); + + fn inner(this: &UdpSocket, addr: &SocketAddr) -> io::Result<()> { + let (addr, len) = socket_addr_to_c(addr); + cvt_r(|| unsafe { c::connect(this.inner.as_raw(), addr.as_ptr(), len) }).map(drop) + } } } diff --git a/library/std/src/sys/net/connection/uefi/mod.rs b/library/std/src/sys/net/connection/uefi/mod.rs index 16e3487a1747..003680428735 100644 --- a/library/std/src/sys/net/connection/uefi/mod.rs +++ b/library/std/src/sys/net/connection/uefi/mod.rs @@ -1,6 +1,7 @@ +use super::each_addr; use crate::fmt; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; -use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr}; +use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, ToSocketAddrs}; use crate::sync::{Arc, Mutex}; use crate::sys::unsupported; use crate::time::Duration; @@ -15,13 +16,17 @@ pub struct TcpStream { } impl TcpStream { - pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result { - let inner = tcp::Tcp::connect(addr?, None)?; - Ok(Self { - inner, - read_timeout: Arc::new(Mutex::new(None)), - write_timeout: Arc::new(Mutex::new(None)), - }) + pub fn connect(addr: A) -> io::Result { + return each_addr(addr, inner); + + fn inner(addr: &SocketAddr) -> io::Result { + let inner = tcp::Tcp::connect(addr, None)?; + Ok(TcpStream { + inner, + read_timeout: Arc::new(Mutex::new(None)), + write_timeout: Arc::new(Mutex::new(None)), + }) + } } pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result { @@ -145,7 +150,7 @@ pub struct TcpListener { } impl TcpListener { - pub fn bind(_: io::Result<&SocketAddr>) -> io::Result { + pub fn bind(_: A) -> io::Result { unsupported() } @@ -195,7 +200,7 @@ impl fmt::Debug for TcpListener { pub struct UdpSocket(!); impl UdpSocket { - pub fn bind(_: io::Result<&SocketAddr>) -> io::Result { + pub fn bind(_: A) -> io::Result { unsupported() } @@ -315,7 +320,7 @@ impl UdpSocket { self.0 } - pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> { + pub fn connect(&self, _: A) -> io::Result<()> { self.0 } } diff --git a/library/std/src/sys/net/connection/unsupported.rs b/library/std/src/sys/net/connection/unsupported.rs index da2174396266..fbc86343272f 100644 --- a/library/std/src/sys/net/connection/unsupported.rs +++ b/library/std/src/sys/net/connection/unsupported.rs @@ -1,13 +1,13 @@ use crate::fmt; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; -use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr}; +use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, ToSocketAddrs}; use crate::sys::unsupported; use crate::time::Duration; pub struct TcpStream(!); impl TcpStream { - pub fn connect(_: io::Result<&SocketAddr>) -> io::Result { + pub fn connect(_: A) -> io::Result { unsupported() } @@ -121,7 +121,7 @@ impl fmt::Debug for TcpStream { pub struct TcpListener(!); impl TcpListener { - pub fn bind(_: io::Result<&SocketAddr>) -> io::Result { + pub fn bind(_: A) -> io::Result { unsupported() } @@ -171,7 +171,7 @@ impl fmt::Debug for TcpListener { pub struct UdpSocket(!); impl UdpSocket { - pub fn bind(_: io::Result<&SocketAddr>) -> io::Result { + pub fn bind(_: A) -> io::Result { unsupported() } @@ -291,7 +291,7 @@ impl UdpSocket { self.0 } - pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> { + pub fn connect(&self, _: A) -> io::Result<()> { self.0 } } diff --git a/library/std/src/sys/net/connection/wasip1.rs b/library/std/src/sys/net/connection/wasip1.rs index 951dc65e5b47..cdfa25c8a440 100644 --- a/library/std/src/sys/net/connection/wasip1.rs +++ b/library/std/src/sys/net/connection/wasip1.rs @@ -2,7 +2,7 @@ use crate::fmt; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; -use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr}; +use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, ToSocketAddrs}; use crate::os::wasi::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd}; use crate::sys::fd::WasiFd; use crate::sys::{err2io, unsupported}; @@ -60,7 +60,7 @@ impl FromRawFd for Socket { } impl TcpStream { - pub fn connect(_: io::Result<&SocketAddr>) -> io::Result { + pub fn connect(_: A) -> io::Result { unsupported() } @@ -212,7 +212,7 @@ pub struct TcpListener { } impl TcpListener { - pub fn bind(_: io::Result<&SocketAddr>) -> io::Result { + pub fn bind(_: A) -> io::Result { unsupported() } @@ -316,7 +316,7 @@ pub struct UdpSocket { } impl UdpSocket { - pub fn bind(_: io::Result<&SocketAddr>) -> io::Result { + pub fn bind(_: A) -> io::Result { unsupported() } @@ -436,7 +436,7 @@ impl UdpSocket { unsupported() } - pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> { + pub fn connect(&self, _: A) -> io::Result<()> { unsupported() } diff --git a/library/std/src/sys/net/connection/xous/tcplistener.rs b/library/std/src/sys/net/connection/xous/tcplistener.rs index bdf1fcd9302b..8818ef2ca9a9 100644 --- a/library/std/src/sys/net/connection/xous/tcplistener.rs +++ b/library/std/src/sys/net/connection/xous/tcplistener.rs @@ -2,9 +2,10 @@ use core::convert::TryInto; use core::sync::atomic::{Atomic, AtomicBool, AtomicU16, AtomicUsize, Ordering}; use super::*; -use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}; +use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, ToSocketAddrs}; use crate::os::xous::services; use crate::sync::Arc; +use crate::sys::net::connection::each_addr; use crate::{fmt, io}; macro_rules! unimpl { @@ -25,16 +26,19 @@ pub struct TcpListener { } impl TcpListener { - pub fn bind(socketaddr: io::Result<&SocketAddr>) -> io::Result { - let mut addr = *socketaddr?; + pub fn bind(addr: A) -> io::Result { + return each_addr(addr, inner); - let fd = TcpListener::bind_inner(&mut addr)?; - return Ok(TcpListener { - fd: Arc::new(AtomicU16::new(fd)), - local: addr, - handle_count: Arc::new(AtomicUsize::new(1)), - nonblocking: Arc::new(AtomicBool::new(false)), - }); + fn inner(addr: &SocketAddr) -> io::Result { + let mut addr = *addr; + let fd = TcpListener::bind_inner(&mut addr)?; + Ok(TcpListener { + fd: Arc::new(AtomicU16::new(fd)), + local: addr, + handle_count: Arc::new(AtomicUsize::new(1)), + nonblocking: Arc::new(AtomicBool::new(false)), + }) + } } /// This returns the raw fd of a Listener, so that it can also be used by the diff --git a/library/std/src/sys/net/connection/xous/tcpstream.rs b/library/std/src/sys/net/connection/xous/tcpstream.rs index 545247674526..4df75453d1f4 100644 --- a/library/std/src/sys/net/connection/xous/tcpstream.rs +++ b/library/std/src/sys/net/connection/xous/tcpstream.rs @@ -3,9 +3,12 @@ use core::sync::atomic::{Atomic, AtomicBool, AtomicU32, AtomicUsize, Ordering}; use super::*; use crate::fmt; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; -use crate::net::{IpAddr, Ipv4Addr, Shutdown, SocketAddr, SocketAddrV4, SocketAddrV6}; +use crate::net::{ + IpAddr, Ipv4Addr, Shutdown, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs, +}; use crate::os::xous::services; use crate::sync::Arc; +use crate::sys::net::connection::each_addr; use crate::time::Duration; macro_rules! unimpl { @@ -79,8 +82,8 @@ impl TcpStream { } } - pub fn connect(socketaddr: io::Result<&SocketAddr>) -> io::Result { - Self::connect_timeout(socketaddr?, Duration::ZERO) + pub fn connect(addr: A) -> io::Result { + each_addr(addr, |addr| Self::connect_timeout(addr, Duration::ZERO)) } pub fn connect_timeout(addr: &SocketAddr, duration: Duration) -> io::Result { diff --git a/library/std/src/sys/net/connection/xous/udp.rs b/library/std/src/sys/net/connection/xous/udp.rs index 2127d3267ed4..ce54ea3b79ef 100644 --- a/library/std/src/sys/net/connection/xous/udp.rs +++ b/library/std/src/sys/net/connection/xous/udp.rs @@ -3,9 +3,10 @@ use core::sync::atomic::{Atomic, AtomicUsize, Ordering}; use super::*; use crate::cell::Cell; -use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}; +use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, ToSocketAddrs}; use crate::os::xous::services; use crate::sync::Arc; +use crate::sys::net::connection::each_addr; use crate::time::Duration; use crate::{fmt, io}; @@ -32,40 +33,45 @@ pub struct UdpSocket { } impl UdpSocket { - pub fn bind(socketaddr: io::Result<&SocketAddr>) -> io::Result { - let addr = socketaddr?; - // Construct the request - let mut connect_request = ConnectRequest { raw: [0u8; 4096] }; + pub fn bind(addr: A) -> io::Result { + return each_addr(addr, inner); - // Serialize the StdUdpBind structure. This is done "manually" because we don't want to - // make an auto-serdes (like bincode or rkyv) crate a dependency of Xous. - let port_bytes = addr.port().to_le_bytes(); - connect_request.raw[0] = port_bytes[0]; - connect_request.raw[1] = port_bytes[1]; - match addr.ip() { - IpAddr::V4(addr) => { - connect_request.raw[2] = 4; - for (dest, src) in connect_request.raw[3..].iter_mut().zip(addr.octets()) { - *dest = src; + fn inner(addr: &SocketAddr) -> io::Result { + // Construct the request + let mut connect_request = ConnectRequest { raw: [0u8; 4096] }; + + // Serialize the StdUdpBind structure. This is done "manually" because we don't want to + // make an auto-serdes (like bincode or rkyv) crate a dependency of Xous. + let port_bytes = addr.port().to_le_bytes(); + connect_request.raw[0] = port_bytes[0]; + connect_request.raw[1] = port_bytes[1]; + match addr.ip() { + IpAddr::V4(addr) => { + connect_request.raw[2] = 4; + for (dest, src) in connect_request.raw[3..].iter_mut().zip(addr.octets()) { + *dest = src; + } + } + IpAddr::V6(addr) => { + connect_request.raw[2] = 6; + for (dest, src) in connect_request.raw[3..].iter_mut().zip(addr.octets()) { + *dest = src; + } } } - IpAddr::V6(addr) => { - connect_request.raw[2] = 6; - for (dest, src) in connect_request.raw[3..].iter_mut().zip(addr.octets()) { - *dest = src; - } - } - } - let response = crate::os::xous::ffi::lend_mut( - services::net_server(), - services::NetLendMut::StdUdpBind.into(), - &mut connect_request.raw, - 0, - 4096, - ); + let response = crate::os::xous::ffi::lend_mut( + services::net_server(), + services::NetLendMut::StdUdpBind.into(), + &mut connect_request.raw, + 0, + 4096, + ); + + let Ok((_, valid)) = response else { + return Err(io::const_error!(io::ErrorKind::InvalidInput, "invalid response")); + }; - if let Ok((_, valid)) = response { // The first four bytes should be zero upon success, and will be nonzero // for an error. let response = connect_request.raw; @@ -87,8 +93,9 @@ impl UdpSocket { )); } } + let fd = response[1] as u16; - return Ok(UdpSocket { + Ok(UdpSocket { fd, local: *addr, remote: Cell::new(None), @@ -96,9 +103,8 @@ impl UdpSocket { write_timeout: Cell::new(0), handle_count: Arc::new(AtomicUsize::new(1)), nonblocking: Cell::new(false), - }); + }) } - Err(io::const_error!(io::ErrorKind::InvalidInput, "invalid response")) } pub fn peer_addr(&self) -> io::Result { @@ -198,10 +204,11 @@ impl UdpSocket { self.peek_from(buf).map(|(len, _addr)| len) } - pub fn connect(&self, maybe_addr: io::Result<&SocketAddr>) -> io::Result<()> { - let addr = maybe_addr?; - self.remote.set(Some(*addr)); - Ok(()) + pub fn connect(&self, addr: A) -> io::Result<()> { + each_addr(addr, |addr| { + self.remote.set(Some(*addr)); + Ok(()) + }) } pub fn send(&self, buf: &[u8]) -> io::Result { diff --git a/library/std/src/sys/net/mod.rs b/library/std/src/sys/net/mod.rs index 5df1fe138ab2..dffc4ea7f81a 100644 --- a/library/std/src/sys/net/mod.rs +++ b/library/std/src/sys/net/mod.rs @@ -1,46 +1,4 @@ -cfg_select! { - any( - all(target_family = "unix", not(target_os = "l4re")), - target_os = "windows", - target_os = "hermit", - all(target_os = "wasi", target_env = "p2"), - target_os = "solid_asp3", - ) => { - mod connection { - mod socket; - pub use socket::*; - } - } - all(target_vendor = "fortanix", target_env = "sgx") => { - mod connection { - mod sgx; - pub use sgx::*; - } - } - all(target_os = "wasi", target_env = "p1") => { - mod connection { - mod wasip1; - pub use wasip1::*; - } - } - target_os = "xous" => { - mod connection { - mod xous; - pub use xous::*; - } - } - target_os = "uefi" => { - mod connection { - mod uefi; - pub use uefi::*; - } - } - _ => { - mod connection { - mod unsupported; - pub use unsupported::*; - } - } -} - +/// This module contains the implementations of `TcpStream`, `TcpListener` and +/// `UdpSocket` as well as related functionality like DNS resolving. +mod connection; pub use connection::*; diff --git a/library/std/src/sys/platform_version/darwin/public_extern.rs b/library/std/src/sys/platform_version/darwin/public_extern.rs index 967cdb4920fd..c0848d94798f 100644 --- a/library/std/src/sys/platform_version/darwin/public_extern.rs +++ b/library/std/src/sys/platform_version/darwin/public_extern.rs @@ -77,6 +77,10 @@ use super::{current_version, pack_i32_os_version}; // NOTE: This symbol has a workaround in the compiler's symbol mangling to avoid mangling it, while // still not exposing it from non-cdylib (like `#[no_mangle]` would). #[rustc_std_internal_symbol] +// NOTE: Making this a weak symbol might not be entirely the right solution for this, `compiler_rt` +// doesn't do that, it instead makes the symbol have "hidden" visibility. But since this is placed +// in `libstd`, which might be used as a dylib, we cannot do the same here. +#[linkage = "weak"] // extern "C" is correct, Clang assumes the function cannot unwind: // https://github.com/llvm/llvm-project/blob/llvmorg-20.1.0/clang/lib/CodeGen/CGObjC.cpp#L3980 // @@ -145,6 +149,7 @@ pub(super) extern "C" fn __isPlatformVersionAtLeast( /// Old entry point for availability. Used when compiling with older Clang versions. // SAFETY: Same as for `__isPlatformVersionAtLeast`. #[rustc_std_internal_symbol] +#[linkage = "weak"] pub(super) extern "C" fn __isOSVersionAtLeast(major: i32, minor: i32, subminor: i32) -> i32 { let version = pack_i32_os_version(major, minor, subminor); (version <= current_version()) as i32 diff --git a/library/std/src/sys/platform_version/darwin/tests.rs b/library/std/src/sys/platform_version/darwin/tests.rs index 76dc4482c983..eecd58ec79e3 100644 --- a/library/std/src/sys/platform_version/darwin/tests.rs +++ b/library/std/src/sys/platform_version/darwin/tests.rs @@ -28,6 +28,9 @@ fn compare_against_sw_vers() { let subminor: i32 = sw_vers.next().unwrap_or("0").parse().unwrap(); assert_eq!(sw_vers.count(), 0); + // Test directly against the lookup + assert_eq!(lookup_version().get(), pack_os_version(major as _, minor as _, subminor as _)); + // Current version is available assert_eq!(__isOSVersionAtLeast(major, minor, subminor), 1); @@ -40,9 +43,6 @@ fn compare_against_sw_vers() { assert_eq!(__isOSVersionAtLeast(major, minor, subminor + 1), 0); assert_eq!(__isOSVersionAtLeast(major, minor + 1, subminor), 0); assert_eq!(__isOSVersionAtLeast(major + 1, minor, subminor), 0); - - // Test directly against the lookup - assert_eq!(lookup_version().get(), pack_os_version(major as _, minor as _, subminor as _)); } #[test] diff --git a/library/std/tests/floats/f32.rs b/library/std/tests/floats/f32.rs index c29d803b25e4..3acd06709141 100644 --- a/library/std/tests/floats/f32.rs +++ b/library/std/tests/floats/f32.rs @@ -193,13 +193,13 @@ fn test_atanh() { #[test] fn test_gamma() { // precision can differ between platforms - assert_approx_eq!(1.0f32.gamma(), 1.0f32); - assert_approx_eq!(2.0f32.gamma(), 1.0f32); - assert_approx_eq!(3.0f32.gamma(), 2.0f32); + assert_approx_eq!(1.0f32.gamma(), 1.0f32, APPROX_DELTA); + assert_approx_eq!(2.0f32.gamma(), 1.0f32, APPROX_DELTA); + assert_approx_eq!(3.0f32.gamma(), 2.0f32, APPROX_DELTA); assert_approx_eq!(4.0f32.gamma(), 6.0f32, APPROX_DELTA); assert_approx_eq!(5.0f32.gamma(), 24.0f32, APPROX_DELTA); - assert_approx_eq!(0.5f32.gamma(), consts::PI.sqrt()); - assert_approx_eq!((-0.5f32).gamma(), -2.0 * consts::PI.sqrt()); + assert_approx_eq!(0.5f32.gamma(), consts::PI.sqrt(), APPROX_DELTA); + assert_approx_eq!((-0.5f32).gamma(), -2.0 * consts::PI.sqrt(), APPROX_DELTA); assert_eq!(0.0f32.gamma(), f32::INFINITY); assert_eq!((-0.0f32).gamma(), f32::NEG_INFINITY); assert!((-1.0f32).gamma().is_nan()); diff --git a/library/std/tests/sync/barrier.rs b/library/std/tests/sync/barrier.rs index 8aefff9d5071..a66bd6296999 100644 --- a/library/std/tests/sync/barrier.rs +++ b/library/std/tests/sync/barrier.rs @@ -1,3 +1,4 @@ +use std::panic::RefUnwindSafe; use std::sync::mpsc::{TryRecvError, channel}; use std::sync::{Arc, Barrier}; use std::thread; @@ -33,3 +34,11 @@ fn test_barrier() { } assert!(leader_found); } + +/// Asserts that `Barrier` is ref unwind safe. +/// +/// See . +const _: () = { + const fn check_ref_unwind_safe() {} + check_ref_unwind_safe::(); +}; diff --git a/library/test/Cargo.toml b/library/test/Cargo.toml index 2a32a7dd76ee..fe749847b7c0 100644 --- a/library/test/Cargo.toml +++ b/library/test/Cargo.toml @@ -6,7 +6,7 @@ version = "0.0.0" edition = "2024" [dependencies] -getopts = { version = "0.2.21", features = ['rustc-dep-of-std'] } +getopts = { version = "0.2.24", default-features = false, features = ['rustc-dep-of-std'] } std = { path = "../std", public = true } core = { path = "../core", public = true } diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 820dda5a6524..a5f0718bc01a 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -88,6 +88,7 @@ impl Step for Docs { tarball.set_product_name("Rust Documentation"); tarball.add_bulk_dir(builder.doc_out(host), dest); tarball.add_file(builder.src.join("src/doc/robots.txt"), dest, FileType::Regular); + tarball.add_file(builder.src.join("src/doc/sitemap.txt"), dest, FileType::Regular); Some(tarball.generate()) } diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 89a0ab7711ee..229adf714598 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -1805,7 +1805,7 @@ mod snapshot { insta::assert_snapshot!( ctx.config("check") .path("compiler") - .render_steps(), @"[check] rustc 0 -> rustc 1 (74 crates)"); + .render_steps(), @"[check] rustc 0 -> rustc 1 (75 crates)"); } #[test] @@ -1831,7 +1831,7 @@ mod snapshot { ctx.config("check") .path("compiler") .stage(1) - .render_steps(), @"[check] rustc 0 -> rustc 1 (74 crates)"); + .render_steps(), @"[check] rustc 0 -> rustc 1 (75 crates)"); } #[test] @@ -1845,7 +1845,7 @@ mod snapshot { [build] llvm [build] rustc 0 -> rustc 1 [build] rustc 1 -> std 1 - [check] rustc 1 -> rustc 2 (74 crates) + [check] rustc 1 -> rustc 2 (75 crates) "); } @@ -1861,7 +1861,7 @@ mod snapshot { [build] rustc 0 -> rustc 1 [build] rustc 1 -> std 1 [check] rustc 1 -> std 1 - [check] rustc 1 -> rustc 2 (74 crates) + [check] rustc 1 -> rustc 2 (75 crates) [check] rustc 1 -> rustc 2 [check] rustc 1 -> Rustdoc 2 [check] rustc 1 -> rustc_codegen_cranelift 2 @@ -1957,7 +1957,7 @@ mod snapshot { ctx.config("check") .paths(&["library", "compiler"]) .args(&args) - .render_steps(), @"[check] rustc 0 -> rustc 1 (74 crates)"); + .render_steps(), @"[check] rustc 0 -> rustc 1 (75 crates)"); } #[test] diff --git a/src/ci/docker/scripts/rfl-build.sh b/src/ci/docker/scripts/rfl-build.sh index 7e0fb5794f47..b7d7151b171d 100755 --- a/src/ci/docker/scripts/rfl-build.sh +++ b/src/ci/docker/scripts/rfl-build.sh @@ -2,9 +2,7 @@ set -euo pipefail -# https://github.com/rust-lang/rust/pull/144443 -# https://github.com/rust-lang/rust/pull/145928 -LINUX_VERSION=8851e27d2cb947ea8bbbe8e812068f7bf5cbd00b +LINUX_VERSION=v6.17-rc5 # Build rustc, rustdoc, cargo, clippy-driver and rustfmt ../x.py build --stage 2 library rustdoc clippy rustfmt diff --git a/src/doc/nomicon b/src/doc/nomicon index 57ed44736605..f17a018b9989 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 57ed4473660565d9357fcae176b358d7e8724ebf +Subproject commit f17a018b9989430967d1c58e9a12c51169abc744 diff --git a/src/doc/reference b/src/doc/reference index 89f67b3c1b90..b3ce60628c6f 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 89f67b3c1b904cbcd9ed55e443d6fc67c8ca2769 +Subproject commit b3ce60628c6f55ab8ff3dba9f3d20203df1c0dee diff --git a/src/doc/robots.txt b/src/doc/robots.txt index 3a2552e9a159..71a60f89c14c 100644 --- a/src/doc/robots.txt +++ b/src/doc/robots.txt @@ -9,3 +9,5 @@ Disallow: /beta/book/first-edition/ Disallow: /beta/book/second-edition/ Disallow: /nightly/book/first-edition/ Disallow: /nightly/book/second-edition/ + +Sitemap: https://doc.rust-lang.org/sitemap.txt diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index ad27f82c1846..dd26bc8e726d 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit ad27f82c18464525c761a4a8db2e01785da59e1f +Subproject commit dd26bc8e726dc2e73534c8972d4dccd1bed7495f diff --git a/src/doc/rustc-dev-guide/.github/workflows/ci.yml b/src/doc/rustc-dev-guide/.github/workflows/ci.yml index 6eabb999fb01..2dd695b7a473 100644 --- a/src/doc/rustc-dev-guide/.github/workflows/ci.yml +++ b/src/doc/rustc-dev-guide/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: if: github.repository == 'rust-lang/rustc-dev-guide' runs-on: ubuntu-latest env: - MDBOOK_VERSION: 0.4.48 + MDBOOK_VERSION: 0.4.52 MDBOOK_LINKCHECK2_VERSION: 0.9.1 MDBOOK_MERMAID_VERSION: 0.12.6 MDBOOK_OUTPUT__LINKCHECK__FOLLOW_WEB_LINKS: ${{ github.event_name != 'pull_request' }} diff --git a/src/doc/rustc-dev-guide/rust-version b/src/doc/rustc-dev-guide/rust-version index f412399cc8c3..df2bac877b66 100644 --- a/src/doc/rustc-dev-guide/rust-version +++ b/src/doc/rustc-dev-guide/rust-version @@ -1 +1 @@ -a1dbb443527bd126452875eb5d5860c1d001d761 +2f3f27bf79ec147fec9d2e7980605307a74067f4 diff --git a/src/doc/rustc-dev-guide/src/about-this-guide.md b/src/doc/rustc-dev-guide/src/about-this-guide.md index f3957724967c..f1a406a1c29b 100644 --- a/src/doc/rustc-dev-guide/src/about-this-guide.md +++ b/src/doc/rustc-dev-guide/src/about-this-guide.md @@ -73,7 +73,7 @@ You might also find the following sites useful: - [compiler-team] -- the home-base for the Rust compiler team, with description of the team procedures, active working groups, and the team calendar. - [std-dev-guide] -- a similar guide for developing the standard library. -- [The t-compiler zulip][z] +- [The t-compiler Zulip][z] - The [Rust Internals forum][rif], a place to ask questions and discuss Rust's internals - The [Rust reference][rr], even though it doesn't specifically talk about diff --git a/src/doc/rustc-dev-guide/src/appendix/code-index.md b/src/doc/rustc-dev-guide/src/appendix/code-index.md index 65fbf752d792..4ddb58b0c39b 100644 --- a/src/doc/rustc-dev-guide/src/appendix/code-index.md +++ b/src/doc/rustc-dev-guide/src/appendix/code-index.md @@ -13,7 +13,7 @@ Item | Kind | Short description | Chapter | `DefId` | struct | One of four types of HIR node identifiers | [Identifiers in the HIR] | [compiler/rustc_hir/src/def_id.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/def_id/struct.DefId.html) `Diag` | struct | A struct for a compiler diagnostic, such as an error or lint | [Emitting Diagnostics] | [compiler/rustc_errors/src/diagnostic.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.Diag.html) `DocContext` | struct | A state container used by rustdoc when crawling through a crate to gather its documentation | [Rustdoc] | [src/librustdoc/core.rs](https://github.com/rust-lang/rust/blob/master/src/librustdoc/core.rs) -`HirId` | struct | One of four types of HIR node identifiers | [Identifiers in the HIR] | [compiler/rustc_hir/src/hir_id.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir_id/struct.HirId.html) +`HirId` | struct | One of four types of HIR node identifiers | [Identifiers in the HIR] | [compiler/rustc_hir_id/src/lib.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/struct.HirId.html) `Lexer` | struct | This is the lexer used during parsing. It consumes characters from the raw source code being compiled and produces a series of tokens for use by the rest of the parser | [The parser] | [compiler/rustc_parse/src/lexer/mod.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/lexer/struct.Lexer.html) `NodeId` | struct | One of four types of HIR node identifiers. Being phased out | [Identifiers in the HIR] | [compiler/rustc_ast/src/ast.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/node_id/struct.NodeId.html) `P` | struct | An owned immutable smart pointer. By contrast, `&T` is not owned, and `Box` is not immutable. | None | [compiler/rustc_ast/src/ptr.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/ptr/struct.P.html) diff --git a/src/doc/rustc-dev-guide/src/backend/debugging.md b/src/doc/rustc-dev-guide/src/backend/debugging.md index 4f8712dfaf3c..3dc95f25d4ae 100644 --- a/src/doc/rustc-dev-guide/src/backend/debugging.md +++ b/src/doc/rustc-dev-guide/src/backend/debugging.md @@ -183,7 +183,7 @@ The quick summary is: ### Getting help and asking questions If you have some questions, head over to the [rust-lang Zulip] and -specifically the `#t-compiler/wg-llvm` stream. +specifically the `#t-compiler/wg-llvm` channel. [rust-lang Zulip]: https://rust-lang.zulipchat.com/ diff --git a/src/doc/rustc-dev-guide/src/compiler-debugging.md b/src/doc/rustc-dev-guide/src/compiler-debugging.md index edd2aa6c5f64..f45144704180 100644 --- a/src/doc/rustc-dev-guide/src/compiler-debugging.md +++ b/src/doc/rustc-dev-guide/src/compiler-debugging.md @@ -367,7 +367,7 @@ error: layout_of(&'a u32) = Layout { error: aborting due to previous error ``` -[`Layout`]: https://doc.rust-lang.org/nightly/nightly-rustc/stable_mir/abi/struct.Layout.html +[`Layout`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_public/abi/struct.Layout.html ## Configuring CodeLLDB for debugging `rustc` diff --git a/src/doc/rustc-dev-guide/src/compiler-src.md b/src/doc/rustc-dev-guide/src/compiler-src.md index d67bacb1b339..27b40f1fe017 100644 --- a/src/doc/rustc-dev-guide/src/compiler-src.md +++ b/src/doc/rustc-dev-guide/src/compiler-src.md @@ -153,7 +153,8 @@ The bulk of [`rustdoc`] is in [`librustdoc`]. However, the [`rustdoc`] binary itself is [`src/tools/rustdoc`], which does nothing except call [`rustdoc::main`]. There is also `JavaScript` and `CSS` for the docs in [`src/tools/rustdoc-js`] -and [`src/tools/rustdoc-themes`]. +and [`src/tools/rustdoc-themes`]. The type definitions for `--output-format=json` +are in a separate crate in [`src/rustdoc-json-types`]. You can read more about [`rustdoc`] in [this chapter][rustdoc-chapter]. @@ -162,6 +163,7 @@ You can read more about [`rustdoc`] in [this chapter][rustdoc-chapter]. [`src/tools/rustdoc-js`]: https://github.com/rust-lang/rust/tree/master/src/tools/rustdoc-js [`src/tools/rustdoc-themes`]: https://github.com/rust-lang/rust/tree/master/src/tools/rustdoc-themes [`src/tools/rustdoc`]: https://github.com/rust-lang/rust/tree/master/src/tools/rustdoc +[`src/rustdoc-json-types`]: https://github.com/rust-lang/rust/tree/master/src/rustdoc-json-types [rustdoc-chapter]: ./rustdoc.md ## Tests diff --git a/src/doc/rustc-dev-guide/src/compiler-team.md b/src/doc/rustc-dev-guide/src/compiler-team.md index 9922ee7ddf23..6be52833f396 100644 --- a/src/doc/rustc-dev-guide/src/compiler-team.md +++ b/src/doc/rustc-dev-guide/src/compiler-team.md @@ -12,7 +12,7 @@ contributions to rustc and its design. Currently the compiler team chats in Zulip: - Team chat occurs in the [`t-compiler`][zulip-t-compiler] stream on the Zulip instance -- There are also a number of other associated Zulip streams, +- There are also a number of other associated Zulip channels, such as [`t-compiler/help`][zulip-help], where people can ask for help with rustc development, or [`t-compiler/meetings`][zulip-meetings], where the team holds their weekly triage and steering meetings. diff --git a/src/doc/rustc-dev-guide/src/contributing.md b/src/doc/rustc-dev-guide/src/contributing.md index 963bef3af8de..3d196ae2308f 100644 --- a/src/doc/rustc-dev-guide/src/contributing.md +++ b/src/doc/rustc-dev-guide/src/contributing.md @@ -26,8 +26,7 @@ conditions that trigger the bug, or part of the error message if there is any. An example could be: **"impossible case reached" on lifetime inference for impl Trait in return position**. -Opening an issue is as easy as following [this -link](https://github.com/rust-lang/rust/issues/new/choose) and filling out the fields +Opening an issue is as easy as following [thi link][create an issue] and filling out the fields in the appropriate provided template. ## Bug fixes or "normal" code changes @@ -75,7 +74,7 @@ Example of things that might require MCPs include major refactorings, changes to important types, or important changes to how the compiler does something, or smaller user-facing changes. -**When in doubt, ask on [zulip]. It would be a shame to put a lot of work +**When in doubt, ask on [Zulip]. It would be a shame to put a lot of work into a PR that ends up not getting merged!** [See this document][mcpinfo] for more info on MCPs. @@ -127,7 +126,7 @@ when contributing to Rust under [the git section](./git.md). > from), and work with the compiler team to see if we can help you **break down a large potentially > unreviewable PR into a series of smaller more individually reviewable PRs**. > -> You can communicate with the compiler team by creating a [#t-compiler thread on zulip][t-compiler] +> You can communicate with the compiler team by creating a [#t-compiler thread on Zulip][t-compiler] > to discuss your proposed changes. > > Communicating with the compiler team beforehand helps in several ways: @@ -154,11 +153,14 @@ The CI in rust-lang/rust applies your patches directly against the current maste not against the commit your branch is based on. This can lead to unexpected failures if your branch is outdated, even when there are no explicit merge conflicts. -Before submitting or updating a PR, make sure to update your branch -as mentioned [here](git.md#keeping-things-up-to-date) if it's significantly -behind the master branch (e.g., more than 100 commits behind). -This fetches the latest master branch and rebases your changes on top of it, -ensuring your PR is tested against the latest code. +Update your branch only when needed: when you have merge conflicts, upstream CI is broken and blocking your green PR, or a maintainer requests it. +Avoid updating an already-green PR under review unless necessary. +During review, make incremental commits to address feedback. +Prefer to squash or rebase only at the end, or when a reviewer requests it. + +When updating, use `git push --force-with-lease` and leave a brief comment explaining what changed. +Some repos prefer merging from `upstream/master` instead of rebasing; follow the project's conventions. +See [keeping things up to date](git.md#keeping-things-up-to-date) for detailed instructions. After rebasing, it's recommended to [run the relevant tests locally](tests/intro.md) to catch any issues before CI runs. @@ -372,6 +374,11 @@ You can also use `rustdoc` directly to check small fixes. For example, `rustdoc src/doc/reference.md` will render reference to `doc/reference.html`. The CSS might be messed up, but you can verify that the HTML is right. +Please notice that we don't accept typography/spellcheck fixes to **internal documentation** +as it's usually not worth the churn or the review time. +Examples of internal documentation is code comments and rustc api docs. +However, feel free to fix those if accompanied by other improvements in the same PR. + ### Contributing to rustc-dev-guide Contributions to the [rustc-dev-guide] are always welcome, and can be made directly at @@ -434,7 +441,8 @@ Just a few things to keep in mind: #### ⚠️ Note: Where to contribute `rustc-dev-guide` changes -For detailed information about where to contribute rustc-dev-guide changes and the benefits of doing so, see [the rustc-dev-guide working group documentation](https://forge.rust-lang.org/wg-rustc-dev-guide/index.html#where-to-contribute-rustc-dev-guide-changes). +For detailed information about where to contribute rustc-dev-guide changes and the benefits of doing so, +see [the rustc-dev-guide working group documentation]. ## Issue triage @@ -451,6 +459,7 @@ Please see . [regression-]: https://github.com/rust-lang/rust/labels?q=regression [relnotes]: https://github.com/rust-lang/rust/labels/relnotes [S-tracking-]: https://github.com/rust-lang/rust/labels?q=s-tracking +[the rustc-dev-guide working group documentation]: https://forge.rust-lang.org/wg-rustc-dev-guide/index.html#where-to-contribute-rustc-dev-guide-changes ### Rfcbot labels @@ -498,3 +507,4 @@ This section has moved to the ["About this guide"] chapter. [RFC 1574]: https://github.com/rust-lang/rfcs/blob/master/text/1574-more-api-documentation-conventions.md#appendix-a-full-conventions-text [rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/ [rdgrepo]: https://github.com/rust-lang/rustc-dev-guide +[create an issue]: https://github.com/rust-lang/rust/issues/new/choose diff --git a/src/doc/rustc-dev-guide/src/hir.md b/src/doc/rustc-dev-guide/src/hir.md index 38ba33112f2e..0b341a40f1dd 100644 --- a/src/doc/rustc-dev-guide/src/hir.md +++ b/src/doc/rustc-dev-guide/src/hir.md @@ -102,7 +102,7 @@ These identifiers can be converted into one another through the `TyCtxt`. [`DefId`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/def_id/struct.DefId.html [`LocalDefId`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/def_id/struct.LocalDefId.html -[`HirId`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir_id/struct.HirId.html +[`HirId`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/struct.HirId.html [`BodyId`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/struct.BodyId.html [Node]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/enum.Node.html [`CrateNum`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/def_id/struct.CrateNum.html diff --git a/src/doc/rustc-dev-guide/src/notification-groups/arm.md b/src/doc/rustc-dev-guide/src/notification-groups/arm.md index 3abc32c68883..5b79030d20de 100644 --- a/src/doc/rustc-dev-guide/src/notification-groups/arm.md +++ b/src/doc/rustc-dev-guide/src/notification-groups/arm.md @@ -9,7 +9,7 @@ This list will be used to ask for help both in diagnosing and testing ARM-related issues as well as suggestions on how to resolve interesting questions regarding our ARM support. -The group also has an associated Zulip stream ([`#t-compiler/arm`]) +The group also has an associated Zulip channel ([`#t-compiler/arm`]) where people can go to pose questions and discuss ARM-specific topics. diff --git a/src/doc/rustc-dev-guide/src/notification-groups/emscripten.md b/src/doc/rustc-dev-guide/src/notification-groups/emscripten.md index 100dbdf9f2b3..9e4086c884e0 100644 --- a/src/doc/rustc-dev-guide/src/notification-groups/emscripten.md +++ b/src/doc/rustc-dev-guide/src/notification-groups/emscripten.md @@ -9,7 +9,7 @@ This list will be used to ask for help both in diagnosing and testing Emscripten-related issues as well as suggestions on how to resolve interesting questions regarding our Emscripten support. -The group also has an associated Zulip stream ([`#t-compiler/wasm`]) +The group also has an associated Zulip channel ([`#t-compiler/wasm`]) where people can go to pose questions and discuss Emscripten-specific topics. diff --git a/src/doc/rustc-dev-guide/src/notification-groups/risc-v.md b/src/doc/rustc-dev-guide/src/notification-groups/risc-v.md index 1b31297b600e..7c8a3cdf8a64 100644 --- a/src/doc/rustc-dev-guide/src/notification-groups/risc-v.md +++ b/src/doc/rustc-dev-guide/src/notification-groups/risc-v.md @@ -9,7 +9,7 @@ This list will be used to ask for help both in diagnosing and testing RISC-V-related issues as well as suggestions on how to resolve interesting questions regarding our RISC-V support. -The group also has an associated Zulip stream ([`#t-compiler/risc-v`]) +The group also has an associated Zulip channel ([`#t-compiler/risc-v`]) where people can go to pose questions and discuss RISC-V-specific topics. diff --git a/src/doc/rustc-dev-guide/src/notification-groups/rust-for-linux.md b/src/doc/rustc-dev-guide/src/notification-groups/rust-for-linux.md index 696f2038e1a4..ed1de9196de6 100644 --- a/src/doc/rustc-dev-guide/src/notification-groups/rust-for-linux.md +++ b/src/doc/rustc-dev-guide/src/notification-groups/rust-for-linux.md @@ -12,7 +12,7 @@ and features. The RfL maintainers should then ideally provide support for resolving the breakage or decide to temporarily accept the breakage and unblock CI by temporarily removing the RfL CI jobs. -The group also has an associated Zulip stream ([`#rust-for-linux`]) +The group also has an associated Zulip channel ([`#rust-for-linux`]) where people can go to ask questions and discuss topics related to Rust for Linux. diff --git a/src/doc/rustc-dev-guide/src/notification-groups/wasi.md b/src/doc/rustc-dev-guide/src/notification-groups/wasi.md index e438ee4bd090..88b9465be018 100644 --- a/src/doc/rustc-dev-guide/src/notification-groups/wasi.md +++ b/src/doc/rustc-dev-guide/src/notification-groups/wasi.md @@ -9,7 +9,7 @@ This list will be used to ask for help both in diagnosing and testing WASI-related issues as well as suggestions on how to resolve interesting questions regarding our WASI support. -The group also has an associated Zulip stream ([`#t-compiler/wasm`]) +The group also has an associated Zulip channel ([`#t-compiler/wasm`]) where people can go to pose questions and discuss WASI-specific topics. diff --git a/src/doc/rustc-dev-guide/src/notification-groups/wasm.md b/src/doc/rustc-dev-guide/src/notification-groups/wasm.md index c8b674cb93f2..6f52b04251f0 100644 --- a/src/doc/rustc-dev-guide/src/notification-groups/wasm.md +++ b/src/doc/rustc-dev-guide/src/notification-groups/wasm.md @@ -9,7 +9,7 @@ This list will be used to ask for help both in diagnosing and testing WebAssembly-related issues as well as suggestions on how to resolve interesting questions regarding our WASM support. -The group also has an associated Zulip stream ([`#t-compiler/wasm`]) +The group also has an associated Zulip channel ([`#t-compiler/wasm`]) where people can go to pose questions and discuss WASM-specific topics. diff --git a/src/doc/rustc-dev-guide/src/notification-groups/windows.md b/src/doc/rustc-dev-guide/src/notification-groups/windows.md index e615a2cbd8de..d245208e2abc 100644 --- a/src/doc/rustc-dev-guide/src/notification-groups/windows.md +++ b/src/doc/rustc-dev-guide/src/notification-groups/windows.md @@ -9,7 +9,7 @@ This list will be used to ask for help both in diagnosing and testing Windows-related issues as well as suggestions on how to resolve interesting questions regarding our Windows support. -The group also has an associated Zulip stream ([`#t-compiler/windows`]) +The group also has an associated Zulip channel ([`#t-compiler/windows`]) where people can go to pose questions and discuss Windows-specific topics. diff --git a/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-json-test-suite.md b/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-json-test-suite.md index e08f77095069..10e9452eda3f 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-json-test-suite.md +++ b/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-json-test-suite.md @@ -1,3 +1,83 @@ # The `rustdoc-json` test suite -> **FIXME**: This section is a stub. It will be populated by [PR #2422](https://github.com/rust-lang/rustc-dev-guide/pull/2422/). +This page is specifically about the test suite named `rustdoc-json`, which tests rustdoc's [json output]. +For other test suites used for testing rustdoc, see [§Rustdoc test suites](../tests/compiletest.md#rustdoc-test-suites). + +Tests are run with compiletest, and have access to the usual set of [directives](../tests/directives.md). +Frequenly used directives here are: + +- [`//@ aux-build`][aux-build] to have dependencies. +- `//@ edition: 2021` (or some other edition). +- `//@ compile-flags: --document-hidden-items` to enable [document private items]. + +Each crate's json output is checked by 2 programs: [jsondoclint](#jsondocck) and [jsondocck](#jsondocck). + +## jsondoclint + +[jsondoclint] checks that all [`Id`]s exist in the `index` (or `paths`). +This makes sure there are no dangling [`Id`]s. + + + +## jsondocck + +[jsondocck] processes direcives given in comments, to assert that the values in the output are expected. +It's alot like [htmldocck](./rustdoc-test-suite.md) in that way. + +It uses [JSONPath] as a query language, which takes a path, and returns a *list* of values that that path is said to match to. + +### Directives + +- `//@ has `: Checks `` exists, i.e. matches at least 1 value. +- `//@ !has `: Checks `` doesn't exist, i.e. matches 0 values. +- `//@ has `: Check `` exists, and at least 1 of the matches is equal to the given `` +- `//@ !has `: Checks `` exists, but none of the matches equal the given ``. +- `//@ is `: Check `` matches exactly one value, and it's equal to the given ``. +- `//@ is ...`: Check that `` matches to exactly every given ``. + Ordering doesn't matter here. +- `//@ !is `: Check `` matches exactly one value, and that value is not equal to the given ``. +- `//@ count `: Check that `` matches to `` of values. +- `//@ set = `: Check that `` matches exactly one value, and store that value to the variable called ``. + +These are defined in [`directive.rs`]. + +### Values + +Values can be either JSON values, or variables. + +- JSON values are JSON literals, e.g. `true`, `"string"`, `{"key": "value"}`. + These often need to be quoted using `'`, to be processed as 1 value. See [§Argument spliting](#argument-spliting) +- Variables can be used to store the value in one path, and use it in later queries. + They are set with the `//@ set = ` directive, and accessed with `$` + + ```rust + //@ set foo = $some.path + //@ is $.some.other.path $foo + ``` + +### Argument spliting + +Arguments to directives are split using the [shlex] crate, which implements POSIX shell escaping. +This is because both `` and `` arguments to [directives](#directives) frequently have both +whitespace and quote marks. + +To use the `@ is` with a `` of `$.index[?(@.docs == "foo")].some.field` and a value of `"bar"` [^why_quote], you'd write: + +```rust +//@ is '$.is[?(@.docs == "foo")].some.field' '"bar"' +``` + +[^why_quote]: The value needs to be `"bar"` *after* shlex splitting, because we + it needs to be a JSON string value. + +[json output]: https://doc.rust-lang.org/nightly/rustdoc/unstable-features.html#json-output +[jsondocck]: https://github.com/rust-lang/rust/tree/master/src/tools/jsondocck +[jsondoclint]: https://github.com/rust-lang/rust/tree/master/src/tools/jsondoclint +[aux-build]: ../tests/compiletest.md#building-auxiliary-crates +[`Id`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustdoc_json_types/struct.Id.html +[document private items]: https://doc.rust-lang.org/nightly/rustdoc/command-line-arguments.html#--document-private-items-show-items-that-are-not-public +[`directive.rs`]: https://github.com/rust-lang/rust/blob/master/src/tools/jsondocck/src/directive.rs +[shlex]: https://docs.rs/shlex/1.3.0/shlex/index.html +[JSONPath]: https://www.rfc-editor.org/rfc/rfc9535.html diff --git a/src/doc/rustc-dev-guide/src/rustdoc.md b/src/doc/rustc-dev-guide/src/rustdoc.md index 9290fcd3b41c..6127a894a0ff 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc.md +++ b/src/doc/rustc-dev-guide/src/rustdoc.md @@ -107,7 +107,7 @@ This comes with several caveats: in particular, rustdoc *cannot* run any parts o require type-checking bodies; for example it cannot generate `.rlib` files or run most lints. We want to move away from this model eventually, but we need some alternative for [the people using it][async-std]; see [various][zulip stop accepting broken code] -[previous][rustdoc meeting 2024-07-08] [zulip][compiler meeting 2023-01-26] [discussion][notriddle rfc]. +[previous][rustdoc meeting 2024-07-08] [Zulip][compiler meeting 2023-01-26] [discussion][notriddle rfc]. For examples of code that breaks if this hack is removed, see [`tests/rustdoc-ui/error-in-impl-trait`]. diff --git a/src/doc/rustc-dev-guide/src/serialization.md b/src/doc/rustc-dev-guide/src/serialization.md index 8eb37bbe20be..702d3cfa6d5e 100644 --- a/src/doc/rustc-dev-guide/src/serialization.md +++ b/src/doc/rustc-dev-guide/src/serialization.md @@ -106,7 +106,7 @@ type wrapper, like [`ty::Predicate`] and manually implementing `Encodable` and [`Encodable`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_serialize/trait.Encodable.html [`Encoder`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_serialize/trait.Encoder.html [`RefDecodable`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/codec/trait.RefDecodable.html -[`rustc_middle`]: https://doc.rust-lang.org/nightly/nightly-rustc/src/rustc_type_ir/codec.rs.html#21 +[`rustc_middle`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/index.html [`ty::Predicate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/predicate/struct.Predicate.html [`TyCtxt`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html [`TyDecodable`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_macros/derive.TyDecodable.html diff --git a/src/doc/rustc-dev-guide/src/solve/caching.md b/src/doc/rustc-dev-guide/src/solve/caching.md index e568d47ca252..cb7403de4e07 100644 --- a/src/doc/rustc-dev-guide/src/solve/caching.md +++ b/src/doc/rustc-dev-guide/src/solve/caching.md @@ -106,7 +106,7 @@ We can implement this optimization in the future. [`provisional_result`]: https://github.com/rust-lang/rust/blob/7606c13961ddc1174b70638e934df0439b7dc515/compiler/rustc_trait_selection/src/solve/search_graph.rs#L57 [initial-prov-result]: https://github.com/rust-lang/rust/blob/7606c13961ddc1174b70638e934df0439b7dc515/compiler/rustc_trait_selection/src/solve/search_graph.rs#L366-L370 [fixpoint]: https://github.com/rust-lang/rust/blob/7606c13961ddc1174b70638e934df0439b7dc515/compiler/rustc_trait_selection/src/solve/search_graph.rs#L425-L446 -[^2]: summarizing the relevant [zulip thread] +[^2]: summarizing the relevant [Zulip thread] [zulip thread]: https://rust-lang.zulipchat.com/#narrow/stream/364551-t-types.2Ftrait-system-refactor/topic/global.20cache [unstable-result-ex]: https://github.com/rust-lang/rust/blob/7606c13961ddc1174b70638e934df0439b7dc515/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.rs#L4-L16 diff --git a/src/doc/rustc-dev-guide/src/solve/the-solver.md b/src/doc/rustc-dev-guide/src/solve/the-solver.md index 006fb649d220..0e095b55437e 100644 --- a/src/doc/rustc-dev-guide/src/solve/the-solver.md +++ b/src/doc/rustc-dev-guide/src/solve/the-solver.md @@ -71,6 +71,6 @@ fails. ## Learning more The solver should be fairly self-contained. I hope that the above information provides a -good foundation when looking at the code itself. Please reach out on zulip if you get stuck +good foundation when looking at the code itself. Please reach out on Zulip if you get stuck while doing so or there are some quirks and design decisions which were unclear and deserve better comments or should be mentioned here. diff --git a/src/doc/rustc-dev-guide/src/stabilization_guide.md b/src/doc/rustc-dev-guide/src/stabilization_guide.md index e399930fc523..7b9e1eb5629b 100644 --- a/src/doc/rustc-dev-guide/src/stabilization_guide.md +++ b/src/doc/rustc-dev-guide/src/stabilization_guide.md @@ -82,7 +82,7 @@ Most importantly, remove the code which flags an error if the feature-gate is no gate_all!(pub_restricted, "`pub(restricted)` syntax is experimental"); ``` -This `gate_feature_post!` macro prints an error if the `pub_restricted` feature is not enabled. It is not needed now that `#[pub_restricted]` is stable. +The `gate_all!` macro reports an error if the `pub_restricted` feature is not enabled. It is not needed now that `pub(restricted)` is stable. For more subtle features, you may find code like this: diff --git a/src/doc/rustc-dev-guide/src/tests/directives.md b/src/doc/rustc-dev-guide/src/tests/directives.md index 4ff6b7cb10f0..4be78fac4ec7 100644 --- a/src/doc/rustc-dev-guide/src/tests/directives.md +++ b/src/doc/rustc-dev-guide/src/tests/directives.md @@ -36,9 +36,9 @@ directive. The following is a list of compiletest directives. Directives are linked to sections that describe the command in more detail if available. This list may not be exhaustive. Directives can generally be found by browsing the -`TestProps` structure found in [`header.rs`] from the compiletest source. +`TestProps` structure found in [`directives.rs`] from the compiletest source. -[`header.rs`]: https://github.com/rust-lang/rust/tree/master/src/tools/compiletest/src/header.rs +[`directives.rs`]: https://github.com/rust-lang/rust/tree/master/src/tools/compiletest/src/directives.rs ### Assembly @@ -374,7 +374,7 @@ the directive's backing store (holds the command's current value) at runtime. To add a new directive property: 1. Look for the `pub struct TestProps` declaration in - [`src/tools/compiletest/src/header.rs`] and add the new public property to + [`src/tools/compiletest/src/directives.rs`] and add the new public property to the end of the declaration. 2. Look for the `impl TestProps` implementation block immediately following the struct declaration and initialize the new property to its default value. @@ -383,7 +383,7 @@ To add a new directive property: When `compiletest` encounters a test file, it parses the file a line at a time by calling every parser defined in the `Config` struct's implementation block, -also in [`src/tools/compiletest/src/header.rs`] (note that the `Config` struct's +also in [`src/tools/compiletest/src/directives.rs`] (note that the `Config` struct's declaration block is found in [`src/tools/compiletest/src/common.rs`]). `TestProps`'s `load_from()` method will try passing the current line of text to each parser, which, in turn typically checks to see if the line begins with a @@ -406,7 +406,7 @@ and their associated parsers immediately above to see how they are used to avoid writing additional parsing code unnecessarily. As a concrete example, here is the implementation for the -`parse_failure_status()` parser, in [`src/tools/compiletest/src/header.rs`]: +`parse_failure_status()` parser, in [`src/tools/compiletest/src/directives.rs`]: ```diff @@ -232,6 +232,7 @@ pub struct TestProps { @@ -508,6 +508,6 @@ example, `//@ failure-status: 1`, `self.props.failure_status` will evaluate to 1, as `parse_failure_status()` will have overridden the `TestProps` default value, for that test specifically. -[`src/tools/compiletest/src/header.rs`]: https://github.com/rust-lang/rust/tree/master/src/tools/compiletest/src/header.rs +[`src/tools/compiletest/src/directives.rs`]: https://github.com/rust-lang/rust/tree/master/src/tools/compiletest/src/directives.rs [`src/tools/compiletest/src/common.rs`]: https://github.com/rust-lang/rust/tree/master/src/tools/compiletest/src/common.rs [`src/tools/compiletest/src/runtest.rs`]: https://github.com/rust-lang/rust/tree/master/src/tools/compiletest/src/runtest.rs diff --git a/src/doc/rustc-dev-guide/src/traits/chalk.md b/src/doc/rustc-dev-guide/src/traits/chalk.md index 844f42b9879f..ca5ed5259173 100644 --- a/src/doc/rustc-dev-guide/src/traits/chalk.md +++ b/src/doc/rustc-dev-guide/src/traits/chalk.md @@ -5,7 +5,7 @@ Its goal is to enable a lot of trait system features and bug fixes that are hard to implement (e.g. GATs or specialization). If you would like to help in hacking on the new solver, drop by on the rust-lang Zulip in the [`#t-types`] -stream and say hello! +channel and say hello! [Types team]: https://github.com/rust-lang/types-team [`#t-types`]: https://rust-lang.zulipchat.com/#narrow/stream/144729-t-types diff --git a/src/doc/rustc-dev-guide/src/type-inference.md b/src/doc/rustc-dev-guide/src/type-inference.md index 2243205f129b..24982a209fd0 100644 --- a/src/doc/rustc-dev-guide/src/type-inference.md +++ b/src/doc/rustc-dev-guide/src/type-inference.md @@ -239,13 +239,13 @@ differently. It uses canonical queries for trait solving which use [`take_and_reset_region_constraints`] at the end. This extracts all of the outlives constraints added during the canonical query. This is required as the NLL solver must not only know *what* regions outlive each other, -but also *where*. Finally, the NLL solver invokes [`take_region_var_origins`], +but also *where*. Finally, the NLL solver invokes [`get_region_var_infos`], providing all region variables to the solver. -[`resolve_regions_and_report_errors`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/infer/struct.InferCtxt.html#method.resolve_regions_and_report_errors +[`resolve_regions_and_report_errors`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/traits/struct.ObligationCtxt.html#method.resolve_regions_and_report_errors [`lexical_region_resolve`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/infer/lexical_region_resolve/index.html [`take_and_reset_region_constraints`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/infer/struct.InferCtxt.html#method.take_and_reset_region_constraints -[`take_region_var_origins`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/infer/struct.InferCtxt.html#method.take_region_var_origins +[`get_region_var_infos`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/infer/struct.InferCtxt.html#method.get_region_var_infos ## Lexical region resolution diff --git a/src/doc/rustc-dev-guide/src/typing_parameter_envs.md b/src/doc/rustc-dev-guide/src/typing_parameter_envs.md index db15467a47a0..45635ebfa15d 100644 --- a/src/doc/rustc-dev-guide/src/typing_parameter_envs.md +++ b/src/doc/rustc-dev-guide/src/typing_parameter_envs.md @@ -2,11 +2,14 @@ ## Typing Environments -When interacting with the type system there are a few variables to consider that can affect the results of trait solving. The set of in-scope where clauses, and what phase of the compiler type system operations are being performed in (the [`ParamEnv`][penv] and [`TypingMode`][tmode] structs respectively). +When interacting with the type system there are a few variables to consider that can affect the results of trait solving. +The set of in-scope where clauses, and what phase of the compiler type system operations are being performed in (the [`ParamEnv`][penv] and [`TypingMode`][tmode] structs respectively). -When an environment to perform type system operations in has not yet been created, the [`TypingEnv`][tenv] can be used to bundle all of the external context required into a single type. +When an environment to perform type system operations in has not yet been created, +the [`TypingEnv`][tenv] can be used to bundle all of the external context required into a single type. -Once a context to perform type system operations in has been created (e.g. an [`ObligationCtxt`][ocx] or [`FnCtxt`][fnctxt]) a `TypingEnv` is typically not stored anywhere as only the `TypingMode` is a property of the whole environment, whereas different `ParamEnv`s can be used on a per-goal basis. +Once a context to perform type system operations in has been created (e.g. an [`ObligationCtxt`][ocx] or [`FnCtxt`][fnctxt]) a `TypingEnv` is typically not stored anywhere as only the `TypingMode` is a property of the whole environment, +whereas different `ParamEnv`s can be used on a per-goal basis. [ocx]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/traits/struct.ObligationCtxt.html [fnctxt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/fn_ctxt/struct.FnCtxt.html @@ -15,9 +18,14 @@ Once a context to perform type system operations in has been created (e.g. an [` ### What is a `ParamEnv` -The [`ParamEnv`][penv] is a list of in-scope where-clauses, it typically corresponds to a specific item's where clauses. Some clauses are not explicitly written but are instead implicitly added in the [`predicates_of`][predicates_of] query, such as `ConstArgHasType` or (some) implied bounds. +The [`ParamEnv`][penv] is a list of in-scope where-clauses, +it typically corresponds to a specific item's where clauses. +Some clauses are not explicitly written but are instead implicitly added in the [`predicates_of`][predicates_of] query, +such as `ConstArgHasType` or (some) implied bounds. -In most cases `ParamEnv`s are initially created via the [`param_env` query][query] which returns a `ParamEnv` derived from the provided item's where clauses. A `ParamEnv` can also be created with arbitrary sets of clauses that are not derived from a specific item, such as in [`compare_method_predicate_entailment`][method_pred_entailment] where we create a hybrid `ParamEnv` consisting of the impl's where clauses and the trait definition's function's where clauses. +In most cases `ParamEnv`s are initially created via the [`param_env` query][query] which returns a `ParamEnv` derived from the provided item's where clauses. +A `ParamEnv` can also be created with arbitrary sets of clauses that are not derived from a specific item, +such as in [`compare_method_predicate_entailment`][method_pred_entailment] where we create a hybrid `ParamEnv` consisting of the impl's where clauses and the trait definition's function's where clauses. --- @@ -30,7 +38,9 @@ where ::Assoc: Clone, {} ``` -If we were conceptually inside of `foo` (for example, type-checking or linting it) we would use this `ParamEnv` everywhere that we interact with the type system. This would allow things such as [normalization], evaluating generic constants, and proving where clauses/goals, to rely on `T` being sized, implementing `Trait`, etc. +If we were conceptually inside of `foo` (for example, type-checking or linting it) we would use this `ParamEnv` everywhere that we interact with the type system. +This would allow things such as [normalization], evaluating generic constants, +and proving where clauses/goals, to rely on `T` being sized, implementing `Trait`, etc. A more concrete example: ```rust @@ -72,9 +82,13 @@ fn foo2(a: T) { ### Acquiring a `ParamEnv` -Using the wrong [`ParamEnv`][penv] when interacting with the type system can lead to ICEs, illformed programs compiling, or erroring when we shouldn't. See [#82159](https://github.com/rust-lang/rust/pull/82159) and [#82067](https://github.com/rust-lang/rust/pull/82067) as examples of PRs that modified the compiler to use the correct param env and in the process fixed ICEs. +Using the wrong [`ParamEnv`][penv] when interacting with the type system can lead to ICEs, +illformed programs compiling, or erroring when we shouldn't. +See [#82159](https://github.com/rust-lang/rust/pull/82159) and [#82067](https://github.com/rust-lang/rust/pull/82067) as examples of PRs that modified the compiler to use the correct param env and in the process fixed ICEs. -In the large majority of cases, when a `ParamEnv` is required it either already exists somewhere in scope, or above in the call stack and should be passed down. A non exhaustive list of places where you might find an existing `ParamEnv`: +In the large majority of cases, when a `ParamEnv` is required it either already exists somewhere in scope, +or above in the call stack and should be passed down. +A non exhaustive list of places where you might find an existing `ParamEnv`: - During typeck `FnCtxt` has a [`param_env` field][fnctxt_param_env] - When writing late lints the `LateContext` has a [`param_env` field][latectxt_param_env] - During well formedness checking the `WfCheckingCtxt` has a [`param_env` field][wfckctxt_param_env] @@ -82,16 +96,20 @@ In the large majority of cases, when a `ParamEnv` is required it either already - In the next-gen trait solver all `Goal`s have a [`param_env` field][goal_param_env] specifying what environment to prove the goal in - When editing an existing [`TypeRelation`][typerelation] if it implements [`PredicateEmittingRelation`][predicate_emitting_relation] then a [`param_env` method][typerelation_param_env] will be available. -If you aren't sure if there's a `ParamEnv` in scope somewhere that can be used it can be worth opening a thread in the [`#t-compiler/help`][compiler_help] zulip stream where someone may be able to point out where a `ParamEnv` can be acquired from. +If you aren't sure if there's a `ParamEnv` in scope somewhere that can be used it can be worth opening a thread in the [`#t-compiler/help`][compiler_help] Zulip channel where someone may be able to point out where a `ParamEnv` can be acquired from. -Manually constructing a `ParamEnv` is typically only needed at the start of some kind of top level analysis (e.g. hir typeck or borrow checking). In such cases there are three ways it can be done: +Manually constructing a `ParamEnv` is typically only needed at the start of some kind of top level analysis (e.g. hir typeck or borrow checking). +In such cases there are three ways it can be done: - Calling the [`tcx.param_env(def_id)` query][param_env_query] which returns the environment associated with a given definition. - Creating an empty environment with [`ParamEnv::empty`][env_empty]. -- Using [`ParamEnv::new`][param_env_new] to construct an env with an arbitrary set of where clauses. Then calling [`traits::normalize_param_env_or_error`][normalize_env_or_error] to handle normalizing and elaborating all the where clauses in the env. +- Using [`ParamEnv::new`][param_env_new] to construct an env with an arbitrary set of where clauses. + Then calling [`traits::normalize_param_env_or_error`][normalize_env_or_error] to handle normalizing and elaborating all the where clauses in the env. Using the `param_env` query is by far the most common way to construct a `ParamEnv` as most of the time the compiler is performing an analysis as part of some specific definition. -Creating an empty environment with `ParamEnv::empty` is typically only done either in codegen (indirectly via [`TypingEnv::fully_monomorphized`][tenv_mono]), or as part of some analysis that do not expect to ever encounter generic parameters (e.g. various parts of coherence/orphan check). +Creating an empty environment with `ParamEnv::empty` is typically only done either in codegen (indirectly via [`TypingEnv::fully_monomorphized`][tenv_mono]), +or as part of some analysis that do not expect to ever encounter generic parameters +(e.g. various parts of coherence/orphan check). Creating an env from an arbitrary set of where clauses is usually unnecessary and should only be done if the environment you need does not correspond to an actual item in the source code (e.g. [`compare_method_predicate_entailment`][method_pred_entailment]). @@ -113,11 +131,14 @@ Creating an env from an arbitrary set of where clauses is usually unnecessary an ### How are `ParamEnv`s constructed -Creating a [`ParamEnv`][pe] is more complicated than simply using the list of where clauses defined on an item as written by the user. We need to both elaborate supertraits into the env and fully normalize all aliases. This logic is handled by [`traits::normalize_param_env_or_error`][normalize_env_or_error] (even though it does not mention anything about elaboration). +Creating a [`ParamEnv`][pe] is more complicated than simply using the list of where clauses defined on an item as written by the user. +We need to both elaborate supertraits into the env and fully normalize all aliases. +This logic is handled by [`traits::normalize_param_env_or_error`][normalize_env_or_error] (even though it does not mention anything about elaboration). #### Elaborating supertraits -When we have a function such as `fn foo()` we would like to be able to prove `T: Clone` inside of the function as the `Copy` trait has a `Clone` supertrait. Constructing a `ParamEnv` looks at all of the trait bounds in the env and explicitly adds new where clauses to the `ParamEnv` for any supertraits found on the traits. +When we have a function such as `fn foo()` we would like to be able to prove `T: Clone` inside of the function as the `Copy` trait has a `Clone` supertrait. +Constructing a `ParamEnv` looks at all of the trait bounds in the env and explicitly adds new where clauses to the `ParamEnv` for any supertraits found on the traits. A concrete example would be the following function: ```rust @@ -133,13 +154,16 @@ fn bar(a: T) { fn requires_impl(a: T) {} ``` -If we did not elaborate the env then the `requires_impl` call would fail to typecheck as we would not be able to prove `T: Clone` or `T: SuperSuperTrait`. In practice we elaborate the env which means that `bar`'s `ParamEnv` is actually: +If we did not elaborate the env then the `requires_impl` call would fail to typecheck as we would not be able to prove `T: Clone` or `T: SuperSuperTrait`. +In practice we elaborate the env which means that `bar`'s `ParamEnv` is actually: `[T: Sized, T: Copy, T: Clone, T: Trait, T: SuperTrait, T: SuperSuperTrait]` This allows us to prove `T: Clone` and `T: SuperSuperTrait` when type checking `bar`. The `Clone` trait has a `Sized` supertrait however we do not end up with two `T: Sized` bounds in the env (one for the supertrait and one for the implicitly added `T: Sized` bound) as the elaboration process (implemented via [`util::elaborate`][elaborate]) deduplicates where clauses. -A side effect of this is that even if no actual elaboration of supertraits takes place, the existing where clauses in the env are _also_ deduplicated. See the following example: +A side effect of this is that even if no actual elaboration of supertraits takes place, +the existing where clauses in the env are _also_ deduplicated. +See the following example: ```rust trait Trait {} // The unelaborated `ParamEnv` would be: @@ -156,7 +180,8 @@ The [next-gen trait solver][next-gen-solver] also requires this elaboration to t #### Normalizing all bounds -In the old trait solver the where clauses stored in `ParamEnv` are required to be fully normalized as otherwise the trait solver will not function correctly. A concrete example of needing to normalize the `ParamEnv` is the following: +In the old trait solver the where clauses stored in `ParamEnv` are required to be fully normalized as otherwise the trait solver will not function correctly. +A concrete example of needing to normalize the `ParamEnv` is the following: ```rust trait Trait { type Assoc; @@ -182,11 +207,14 @@ where fn requires_impl>(_: U) {} ``` -As humans we can tell that `::Bar` is equal to `u32` so the trait bound on `U` is equivalent to `U: Trait`. In practice trying to prove `U: Trait` in the old solver in this environment would fail as it is unable to determine that `::Bar` is equal to `u32`. +As humans we can tell that `::Bar` is equal to `u32` so the trait bound on `U` is equivalent to `U: Trait`. +In practice trying to prove `U: Trait` in the old solver in this environment would fail as it is unable to determine that `::Bar` is equal to `u32`. To work around this we normalize `ParamEnv`'s after constructing them so that `foo`'s `ParamEnv` is actually: `[T: Sized, U: Sized, U: Trait]` which means the trait solver is now able to use the `U: Trait` in the `ParamEnv` to determine that the trait bound `U: Trait` holds. -This workaround does not work in all cases as normalizing associated types requires a `ParamEnv` which introduces a bootstrapping problem. We need a normalized `ParamEnv` in order for normalization to give correct results, but we need to normalize to get that `ParamEnv`. Currently we normalize the `ParamEnv` once using the unnormalized param env and it tends to give okay results in practice even though there are some examples where this breaks ([example]). +This workaround does not work in all cases as normalizing associated types requires a `ParamEnv` which introduces a bootstrapping problem. +We need a normalized `ParamEnv` in order for normalization to give correct results, but we need to normalize to get that `ParamEnv`. +Currently we normalize the `ParamEnv` once using the unnormalized param env and it tends to give okay results in practice even though there are some examples where this breaks ([example]). In the next-gen trait solver the requirement for all where clauses in the `ParamEnv` to be fully normalized is not present and so we do not normalize when constructing `ParamEnv`s. @@ -196,9 +224,12 @@ In the next-gen trait solver the requirement for all where clauses in the `Param ## Typing Modes -Depending on what context we are performing type system operations in, different behaviour may be required. For example during coherence there are stronger requirements about when we can consider goals to not hold or when we can consider types to be unequal. +Depending on what context we are performing type system operations in, +different behaviour may be required. +For example during coherence there are stronger requirements about when we can consider goals to not hold or when we can consider types to be unequal. -Tracking which "phase" of the compiler type system operations are being performed in is done by the [`TypingMode`][tmode] enum. The documentation on the `TypingMode` enum is quite good so instead of repeating it here verbatim we would recommend reading the API documentation directly. +Tracking which "phase" of the compiler type system operations are being performed in is done by the [`TypingMode`][tmode] enum. +The documentation on the `TypingMode` enum is quite good so instead of repeating it here verbatim we would recommend reading the API documentation directly. [penv]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html [tenv]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypingEnv.html diff --git a/src/doc/rustc-dev-guide/triagebot.toml b/src/doc/rustc-dev-guide/triagebot.toml index 3ac5d57a52b0..4a8852391520 100644 --- a/src/doc/rustc-dev-guide/triagebot.toml +++ b/src/doc/rustc-dev-guide/triagebot.toml @@ -90,7 +90,6 @@ does not need reviews. You can request a review using `r? rustc-dev-guide` or \ [assign.adhoc_groups] rustc-dev-guide = [ "@BoxyUwU", - "@jieyouxu", "@jyn514", "@tshepang", ] diff --git a/src/doc/sitemap.txt b/src/doc/sitemap.txt new file mode 100644 index 000000000000..6e5f0fbad37f --- /dev/null +++ b/src/doc/sitemap.txt @@ -0,0 +1,4 @@ +https://doc.rust-lang.org/stable/ +https://doc.rust-lang.org/beta/ +https://doc.rust-lang.org/nightly/ + diff --git a/src/librustdoc/clean/render_macro_matchers.rs b/src/librustdoc/clean/render_macro_matchers.rs index d684e6f8650f..b5a8d64ff4f5 100644 --- a/src/librustdoc/clean/render_macro_matchers.rs +++ b/src/librustdoc/clean/render_macro_matchers.rs @@ -3,6 +3,7 @@ use rustc_ast::tokenstream::{TokenStream, TokenTree}; use rustc_ast_pretty::pprust::PrintState; use rustc_ast_pretty::pprust::state::State as Printer; use rustc_middle::ty::TyCtxt; +use rustc_parse::lexer::StripTokens; use rustc_session::parse::ParseSess; use rustc_span::symbol::{Ident, Symbol, kw}; use rustc_span::{FileName, Span}; @@ -64,14 +65,18 @@ fn snippet_equal_to_token(tcx: TyCtxt<'_>, matcher: &TokenTree) -> Option parser, - Err(errs) => { - errs.into_iter().for_each(|err| err.cancel()); - return None; - } - }; + let mut parser = match rustc_parse::new_parser_from_source_str( + &psess, + file_name, + snippet.clone(), + StripTokens::Nothing, + ) { + Ok(parser) => parser, + Err(errs) => { + errs.into_iter().for_each(|err| err.cancel()); + return None; + } + }; // Reparse a single token tree. if parser.token == token::Eof { diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs index f229f77c9784..5eaadc9eb451 100644 --- a/src/librustdoc/doctest/make.rs +++ b/src/librustdoc/doctest/make.rs @@ -10,6 +10,7 @@ use rustc_ast::tokenstream::TokenTree; use rustc_ast::{self as ast, AttrStyle, HasAttrs, StmtKind}; use rustc_errors::emitter::stderr_destination; use rustc_errors::{ColorConfig, DiagCtxtHandle}; +use rustc_parse::lexer::StripTokens; use rustc_parse::new_parser_from_source_str; use rustc_session::parse::ParseSess; use rustc_span::edition::{DEFAULT_EDITION, Edition}; @@ -468,14 +469,16 @@ fn parse_source( let dcx = DiagCtxt::new(Box::new(emitter)).disable_warnings(); let psess = ParseSess::with_dcx(dcx, sm); - let mut parser = match new_parser_from_source_str(&psess, filename, wrapped_source) { - Ok(p) => p, - Err(errs) => { - errs.into_iter().for_each(|err| err.cancel()); - reset_error_count(&psess); - return Err(()); - } - }; + // Don't strip any tokens; it wouldn't matter anyway because the source is wrapped in a function. + let mut parser = + match new_parser_from_source_str(&psess, filename, wrapped_source, StripTokens::Nothing) { + Ok(p) => p, + Err(errs) => { + errs.into_iter().for_each(|err| err.cancel()); + reset_error_count(&psess); + return Err(()); + } + }; fn push_to_s(s: &mut String, source: &str, span: rustc_span::Span, prev_span_hi: &mut usize) { let extra_len = DOCTEST_CODE_WRAPPER.len(); diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index feafb41dc990..0e06361024b9 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -578,7 +578,7 @@ pub(super) fn write_code( } fn write_footer(out: &mut String, playground_button: Option<&str>) { - write_str(out, format_args_nl!("{}", playground_button.unwrap_or_default())); + write_str(out, format_args!("{}", playground_button.unwrap_or_default())); } /// How a span of text is classified. Mostly corresponds to token kinds. diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index f62eba4b3c19..9871066b9eb5 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -10,7 +10,6 @@ #![feature(box_patterns)] #![feature(debug_closure_helpers)] #![feature(file_buffered)] -#![feature(format_args_nl)] #![feature(if_let_guard)] #![feature(iter_advance_by)] #![feature(iter_intersperse)] diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index 9aa2f3cf0a5b..9645a26a68ae 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -364,7 +364,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> { // priority. if let Some(fn_id) = typeck.type_dependent_def_id(hir_id) && let Some(trait_id) = cx.tcx.trait_of_assoc(fn_id) - && let arg_ty = cx.tcx.erase_regions(adjusted_ty) + && let arg_ty = cx.tcx.erase_and_anonymize_regions(adjusted_ty) && let ty::Ref(_, sub_ty, _) = *arg_ty.kind() && let args = typeck.node_args_opt(hir_id).map(|args| &args[1..]).unwrap_or_default() diff --git a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs index 74283d7ba863..43bb97235550 100644 --- a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs +++ b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs @@ -8,6 +8,7 @@ use rustc_ast::{CoroutineKind, Fn, FnRetTy, Item, ItemKind}; use rustc_errors::emitter::HumanEmitter; use rustc_errors::{Diag, DiagCtxt}; use rustc_lint::LateContext; +use rustc_parse::lexer::StripTokens; use rustc_parse::new_parser_from_source_str; use rustc_parse::parser::ForceCollect; use rustc_session::parse::ParseSess; @@ -49,13 +50,14 @@ pub fn check( let sm = Arc::new(SourceMap::new(FilePathMapping::empty())); let psess = ParseSess::with_dcx(dcx, sm); - let mut parser = match new_parser_from_source_str(&psess, filename, code) { - Ok(p) => p, - Err(errs) => { - errs.into_iter().for_each(Diag::cancel); - return (false, test_attr_spans); - }, - }; + let mut parser = + match new_parser_from_source_str(&psess, filename, code, StripTokens::ShebangAndFrontmatter) { + Ok(p) => p, + Err(errs) => { + errs.into_iter().for_each(Diag::cancel); + return (false, test_attr_spans); + }, + }; let mut relevant_main_found = false; let mut eligible = true; diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs index 010652e1cb90..6ce7f0b1f0bc 100644 --- a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs @@ -140,7 +140,7 @@ fn is_ref_iterable<'tcx>( let res_ty = cx .tcx - .erase_regions(EarlyBinder::bind(req_res_ty).instantiate(cx.tcx, typeck.node_args(call_expr.hir_id))); + .erase_and_anonymize_regions(EarlyBinder::bind(req_res_ty).instantiate(cx.tcx, typeck.node_args(call_expr.hir_id))); let mutbl = if let ty::Ref(_, _, mutbl) = *req_self_ty.kind() { Some(mutbl) } else { diff --git a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs index a42763172f56..809a6728e128 100644 --- a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs +++ b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs @@ -252,7 +252,7 @@ impl<'tcx> LateLintPass<'tcx> for OnlyUsedInRecursion { { ( trait_item_id, - FnKind::ImplTraitFn(std::ptr::from_ref(cx.tcx.erase_regions(trait_ref.args)) as usize), + FnKind::ImplTraitFn(std::ptr::from_ref(cx.tcx.erase_and_anonymize_regions(trait_ref.args)) as usize), usize::from(sig.decl.implicit_self.has_implicit_self()), ) } else { diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs index 3842c4eb60e8..6aeb22d41a7d 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs @@ -45,7 +45,7 @@ pub(super) fn check<'tcx>( Applicability::MaybeIncorrect, ); triggered = true; - } else if (cx.tcx.erase_regions(from_ty) != cx.tcx.erase_regions(to_ty)) && !const_context { + } else if (cx.tcx.erase_and_anonymize_regions(from_ty) != cx.tcx.erase_and_anonymize_regions(to_ty)) && !const_context { span_lint_and_then( cx, TRANSMUTE_PTR_TO_PTR, diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs index 26323af31228..3e6aae475ecc 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs @@ -12,8 +12,8 @@ pub(super) fn check<'tcx>( from_ty_orig: Ty<'tcx>, to_ty_orig: Ty<'tcx>, ) -> bool { - let mut from_ty = cx.tcx.erase_regions(from_ty_orig); - let mut to_ty = cx.tcx.erase_regions(to_ty_orig); + let mut from_ty = cx.tcx.erase_and_anonymize_regions(from_ty_orig); + let mut to_ty = cx.tcx.erase_and_anonymize_regions(to_ty_orig); while from_ty != to_ty { let reduced_tys = reduce_refs(cx, from_ty, to_ty); diff --git a/src/tools/clippy/clippy_lints/src/useless_conversion.rs b/src/tools/clippy/clippy_lints/src/useless_conversion.rs index 70ae982a4458..e45f884cfcbc 100644 --- a/src/tools/clippy/clippy_lints/src/useless_conversion.rs +++ b/src/tools/clippy/clippy_lints/src/useless_conversion.rs @@ -98,7 +98,7 @@ fn into_iter_bound<'tcx>( if tr.def_id() == into_iter_did { into_iter_span = Some(*span); } else { - let tr = cx.tcx.erase_regions(tr); + let tr = cx.tcx.erase_and_anonymize_regions(tr); if tr.has_escaping_bound_vars() { return None; } diff --git a/src/tools/clippy/clippy_utils/src/sym.rs b/src/tools/clippy/clippy_utils/src/sym.rs index 278101ac27f9..8033b74a8d25 100644 --- a/src/tools/clippy/clippy_utils/src/sym.rs +++ b/src/tools/clippy/clippy_utils/src/sym.rs @@ -194,7 +194,6 @@ generate! { itertools, join, kw, - last, lazy_static, lint_vec, ln, diff --git a/src/tools/clippy/clippy_utils/src/ty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/mod.rs index 8e302f9d2ad1..9f77a1c4d9b6 100644 --- a/src/tools/clippy/clippy_utils/src/ty/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ty/mod.rs @@ -285,7 +285,7 @@ pub fn implements_trait_with_env_from_iter<'tcx>( let _ = tcx.hir_body_owner_kind(callee_id); } - let ty = tcx.erase_regions(ty); + let ty = tcx.erase_and_anonymize_regions(ty); if ty.has_escaping_bound_vars() { return false; } diff --git a/src/tools/linkchecker/Cargo.toml b/src/tools/linkchecker/Cargo.toml index fb5bff3fe63f..f0886e31b243 100644 --- a/src/tools/linkchecker/Cargo.toml +++ b/src/tools/linkchecker/Cargo.toml @@ -10,3 +10,4 @@ path = "main.rs" [dependencies] regex = "1" html5ever = "0.29.0" +urlencoding = "2.1.3" diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs index 1dc45728c90c..e07a0784cdb3 100644 --- a/src/tools/linkchecker/main.rs +++ b/src/tools/linkchecker/main.rs @@ -232,18 +232,7 @@ enum FileEntry { type Cache = HashMap; fn small_url_encode(s: &str) -> String { - s.replace('<', "%3C") - .replace('>', "%3E") - .replace(' ', "%20") - .replace('?', "%3F") - .replace('\'', "%27") - .replace('&', "%26") - .replace(',', "%2C") - .replace(':', "%3A") - .replace(';', "%3B") - .replace('[', "%5B") - .replace(']', "%5D") - .replace('\"', "%22") + urlencoding::encode(s).to_string() } impl Checker { diff --git a/src/tools/linkchecker/tests/valid/inner/bar.html b/src/tools/linkchecker/tests/valid/inner/bar.html index 4b500d78b76e..6ffda259c40e 100644 --- a/src/tools/linkchecker/tests/valid/inner/bar.html +++ b/src/tools/linkchecker/tests/valid/inner/bar.html @@ -3,5 +3,8 @@

Bar

+ +

Bar

+ diff --git a/src/tools/linkchecker/tests/valid/inner/foo.html b/src/tools/linkchecker/tests/valid/inner/foo.html index 3c6a7483bcd4..f30bf7182051 100644 --- a/src/tools/linkchecker/tests/valid/inner/foo.html +++ b/src/tools/linkchecker/tests/valid/inner/foo.html @@ -8,7 +8,15 @@
external links not validated Redirect + + + + +

Local

+ +

Local

+ diff --git a/src/tools/linkchecker/tests/valid/inner/redir-target.html b/src/tools/linkchecker/tests/valid/inner/redir-target.html index bd59884a01ec..ac1dec6d5b4a 100644 --- a/src/tools/linkchecker/tests/valid/inner/redir-target.html +++ b/src/tools/linkchecker/tests/valid/inner/redir-target.html @@ -1,5 +1,8 @@

Redir

+ + +

Redir

diff --git a/src/tools/miri/tests/pass/static_align.rs b/src/tools/miri/tests/pass/static_align.rs new file mode 100644 index 000000000000..f292f028568b --- /dev/null +++ b/src/tools/miri/tests/pass/static_align.rs @@ -0,0 +1,14 @@ +#![feature(static_align)] + +// When a static uses `align(N)`, its address should be a multiple of `N`. + +#[rustc_align_static(256)] +static FOO: u64 = 0; + +#[rustc_align_static(512)] +static BAR: u64 = 0; + +fn main() { + assert!(core::ptr::from_ref(&FOO).addr().is_multiple_of(256)); + assert!(core::ptr::from_ref(&BAR).addr().is_multiple_of(512)); +} diff --git a/src/tools/rustfmt/src/parse/parser.rs b/src/tools/rustfmt/src/parse/parser.rs index 2ec8769c45f2..63c6c8c99d0d 100644 --- a/src/tools/rustfmt/src/parse/parser.rs +++ b/src/tools/rustfmt/src/parse/parser.rs @@ -3,6 +3,7 @@ use std::path::{Path, PathBuf}; use rustc_ast::{ast, attr}; use rustc_errors::Diag; +use rustc_parse::lexer::StripTokens; use rustc_parse::parser::Parser as RawParser; use rustc_parse::{exp, new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal}; use rustc_span::{Span, sym}; @@ -64,11 +65,14 @@ impl<'a> ParserBuilder<'a> { input: Input, ) -> Result, Vec>> { match input { - Input::File(ref file) => new_parser_from_file(psess, file, None), + Input::File(ref file) => { + new_parser_from_file(psess, file, StripTokens::ShebangAndFrontmatter, None) + } Input::Text(text) => new_parser_from_source_str( psess, rustc_span::FileName::Custom("stdin".to_owned()), text, + StripTokens::ShebangAndFrontmatter, ), } } @@ -104,8 +108,12 @@ impl<'a> Parser<'a> { span: Span, ) -> Result<(ast::AttrVec, ThinVec>, Span), ParserError> { let result = catch_unwind(AssertUnwindSafe(|| { - let mut parser = - unwrap_or_emit_fatal(new_parser_from_file(psess.inner(), path, Some(span))); + let mut parser = unwrap_or_emit_fatal(new_parser_from_file( + psess.inner(), + path, + StripTokens::ShebangAndFrontmatter, + Some(span), + )); match parser.parse_mod(exp!(Eof)) { Ok((a, i, spans)) => Some((a, i, spans.inner_span)), Err(e) => { diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index fee48bea144d..60347b2ea645 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -477,7 +477,6 @@ const PERMITTED_STDLIB_DEPENDENCIES: &[&str] = &[ "rustc-demangle", "rustc-literal-escaper", "shlex", - "unicode-width", "unwinding", "wasi", "windows-sys", diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index ee06707415f5..849dcb9e88fb 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -2021,7 +2021,6 @@ ui/parser/issues/issue-5806.rs ui/parser/issues/issue-58094-missing-right-square-bracket.rs ui/parser/issues/issue-58856-1.rs ui/parser/issues/issue-58856-2.rs -ui/parser/issues/issue-59418.rs ui/parser/issues/issue-60075.rs ui/parser/issues/issue-61858.rs ui/parser/issues/issue-62524.rs diff --git a/src/tools/unicode-table-generator/src/cascading_map.rs b/src/tools/unicode-table-generator/src/cascading_map.rs index 78a7bba32087..56e6401908dc 100644 --- a/src/tools/unicode-table-generator/src/cascading_map.rs +++ b/src/tools/unicode-table-generator/src/cascading_map.rs @@ -64,6 +64,7 @@ impl RawEmitter { writeln!(&mut self.file, "#[inline]").unwrap(); writeln!(&mut self.file, "pub const fn lookup(c: char) -> bool {{").unwrap(); + writeln!(&mut self.file, " debug_assert!(!c.is_ascii());").unwrap(); writeln!(&mut self.file, " match c as u32 >> 8 {{").unwrap(); for arm in arms { writeln!(&mut self.file, " {arm},").unwrap(); diff --git a/src/tools/unicode-table-generator/src/main.rs b/src/tools/unicode-table-generator/src/main.rs index aa7d97f7f3d7..ded9205ffc4b 100644 --- a/src/tools/unicode-table-generator/src/main.rs +++ b/src/tools/unicode-table-generator/src/main.rs @@ -195,6 +195,7 @@ fn load_data() -> UnicodeData { .into_iter() .flatten() .flat_map(|cp| cp.scalar()) + .filter(|c| !c.is_ascii()) .map(u32::from) .collect::>(); (prop, ranges_from_set(&codepoints)) diff --git a/src/tools/unicode-table-generator/src/raw_emitter.rs b/src/tools/unicode-table-generator/src/raw_emitter.rs index 03ed9499e26c..297965615c1a 100644 --- a/src/tools/unicode-table-generator/src/raw_emitter.rs +++ b/src/tools/unicode-table-generator/src/raw_emitter.rs @@ -98,6 +98,7 @@ impl RawEmitter { self.blank_line(); writeln!(&mut self.file, "pub const fn lookup(c: char) -> bool {{").unwrap(); + writeln!(&mut self.file, " debug_assert!(!c.is_ascii());").unwrap(); if first_code_point > 0x7f { writeln!(&mut self.file, " (c as u32) >= {first_code_point:#04x} &&").unwrap(); } diff --git a/src/tools/unicode-table-generator/src/skiplist.rs b/src/tools/unicode-table-generator/src/skiplist.rs index 34c9802e122f..660a8f342f7a 100644 --- a/src/tools/unicode-table-generator/src/skiplist.rs +++ b/src/tools/unicode-table-generator/src/skiplist.rs @@ -99,6 +99,7 @@ impl RawEmitter { if first_code_point > 0x7f { writeln!(&mut self.file, "#[inline]").unwrap(); writeln!(&mut self.file, "pub fn lookup(c: char) -> bool {{").unwrap(); + writeln!(&mut self.file, " debug_assert!(!c.is_ascii());").unwrap(); writeln!(&mut self.file, " (c as u32) >= {first_code_point:#04x} && lookup_slow(c)") .unwrap(); writeln!(&mut self.file, "}}").unwrap(); @@ -107,6 +108,7 @@ impl RawEmitter { writeln!(&mut self.file, "fn lookup_slow(c: char) -> bool {{").unwrap(); } else { writeln!(&mut self.file, "pub fn lookup(c: char) -> bool {{").unwrap(); + writeln!(&mut self.file, " debug_assert!(!c.is_ascii());").unwrap(); } writeln!(&mut self.file, " const {{").unwrap(); writeln!( diff --git a/src/tools/wasm-component-ld/Cargo.toml b/src/tools/wasm-component-ld/Cargo.toml index 23dc86998e88..3def2391a13f 100644 --- a/src/tools/wasm-component-ld/Cargo.toml +++ b/src/tools/wasm-component-ld/Cargo.toml @@ -10,4 +10,4 @@ name = "wasm-component-ld" path = "src/main.rs" [dependencies] -wasm-component-ld = "0.5.16" +wasm-component-ld = "0.5.17" diff --git a/tests/codegen-llvm/align-static.rs b/tests/codegen-llvm/align-static.rs new file mode 100644 index 000000000000..53db998919af --- /dev/null +++ b/tests/codegen-llvm/align-static.rs @@ -0,0 +1,31 @@ +//@ compile-flags: -C no-prepopulate-passes -Z mir-opt-level=0 + +#![crate_type = "lib"] +#![feature(static_align)] + +// CHECK: @STATIC_ALIGN = +// CHECK-SAME: align 16 +#[no_mangle] +#[rustc_align_static(16)] +pub static STATIC_ALIGN: u64 = 0; + +// CHECK: @ALIGN_SPECIFIED_TWICE_1 = +// CHECK-SAME: align 64 +#[no_mangle] +#[rustc_align_static(32)] +#[rustc_align_static(64)] +pub static ALIGN_SPECIFIED_TWICE_1: u64 = 0; + +// CHECK: @ALIGN_SPECIFIED_TWICE_2 = +// CHECK-SAME: align 128 +#[no_mangle] +#[rustc_align_static(128)] +#[rustc_align_static(32)] +pub static ALIGN_SPECIFIED_TWICE_2: u64 = 0; + +// CHECK: @ALIGN_SPECIFIED_TWICE_3 = +// CHECK-SAME: align 256 +#[no_mangle] +#[rustc_align_static(32)] +#[rustc_align_static(256)] +pub static ALIGN_SPECIFIED_TWICE_3: u64 = 0; diff --git a/tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir b/tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir index 8afb6ad250e0..a18d7e7478fc 100644 --- a/tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir @@ -1,30 +1,30 @@ // MIR for `address_of_reborrow` after SimplifyCfg-initial | User Type Annotations -| 0: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [Ty(General(U0))] }, span: $DIR/address_of.rs:8:10: 8:18, inferred_ty: *const [i32; 10] +| 0: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:8:10: 8:18, inferred_ty: *const [i32; 10] | 1: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [Region(U0)] }, span: $DIR/address_of.rs:10:10: 10:25, inferred_ty: *const dyn std::marker::Send -| 2: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [Ty(General(U0))] }, span: $DIR/address_of.rs:14:12: 14:20, inferred_ty: *const [i32; 10] -| 3: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [Ty(General(U0))] }, span: $DIR/address_of.rs:14:12: 14:20, inferred_ty: *const [i32; 10] +| 2: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:14:12: 14:20, inferred_ty: *const [i32; 10] +| 3: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:14:12: 14:20, inferred_ty: *const [i32; 10] | 4: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:15:12: 15:28, inferred_ty: *const [i32; 10] | 5: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:15:12: 15:28, inferred_ty: *const [i32; 10] | 6: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [Region(U0)] }, span: $DIR/address_of.rs:16:12: 16:27, inferred_ty: *const dyn std::marker::Send | 7: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [Region(U0)] }, span: $DIR/address_of.rs:16:12: 16:27, inferred_ty: *const dyn std::marker::Send | 8: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:17:12: 17:24, inferred_ty: *const [i32] | 9: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:17:12: 17:24, inferred_ty: *const [i32] -| 10: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [Ty(General(U0))] }, span: $DIR/address_of.rs:19:10: 19:18, inferred_ty: *const [i32; 10] +| 10: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:19:10: 19:18, inferred_ty: *const [i32; 10] | 11: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [Region(U0)] }, span: $DIR/address_of.rs:21:10: 21:25, inferred_ty: *const dyn std::marker::Send -| 12: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [Ty(General(U0))] }, span: $DIR/address_of.rs:24:12: 24:20, inferred_ty: *const [i32; 10] -| 13: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [Ty(General(U0))] }, span: $DIR/address_of.rs:24:12: 24:20, inferred_ty: *const [i32; 10] +| 12: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:24:12: 24:20, inferred_ty: *const [i32; 10] +| 13: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:24:12: 24:20, inferred_ty: *const [i32; 10] | 14: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:25:12: 25:28, inferred_ty: *const [i32; 10] | 15: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:25:12: 25:28, inferred_ty: *const [i32; 10] | 16: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [Region(U0)] }, span: $DIR/address_of.rs:26:12: 26:27, inferred_ty: *const dyn std::marker::Send | 17: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [Region(U0)] }, span: $DIR/address_of.rs:26:12: 26:27, inferred_ty: *const dyn std::marker::Send | 18: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:27:12: 27:24, inferred_ty: *const [i32] | 19: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:27:12: 27:24, inferred_ty: *const [i32] -| 20: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [Ty(General(U0))] }, span: $DIR/address_of.rs:29:10: 29:16, inferred_ty: *mut [i32; 10] +| 20: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:29:10: 29:16, inferred_ty: *mut [i32; 10] | 21: user_ty: Canonical { value: Ty(*mut dyn std::marker::Send), max_universe: U0, variables: [Region(U0)] }, span: $DIR/address_of.rs:31:10: 31:23, inferred_ty: *mut dyn std::marker::Send -| 22: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [Ty(General(U0))] }, span: $DIR/address_of.rs:34:12: 34:18, inferred_ty: *mut [i32; 10] -| 23: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [Ty(General(U0))] }, span: $DIR/address_of.rs:34:12: 34:18, inferred_ty: *mut [i32; 10] +| 22: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:34:12: 34:18, inferred_ty: *mut [i32; 10] +| 23: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:34:12: 34:18, inferred_ty: *mut [i32; 10] | 24: user_ty: Canonical { value: Ty(*mut [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:35:12: 35:26, inferred_ty: *mut [i32; 10] | 25: user_ty: Canonical { value: Ty(*mut [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:35:12: 35:26, inferred_ty: *mut [i32; 10] | 26: user_ty: Canonical { value: Ty(*mut dyn std::marker::Send), max_universe: U0, variables: [Region(U0)] }, span: $DIR/address_of.rs:36:12: 36:25, inferred_ty: *mut dyn std::marker::Send diff --git a/tests/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.panic-abort.mir b/tests/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.panic-abort.mir index 7be3ab8cbae9..8e47aabb9b9f 100644 --- a/tests/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.panic-abort.mir +++ b/tests/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.panic-abort.mir @@ -1,4 +1,4 @@ -// MIR for `drop_in_place` after SimplifyCfg-make_shim +// MIR for `std::ptr::drop_in_place` after SimplifyCfg-make_shim fn drop_in_place(_1: *mut Test) -> () { let mut _0: (); diff --git a/tests/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.panic-unwind.mir b/tests/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.panic-unwind.mir index 6c3c1aaa2bd2..2457405d9969 100644 --- a/tests/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.panic-unwind.mir +++ b/tests/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.panic-unwind.mir @@ -1,4 +1,4 @@ -// MIR for `drop_in_place` after SimplifyCfg-make_shim +// MIR for `std::ptr::drop_in_place` after SimplifyCfg-make_shim fn drop_in_place(_1: *mut Test) -> () { let mut _0: (); diff --git a/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String;42].AddMovesForPackedDrops.before.mir b/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String;42].AddMovesForPackedDrops.before.mir index 9d5af8e84e4f..ed3f4788cea7 100644 --- a/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String;42].AddMovesForPackedDrops.before.mir +++ b/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String;42].AddMovesForPackedDrops.before.mir @@ -1,4 +1,4 @@ -// MIR for `drop_in_place` before AddMovesForPackedDrops +// MIR for `std::ptr::drop_in_place` before AddMovesForPackedDrops fn drop_in_place(_1: *mut [String; 42]) -> () { let mut _0: (); diff --git a/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir b/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir index 144880d15989..bee671af6dfe 100644 --- a/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir +++ b/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir @@ -1,4 +1,4 @@ -// MIR for `drop_in_place` before AddMovesForPackedDrops +// MIR for `std::ptr::drop_in_place` before AddMovesForPackedDrops fn drop_in_place(_1: *mut [String]) -> () { let mut _0: (); diff --git a/tests/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir b/tests/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir index 51ef9f7c068e..1bdb1c1debdb 100644 --- a/tests/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir +++ b/tests/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir @@ -1,4 +1,4 @@ -// MIR for `drop_in_place` before AddMovesForPackedDrops +// MIR for `std::ptr::drop_in_place` before AddMovesForPackedDrops fn drop_in_place(_1: *mut Vec) -> () { let mut _0: (); diff --git a/tests/ui-fulldeps/auxiliary/parser.rs b/tests/ui-fulldeps/auxiliary/parser.rs index 6726969350dd..6ee39e5130f6 100644 --- a/tests/ui-fulldeps/auxiliary/parser.rs +++ b/tests/ui-fulldeps/auxiliary/parser.rs @@ -10,7 +10,7 @@ extern crate rustc_span; use rustc_ast::ast::{AttrKind, Attribute, DUMMY_NODE_ID, Expr}; use rustc_ast::mut_visit::{self, MutVisitor}; use rustc_ast::node_id::NodeId; -use rustc_ast::token::{self, Token}; +use rustc_ast::token; use rustc_ast::tokenstream::{AttrTokenStream, AttrTokenTree, LazyAttrTokenStream}; use rustc_errors::Diag; use rustc_parse::parser::Recovery; @@ -23,6 +23,7 @@ pub fn parse_expr(psess: &ParseSess, source_code: &str) -> Option> { psess, FileName::anon_source_code(source_code), source_code.to_owned(), + rustc_parse::lexer::StripTokens::Nothing, )); let mut parser = parser.recovery(Recovery::Forbidden); diff --git a/tests/ui-fulldeps/mod_dir_path_canonicalized.rs b/tests/ui-fulldeps/mod_dir_path_canonicalized.rs index 99cb5fc5aa1c..df5f29e35fe6 100644 --- a/tests/ui-fulldeps/mod_dir_path_canonicalized.rs +++ b/tests/ui-fulldeps/mod_dir_path_canonicalized.rs @@ -16,7 +16,7 @@ extern crate rustc_span; #[allow(unused_extern_crates)] extern crate rustc_driver; -use rustc_parse::{new_parser_from_file, unwrap_or_emit_fatal}; +use rustc_parse::{lexer::StripTokens, new_parser_from_file, unwrap_or_emit_fatal}; use rustc_session::parse::ParseSess; use std::path::Path; @@ -34,6 +34,11 @@ fn parse() { let path = Path::new(file!()); let path = path.canonicalize().unwrap(); - let mut parser = unwrap_or_emit_fatal(new_parser_from_file(&psess, &path, None)); + let mut parser = unwrap_or_emit_fatal(new_parser_from_file( + &psess, + &path, + StripTokens::ShebangAndFrontmatter, + None, + )); let _ = parser.parse_crate_mod(); } diff --git a/tests/ui/attributes/malformed-static-align.rs b/tests/ui/attributes/malformed-static-align.rs new file mode 100644 index 000000000000..305d8acf8af2 --- /dev/null +++ b/tests/ui/attributes/malformed-static-align.rs @@ -0,0 +1,17 @@ +#![feature(static_align)] +#![crate_type = "lib"] + +#[rustc_align_static = 16] //~ ERROR malformed `rustc_align_static` attribute input +static S1: () = (); + +#[rustc_align_static("hello")] //~ ERROR invalid alignment value: not an unsuffixed integer +static S2: () = (); + +#[rustc_align_static(0)] //~ ERROR invalid alignment value: not a power of two +static S3: () = (); + +#[repr(align(16))] //~ ERROR `#[repr(align(...))]` is not supported on static +static S4: () = (); + +#[rustc_align_static(16)] //~ ERROR `#[rustc_align_static]` attribute cannot be used on structs +struct Struct1; diff --git a/tests/ui/attributes/malformed-static-align.stderr b/tests/ui/attributes/malformed-static-align.stderr new file mode 100644 index 000000000000..35f654d3990f --- /dev/null +++ b/tests/ui/attributes/malformed-static-align.stderr @@ -0,0 +1,45 @@ +error[E0539]: malformed `rustc_align_static` attribute input + --> $DIR/malformed-static-align.rs:4:1 + | +LL | #[rustc_align_static = 16] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected this to be a list + | help: must be of the form: `#[rustc_align_static()]` + +error[E0589]: invalid alignment value: not an unsuffixed integer + --> $DIR/malformed-static-align.rs:7:22 + | +LL | #[rustc_align_static("hello")] + | ^^^^^^^ + +error[E0589]: invalid alignment value: not a power of two + --> $DIR/malformed-static-align.rs:10:22 + | +LL | #[rustc_align_static(0)] + | ^ + +error: `#[rustc_align_static]` attribute cannot be used on structs + --> $DIR/malformed-static-align.rs:16:1 + | +LL | #[rustc_align_static(16)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_align_static]` can be applied to statics and foreign statics + +error: `#[repr(align(...))]` is not supported on statics + --> $DIR/malformed-static-align.rs:13:8 + | +LL | #[repr(align(16))] + | ^^^^^^^^^ + | +help: use `#[rustc_align_static(...)]` instead + --> $DIR/malformed-static-align.rs:13:8 + | +LL | #[repr(align(16))] + | ^^^^^^^^^ + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0539, E0589. +For more information about an error, try `rustc --explain E0539`. diff --git a/tests/ui/c-variadic/issue-86053-1.rs b/tests/ui/c-variadic/issue-86053-1.rs index 537d0263adf7..58dfee55cf88 100644 --- a/tests/ui/c-variadic/issue-86053-1.rs +++ b/tests/ui/c-variadic/issue-86053-1.rs @@ -13,6 +13,6 @@ fn ordering4 < 'a , 'b > ( a : , self , self , self , //~| ERROR unexpected `self` parameter in function //~| ERROR unexpected `self` parameter in function //~| ERROR `...` must be the last argument of a C-variadic function - //~| ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention + //~| ERROR `...` is not supported for non-extern functions //~| ERROR cannot find type `F` in this scope } diff --git a/tests/ui/c-variadic/issue-86053-1.stderr b/tests/ui/c-variadic/issue-86053-1.stderr index 675dfd335c42..adbc04d3a65a 100644 --- a/tests/ui/c-variadic/issue-86053-1.stderr +++ b/tests/ui/c-variadic/issue-86053-1.stderr @@ -46,11 +46,13 @@ error: `...` must be the last argument of a C-variadic function LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) { | ^^^ -error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention - --> $DIR/issue-86053-1.rs:11:12 +error: `...` is not supported for non-extern functions + --> $DIR/issue-86053-1.rs:11:36 | LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) { - | ^^^ ^^^ + | ^^^ + | + = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list error[E0412]: cannot find type `F` in this scope --> $DIR/issue-86053-1.rs:11:48 diff --git a/tests/ui/c-variadic/no-closure.rs b/tests/ui/c-variadic/no-closure.rs new file mode 100644 index 000000000000..c0b77786e8b4 --- /dev/null +++ b/tests/ui/c-variadic/no-closure.rs @@ -0,0 +1,17 @@ +#![feature(c_variadic)] +#![crate_type = "lib"] + +// Check that `...` in closures is rejected. + +const F: extern "C" fn(...) = |_: ...| {}; +//~^ ERROR C-variadic type `...` may not be nested inside another type + +fn foo() { + let f = |...| {}; + //~^ ERROR: `..` patterns are not allowed here + //~| ERROR: unexpected `...` + + let f = |_: ...| {}; + //~^ ERROR C-variadic type `...` may not be nested inside another type + f(1i64) +} diff --git a/tests/ui/c-variadic/no-closure.stderr b/tests/ui/c-variadic/no-closure.stderr new file mode 100644 index 000000000000..77bd106bb951 --- /dev/null +++ b/tests/ui/c-variadic/no-closure.stderr @@ -0,0 +1,35 @@ +error[E0743]: C-variadic type `...` may not be nested inside another type + --> $DIR/no-closure.rs:6:35 + | +LL | const F: extern "C" fn(...) = |_: ...| {}; + | ^^^ + +error: unexpected `...` + --> $DIR/no-closure.rs:10:14 + | +LL | let f = |...| {}; + | ^^^ not a valid pattern + | +help: for a rest pattern, use `..` instead of `...` + | +LL - let f = |...| {}; +LL + let f = |..| {}; + | + +error[E0743]: C-variadic type `...` may not be nested inside another type + --> $DIR/no-closure.rs:14:17 + | +LL | let f = |_: ...| {}; + | ^^^ + +error: `..` patterns are not allowed here + --> $DIR/no-closure.rs:10:14 + | +LL | let f = |...| {}; + | ^^^ + | + = note: only allowed in tuple, tuple struct, and slice patterns + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0743`. diff --git a/tests/ui/c-variadic/not-async.rs b/tests/ui/c-variadic/not-async.rs new file mode 100644 index 000000000000..45a7e1f8972b --- /dev/null +++ b/tests/ui/c-variadic/not-async.rs @@ -0,0 +1,7 @@ +//@ edition: 2021 +#![feature(c_variadic)] +#![crate_type = "lib"] + +async unsafe extern "C" fn cannot_be_async(x: isize, ...) {} +//~^ ERROR functions cannot be both `async` and C-variadic +//~| ERROR hidden type for `impl Future` captures lifetime that does not appear in bounds diff --git a/tests/ui/c-variadic/not-async.stderr b/tests/ui/c-variadic/not-async.stderr new file mode 100644 index 000000000000..b8caf0d8bd85 --- /dev/null +++ b/tests/ui/c-variadic/not-async.stderr @@ -0,0 +1,19 @@ +error: functions cannot be both `async` and C-variadic + --> $DIR/not-async.rs:5:1 + | +LL | async unsafe extern "C" fn cannot_be_async(x: isize, ...) {} + | ^^^^^ `async` because of this ^^^ C-variadic because of this + +error[E0700]: hidden type for `impl Future` captures lifetime that does not appear in bounds + --> $DIR/not-async.rs:5:59 + | +LL | async unsafe extern "C" fn cannot_be_async(x: isize, ...) {} + | --------------------------------------------------------- ^^ + | | + | opaque type defined here + | + = note: hidden type `{async fn body of cannot_be_async()}` captures lifetime `'_` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/c-variadic/valid.rs b/tests/ui/c-variadic/valid.rs new file mode 100644 index 000000000000..5a0b32026dc7 --- /dev/null +++ b/tests/ui/c-variadic/valid.rs @@ -0,0 +1,29 @@ +//@ run-pass +#![feature(c_variadic)] + +// In rust (and C23 and above) `...` can be the only argument. +unsafe extern "C" fn only_dot_dot_dot(mut ap: ...) -> i32 { + unsafe { ap.arg() } +} + +unsafe extern "C-unwind" fn abi_c_unwind(mut ap: ...) -> i32 { + unsafe { ap.arg() } +} + +#[allow(improper_ctypes_definitions)] +unsafe extern "C" fn mix_int_float(mut ap: ...) -> (i64, f64, *const i32, f64) { + (ap.arg(), ap.arg(), ap.arg(), ap.arg()) +} + +fn main() { + unsafe { + assert_eq!(only_dot_dot_dot(32), 32); + assert_eq!(abi_c_unwind(32), 32); + + // Passing more arguments than expected is allowed. + assert_eq!(only_dot_dot_dot(32, 1i64, core::ptr::null::(), 3.14f64), 32); + + let ptr = &14i32 as *const i32; + assert_eq!(mix_int_float(12i64, 13.0f64, ptr, 15.0f64), (12, 13.0, ptr, 15.0)); + } +} diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.rs index ad4fca8252d2..eb6f4a323655 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.rs @@ -53,9 +53,7 @@ extern "cmse-nonsecure-entry" fn trait_object(x: &dyn Trait) -> &dyn Trait { x } -extern "cmse-nonsecure-entry" fn static_trait_object( - x: &'static dyn Trait, -) -> &'static dyn Trait { +extern "cmse-nonsecure-entry" fn static_trait_object(x: &'static dyn Trait) -> &'static dyn Trait { //~^ ERROR return value of `"cmse-nonsecure-entry"` function too large to pass via registers [E0798] x } @@ -63,14 +61,12 @@ extern "cmse-nonsecure-entry" fn static_trait_object( #[repr(transparent)] struct WrapperTransparent<'a>(&'a dyn Trait); -extern "cmse-nonsecure-entry" fn wrapped_trait_object( - x: WrapperTransparent, -) -> WrapperTransparent { +extern "cmse-nonsecure-entry" fn wrapped_trait_object(x: WrapperTransparent) -> WrapperTransparent { //~^ ERROR return value of `"cmse-nonsecure-entry"` function too large to pass via registers [E0798] x } -extern "cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) { - //~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention +unsafe extern "cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) { + //~^ ERROR `...` is not supported for `extern "cmse-nonsecure-entry"` functions //~| ERROR requires `va_list` lang_item } diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.stderr index 7aeb6969feb9..8937def9428c 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.stderr @@ -1,8 +1,12 @@ -error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention - --> $DIR/generics.rs:73:53 +error: `...` is not supported for `extern "cmse-nonsecure-entry"` functions + --> $DIR/generics.rs:69:60 | -LL | extern "cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) { - | ^^^^^^ +LL | unsafe extern "cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) { + | ----------------------------- ^^^^^^ + | | + | `extern "cmse-nonsecure-entry"` because of this + | + = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list error[E0798]: functions with the `"cmse-nonsecure-entry"` ABI cannot contain generics in their type --> $DIR/generics.rs:30:1 @@ -50,28 +54,28 @@ LL | extern "cmse-nonsecure-entry" fn trait_object(x: &dyn Trait) -> &dyn Trait = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size error[E0798]: return value of `"cmse-nonsecure-entry"` function too large to pass via registers - --> $DIR/generics.rs:58:6 + --> $DIR/generics.rs:56:80 | -LL | ) -> &'static dyn Trait { - | ^^^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers +LL | extern "cmse-nonsecure-entry" fn static_trait_object(x: &'static dyn Trait) -> &'static dyn Trait { + | ^^^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers | = note: functions with the `"cmse-nonsecure-entry"` ABI must pass their result via the available return registers = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size error[E0798]: return value of `"cmse-nonsecure-entry"` function too large to pass via registers - --> $DIR/generics.rs:68:6 + --> $DIR/generics.rs:64:81 | -LL | ) -> WrapperTransparent { - | ^^^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers +LL | extern "cmse-nonsecure-entry" fn wrapped_trait_object(x: WrapperTransparent) -> WrapperTransparent { + | ^^^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers | = note: functions with the `"cmse-nonsecure-entry"` ABI must pass their result via the available return registers = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size error: requires `va_list` lang_item - --> $DIR/generics.rs:73:53 + --> $DIR/generics.rs:69:60 | -LL | extern "cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) { - | ^^^^^^ +LL | unsafe extern "cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) { + | ^^^^^^ error: aborting due to 9 previous errors diff --git a/tests/ui/const-generics/std/const-generics-range.full.stderr b/tests/ui/const-generics/std/const-generics-range.full.stderr index 2b5c63e6643d..ccede2af9e55 100644 --- a/tests/ui/const-generics/std/const-generics-range.full.stderr +++ b/tests/ui/const-generics/std/const-generics-range.full.stderr @@ -28,7 +28,7 @@ error[E0741]: `RangeTo` must implement `ConstParamTy` to be used as the t LL | struct _RangeTo>; | ^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0741]: `RangeToInclusive` must implement `ConstParamTy` to be used as the type of a const generic parameter +error[E0741]: `std::ops::RangeToInclusive` must implement `ConstParamTy` to be used as the type of a const generic parameter --> $DIR/const-generics-range.rs:34:35 | LL | struct _RangeToInclusive>; diff --git a/tests/ui/const-generics/std/const-generics-range.min.stderr b/tests/ui/const-generics/std/const-generics-range.min.stderr index 04e3fe744534..43a57c880d5d 100644 --- a/tests/ui/const-generics/std/const-generics-range.min.stderr +++ b/tests/ui/const-generics/std/const-generics-range.min.stderr @@ -58,7 +58,7 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more LL + #![feature(adt_const_params)] | -error: `RangeToInclusive` is forbidden as the type of a const generic parameter +error: `std::ops::RangeToInclusive` is forbidden as the type of a const generic parameter --> $DIR/const-generics-range.rs:34:35 | LL | struct _RangeToInclusive>; diff --git a/tests/ui/const-generics/std/const-generics-range.rs b/tests/ui/const-generics/std/const-generics-range.rs index 3a238ed177e0..391366dadba0 100644 --- a/tests/ui/const-generics/std/const-generics-range.rs +++ b/tests/ui/const-generics/std/const-generics-range.rs @@ -7,32 +7,32 @@ // `Range` should be usable within const generics: struct _Range>; //[min]~^ ERROR `std::ops::Range` is forbidden -const RANGE : _Range<{ 0 .. 1000 }> = _Range; +const RANGE: _Range<{ 0..1000 }> = _Range; // `RangeFrom` should be usable within const generics: struct _RangeFrom>; //[min]~^ ERROR `std::ops::RangeFrom` is forbidden -const RANGE_FROM : _RangeFrom<{ 0 .. }> = _RangeFrom; +const RANGE_FROM: _RangeFrom<{ 0.. }> = _RangeFrom; // `RangeFull` should be usable within const generics: struct _RangeFull; //[min]~^ ERROR `RangeFull` is forbidden -const RANGE_FULL : _RangeFull<{ .. }> = _RangeFull; +const RANGE_FULL: _RangeFull<{ .. }> = _RangeFull; // Regression test for #70155 // `RangeInclusive` should be usable within const generics: struct _RangeInclusive>; //[min]~^ ERROR `std::ops::RangeInclusive` is forbidden -const RANGE_INCLUSIVE : _RangeInclusive<{ 0 ..= 999 }> = _RangeInclusive; +const RANGE_INCLUSIVE: _RangeInclusive<{ 0..=999 }> = _RangeInclusive; // `RangeTo` should be usable within const generics: struct _RangeTo>; //[min]~^ ERROR `RangeTo` is forbidden -const RANGE_TO : _RangeTo<{ .. 1000 }> = _RangeTo; +const RANGE_TO: _RangeTo<{ ..1000 }> = _RangeTo; // `RangeToInclusive` should be usable within const generics: struct _RangeToInclusive>; -//[min]~^ ERROR `RangeToInclusive` is forbidden -const RANGE_TO_INCLUSIVE : _RangeToInclusive<{ ..= 999 }> = _RangeToInclusive; +//[min]~^ ERROR `std::ops::RangeToInclusive` is forbidden +const RANGE_TO_INCLUSIVE: _RangeToInclusive<{ ..=999 }> = _RangeToInclusive; pub fn main() {} diff --git a/tests/ui/consts/const-eval/ptr_fragments.rs b/tests/ui/consts/const-eval/ptr_fragments.rs index 04dcbe55590e..7dc5870f89e2 100644 --- a/tests/ui/consts/const-eval/ptr_fragments.rs +++ b/tests/ui/consts/const-eval/ptr_fragments.rs @@ -1,5 +1,6 @@ //! Test that various operations involving pointer fragments work as expected. //@ run-pass +//@ ignore-test: disabled due to use std::mem::{self, MaybeUninit, transmute}; use std::ptr; diff --git a/tests/ui/consts/const-eval/ptr_fragments_in_final.rs b/tests/ui/consts/const-eval/ptr_fragments_in_final.rs index e2f3f51b0863..aed33d7ed8d3 100644 --- a/tests/ui/consts/const-eval/ptr_fragments_in_final.rs +++ b/tests/ui/consts/const-eval/ptr_fragments_in_final.rs @@ -1,4 +1,5 @@ //! Test that we properly error when there is a pointer fragment in the final value. +//@ ignore-test: disabled due to use std::{mem::{self, MaybeUninit}, ptr}; diff --git a/tests/ui/consts/const-eval/ptr_fragments_mixed.rs b/tests/ui/consts/const-eval/ptr_fragments_mixed.rs new file mode 100644 index 000000000000..79a42820f501 --- /dev/null +++ b/tests/ui/consts/const-eval/ptr_fragments_mixed.rs @@ -0,0 +1,28 @@ +//! This mixes fragments from different pointers to the same allocarion, in a way +//! that we should not accept. See . +static A: u8 = 123; + +const HALF_PTR: usize = std::mem::size_of::<*const ()>() / 2; + +const fn mix_ptr() -> *const u8 { + unsafe { + let x: *const u8 = &raw const A; + let mut y = x.wrapping_add(usize::MAX / 4); + core::ptr::copy_nonoverlapping( + (&raw const x).cast::(), + (&raw mut y).cast::(), + HALF_PTR, + ); + y + } +} + +const APTR: *const u8 = mix_ptr(); //~ERROR: unable to read parts of a pointer + +fn main() { + let a = APTR; + println!("{a:p}"); + let b = mix_ptr(); + println!("{b:p}"); + assert_eq!(a, b); +} diff --git a/tests/ui/consts/const-eval/ptr_fragments_mixed.stderr b/tests/ui/consts/const-eval/ptr_fragments_mixed.stderr new file mode 100644 index 000000000000..9e991ab7a7d3 --- /dev/null +++ b/tests/ui/consts/const-eval/ptr_fragments_mixed.stderr @@ -0,0 +1,23 @@ +error[E0080]: unable to read parts of a pointer from memory at ALLOC0 + --> $DIR/ptr_fragments_mixed.rs:20:25 + | +LL | const APTR: *const u8 = mix_ptr(); + | ^^^^^^^^^ evaluation of `APTR` failed inside this call + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported +note: inside `mix_ptr` + --> $DIR/ptr_fragments_mixed.rs:11:9 + | +LL | / core::ptr::copy_nonoverlapping( +LL | | (&raw const x).cast::(), +LL | | (&raw mut y).cast::(), +LL | | HALF_PTR, +LL | | ); + | |_________^ +note: inside `std::ptr::copy_nonoverlapping::` + --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/read_partial_ptr.rs b/tests/ui/consts/const-eval/read_partial_ptr.rs index bccef9c0bc6c..c153e274e41f 100644 --- a/tests/ui/consts/const-eval/read_partial_ptr.rs +++ b/tests/ui/consts/const-eval/read_partial_ptr.rs @@ -1,4 +1,5 @@ //! Ensure we error when trying to load from a pointer whose provenance has been messed with. +//@ ignore-test: disabled due to const PARTIAL_OVERWRITE: () = { let mut p = &42; diff --git a/tests/ui/deref/pin-deref-const.rs b/tests/ui/deref/pin-deref-const.rs new file mode 100644 index 000000000000..6ed00177b232 --- /dev/null +++ b/tests/ui/deref/pin-deref-const.rs @@ -0,0 +1,79 @@ +// The purpose of this file is to track the error messages from Pin and DerefMut interacting. +// +// Identical to `pin-deref.rs` except for using unstable `const fn`. + +//@ check-fail + +#![feature(const_convert)] +#![feature(const_trait_impl)] + +use std::ops::DerefMut; +use std::pin::Pin; + +struct MyUnpinType {} + +impl MyUnpinType { + const fn at_self(&self) {} + const fn at_mut_self(&mut self) {} +} + +struct MyPinType(core::marker::PhantomPinned); + +impl MyPinType { + const fn at_self(&self) {} + const fn at_mut_self(&mut self) {} +} + +const fn call_mut_ref_unpin(mut r_unpin: Pin<&mut MyUnpinType>) { + r_unpin.at_self(); + r_unpin.at_mut_self(); +} + +const fn call_ref_unpin(mut r_unpin: Pin<&MyUnpinType>) { + r_unpin.at_self(); + r_unpin.at_mut_self(); //~ ERROR: cannot borrow data in dereference of `Pin<&MyUnpinType>` as mutable +} + +const fn call_mut_ref_pin(mut r_pin: Pin<&mut MyPinType>) { + r_pin.at_self(); + r_pin.at_mut_self(); //~ ERROR: cannot borrow data in dereference of `Pin<&mut MyPinType>` as mutable +} + +const fn call_ref_pin(mut r_pin: Pin<&MyPinType>) { + r_pin.at_self(); + r_pin.at_mut_self(); //~ ERROR: cannot borrow data in dereference of `Pin<&MyPinType>` as mutable +} + +const fn coerce_unpin_rr<'a>(mut r_unpin: &'a mut Pin<&MyUnpinType>) -> &'a MyUnpinType { + r_unpin +} + +const fn coerce_unpin_rm<'a>(mut r_unpin: &'a mut Pin<&MyUnpinType>) -> &'a mut MyUnpinType { + r_unpin //~ ERROR: cannot borrow data in dereference of `Pin<&MyUnpinType>` as mutable +} + +const fn coerce_unpin_mr<'a>(mut r_unpin: &'a mut Pin<&mut MyUnpinType>) -> &'a MyUnpinType { + r_unpin +} + +const fn coerce_unpin_mm<'a>(mut r_unpin: &'a mut Pin<&mut MyUnpinType>) -> &'a mut MyUnpinType { + r_unpin +} + +const fn coerce_pin_rr<'a>(mut r_pin: &'a mut Pin<&MyPinType>) -> &'a MyPinType { + r_pin +} + +const fn coerce_pin_rm<'a>(mut r_pin: &'a mut Pin<&MyPinType>) -> &'a mut MyPinType { + r_pin //~ ERROR: cannot borrow data in dereference of `Pin<&MyPinType>` as mutable +} + +const fn coerce_pin_mr<'a>(mut r_pin: &'a mut Pin<&mut MyPinType>) -> &'a MyPinType { + r_pin +} + +const fn coerce_pin_mm<'a>(mut r_pin: &'a mut Pin<&mut MyPinType>) -> &'a mut MyPinType { + r_pin //~ ERROR: cannot borrow data in dereference of `Pin<&mut MyPinType>` as mutable +} + +fn main() {} diff --git a/tests/ui/deref/pin-deref-const.stderr b/tests/ui/deref/pin-deref-const.stderr new file mode 100644 index 000000000000..caa270e64ffe --- /dev/null +++ b/tests/ui/deref/pin-deref-const.stderr @@ -0,0 +1,51 @@ +error[E0596]: cannot borrow data in dereference of `Pin<&MyUnpinType>` as mutable + --> $DIR/pin-deref-const.rs:34:5 + | +LL | r_unpin.at_mut_self(); + | ^^^^^^^ cannot borrow as mutable + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Pin<&MyUnpinType>` + +error[E0596]: cannot borrow data in dereference of `Pin<&mut MyPinType>` as mutable + --> $DIR/pin-deref-const.rs:39:5 + | +LL | r_pin.at_mut_self(); + | ^^^^^ cannot borrow as mutable + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Pin<&mut MyPinType>` + +error[E0596]: cannot borrow data in dereference of `Pin<&MyPinType>` as mutable + --> $DIR/pin-deref-const.rs:44:5 + | +LL | r_pin.at_mut_self(); + | ^^^^^ cannot borrow as mutable + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Pin<&MyPinType>` + +error[E0596]: cannot borrow data in dereference of `Pin<&MyUnpinType>` as mutable + --> $DIR/pin-deref-const.rs:52:5 + | +LL | r_unpin + | ^^^^^^^ cannot borrow as mutable + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Pin<&MyUnpinType>` + +error[E0596]: cannot borrow data in dereference of `Pin<&MyPinType>` as mutable + --> $DIR/pin-deref-const.rs:68:5 + | +LL | r_pin + | ^^^^^ cannot borrow as mutable + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Pin<&MyPinType>` + +error[E0596]: cannot borrow data in dereference of `Pin<&mut MyPinType>` as mutable + --> $DIR/pin-deref-const.rs:76:5 + | +LL | r_pin + | ^^^^^ cannot borrow as mutable + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Pin<&mut MyPinType>` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/deref/pin-deref.rs b/tests/ui/deref/pin-deref.rs new file mode 100644 index 000000000000..180831c9bc61 --- /dev/null +++ b/tests/ui/deref/pin-deref.rs @@ -0,0 +1,76 @@ +// The purpose of this file is to track the error messages from Pin and DerefMut interacting. +// +// Identical to `pin-deref-const.rs` except for being stable and not using `const fn`. + +//@ check-fail + +use std::ops::DerefMut; +use std::pin::Pin; + +struct MyUnpinType {} + +impl MyUnpinType { + fn at_self(&self) {} + fn at_mut_self(&mut self) {} +} + +struct MyPinType(core::marker::PhantomPinned); + +impl MyPinType { + fn at_self(&self) {} + fn at_mut_self(&mut self) {} +} + +fn call_mut_ref_unpin(mut r_unpin: Pin<&mut MyUnpinType>) { + r_unpin.at_self(); + r_unpin.at_mut_self(); +} + +fn call_ref_unpin(mut r_unpin: Pin<&MyUnpinType>) { + r_unpin.at_self(); + r_unpin.at_mut_self(); //~ ERROR: cannot borrow data in dereference of `Pin<&MyUnpinType>` as mutable +} + +fn call_mut_ref_pin(mut r_pin: Pin<&mut MyPinType>) { + r_pin.at_self(); + r_pin.at_mut_self(); //~ ERROR: cannot borrow data in dereference of `Pin<&mut MyPinType>` as mutable +} + +fn call_ref_pin(mut r_pin: Pin<&MyPinType>) { + r_pin.at_self(); + r_pin.at_mut_self(); //~ ERROR: cannot borrow data in dereference of `Pin<&MyPinType>` as mutable +} + +fn coerce_unpin_rr<'a>(mut r_unpin: &'a mut Pin<&MyUnpinType>) -> &'a MyUnpinType { + r_unpin +} + +fn coerce_unpin_rm<'a>(mut r_unpin: &'a mut Pin<&MyUnpinType>) -> &'a mut MyUnpinType { + r_unpin //~ ERROR: cannot borrow data in dereference of `Pin<&MyUnpinType>` as mutable +} + +fn coerce_unpin_mr<'a>(mut r_unpin: &'a mut Pin<&mut MyUnpinType>) -> &'a MyUnpinType { + r_unpin +} + +fn coerce_unpin_mm<'a>(mut r_unpin: &'a mut Pin<&mut MyUnpinType>) -> &'a mut MyUnpinType { + r_unpin +} + +fn coerce_pin_rr<'a>(mut r_pin: &'a mut Pin<&MyPinType>) -> &'a MyPinType { + r_pin +} + +fn coerce_pin_rm<'a>(mut r_pin: &'a mut Pin<&MyPinType>) -> &'a mut MyPinType { + r_pin //~ ERROR: cannot borrow data in dereference of `Pin<&MyPinType>` as mutable +} + +fn coerce_pin_mr<'a>(mut r_pin: &'a mut Pin<&mut MyPinType>) -> &'a MyPinType { + r_pin +} + +fn coerce_pin_mm<'a>(mut r_pin: &'a mut Pin<&mut MyPinType>) -> &'a mut MyPinType { + r_pin //~ ERROR: cannot borrow data in dereference of `Pin<&mut MyPinType>` as mutable +} + +fn main() {} diff --git a/tests/ui/deref/pin-deref.stderr b/tests/ui/deref/pin-deref.stderr new file mode 100644 index 000000000000..71277a10cdfb --- /dev/null +++ b/tests/ui/deref/pin-deref.stderr @@ -0,0 +1,51 @@ +error[E0596]: cannot borrow data in dereference of `Pin<&MyUnpinType>` as mutable + --> $DIR/pin-deref.rs:31:5 + | +LL | r_unpin.at_mut_self(); + | ^^^^^^^ cannot borrow as mutable + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Pin<&MyUnpinType>` + +error[E0596]: cannot borrow data in dereference of `Pin<&mut MyPinType>` as mutable + --> $DIR/pin-deref.rs:36:5 + | +LL | r_pin.at_mut_self(); + | ^^^^^ cannot borrow as mutable + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Pin<&mut MyPinType>` + +error[E0596]: cannot borrow data in dereference of `Pin<&MyPinType>` as mutable + --> $DIR/pin-deref.rs:41:5 + | +LL | r_pin.at_mut_self(); + | ^^^^^ cannot borrow as mutable + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Pin<&MyPinType>` + +error[E0596]: cannot borrow data in dereference of `Pin<&MyUnpinType>` as mutable + --> $DIR/pin-deref.rs:49:5 + | +LL | r_unpin + | ^^^^^^^ cannot borrow as mutable + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Pin<&MyUnpinType>` + +error[E0596]: cannot borrow data in dereference of `Pin<&MyPinType>` as mutable + --> $DIR/pin-deref.rs:65:5 + | +LL | r_pin + | ^^^^^ cannot borrow as mutable + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Pin<&MyPinType>` + +error[E0596]: cannot borrow data in dereference of `Pin<&mut MyPinType>` as mutable + --> $DIR/pin-deref.rs:73:5 + | +LL | r_pin + | ^^^^^ cannot borrow as mutable + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Pin<&mut MyPinType>` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/deref/pin-impl-deref.rs b/tests/ui/deref/pin-impl-deref.rs new file mode 100644 index 000000000000..b1dc8dea3f24 --- /dev/null +++ b/tests/ui/deref/pin-impl-deref.rs @@ -0,0 +1,40 @@ +// The purpose of this file is to track the error messages from Pin and DerefMut interacting. + +//@ check-fail + +use std::ops::DerefMut; +use std::pin::Pin; + +struct MyUnpinType {} + +impl MyUnpinType { + fn at_self(&self) {} + fn at_mut_self(&mut self) {} +} + +struct MyPinType(core::marker::PhantomPinned); + +impl MyPinType { + fn at_self(&self) {} + fn at_mut_self(&mut self) {} +} + +fn impl_deref_mut(_: impl DerefMut) {} +fn unpin_impl_ref(r_unpin: Pin<&MyUnpinType>) { + impl_deref_mut(r_unpin) + //~^ ERROR: the trait bound `Pin<&MyUnpinType>: DerefMut` is not satisfied +} +fn unpin_impl_mut(r_unpin: Pin<&mut MyUnpinType>) { + impl_deref_mut(r_unpin) +} +fn pin_impl_ref(r_pin: Pin<&MyPinType>) { + impl_deref_mut(r_pin) + //~^ ERROR: `PhantomPinned` cannot be unpinned + //~| ERROR: the trait bound `Pin<&MyPinType>: DerefMut` is not satisfied +} +fn pin_impl_mut(r_pin: Pin<&mut MyPinType>) { + impl_deref_mut(r_pin) + //~^ ERROR: `PhantomPinned` cannot be unpinned +} + +fn main() {} diff --git a/tests/ui/deref/pin-impl-deref.stderr b/tests/ui/deref/pin-impl-deref.stderr new file mode 100644 index 000000000000..106654641a11 --- /dev/null +++ b/tests/ui/deref/pin-impl-deref.stderr @@ -0,0 +1,85 @@ +error[E0277]: the trait bound `Pin<&MyUnpinType>: DerefMut` is not satisfied + --> $DIR/pin-impl-deref.rs:24:20 + | +LL | impl_deref_mut(r_unpin) + | -------------- ^^^^^^^ the trait `DerefMut` is not implemented for `Pin<&MyUnpinType>` + | | + | required by a bound introduced by this call + | + = note: required for `Pin<&MyUnpinType>` to implement `DerefMut` +note: required by a bound in `impl_deref_mut` + --> $DIR/pin-impl-deref.rs:22:27 + | +LL | fn impl_deref_mut(_: impl DerefMut) {} + | ^^^^^^^^ required by this bound in `impl_deref_mut` +help: consider mutably borrowing here + | +LL | impl_deref_mut(&mut r_unpin) + | ++++ + +error[E0277]: the trait bound `Pin<&MyPinType>: DerefMut` is not satisfied + --> $DIR/pin-impl-deref.rs:31:20 + | +LL | impl_deref_mut(r_pin) + | -------------- ^^^^^ the trait `DerefMut` is not implemented for `Pin<&MyPinType>` + | | + | required by a bound introduced by this call + | + = note: required for `Pin<&MyPinType>` to implement `DerefMut` +note: required by a bound in `impl_deref_mut` + --> $DIR/pin-impl-deref.rs:22:27 + | +LL | fn impl_deref_mut(_: impl DerefMut) {} + | ^^^^^^^^ required by this bound in `impl_deref_mut` +help: consider mutably borrowing here + | +LL | impl_deref_mut(&mut r_pin) + | ++++ + +error[E0277]: `PhantomPinned` cannot be unpinned + --> $DIR/pin-impl-deref.rs:31:20 + | +LL | impl_deref_mut(r_pin) + | -------------- ^^^^^ within `MyPinType`, the trait `Unpin` is not implemented for `PhantomPinned` + | | + | required by a bound introduced by this call + | + = note: consider using the `pin!` macro + consider using `Box::pin` if you need to access the pinned value outside of the current scope +note: required because it appears within the type `MyPinType` + --> $DIR/pin-impl-deref.rs:15:8 + | +LL | struct MyPinType(core::marker::PhantomPinned); + | ^^^^^^^^^ + = note: required for `Pin<&MyPinType>` to implement `DerefMut` +note: required by a bound in `impl_deref_mut` + --> $DIR/pin-impl-deref.rs:22:27 + | +LL | fn impl_deref_mut(_: impl DerefMut) {} + | ^^^^^^^^ required by this bound in `impl_deref_mut` + +error[E0277]: `PhantomPinned` cannot be unpinned + --> $DIR/pin-impl-deref.rs:36:20 + | +LL | impl_deref_mut(r_pin) + | -------------- ^^^^^ within `MyPinType`, the trait `Unpin` is not implemented for `PhantomPinned` + | | + | required by a bound introduced by this call + | + = note: consider using the `pin!` macro + consider using `Box::pin` if you need to access the pinned value outside of the current scope +note: required because it appears within the type `MyPinType` + --> $DIR/pin-impl-deref.rs:15:8 + | +LL | struct MyPinType(core::marker::PhantomPinned); + | ^^^^^^^^^ + = note: required for `Pin<&mut MyPinType>` to implement `DerefMut` +note: required by a bound in `impl_deref_mut` + --> $DIR/pin-impl-deref.rs:22:27 + | +LL | fn impl_deref_mut(_: impl DerefMut) {} + | ^^^^^^^^ required by this bound in `impl_deref_mut` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/error-emitter/multiline-removal-suggestion.svg b/tests/ui/error-emitter/multiline-removal-suggestion.svg index 9c9bd163ecd4..7a88ac55b23e 100644 --- a/tests/ui/error-emitter/multiline-removal-suggestion.svg +++ b/tests/ui/error-emitter/multiline-removal-suggestion.svg @@ -1,4 +1,4 @@ - + , U: ?Sized + ?Leak> CoerceUnsized<&'a U> for &'b T {} +// Omit `T: ?Leak` and `U: ?Leak`. +impl<'a, 'b: 'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a mut U> for &'b mut T {} #[lang = "dispatch_from_dyn"] -trait DispatchFromDyn {} +trait DispatchFromDyn: ?Leak {} impl<'a, T: ?Sized + ?Leak + Unsize, U: ?Sized + ?Leak> DispatchFromDyn<&'a U> for &'a T {} +// Omit `T: ?Leak` and `U: ?Leak`. +impl<'a, T: ?Sized + Unsize, U: ?Sized> DispatchFromDyn<&'a mut U> for &'a mut T {} #[lang = "default_trait1"] auto trait Leak {} @@ -47,25 +52,52 @@ struct NonLeakS; impl !Leak for NonLeakS {} struct LeakS; -trait Trait { - fn leak_foo(&self) {} - fn maybe_leak_foo(&self) where Self: ?Leak {} +fn bounds_check() { + trait LeakTr {} + + trait MaybeLeakTr: ?Leak {} + + impl MaybeLeakTr for NonLeakS {} + + impl LeakTr for LeakS {} + impl MaybeLeakTr for LeakS {} + + let _: &dyn LeakTr = &NonLeakS; + //~^ ERROR the trait bound `NonLeakS: bounds_check::LeakTr` is not satisfied + let _: &dyn LeakTr = &LeakS; + + let _: &(dyn LeakTr + ?Leak) = &NonLeakS; + let _: &(dyn LeakTr + ?Leak) = &LeakS; + + let _: &dyn MaybeLeakTr = &NonLeakS; + let _: &dyn MaybeLeakTr = &LeakS; } -impl Trait for NonLeakS {} -impl Trait for LeakS {} +fn dyn_compat_check() { + trait DynCompatCheck1: ?Leak { + fn foo(&self) {} + } + + trait DynCompatCheck2: ?Leak { + fn mut_foo(&mut self) {} + } + + impl DynCompatCheck1 for NonLeakS {} + impl DynCompatCheck2 for NonLeakS {} + + let _: &(dyn DynCompatCheck1 + ?Leak) = &NonLeakS; + // There is no `?Leak` bound on corresponding `DispatchFromDyn` impl. + let _: &dyn DynCompatCheck2 = &NonLeakS; + //~^ ERROR the trait `DynCompatCheck2` is not dyn compatible +} + +fn args_check() { + trait LeakTr {} -fn main() { - let _: &dyn Trait = &NonLeakS; - //~^ ERROR the trait bound `NonLeakS: Leak` is not satisfied - let _: &dyn Trait = &LeakS; - let _: &(dyn Trait + ?Leak) = &LeakS; - let x: &(dyn Trait + ?Leak) = &NonLeakS; - x.leak_foo(); - //~^ ERROR the trait bound `dyn Trait: Leak` is not satisfied - x.maybe_leak_foo(); // Ensure that we validate the generic args of relaxed bounds in trait object types. - let _: dyn Trait + ?Leak<(), Undefined = ()>; + let _: dyn LeakTr + ?Leak<(), Undefined = ()>; //~^ ERROR trait takes 0 generic arguments but 1 generic argument was supplied //~| ERROR associated type `Undefined` not found for `Leak` } + +fn main() {} diff --git a/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.stderr b/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.stderr index b19c082a1b8f..b96a2915c333 100644 --- a/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.stderr +++ b/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.stderr @@ -1,49 +1,57 @@ -error[E0277]: the trait bound `NonLeakS: Leak` is not satisfied - --> $DIR/maybe-bounds-in-dyn-traits.rs:59:25 +error[E0277]: the trait bound `NonLeakS: bounds_check::LeakTr` is not satisfied + --> $DIR/maybe-bounds-in-dyn-traits.rs:65:26 | -LL | let _: &dyn Trait = &NonLeakS; - | ^^^^^^^^^ unsatisfied trait bound +LL | let _: &dyn LeakTr = &NonLeakS; + | ^^^^^^^^^ unsatisfied trait bound | -help: the trait `Leak` is not implemented for `NonLeakS` - --> $DIR/maybe-bounds-in-dyn-traits.rs:46:1 +help: the trait `bounds_check::LeakTr` is not implemented for `NonLeakS` + --> $DIR/maybe-bounds-in-dyn-traits.rs:51:1 | LL | struct NonLeakS; | ^^^^^^^^^^^^^^^ - = note: required for the cast from `&NonLeakS` to `&dyn Trait + Leak` + = help: the trait `bounds_check::LeakTr` is implemented for `LeakS` + = note: required for the cast from `&NonLeakS` to `&dyn bounds_check::LeakTr + Leak` -error[E0277]: the trait bound `dyn Trait: Leak` is not satisfied - --> $DIR/maybe-bounds-in-dyn-traits.rs:64:7 +error[E0038]: the trait `DynCompatCheck2` is not dyn compatible + --> $DIR/maybe-bounds-in-dyn-traits.rs:90:17 | -LL | x.leak_foo(); - | ^^^^^^^^ the trait `Leak` is not implemented for `dyn Trait` +LL | fn mut_foo(&mut self) {} + | --------- help: consider changing method `mut_foo`'s `self` parameter to be `&self`: `&Self` +... +LL | let _: &dyn DynCompatCheck2 = &NonLeakS; + | ^^^^^^^^^^^^^^^ `DynCompatCheck2` is not dyn compatible | -note: required by a bound in `Trait::leak_foo` - --> $DIR/maybe-bounds-in-dyn-traits.rs:51:5 +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/maybe-bounds-in-dyn-traits.rs:82:20 | -LL | fn leak_foo(&self) {} - | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Trait::leak_foo` +LL | trait DynCompatCheck2: ?Leak { + | --------------- this trait is not dyn compatible... +LL | fn mut_foo(&mut self) {} + | ^^^^^^^^^ ...because method `mut_foo`'s `self` parameter cannot be dispatched on + = help: only type `NonLeakS` implements `DynCompatCheck2`; consider using it directly instead. error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/maybe-bounds-in-dyn-traits.rs:68:25 + --> $DIR/maybe-bounds-in-dyn-traits.rs:98:26 | -LL | let _: dyn Trait + ?Leak<(), Undefined = ()>; - | ^^^^-------------------- help: remove the unnecessary generics - | | - | expected 0 generic arguments +LL | let _: dyn LeakTr + ?Leak<(), Undefined = ()>; + | ^^^^-------------------- help: remove the unnecessary generics + | | + | expected 0 generic arguments | note: trait defined here, with 0 generic parameters - --> $DIR/maybe-bounds-in-dyn-traits.rs:44:12 + --> $DIR/maybe-bounds-in-dyn-traits.rs:49:12 | LL | auto trait Leak {} | ^^^^ error[E0220]: associated type `Undefined` not found for `Leak` - --> $DIR/maybe-bounds-in-dyn-traits.rs:68:34 + --> $DIR/maybe-bounds-in-dyn-traits.rs:98:35 | -LL | let _: dyn Trait + ?Leak<(), Undefined = ()>; - | ^^^^^^^^^ associated type `Undefined` not found +LL | let _: dyn LeakTr + ?Leak<(), Undefined = ()>; + | ^^^^^^^^^ associated type `Undefined` not found error: aborting due to 4 previous errors -Some errors have detailed explanations: E0107, E0220, E0277. -For more information about an error, try `rustc --explain E0107`. +Some errors have detailed explanations: E0038, E0107, E0220, E0277. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/default_auto_traits/maybe-bounds-in-traits.rs b/tests/ui/traits/default_auto_traits/maybe-bounds-in-traits.rs index b3801baaf704..ac4c4aca2efe 100644 --- a/tests/ui/traits/default_auto_traits/maybe-bounds-in-traits.rs +++ b/tests/ui/traits/default_auto_traits/maybe-bounds-in-traits.rs @@ -14,18 +14,22 @@ #![no_std] #![no_core] +#[lang = "copy"] +pub trait Copy: ?Leak {} + #[lang = "pointee_sized"] -trait PointeeSized {} +trait PointeeSized: ?Leak {} #[lang = "meta_sized"] -trait MetaSized: PointeeSized {} +trait MetaSized: PointeeSized + ?Leak {} #[lang = "sized"] -trait Sized: MetaSized {} +trait Sized: MetaSized + ?Leak {} #[lang = "legacy_receiver"] -trait LegacyReceiver {} +trait LegacyReceiver: ?Leak {} impl LegacyReceiver for &T {} +// Omit `T: ?Leak`. impl LegacyReceiver for &mut T {} #[lang = "default_trait1"] @@ -38,83 +42,40 @@ struct LeakS; mod supertraits { use crate::*; - trait MaybeLeakT1: ?Leak {} - trait MaybeLeakT2 where Self: ?Leak {} + trait MaybeLeak: ?Leak {} + impl MaybeLeak for NonLeakS {} - impl MaybeLeakT1 for NonLeakS {} - impl MaybeLeakT2 for NonLeakS {} + trait LeakT {} + impl LeakT for NonLeakS {} + //~^ ERROR the trait bound `NonLeakS: Leak` is not satisfied } -mod maybe_self_assoc_type { +mod assoc_type_maybe_bounds { use crate::*; - trait TestBase1 {} - trait TestBase2 {} - - trait Test1 { - type MaybeLeakSelf: TestBase1 where Self: ?Leak; - //~^ ERROR the trait bound `Self: Leak` is not satisfied - type LeakSelf: TestBase1; - } - - trait Test2 { - type MaybeLeakSelf: TestBase2 where Self: ?Leak; - type LeakSelf: TestBase2; - } - - trait Test3 { + trait Test1 { type Leak1 = LeakS; type Leak2 = NonLeakS; //~^ ERROR the trait bound `NonLeakS: Leak` is not satisfied } - trait Test4 { + trait Test2 { type MaybeLeak1: ?Leak = LeakS; type MaybeLeak2: ?Leak = NonLeakS; } - - trait Test5: ?Leak { - // ok, because assoc types have implicit where Self: Leak - type MaybeLeakSelf1: TestBase1; - type MaybeLeakSelf2: TestBase2; - } -} - -mod maybe_self_assoc_const { - use crate::*; - - const fn size_of() -> usize { - 0 - } - - trait Trait { - const CLeak: usize = size_of::(); - const CNonLeak: usize = size_of::() where Self: ?Leak; - //~^ ERROR the trait bound `Self: Leak` is not satisfied - } } mod methods { use crate::*; - trait Trait { - fn leak_foo(&self) {} - fn maybe_leak_foo(&self) where Self: ?Leak {} - fn mut_leak_foo(&mut self) {} - // there is no relax bound on corresponding Receiver impl - fn mut_maybe_leak_foo(&mut self) where Self: ?Leak {} - //~^ ERROR `&mut Self` cannot be used as the type of `self` without the `arbitrary_self_types` + trait ReceiveCheck1: ?Leak { + fn foo(&self) {} } - impl Trait for NonLeakS {} - impl Trait for LeakS {} - - fn foo() { - LeakS.leak_foo(); - LeakS.maybe_leak_foo(); - NonLeakS.leak_foo(); - //~^ ERROR the trait bound `NonLeakS: Leak` is not satisfied - NonLeakS.maybe_leak_foo(); + trait ReceiveCheck2: ?Leak { + // There is no `?Leak` bound on corresponding `LegacyReceiver` impl. + fn mut_foo(&mut self) {} + //~^ ERROR `&mut Self` cannot be used as the type of `self` without the `arbitrary_self_types` } } diff --git a/tests/ui/traits/default_auto_traits/maybe-bounds-in-traits.stderr b/tests/ui/traits/default_auto_traits/maybe-bounds-in-traits.stderr index 372bf8176009..ab62ab81b213 100644 --- a/tests/ui/traits/default_auto_traits/maybe-bounds-in-traits.stderr +++ b/tests/ui/traits/default_auto_traits/maybe-bounds-in-traits.stderr @@ -1,81 +1,49 @@ error[E0277]: the trait bound `NonLeakS: Leak` is not satisfied - --> $DIR/maybe-bounds-in-traits.rs:67:22 + --> $DIR/maybe-bounds-in-traits.rs:49:20 + | +LL | impl LeakT for NonLeakS {} + | ^^^^^^^^ unsatisfied trait bound + | +help: the trait `Leak` is not implemented for `NonLeakS` + --> $DIR/maybe-bounds-in-traits.rs:38:1 + | +LL | struct NonLeakS; + | ^^^^^^^^^^^^^^^ +note: required by a bound in `LeakT` + --> $DIR/maybe-bounds-in-traits.rs:48:5 + | +LL | trait LeakT {} + | ^^^^^^^^^^^^^^ required by this bound in `LeakT` + +error[E0277]: the trait bound `NonLeakS: Leak` is not satisfied + --> $DIR/maybe-bounds-in-traits.rs:58:22 | LL | type Leak2 = NonLeakS; | ^^^^^^^^ unsatisfied trait bound | help: the trait `Leak` is not implemented for `NonLeakS` - --> $DIR/maybe-bounds-in-traits.rs:34:1 + --> $DIR/maybe-bounds-in-traits.rs:38:1 | LL | struct NonLeakS; | ^^^^^^^^^^^^^^^ -note: required by a bound in `Test3::Leak2` - --> $DIR/maybe-bounds-in-traits.rs:67:9 +note: required by a bound in `Test1::Leak2` + --> $DIR/maybe-bounds-in-traits.rs:58:9 | LL | type Leak2 = NonLeakS; - | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Test3::Leak2` - -error[E0277]: the trait bound `Self: Leak` is not satisfied - --> $DIR/maybe-bounds-in-traits.rs:55:29 - | -LL | type MaybeLeakSelf: TestBase1 where Self: ?Leak; - | ^^^^^^^^^^^^^^^ the trait `Leak` is not implemented for `Self` - | -note: required by a bound in `TestBase1` - --> $DIR/maybe-bounds-in-traits.rs:51:21 - | -LL | trait TestBase1 {} - | ^ required by this bound in `TestBase1` -help: consider further restricting `Self` - | -LL | trait Test1: Leak { - | ++++++ + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Test1::Leak2` error[E0658]: `&mut Self` cannot be used as the type of `self` without the `arbitrary_self_types` feature - --> $DIR/maybe-bounds-in-traits.rs:105:31 + --> $DIR/maybe-bounds-in-traits.rs:77:20 | -LL | fn mut_maybe_leak_foo(&mut self) where Self: ?Leak {} - | ^^^^^^^^^ +LL | fn mut_foo(&mut self) {} + | ^^^^^^^^^ | = note: see issue #44874 for more information = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` -error[E0277]: the trait bound `Self: Leak` is not satisfied - --> $DIR/maybe-bounds-in-traits.rs:92:43 - | -LL | const CNonLeak: usize = size_of::() where Self: ?Leak; - | ^^^^ the trait `Leak` is not implemented for `Self` - | -note: required by a bound in `size_of` - --> $DIR/maybe-bounds-in-traits.rs:86:22 - | -LL | const fn size_of() -> usize { - | ^ required by this bound in `size_of` -help: consider further restricting `Self` - | -LL | trait Trait: Leak { - | ++++++ - -error[E0277]: the trait bound `NonLeakS: Leak` is not satisfied - --> $DIR/maybe-bounds-in-traits.rs:115:18 - | -LL | NonLeakS.leak_foo(); - | ^^^^^^^^ unsatisfied trait bound - | -help: the trait `Leak` is not implemented for `NonLeakS` - --> $DIR/maybe-bounds-in-traits.rs:34:1 - | -LL | struct NonLeakS; - | ^^^^^^^^^^^^^^^ -note: required by a bound in `methods::Trait::leak_foo` - --> $DIR/maybe-bounds-in-traits.rs:101:9 - | -LL | fn leak_foo(&self) {} - | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Trait::leak_foo` - -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0277, E0658. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/fallback.rs b/tests/ui/type-alias-impl-trait/fallback.rs deleted file mode 100644 index a2f25acca0d3..000000000000 --- a/tests/ui/type-alias-impl-trait/fallback.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Tests that we correctly handle opaque types being used opaquely, -// even within their defining scope. -// -#![feature(type_alias_impl_trait)] - -type Foo = impl Copy; - -enum Wrapper { - First(T), - Second, -} - -// This method constrains `Foo` to be `bool` -#[define_opaque(Foo)] -fn constrained_foo() -> Foo { - true -} - -// This method does not constrain `Foo`. -// Per RFC 2071, function bodies may either -// fully constrain an opaque type, or place no -// constraints on it. -#[define_opaque(Foo)] -fn unconstrained_foo() -> Wrapper { - Wrapper::Second - //~^ ERROR: type annotations needed -} - -fn main() {} diff --git a/tests/ui/type-alias-impl-trait/fallback.stderr b/tests/ui/type-alias-impl-trait/fallback.stderr deleted file mode 100644 index 1eb0afb13a8d..000000000000 --- a/tests/ui/type-alias-impl-trait/fallback.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error[E0283]: type annotations needed - --> $DIR/fallback.rs:25:5 - | -LL | fn unconstrained_foo() -> Wrapper { - | ------------ type must be known at this point -LL | Wrapper::Second - | ^^^^^^^^^^^^^^^ - | | - | cannot infer type of the type parameter `T` declared on the enum `Wrapper` - | return type was inferred to be `Wrapper<_>` here - | - = note: cannot satisfy `_: Copy` -help: consider specifying the generic argument - | -LL | Wrapper::::Second - | +++++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/type/type-name-basic.rs b/tests/ui/type/type-name-basic.rs index 343bcae175a0..2c41cb80aea8 100644 --- a/tests/ui/type/type-name-basic.rs +++ b/tests/ui/type/type-name-basic.rs @@ -107,4 +107,19 @@ pub fn main() { } let a = Wrap(&()).get(); v!(a, "type_name_basic::main::Wrap<&()>::get::Info"); + + struct Issue146249(T); + impl Issue146249> { + pub fn bar(&self) { + let f = || {}; + v!( + f, + "type_name_basic::main::Issue146249<\ + alloc::boxed::Box\ + >::bar::{{closure}}" + ); + } + } + let v: Issue146249> = Issue146249(Box::new(|| {})); + v.bar(); } diff --git a/triagebot.toml b/triagebot.toml index bf9bfee4306d..2d58c616bc27 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1308,21 +1308,32 @@ cc = ["@m-ou-se"] [mentions."compiler/rustc_ast_lowering/src/format.rs"] cc = ["@m-ou-se"] +# Content-based mentions + [mentions."#[miri::intrinsic_fallback_is_spec]"] type = "content" message = """ -`#[miri::intrinsic_fallback_is_spec]` must only be used if the function actively checks for all UB cases, +⚠️ `#[miri::intrinsic_fallback_is_spec]` must only be used if the function actively checks for all UB cases, and explores the possible non-determinism of the intrinsic. """ cc = ["@rust-lang/miri"] + [mentions."#[rustc_allow_const_fn_unstable"] type = "content" message = """ -`#[rustc_allow_const_fn_unstable]` needs careful audit to avoid accidentally exposing unstable +⚠️ `#[rustc_allow_const_fn_unstable]` needs careful audit to avoid accidentally exposing unstable implementation details on stable. """ cc = ["@rust-lang/wg-const-eval"] +[mentions."#[rustc_intrinsic_const_stable_indirect]"] +type = "content" +message = """ +⚠️ `#[rustc_intrinsic_const_stable_indirect]` controls whether intrinsics can be exposed to stable const +code; adding it needs t-lang approval. +""" +cc = ["@rust-lang/wg-const-eval"] + # ------------------------------------------------------------------------------ # PR assignments