diff options
150 files changed, 2282 insertions, 612 deletions
diff --git a/Cargo.lock b/Cargo.lock index 4bea3af7f3b..5511d301775 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -36,6 +36,17 @@ dependencies = [ ] [[package]] +name = "ahash" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf6ccdb167abbf410dcb915cabd428929d7f6a04980b54a11f26a39f1c7f7107" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", +] + +[[package]] name = "aho-corasick" version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -107,7 +118,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "276881980556fdadeb88aa1ffc667e4d2e8fe72531dfabcb7a82bb3c9ea9ba31" dependencies = [ - "object", + "object 0.29.0", ] [[package]] @@ -193,7 +204,7 @@ dependencies = [ "cfg-if", "libc", "miniz_oxide", - "object", + "object 0.29.0", "rustc-demangle", ] @@ -340,7 +351,7 @@ dependencies = [ "cargo-test-macro", "cargo-test-support", "cargo-util", - "clap 4.0.15", + "clap 4.0.32", "crates-io", "curl", "curl-sys", @@ -644,26 +655,27 @@ dependencies = [ [[package]] name = "clap" -version = "4.0.15" +version = "4.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bf8832993da70a4c6d13c581f4463c2bdda27b9bf1c5498dc4365543abe6d6f" +checksum = "a7db700bc935f9e43e88d00b0850dae18a63773cfbec6d8e070fccf7fef89a39" dependencies = [ - "atty", "bitflags", - "clap_derive 4.0.13", + "clap_derive 4.0.21", "clap_lex 0.3.0", + "is-terminal", "once_cell", "strsim", "termcolor", + "terminal_size", ] [[package]] name = "clap_complete" -version = "3.1.1" +version = "4.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df6f3613c0a3cddfd78b41b10203eb322cb29b600cbdf808a7d3db95691b8e25" +checksum = "10861370d2ba66b0f5989f83ebf35db6421713fd92351790e7fdd6c36774c56b" dependencies = [ - "clap 3.2.20", + "clap 4.0.32", ] [[package]] @@ -681,9 +693,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.0.13" +version = "4.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42f169caba89a7d512b5418b09864543eeb4d497416c917d7137863bd2076ad" +checksum = "0177313f9f02afc995627906bbd8967e2be069f5261954222dac78290c2b9014" dependencies = [ "heck", "proc-macro-error", @@ -1773,9 +1785,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.26.1" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" +checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" dependencies = [ "compiler_builtins", "fallible-iterator", @@ -1886,13 +1898,22 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ - "ahash", + "ahash 0.7.4", "compiler_builtins", "rustc-std-workspace-alloc", "rustc-std-workspace-core", ] [[package]] +name = "hashbrown" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ff8ae62cd3a9102e5637afc8452c55acf3844001bd5374e0b0bd7b6616c038" +dependencies = [ + "ahash 0.8.2", +] + +[[package]] name = "heck" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2128,12 +2149,12 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" [[package]] name = "indexmap" -version = "1.9.1" +version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.12.3", "rustc-rayon", "serde", ] @@ -2273,7 +2294,7 @@ name = "jsondoclint" version = "0.1.0" dependencies = [ "anyhow", - "clap 4.0.15", + "clap 4.0.32", "fs-err", "rustdoc-json-types", "serde", @@ -2529,21 +2550,21 @@ dependencies = [ [[package]] name = "mdbook" -version = "0.4.21" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23f3e133c6d515528745ffd3b9f0c7d975ae039f0b6abb099f2168daa2afb4f9" +checksum = "d1ed28d5903dde77bd5182645078a37ee57014cac6ccb2d54e1d6496386648e4" dependencies = [ "ammonia", "anyhow", "chrono", - "clap 3.2.20", + "clap 4.0.32", "clap_complete", "elasticlunr-rs", - "env_logger 0.9.0", + "env_logger 0.10.0", "handlebars 4.3.3", - "lazy_static", "log", "memchr", + "once_cell", "opener", "pulldown-cmark 0.9.2", "regex", @@ -2739,13 +2760,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" dependencies = [ "compiler_builtins", + "memchr", + "rustc-std-workspace-alloc", + "rustc-std-workspace-core", +] + +[[package]] +name = "object" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d864c91689fdc196779b98dba0aceac6118594c2df6ee5d943eb6a8df4d107a" +dependencies = [ "crc32fast", "flate2", - "hashbrown", + "hashbrown 0.13.1", "indexmap", "memchr", - "rustc-std-workspace-alloc", - "rustc-std-workspace-core", ] [[package]] @@ -3013,9 +3043,9 @@ dependencies = [ [[package]] name = "pest" -version = "2.3.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b0560d531d1febc25a3c9398a62a71256c0178f2e3443baedd9ad4bb8c9deb4" +checksum = "0f6e86fb9e7026527a0d46bc308b841d73170ef8f443e1807f6ef88526a816d4" dependencies = [ "thiserror", "ucd-trie", @@ -3023,9 +3053,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.3.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "905708f7f674518498c1f8d644481440f476d39ca6ecae83319bba7c6c12da91" +checksum = "96504449aa860c8dcde14f9fba5c58dc6658688ca1fe363589d6327b8662c603" dependencies = [ "pest", "pest_generator", @@ -3033,9 +3063,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.3.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5803d8284a629cc999094ecd630f55e91b561a1d1ba75e233b00ae13b91a69ad" +checksum = "798e0220d1111ae63d66cb66a5dcb3fc2d986d520b98e49e1852bfdb11d7c5e7" dependencies = [ "pest", "pest_meta", @@ -3046,13 +3076,13 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.3.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1538eb784f07615c6d9a8ab061089c6c54a344c5b4301db51990ca1c241e8c04" +checksum = "984298b75898e30a843e278a9f2452c31e349a073a0ce6fd950a12a74464e065" dependencies = [ "once_cell", "pest", - "sha-1", + "sha1", ] [[package]] @@ -3498,7 +3528,7 @@ dependencies = [ name = "rustbook" version = "0.1.0" dependencies = [ - "clap 3.2.20", + "clap 4.0.32", "env_logger 0.7.1", "mdbook", ] @@ -3790,7 +3820,7 @@ dependencies = [ "cstr", "libc", "measureme", - "object", + "object 0.30.1", "rustc-demangle", "rustc_ast", "rustc_attr", @@ -3825,7 +3855,7 @@ dependencies = [ "itertools", "jobserver", "libc", - "object", + "object 0.30.1", "pathdiff", "regex", "rustc_arena", @@ -4273,6 +4303,7 @@ version = "0.0.0" dependencies = [ "rustc_span", "tracing", + "tracing-core", "tracing-subscriber", "tracing-tree", ] @@ -4683,7 +4714,7 @@ dependencies = [ "rustc_macros", "rustc_serialize", "scoped-tls", - "sha-1", + "sha1", "sha2", "tracing", "unicode-width", @@ -5093,17 +5124,6 @@ dependencies = [ ] [[package]] -name = "sha-1" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] name = "sha1" version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -5305,11 +5325,11 @@ dependencies = [ "core", "dlmalloc", "fortanix-sgx-abi", - "hashbrown", + "hashbrown 0.12.3", "hermit-abi 0.2.6", "libc", "miniz_oxide", - "object", + "object 0.29.0", "panic_abort", "panic_unwind", "profiler_builtins", @@ -5478,6 +5498,16 @@ dependencies = [ ] [[package]] +name = "terminal_size" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb20089a8ba2b69debd491f8d2d023761cbf196e999218c591fa1e7e15a21907" +dependencies = [ + "rustix", + "windows-sys", +] + +[[package]] name = "termize" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -5528,18 +5558,18 @@ checksum = "ceb05e71730d396f960f8f3901cdb41be2d339b303e9d7d3a07c5ff0536e671b" [[package]] name = "thiserror" -version = "1.0.33" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d0a539a918745651435ac7db7a18761589a94cd7e94cd56999f828bf73c8a57" +checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.33" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c251e90f708e16c49a16f4917dc2131e75222b72edfa9cb7f7c58ae56aae0c09" +checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" dependencies = [ "proc-macro2", "quote", @@ -5548,13 +5578,13 @@ dependencies = [ [[package]] name = "thorin-dwp" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6cb0c7868d7f90407531108ab03263d9452a8811b7cdd87675343a40d4aa254" +checksum = "da8fbf660a019b6bf11ea95762041464aa9099cc293b6a66d77cea5107619671" dependencies = [ "gimli", - "hashbrown", - "object", + "hashbrown 0.12.3", + "object 0.30.1", "tracing", ] @@ -5571,6 +5601,7 @@ dependencies = [ name = "tidy" version = "0.1.0" dependencies = [ + "cargo-platform 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "cargo_metadata 0.14.0", "ignore", "lazy_static", @@ -5692,9 +5723,9 @@ dependencies = [ [[package]] name = "topological-sort" -version = "0.1.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa7c7f42dea4b1b99439786f5633aeb9c14c1b53f75e282803c2ec2ad545873c" +checksum = "ea68304e134ecd095ac6c3574494fc62b909f416c4fca77e440530221e549d3d" [[package]] name = "tracing" @@ -5820,9 +5851,9 @@ dependencies = [ [[package]] name = "ucd-trie" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" +checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" [[package]] name = "ui_test" @@ -6089,9 +6120,9 @@ checksum = "6454029bf181f092ad1b853286f23e2c507d8e8194d01d92da4a55c274a5508c" [[package]] name = "version_check" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "vte" diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 6658ee89ad6..968c1f49b95 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -6,6 +6,7 @@ use rustc_errors::{ struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan, }; use rustc_hir as hir; +use rustc_hir::def::Res; use rustc_hir::intravisit::{walk_block, walk_expr, Visitor}; use rustc_hir::{AsyncGeneratorKind, GeneratorKind, LangItem}; use rustc_infer::infer::TyCtxtInferExt; @@ -20,7 +21,7 @@ use rustc_middle::ty::{self, suggest_constraining_type_params, PredicateKind, Ty use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex}; use rustc_span::def_id::LocalDefId; use rustc_span::hygiene::DesugaringKind; -use rustc_span::symbol::sym; +use rustc_span::symbol::{kw, sym}; use rustc_span::{BytePos, Span, Symbol}; use rustc_trait_selection::infer::InferCtxtExt; @@ -29,6 +30,7 @@ use crate::borrowck_errors; use crate::diagnostics::conflict_errors::StorageDeadOrDrop::LocalStorageDead; use crate::diagnostics::find_all_local_uses; +use crate::diagnostics::mutability_errors::mut_borrow_of_mutable_ref; use crate::{ borrow_set::BorrowData, diagnostics::Instance, prefixes::IsPrefixOf, InitializationRequiringAction, MirBorrowckCtxt, PrefixSet, WriteKind, @@ -356,7 +358,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. - })) = hir.find(hir.local_def_id_to_hir_id(self.mir_def_id())) + })) = hir.find(self.mir_hir_id()) && let Some(hir::Node::Expr(expr)) = hir.find(body_id.hir_id) { let place = &self.move_data.move_paths[mpi].place; @@ -948,7 +950,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } (BorrowKind::Mut { .. }, BorrowKind::Shared) => { first_borrow_desc = "immutable "; - self.cannot_reborrow_already_borrowed( + let mut err = self.cannot_reborrow_already_borrowed( span, &desc_place, &msg_place, @@ -958,7 +960,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { "immutable", &msg_borrow, None, - ) + ); + self.suggest_binding_for_closure_capture_self( + &mut err, + issued_borrow.borrowed_place, + &issued_spans, + ); + err } (BorrowKind::Mut { .. }, BorrowKind::Mut { .. }) => { @@ -1240,6 +1248,138 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } + fn suggest_binding_for_closure_capture_self( + &self, + err: &mut Diagnostic, + borrowed_place: Place<'tcx>, + issued_spans: &UseSpans<'tcx>, + ) { + let UseSpans::ClosureUse { capture_kind_span, .. } = issued_spans else { return }; + let hir = self.infcx.tcx.hir(); + + // check whether the borrowed place is capturing `self` by mut reference + let local = borrowed_place.local; + let Some(_) = self + .body + .local_decls + .get(local) + .map(|l| mut_borrow_of_mutable_ref(l, self.local_names[local])) else { return }; + + struct ExpressionFinder<'hir> { + capture_span: Span, + closure_change_spans: Vec<Span>, + closure_arg_span: Option<Span>, + in_closure: bool, + suggest_arg: String, + hir: rustc_middle::hir::map::Map<'hir>, + closure_local_id: Option<hir::HirId>, + closure_call_changes: Vec<(Span, String)>, + } + impl<'hir> Visitor<'hir> for ExpressionFinder<'hir> { + fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) { + if e.span.contains(self.capture_span) { + if let hir::ExprKind::Closure(&hir::Closure { + movability: None, + body, + fn_arg_span, + fn_decl: hir::FnDecl{ inputs, .. }, + .. + }) = e.kind && + let Some(hir::Node::Expr(body )) = self.hir.find(body.hir_id) { + self.suggest_arg = "this: &Self".to_string(); + if inputs.len() > 0 { + self.suggest_arg.push_str(", "); + } + self.in_closure = true; + self.closure_arg_span = fn_arg_span; + self.visit_expr(body); + self.in_closure = false; + } + } + if let hir::Expr { kind: hir::ExprKind::Path(path), .. } = e { + if let hir::QPath::Resolved(_, hir::Path { segments: [seg], ..}) = path && + seg.ident.name == kw::SelfLower && self.in_closure { + self.closure_change_spans.push(e.span); + } + } + hir::intravisit::walk_expr(self, e); + } + + fn visit_local(&mut self, local: &'hir hir::Local<'hir>) { + if let hir::Pat { kind: hir::PatKind::Binding(_, hir_id, _ident, _), .. } = local.pat && + let Some(init) = local.init + { + if let hir::Expr { kind: hir::ExprKind::Closure(&hir::Closure { + movability: None, + .. + }), .. } = init && + init.span.contains(self.capture_span) { + self.closure_local_id = Some(*hir_id); + } + } + hir::intravisit::walk_local(self, local); + } + + fn visit_stmt(&mut self, s: &'hir hir::Stmt<'hir>) { + if let hir::StmtKind::Semi(e) = s.kind && + let hir::ExprKind::Call(hir::Expr { kind: hir::ExprKind::Path(path), ..}, args) = e.kind && + let hir::QPath::Resolved(_, hir::Path { segments: [seg], ..}) = path && + let Res::Local(hir_id) = seg.res && + Some(hir_id) == self.closure_local_id { + let (span, arg_str) = if args.len() > 0 { + (args[0].span.shrink_to_lo(), "self, ".to_string()) + } else { + let span = e.span.trim_start(seg.ident.span).unwrap_or(e.span); + (span, "(self)".to_string()) + }; + self.closure_call_changes.push((span, arg_str)); + } + hir::intravisit::walk_stmt(self, s); + } + } + + if let Some(hir::Node::ImplItem( + hir::ImplItem { kind: hir::ImplItemKind::Fn(_fn_sig, body_id), .. } + )) = hir.find(self.mir_hir_id()) && + let Some(hir::Node::Expr(expr)) = hir.find(body_id.hir_id) { + let mut finder = ExpressionFinder { + capture_span: *capture_kind_span, + closure_change_spans: vec![], + closure_arg_span: None, + in_closure: false, + suggest_arg: String::new(), + closure_local_id: None, + closure_call_changes: vec![], + hir, + }; + finder.visit_expr(expr); + + if finder.closure_change_spans.is_empty() || finder.closure_call_changes.is_empty() { + return; + } + + let mut sugg = vec![]; + let sm = self.infcx.tcx.sess.source_map(); + + if let Some(span) = finder.closure_arg_span { + sugg.push((sm.next_point(span.shrink_to_lo()).shrink_to_hi(), finder.suggest_arg)); + } + for span in finder.closure_change_spans { + sugg.push((span, "this".to_string())); + } + + for (span, suggest) in finder.closure_call_changes { + sugg.push((span, suggest)); + } + + err.multipart_suggestion_verbose( + "try explicitly pass `&Self` into the Closure as an argument", + sugg, + Applicability::MachineApplicable, + ); + } + } + /// Returns the description of the root place for a conflicting borrow and the full /// descriptions of the places that caused the conflict. /// diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index b9cfc7e6961..45b15c2c5bd 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -1094,7 +1094,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } } -fn mut_borrow_of_mutable_ref(local_decl: &LocalDecl<'_>, local_name: Option<Symbol>) -> bool { +pub fn mut_borrow_of_mutable_ref(local_decl: &LocalDecl<'_>, local_name: Option<Symbol>) -> bool { debug!("local_info: {:?}, ty.kind(): {:?}", local_decl.local_info, local_decl.ty.kind()); match local_decl.local_info.as_deref() { diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml index 93d6234dc88..9c1bcd431ec 100644 --- a/compiler/rustc_codegen_llvm/Cargo.toml +++ b/compiler/rustc_codegen_llvm/Cargo.toml @@ -11,7 +11,10 @@ bitflags = "1.0" cstr = "0.2" libc = "0.2" measureme = "10.0.0" -object = { version = "0.29.0", default-features = false, features = ["std", "read"] } +object = { version = "0.30.1", default-features = false, features = [ + "std", + "read", +] } tracing = "0.1" rustc_middle = { path = "../rustc_middle" } rustc-demangle = "0.1.21" diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index d1ad687e6ae..0d2d2ec68a2 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -15,7 +15,7 @@ tracing = "0.1" libc = "0.2.50" jobserver = "0.1.22" tempfile = "3.2" -thorin-dwp = "0.3" +thorin-dwp = "0.4" pathdiff = "0.2.0" serde_json = "1.0.59" snap = "1" @@ -44,6 +44,6 @@ rustc_session = { path = "../rustc_session" } rustc_const_eval = { path = "../rustc_const_eval" } [dependencies.object] -version = "0.29.0" +version = "0.30.1" default-features = false features = ["read_core", "elf", "macho", "pe", "unaligned", "archive", "write"] diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 8ca7103ed48..342abf81f6a 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1231,12 +1231,21 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) { sess.emit_fatal(errors::LinkerFileStem); }); + // Remove any version postfix. + let stem = stem + .rsplit_once('-') + .and_then(|(lhs, rhs)| rhs.chars().all(char::is_numeric).then_some(lhs)) + .unwrap_or(stem); + + // GCC can have an optional target prefix. let flavor = if stem == "emcc" { LinkerFlavor::EmCc } else if stem == "gcc" || stem.ends_with("-gcc") + || stem == "g++" + || stem.ends_with("-g++") || stem == "clang" - || stem.ends_with("-clang") + || stem == "clang++" { LinkerFlavor::from_cli(LinkerFlavorCli::Gcc, &sess.target) } else if stem == "wasm-ld" || stem.ends_with("-wasm-ld") { diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index 51c5c375d51..7d3c14fec5f 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -100,7 +100,13 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static }; let architecture = match &sess.target.arch[..] { "arm" => Architecture::Arm, - "aarch64" => Architecture::Aarch64, + "aarch64" => { + if sess.target.pointer_width == 32 { + Architecture::Aarch64_Ilp32 + } else { + Architecture::Aarch64 + } + } "x86" => Architecture::I386, "s390x" => Architecture::S390x, "mips" => Architecture::Mips, @@ -165,11 +171,23 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static }; e_flags } - Architecture::Riscv64 if sess.target.options.features.contains("+d") => { - // copied from `riscv64-linux-gnu-gcc foo.c -c`, note though - // that the `+d` target feature represents whether the double - // float abi is enabled. - let e_flags = elf::EF_RISCV_RVC | elf::EF_RISCV_FLOAT_ABI_DOUBLE; + Architecture::Riscv32 | Architecture::Riscv64 => { + // Source: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/079772828bd10933d34121117a222b4cc0ee2200/riscv-elf.adoc + let mut e_flags: u32 = 0x0; + let features = &sess.target.options.features; + // Check if compressed is enabled + if features.contains("+c") { + e_flags |= elf::EF_RISCV_RVC; + } + + // Select the appropriate floating-point ABI + if features.contains("+d") { + e_flags |= elf::EF_RISCV_FLOAT_ABI_DOUBLE; + } else if features.contains("+f") { + e_flags |= elf::EF_RISCV_FLOAT_ABI_SINGLE; + } else { + e_flags |= elf::EF_RISCV_FLOAT_ABI_SOFT; + } e_flags } _ => 0, diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 16f64235562..a62e5dec4b8 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -231,6 +231,10 @@ fn run_compiler( registry: diagnostics_registry(), }; + if !tracing::dispatcher::has_been_set() { + init_rustc_env_logger_with_backtrace_option(&config.opts.unstable_opts.log_backtrace); + } + match make_input(config.opts.error_format, &matches.free) { Err(reported) => return Err(reported), Ok(Some((input, input_file_path))) => { @@ -1300,7 +1304,14 @@ pub fn install_ice_hook() { /// This allows tools to enable rust logging without having to magically match rustc's /// tracing crate version. pub fn init_rustc_env_logger() { - if let Err(error) = rustc_log::init_rustc_env_logger() { + init_rustc_env_logger_with_backtrace_option(&None); +} + +/// This allows tools to enable rust logging without having to magically match rustc's +/// tracing crate version. In contrast to `init_rustc_env_logger` it allows you to +/// choose a target module you wish to show backtraces along with its logging. +pub fn init_rustc_env_logger_with_backtrace_option(backtrace_target: &Option<String>) { + if let Err(error) = rustc_log::init_rustc_env_logger_with_backtrace_option(backtrace_target) { early_error(ErrorOutputType::default(), &error.to_string()); } } @@ -1366,7 +1377,6 @@ mod signal_handler { pub fn main() -> ! { let start_time = Instant::now(); let start_rss = get_resident_set_size(); - init_rustc_env_logger(); signal_handler::install(); let mut callbacks = TimePassesCallbacks::default(); install_ice_hook(); diff --git a/compiler/rustc_error_messages/locales/en-US/interface.ftl b/compiler/rustc_error_messages/locales/en-US/interface.ftl index bbcb8fc28cf..688b0447222 100644 --- a/compiler/rustc_error_messages/locales/en-US/interface.ftl +++ b/compiler/rustc_error_messages/locales/en-US/interface.ftl @@ -41,3 +41,6 @@ interface_rustc_error_unexpected_annotation = interface_failed_writing_file = failed to write file {$path}: {$error}" + +interface_proc_macro_crate_panic_abort = + building proc macro crate with `panic=abort` may crash the compiler should the proc-macro panic diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 00453f78287..ffde8480c02 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -31,11 +31,11 @@ use rustc_span::edition::Edition; use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId}; use rustc_span::source_map::SourceMap; use rustc_span::symbol::{kw, sym, Ident, Symbol}; -use rustc_span::{BytePos, FileName, RealFileName, Span, DUMMY_SP}; +use rustc_span::{BytePos, FileName, Span, DUMMY_SP}; use smallvec::{smallvec, SmallVec}; use std::iter; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::rc::Rc; pub(crate) use rustc_span::hygiene::MacroKind; @@ -1423,8 +1423,10 @@ fn pretty_printing_compatibility_hack(item: &Item, sess: &ParseSess) -> bool { if let [variant] = &*enum_def.variants { if variant.ident.name == sym::Input { let filename = sess.source_map().span_to_filename(item.ident.span); - if let FileName::Real(RealFileName::LocalPath(path)) = filename { - if let Some(c) = path + if let FileName::Real(real) = filename { + if let Some(c) = real + .local_path() + .unwrap_or(Path::new("")) .components() .flat_map(|c| c.as_os_str().to_str()) .find(|c| c.starts_with("rental") || c.starts_with("allsorts-rental")) diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 9fa0e6e8eaa..3521911b055 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -27,6 +27,7 @@ use rustc_hir::def::{CtorOf, DefKind, Namespace, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{walk_generics, Visitor as _}; use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin}; +use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::middle::stability::AllowUnstable; use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, SubstsRef}; use rustc_middle::ty::GenericParamDefKind; @@ -1643,8 +1644,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { fn report_ambiguous_associated_type( &self, span: Span, - type_str: &str, - trait_str: &str, + types: &[String], + traits: &[String], name: Symbol, ) -> ErrorGuaranteed { let mut err = struct_span_err!(self.tcx().sess, span, E0223, "ambiguous associated type"); @@ -1655,19 +1656,92 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .keys() .any(|full_span| full_span.contains(span)) { - err.span_suggestion( + err.span_suggestion_verbose( span.shrink_to_lo(), "you are looking for the module in `std`, not the primitive type", "std::", Applicability::MachineApplicable, ); } else { - err.span_suggestion( - span, - "use fully-qualified syntax", - format!("<{} as {}>::{}", type_str, trait_str, name), - Applicability::HasPlaceholders, - ); + match (types, traits) { + ([], []) => { + err.span_suggestion_verbose( + span, + &format!( + "if there were a type named `Type` that implements a trait named \ + `Trait` with associated type `{name}`, you could use the \ + fully-qualified path", + ), + format!("<Type as Trait>::{name}"), + Applicability::HasPlaceholders, + ); + } + ([], [trait_str]) => { + err.span_suggestion_verbose( + span, + &format!( + "if there were a type named `Example` that implemented `{trait_str}`, \ + you could use the fully-qualified path", + ), + format!("<Example as {trait_str}>::{name}"), + Applicability::HasPlaceholders, + ); + } + ([], traits) => { + err.span_suggestions( + span, + &format!( + "if there were a type named `Example` that implemented one of the \ + traits with associated type `{name}`, you could use the \ + fully-qualified path", + ), + traits + .iter() + .map(|trait_str| format!("<Example as {trait_str}>::{name}")) + .collect::<Vec<_>>(), + Applicability::HasPlaceholders, + ); + } + ([type_str], []) => { + err.span_suggestion_verbose( + span, + &format!( + "if there were a trait named `Example` with associated type `{name}` \ + implemented for `{type_str}`, you could use the fully-qualified path", + ), + format!("<{type_str} as Example>::{name}"), + Applicability::HasPlaceholders, + ); + } + (types, []) => { + err.span_suggestions( + span, + &format!( + "if there were a trait named `Example` with associated type `{name}` \ + implemented for one of the types, you could use the fully-qualified \ + path", + ), + types + .into_iter() + .map(|type_str| format!("<{type_str} as Example>::{name}")), + Applicability::HasPlaceholders, + ); + } + (types, traits) => { + let mut suggestions = vec![]; + for type_str in types { + for trait_str in traits { + suggestions.push(format!("<{type_str} as {trait_str}>::{name}")); + } + } + err.span_suggestions( + span, + "use the fully-qualified path", + suggestions, + Applicability::MachineApplicable, + ); + } + } } err.emit() } @@ -2050,12 +2124,64 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { err.emit() } else if let Err(reported) = qself_ty.error_reported() { reported + } else if let ty::Alias(ty::Opaque, alias_ty) = qself_ty.kind() { + // `<impl Trait as OtherTrait>::Assoc` makes no sense. + struct_span_err!( + tcx.sess, + tcx.def_span(alias_ty.def_id), + E0667, + "`impl Trait` is not allowed in path parameters" + ) + .emit() // Already reported in an earlier stage. } else { + // Find all the `impl`s that `qself_ty` has for any trait that has the + // associated type, so that we suggest the right one. + let infcx = tcx.infer_ctxt().build(); + // We create a fresh `ty::ParamEnv` instead of the one for `self.item_def_id()` + // to avoid a cycle error in `src/test/ui/resolve/issue-102946.rs`. + let param_env = ty::ParamEnv::empty(); + let traits: Vec<_> = self + .tcx() + .all_traits() + .filter(|trait_def_id| { + // Consider only traits with the associated type + tcx.associated_items(*trait_def_id) + .in_definition_order() + .any(|i| { + i.kind.namespace() == Namespace::TypeNS + && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident + && matches!(i.kind, ty::AssocKind::Type) + }) + // Consider only accessible traits + && tcx.visibility(*trait_def_id) + .is_accessible_from(self.item_def_id(), tcx) + && tcx.all_impls(*trait_def_id) + .any(|impl_def_id| { + let trait_ref = tcx.bound_impl_trait_ref(impl_def_id); + trait_ref.map_or(false, |trait_ref| { + let impl_ = trait_ref.subst( + tcx, + infcx.fresh_substs_for_item(span, impl_def_id), + ); + infcx + .can_eq( + param_env, + tcx.erase_regions(impl_.self_ty()), + tcx.erase_regions(qself_ty), + ) + .is_ok() + }) + && tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative + }) + }) + .map(|trait_def_id| tcx.def_path_str(trait_def_id)) + .collect(); + // Don't print `TyErr` to the user. self.report_ambiguous_associated_type( span, - &qself_ty.to_string(), - "Trait", + &[qself_ty.to_string()], + &traits, assoc_ident.name, ) }; @@ -2173,16 +2299,30 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let is_part_of_self_trait_constraints = def_id == trait_def_id; let is_part_of_fn_in_self_trait = parent_def_id == Some(trait_def_id); - let type_name = if is_part_of_self_trait_constraints || is_part_of_fn_in_self_trait { - "Self" + let type_names = if is_part_of_self_trait_constraints || is_part_of_fn_in_self_trait { + vec!["Self".to_string()] } else { - "Type" + // Find all the types that have an `impl` for the trait. + tcx.all_impls(trait_def_id) + .filter(|impl_def_id| { + // Consider only accessible traits + tcx.visibility(*impl_def_id).is_accessible_from(self.item_def_id(), tcx) + && tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative + }) + .filter_map(|impl_def_id| tcx.impl_trait_ref(impl_def_id)) + .map(|impl_| impl_.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()) + .collect() }; - + // FIXME: also look at `tcx.generics_of(self.item_def_id()).params` any that + // references the trait. Relevant for the first case in + // `src/test/ui/associated-types/associated-types-in-ambiguous-context.rs` let reported = self.report_ambiguous_associated_type( span, - type_name, - &path_str, + &type_names, + &[path_str], item_segment.ident.name, ); return tcx.ty_error_with_guaranteed(reported) diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 7af89934d14..2cdf7579471 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -2,7 +2,9 @@ use super::potentially_plural_count; use crate::errors::LifetimesOrBoundsMismatchOnTrait; use hir::def_id::{DefId, LocalDefId}; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; -use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed}; +use rustc_errors::{ + pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed, MultiSpan, +}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit; @@ -320,15 +322,6 @@ fn compare_method_predicate_entailment<'tcx>( ty::Binder::dummy(ty::PredicateKind::WellFormed(unnormalized_impl_fty.into())), )); } - let emit_implied_wf_lint = || { - infcx.tcx.struct_span_lint_hir( - rustc_session::lint::builtin::IMPLIED_BOUNDS_ENTAILMENT, - impl_m_hir_id, - infcx.tcx.def_span(impl_m.def_id), - "impl method assumes more implied bounds than the corresponding trait method", - |lint| lint, - ); - }; // Check that all obligations are satisfied by the implementation's // version. @@ -346,7 +339,7 @@ fn compare_method_predicate_entailment<'tcx>( ) .map(|()| { // If the skip-mode was successful, emit a lint. - emit_implied_wf_lint(); + emit_implied_wf_lint(infcx.tcx, impl_m, impl_m_hir_id, vec![]); }); } CheckImpliedWfMode::Skip => { @@ -382,8 +375,16 @@ fn compare_method_predicate_entailment<'tcx>( CheckImpliedWfMode::Skip, ) .map(|()| { + let bad_args = extract_bad_args_for_implies_lint( + tcx, + &errors, + (trait_m, trait_sig), + // Unnormalized impl sig corresponds to the HIR types written + (impl_m, unnormalized_impl_sig), + impl_m_hir_id, + ); // If the skip-mode was successful, emit a lint. - emit_implied_wf_lint(); + emit_implied_wf_lint(tcx, impl_m, impl_m_hir_id, bad_args); }); } CheckImpliedWfMode::Skip => { @@ -400,6 +401,141 @@ fn compare_method_predicate_entailment<'tcx>( Ok(()) } +fn extract_bad_args_for_implies_lint<'tcx>( + tcx: TyCtxt<'tcx>, + errors: &[infer::RegionResolutionError<'tcx>], + (trait_m, trait_sig): (&ty::AssocItem, ty::FnSig<'tcx>), + (impl_m, impl_sig): (&ty::AssocItem, ty::FnSig<'tcx>), + hir_id: hir::HirId, +) -> Vec<(Span, Option<String>)> { + let mut blame_generics = vec![]; + for error in errors { + // Look for the subregion origin that contains an input/output type + let origin = match error { + infer::RegionResolutionError::ConcreteFailure(o, ..) => o, + infer::RegionResolutionError::GenericBoundFailure(o, ..) => o, + infer::RegionResolutionError::SubSupConflict(_, _, o, ..) => o, + infer::RegionResolutionError::UpperBoundUniverseConflict(.., o, _) => o, + }; + // Extract (possible) input/output types from origin + match origin { + infer::SubregionOrigin::Subtype(trace) => { + if let Some((a, b)) = trace.values.ty() { + blame_generics.extend([a, b]); + } + } + infer::SubregionOrigin::RelateParamBound(_, ty, _) => blame_generics.push(*ty), + infer::SubregionOrigin::ReferenceOutlivesReferent(ty, _) => blame_generics.push(*ty), + _ => {} + } + } + + let fn_decl = tcx.hir().fn_decl_by_hir_id(hir_id).unwrap(); + let opt_ret_ty = match fn_decl.output { + hir::FnRetTy::DefaultReturn(_) => None, + hir::FnRetTy::Return(ty) => Some(ty), + }; + + // Map late-bound regions from trait to impl, so the names are right. + let mapping = std::iter::zip( + tcx.fn_sig(trait_m.def_id).bound_vars(), + tcx.fn_sig(impl_m.def_id).bound_vars(), + ) + .filter_map(|(impl_bv, trait_bv)| { + if let ty::BoundVariableKind::Region(impl_bv) = impl_bv + && let ty::BoundVariableKind::Region(trait_bv) = trait_bv + { + Some((impl_bv, trait_bv)) + } else { + None + } + }) + .collect(); + + // For each arg, see if it was in the "blame" of any of the region errors. + // If so, then try to produce a suggestion to replace the argument type with + // one from the trait. + let mut bad_args = vec![]; + for (idx, (ty, hir_ty)) in + std::iter::zip(impl_sig.inputs_and_output, fn_decl.inputs.iter().chain(opt_ret_ty)) + .enumerate() + { + let expected_ty = trait_sig.inputs_and_output[idx] + .fold_with(&mut RemapLateBound { tcx, mapping: &mapping }); + if blame_generics.iter().any(|blame| ty.contains(*blame)) { + let expected_ty_sugg = expected_ty.to_string(); + bad_args.push(( + hir_ty.span, + // Only suggest something if it actually changed. + (expected_ty_sugg != ty.to_string()).then_some(expected_ty_sugg), + )); + } + } + + bad_args +} + +struct RemapLateBound<'a, 'tcx> { + tcx: TyCtxt<'tcx>, + mapping: &'a FxHashMap<ty::BoundRegionKind, ty::BoundRegionKind>, +} + +impl<'tcx> TypeFolder<'tcx> for RemapLateBound<'_, 'tcx> { + fn tcx(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + if let ty::ReFree(fr) = *r { + self.tcx.mk_region(ty::ReFree(ty::FreeRegion { + bound_region: self + .mapping + .get(&fr.bound_region) + .copied() + .unwrap_or(fr.bound_region), + ..fr + })) + } else { + r + } + } +} + +fn emit_implied_wf_lint<'tcx>( + tcx: TyCtxt<'tcx>, + impl_m: &ty::AssocItem, + hir_id: hir::HirId, + bad_args: Vec<(Span, Option<String>)>, +) { + let span: MultiSpan = if bad_args.is_empty() { + tcx.def_span(impl_m.def_id).into() + } else { + bad_args.iter().map(|(span, _)| *span).collect::<Vec<_>>().into() + }; + tcx.struct_span_lint_hir( + rustc_session::lint::builtin::IMPLIED_BOUNDS_ENTAILMENT, + hir_id, + span, + "impl method assumes more implied bounds than the corresponding trait method", + |lint| { + let bad_args: Vec<_> = + bad_args.into_iter().filter_map(|(span, sugg)| Some((span, sugg?))).collect(); + if !bad_args.is_empty() { + lint.multipart_suggestion( + format!( + "replace {} type{} to make the impl signature compatible", + pluralize!("this", bad_args.len()), + pluralize!(bad_args.len()) + ), + bad_args, + Applicability::MaybeIncorrect, + ); + } + lint + }, + ); +} + #[derive(Debug, PartialEq, Eq)] enum CheckImpliedWfMode { /// Checks implied well-formedness of the impl method. If it fails, we will diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 6c128d0aa1a..665dc8b6a2f 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -85,6 +85,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.note_internal_mutation_in_method(err, expr, expected, expr_ty); self.check_for_range_as_method_call(err, expr, expr_ty, expected); self.check_for_binding_assigned_block_without_tail_expression(err, expr, expr_ty, expected); + self.check_wrong_return_type_due_to_generic_arg(err, expr, expr_ty); } /// Requires that the two types unify, and prints an error message if @@ -1941,4 +1942,77 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_label(block.span, "this block is missing a tail expression"); } } + + fn check_wrong_return_type_due_to_generic_arg( + &self, + err: &mut Diagnostic, + expr: &hir::Expr<'_>, + checked_ty: Ty<'tcx>, + ) { + let Some(hir::Node::Expr(parent_expr)) = self.tcx.hir().find_parent(expr.hir_id) else { return; }; + enum CallableKind { + Function, + Method, + Constructor, + } + let mut maybe_emit_help = |def_id: hir::def_id::DefId, + callable: rustc_span::symbol::Ident, + args: &[hir::Expr<'_>], + kind: CallableKind| { + let arg_idx = args.iter().position(|a| a.hir_id == expr.hir_id).unwrap(); + let fn_ty = self.tcx.bound_type_of(def_id).0; + if !fn_ty.is_fn() { + return; + } + let fn_sig = fn_ty.fn_sig(self.tcx).skip_binder(); + let Some(&arg) = fn_sig.inputs().get(arg_idx + if matches!(kind, CallableKind::Method) { 1 } else { 0 }) else { return; }; + if matches!(arg.kind(), ty::Param(_)) + && fn_sig.output().contains(arg) + && self.node_ty(args[arg_idx].hir_id) == checked_ty + { + let mut multi_span: MultiSpan = parent_expr.span.into(); + multi_span.push_span_label( + args[arg_idx].span, + format!( + "this argument influences the {} of `{}`", + if matches!(kind, CallableKind::Constructor) { + "type" + } else { + "return type" + }, + callable + ), + ); + err.span_help( + multi_span, + format!( + "the {} `{}` due to the type of the argument passed", + match kind { + CallableKind::Function => "return type of this call is", + CallableKind::Method => "return type of this call is", + CallableKind::Constructor => "type constructed contains", + }, + checked_ty + ), + ); + } + }; + match parent_expr.kind { + hir::ExprKind::Call(fun, args) => { + let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = fun.kind else { return; }; + let hir::def::Res::Def(kind, def_id) = path.res else { return; }; + let callable_kind = if matches!(kind, hir::def::DefKind::Ctor(_, _)) { + CallableKind::Constructor + } else { + CallableKind::Function + }; + maybe_emit_help(def_id, path.segments[0].ident, args, callable_kind); + } + hir::ExprKind::MethodCall(method, _receiver, args, _span) => { + let Some(def_id) = self.typeck_results.borrow().type_dependent_def_id(parent_expr.hir_id) else { return; }; + maybe_emit_help(def_id, method.ident, args, CallableKind::Method) + } + _ => return, + } + } } diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index e67dec31dce..f817c5bc1cd 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -45,6 +45,7 @@ rustc_plugin_impl = { path = "../rustc_plugin_impl" } rustc_privacy = { path = "../rustc_privacy" } rustc_query_impl = { path = "../rustc_query_impl" } rustc_resolve = { path = "../rustc_resolve" } +rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_ty_utils = { path = "../rustc_ty_utils" } diff --git a/compiler/rustc_interface/src/errors.rs b/compiler/rustc_interface/src/errors.rs index f5135c78dc8..15d7e977bbe 100644 --- a/compiler/rustc_interface/src/errors.rs +++ b/compiler/rustc_interface/src/errors.rs @@ -87,3 +87,7 @@ pub struct FailedWritingFile<'a> { pub path: &'a Path, pub error: io::Error, } + +#[derive(Diagnostic)] +#[diag(interface_proc_macro_crate_panic_abort)] +pub struct ProcMacroCratePanicAbort; diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 2a6852d44eb..50c40206d80 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -1,7 +1,8 @@ use crate::errors::{ CantEmitMIR, EmojiIdentifier, ErrorWritingDependencies, FerrisIdentifier, GeneratedFileConflictsWithDirectory, InputFileWouldBeOverWritten, MixedBinCrate, - MixedProcMacroCrate, OutDirError, ProcMacroDocWithoutArg, TempsDirError, + MixedProcMacroCrate, OutDirError, ProcMacroCratePanicAbort, ProcMacroDocWithoutArg, + TempsDirError, }; use crate::interface::{Compiler, Result}; use crate::proc_macro_decls; @@ -36,6 +37,7 @@ use rustc_session::search_paths::PathKind; use rustc_session::{Limit, Session}; use rustc_span::symbol::{sym, Symbol}; use rustc_span::FileName; +use rustc_target::spec::PanicStrategy; use rustc_trait_selection::traits; use std::any::Any; @@ -380,6 +382,10 @@ pub fn configure_and_expand( } } + if is_proc_macro_crate && sess.panic_strategy() == PanicStrategy::Abort { + sess.emit_warning(ProcMacroCratePanicAbort); + } + // For backwards compatibility, we don't try to run proc macro injection // if rustdoc is run on a proc macro crate without '--crate-type proc-macro' being // specified. This should only affect users who manually invoke 'rustdoc', as diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index a3b9891ee64..07b28cc86ce 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -748,6 +748,7 @@ fn test_unstable_options_tracking_hash() { tracked!(link_only, true); tracked!(llvm_plugins, vec![String::from("plugin_name")]); tracked!(location_detail, LocationDetail { file: true, line: false, column: false }); + tracked!(log_backtrace, Some("filter".to_string())); tracked!(maximal_hir_to_mir_coverage, true); tracked!(merge_functions, Some(MergeFunctions::Disabled)); tracked!(mir_emit_retag, true); diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 28317d6cea0..6cdf5097083 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -4033,10 +4033,10 @@ declare_lint! { /// /// This can be used to implement an unsound API if used incorrectly. pub IMPLIED_BOUNDS_ENTAILMENT, - Warn, + Deny, "impl method assumes more implied bounds than its corresponding trait method", @future_incompatible = FutureIncompatibleInfo { reference: "issue #105572 <https://github.com/rust-lang/rust/issues/105572>", - reason: FutureIncompatibilityReason::FutureReleaseError, + reason: FutureIncompatibilityReason::FutureReleaseErrorReportNow, }; } diff --git a/compiler/rustc_log/Cargo.toml b/compiler/rustc_log/Cargo.toml index 3c50827c1ab..7f955b0a750 100644 --- a/compiler/rustc_log/Cargo.toml +++ b/compiler/rustc_log/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" tracing = "0.1.28" tracing-subscriber = { version = "0.3.3", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] } tracing-tree = "0.2.0" +tracing-core = "0.1.28" [dev-dependencies] rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs index 4cac88aff64..fc1cabd2de9 100644 --- a/compiler/rustc_log/src/lib.rs +++ b/compiler/rustc_log/src/lib.rs @@ -45,16 +45,34 @@ use std::env::{self, VarError}; use std::fmt::{self, Display}; use std::io::{self, IsTerminal}; +use tracing_core::{Event, Subscriber}; use tracing_subscriber::filter::{Directive, EnvFilter, LevelFilter}; +use tracing_subscriber::fmt::{ + format::{self, FormatEvent, FormatFields}, + FmtContext, +}; use tracing_subscriber::layer::SubscriberExt; pub fn init_rustc_env_logger() -> Result<(), Error> { - init_env_logger("RUSTC_LOG") + init_rustc_env_logger_with_backtrace_option(&None) +} + +pub fn init_rustc_env_logger_with_backtrace_option( + backtrace_target: &Option<String>, +) -> Result<(), Error> { + init_env_logger_with_backtrace_option("RUSTC_LOG", backtrace_target) } /// In contrast to `init_rustc_env_logger` this allows you to choose an env var /// other than `RUSTC_LOG`. pub fn init_env_logger(env: &str) -> Result<(), Error> { + init_env_logger_with_backtrace_option(env, &None) +} + +pub fn init_env_logger_with_backtrace_option( + env: &str, + backtrace_target: &Option<String>, +) -> Result<(), Error> { let filter = match env::var(env) { Ok(env) => EnvFilter::new(env), _ => EnvFilter::default().add_directive(Directive::from(LevelFilter::WARN)), @@ -88,11 +106,47 @@ pub fn init_env_logger(env: &str) -> Result<(), Error> { let layer = layer.with_thread_ids(true).with_thread_names(true); let subscriber = tracing_subscriber::Registry::default().with(filter).with(layer); - tracing::subscriber::set_global_default(subscriber).unwrap(); + match backtrace_target { + Some(str) => { + let fmt_layer = tracing_subscriber::fmt::layer() + .with_writer(io::stderr) + .without_time() + .event_format(BacktraceFormatter { backtrace_target: str.to_string() }); + let subscriber = subscriber.with(fmt_layer); + tracing::subscriber::set_global_default(subscriber).unwrap(); + } + None => { + tracing::subscriber::set_global_default(subscriber).unwrap(); + } + }; Ok(()) } +struct BacktraceFormatter { + backtrace_target: String, +} + +impl<S, N> FormatEvent<S, N> for BacktraceFormatter +where + S: Subscriber + for<'a> tracing_subscriber::registry::LookupSpan<'a>, + N: for<'a> FormatFields<'a> + 'static, +{ + fn format_event( + &self, + _ctx: &FmtContext<'_, S, N>, + mut writer: format::Writer<'_>, + event: &Event<'_>, + ) -> fmt::Result { + let target = event.metadata().target(); + if !target.contains(&self.backtrace_target) { + return Ok(()); + } + let backtrace = std::backtrace::Backtrace::capture(); + writeln!(writer, "stack backtrace: \n{:?}", backtrace) + } +} + pub fn stdout_isatty() -> bool { io::stdout().is_terminal() } diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index f027843e6b4..8761c23625b 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -79,7 +79,7 @@ impl<'a> StringReader<'a> { /// preceded by whitespace. fn next_token(&mut self) -> (Token, bool) { let mut preceded_by_whitespace = false; - + let mut swallow_next_invalid = 0; // Skip trivial (whitespace & comments) tokens loop { let token = self.cursor.advance_token(); @@ -232,19 +232,34 @@ impl<'a> StringReader<'a> { rustc_lexer::TokenKind::Percent => token::BinOp(token::Percent), rustc_lexer::TokenKind::Unknown | rustc_lexer::TokenKind::InvalidIdent => { - let c = self.str_from(start).chars().next().unwrap(); + // Don't emit diagnostics for sequences of the same invalid token + if swallow_next_invalid > 0 { + swallow_next_invalid -= 1; + continue; + } + let mut it = self.str_from_to_end(start).chars(); + let c = it.next().unwrap(); + let repeats = it.take_while(|c1| *c1 == c).count(); let mut err = - self.struct_err_span_char(start, self.pos, "unknown start of token", c); + self.struct_err_span_char(start, self.pos + Pos::from_usize(repeats * c.len_utf8()), "unknown start of token", c); // FIXME: the lexer could be used to turn the ASCII version of unicode // homoglyphs, instead of keeping a table in `check_for_substitution`into the // token. Ideally, this should be inside `rustc_lexer`. However, we should // first remove compound tokens like `<<` from `rustc_lexer`, and then add // fancier error recovery to it, as there will be less overall work to do this // way. - let token = unicode_chars::check_for_substitution(self, start, c, &mut err); + let token = unicode_chars::check_for_substitution(self, start, c, &mut err, repeats+1); if c == '\x00' { err.help("source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used"); } + if repeats > 0 { + if repeats == 1 { + err.note(format!("character appears once more")); + } else { + err.note(format!("character appears {repeats} more times")); + } + swallow_next_invalid = repeats; + } err.emit(); if let Some(token) = token { token @@ -486,6 +501,11 @@ impl<'a> StringReader<'a> { &self.src[self.src_index(start)..self.src_index(end)] } + /// Slice of the source text spanning from `start` until the end + fn str_from_to_end(&self, start: BytePos) -> &str { + &self.src[self.src_index(start)..] + } + fn report_raw_str_error(&self, start: BytePos, prefix_len: u32) -> ! { match rustc_lexer::validate_raw_str(self.str_from(start), prefix_len) { Err(RawStrError::InvalidStarter { bad_char }) => { diff --git a/compiler/rustc_parse/src/lexer/unicode_chars.rs b/compiler/rustc_parse/src/lexer/unicode_chars.rs index f1b50296e25..65479b341d7 100644 --- a/compiler/rustc_parse/src/lexer/unicode_chars.rs +++ b/compiler/rustc_parse/src/lexer/unicode_chars.rs @@ -337,10 +337,11 @@ pub(super) fn check_for_substitution<'a>( pos: BytePos, ch: char, err: &mut Diagnostic, + count: usize, ) -> Option<token::TokenKind> { let &(_u_char, u_name, ascii_char) = UNICODE_ARRAY.iter().find(|&&(c, _, _)| c == ch)?; - let span = Span::with_root_ctxt(pos, pos + Pos::from_usize(ch.len_utf8())); + let span = Span::with_root_ctxt(pos, pos + Pos::from_usize(ch.len_utf8() * count)); let Some((_ascii_char, ascii_name, token)) = ASCII_ARRAY.iter().find(|&&(c, _, _)| c == ascii_char) else { let msg = format!("substitution character not found for '{}'", ch); @@ -369,7 +370,12 @@ pub(super) fn check_for_substitution<'a>( "Unicode character '{}' ({}) looks like '{}' ({}), but it is not", ch, u_name, ascii_char, ascii_name ); - err.span_suggestion(span, &msg, ascii_char, Applicability::MaybeIncorrect); + err.span_suggestion( + span, + &msg, + ascii_char.to_string().repeat(count), + Applicability::MaybeIncorrect, + ); } token.clone() } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 84d9794ccf2..f950e4a9bee 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1137,7 +1137,7 @@ impl<'a, 'b> DefIdTree for &'a Resolver<'b> { } } -impl Resolver<'_> { +impl<'a> Resolver<'a> { fn opt_local_def_id(&self, node: NodeId) -> Option<LocalDefId> { self.node_id_to_def_id.get(&node).copied() } @@ -1194,6 +1194,10 @@ impl Resolver<'_> { self.cstore().item_generics_num_lifetimes(def_id, self.session) } } + + pub fn sess(&self) -> &'a Session { + self.session + } } impl<'a> Resolver<'a> { diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index b062b43873b..7b5fd6cc2a8 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1411,6 +1411,8 @@ options! { "what location details should be tracked when using caller_location, either \ `none`, or a comma separated list of location details, for which \ valid options are `file`, `line`, and `column` (default: `file,line,column`)"), + log_backtrace: Option<String> = (None, parse_opt_string, [TRACKED], + "add a backtrace along with logging"), ls: bool = (false, parse_bool, [UNTRACKED], "list the symbols defined by a library crate (default: no)"), macro_backtrace: bool = (false, parse_bool, [UNTRACKED], diff --git a/compiler/rustc_span/Cargo.toml b/compiler/rustc_span/Cargo.toml index 5ce2577b63c..ae81d95e279 100644 --- a/compiler/rustc_span/Cargo.toml +++ b/compiler/rustc_span/Cargo.toml @@ -15,6 +15,6 @@ scoped-tls = "1.0" unicode-width = "0.1.4" cfg-if = "1.0" tracing = "0.1" -sha1 = { package = "sha-1", version = "0.10.0" } +sha1 = "0.10.0" sha2 = "0.10.1" md5 = { package = "md-5", version = "0.10.0" } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 0c7ffb056cc..41a64a844ce 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -374,6 +374,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { }) } } + impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { fn report_fulfillment_errors( &self, @@ -852,6 +853,29 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let mut suggested = self.suggest_dereferences(&obligation, &mut err, trait_predicate); suggested |= self.suggest_fn_call(&obligation, &mut err, trait_predicate); + let impl_candidates = self.find_similar_impl_candidates(trait_predicate); + suggested = if let &[cand] = &impl_candidates[..] { + let cand = cand.trait_ref; + if let (ty::FnPtr(_), ty::FnDef(..)) = + (cand.self_ty().kind(), trait_ref.self_ty().skip_binder().kind()) + { + err.span_suggestion( + span.shrink_to_hi(), + format!( + "the trait `{}` is implemented for fn pointer `{}`, try casting using `as`", + cand.print_only_trait_path(), + cand.self_ty(), + ), + format!(" as {}", cand.self_ty()), + Applicability::MaybeIncorrect, + ); + true + } else { + false + } + } else { + false + } || suggested; suggested |= self.suggest_remove_reference(&obligation, &mut err, trait_predicate); suggested |= self.suggest_semicolon_removal( @@ -1968,27 +1992,25 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { candidates.sort(); candidates.dedup(); let len = candidates.len(); - if candidates.len() == 0 { + if candidates.is_empty() { return false; } - if candidates.len() == 1 { - let ty_desc = match candidates[0].self_ty().kind() { - ty::FnPtr(_) => Some("fn pointer"), - _ => None, - }; - let the_desc = match ty_desc { - Some(desc) => format!(" implemented for {} `", desc), - None => " implemented for `".to_string(), - }; + if let &[cand] = &candidates[..] { + let (desc, mention_castable) = + match (cand.self_ty().kind(), trait_ref.self_ty().skip_binder().kind()) { + (ty::FnPtr(_), ty::FnDef(..)) => { + (" implemented for fn pointer `", ", cast using `as`") + } + (ty::FnPtr(_), _) => (" implemented for fn pointer `", ""), + _ => (" implemented for `", ""), + }; err.highlighted_help(vec![ - ( - format!("the trait `{}` ", candidates[0].print_only_trait_path()), - Style::NoStyle, - ), + (format!("the trait `{}` ", cand.print_only_trait_path()), Style::NoStyle), ("is".to_string(), Style::Highlight), - (the_desc, Style::NoStyle), - (candidates[0].self_ty().to_string(), Style::Highlight), + (desc.to_string(), Style::NoStyle), + (cand.self_ty().to_string(), Style::Highlight), ("`".to_string(), Style::NoStyle), + (mention_castable.to_string(), Style::NoStyle), ]); return true; } diff --git a/library/alloc/src/collections/binary_heap.rs b/library/alloc/src/collections/binary_heap/mod.rs index 4583bc9a158..4583bc9a158 100644 --- a/library/alloc/src/collections/binary_heap.rs +++ b/library/alloc/src/collections/binary_heap/mod.rs diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 51e6a76cea8..fa5073e3304 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -174,6 +174,11 @@ pub trait Write { /// This method should generally not be invoked manually, but rather through /// the [`write!`] macro itself. /// + /// # Errors + /// + /// This function will return an instance of [`Error`] on error. Please see + /// [write_str](Write::write_str) for details. + /// /// # Examples /// /// ``` diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 39462dca4ff..7cc00e3f8d1 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -652,13 +652,14 @@ impl<T> Option<T> { /// /// # Examples /// - /// Converts an <code>Option<[String]></code> into an <code>Option<[usize]></code>, preserving - /// the original. The [`map`] method takes the `self` argument by value, consuming the original, - /// so this technique uses `as_ref` to first take an `Option` to a reference - /// to the value inside the original. + /// Calculates the length of an <code>Option<[String]></code> as an <code>Option<[usize]></code> + /// without moving the [`String`]. The [`map`] method takes the `self` argument by value, + /// consuming the original, so this technique uses `as_ref` to first take an `Option` to a + /// reference to the value inside the original. /// /// [`map`]: Option::map /// [String]: ../../std/string/struct.String.html "String" + /// [`String`]: ../../std/string/struct.String.html "String" /// /// ``` /// let text: Option<String> = Some("Hello, world!".to_string()); @@ -946,8 +947,8 @@ impl<T> Option<T> { /// /// # Examples /// - /// Converts an <code>Option<[String]></code> into an <code>Option<[usize]></code>, consuming - /// the original: + /// Calculates the length of an <code>Option<[String]></code> as an + /// <code>Option<[usize]></code>, consuming the original: /// /// [String]: ../../std/string/struct.String.html "String" /// ``` diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index edc68d6fae5..14367eb09bc 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -1786,6 +1786,42 @@ impl<T> AtomicPtr<T> { // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_xor(self.p.get(), core::ptr::invalid_mut(val), order).cast() } } + + /// Returns a mutable pointer to the underlying pointer. + /// + /// Doing non-atomic reads and writes on the resulting integer can be a data race. + /// This method is mostly useful for FFI, where the function signature may use + /// `*mut *mut T` instead of `&AtomicPtr<T>`. + /// + /// Returning an `*mut` pointer from a shared reference to this atomic is safe because the + /// atomic types work with interior mutability. All modifications of an atomic change the value + /// through a shared reference, and can do so safely as long as they use atomic operations. Any + /// use of the returned raw pointer requires an `unsafe` block and still has to uphold the same + /// restriction: operations on it must be atomic. + /// + /// # Examples + /// + /// ```ignore (extern-declaration) + /// #![feature(atomic_mut_ptr)] + //// use std::sync::atomic::AtomicPtr; + /// + /// extern "C" { + /// fn my_atomic_op(arg: *mut *mut u32); + /// } + /// + /// let mut value = 17; + /// let atomic = AtomicPtr::new(&mut value); + /// + /// // SAFETY: Safe as long as `my_atomic_op` is atomic. + /// unsafe { + /// my_atomic_op(atomic.as_mut_ptr()); + /// } + /// ``` + #[inline] + #[unstable(feature = "atomic_mut_ptr", reason = "recently added", issue = "66893")] + pub fn as_mut_ptr(&self) -> *mut *mut T { + self.p.get() + } } #[cfg(target_has_atomic_load_store = "8")] @@ -2678,9 +2714,9 @@ macro_rules! atomic_int { #[doc = concat!(" fn my_atomic_op(arg: *mut ", stringify!($int_type), ");")] /// } /// - #[doc = concat!("let mut atomic = ", stringify!($atomic_type), "::new(1);")] + #[doc = concat!("let atomic = ", stringify!($atomic_type), "::new(1);")] /// - // SAFETY: Safe as long as `my_atomic_op` is atomic. + /// // SAFETY: Safe as long as `my_atomic_op` is atomic. /// unsafe { /// my_atomic_op(atomic.as_mut_ptr()); /// } diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 82d68369312..a2dcee0e2bd 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -3177,9 +3177,9 @@ impl<'a> IntoIterator for &'a Path { } macro_rules! impl_cmp { - ($lhs:ty, $rhs: ty) => { + (<$($life:lifetime),*> $lhs:ty, $rhs: ty) => { #[stable(feature = "partialeq_path", since = "1.6.0")] - impl<'a, 'b> PartialEq<$rhs> for $lhs { + impl<$($life),*> PartialEq<$rhs> for $lhs { #[inline] fn eq(&self, other: &$rhs) -> bool { <Path as PartialEq>::eq(self, other) @@ -3187,7 +3187,7 @@ macro_rules! impl_cmp { } #[stable(feature = "partialeq_path", since = "1.6.0")] - impl<'a, 'b> PartialEq<$lhs> for $rhs { + impl<$($life),*> PartialEq<$lhs> for $rhs { #[inline] fn eq(&self, other: &$lhs) -> bool { <Path as PartialEq>::eq(self, other) @@ -3195,7 +3195,7 @@ macro_rules! impl_cmp { } #[stable(feature = "cmp_path", since = "1.8.0")] - impl<'a, 'b> PartialOrd<$rhs> for $lhs { + impl<$($life),*> PartialOrd<$rhs> for $lhs { #[inline] fn partial_cmp(&self, other: &$rhs) -> Option<cmp::Ordering> { <Path as PartialOrd>::partial_cmp(self, other) @@ -3203,7 +3203,7 @@ macro_rules! impl_cmp { } #[stable(feature = "cmp_path", since = "1.8.0")] - impl<'a, 'b> PartialOrd<$lhs> for $rhs { + impl<$($life),*> PartialOrd<$lhs> for $rhs { #[inline] fn partial_cmp(&self, other: &$lhs) -> Option<cmp::Ordering> { <Path as PartialOrd>::partial_cmp(self, other) @@ -3212,16 +3212,16 @@ macro_rules! impl_cmp { }; } -impl_cmp!(PathBuf, Path); -impl_cmp!(PathBuf, &'a Path); -impl_cmp!(Cow<'a, Path>, Path); -impl_cmp!(Cow<'a, Path>, &'b Path); -impl_cmp!(Cow<'a, Path>, PathBuf); +impl_cmp!(<> PathBuf, Path); +impl_cmp!(<'a> PathBuf, &'a Path); +impl_cmp!(<'a> Cow<'a, Path>, Path); +impl_cmp!(<'a, 'b> Cow<'a, Path>, &'b Path); +impl_cmp!(<'a> Cow<'a, Path>, PathBuf); macro_rules! impl_cmp_os_str { - ($lhs:ty, $rhs: ty) => { + (<$($life:lifetime),*> $lhs:ty, $rhs: ty) => { #[stable(feature = "cmp_path", since = "1.8.0")] - impl<'a, 'b> PartialEq<$rhs> for $lhs { + impl<$($life),*> PartialEq<$rhs> for $lhs { #[inline] fn eq(&self, other: &$rhs) -> bool { <Path as PartialEq>::eq(self, other.as_ref()) @@ -3229,7 +3229,7 @@ macro_rules! impl_cmp_os_str { } #[stable(feature = "cmp_path", since = "1.8.0")] - impl<'a, 'b> PartialEq<$lhs> for $rhs { + impl<$($life),*> PartialEq<$lhs> for $rhs { #[inline] fn eq(&self, other: &$lhs) -> bool { <Path as PartialEq>::eq(self.as_ref(), other) @@ -3237,7 +3237,7 @@ macro_rules! impl_cmp_os_str { } #[stable(feature = "cmp_path", since = "1.8.0")] - impl<'a, 'b> PartialOrd<$rhs> for $lhs { + impl<$($life),*> PartialOrd<$rhs> for $lhs { #[inline] fn partial_cmp(&self, other: &$rhs) -> Option<cmp::Ordering> { <Path as PartialOrd>::partial_cmp(self, other.as_ref()) @@ -3245,7 +3245,7 @@ macro_rules! impl_cmp_os_str { } #[stable(feature = "cmp_path", since = "1.8.0")] - impl<'a, 'b> PartialOrd<$lhs> for $rhs { + impl<$($life),*> PartialOrd<$lhs> for $rhs { #[inline] fn partial_cmp(&self, other: &$lhs) -> Option<cmp::Ordering> { <Path as PartialOrd>::partial_cmp(self.as_ref(), other) @@ -3254,20 +3254,20 @@ macro_rules! impl_cmp_os_str { }; } -impl_cmp_os_str!(PathBuf, OsStr); -impl_cmp_os_str!(PathBuf, &'a OsStr); -impl_cmp_os_str!(PathBuf, Cow<'a, OsStr>); -impl_cmp_os_str!(PathBuf, OsString); -impl_cmp_os_str!(Path, OsStr); -impl_cmp_os_str!(Path, &'a OsStr); -impl_cmp_os_str!(Path, Cow<'a, OsStr>); -impl_cmp_os_str!(Path, OsString); -impl_cmp_os_str!(&'a Path, OsStr); -impl_cmp_os_str!(&'a Path, Cow<'b, OsStr>); -impl_cmp_os_str!(&'a Path, OsString); -impl_cmp_os_str!(Cow<'a, Path>, OsStr); -impl_cmp_os_str!(Cow<'a, Path>, &'b OsStr); -impl_cmp_os_str!(Cow<'a, Path>, OsString); +impl_cmp_os_str!(<> PathBuf, OsStr); +impl_cmp_os_str!(<'a> PathBuf, &'a OsStr); +impl_cmp_os_str!(<'a> PathBuf, Cow<'a, OsStr>); +impl_cmp_os_str!(<> PathBuf, OsString); +impl_cmp_os_str!(<> Path, OsStr); +impl_cmp_os_str!(<'a> Path, &'a OsStr); +impl_cmp_os_str!(<'a> Path, Cow<'a, OsStr>); +impl_cmp_os_str!(<> Path, OsString); +impl_cmp_os_str!(<'a> &'a Path, OsStr); +impl_cmp_os_str!(<'a, 'b> &'a Path, Cow<'b, OsStr>); +impl_cmp_os_str!(<'a> &'a Path, OsString); +impl_cmp_os_str!(<'a> Cow<'a, Path>, OsStr); +impl_cmp_os_str!(<'a, 'b> Cow<'a, Path>, &'b OsStr); +impl_cmp_os_str!(<'a> Cow<'a, Path>, OsString); #[stable(since = "1.7.0", feature = "strip_prefix")] impl fmt::Display for StripPrefixError { diff --git a/library/std/src/sync/mpmc/array.rs b/library/std/src/sync/mpmc/array.rs index f71edc6c525..c1e3e48b044 100644 --- a/library/std/src/sync/mpmc/array.rs +++ b/library/std/src/sync/mpmc/array.rs @@ -168,7 +168,7 @@ impl<T> Channel<T> { return true; } Err(_) => { - backoff.spin(); + backoff.spin_light(); tail = self.tail.load(Ordering::Relaxed); } } @@ -182,11 +182,11 @@ impl<T> Channel<T> { return false; } - backoff.spin(); + backoff.spin_light(); tail = self.tail.load(Ordering::Relaxed); } else { // Snooze because we need to wait for the stamp to get updated. - backoff.snooze(); + backoff.spin_heavy(); tail = self.tail.load(Ordering::Relaxed); } } @@ -251,7 +251,7 @@ impl<T> Channel<T> { return true; } Err(_) => { - backoff.spin(); + backoff.spin_light(); head = self.head.load(Ordering::Relaxed); } } @@ -273,11 +273,11 @@ impl<T> Channel<T> { } } - backoff.spin(); + backoff.spin_light(); head = self.head.load(Ordering::Relaxed); } else { // Snooze because we need to wait for the stamp to get updated. - backoff.snooze(); + backoff.spin_heavy(); head = self.head.load(Ordering::Relaxed); } } @@ -330,7 +330,7 @@ impl<T> Channel<T> { if backoff.is_completed() { break; } else { - backoff.spin(); + backoff.spin_light(); } } diff --git a/library/std/src/sync/mpmc/list.rs b/library/std/src/sync/mpmc/list.rs index 2d5b2fb3b23..ec6c0726ac7 100644 --- a/library/std/src/sync/mpmc/list.rs +++ b/library/std/src/sync/mpmc/list.rs @@ -46,7 +46,7 @@ impl<T> Slot<T> { fn wait_write(&self) { let backoff = Backoff::new(); while self.state.load(Ordering::Acquire) & WRITE == 0 { - backoff.snooze(); + backoff.spin_heavy(); } } } @@ -82,7 +82,7 @@ impl<T> Block<T> { if !next.is_null() { return next; } - backoff.snooze(); + backoff.spin_heavy(); } } @@ -191,7 +191,7 @@ impl<T> Channel<T> { // If we reached the end of the block, wait until the next one is installed. if offset == BLOCK_CAP { - backoff.snooze(); + backoff.spin_heavy(); tail = self.tail.index.load(Ordering::Acquire); block = self.tail.block.load(Ordering::Acquire); continue; @@ -247,7 +247,7 @@ impl<T> Channel<T> { return true; }, Err(_) => { - backoff.spin(); + backoff.spin_light(); tail = self.tail.index.load(Ordering::Acquire); block = self.tail.block.load(Ordering::Acquire); } @@ -286,7 +286,7 @@ impl<T> Channel<T> { // If we reached the end of the block, wait until the next one is installed. if offset == BLOCK_CAP { - backoff.snooze(); + backoff.spin_heavy(); head = self.head.index.load(Ordering::Acquire); block = self.head.block.load(Ordering::Acquire); continue; @@ -320,7 +320,7 @@ impl<T> Channel<T> { // The block can be null here only if the first message is being sent into the channel. // In that case, just wait until it gets initialized. if block.is_null() { - backoff.snooze(); + backoff.spin_heavy(); head = self.head.index.load(Ordering::Acquire); block = self.head.block.load(Ordering::Acquire); continue; @@ -351,7 +351,7 @@ impl<T> Channel<T> { return true; }, Err(_) => { - backoff.spin(); + backoff.spin_light(); head = self.head.index.load(Ordering::Acquire); block = self.head.block.load(Ordering::Acquire); } @@ -542,7 +542,7 @@ impl<T> Channel<T> { // New updates to tail will be rejected by MARK_BIT and aborted unless it's // at boundary. We need to wait for the updates take affect otherwise there // can be memory leaks. - backoff.snooze(); + backoff.spin_heavy(); tail = self.tail.index.load(Ordering::Acquire); } diff --git a/library/std/src/sync/mpmc/mod.rs b/library/std/src/sync/mpmc/mod.rs index cef99c58843..7a602cecd3b 100644 --- a/library/std/src/sync/mpmc/mod.rs +++ b/library/std/src/sync/mpmc/mod.rs @@ -43,7 +43,7 @@ mod zero; use crate::fmt; use crate::panic::{RefUnwindSafe, UnwindSafe}; use crate::time::{Duration, Instant}; -use error::*; +pub use error::*; /// Creates a channel of unbounded capacity. /// diff --git a/library/std/src/sync/mpmc/utils.rs b/library/std/src/sync/mpmc/utils.rs index e030c55ce8f..cfe42750d52 100644 --- a/library/std/src/sync/mpmc/utils.rs +++ b/library/std/src/sync/mpmc/utils.rs @@ -91,9 +91,8 @@ impl<T> DerefMut for CachePadded<T> { } const SPIN_LIMIT: u32 = 6; -const YIELD_LIMIT: u32 = 10; -/// Performs exponential backoff in spin loops. +/// Performs quadratic backoff in spin loops. pub struct Backoff { step: Cell<u32>, } @@ -104,25 +103,27 @@ impl Backoff { Backoff { step: Cell::new(0) } } - /// Backs off in a lock-free loop. + /// Backs off using lightweight spinning. /// - /// This method should be used when we need to retry an operation because another thread made - /// progress. + /// This method should be used for: + /// - Retrying an operation because another thread made progress. i.e. on CAS failure. + /// - Waiting for an operation to complete by spinning optimistically for a few iterations + /// before falling back to parking the thread (see `Backoff::is_completed`). #[inline] - pub fn spin(&self) { + pub fn spin_light(&self) { let step = self.step.get().min(SPIN_LIMIT); for _ in 0..step.pow(2) { crate::hint::spin_loop(); } - if self.step.get() <= SPIN_LIMIT { - self.step.set(self.step.get() + 1); - } + self.step.set(self.step.get() + 1); } - /// Backs off in a blocking loop. + /// Backs off using heavyweight spinning. + /// + /// This method should be used in blocking loops where parking the thread is not an option. #[inline] - pub fn snooze(&self) { + pub fn spin_heavy(&self) { if self.step.get() <= SPIN_LIMIT { for _ in 0..self.step.get().pow(2) { crate::hint::spin_loop() @@ -131,14 +132,12 @@ impl Backoff { crate::thread::yield_now(); } - if self.step.get() <= YIELD_LIMIT { - self.step.set(self.step.get() + 1); - } + self.step.set(self.step.get() + 1); } - /// Returns `true` if quadratic backoff has completed and blocking the thread is advised. + /// Returns `true` if quadratic backoff has completed and parking the thread is advised. #[inline] pub fn is_completed(&self) -> bool { - self.step.get() > YIELD_LIMIT + self.step.get() > SPIN_LIMIT } } diff --git a/library/std/src/sync/mpmc/zero.rs b/library/std/src/sync/mpmc/zero.rs index fccd6c29a7e..33f768dcbe9 100644 --- a/library/std/src/sync/mpmc/zero.rs +++ b/library/std/src/sync/mpmc/zero.rs @@ -57,7 +57,7 @@ impl<T> Packet<T> { fn wait_ready(&self) { let backoff = Backoff::new(); while !self.ready.load(Ordering::Acquire) { - backoff.snooze(); + backoff.spin_heavy(); } } } diff --git a/library/std/src/sync/mpsc/mod.rs b/library/std/src/sync/mpsc/mod.rs index adb488d4378..6e3c28f10bb 100644 --- a/library/std/src/sync/mpsc/mod.rs +++ b/library/std/src/sync/mpsc/mod.rs @@ -738,6 +738,15 @@ impl<T> SyncSender<T> { pub fn try_send(&self, t: T) -> Result<(), TrySendError<T>> { self.inner.try_send(t) } + + // Attempts to send for a value on this receiver, returning an error if the + // corresponding channel has hung up, or if it waits more than `timeout`. + // + // This method is currently private and only used for tests. + #[allow(unused)] + fn send_timeout(&self, t: T, timeout: Duration) -> Result<(), mpmc::SendTimeoutError<T>> { + self.inner.send_timeout(t, timeout) + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/sync/mpsc/sync_tests.rs b/library/std/src/sync/mpsc/sync_tests.rs index 63c79436974..9d2f92ffc9b 100644 --- a/library/std/src/sync/mpsc/sync_tests.rs +++ b/library/std/src/sync/mpsc/sync_tests.rs @@ -1,5 +1,6 @@ use super::*; use crate::env; +use crate::sync::mpmc::SendTimeoutError; use crate::thread; use crate::time::Duration; @@ -42,6 +43,13 @@ fn recv_timeout() { } #[test] +fn send_timeout() { + let (tx, _rx) = sync_channel::<i32>(1); + assert_eq!(tx.send_timeout(1, Duration::from_millis(1)), Ok(())); + assert_eq!(tx.send_timeout(1, Duration::from_millis(1)), Err(SendTimeoutError::Timeout(1))); +} + +#[test] fn smoke_threads() { let (tx, rx) = sync_channel::<i32>(0); let _t = thread::spawn(move || { diff --git a/src/README.md b/src/README.md index 90ab8026970..7b357da2ffc 100644 --- a/src/README.md +++ b/src/README.md @@ -1,8 +1,7 @@ -This directory contains the source code of the rust project, including: +This directory contains some source code for the Rust project, including: -- The test suite - The bootstrapping build system -- Various submodules for tools, like cargo, etc. +- Various submodules for tools, like cargo, tidy, etc. For more information on how various parts of the compiler work, see the [rustc dev guide]. diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 1d526022812..9611c866df5 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -154,6 +154,41 @@ fn main() { cmd.arg("-Z").arg("force-unstable-if-unmarked"); } + // allow-features is handled from within this rustc wrapper because of + // issues with build scripts. Some packages use build scripts to + // dynamically detect if certain nightly features are available. + // There are different ways this causes problems: + // + // * rustix runs `rustc` on a small test program to see if the feature is + // available (and sets a `cfg` if it is). It does not honor + // CARGO_ENCODED_RUSTFLAGS. + // * proc-macro2 detects if `rustc -vV` says "nighty" or "dev" and enables + // nightly features. It will scan CARGO_ENCODED_RUSTFLAGS for + // -Zallow-features. Unfortunately CARGO_ENCODED_RUSTFLAGS is not set + // for build-dependencies when --target is used. + // + // The issues above means we can't just use RUSTFLAGS, and we can't use + // `cargo -Zallow-features=…`. Passing it through here ensures that it + // always gets set. Unfortunately that also means we need to enable more + // features than we really want (like those for proc-macro2), but there + // isn't much of a way around it. + // + // I think it is unfortunate that build scripts are doing this at all, + // since changes to nightly features can cause crates to break even if the + // user didn't want or care about the use of the nightly features. I think + // nightly features should be opt-in only. Unfortunately the dynamic + // checks are now too wide spread that we just need to deal with it. + // + // If you want to try to remove this, I suggest working with the crate + // authors to remove the dynamic checking. Another option is to pursue + // https://github.com/rust-lang/cargo/issues/11244 and + // https://github.com/rust-lang/cargo/issues/4423, which will likely be + // very difficult, but could help expose -Zallow-features into build + // scripts so they could try to honor them. + if let Ok(allow_features) = env::var("RUSTC_ALLOW_FEATURES") { + cmd.arg(format!("-Zallow-features={allow_features}")); + } + if let Ok(flags) = env::var("MAGIC_EXTRA_RUSTFLAGS") { for flag in flags.split(' ') { cmd.arg(flag); diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 52a83fa29c7..b4fc1d4f28d 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -1381,18 +1381,29 @@ impl<'a> Builder<'a> { // this), as well as #63012 which is the tracking issue for this // feature on the rustc side. cargo.arg("-Zbinary-dep-depinfo"); - match mode { - Mode::ToolBootstrap => { - // Restrict the allowed features to those passed by rustbuild, so we don't depend on nightly accidentally. - rustflags.arg("-Zallow-features=binary-dep-depinfo"); - } - Mode::ToolStd => { - // Right now this is just compiletest and a few other tools that build on stable. - // Allow them to use `feature(test)`, but nothing else. - rustflags.arg("-Zallow-features=binary-dep-depinfo,test,proc_macro_internals,proc_macro_diagnostic,proc_macro_span"); + let allow_features = match mode { + Mode::ToolBootstrap | Mode::ToolStd => { + // Restrict the allowed features so we don't depend on nightly + // accidentally. + // + // binary-dep-depinfo is used by rustbuild itself for all + // compilations. + // + // Lots of tools depend on proc_macro2 and proc-macro-error. + // Those have build scripts which assume nightly features are + // available if the `rustc` version is "nighty" or "dev". See + // bin/rustc.rs for why that is a problem. Instead of labeling + // those features for each individual tool that needs them, + // just blanket allow them here. + // + // If this is ever removed, be sure to add something else in + // its place to keep the restrictions in place (or make a way + // to unset RUSTC_BOOTSTRAP). + "binary-dep-depinfo,proc_macro_span,proc_macro_span_shrink,proc_macro_diagnostic" + .to_string() } - Mode::Std | Mode::Rustc | Mode::Codegen | Mode::ToolRustc => {} - } + Mode::Std | Mode::Rustc | Mode::Codegen | Mode::ToolRustc => String::new(), + }; cargo.arg("-j").arg(self.jobs().to_string()); @@ -1915,7 +1926,7 @@ impl<'a> Builder<'a> { } } - Cargo { command: cargo, rustflags, rustdocflags } + Cargo { command: cargo, rustflags, rustdocflags, allow_features } } /// Ensure that a given step is built, returning its output. This will @@ -2094,6 +2105,7 @@ pub struct Cargo { command: Command, rustflags: Rustflags, rustdocflags: Rustflags, + allow_features: String, } impl Cargo { @@ -2138,6 +2150,18 @@ impl Cargo { self.command.current_dir(dir); self } + + /// Adds nightly-only features that this invocation is allowed to use. + /// + /// By default, all nightly features are allowed. Once this is called, it + /// will be restricted to the given set. + pub fn allow_features(&mut self, features: &str) -> &mut Cargo { + if !self.allow_features.is_empty() { + self.allow_features.push(','); + } + self.allow_features.push_str(features); + self + } } impl From<Cargo> for Command { @@ -2152,6 +2176,10 @@ impl From<Cargo> for Command { cargo.command.env("RUSTDOCFLAGS", rustdocflags); } + if !cargo.allow_features.is_empty() { + cargo.command.env("RUSTC_ALLOW_FEATURES", cargo.allow_features); + } + cargo.command } } diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 2771bd2264c..4b8a58e87b6 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -346,9 +346,7 @@ impl Step for RustAnalyzer { &["rust-analyzer/in-rust-tree".to_owned()], ); - cargo.rustflag( - "-Zallow-features=proc_macro_internals,proc_macro_diagnostic,proc_macro_span", - ); + cargo.allow_features(crate::tool::RustAnalyzer::ALLOW_FEATURES); // For ./x.py clippy, don't check those targets because // linting tests and benchmarks can produce very noisy results diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 159f2fba671..6078e39ac9d 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -378,6 +378,7 @@ impl Step for RustAnalyzer { SourceType::InTree, &["sysroot-abi".to_owned()], ); + cargo.allow_features(tool::RustAnalyzer::ALLOW_FEATURES); let dir = builder.src.join(workspace_path); // needed by rust-analyzer to find its own text fixtures, cf. @@ -690,7 +691,7 @@ impl Step for CompiletestTest { // We need `ToolStd` for the locally-built sysroot because // compiletest uses unstable features of the `test` crate. builder.ensure(compile::Std::new(compiler, host)); - let cargo = tool::prepare_tool_cargo( + let mut cargo = tool::prepare_tool_cargo( builder, compiler, Mode::ToolStd, @@ -700,6 +701,7 @@ impl Step for CompiletestTest { SourceType::InTree, &[], ); + cargo.allow_features("test"); try_run(builder, &mut cargo.into()); } diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 24b033cc0dc..9a2100c2fb7 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -29,6 +29,8 @@ struct ToolBuild { is_optional_tool: bool, source_type: SourceType, extra_features: Vec<String>, + /// Nightly-only features that are allowed (comma-separated list). + allow_features: &'static str, } impl Step for ToolBuild { @@ -59,7 +61,7 @@ impl Step for ToolBuild { _ => panic!("unexpected Mode for tool build"), } - let cargo = prepare_tool_cargo( + let mut cargo = prepare_tool_cargo( builder, compiler, self.mode, @@ -69,6 +71,9 @@ impl Step for ToolBuild { self.source_type, &self.extra_features, ); + if !self.allow_features.is_empty() { + cargo.allow_features(self.allow_features); + } builder.info(&format!("Building stage{} tool {} ({})", compiler.stage, tool, target)); let mut duplicates = Vec::new(); @@ -292,6 +297,7 @@ macro_rules! bootstrap_tool { $name:ident, $path:expr, $tool_name:expr $(,is_external_tool = $external:expr)* $(,is_unstable_tool = $unstable:expr)* + $(,allow_features = $allow_features:expr)? ; )+) => { #[derive(Copy, PartialEq, Eq, Clone)] @@ -355,6 +361,7 @@ macro_rules! bootstrap_tool { SourceType::InTree }, extra_features: vec![], + allow_features: concat!($($allow_features)*), }).expect("expected to build -- essential tool") } } @@ -368,7 +375,7 @@ bootstrap_tool!( Tidy, "src/tools/tidy", "tidy"; Linkchecker, "src/tools/linkchecker", "linkchecker"; CargoTest, "src/tools/cargotest", "cargotest"; - Compiletest, "src/tools/compiletest", "compiletest", is_unstable_tool = true; + Compiletest, "src/tools/compiletest", "compiletest", is_unstable_tool = true, allow_features = "test"; BuildManifest, "src/tools/build-manifest", "build-manifest"; RemoteTestClient, "src/tools/remote-test-client", "remote-test-client"; RustInstaller, "src/tools/rust-installer", "rust-installer", is_external_tool = true; @@ -435,6 +442,7 @@ impl Step for ErrorIndex { is_optional_tool: false, source_type: SourceType::InTree, extra_features: Vec::new(), + allow_features: "", }) .expect("expected to build -- essential tool") } @@ -471,6 +479,7 @@ impl Step for RemoteTestServer { is_optional_tool: false, source_type: SourceType::InTree, extra_features: Vec::new(), + allow_features: "", }) .expect("expected to build -- essential tool") } @@ -622,6 +631,7 @@ impl Step for Cargo { is_optional_tool: false, source_type: SourceType::Submodule, extra_features: Vec::new(), + allow_features: "", }) .expect("expected to build -- essential tool"); @@ -637,6 +647,7 @@ impl Step for Cargo { is_optional_tool: true, source_type: SourceType::Submodule, extra_features: Vec::new(), + allow_features: "", }); }; @@ -684,6 +695,7 @@ impl Step for LldWrapper { is_optional_tool: false, source_type: SourceType::InTree, extra_features: Vec::new(), + allow_features: "", }) .expect("expected to build -- essential tool"); @@ -697,6 +709,11 @@ pub struct RustAnalyzer { pub target: TargetSelection, } +impl RustAnalyzer { + pub const ALLOW_FEATURES: &str = + "proc_macro_internals,proc_macro_diagnostic,proc_macro_span,proc_macro_span_shrink"; +} + impl Step for RustAnalyzer { type Output = Option<PathBuf>; const DEFAULT: bool = true; @@ -731,6 +748,7 @@ impl Step for RustAnalyzer { extra_features: vec!["rust-analyzer/in-rust-tree".to_owned()], is_optional_tool: false, source_type: SourceType::InTree, + allow_features: RustAnalyzer::ALLOW_FEATURES, }) } } @@ -769,6 +787,7 @@ impl Step for RustAnalyzerProcMacroSrv { extra_features: vec!["proc-macro-srv/sysroot-abi".to_owned()], is_optional_tool: false, source_type: SourceType::InTree, + allow_features: RustAnalyzer::ALLOW_FEATURES, })?; // Copy `rust-analyzer-proc-macro-srv` to `<sysroot>/libexec/` @@ -788,6 +807,7 @@ macro_rules! tool_extended { $tool_name:expr, stable = $stable:expr $(,tool_std = $tool_std:literal)? + $(,allow_features = $allow_features:expr)? ;)+) => { $( #[derive(Debug, Clone, Hash, PartialEq, Eq)] @@ -839,6 +859,7 @@ macro_rules! tool_extended { extra_features: $sel.extra_features, is_optional_tool: true, source_type: SourceType::InTree, + allow_features: concat!($($allow_features)*), }) } } diff --git a/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh b/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh index 67cee0148b2..5fbce36c39d 100755 --- a/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh +++ b/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh @@ -10,7 +10,7 @@ bin="$PWD/clang+llvm-15.0.6-x86_64-linux-gnu-ubuntu-18.04/bin" git clone https://github.com/WebAssembly/wasi-libc cd wasi-libc -git reset --hard 8b7148f69ae241a2749b3defe4606da8143b72e0 +git reset --hard 4362b1885fd369e042a7c0ecd8df3b6cd47fb4e8 make -j$(nproc) \ CC="$bin/clang" \ NM="$bin/llvm-nm" \ diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile index adf6bb4b377..d5bc76eeb23 100644 --- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile +++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile @@ -45,6 +45,7 @@ ENV SCRIPT python3 ../x.py --stage 2 test src/tools/expand-yaml-anchors && \ python3 ../x.py test --stage 0 src/tools/compiletest && \ python3 ../x.py test --stage 0 core alloc std test proc_macro && \ # Build both public and internal documentation. + RUSTDOCFLAGS=\"--document-private-items --document-hidden-items\" python3 ../x.py doc --stage 0 compiler && \ RUSTDOCFLAGS=\"--document-private-items --document-hidden-items\" python3 ../x.py doc --stage 0 library/test && \ /scripts/validate-toolstate.sh && \ /scripts/validate-error-codes.sh && \ diff --git a/src/doc/rustdoc/src/lints.md b/src/doc/rustdoc/src/lints.md index bff01d7cb7c..45db3bb9b00 100644 --- a/src/doc/rustdoc/src/lints.md +++ b/src/doc/rustdoc/src/lints.md @@ -261,7 +261,7 @@ typo mistakes for some common attributes. ## `invalid_html_tags` -This lint is **allowed by default** and is **nightly-only**. It detects unclosed +This lint **warns by default**. It detects unclosed or invalid HTML tags. For example: ```rust diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index c8899ee62b5..20b51336c35 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -639,7 +639,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { write!( buf, "<div class=\"main-heading\">\ - <h1 class=\"fqn\">Rustdoc settings</h1>\ + <h1>Rustdoc settings</h1>\ <span class=\"out-of-band\">\ <a id=\"back\" href=\"javascript:void(0)\" onclick=\"history.back();\">\ Back\ @@ -677,7 +677,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { write!( buf, "<div class=\"main-heading\">\ - <h1 class=\"fqn\">Rustdoc help</h1>\ + <h1>Rustdoc help</h1>\ <span class=\"out-of-band\">\ <a id=\"back\" href=\"javascript:void(0)\" onclick=\"history.back();\">\ Back\ diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 8bccf68029a..358b9185fb3 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -364,7 +364,7 @@ impl AllTypes { } } - f.write_str("<h1 class=\"fqn\">List of all items</h1>"); + f.write_str("<h1>List of all items</h1>"); // Note: print_entries does not escape the title, because we know the current set of titles // doesn't require escaping. print_entries(f, &self.structs, ItemSection::Structs); @@ -394,7 +394,7 @@ fn scrape_examples_help(shared: &SharedContext<'_>) -> String { let mut ids = IdMap::default(); format!( "<div class=\"main-heading\">\ - <h1 class=\"fqn\">About scraped examples</h1>\ + <h1>About scraped examples</h1>\ </div>\ <div>{}</div>", Markdown { @@ -513,7 +513,7 @@ fn document_full_inner( debug!("Doc block: =====\n{}\n=====", s); if is_collapsible { w.write_str( - "<details class=\"rustdoc-toggle top-doc\" open>\ + "<details class=\"toggle top-doc\" open>\ <summary class=\"hideme\">\ <span>Expand description</span>\ </summary>", @@ -1514,7 +1514,7 @@ fn render_impl( let toggled = !doc_buffer.is_empty(); if toggled { let method_toggle_class = if item_type.is_method() { " method-toggle" } else { "" }; - write!(w, "<details class=\"rustdoc-toggle{}\" open><summary>", method_toggle_class); + write!(w, "<details class=\"toggle{}\" open><summary>", method_toggle_class); } match &*item.kind { clean::MethodItem(..) | clean::TyMethodItem(_) => { @@ -1730,7 +1730,7 @@ fn render_impl( close_tags.insert_str(0, "</details>"); write!( w, - "<details class=\"rustdoc-toggle implementors-toggle\"{}>", + "<details class=\"toggle implementors-toggle\"{}>", if rendering_params.toggle_open_by_default { " open" } else { "" } ); write!(w, "<summary>") @@ -2999,7 +2999,7 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite if it.peek().is_some() { write!( w, - "<details class=\"rustdoc-toggle more-examples-toggle\">\ + "<details class=\"toggle more-examples-toggle\">\ <summary class=\"hideme\">\ <span>More examples</span>\ </summary>\ diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index c16d6477fc3..d6e57decdcf 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -204,7 +204,7 @@ fn should_hide_fields(n_fields: usize) -> bool { fn toggle_open(w: &mut Buffer, text: impl fmt::Display) { write!( w, - "<details class=\"rustdoc-toggle type-contents-toggle\">\ + "<details class=\"toggle type-contents-toggle\">\ <summary class=\"hideme\">\ <span>Show {}</span>\ </summary>", @@ -733,7 +733,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: let toggled = !content.is_empty(); if toggled { let method_toggle_class = if item_type.is_method() { " method-toggle" } else { "" }; - write!(w, "<details class=\"rustdoc-toggle{method_toggle_class}\" open><summary>"); + write!(w, "<details class=\"toggle{method_toggle_class}\" open><summary>"); } write!(w, "<section id=\"{}\" class=\"method has-srclink\">", id); render_rightside(w, cx, m, t, RenderMode::Normal); @@ -1840,7 +1840,7 @@ fn document_non_exhaustive(w: &mut Buffer, item: &clean::Item) { if item.is_non_exhaustive() { write!( w, - "<details class=\"rustdoc-toggle non-exhaustive\">\ + "<details class=\"toggle non-exhaustive\">\ <summary class=\"hideme\"><span>{}</span></summary>\ <div class=\"docblock\">", { diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index 3ea4c4bea88..ca3e9916487 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -345,7 +345,7 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex}; }; let content = format!( - "<h1 class=\"fqn\">List of all crates</h1><ul class=\"all-items\">{}</ul>", + "<h1>List of all crates</h1><ul class=\"all-items\">{}</ul>", krates .iter() .map(|s| { diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index b2fa6e82acc..2070bb54b1b 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -139,7 +139,7 @@ h1, h2, h3, h4 { .docblock > h6:first-child { margin-top: 0; } -h1.fqn { +.main-heading h1 { margin: 0; padding: 0; flex-grow: 1; @@ -317,7 +317,7 @@ main { margin-right: auto; } -details:not(.rustdoc-toggle) summary { +details:not(.toggle) summary { margin-bottom: .6em; } @@ -1401,7 +1401,7 @@ details.dir-entry a { Unfortunately we can't yet specify contain: content or contain: strict because the [-]/[+] toggles extend past the boundaries of the <details> https://developer.mozilla.org/en-US/docs/Web/CSS/contain */ -details.rustdoc-toggle { +details.toggle { contain: layout; position: relative; } @@ -1409,26 +1409,26 @@ details.rustdoc-toggle { /* The hideme class is used on summary tags that contain a span with placeholder text shown only when the toggle is closed. For instance, "Expand description" or "Show methods". */ -details.rustdoc-toggle > summary.hideme { +details.toggle > summary.hideme { cursor: pointer; font-size: 1rem; } -details.rustdoc-toggle > summary { +details.toggle > summary { list-style: none; /* focus outline is shown on `::before` instead of this */ outline: none; } -details.rustdoc-toggle > summary::-webkit-details-marker, -details.rustdoc-toggle > summary::marker { +details.toggle > summary::-webkit-details-marker, +details.toggle > summary::marker { display: none; } -details.rustdoc-toggle > summary.hideme > span { +details.toggle > summary.hideme > span { margin-left: 9px; } -details.rustdoc-toggle > summary::before { +details.toggle > summary::before { background: url("toggle-plus-1092eb4930d581b0.svg") no-repeat top left; content: ""; cursor: pointer; @@ -1440,14 +1440,14 @@ details.rustdoc-toggle > summary::before { filter: var(--toggle-filter); } -details.rustdoc-toggle > summary.hideme > span, +details.toggle > summary.hideme > span, .more-examples-toggle summary, .more-examples-toggle .hide-more { color: var(--toggles-color); } /* Screen readers see the text version at the end the line. Visual readers see the icon at the start of the line, but small and transparent. */ -details.rustdoc-toggle > summary::after { +details.toggle > summary::after { content: "Expand"; overflow: hidden; width: 0; @@ -1455,17 +1455,17 @@ details.rustdoc-toggle > summary::after { position: absolute; } -details.rustdoc-toggle > summary.hideme::after { +details.toggle > summary.hideme::after { /* "hideme" toggles already have a description when they're contracted */ content: ""; } -details.rustdoc-toggle > summary:focus::before, -details.rustdoc-toggle > summary:hover::before { +details.toggle > summary:focus::before, +details.toggle > summary:hover::before { opacity: 1; } -details.rustdoc-toggle > summary:focus-visible::before { +details.toggle > summary:focus-visible::before { /* The SVG is black, and gets turned white using a filter in the dark themes. Do the same with the outline. The dotted 1px style is copied from Firefox's focus ring style. @@ -1478,17 +1478,17 @@ details.non-exhaustive { margin-bottom: 8px; } -details.rustdoc-toggle > summary.hideme::before { +details.toggle > summary.hideme::before { position: relative; } -details.rustdoc-toggle > summary:not(.hideme)::before { +details.toggle > summary:not(.hideme)::before { position: absolute; left: -24px; top: 4px; } -.impl-items > details.rustdoc-toggle > summary:not(.hideme)::before { +.impl-items > details.toggle > summary:not(.hideme)::before { position: absolute; left: -24px; } @@ -1498,19 +1498,19 @@ details.rustdoc-toggle > summary:not(.hideme)::before { affect the layout of the items to its right. To do that, we use absolute positioning. Note that we also set position: relative on the parent <details> to make this work properly. */ -details.rustdoc-toggle[open] > summary.hideme { +details.toggle[open] > summary.hideme { position: absolute; } -details.rustdoc-toggle[open] > summary.hideme > span { +details.toggle[open] > summary.hideme > span { display: none; } -details.rustdoc-toggle[open] > summary::before { +details.toggle[open] > summary::before { background: url("toggle-minus-31bbd6e4c77f5c96.svg") no-repeat top left; } -details.rustdoc-toggle[open] > summary::after { +details.toggle[open] > summary::after { content: "Collapse"; } @@ -1660,8 +1660,8 @@ in storage.js display: block; } - #main-content > details.rustdoc-toggle > summary::before, - #main-content > div > details.rustdoc-toggle > summary::before { + #main-content > details.toggle > summary::before, + #main-content > div > details.toggle > summary::before { left: -11px; } @@ -1715,12 +1715,12 @@ in storage.js } /* Position of the "[-]" element. */ - details.rustdoc-toggle:not(.top-doc) > summary { + details.toggle:not(.top-doc) > summary { margin-left: 10px; } - .impl-items > details.rustdoc-toggle > summary:not(.hideme)::before, - #main-content > details.rustdoc-toggle:not(.top-doc) > summary::before, - #main-content > div > details.rustdoc-toggle > summary::before { + .impl-items > details.toggle > summary:not(.hideme)::before, + #main-content > details.toggle:not(.top-doc) > summary::before, + #main-content > div > details.toggle > summary::before { left: -11px; } @@ -1753,8 +1753,8 @@ in storage.js @media print { nav.sidebar, nav.sub, .out-of-band, a.srclink, #copy-path, - details.rustdoc-toggle[open] > summary::before, details.rustdoc-toggle > summary::before, - details.rustdoc-toggle.top-doc > summary { + details.toggle[open] > summary::before, details.toggle > summary::before, + details.toggle.top-doc > summary { display: none; } @@ -1796,24 +1796,24 @@ in storage.js .impl, #implementors-list > .docblock, .impl-items > section, -.impl-items > .rustdoc-toggle > summary, +.impl-items > .toggle > summary, .methods > section, -.methods > .rustdoc-toggle > summary +.methods > .toggle > summary { margin-bottom: 0.75em; } .variants > .docblock, .implementors-toggle > .docblock, -.impl-items > .rustdoc-toggle[open]:not(:last-child), -.methods > .rustdoc-toggle[open]:not(:last-child), +.impl-items > .toggle[open]:not(:last-child), +.methods > .toggle[open]:not(:last-child), .implementors-toggle[open]:not(:last-child) { margin-bottom: 2em; } -#trait-implementations-list .impl-items > .rustdoc-toggle:not(:last-child), -#synthetic-implementations-list .impl-items > .rustdoc-toggle:not(:last-child), -#blanket-implementations-list .impl-items > .rustdoc-toggle:not(:last-child) { +#trait-implementations-list .impl-items > .toggle:not(:last-child), +#synthetic-implementations-list .impl-items > .toggle:not(:last-child), +#blanket-implementations-list .impl-items > .toggle:not(:last-child) { margin-bottom: 1em; } diff --git a/src/librustdoc/html/static/css/settings.css b/src/librustdoc/html/static/css/settings.css index 875a260c811..91419093147 100644 --- a/src/librustdoc/html/static/css/settings.css +++ b/src/librustdoc/html/static/css/settings.css @@ -9,7 +9,7 @@ } .setting-line .radio-line input, -.setting-line .toggle input { +.setting-line .settings-toggle input { margin-right: 0.3em; height: 1.2rem; width: 1.2rem; @@ -22,14 +22,14 @@ .setting-line .radio-line input { border-radius: 50%; } -.setting-line .toggle input:checked { +.setting-line .settings-toggle input:checked { content: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40">\ <path d="M7,25L17,32L33,12" fill="none" stroke="black" stroke-width="5"/>\ <path d="M7,23L17,30L33,10" fill="none" stroke="white" stroke-width="5"/></svg>'); } .setting-line .radio-line input + span, -.setting-line .toggle span { +.setting-line .settings-toggle span { padding-bottom: 1px; } @@ -50,7 +50,7 @@ margin-left: 0.5em; } -.toggle { +.settings-toggle { position: relative; width: 100%; margin-right: 20px; @@ -67,11 +67,11 @@ box-shadow: inset 0 0 0 3px var(--main-background-color); background-color: var(--settings-input-color); } -.setting-line .toggle input:checked { +.setting-line .settings-toggle input:checked { background-color: var(--settings-input-color); } .setting-line .radio-line input:focus, -.setting-line .toggle input:focus { +.setting-line .settings-toggle input:focus { box-shadow: 0 0 1px 1px var(--settings-input-color); } /* In here we combine both `:focus` and `:checked` properties. */ @@ -80,6 +80,6 @@ 0 0 2px 2px var(--settings-input-color); } .setting-line .radio-line input:hover, -.setting-line .toggle input:hover { +.setting-line .settings-toggle input:hover { border-color: var(--settings-input-color) !important; } diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 51aee8e7c89..4f6f8c57597 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -526,7 +526,7 @@ function loadCss(cssUrl) { } let currentNbImpls = implementors.getElementsByClassName("impl").length; - const traitName = document.querySelector("h1.fqn > .trait").textContent; + const traitName = document.querySelector(".main-heading h1 > .trait").textContent; const baseIdName = "impl-" + traitName + "-"; const libs = Object.getOwnPropertyNames(imp); // We don't want to include impls from this JS file, when the HTML already has them. @@ -620,7 +620,7 @@ function loadCss(cssUrl) { function expandAllDocs() { const innerToggle = document.getElementById(toggleAllDocsId); removeClass(innerToggle, "will-expand"); - onEachLazy(document.getElementsByClassName("rustdoc-toggle"), e => { + onEachLazy(document.getElementsByClassName("toggle"), e => { if (!hasClass(e, "type-contents-toggle") && !hasClass(e, "more-examples-toggle")) { e.open = true; } @@ -632,7 +632,7 @@ function loadCss(cssUrl) { function collapseAllDocs() { const innerToggle = document.getElementById(toggleAllDocsId); addClass(innerToggle, "will-expand"); - onEachLazy(document.getElementsByClassName("rustdoc-toggle"), e => { + onEachLazy(document.getElementsByClassName("toggle"), e => { if (e.parentNode.id !== "implementations-list" || (!hasClass(e, "implementors-toggle") && !hasClass(e, "type-contents-toggle")) @@ -680,7 +680,7 @@ function loadCss(cssUrl) { setImplementorsTogglesOpen("blanket-implementations-list", false); } - onEachLazy(document.getElementsByClassName("rustdoc-toggle"), e => { + onEachLazy(document.getElementsByClassName("toggle"), e => { if (!hideLargeItemContents && hasClass(e, "type-contents-toggle")) { e.open = true; } @@ -823,7 +823,7 @@ function loadCss(cssUrl) { }); }); - onEachLazy(document.querySelectorAll(".rustdoc-toggle > summary:not(.hideme)"), el => { + onEachLazy(document.querySelectorAll(".toggle > summary:not(.hideme)"), el => { el.addEventListener("click", e => { if (e.target.tagName !== "SUMMARY" && e.target.tagName !== "A") { e.preventDefault(); diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js index 589bfc79360..9ed8f63610f 100644 --- a/src/librustdoc/html/static/js/settings.js +++ b/src/librustdoc/html/static/js/settings.js @@ -150,10 +150,10 @@ }); output += "</div></div>"; } else { - // This is a toggle. + // This is a checkbox toggle. const checked = setting["default"] === true ? " checked" : ""; output += `\ -<label class="toggle">\ +<label class="settings-toggle">\ <input type="checkbox" id="${js_data_name}"${checked}>\ <span class="label">${setting_name}</span>\ </label>`; diff --git a/src/librustdoc/html/templates/print_item.html b/src/librustdoc/html/templates/print_item.html index 611d124d4b9..ee2880bf6d1 100644 --- a/src/librustdoc/html/templates/print_item.html +++ b/src/librustdoc/html/templates/print_item.html @@ -1,5 +1,5 @@ <div class="main-heading"> {#- -#} - <h1 class="fqn"> {#- -#} + <h1> {#- -#} {{-typ-}} {#- The breadcrumbs of the item path, like std::string -#} {%- for component in path_components -%} diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index ed77de200a9..86454e1f2eb 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -772,7 +772,6 @@ fn main_args(at_args: &[String]) -> MainResult { let crate_version = options.crate_version.clone(); let output_format = options.output_format; - let externs = options.externs.clone(); let scrape_examples_options = options.scrape_examples_options.clone(); let bin_crate = options.bin_crate; @@ -805,9 +804,7 @@ fn main_args(at_args: &[String]) -> MainResult { let resolver_caches = resolver.borrow_mut().access(|resolver| { collect_intra_doc_links::early_resolve_intra_doc_links( resolver, - sess, krate, - externs, render_options.document_private, ) }); diff --git a/src/librustdoc/passes/collect_intra_doc_links/early.rs b/src/librustdoc/passes/collect_intra_doc_links/early.rs index 1b373cfe5bb..42677bd8497 100644 --- a/src/librustdoc/passes/collect_intra_doc_links/early.rs +++ b/src/librustdoc/passes/collect_intra_doc_links/early.rs @@ -12,8 +12,6 @@ use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, CRATE_DEF_ID}; use rustc_hir::TraitCandidate; use rustc_middle::ty::{DefIdTree, Visibility}; use rustc_resolve::{ParentScope, Resolver}; -use rustc_session::config::Externs; -use rustc_session::Session; use rustc_span::symbol::sym; use rustc_span::{Symbol, SyntaxContext}; @@ -22,16 +20,13 @@ use std::mem; pub(crate) fn early_resolve_intra_doc_links( resolver: &mut Resolver<'_>, - sess: &Session, krate: &ast::Crate, - externs: Externs, document_private_items: bool, ) -> ResolverCaches { let parent_scope = ParentScope::module(resolver.expect_module(CRATE_DEF_ID.to_def_id()), resolver); let mut link_resolver = EarlyDocLinkResolver { resolver, - sess, parent_scope, visited_mods: Default::default(), markdown_links: Default::default(), @@ -52,7 +47,9 @@ pub(crate) fn early_resolve_intra_doc_links( // the known necessary crates. Load them all unconditionally until we find a way to fix this. // DO NOT REMOVE THIS without first testing on the reproducer in // https://github.com/jyn514/objr/commit/edcee7b8124abf0e4c63873e8422ff81beb11ebb - for (extern_name, _) in externs.iter().filter(|(_, entry)| entry.add_prelude) { + for (extern_name, _) in + link_resolver.resolver.sess().opts.externs.iter().filter(|(_, entry)| entry.add_prelude) + { link_resolver.resolver.resolve_rustdoc_path(extern_name, TypeNS, parent_scope); } @@ -73,7 +70,6 @@ fn doc_attrs<'a>(attrs: impl Iterator<Item = &'a ast::Attribute>) -> Attributes struct EarlyDocLinkResolver<'r, 'ra> { resolver: &'r mut Resolver<'ra>, - sess: &'r Session, parent_scope: ParentScope<'ra>, visited_mods: DefIdSet, markdown_links: FxHashMap<String, Vec<PreprocessedMarkdownLink>>, @@ -166,7 +162,7 @@ impl<'ra> EarlyDocLinkResolver<'_, 'ra> { fn resolve_doc_links_extern_impl(&mut self, def_id: DefId, is_inherent: bool) { self.resolve_doc_links_extern_outer_fixme(def_id, def_id); let assoc_item_def_ids = Vec::from_iter( - self.resolver.cstore().associated_item_def_ids_untracked(def_id, self.sess), + self.resolver.cstore().associated_item_def_ids_untracked(def_id, self.resolver.sess()), ); for assoc_def_id in assoc_item_def_ids { if !is_inherent || self.resolver.cstore().visibility_untracked(assoc_def_id).is_public() @@ -191,7 +187,9 @@ impl<'ra> EarlyDocLinkResolver<'_, 'ra> { if !self.resolver.cstore().may_have_doc_links_untracked(def_id) { return; } - let attrs = Vec::from_iter(self.resolver.cstore().item_attrs_untracked(def_id, self.sess)); + let attrs = Vec::from_iter( + self.resolver.cstore().item_attrs_untracked(def_id, self.resolver.sess()), + ); let parent_scope = ParentScope::module( self.resolver.get_nearest_non_block_module( self.resolver.opt_parent(scope_id).unwrap_or(scope_id), @@ -205,7 +203,9 @@ impl<'ra> EarlyDocLinkResolver<'_, 'ra> { if !self.resolver.cstore().may_have_doc_links_untracked(def_id) { return; } - let attrs = Vec::from_iter(self.resolver.cstore().item_attrs_untracked(def_id, self.sess)); + let attrs = Vec::from_iter( + self.resolver.cstore().item_attrs_untracked(def_id, self.resolver.sess()), + ); let parent_scope = ParentScope::module(self.resolver.expect_module(def_id), self.resolver); self.resolve_doc_links(doc_attrs(attrs.iter()), parent_scope); } @@ -321,7 +321,7 @@ impl<'ra> EarlyDocLinkResolver<'_, 'ra> { let field_def_ids = Vec::from_iter( self.resolver .cstore() - .associated_item_def_ids_untracked(def_id, self.sess), + .associated_item_def_ids_untracked(def_id, self.resolver.sess()), ); for field_def_id in field_def_ids { self.resolve_doc_links_extern_outer(field_def_id, scope_id); diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs index f5501b3d523..048ed264623 100644 --- a/src/librustdoc/passes/stripper.rs +++ b/src/librustdoc/passes/stripper.rs @@ -97,17 +97,7 @@ impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> { } // handled in the `strip-priv-imports` pass - clean::ExternCrateItem { .. } => {} - clean::ImportItem(ref imp) => { - // Because json doesn't inline imports from private modules, we need to mark - // the imported item as retained so it's impls won't be stripped. - // - // FIXME: Is it necessary to check for json output here: See - // https://github.com/rust-lang/rust/pull/100325#discussion_r941495215 - if let Some(did) = imp.source.did && self.is_json_output { - self.retained.insert(did.into()); - } - } + clean::ExternCrateItem { .. } | clean::ImportItem(_) => {} clean::ImplItem(..) => {} diff --git a/src/tools/cargo b/src/tools/cargo -Subproject d992ab4e9034930e7809749f04077045af8f4d7 +Subproject 1cd6d3803dfb0b342272862a8590f5dfc9f7257 diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml index 33c05180408..b296aa2f4e6 100644 --- a/src/tools/rustbook/Cargo.toml +++ b/src/tools/rustbook/Cargo.toml @@ -5,10 +5,10 @@ license = "MIT OR Apache-2.0" edition = "2021" [dependencies] -clap = "3.1.1" +clap = "4.0.32" env_logger = "0.7.1" [dependencies.mdbook] -version = "0.4.21" +version = "0.4.25" default-features = false features = ["search"] diff --git a/src/tools/rustbook/src/main.rs b/src/tools/rustbook/src/main.rs index 3c7dc0183d7..1368ec653de 100644 --- a/src/tools/rustbook/src/main.rs +++ b/src/tools/rustbook/src/main.rs @@ -9,18 +9,21 @@ use mdbook::errors::Result as Result3; use mdbook::MDBook; fn main() { - let crate_version = format!("v{}", crate_version!()); + let crate_version = concat!("v", crate_version!()); env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("warn")).init(); let d_arg = arg!(-d --"dest-dir" <DEST_DIR> "The output directory for your book\n(Defaults to ./book when omitted)") - .required(false); - let dir_arg = arg!([dir] -"A directory for your book\n(Defaults to Current Directory when omitted)"); + .required(false) + .value_parser(clap::value_parser!(PathBuf)); + + let dir_arg = arg!([dir] "Root directory for the book\n\ + (Defaults to the current directory when omitted)") + .value_parser(clap::value_parser!(PathBuf)); let matches = Command::new("rustbook") .about("Build a book with mdBook") .author("Steve Klabnik <steve@steveklabnik.com>") - .version(&*crate_version) + .version(crate_version) .subcommand_required(true) .arg_required_else_help(true) .subcommand( @@ -60,8 +63,8 @@ pub fn build(args: &ArgMatches) -> Result3<()> { // Set this to allow us to catch bugs in advance. book.config.build.create_missing = false; - if let Some(dest_dir) = args.value_of("dest-dir") { - book.config.build.build_dir = PathBuf::from(dest_dir); + if let Some(dest_dir) = args.get_one::<PathBuf>("dest-dir") { + book.config.build.build_dir = dest_dir.into(); } book.build()?; @@ -76,10 +79,9 @@ fn test(args: &ArgMatches) -> Result3<()> { } fn get_book_dir(args: &ArgMatches) -> PathBuf { - if let Some(dir) = args.value_of("dir") { + if let Some(p) = args.get_one::<PathBuf>("dir") { // Check if path is relative from current dir, or absolute... - let p = Path::new(dir); - if p.is_relative() { env::current_dir().unwrap().join(dir) } else { p.to_path_buf() } + if p.is_relative() { env::current_dir().unwrap().join(p) } else { p.to_path_buf() } } else { env::current_dir().unwrap() } diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml index fff83a1d097..19812fc6f55 100644 --- a/src/tools/tidy/Cargo.toml +++ b/src/tools/tidy/Cargo.toml @@ -6,6 +6,7 @@ autobins = false [dependencies] cargo_metadata = "0.14" +cargo-platform = "0.1.2" regex = "1" miropt-test-tools = { path = "../miropt-test-tools" } lazy_static = "1" diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 29501d2d3b6..bc2edf634de 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -1,7 +1,7 @@ //! Checks the licenses of third-party dependencies. -use cargo_metadata::{Metadata, Package, PackageId, Resolve}; -use std::collections::{BTreeSet, HashSet}; +use cargo_metadata::{DepKindInfo, Metadata, Package, PackageId}; +use std::collections::HashSet; use std::path::Path; /// These are licenses that are allowed for all crates, including the runtime, @@ -98,14 +98,12 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "autocfg", "bitflags", "block-buffer", - "bumpalo", // Included in Cargo's dep graph but only activated on wasm32-*-unknown. "cc", "cfg-if", "chalk-derive", "chalk-engine", "chalk-ir", "chalk-solve", - "chrono", "convert_case", // dependency of derive_more "compiler_builtins", "cpufeatures", @@ -124,11 +122,9 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "dlmalloc", "either", "ena", - "env_logger", "expect-test", "fallible-iterator", // dependency of `thorin` "fastrand", - "filetime", "fixedbitset", "flate2", "fluent-bundle", @@ -142,13 +138,11 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "gsgdt", "hashbrown", "hermit-abi", - "humantime", "icu_list", "icu_locid", "icu_provider", "icu_provider_adapters", "icu_provider_macros", - "if_chain", "indexmap", "instant", "intl-memoizer", @@ -156,7 +150,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "itertools", "itoa", "jobserver", - "js-sys", // Included in Cargo's dep graph but only activated on wasm32-*-unknown. "lazy_static", "libc", "libloading", @@ -171,8 +164,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "memmap2", "memoffset", "miniz_oxide", - "num-integer", - "num-traits", "num_cpus", "object", "odht", @@ -190,7 +181,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "proc-macro2", "psm", "punycode", - "quick-error", "quote", "rand", "rand_chacha", @@ -217,7 +207,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "serde", "serde_derive", "serde_json", - "sha-1", + "sha1", "sha2", "sharded-slab", "smallvec", @@ -235,7 +225,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "thiserror-impl", "thorin-dwp", "thread_local", - "time", "tinystr", "tinyvec", "tinyvec_macros", @@ -268,13 +257,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "valuable", "version_check", "wasi", - // vvv Included in Cargo's dep graph but only activated on wasm32-*-unknown. - "wasm-bindgen", - "wasm-bindgen-backend", - "wasm-bindgen-macro", - "wasm-bindgen-macro-support", - "wasm-bindgen-shared", - // ^^^ Included in Cargo's dep graph but only activated on wasm32-*-unknown. "winapi", "winapi-i686-pc-windows-gnu", "winapi-util", @@ -485,73 +467,55 @@ fn check_permitted_dependencies( restricted_dependency_crates: &[&'static str], bad: &mut bool, ) { + let mut deps = HashSet::new(); + for to_check in restricted_dependency_crates { + let to_check = pkg_from_name(metadata, to_check); + use cargo_platform::Cfg; + use std::str::FromStr; + // We don't expect the compiler to ever run on wasm32, so strip + // out those dependencies to avoid polluting the permitted list. + deps_of_filtered(metadata, &to_check.id, &mut deps, &|dep_kinds| { + dep_kinds.iter().any(|dep_kind| { + dep_kind + .target + .as_ref() + .map(|target| { + !target.matches( + "wasm32-unknown-unknown", + &[ + Cfg::from_str("target_arch=\"wasm32\"").unwrap(), + Cfg::from_str("target_os=\"unknown\"").unwrap(), + ], + ) + }) + .unwrap_or(true) + }) + }); + } + // Check that the PERMITTED_DEPENDENCIES does not have unused entries. - for name in permitted_dependencies { - if !metadata.packages.iter().any(|p| p.name == *name) { + for permitted in permitted_dependencies { + if !deps.iter().any(|dep_id| &pkg_from_id(metadata, dep_id).name == permitted) { tidy_error!( bad, - "could not find allowed package `{}`\n\ + "could not find allowed package `{permitted}`\n\ Remove from PERMITTED_DEPENDENCIES list if it is no longer used.", - name ); } } - // Get the list in a convenient form. - let permitted_dependencies: HashSet<_> = permitted_dependencies.iter().cloned().collect(); - - // Check dependencies. - let mut visited = BTreeSet::new(); - let mut unapproved = BTreeSet::new(); - for &krate in restricted_dependency_crates.iter() { - let pkg = pkg_from_name(metadata, krate); - let mut bad = - check_crate_dependencies(&permitted_dependencies, metadata, &mut visited, pkg); - unapproved.append(&mut bad); - } - - if !unapproved.is_empty() { - tidy_error!(bad, "Dependencies for {} not explicitly permitted:", descr); - for dep in unapproved { - println!("* {dep}"); - } - } -} - -/// Checks the dependencies of the given crate from the given cargo metadata to see if they are on -/// the list of permitted dependencies. Returns a list of disallowed dependencies. -fn check_crate_dependencies<'a>( - permitted_dependencies: &'a HashSet<&'static str>, - metadata: &'a Metadata, - visited: &mut BTreeSet<&'a PackageId>, - krate: &'a Package, -) -> BTreeSet<&'a PackageId> { - // This will contain bad deps. - let mut unapproved = BTreeSet::new(); - - // Check if we have already visited this crate. - if visited.contains(&krate.id) { - return unapproved; - } - visited.insert(&krate.id); + // Get in a convenient form. + let permitted_dependencies: HashSet<_> = permitted_dependencies.iter().cloned().collect(); - // If this path is in-tree, we don't require it to be explicitly permitted. - if krate.source.is_some() { - // If this dependency is not on `PERMITTED_DEPENDENCIES`, add to bad set. - if !permitted_dependencies.contains(krate.name.as_str()) { - unapproved.insert(&krate.id); + for dep in deps { + let dep = pkg_from_id(metadata, dep); + // If this path is in-tree, we don't require it to be explicitly permitted. + if dep.source.is_some() { + if !permitted_dependencies.contains(dep.name.as_str()) { + tidy_error!(bad, "Dependency for {descr} not explicitly permitted: {}", dep.id); + } } } - - // Do a DFS in the crate graph. - let to_check = deps_of(metadata, &krate.id); - - for dep in to_check { - let mut bad = check_crate_dependencies(permitted_dependencies, metadata, visited, dep); - unapproved.append(&mut bad); - } - - unapproved } /// Prevents multiple versions of some expensive crates. @@ -588,24 +552,6 @@ fn check_crate_duplicate( } } -/// Returns a list of dependencies for the given package. -fn deps_of<'a>(metadata: &'a Metadata, pkg_id: &'a PackageId) -> Vec<&'a Package> { - let resolve = metadata.resolve.as_ref().unwrap(); - let node = resolve - .nodes - .iter() - .find(|n| &n.id == pkg_id) - .unwrap_or_else(|| panic!("could not find `{pkg_id}` in resolve")); - node.deps - .iter() - .map(|dep| { - metadata.packages.iter().find(|pkg| pkg.id == dep.pkg).unwrap_or_else(|| { - panic!("could not find dep `{}` for pkg `{}` in resolve", dep.pkg, pkg_id) - }) - }) - .collect() -} - /// Finds a package with the given name. fn pkg_from_name<'a>(metadata: &'a Metadata, name: &'static str) -> &'a Package { let mut i = metadata.packages.iter().filter(|p| p.name == name); @@ -615,41 +561,57 @@ fn pkg_from_name<'a>(metadata: &'a Metadata, name: &'static str) -> &'a Package result } +fn pkg_from_id<'a>(metadata: &'a Metadata, id: &PackageId) -> &'a Package { + metadata.packages.iter().find(|p| &p.id == id).unwrap() +} + /// Finds all the packages that are in the rust runtime. fn compute_runtime_crates<'a>(metadata: &'a Metadata) -> HashSet<&'a PackageId> { - let resolve = metadata.resolve.as_ref().unwrap(); let mut result = HashSet::new(); for name in RUNTIME_CRATES { let id = &pkg_from_name(metadata, name).id; - normal_deps_of_r(resolve, id, &mut result); + deps_of_filtered(metadata, id, &mut result, &|_| true); } result } -/// Recursively find all normal dependencies. -fn normal_deps_of_r<'a>( - resolve: &'a Resolve, +/// Recursively find all dependencies. +fn deps_of_filtered<'a>( + metadata: &'a Metadata, pkg_id: &'a PackageId, result: &mut HashSet<&'a PackageId>, + filter: &dyn Fn(&[DepKindInfo]) -> bool, ) { if !result.insert(pkg_id) { return; } - let node = resolve + let node = metadata + .resolve + .as_ref() + .unwrap() .nodes .iter() .find(|n| &n.id == pkg_id) .unwrap_or_else(|| panic!("could not find `{pkg_id}` in resolve")); for dep in &node.deps { - normal_deps_of_r(resolve, &dep.pkg, result); + if !filter(&dep.dep_kinds) { + continue; + } + deps_of_filtered(metadata, &dep.pkg, result, filter); } } +fn direct_deps_of<'a>(metadata: &'a Metadata, pkg_id: &'a PackageId) -> Vec<&'a Package> { + let resolve = metadata.resolve.as_ref().unwrap(); + let node = resolve.nodes.iter().find(|n| &n.id == pkg_id).unwrap(); + node.deps.iter().map(|dep| pkg_from_id(metadata, &dep.pkg)).collect() +} + fn check_rustfix(metadata: &Metadata, bad: &mut bool) { let cargo = pkg_from_name(metadata, "cargo"); let compiletest = pkg_from_name(metadata, "compiletest"); - let cargo_deps = deps_of(metadata, &cargo.id); - let compiletest_deps = deps_of(metadata, &compiletest.id); + let cargo_deps = direct_deps_of(metadata, &cargo.id); + let compiletest_deps = direct_deps_of(metadata, &compiletest.id); let cargo_rustfix = cargo_deps.iter().find(|p| p.name == "rustfix").unwrap(); let compiletest_rustfix = compiletest_deps.iter().find(|p| p.name == "rustfix").unwrap(); if cargo_rustfix.version != compiletest_rustfix.version { diff --git a/tests/mir-opt/building/custom/consts.rs b/tests/mir-opt/building/custom/consts.rs index ff4fe1a9324..16d10eb5968 100644 --- a/tests/mir-opt/building/custom/consts.rs +++ b/tests/mir-opt/building/custom/consts.rs @@ -18,8 +18,8 @@ fn consts<const C: u32>() { }) } -static S: i32 = 5; -static mut T: i32 = 10; +static S: i32 = 0x05050505; +static mut T: i32 = 0x0a0a0a0a; // EMIT_MIR consts.statics.built.after.mir #[custom_mir(dialect = "built")] fn statics() { diff --git a/tests/mir-opt/building/custom/consts.statics.built.after.mir b/tests/mir-opt/building/custom/consts.statics.built.after.mir index ee768e263ec..bfef976aa02 100644 --- a/tests/mir-opt/building/custom/consts.statics.built.after.mir +++ b/tests/mir-opt/building/custom/consts.statics.built.after.mir @@ -19,9 +19,9 @@ fn statics() -> () { } alloc2 (static: T, size: 4, align: 4) { - 0a 00 00 00 │ .... + 0a 0a 0a 0a │ .... } alloc1 (static: S, size: 4, align: 4) { - 05 00 00 00 │ .... + 05 05 05 05 │ .... } diff --git a/tests/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff b/tests/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff index b9d551c5e5f..7fa29cccd50 100644 --- a/tests/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff @@ -38,6 +38,6 @@ } alloc1 (static: STATIC, size: 4, align: 4) { - 2a 00 00 00 │ *... + 42 42 42 42 │ BBBB } diff --git a/tests/mir-opt/const_prop/mutable_variable_no_prop.rs b/tests/mir-opt/const_prop/mutable_variable_no_prop.rs index 8c23c5fcf0f..b69ec931a63 100644 --- a/tests/mir-opt/const_prop/mutable_variable_no_prop.rs +++ b/tests/mir-opt/const_prop/mutable_variable_no_prop.rs @@ -1,7 +1,7 @@ // unit-test // compile-flags: -O -static mut STATIC: u32 = 42; +static mut STATIC: u32 = 0x42424242; // EMIT_MIR mutable_variable_no_prop.main.ConstProp.diff fn main() { diff --git a/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff b/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff index 1c69a6232d6..93804780371 100644 --- a/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff +++ b/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff @@ -26,7 +26,7 @@ _3 = _1; // scope 2 at $DIR/issue_75439.rs:+2:47: +2:52 _2 = transmute::<[u8; 16], [u32; 4]>(move _3) -> bb1; // scope 2 at $DIR/issue_75439.rs:+2:37: +2:53 // mir::Constant - // + span: $DIR/issue_75439.rs:7:37: 7:46 + // + span: $DIR/issue_75439.rs:8:37: 8:46 // + literal: Const { ty: unsafe extern "rust-intrinsic" fn([u8; 16]) -> [u32; 4] {transmute::<[u8; 16], [u32; 4]>}, val: Value(<ZST>) } } @@ -49,7 +49,7 @@ _6 = _4; // scope 4 at $DIR/issue_75439.rs:+5:33: +5:35 _5 = transmute::<u32, [u8; 4]>(move _6) -> bb7; // scope 4 at $DIR/issue_75439.rs:+5:23: +5:36 // mir::Constant - // + span: $DIR/issue_75439.rs:10:23: 10:32 + // + span: $DIR/issue_75439.rs:11:23: 11:32 // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u32) -> [u8; 4] {transmute::<u32, [u8; 4]>}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/issues/issue_75439.rs b/tests/mir-opt/issues/issue_75439.rs index ae2e036312e..4c749a150c0 100644 --- a/tests/mir-opt/issues/issue_75439.rs +++ b/tests/mir-opt/issues/issue_75439.rs @@ -1,4 +1,5 @@ // EMIT_MIR issue_75439.foo.MatchBranchSimplification.diff +// ignore-endian-big use std::mem::transmute; diff --git a/tests/rustdoc-gui/anchors.goml b/tests/rustdoc-gui/anchors.goml index c9b53a1a0f7..85cb7227420 100644 --- a/tests/rustdoc-gui/anchors.goml +++ b/tests/rustdoc-gui/anchors.goml @@ -2,7 +2,7 @@ define-function: ( "check-colors", - (theme, main_color, title_color, fqn_color, fqn_type_color, src_link_color, sidebar_link_color), + (theme, main_color, title_color, main_heading_color, main_heading_type_color, src_link_color, sidebar_link_color), block { goto: "file://" + |DOC_PATH| + "/staged_api/struct.Foo.html" // This is needed to ensure that the text color is computed. @@ -14,8 +14,8 @@ define-function: ( reload: assert-css: ("#toggle-all-docs", {"color": |main_color|}) - assert-css: (".fqn a:nth-of-type(1)", {"color": |fqn_color|}) - assert-css: (".fqn a:nth-of-type(2)", {"color": |fqn_type_color|}) + assert-css: (".main-heading h1 a:nth-of-type(1)", {"color": |main_heading_color|}) + assert-css: (".main-heading a:nth-of-type(2)", {"color": |main_heading_type_color|}) assert-css: ( ".rightside .srclink", {"color": |src_link_color|, "text-decoration": "none solid " + |src_link_color|}, @@ -57,7 +57,7 @@ define-function: ( assert-css: ("#top-doc-prose-title", {"color": |title_color|}) assert-css: (".sidebar a", {"color": |sidebar_link_color|}) - assert-css: ("h1.fqn a", {"color": |title_color|}) + assert-css: (".main-heading h1 a", {"color": |title_color|}) // We move the cursor over the "Implementations" title so the anchor is displayed. move-cursor-to: "h2#implementations" @@ -77,8 +77,8 @@ call-function: ( "theme": "ayu", "main_color": "rgb(197, 197, 197)", "title_color": "rgb(255, 255, 255)", - "fqn_color": "rgb(255, 255, 255)", - "fqn_type_color": "rgb(255, 160, 165)", + "main_heading_color": "rgb(255, 255, 255)", + "main_heading_type_color": "rgb(255, 160, 165)", "src_link_color": "rgb(57, 175, 215)", "sidebar_link_color": "rgb(83, 177, 219)", }, @@ -89,8 +89,8 @@ call-function: ( "theme": "dark", "main_color": "rgb(221, 221, 221)", "title_color": "rgb(221, 221, 221)", - "fqn_color": "rgb(221, 221, 221)", - "fqn_type_color": "rgb(45, 191, 184)", + "main_heading_color": "rgb(221, 221, 221)", + "main_heading_type_color": "rgb(45, 191, 184)", "src_link_color": "rgb(210, 153, 29)", "sidebar_link_color": "rgb(253, 191, 53)", }, @@ -101,8 +101,8 @@ call-function: ( "theme": "light", "main_color": "rgb(0, 0, 0)", "title_color": "rgb(0, 0, 0)", - "fqn_color": "rgb(0, 0, 0)", - "fqn_type_color": "rgb(173, 55, 138)", + "main_heading_color": "rgb(0, 0, 0)", + "main_heading_type_color": "rgb(173, 55, 138)", "src_link_color": "rgb(56, 115, 173)", "sidebar_link_color": "rgb(53, 109, 164)", }, diff --git a/tests/rustdoc-gui/headings.goml b/tests/rustdoc-gui/headings.goml index 45b3fee26e4..e4ba5f1246d 100644 --- a/tests/rustdoc-gui/headings.goml +++ b/tests/rustdoc-gui/headings.goml @@ -13,7 +13,7 @@ // 14px 0.875rem goto: "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html" -assert-css: ("h1.fqn", {"font-size": "24px"}) +assert-css: (".main-heading h1", {"font-size": "24px"}) assert-css: ("h2#top-doc-prose-title", {"font-size": "22px"}) assert-css: ("h2#top-doc-prose-title", {"border-bottom-width": "1px"}) @@ -52,7 +52,7 @@ assert-css: ("h6#sub-sub-heading-for-struct-impl-item-doc", {"font-size": "14px" goto: "file://" + |DOC_PATH| + "/test_docs/enum.HeavilyDocumentedEnum.html" -assert-css: ("h1.fqn", {"font-size": "24px"}) +assert-css: (".main-heading h1", {"font-size": "24px"}) assert-css: ("h2#top-doc-prose-title", {"font-size": "22px"}) assert-css: ("h2#top-doc-prose-title", {"border-bottom-width": "1px"}) @@ -111,7 +111,7 @@ assert-css: ("//ul[@class='block mod']/preceding-sibling::h3", {"border-bottom-w goto: "file://" + |DOC_PATH| + "/test_docs/union.HeavilyDocumentedUnion.html" -assert-css: ("h1.fqn", {"font-size": "24px"}) +assert-css: (".main-heading h1", {"font-size": "24px"}) assert-css: ("h2#top-doc-prose-title", {"font-size": "22px"}) assert-css: ("h2#top-doc-prose-title", {"border-bottom-width": "1px"}) @@ -143,7 +143,7 @@ assert-css: ("h6#sub-heading-for-union-impl-item-doc", {"border-bottom-width": " goto: "file://" + |DOC_PATH| + "/test_docs/macro.heavily_documented_macro.html" -assert-css: ("h1.fqn", {"font-size": "24px"}) +assert-css: (".main-heading h1", {"font-size": "24px"}) assert-css: ("h2#top-doc-prose-title", {"font-size": "22px"}) assert-css: ("h2#top-doc-prose-title", {"border-bottom-width": "1px"}) diff --git a/tests/rustdoc-gui/method-margins.goml b/tests/rustdoc-gui/method-margins.goml index ed36bcdec17..720268a9e7e 100644 --- a/tests/rustdoc-gui/method-margins.goml +++ b/tests/rustdoc-gui/method-margins.goml @@ -1,18 +1,18 @@ // This test ensures that the margins on methods are coherent inside an impl block. goto: "file://" + |DOC_PATH| + "/test_docs/trait_members/struct.HasTrait.html#impl-TraitMembers-for-HasTrait" -assert-count: ("#trait-implementations-list > .rustdoc-toggle", 1) +assert-count: ("#trait-implementations-list > .toggle", 1) compare-elements-css: ( // compare margin on type with margin on method - "#trait-implementations-list .impl-items > .rustdoc-toggle:nth-child(1) > summary", - "#trait-implementations-list .impl-items > .rustdoc-toggle:nth-child(2) > summary", + "#trait-implementations-list .impl-items > .toggle:nth-child(1) > summary", + "#trait-implementations-list .impl-items > .toggle:nth-child(2) > summary", ["margin"] ) compare-elements-css: ( // compare margin on type with margin on method - "#trait-implementations-list .impl-items > .rustdoc-toggle:nth-child(1)", - "#trait-implementations-list .impl-items > .rustdoc-toggle:nth-child(2)", + "#trait-implementations-list .impl-items > .toggle:nth-child(1)", + "#trait-implementations-list .impl-items > .toggle:nth-child(2)", ["margin"] ) diff --git a/tests/rustdoc-gui/search-result-go-to-first.goml b/tests/rustdoc-gui/search-result-go-to-first.goml index 994fd87c996..f444baa6ce1 100644 --- a/tests/rustdoc-gui/search-result-go-to-first.goml +++ b/tests/rustdoc-gui/search-result-go-to-first.goml @@ -3,17 +3,17 @@ // First, we check that the first page doesn't have the string we're looking for to ensure // that the feature is changing page as expected. goto: "file://" + |DOC_PATH| + "/test_docs/index.html" -assert-text-false: (".fqn", "Struct test_docs::Foo") +assert-text-false: (".main-heading h1", "Struct test_docs::Foo") // We now check that we land on the search result page if "go_to_first" isn't set. goto: "file://" + |DOC_PATH| + "/test_docs/index.html?search=struct%3AFoo" // Waiting for the search results to appear... wait-for: "#search-tabs" -assert-text-false: (".fqn", "Struct test_docs::Foo") +assert-text-false: (".main-heading h1", "Struct test_docs::Foo") // Ensure that the search results are displayed, not the "normal" content. assert-css: ("#main-content", {"display": "none"}) // Now we can check that the feature is working as expected! goto: "file://" + |DOC_PATH| + "/test_docs/index.html?search=struct%3AFoo&go_to_first=true" // Waiting for the page to load... -wait-for-text: (".fqn", "Struct test_docs::Foo") +wait-for-text: (".main-heading h1", "Struct test_docs::Foo") diff --git a/tests/rustdoc-gui/settings.goml b/tests/rustdoc-gui/settings.goml index fc3beaa53fa..f236dc3e0fe 100644 --- a/tests/rustdoc-gui/settings.goml +++ b/tests/rustdoc-gui/settings.goml @@ -159,7 +159,7 @@ assert-text: ("#preferred-light-theme .setting-name", "Preferred light theme") // We now check that clicking on the toggles' text is like clicking on the checkbox. // To test it, we use the "Disable keyboard shortcuts". local-storage: {"rustdoc-disable-shortcuts": "false"} -click: ".setting-line:last-child .toggle .label" +click: ".setting-line:last-child .settings-toggle .label" assert-local-storage: {"rustdoc-disable-shortcuts": "true"} // Make sure that "Disable keyboard shortcuts" actually took effect. @@ -169,7 +169,7 @@ assert-false: "#help-button .popover" wait-for-css: ("#settings-menu .popover", {"display": "block"}) // Now turn keyboard shortcuts back on, and see if they work. -click: ".setting-line:last-child .toggle .label" +click: ".setting-line:last-child .settings-toggle .label" assert-local-storage: {"rustdoc-disable-shortcuts": "false"} press-key: "Escape" press-key: "?" diff --git a/tests/rustdoc-gui/toggle-click-deadspace.goml b/tests/rustdoc-gui/toggle-click-deadspace.goml index 029403ee13e..ac346f25b88 100644 --- a/tests/rustdoc-gui/toggle-click-deadspace.goml +++ b/tests/rustdoc-gui/toggle-click-deadspace.goml @@ -1,15 +1,15 @@ // This test ensures that clicking on a method summary, but not on the "[-]", // doesn't toggle the <details>. goto: "file://" + |DOC_PATH| + "/lib2/struct.Foo.html" -assert-attribute: (".impl-items .rustdoc-toggle", {"open": ""}) +assert-attribute: (".impl-items .toggle", {"open": ""}) click: "h4.code-header" // This is the position of "pub" in "pub fn a_method" -assert-attribute: (".impl-items .rustdoc-toggle", {"open": ""}) +assert-attribute: (".impl-items .toggle", {"open": ""}) click-with-offset: ( - ".impl-items .rustdoc-toggle summary", + ".impl-items .toggle summary", {"x": -24, "y": 8}, // This is the position of "[-]" next to that pub fn. ) -assert-attribute-false: (".impl-items .rustdoc-toggle", {"open": ""}) +assert-attribute-false: (".impl-items .toggle", {"open": ""}) // Click the "Trait" part of "impl Trait" and verify it navigates. click: "#impl-Trait-for-Foo h3 a:first-of-type" -assert-text: (".fqn", "Trait lib2::Trait") +assert-text: (".main-heading h1", "Trait lib2::Trait") diff --git a/tests/rustdoc-gui/toggle-docs.goml b/tests/rustdoc-gui/toggle-docs.goml index 89ce78e3aab..c9d236e9bba 100644 --- a/tests/rustdoc-gui/toggle-docs.goml +++ b/tests/rustdoc-gui/toggle-docs.goml @@ -20,10 +20,10 @@ assert-text: ("#toggle-all-docs", "[−]") goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html" // We first check that everything is visible. assert-text: ("#toggle-all-docs", "[−]") -assert-attribute: ("#implementations-list details.rustdoc-toggle", {"open": ""}, ALL) -assert-attribute: ("#trait-implementations-list details.rustdoc-toggle", {"open": ""}, ALL) +assert-attribute: ("#implementations-list details.toggle", {"open": ""}, ALL) +assert-attribute: ("#trait-implementations-list details.toggle", {"open": ""}, ALL) assert-attribute-false: ( - "#blanket-implementations-list > details.rustdoc-toggle", + "#blanket-implementations-list > details.toggle", {"open": ""}, ALL, ) @@ -32,18 +32,18 @@ assert-attribute-false: ( click: "#toggle-all-docs" wait-for-text: ("#toggle-all-docs", "[+]") // We check that all <details> are collapsed (except for the impl block ones). -assert-attribute-false: ("details.rustdoc-toggle:not(.implementors-toggle)", {"open": ""}, ALL) +assert-attribute-false: ("details.toggle:not(.implementors-toggle)", {"open": ""}, ALL) assert-attribute: ("#implementations-list > details.implementors-toggle", {"open": ""}) // We now check that the other impl blocks are collapsed. assert-attribute-false: ( - "#blanket-implementations-list > details.rustdoc-toggle.implementors-toggle", + "#blanket-implementations-list > details.toggle.implementors-toggle", {"open": ""}, ALL, ) // We open them all again. click: "#toggle-all-docs" wait-for-text: ("#toggle-all-docs", "[−]") -assert-attribute: ("details.rustdoc-toggle", {"open": ""}, ALL) +assert-attribute: ("details.toggle", {"open": ""}, ALL) // Checking the toggles style. show-text: true @@ -56,12 +56,12 @@ define-function: ( // We reload the page so the local storage settings are being used. reload: - assert-css: ("details.rustdoc-toggle > summary::before", { + assert-css: ("details.toggle > summary::before", { "opacity": "0.5", "filter": |filter|, }, ALL) - move-cursor-to: "details.rustdoc-toggle summary" - assert-css: ("details.rustdoc-toggle > summary:hover::before", { + move-cursor-to: "details.toggle summary" + assert-css: ("details.toggle > summary:hover::before", { "opacity": "1", "filter": |filter|, }) diff --git a/tests/rustdoc-gui/toggled-open-implementations.goml b/tests/rustdoc-gui/toggled-open-implementations.goml index e4d59b5d728..000293b555f 100644 --- a/tests/rustdoc-gui/toggled-open-implementations.goml +++ b/tests/rustdoc-gui/toggled-open-implementations.goml @@ -2,4 +2,4 @@ // has all the implementations toggled open by default, so users can // find method names in those implementations with Ctrl-F. goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html" -assert-attribute: (".rustdoc-toggle.implementors-toggle", {"open": ""}) +assert-attribute: (".toggle.implementors-toggle", {"open": ""}) diff --git a/tests/rustdoc-ui/invalid-syntax.stderr b/tests/rustdoc-ui/invalid-syntax.stderr index 597d19e748c..6140a06c555 100644 --- a/tests/rustdoc-ui/invalid-syntax.stderr +++ b/tests/rustdoc-ui/invalid-syntax.stderr @@ -77,8 +77,6 @@ LL | /// ``` | ^^^ | = note: error from rustc: unknown start of token: ` - = note: error from rustc: unknown start of token: ` - = note: error from rustc: unknown start of token: ` warning: could not parse code block as Rust code --> $DIR/invalid-syntax.rs:64:5 diff --git a/tests/rustdoc-ui/z-help.stdout b/tests/rustdoc-ui/z-help.stdout index 43f30f3d6e8..4bdecdc1b79 100644 --- a/tests/rustdoc-ui/z-help.stdout +++ b/tests/rustdoc-ui/z-help.stdout @@ -76,6 +76,7 @@ -Z llvm-plugins=val -- a list LLVM plugins to enable (space separated) -Z llvm-time-trace=val -- generate JSON tracing data file from LLVM data (default: no) -Z location-detail=val -- what location details should be tracked when using caller_location, either `none`, or a comma separated list of location details, for which valid options are `file`, `line`, and `column` (default: `file,line,column`) + -Z log-backtrace=val -- add a backtrace along with logging -Z ls=val -- list the symbols defined by a library crate (default: no) -Z macro-backtrace=val -- show macro backtraces (default: no) -Z maximal-hir-to-mir-coverage=val -- save as much information as possible about the correspondence between MIR and HIR as source scopes (default: no) diff --git a/tests/rustdoc/index-page.rs b/tests/rustdoc/index-page.rs index 0c947ea2e28..fc755afda4a 100644 --- a/tests/rustdoc/index-page.rs +++ b/tests/rustdoc/index-page.rs @@ -5,7 +5,7 @@ #![crate_name = "foo"] // @has foo/../index.html -// @has - '//h1[@class="fqn"]' 'List of all crates' +// @has - '//h1' 'List of all crates' // @has - '//ul[@class="all-items"]//a[@href="foo/index.html"]' 'foo' // @has - '//ul[@class="all-items"]//a[@href="all_item_types/index.html"]' 'all_item_types' pub struct Foo; diff --git a/tests/rustdoc/issue-41783.rs b/tests/rustdoc/issue-41783.rs index 769f984a274..7578d49daa5 100644 --- a/tests/rustdoc/issue-41783.rs +++ b/tests/rustdoc/issue-41783.rs @@ -5,7 +5,7 @@ // @!hasraw - '<span class="attr">#[outer]</span>' // @hasraw - '#![inner]</span>' // @!hasraw - '<span class="attr">#![inner]</span>' -// @snapshot 'codeblock' - '//*[@class="rustdoc-toggle top-doc"]/*[@class="docblock"]//pre/code' +// @snapshot 'codeblock' - '//*[@class="toggle top-doc"]/*[@class="docblock"]//pre/code' /// ```no_run /// # # space diff --git a/tests/rustdoc/keyword.rs b/tests/rustdoc/keyword.rs index ea127385091..4d047af3255 100644 --- a/tests/rustdoc/keyword.rs +++ b/tests/rustdoc/keyword.rs @@ -7,7 +7,7 @@ // @has foo/index.html '//div[@class="sidebar-elems"]//li/a' 'Keywords' // @has foo/index.html '//div[@class="sidebar-elems"]//li/a/@href' '#keywords' // @has foo/keyword.match.html '//a[@class="keyword"]' 'match' -// @has foo/keyword.match.html '//h1[@class="fqn"]' 'Keyword match' +// @has foo/keyword.match.html '//h1' 'Keyword match' // @has foo/keyword.match.html '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!' // @has foo/index.html '//a/@href' '../foo/index.html' // @!has foo/foo/index.html diff --git a/tests/rustdoc/local-reexport-doc.rs b/tests/rustdoc/local-reexport-doc.rs index 1c8468008dd..5dc857773a3 100644 --- a/tests/rustdoc/local-reexport-doc.rs +++ b/tests/rustdoc/local-reexport-doc.rs @@ -4,7 +4,7 @@ #![crate_name = "foo"] // @has 'foo/fn.g.html' -// @has - '//*[@class="rustdoc-toggle top-doc"]/*[@class="docblock"]' \ +// @has - '//*[@class="toggle top-doc"]/*[@class="docblock"]' \ // 'outer module inner module' mod inner_mod { diff --git a/tests/rustdoc/mixing-doc-comments-and-attrs.rs b/tests/rustdoc/mixing-doc-comments-and-attrs.rs index a27c5ae6d01..010058361fa 100644 --- a/tests/rustdoc/mixing-doc-comments-and-attrs.rs +++ b/tests/rustdoc/mixing-doc-comments-and-attrs.rs @@ -1,7 +1,7 @@ #![crate_name = "foo"] // @has 'foo/struct.S1.html' -// @snapshot S1_top-doc - '//details[@class="rustdoc-toggle top-doc"]/div[@class="docblock"]' +// @snapshot S1_top-doc - '//details[@class="toggle top-doc"]/div[@class="docblock"]' #[doc = "Hello world!\n\n"] /// Goodbye! @@ -9,7 +9,7 @@ pub struct S1; // @has 'foo/struct.S2.html' -// @snapshot S2_top-doc - '//details[@class="rustdoc-toggle top-doc"]/div[@class="docblock"]' +// @snapshot S2_top-doc - '//details[@class="toggle top-doc"]/div[@class="docblock"]' /// Hello world! /// @@ -18,7 +18,7 @@ pub struct S1; pub struct S2; // @has 'foo/struct.S3.html' -// @snapshot S3_top-doc - '//details[@class="rustdoc-toggle top-doc"]/div[@class="docblock"]' +// @snapshot S3_top-doc - '//details[@class="toggle top-doc"]/div[@class="docblock"]' /** Par 1 */ /// /// Par 2 diff --git a/tests/rustdoc/multiple-import-levels.rs b/tests/rustdoc/multiple-import-levels.rs index 1daae49cde9..29b67c6b2b1 100644 --- a/tests/rustdoc/multiple-import-levels.rs +++ b/tests/rustdoc/multiple-import-levels.rs @@ -21,14 +21,14 @@ mod c { } // @has 'foo/struct.Type.html' -// @has - '//*[@class="rustdoc-toggle top-doc"]/*[@class="docblock"]' 'foo 2 1' +// @has - '//*[@class="toggle top-doc"]/*[@class="docblock"]' 'foo 2 1' /// foo pub use b::Type; // @has 'foo/struct.Whatever.html' -// @has - '//*[@class="rustdoc-toggle top-doc"]/*[@class="docblock"]' 'whatever 3 2 1' +// @has - '//*[@class="toggle top-doc"]/*[@class="docblock"]' 'whatever 3 2 1' /// whatever pub use c::Type as Whatever; // @has 'foo/struct.Woof.html' -// @has - '//*[@class="rustdoc-toggle top-doc"]/*[@class="docblock"]' 'a dog 4 2 1' +// @has - '//*[@class="toggle top-doc"]/*[@class="docblock"]' 'a dog 4 2 1' /// a dog pub use c::Woof; diff --git a/tests/rustdoc/primitive-reference.rs b/tests/rustdoc/primitive-reference.rs index ea8d2d16602..c3a5eb6d324 100644 --- a/tests/rustdoc/primitive-reference.rs +++ b/tests/rustdoc/primitive-reference.rs @@ -9,7 +9,7 @@ // @has - '//div[@class="sidebar-elems"]//li/a/@href' '#primitives' // @has foo/primitive.reference.html // @has - '//a[@class="primitive"]' 'reference' -// @has - '//h1[@class="fqn"]' 'Primitive Type reference' +// @has - '//h1' 'Primitive Type reference' // @has - '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!' // There should be only one implementation listed. diff --git a/tests/rustdoc/primitive-slice-auto-trait.rs b/tests/rustdoc/primitive-slice-auto-trait.rs index cdddd6b6507..77922414676 100644 --- a/tests/rustdoc/primitive-slice-auto-trait.rs +++ b/tests/rustdoc/primitive-slice-auto-trait.rs @@ -4,7 +4,7 @@ #![feature(rustdoc_internals)] // @has foo/primitive.slice.html '//a[@class="primitive"]' 'slice' -// @has - '//h1[@class="fqn"]' 'Primitive Type slice' +// @has - '//h1' 'Primitive Type slice' // @has - '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!' // @has - '//h2[@id="synthetic-implementations"]' 'Auto Trait Implementations' // @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl<T> Send for [T]where T: Send' diff --git a/tests/rustdoc/primitive-tuple-auto-trait.rs b/tests/rustdoc/primitive-tuple-auto-trait.rs index df681457f0f..4344d24f986 100644 --- a/tests/rustdoc/primitive-tuple-auto-trait.rs +++ b/tests/rustdoc/primitive-tuple-auto-trait.rs @@ -4,7 +4,7 @@ #![feature(rustdoc_internals)] // @has foo/primitive.tuple.html '//a[@class="primitive"]' 'tuple' -// @has - '//h1[@class="fqn"]' 'Primitive Type tuple' +// @has - '//h1' 'Primitive Type tuple' // @has - '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!' // @has - '//h2[@id="synthetic-implementations"]' 'Auto Trait Implementations' // @has - '//div[@id="synthetic-implementations-list"]//h3' 'Send' diff --git a/tests/rustdoc/primitive-unit-auto-trait.rs b/tests/rustdoc/primitive-unit-auto-trait.rs index 391e33bea61..61850e2462d 100644 --- a/tests/rustdoc/primitive-unit-auto-trait.rs +++ b/tests/rustdoc/primitive-unit-auto-trait.rs @@ -4,7 +4,7 @@ #![feature(rustdoc_internals)] // @has foo/primitive.unit.html '//a[@class="primitive"]' 'unit' -// @has - '//h1[@class="fqn"]' 'Primitive Type unit' +// @has - '//h1' 'Primitive Type unit' // @has - '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!' // @has - '//h2[@id="synthetic-implementations"]' 'Auto Trait Implementations' // @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl Send for ()' diff --git a/tests/rustdoc/primitive.rs b/tests/rustdoc/primitive.rs index 6347fdac3db..516c7c0c6fe 100644 --- a/tests/rustdoc/primitive.rs +++ b/tests/rustdoc/primitive.rs @@ -7,7 +7,7 @@ // @has foo/index.html '//div[@class="sidebar-elems"]//li/a' 'Primitive Types' // @has foo/index.html '//div[@class="sidebar-elems"]//li/a/@href' '#primitives' // @has foo/primitive.i32.html '//a[@class="primitive"]' 'i32' -// @has foo/primitive.i32.html '//h1[@class="fqn"]' 'Primitive Type i32' +// @has foo/primitive.i32.html '//h1' 'Primitive Type i32' // @has foo/primitive.i32.html '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!' // @has foo/index.html '//a/@href' '../foo/index.html' // @!has foo/index.html '//span' '🔒' diff --git a/tests/rustdoc/strip-block-doc-comments-stars.rs b/tests/rustdoc/strip-block-doc-comments-stars.rs index ea28d84f1ff..ca4c93f92e0 100644 --- a/tests/rustdoc/strip-block-doc-comments-stars.rs +++ b/tests/rustdoc/strip-block-doc-comments-stars.rs @@ -4,7 +4,7 @@ // block doc comments can have their lines starting with a star. // @has foo/fn.foo.html -// @snapshot docblock - '//*[@class="rustdoc-toggle top-doc"]//*[@class="docblock"]' +// @snapshot docblock - '//*[@class="toggle top-doc"]//*[@class="docblock"]' /** * a */ diff --git a/tests/rustdoc/toggle-item-contents.rs b/tests/rustdoc/toggle-item-contents.rs index 47a1d62f5a7..87240f233ff 100644 --- a/tests/rustdoc/toggle-item-contents.rs +++ b/tests/rustdoc/toggle-item-contents.rs @@ -1,15 +1,15 @@ #![allow(unused)] // @has 'toggle_item_contents/struct.PubStruct.html' -// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 0 +// @count - '//details[@class="toggle type-contents-toggle"]' 0 pub struct PubStruct { pub a: usize, pub b: usize, } // @has 'toggle_item_contents/struct.BigPubStruct.html' -// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1 -// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 13 fields' +// @count - '//details[@class="toggle type-contents-toggle"]' 1 +// @has - '//details[@class="toggle type-contents-toggle"]' 'Show 13 fields' pub struct BigPubStruct { pub a: usize, pub b: usize, @@ -27,8 +27,8 @@ pub struct BigPubStruct { } // @has 'toggle_item_contents/union.BigUnion.html' -// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1 -// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 13 fields' +// @count - '//details[@class="toggle type-contents-toggle"]' 1 +// @has - '//details[@class="toggle type-contents-toggle"]' 'Show 13 fields' pub union BigUnion { pub a: usize, pub b: usize, @@ -46,7 +46,7 @@ pub union BigUnion { } // @has 'toggle_item_contents/union.Union.html' -// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 0 +// @count - '//details[@class="toggle type-contents-toggle"]' 0 pub union Union { pub a: usize, pub b: usize, @@ -54,7 +54,7 @@ pub union Union { } // @has 'toggle_item_contents/struct.PrivStruct.html' -// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 0 +// @count - '//details[@class="toggle type-contents-toggle"]' 0 // @has - '//div[@class="item-decl"]' '/* private fields */' pub struct PrivStruct { a: usize, @@ -62,7 +62,7 @@ pub struct PrivStruct { } // @has 'toggle_item_contents/enum.Enum.html' -// @!has - '//details[@class="rustdoc-toggle type-contents-toggle"]' '' +// @!has - '//details[@class="toggle type-contents-toggle"]' '' pub enum Enum { A, B, C, D { @@ -72,7 +72,7 @@ pub enum Enum { } // @has 'toggle_item_contents/enum.EnumStructVariant.html' -// @!has - '//details[@class="rustdoc-toggle type-contents-toggle"]' '' +// @!has - '//details[@class="toggle type-contents-toggle"]' '' pub enum EnumStructVariant { A, B, C, D { @@ -81,14 +81,14 @@ pub enum EnumStructVariant { } // @has 'toggle_item_contents/enum.LargeEnum.html' -// @count - '//*[@class="rust enum"]//details[@class="rustdoc-toggle type-contents-toggle"]' 1 -// @has - '//*[@class="rust enum"]//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 13 variants' +// @count - '//*[@class="rust enum"]//details[@class="toggle type-contents-toggle"]' 1 +// @has - '//*[@class="rust enum"]//details[@class="toggle type-contents-toggle"]' 'Show 13 variants' pub enum LargeEnum { A, B, C, D, E, F(u8), G, H, I, J, K, L, M } // @has 'toggle_item_contents/trait.Trait.html' -// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 0 +// @count - '//details[@class="toggle type-contents-toggle"]' 0 pub trait Trait { type A; #[must_use] @@ -97,8 +97,8 @@ pub trait Trait { } // @has 'toggle_item_contents/trait.GinormousTrait.html' -// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1 -// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 16 associated items' +// @count - '//details[@class="toggle type-contents-toggle"]' 1 +// @has - '//details[@class="toggle type-contents-toggle"]' 'Show 16 associated items' pub trait GinormousTrait { type A; type B; @@ -120,8 +120,8 @@ pub trait GinormousTrait { } // @has 'toggle_item_contents/trait.HugeTrait.html' -// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1 -// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 12 associated constants and 2 methods' +// @count - '//details[@class="toggle type-contents-toggle"]' 1 +// @has - '//details[@class="toggle type-contents-toggle"]' 'Show 12 associated constants and 2 methods' pub trait HugeTrait { type A; const M: usize = 1; @@ -142,8 +142,8 @@ pub trait HugeTrait { } // @has 'toggle_item_contents/trait.GiganticTrait.html' -// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1 -// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 1 associated constant and 1 method' +// @count - '//details[@class="toggle type-contents-toggle"]' 1 +// @has - '//details[@class="toggle type-contents-toggle"]' 'Show 1 associated constant and 1 method' pub trait GiganticTrait { type A; type B; @@ -163,8 +163,8 @@ pub trait GiganticTrait { } // @has 'toggle_item_contents/trait.BigTrait.html' -// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1 -// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 14 methods' +// @count - '//details[@class="toggle type-contents-toggle"]' 1 +// @has - '//details[@class="toggle type-contents-toggle"]' 'Show 14 methods' pub trait BigTrait { type A; #[must_use] diff --git a/tests/rustdoc/toggle-method.rs b/tests/rustdoc/toggle-method.rs index 1aa74e59659..ebc316ca8ad 100644 --- a/tests/rustdoc/toggle-method.rs +++ b/tests/rustdoc/toggle-method.rs @@ -4,9 +4,9 @@ // summary. Struct methods with no documentation should not be wrapped. // // @has foo/struct.Foo.html -// @has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'is_documented()' -// @has - '//details[@class="rustdoc-toggle method-toggle"]//*[@class="docblock"]' 'is_documented is documented' -// @!has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'not_documented()' +// @has - '//details[@class="toggle method-toggle"]//summary//h4[@class="code-header"]' 'is_documented()' +// @has - '//details[@class="toggle method-toggle"]//*[@class="docblock"]' 'is_documented is documented' +// @!has - '//details[@class="toggle method-toggle"]//summary//h4[@class="code-header"]' 'not_documented()' pub struct Foo { } diff --git a/tests/rustdoc/toggle-trait-fn.rs b/tests/rustdoc/toggle-trait-fn.rs index 0a1f088b9ab..686a174fc8f 100644 --- a/tests/rustdoc/toggle-trait-fn.rs +++ b/tests/rustdoc/toggle-trait-fn.rs @@ -4,14 +4,14 @@ // summary. Trait methods with no documentation should not be wrapped. // // @has foo/trait.Foo.html -// @has - '//details[@class="rustdoc-toggle"]//summary//h4[@class="code-header"]' 'type Item' -// @!has - '//details[@class="rustdoc-toggle"]//summary//h4[@class="code-header"]' 'type Item2' -// @has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'is_documented()' -// @!has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'not_documented()' -// @has - '//details[@class="rustdoc-toggle method-toggle"]//*[@class="docblock"]' 'is_documented is documented' -// @has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'is_documented_optional()' -// @!has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'not_documented_optional()' -// @has - '//details[@class="rustdoc-toggle method-toggle"]//*[@class="docblock"]' 'is_documented_optional is documented' +// @has - '//details[@class="toggle"]//summary//h4[@class="code-header"]' 'type Item' +// @!has - '//details[@class="toggle"]//summary//h4[@class="code-header"]' 'type Item2' +// @has - '//details[@class="toggle method-toggle"]//summary//h4[@class="code-header"]' 'is_documented()' +// @!has - '//details[@class="toggle method-toggle"]//summary//h4[@class="code-header"]' 'not_documented()' +// @has - '//details[@class="toggle method-toggle"]//*[@class="docblock"]' 'is_documented is documented' +// @has - '//details[@class="toggle method-toggle"]//summary//h4[@class="code-header"]' 'is_documented_optional()' +// @!has - '//details[@class="toggle method-toggle"]//summary//h4[@class="code-header"]' 'not_documented_optional()' +// @has - '//details[@class="toggle method-toggle"]//*[@class="docblock"]' 'is_documented_optional is documented' pub trait Foo { /// is documented type Item; diff --git a/tests/ui/associated-item/ambiguous-associated-type-with-generics.fixed b/tests/ui/associated-item/ambiguous-associated-type-with-generics.fixed new file mode 100644 index 00000000000..23f71520040 --- /dev/null +++ b/tests/ui/associated-item/ambiguous-associated-type-with-generics.fixed @@ -0,0 +1,14 @@ +// run-rustfix +trait Trait<A> {} + +trait Assoc { + type Ty; +} + +impl<A> Assoc for dyn Trait<A> { + type Ty = i32; +} + +fn main() { + let _x: <dyn Trait<i32> as Assoc>::Ty; //~ ERROR ambiguous associated type +} diff --git a/tests/ui/associated-item/ambiguous-associated-type-with-generics.rs b/tests/ui/associated-item/ambiguous-associated-type-with-generics.rs new file mode 100644 index 00000000000..9c26e339a44 --- /dev/null +++ b/tests/ui/associated-item/ambiguous-associated-type-with-generics.rs @@ -0,0 +1,14 @@ +// run-rustfix +trait Trait<A> {} + +trait Assoc { + type Ty; +} + +impl<A> Assoc for dyn Trait<A> { + type Ty = i32; +} + +fn main() { + let _x: <dyn Trait<i32>>::Ty; //~ ERROR ambiguous associated type +} diff --git a/tests/ui/associated-item/ambiguous-associated-type-with-generics.stderr b/tests/ui/associated-item/ambiguous-associated-type-with-generics.stderr new file mode 100644 index 00000000000..97088b79fd6 --- /dev/null +++ b/tests/ui/associated-item/ambiguous-associated-type-with-generics.stderr @@ -0,0 +1,9 @@ +error[E0223]: ambiguous associated type + --> $DIR/ambiguous-associated-type-with-generics.rs:13:13 + | +LL | let _x: <dyn Trait<i32>>::Ty; + | ^^^^^^^^^^^^^^^^^^^^ help: use the fully-qualified path: `<dyn Trait<i32> as Assoc>::Ty` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/associated-item/associated-item-duplicate-names-3.stderr b/tests/ui/associated-item/associated-item-duplicate-names-3.stderr index bf4bd634cf1..d0c17062076 100644 --- a/tests/ui/associated-item/associated-item-duplicate-names-3.stderr +++ b/tests/ui/associated-item/associated-item-duplicate-names-3.stderr @@ -13,7 +13,7 @@ error[E0223]: ambiguous associated type --> $DIR/associated-item-duplicate-names-3.rs:18:12 | LL | let x: Baz::Bar = 5; - | ^^^^^^^^ help: use fully-qualified syntax: `<Baz as Trait>::Bar` + | ^^^^^^^^ help: use the fully-qualified path: `<Baz as Foo>::Bar` error: aborting due to 2 previous errors diff --git a/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr b/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr index 289911779ff..00856b55df5 100644 --- a/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr +++ b/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr @@ -2,31 +2,46 @@ error[E0223]: ambiguous associated type --> $DIR/associated-types-in-ambiguous-context.rs:6:36 | LL | fn get<T:Get,U:Get>(x: T, y: U) -> Get::Value {} - | ^^^^^^^^^^ help: use fully-qualified syntax: `<Type as Get>::Value` + | ^^^^^^^^^^ + | +help: if there were a type named `Example` that implemented `Get`, you could use the fully-qualified path + | +LL | fn get<T:Get,U:Get>(x: T, y: U) -> <Example as Get>::Value {} + | ~~~~~~~~~~~~~~~~~~~~~~~ error[E0223]: ambiguous associated type --> $DIR/associated-types-in-ambiguous-context.rs:20:17 | LL | trait Foo where Foo::Assoc: Bar { - | ^^^^^^^^^^ help: use fully-qualified syntax: `<Self as Foo>::Assoc` + | ^^^^^^^^^^ help: use the fully-qualified path: `<Self as Foo>::Assoc` error[E0223]: ambiguous associated type --> $DIR/associated-types-in-ambiguous-context.rs:25:10 | LL | type X = std::ops::Deref::Target; - | ^^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<Type as Deref>::Target` + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: if there were a type named `Example` that implemented `Deref`, you could use the fully-qualified path + | +LL | type X = <Example as Deref>::Target; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ error[E0223]: ambiguous associated type --> $DIR/associated-types-in-ambiguous-context.rs:11:23 | LL | fn grab(&self) -> Grab::Value; - | ^^^^^^^^^^^ help: use fully-qualified syntax: `<Self as Grab>::Value` + | ^^^^^^^^^^^ help: use the fully-qualified path: `<Self as Grab>::Value` error[E0223]: ambiguous associated type --> $DIR/associated-types-in-ambiguous-context.rs:14:22 | LL | fn get(&self) -> Get::Value; - | ^^^^^^^^^^ help: use fully-qualified syntax: `<Type as Get>::Value` + | ^^^^^^^^^^ + | +help: if there were a type named `Example` that implemented `Get`, you could use the fully-qualified path + | +LL | fn get(&self) -> <Example as Get>::Value; + | ~~~~~~~~~~~~~~~~~~~~~~~ error: aborting due to 5 previous errors diff --git a/tests/ui/attributes/log-backtrace.rs b/tests/ui/attributes/log-backtrace.rs new file mode 100644 index 00000000000..3979d2001fc --- /dev/null +++ b/tests/ui/attributes/log-backtrace.rs @@ -0,0 +1,9 @@ +// run-pass +// +// This test makes sure that log-backtrace option doesn't give a compilation error. +// +// dont-check-compiler-stdout +// dont-check-compiler-stderr +// rustc-env:RUSTC_LOG=info +// compile-flags: -Zlog-backtrace=rustc_metadata::creader +fn main() {} diff --git a/tests/ui/chalkify/bugs/async.rs b/tests/ui/chalkify/bugs/async.rs index 86ce42631b4..1c69b07e3d4 100644 --- a/tests/ui/chalkify/bugs/async.rs +++ b/tests/ui/chalkify/bugs/async.rs @@ -2,12 +2,21 @@ // known-bug // unset-rustc-env:RUST_BACKTRACE // compile-flags:-Z trait-solver=chalk --edition=2021 -// error-pattern:stack backtrace: +// error-pattern:internal compiler error // failure-status:101 -// normalize-stderr-test "note: .*" -> "" -// normalize-stderr-test "thread 'rustc' .*" -> "" -// normalize-stderr-test " .*\n" -> "" // normalize-stderr-test "DefId([^)]*)" -> "..." +// normalize-stderr-test "\nerror: internal compiler error.*\n\n" -> "" +// normalize-stderr-test "note:.*unexpectedly panicked.*\n\n" -> "" +// normalize-stderr-test "note: we would appreciate a bug report.*\n\n" -> "" +// normalize-stderr-test "note: compiler flags.*\n\n" -> "" +// normalize-stderr-test "note: rustc.*running on.*\n\n" -> "" +// normalize-stderr-test "thread.*panicked.*\n" -> "" +// normalize-stderr-test "stack backtrace:\n" -> "" +// normalize-stderr-test "\s\d{1,}: .*\n" -> "" +// normalize-stderr-test "\s at .*\n" -> "" +// normalize-stderr-test ".*note: Some details.*\n" -> "" +// normalize-stderr-test "\n\n[ ]*\n" -> "" +// normalize-stderr-test "compiler/.*: projection" -> "projection" fn main() -> () {} diff --git a/tests/ui/chalkify/bugs/async.stderr b/tests/ui/chalkify/bugs/async.stderr index 7e2466dece4..d1508cb1700 100644 --- a/tests/ui/chalkify/bugs/async.stderr +++ b/tests/ui/chalkify/bugs/async.stderr @@ -1,29 +1,47 @@ -error[E0277]: `[async fn body@$DIR/async.rs:14:29: 16:2]` is not a future -LL |LL | |LL | | } - - -error[E0277]: the size for values of type `<[async fn body@$DIR/async.rs:14:29: 16:2] as Future>::Output` cannot be known at compilation time -LL |LL | |LL | | } - - -error[E0277]: `[async fn body@$DIR/async.rs:14:29: 16:2]` is not a future +error[E0277]: `[async fn body@$DIR/async.rs:23:29: 25:2]` is not a future + --> $DIR/async.rs:23:29 + | +LL | async fn foo(x: u32) -> u32 { + | _____________________________- +LL | | x +LL | | } + | | ^ + | | | + | |_`[async fn body@$DIR/async.rs:23:29: 25:2]` is not a future + | required by a bound introduced by this call + | + = help: the trait `Future` is not implemented for `[async fn body@$DIR/async.rs:23:29: 25:2]` + = note: [async fn body@$DIR/async.rs:23:29: 25:2] must be a future or must implement `IntoFuture` to be awaited +note: required by a bound in `identity_future` + --> $SRC_DIR/core/src/future/mod.rs:LL:COL + +error[E0277]: the size for values of type `<[async fn body@$DIR/async.rs:23:29: 25:2] as Future>::Output` cannot be known at compilation time + --> $DIR/async.rs:23:29 + | +LL | async fn foo(x: u32) -> u32 { + | _____________________________^ +LL | | x +LL | | } + | |_^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `<[async fn body@$DIR/async.rs:23:29: 25:2] as Future>::Output` +note: required by a bound in `identity_future` + --> $SRC_DIR/core/src/future/mod.rs:LL:COL + +error[E0277]: `[async fn body@$DIR/async.rs:23:29: 25:2]` is not a future + --> $DIR/async.rs:23:25 + | LL | async fn foo(x: u32) -> u32 { - -error: internal compiler error: compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs:1114:25: projection clauses should be implied from elsewhere. obligation: `Obligation(predicate=Binder(ProjectionPredicate(AliasTy { substs: [[async fn body@$DIR/async.rs:14:29: 16:2]], def_id: ...), _use_mk_alias_ty_instead: () }, Term::Ty(u32)), []), depth=0)` + | ^^^ `[async fn body@$DIR/async.rs:23:29: 25:2]` is not a future + | + = help: the trait `Future` is not implemented for `[async fn body@$DIR/async.rs:23:29: 25:2]` + = note: [async fn body@$DIR/async.rs:23:29: 25:2] must be a future or must implement `IntoFuture` to be awaited + +error: internal compiler error: projection clauses should be implied from elsewhere. obligation: `Obligation(predicate=Binder(ProjectionPredicate(AliasTy { substs: [[async fn body@$DIR/async.rs:23:29: 25:2]], def_id: ...), _use_mk_alias_ty_instead: () }, Term::Ty(u32)), []), depth=0)` + --> $DIR/async.rs:23:25 + | LL | async fn foo(x: u32) -> u32 { - - -stack backtrace: - - - - - - - - - -query stack during panic: + | ^^^query stack during panic: #0 [typeck] type-checking `foo` #1 [thir_body] building THIR for `foo` #2 [mir_built] building MIR for `foo` diff --git a/tests/ui/closures/issue-84128.stderr b/tests/ui/closures/issue-84128.stderr index 59607afec8f..1cd8949b8c4 100644 --- a/tests/ui/closures/issue-84128.stderr +++ b/tests/ui/closures/issue-84128.stderr @@ -6,6 +6,13 @@ LL | Foo(()) | | | arguments to this struct are incorrect | +help: the type constructed contains `()` due to the type of the argument passed + --> $DIR/issue-84128.rs:13:9 + | +LL | Foo(()) + | ^^^^--^ + | | + | this argument influences the type of `Foo` note: tuple struct defined here --> $DIR/issue-84128.rs:5:8 | diff --git a/tests/ui/closures/issue-87461.stderr b/tests/ui/closures/issue-87461.stderr index 72337892734..b492251c016 100644 --- a/tests/ui/closures/issue-87461.stderr +++ b/tests/ui/closures/issue-87461.stderr @@ -6,6 +6,13 @@ LL | Ok(()) | | | arguments to this enum variant are incorrect | +help: the type constructed contains `()` due to the type of the argument passed + --> $DIR/issue-87461.rs:10:5 + | +LL | Ok(()) + | ^^^--^ + | | + | this argument influences the type of `Ok` note: tuple variant defined here --> $SRC_DIR/core/src/result.rs:LL:COL @@ -17,6 +24,13 @@ LL | Ok(()) | | | arguments to this enum variant are incorrect | +help: the type constructed contains `()` due to the type of the argument passed + --> $DIR/issue-87461.rs:17:5 + | +LL | Ok(()) + | ^^^--^ + | | + | this argument influences the type of `Ok` note: tuple variant defined here --> $SRC_DIR/core/src/result.rs:LL:COL @@ -28,6 +42,13 @@ LL | Ok(()) | | | arguments to this enum variant are incorrect | +help: the type constructed contains `()` due to the type of the argument passed + --> $DIR/issue-87461.rs:26:9 + | +LL | Ok(()) + | ^^^--^ + | | + | this argument influences the type of `Ok` note: tuple variant defined here --> $SRC_DIR/core/src/result.rs:LL:COL diff --git a/tests/ui/did_you_mean/bad-assoc-ty.stderr b/tests/ui/did_you_mean/bad-assoc-ty.stderr index 21f957ab549..55096e95df7 100644 --- a/tests/ui/did_you_mean/bad-assoc-ty.stderr +++ b/tests/ui/did_you_mean/bad-assoc-ty.stderr @@ -61,25 +61,45 @@ error[E0223]: ambiguous associated type --> $DIR/bad-assoc-ty.rs:1:10 | LL | type A = [u8; 4]::AssocTy; - | ^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<[u8; 4] as Trait>::AssocTy` + | ^^^^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `AssocTy` implemented for `[u8; 4]`, you could use the fully-qualified path + | +LL | type A = <[u8; 4] as Example>::AssocTy; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error[E0223]: ambiguous associated type --> $DIR/bad-assoc-ty.rs:5:10 | LL | type B = [u8]::AssocTy; - | ^^^^^^^^^^^^^ help: use fully-qualified syntax: `<[u8] as Trait>::AssocTy` + | ^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `AssocTy` implemented for `[u8]`, you could use the fully-qualified path + | +LL | type B = <[u8] as Example>::AssocTy; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ error[E0223]: ambiguous associated type --> $DIR/bad-assoc-ty.rs:9:10 | LL | type C = (u8)::AssocTy; - | ^^^^^^^^^^^^^ help: use fully-qualified syntax: `<u8 as Trait>::AssocTy` + | ^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `AssocTy` implemented for `u8`, you could use the fully-qualified path + | +LL | type C = <u8 as Example>::AssocTy; + | ~~~~~~~~~~~~~~~~~~~~~~~~ error[E0223]: ambiguous associated type --> $DIR/bad-assoc-ty.rs:13:10 | LL | type D = (u8, u8)::AssocTy; - | ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<(u8, u8) as Trait>::AssocTy` + | ^^^^^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `AssocTy` implemented for `(u8, u8)`, you could use the fully-qualified path + | +LL | type D = <(u8, u8) as Example>::AssocTy; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error[E0121]: the placeholder `_` is not allowed within types on item signatures for type aliases --> $DIR/bad-assoc-ty.rs:17:10 @@ -91,13 +111,23 @@ error[E0223]: ambiguous associated type --> $DIR/bad-assoc-ty.rs:21:19 | LL | type F = &'static (u8)::AssocTy; - | ^^^^^^^^^^^^^ help: use fully-qualified syntax: `<u8 as Trait>::AssocTy` + | ^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `AssocTy` implemented for `u8`, you could use the fully-qualified path + | +LL | type F = &'static <u8 as Example>::AssocTy; + | ~~~~~~~~~~~~~~~~~~~~~~~~ error[E0223]: ambiguous associated type --> $DIR/bad-assoc-ty.rs:27:10 | LL | type G = dyn 'static + (Send)::AssocTy; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<(dyn Send + 'static) as Trait>::AssocTy` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `AssocTy` implemented for `(dyn Send + 'static)`, you could use the fully-qualified path + | +LL | type G = <(dyn Send + 'static) as Example>::AssocTy; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ warning: trait objects without an explicit `dyn` are deprecated --> $DIR/bad-assoc-ty.rs:33:10 @@ -117,24 +147,33 @@ error[E0223]: ambiguous associated type --> $DIR/bad-assoc-ty.rs:33:10 | LL | type H = Fn(u8) -> (u8)::Output; - | ^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<(dyn Fn(u8) -> u8 + 'static) as Trait>::Output` + | ^^^^^^^^^^^^^^^^^^^^^^ help: use the fully-qualified path: `<(dyn Fn(u8) -> u8 + 'static) as IntoFuture>::Output` error[E0223]: ambiguous associated type --> $DIR/bad-assoc-ty.rs:39:19 | LL | ($ty: ty) => ($ty::AssocTy); - | ^^^^^^^^^^^^ help: use fully-qualified syntax: `<u8 as Trait>::AssocTy` + | ^^^^^^^^^^^^ ... LL | type J = ty!(u8); | ------- in this macro invocation | = note: this error originates in the macro `ty` (in Nightly builds, run with -Z macro-backtrace for more info) +help: if there were a trait named `Example` with associated type `AssocTy` implemented for `u8`, you could use the fully-qualified path + | +LL | ($ty: ty) => (<u8 as Example>::AssocTy); + | ~~~~~~~~~~~~~~~~~~~~~~~~ error[E0223]: ambiguous associated type --> $DIR/bad-assoc-ty.rs:46:10 | LL | type I = ty!()::AssocTy; - | ^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<u8 as Trait>::AssocTy` + | ^^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `AssocTy` implemented for `u8`, you could use the fully-qualified path + | +LL | type I = <u8 as Example>::AssocTy; + | ~~~~~~~~~~~~~~~~~~~~~~~~ error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/bad-assoc-ty.rs:51:13 diff --git a/tests/ui/error-codes/E0223.rs b/tests/ui/error-codes/E0223.rs index 6031b682d72..2fe252de256 100644 --- a/tests/ui/error-codes/E0223.rs +++ b/tests/ui/error-codes/E0223.rs @@ -1,4 +1,8 @@ trait MyTrait { type X; } +struct MyStruct; +impl MyTrait for MyStruct { + type X = (); +} fn main() { let foo: MyTrait::X; diff --git a/tests/ui/error-codes/E0223.stderr b/tests/ui/error-codes/E0223.stderr index 726f39e11f1..42945e42f6e 100644 --- a/tests/ui/error-codes/E0223.stderr +++ b/tests/ui/error-codes/E0223.stderr @@ -1,8 +1,8 @@ error[E0223]: ambiguous associated type - --> $DIR/E0223.rs:4:14 + --> $DIR/E0223.rs:8:14 | LL | let foo: MyTrait::X; - | ^^^^^^^^^^ help: use fully-qualified syntax: `<Type as MyTrait>::X` + | ^^^^^^^^^^ help: use the fully-qualified path: `<MyStruct as MyTrait>::X` error: aborting due to previous error diff --git a/tests/ui/generic-associated-types/missing-bounds.stderr b/tests/ui/generic-associated-types/missing-bounds.stderr index c913483a874..9f669b9a521 100644 --- a/tests/ui/generic-associated-types/missing-bounds.stderr +++ b/tests/ui/generic-associated-types/missing-bounds.stderr @@ -23,6 +23,13 @@ LL | A(self.0 + rhs.0) | = note: expected type parameter `B` found associated type `<B as Add>::Output` +help: the type constructed contains `<B as Add>::Output` due to the type of the argument passed + --> $DIR/missing-bounds.rs:11:9 + | +LL | A(self.0 + rhs.0) + | ^^--------------^ + | | + | this argument influences the type of `A` note: tuple struct defined here --> $DIR/missing-bounds.rs:5:8 | diff --git a/tests/ui/impl-trait/impl_trait_projections.rs b/tests/ui/impl-trait/impl_trait_projections.rs index fd0986d7c0a..b3ff2ce5a7b 100644 --- a/tests/ui/impl-trait/impl_trait_projections.rs +++ b/tests/ui/impl-trait/impl_trait_projections.rs @@ -11,7 +11,7 @@ fn path_parametrized_type_is_allowed() -> option::Option<impl Debug> { fn projection_is_disallowed(x: impl Iterator) -> <impl Iterator>::Item { //~^ ERROR `impl Trait` is not allowed in path parameters -//~^^ ERROR ambiguous associated type +//~| ERROR `impl Trait` is not allowed in path parameters x.next().unwrap() } diff --git a/tests/ui/impl-trait/impl_trait_projections.stderr b/tests/ui/impl-trait/impl_trait_projections.stderr index 82d2422c407..4deb24731bc 100644 --- a/tests/ui/impl-trait/impl_trait_projections.stderr +++ b/tests/ui/impl-trait/impl_trait_projections.stderr @@ -22,13 +22,12 @@ error[E0667]: `impl Trait` is not allowed in path parameters LL | -> <dyn Iterator<Item = impl Debug> as Iterator>::Item | ^^^^^^^^^^ -error[E0223]: ambiguous associated type - --> $DIR/impl_trait_projections.rs:12:50 +error[E0667]: `impl Trait` is not allowed in path parameters + --> $DIR/impl_trait_projections.rs:12:51 | LL | fn projection_is_disallowed(x: impl Iterator) -> <impl Iterator>::Item { - | ^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<impl Iterator as Trait>::Item` + | ^^^^^^^^^^^^^ error: aborting due to 5 previous errors -Some errors have detailed explanations: E0223, E0667. -For more information about an error, try `rustc --explain E0223`. +For more information about this error, try `rustc --explain E0667`. diff --git a/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr b/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr index 0ac31c642eb..ebe07027d2f 100644 --- a/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr +++ b/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr @@ -1,8 +1,8 @@ error: impl method assumes more implied bounds than the corresponding trait method - --> $DIR/impl-implied-bounds-compatibility-unnormalized.rs:13:5 + --> $DIR/impl-implied-bounds-compatibility-unnormalized.rs:13:31 | LL | fn get<'s>(s: &'s str, _: <&'static &'s () as Project>::Ty) -> &'static str { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace this type to make the impl signature compatible: `()` | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #105572 <https://github.com/rust-lang/rust/issues/105572> @@ -14,3 +14,18 @@ LL | #![deny(implied_bounds_entailment)] error: aborting due to previous error +Future incompatibility report: Future breakage diagnostic: +error: impl method assumes more implied bounds than the corresponding trait method + --> $DIR/impl-implied-bounds-compatibility-unnormalized.rs:13:31 + | +LL | fn get<'s>(s: &'s str, _: <&'static &'s () as Project>::Ty) -> &'static str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace this type to make the impl signature compatible: `()` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #105572 <https://github.com/rust-lang/rust/issues/105572> +note: the lint level is defined here + --> $DIR/impl-implied-bounds-compatibility-unnormalized.rs:1:9 + | +LL | #![deny(implied_bounds_entailment)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/implied-bounds/impl-implied-bounds-compatibility.stderr b/tests/ui/implied-bounds/impl-implied-bounds-compatibility.stderr index 0dfa8167a99..43d3e058ffe 100644 --- a/tests/ui/implied-bounds/impl-implied-bounds-compatibility.stderr +++ b/tests/ui/implied-bounds/impl-implied-bounds-compatibility.stderr @@ -1,8 +1,8 @@ error: impl method assumes more implied bounds than the corresponding trait method - --> $DIR/impl-implied-bounds-compatibility.rs:14:5 + --> $DIR/impl-implied-bounds-compatibility.rs:14:35 | LL | fn listeners<'b>(&'b self) -> &'a MessageListeners<'b> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace this type to make the impl signature compatible: `&'b MessageListeners<'b>` | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #105572 <https://github.com/rust-lang/rust/issues/105572> @@ -14,3 +14,18 @@ LL | #![deny(implied_bounds_entailment)] error: aborting due to previous error +Future incompatibility report: Future breakage diagnostic: +error: impl method assumes more implied bounds than the corresponding trait method + --> $DIR/impl-implied-bounds-compatibility.rs:14:35 + | +LL | fn listeners<'b>(&'b self) -> &'a MessageListeners<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace this type to make the impl signature compatible: `&'b MessageListeners<'b>` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #105572 <https://github.com/rust-lang/rust/issues/105572> +note: the lint level is defined here + --> $DIR/impl-implied-bounds-compatibility.rs:1:9 + | +LL | #![deny(implied_bounds_entailment)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/issues/issue-23073.stderr b/tests/ui/issues/issue-23073.stderr index 3a10a1ab11a..3a9f49ef167 100644 --- a/tests/ui/issues/issue-23073.stderr +++ b/tests/ui/issues/issue-23073.stderr @@ -2,7 +2,12 @@ error[E0223]: ambiguous associated type --> $DIR/issue-23073.rs:6:17 | LL | type FooT = <<Self as Bar>::Foo>::T; - | ^^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<<Self as Bar>::Foo as Trait>::T` + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `T` implemented for `<Self as Bar>::Foo`, you could use the fully-qualified path + | +LL | type FooT = <<Self as Bar>::Foo as Example>::T; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: aborting due to previous error diff --git a/tests/ui/issues/issue-78622.stderr b/tests/ui/issues/issue-78622.stderr index f7d44f21d3b..70daf8a2f1a 100644 --- a/tests/ui/issues/issue-78622.stderr +++ b/tests/ui/issues/issue-78622.stderr @@ -2,7 +2,12 @@ error[E0223]: ambiguous associated type --> $DIR/issue-78622.rs:5:5 | LL | S::A::<f> {} - | ^^^^ help: use fully-qualified syntax: `<S as Trait>::A` + | ^^^^ + | +help: if there were a trait named `Example` with associated type `A` implemented for `S`, you could use the fully-qualified path + | +LL | <S as Example>::A::<f> {} + | ~~~~~~~~~~~~~~~~~ error: aborting due to previous error diff --git a/tests/ui/lint/bare-trait-objects-path.stderr b/tests/ui/lint/bare-trait-objects-path.stderr index 8ed303ca606..a19f4963c23 100644 --- a/tests/ui/lint/bare-trait-objects-path.stderr +++ b/tests/ui/lint/bare-trait-objects-path.stderr @@ -16,7 +16,7 @@ error[E0223]: ambiguous associated type --> $DIR/bare-trait-objects-path.rs:23:12 | LL | let _: Dyn::Ty; - | ^^^^^^^ help: use fully-qualified syntax: `<dyn Dyn as Trait>::Ty` + | ^^^^^^^ help: use the fully-qualified path: `<dyn Dyn as Assoc>::Ty` warning: trait objects without an explicit `dyn` are deprecated --> $DIR/bare-trait-objects-path.rs:14:5 diff --git a/tests/ui/mismatched_types/issue-35030.stderr b/tests/ui/mismatched_types/issue-35030.stderr index 680aff1726f..de4e067fead 100644 --- a/tests/ui/mismatched_types/issue-35030.stderr +++ b/tests/ui/mismatched_types/issue-35030.stderr @@ -11,6 +11,13 @@ LL | Some(true) | = note: expected type parameter `bool` (type parameter `bool`) found type `bool` (`bool`) +help: the type constructed contains `bool` due to the type of the argument passed + --> $DIR/issue-35030.rs:9:9 + | +LL | Some(true) + | ^^^^^----^ + | | + | this argument influences the type of `Some` note: tuple variant defined here --> $SRC_DIR/core/src/option.rs:LL:COL diff --git a/tests/ui/parser/issues/issue-66473.stderr b/tests/ui/parser/issues/issue-66473.stderr index 8a16d7f9551..0e8b0a5da22 100644 --- a/tests/ui/parser/issues/issue-66473.stderr +++ b/tests/ui/parser/issues/issue-66473.stderr Binary files differdiff --git a/tests/ui/parser/issues/issue-68629.stderr b/tests/ui/parser/issues/issue-68629.stderr index b2c7dddc801..43a903e6c46 100644 --- a/tests/ui/parser/issues/issue-68629.stderr +++ b/tests/ui/parser/issues/issue-68629.stderr Binary files differdiff --git a/tests/ui/parser/issues/issue-68730.stderr b/tests/ui/parser/issues/issue-68730.stderr index 6585a19d954..5bca5bbebea 100644 --- a/tests/ui/parser/issues/issue-68730.stderr +++ b/tests/ui/parser/issues/issue-68730.stderr Binary files differdiff --git a/tests/ui/parser/unicode-chars.rs b/tests/ui/parser/unicode-chars.rs index 89ae85ec990..ba35e95c82a 100644 --- a/tests/ui/parser/unicode-chars.rs +++ b/tests/ui/parser/unicode-chars.rs @@ -2,4 +2,8 @@ fn main() { let y = 0; //~^ ERROR unknown start of token: \u{37e} //~^^ HELP Unicode character ';' (Greek Question Mark) looks like ';' (Semicolon), but it is not +     let x = 0; + //~^ ERROR unknown start of token: \u{a0} + //~^^ NOTE character appears 3 more times + //~^^^ HELP Unicode character ' ' (No-Break Space) looks like ' ' (Space), but it is not } diff --git a/tests/ui/parser/unicode-chars.stderr b/tests/ui/parser/unicode-chars.stderr index 0cfe9240e85..6a5b27872e7 100644 --- a/tests/ui/parser/unicode-chars.stderr +++ b/tests/ui/parser/unicode-chars.stderr @@ -9,5 +9,17 @@ help: Unicode character ';' (Greek Question Mark) looks like ';' (Semicolon), b LL | let y = 0; | ~ -error: aborting due to previous error +error: unknown start of token: \u{a0} + --> $DIR/unicode-chars.rs:5:5 + | +LL |     let x = 0; + | ^^^^ + | + = note: character appears 3 more times +help: Unicode character ' ' (No-Break Space) looks like ' ' (Space), but it is not + | +LL | let x = 0; + | ++++ + +error: aborting due to 2 previous errors diff --git a/tests/ui/proc-macro/panic-abort.rs b/tests/ui/proc-macro/panic-abort.rs new file mode 100644 index 00000000000..ad312a875e3 --- /dev/null +++ b/tests/ui/proc-macro/panic-abort.rs @@ -0,0 +1,4 @@ +// error-pattern: building proc macro crate with `panic=abort` may crash the compiler should the proc-macro panic +// compile-flags: --crate-type proc-macro -Cpanic=abort +// force-host +// check-pass diff --git a/tests/ui/proc-macro/panic-abort.stderr b/tests/ui/proc-macro/panic-abort.stderr new file mode 100644 index 00000000000..a6e18614f8f --- /dev/null +++ b/tests/ui/proc-macro/panic-abort.stderr @@ -0,0 +1,4 @@ +warning: building proc macro crate with `panic=abort` may crash the compiler should the proc-macro panic + +warning: 1 warning emitted + diff --git a/tests/ui/proc-macro/pretty-print-hack-show.stderr b/tests/ui/proc-macro/pretty-print-hack-show.local.stderr index 873054927c9..873054927c9 100644 --- a/tests/ui/proc-macro/pretty-print-hack-show.stderr +++ b/tests/ui/proc-macro/pretty-print-hack-show.local.stderr diff --git a/tests/ui/proc-macro/pretty-print-hack-show.stdout b/tests/ui/proc-macro/pretty-print-hack-show.local.stdout index 3d793d2a014..3d793d2a014 100644 --- a/tests/ui/proc-macro/pretty-print-hack-show.stdout +++ b/tests/ui/proc-macro/pretty-print-hack-show.local.stdout diff --git a/tests/ui/proc-macro/pretty-print-hack-show.remapped.stderr b/tests/ui/proc-macro/pretty-print-hack-show.remapped.stderr new file mode 100644 index 00000000000..ab501384889 --- /dev/null +++ b/tests/ui/proc-macro/pretty-print-hack-show.remapped.stderr @@ -0,0 +1,179 @@ +error: using an old version of `rental` + --> remapped/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125> + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: `#[deny(proc_macro_back_compat)]` on by default + +error: using an old version of `rental` + --> remapped/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125> + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + +error: using an old version of `rental` + --> remapped/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125> + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + +error: using an old version of `rental` + --> remapped/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125> + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + +error: using an old version of `rental` + --> remapped/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125> + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + +error: using an old version of `rental` + --> remapped/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125> + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + +error: using an old version of `rental` + --> remapped/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125> + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + +error: using an old version of `rental` + --> remapped/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125> + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + +error: aborting due to 8 previous errors + +Future incompatibility report: Future breakage diagnostic: +error: using an old version of `rental` + --> remapped/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125> + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: `#[deny(proc_macro_back_compat)]` on by default + +Future breakage diagnostic: +error: using an old version of `rental` + --> remapped/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125> + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: `#[deny(proc_macro_back_compat)]` on by default + +Future breakage diagnostic: +error: using an old version of `rental` + --> remapped/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125> + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: `#[deny(proc_macro_back_compat)]` on by default + +Future breakage diagnostic: +error: using an old version of `rental` + --> remapped/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125> + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: `#[deny(proc_macro_back_compat)]` on by default + +Future breakage diagnostic: +error: using an old version of `rental` + --> remapped/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125> + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: `#[deny(proc_macro_back_compat)]` on by default + +Future breakage diagnostic: +error: using an old version of `rental` + --> remapped/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125> + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: `#[deny(proc_macro_back_compat)]` on by default + +Future breakage diagnostic: +error: using an old version of `rental` + --> remapped/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125> + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: `#[deny(proc_macro_back_compat)]` on by default + +Future breakage diagnostic: +error: using an old version of `rental` + --> remapped/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125> + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: `#[deny(proc_macro_back_compat)]` on by default + diff --git a/tests/ui/proc-macro/pretty-print-hack-show.remapped.stdout b/tests/ui/proc-macro/pretty-print-hack-show.remapped.stdout new file mode 100644 index 00000000000..61ca53b28d4 --- /dev/null +++ b/tests/ui/proc-macro/pretty-print-hack-show.remapped.stdout @@ -0,0 +1,44 @@ +PRINT-DERIVE INPUT (DISPLAY): enum ProceduralMasqueradeDummyType { Input, } +PRINT-DERIVE RE-COLLECTED (DISPLAY): enum ProceduralMasqueradeDummyType { Input } +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "enum", + span: remapped/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:1: 4:5 (#0), + }, + Ident { + ident: "ProceduralMasqueradeDummyType", + span: remapped/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6: 4:35 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "Input", + span: remapped/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:13:5: 13:10 (#0), + }, + ], + span: remapped/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:36: 14:2 (#0), + }, +] +PRINT-DERIVE INPUT (DISPLAY): enum ProceduralMasqueradeDummyType { Input, } +PRINT-DERIVE RE-COLLECTED (DISPLAY): enum ProceduralMasqueradeDummyType { Input } +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "enum", + span: remapped/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs:4:1: 4:5 (#0), + }, + Ident { + ident: "ProceduralMasqueradeDummyType", + span: remapped/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6: 4:35 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "Input", + span: remapped/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs:13:5: 13:10 (#0), + }, + ], + span: remapped/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs:4:36: 14:2 (#0), + }, +] diff --git a/tests/ui/proc-macro/pretty-print-hack-show.rs b/tests/ui/proc-macro/pretty-print-hack-show.rs index 9b1899e4922..e9ff66ba45a 100644 --- a/tests/ui/proc-macro/pretty-print-hack-show.rs +++ b/tests/ui/proc-macro/pretty-print-hack-show.rs @@ -1,5 +1,11 @@ // aux-build:test-macros.rs // compile-flags: -Z span-debug +// revisions: local remapped +// [remapped]compile-flags: --remap-path-prefix={{src-base}}=remapped + +// The remapped paths are not normalized by compiletest. +// normalize-stdout-test: "\\(proc-macro|pretty-print-hack)" -> "/$1" +// normalize-stderr-test: "\\(proc-macro|pretty-print-hack)" -> "/$1" #![no_std] // Don't load unnecessary hygiene information from std extern crate std; diff --git a/tests/ui/qualified/qualified-path-params-2.stderr b/tests/ui/qualified/qualified-path-params-2.stderr index 948f21fce4b..b6cf19b8286 100644 --- a/tests/ui/qualified/qualified-path-params-2.stderr +++ b/tests/ui/qualified/qualified-path-params-2.stderr @@ -2,7 +2,12 @@ error[E0223]: ambiguous associated type --> $DIR/qualified-path-params-2.rs:18:10 | LL | type A = <S as Tr>::A::f<u8>; - | ^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<<S as Tr>::A as Trait>::f` + | ^^^^^^^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `f` implemented for `<S as Tr>::A`, you could use the fully-qualified path + | +LL | type A = <<S as Tr>::A as Example>::f; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: aborting due to previous error diff --git a/tests/ui/resolve/issue-103202.stderr b/tests/ui/resolve/issue-103202.stderr index 880389371ef..d4d141fb06f 100644 --- a/tests/ui/resolve/issue-103202.stderr +++ b/tests/ui/resolve/issue-103202.stderr @@ -2,7 +2,12 @@ error[E0223]: ambiguous associated type --> $DIR/issue-103202.rs:4:17 | LL | fn f(self: &S::x) {} - | ^^^^ help: use fully-qualified syntax: `<S as Trait>::x` + | ^^^^ + | +help: if there were a trait named `Example` with associated type `x` implemented for `S`, you could use the fully-qualified path + | +LL | fn f(self: &<S as Example>::x) {} + | ~~~~~~~~~~~~~~~~~ error: aborting due to previous error diff --git a/tests/ui/self/self-impl.stderr b/tests/ui/self/self-impl.stderr index fb47f27e022..36372b644d6 100644 --- a/tests/ui/self/self-impl.stderr +++ b/tests/ui/self/self-impl.stderr @@ -2,13 +2,13 @@ error[E0223]: ambiguous associated type --> $DIR/self-impl.rs:23:16 | LL | let _: <Self>::Baz = true; - | ^^^^^^^^^^^ help: use fully-qualified syntax: `<Bar as Trait>::Baz` + | ^^^^^^^^^^^ help: use the fully-qualified path: `<Bar as Foo>::Baz` error[E0223]: ambiguous associated type --> $DIR/self-impl.rs:25:16 | LL | let _: Self::Baz = true; - | ^^^^^^^^^ help: use fully-qualified syntax: `<Bar as Trait>::Baz` + | ^^^^^^^^^ help: use the fully-qualified path: `<Bar as Foo>::Baz` error: aborting due to 2 previous errors diff --git a/tests/ui/structs/struct-path-associated-type.stderr b/tests/ui/structs/struct-path-associated-type.stderr index abb445214f3..ca5f0b7e21e 100644 --- a/tests/ui/structs/struct-path-associated-type.stderr +++ b/tests/ui/structs/struct-path-associated-type.stderr @@ -48,19 +48,19 @@ error[E0223]: ambiguous associated type --> $DIR/struct-path-associated-type.rs:32:13 | LL | let s = S::A {}; - | ^^^^ help: use fully-qualified syntax: `<S as Trait>::A` + | ^^^^ help: use the fully-qualified path: `<S as Tr>::A` error[E0223]: ambiguous associated type --> $DIR/struct-path-associated-type.rs:33:13 | LL | let z = S::A::<u8> {}; - | ^^^^ help: use fully-qualified syntax: `<S as Trait>::A` + | ^^^^ help: use the fully-qualified path: `<S as Tr>::A` error[E0223]: ambiguous associated type --> $DIR/struct-path-associated-type.rs:35:9 | LL | S::A {} => {} - | ^^^^ help: use fully-qualified syntax: `<S as Trait>::A` + | ^^^^ help: use the fully-qualified path: `<S as Tr>::A` error: aborting due to 8 previous errors diff --git a/tests/ui/suggestions/args-instead-of-tuple-errors.stderr b/tests/ui/suggestions/args-instead-of-tuple-errors.stderr index 44a39efdf25..bc097bf6eb4 100644 --- a/tests/ui/suggestions/args-instead-of-tuple-errors.stderr +++ b/tests/ui/suggestions/args-instead-of-tuple-errors.stderr @@ -11,6 +11,13 @@ LL | let _: Option<(i32, bool)> = Some(1, 2); | ^ = note: expected tuple `(i32, bool)` found type `{integer}` +help: the type constructed contains `{integer}` due to the type of the argument passed + --> $DIR/args-instead-of-tuple-errors.rs:6:34 + | +LL | let _: Option<(i32, bool)> = Some(1, 2); + | ^^^^^-^^^^ + | | + | this argument influences the type of `Some` note: tuple variant defined here --> $SRC_DIR/core/src/option.rs:LL:COL help: remove the extra argument @@ -64,6 +71,13 @@ LL | let _: Option<(i32,)> = Some(5_usize); | = note: expected tuple `(i32,)` found type `usize` +help: the type constructed contains `usize` due to the type of the argument passed + --> $DIR/args-instead-of-tuple-errors.rs:14:29 + | +LL | let _: Option<(i32,)> = Some(5_usize); + | ^^^^^-------^ + | | + | this argument influences the type of `Some` note: tuple variant defined here --> $SRC_DIR/core/src/option.rs:LL:COL @@ -77,6 +91,13 @@ LL | let _: Option<(i32,)> = Some((5_usize)); | = note: expected tuple `(i32,)` found type `usize` +help: the type constructed contains `usize` due to the type of the argument passed + --> $DIR/args-instead-of-tuple-errors.rs:17:29 + | +LL | let _: Option<(i32,)> = Some((5_usize)); + | ^^^^^---------^ + | | + | this argument influences the type of `Some` note: tuple variant defined here --> $SRC_DIR/core/src/option.rs:LL:COL diff --git a/tests/ui/suggestions/issue-105761-suggest-self-for-closure.fixed b/tests/ui/suggestions/issue-105761-suggest-self-for-closure.fixed new file mode 100644 index 00000000000..78e48364bba --- /dev/null +++ b/tests/ui/suggestions/issue-105761-suggest-self-for-closure.fixed @@ -0,0 +1,28 @@ +//run-rustfix +#![allow(unused)] + +struct S; +impl S { + fn foo(&mut self) { + let x = |this: &Self, v: i32| { + this.bar(); + this.hel(); + }; + self.qux(); //~ ERROR cannot borrow `*self` as mutable because it is also borrowed as immutable + x(self, 1); + x(self, 3); + } + fn bar(&self) {} + fn hel(&self) {} + fn qux(&mut self) {} + + fn hello(&mut self) { + let y = |this: &Self| { + this.bar(); + }; + self.qux(); //~ ERROR cannot borrow `*self` as mutable because it is also borrowed as immutable + y(self); + } +} + +fn main() {} diff --git a/tests/ui/suggestions/issue-105761-suggest-self-for-closure.rs b/tests/ui/suggestions/issue-105761-suggest-self-for-closure.rs new file mode 100644 index 00000000000..6d8a9ffc12d --- /dev/null +++ b/tests/ui/suggestions/issue-105761-suggest-self-for-closure.rs @@ -0,0 +1,28 @@ +//run-rustfix +#![allow(unused)] + +struct S; +impl S { + fn foo(&mut self) { + let x = |v: i32| { + self.bar(); + self.hel(); + }; + self.qux(); //~ ERROR cannot borrow `*self` as mutable because it is also borrowed as immutable + x(1); + x(3); + } + fn bar(&self) {} + fn hel(&self) {} + fn qux(&mut self) {} + + fn hello(&mut self) { + let y = || { + self.bar(); + }; + self.qux(); //~ ERROR cannot borrow `*self` as mutable because it is also borrowed as immutable + y(); + } +} + +fn main() {} diff --git a/tests/ui/suggestions/issue-105761-suggest-self-for-closure.stderr b/tests/ui/suggestions/issue-105761-suggest-self-for-closure.stderr new file mode 100644 index 00000000000..bc97d32ebb6 --- /dev/null +++ b/tests/ui/suggestions/issue-105761-suggest-self-for-closure.stderr @@ -0,0 +1,49 @@ +error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable + --> $DIR/issue-105761-suggest-self-for-closure.rs:11:9 + | +LL | let x = |v: i32| { + | -------- immutable borrow occurs here +LL | self.bar(); + | ---- first borrow occurs due to use of `self` in closure +... +LL | self.qux(); + | ^^^^^^^^^^ mutable borrow occurs here +LL | x(1); + | - immutable borrow later used here + | +help: try explicitly pass `&Self` into the Closure as an argument + | +LL ~ let x = |this: &Self, v: i32| { +LL ~ this.bar(); +LL ~ this.hel(); +LL | }; +LL | self.qux(); +LL ~ x(self, 1); +LL ~ x(self, 3); + | + +error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable + --> $DIR/issue-105761-suggest-self-for-closure.rs:23:9 + | +LL | let y = || { + | -- immutable borrow occurs here +LL | self.bar(); + | ---- first borrow occurs due to use of `self` in closure +LL | }; +LL | self.qux(); + | ^^^^^^^^^^ mutable borrow occurs here +LL | y(); + | - immutable borrow later used here + | +help: try explicitly pass `&Self` into the Closure as an argument + | +LL ~ let y = |this: &Self| { +LL ~ this.bar(); +LL | }; +LL | self.qux(); +LL ~ y(self); + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/suggestions/let-binding-init-expr-as-ty.stderr b/tests/ui/suggestions/let-binding-init-expr-as-ty.stderr index 2bf072ef521..b90ae051fb7 100644 --- a/tests/ui/suggestions/let-binding-init-expr-as-ty.stderr +++ b/tests/ui/suggestions/let-binding-init-expr-as-ty.stderr @@ -21,7 +21,12 @@ error[E0223]: ambiguous associated type --> $DIR/let-binding-init-expr-as-ty.rs:2:14 | LL | let foo: i32::from_be(num); - | ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<i32 as Trait>::from_be` + | ^^^^^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `from_be` implemented for `i32`, you could use the fully-qualified path + | +LL | let foo: <i32 as Example>::from_be; + | ~~~~~~~~~~~~~~~~~~~~~~~~~ error: aborting due to 3 previous errors diff --git a/tests/ui/suggestions/sugg-else-for-closure.stderr b/tests/ui/suggestions/sugg-else-for-closure.stderr index 5f59d0f541c..7f05832bcd7 100644 --- a/tests/ui/suggestions/sugg-else-for-closure.stderr +++ b/tests/ui/suggestions/sugg-else-for-closure.stderr @@ -8,6 +8,13 @@ LL | let _s = y.unwrap_or(|| x.split('.').nth(1).unwrap()); | = note: expected reference `&str` found closure `[closure@$DIR/sugg-else-for-closure.rs:6:26: 6:28]` +help: the return type of this call is `[closure@$DIR/sugg-else-for-closure.rs:6:26: 6:28]` due to the type of the argument passed + --> $DIR/sugg-else-for-closure.rs:6:14 + | +LL | let _s = y.unwrap_or(|| x.split('.').nth(1).unwrap()); + | ^^^^^^^^^^^^-------------------------------^ + | | + | this argument influences the return type of `unwrap_or` note: associated function defined here --> $SRC_DIR/core/src/option.rs:LL:COL help: try calling `unwrap_or_else` instead diff --git a/tests/ui/traits/fn-trait-cast-diagnostic.rs b/tests/ui/traits/fn-trait-cast-diagnostic.rs new file mode 100644 index 00000000000..e20aa210e58 --- /dev/null +++ b/tests/ui/traits/fn-trait-cast-diagnostic.rs @@ -0,0 +1,26 @@ +// There are two different instances to check that even if +// the trait is implemented for the output of a function, +// it will still be displayed if the function itself implements a trait. +trait Foo {} + +impl Foo for fn() -> bool {} +impl Foo for bool {} + +fn example() -> bool { + true +} + +trait NoOtherFoo {} + +impl NoOtherFoo for fn() -> bool {} + +fn do_on_foo(v: impl Foo) {} +fn do_on_single_foo(v: impl NoOtherFoo) {} + +fn main() { + do_on_foo(example); + //~^ ERROR the trait bound + + do_on_single_foo(example); + //~^ ERROR the trait bound +} diff --git a/tests/ui/traits/fn-trait-cast-diagnostic.stderr b/tests/ui/traits/fn-trait-cast-diagnostic.stderr new file mode 100644 index 00000000000..6851dcdd504 --- /dev/null +++ b/tests/ui/traits/fn-trait-cast-diagnostic.stderr @@ -0,0 +1,43 @@ +error[E0277]: the trait bound `fn() -> bool {example}: Foo` is not satisfied + --> $DIR/fn-trait-cast-diagnostic.rs:21:15 + | +LL | do_on_foo(example); + | --------- ^^^^^^^ the trait `Foo` is not implemented for fn item `fn() -> bool {example}` + | | + | required by a bound introduced by this call + | +note: required by a bound in `do_on_foo` + --> $DIR/fn-trait-cast-diagnostic.rs:17:22 + | +LL | fn do_on_foo(v: impl Foo) {} + | ^^^ required by this bound in `do_on_foo` +help: use parentheses to call this function + | +LL | do_on_foo(example()); + | ++ +help: the trait `Foo` is implemented for fn pointer `fn() -> bool`, try casting using `as` + | +LL | do_on_foo(example as fn() -> bool); + | +++++++++++++++ + +error[E0277]: the trait bound `fn() -> bool {example}: NoOtherFoo` is not satisfied + --> $DIR/fn-trait-cast-diagnostic.rs:24:22 + | +LL | do_on_single_foo(example); + | ---------------- ^^^^^^^ the trait `NoOtherFoo` is not implemented for fn item `fn() -> bool {example}` + | | + | required by a bound introduced by this call + | +note: required by a bound in `do_on_single_foo` + --> $DIR/fn-trait-cast-diagnostic.rs:18:29 + | +LL | fn do_on_single_foo(v: impl NoOtherFoo) {} + | ^^^^^^^^^^ required by this bound in `do_on_single_foo` +help: the trait `NoOtherFoo` is implemented for fn pointer `fn() -> bool`, try casting using `as` + | +LL | do_on_single_foo(example as fn() -> bool); + | +++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/issue-52893.stderr b/tests/ui/traits/issue-52893.stderr index 7924d3db06f..a11867c03a6 100644 --- a/tests/ui/traits/issue-52893.stderr +++ b/tests/ui/traits/issue-52893.stderr @@ -11,6 +11,13 @@ LL | builder.push(output); | = note: expected type parameter `F` found struct `Class<P>` +help: the return type of this call is `Class<P>` due to the type of the argument passed + --> $DIR/issue-52893.rs:53:9 + | +LL | builder.push(output); + | ^^^^^^^^^^^^^------^ + | | + | this argument influences the return type of `push` note: associated function defined here --> $DIR/issue-52893.rs:11:8 | diff --git a/tests/ui/traits/issue-99875.stderr b/tests/ui/traits/issue-99875.stderr index 3ff8f12f1b8..fb6eebbd254 100644 --- a/tests/ui/traits/issue-99875.stderr +++ b/tests/ui/traits/issue-99875.stderr @@ -6,12 +6,15 @@ LL | takes(function); | | | required by a bound introduced by this call | - = help: the trait `Trait` is implemented for fn pointer `fn(Argument) -> Return` note: required by a bound in `takes` --> $DIR/issue-99875.rs:9:18 | LL | fn takes(_: impl Trait) {} | ^^^^^ required by this bound in `takes` +help: the trait `Trait` is implemented for fn pointer `fn(Argument) -> Return`, try casting using `as` + | +LL | takes(function as fn(Argument) -> Return); + | +++++++++++++++++++++++++ error[E0277]: the trait bound `[closure@$DIR/issue-99875.rs:14:11: 14:34]: Trait` is not satisfied --> $DIR/issue-99875.rs:14:11 diff --git a/tests/ui/traits/item-privacy.stderr b/tests/ui/traits/item-privacy.stderr index f137a298a7f..293cfbda86c 100644 --- a/tests/ui/traits/item-privacy.stderr +++ b/tests/ui/traits/item-privacy.stderr @@ -148,19 +148,24 @@ error[E0223]: ambiguous associated type --> $DIR/item-privacy.rs:115:12 | LL | let _: S::A; - | ^^^^ help: use fully-qualified syntax: `<S as Trait>::A` + | ^^^^ + | +help: if there were a trait named `Example` with associated type `A` implemented for `S`, you could use the fully-qualified path + | +LL | let _: <S as Example>::A; + | ~~~~~~~~~~~~~~~~~ error[E0223]: ambiguous associated type --> $DIR/item-privacy.rs:116:12 | LL | let _: S::B; - | ^^^^ help: use fully-qualified syntax: `<S as Trait>::B` + | ^^^^ help: use the fully-qualified path: `<S as assoc_ty::B>::B` error[E0223]: ambiguous associated type --> $DIR/item-privacy.rs:117:12 | LL | let _: S::C; - | ^^^^ help: use fully-qualified syntax: `<S as Trait>::C` + | ^^^^ help: use the fully-qualified path: `<S as assoc_ty::C>::C` error[E0624]: associated type `A` is private --> $DIR/item-privacy.rs:119:12 diff --git a/tests/ui/type/wrong-call-return-type-due-to-generic-arg.rs b/tests/ui/type/wrong-call-return-type-due-to-generic-arg.rs new file mode 100644 index 00000000000..ba5b9f54246 --- /dev/null +++ b/tests/ui/type/wrong-call-return-type-due-to-generic-arg.rs @@ -0,0 +1,28 @@ +fn function<T>(x: T, y: bool) -> T { + x +} + +struct S {} +impl S { + fn method<T>(&self, x: T) -> T { + x + } +} + +fn wrong_arg_type(x: u32) -> u32 { + x +} + +fn main() { + // Should not trigger. + let x = wrong_arg_type(0u16); //~ ERROR mismatched types + let x: u16 = function(0, 0u8); //~ ERROR mismatched types + + // Should trigger exactly once for the first argument. + let x: u16 = function(0u32, 0u8); //~ ERROR arguments to this function are incorrect + + // Should trigger. + let x: u16 = function(0u32, true); //~ ERROR mismatched types + let x: u16 = (S {}).method(0u32); //~ ERROR mismatched types + function(0u32, 8u8) //~ ERROR arguments to this function are incorrect +} diff --git a/tests/ui/type/wrong-call-return-type-due-to-generic-arg.stderr b/tests/ui/type/wrong-call-return-type-due-to-generic-arg.stderr new file mode 100644 index 00000000000..4d012cb156b --- /dev/null +++ b/tests/ui/type/wrong-call-return-type-due-to-generic-arg.stderr @@ -0,0 +1,131 @@ +error[E0308]: mismatched types + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:18:28 + | +LL | let x = wrong_arg_type(0u16); + | -------------- ^^^^ expected `u32`, found `u16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:12:4 + | +LL | fn wrong_arg_type(x: u32) -> u32 { + | ^^^^^^^^^^^^^^ ------ +help: change the type of the numeric literal from `u16` to `u32` + | +LL | let x = wrong_arg_type(0u32); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:19:30 + | +LL | let x: u16 = function(0, 0u8); + | -------- ^^^ expected `bool`, found `u8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:1:4 + | +LL | fn function<T>(x: T, y: bool) -> T { + | ^^^^^^^^ ------- + +error[E0308]: arguments to this function are incorrect + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:22:18 + | +LL | let x: u16 = function(0u32, 0u8); + | ^^^^^^^^ ---- --- expected `bool`, found `u8` + | | + | expected `u16`, found `u32` + | +help: the return type of this call is `u32` due to the type of the argument passed + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:22:18 + | +LL | let x: u16 = function(0u32, 0u8); + | ^^^^^^^^^----^^^^^^ + | | + | this argument influences the return type of `function` +note: function defined here + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:1:4 + | +LL | fn function<T>(x: T, y: bool) -> T { + | ^^^^^^^^ ---- ------- +help: change the type of the numeric literal from `u32` to `u16` + | +LL | let x: u16 = function(0u16, 0u8); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:25:27 + | +LL | let x: u16 = function(0u32, true); + | -------- ^^^^ expected `u16`, found `u32` + | | + | arguments to this function are incorrect + | +help: the return type of this call is `u32` due to the type of the argument passed + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:25:18 + | +LL | let x: u16 = function(0u32, true); + | ^^^^^^^^^----^^^^^^^ + | | + | this argument influences the return type of `function` +note: function defined here + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:1:4 + | +LL | fn function<T>(x: T, y: bool) -> T { + | ^^^^^^^^ ---- +help: change the type of the numeric literal from `u32` to `u16` + | +LL | let x: u16 = function(0u16, true); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:26:32 + | +LL | let x: u16 = (S {}).method(0u32); + | ------ ^^^^ expected `u16`, found `u32` + | | + | arguments to this method are incorrect + | +help: the return type of this call is `u32` due to the type of the argument passed + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:26:18 + | +LL | let x: u16 = (S {}).method(0u32); + | ^^^^^^^^^^^^^^----^ + | | + | this argument influences the return type of `method` +note: associated function defined here + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:7:8 + | +LL | fn method<T>(&self, x: T) -> T { + | ^^^^^^ ---- +help: change the type of the numeric literal from `u32` to `u16` + | +LL | let x: u16 = (S {}).method(0u16); + | ~~~ + +error[E0308]: arguments to this function are incorrect + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:27:5 + | +LL | function(0u32, 8u8) + | ^^^^^^^^ ---- --- expected `bool`, found `u8` + | | + | expected `()`, found `u32` + | +help: the return type of this call is `u32` due to the type of the argument passed + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:27:5 + | +LL | function(0u32, 8u8) + | ^^^^^^^^^----^^^^^^ + | | + | this argument influences the return type of `function` +note: function defined here + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:1:4 + | +LL | fn function<T>(x: T, y: bool) -> T { + | ^^^^^^^^ ---- ------- + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/issue-46112.stderr b/tests/ui/typeck/issue-46112.stderr index f488463ae3c..8f5ff51fbe1 100644 --- a/tests/ui/typeck/issue-46112.stderr +++ b/tests/ui/typeck/issue-46112.stderr @@ -8,6 +8,13 @@ LL | fn main() { test(Ok(())); } | = note: expected enum `Option<()>` found unit type `()` +help: the type constructed contains `()` due to the type of the argument passed + --> $DIR/issue-46112.rs:9:18 + | +LL | fn main() { test(Ok(())); } + | ^^^--^ + | | + | this argument influences the type of `Ok` note: tuple variant defined here --> $SRC_DIR/core/src/result.rs:LL:COL help: try wrapping the expression in `Some` diff --git a/tests/ui/typeck/issue-84768.stderr b/tests/ui/typeck/issue-84768.stderr index 00d23389720..09f3aee2d9e 100644 --- a/tests/ui/typeck/issue-84768.stderr +++ b/tests/ui/typeck/issue-84768.stderr @@ -14,6 +14,13 @@ LL | <F as FnOnce(&mut u8)>::call_once(f, 1) | = note: expected tuple `(&mut u8,)` found type `{integer}` +help: the return type of this call is `{integer}` due to the type of the argument passed + --> $DIR/issue-84768.rs:7:5 + | +LL | <F as FnOnce(&mut u8)>::call_once(f, 1) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^ + | | + | this argument influences the return type of `FnOnce` note: associated function defined here --> $SRC_DIR/core/src/ops/function.rs:LL:COL diff --git a/tests/ui/ufcs/ufcs-partially-resolved.stderr b/tests/ui/ufcs/ufcs-partially-resolved.stderr index 5f7f6aa9f6e..72fccea8ae3 100644 --- a/tests/ui/ufcs/ufcs-partially-resolved.stderr +++ b/tests/ui/ufcs/ufcs-partially-resolved.stderr @@ -205,7 +205,12 @@ error[E0223]: ambiguous associated type --> $DIR/ufcs-partially-resolved.rs:36:12 | LL | let _: <u8 as Tr>::Y::NN; - | ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<<u8 as Tr>::Y as Trait>::NN` + | ^^^^^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `NN` implemented for `<u8 as Tr>::Y`, you could use the fully-qualified path + | +LL | let _: <<u8 as Tr>::Y as Example>::NN; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error[E0599]: no associated item named `NN` found for type `u16` in the current scope --> $DIR/ufcs-partially-resolved.rs:38:20 diff --git a/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr b/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr index a2fe627868a..e85144a31ca 100644 --- a/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr +++ b/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr @@ -21,6 +21,13 @@ LL | <i32 as Add<i32>>::add(1u32, 2); | | | arguments to this function are incorrect | +help: the return type of this call is `u32` due to the type of the argument passed + --> $DIR/ufcs-qpath-self-mismatch.rs:7:5 + | +LL | <i32 as Add<i32>>::add(1u32, 2); + | ^^^^^^^^^^^^^^^^^^^^^^^----^^^^ + | | + | this argument influences the return type of `Add` note: associated function defined here --> $SRC_DIR/core/src/ops/arith.rs:LL:COL help: change the type of the numeric literal from `u32` to `i32` @@ -36,6 +43,13 @@ LL | <i32 as Add<i32>>::add(1, 2u32); | | | arguments to this function are incorrect | +help: the return type of this call is `u32` due to the type of the argument passed + --> $DIR/ufcs-qpath-self-mismatch.rs:9:5 + | +LL | <i32 as Add<i32>>::add(1, 2u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^----^ + | | + | this argument influences the return type of `Add` note: associated function defined here --> $SRC_DIR/core/src/ops/arith.rs:LL:COL help: change the type of the numeric literal from `u32` to `i32` |
