Skip to content

Rollup of 9 pull requests #107290

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 24 commits into from
Jan 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
0a03d1c
Allow setting CFG_DISABLE_UNSTABLE_FEATURES to 0
chbaker0 Jan 12, 2023
a37b484
Allow fmt::Arguments::as_str() to return more Some(_).
m-ou-se Jan 13, 2023
236f823
`sub_ptr()` is equivalent to `usize::try_from().unwrap_unchecked()`, …
ChayimFriedman2 Jan 23, 2023
e477cf9
Suggest coercion of `Result` using `?`
estebank Jan 8, 2023
d5a1609
review comment: use `fcx.infcx`
estebank Jan 8, 2023
ddd9a9f
Add call in `emit_type_mismatch_suggestions`
estebank Jan 8, 2023
fcf0ed9
Do not erase regions
estebank Jan 8, 2023
df81147
Ensure suggestion correctness
estebank Jan 8, 2023
62aff3b
tweak wording
estebank Jan 23, 2023
033047a
`new_outside_solver` -> `evaluate_root_goal`
lcnr Jan 23, 2023
91fdbd7
rustc_metadata: Support non-`Option` nullable values in metadata tables
petrochenkov Jan 21, 2023
5dd87c5
rustdoc: simplify settings popover DOM
notriddle Jan 23, 2023
1c41b4d
rustdoc: remove dead settings JS for obsolete select-wrapper
notriddle Jan 23, 2023
a8b77cf
Add suggestion to remove if in let...else block
edward-shen Jan 24, 2023
1e22280
Add suggestions for function pointers
mattjperez Dec 11, 2022
c0930c4
Rollup merge of #105552 - mattjperez:add-incompatible-types-note, r=c…
Dylan-DPC Jan 25, 2023
b36a8dc
Rollup merge of #106583 - estebank:suggest-result-coercion, r=compile…
Dylan-DPC Jan 25, 2023
9e6873f
Rollup merge of #106767 - chbaker0:disable-unstable-features, r=Mark-…
Dylan-DPC Jan 25, 2023
0c53b21
Rollup merge of #106823 - m-ou-se:format-args-as-str-guarantees, r=dt…
Dylan-DPC Jan 25, 2023
a788ce2
Rollup merge of #107166 - petrochenkov:nooptable, r=oli-obk
Dylan-DPC Jan 25, 2023
4e2b5d1
Rollup merge of #107213 - edward-shen:edward-shen/fix-accidental-let-…
Dylan-DPC Jan 25, 2023
2406691
Rollup merge of #107223 - ChayimFriedman2:patch-5, r=WaffleLapkin
Dylan-DPC Jan 25, 2023
139a3c5
Rollup merge of #107227 - lcnr:solver-new-external-api, r=compiler-er…
Dylan-DPC Jan 25, 2023
e78fa8a
Rollup merge of #107232 - notriddle:notriddle/settings-choice, r=Guil…
Dylan-DPC Jan 25, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions compiler/rustc_error_messages/locales/en-US/parse.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ parse_const_let_mutually_exclusive = `const` and `let` are mutually exclusive

parse_invalid_expression_in_let_else = a `{$operator}` expression cannot be directly assigned in `let...else`
parse_invalid_curly_in_let_else = right curly brace `{"}"}` before `else` in a `let...else` statement not allowed
parse_extra_if_in_let_else = remove the `if` if you meant to write a `let...else` statement

parse_compound_assignment_expression_in_let = can't reassign to an uninitialized variable
.suggestion = initialize the variable
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_feature/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ impl UnstableFeatures {
/// Otherwise, only `RUSTC_BOOTSTRAP=1` will work.
pub fn from_environment(krate: Option<&str>) -> Self {
// `true` if this is a feature-staged build, i.e., on the beta or stable channel.
let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
let disable_unstable_features =
option_env!("CFG_DISABLE_UNSTABLE_FEATURES").map(|s| s != "0").unwrap_or(false);
// Returns whether `krate` should be counted as unstable
let is_unstable_crate = |var: &str| {
krate.map_or(false, |name| var.split(',').any(|new_krate| new_krate == name))
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_hir_typeck/src/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1613,12 +1613,14 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
if visitor.ret_exprs.len() > 0 && let Some(expr) = expression {
self.note_unreachable_loop_return(&mut err, &expr, &visitor.ret_exprs);
}

let reported = err.emit_unless(unsized_return);

self.final_ty = Some(fcx.tcx.ty_error_with_guaranteed(reported));
}
}
}

