Skip to content

Commit 95b61d1

Browse files
committed
Auto merge of #107290 - Dylan-DPC:rollup-tovojhr, r=Dylan-DPC
Rollup of 9 pull requests Successful merges: - #105552 (Add help message about function pointers) - #106583 (Suggest coercion of `Result` using `?`) - #106767 (Allow setting CFG_DISABLE_UNSTABLE_FEATURES to 0) - #106823 (Allow fmt::Arguments::as_str() to return more Some(_).) - #107166 (rustc_metadata: Support non-`Option` nullable values in metadata tables) - #107213 (Add suggestion to remove if in let..else block) - #107223 (`sub_ptr()` is equivalent to `usize::try_from().unwrap_unchecked()`, not `usize::from().unwrap_unchecked()`) - #107227 (`new_outside_solver` -> `evaluate_root_goal`) - #107232 (rustdoc: simplify settings popover DOM, CSS, JS) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 9467f95 + e78fa8a commit 95b61d1

Some content is hidden

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

42 files changed

+752
-284
lines changed

compiler/rustc_error_messages/locales/en-US/parse.ftl

+1
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ parse_const_let_mutually_exclusive = `const` and `let` are mutually exclusive
238238
239239
parse_invalid_expression_in_let_else = a `{$operator}` expression cannot be directly assigned in `let...else`
240240
parse_invalid_curly_in_let_else = right curly brace `{"}"}` before `else` in a `let...else` statement not allowed
241+
parse_extra_if_in_let_else = remove the `if` if you meant to write a `let...else` statement
241242
242243
parse_compound_assignment_expression_in_let = can't reassign to an uninitialized variable
243244
.suggestion = initialize the variable

compiler/rustc_feature/src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,8 @@ impl UnstableFeatures {
8383
/// Otherwise, only `RUSTC_BOOTSTRAP=1` will work.
8484
pub fn from_environment(krate: Option<&str>) -> Self {
8585
// `true` if this is a feature-staged build, i.e., on the beta or stable channel.
86-
let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
86+
let disable_unstable_features =
87+
option_env!("CFG_DISABLE_UNSTABLE_FEATURES").map(|s| s != "0").unwrap_or(false);
8788
// Returns whether `krate` should be counted as unstable
8889
let is_unstable_crate = |var: &str| {
8990
krate.map_or(false, |name| var.split(',').any(|new_krate| new_krate == name))

compiler/rustc_hir_typeck/src/coercion.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1613,12 +1613,14 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
16131613
if visitor.ret_exprs.len() > 0 && let Some(expr) = expression {
16141614
self.note_unreachable_loop_return(&mut err, &expr, &visitor.ret_exprs);
16151615
}
1616+
16161617
let reported = err.emit_unless(unsized_return);
16171618

16181619
self.final_ty = Some(fcx.tcx.ty_error_with_guaranteed(reported));
16191620
}
16201621
}
16211622
}
1623+
16221624
fn note_unreachable_loop_return(
16231625
&self,
16241626
err: &mut Diagnostic,

compiler/rustc_hir_typeck/src/demand.rs

+52-2
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
5959
|| self.suggest_copied_or_cloned(err, expr, expr_ty, expected)
6060
|| self.suggest_clone_for_ref(err, expr, expr_ty, expected)
6161
|| self.suggest_into(err, expr, expr_ty, expected)
62-
|| self.suggest_floating_point_literal(err, expr, expected);
62+
|| self.suggest_floating_point_literal(err, expr, expected)
63+
|| self.note_result_coercion(err, expr, expected, expr_ty);
6364
if !suggested {
6465
self.point_at_expr_source_of_inferred_type(err, expr, expr_ty, expected);
6566
}
@@ -81,7 +82,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
8182
self.annotate_expected_due_to_let_ty(err, expr, error);
8283
self.emit_type_mismatch_suggestions(err, expr, expr_ty, expected, expected_ty_expr, error);
8384
self.note_type_is_not_clone(err, expected, expr_ty, expr);
84-
self.note_need_for_fn_pointer(err, expected, expr_ty);
8585
self.note_internal_mutation_in_method(err, expr, expected, expr_ty);
8686
self.check_for_range_as_method_call(err, expr, expr_ty, expected);
8787
self.check_for_binding_assigned_block_without_tail_expression(err, expr, expr_ty, expected);
@@ -697,6 +697,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
697697
);
698698
}
699699

