From bd287fa5084f2e153c1044632f9f3d190f090d69 Mon Sep 17 00:00:00 2001 From: Hans Kratz Date: Wed, 10 Nov 2021 20:24:33 +0100 Subject: [PATCH 01/20] Disable aarch64 outline atomics with musl for now. The introduced dependency on `getauxval`causes linking problems with musl, see #89626. --- .../rustc_target/src/spec/aarch64_unknown_linux_musl.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs index 0770f3496c279..6a16b4ce41964 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs @@ -9,10 +9,6 @@ pub fn target() -> Target { pointer_width: 64, data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(), arch: "aarch64".to_string(), - options: TargetOptions { - features: "+outline-atomics".to_string(), - mcount: "\u{1}_mcount".to_string(), - ..base - }, + options: TargetOptions { mcount: "\u{1}_mcount".to_string(), ..base }, } } From e6ab982d462994dc21a81561ae03bac476431b96 Mon Sep 17 00:00:00 2001 From: Jacob Hoffman-Andrews Date: Fri, 19 Nov 2021 22:47:07 -0800 Subject: [PATCH 02/20] Reduce prominence of item-infos - Remove border. - Reduce size of emoji slightly. - Remove details disclosure for unstable reason. This was inconsistent with our other details disclosures, and the detail revealed was usually better explained by clicking on the issue link. --- src/librustdoc/html/render/mod.rs | 18 +----------------- src/librustdoc/html/static/css/rustdoc.css | 4 +--- src/test/rustdoc-gui/item-info-width.goml | 2 +- src/test/rustdoc/issue-32374.rs | 9 +-------- 4 files changed, 4 insertions(+), 29 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index dd592de41bd6c..0ab6494d18453 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -682,7 +682,7 @@ fn short_item_info( // Render unstable items. But don't render "rustc_private" crates (internal compiler crates). // Those crates are permanently unstable so it makes no sense to render "unstable" everywhere. - if let Some((StabilityLevel::Unstable { reason, issue, .. }, feature)) = item + if let Some((StabilityLevel::Unstable { reason: _, issue, .. }, feature)) = item .stability(cx.tcx()) .as_ref() .filter(|stab| stab.feature != sym::rustc_private) @@ -702,22 +702,6 @@ fn short_item_info( message.push_str(&format!(" ({})", feature)); - if let Some(unstable_reason) = reason { - let mut ids = cx.id_map.borrow_mut(); - message = format!( - "
{}{}
", - message, - MarkdownHtml( - &unstable_reason.as_str(), - &mut ids, - error_codes, - cx.shared.edition(), - &cx.shared.playground, - ) - .into_string() - ); - } - extra_info.push(format!("
{}
", message)); } diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 89a763ef6d707..26ba023606d09 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -965,8 +965,6 @@ body.blur > :not(#help) { display: table; } .stab { - border-width: 1px; - border-style: solid; padding: 3px; margin-bottom: 5px; font-size: 90%; @@ -977,7 +975,7 @@ body.blur > :not(#help) { } .stab .emoji { - font-size: 1.5em; + font-size: 1.2em; } /* Black one-pixel outline around emoji shapes */ diff --git a/src/test/rustdoc-gui/item-info-width.goml b/src/test/rustdoc-gui/item-info-width.goml index 44b79e60912c6..cdc00d3411403 100644 --- a/src/test/rustdoc-gui/item-info-width.goml +++ b/src/test/rustdoc-gui/item-info-width.goml @@ -4,4 +4,4 @@ goto: file://|DOC_PATH|/lib2/struct.Foo.html size: (1100, 800) // We check that ".item-info" is bigger than its content. assert-css: (".item-info", {"width": "807px"}) -assert-css: (".item-info .stab", {"width": "343px"}) +assert-css: (".item-info .stab", {"width": "341px"}) diff --git a/src/test/rustdoc/issue-32374.rs b/src/test/rustdoc/issue-32374.rs index 4e92ae49a20af..7654a5615275a 100644 --- a/src/test/rustdoc/issue-32374.rs +++ b/src/test/rustdoc/issue-32374.rs @@ -1,7 +1,6 @@ #![feature(staged_api)] #![doc(issue_tracker_base_url = "https://issue_url/")] - -#![unstable(feature="test", issue = "32374")] +#![unstable(feature = "test", issue = "32374")] // @matches issue_32374/index.html '//*[@class="item-left unstable deprecated module-item"]/span[@class="stab deprecated"]' \ // 'Deprecated' @@ -23,12 +22,6 @@ pub struct T; // '๐Ÿ‘Ž Deprecated since 1.0.0: deprecated' // @has issue_32374/struct.U.html '//*[@class="stab unstable"]' \ // '๐Ÿ”ฌ This is a nightly-only experimental API. (test #32374)' -// @has issue_32374/struct.U.html '//details' \ -// '๐Ÿ”ฌ This is a nightly-only experimental API. (test #32374)' -// @has issue_32374/struct.U.html '//summary' \ -// '๐Ÿ”ฌ This is a nightly-only experimental API. (test #32374)' -// @has issue_32374/struct.U.html '//details/p' \ -// 'unstable' #[rustc_deprecated(since = "1.0.0", reason = "deprecated")] #[unstable(feature = "test", issue = "32374", reason = "unstable")] pub struct U; From 0e1c21132aeb4d9525918fb91f7afebd4ca5c682 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 6 May 2021 19:09:35 -0700 Subject: [PATCH 03/20] On type mismatch caused by assignment, point at assignee * Do not emit unnecessary E0308 after E0070 * Show fewer errors on `while let` missing `let` * Hide redundant E0308 on `while let` missing `let` * Point at binding definition when possible on invalid assignment * do not point at closure twice * do not suggest `if let` for literals in lhs * account for parameter types --- compiler/rustc_ast_lowering/src/expr.rs | 16 +++- compiler/rustc_typeck/src/check/coercion.rs | 20 ++++- compiler/rustc_typeck/src/check/demand.rs | 81 +++++++++++++++++-- compiler/rustc_typeck/src/check/expr.rs | 57 +++++++++++-- .../rustc_typeck/src/check/fn_ctxt/checks.rs | 18 +++++ compiler/rustc_typeck/src/check/op.rs | 2 +- src/test/ui/dst/dst-bad-assign-3.stderr | 4 +- src/test/ui/dst/dst-bad-assign.stderr | 4 +- src/test/ui/error-codes/E0070.rs | 1 - src/test/ui/error-codes/E0070.stderr | 11 +-- .../fully-qualified-type-name1.rs | 8 +- .../fully-qualified-type-name1.stderr | 6 +- .../ui/impl-trait/impl-trait-in-macro.stderr | 2 + .../universal-two-impl-traits.stderr | 1 + .../ui/integral-variable-unification-error.rs | 6 +- ...integral-variable-unification-error.stderr | 7 +- src/test/ui/issues/issue-13407.rs | 1 - src/test/ui/issues/issue-13407.stderr | 10 +-- src/test/ui/issues/issue-2951.stderr | 1 + src/test/ui/issues/issue-53348.rs | 2 +- src/test/ui/issues/issue-53348.stderr | 3 + src/test/ui/issues/issue-77218.rs | 11 --- src/test/ui/issues/issue-77218.stderr | 40 --------- .../ui/issues/issue-77218/issue-77218-2.fixed | 7 ++ .../ui/issues/issue-77218/issue-77218-2.rs | 7 ++ .../issues/issue-77218/issue-77218-2.stderr | 16 ++++ .../ui/issues/issue-77218/issue-77218.fixed | 6 ++ src/test/ui/issues/issue-77218/issue-77218.rs | 6 ++ .../ui/issues/issue-77218/issue-77218.stderr | 18 +++++ .../ui/mismatched_types/issue-84976.stderr | 6 ++ src/test/ui/output-type-mismatch.stderr | 4 +- .../ui/static/static-mut-bad-types.stderr | 4 +- src/test/ui/suggestions/if-let-typo.stderr | 5 -- .../suggestions/mut-ref-reassignment.stderr | 8 ++ .../argument-types.stderr | 2 + .../assignment-expected-bool.stderr | 4 - .../type/type-check/assignment-in-if.stderr | 4 - src/test/ui/typeck/issue-81293.stderr | 3 + ...sue-87771-ice-assign-assign-to-bool.stderr | 2 + 39 files changed, 297 insertions(+), 117 deletions(-) delete mode 100644 src/test/ui/issues/issue-77218.rs delete mode 100644 src/test/ui/issues/issue-77218.stderr create mode 100644 src/test/ui/issues/issue-77218/issue-77218-2.fixed create mode 100644 src/test/ui/issues/issue-77218/issue-77218-2.rs create mode 100644 src/test/ui/issues/issue-77218/issue-77218-2.stderr create mode 100644 src/test/ui/issues/issue-77218/issue-77218.fixed create mode 100644 src/test/ui/issues/issue-77218/issue-77218.rs create mode 100644 src/test/ui/issues/issue-77218/issue-77218.stderr diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 405e9035c4c19..4adf20f7347a9 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -915,14 +915,22 @@ impl<'hir> LoweringContext<'_, 'hir> { ); } if !self.sess.features_untracked().destructuring_assignment { - feature_err( + let mut err = feature_err( &self.sess.parse_sess, sym::destructuring_assignment, eq_sign_span, "destructuring assignments are unstable", - ) - .span_label(lhs.span, "cannot assign to this expression") - .emit(); + ); + err.span_label(lhs.span, "cannot assign to this expression"); + if self.is_in_loop_condition { + err.span_suggestion_verbose( + lhs.span.shrink_to_lo(), + "you might have meant to use pattern destructuring", + "let ".to_string(), + rustc_errors::Applicability::MachineApplicable, + ); + } + err.emit(); } let mut assignments = vec![]; diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs index 28712e0658269..77f7cccc04ba4 100644 --- a/compiler/rustc_typeck/src/check/coercion.rs +++ b/compiler/rustc_typeck/src/check/coercion.rs @@ -1458,7 +1458,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { cause, expected, found, - coercion_error, + coercion_error.clone(), fcx, parent_id, expression.map(|expr| (expr, blk_id)), @@ -1472,7 +1472,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { cause, expected, found, - coercion_error, + coercion_error.clone(), fcx, id, None, @@ -1483,7 +1483,12 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { } } _ => { - err = fcx.report_mismatched_types(cause, expected, found, coercion_error); + err = fcx.report_mismatched_types( + cause, + expected, + found, + coercion_error.clone(), + ); } } @@ -1492,7 +1497,14 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { } if let Some(expr) = expression { - fcx.emit_coerce_suggestions(&mut err, expr, found, expected, None); + fcx.emit_coerce_suggestions( + &mut err, + expr, + found, + expected, + None, + coercion_error, + ); } err.emit_unless(unsized_return); diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index ece2d7b4f3793..5d121913aac98 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -10,6 +10,7 @@ use rustc_hir::lang_items::LangItem; use rustc_hir::{is_range_literal, Node}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::adjustment::AllowTwoPhase; +use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, AssocItem, Ty, TypeAndMut}; use rustc_span::symbol::sym; @@ -27,8 +28,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr_ty: Ty<'tcx>, expected: Ty<'tcx>, expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>, + error: TypeError<'tcx>, ) { - self.annotate_expected_due_to_let_ty(err, expr); + self.annotate_expected_due_to_let_ty(err, expr, error); self.suggest_box_deref(err, expr, expected, expr_ty); self.suggest_compatible_variants(err, expr, expected, expr_ty); self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr); @@ -145,9 +147,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let expr = expr.peel_drop_temps(); let cause = self.misc(expr.span); let expr_ty = self.resolve_vars_with_obligations(checked_ty); - let mut err = self.report_mismatched_types(&cause, expected, expr_ty, e); + let mut err = self.report_mismatched_types(&cause, expected, expr_ty, e.clone()); - self.emit_coerce_suggestions(&mut err, expr, expr_ty, expected, expected_ty_expr); + self.emit_coerce_suggestions(&mut err, expr, expr_ty, expected, expected_ty_expr, e); (expected, Some(err)) } @@ -156,15 +158,80 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, err: &mut DiagnosticBuilder<'_>, expr: &hir::Expr<'_>, + error: TypeError<'_>, ) { let parent = self.tcx.hir().get_parent_node(expr.hir_id); - if let Some(hir::Node::Local(hir::Local { ty: Some(ty), init: Some(init), .. })) = - self.tcx.hir().find(parent) - { - if init.hir_id == expr.hir_id { + match (self.tcx.hir().find(parent), error) { + (Some(hir::Node::Local(hir::Local { ty: Some(ty), init: Some(init), .. })), _) + if init.hir_id == expr.hir_id => + { // Point at `let` assignment type. err.span_label(ty.span, "expected due to this"); } + ( + Some(hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::Assign(lhs, rhs, _), .. + })), + TypeError::Sorts(ExpectedFound { expected, .. }), + ) if rhs.hir_id == expr.hir_id && !expected.is_closure() => { + // We ignore closures explicitly because we already point at them elsewhere. + // Point at the assigned-to binding. + let mut primary_span = lhs.span; + let mut secondary_span = lhs.span; + let mut post_message = ""; + if let hir::ExprKind::Path(hir::QPath::Resolved( + None, + hir::Path { res: hir::def::Res::Local(hir_id), .. }, + )) = lhs.kind + { + if let Some(hir::Node::Binding(pat)) = self.tcx.hir().find(*hir_id) { + let parent = self.tcx.hir().get_parent_node(pat.hir_id); + primary_span = pat.span; + secondary_span = pat.span; + match self.tcx.hir().find(parent) { + Some(hir::Node::Local(hir::Local { ty: Some(ty), .. })) => { + primary_span = ty.span; + post_message = " type"; + } + Some(hir::Node::Local(hir::Local { init: Some(init), .. })) => { + primary_span = init.span; + post_message = " value"; + } + Some(hir::Node::Param(hir::Param { ty_span, .. })) => { + primary_span = *ty_span; + post_message = " parameter type"; + } + _ => {} + } + } + } + + if primary_span != secondary_span + && self + .tcx + .sess + .source_map() + .is_multiline(secondary_span.shrink_to_hi().until(primary_span)) + { + // We are pointing at the binding's type or initializer value, but it's pattern + // is in a different line, so we point at both. + err.span_label(secondary_span, "expected due to the type of this binding"); + err.span_label(primary_span, &format!("expected due to this{}", post_message)); + } else if post_message == "" { + // We are pointing at either the assignment lhs or the binding def pattern. + err.span_label(primary_span, "expected due to the type of this binding"); + } else { + // We are pointing at the binding's type or initializer value. + err.span_label(primary_span, &format!("expected due to this{}", post_message)); + } + + if !lhs.is_syntactic_place_expr() { + // We already emitted E0070 "invalid left-hand side of assignment", so we + // silence this. + err.delay_as_bug(); + } + } + _ => {} } } diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index c9fa0fd72fc50..eb997b014c77b 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -833,7 +833,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, lhs: &'tcx hir::Expr<'tcx>, err_code: &'static str, - expr_span: &Span, + op_span: Span, ) { if lhs.is_syntactic_place_expr() { return; @@ -841,11 +841,58 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // FIXME: Make this use SessionDiagnostic once error codes can be dynamically set. let mut err = self.tcx.sess.struct_span_err_with_code( - *expr_span, + op_span, "invalid left-hand side of assignment", DiagnosticId::Error(err_code.into()), ); err.span_label(lhs.span, "cannot assign to this expression"); + + let mut parent = self.tcx.hir().get_parent_node(lhs.hir_id); + while let Some(node) = self.tcx.hir().find(parent) { + match node { + hir::Node::Expr(hir::Expr { + kind: + hir::ExprKind::Loop( + hir::Block { + expr: + Some(hir::Expr { + kind: + hir::ExprKind::Match(expr, ..) | hir::ExprKind::If(expr, ..), + .. + }), + .. + }, + _, + hir::LoopSource::While, + _, + ), + .. + }) => { + // We have a situation like `while Some(0) = value.get(0) {`, where `while let` + // was more likely intended. + err.span_suggestion_verbose( + expr.span.shrink_to_lo(), + "you might have meant to use pattern destructuring", + "let ".to_string(), + Applicability::MachineApplicable, + ); + if !self.sess().features_untracked().destructuring_assignment { + // We already emit an E0658 with a suggestion for `while let`, this is + // redundant output. + err.delay_as_bug(); + } + break; + } + hir::Node::Item(_) + | hir::Node::ImplItem(_) + | hir::Node::TraitItem(_) + | hir::Node::Crate(_) => break, + _ => { + parent = self.tcx.hir().get_parent_node(parent); + } + } + } + err.emit(); } @@ -953,7 +1000,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { (Applicability::MaybeIncorrect, false) }; - if !lhs.is_syntactic_place_expr() { + if !lhs.is_syntactic_place_expr() && !matches!(lhs.kind, hir::ExprKind::Lit(_)) { // Do not suggest `if let x = y` as `==` is way more likely to be the intention. let hir = self.tcx.hir(); if let hir::Node::Expr(hir::Expr { kind: ExprKind::If { .. }, .. }) = @@ -965,7 +1012,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "let ".to_string(), applicability, ); - } + }; } if eq { err.span_suggestion_verbose( @@ -986,7 +1033,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return self.tcx.ty_error(); } - self.check_lhs_assignable(lhs, "E0070", span); + self.check_lhs_assignable(lhs, "E0070", *span); let lhs_ty = self.check_expr_with_needs(&lhs, Needs::MutPlace); let rhs_ty = self.check_expr_coercable_to_type(&rhs, lhs_ty, Some(lhs)); diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index 7d9483201f6a5..d36dc74ef254b 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -740,6 +740,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &mut |err| { if let Some(expected_ty) = expected.only_has_type(self) { self.consider_hint_about_removing_semicolon(blk, expected_ty, err); + if expected_ty == self.tcx.types.bool { + // If this is caused by a missing `let` in a `while let`, + // silence this redundant error, as we already emit E0070. + let parent = self.tcx.hir().get_parent_node(blk.hir_id); + let parent = self.tcx.hir().get_parent_node(parent); + let parent = self.tcx.hir().get_parent_node(parent); + let parent = self.tcx.hir().get_parent_node(parent); + let parent = self.tcx.hir().get_parent_node(parent); + match self.tcx.hir().find(parent) { + Some(hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::Loop(_, _, hir::LoopSource::While, _), + .. + })) => { + err.delay_as_bug(); + } + _ => {} + } + } } if let Some(fn_span) = fn_span { err.span_label( diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs index 9c53a1d4eb68d..f83209f57a897 100644 --- a/compiler/rustc_typeck/src/check/op.rs +++ b/compiler/rustc_typeck/src/check/op.rs @@ -42,7 +42,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return_ty }; - self.check_lhs_assignable(lhs, "E0067", &op.span); + self.check_lhs_assignable(lhs, "E0067", op.span); ty } diff --git a/src/test/ui/dst/dst-bad-assign-3.stderr b/src/test/ui/dst/dst-bad-assign-3.stderr index 04e46233532b2..b326dbbbc1405 100644 --- a/src/test/ui/dst/dst-bad-assign-3.stderr +++ b/src/test/ui/dst/dst-bad-assign-3.stderr @@ -2,7 +2,9 @@ error[E0308]: mismatched types --> $DIR/dst-bad-assign-3.rs:33:12 | LL | f5.2 = Bar1 {f: 36}; - | ^^^^^^^^^^^^ expected trait object `dyn ToBar`, found struct `Bar1` + | ---- ^^^^^^^^^^^^ expected trait object `dyn ToBar`, found struct `Bar1` + | | + | expected due to the type of this binding | = note: expected trait object `dyn ToBar` found struct `Bar1` diff --git a/src/test/ui/dst/dst-bad-assign.stderr b/src/test/ui/dst/dst-bad-assign.stderr index f87a34c6d3783..614f213875129 100644 --- a/src/test/ui/dst/dst-bad-assign.stderr +++ b/src/test/ui/dst/dst-bad-assign.stderr @@ -2,7 +2,9 @@ error[E0308]: mismatched types --> $DIR/dst-bad-assign.rs:35:14 | LL | f5.ptr = Bar1 {f: 36}; - | ^^^^^^^^^^^^ expected trait object `dyn ToBar`, found struct `Bar1` + | ------ ^^^^^^^^^^^^ expected trait object `dyn ToBar`, found struct `Bar1` + | | + | expected due to the type of this binding | = note: expected trait object `dyn ToBar` found struct `Bar1` diff --git a/src/test/ui/error-codes/E0070.rs b/src/test/ui/error-codes/E0070.rs index ab956d8109838..3aae0c9ff6e72 100644 --- a/src/test/ui/error-codes/E0070.rs +++ b/src/test/ui/error-codes/E0070.rs @@ -6,7 +6,6 @@ fn some_function() { SOME_CONST = 14; //~ ERROR E0070 1 = 3; //~ ERROR E0070 some_other_func() = 4; //~ ERROR E0070 - //~^ ERROR E0308 } fn main() { diff --git a/src/test/ui/error-codes/E0070.stderr b/src/test/ui/error-codes/E0070.stderr index e24d498e3520c..8868bc257a703 100644 --- a/src/test/ui/error-codes/E0070.stderr +++ b/src/test/ui/error-codes/E0070.stderr @@ -22,13 +22,6 @@ LL | some_other_func() = 4; | | | cannot assign to this expression -error[E0308]: mismatched types - --> $DIR/E0070.rs:8:25 - | -LL | some_other_func() = 4; - | ^ expected `()`, found integer - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0070, E0308. -For more information about an error, try `rustc --explain E0070`. +For more information about this error, try `rustc --explain E0070`. diff --git a/src/test/ui/fully-qualified-type/fully-qualified-type-name1.rs b/src/test/ui/fully-qualified-type/fully-qualified-type-name1.rs index 1c6b9805b51b6..229c174daa864 100644 --- a/src/test/ui/fully-qualified-type/fully-qualified-type-name1.rs +++ b/src/test/ui/fully-qualified-type/fully-qualified-type-name1.rs @@ -1,10 +1,10 @@ // Test that we use fully-qualified type names in error messages. fn main() { - let x: Option; + let x: //~ NOTE expected due to the type of this binding + Option; //~ NOTE expected due to this type x = 5; //~^ ERROR mismatched types - //~| expected enum `Option` - //~| found type `{integer}` - //~| expected enum `Option`, found integer + //~| NOTE expected enum `Option` + //~| NOTE expected enum `Option`, found integer } diff --git a/src/test/ui/fully-qualified-type/fully-qualified-type-name1.stderr b/src/test/ui/fully-qualified-type/fully-qualified-type-name1.stderr index 03fb299b39cd2..4750c5ccdf702 100644 --- a/src/test/ui/fully-qualified-type/fully-qualified-type-name1.stderr +++ b/src/test/ui/fully-qualified-type/fully-qualified-type-name1.stderr @@ -1,6 +1,10 @@ error[E0308]: mismatched types - --> $DIR/fully-qualified-type-name1.rs:5:9 + --> $DIR/fully-qualified-type-name1.rs:6:9 | +LL | let x: + | - expected due to the type of this binding +LL | Option; + | ------------- expected due to this type LL | x = 5; | ^ expected enum `Option`, found integer | diff --git a/src/test/ui/impl-trait/impl-trait-in-macro.stderr b/src/test/ui/impl-trait/impl-trait-in-macro.stderr index b5f9986ce4089..7cfbe3447b813 100644 --- a/src/test/ui/impl-trait/impl-trait-in-macro.stderr +++ b/src/test/ui/impl-trait/impl-trait-in-macro.stderr @@ -7,6 +7,8 @@ LL | ($($tr:tt)*) => { impl $($tr)* }; | expected type parameter | found type parameter ... +LL | let mut a = x; + | - expected due to this value LL | a = y; | ^ expected type parameter `impl Debug`, found a different type parameter `impl Debug` | diff --git a/src/test/ui/impl-trait/universal-two-impl-traits.stderr b/src/test/ui/impl-trait/universal-two-impl-traits.stderr index 7c120235fd176..ab8a53d0db399 100644 --- a/src/test/ui/impl-trait/universal-two-impl-traits.stderr +++ b/src/test/ui/impl-trait/universal-two-impl-traits.stderr @@ -6,6 +6,7 @@ LL | fn foo(x: impl Debug, y: impl Debug) -> String { | | | expected type parameter LL | let mut a = x; + | - expected due to this value LL | a = y; | ^ expected type parameter `impl Debug`, found a different type parameter `impl Debug` | diff --git a/src/test/ui/integral-variable-unification-error.rs b/src/test/ui/integral-variable-unification-error.rs index 5200b4a829db2..8d1621321e8e6 100644 --- a/src/test/ui/integral-variable-unification-error.rs +++ b/src/test/ui/integral-variable-unification-error.rs @@ -1,6 +1,8 @@ fn main() { - let mut x = 2; + let mut x //~ NOTE expected due to the type of this binding + = + 2; //~ NOTE expected due to this value x = 5.0; //~^ ERROR mismatched types - //~| expected integer, found floating-point number + //~| NOTE expected integer, found floating-point number } diff --git a/src/test/ui/integral-variable-unification-error.stderr b/src/test/ui/integral-variable-unification-error.stderr index b49bff1b0d84d..f77c265a2ada7 100644 --- a/src/test/ui/integral-variable-unification-error.stderr +++ b/src/test/ui/integral-variable-unification-error.stderr @@ -1,6 +1,11 @@ error[E0308]: mismatched types - --> $DIR/integral-variable-unification-error.rs:3:9 + --> $DIR/integral-variable-unification-error.rs:5:9 | +LL | let mut x + | ----- expected due to the type of this binding +LL | = +LL | 2; + | - expected due to this value LL | x = 5.0; | ^^^ expected integer, found floating-point number diff --git a/src/test/ui/issues/issue-13407.rs b/src/test/ui/issues/issue-13407.rs index fa53d55f5b3d7..7ea81ffb59e7e 100644 --- a/src/test/ui/issues/issue-13407.rs +++ b/src/test/ui/issues/issue-13407.rs @@ -5,6 +5,5 @@ mod A { fn main() { A::C = 1; //~^ ERROR: invalid left-hand side of assignment - //~| ERROR: mismatched types //~| ERROR: struct `C` is private } diff --git a/src/test/ui/issues/issue-13407.stderr b/src/test/ui/issues/issue-13407.stderr index 4df1813a710ff..54b6c640d9d79 100644 --- a/src/test/ui/issues/issue-13407.stderr +++ b/src/test/ui/issues/issue-13407.stderr @@ -18,13 +18,7 @@ LL | A::C = 1; | | | cannot assign to this expression -error[E0308]: mismatched types - --> $DIR/issue-13407.rs:6:12 - | -LL | A::C = 1; - | ^ expected struct `C`, found integer - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0070, E0308, E0603. +Some errors have detailed explanations: E0070, E0603. For more information about an error, try `rustc --explain E0070`. diff --git a/src/test/ui/issues/issue-2951.stderr b/src/test/ui/issues/issue-2951.stderr index b966b33938917..538bbe2f50296 100644 --- a/src/test/ui/issues/issue-2951.stderr +++ b/src/test/ui/issues/issue-2951.stderr @@ -6,6 +6,7 @@ LL | fn foo(x: T, y: U) { | | | expected type parameter LL | let mut xx = x; + | - expected due to this value LL | xx = y; | ^ expected type parameter `T`, found type parameter `U` | diff --git a/src/test/ui/issues/issue-53348.rs b/src/test/ui/issues/issue-53348.rs index 65f4656b02266..d2f8c77c0ce11 100644 --- a/src/test/ui/issues/issue-53348.rs +++ b/src/test/ui/issues/issue-53348.rs @@ -5,7 +5,7 @@ fn main() { v.into_iter().map(|s|s.to_owned()).collect::>(); - let mut a = String::new(); + let mut a = String::new(); //~ NOTE expected due to this value for i in v { a = *i.to_string(); //~^ ERROR mismatched types diff --git a/src/test/ui/issues/issue-53348.stderr b/src/test/ui/issues/issue-53348.stderr index 8f500261243f1..71d9f5b3dbbff 100644 --- a/src/test/ui/issues/issue-53348.stderr +++ b/src/test/ui/issues/issue-53348.stderr @@ -1,6 +1,9 @@ error[E0308]: mismatched types --> $DIR/issue-53348.rs:10:13 | +LL | let mut a = String::new(); + | ------------- expected due to this value +LL | for i in v { LL | a = *i.to_string(); | ^^^^^^^^^^^^^^ expected struct `String`, found `str` diff --git a/src/test/ui/issues/issue-77218.rs b/src/test/ui/issues/issue-77218.rs deleted file mode 100644 index a6a2401795ff4..0000000000000 --- a/src/test/ui/issues/issue-77218.rs +++ /dev/null @@ -1,11 +0,0 @@ -fn main() { - let value = [7u8]; - while Some(0) = value.get(0) { //~ ERROR destructuring assignments are unstable - //~| ERROR invalid left-hand side of assignment - //~| ERROR mismatched types - //~| ERROR mismatched types - - // FIXME The following diagnostic should also be emitted - // HELP you might have meant to use pattern matching - } -} diff --git a/src/test/ui/issues/issue-77218.stderr b/src/test/ui/issues/issue-77218.stderr deleted file mode 100644 index ce70c0111bee2..0000000000000 --- a/src/test/ui/issues/issue-77218.stderr +++ /dev/null @@ -1,40 +0,0 @@ -error[E0658]: destructuring assignments are unstable - --> $DIR/issue-77218.rs:3:19 - | -LL | while Some(0) = value.get(0) { - | ------- ^ - | | - | cannot assign to this expression - | - = note: see issue #71126 for more information - = help: add `#![feature(destructuring_assignment)]` to the crate attributes to enable - -error[E0070]: invalid left-hand side of assignment - --> $DIR/issue-77218.rs:3:19 - | -LL | while Some(0) = value.get(0) { - | - ^ - | | - | cannot assign to this expression - -error[E0308]: mismatched types - --> $DIR/issue-77218.rs:3:16 - | -LL | while Some(0) = value.get(0) { - | ^ expected integer, found `&u8` - | -help: consider dereferencing the borrow - | -LL | while Some(*0) = value.get(0) { - | + - -error[E0308]: mismatched types - --> $DIR/issue-77218.rs:3:11 - | -LL | while Some(0) = value.get(0) { - | ^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()` - -error: aborting due to 4 previous errors - -Some errors have detailed explanations: E0070, E0308, E0658. -For more information about an error, try `rustc --explain E0070`. diff --git a/src/test/ui/issues/issue-77218/issue-77218-2.fixed b/src/test/ui/issues/issue-77218/issue-77218-2.fixed new file mode 100644 index 0000000000000..06487fe0886f9 --- /dev/null +++ b/src/test/ui/issues/issue-77218/issue-77218-2.fixed @@ -0,0 +1,7 @@ +// run-rustfix +#![feature(destructuring_assignment)] +fn main() { + let value = [7u8]; + while let Some(0) = value.get(0) { //~ ERROR invalid left-hand side of assignment + } +} diff --git a/src/test/ui/issues/issue-77218/issue-77218-2.rs b/src/test/ui/issues/issue-77218/issue-77218-2.rs new file mode 100644 index 0000000000000..e19cec08e4318 --- /dev/null +++ b/src/test/ui/issues/issue-77218/issue-77218-2.rs @@ -0,0 +1,7 @@ +// run-rustfix +#![feature(destructuring_assignment)] +fn main() { + let value = [7u8]; + while Some(0) = value.get(0) { //~ ERROR invalid left-hand side of assignment + } +} diff --git a/src/test/ui/issues/issue-77218/issue-77218-2.stderr b/src/test/ui/issues/issue-77218/issue-77218-2.stderr new file mode 100644 index 0000000000000..8d9eb2219d54c --- /dev/null +++ b/src/test/ui/issues/issue-77218/issue-77218-2.stderr @@ -0,0 +1,16 @@ +error[E0070]: invalid left-hand side of assignment + --> $DIR/issue-77218-2.rs:5:19 + | +LL | while Some(0) = value.get(0) { + | - ^ + | | + | cannot assign to this expression + | +help: you might have meant to use pattern destructuring + | +LL | while let Some(0) = value.get(0) { + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0070`. diff --git a/src/test/ui/issues/issue-77218/issue-77218.fixed b/src/test/ui/issues/issue-77218/issue-77218.fixed new file mode 100644 index 0000000000000..4ea5110902225 --- /dev/null +++ b/src/test/ui/issues/issue-77218/issue-77218.fixed @@ -0,0 +1,6 @@ +// run-rustfix +fn main() { + let value = [7u8]; + while let Some(0) = value.get(0) { //~ ERROR destructuring assignments are unstable + } +} diff --git a/src/test/ui/issues/issue-77218/issue-77218.rs b/src/test/ui/issues/issue-77218/issue-77218.rs new file mode 100644 index 0000000000000..0f3c12f56351d --- /dev/null +++ b/src/test/ui/issues/issue-77218/issue-77218.rs @@ -0,0 +1,6 @@ +// run-rustfix +fn main() { + let value = [7u8]; + while Some(0) = value.get(0) { //~ ERROR destructuring assignments are unstable + } +} diff --git a/src/test/ui/issues/issue-77218/issue-77218.stderr b/src/test/ui/issues/issue-77218/issue-77218.stderr new file mode 100644 index 0000000000000..54f49609a4427 --- /dev/null +++ b/src/test/ui/issues/issue-77218/issue-77218.stderr @@ -0,0 +1,18 @@ +error[E0658]: destructuring assignments are unstable + --> $DIR/issue-77218.rs:4:19 + | +LL | while Some(0) = value.get(0) { + | ------- ^ + | | + | cannot assign to this expression + | + = note: see issue #71126 for more information + = help: add `#![feature(destructuring_assignment)]` to the crate attributes to enable +help: you might have meant to use pattern destructuring + | +LL | while let Some(0) = value.get(0) { + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/mismatched_types/issue-84976.stderr b/src/test/ui/mismatched_types/issue-84976.stderr index 0c27e17294131..f8f2b1f0f5720 100644 --- a/src/test/ui/mismatched_types/issue-84976.stderr +++ b/src/test/ui/mismatched_types/issue-84976.stderr @@ -7,6 +7,9 @@ LL | length = { foo(&length) }; error[E0308]: mismatched types --> $DIR/issue-84976.rs:17:14 | +LL | let mut length = 0; + | - expected due to this value +... LL | length = foo(&length); | ^^^^^^^^^^^^ expected `u32`, found `i32` @@ -19,6 +22,9 @@ LL | float_length = { bar(&float_length) }; error[E0308]: mismatched types --> $DIR/issue-84976.rs:23:20 | +LL | let mut float_length = 0.0; + | --- expected due to this value +... LL | float_length = bar(&float_length); | ^^^^^^^^^^^^^^^^^^ expected `f32`, found `f64` diff --git a/src/test/ui/output-type-mismatch.stderr b/src/test/ui/output-type-mismatch.stderr index 533bd87c9cccb..4507a4df621e1 100644 --- a/src/test/ui/output-type-mismatch.stderr +++ b/src/test/ui/output-type-mismatch.stderr @@ -2,7 +2,9 @@ error[E0308]: mismatched types --> $DIR/output-type-mismatch.rs:5:31 | LL | fn main() { let i: isize; i = f(); } - | ^^^ expected `isize`, found `()` + | ----- ^^^ expected `isize`, found `()` + | | + | expected due to this type error: aborting due to previous error diff --git a/src/test/ui/static/static-mut-bad-types.stderr b/src/test/ui/static/static-mut-bad-types.stderr index ddd98ff40798a..e5a59de6f1461 100644 --- a/src/test/ui/static/static-mut-bad-types.stderr +++ b/src/test/ui/static/static-mut-bad-types.stderr @@ -2,7 +2,9 @@ error[E0308]: mismatched types --> $DIR/static-mut-bad-types.rs:5:13 | LL | a = true; - | ^^^^ expected `isize`, found `bool` + | - ^^^^ expected `isize`, found `bool` + | | + | expected due to the type of this binding error: aborting due to previous error diff --git a/src/test/ui/suggestions/if-let-typo.stderr b/src/test/ui/suggestions/if-let-typo.stderr index 7f71cb485815f..058f42f220064 100644 --- a/src/test/ui/suggestions/if-let-typo.stderr +++ b/src/test/ui/suggestions/if-let-typo.stderr @@ -70,11 +70,6 @@ error[E0308]: mismatched types | LL | if 3 = foo {} | ^^^^^^^ expected `bool`, found `()` - | -help: you might have meant to use pattern matching - | -LL | if let 3 = foo {} - | +++ error[E0070]: invalid left-hand side of assignment --> $DIR/if-let-typo.rs:10:16 diff --git a/src/test/ui/suggestions/mut-ref-reassignment.stderr b/src/test/ui/suggestions/mut-ref-reassignment.stderr index fd5677898e656..3bd98c7630780 100644 --- a/src/test/ui/suggestions/mut-ref-reassignment.stderr +++ b/src/test/ui/suggestions/mut-ref-reassignment.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/mut-ref-reassignment.rs:2:11 | +LL | fn suggestion(opt: &mut Option) { + | ------------------- expected due to this parameter type LL | opt = None; | ^^^^ expected mutable reference, found enum `Option` | @@ -14,6 +16,8 @@ LL | *opt = None; error[E0308]: mismatched types --> $DIR/mut-ref-reassignment.rs:6:11 | +LL | fn no_suggestion(opt: &mut Result) { + | ----------------------- expected due to this parameter type LL | opt = None | ^^^^ expected mutable reference, found enum `Option` | @@ -23,6 +27,8 @@ LL | opt = None error[E0308]: mismatched types --> $DIR/mut-ref-reassignment.rs:10:11 | +LL | fn suggestion2(opt: &mut Option) { + | ------------------- expected due to this parameter type LL | opt = Some(String::new()) | ^^^^^^^^^^^^^^^^^^^ expected mutable reference, found enum `Option` | @@ -36,6 +42,8 @@ LL | *opt = Some(String::new()) error[E0308]: mismatched types --> $DIR/mut-ref-reassignment.rs:14:11 | +LL | fn no_suggestion2(opt: &mut Option) { + | ------------------- expected due to this parameter type LL | opt = Some(42) | ^^^^^^^^ expected mutable reference, found enum `Option` | diff --git a/src/test/ui/type-alias-impl-trait/argument-types.stderr b/src/test/ui/type-alias-impl-trait/argument-types.stderr index 1cbf9c95d3148..a87e44a048b25 100644 --- a/src/test/ui/type-alias-impl-trait/argument-types.stderr +++ b/src/test/ui/type-alias-impl-trait/argument-types.stderr @@ -4,6 +4,8 @@ error[E0308]: mismatched types LL | type Foo = impl Debug; | ---------- the expected opaque type ... +LL | fn foo1(mut x: Foo) { + | --- expected due to this parameter type LL | x = 22_u32; | ^^^^^^ expected opaque type, found `u32` | diff --git a/src/test/ui/type/type-check/assignment-expected-bool.stderr b/src/test/ui/type/type-check/assignment-expected-bool.stderr index 862ac65bc24e4..e2b821f7b05e9 100644 --- a/src/test/ui/type/type-check/assignment-expected-bool.stderr +++ b/src/test/ui/type/type-check/assignment-expected-bool.stderr @@ -48,10 +48,6 @@ error[E0308]: mismatched types LL | if 0 = 0 {} | ^^^^^ expected `bool`, found `()` | -help: you might have meant to use pattern matching - | -LL | if let 0 = 0 {} - | +++ help: you might have meant to compare for equality | LL | if 0 == 0 {} diff --git a/src/test/ui/type/type-check/assignment-in-if.stderr b/src/test/ui/type/type-check/assignment-in-if.stderr index 710be9d6a0420..f4ef44e2444ee 100644 --- a/src/test/ui/type/type-check/assignment-in-if.stderr +++ b/src/test/ui/type/type-check/assignment-in-if.stderr @@ -37,10 +37,6 @@ error[E0308]: mismatched types LL | if 3 = x { | ^^^^^ expected `bool`, found `()` | -help: you might have meant to use pattern matching - | -LL | if let 3 = x { - | +++ help: you might have meant to compare for equality | LL | if 3 == x { diff --git a/src/test/ui/typeck/issue-81293.stderr b/src/test/ui/typeck/issue-81293.stderr index 1e6ff3b5f9ee7..c545a563b0d0a 100644 --- a/src/test/ui/typeck/issue-81293.stderr +++ b/src/test/ui/typeck/issue-81293.stderr @@ -7,6 +7,9 @@ LL | a = c + b * 5; error[E0308]: mismatched types --> $DIR/issue-81293.rs:6:9 | +LL | let a: u16; + | --- expected due to this type +... LL | a = c + b * 5; | ^^^^^^^^^ expected `u16`, found `usize` diff --git a/src/test/ui/typeck/issue-87771-ice-assign-assign-to-bool.stderr b/src/test/ui/typeck/issue-87771-ice-assign-assign-to-bool.stderr index fe10fa733d238..56817ee2ca9f8 100644 --- a/src/test/ui/typeck/issue-87771-ice-assign-assign-to-bool.stderr +++ b/src/test/ui/typeck/issue-87771-ice-assign-assign-to-bool.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/issue-87771-ice-assign-assign-to-bool.rs:3:9 | +LL | let mut a; + | ----- expected due to the type of this binding LL | a = a = true; | ^^^^^^^^ expected `bool`, found `()` From d4e5cf47fe5c9576dc80f7cb113d4430732ebe98 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Sun, 21 Nov 2021 01:49:51 +0000 Subject: [PATCH 04/20] Account for type obligation coming from `const` and `static` --- compiler/rustc_typeck/src/check/demand.rs | 68 +++++++++++++------ .../ui/static/static-mut-bad-types.stderr | 7 +- 2 files changed, 50 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index 5d121913aac98..12cd7ad184892 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -179,31 +179,55 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut primary_span = lhs.span; let mut secondary_span = lhs.span; let mut post_message = ""; - if let hir::ExprKind::Path(hir::QPath::Resolved( - None, - hir::Path { res: hir::def::Res::Local(hir_id), .. }, - )) = lhs.kind - { - if let Some(hir::Node::Binding(pat)) = self.tcx.hir().find(*hir_id) { - let parent = self.tcx.hir().get_parent_node(pat.hir_id); - primary_span = pat.span; - secondary_span = pat.span; - match self.tcx.hir().find(parent) { - Some(hir::Node::Local(hir::Local { ty: Some(ty), .. })) => { - primary_span = ty.span; - post_message = " type"; - } - Some(hir::Node::Local(hir::Local { init: Some(init), .. })) => { - primary_span = init.span; - post_message = " value"; - } - Some(hir::Node::Param(hir::Param { ty_span, .. })) => { - primary_span = *ty_span; - post_message = " parameter type"; + match lhs.kind { + hir::ExprKind::Path(hir::QPath::Resolved( + None, + hir::Path { + res: + hir::def::Res::Def( + hir::def::DefKind::Static | hir::def::DefKind::Const, + def_id, + ), + .. + }, + )) => { + if let Some(hir::Node::Item(hir::Item { + ident, + kind: hir::ItemKind::Static(ty, ..) | hir::ItemKind::Const(ty, ..), + .. + })) = self.tcx.hir().get_if_local(*def_id) + { + primary_span = ty.span; + secondary_span = ident.span; + post_message = " type"; + } + } + hir::ExprKind::Path(hir::QPath::Resolved( + None, + hir::Path { res: hir::def::Res::Local(hir_id), .. }, + )) => { + if let Some(hir::Node::Binding(pat)) = self.tcx.hir().find(*hir_id) { + let parent = self.tcx.hir().get_parent_node(pat.hir_id); + primary_span = pat.span; + secondary_span = pat.span; + match self.tcx.hir().find(parent) { + Some(hir::Node::Local(hir::Local { ty: Some(ty), .. })) => { + primary_span = ty.span; + post_message = " type"; + } + Some(hir::Node::Local(hir::Local { init: Some(init), .. })) => { + primary_span = init.span; + post_message = " value"; + } + Some(hir::Node::Param(hir::Param { ty_span, .. })) => { + primary_span = *ty_span; + post_message = " parameter type"; + } + _ => {} } - _ => {} } } + _ => {} } if primary_span != secondary_span diff --git a/src/test/ui/static/static-mut-bad-types.stderr b/src/test/ui/static/static-mut-bad-types.stderr index e5a59de6f1461..983e1026f91e9 100644 --- a/src/test/ui/static/static-mut-bad-types.stderr +++ b/src/test/ui/static/static-mut-bad-types.stderr @@ -1,10 +1,11 @@ error[E0308]: mismatched types --> $DIR/static-mut-bad-types.rs:5:13 | +LL | static mut a: isize = 3; + | ----- expected due to this type +... LL | a = true; - | - ^^^^ expected `isize`, found `bool` - | | - | expected due to the type of this binding + | ^^^^ expected `isize`, found `bool` error: aborting due to previous error From 08a500ffc9239fed0f26ba12d7459cfa11821353 Mon Sep 17 00:00:00 2001 From: name1e5s Date: Tue, 23 Nov 2021 13:40:19 +0800 Subject: [PATCH 05/20] fix test in std::process on android --- library/std/src/process/tests.rs | 64 ++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/library/std/src/process/tests.rs b/library/std/src/process/tests.rs index 094d2efbdd509..67b747e410732 100644 --- a/library/std/src/process/tests.rs +++ b/library/std/src/process/tests.rs @@ -4,15 +4,23 @@ use super::{Command, Output, Stdio}; use crate::io::ErrorKind; use crate::str; -// FIXME(#10380) these tests should not all be ignored on android. +#[cfg(target_os = "android")] +fn shell_cmd() -> Command { + Command::new("/system/bin/sh") +} + +#[cfg(not(target_os = "android"))] +fn shell_cmd() -> Command { + Command::new("/bin/sh") +} #[test] -#[cfg_attr(any(target_os = "vxworks", target_os = "android"), ignore)] +#[cfg_attr(any(target_os = "vxworks"), ignore)] fn smoke() { let p = if cfg!(target_os = "windows") { Command::new("cmd").args(&["/C", "exit 0"]).spawn() } else { - Command::new("true").spawn() + shell_cmd().arg("-c").arg("true").spawn() }; assert!(p.is_ok()); let mut p = p.unwrap(); @@ -29,12 +37,12 @@ fn smoke_failure() { } #[test] -#[cfg_attr(any(target_os = "vxworks", target_os = "android"), ignore)] +#[cfg_attr(any(target_os = "vxworks"), ignore)] fn exit_reported_right() { let p = if cfg!(target_os = "windows") { Command::new("cmd").args(&["/C", "exit 1"]).spawn() } else { - Command::new("false").spawn() + shell_cmd().arg("-c").arg("false").spawn() }; assert!(p.is_ok()); let mut p = p.unwrap(); @@ -44,12 +52,11 @@ fn exit_reported_right() { #[test] #[cfg(unix)] -#[cfg_attr(any(target_os = "vxworks", target_os = "android"), ignore)] +#[cfg_attr(any(target_os = "vxworks"), ignore)] fn signal_reported_right() { use crate::os::unix::process::ExitStatusExt; - let mut p = - Command::new("/bin/sh").arg("-c").arg("read a").stdin(Stdio::piped()).spawn().unwrap(); + let mut p = shell_cmd().arg("-c").arg("read a").stdin(Stdio::piped()).spawn().unwrap(); p.kill().unwrap(); match p.wait().unwrap().signal() { Some(9) => {} @@ -69,31 +76,31 @@ pub fn run_output(mut cmd: Command) -> String { } #[test] -#[cfg_attr(any(target_os = "vxworks", target_os = "android"), ignore)] +#[cfg_attr(any(target_os = "vxworks"), ignore)] fn stdout_works() { if cfg!(target_os = "windows") { let mut cmd = Command::new("cmd"); cmd.args(&["/C", "echo foobar"]).stdout(Stdio::piped()); assert_eq!(run_output(cmd), "foobar\r\n"); } else { - let mut cmd = Command::new("echo"); - cmd.arg("foobar").stdout(Stdio::piped()); + let mut cmd = shell_cmd(); + cmd.arg("-c").arg("echo foobar").stdout(Stdio::piped()); assert_eq!(run_output(cmd), "foobar\n"); } } #[test] -#[cfg_attr(any(windows, target_os = "android", target_os = "vxworks"), ignore)] +#[cfg_attr(any(windows, target_os = "vxworks"), ignore)] fn set_current_dir_works() { - let mut cmd = Command::new("/bin/sh"); + let mut cmd = shell_cmd(); cmd.arg("-c").arg("pwd").current_dir("/").stdout(Stdio::piped()); assert_eq!(run_output(cmd), "/\n"); } #[test] -#[cfg_attr(any(windows, target_os = "android", target_os = "vxworks"), ignore)] +#[cfg_attr(any(windows, target_os = "vxworks"), ignore)] fn stdin_works() { - let mut p = Command::new("/bin/sh") + let mut p = shell_cmd() .arg("-c") .arg("read line; echo $line") .stdin(Stdio::piped()) @@ -109,19 +116,19 @@ fn stdin_works() { } #[test] -#[cfg_attr(any(target_os = "vxworks", target_os = "android"), ignore)] +#[cfg_attr(any(target_os = "vxworks"), ignore)] fn test_process_status() { let mut status = if cfg!(target_os = "windows") { Command::new("cmd").args(&["/C", "exit 1"]).status().unwrap() } else { - Command::new("false").status().unwrap() + shell_cmd().arg("-c").arg("false").status().unwrap() }; assert!(status.code() == Some(1)); status = if cfg!(target_os = "windows") { Command::new("cmd").args(&["/C", "exit 0"]).status().unwrap() } else { - Command::new("true").status().unwrap() + shell_cmd().arg("-c").arg("true").status().unwrap() }; assert!(status.success()); } @@ -135,12 +142,12 @@ fn test_process_output_fail_to_start() { } #[test] -#[cfg_attr(any(target_os = "vxworks", target_os = "android"), ignore)] +#[cfg_attr(any(target_os = "vxworks"), ignore)] fn test_process_output_output() { let Output { status, stdout, stderr } = if cfg!(target_os = "windows") { Command::new("cmd").args(&["/C", "echo hello"]).output().unwrap() } else { - Command::new("echo").arg("hello").output().unwrap() + shell_cmd().arg("-c").arg("echo hello").output().unwrap() }; let output_str = str::from_utf8(&stdout).unwrap(); @@ -150,7 +157,7 @@ fn test_process_output_output() { } #[test] -#[cfg_attr(any(target_os = "vxworks", target_os = "android"), ignore)] +#[cfg_attr(any(target_os = "vxworks"), ignore)] fn test_process_output_error() { let Output { status, stdout, stderr } = if cfg!(target_os = "windows") { Command::new("cmd").args(&["/C", "mkdir ."]).output().unwrap() @@ -158,41 +165,42 @@ fn test_process_output_error() { Command::new("mkdir").arg("./").output().unwrap() }; - assert!(status.code() == Some(1)); + assert!(status.code().is_some()); + assert!(status.code() != Some(0)); assert_eq!(stdout, Vec::new()); assert!(!stderr.is_empty()); } #[test] -#[cfg_attr(any(target_os = "vxworks", target_os = "android"), ignore)] +#[cfg_attr(any(target_os = "vxworks"), ignore)] fn test_finish_once() { let mut prog = if cfg!(target_os = "windows") { Command::new("cmd").args(&["/C", "exit 1"]).spawn().unwrap() } else { - Command::new("false").spawn().unwrap() + shell_cmd().arg("-c").arg("false").spawn().unwrap() }; assert!(prog.wait().unwrap().code() == Some(1)); } #[test] -#[cfg_attr(any(target_os = "vxworks", target_os = "android"), ignore)] +#[cfg_attr(any(target_os = "vxworks"), ignore)] fn test_finish_twice() { let mut prog = if cfg!(target_os = "windows") { Command::new("cmd").args(&["/C", "exit 1"]).spawn().unwrap() } else { - Command::new("false").spawn().unwrap() + shell_cmd().arg("-c").arg("false").spawn().unwrap() }; assert!(prog.wait().unwrap().code() == Some(1)); assert!(prog.wait().unwrap().code() == Some(1)); } #[test] -#[cfg_attr(any(target_os = "vxworks", target_os = "android"), ignore)] +#[cfg_attr(any(target_os = "vxworks"), ignore)] fn test_wait_with_output_once() { let prog = if cfg!(target_os = "windows") { Command::new("cmd").args(&["/C", "echo hello"]).stdout(Stdio::piped()).spawn().unwrap() } else { - Command::new("echo").arg("hello").stdout(Stdio::piped()).spawn().unwrap() + shell_cmd().arg("-c").arg("echo hello").stdout(Stdio::piped()).spawn().unwrap() }; let Output { status, stdout, stderr } = prog.wait_with_output().unwrap(); From 8756d0701edf813f5bf321f63c9502321c0f3824 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 21 Nov 2021 20:41:46 -0800 Subject: [PATCH 06/20] Derive Ord and PartialOrd for TraitRef --- compiler/rustc_middle/src/ty/sty.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index c79e25f4781c8..8683e95401989 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -890,7 +890,7 @@ impl<'tcx> List>> { /// /// Trait references also appear in object types like `Foo`, but in /// that case the `Self` parameter is absent from the substitutions. -#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)] #[derive(HashStable, TypeFoldable)] pub struct TraitRef<'tcx> { pub def_id: DefId, From c969b1dea0f523d604a7a6bd7eeb698bc5be3696 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 21 Nov 2021 20:43:48 -0800 Subject: [PATCH 07/20] Add supertraits method to rustc_middle --- compiler/rustc_middle/src/traits/mod.rs | 1 + compiler/rustc_middle/src/traits/util.rs | 49 ++++++++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 compiler/rustc_middle/src/traits/util.rs diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 49071e7995b4c..49a64cb246ad0 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -7,6 +7,7 @@ pub mod query; pub mod select; pub mod specialization_graph; mod structural_impls; +pub mod util; use crate::infer::canonical::Canonical; use crate::thir::abstract_const::NotConstEvaluatable; diff --git a/compiler/rustc_middle/src/traits/util.rs b/compiler/rustc_middle/src/traits/util.rs new file mode 100644 index 0000000000000..3490c6881704a --- /dev/null +++ b/compiler/rustc_middle/src/traits/util.rs @@ -0,0 +1,49 @@ +use rustc_data_structures::stable_set::FxHashSet; + +use crate::ty::{PolyTraitRef, TyCtxt}; + +/// Given a PolyTraitRef, get the PolyTraitRefs of the trait's (transitive) supertraits. +/// +/// A simplfied version of the same function at `rustc_infer::traits::util::supertraits`. +pub fn supertraits<'tcx>( + tcx: TyCtxt<'tcx>, + trait_ref: PolyTraitRef<'tcx>, +) -> impl Iterator> { + Elaborator { tcx, visited: FxHashSet::from_iter([trait_ref]), stack: vec![trait_ref] } +} + +struct Elaborator<'tcx> { + tcx: TyCtxt<'tcx>, + visited: FxHashSet>, + stack: Vec>, +} + +impl<'tcx> Elaborator<'tcx> { + fn elaborate(&mut self, trait_ref: PolyTraitRef<'tcx>) { + let supertrait_refs = self + .tcx + .super_predicates_of(trait_ref.def_id()) + .predicates + .into_iter() + .flat_map(|(pred, _)| { + pred.subst_supertrait(self.tcx, &trait_ref).to_opt_poly_trait_ref() + }) + .map(|t| t.value) + .filter(|supertrait_ref| self.visited.insert(*supertrait_ref)); + + self.stack.extend(supertrait_refs); + } +} + +impl<'tcx> Iterator for Elaborator<'tcx> { + type Item = PolyTraitRef<'tcx>; + + fn next(&mut self) -> Option> { + if let Some(trait_ref) = self.stack.pop() { + self.elaborate(trait_ref); + Some(trait_ref) + } else { + None + } + } +} From ce182d17f8abf4757f8d578b4c02c9786ebc2fb5 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 19 Nov 2021 20:51:19 -0800 Subject: [PATCH 08/20] Elaborate trait generics and associated types --- compiler/rustc_middle/src/ty/print/pretty.rs | 284 ++++++++++++++----- 1 file changed, 210 insertions(+), 74 deletions(-) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 3846cf19d915b..5a8fc943f9a6c 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -643,81 +643,8 @@ pub trait PrettyPrinter<'tcx>: } return Ok(self); } - // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, - // by looking up the projections associated with the def_id. - let bounds = self.tcx().explicit_item_bounds(def_id); - - let mut first = true; - let mut is_sized = false; - let mut is_future = false; - let mut future_output_ty = None; - - p!("impl"); - for (predicate, _) in bounds { - let predicate = predicate.subst(self.tcx(), substs); - let bound_predicate = predicate.kind(); - - match bound_predicate.skip_binder() { - ty::PredicateKind::Projection(projection_predicate) => { - let Some(future_trait) = self.tcx().lang_items().future_trait() else { continue }; - let future_output_def_id = - self.tcx().associated_item_def_ids(future_trait)[0]; - - if projection_predicate.projection_ty.item_def_id - == future_output_def_id - { - // We don't account for multiple `Future::Output = Ty` contraints. - is_future = true; - future_output_ty = Some(projection_predicate.ty); - } - } - ty::PredicateKind::Trait(pred) => { - let trait_ref = bound_predicate.rebind(pred.trait_ref); - // Don't print +Sized, but rather +?Sized if absent. - if Some(trait_ref.def_id()) == self.tcx().lang_items().sized_trait() - { - is_sized = true; - continue; - } - - if Some(trait_ref.def_id()) - == self.tcx().lang_items().future_trait() - { - is_future = true; - continue; - } - - p!( - write("{}", if first { " " } else { " + " }), - print(trait_ref.print_only_trait_path()) - ); - - first = false; - } - _ => {} - } - } - if is_future { - p!(write("{}Future", if first { " " } else { " + " })); - first = false; - - if let Some(future_output_ty) = future_output_ty { - // Don't print projection types, which we (unfortunately) see often - // in the error outputs involving async blocks. - if !matches!(future_output_ty.kind(), ty::Projection(_)) { - p!(""); - } - } - } - - if !is_sized { - p!(write("{}?Sized", if first { " " } else { " + " })); - } else if first { - p!(" Sized"); - } - - Ok(self) + self.pretty_print_opaque_impl_type(def_id, substs) }); } ty::Str => p!("str"), @@ -826,6 +753,208 @@ pub trait PrettyPrinter<'tcx>: Ok(self) } + fn pretty_print_opaque_impl_type( + mut self, + def_id: DefId, + substs: &'tcx ty::List>, + ) -> Result { + define_scoped_cx!(self); + + // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, + // by looking up the projections associated with the def_id. + let bounds = self.tcx().explicit_item_bounds(def_id); + + let mut traits = BTreeMap::new(); + let mut fn_traits = BTreeMap::new(); + let mut is_sized = false; + + for (predicate, _) in bounds { + let predicate = predicate.subst(self.tcx(), substs); + let bound_predicate = predicate.kind(); + + match bound_predicate.skip_binder() { + ty::PredicateKind::Trait(pred) => { + let trait_ref = bound_predicate.rebind(pred.trait_ref); + + // Don't print + Sized, but rather + ?Sized if absent. + if Some(trait_ref.def_id()) == self.tcx().lang_items().sized_trait() { + is_sized = true; + continue; + } + + self.insert_trait_and_projection(trait_ref, None, &mut traits, &mut fn_traits); + } + ty::PredicateKind::Projection(pred) => { + let proj_ref = bound_predicate.rebind(pred); + let trait_ref = proj_ref.required_poly_trait_ref(self.tcx()); + + // Projection type entry -- the def-id for naming, and the ty. + let proj_ty = (proj_ref.projection_def_id(), proj_ref.ty()); + + self.insert_trait_and_projection( + trait_ref, + Some(proj_ty), + &mut traits, + &mut fn_traits, + ); + } + _ => {} + } + } + + let mut first = true; + // Insert parenthesis around (Fn(A, B) -> C) if the opaque ty has more than one other trait + let paren_needed = fn_traits.len() > 1 || traits.len() > 0 || !is_sized; + + p!("impl"); + + for (fn_once_trait_ref, entry) in fn_traits { + // Get the (single) generic ty (the args) of this FnOnce trait ref. + let generics = self.generic_args_to_print( + self.tcx().generics_of(fn_once_trait_ref.def_id()), + fn_once_trait_ref.skip_binder().substs, + ); + + match (entry.return_ty, generics[0].expect_ty()) { + // We can only print `impl Fn() -> ()` if we have a tuple of args and we recorded + // a return type. + (Some(return_ty), arg_tys) if matches!(arg_tys.kind(), ty::Tuple(_)) => { + let name = if entry.fn_trait_ref.is_some() { + "Fn" + } else if entry.fn_mut_trait_ref.is_some() { + "FnMut" + } else { + "FnOnce" + }; + + p!( + write("{}", if first { " " } else { " + " }), + write("{}{}(", if paren_needed { "(" } else { "" }, name) + ); + + for (idx, ty) in arg_tys.tuple_fields().enumerate() { + if idx > 0 { + p!(", "); + } + p!(print(ty)); + } + + p!(") -> ", print(return_ty), write("{}", if paren_needed { ")" } else { "" })); + + first = false; + } + // If we got here, we can't print as a `impl Fn(A, B) -> C`. Just record the + // trait_refs we collected in the OpaqueFnEntry as normal trait refs. + _ => { + traits.entry(fn_once_trait_ref).or_default().extend( + // Group the return ty with its def id, if we had one. + entry + .return_ty + .map(|ty| (self.tcx().lang_items().fn_once_output().unwrap(), ty)), + ); + if let Some(trait_ref) = entry.fn_mut_trait_ref { + traits.entry(trait_ref).or_default(); + } + if let Some(trait_ref) = entry.fn_trait_ref { + traits.entry(trait_ref).or_default(); + } + } + } + } + + // Print the rest of the trait types (that aren't Fn* family of traits) + for (trait_ref, assoc_items) in traits { + p!( + write("{}", if first { " " } else { " + " }), + print(trait_ref.skip_binder().print_only_trait_name()) + ); + + let generics = self.generic_args_to_print( + self.tcx().generics_of(trait_ref.def_id()), + trait_ref.skip_binder().substs, + ); + + if !generics.is_empty() || !assoc_items.is_empty() { + p!("<"); + let mut first = true; + + for ty in generics { + if !first { + p!(", "); + } + p!(print(trait_ref.rebind(*ty))); + first = false; + } + + for (assoc_item_def_id, ty) in assoc_items { + if !first { + p!(", "); + } + p!( + write("{} = ", self.tcx().associated_item(assoc_item_def_id).ident), + print(ty) + ); + first = false; + } + + p!(">"); + } + + first = false; + } + + if !is_sized { + p!(write("{}?Sized", if first { " " } else { " + " })); + } else if first { + p!(" Sized"); + } + + Ok(self) + } + + /// Insert the trait ref and optionally a projection type associated with it into either the + /// traits map or fn_traits map, depending on if the trait is in the Fn* family of traits. + fn insert_trait_and_projection( + &mut self, + trait_ref: ty::PolyTraitRef<'tcx>, + proj_ty: Option<(DefId, ty::Binder<'tcx, Ty<'tcx>>)>, + traits: &mut BTreeMap, BTreeMap>>>, + fn_traits: &mut BTreeMap, OpaqueFnEntry<'tcx>>, + ) { + let trait_def_id = trait_ref.def_id(); + + // If our trait_ref is FnOnce or any of its children, project it onto the parent FnOnce + // super-trait ref and record it there. + if let Some(fn_once_trait) = self.tcx().lang_items().fn_once_trait() { + // If we have a FnOnce, then insert it into + if trait_def_id == fn_once_trait { + let entry = fn_traits.entry(trait_ref).or_default(); + // Optionally insert the return_ty as well. + if let Some((_, ty)) = proj_ty { + entry.return_ty = Some(ty); + } + return; + } else if Some(trait_def_id) == self.tcx().lang_items().fn_mut_trait() { + let super_trait_ref = crate::traits::util::supertraits(self.tcx(), trait_ref) + .find(|super_trait_ref| super_trait_ref.def_id() == fn_once_trait) + .unwrap(); + + fn_traits.entry(super_trait_ref).or_default().fn_mut_trait_ref = Some(trait_ref); + return; + } else if Some(trait_def_id) == self.tcx().lang_items().fn_trait() { + let super_trait_ref = crate::traits::util::supertraits(self.tcx(), trait_ref) + .find(|super_trait_ref| super_trait_ref.def_id() == fn_once_trait) + .unwrap(); + + fn_traits.entry(super_trait_ref).or_default().fn_trait_ref = Some(trait_ref); + return; + } + } + + // Otherwise, just group our traits and projection types. + traits.entry(trait_ref).or_default().extend(proj_ty); + } + fn pretty_print_bound_var( &mut self, debruijn: ty::DebruijnIndex, @@ -2553,3 +2682,10 @@ fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> FxHashMap { pub fn provide(providers: &mut ty::query::Providers) { *providers = ty::query::Providers { trimmed_def_paths, ..*providers }; } + +#[derive(Default)] +pub struct OpaqueFnEntry<'tcx> { + fn_mut_trait_ref: Option>, + fn_trait_ref: Option>, + return_ty: Option>>, +} From b84a52c95a8b7016bdadfef419e222c92133c785 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 21 Nov 2021 21:15:27 -0800 Subject: [PATCH 09/20] Add generator lang-item --- compiler/rustc_hir/src/lang_items.rs | 1 + compiler/rustc_span/src/symbol.rs | 1 + library/core/src/ops/generator.rs | 1 + 3 files changed, 3 insertions(+) diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 3037996d48bc0..05659e976dd44 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -268,6 +268,7 @@ language_item_table! { Future, sym::future_trait, future_trait, Target::Trait, GenericRequirement::Exact(0); GeneratorState, sym::generator_state, gen_state, Target::Enum, GenericRequirement::None; Generator, sym::generator, gen_trait, Target::Trait, GenericRequirement::Minimum(1); + GeneratorReturn, sym::generator_return, generator_return, Target::AssocTy, GenericRequirement::None; Unpin, sym::unpin, unpin_trait, Target::Trait, GenericRequirement::None; Pin, sym::pin, pin_type, Target::Struct, GenericRequirement::None; diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 0d556b5eda609..2977a0e39e96a 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -678,6 +678,7 @@ symbols! { gen_future, gen_kill, generator, + generator_return, generator_state, generators, generic_arg_infer, diff --git a/library/core/src/ops/generator.rs b/library/core/src/ops/generator.rs index 4f23620b92b80..b527c4b04ad7f 100644 --- a/library/core/src/ops/generator.rs +++ b/library/core/src/ops/generator.rs @@ -82,6 +82,7 @@ pub trait Generator { /// `return` statement or implicitly as the last expression of a generator /// literal. For example futures would use this as `Result` as it /// represents a completed future. + #[cfg_attr(not(bootstrap), lang = "generator_return")] type Return; /// Resumes the execution of this generator. From 471334e99617e20a2165b035241e6aa51bb29628 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 21 Nov 2021 21:15:57 -0800 Subject: [PATCH 10/20] Suppress noisy generator associated type --- compiler/rustc_middle/src/ty/print/pretty.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 5a8fc943f9a6c..aa175baa8c731 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -890,10 +890,20 @@ pub trait PrettyPrinter<'tcx>: if !first { p!(", "); } - p!( - write("{} = ", self.tcx().associated_item(assoc_item_def_id).ident), - print(ty) - ); + p!(write("{} = ", self.tcx().associated_item(assoc_item_def_id).ident)); + + // Skip printing `<[generator@] as Generator<_>>::Return` from async blocks + match ty.skip_binder().kind() { + ty::Projection(ty::ProjectionTy { item_def_id, .. }) + if Some(*item_def_id) == self.tcx().lang_items().generator_return() => + { + p!("[async output]") + } + _ => { + p!(print(ty)) + } + } + first = false; } From 9ae575c795a809f2a25ce487cfb0297511297a8a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 19 Nov 2021 20:51:44 -0800 Subject: [PATCH 11/20] Update test outputs --- .../inline/issue_78442.bar.Inline.diff | 6 ++--- .../inline/issue_78442.bar.RevealAll.diff | 10 ++++---- src/test/ui/associated-types/issue-87261.rs | 8 +++---- .../ui/associated-types/issue-87261.stderr | 24 +++++++++---------- ...ync-block-control-flow-static-semantics.rs | 6 ++--- ...block-control-flow-static-semantics.stderr | 4 ++-- src/test/ui/async-await/generator-desc.stderr | 4 ++-- .../issue-67252-unnamed-future.stderr | 2 +- src/test/ui/async-await/issue-68112.stderr | 4 ++-- .../issue-65436-raw-ptr-not-send.stderr | 2 +- ...d_main_const_fn_item_type_forbidden.stderr | 2 +- src/test/ui/generator/issue-68112.stderr | 8 +++---- .../ui/impl-trait/auto-trait-leak2.stderr | 12 +++++----- src/test/ui/impl-trait/issue-55872-2.rs | 2 +- src/test/ui/impl-trait/issue-55872-2.stderr | 4 ++-- src/test/ui/impl-trait/issue-72911.stderr | 8 +++---- src/test/ui/impl-trait/issue-87450.stderr | 4 ++-- .../ui/impl-trait/issues/issue-78722.stderr | 2 +- .../ui/impl-trait/issues/issue-86201.stderr | 2 +- src/test/ui/issues/issue-59494.rs | 2 +- src/test/ui/issues/issue-59494.stderr | 6 ++--- src/test/ui/lint/lint-ctypes-73251-2.rs | 2 +- src/test/ui/lint/lint-ctypes-73251-2.stderr | 2 +- src/test/ui/lint/opaque-ty-ffi-unsafe.rs | 2 +- src/test/ui/lint/opaque-ty-ffi-unsafe.stderr | 2 +- .../pattern/non-structural-match-types.stderr | 2 +- .../expected-boxed-future-isnt-pinned.stderr | 2 +- ...rg-where-it-should-have-been-called.stderr | 4 ++-- .../ui/type-alias-impl-trait/issue-89686.rs | 2 +- .../type-alias-impl-trait/issue-89686.stderr | 6 ++--- 30 files changed, 73 insertions(+), 73 deletions(-) diff --git a/src/test/mir-opt/inline/issue_78442.bar.Inline.diff b/src/test/mir-opt/inline/issue_78442.bar.Inline.diff index 4d9e022d82555..3e72d1c42fade 100644 --- a/src/test/mir-opt/inline/issue_78442.bar.Inline.diff +++ b/src/test/mir-opt/inline/issue_78442.bar.Inline.diff @@ -19,16 +19,16 @@ + _4 = hide_foo() -> [return: bb1, unwind: bb3]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:15 // mir::Constant // + span: $DIR/issue-78442.rs:11:5: 11:13 - // + literal: Const { ty: fn() -> impl std::ops::Fn<()> {hide_foo}, val: Value(Scalar()) } + // + literal: Const { ty: fn() -> impl Fn() -> () {hide_foo}, val: Value(Scalar()) } } bb1: { _3 = &_4; // scope 0 at $DIR/issue-78442.rs:11:5: 11:15 StorageLive(_5); // scope 0 at $DIR/issue-78442.rs:11:5: 11:17 -- _2 = as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:17 +- _2 = () as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:17 - // mir::Constant - // + span: $DIR/issue-78442.rs:11:5: 11:15 -- // + literal: Const { ty: for<'r> extern "rust-call" fn(&'r impl std::ops::Fn<()>, ()) -> as std::ops::FnOnce<()>>::Output { as std::ops::Fn<()>>::call}, val: Value(Scalar()) } +- // + literal: Const { ty: for<'r> extern "rust-call" fn(&'r impl Fn() -> (), ()) -> () as std::ops::FnOnce<()>>::Output { () as std::ops::Fn<()>>::call}, val: Value(Scalar()) } + _2 = move (*_3)() -> [return: bb5, unwind: bb3]; // scope 1 at $DIR/issue-78442.rs:11:5: 11:17 } diff --git a/src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff b/src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff index 45b552cc6340a..622599a2d18d5 100644 --- a/src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff +++ b/src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff @@ -5,8 +5,8 @@ debug _baz => _1; // in scope 0 at $DIR/issue-78442.rs:9:5: 9:9 let mut _0: (); // return place in scope 0 at $DIR/issue-78442.rs:10:3: 10:3 let _2: (); // in scope 0 at $DIR/issue-78442.rs:11:5: 11:17 -- let mut _3: &impl std::ops::Fn<()>; // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15 -- let _4: impl std::ops::Fn<()>; // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15 +- let mut _3: &impl Fn() -> (); // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15 +- let _4: impl Fn() -> (); // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15 + let mut _3: &fn() {foo}; // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15 + let _4: fn() {foo}; // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15 let mut _5: (); // in scope 0 at $DIR/issue-78442.rs:11:5: 11:17 @@ -18,17 +18,17 @@ _4 = hide_foo() -> [return: bb1, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:15 // mir::Constant // + span: $DIR/issue-78442.rs:11:5: 11:13 - // + literal: Const { ty: fn() -> impl std::ops::Fn<()> {hide_foo}, val: Value(Scalar()) } + // + literal: Const { ty: fn() -> impl Fn() -> () {hide_foo}, val: Value(Scalar()) } } bb1: { _3 = &_4; // scope 0 at $DIR/issue-78442.rs:11:5: 11:15 StorageLive(_5); // scope 0 at $DIR/issue-78442.rs:11:5: 11:17 nop; // scope 0 at $DIR/issue-78442.rs:11:5: 11:17 - _2 = as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:17 + _2 = () as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:17 // mir::Constant // + span: $DIR/issue-78442.rs:11:5: 11:15 - // + literal: Const { ty: for<'r> extern "rust-call" fn(&'r impl std::ops::Fn<()>, ()) -> as std::ops::FnOnce<()>>::Output { as std::ops::Fn<()>>::call}, val: Value(Scalar()) } + // + literal: Const { ty: for<'r> extern "rust-call" fn(&'r impl Fn() -> (), ()) -> () as std::ops::FnOnce<()>>::Output { () as std::ops::Fn<()>>::call}, val: Value(Scalar()) } } bb2: { diff --git a/src/test/ui/associated-types/issue-87261.rs b/src/test/ui/associated-types/issue-87261.rs index 384561f8ccd7e..aae562ae72243 100644 --- a/src/test/ui/associated-types/issue-87261.rs +++ b/src/test/ui/associated-types/issue-87261.rs @@ -83,17 +83,17 @@ fn main() { //~^ ERROR type mismatch resolving `::Associated == ()` accepts_trait(returns_opaque_foo()); - //~^ ERROR type mismatch resolving `::Associated == ()` + //~^ ERROR type mismatch resolving `::Associated == ()` accepts_trait(returns_opaque_derived_foo()); - //~^ ERROR type mismatch resolving `::Associated == ()` + //~^ ERROR type mismatch resolving `::Associated == ()` accepts_generic_trait(returns_opaque_generic()); //~^ ERROR type mismatch resolving ` as GenericTrait<()>>::Associated == ()` accepts_generic_trait(returns_opaque_generic_foo()); - //~^ ERROR type mismatch resolving ` + Foo as GenericTrait<()>>::Associated == ()` + //~^ ERROR type mismatch resolving ` as GenericTrait<()>>::Associated == ()` accepts_generic_trait(returns_opaque_generic_duplicate()); - //~^ ERROR type mismatch resolving ` + GenericTrait as GenericTrait<()>>::Associated == ()` + //~^ ERROR type mismatch resolving ` + GenericTrait<()> as GenericTrait<()>>::Associated == ()` } diff --git a/src/test/ui/associated-types/issue-87261.stderr b/src/test/ui/associated-types/issue-87261.stderr index 8db4a49da3c96..c00b48abc1c33 100644 --- a/src/test/ui/associated-types/issue-87261.stderr +++ b/src/test/ui/associated-types/issue-87261.stderr @@ -160,7 +160,7 @@ help: consider constraining the associated type `::A LL | fn returns_opaque_derived() -> impl DerivedTrait + 'static { | +++++++++++++++++ -error[E0271]: type mismatch resolving `::Associated == ()` +error[E0271]: type mismatch resolving `::Associated == ()` --> $DIR/issue-87261.rs:85:5 | LL | fn returns_opaque_foo() -> impl Trait + Foo { @@ -170,18 +170,18 @@ LL | accepts_trait(returns_opaque_foo()); | ^^^^^^^^^^^^^ expected `()`, found associated type | = note: expected unit type `()` - found associated type `::Associated` + found associated type `::Associated` note: required by a bound in `accepts_trait` --> $DIR/issue-87261.rs:43:27 | LL | fn accepts_trait>(_: T) {} | ^^^^^^^^^^^^^^^ required by this bound in `accepts_trait` -help: consider constraining the associated type `::Associated` to `()` +help: consider constraining the associated type `::Associated` to `()` | LL | fn returns_opaque_foo() -> impl Trait + Foo { | +++++++++++++++++ -error[E0271]: type mismatch resolving `::Associated == ()` +error[E0271]: type mismatch resolving `::Associated == ()` --> $DIR/issue-87261.rs:88:5 | LL | fn returns_opaque_derived_foo() -> impl DerivedTrait + Foo { @@ -191,8 +191,8 @@ LL | accepts_trait(returns_opaque_derived_foo()); | ^^^^^^^^^^^^^ expected `()`, found associated type | = note: expected unit type `()` - found associated type `::Associated` - = help: consider constraining the associated type `::Associated` to `()` + found associated type `::Associated` + = help: consider constraining the associated type `::Associated` to `()` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html note: required by a bound in `accepts_trait` --> $DIR/issue-87261.rs:43:27 @@ -221,7 +221,7 @@ help: consider constraining the associated type ` as Gener LL | fn returns_opaque_generic() -> impl GenericTrait<(), Associated = ()> + 'static { | +++++++++++++++++ -error[E0271]: type mismatch resolving ` + Foo as GenericTrait<()>>::Associated == ()` +error[E0271]: type mismatch resolving ` as GenericTrait<()>>::Associated == ()` --> $DIR/issue-87261.rs:94:5 | LL | fn returns_opaque_generic_foo() -> impl GenericTrait<()> + Foo { @@ -231,18 +231,18 @@ LL | accepts_generic_trait(returns_opaque_generic_foo()); | ^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type | = note: expected unit type `()` - found associated type ` + Foo as GenericTrait<()>>::Associated` + found associated type ` as GenericTrait<()>>::Associated` note: required by a bound in `accepts_generic_trait` --> $DIR/issue-87261.rs:44:46 | LL | fn accepts_generic_trait>(_: T) {} | ^^^^^^^^^^^^^^^ required by this bound in `accepts_generic_trait` -help: consider constraining the associated type ` + Foo as GenericTrait<()>>::Associated` to `()` +help: consider constraining the associated type ` as GenericTrait<()>>::Associated` to `()` | LL | fn returns_opaque_generic_foo() -> impl GenericTrait<(), Associated = ()> + Foo { | +++++++++++++++++ -error[E0271]: type mismatch resolving ` + GenericTrait as GenericTrait<()>>::Associated == ()` +error[E0271]: type mismatch resolving ` + GenericTrait<()> as GenericTrait<()>>::Associated == ()` --> $DIR/issue-87261.rs:97:5 | LL | fn returns_opaque_generic_duplicate() -> impl GenericTrait<()> + GenericTrait { @@ -252,8 +252,8 @@ LL | accepts_generic_trait(returns_opaque_generic_duplicate()); | ^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type | = note: expected unit type `()` - found associated type ` + GenericTrait as GenericTrait<()>>::Associated` - = help: consider constraining the associated type ` + GenericTrait as GenericTrait<()>>::Associated` to `()` + found associated type ` + GenericTrait<()> as GenericTrait<()>>::Associated` + = help: consider constraining the associated type ` + GenericTrait<()> as GenericTrait<()>>::Associated` to `()` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html note: required by a bound in `accepts_generic_trait` --> $DIR/issue-87261.rs:44:46 diff --git a/src/test/ui/async-await/async-block-control-flow-static-semantics.rs b/src/test/ui/async-await/async-block-control-flow-static-semantics.rs index 5bc7069ff89e3..e3832767203bb 100644 --- a/src/test/ui/async-await/async-block-control-flow-static-semantics.rs +++ b/src/test/ui/async-await/async-block-control-flow-static-semantics.rs @@ -15,16 +15,16 @@ fn return_targets_async_block_not_fn() -> u8 { return 0u8; }; let _: &dyn Future = █ - //~^ ERROR type mismatch resolving `::Output == ()` + //~^ ERROR type mismatch } async fn return_targets_async_block_not_async_fn() -> u8 { - //~^ ERROR mismatched types + //~^ ERROR mismatched types [E0308] let block = async { return 0u8; }; let _: &dyn Future = █ - //~^ ERROR type mismatch resolving `::Output == ()` + //~^ ERROR type mismatch resolving ` as Future>::Output == ()` } fn no_break_in_async_block() { diff --git a/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr b/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr index 919904ce3b6a2..fe864c65b7cf2 100644 --- a/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr +++ b/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr @@ -31,7 +31,7 @@ LL | | LL | | } | |_^ expected `u8`, found `()` -error[E0271]: type mismatch resolving `::Output == ()` +error[E0271]: type mismatch resolving ` as Future>::Output == ()` --> $DIR/async-block-control-flow-static-semantics.rs:26:39 | LL | let _: &dyn Future = █ @@ -47,7 +47,7 @@ LL | fn return_targets_async_block_not_fn() -> u8 { | | | implicitly returns `()` as its body has no tail or `return` expression -error[E0271]: type mismatch resolving `::Output == ()` +error[E0271]: type mismatch resolving ` as Future>::Output == ()` --> $DIR/async-block-control-flow-static-semantics.rs:17:39 | LL | let _: &dyn Future = █ diff --git a/src/test/ui/async-await/generator-desc.stderr b/src/test/ui/async-await/generator-desc.stderr index 79834ed7ec1a8..4a45d8d2a9423 100644 --- a/src/test/ui/async-await/generator-desc.stderr +++ b/src/test/ui/async-await/generator-desc.stderr @@ -46,8 +46,8 @@ LL | pub const fn from_generator(gen: T) -> impl Future | the expected opaque type | the found opaque type | - = note: expected opaque type `impl Future` (`async` closure body) - found opaque type `impl Future` (`async` closure body) + = note: expected opaque type `impl Future` (`async` closure body) + found opaque type `impl Future` (`async` closure body) error: aborting due to 3 previous errors diff --git a/src/test/ui/async-await/issue-67252-unnamed-future.stderr b/src/test/ui/async-await/issue-67252-unnamed-future.stderr index d046e2a05611c..b61694ad53e5b 100644 --- a/src/test/ui/async-await/issue-67252-unnamed-future.stderr +++ b/src/test/ui/async-await/issue-67252-unnamed-future.stderr @@ -4,7 +4,7 @@ error: future cannot be sent between threads safely LL | spawn(async { | ^^^^^ future created by async block is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `*mut ()` + = help: within `impl Future`, the trait `Send` is not implemented for `*mut ()` note: future is not `Send` as this value is used across an await --> $DIR/issue-67252-unnamed-future.rs:20:9 | diff --git a/src/test/ui/async-await/issue-68112.stderr b/src/test/ui/async-await/issue-68112.stderr index 9682a7055e93c..a8c2ebe12fa18 100644 --- a/src/test/ui/async-await/issue-68112.stderr +++ b/src/test/ui/async-await/issue-68112.stderr @@ -44,13 +44,13 @@ LL | require_send(send_fut); = note: required because of the requirements on the impl of `Send` for `Arc>` = note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:47:31: 47:36]` = note: required because it appears within the type `from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:47:31: 47:36]>` - = note: required because it appears within the type `impl Future` + = note: required because it appears within the type `impl Future` = note: required because it appears within the type `impl Future>>` = note: required because it appears within the type `impl Future>>` = note: required because it appears within the type `{ResumeTy, impl Future>>, (), i32, Ready}` = note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:55:26: 59:6]` = note: required because it appears within the type `from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:55:26: 59:6]>` - = note: required because it appears within the type `impl Future` + = note: required because it appears within the type `impl Future` note: required by a bound in `require_send` --> $DIR/issue-68112.rs:11:25 | diff --git a/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr index 666ef851ad66f..6ebefbebe5362 100644 --- a/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr +++ b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr @@ -4,7 +4,7 @@ error: future cannot be sent between threads safely LL | assert_send(async { | ^^^^^^^^^^^ future created by async block is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `*const u8` + = help: within `impl Future`, the trait `Send` is not implemented for `*const u8` note: future is not `Send` as this value is used across an await --> $DIR/issue-65436-raw-ptr-not-send.rs:14:9 | diff --git a/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr b/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr index 6aa170fdfd2a7..42c6de2012768 100644 --- a/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr +++ b/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr @@ -21,7 +21,7 @@ LL | type MainFn = impl Fn(); LL | pub const BAR: MainFn = bar; | ^^^ expected opaque type, found fn item | - = note: expected opaque type `impl Fn<()>` + = note: expected opaque type `impl Fn() -> ()` found fn item `fn() {bar}` error: could not find defining uses diff --git a/src/test/ui/generator/issue-68112.stderr b/src/test/ui/generator/issue-68112.stderr index c3fc8dd8f9286..a7d7a73254886 100644 --- a/src/test/ui/generator/issue-68112.stderr +++ b/src/test/ui/generator/issue-68112.stderr @@ -9,7 +9,7 @@ note: generator is not `Send` as this value is used across a yield --> $DIR/issue-68112.rs:31:9 | LL | let _non_send_gen = make_non_send_generator(); - | ------------- has type `impl Generator` which is not `Send` + | ------------- has type `impl Generator>>` which is not `Send` LL | yield; | ^^^^^ yield occurs here, with `_non_send_gen` maybe used later LL | }; @@ -29,9 +29,9 @@ LL | require_send(send_gen); = help: the trait `Sync` is not implemented for `RefCell` = note: required because of the requirements on the impl of `Send` for `Arc>` = note: required because it appears within the type `[generator@$DIR/issue-68112.rs:38:5: 41:6]` - = note: required because it appears within the type `impl Generator` - = note: required because it appears within the type `impl Generator` - = note: required because it appears within the type `{impl Generator, ()}` + = note: required because it appears within the type `impl Generator>>` + = note: required because it appears within the type `impl Generator>>` + = note: required because it appears within the type `{impl Generator>>, ()}` = note: required because it appears within the type `[generator@$DIR/issue-68112.rs:48:20: 51:6]` note: required by a bound in `require_send` --> $DIR/issue-68112.rs:22:25 diff --git a/src/test/ui/impl-trait/auto-trait-leak2.stderr b/src/test/ui/impl-trait/auto-trait-leak2.stderr index 8c53b4105bb8b..2ca180029ae7f 100644 --- a/src/test/ui/impl-trait/auto-trait-leak2.stderr +++ b/src/test/ui/impl-trait/auto-trait-leak2.stderr @@ -2,16 +2,16 @@ error[E0277]: `Rc>` cannot be sent between threads safely --> $DIR/auto-trait-leak2.rs:13:10 | LL | fn before() -> impl Fn(i32) { - | ------------ within this `impl Fn<(i32,)>` + | ------------ within this `impl Fn(i32) -> ()` ... LL | send(before()); | ---- ^^^^^^^^ `Rc>` cannot be sent between threads safely | | | required by a bound introduced by this call | - = help: within `impl Fn<(i32,)>`, the trait `Send` is not implemented for `Rc>` + = help: within `impl Fn(i32) -> ()`, the trait `Send` is not implemented for `Rc>` = note: required because it appears within the type `[closure@$DIR/auto-trait-leak2.rs:7:5: 7:22]` - = note: required because it appears within the type `impl Fn<(i32,)>` + = note: required because it appears within the type `impl Fn(i32) -> ()` note: required by a bound in `send` --> $DIR/auto-trait-leak2.rs:10:12 | @@ -27,11 +27,11 @@ LL | send(after()); | required by a bound introduced by this call ... LL | fn after() -> impl Fn(i32) { - | ------------ within this `impl Fn<(i32,)>` + | ------------ within this `impl Fn(i32) -> ()` | - = help: within `impl Fn<(i32,)>`, the trait `Send` is not implemented for `Rc>` + = help: within `impl Fn(i32) -> ()`, the trait `Send` is not implemented for `Rc>` = note: required because it appears within the type `[closure@$DIR/auto-trait-leak2.rs:24:5: 24:22]` - = note: required because it appears within the type `impl Fn<(i32,)>` + = note: required because it appears within the type `impl Fn(i32) -> ()` note: required by a bound in `send` --> $DIR/auto-trait-leak2.rs:10:12 | diff --git a/src/test/ui/impl-trait/issue-55872-2.rs b/src/test/ui/impl-trait/issue-55872-2.rs index 9546d01ac5c68..a519397806e07 100644 --- a/src/test/ui/impl-trait/issue-55872-2.rs +++ b/src/test/ui/impl-trait/issue-55872-2.rs @@ -13,7 +13,7 @@ impl Bar for S { type E = impl std::marker::Copy; fn foo() -> Self::E { //~^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias - //~| ERROR the trait bound `impl Future: Copy` is not satisfied [E0277] + //~| ERROR the trait bound `impl Future: Copy` is not satisfied async {} } } diff --git a/src/test/ui/impl-trait/issue-55872-2.stderr b/src/test/ui/impl-trait/issue-55872-2.stderr index 31b8fbd299c51..97545ba3d1124 100644 --- a/src/test/ui/impl-trait/issue-55872-2.stderr +++ b/src/test/ui/impl-trait/issue-55872-2.stderr @@ -1,8 +1,8 @@ -error[E0277]: the trait bound `impl Future: Copy` is not satisfied +error[E0277]: the trait bound `impl Future: Copy` is not satisfied --> $DIR/issue-55872-2.rs:14:20 | LL | fn foo() -> Self::E { - | ^^^^^^^ the trait `Copy` is not implemented for `impl Future` + | ^^^^^^^ the trait `Copy` is not implemented for `impl Future` error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias --> $DIR/issue-55872-2.rs:14:28 diff --git a/src/test/ui/impl-trait/issue-72911.stderr b/src/test/ui/impl-trait/issue-72911.stderr index 17748ae42770f..e57fbf104dc6f 100644 --- a/src/test/ui/impl-trait/issue-72911.stderr +++ b/src/test/ui/impl-trait/issue-72911.stderr @@ -19,14 +19,14 @@ LL | LL | lint_files().flat_map(|f| gather_from_file(&f)) | ----------------------------------------------- | | - | returning here with type `FlatMap` - | returning here with type `FlatMap` + | returning here with type `FlatMap, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>` + | returning here with type `FlatMap, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>` ... LL | fn gather_from_file(dir_entry: &foo::MissingItem) -> impl Iterator { - | -------------------------- returning this opaque type `FlatMap` + | -------------------------- returning this opaque type `FlatMap, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>` ... LL | fn lint_files() -> impl Iterator { - | -------------------------------------- returning this opaque type `FlatMap` + | -------------------------------------- returning this opaque type `FlatMap, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>` error: aborting due to 3 previous errors diff --git a/src/test/ui/impl-trait/issue-87450.stderr b/src/test/ui/impl-trait/issue-87450.stderr index 83eb33efc6b6a..9b7d225a53eee 100644 --- a/src/test/ui/impl-trait/issue-87450.stderr +++ b/src/test/ui/impl-trait/issue-87450.stderr @@ -17,10 +17,10 @@ LL | fn foo() -> impl Fn() { | ^^^^^^^^^ recursive opaque type ... LL | wrap(wrap(wrap(wrap(wrap(wrap(wrap(foo()))))))) - | ----------------------------------------------- returning here with type `impl Fn<()>` + | ----------------------------------------------- returning here with type `impl Fn() -> ()` ... LL | fn wrap(f: impl Fn()) -> impl Fn() { - | --------- returning this opaque type `impl Fn<()>` + | --------- returning this opaque type `impl Fn() -> ()` error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/impl-trait/issues/issue-78722.stderr b/src/test/ui/impl-trait/issues/issue-78722.stderr index 86bde9a0cddab..130678de2370c 100644 --- a/src/test/ui/impl-trait/issues/issue-78722.stderr +++ b/src/test/ui/impl-trait/issues/issue-78722.stderr @@ -15,7 +15,7 @@ LL | pub const fn from_generator(gen: T) -> impl Future | ------------------------------- the found opaque type | = note: expected opaque type `impl Future` - found opaque type `impl Future` + found opaque type `impl Future` = note: distinct uses of `impl Trait` result in different opaque types error: aborting due to previous error diff --git a/src/test/ui/impl-trait/issues/issue-86201.stderr b/src/test/ui/impl-trait/issues/issue-86201.stderr index b1460096ded66..d65bddf7cfa3f 100644 --- a/src/test/ui/impl-trait/issues/issue-86201.stderr +++ b/src/test/ui/impl-trait/issues/issue-86201.stderr @@ -7,7 +7,7 @@ LL | LL | static STATIC_FN: FunType = some_fn; | ^^^^^^^ expected opaque type, found fn item | - = note: expected opaque type `impl Fn<()>` + = note: expected opaque type `impl Fn<()> + FnOnce<()>` found fn item `fn() {some_fn}` error: could not find defining uses diff --git a/src/test/ui/issues/issue-59494.rs b/src/test/ui/issues/issue-59494.rs index 06b8eb777c035..65ef436129e91 100644 --- a/src/test/ui/issues/issue-59494.rs +++ b/src/test/ui/issues/issue-59494.rs @@ -19,5 +19,5 @@ fn main() { let g = |(a, _)| a; let t7 = |env| |a| |b| t7p(f, g)(((env, a), b)); let t8 = t8n(t7, t7p(f, g)); - //~^ ERROR: expected a `Fn<(_,)>` closure, found `impl Fn<(((_, _), _),)> + //~^ ERROR: expected a `Fn<(_,)>` closure, found `impl Fn(((_, _), _)) -> ()` [E0277] } diff --git a/src/test/ui/issues/issue-59494.stderr b/src/test/ui/issues/issue-59494.stderr index 9b7fe1ef786f0..0af54f567f0ff 100644 --- a/src/test/ui/issues/issue-59494.stderr +++ b/src/test/ui/issues/issue-59494.stderr @@ -1,12 +1,12 @@ -error[E0277]: expected a `Fn<(_,)>` closure, found `impl Fn<(((_, _), _),)>` +error[E0277]: expected a `Fn<(_,)>` closure, found `impl Fn(((_, _), _)) -> ()` --> $DIR/issue-59494.rs:21:22 | LL | let t8 = t8n(t7, t7p(f, g)); - | --- ^^^^^^^^^ expected an `Fn<(_,)>` closure, found `impl Fn<(((_, _), _),)>` + | --- ^^^^^^^^^ expected an `Fn<(_,)>` closure, found `impl Fn(((_, _), _)) -> ()` | | | required by a bound introduced by this call | - = help: the trait `Fn<(_,)>` is not implemented for `impl Fn<(((_, _), _),)>` + = help: the trait `Fn<(_,)>` is not implemented for `impl Fn(((_, _), _)) -> ()` note: required by a bound in `t8n` --> $DIR/issue-59494.rs:5:45 | diff --git a/src/test/ui/lint/lint-ctypes-73251-2.rs b/src/test/ui/lint/lint-ctypes-73251-2.rs index 79effd054b083..717ca4986f700 100644 --- a/src/test/ui/lint/lint-ctypes-73251-2.rs +++ b/src/test/ui/lint/lint-ctypes-73251-2.rs @@ -33,7 +33,7 @@ fn use_of_b() -> AliasB { } extern "C" { - pub fn lint_me() -> ::Assoc; //~ ERROR: uses type `impl TraitA` + pub fn lint_me() -> ::Assoc; //~ ERROR: uses type `impl TraitA` } fn main() {} diff --git a/src/test/ui/lint/lint-ctypes-73251-2.stderr b/src/test/ui/lint/lint-ctypes-73251-2.stderr index 94ee95d422e08..d7e10db441ec2 100644 --- a/src/test/ui/lint/lint-ctypes-73251-2.stderr +++ b/src/test/ui/lint/lint-ctypes-73251-2.stderr @@ -1,4 +1,4 @@ -error: `extern` block uses type `impl TraitA`, which is not FFI-safe +error: `extern` block uses type `impl TraitA`, which is not FFI-safe --> $DIR/lint-ctypes-73251-2.rs:36:25 | LL | pub fn lint_me() -> ::Assoc; diff --git a/src/test/ui/lint/opaque-ty-ffi-unsafe.rs b/src/test/ui/lint/opaque-ty-ffi-unsafe.rs index fadb7471952f5..efdc4037b6356 100644 --- a/src/test/ui/lint/opaque-ty-ffi-unsafe.rs +++ b/src/test/ui/lint/opaque-ty-ffi-unsafe.rs @@ -9,7 +9,7 @@ pub fn ret_closure() -> A { extern "C" { pub fn a(_: A); - //~^ ERROR `extern` block uses type `impl Fn<()>`, which is not FFI-safe + //~^ ERROR `extern` block uses type `impl Fn() -> ()`, which is not FFI-safe [improper_ctypes] } fn main() {} diff --git a/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr b/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr index 9d46f6d936e25..c77d8c0c18bc8 100644 --- a/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr +++ b/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr @@ -1,4 +1,4 @@ -error: `extern` block uses type `impl Fn<()>`, which is not FFI-safe +error: `extern` block uses type `impl Fn() -> ()`, which is not FFI-safe --> $DIR/opaque-ty-ffi-unsafe.rs:11:17 | LL | pub fn a(_: A); diff --git a/src/test/ui/pattern/non-structural-match-types.stderr b/src/test/ui/pattern/non-structural-match-types.stderr index 91fed81eaeff6..31168e29eb82f 100644 --- a/src/test/ui/pattern/non-structural-match-types.stderr +++ b/src/test/ui/pattern/non-structural-match-types.stderr @@ -4,7 +4,7 @@ error: `[closure@$DIR/non-structural-match-types.rs:9:17: 9:22]` cannot be used LL | const { || {} } => {}, | ^^^^^^^^^^^^^^^ -error: `impl Future` cannot be used in patterns +error: `impl Future` cannot be used in patterns --> $DIR/non-structural-match-types.rs:12:9 | LL | const { async {} } => {}, diff --git a/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr index 7ef4895249cec..550ed4b03b039 100644 --- a/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr +++ b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr @@ -81,7 +81,7 @@ LL | pub const fn from_generator(gen: T) -> impl Future | ------------------------------- the found opaque type | = note: expected struct `Pin + Send + 'static)>>` - found opaque type `impl Future` + found opaque type `impl Future` help: you need to pin and box this expression | LL ~ Box::pin(async { diff --git a/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr index b111df49f6e53..101e7aecc0226 100644 --- a/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr +++ b/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr @@ -1,11 +1,11 @@ -error[E0277]: the trait bound `fn() -> impl T {foo}: T` is not satisfied +error[E0277]: the trait bound `fn() -> impl T {foo}: T` is not satisfied --> $DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:17:9 | LL | fn foo() -> impl T { S } | --- consider calling this function ... LL | bar(foo); - | --- ^^^ the trait `T` is not implemented for `fn() -> impl T {foo}` + | --- ^^^ the trait `T` is not implemented for `fn() -> impl T {foo}` | | | required by a bound introduced by this call | diff --git a/src/test/ui/type-alias-impl-trait/issue-89686.rs b/src/test/ui/type-alias-impl-trait/issue-89686.rs index 2b6ce49e7e2d7..5878b26fddbc7 100644 --- a/src/test/ui/type-alias-impl-trait/issue-89686.rs +++ b/src/test/ui/type-alias-impl-trait/issue-89686.rs @@ -5,7 +5,7 @@ use std::future::Future; type G<'a, T> = impl Future; -//~^ ERROR: type mismatch resolving `::Output == ()` +//~^ ERROR: type mismatch resolving ` as Future>::Output == ()` //~| ERROR: the trait bound `T: Trait` is not satisfied trait Trait { diff --git a/src/test/ui/type-alias-impl-trait/issue-89686.stderr b/src/test/ui/type-alias-impl-trait/issue-89686.stderr index accc84d30a7bd..19ed9a7476c1b 100644 --- a/src/test/ui/type-alias-impl-trait/issue-89686.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-89686.stderr @@ -1,4 +1,4 @@ -error[E0271]: type mismatch resolving `::Output == ()` +error[E0271]: type mismatch resolving ` as Future>::Output == ()` --> $DIR/issue-89686.rs:7:17 | LL | type G<'a, T> = impl Future; @@ -13,8 +13,8 @@ LL | pub const fn from_generator(gen: T) -> impl Future | ------------------------------- the found opaque type | = note: expected unit type `()` - found associated type `::Output` - = help: consider constraining the associated type `::Output` to `()` + found associated type ` as Future>::Output` + = help: consider constraining the associated type ` as Future>::Output` to `()` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0277]: the trait bound `T: Trait` is not satisfied From 9cc117930b02b86795946e6b8748166c17fd4f16 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 23 Nov 2021 10:34:01 -0800 Subject: [PATCH 12/20] Fix printing unit return ty, don't elaborate FnOnce unless we see it --- compiler/rustc_middle/src/ty/print/pretty.rs | 23 +++++++++++++------ .../inline/issue_78442.bar.Inline.diff | 6 ++--- .../inline/issue_78442.bar.RevealAll.diff | 10 ++++---- ...d_main_const_fn_item_type_forbidden.stderr | 2 +- .../ui/impl-trait/auto-trait-leak2.stderr | 12 +++++----- src/test/ui/impl-trait/issue-87450.stderr | 4 ++-- .../ui/impl-trait/issues/issue-86201.stderr | 2 +- src/test/ui/issues/issue-59494.rs | 2 +- src/test/ui/issues/issue-59494.stderr | 6 ++--- src/test/ui/lint/opaque-ty-ffi-unsafe.rs | 2 +- src/test/ui/lint/opaque-ty-ffi-unsafe.stderr | 2 +- 11 files changed, 40 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index aa175baa8c731..175295b3199e8 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -839,19 +839,25 @@ pub trait PrettyPrinter<'tcx>: p!(print(ty)); } - p!(") -> ", print(return_ty), write("{}", if paren_needed { ")" } else { "" })); + p!(")"); + if !return_ty.skip_binder().is_unit() { + p!("-> ", print(return_ty)); + } + p!(write("{}", if paren_needed { ")" } else { "" })); first = false; } // If we got here, we can't print as a `impl Fn(A, B) -> C`. Just record the // trait_refs we collected in the OpaqueFnEntry as normal trait refs. _ => { - traits.entry(fn_once_trait_ref).or_default().extend( - // Group the return ty with its def id, if we had one. - entry - .return_ty - .map(|ty| (self.tcx().lang_items().fn_once_output().unwrap(), ty)), - ); + if entry.has_fn_once { + traits.entry(fn_once_trait_ref).or_default().extend( + // Group the return ty with its def id, if we had one. + entry + .return_ty + .map(|ty| (self.tcx().lang_items().fn_once_output().unwrap(), ty)), + ); + } if let Some(trait_ref) = entry.fn_mut_trait_ref { traits.entry(trait_ref).or_default(); } @@ -943,6 +949,7 @@ pub trait PrettyPrinter<'tcx>: if let Some((_, ty)) = proj_ty { entry.return_ty = Some(ty); } + entry.has_fn_once = true; return; } else if Some(trait_def_id) == self.tcx().lang_items().fn_mut_trait() { let super_trait_ref = crate::traits::util::supertraits(self.tcx(), trait_ref) @@ -2695,6 +2702,8 @@ pub fn provide(providers: &mut ty::query::Providers) { #[derive(Default)] pub struct OpaqueFnEntry<'tcx> { + // The trait ref is already stored as a key, so just track if we have it as a real predicate + has_fn_once: bool, fn_mut_trait_ref: Option>, fn_trait_ref: Option>, return_ty: Option>>, diff --git a/src/test/mir-opt/inline/issue_78442.bar.Inline.diff b/src/test/mir-opt/inline/issue_78442.bar.Inline.diff index 3e72d1c42fade..045bc720ca701 100644 --- a/src/test/mir-opt/inline/issue_78442.bar.Inline.diff +++ b/src/test/mir-opt/inline/issue_78442.bar.Inline.diff @@ -19,16 +19,16 @@ + _4 = hide_foo() -> [return: bb1, unwind: bb3]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:15 // mir::Constant // + span: $DIR/issue-78442.rs:11:5: 11:13 - // + literal: Const { ty: fn() -> impl Fn() -> () {hide_foo}, val: Value(Scalar()) } + // + literal: Const { ty: fn() -> impl Fn() {hide_foo}, val: Value(Scalar()) } } bb1: { _3 = &_4; // scope 0 at $DIR/issue-78442.rs:11:5: 11:15 StorageLive(_5); // scope 0 at $DIR/issue-78442.rs:11:5: 11:17 -- _2 = () as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:17 +- _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:17 - // mir::Constant - // + span: $DIR/issue-78442.rs:11:5: 11:15 -- // + literal: Const { ty: for<'r> extern "rust-call" fn(&'r impl Fn() -> (), ()) -> () as std::ops::FnOnce<()>>::Output { () as std::ops::Fn<()>>::call}, val: Value(Scalar()) } +- // + literal: Const { ty: for<'r> extern "rust-call" fn(&'r impl Fn(), ()) -> >::Output {>::call}, val: Value(Scalar()) } + _2 = move (*_3)() -> [return: bb5, unwind: bb3]; // scope 1 at $DIR/issue-78442.rs:11:5: 11:17 } diff --git a/src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff b/src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff index 622599a2d18d5..3190db52286bc 100644 --- a/src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff +++ b/src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff @@ -5,8 +5,8 @@ debug _baz => _1; // in scope 0 at $DIR/issue-78442.rs:9:5: 9:9 let mut _0: (); // return place in scope 0 at $DIR/issue-78442.rs:10:3: 10:3 let _2: (); // in scope 0 at $DIR/issue-78442.rs:11:5: 11:17 -- let mut _3: &impl Fn() -> (); // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15 -- let _4: impl Fn() -> (); // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15 +- let mut _3: &impl Fn(); // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15 +- let _4: impl Fn(); // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15 + let mut _3: &fn() {foo}; // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15 + let _4: fn() {foo}; // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15 let mut _5: (); // in scope 0 at $DIR/issue-78442.rs:11:5: 11:17 @@ -18,17 +18,17 @@ _4 = hide_foo() -> [return: bb1, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:15 // mir::Constant // + span: $DIR/issue-78442.rs:11:5: 11:13 - // + literal: Const { ty: fn() -> impl Fn() -> () {hide_foo}, val: Value(Scalar()) } + // + literal: Const { ty: fn() -> impl Fn() {hide_foo}, val: Value(Scalar()) } } bb1: { _3 = &_4; // scope 0 at $DIR/issue-78442.rs:11:5: 11:15 StorageLive(_5); // scope 0 at $DIR/issue-78442.rs:11:5: 11:17 nop; // scope 0 at $DIR/issue-78442.rs:11:5: 11:17 - _2 = () as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:17 + _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:17 // mir::Constant // + span: $DIR/issue-78442.rs:11:5: 11:15 - // + literal: Const { ty: for<'r> extern "rust-call" fn(&'r impl Fn() -> (), ()) -> () as std::ops::FnOnce<()>>::Output { () as std::ops::Fn<()>>::call}, val: Value(Scalar()) } + // + literal: Const { ty: for<'r> extern "rust-call" fn(&'r impl Fn(), ()) -> >::Output {>::call}, val: Value(Scalar()) } } bb2: { diff --git a/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr b/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr index 42c6de2012768..c731c32832222 100644 --- a/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr +++ b/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr @@ -21,7 +21,7 @@ LL | type MainFn = impl Fn(); LL | pub const BAR: MainFn = bar; | ^^^ expected opaque type, found fn item | - = note: expected opaque type `impl Fn() -> ()` + = note: expected opaque type `impl Fn()` found fn item `fn() {bar}` error: could not find defining uses diff --git a/src/test/ui/impl-trait/auto-trait-leak2.stderr b/src/test/ui/impl-trait/auto-trait-leak2.stderr index 2ca180029ae7f..37ae3c6802964 100644 --- a/src/test/ui/impl-trait/auto-trait-leak2.stderr +++ b/src/test/ui/impl-trait/auto-trait-leak2.stderr @@ -2,16 +2,16 @@ error[E0277]: `Rc>` cannot be sent between threads safely --> $DIR/auto-trait-leak2.rs:13:10 | LL | fn before() -> impl Fn(i32) { - | ------------ within this `impl Fn(i32) -> ()` + | ------------ within this `impl Fn(i32)` ... LL | send(before()); | ---- ^^^^^^^^ `Rc>` cannot be sent between threads safely | | | required by a bound introduced by this call | - = help: within `impl Fn(i32) -> ()`, the trait `Send` is not implemented for `Rc>` + = help: within `impl Fn(i32)`, the trait `Send` is not implemented for `Rc>` = note: required because it appears within the type `[closure@$DIR/auto-trait-leak2.rs:7:5: 7:22]` - = note: required because it appears within the type `impl Fn(i32) -> ()` + = note: required because it appears within the type `impl Fn(i32)` note: required by a bound in `send` --> $DIR/auto-trait-leak2.rs:10:12 | @@ -27,11 +27,11 @@ LL | send(after()); | required by a bound introduced by this call ... LL | fn after() -> impl Fn(i32) { - | ------------ within this `impl Fn(i32) -> ()` + | ------------ within this `impl Fn(i32)` | - = help: within `impl Fn(i32) -> ()`, the trait `Send` is not implemented for `Rc>` + = help: within `impl Fn(i32)`, the trait `Send` is not implemented for `Rc>` = note: required because it appears within the type `[closure@$DIR/auto-trait-leak2.rs:24:5: 24:22]` - = note: required because it appears within the type `impl Fn(i32) -> ()` + = note: required because it appears within the type `impl Fn(i32)` note: required by a bound in `send` --> $DIR/auto-trait-leak2.rs:10:12 | diff --git a/src/test/ui/impl-trait/issue-87450.stderr b/src/test/ui/impl-trait/issue-87450.stderr index 9b7d225a53eee..5019e544bd562 100644 --- a/src/test/ui/impl-trait/issue-87450.stderr +++ b/src/test/ui/impl-trait/issue-87450.stderr @@ -17,10 +17,10 @@ LL | fn foo() -> impl Fn() { | ^^^^^^^^^ recursive opaque type ... LL | wrap(wrap(wrap(wrap(wrap(wrap(wrap(foo()))))))) - | ----------------------------------------------- returning here with type `impl Fn() -> ()` + | ----------------------------------------------- returning here with type `impl Fn()` ... LL | fn wrap(f: impl Fn()) -> impl Fn() { - | --------- returning this opaque type `impl Fn() -> ()` + | --------- returning this opaque type `impl Fn()` error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/impl-trait/issues/issue-86201.stderr b/src/test/ui/impl-trait/issues/issue-86201.stderr index d65bddf7cfa3f..b1460096ded66 100644 --- a/src/test/ui/impl-trait/issues/issue-86201.stderr +++ b/src/test/ui/impl-trait/issues/issue-86201.stderr @@ -7,7 +7,7 @@ LL | LL | static STATIC_FN: FunType = some_fn; | ^^^^^^^ expected opaque type, found fn item | - = note: expected opaque type `impl Fn<()> + FnOnce<()>` + = note: expected opaque type `impl Fn<()>` found fn item `fn() {some_fn}` error: could not find defining uses diff --git a/src/test/ui/issues/issue-59494.rs b/src/test/ui/issues/issue-59494.rs index 65ef436129e91..a53e28f7246e6 100644 --- a/src/test/ui/issues/issue-59494.rs +++ b/src/test/ui/issues/issue-59494.rs @@ -19,5 +19,5 @@ fn main() { let g = |(a, _)| a; let t7 = |env| |a| |b| t7p(f, g)(((env, a), b)); let t8 = t8n(t7, t7p(f, g)); - //~^ ERROR: expected a `Fn<(_,)>` closure, found `impl Fn(((_, _), _)) -> ()` [E0277] + //~^ ERROR: expected a `Fn<(_,)>` closure, found `impl Fn(((_, _), _))` [E0277] } diff --git a/src/test/ui/issues/issue-59494.stderr b/src/test/ui/issues/issue-59494.stderr index 0af54f567f0ff..a9284535e4dc4 100644 --- a/src/test/ui/issues/issue-59494.stderr +++ b/src/test/ui/issues/issue-59494.stderr @@ -1,12 +1,12 @@ -error[E0277]: expected a `Fn<(_,)>` closure, found `impl Fn(((_, _), _)) -> ()` +error[E0277]: expected a `Fn<(_,)>` closure, found `impl Fn(((_, _), _))` --> $DIR/issue-59494.rs:21:22 | LL | let t8 = t8n(t7, t7p(f, g)); - | --- ^^^^^^^^^ expected an `Fn<(_,)>` closure, found `impl Fn(((_, _), _)) -> ()` + | --- ^^^^^^^^^ expected an `Fn<(_,)>` closure, found `impl Fn(((_, _), _))` | | | required by a bound introduced by this call | - = help: the trait `Fn<(_,)>` is not implemented for `impl Fn(((_, _), _)) -> ()` + = help: the trait `Fn<(_,)>` is not implemented for `impl Fn(((_, _), _))` note: required by a bound in `t8n` --> $DIR/issue-59494.rs:5:45 | diff --git a/src/test/ui/lint/opaque-ty-ffi-unsafe.rs b/src/test/ui/lint/opaque-ty-ffi-unsafe.rs index efdc4037b6356..3a62b6a21a56a 100644 --- a/src/test/ui/lint/opaque-ty-ffi-unsafe.rs +++ b/src/test/ui/lint/opaque-ty-ffi-unsafe.rs @@ -9,7 +9,7 @@ pub fn ret_closure() -> A { extern "C" { pub fn a(_: A); - //~^ ERROR `extern` block uses type `impl Fn() -> ()`, which is not FFI-safe [improper_ctypes] + //~^ ERROR `extern` block uses type `impl Fn()`, which is not FFI-safe [improper_ctypes] } fn main() {} diff --git a/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr b/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr index c77d8c0c18bc8..5afbef778b3e3 100644 --- a/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr +++ b/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr @@ -1,4 +1,4 @@ -error: `extern` block uses type `impl Fn() -> ()`, which is not FFI-safe +error: `extern` block uses type `impl Fn()`, which is not FFI-safe --> $DIR/opaque-ty-ffi-unsafe.rs:11:17 | LL | pub fn a(_: A); From 94c9c22b39d7d82021fe342d19b5248f19335b2f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 23 Nov 2021 14:12:14 -0500 Subject: [PATCH 13/20] explain why CTFE/Miri perform truncation on shift offset --- compiler/rustc_const_eval/src/interpret/operator.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index ac000b1bb566f..a90582fc33820 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -130,7 +130,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let signed = left_layout.abi.is_signed(); let size = u128::from(left_layout.size.bits()); let overflow = r >= size; - let r = r % size; // mask to type size + // The shift offset is implicitly masked to the type size, to make sure this operation + // is always defined. This is the one MIR operator that does *not* directly map to a + // single LLVM operation. See + // + // for the corresponding truncation in our codegen backends. + let r = r % size; let r = u32::try_from(r).unwrap(); // we masked so this will always fit let result = if signed { let l = self.sign_extend(l, left_layout) as i128; From 5f6ccf61218fb98c2aa2cff0af83557d7ccaa5fd Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 23 Nov 2021 20:30:26 -0500 Subject: [PATCH 14/20] document BinOp behavior quirks in the corresponding enum --- compiler/rustc_middle/src/mir/mod.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 253ac266bedaa..4210e07d2780b 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -2246,8 +2246,12 @@ pub enum BinOp { /// The `*` operator (multiplication) Mul, /// The `/` operator (division) + /// + /// Division by zero is UB. Div, /// The `%` operator (modulus) + /// + /// Using zero as the modulus (second operand) is UB. Rem, /// The `^` operator (bitwise xor) BitXor, @@ -2256,8 +2260,12 @@ pub enum BinOp { /// The `|` operator (bitwise or) BitOr, /// The `<<` operator (shift left) + /// + /// The offset is truncated to the size of the first operand before shifting. Shl, /// The `>>` operator (shift right) + /// + /// The offset is truncated to the size of the first operand before shifting. Shr, /// The `==` operator (equality) Eq, From 3b25e92a8fbb5856499a84e02bf393a9c18eb962 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Wed, 29 Sep 2021 12:12:21 +0000 Subject: [PATCH 15/20] Debug --- .../rustc_const_eval/src/transform/check_consts/check.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 2854e6fd396c2..4e3a8b64094af 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -1004,11 +1004,12 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> { } let mut err_span = self.span; + let ty_of_dropped_place = dropped_place.ty(self.body, self.tcx).ty; - let ty_needs_non_const_drop = qualifs::NeedsNonConstDrop::in_any_value_of_ty( - self.ccx, - dropped_place.ty(self.body, self.tcx).ty, - ); + let ty_needs_non_const_drop = + qualifs::NeedsNonConstDrop::in_any_value_of_ty(self.ccx, ty_of_dropped_place); + + debug!(?ty_of_dropped_place, ?ty_needs_non_const_drop); if !ty_needs_non_const_drop { return; From e0c2ff7ccc0b0ffe095bbf7e1ae358d96bb9152f Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Wed, 29 Sep 2021 12:15:17 +0000 Subject: [PATCH 16/20] Allow more cases to match ~const Drop. --- .../src/traits/select/candidate_assembly.rs | 80 +++++++++++-------- .../const-drop-bound.rs | 20 +++++ 2 files changed, 68 insertions(+), 32 deletions(-) create mode 100644 src/test/ui/rfc-2632-const-trait-impl/const-drop-bound.rs diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 1d0c54f86dea8..c925672fa3529 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -284,32 +284,32 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // structs and enums. self.assemble_candidates_from_impls(obligation, &mut candidates); - // For other types, we'll use the builtin rules. - let copy_conditions = self.copy_clone_conditions(obligation); - self.assemble_builtin_bound_candidates(copy_conditions, &mut candidates); - } else if lang_items.discriminant_kind_trait() == Some(def_id) { - // `DiscriminantKind` is automatically implemented for every type. - candidates.vec.push(DiscriminantKindCandidate); - } else if lang_items.pointee_trait() == Some(def_id) { - // `Pointee` is automatically implemented for every type. - candidates.vec.push(PointeeCandidate); - } else if lang_items.sized_trait() == Some(def_id) { - // Sized is never implementable by end-users, it is - // always automatically computed. - let sized_conditions = self.sized_conditions(obligation); - self.assemble_builtin_bound_candidates(sized_conditions, &mut candidates); - } else if lang_items.unsize_trait() == Some(def_id) { - self.assemble_candidates_for_unsizing(obligation, &mut candidates); - } else if lang_items.drop_trait() == Some(def_id) - && obligation.predicate.skip_binder().constness == ty::BoundConstness::ConstIfConst - { - if self.is_in_const_context { - self.assemble_const_drop_candidates(obligation, &mut candidates)?; - } else { - debug!("passing ~const Drop bound; in non-const context"); - // `~const Drop` when we are not in a const context has no effect. - candidates.vec.push(ConstDropCandidate) - } + // For other types, we'll use the builtin rules. + let copy_conditions = self.copy_clone_conditions(obligation); + self.assemble_builtin_bound_candidates(copy_conditions, &mut candidates); + } else if lang_items.discriminant_kind_trait() == Some(def_id) { + // `DiscriminantKind` is automatically implemented for every type. + candidates.vec.push(DiscriminantKindCandidate); + } else if lang_items.pointee_trait() == Some(def_id) { + // `Pointee` is automatically implemented for every type. + candidates.vec.push(PointeeCandidate); + } else if lang_items.sized_trait() == Some(def_id) { + // Sized is never implementable by end-users, it is + // always automatically computed. + let sized_conditions = self.sized_conditions(obligation); + self.assemble_builtin_bound_candidates(sized_conditions, &mut candidates); + } else if lang_items.unsize_trait() == Some(def_id) { + self.assemble_candidates_for_unsizing(obligation, &mut candidates); + } else if lang_items.drop_trait() == Some(def_id) + && obligation.predicate.skip_binder().constness == ty::BoundConstness::ConstIfConst + { + if self.is_in_const_context { + self.assemble_const_drop_candidates(obligation, stack, &mut candidates)?; + } else { + debug!("passing ~const Drop bound; in non-const context"); + // `~const Drop` when we are not in a const context has no effect. + candidates.vec.push(ConstDropCandidate) + } } else { if lang_items.clone_trait() == Some(def_id) { // Same builtin conditions as `Copy`, i.e., every type which has builtin support @@ -911,9 +911,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - fn assemble_const_drop_candidates( + fn assemble_const_drop_candidates<'a>( &mut self, obligation: &TraitObligation<'tcx>, + obligation_stack: &TraitObligationStack<'a, 'tcx>, candidates: &mut SelectionCandidateSet<'tcx>, ) -> Result<(), SelectionError<'tcx>> { let mut stack: Vec<(Ty<'tcx>, usize)> = vec![(obligation.self_ty().skip_binder(), 0)]; @@ -922,7 +923,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let mut noreturn = false; self.check_recursion_depth(depth, obligation)?; - let mut copy_candidates = SelectionCandidateSet { vec: Vec::new(), ambiguous: false }; + let mut new_candidates = SelectionCandidateSet { vec: Vec::new(), ambiguous: false }; let mut copy_obligation = obligation.with(obligation.predicate.rebind(ty::TraitPredicate { trait_ref: ty::TraitRef { @@ -933,13 +934,28 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { polarity: ty::ImplPolarity::Positive, })); copy_obligation.recursion_depth = depth + 1; - self.assemble_candidates_from_impls(©_obligation, &mut copy_candidates); + self.assemble_candidates_from_impls(©_obligation, &mut new_candidates); let copy_conditions = self.copy_clone_conditions(©_obligation); - self.assemble_builtin_bound_candidates(copy_conditions, &mut copy_candidates); - if !copy_candidates.vec.is_empty() { + self.assemble_builtin_bound_candidates(copy_conditions, &mut new_candidates); + let copy_stack = self.push_stack(obligation_stack.list(), ©_obligation); + self.assemble_candidates_from_caller_bounds(©_stack, &mut new_candidates)?; + + let const_drop_obligation = + obligation.with(obligation.predicate.rebind(ty::TraitPredicate { + trait_ref: ty::TraitRef { + def_id: self.tcx().require_lang_item(hir::LangItem::Drop, None), + substs: self.tcx().mk_substs_trait(ty, &[]), + }, + constness: ty::BoundConstness::ConstIfConst, + })); + + let const_drop_stack = self.push_stack(obligation_stack.list(), &const_drop_obligation); + self.assemble_candidates_from_caller_bounds(&const_drop_stack, &mut new_candidates)?; + + if !new_candidates.vec.is_empty() { noreturn = true; } - debug!(?copy_candidates.vec, "assemble_const_drop_candidates - copy"); + debug!(?new_candidates.vec, "assemble_const_drop_candidates"); match ty.kind() { ty::Int(_) diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-bound.rs b/src/test/ui/rfc-2632-const-trait-impl/const-drop-bound.rs new file mode 100644 index 0000000000000..83fa32bf092bb --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-bound.rs @@ -0,0 +1,20 @@ +// check-pass + +#![feature(const_trait_impl)] +#![feature(const_fn_trait_bound)] +#![feature(const_precise_live_drops)] + +const fn foo(res: Result) -> Option where E: ~const Drop { + match res { + Ok(t) => Some(t), + Err(_e) => None, + } +} + +pub struct Foo(T); + +const fn baz(res: Result, Foo>) -> Option> { + foo(res) +} + +fn main() {} From b2005117bc475700f117ab01cf72fb46f1fe2d69 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Wed, 29 Sep 2021 12:15:35 +0000 Subject: [PATCH 17/20] Allow features like const_try in d_m_b_i_c --- compiler/rustc_passes/src/check_const.rs | 6 +++ .../trait-default-body-stability.rs | 51 +++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 src/test/ui/rfc-2632-const-trait-impl/trait-default-body-stability.rs diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs index 82486a6a5f2e2..9ccf76b5700c2 100644 --- a/compiler/rustc_passes/src/check_const.rs +++ b/compiler/rustc_passes/src/check_const.rs @@ -173,6 +173,12 @@ impl<'tcx> CheckConstVisitor<'tcx> { None => return true, }; + // If the function belongs to a trait, then it must enable the const_trait_impl + // feature to use that trait function (with a const default body). + if tcx.trait_of_item(def_id).is_some() { + return true; + } + // If this crate is not using stability attributes, or this function is not claiming to be a // stable `const fn`, that is all that is required. if !tcx.features().staged_api || tcx.has_attr(def_id, sym::rustc_const_unstable) { diff --git a/src/test/ui/rfc-2632-const-trait-impl/trait-default-body-stability.rs b/src/test/ui/rfc-2632-const-trait-impl/trait-default-body-stability.rs new file mode 100644 index 0000000000000..cbfdf89b7bd19 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/trait-default-body-stability.rs @@ -0,0 +1,51 @@ +// check-pass + +#![feature(staged_api)] +#![feature(const_trait_impl)] +#![feature(const_fn_trait_bound)] +#![feature(const_t_try)] +#![feature(const_try)] +#![feature(try_trait_v2)] + +#![stable(feature = "foo", since = "1.0")] + +use std::ops::{ControlFlow, FromResidual, Try}; + +#[stable(feature = "foo", since = "1.0")] +pub struct T; + +#[stable(feature = "foo", since = "1.0")] +#[rustc_const_unstable(feature = "const_t_try", issue = "none")] +impl const Try for T { + type Output = T; + type Residual = T; + + fn from_output(t: T) -> T { + t + } + + fn branch(self) -> ControlFlow { + ControlFlow::Continue(self) + } +} + +#[stable(feature = "foo", since = "1.0")] +#[rustc_const_unstable(feature = "const_t_try", issue = "none")] +impl const FromResidual for T { + fn from_residual(t: T) -> T { + t + } +} + +#[stable(feature = "foo", since = "1.0")] +pub trait Tr { + #[default_method_body_is_const] + #[stable(feature = "foo", since = "1.0")] + fn bar() -> T { + T? + // Should be allowed. + // Must enable unstable features to call this trait fn in const contexts. + } +} + +fn main() {} From 4f29f3cef85a2a66fcfc76bc7fa3cca3d84266f8 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Wed, 24 Nov 2021 16:07:38 +0800 Subject: [PATCH 18/20] Add impl polarity to fields --- .../src/traits/select/candidate_assembly.rs | 53 ++++++++++--------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index c925672fa3529..0ff3611f8f80d 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -284,32 +284,32 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // structs and enums. self.assemble_candidates_from_impls(obligation, &mut candidates); - // For other types, we'll use the builtin rules. - let copy_conditions = self.copy_clone_conditions(obligation); - self.assemble_builtin_bound_candidates(copy_conditions, &mut candidates); - } else if lang_items.discriminant_kind_trait() == Some(def_id) { - // `DiscriminantKind` is automatically implemented for every type. - candidates.vec.push(DiscriminantKindCandidate); - } else if lang_items.pointee_trait() == Some(def_id) { - // `Pointee` is automatically implemented for every type. - candidates.vec.push(PointeeCandidate); - } else if lang_items.sized_trait() == Some(def_id) { - // Sized is never implementable by end-users, it is - // always automatically computed. - let sized_conditions = self.sized_conditions(obligation); - self.assemble_builtin_bound_candidates(sized_conditions, &mut candidates); - } else if lang_items.unsize_trait() == Some(def_id) { - self.assemble_candidates_for_unsizing(obligation, &mut candidates); - } else if lang_items.drop_trait() == Some(def_id) - && obligation.predicate.skip_binder().constness == ty::BoundConstness::ConstIfConst - { - if self.is_in_const_context { - self.assemble_const_drop_candidates(obligation, stack, &mut candidates)?; - } else { - debug!("passing ~const Drop bound; in non-const context"); - // `~const Drop` when we are not in a const context has no effect. - candidates.vec.push(ConstDropCandidate) - } + // For other types, we'll use the builtin rules. + let copy_conditions = self.copy_clone_conditions(obligation); + self.assemble_builtin_bound_candidates(copy_conditions, &mut candidates); + } else if lang_items.discriminant_kind_trait() == Some(def_id) { + // `DiscriminantKind` is automatically implemented for every type. + candidates.vec.push(DiscriminantKindCandidate); + } else if lang_items.pointee_trait() == Some(def_id) { + // `Pointee` is automatically implemented for every type. + candidates.vec.push(PointeeCandidate); + } else if lang_items.sized_trait() == Some(def_id) { + // Sized is never implementable by end-users, it is + // always automatically computed. + let sized_conditions = self.sized_conditions(obligation); + self.assemble_builtin_bound_candidates(sized_conditions, &mut candidates); + } else if lang_items.unsize_trait() == Some(def_id) { + self.assemble_candidates_for_unsizing(obligation, &mut candidates); + } else if lang_items.drop_trait() == Some(def_id) + && obligation.predicate.skip_binder().constness == ty::BoundConstness::ConstIfConst + { + if self.is_in_const_context { + self.assemble_const_drop_candidates(obligation, stack, &mut candidates)?; + } else { + debug!("passing ~const Drop bound; in non-const context"); + // `~const Drop` when we are not in a const context has no effect. + candidates.vec.push(ConstDropCandidate) + } } else { if lang_items.clone_trait() == Some(def_id) { // Same builtin conditions as `Copy`, i.e., every type which has builtin support @@ -947,6 +947,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { substs: self.tcx().mk_substs_trait(ty, &[]), }, constness: ty::BoundConstness::ConstIfConst, + polarity: ty::ImplPolarity::Positive, })); let const_drop_stack = self.push_stack(obligation_stack.list(), &const_drop_obligation); From 58720096f2b0146f6a5bbf32063dc136dc1ad150 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 24 Nov 2021 13:35:15 +0100 Subject: [PATCH 19/20] Fix more color --- src/librustdoc/html/static/css/themes/ayu.css | 2 ++ src/librustdoc/html/static/css/themes/dark.css | 2 ++ src/librustdoc/html/static/css/themes/light.css | 2 ++ 3 files changed, 6 insertions(+) diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index 85fb34b39595c..13e8dc85a243c 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -218,6 +218,8 @@ a { } a.srclink, a#toggle-all-docs, +a.anchor, +.section-header a, #source-sidebar a, pre.rust a, .sidebar a, diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css index 5a6c08bafd240..8caf8a05d507f 100644 --- a/src/librustdoc/html/static/css/themes/dark.css +++ b/src/librustdoc/html/static/css/themes/dark.css @@ -180,6 +180,8 @@ a { } a.srclink, a#toggle-all-docs, +a.anchor, +.section-header a, #source-sidebar a, pre.rust a, .sidebar a, diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css index 05f12fc365d74..fec71674e634f 100644 --- a/src/librustdoc/html/static/css/themes/light.css +++ b/src/librustdoc/html/static/css/themes/light.css @@ -175,6 +175,8 @@ a { } a.srclink, a#toggle-all-docs, +a.anchor, +.section-header a, #source-sidebar a, pre.rust a, .sidebar a, From 0ba92fe5a399b2e36c7114e9828fc868aad616ac Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 24 Nov 2021 13:35:25 +0100 Subject: [PATCH 20/20] Update GUI tests for color --- src/test/rustdoc-gui/anchors.goml | 28 ++++++++++++++++++------- src/test/rustdoc-gui/headers-color.goml | 9 ++++++++ 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/test/rustdoc-gui/anchors.goml b/src/test/rustdoc-gui/anchors.goml index 6953009604c5e..4ce0ed1a4b8fd 100644 --- a/src/test/rustdoc-gui/anchors.goml +++ b/src/test/rustdoc-gui/anchors.goml @@ -1,17 +1,29 @@ +// This test is to ensure that the anchors (`ยง`) have the expected color. goto: file://|DOC_PATH|/test_docs/struct.HeavilyDocumentedStruct.html +// This is needed to ensure that the text color is computed. +show-text: true + // Set the theme to light. local-storage: {"rustdoc-theme": "light", "rustdoc-use-system-theme": "false"} // We reload the page so the local storage settings are being used. reload: -assert-css: ("#toggle-all-docs", {"color": "rgba(0, 0, 0, 0)"}) -assert-css: (".fqn .in-band a:nth-of-type(1)", {"color": "rgba(0, 0, 0, 0)"}) -assert-css: (".fqn .in-band a:nth-of-type(2)", {"color": "rgba(0, 0, 0, 0)"}) -assert-css: (".srclink", {"color": "rgba(0, 0, 0, 0)"}) -assert-css: (".srclink", {"color": "rgba(0, 0, 0, 0)"}) +assert-css: ("#toggle-all-docs", {"color": "rgb(0, 0, 0)"}) +assert-css: (".fqn .in-band a:nth-of-type(1)", {"color": "rgb(0, 0, 0)"}) +assert-css: (".fqn .in-band a:nth-of-type(2)", {"color": "rgb(173, 68, 142)"}) +assert-css: (".srclink", {"color": "rgb(0, 0, 0)"}) +assert-css: (".srclink", {"color": "rgb(0, 0, 0)"}) + +assert-css: ("#top-doc-prose-title", {"color": "rgb(0, 0, 0)"}) + +assert-css: (".sidebar a", {"color": "rgb(0, 0, 0)"}) +assert-css: (".in-band a", {"color": "rgb(0, 0, 0)"}) -assert-css: ("#top-doc-prose-title", {"color": "rgba(0, 0, 0, 0)"}) +// We move the cursor over the "Implementations" title so the anchor is displayed. +move-cursor-to: "h2#implementations" +assert-css: ("h2#implementations a.anchor", {"color": "rgb(0, 0, 0)"}) -assert-css: (".sidebar a", {"color": "rgba(0, 0, 0, 0)"}) -assert-css: (".in-band a", {"color": "rgba(0, 0, 0, 0)"}) +// Same thing with the impl block title. +move-cursor-to: "#impl" +assert-css: ("#impl a.anchor", {"color": "rgb(0, 0, 0)"}) diff --git a/src/test/rustdoc-gui/headers-color.goml b/src/test/rustdoc-gui/headers-color.goml index b5be31bd2cc0a..7002812bb62c4 100644 --- a/src/test/rustdoc-gui/headers-color.goml +++ b/src/test/rustdoc-gui/headers-color.goml @@ -17,6 +17,9 @@ assert-css: ("#impl", {"color": "rgb(197, 197, 197)", "background-color": "rgba( goto: file://|DOC_PATH|/test_docs/struct.Foo.html#method.must_use assert-css: ("#method\.must_use", {"color": "rgb(197, 197, 197)", "background-color": "rgba(255, 236, 164, 0.06)"}, ALL) +goto: file://|DOC_PATH|/test_docs/index.html +assert-css: (".section-header a", {"color": "rgb(197, 197, 197)"}, ALL) + // Dark theme local-storage: {"rustdoc-theme": "dark", "rustdoc-preferred-dark-theme": "dark", "rustdoc-use-system-theme": "false"} goto: file://|DOC_PATH|/test_docs/struct.Foo.html @@ -30,6 +33,9 @@ assert-css: ("#impl", {"color": "rgb(221, 221, 221)", "background-color": "rgb(7 goto: file://|DOC_PATH|/test_docs/struct.Foo.html#method.must_use assert-css: ("#method\.must_use", {"color": "rgb(221, 221, 221)", "background-color": "rgb(73, 74, 61)"}, ALL) +goto: file://|DOC_PATH|/test_docs/index.html +assert-css: (".section-header a", {"color": "rgb(221, 221, 221)"}, ALL) + // Light theme local-storage: {"rustdoc-theme": "light", "rustdoc-use-system-theme": "false"} reload: @@ -44,3 +50,6 @@ assert-css: ("#impl", {"color": "rgb(0, 0, 0)", "background-color": "rgb(253, 25 goto: file://|DOC_PATH|/test_docs/struct.Foo.html#method.must_use assert-css: ("#method\.must_use", {"color": "rgb(0, 0, 0)", "background-color": "rgb(253, 255, 211)"}, ALL) + +goto: file://|DOC_PATH|/test_docs/index.html +assert-css: (".section-header a", {"color": "rgb(0, 0, 0)"}, ALL)