Skip to content

Commit 2fbc08e

Browse files
committed
Auto merge of #100516 - compiler-errors:rollup-fgrfeb3, r=compiler-errors
Rollup of 8 pull requests Successful merges: - #99646 (Only point out a single function parameter if we have a single arg incompatibility) - #100299 (make `clean::Item::span` return `Option` instead of dummy span) - #100335 (Rustdoc-Json: Add `Path` type for traits.) - #100367 (Suggest the path separator when a dot is used on a trait) - #100431 (Enum variant ctor inherits the stability of the enum variant) - #100446 (Suggest removing a semicolon after impl/trait items) - #100468 (Use an extensionless `x` script for non-Windows) - #100479 (Argument type error improvements) Failed merges: - #100483 (Point to generic or arg if it's the self type of unsatisfied projection predicate) r? `@ghost` `@rustbot` modify labels: rollup
2 parents d70c0ec + b3e76aa commit 2fbc08e

File tree

63 files changed

+843
-269
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+843
-269
lines changed

compiler/rustc_infer/src/infer/error_reporting/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1424,7 +1424,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
14241424
/// E0271, like `src/test/ui/issues/issue-39970.stderr`.
14251425
#[tracing::instrument(
14261426
level = "debug",
1427-
skip(self, diag, secondary_span, swap_secondary_and_primary, force_label)
1427+
skip(self, diag, secondary_span, swap_secondary_and_primary, prefer_label)
14281428
)]
14291429
pub fn note_type_err(
14301430
&self,
@@ -1434,7 +1434,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
14341434
mut values: Option<ValuePairs<'tcx>>,
14351435
terr: &TypeError<'tcx>,
14361436
swap_secondary_and_primary: bool,
1437-
force_label: bool,
1437+
prefer_label: bool,
14381438
) {
14391439
let span = cause.span();
14401440

@@ -1612,7 +1612,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
16121612
TypeError::ObjectUnsafeCoercion(_) => {}
16131613
_ => {
16141614
let mut label_or_note = |span: Span, msg: &str| {
1615-
if force_label || &[span] == diag.span.primary_spans() {
1615+
if (prefer_label && is_simple_error) || &[span] == diag.span.primary_spans() {
16161616
diag.span_label(span, msg);
16171617
} else {
16181618
diag.span_note(span, msg);

compiler/rustc_parse/src/parser/expr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2268,7 +2268,7 @@ impl<'a> Parser<'a> {
22682268
attrs: attrs.into(),
22692269
ty,
22702270
pat,
2271-
span: lo.to(this.token.span),
2271+
span: lo.to(this.prev_token.span),
22722272
id: DUMMY_NODE_ID,
22732273
is_placeholder: false,
22742274
},

compiler/rustc_parse/src/parser/item.rs

+34-4
Original file line numberDiff line numberDiff line change
@@ -675,14 +675,44 @@ impl<'a> Parser<'a> {
675675
}
676676
match parse_item(self) {
677677
Ok(None) => {
678+
let is_unnecessary_semicolon = !items.is_empty()
679+
// When the close delim is `)` in a case like the following, `token.kind` is expected to be `token::CloseDelim(Delimiter::Parenthesis)`,
680+
// but the actual `token.kind` is `token::CloseDelim(Delimiter::Bracket)`.
681+
// This is because the `token.kind` of the close delim is treated as the same as
682+
// that of the open delim in `TokenTreesReader::parse_token_tree`, even if the delimiters of them are different.
683+
// Therefore, `token.kind` should not be compared here.
684+
//
685+
// issue-60075.rs
686+
// ```
687+
// trait T {
688+
// fn qux() -> Option<usize> {
689+
// let _ = if true {
690+
// });
691+
// ^ this close delim
692+
// Some(4)
693+
// }
694+
// ```
695+
&& self
696+
.span_to_snippet(self.prev_token.span)
697+
.map_or(false, |snippet| snippet == "}")
698+
&& self.token.kind == token::Semi;
699+
let semicolon_span = self.token.span;
678700
// We have to bail or we'll potentially never make progress.
679701
let non_item_span = self.token.span;
680702
self.consume_block(Delimiter::Brace, ConsumeClosingDelim::Yes);
681-
self.struct_span_err(non_item_span, "non-item in item list")
682-
.span_label(open_brace_span, "item list starts here")
703+
let mut err = self.struct_span_err(non_item_span, "non-item in item list");
704+
err.span_label(open_brace_span, "item list starts here")
683705
.span_label(non_item_span, "non-item starts here")
684-
.span_label(self.prev_token.span, "item list ends here")
685-
.emit();
706+
.span_label(self.prev_token.span, "item list ends here");
707+
if is_unnecessary_semicolon {
708+
err.span_suggestion(
709+
semicolon_span,
710+
"consider removing this semicolon",
711+
"",
712+
Applicability::MaybeIncorrect,
713+
);
714+
}
715+
err.emit();
686716
break;
687717
}
688718
Ok(Some(item)) => items.extend(item),

compiler/rustc_passes/src/stability.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
460460
AnnotationKind::Required,
461461
InheritDeprecation::Yes,
462462
InheritConstStability::No,
463-
InheritStability::No,
463+
InheritStability::Yes,
464464
|_| {},
465465
);
466466
}
@@ -600,6 +600,9 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> {
600600

601601
fn visit_variant(&mut self, var: &'tcx Variant<'tcx>) {
602602
self.check_missing_stability(self.tcx.hir().local_def_id(var.id), var.span);
603+
if let Some(ctor_hir_id) = var.data.ctor_hir_id() {
604+
self.check_missing_stability(self.tcx.hir().local_def_id(ctor_hir_id), var.span);
605+
}
603606
intravisit::walk_variant(self, var);
604607
}
605608

compiler/rustc_resolve/src/late/diagnostics.rs

+37-16
Original file line numberDiff line numberDiff line change
@@ -985,27 +985,45 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
985985
let ns = source.namespace();
986986
let is_expected = &|res| source.is_expected(res);
987987

988-
let path_sep = |err: &mut Diagnostic, expr: &Expr| match expr.kind {
989-
ExprKind::Field(_, ident) => {
988+
let path_sep = |err: &mut Diagnostic, expr: &Expr, kind: DefKind| {
989+
const MESSAGE: &str = "use the path separator to refer to an item";
990+
991+
let (lhs_span, rhs_span) = match &expr.kind {
992+
ExprKind::Field(base, ident) => (base.span, ident.span),
993+
ExprKind::MethodCall(_, receiver, _, span) => (receiver.span, *span),
994+
_ => return false,
995+
};
996+
997+
if lhs_span.eq_ctxt(rhs_span) {
990998
err.span_suggestion(
991-
expr.span,
992-
"use the path separator to refer to an item",
993-
format!("{}::{}", path_str, ident),
999+
lhs_span.between(rhs_span),
1000+
MESSAGE,
1001+
"::",
9941002
Applicability::MaybeIncorrect,
9951003
);
9961004
true
997-
}
998-
ExprKind::MethodCall(ref segment, ..) => {
999-
let span = expr.span.with_hi(segment.ident.span.hi());
1000-
err.span_suggestion(
1001-
span,
1002-
"use the path separator to refer to an item",
1003-
format!("{}::{}", path_str, segment.ident),
1005+
} else if kind == DefKind::Struct
1006+
&& let Some(lhs_source_span) = lhs_span.find_ancestor_inside(expr.span)
1007+
&& let Ok(snippet) = self.r.session.source_map().span_to_snippet(lhs_source_span)
1008+
{
1009+
// The LHS is a type that originates from a macro call.
1010+
// We have to add angle brackets around it.
1011+
1012+
err.span_suggestion_verbose(
1013+
lhs_source_span.until(rhs_span),
1014+
MESSAGE,
1015+
format!("<{snippet}>::"),
10041016
Applicability::MaybeIncorrect,
10051017
);
10061018
true
1019+
} else {
1020+
// Either we were unable to obtain the source span / the snippet or
1021+
// the LHS originates from a macro call and it is not a type and thus
1022+
// there is no way to replace `.` with `::` and still somehow suggest
1023+
// valid Rust code.
1024+
1025+
false
10071026
}
1008-
_ => false,
10091027
};
10101028

10111029
let find_span = |source: &PathSource<'_>, err: &mut Diagnostic| {
@@ -1027,7 +1045,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
10271045
match source {
10281046
PathSource::Expr(Some(
10291047
parent @ Expr { kind: ExprKind::Field(..) | ExprKind::MethodCall(..), .. },
1030-
)) if path_sep(err, &parent) => {}
1048+
)) if path_sep(err, &parent, DefKind::Struct) => {}
10311049
PathSource::Expr(
10321050
None
10331051
| Some(Expr {
@@ -1143,8 +1161,11 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
11431161
}
11441162
}
11451163
}
1146-
(Res::Def(DefKind::Mod, _), PathSource::Expr(Some(parent))) => {
1147-
if !path_sep(err, &parent) {
1164+
(
1165+
Res::Def(kind @ (DefKind::Mod | DefKind::Trait), _),
1166+
PathSource::Expr(Some(parent)),
1167+
) => {
1168+
if !path_sep(err, &parent, kind) {
11481169
return false;
11491170
}
11501171
}

compiler/rustc_typeck/src/check/fn_ctxt/checks.rs

+43-19
Original file line numberDiff line numberDiff line change
@@ -440,30 +440,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
440440
call_expr: &hir::Expr<'tcx>,
441441
) {
442442
// Next, let's construct the error
443-
let (error_span, full_call_span, ctor_of) = match &call_expr.kind {
443+
let (error_span, full_call_span, ctor_of, is_method) = match &call_expr.kind {
444444
hir::ExprKind::Call(
445445
hir::Expr { hir_id, span, kind: hir::ExprKind::Path(qpath), .. },
446446
_,
447447
) => {
448448
if let Res::Def(DefKind::Ctor(of, _), _) =
449449
self.typeck_results.borrow().qpath_res(qpath, *hir_id)
450450
{
451-
(call_span, *span, Some(of))
451+
(call_span, *span, Some(of), false)
452452
} else {
453-
(call_span, *span, None)
453+
(call_span, *span, None, false)
454454
}
455455
}
456-
hir::ExprKind::Call(hir::Expr { span, .. }, _) => (call_span, *span, None),
456+
hir::ExprKind::Call(hir::Expr { span, .. }, _) => (call_span, *span, None, false),
457457
hir::ExprKind::MethodCall(path_segment, _, span) => {
458458
let ident_span = path_segment.ident.span;
459459
let ident_span = if let Some(args) = path_segment.args {
460460
ident_span.with_hi(args.span_ext.hi())
461461
} else {
462462
ident_span
463463
};
464-
(
465-
*span, ident_span, None, // methods are never ctors
466-
)
464+
// methods are never ctors
465+
(*span, ident_span, None, true)
467466
}
468467
k => span_bug!(call_span, "checking argument types on a non-call: `{:?}`", k),
469468
};
@@ -545,7 +544,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
545544
let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty);
546545
let can_coerce = self.can_coerce(arg_ty, coerced_ty);
547546
if !can_coerce {
548-
return Compatibility::Incompatible(None);
547+
return Compatibility::Incompatible(Some(ty::error::TypeError::Sorts(
548+
ty::error::ExpectedFound::new(true, coerced_ty, arg_ty),
549+
)));
549550
}
550551

551552
// Using probe here, since we don't want this subtyping to affect inference.
@@ -659,7 +660,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
659660
Applicability::MachineApplicable,
660661
);
661662
};
662-
self.label_fn_like(&mut err, fn_def_id, callee_ty);
663+
self.label_fn_like(&mut err, fn_def_id, callee_ty, Some(mismatch_idx), is_method);
663664
err.emit();
664665
return;
665666
}
@@ -701,16 +702,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
701702
}
702703

703704
errors.drain_filter(|error| {
704-
let Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(error)) = error else { return false };
705+
let Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(e))) = error else { return false };
705706
let (provided_ty, provided_span) = provided_arg_tys[*provided_idx];
706707
let (expected_ty, _) = formal_and_expected_inputs[*expected_idx];
707708
let cause = &self.misc(provided_span);
708709
let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
709-
if let Some(e) = error {
710-
if !matches!(trace.cause.as_failure_code(e), FailureCode::Error0308(_)) {
711-
self.report_and_explain_type_error(trace, e).emit();
712-
return true;
713-
}
710+
if !matches!(trace.cause.as_failure_code(e), FailureCode::Error0308(_)) {
711+
self.report_and_explain_type_error(trace, e).emit();
712+
return true;
714713
}
715714
false
716715
});
@@ -749,7 +748,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
749748
format!("arguments to this {} are incorrect", call_name),
750749
);
751750
// Call out where the function is defined
752-
self.label_fn_like(&mut err, fn_def_id, callee_ty);
751+
self.label_fn_like(
752+
&mut err,
753+
fn_def_id,
754+
callee_ty,
755+
Some(expected_idx.as_usize()),
756+
is_method,
757+
);
753758
err.emit();
754759
return;
755760
}
@@ -1031,7 +1036,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10311036
}
10321037