700+
pub(crate) fn note_result_coercion(
701+
&self,
702+
err: &mut Diagnostic,
703+
expr: &hir::Expr<'tcx>,
704+
expected: Ty<'tcx>,
705+
found: Ty<'tcx>,
706+
) -> bool {
707+
let ty::Adt(e, substs_e) = expected.kind() else { return false; };
708+
let ty::Adt(f, substs_f) = found.kind() else { return false; };
709+
if e.did() != f.did() {
710+
return false;
711+
}
712+
if Some(e.did()) != self.tcx.get_diagnostic_item(sym::Result) {
713+
return false;
714+
}
715+
let map = self.tcx.hir();
716+
if let Some(hir::Node::Expr(expr)) = map.find_parent(expr.hir_id)
717+
&& let hir::ExprKind::Ret(_) = expr.kind
718+
{
719+
// `return foo;`
720+
} else if map.get_return_block(expr.hir_id).is_some() {
721+
// Function's tail expression.
722+
} else {
723+
return false;
724+
}
725+
let e = substs_e.type_at(1);
726+
let f = substs_f.type_at(1);
727+
if self
728+
.infcx
729+
.type_implements_trait(
730+
self.tcx.get_diagnostic_item(sym::Into).unwrap(),
731+
[f, e],
732+
self.param_env,
733+
)
734+
.must_apply_modulo_regions()
735+
{
736+
err.multipart_suggestion(
737+
"use `?` to coerce and return an appropriate `Err`, and wrap the resulting value \
738+
in `Ok` so the expression remains of type `Result`",
739+
vec![
740+
(expr.span.shrink_to_lo(), "Ok(".to_string()),
741+
(expr.span.shrink_to_hi(), "?)".to_string()),
742+
],
743+
Applicability::MaybeIncorrect,
744+
);
745+
return true;
746+
}
747+
false
748+
}
749+
700750
/// If the expected type is an enum (Issue #55250) with any variants whose
701751
/// sole field is of the found type, suggest such variants. (Issue #42764)
702752
fn suggest_compatible_variants(

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

-37
Original file line numberDiff line numberDiff line change
@@ -926,43 +926,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
926926
}
927927
}
928928

929-
pub(in super::super) fn note_need_for_fn_pointer(
930-
&self,
931-
err: &mut Diagnostic,
932-
expected: Ty<'tcx>,
933-
found: Ty<'tcx>,
934-
) {
935-
let (sig, did, substs) = match (&expected.kind(), &found.kind()) {
936-
(ty::FnDef(did1, substs1), ty::FnDef(did2, substs2)) => {
937-
let sig1 = self.tcx.bound_fn_sig(*did1).subst(self.tcx, substs1);
938-
let sig2 = self.tcx.bound_fn_sig(*did2).subst(self.tcx, substs2);
939-
if sig1 != sig2 {
940-
return;
941-
}
942-
err.note(
943-
"different `fn` items always have unique types, even if their signatures are \
944-
the same",
945-
);
946-
(sig1, *did1, substs1)
947-
}
948-
(ty::FnDef(did, substs), ty::FnPtr(sig2)) => {
949-
let sig1 = self.tcx.bound_fn_sig(*did).subst(self.tcx, substs);
950-
if sig1 != *sig2 {
951-
return;
952-
}
953-
(sig1, *did, substs)
954-
}
955-
_ => return,
956-
};
957-
err.help(&format!("change the expected type to be function pointer `{}`", sig));
958-
err.help(&format!(
959-
"if the expected type is due to type inference, cast the expected `fn` to a function \
960-
pointer: `{} as {}`",
961-
self.tcx.def_path_str_with_substs(did, substs),
962-
sig
963-
));
964-
}
965-
966929
// Instantiates the given path, which must refer to an item with the given
967930
// number of type parameters and type.
968931
#[instrument(skip(self, span), level = "debug")]

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -1841,6 +1841,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
18411841
self.suggest_as_ref_where_appropriate(span, &exp_found, diag);
18421842
self.suggest_accessing_field_where_appropriate(cause, &exp_found, diag);
18431843
self.suggest_await_on_expect_found(cause, span, &exp_found, diag);
1844+
self.suggest_function_pointers(cause, span, &exp_found, diag);
18441845
}
18451846
}
18461847

@@ -2585,7 +2586,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
25852586
/// with the other type. A TyVar inference type is compatible with any type, and an IntVar or
25862587
/// FloatVar inference type are compatible with themselves or their concrete types (Int and
25872588
/// Float types, respectively). When comparing two ADTs, these rules apply recursively.
2588-
pub fn same_type_modulo_infer(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
2589+
pub fn same_type_modulo_infer<T: relate::Relate<'tcx>>(&self, a: T, b: T) -> bool {
25892590
let (a, b) = self.resolve_vars_if_possible((a, b));
25902591
SameTypeModuloInfer(self).relate(a, b).is_ok()
25912592
}

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

