From 1d7d10a93d7a7f3e761a9b1fc6aeeff84d7483ef Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 4 Jan 2023 14:05:58 -0800 Subject: [PATCH 01/10] tidy: Don't include wasm32 in compiler dependency check --- Cargo.lock | 1 + src/tools/tidy/Cargo.toml | 1 + src/tools/tidy/src/deps.rs | 168 ++++++++++++++----------------------- 3 files changed, 67 insertions(+), 103 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d7381b6c93866..77c8809785a2f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5596,6 +5596,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", diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml index 5f5ae3a65efa8..714bdace84889 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 f649e391b798e..9870af86d7eaf 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", @@ -236,7 +226,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "thiserror-impl", "thorin-dwp", "thread_local", - "time", "tinystr", "tinyvec", "tinyvec_macros", @@ -269,13 +258,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", @@ -486,73 +468,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. @@ -589,24 +553,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); @@ -616,41 +562,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 { From 6885733c41844ac0ea24b965e91616a16a631697 Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Thu, 22 Dec 2022 16:33:12 +0100 Subject: [PATCH 02/10] Fix mir-opt tests for big-endian platforms The test cases src/test/mir-opt/building/custom/consts.rs and src/test/mir-opt/const_prop/mutable_variable_no_prop.rs are currently failing on big-endian platforms as the binary encoding of some constants is hard-coded in the MIR test files. Fix this by choosing constant values that have the same encoding on big- and little-endian platforms. The test case src/test/mir-opt/issues/issue_75439.rs is failing as well, but since the purpose of the test is to validate handling of big-endian integer encodings on a little-endian platform, it does not make much sense to run it on big-endian platforms in the first place - we can just ignore it there. Fixed part of https://github.com/rust-lang/rust/issues/105383. --- tests/mir-opt/building/custom/consts.rs | 4 ++-- tests/mir-opt/building/custom/consts.statics.built.after.mir | 4 ++-- .../const_prop/mutable_variable_no_prop.main.ConstProp.diff | 2 +- tests/mir-opt/const_prop/mutable_variable_no_prop.rs | 2 +- .../issues/issue_75439.foo.MatchBranchSimplification.diff | 4 ++-- tests/mir-opt/issues/issue_75439.rs | 1 + 6 files changed, 9 insertions(+), 8 deletions(-) diff --git a/tests/mir-opt/building/custom/consts.rs b/tests/mir-opt/building/custom/consts.rs index ff4fe1a93246e..16d10eb5968c1 100644 --- a/tests/mir-opt/building/custom/consts.rs +++ b/tests/mir-opt/building/custom/consts.rs @@ -18,8 +18,8 @@ fn consts() { }) } -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 ee768e263ecdf..bfef976aa0272 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 b9d551c5e5fc2..7fa29cccd50d6 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 8c23c5fcf0f88..b69ec931a6311 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 1c69a6232d606..93804780371cd 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() } } @@ -49,7 +49,7 @@ _6 = _4; // scope 4 at $DIR/issue_75439.rs:+5:33: +5:35 _5 = transmute::(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::}, val: Value() } } diff --git a/tests/mir-opt/issues/issue_75439.rs b/tests/mir-opt/issues/issue_75439.rs index ae2e036312e88..4c749a150c091 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; From 6155b9a772c944702f931ce5940d6c19cb7ced07 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Thu, 12 Jan 2023 18:47:05 +0000 Subject: [PATCH 03/10] Avoid __cxa_thread_atexit_impl on Emscripten - Fixes https://github.com/rust-lang/rust/issues/91628. - Fixes https://github.com/emscripten-core/emscripten/issues/15722. See discussion in both issues. The TL;DR is that weak linkage causes LLVM to produce broken Wasm, presumably due to pointer mismatch. The code is casting a void pointer to a function pointer with specific signature, but Wasm is very strict about function pointer compatibility, so the resulting code is invalid. Ideally LLVM should catch this earlier in the process rather than emit invalid Wasm, but it currently doesn't and this is an easy and valid fix, given that Emcripten doesn't have `__cxa_thread_atexit_impl` these days anyway. Unfortunately, I can't add a regression test as even after looking into this issue for a long time, I couldn't reproduce it with any minimal Rust example, only with extracted LLVM IR or on a large project involving Rust + C++. r? @alexcrichton --- library/std/src/sys/unix/thread_local_dtor.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/library/std/src/sys/unix/thread_local_dtor.rs b/library/std/src/sys/unix/thread_local_dtor.rs index d7fd2130f7cce..aa4df00063208 100644 --- a/library/std/src/sys/unix/thread_local_dtor.rs +++ b/library/std/src/sys/unix/thread_local_dtor.rs @@ -11,13 +11,7 @@ // Note, however, that we run on lots older linuxes, as well as cross // compiling from a newer linux to an older linux, so we also have a // fallback implementation to use as well. -#[cfg(any( - target_os = "linux", - target_os = "fuchsia", - target_os = "redox", - target_os = "emscripten" -))] -#[cfg_attr(target_family = "wasm", allow(unused))] // might remain unused depending on target details (e.g. wasm32-unknown-emscripten) +#[cfg(any(target_os = "linux", target_os = "fuchsia", target_os = "redox"))] pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { use crate::mem; use crate::sys_common::thread_local_dtor::register_dtor_fallback; @@ -94,7 +88,7 @@ pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { } } -#[cfg(any(target_os = "vxworks", target_os = "horizon"))] +#[cfg(any(target_os = "vxworks", target_os = "horizon", target_os = "emscripten"))] pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { use crate::sys_common::thread_local_dtor::register_dtor_fallback; register_dtor_fallback(t, dtor); From a3cf3822d267524e3d9fa45309f2718793f3cf7f Mon Sep 17 00:00:00 2001 From: Robin Schroer Date: Sun, 8 Jan 2023 21:10:48 +0900 Subject: [PATCH 04/10] Emit a hint for bad call return types due to generic arguments When the return type of a function call depends on the type of an argument, e.g. ``` fn foo(x: T) -> T { x } ``` and the expected type is set due to either an explicitly typed binding, or because the call to the function is in a tail position without semicolon, the current error implies that the argument in the call has the wrong type. This new hint highlights that the expected type doesn't match the returned type, which matches the argument type, and that that's why we're flagging the argument type. Fixes #43608. --- compiler/rustc_hir_typeck/src/demand.rs | 74 ++++++++++ tests/ui/closures/issue-84128.stderr | 7 + tests/ui/closures/issue-87461.stderr | 21 +++ .../missing-bounds.stderr | 7 + tests/ui/mismatched_types/issue-35030.stderr | 7 + .../args-instead-of-tuple-errors.stderr | 21 +++ .../suggestions/sugg-else-for-closure.stderr | 7 + tests/ui/traits/issue-52893.stderr | 7 + ...ong-call-return-type-due-to-generic-arg.rs | 28 ++++ ...call-return-type-due-to-generic-arg.stderr | 131 ++++++++++++++++++ tests/ui/typeck/issue-46112.stderr | 7 + tests/ui/typeck/issue-84768.stderr | 7 + tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr | 14 ++ 13 files changed, 338 insertions(+) create mode 100644 tests/ui/type/wrong-call-return-type-due-to-generic-arg.rs create mode 100644 tests/ui/type/wrong-call-return-type-due-to-generic-arg.stderr diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 6c128d0aa1a65..665dc8b6a2f2a 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/tests/ui/closures/issue-84128.stderr b/tests/ui/closures/issue-84128.stderr index 59607afec8f8d..1cd8949b8c4b7 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 72337892734e6..b492251c01691 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/generic-associated-types/missing-bounds.stderr b/tests/ui/generic-associated-types/missing-bounds.stderr index c913483a8747c..9f669b9a5214b 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 `::Output` +help: the type constructed contains `::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/mismatched_types/issue-35030.stderr b/tests/ui/mismatched_types/issue-35030.stderr index 680aff1726f9f..de4e067fead4c 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/suggestions/args-instead-of-tuple-errors.stderr b/tests/ui/suggestions/args-instead-of-tuple-errors.stderr index 44a39efdf2542..bc097bf6eb451 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/sugg-else-for-closure.stderr b/tests/ui/suggestions/sugg-else-for-closure.stderr index 5f59d0f541c99..7f05832bcd728 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/issue-52893.stderr b/tests/ui/traits/issue-52893.stderr index 7924d3db06f36..a11867c03a689 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