fn note_unreachable_loop_return(
&self,
err: &mut Diagnostic,
Expand Down
54 changes: 52 additions & 2 deletions compiler/rustc_hir_typeck/src/demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|| self.suggest_copied_or_cloned(err, expr, expr_ty, expected)
|| self.suggest_clone_for_ref(err, expr, expr_ty, expected)
|| self.suggest_into(err, expr, expr_ty, expected)
|| self.suggest_floating_point_literal(err, expr, expected);
|| self.suggest_floating_point_literal(err, expr, expected)
|| self.note_result_coercion(err, expr, expected, expr_ty);
if !suggested {
self.point_at_expr_source_of_inferred_type(err, expr, expr_ty, expected);
}
Expand All @@ -81,7 +82,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.annotate_expected_due_to_let_ty(err, expr, error);
self.emit_type_mismatch_suggestions(err, expr, expr_ty, expected, expected_ty_expr, error);
self.note_type_is_not_clone(err, expected, expr_ty, expr);
self.note_need_for_fn_pointer(err, expected, expr_ty);
self.note_internal_mutation_in_method(err, expr, expected, expr_ty);
self.check_for_range_as_method_call(err, expr, expr_ty, expected);
self.check_for_binding_assigned_block_without_tail_expression(err, expr, expr_ty, expected);
Expand Down Expand Up @@ -697,6 +697,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
}

pub(crate) fn note_result_coercion(
&self,
err: &mut Diagnostic,
expr: &hir::Expr<'tcx>,
expected: Ty<'tcx>,
found: Ty<'tcx>,
) -> bool {
let ty::Adt(e, substs_e) = expected.kind() else { return false; };
let ty::Adt(f, substs_f) = found.kind() else { return false; };
if e.did() != f.did() {
return false;
}
if Some(e.did()) != self.tcx.get_diagnostic_item(sym::Result) {
return false;
}
let map = self.tcx.hir();
if let Some(hir::Node::Expr(expr)) = map.find_parent(expr.hir_id)
&& let hir::ExprKind::Ret(_) = expr.kind
{
// `return foo;`
} else if map.get_return_block(expr.hir_id).is_some() {
// Function's tail expression.
} else {
return false;
}
let e = substs_e.type_at(1);
let f = substs_f.type_at(1);
if self
.infcx
.type_implements_trait(
self.tcx.get_diagnostic_item(sym::Into).unwrap(),
[f, e],
self.param_env,
)
.must_apply_modulo_regions()
{
err.multipart_suggestion(
"use `?` to coerce and return an appropriate `Err`, and wrap the resulting value \
in `Ok` so the expression remains of type `Result`",
vec![
(expr.span.shrink_to_lo(), "Ok(".to_string()),
(expr.span.shrink_to_hi(), "?)".to_string()),
],
Applicability::MaybeIncorrect,
);
return true;
}
false
}

/// If the expected type is an enum (Issue #55250) with any variants whose
/// sole field is of the found type, suggest such variants. (Issue #42764)
fn suggest_compatible_variants(
Expand Down
37 changes: 0 additions & 37 deletions compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -926,43 +926,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}

pub(in super::super) fn note_need_for_fn_pointer(
&self,
err: &mut Diagnostic,
expected: Ty<'tcx>,
found: Ty<'tcx>,
) {
let (sig, did, substs) = match (&expected.kind(), &found.kind()) {
(ty::FnDef(did1, substs1), ty::FnDef(did2, substs2)) => {
let sig1 = self.tcx.bound_fn_sig(*did1).subst(self.tcx, substs1);
let sig2 = self.tcx.bound_fn_sig(*did2).subst(self.tcx, substs2);
if sig1 != sig2 {
return;
}
err.note(
"different `fn` items always have unique types, even if their signatures are \
the same",
);
(sig1, *did1, substs1)
}
(ty::FnDef(did, substs), ty::FnPtr(sig2)) => {
let sig1 = self.tcx.bound_fn_sig(*did).subst(self.tcx, substs);
if sig1 != *sig2 {
return;
}
(sig1, *did, substs)
}
_ => return,
};
err.help(&format!("change the expected type to be function pointer `{}`", sig));
err.help(&format!(
"if the expected type is due to type inference, cast the expected `fn` to a function \
pointer: `{} as {}`",
self.tcx.def_path_str_with_substs(did, substs),
sig
));
}