10331038
// Call out where the function is defined
1034-
self.label_fn_like(&mut err, fn_def_id, callee_ty);
1039+
self.label_fn_like(&mut err, fn_def_id, callee_ty, None, is_method);
10351040

10361041
// And add a suggestion block for all of the parameters
10371042
let suggestion_text = match suggestion_text {
@@ -1781,6 +1786,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17811786
err: &mut Diagnostic,
17821787
callable_def_id: Option<DefId>,
17831788
callee_ty: Option<Ty<'tcx>>,
1789+
// A specific argument should be labeled, instead of all of them
1790+
expected_idx: Option<usize>,
1791+
is_method: bool,
17841792
) {
17851793
let Some(mut def_id) = callable_def_id else {
17861794
return;
@@ -1881,14 +1889,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
18811889
.get_if_local(def_id)
18821890
.and_then(|node| node.body_id())
18831891
.into_iter()
1884-
.flat_map(|id| self.tcx.hir().body(id).params);
1892+
.flat_map(|id| self.tcx.hir().body(id).params)
1893+
.skip(if is_method { 1 } else { 0 });
18851894

1886-
for param in params {
1895+
for (_, param) in params
1896+
.into_iter()
1897+
.enumerate()
1898+
.filter(|(idx, _)| expected_idx.map_or(true, |expected_idx| expected_idx == *idx))
1899+
{
18871900
spans.push_span_label(param.span, "");
18881901
}
18891902

18901903
let def_kind = self.tcx.def_kind(def_id);
18911904
err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id)));
1905+
} else if let Some(hir::Node::Expr(e)) = self.tcx.hir().get_if_local(def_id)
1906+
&& let hir::ExprKind::Closure(hir::Closure { body, .. }) = &e.kind
1907+
{
1908+
let param = expected_idx
1909+
.and_then(|expected_idx| self.tcx.hir().body(*body).params.get(expected_idx));
1910+
let (kind, span) = if let Some(param) = param {
1911+
("closure parameter", param.span)
1912+
} else {
1913+
("closure", self.tcx.def_span(def_id))
1914+
};
1915+
err.span_note(span, &format!("{} defined here", kind));
18921916
} else {
18931917
let def_kind = self.tcx.def_kind(def_id);
18941918
err.span_note(

src/bootstrap/mk/Makefile.in

+1-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ TESTS_IN_MINGW_2 := \
8080
src/test/ui
8181

8282
ci-mingw-subset-1:
83-
$(Q)$(CFG_SRC_DIR)/x.sh test --stage 2 $(TESTS_IN_MINGW_2:%=--exclude %)
83+
$(Q)$(CFG_SRC_DIR)/x test --stage 2 $(TESTS_IN_MINGW_2:%=--exclude %)
8484
ci-mingw-subset-2:
8585
$(Q)$(BOOTSTRAP) test --stage 2 $(TESTS_IN_MINGW_2)
8686

src/ci/docker/host-x86_64/x86_64-gnu-llvm-12/Dockerfile

+2-2
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,15 @@ ENV RUST_CONFIGURE_ARGS \
4444
--enable-llvm-link-shared \
4545
--set rust.thin-lto-import-instr-limit=10
4646

47-
# NOTE: intentionally uses all of `x.py`, `x.sh`, and `x.ps1` to make sure they all work on Linux.
47+
# NOTE: intentionally uses all of `x.py`, `x`, and `x.ps1` to make sure they all work on Linux.
4848
ENV SCRIPT ../x.py --stage 2 test --exclude src/tools/tidy && \
4949
# Run the `mir-opt` tests again but this time for a 32-bit target.
5050
# This enforces that tests using `// EMIT_MIR_FOR_EACH_BIT_WIDTH` have
5151
# both 32-bit and 64-bit outputs updated by the PR author, before
5252
# the PR is approved and tested for merging.
5353
# It will also detect tests lacking `// EMIT_MIR_FOR_EACH_BIT_WIDTH`,
5454
# despite having different output on 32-bit vs 64-bit targets.
55-
../x.sh --stage 2 test src/test/mir-opt \
55+
../x --stage 2 test src/test/mir-opt \
5656
--host='' --target=i686-unknown-linux-gnu && \
5757
# Run the UI test suite again, but in `--pass=check` mode
5858
#

0 commit comments

Comments
 (0)