Auto merge of #107919 - Dylan-DPC:rollup-fkl9swa, r=Dylan-DPC
Rollup of 9 pull requests Successful merges: - #105019 (Add parentheses properly for borrowing suggestion) - #106001 (Stop at the first `NULL` argument when iterating `argv`) - #107098 (Suggest function call on pattern type mismatch) - #107490 (rustdoc: remove inconsistently-present sidebar tooltips) - #107855 (Add a couple random projection tests for new solver) - #107857 (Add ui test for implementation on projection) - #107878 (Clarify `new_size` for realloc means bytes) - #107888 (revert #107074, add regression test) - #107900 (Zero the `REPARSE_MOUNTPOINT_DATA_BUFFER` header) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
71f6675de1
25 changed files with 320 additions and 70 deletions
|
@ -13,7 +13,7 @@ use rustc_middle::mir::{
|
|||
RetagKind, RuntimePhase, Rvalue, SourceScope, Statement, StatementKind, Terminator,
|
||||
TerminatorKind, UnOp, START_BLOCK,
|
||||
};
|
||||
use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitable};
|
||||
use rustc_mir_dataflow::impls::MaybeStorageLive;
|
||||
use rustc_mir_dataflow::storage::always_storage_live_locals;
|
||||
use rustc_mir_dataflow::{Analysis, ResultsCursor};
|
||||
|
@ -231,6 +231,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
return true;
|
||||
}
|
||||
|
||||
// We sometimes have to use `defining_opaque_types` for subtyping
|
||||
// to succeed here and figuring out how exactly that should work
|
||||
// is annoying. It is harmless enough to just not validate anything
|
||||
// in that case. We still check this after analysis as all opque
|
||||
// types have been revealed at this point.
|
||||
if (src, dest).has_opaque_types() {
|
||||
return true;
|
||||
}
|
||||
|
||||
crate::util::is_subtype(self.tcx, self.param_env, src, dest)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// #55810: Type check patterns first so we get types for all bindings.
|
||||
let scrut_span = scrut.span.find_ancestor_inside(expr.span).unwrap_or(scrut.span);
|
||||
for arm in arms {
|
||||
self.check_pat_top(&arm.pat, scrutinee_ty, Some(scrut_span), true);
|
||||
self.check_pat_top(&arm.pat, scrutinee_ty, Some(scrut_span), Some(scrut));
|
||||
}
|
||||
|
||||
// Now typecheck the blocks.
|
||||
|
|
|
@ -90,7 +90,7 @@ pub(super) fn check_fn<'a, 'tcx>(
|
|||
for (idx, (param_ty, param)) in inputs_fn.chain(maybe_va_list).zip(body.params).enumerate() {
|
||||
// Check the pattern.
|
||||
let ty_span = try { inputs_hir?.get(idx)?.span };
|
||||
fcx.check_pat_top(¶m.pat, param_ty, ty_span, false);
|
||||
fcx.check_pat_top(¶m.pat, param_ty, ty_span, None);
|
||||
|
||||
// Check that argument is Sized.
|
||||
// The check for a non-trivial pattern is a hack to avoid duplicate warnings
|
||||
|
|
|
@ -1330,11 +1330,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
// Does the expected pattern type originate from an expression and what is the span?
|
||||
let (origin_expr, ty_span) = match (decl.ty, decl.init) {
|
||||
(Some(ty), _) => (false, Some(ty.span)), // Bias towards the explicit user type.
|
||||
(Some(ty), _) => (None, Some(ty.span)), // Bias towards the explicit user type.
|
||||
(_, Some(init)) => {
|
||||
(true, Some(init.span.find_ancestor_inside(decl.span).unwrap_or(init.span)))
|
||||
(Some(init), Some(init.span.find_ancestor_inside(decl.span).unwrap_or(init.span)))
|
||||
} // No explicit type; so use the scrutinee.
|
||||
_ => (false, None), // We have `let $pat;`, so the expected type is unconstrained.
|
||||
_ => (None, None), // We have `let $pat;`, so the expected type is unconstrained.
|
||||
};
|
||||
|
||||
// Type check the pattern. Override if necessary to avoid knock-on errors.
|
||||
|
|
|
@ -46,7 +46,7 @@ struct TopInfo<'tcx> {
|
|||
/// Was the origin of the `span` from a scrutinee expression?
|
||||
///
|
||||
/// Otherwise there is no scrutinee and it could be e.g. from the type of a formal parameter.
|
||||
origin_expr: bool,
|
||||
origin_expr: Option<&'tcx hir::Expr<'tcx>>,
|
||||
/// The span giving rise to the `expected` type, if one could be provided.
|
||||
///
|
||||
/// If `origin_expr` is `true`, then this is the span of the scrutinee as in:
|
||||
|
@ -74,7 +74,8 @@ struct TopInfo<'tcx> {
|
|||
|
||||
impl<'tcx> FnCtxt<'_, 'tcx> {
|
||||
fn pattern_cause(&self, ti: TopInfo<'tcx>, cause_span: Span) -> ObligationCause<'tcx> {
|
||||
let code = Pattern { span: ti.span, root_ty: ti.expected, origin_expr: ti.origin_expr };
|
||||
let code =
|
||||
Pattern { span: ti.span, root_ty: ti.expected, origin_expr: ti.origin_expr.is_some() };
|
||||
self.cause(cause_span, code)
|
||||
}
|
||||
|
||||
|
@ -85,7 +86,14 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
|||
actual: Ty<'tcx>,
|
||||
ti: TopInfo<'tcx>,
|
||||
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
|
||||
self.demand_eqtype_with_origin(&self.pattern_cause(ti, cause_span), expected, actual)
|
||||
let mut diag =
|
||||
self.demand_eqtype_with_origin(&self.pattern_cause(ti, cause_span), expected, actual)?;
|
||||
if let Some(expr) = ti.origin_expr {
|
||||
self.suggest_fn_call(&mut diag, expr, expected, |output| {
|
||||
self.can_eq(self.param_env, output, actual).is_ok()
|
||||
});
|
||||
}
|
||||
Some(diag)
|
||||
}
|
||||
|
||||
fn demand_eqtype_pat(
|
||||
|
@ -127,7 +135,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
pat: &'tcx Pat<'tcx>,
|
||||
expected: Ty<'tcx>,
|
||||
span: Option<Span>,
|
||||
origin_expr: bool,
|
||||
origin_expr: Option<&'tcx hir::Expr<'tcx>>,
|
||||
) {
|
||||
let info = TopInfo { expected, origin_expr, span };
|
||||
self.check_pat(pat, expected, INITIAL_BM, info);
|
||||
|
@ -2146,7 +2154,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
err.help("the semantics of slice patterns changed recently; see issue #62254");
|
||||
} else if self.autoderef(span, expected_ty)
|
||||
.any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
|
||||
&& let (Some(span), true) = (ti.span, ti.origin_expr)
|
||||
&& let Some(span) = ti.span
|
||||
&& let Some(_) = ti.origin_expr
|
||||
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
|
||||
{
|
||||
let ty = self.resolve_vars_if_possible(ti.expected);
|
||||
|
|
|
@ -19,6 +19,7 @@ use rustc_hir as hir;
|
|||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::is_range_literal;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Node};
|
||||
use rustc_hir::{Expr, HirId};
|
||||
|
@ -1349,14 +1350,41 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
} else {
|
||||
// Issue #104961, we need to add parentheses properly for compond expressions
|
||||
// for example, `x.starts_with("hi".to_string() + "you")`
|
||||
// should be `x.starts_with(&("hi".to_string() + "you"))`
|
||||
let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) else { return false; };
|
||||
let body = self.tcx.hir().body(body_id);
|
||||
let mut expr_finder = FindExprBySpan::new(span);
|
||||
expr_finder.visit_expr(body.value);
|
||||
let Some(expr) = expr_finder.result else { return false; };
|
||||
let needs_parens = match expr.kind {
|
||||
// parenthesize if needed (Issue #46756)
|
||||
hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true,
|
||||
// parenthesize borrows of range literals (Issue #54505)
|
||||
_ if is_range_literal(expr) => true,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
let is_mut = mut_ref_self_ty_satisfies_pred || ref_inner_ty_mut;
|
||||
err.span_suggestion_verbose(
|
||||
span.shrink_to_lo(),
|
||||
&format!(
|
||||
"consider{} borrowing here",
|
||||
if is_mut { " mutably" } else { "" }
|
||||
),
|
||||
format!("&{}", if is_mut { "mut " } else { "" }),
|
||||
let span = if needs_parens { span } else { span.shrink_to_lo() };
|
||||
let sugg_prefix = format!("&{}", if is_mut { "mut " } else { "" });
|
||||
let sugg_msg = &format!(
|
||||
"consider{} borrowing here",
|
||||
if is_mut { " mutably" } else { "" }
|
||||
);
|
||||
|
||||
let suggestions = if !needs_parens {
|
||||
vec![(span.shrink_to_lo(), format!("{}", sugg_prefix))]
|
||||
} else {
|
||||
vec![
|
||||
(span.shrink_to_lo(), format!("{}(", sugg_prefix)),
|
||||
(span.shrink_to_hi(), ")".to_string()),
|
||||
]
|
||||
};
|
||||
err.multipart_suggestion_verbose(
|
||||
sugg_msg,
|
||||
suggestions,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue