Skip to content

Rollup of 9 pull requests #104246

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 27 commits into from
Nov 10, 2022
Merged
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
c7961da
Add loongarch64 abi support
zhaixiaojuan Sep 17, 2022
1bcf9fa
Made `Hash` and `Hasher` const_trait
onestacked Nov 4, 2022
3ea4165
Make `BuildHasher` const_trait
onestacked Nov 4, 2022
5f9899b
Made `Sip` const `Hasher`
onestacked Nov 6, 2022
dc1f1a8
Added `const_hash` tracking issue id
onestacked Nov 6, 2022
42cbb40
Use aapcs for efiapi calling convention on arm
nicholasbishop Nov 6, 2022
cebce1e
Removed unnecessary Trait bound
onestacked Nov 7, 2022
56e59bc
Test const `Hash`, fix nits
onestacked Nov 8, 2022
952df48
Fix #104086, Tighten the 'introduce new binding' suggestion
chenyukang Nov 9, 2022
5689f9c
fix tests and code cleanup
chenyukang Nov 9, 2022
4c197c0
docs
BoxyUwU Nov 9, 2022
c69872b
add 'is_assign_rhs' to avoid weird suggesting 'let'
chenyukang Nov 9, 2022
38ada60
Suggest is_some or let when encountering Option and bool type mismatch
compiler-errors Nov 6, 2022
ed17c6b
Use TraitEngine in more places, make FulfillmentCtxt constructor more…
compiler-errors Nov 2, 2022
27fddcf
bless a chalk test
compiler-errors Nov 10, 2022
31157de
Don't ICE when encountering ConstKind::Error in RequiredConstsVisitor
compiler-errors Nov 10, 2022
0f89fb1
Use const_error_with_guaranteed more
compiler-errors Nov 10, 2022
2566701
broken links go brrrrr
BoxyUwU Nov 10, 2022
a7cd4f2
Rollup merge of #101939 - zhaixiaojuan:loongarch64-abi, r=oli-obk
Manishearth Nov 10, 2022
9c0e783
Rollup merge of #103863 - compiler-errors:fulfillcx-less, r=wesleywiser
Manishearth Nov 10, 2022
529f714
Rollup merge of #104036 - compiler-errors:option-sugg, r=petrochenkov
Manishearth Nov 10, 2022
150e0ec
Rollup merge of #104060 - ink-feather-org:const_hash, r=fee1-dead
Manishearth Nov 10, 2022
8f2c1f8
Rollup merge of #104077 - nicholasbishop:bishop-uefi-aapcs, r=nagisa
Manishearth Nov 10, 2022
819c931
Rollup merge of #104186 - chenyukang:yukang/fix-104086-let-binding-is…
Manishearth Nov 10, 2022
c6595ea
Rollup merge of #104194 - BoxyUwU:early_binder_docs, r=compiler-errors
Manishearth Nov 10, 2022
77fde5d
Rollup merge of #104233 - compiler-errors:issue-104209, r=lcnr
Manishearth Nov 10, 2022
ea56e80
Rollup merge of #104235 - compiler-errors:more-ct-guar, r=oli-obk
Manishearth Nov 10, 2022
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
3 changes: 2 additions & 1 deletion compiler/rustc_hir_typeck/src/coercion.rs
Original file line number Diff line number Diff line change
@@ -62,6 +62,7 @@ use rustc_span::{self, BytePos, DesugaringKind, Span};
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::infer::InferCtxtExt as _;
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
use rustc_trait_selection::traits::TraitEngineExt as _;
use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode};

