Skip to content

Commit 241fc13

Browse files
committed
Auto merge of rust-lang#123776 - matthiaskrgr:rollup-x8wzvdf, r=matthiaskrgr
Rollup of 2 pull requests Successful merges: - rust-lang#123704 (Tweak value suggestions in `borrowck` and `hir_analysis`) - rust-lang#123753 (compiletest: error when finding a trailing directive) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 05ccc49 + a6448d3 commit 241fc13

File tree

59 files changed

+441
-199
lines changed

Some content is hidden

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

59 files changed

+441
-199
lines changed

Diff for: compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

+70-26
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,68 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
652652
err
653653
}
654654

655+
fn ty_kind_suggestion(&self, ty: Ty<'tcx>) -> Option<String> {
656+
// Keep in sync with `rustc_hir_analysis/src/check/mod.rs:ty_kind_suggestion`.
657+
// FIXME: deduplicate the above.
658+
let tcx = self.infcx.tcx;
659+
let implements_default = |ty| {
660+
let Some(default_trait) = tcx.get_diagnostic_item(sym::Default) else {
661+
return false;
662+
};
663+
self.infcx
664+
.type_implements_trait(default_trait, [ty], self.param_env)
665+
.must_apply_modulo_regions()
666+
};
667+
668+
Some(match ty.kind() {
669+
ty::Never | ty::Error(_) => return None,
670+
ty::Bool => "false".to_string(),
671+
ty::Char => "\'x\'".to_string(),
672+
ty::Int(_) | ty::Uint(_) => "42".into(),
673+
ty::Float(_) => "3.14159".into(),
674+
ty::Slice(_) => "[]".to_string(),
675+
ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Vec) => {
676+
"vec![]".to_string()
677+
}
678+
ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::String) => {
679+
"String::new()".to_string()
680+
}
681+
ty::Adt(def, args) if def.is_box() => {
682+
format!("Box::new({})", self.ty_kind_suggestion(args[0].expect_ty())?)
683+
}
684+
ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Option) => {
685+
"None".to_string()
686+
}
687+
ty::Adt(def, args) if Some(def.did()) == tcx.get_diagnostic_item(sym::Result) => {
688+
format!("Ok({})", self.ty_kind_suggestion(args[0].expect_ty())?)
689+
}
690+
ty::Adt(_, _) if implements_default(ty) => "Default::default()".to_string(),
691+
ty::Ref(_, ty, mutability) => {
692+
if let (ty::Str, hir::Mutability::Not) = (ty.kind(), mutability) {
693+
"\"\"".to_string()
694+
} else {
695+
let Some(ty) = self.ty_kind_suggestion(*ty) else {
696+
return None;
697+
};
698+
format!("&{}{ty}", mutability.prefix_str())
699+
}
700+
}
701+
ty::Array(ty, len) => format!(
702+
"[{}; {}]",
703+
self.ty_kind_suggestion(*ty)?,
704+
len.eval_target_usize(tcx, ty::ParamEnv::reveal_all()),
705+
),
706+
ty::Tuple(tys) => format!(
707+
"({})",
708+
tys.iter()
709+
.map(|ty| self.ty_kind_suggestion(ty))
710+
.collect::<Option<Vec<String>>>()?
711+
.join(", ")
712+
),
713+
_ => "value".to_string(),
714+
})
715+
}
716+
655717
fn suggest_assign_value(
656718
&self,
657719
err: &mut Diag<'_>,
@@ -661,34 +723,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
661723
let ty = moved_place.ty(self.body, self.infcx.tcx).ty;
662724
debug!("ty: {:?}, kind: {:?}", ty, ty.kind());
663725

664-
let tcx = self.infcx.tcx;
665-
let implements_default = |ty, param_env| {
666-
let Some(default_trait) = tcx.get_diagnostic_item(sym::Default) else {
667-
return false;
668-
};
669-
self.infcx
670-
.type_implements_trait(default_trait, [ty], param_env)
671-
.must_apply_modulo_regions()
672-
};
673-
674-
let assign_value = match ty.kind() {
675-
ty::Bool => "false",
676-
ty::Float(_) => "0.0",
677-
ty::Int(_) | ty::Uint(_) => "0",
678-
ty::Never | ty::Error(_) => "",
679-
ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Vec) => "vec![]",
680-
ty::Adt(_, _) if implements_default(ty, self.param_env) => "Default::default()",
681-
_ => "todo!()",
726+
let Some(assign_value) = self.ty_kind_suggestion(ty) else {
727+
return;
682728
};
683729

684-
if !assign_value.is_empty() {
685-
err.span_suggestion_verbose(
686-
sugg_span.shrink_to_hi(),
687-
"consider assigning a value",
688-
format!(" = {assign_value}"),
689-
Applicability::MaybeIncorrect,
690-
);
691-
}
730+
err.span_suggestion_verbose(
731+
sugg_span.shrink_to_hi(),
732+
"consider assigning a value",
733+
format!(" = {assign_value}"),
734+
Applicability::MaybeIncorrect,
735+
);
692736
}
693737

