Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit a3c0a02

Browse files
committed
Auto merge of rust-lang#104246 - Manishearth:rollup-9o3txc7, r=Manishearth
Rollup of 9 pull requests Successful merges: - rust-lang#101939 (Add loongarch64 abi support) - rust-lang#103863 (Use `TraitEngine` in more places, restrict visibility of `FulfillmentCtxt` constructor) - rust-lang#104036 (Suggest `is_some` when we've found `Option` but expected `bool`) - rust-lang#104060 (Make `Hash`, `Hasher` and `BuildHasher` `#[const_trait]` and make `Sip` const `Hasher`) - rust-lang#104077 (Use aapcs for efiapi calling convention on arm) - rust-lang#104186 (Tighten the 'introduce new binding' suggestion) - rust-lang#104194 (`EarlyBinder` docs) - rust-lang#104233 (Don't ICE when encountering `ConstKind::Error` in `RequiredConstsVisitor`) - rust-lang#104235 (Use `const_error_with_guaranteed` more) Failed merges: - rust-lang#104078 (Print "Checking/Building ..." message even when --dry-run is passed) - rust-lang#104169 (Migrate `:target` rules to use CSS variables) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 01a6f30 + ea56e80 commit a3c0a02

File tree

38 files changed

+827
-104
lines changed

38 files changed

+827
-104
lines changed

compiler/rustc_hir_typeck/src/coercion.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ use rustc_span::{self, BytePos, DesugaringKind, Span};
6262
use rustc_target::spec::abi::Abi;
6363
use rustc_trait_selection::infer::InferCtxtExt as _;
6464
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
65+
use rustc_trait_selection::traits::TraitEngineExt as _;
6566
use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode};
6667

6768
use smallvec::{smallvec, SmallVec};
@@ -1038,7 +1039,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10381039
let Ok(ok) = coerce.coerce(source, target) else {
10391040
return false;
10401041
};
1041-
let mut fcx = traits::FulfillmentContext::new_in_snapshot();
1042+
let mut fcx = <dyn TraitEngine<'tcx>>::new_in_snapshot(self.tcx);
10421043
fcx.register_predicate_obligations(self, ok.obligations);
10431044
fcx.select_where_possible(&self).is_empty()
10441045
})

compiler/rustc_hir_typeck/src/demand.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
4242
|| self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty)
4343
|| self.suggest_block_to_brackets_peeling_refs(err, expr, expr_ty, expected)
4444
|| self.suggest_copied_or_cloned(err, expr, expr_ty, expected)
45-
|| self.suggest_into(err, expr, expr_ty, expected);
45+
|| self.suggest_into(err, expr, expr_ty, expected)
46+
|| self.suggest_option_to_bool(err, expr, expr_ty, expected);
4647

4748
self.note_type_is_not_clone(err, expected, expr_ty, expr);
4849
self.note_need_for_fn_pointer(err, expected, expr_ty);

compiler/rustc_hir_typeck/src/expr.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
103103
}
104104

105105
if let Some(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) {
106-
let expr = expr.peel_drop_temps();
107-
self.suggest_deref_ref_or_into(&mut err, expr, expected_ty, ty, None);
106+
// FIXME(compiler-errors): We probably should fold some of the
107+
// `suggest_` functions from `emit_coerce_suggestions` into here,
108+
// since some of those aren't necessarily just coerce suggestions.
109+
let _ = self.suggest_deref_ref_or_into(
110+
&mut err,
111+
expr.peel_drop_temps(),
112+
expected_ty,
113+
ty,
114+
None,
115+
) || self.suggest_option_to_bool(&mut err, expr, ty, expected_ty);
108116
extend_err(&mut err);
109117
err.emit();
110118
}

compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use rustc_hir_analysis::astconv::AstConv;
1313
use rustc_infer::infer::{self, TyCtxtInferExt};
1414
use rustc_infer::traits::{self, StatementAsExpression};
1515
use rustc_middle::lint::in_external_macro;
16-
use rustc_middle::ty::{self, Binder, IsSuggestable, ToPredicate, Ty};
16+
use rustc_middle::ty::{self, Binder, DefIdTree, IsSuggestable, ToPredicate, Ty};
1717
use rustc_session::errors::ExprParenthesesNeeded;
1818
use rustc_span::symbol::sym;
1919
use rustc_span::Span;
@@ -1116,6 +1116,53 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11161116
false
11171117
}
11181118

1119+
/// When expecting a `bool` and finding an `Option`, suggests using `let Some(..)` or `.is_some()`
1120+
pub(crate) fn suggest_option_to_bool(
1121+
&self,
1122+
diag: &mut Diagnostic,
1123+
expr: &hir::Expr<'_>,
1124+
expr_ty: Ty<'tcx>,
1125+
expected_ty: Ty<'tcx>,
1126+
) -> bool {
1127+
if !expected_ty.is_bool() {
1128+
return false;
1129+
}
1130+
1131+
let ty::Adt(def, _) = expr_ty.peel_refs().kind() else { return false; };
1132+
if !self.tcx.is_diagnostic_item(sym::Option, def.did()) {
1133+
return false;
1134+
}
1135+
1136+
let hir = self.tcx.hir();
1137+
let cond_parent = hir.parent_iter(expr.hir_id).skip_while(|(_, node)| {
1138+
matches!(node, hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Binary(op, _, _), .. }) if op.node == hir::BinOpKind::And)
1139+
}).next();
1140+
// Don't suggest:
1141+
// `let Some(_) = a.is_some() && b`
1142+
// ++++++++++
1143+
// since the user probably just misunderstood how `let else`
1144+
// and `&&` work together.
1145+
if let Some((_, hir::Node::Local(local))) = cond_parent
1146+
&& let hir::PatKind::Path(qpath) | hir::PatKind::TupleStruct(qpath, _, _) = &local.pat.kind
1147+
&& let hir::QPath::Resolved(None, path) = qpath
1148+
&& let Some(did) = path.res.opt_def_id()
1149+
.and_then(|did| self.tcx.opt_parent(did))
1150+
.and_then(|did| self.tcx.opt_parent(did))
1151+
&& self.tcx.is_diagnostic_item(sym::Option, did)
1152+
{
1153+
return false;
1154+
}
1155+
1156+
diag.span_suggestion(
1157+
expr.span.shrink_to_hi(),
1158+
"use `Option::is_some` to test if the `Option` has a value",
1159+
".is_some()",
1160+
Applicability::MachineApplicable,
1161+
);
1162+
1163+
true
1164+
}
1165+
11191166
/// Suggest wrapping the block in square brackets instead of curly braces
11201167
/// in case the block was mistaken array syntax, e.g. `{ 1 }` -> `[ 1 ]`.
11211168
pub(crate) fn suggest_block_to_brackets(

compiler/rustc_middle/src/mir/interpret/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ use rustc_ast::LitKind;
106106
use rustc_data_structures::fx::FxHashMap;
107107
use rustc_data_structures::sync::{HashMapExt, Lock};
108108
use rustc_data_structures::tiny_list::TinyList;
109+
use rustc_errors::ErrorGuaranteed;
109110
use rustc_hir::def_id::DefId;
110111
use rustc_macros::HashStable;
111112
use rustc_middle::ty::print::with_no_trimmed_paths;
@@ -176,7 +177,7 @@ pub enum LitToConstError {
176177
/// This is used for graceful error handling (`delay_span_bug`) in
177178
/// type checking (`Const::from_anon_const`).
178179
TypeError,
179-
Reported,
180+
Reported(ErrorGuaranteed),
180181
}
181182

182183
#[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]

compiler/rustc_middle/src/mir/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2251,7 +2251,9 @@ impl<'tcx> ConstantKind<'tcx> {
22512251
match tcx.const_eval_resolve(param_env, uneval, None) {
22522252
Ok(val) => Self::Val(val, ty),
22532253
Err(ErrorHandled::TooGeneric | ErrorHandled::Linted) => self,
2254-
Err(_) => Self::Ty(tcx.const_error(ty)),
2254+
Err(ErrorHandled::Reported(guar)) => {
2255+
Self::Ty(tcx.const_error_with_guaranteed(ty, guar))
2256+
}
22552257
}
22562258
}
22572259
}