use smallvec::{smallvec, SmallVec};
@@ -1038,7 +1039,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let Ok(ok) = coerce.coerce(source, target) else {
return false;
};
let mut fcx = traits::FulfillmentContext::new_in_snapshot();
let mut fcx = <dyn TraitEngine<'tcx>>::new_in_snapshot(self.tcx);
fcx.register_predicate_obligations(self, ok.obligations);
fcx.select_where_possible(&self).is_empty()
})
3 changes: 2 additions & 1 deletion compiler/rustc_hir_typeck/src/demand.rs
Original file line number Diff line number Diff line change
@@ -42,7 +42,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|| self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty)
|| self.suggest_block_to_brackets_peeling_refs(err, expr, expr_ty, expected)
|| self.suggest_copied_or_cloned(err, expr, expr_ty, expected)
|| self.suggest_into(err, expr, expr_ty, expected);
|| self.suggest_into(err, expr, expr_ty, expected)
|| self.suggest_option_to_bool(err, expr, expr_ty, expected);

self.note_type_is_not_clone(err, expected, expr_ty, expr);
self.note_need_for_fn_pointer(err, expected, expr_ty);
12 changes: 10 additions & 2 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
@@ -103,8 +103,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}

if let Some(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) {
let expr = expr.peel_drop_temps();
self.suggest_deref_ref_or_into(&mut err, expr, expected_ty, ty, None);
// FIXME(compiler-errors): We probably should fold some of the
// `suggest_` functions from `emit_coerce_suggestions` into here,
// since some of those aren't necessarily just coerce suggestions.
let _ = self.suggest_deref_ref_or_into(
&mut err,
expr.peel_drop_temps(),
expected_ty,
ty,
None,
) || self.suggest_option_to_bool(&mut err, expr, ty, expected_ty);
extend_err(&mut err);
err.emit();
}
49 changes: 48 additions & 1 deletion compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@ use rustc_hir_analysis::astconv::AstConv;
use rustc_infer::infer::{self, TyCtxtInferExt};
use rustc_infer::traits::{self, StatementAsExpression};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::{self, Binder, IsSuggestable, ToPredicate, Ty};
use rustc_middle::ty::{self, Binder, DefIdTree, IsSuggestable, ToPredicate, Ty};
use rustc_session::errors::ExprParenthesesNeeded;
use rustc_span::symbol::sym;
use rustc_span::Span;
@@ -1116,6 +1116,53 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
false
}

/// When expecting a `bool` and finding an `Option`, suggests using `let Some(..)` or `.is_some()`
pub(crate) fn suggest_option_to_bool(
&self,
diag: &mut Diagnostic,
expr: &hir::Expr<'_>,
expr_ty: Ty<'tcx>,
expected_ty: Ty<'tcx>,
) -> bool {
if !expected_ty.is_bool() {
return false;
}

let ty::Adt(def, _) = expr_ty.peel_refs().kind() else { return false; };
if !self.tcx.is_diagnostic_item(sym::Option, def.did()) {
return false;
}

let hir = self.tcx.hir();
let cond_parent = hir.parent_iter(expr.hir_id).skip_while(|(_, node)| {
matches!(node, hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Binary(op, _, _), .. }) if op.node == hir::BinOpKind::And)
}).next();
// Don't suggest:
// `let Some(_) = a.is_some() && b`
// ++++++++++
// since the user probably just misunderstood how `let else`
// and `&&` work together.
if let Some((_, hir::Node::Local(local))) = cond_parent
&& let hir::PatKind::Path(qpath) | hir::PatKind::TupleStruct(qpath, _, _) = &local.pat.kind
&& let hir::QPath::Resolved(None, path) = qpath
&& let Some(did) = path.res.opt_def_id()
.and_then(|did| self.tcx.opt_parent(did))
.and_then(|did| self.tcx.opt_parent(did))
&& self.tcx.is_diagnostic_item(sym::Option, did)
{
return false;
}

diag.span_suggestion(
expr.span.shrink_to_hi(),
"use `Option::is_some` to test if the `Option` has a value",
".is_some()",
Applicability::MachineApplicable,
);

true
}