` +help: the return type of this call is `Class

` 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/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 0000000000000..ba5b9f54246e2 --- /dev/null +++ b/tests/ui/type/wrong-call-return-type-due-to-generic-arg.rs @@ -0,0 +1,28 @@ +fn function(x: T, y: bool) -> T { + x +} + +struct S {} +impl S { + fn method(&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 0000000000000..4d012cb156bb5 --- /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(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(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(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(&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(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 f488463ae3ce9..8f5ff51fbe100 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 00d23389720b9..09f3aee2d9ec5 100644 --- a/tests/ui/typeck/issue-84768.stderr +++ b/tests/ui/typeck/issue-84768.stderr @@ -14,6 +14,13 @@ LL | ::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 | ::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-qpath-self-mismatch.stderr b/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr index a2fe627868aeb..e85144a31ca96 100644 --- a/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr +++ b/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr @@ -21,6 +21,13 @@ LL | >::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 | >::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 | >::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 | >::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` From f6e6d2a035d9e86e7053847aa60a99940f41064c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 12 Jan 2023 19:53:01 +0000 Subject: [PATCH 05/10] Elaborate unmet obligations in E0599 for more context --- compiler/rustc_hir_typeck/src/method/probe.rs | 28 ++++++++++++++---- tests/ui/derives/issue-91550.stderr | 29 ++++++++++++++++--- .../ui/missing-trait-bounds/issue-35677.fixed | 2 +- .../missing-trait-bounds/issue-35677.stderr | 6 ++-- 4 files changed, 53 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index dd827777df94e..15f6e11717768 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -1587,11 +1587,29 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let o = self.resolve_vars_if_possible(o); if !self.predicate_may_hold(&o) { result = ProbeResult::NoMatch; - possibly_unsatisfied_predicates.push(( - o.predicate, - None, - Some(o.cause), - )); + let parent_o = o.clone(); + let implied_obligations = + traits::elaborate_obligations(self.tcx, vec![o]); + for o in implied_obligations { + let parent = if o == parent_o { + None + } else { + if o.predicate.to_opt_poly_trait_pred().map(|p| p.def_id()) + == self.tcx.lang_items().sized_trait() + { + // We don't care to talk about implicit `Sized` bounds. + continue; + } + Some(parent_o.predicate) + }; + if !self.predicate_may_hold(&o) { + possibly_unsatisfied_predicates.push(( + o.predicate, + parent, + Some(o.cause), + )); + } + } } } } diff --git a/tests/ui/derives/issue-91550.stderr b/tests/ui/derives/issue-91550.stderr index bf0bb3fbdf8f7..381d860a9c36d 100644 --- a/tests/ui/derives/issue-91550.stderr +++ b/tests/ui/derives/issue-91550.stderr @@ -6,12 +6,15 @@ LL | struct Value(u32); | | | doesn't satisfy `Value: Eq` | doesn't satisfy `Value: Hash` + | doesn't satisfy `Value: PartialEq` ... LL | hs.insert(Value(0)); | ^^^^^^ | = note: the following trait bounds were not satisfied: `Value: Eq` + `Value: PartialEq` + which is required by `Value: Eq` `Value: Hash` help: consider annotating `Value` with `#[derive(Eq, Hash, PartialEq)]` | @@ -22,7 +25,10 @@ error[E0599]: the method `use_eq` exists for struct `Object`, but its --> $DIR/issue-91550.rs:26:9 | LL | pub struct NoDerives; - | -------------------- doesn't satisfy `NoDerives: Eq` + | -------------------- + | | + | doesn't satisfy `NoDerives: Eq` + | doesn't satisfy `NoDerives: PartialEq` LL | LL | struct Object(T); | ---------------- method `use_eq` not found for this struct @@ -30,7 +36,9 @@ LL | struct Object(T); LL | foo.use_eq(); | ^^^^^^ method cannot be called on `Object` due to unsatisfied trait bounds | -note: trait bound `NoDerives: Eq` was not satisfied +note: the following trait bounds were not satisfied: + `NoDerives: Eq` + `NoDerives: PartialEq` --> $DIR/issue-91550.rs:15:9 | LL | impl Object { @@ -46,7 +54,12 @@ error[E0599]: the method `use_ord` exists for struct `Object`, but it --> $DIR/issue-91550.rs:27:9 | LL | pub struct NoDerives; - | -------------------- doesn't satisfy `NoDerives: Ord` + | -------------------- + | | + | doesn't satisfy `NoDerives: Eq` + | doesn't satisfy `NoDerives: Ord` + | doesn't satisfy `NoDerives: PartialEq` + | doesn't satisfy `NoDerives: PartialOrd` LL | LL | struct Object(T); | ---------------- method `use_ord` not found for this struct @@ -54,7 +67,11 @@ LL | struct Object(T); LL | foo.use_ord(); | ^^^^^^^ method cannot be called on `Object` due to unsatisfied trait bounds | -note: trait bound `NoDerives: Ord` was not satisfied +note: the following trait bounds were not satisfied: + `NoDerives: Eq` + `NoDerives: Ord` + `NoDerives: PartialEq` + `NoDerives: PartialOrd` --> $DIR/issue-91550.rs:18:9 | LL | impl Object { @@ -72,7 +89,9 @@ error[E0599]: the method `use_ord_and_partial_ord` exists for struct `Object(T); @@ -82,7 +101,9 @@ LL | foo.use_ord_and_partial_ord(); | ^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `Object` due to unsatisfied trait bounds | note: the following trait bounds were not satisfied: + `NoDerives: Eq` `NoDerives: Ord` + `NoDerives: PartialEq` `NoDerives: PartialOrd` --> $DIR/issue-91550.rs:21:9 | diff --git a/tests/ui/missing-trait-bounds/issue-35677.fixed b/tests/ui/missing-trait-bounds/issue-35677.fixed index 08174d8d8d53a..c76b6bc9c1851 100644 --- a/tests/ui/missing-trait-bounds/issue-35677.fixed +++ b/tests/ui/missing-trait-bounds/issue-35677.fixed @@ -3,7 +3,7 @@ use std::collections::HashSet; use std::hash::Hash; -fn is_subset(this: &HashSet, other: &HashSet) -> bool where T: Eq, T: Hash { +fn is_subset(this: &HashSet, other: &HashSet) -> bool where T: Eq, T: Hash, T: PartialEq { this.is_subset(other) //~^ ERROR the method } diff --git a/tests/ui/missing-trait-bounds/issue-35677.stderr b/tests/ui/missing-trait-bounds/issue-35677.stderr index a2201b946a6f0..067b10b873abf 100644 --- a/tests/ui/missing-trait-bounds/issue-35677.stderr +++ b/tests/ui/missing-trait-bounds/issue-35677.stderr @@ -6,11 +6,13 @@ LL | this.is_subset(other) | = note: the following trait bounds were not satisfied: `T: Eq` + `T: PartialEq` + which is required by `T: Eq` `T: Hash` help: consider restricting the type parameters to satisfy the trait bounds | -LL | fn is_subset(this: &HashSet, other: &HashSet) -> bool where T: Eq, T: Hash { - | ++++++++++++++++++++ +LL | fn is_subset(this: &HashSet, other: &HashSet) -> bool where T: Eq, T: Hash, T: PartialEq { + | ++++++++++++++++++++++++++++++++++ error: aborting due to previous error From 3d6b09e53e0b1d5920fe3c6106f676b7b95f4a70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 12 Jan 2023 21:32:06 +0000 Subject: [PATCH 06/10] Keep obligation chain when elaborating obligations --- .../rustc_hir_typeck/src/method/suggest.rs | 15 +++++++++- compiler/rustc_infer/src/traits/util.rs | 18 ++++++++++-- .../issue-43784-associated-type.stderr | 5 ++++ tests/ui/derives/issue-91550.stderr | 29 ++++++++++++------- .../issue-74824.stderr | 1 + tests/ui/traits/issue-43784-supertrait.stderr | 5 ++++ 6 files changed, 59 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 8166eb8299041..338fabca38919 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -692,7 +692,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "auto trait is invoked with no method error, but no error reported?", ); } - Some(_) => unreachable!(), + Some(Node::Item(hir::Item { + ident, kind: hir::ItemKind::Trait(..), .. + })) => { + skip_list.insert(p); + let entry = spanned_predicates.entry(ident.span); + let entry = entry.or_insert_with(|| { + (FxHashSet::default(), FxHashSet::default(), Vec::new()) + }); + entry.0.insert(cause.span); + entry.1.insert((ident.span, "")); + entry.1.insert((cause.span, "unsatisfied trait bound introduced here")); + entry.2.push(p); + } + Some(node) => unreachable!("encountered `{node:?}`"), None => (), } } diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index 8f0bd3a9abe5e..1817bbf922854 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -1,7 +1,7 @@ use smallvec::smallvec; use crate::infer::outlives::components::{push_outlives_components, Component}; -use crate::traits::{Obligation, ObligationCause, PredicateObligation}; +use crate::traits::{self, Obligation, ObligationCause, PredicateObligation}; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_middle::ty::{self, ToPredicate, TyCtxt}; use rustc_span::symbol::Ident; @@ -145,16 +145,28 @@ impl<'tcx> Elaborator<'tcx> { // Get predicates declared on the trait. let predicates = tcx.super_predicates_of(data.def_id()); - let obligations = predicates.predicates.iter().map(|&(mut pred, _)| { + let obligations = predicates.predicates.iter().map(|&(mut pred, span)| { // when parent predicate is non-const, elaborate it to non-const predicates. if data.constness == ty::BoundConstness::NotConst { pred = pred.without_const(tcx); } + let cause = obligation.cause.clone().derived_cause( + bound_predicate.rebind(data), + |derived| { + traits::ImplDerivedObligation(Box::new( + traits::ImplDerivedObligationCause { + derived, + impl_def_id: data.def_id(), + span, + }, + )) + }, + ); predicate_obligation( pred.subst_supertrait(tcx, &bound_predicate.rebind(data.trait_ref)), obligation.param_env, - obligation.cause.clone(), + cause, ) }); debug!(?data, ?obligations, "super_predicates"); diff --git a/tests/ui/associated-types/issue-43784-associated-type.stderr b/tests/ui/associated-types/issue-43784-associated-type.stderr index f1677b822b4c9..50fa7d1ac4d43 100644 --- a/tests/ui/associated-types/issue-43784-associated-type.stderr +++ b/tests/ui/associated-types/issue-43784-associated-type.stderr @@ -4,6 +4,11 @@ error[E0277]: the trait bound `T: Copy` is not satisfied LL | type Assoc = T; | ^ the trait `Copy` is not implemented for `T` | +note: required for `::Assoc` to implement `Partial` + --> $DIR/issue-43784-associated-type.rs:1:11 + | +LL | pub trait Partial: Copy { + | ^^^^^^^ note: required by a bound in `Complete::Assoc` --> $DIR/issue-43784-associated-type.rs:5:17 | diff --git a/tests/ui/derives/issue-91550.stderr b/tests/ui/derives/issue-91550.stderr index 381d860a9c36d..af03f0e5e5f43 100644 --- a/tests/ui/derives/issue-91550.stderr +++ b/tests/ui/derives/issue-91550.stderr @@ -36,15 +36,16 @@ LL | struct Object(T); LL | foo.use_eq(); | ^^^^^^ method cannot be called on `Object` due to unsatisfied trait bounds | -note: the following trait bounds were not satisfied: - `NoDerives: Eq` - `NoDerives: PartialEq` +note: trait bound `NoDerives: Eq` was not satisfied --> $DIR/issue-91550.rs:15:9 | LL | impl Object { | ^^ --------- | | | unsatisfied trait bound introduced here + = note: the following trait bounds were not satisfied: + `NoDerives: PartialEq` + which is required by `NoDerives: Eq` help: consider annotating `NoDerives` with `#[derive(Eq, PartialEq)]` | LL | #[derive(Eq, PartialEq)] @@ -67,17 +68,20 @@ LL | struct Object(T); LL | foo.use_ord(); | ^^^^^^^ method cannot be called on `Object` due to unsatisfied trait bounds | -note: the following trait bounds were not satisfied: - `NoDerives: Eq` - `NoDerives: Ord` - `NoDerives: PartialEq` - `NoDerives: PartialOrd` +note: trait bound `NoDerives: Ord` was not satisfied --> $DIR/issue-91550.rs:18:9 | LL | impl Object { | ^^^ --------- | | | unsatisfied trait bound introduced here + = note: the following trait bounds were not satisfied: + `NoDerives: PartialOrd` + which is required by `NoDerives: Ord` + `NoDerives: PartialEq` + which is required by `NoDerives: Ord` + `NoDerives: Eq` + which is required by `NoDerives: Ord` help: consider annotating `NoDerives` with `#[derive(Eq, Ord, PartialEq, PartialOrd)]` | LL | #[derive(Eq, Ord, PartialEq, PartialOrd)] @@ -101,9 +105,7 @@ LL | foo.use_ord_and_partial_ord(); | ^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `Object` due to unsatisfied trait bounds | note: the following trait bounds were not satisfied: - `NoDerives: Eq` `NoDerives: Ord` - `NoDerives: PartialEq` `NoDerives: PartialOrd` --> $DIR/issue-91550.rs:21:9 | @@ -112,6 +114,13 @@ LL | impl Object { | | | | | unsatisfied trait bound introduced here | unsatisfied trait bound introduced here + = note: the following trait bounds were not satisfied: + `NoDerives: PartialEq` + which is required by `NoDerives: Ord` + `NoDerives: Eq` + which is required by `NoDerives: Ord` + `NoDerives: PartialEq` + which is required by `NoDerives: PartialOrd` help: consider annotating `NoDerives` with `#[derive(Eq, Ord, PartialEq, PartialOrd)]` | LL | #[derive(Eq, Ord, PartialEq, PartialOrd)] diff --git a/tests/ui/generic-associated-types/issue-74824.stderr b/tests/ui/generic-associated-types/issue-74824.stderr index 623adb1c2ad1e..e5638d90ee8e7 100644 --- a/tests/ui/generic-associated-types/issue-74824.stderr +++ b/tests/ui/generic-associated-types/issue-74824.stderr @@ -17,6 +17,7 @@ LL | type Copy: Copy = Box; | ^^^^^^ the trait `Clone` is not implemented for `T` | = note: required for `Box` to implement `Clone` + = note: required for `::Copy` to implement `Copy` note: required by a bound in `UnsafeCopy::Copy` --> $DIR/issue-74824.rs:6:19 | diff --git a/tests/ui/traits/issue-43784-supertrait.stderr b/tests/ui/traits/issue-43784-supertrait.stderr index 4fe12731475b4..6b5b721384cbb 100644 --- a/tests/ui/traits/issue-43784-supertrait.stderr +++ b/tests/ui/traits/issue-43784-supertrait.stderr @@ -4,6 +4,11 @@ error[E0277]: the trait bound `T: Copy` is not satisfied LL | impl Complete for T {} | ^ the trait `Copy` is not implemented for `T` | +note: required for `T` to implement `Partial` + --> $DIR/issue-43784-supertrait.rs:1:11 + | +LL | pub trait Partial: Copy { + | ^^^^^^^ note: required by a bound in `Complete` --> $DIR/issue-43784-supertrait.rs:4:21 | From 81ba427a7b15d614a74812ef3fd1467c85d4768d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 12 Jan 2023 21:48:07 +0000 Subject: [PATCH 07/10] Add tests --- tests/ui/traits/track-obligations.rs | 88 ++++++++++++++++++++++++ tests/ui/traits/track-obligations.stderr | 76 ++++++++++++++++++++ 2 files changed, 164 insertions(+) create mode 100644 tests/ui/traits/track-obligations.rs create mode 100644 tests/ui/traits/track-obligations.stderr diff --git a/tests/ui/traits/track-obligations.rs b/tests/ui/traits/track-obligations.rs new file mode 100644 index 0000000000000..77e753c13f739 --- /dev/null +++ b/tests/ui/traits/track-obligations.rs @@ -0,0 +1,88 @@ +// These are simplifications of the tower traits by the same name: + +pub trait Service { + type Response; +} + +pub trait Layer { + type Service; +} + +// Any type will do here: + +pub struct Req; +pub struct Res; + +// This is encoding a trait alias. + +pub trait ParticularService: + Service { +} + +impl ParticularService for T +where + T: Service, +{ +} + +// This is also a trait alias. +// The weird = bound is there so that users of the trait do not +// need to repeat the bounds. See https://github.com/rust-lang/rust/issues/20671 +// for context, and in particular the workaround in: +// https://github.com/rust-lang/rust/issues/20671#issuecomment-529752828 + +pub trait ParticularServiceLayer: + Layer>::Service> +{ + type Service: ParticularService; +} + +impl ParticularServiceLayer for T +where + T: Layer, + T::Service: ParticularService, +{ + type Service = T::Service; +} + +// These are types that implement the traits that the trait aliases refer to. +// They should also implement the alias traits due to the blanket impls. + +struct ALayer(C); +impl Layer for ALayer { + type Service = AService; +} + +struct AService; +impl Service for AService { + // However, AService does _not_ meet the blanket implementation, + // since its Response type is bool, not Res as it should be. + type Response = bool; +} + +// This is a wrapper type around ALayer that uses the trait alias +// as a way to communicate the requirements of the provided types. +struct Client(C); + +// The method and the free-standing function below both have the same bounds. + +impl Client +where + ALayer: ParticularServiceLayer, +{ + fn check(&self) {} +} + +fn check(_: C) where ALayer: ParticularServiceLayer {} + +// But, they give very different error messages. + +fn main() { + // This gives a very poor error message that does nothing to point the user + // at the underlying cause of why the types involved do not meet the bounds. + Client(()).check(); //~ ERROR E0599 + + // This gives a good(ish) error message that points the user at _why_ the + // bound isn't met, and thus how they might fix it. + check(()); //~ ERROR E0271 +} diff --git a/tests/ui/traits/track-obligations.stderr b/tests/ui/traits/track-obligations.stderr new file mode 100644 index 0000000000000..89477475970f4 --- /dev/null +++ b/tests/ui/traits/track-obligations.stderr @@ -0,0 +1,76 @@ +error[E0599]: the method `check` exists for struct `Client<()>`, but its trait bounds were not satisfied + --> $DIR/track-obligations.rs:83:16 + | +LL | struct ALayer(C); + | ---------------- + | | + | doesn't satisfy `<_ as Layer<()>>::Service = as ParticularServiceLayer<()>>::Service` + | doesn't satisfy `ALayer<()>: ParticularServiceLayer<()>` +... +LL | struct Client(C); + | ---------------- method `check` not found for this struct +... +LL | Client(()).check(); + | ^^^^^ method cannot be called on `Client<()>` due to unsatisfied trait bounds + | +note: trait bound ` as Layer<()>>::Service = as ParticularServiceLayer<()>>::Service` was not satisfied + --> $DIR/track-obligations.rs:35:14 + | +LL | pub trait ParticularServiceLayer: + | ---------------------- +LL | Layer>::Service> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here +note: trait bound `ALayer<()>: ParticularServiceLayer<()>` was not satisfied + --> $DIR/track-obligations.rs:71:16 + | +LL | impl Client + | --------- +LL | where +LL | ALayer: ParticularServiceLayer, + | ^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here +note: the trait `ParticularServiceLayer` must be implemented + --> $DIR/track-obligations.rs:34:1 + | +LL | / pub trait ParticularServiceLayer: +LL | | Layer>::Service> + | |____________________________________________________________________^ + +error[E0271]: type mismatch resolving `>::Response == Res` + --> $DIR/track-obligations.rs:87:11 + | +LL | check(()); + | ----- ^^ type mismatch resolving `>::Response == Res` + | | + | required by a bound introduced by this call + | +note: expected this to be `Res` + --> $DIR/track-obligations.rs:60:21 + | +LL | type Response = bool; + | ^^^^ +note: required for `AService` to implement `ParticularService` + --> $DIR/track-obligations.rs:22:9 + | +LL | impl ParticularService for T + | ^^^^^^^^^^^^^^^^^ ^ +LL | where +LL | T: Service, + | -------------- unsatisfied trait bound introduced here +note: required for `ALayer<_>` to implement `ParticularServiceLayer<_>` + --> $DIR/track-obligations.rs:40:12 + | +LL | impl ParticularServiceLayer for T + | ^^^^^^^^^^^^^^^^^^^^^^^^^ ^ +... +LL | T::Service: ParticularService, + | ----------------- unsatisfied trait bound introduced here +note: required by a bound in `check` + --> $DIR/track-obligations.rs:76:36 + | +LL | fn check(_: C) where ALayer: ParticularServiceLayer {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0271, E0599. +For more information about an error, try `rustc --explain E0271`. From 22a0e4fa6e08acf2de50ed87cfb909092ab0459d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 13 Jan 2023 20:50:34 +0000 Subject: [PATCH 08/10] Do not incorrectly suggest restricting implied bounds When we have already suggested bounds that imply the about to be suggested bound, skip them. --- .../rustc_hir_typeck/src/method/suggest.rs | 48 ++++++++++++++----- .../ui/missing-trait-bounds/issue-35677.fixed | 2 +- .../missing-trait-bounds/issue-35677.stderr | 4 +- 3 files changed, 38 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 338fabca38919..f49fde04e8444 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -505,19 +505,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } _ => None, }; - if let Some(hir::Node::Item(hir::Item { kind, .. })) = node { - if let Some(g) = kind.generics() { - let key = ( - g.tail_span_for_predicate_suggestion(), - g.add_where_or_trailing_comma(), - ); - type_params - .entry(key) - .or_insert_with(FxHashSet::default) - .insert(obligation.to_owned()); - } + if let Some(hir::Node::Item(hir::Item { kind, .. })) = node + && let Some(g) = kind.generics() + { + let key = ( + g.tail_span_for_predicate_suggestion(), + g.add_where_or_trailing_comma(), + ); + type_params + .entry(key) + .or_insert_with(FxHashSet::default) + .insert(obligation.to_owned()); + return true; } } + false }; let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| { let msg = format!( @@ -732,19 +734,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { unsatisfied_bounds = true; } + let mut suggested_bounds = FxHashSet::default(); // The requirements that didn't have an `impl` span to show. let mut bound_list = unsatisfied_predicates .iter() .filter_map(|(pred, parent_pred, _cause)| { + let mut suggested = false; format_pred(*pred).map(|(p, self_ty)| { - collect_type_param_suggestions(self_ty, *pred, &p); + if let Some(parent) = parent_pred && suggested_bounds.contains(parent) { + // We don't suggest `PartialEq` when we already suggest `Eq`. + } else if !suggested_bounds.contains(pred) { + if collect_type_param_suggestions(self_ty, *pred, &p) { + suggested = true; + suggested_bounds.insert(pred); + } + } ( match parent_pred { None => format!("`{}`", &p), Some(parent_pred) => match format_pred(*parent_pred) { None => format!("`{}`", &p), Some((parent_p, _)) => { - collect_type_param_suggestions(self_ty, *parent_pred, &p); + if !suggested + && !suggested_bounds.contains(pred) + && !suggested_bounds.contains(parent_pred) + { + if collect_type_param_suggestions( + self_ty, + *parent_pred, + &p, + ) { + suggested_bounds.insert(pred); + } + } format!("`{}`\nwhich is required by `{}`", p, parent_p) } }, diff --git a/tests/ui/missing-trait-bounds/issue-35677.fixed b/tests/ui/missing-trait-bounds/issue-35677.fixed index c76b6bc9c1851..08174d8d8d53a 100644 --- a/tests/ui/missing-trait-bounds/issue-35677.fixed +++ b/tests/ui/missing-trait-bounds/issue-35677.fixed @@ -3,7 +3,7 @@ use std::collections::HashSet; use std::hash::Hash; -fn is_subset(this: &HashSet, other: &HashSet) -> bool where T: Eq, T: Hash, T: PartialEq { +fn is_subset(this: &HashSet, other: &HashSet) -> bool where T: Eq, T: Hash { this.is_subset(other) //~^ ERROR the method } diff --git a/tests/ui/missing-trait-bounds/issue-35677.stderr b/tests/ui/missing-trait-bounds/issue-35677.stderr index 067b10b873abf..05d3de80d8449 100644 --- a/tests/ui/missing-trait-bounds/issue-35677.stderr +++ b/tests/ui/missing-trait-bounds/issue-35677.stderr @@ -11,8 +11,8 @@ LL | this.is_subset(other) `T: Hash` help: consider restricting the type parameters to satisfy the trait bounds | -LL | fn is_subset(this: &HashSet, other: &HashSet) -> bool where T: Eq, T: Hash, T: PartialEq { - | ++++++++++++++++++++++++++++++++++ +LL | fn is_subset(this: &HashSet, other: &HashSet) -> bool where T: Eq, T: Hash { + | ++++++++++++++++++++ error: aborting due to previous error From b047aec122c291a6e9e32e45ec2c4d715f6415ab Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 9 Jan 2023 09:00:09 -0800 Subject: [PATCH 09/10] Update the wasi-libc used for the wasm32-wasi target This commit updates the wasi-libc revision used to build with the wasm32-wasi target. This notably pulls in WebAssembly/wasi-libc#377 which is needed to fix a use case I've been working on recently. This should be a relatively small update hopefully and is not expected to have any user impact. --- .../docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 67cee0148b24e..5fbce36c39d28 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" \ From a1614d0cf8472a20717135a377e55281fab440dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 14 Jan 2023 01:17:18 +0000 Subject: [PATCH 10/10] Use GitHub yaml templates for ICE, Docs and Diagnostics tickets --- .github/ISSUE_TEMPLATE/diagnostics.md | 46 ------------- .github/ISSUE_TEMPLATE/diagnostics.yaml | 65 ++++++++++++++++++ .github/ISSUE_TEMPLATE/documentation.md | 31 --------- .github/ISSUE_TEMPLATE/documentation.yaml | 38 +++++++++++ .github/ISSUE_TEMPLATE/ice.md | 52 -------------- .github/ISSUE_TEMPLATE/ice.yaml | 82 +++++++++++++++++++++++ 6 files changed, 185 insertions(+), 129 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/diagnostics.md create mode 100644 .github/ISSUE_TEMPLATE/diagnostics.yaml delete mode 100644 .github/ISSUE_TEMPLATE/documentation.md create mode 100644 .github/ISSUE_TEMPLATE/documentation.yaml delete mode 100644 .github/ISSUE_TEMPLATE/ice.md create mode 100644 .github/ISSUE_TEMPLATE/ice.yaml diff --git a/.github/ISSUE_TEMPLATE/diagnostics.md b/.github/ISSUE_TEMPLATE/diagnostics.md deleted file mode 100644 index a7b70cea927d0..0000000000000 --- a/.github/ISSUE_TEMPLATE/diagnostics.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -name: Diagnostic issue -about: Create a bug report or feature request for a change to `rustc`'s error output -labels: A-diagnostics, T-compiler ---- - - -Given the following code: - -```rust - -``` - -The current output is: - -``` - -``` - - -Ideally the output should look like: - -``` - -``` - - - - diff --git a/.github/ISSUE_TEMPLATE/diagnostics.yaml b/.github/ISSUE_TEMPLATE/diagnostics.yaml new file mode 100644 index 0000000000000..873fbaaf654fd --- /dev/null +++ b/.github/ISSUE_TEMPLATE/diagnostics.yaml @@ -0,0 +1,65 @@ +name: Diagnostic issue +description: Create a bug report or feature request for a change to `rustc`'s error output +labels: ["A-diagnostics", "T-compiler"] +body: + - type: markdown + attributes: + value: | + Thank you for filing a diagnostics bug report! 🐛 + + Please provide a short summary of the bug, along with any information you feel relevant to replicating the bug. + + If you cannot produce a minimal reproduction case (something that would work in isolation), please provide the steps or even link to a repository that causes the problematic output to occur. + - type: textarea + id: code + attributes: + label: Code + description: Please provide code that can reproduce the problem + placeholder: code + render: Rust + validations: + required: true + - type: textarea + id: output + attributes: + label: Current output + description: Please provide the `rustc` output you see + placeholder: rustc output + render: Shell + validations: + required: true + - type: textarea + id: desired-output + attributes: + label: Desired output + description: Please provide what the output *should* be + placeholder: proposed output + render: Shell + validations: + required: false + - type: textarea + id: rationale + attributes: + label: Rationale and extra context + description: If the problem is not self-explanatory, please provide a rationale for the change. + validations: + required: false + - type: textarea + id: other-output + attributes: + label: Other cases + description: If dramatically different output is caused by small changes, consider also adding them here. + render: Rust + validations: + required: false + - type: markdown + attributes: + value: | + If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. The output might also be different depending on the Edition. + - type: textarea + id: extra + attributes: + label: Anything else? + description: If you have more details you want to give us to reproduce this issue, please add it here + validations: + required: false \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/documentation.md b/.github/ISSUE_TEMPLATE/documentation.md deleted file mode 100644 index 9ccda17a6ef47..0000000000000 --- a/.github/ISSUE_TEMPLATE/documentation.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -name: Documentation problem -about: Create a report for a documentation problem. -labels: A-docs ---- - - -### Location - -### Summary diff --git a/.github/ISSUE_TEMPLATE/documentation.yaml b/.github/ISSUE_TEMPLATE/documentation.yaml new file mode 100644 index 0000000000000..712b32759ae01 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/documentation.yaml @@ -0,0 +1,38 @@ +name: Documentation problem +description: Create a report for a documentation problem. +labels: ["A-docs"] +body: + - type: markdown + attributes: + value: | + Thank you for finding a documentation problem! 📚 + + Documentation problems might be grammatical issues, typos, or unclear wording, please provide details regarding the documentation including where it is present. + + Note: If your issue is for one of these, please use their dedicated issue tracker instead: + - [The Rust Book](https://github.com/rust-lang/book/issues) + - [Rust by Example](https://github.com/rust-lang/rust-by-example/issues) + - [The Edition Guide](https://github.com/rust-lang/edition-guide/issues) + - [The Cargo Book](https://github.com/rust-lang/cargo/issues) + - [The Clippy Book](https://github.com/rust-lang/rust-clippy/issues) + - [The Reference](https://github.com/rust-lang/reference/issues) + - [The Rustonomicon](https://github.com/rust-lang/nomicon/issues) + - [The Embedded Book](https://github.com/rust-embedded/book/issues) + + All other documentation issues should be filed here. + + Or, if you find an issue related to rustdoc (e.g. doctest, rustdoc UI), please use the bug report or blank issue template instead. + + - type: textarea + id: location + attributes: + label: Location + validations: + required: true + + - type: textarea + id: summary + attributes: + label: Summary + validations: + required: true \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/ice.md b/.github/ISSUE_TEMPLATE/ice.md deleted file mode 100644 index 03bc4bab45137..0000000000000 --- a/.github/ISSUE_TEMPLATE/ice.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -name: Internal Compiler Error -about: Create a report for an internal compiler error in rustc. -labels: C-bug, I-ICE, T-compiler ---- - - -### Code - -```Rust - -``` - - -### Meta - - -`rustc --version --verbose`: -``` - -``` - -### Error output - -``` - -``` - - -

Backtrace -

- -``` - -``` - -

-
- diff --git a/.github/ISSUE_TEMPLATE/ice.yaml b/.github/ISSUE_TEMPLATE/ice.yaml new file mode 100644 index 0000000000000..54136cc6d439d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/ice.yaml @@ -0,0 +1,82 @@ +name: Internal Compiler Error +description: Create a report for an internal compiler error in `rustc` +labels: ["C-bug", "I-ICE", "T-compiler"] +title: "[ICE]: " +body: + - type: markdown + attributes: + value: | + Thank you for finding an Internal Compiler Error! 🧊 + + If possible, try to provide a minimal verifiable example. + + You can read "[Rust Bug Minimization Patterns](http://blog.pnkfx.org/blog/2019/11/18/rust-bug-minimization-patterns/)" for how to create smaller examples. + + - type: textarea + id: code + attributes: + label: Code + description: Please provide code or a link to a repository that can reproduce the problem + placeholder: code + render: Rust + validations: + required: false + + - type: checkboxes + attributes: + label: Affected release channels + description: If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions + options: + - label: Previous Stable + required: false + - label: Current Stable + required: false + - label: Current Beta + required: false + - label: Current Nightly + required: false + + - type: textarea + id: version + attributes: + label: Rust Version + description: Please provide the `rustc` version, `rustc --version --verbose` + placeholder: | + $ rustc --version --verbose + rustc 1.XX.Y (SHORTHASH DATE) + binary: rustc + commit-hash: LONGHASHVALUE + commit-date: DATE + host: PLATFORMTRIPLE + release: 1.XX.Y + LLVM version: XX.YY.ZZ + render: Shell + validations: + required: true + + - type: textarea + id: output + attributes: + label: Current error output + description: Please provide the `rustc` output you see + placeholder: output + render: Shell + validations: + required: false + + - type: textarea + id: backtrace + attributes: + label: Backtrace + description: Include a backtrace in the code block by setting `RUST_BACKTRACE=full` in your environment, e.g. `RUST_BACKTRACE=full cargo build` + render: Shell + validations: + required: true + + - type: textarea + id: extra + attributes: + label: Anything else? + description: If you have more details you want to give us to reproduce this issue, please add it here + validations: + required: false \ No newline at end of file