compiler/rustc_middle/src/ty/consts.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ use crate::mir::interpret::LitToConstInput;
22
use crate::mir::ConstantKind;
33
use crate::ty::{self, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
44
use rustc_data_structures::intern::Interned;
5-
use rustc_errors::ErrorGuaranteed;
65
use rustc_hir as hir;
76
use rustc_hir::def_id::{DefId, LocalDefId};
87
use rustc_macros::HashStable;
@@ -225,7 +224,7 @@ impl<'tcx> Const<'tcx> {
225224
if let Some(val) = self.kind().try_eval_for_typeck(tcx, param_env) {
226225
match val {
227226
Ok(val) => Const::from_value(tcx, val, self.ty()),
228-
Err(ErrorGuaranteed { .. }) => tcx.const_error(self.ty()),
227+
Err(guar) => tcx.const_error_with_guaranteed(self.ty(), guar),
229228
}
230229
} else {
231230
// Either the constant isn't evaluatable or ValTree creation failed.
@@ -240,7 +239,7 @@ impl<'tcx> Const<'tcx> {
240239
if let Some(val) = self.kind().try_eval_for_mir(tcx, param_env) {
241240
match val {
242241
Ok(const_val) => ConstantKind::from_value(const_val, self.ty()),
243-
Err(ErrorGuaranteed { .. }) => ConstantKind::Ty(tcx.const_error(self.ty())),
242+
Err(guar) => ConstantKind::Ty(tcx.const_error_with_guaranteed(self.ty(), guar)),
244243
}
245244
} else {
246245
ConstantKind::Ty(self)

compiler/rustc_middle/src/ty/subst.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,9 @@ impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for &'tcx ty::List<T> {
506506
}
507507
}
508508

509+
/// Similar to [`super::Binder`] except that it tracks early bound generics, i.e. `struct Foo<T>(T)`
510+
/// needs `T` substituted immediately. This type primarily exists to avoid forgetting to call
511+
/// `subst`.
509512
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
510513
#[derive(Encodable, Decodable, HashStable)]
511514
pub struct EarlyBinder<T>(pub T);

compiler/rustc_mir_build/src/build/expr/as_constant.rs

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use rustc_middle::mir::interpret::{
99
use rustc_middle::mir::*;
1010
use rustc_middle::thir::*;
1111
use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, TyCtxt};
12+
use rustc_span::DUMMY_SP;
1213
use rustc_target::abi::Size;
1314

1415
impl<'a, 'tcx> Builder<'a, 'tcx> {
@@ -26,7 +27,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
2627
let literal =
2728
match lit_to_mir_constant(tcx, LitToConstInput { lit: &lit.node, ty, neg }) {
2829
Ok(c) => c,
29-
Err(LitToConstError::Reported) => ConstantKind::Ty(tcx.const_error(ty)),
30+
Err(LitToConstError::Reported(guar)) => {
31+
ConstantKind::Ty(tcx.const_error_with_guaranteed(ty, guar))
32+
}
3033
Err(LitToConstError::TypeError) => {
3134
bug!("encountered type error in `lit_to_mir_constant")
3235
}
@@ -105,7 +108,15 @@ pub(crate) fn lit_to_mir_constant<'tcx>(
105108
let LitToConstInput { lit, ty, neg } = lit_input;
106109
let trunc = |n| {
107110
let param_ty = ty::ParamEnv::reveal_all().and(ty);
108-
let width = tcx.layout_of(param_ty).map_err(|_| LitToConstError::Reported)?.size;
111+
let width = tcx
112+
.layout_of(param_ty)
113+
.map_err(|_| {
114+
LitToConstError::Reported(tcx.sess.delay_span_bug(
115+
DUMMY_SP,
116+
format!("couldn't compute width of literal: {:?}", lit_input.lit),
117+
))
118+
})?
119+
.size;
109120
trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits());
110121
let result = width.truncate(n);
111122
trace!("trunc result: {}", result);
@@ -136,12 +147,20 @@ pub(crate) fn lit_to_mir_constant<'tcx>(
136147
(ast::LitKind::Int(n, _), ty::Uint(_)) | (ast::LitKind::Int(n, _), ty::Int(_)) => {
137148
trunc(if neg { (*n as i128).overflowing_neg().0 as u128 } else { *n })?
138149
}
139-
(ast::LitKind::Float(n, _), ty::Float(fty)) => {
140-
parse_float_into_constval(*n, *fty, neg).ok_or(LitToConstError::Reported)?
141-
}
150+
(ast::LitKind::Float(n, _), ty::Float(fty)) => parse_float_into_constval(*n, *fty, neg)
151+
.ok_or_else(|| {
152+
LitToConstError::Reported(tcx.sess.delay_span_bug(
153+
DUMMY_SP,
154+
format!("couldn't parse float literal: {:?}", lit_input.lit),
155+
))
156+
})?,
142157
(ast::LitKind::Bool(b), ty::Bool) => ConstValue::Scalar(Scalar::from_bool(*b)),
143158
(ast::LitKind::Char(c), ty::Char) => ConstValue::Scalar(Scalar::from_char(*c)),
144-
(ast::LitKind::Err, _) => return Err(LitToConstError::Reported),
159+
(ast::LitKind::Err, _) => {
160+
return Err(LitToConstError::Reported(
161+
tcx.sess.delay_span_bug(DUMMY_SP, "encountered LitKind::Err during mir build"),
162+
));
163+
}
145164
_ => return Err(LitToConstError::TypeError),
146165
};
147166

compiler/rustc_mir_build/src/thir/constant.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use rustc_ast as ast;
22
use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput};
33
use rustc_middle::ty::{self, ParamEnv, ScalarInt, TyCtxt};
4+
use rustc_span::DUMMY_SP;
45

56
pub(crate) fn lit_to_const<'tcx>(
67
tcx: TyCtxt<'tcx>,
@@ -10,7 +11,15 @@ pub(crate) fn lit_to_const<'tcx>(
1011

1112
let trunc = |n| {
1213
let param_ty = ParamEnv::reveal_all().and(ty);
13-
let width = tcx.layout_of(param_ty).map_err(|_| LitToConstError::Reported)?.size;
14+
let width = tcx
15+
.layout_of(param_ty)
16+
.map_err(|_| {
17+
LitToConstError::Reported(tcx.sess.delay_span_bug(
18+
DUMMY_SP,
19+
format!("couldn't compute width of literal: {:?}", lit_input.lit),
20+
))
21+
})?
22+
.size;
1423
trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits());
1524
let result = width.truncate(n);
1625
trace!("trunc result: {}", result);
@@ -44,7 +53,11 @@ pub(crate) fn lit_to_const<'tcx>(
4453
}
4554
(ast::LitKind::Bool(b), ty::Bool) => ty::ValTree::from_scalar_int((*b).into()),
4655
(ast::LitKind::Char(c), ty::Char) => ty::ValTree::from_scalar_int((*c).into()),
47-
(ast::LitKind::Err, _) => return Err(LitToConstError::Reported),
56+
(ast::LitKind::Err, _) => {
57+
return Err(LitToConstError::Reported(
58+
tcx.sess.delay_span_bug(DUMMY_SP, "encountered LitKind::Err during mir build"),
59+
));
60+
}
4861
_ => return Err(LitToConstError::TypeError),
4962
};
5063

0 commit comments

Comments
 (0)