/// Suggest wrapping the block in square brackets instead of curly braces
/// in case the block was mistaken array syntax, e.g. `{ 1 }` -> `[ 1 ]`.
pub(crate) fn suggest_block_to_brackets(
3 changes: 2 additions & 1 deletion compiler/rustc_middle/src/mir/interpret/mod.rs
Original file line number Diff line number Diff line change
@@ -106,6 +106,7 @@ use rustc_ast::LitKind;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::{HashMapExt, Lock};
use rustc_data_structures::tiny_list::TinyList;
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def_id::DefId;
use rustc_macros::HashStable;
use rustc_middle::ty::print::with_no_trimmed_paths;
@@ -176,7 +177,7 @@ pub enum LitToConstError {
/// This is used for graceful error handling (`delay_span_bug`) in
/// type checking (`Const::from_anon_const`).
TypeError,
Reported,
Reported(ErrorGuaranteed),
}

#[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
4 changes: 3 additions & 1 deletion compiler/rustc_middle/src/mir/mod.rs
Original file line number Diff line number Diff line change
@@ -2251,7 +2251,9 @@ impl<'tcx> ConstantKind<'tcx> {
match tcx.const_eval_resolve(param_env, uneval, None) {
Ok(val) => Self::Val(val, ty),
Err(ErrorHandled::TooGeneric | ErrorHandled::Linted) => self,
Err(_) => Self::Ty(tcx.const_error(ty)),
Err(ErrorHandled::Reported(guar)) => {
Self::Ty(tcx.const_error_with_guaranteed(ty, guar))
}
}
}
}
5 changes: 2 additions & 3 deletions compiler/rustc_middle/src/ty/consts.rs
Original file line number Diff line number Diff line change
@@ -2,7 +2,6 @@ use crate::mir::interpret::LitToConstInput;
use crate::mir::ConstantKind;
use crate::ty::{self, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
use rustc_data_structures::intern::Interned;
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_macros::HashStable;
@@ -225,7 +224,7 @@ impl<'tcx> Const<'tcx> {
if let Some(val) = self.kind().try_eval_for_typeck(tcx, param_env) {
match val {
Ok(val) => Const::from_value(tcx, val, self.ty()),
Err(ErrorGuaranteed { .. }) => tcx.const_error(self.ty()),
Err(guar) => tcx.const_error_with_guaranteed(self.ty(), guar),
}
} else {
// Either the constant isn't evaluatable or ValTree creation failed.
@@ -240,7 +239,7 @@ impl<'tcx> Const<'tcx> {
if let Some(val) = self.kind().try_eval_for_mir(tcx, param_env) {
match val {
Ok(const_val) => ConstantKind::from_value(const_val, self.ty()),
Err(ErrorGuaranteed { .. }) => ConstantKind::Ty(tcx.const_error(self.ty())),
Err(guar) => ConstantKind::Ty(tcx.const_error_with_guaranteed(self.ty(), guar)),
}
} else {
ConstantKind::Ty(self)
3 changes: 3 additions & 0 deletions compiler/rustc_middle/src/ty/subst.rs
Original file line number Diff line number Diff line change
@@ -506,6 +506,9 @@ impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for &'tcx ty::List<T> {
}
}

/// Similar to [`super::Binder`] except that it tracks early bound generics, i.e. `struct Foo<T>(T)`
/// needs `T` substituted immediately. This type primarily exists to avoid forgetting to call
/// `subst`.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[derive(Encodable, Decodable, HashStable)]
pub struct EarlyBinder<T>(pub T);
31 changes: 25 additions & 6 deletions compiler/rustc_mir_build/src/build/expr/as_constant.rs
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@ use rustc_middle::mir::interpret::{
use rustc_middle::mir::*;
use rustc_middle::thir::*;
use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, TyCtxt};
use rustc_span::DUMMY_SP;
use rustc_target::abi::Size;

impl<'a, 'tcx> Builder<'a, 'tcx> {
@@ -26,7 +27,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let literal =
match lit_to_mir_constant(tcx, LitToConstInput { lit: &lit.node, ty, neg }) {
Ok(c) => c,
Err(LitToConstError::Reported) => ConstantKind::Ty(tcx.const_error(ty)),
Err(LitToConstError::Reported(guar)) => {
ConstantKind::Ty(tcx.const_error_with_guaranteed(ty, guar))
}
Err(LitToConstError::TypeError) => {
bug!("encountered type error in `lit_to_mir_constant")
}
@@ -105,7 +108,15 @@ pub(crate) fn lit_to_mir_constant<'tcx>(
let LitToConstInput { lit, ty, neg } = lit_input;
let trunc = |n| {
let param_ty = ty::ParamEnv::reveal_all().and(ty);
let width = tcx.layout_of(param_ty).map_err(|_| LitToConstError::Reported)?.size;
let width = tcx
.layout_of(param_ty)
.map_err(|_| {
LitToConstError::Reported(tcx.sess.delay_span_bug(
DUMMY_SP,
format!("couldn't compute width of literal: {:?}", lit_input.lit),
))
})?
.size;
trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits());
let result = width.truncate(n);
trace!("trunc result: {}", result);
@@ -136,12 +147,20 @@ pub(crate) fn lit_to_mir_constant<'tcx>(
(ast::LitKind::Int(n, _), ty::Uint(_)) | (ast::LitKind::Int(n, _), ty::Int(_)) => {
trunc(if neg { (*n as i128).overflowing_neg().0 as u128 } else { *n })?
}
(ast::LitKind::Float(n, _), ty::Float(fty)) => {
parse_float_into_constval(*n, *fty, neg).ok_or(LitToConstError::Reported)?
}
(ast::LitKind::Float(n, _), ty::Float(fty)) => parse_float_into_constval(*n, *fty, neg)
.ok_or_else(|| {
LitToConstError::Reported(tcx.sess.delay_span_bug(
DUMMY_SP,
format!("couldn't parse float literal: {:?}", lit_input.lit),
))
})?,
(ast::LitKind::Bool(b), ty::Bool) => ConstValue::Scalar(Scalar::from_bool(*b)),
(ast::LitKind::Char(c), ty::Char) => ConstValue::Scalar(Scalar::from_char(*c)),
(ast::LitKind::Err, _) => return Err(LitToConstError::Reported),
(ast::LitKind::Err, _) => {
return Err(LitToConstError::Reported(
tcx.sess.delay_span_bug(DUMMY_SP, "encountered LitKind::Err during mir build"),
));
}
_ => return Err(LitToConstError::TypeError),
};

17 changes: 15 additions & 2 deletions compiler/rustc_mir_build/src/thir/constant.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use rustc_ast as ast;
use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput};
use rustc_middle::ty::{self, ParamEnv, ScalarInt, TyCtxt};
use rustc_span::DUMMY_SP;

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

let trunc = |n| {
let param_ty = ParamEnv::reveal_all().and(ty);
let width = tcx.layout_of(param_ty).map_err(|_| LitToConstError::Reported)?.size;
let width = tcx
.layout_of(param_ty)
.map_err(|_| {
LitToConstError::Reported(tcx.sess.delay_span_bug(
DUMMY_SP,
format!("couldn't compute width of literal: {:?}", lit_input.lit),
))
})?
.size;
trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits());
let result = width.truncate(n);
trace!("trunc result: {}", result);
@@ -44,7 +53,11 @@ pub(crate) fn lit_to_const<'tcx>(
}
(ast::LitKind::Bool(b), ty::Bool) => ty::ValTree::from_scalar_int((*b).into()),
(ast::LitKind::Char(c), ty::Char) => ty::ValTree::from_scalar_int((*c).into()),
(ast::LitKind::Err, _) => return Err(LitToConstError::Reported),
(ast::LitKind::Err, _) => {
return Err(LitToConstError::Reported(
tcx.sess.delay_span_bug(DUMMY_SP, "encountered LitKind::Err during mir build"),
));
}
_ => return Err(LitToConstError::TypeError),
};

2 changes: 1 addition & 1 deletion compiler/rustc_mir_build/src/thir/pattern/mod.rs
Original file line number Diff line number Diff line change
@@ -614,7 +614,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg };
match self.tcx.at(expr.span).lit_to_mir_constant(lit_input) {
Ok(constant) => self.const_to_pat(constant, expr.hir_id, lit.span, false).kind,
Err(LitToConstError::Reported) => PatKind::Wild,
Err(LitToConstError::Reported(_)) => PatKind::Wild,
Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"),
}
}
2 changes: 1 addition & 1 deletion compiler/rustc_mir_transform/src/required_consts.rs
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@ impl<'tcx> Visitor<'tcx> for RequiredConstsVisitor<'_, 'tcx> {
let literal = constant.literal;
match literal {
ConstantKind::Ty(c) => match c.kind() {
ConstKind::Param(_) => {}
ConstKind::Param(_) | ConstKind::Error(_) => {}
_ => bug!("only ConstKind::Param should be encountered here, got {:#?}", c),
},
ConstantKind::Unevaluated(..) => self.required_consts.push(*constant),
14 changes: 10 additions & 4 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
@@ -527,6 +527,7 @@ struct DiagnosticMetadata<'ast> {

/// Used to detect possible new binding written without `let` and to provide structured suggestion.
in_assignment: Option<&'ast Expr>,
is_assign_rhs: bool,

/// If we are currently in a trait object definition. Used to point at the bounds when
/// encountering a struct or enum.
@@ -3963,10 +3964,15 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
self.resolve_expr(elem, Some(expr));
self.visit_expr(idx);
}
ExprKind::Assign(..) => {
let old = self.diagnostic_metadata.in_assignment.replace(expr);
visit::walk_expr(self, expr);
self.diagnostic_metadata.in_assignment = old;
ExprKind::Assign(ref lhs, ref rhs, _) => {
if !self.diagnostic_metadata.is_assign_rhs {
self.diagnostic_metadata.in_assignment = Some(expr);
}
self.visit_expr(lhs);
self.diagnostic_metadata.is_assign_rhs = true;
self.diagnostic_metadata.in_assignment = None;
self.visit_expr(rhs);
self.diagnostic_metadata.is_assign_rhs = false;
}
_ => {
visit::walk_expr(self, expr);
21 changes: 7 additions & 14 deletions compiler/rustc_resolve/src/late/diagnostics.rs
Original file line number Diff line number Diff line change
@@ -1810,29 +1810,22 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
false
}

fn let_binding_suggestion(&self, err: &mut Diagnostic, ident_span: Span) -> bool {
// try to give a suggestion for this pattern: `name = 1`, which is common in other languages
let mut added_suggestion = false;
if let Some(Expr { kind: ExprKind::Assign(lhs, _rhs, _), .. }) = self.diagnostic_metadata.in_assignment &&
// try to give a suggestion for this pattern: `name = blah`, which is common in other languages
// suggest `let name = blah` to introduce a new binding
fn let_binding_suggestion(&mut self, err: &mut Diagnostic, ident_span: Span) -> bool {
if let Some(Expr { kind: ExprKind::Assign(lhs, .. ), .. }) = self.diagnostic_metadata.in_assignment &&
let ast::ExprKind::Path(None, _) = lhs.kind {
let sm = self.r.session.source_map();
let line_span = sm.span_extend_to_line(ident_span);
let ident_name = sm.span_to_snippet(ident_span).unwrap();
// HACK(chenyukang): make sure ident_name is at the starting of the line to protect against macros
if sm
.span_to_snippet(line_span)
.map_or(false, |s| s.trim().starts_with(&ident_name))
{
if !ident_span.from_expansion() {
err.span_suggestion_verbose(
ident_span.shrink_to_lo(),
"you might have meant to introduce a new binding",
"let ".to_string(),
Applicability::MaybeIncorrect,
);
added_suggestion = true;
return true;
}
}
added_suggestion
false
}

fn find_module(&mut self, def_id: DefId) -> Option<(Module<'a>, ImportSuggestion)> {
Loading