// Instantiates the given path, which must refer to an item with the given
// number of type parameters and type.
#[instrument(skip(self, span), level = "debug")]
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_infer/src/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1841,6 +1841,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
self.suggest_as_ref_where_appropriate(span, &exp_found, diag);
self.suggest_accessing_field_where_appropriate(cause, &exp_found, diag);
self.suggest_await_on_expect_found(cause, span, &exp_found, diag);
self.suggest_function_pointers(cause, span, &exp_found, diag);
}
}

Expand Down Expand Up @@ -2585,7 +2586,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
/// with the other type. A TyVar inference type is compatible with any type, and an IntVar or
/// FloatVar inference type are compatible with themselves or their concrete types (Int and
/// Float types, respectively). When comparing two ADTs, these rules apply recursively.
pub fn same_type_modulo_infer(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
pub fn same_type_modulo_infer<T: relate::Relate<'tcx>>(&self, a: T, b: T) -> bool {
let (a, b) = self.resolve_vars_if_possible((a, b));
SameTypeModuloInfer(self).relate(a, b).is_ok()
}
Expand Down
78 changes: 77 additions & 1 deletion compiler/rustc_infer/src/infer/error_reporting/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use rustc_middle::traits::{
StatementAsExpression,
};
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self as ty, Ty, TypeVisitable};
use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TypeVisitable};
use rustc_span::{sym, BytePos, Span};

use crate::errors::SuggAddLetForLetChains;
Expand Down Expand Up @@ -351,6 +351,82 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}
}

pub(super) fn suggest_function_pointers(
&self,
cause: &ObligationCause<'tcx>,
span: Span,
exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
diag: &mut Diagnostic,
) {
debug!("suggest_function_pointers(cause={:?}, exp_found={:?})", cause, exp_found);
let ty::error::ExpectedFound { expected, found } = exp_found;
let expected_inner = expected.peel_refs();
let found_inner = found.peel_refs();
if !expected_inner.is_fn() || !found_inner.is_fn() {
return;
}
match (&expected_inner.kind(), &found_inner.kind()) {
(ty::FnPtr(sig), ty::FnDef(did, substs)) => {
let expected_sig = &(self.normalize_fn_sig)(*sig);
let found_sig =
&(self.normalize_fn_sig)(self.tcx.bound_fn_sig(*did).subst(self.tcx, substs));

let fn_name = self.tcx.def_path_str_with_substs(*did, substs);

if !self.same_type_modulo_infer(*found_sig, *expected_sig)
|| !sig.is_suggestable(self.tcx, true)
|| ty::util::is_intrinsic(self.tcx, *did)
{
return;
}

let (msg, sugg) = match (expected.is_ref(), found.is_ref()) {
(true, false) => {
let msg = "consider using a reference";
let sug = format!("&{fn_name}");
(msg, sug)
}
(false, true) => {
let msg = "consider removing the reference";
let sug = format!("{fn_name}");
(msg, sug)
}
(true, true) => {
diag.note("fn items are distinct from fn pointers");
let msg = "consider casting to a fn pointer";
let sug = format!("&({fn_name} as {sig})");
(msg, sug)
}
(false, false) => {
diag.note("fn items are distinct from fn pointers");
let msg = "consider casting to a fn pointer";
let sug = format!("{fn_name} as {sig}");
(msg, sug)
}
};
diag.span_suggestion(span, msg, &sugg, Applicability::MaybeIncorrect);
}
(ty::FnDef(did1, substs1), ty::FnDef(did2, substs2)) => {
let expected_sig =
&(self.normalize_fn_sig)(self.tcx.bound_fn_sig(*did1).subst(self.tcx, substs1));
let found_sig =
&(self.normalize_fn_sig)(self.tcx.bound_fn_sig(*did2).subst(self.tcx, substs2));

if self.same_type_modulo_infer(*found_sig, *expected_sig) {
diag.note(
"different fn items have unique types, even if their signatures are the same",
);
}
}
(ty::FnDef(_, _), ty::FnPtr(_)) => {
diag.note("fn items are distinct from fn pointers");
}
_ => {
return;
}
};
}