694738
fn suggest_borrow_fn_like(

Diff for: compiler/rustc_hir_analysis/src/check/check.rs

-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ use rustc_middle::ty::{
2222
AdtDef, ParamEnv, RegionKind, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
2323
};
2424
use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS};
25-
use rustc_span::symbol::sym;
2625
use rustc_target::abi::FieldIdx;
2726
use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedDirective;
2827
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;

Diff for: compiler/rustc_hir_analysis/src/check/mod.rs

+62-10
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ use rustc_errors::ErrorGuaranteed;
8181
use rustc_errors::{pluralize, struct_span_code_err, Diag};
8282
use rustc_hir::def_id::{DefId, LocalDefId};
8383
use rustc_hir::intravisit::Visitor;
84+
use rustc_hir::Mutability;
8485
use rustc_index::bit_set::BitSet;
8586
use rustc_infer::infer::error_reporting::ObligationCauseExt as _;
8687
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
@@ -91,10 +92,11 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError};
9192
use rustc_middle::ty::{self, Ty, TyCtxt};
9293
use rustc_middle::ty::{GenericArgs, GenericArgsRef};
9394
use rustc_session::parse::feature_err;
94-
use rustc_span::symbol::{kw, Ident};
95-
use rustc_span::{self, def_id::CRATE_DEF_ID, BytePos, Span, Symbol, DUMMY_SP};
95+
use rustc_span::symbol::{kw, sym, Ident};
96+
use rustc_span::{def_id::CRATE_DEF_ID, BytePos, Span, Symbol, DUMMY_SP};
9697
use rustc_target::abi::VariantIdx;
9798
use rustc_target::spec::abi::Abi;
99+
use rustc_trait_selection::infer::InferCtxtExt;
98100
use rustc_trait_selection::traits::error_reporting::suggestions::ReturnsVisitor;
99101
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
100102
use rustc_trait_selection::traits::ObligationCtxt;
@@ -466,14 +468,64 @@ fn fn_sig_suggestion<'tcx>(
466468
)
467469
}
468470

469-
pub fn ty_kind_suggestion(ty: Ty<'_>) -> Option<&'static str> {
471+
pub fn ty_kind_suggestion<'tcx>(ty: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> Option<String> {
472+
// Keep in sync with `rustc_borrowck/src/diagnostics/conflict_errors.rs:ty_kind_suggestion`.
473+
// FIXME: deduplicate the above.
474+
let implements_default = |ty| {
475+
let Some(default_trait) = tcx.get_diagnostic_item(sym::Default) else {
476+
return false;
477+
};
478+
let infcx = tcx.infer_ctxt().build();
479+
infcx
480+
.type_implements_trait(default_trait, [ty], ty::ParamEnv::reveal_all())
481+
.must_apply_modulo_regions()
482+
};
470483
Some(match ty.kind() {
471-
ty::Bool => "true",
472-
ty::Char => "'a'",
473-
ty::Int(_) | ty::Uint(_) => "42",
474-
ty::Float(_) => "3.14159",
475-
ty::Error(_) | ty::Never => return None,
476-
_ => "value",
484+
ty::Never | ty::Error(_) => return None,
485+
ty::Bool => "false".to_string(),
486+
ty::Char => "\'x\'".to_string(),
487+
ty::Int(_) | ty::Uint(_) => "42".into(),
488+
ty::Float(_) => "3.14159".into(),
489+
ty::Slice(_) => "[]".to_string(),
490+
ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Vec) => {
491+
"vec![]".to_string()
492+
}
493+
ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::String) => {
494+
"String::new()".to_string()
495+
}
496+
ty::Adt(def, args) if def.is_box() => {
497+
format!("Box::new({})", ty_kind_suggestion(args[0].expect_ty(), tcx)?)
498+
}
499+
ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Option) => {
500+
"None".to_string()
501+
}
502+
ty::Adt(def, args) if Some(def.did()) == tcx.get_diagnostic_item(sym::Result) => {
503+
format!("Ok({})", ty_kind_suggestion(args[0].expect_ty(), tcx)?)
504+
}
505+
ty::Adt(_, _) if implements_default(ty) => "Default::default()".to_string(),
506+
ty::Ref(_, ty, mutability) => {
507+
if let (ty::Str, Mutability::Not) = (ty.kind(), mutability) {
508+
"\"\"".to_string()
509+
} else {
510+
let Some(ty) = ty_kind_suggestion(*ty, tcx) else {
511+
return None;
512+
};
513+
format!("&{}{ty}", mutability.prefix_str())
514+
}
515+
}
516+
ty::Array(ty, len) => format!(
517+
"[{}; {}]",
518+
ty_kind_suggestion(*ty, tcx)?,
519+
len.eval_target_usize(tcx, ty::ParamEnv::reveal_all()),
520+
),
521+
ty::Tuple(tys) => format!(
522+
"({})",
523+
tys.iter()
524+
.map(|ty| ty_kind_suggestion(ty, tcx))
525+
.collect::<Option<Vec<String>>>()?
526+
.join(", ")
527+
),
528+
_ => "value".to_string(),
477529
})
478530
}
479531

