Skip to content

Commit

Permalink
Rollup merge of rust-lang#123704 - estebank:diag-changes, r=compiler-…
Browse files Browse the repository at this point in the history
…errors

Tweak value suggestions in `borrowck` and `hir_analysis`

Unify the output of `suggest_assign_value` and `ty_kind_suggestion`.

Ideally we'd make these a single function, but doing so would likely require modify the crate dependency tree.
  • Loading branch information
matthiaskrgr authored Apr 11, 2024
2 parents ecf5515 + 1eda056 commit cd623c0
Show file tree
Hide file tree
Showing 57 changed files with 389 additions and 194 deletions.
96 changes: 70 additions & 26 deletions compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,68 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
err
}

fn ty_kind_suggestion(&self, ty: Ty<'tcx>) -> Option<String> {
// Keep in sync with `rustc_hir_analysis/src/check/mod.rs:ty_kind_suggestion`.
// FIXME: deduplicate the above.
let tcx = self.infcx.tcx;
let implements_default = |ty| {
let Some(default_trait) = tcx.get_diagnostic_item(sym::Default) else {
return false;
};
self.infcx
.type_implements_trait(default_trait, [ty], self.param_env)
.must_apply_modulo_regions()
};

Some(match ty.kind() {
ty::Never | ty::Error(_) => return None,
ty::Bool => "false".to_string(),
ty::Char => "\'x\'".to_string(),
ty::Int(_) | ty::Uint(_) => "42".into(),
ty::Float(_) => "3.14159".into(),
ty::Slice(_) => "[]".to_string(),
ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Vec) => {
"vec![]".to_string()
}
ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::String) => {
"String::new()".to_string()
}
ty::Adt(def, args) if def.is_box() => {
format!("Box::new({})", self.ty_kind_suggestion(args[0].expect_ty())?)
}
ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Option) => {
"None".to_string()
}
ty::Adt(def, args) if Some(def.did()) == tcx.get_diagnostic_item(sym::Result) => {
format!("Ok({})", self.ty_kind_suggestion(args[0].expect_ty())?)
}
ty::Adt(_, _) if implements_default(ty) => "Default::default()".to_string(),
ty::Ref(_, ty, mutability) => {
if let (ty::Str, hir::Mutability::Not) = (ty.kind(), mutability) {
"\"\"".to_string()
} else {
let Some(ty) = self.ty_kind_suggestion(*ty) else {
return None;
};
format!("&{}{ty}", mutability.prefix_str())
}
}
ty::Array(ty, len) => format!(
"[{}; {}]",
self.ty_kind_suggestion(*ty)?,
len.eval_target_usize(tcx, ty::ParamEnv::reveal_all()),
),
ty::Tuple(tys) => format!(
"({})",
tys.iter()
.map(|ty| self.ty_kind_suggestion(ty))
.collect::<Option<Vec<String>>>()?
.join(", ")
),
_ => "value".to_string(),
})
}

fn suggest_assign_value(
&self,
err: &mut Diag<'_>,
Expand All @@ -661,34 +723,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let ty = moved_place.ty(self.body, self.infcx.tcx).ty;
debug!("ty: {:?}, kind: {:?}", ty, ty.kind());

let tcx = self.infcx.tcx;
let implements_default = |ty, param_env| {
let Some(default_trait) = tcx.get_diagnostic_item(sym::Default) else {
return false;
};
self.infcx
.type_implements_trait(default_trait, [ty], param_env)
.must_apply_modulo_regions()
};

let assign_value = match ty.kind() {
ty::Bool => "false",
ty::Float(_) => "0.0",
ty::Int(_) | ty::Uint(_) => "0",
ty::Never | ty::Error(_) => "",
ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Vec) => "vec![]",
ty::Adt(_, _) if implements_default(ty, self.param_env) => "Default::default()",
_ => "todo!()",
let Some(assign_value) = self.ty_kind_suggestion(ty) else {
return;
};

if !assign_value.is_empty() {
err.span_suggestion_verbose(
sugg_span.shrink_to_hi(),
"consider assigning a value",
format!(" = {assign_value}"),
Applicability::MaybeIncorrect,
);
}
err.span_suggestion_verbose(
sugg_span.shrink_to_hi(),
"consider assigning a value",
format!(" = {assign_value}"),
Applicability::MaybeIncorrect,
);
}