pub fn should_suggest_as_ref(&self, expected: Ty<'tcx>, found: Ty<'tcx>) -> Option<&str> {
if let (ty::Adt(exp_def, exp_substs), ty::Ref(_, found_ty, _)) =
(expected.kind(), found.kind())
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_metadata/src/rmeta/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -985,7 +985,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
let vis = self.get_visibility(id);
let span = self.get_span(id, sess);
let macro_rules = match kind {
DefKind::Macro(..) => self.root.tables.macro_rules.get(self, id).is_some(),
DefKind::Macro(..) => self.root.tables.is_macro_rules.get(self, id),
_ => false,
};

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

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

fn get_is_intrinsic(self, index: DefIndex) -> bool {
self.root.tables.is_intrinsic.get(self, index).is_some()
self.root.tables.is_intrinsic.get(self, index)
}
}

Expand Down
7 changes: 1 addition & 6 deletions compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,12 +226,7 @@ provide! { tcx, def_id, other, cdata,
deduced_param_attrs => { table }
is_type_alias_impl_trait => {
debug_assert_eq!(tcx.def_kind(def_id), DefKind::OpaqueTy);
cdata
.root
.tables
.is_type_alias_impl_trait
.get(cdata, def_id.index)
.is_some()
cdata.root.tables.is_type_alias_impl_trait.get(cdata, def_id.index)
}
collect_return_position_impl_trait_in_trait_tys => {
Ok(cdata
Expand Down
14 changes: 7 additions & 7 deletions compiler/rustc_metadata/src/rmeta/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
self.lazy(DefPathHashMapRef::BorrowedFromTcx(self.tcx.def_path_hash_to_def_index_map()))
}

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

Expand Down Expand Up @@ -1130,7 +1130,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
attr_flags |= AttrFlags::IS_DOC_HIDDEN;
}
if !attr_flags.is_empty() {
self.tables.attr_flags.set(def_id.local_def_index, attr_flags);
self.tables.attr_flags.set_nullable(def_id.local_def_index, attr_flags);
}
}

Expand Down Expand Up @@ -1387,7 +1387,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
if impl_item.kind == ty::AssocKind::Fn {
record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
if tcx.is_intrinsic(def_id) {
self.tables.is_intrinsic.set(def_id.index, ());
self.tables.is_intrinsic.set_nullable(def_id.index, true);
}
}
}
Expand Down Expand Up @@ -1519,7 +1519,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
}
hir::ItemKind::Macro(ref macro_def, _) => {
if macro_def.macro_rules {
self.tables.macro_rules.set(def_id.index, ());
self.tables.is_macro_rules.set_nullable(def_id.index, true);
}
record!(self.tables.macro_definition[def_id] <- &*macro_def.body);
}
Expand All @@ -1529,7 +1529,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
hir::ItemKind::OpaqueTy(ref opaque) => {
self.encode_explicit_item_bounds(def_id);
if matches!(opaque.origin, hir::OpaqueTyOrigin::TyAlias) {
self.tables.is_type_alias_impl_trait.set(def_id.index, ());
self.tables.is_type_alias_impl_trait.set_nullable(def_id.index, true);
}
}
hir::ItemKind::Enum(..) => {
Expand Down Expand Up @@ -1636,7 +1636,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
if let hir::ItemKind::Fn(..) = item.kind {
record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
if tcx.is_intrinsic(def_id) {
self.tables.is_intrinsic.set(def_id.index, ());
self.tables.is_intrinsic.set_nullable(def_id.index, true);
}
}
if let hir::ItemKind::Impl { .. } = item.kind {
Expand Down Expand Up @@ -2038,7 +2038,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
}
if let hir::ForeignItemKind::Fn(..) = nitem.kind {
if tcx.is_intrinsic(def_id) {
self.tables.is_intrinsic.set(def_id.index, ());
self.tables.is_intrinsic.set_nullable(def_id.index, true);
}
}
}
Expand Down
Loading