@@ -511,7 +563,7 @@ fn suggestion_signature<'tcx>(
511563
}
512564
ty::AssocKind::Const => {
513565
let ty = tcx.type_of(assoc.def_id).instantiate_identity();
514-
let val = ty_kind_suggestion(ty).unwrap_or("todo!()");
566+
let val = ty_kind_suggestion(ty, tcx).unwrap_or_else(|| "value".to_string());
515567
format!("const {}: {} = {};", assoc.name, ty, val)
516568
}
517569
}

Diff for: compiler/rustc_hir_typeck/src/expr.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -694,10 +694,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
694694
);
695695
let error = Some(Sorts(ExpectedFound { expected: ty, found: e_ty }));
696696
self.annotate_loop_expected_due_to_inference(err, expr, error);
697-
if let Some(val) = ty_kind_suggestion(ty) {
697+
if let Some(val) = ty_kind_suggestion(ty, tcx) {
698698
err.span_suggestion_verbose(
699699
expr.span.shrink_to_hi(),
700-
"give it a value of the expected type",
700+
"give the `break` a value of the expected type",
701701
format!(" {val}"),
702702
Applicability::HasPlaceholders,
703703
);

Diff for: src/tools/compiletest/src/header.rs

+31-5
Original file line numberDiff line numberDiff line change
@@ -935,16 +935,25 @@ struct HeaderLine<'ln> {
935935
pub(crate) struct CheckDirectiveResult<'ln> {
936936
is_known_directive: bool,
937937
directive_name: &'ln str,
938+
trailing_directive: Option<&'ln str>,
938939
}
939940

940-
// Returns `(is_known_directive, directive_name)`.
941941
pub(crate) fn check_directive(directive_ln: &str) -> CheckDirectiveResult<'_> {
942-
let directive_name =
943-
directive_ln.split_once([':', ' ']).map(|(pre, _)| pre).unwrap_or(directive_ln);
942+
let (directive_name, post) = directive_ln.split_once([':', ' ']).unwrap_or((directive_ln, ""));
943+
944+
let trailing = post.trim().split_once(' ').map(|(pre, _)| pre).unwrap_or(post);
945+
let trailing_directive = {
946+
// 1. is the directive name followed by a space? (to exclude `:`)
947+
matches!(directive_ln.get(directive_name.len()..), Some(s) if s.starts_with(" "))
948+
// 2. is what is after that directive also a directive (ex: "only-x86 only-arm")
949+
&& KNOWN_DIRECTIVE_NAMES.contains(&trailing)
950+
}
951+
.then_some(trailing);
944952

945953
CheckDirectiveResult {
946954
is_known_directive: KNOWN_DIRECTIVE_NAMES.contains(&directive_name),
947955
directive_name: directive_ln,
956+
trailing_directive,
948957
}
949958
}
950959