fn suggest_borrow_fn_like(
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ use rustc_middle::ty::{
AdtDef, ParamEnv, RegionKind, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
};
use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS};
use rustc_span::symbol::sym;
use rustc_target::abi::FieldIdx;
use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedDirective;
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
Expand Down
72 changes: 62 additions & 10 deletions compiler/rustc_hir_analysis/src/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ use rustc_errors::ErrorGuaranteed;
use rustc_errors::{pluralize, struct_span_code_err, Diag};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::Visitor;
use rustc_hir::Mutability;
use rustc_index::bit_set::BitSet;
use rustc_infer::infer::error_reporting::ObligationCauseExt as _;
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
Expand All @@ -91,10 +92,11 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{GenericArgs, GenericArgsRef};
use rustc_session::parse::feature_err;
use rustc_span::symbol::{kw, Ident};
use rustc_span::{self, def_id::CRATE_DEF_ID, BytePos, Span, Symbol, DUMMY_SP};
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::{def_id::CRATE_DEF_ID, BytePos, Span, Symbol, DUMMY_SP};
use rustc_target::abi::VariantIdx;
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::error_reporting::suggestions::ReturnsVisitor;
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
use rustc_trait_selection::traits::ObligationCtxt;
Expand Down Expand Up @@ -466,14 +468,64 @@ fn fn_sig_suggestion<'tcx>(
)
}

pub fn ty_kind_suggestion(ty: Ty<'_>) -> Option<&'static str> {
pub fn ty_kind_suggestion<'tcx>(ty: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> Option<String> {
// Keep in sync with `rustc_borrowck/src/diagnostics/conflict_errors.rs:ty_kind_suggestion`.
// FIXME: deduplicate the above.
let implements_default = |ty| {
let Some(default_trait) = tcx.get_diagnostic_item(sym::Default) else {
return false;
};
let infcx = tcx.infer_ctxt().build();
infcx
.type_implements_trait(default_trait, [ty], ty::ParamEnv::reveal_all())
.must_apply_modulo_regions()
};
Some(match ty.kind() {
ty::Bool => "true",
ty::Char => "'a'",
ty::Int(_) | ty::Uint(_) => "42",
ty::Float(_) => "3.14159",
ty::Error(_) | ty::Never => return None,
_ => "value",
ty::Never | ty::Error(_) => return None,
ty::Bool => "false".to_string(),
ty::Char => "\'x\'".to_string(),
ty::Int(_) | ty::Uint(_) => "42".into(),
ty::Float(_) => "3.14159".into(),
ty::Slice(_) => "[]".to_string(),
ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Vec) => {
"vec![]".to_string()
}
ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::String) => {
"String::new()".to_string()
}
ty::Adt(def, args) if def.is_box() => {
format!("Box::new({})", ty_kind_suggestion(args[0].expect_ty(), tcx)?)
}
ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Option) => {
"None".to_string()
}
ty::Adt(def, args) if Some(def.did()) == tcx.get_diagnostic_item(sym::Result) => {
format!("Ok({})", ty_kind_suggestion(args[0].expect_ty(), tcx)?)
}
ty::Adt(_, _) if implements_default(ty) => "Default::default()".to_string(),
ty::Ref(_, ty, mutability) => {
if let (ty::Str, Mutability::Not) = (ty.kind(), mutability) {
"\"\"".to_string()
} else {
let Some(ty) = ty_kind_suggestion(*ty, tcx) else {
return None;
};
format!("&{}{ty}", mutability.prefix_str())
}
}
ty::Array(ty, len) => format!(
"[{}; {}]",
ty_kind_suggestion(*ty, tcx)?,
len.eval_target_usize(tcx, ty::ParamEnv::reveal_all()),
),
ty::Tuple(tys) => format!(
"({})",
tys.iter()
.map(|ty| ty_kind_suggestion(ty, tcx))
.collect::<Option<Vec<String>>>()?
.join(", ")
),
_ => "value".to_string(),
})
}