+77-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_middle::traits::{
88
StatementAsExpression,
99
};
1010
use rustc_middle::ty::print::with_no_trimmed_paths;
11-
use rustc_middle::ty::{self as ty, Ty, TypeVisitable};
11+
use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TypeVisitable};
1212
use rustc_span::{sym, BytePos, Span};
1313

1414
use crate::errors::SuggAddLetForLetChains;
@@ -351,6 +351,82 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
351351
}
352352
}
353353

354+
pub(super) fn suggest_function_pointers(
355+
&self,
356+
cause: &ObligationCause<'tcx>,
357+
span: Span,
358+
exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
359+
diag: &mut Diagnostic,
360+
) {
361+
debug!("suggest_function_pointers(cause={:?}, exp_found={:?})", cause, exp_found);
362+
let ty::error::ExpectedFound { expected, found } = exp_found;
363+
let expected_inner = expected.peel_refs();
364+
let found_inner = found.peel_refs();
365+
if !expected_inner.is_fn() || !found_inner.is_fn() {
366+
return;
367+
}
368+
match (&expected_inner.kind(), &found_inner.kind()) {
369+
(ty::FnPtr(sig), ty::FnDef(did, substs)) => {
370+
let expected_sig = &(self.normalize_fn_sig)(*sig);
371+
let found_sig =
372+
&(self.normalize_fn_sig)(self.tcx.bound_fn_sig(*did).subst(self.tcx, substs));
373+
374+
let fn_name = self.tcx.def_path_str_with_substs(*did, substs);
375+
376+
if !self.same_type_modulo_infer(*found_sig, *expected_sig)
377+
|| !sig.is_suggestable(self.tcx, true)
378+
|| ty::util::is_intrinsic(self.tcx, *did)
379+
{
380+
return;
381+
}
382+
383+
let (msg, sugg) = match (expected.is_ref(), found.is_ref()) {
384+
(true, false) => {
385+
let msg = "consider using a reference";
386+
let sug = format!("&{fn_name}");
387+
(msg, sug)
388+
}
389+
(false, true) => {
390+
let msg = "consider removing the reference";
391+
let sug = format!("{fn_name}");
392+
(msg, sug)
393+
}
394+
(true, true) => {
395+
diag.note("fn items are distinct from fn pointers");
396+
let msg = "consider casting to a fn pointer";
397+
let sug = format!("&({fn_name} as {sig})");
398+
(msg, sug)
399+
}
400+
(false, false) => {
401+
diag.note("fn items are distinct from fn pointers");
402+
let msg = "consider casting to a fn pointer";
403+
let sug = format!("{fn_name} as {sig}");
404+
(msg, sug)
405+
}
406+
};
407+
diag.span_suggestion(span, msg, &sugg, Applicability::MaybeIncorrect);
408+
}
409+
(ty::FnDef(did1, substs1), ty::FnDef(did2, substs2)) => {
410+
let expected_sig =
411+
&(self.normalize_fn_sig)(self.tcx.bound_fn_sig(*did1).subst(self.tcx, substs1));
412+
let found_sig =
413+
&(self.normalize_fn_sig)(self.tcx.bound_fn_sig(*did2).subst(self.tcx, substs2));
414+
415+
if self.same_type_modulo_infer(*found_sig, *expected_sig) {
416+
diag.note(
417+
"different fn items have unique types, even if their signatures are the same",
418+
);
419+
}
420+
}
421+
(ty::FnDef(_, _), ty::FnPtr(_)) => {
422+
diag.note("fn items are distinct from fn pointers");
423+
}
424+
_ => {
425+
return;
426+
}
427+
};
428+
}
429+
354430
pub fn should_suggest_as_ref(&self, expected: Ty<'tcx>, found: Ty<'tcx>) -> Option<&str> {
355431
if let (ty::Adt(exp_def, exp_substs), ty::Ref(_, found_ty, _)) =
356432
(expected.kind(), found.kind())

compiler/rustc_metadata/src/rmeta/decoder.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -985,7 +985,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
985985
let vis = self.get_visibility(id);
986986
let span = self.get_span(id, sess);
987987
let macro_rules = match kind {
988-
DefKind::Macro(..) => self.root.tables.macro_rules.get(self, id).is_some(),
988+
DefKind::Macro(..) => self.root.tables.is_macro_rules.get(self, id),
989989
_ => false,
990990
};
991991

@@ -1283,7 +1283,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
12831283
fn get_macro(self, id: DefIndex, sess: &Session) -> ast::MacroDef {
12841284
match self.def_kind(id) {
12851285
DefKind::Macro(_) => {
1286-
let macro_rules = self.root.tables.macro_rules.get(self, id).is_some();
1286+
let macro_rules = self.root.tables.is_macro_rules.get(self, id);
12871287
let body =
12881288
self.root.tables.macro_definition.get(self, id).unwrap().decode((self, sess));
12891289
ast::MacroDef { macro_rules, body: ast::ptr::P(body) }
@@ -1595,11 +1595,11 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
15951595
}
15961596

15971597
fn get_attr_flags(self, index: DefIndex) -> AttrFlags {
1598-
self.root.tables.attr_flags.get(self, index).unwrap_or(AttrFlags::empty())
1598+
self.root.tables.attr_flags.get(self, index)
15991599
}
16001600

16011601
fn get_is_intrinsic(self, index: DefIndex) -> bool {
1602-
self.root.tables.is_intrinsic.get(self, index).is_some()
1602+
self.root.tables.is_intrinsic.get(self, index)
16031603
}
16041604
}
16051605

compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -226,12 +226,7 @@ provide! { tcx, def_id, other, cdata,
226226
deduced_param_attrs => { table }
227227
is_type_alias_impl_trait => {
228228
debug_assert_eq!(tcx.def_kind(def_id), DefKind::OpaqueTy);
229-
cdata
230-
.root
231-
.tables
232-
.is_type_alias_impl_trait
233-
.get(cdata, def_id.index)
234-
.is_some()
229+
cdata.root.tables.is_type_alias_impl_trait.get(cdata, def_id.index)
235230
}
236231
collect_return_position_impl_trait_in_trait_tys => {
237232
Ok(cdata

compiler/rustc_metadata/src/rmeta/encoder.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
483483
self.lazy(DefPathHashMapRef::BorrowedFromTcx(self.tcx.def_path_hash_to_def_index_map()))
484484
}
485485

486-
fn encode_source_map(&mut self) -> LazyTable<u32, LazyValue<rustc_span::SourceFile>> {
486+
fn encode_source_map(&mut self) -> LazyTable<u32, Option<LazyValue<rustc_span::SourceFile>>> {
487487
let source_map = self.tcx.sess.source_map();
488488
let all_source_files = source_map.files();
489489

@@ -1130,7 +1130,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
11301130
attr_flags |= AttrFlags::IS_DOC_HIDDEN;
11311131
}
11321132
if !attr_flags.is_empty() {
1133-
self.tables.attr_flags.set(def_id.local_def_index, attr_flags);
1133+
self.tables.attr_flags.set_nullable(def_id.local_def_index, attr_flags);
11341134
}
11351135
}
11361136

@@ -1387,7 +1387,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
13871387
if impl_item.kind == ty::AssocKind::Fn {
13881388
record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
13891389
if tcx.is_intrinsic(def_id) {
1390-
self.tables.is_intrinsic.set(def_id.index, ());
1390+
self.tables.is_intrinsic.set_nullable(def_id.index, true);
13911391
}
13921392
}
13931393
}
@@ -1519,7 +1519,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
15191519
}
15201520
hir::ItemKind::Macro(ref macro_def, _) => {
15211521
if macro_def.macro_rules {
1522-
self.tables.macro_rules.set(def_id.index, ());
1522+
self.tables.is_macro_rules.set_nullable(def_id.index, true);
15231523
}
15241524
record!(self.tables.macro_definition[def_id] <- &*macro_def.body);
15251525
}
@@ -1529,7 +1529,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
15291529
hir::ItemKind::OpaqueTy(ref opaque) => {
15301530
self.encode_explicit_item_bounds(def_id);
15311531
if matches!(opaque.origin, hir::OpaqueTyOrigin::TyAlias) {
1532-
self.tables.is_type_alias_impl_trait.set(def_id.index, ());
1532+
self.tables.is_type_alias_impl_trait.set_nullable(def_id.index, true);
15331533
}
15341534
}
15351535
hir::ItemKind::Enum(..) => {
@@ -1636,7 +1636,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
16361636
if let hir::ItemKind::Fn(..) = item.kind {
16371637
record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
16381638
if tcx.is_intrinsic(def_id) {
1639-
self.tables.is_intrinsic.set(def_id.index, ());
1639+
self.tables.is_intrinsic.set_nullable(def_id.index, true);
16401640
}
16411641
}
16421642
if let hir::ItemKind::Impl { .. } = item.kind {
@@ -2038,7 +2038,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
20382038
}
20392039
if let hir::ForeignItemKind::Fn(..) = nitem.kind {
20402040
if tcx.is_intrinsic(def_id) {
2041-
self.tables.is_intrinsic.set(def_id.index, ());
2041+
self.tables.is_intrinsic.set_nullable(def_id.index, true);
20422042
}
20432043
}
20442044
}

0 commit comments

Comments
 (0)