@@ -1014,7 +1023,8 @@ fn iter_header(
10141023
if testfile.extension().map(|e| e == "rs").unwrap_or(false) {
10151024
let directive_ln = non_revisioned_directive_line.trim();
10161025

1017-
let CheckDirectiveResult { is_known_directive, .. } = check_directive(directive_ln);
1026+
let CheckDirectiveResult { is_known_directive, trailing_directive, .. } =
1027+
check_directive(directive_ln);
10181028

10191029
if !is_known_directive {
10201030
*poisoned = true;
@@ -1028,6 +1038,21 @@ fn iter_header(
10281038

10291039
return;
10301040
}
1041+
1042+
if let Some(trailing_directive) = &trailing_directive {
1043+
*poisoned = true;
1044+
1045+
eprintln!(
1046+
"error: detected trailing compiletest test directive `{}` in {}:{}\n \
1047+
help: put the trailing directive in it's own line: `//@ {}`",
1048+
trailing_directive,
1049+
testfile.display(),
1050+
line_number,
1051+
trailing_directive,
1052+
);
1053+
1054+
return;
1055+
}
10311056
}
10321057

10331058
it(HeaderLine {
@@ -1051,7 +1076,8 @@ fn iter_header(
10511076

10521077
let rest = rest.trim_start();
10531078

1054-
let CheckDirectiveResult { is_known_directive, directive_name } = check_directive(rest);
1079+
let CheckDirectiveResult { is_known_directive, directive_name, .. } =
1080+
check_directive(rest);
10551081

10561082
if is_known_directive {
10571083
*poisoned = true;

Diff for: src/tools/compiletest/src/header/tests.rs

+21
Original file line numberDiff line numberDiff line change
@@ -667,3 +667,24 @@ fn test_non_rs_unknown_directive_not_checked() {
667667
);
668668
assert!(!poisoned);
669669
}
670+
671+
#[test]
672+
fn test_trailing_directive() {
673+
let mut poisoned = false;
674+
run_path(&mut poisoned, Path::new("a.rs"), b"//@ only-x86 only-arm");
675+
assert!(poisoned);
676+
}
677+
678+
#[test]
679+
fn test_trailing_directive_with_comment() {
680+
let mut poisoned = false;
681+
run_path(&mut poisoned, Path::new("a.rs"), b"//@ only-x86 only-arm with comment");
682+
assert!(poisoned);
683+
}
684+
685+
#[test]
686+
fn test_not_trailing_directive() {
687+
let mut poisoned = false;
688+
run_path(&mut poisoned, Path::new("a.rs"), b"//@ revisions: incremental");
689+
assert!(!poisoned);
690+
}

Diff for: tests/ui/asm/aarch64/type-check-2-2.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ LL | asm!("{}", in(reg) x);
88
|
99
help: consider assigning a value
1010
|
11-
LL | let x: u64 = 0;
12-
| +++
11+
LL | let x: u64 = 42;
12+
| ++++
1313

1414
error[E0381]: used binding `y` isn't initialized
1515
--> $DIR/type-check-2-2.rs:22:9
@@ -21,8 +21,8 @@ LL | asm!("{}", inout(reg) y);
2121
|
2222
help: consider assigning a value
2323
|
24-
LL | let mut y: u64 = 0;
25-
| +++
24+
LL | let mut y: u64 = 42;
25+
| ++++
2626

2727
error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
2828
--> $DIR/type-check-2-2.rs:28:13

Diff for: tests/ui/asm/x86_64/type-check-5.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ LL | asm!("{}", in(reg) x);
88
|
99
help: consider assigning a value
1010
|
11-
LL | let x: u64 = 0;
12-
| +++
11+
LL | let x: u64 = 42;
12+
| ++++
1313

1414
error[E0381]: used binding `y` isn't initialized
1515
--> $DIR/type-check-5.rs:18:9
@@ -21,8 +21,8 @@ LL | asm!("{}", inout(reg) y);
2121
|
2222
help: consider assigning a value
2323
|
24-
LL | let mut y: u64 = 0;
25-
| +++
24+
LL | let mut y: u64 = 42;
25+
| ++++
2626

2727
error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
2828
--> $DIR/type-check-5.rs:24:13

Diff for: tests/ui/binop/issue-77910-1.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ LL | xs
3232
|
3333
help: consider assigning a value
3434
|
35-
LL | let xs = todo!();
36-
| +++++++++
35+
LL | let xs = &42;
36+
| +++++
3737

3838
error: aborting due to 3 previous errors
3939

Diff for: tests/ui/binop/issue-77910-2.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ LL | xs
2121
|
2222
help: consider assigning a value
2323
|
24-
LL | let xs = todo!();
25-
| +++++++++
24+
LL | let xs = &42;
25+
| +++++
2626

2727
error: aborting due to 2 previous errors
2828

0 commit comments

Comments
 (0)