Expand Down Expand Up @@ -511,7 +563,7 @@ fn suggestion_signature<'tcx>(
}
ty::AssocKind::Const => {
let ty = tcx.type_of(assoc.def_id).instantiate_identity();
let val = ty_kind_suggestion(ty).unwrap_or("todo!()");
let val = ty_kind_suggestion(ty, tcx).unwrap_or_else(|| "value".to_string());
format!("const {}: {} = {};", assoc.name, ty, val)
}
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -694,10 +694,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
let error = Some(Sorts(ExpectedFound { expected: ty, found: e_ty }));
self.annotate_loop_expected_due_to_inference(err, expr, error);
if let Some(val) = ty_kind_suggestion(ty) {
if let Some(val) = ty_kind_suggestion(ty, tcx) {
err.span_suggestion_verbose(
expr.span.shrink_to_hi(),
"give it a value of the expected type",
"give the `break` a value of the expected type",
format!(" {val}"),
Applicability::HasPlaceholders,
);
Expand Down
8 changes: 4 additions & 4 deletions tests/ui/asm/aarch64/type-check-2-2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ LL | asm!("{}", in(reg) x);
|
help: consider assigning a value
|
LL | let x: u64 = 0;
| +++
LL | let x: u64 = 42;
| ++++

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

error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
--> $DIR/type-check-2-2.rs:28:13
Expand Down
8 changes: 4 additions & 4 deletions tests/ui/asm/x86_64/type-check-5.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ LL | asm!("{}", in(reg) x);
|
help: consider assigning a value
|
LL | let x: u64 = 0;
| +++
LL | let x: u64 = 42;
| ++++

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

error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
--> $DIR/type-check-5.rs:24:13
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/binop/issue-77910-1.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ LL | xs
|
help: consider assigning a value
|
LL | let xs = todo!();
| +++++++++
LL | let xs = &42;
| +++++

error: aborting due to 3 previous errors

Expand Down
4 changes: 2 additions & 2 deletions tests/ui/binop/issue-77910-2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ LL | xs
|
help: consider assigning a value
|
LL | let xs = todo!();
| +++++++++
LL | let xs = &42;
| +++++

error: aborting due to 2 previous errors

Expand Down
4 changes: 2 additions & 2 deletions tests/ui/borrowck/borrowck-block-uninit.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ LL | println!("{}", x);
|
help: consider assigning a value
|
LL | let x: isize = 0;
| +++
LL | let x: isize = 42;
| ++++

error: aborting due to 1 previous error

Expand Down
4 changes: 2 additions & 2 deletions tests/ui/borrowck/borrowck-break-uninit-2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ LL | println!("{}", x);
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider assigning a value
|
LL | let x: isize = 0;
| +++
LL | let x: isize = 42;
| ++++

error: aborting due to 1 previous error

Expand Down
4 changes: 2 additions & 2 deletions tests/ui/borrowck/borrowck-break-uninit.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ LL | println!("{}", x);
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider assigning a value
|
LL | let x: isize = 0;
| +++
LL | let x: isize = 42;
| ++++

error: aborting due to 1 previous error

Expand Down
4 changes: 2 additions & 2 deletions tests/ui/borrowck/borrowck-init-in-called-fn-expr.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ LL | i
|
help: consider assigning a value
|
LL | let i: isize = 0;
| +++
LL | let i: isize = 42;
| ++++

error: aborting due to 1 previous error

Expand Down
4 changes: 2 additions & 2 deletions tests/ui/borrowck/borrowck-init-in-fn-expr.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ LL | i
|
help: consider assigning a value
|
LL | let i: isize = 0;
| +++
LL | let i: isize = 42;
| ++++

error: aborting due to 1 previous error

Expand Down
4 changes: 2 additions & 2 deletions tests/ui/borrowck/borrowck-init-in-fru.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ LL | origin = Point { x: 10, ..origin };
|
help: consider assigning a value
|
LL | let mut origin: Point = todo!();
| +++++++++
LL | let mut origin: Point = value;
| +++++++

error: aborting due to 1 previous error

Expand Down
4 changes: 2 additions & 2 deletions tests/ui/borrowck/borrowck-init-op-equal.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ LL | v += 1;
|
help: consider assigning a value
|
LL | let v: isize = 0;
| +++
LL | let v: isize = 42;
| ++++

error: aborting due to 1 previous error

Expand Down
4 changes: 2 additions & 2 deletions tests/ui/borrowck/borrowck-init-plus-equal.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ LL | v = v + 1;
|
help: consider assigning a value
|
LL | let mut v: isize = 0;
| +++
LL | let mut v: isize = 42;
| ++++

error: aborting due to 1 previous error

Expand Down
Loading

0 comments on commit cd623c0

Please sign in to comment.