1
Fork 0

Auto merge of #114864 - matthiaskrgr:rollup-uw47qco, r=matthiaskrgr

Rollup of 8 pull requests

Successful merges:

 - #114588 (Improve docs for impl Default for ExitStatus)
 - #114619 (Fix pthread_attr_union layout on Wasi)
 - #114644 (Point out expectation even if we have `TypeError::RegionsInsufficientlyPolymorphic`)
 - #114668 (Deny `FnDef` in patterns)
 - #114819 (Point at return type when it influences non-first `match` arm)
 - #114826 (Fix typos)
 - #114837 (add missing feature(error_in_core))
 - #114853 (Migrate GUI colors test to original CSS color format)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-08-15 20:58:20 +00:00
commit 0bdb00d55a
58 changed files with 262 additions and 116 deletions

View file

@ -1648,7 +1648,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
hir::ExprKind::Match( hir::ExprKind::Match(
scrutinee, scrutinee,
arena_vec![self; break_arm, continue_arm], arena_vec![self; break_arm, continue_arm],
hir::MatchSource::TryDesugar, hir::MatchSource::TryDesugar(scrutinee.hir_id),
) )
} }

View file

@ -2148,7 +2148,7 @@ pub enum MatchSource {
/// A desugared `for _ in _ { .. }` loop. /// A desugared `for _ in _ { .. }` loop.
ForLoopDesugar, ForLoopDesugar,
/// A desugared `?` operator. /// A desugared `?` operator.
TryDesugar, TryDesugar(HirId),
/// A desugared `<expr>.await`. /// A desugared `<expr>.await`.
AwaitDesugar, AwaitDesugar,
/// A desugared `format_args!()`. /// A desugared `format_args!()`.
@ -2162,7 +2162,7 @@ impl MatchSource {
match self { match self {
Normal => "match", Normal => "match",
ForLoopDesugar => "for", ForLoopDesugar => "for",
TryDesugar => "?", TryDesugar(_) => "?",
AwaitDesugar => ".await", AwaitDesugar => ".await",
FormatArgs => "format_args!()", FormatArgs => "format_args!()",
} }

View file

@ -107,7 +107,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let (span, code) = match prior_arm { let (span, code) = match prior_arm {
// The reason for the first arm to fail is not that the match arms diverge, // The reason for the first arm to fail is not that the match arms diverge,
// but rather that there's a prior obligation that doesn't hold. // but rather that there's a prior obligation that doesn't hold.
None => (arm_span, ObligationCauseCode::BlockTailExpression(arm.body.hir_id)), None => {
(arm_span, ObligationCauseCode::BlockTailExpression(arm.body.hir_id, match_src))
}
Some((prior_arm_block_id, prior_arm_ty, prior_arm_span)) => ( Some((prior_arm_block_id, prior_arm_ty, prior_arm_span)) => (
expr.span, expr.span,
ObligationCauseCode::MatchExpressionArm(Box::new(MatchExpressionArmCause { ObligationCauseCode::MatchExpressionArm(Box::new(MatchExpressionArmCause {
@ -120,7 +122,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
scrut_span: scrut.span, scrut_span: scrut.span,
source: match_src, source: match_src,
prior_arms: other_arms.clone(), prior_arms: other_arms.clone(),
scrut_hir_id: scrut.hir_id,
opt_suggest_box_span, opt_suggest_box_span,
})), })),
), ),
@ -145,7 +146,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
other_arms.remove(0); other_arms.remove(0);
} }
prior_arm = Some((arm_block_id, arm_ty, arm_span)); if !arm_ty.is_never() {
// When a match arm has type `!`, then it doesn't influence the expected type for
// the following arm. If all of the prior arms are `!`, then the influence comes
// from elsewhere and we shouldn't point to any previous arm.
prior_arm = Some((arm_block_id, arm_ty, arm_span));
}
} }
// If all of the arms in the `match` diverge, // If all of the arms in the `match` diverge,

View file

@ -1603,7 +1603,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
); );
err.span_label(cause.span, "return type is not `()`"); err.span_label(cause.span, "return type is not `()`");
} }
ObligationCauseCode::BlockTailExpression(blk_id) => { ObligationCauseCode::BlockTailExpression(blk_id, ..) => {
let parent_id = fcx.tcx.hir().parent_id(blk_id); let parent_id = fcx.tcx.hir().parent_id(blk_id);
err = self.report_return_mismatched_types( err = self.report_return_mismatched_types(
cause, cause,
@ -1650,10 +1650,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
augment_error(&mut err); augment_error(&mut err);
let is_insufficiently_polymorphic = if let Some(expr) = expression {
matches!(coercion_error, TypeError::RegionsInsufficientlyPolymorphic(..));
if !is_insufficiently_polymorphic && let Some(expr) = expression {
fcx.emit_coerce_suggestions( fcx.emit_coerce_suggestions(
&mut err, &mut err,
expr, expr,
@ -1751,7 +1748,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
) && !in_external_macro(fcx.tcx.sess, cond_expr.span) ) && !in_external_macro(fcx.tcx.sess, cond_expr.span)
&& !matches!( && !matches!(
cond_expr.kind, cond_expr.kind,
hir::ExprKind::Match(.., hir::MatchSource::TryDesugar) hir::ExprKind::Match(.., hir::MatchSource::TryDesugar(_))
) )
{ {
err.span_label(cond_expr.span, "expected this to be `()`"); err.span_label(cond_expr.span, "expected this to be `()`");

View file

@ -84,6 +84,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.annotate_expected_due_to_let_ty(err, expr, error); self.annotate_expected_due_to_let_ty(err, expr, error);
// FIXME(#73154): For now, we do leak check when coercing function
// pointers in typeck, instead of only during borrowck. This can lead
// to these `RegionsInsufficientlyPolymorphic` errors that aren't helpful.
if matches!(error, Some(TypeError::RegionsInsufficientlyPolymorphic(..))) {
return;
}
if self.is_destruct_assignment_desugaring(expr) { if self.is_destruct_assignment_desugaring(expr) {
return; return;
} }
@ -263,22 +270,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let expr_ty = self.resolve_vars_if_possible(checked_ty); let expr_ty = self.resolve_vars_if_possible(checked_ty);
let mut err = self.err_ctxt().report_mismatched_types(&cause, expected, expr_ty, e); let mut err = self.err_ctxt().report_mismatched_types(&cause, expected, expr_ty, e);
let is_insufficiently_polymorphic = self.emit_coerce_suggestions(&mut err, expr, expr_ty, expected, expected_ty_expr, Some(e));
matches!(e, TypeError::RegionsInsufficientlyPolymorphic(..));
// FIXME(#73154): For now, we do leak check when coercing function
// pointers in typeck, instead of only during borrowck. This can lead
// to these `RegionsInsufficientlyPolymorphic` errors that aren't helpful.
if !is_insufficiently_polymorphic {
self.emit_coerce_suggestions(
&mut err,
expr,
expr_ty,
expected,
expected_ty_expr,
Some(e),
);
}
(expected, Some(err)) (expected, Some(err))
} }

View file

@ -1580,7 +1580,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let coerce = ctxt.coerce.as_mut().unwrap(); let coerce = ctxt.coerce.as_mut().unwrap();
if let Some((tail_expr, tail_expr_ty)) = tail_expr_ty { if let Some((tail_expr, tail_expr_ty)) = tail_expr_ty {
let span = self.get_expr_coercion_span(tail_expr); let span = self.get_expr_coercion_span(tail_expr);
let cause = self.cause(span, ObligationCauseCode::BlockTailExpression(blk.hir_id)); let cause = self.cause(
span,
ObligationCauseCode::BlockTailExpression(blk.hir_id, hir::MatchSource::Normal),
);
let ty_for_diagnostic = coerce.merged_ty(); let ty_for_diagnostic = coerce.merged_ty();
// We use coerce_inner here because we want to augment the error // We use coerce_inner here because we want to augment the error
// suggesting to wrap the block in square brackets if it might've // suggesting to wrap the block in square brackets if it might've

View file

@ -743,6 +743,35 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
ObligationCauseCode::Pattern { origin_expr: false, span: Some(span), .. } => { ObligationCauseCode::Pattern { origin_expr: false, span: Some(span), .. } => {
err.span_label(span, "expected due to this"); err.span_label(span, "expected due to this");
} }
ObligationCauseCode::BlockTailExpression(
_,
hir::MatchSource::TryDesugar(scrut_hir_id),
) => {
if let Some(ty::error::ExpectedFound { expected, .. }) = exp_found {
let scrut_expr = self.tcx.hir().expect_expr(scrut_hir_id);
let scrut_ty = if let hir::ExprKind::Call(_, args) = &scrut_expr.kind {
let arg_expr = args.first().expect("try desugaring call w/out arg");
self.typeck_results.as_ref().and_then(|typeck_results| {
typeck_results.expr_ty_opt(arg_expr)
})
} else {
bug!("try desugaring w/out call expr as scrutinee");
};
match scrut_ty {
Some(ty) if expected == ty => {
let source_map = self.tcx.sess.source_map();
err.span_suggestion(
source_map.end_point(cause.span()),
"try removing this `?`",
"",
Applicability::MachineApplicable,
);
}
_ => {}
}
}
},
ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause { ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
arm_block_id, arm_block_id,
arm_span, arm_span,
@ -752,12 +781,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
prior_arm_ty, prior_arm_ty,
source, source,
ref prior_arms, ref prior_arms,
scrut_hir_id,
opt_suggest_box_span, opt_suggest_box_span,
scrut_span, scrut_span,
.. ..
}) => match source { }) => match source {
hir::MatchSource::TryDesugar => { hir::MatchSource::TryDesugar(scrut_hir_id) => {
if let Some(ty::error::ExpectedFound { expected, .. }) = exp_found { if let Some(ty::error::ExpectedFound { expected, .. }) = exp_found {
let scrut_expr = self.tcx.hir().expect_expr(scrut_hir_id); let scrut_expr = self.tcx.hir().expect_expr(scrut_hir_id);
let scrut_ty = if let hir::ExprKind::Call(_, args) = &scrut_expr.kind { let scrut_ty = if let hir::ExprKind::Call(_, args) = &scrut_expr.kind {
@ -1927,7 +1955,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
true true
}; };
if should_suggest_fixes { // FIXME(#73154): For now, we do leak check when coercing function
// pointers in typeck, instead of only during borrowck. This can lead
// to these `RegionsInsufficientlyPolymorphic` errors that aren't helpful.
if should_suggest_fixes
&& !matches!(terr, TypeError::RegionsInsufficientlyPolymorphic(..))
{
self.suggest_tuple_pattern(cause, &exp_found, diag); self.suggest_tuple_pattern(cause, &exp_found, diag);
self.suggest_accessing_field_where_appropriate(cause, &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_await_on_expect_found(cause, span, &exp_found, diag);
@ -1973,7 +2006,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
trace: &TypeTrace<'tcx>, trace: &TypeTrace<'tcx>,
terr: TypeError<'tcx>, terr: TypeError<'tcx>,
) -> Vec<TypeErrorAdditionalDiags> { ) -> Vec<TypeErrorAdditionalDiags> {
use crate::traits::ObligationCauseCode::MatchExpressionArm; use crate::traits::ObligationCauseCode::{BlockTailExpression, MatchExpressionArm};
let mut suggestions = Vec::new(); let mut suggestions = Vec::new();
let span = trace.cause.span(); let span = trace.cause.span();
let values = self.resolve_vars_if_possible(trace.values); let values = self.resolve_vars_if_possible(trace.values);
@ -1991,11 +2024,17 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
// specify a byte literal // specify a byte literal
(ty::Uint(ty::UintTy::U8), ty::Char) => { (ty::Uint(ty::UintTy::U8), ty::Char) => {
if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span) if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span)
&& let Some(code) = code.strip_prefix('\'').and_then(|s| s.strip_suffix('\'')) && let Some(code) =
&& !code.starts_with("\\u") // forbid all Unicode escapes code.strip_prefix('\'').and_then(|s| s.strip_suffix('\''))
&& code.chars().next().is_some_and(|c| c.is_ascii()) // forbids literal Unicode characters beyond ASCII // forbid all Unicode escapes
&& !code.starts_with("\\u")
// forbids literal Unicode characters beyond ASCII
&& code.chars().next().is_some_and(|c| c.is_ascii())
{ {
suggestions.push(TypeErrorAdditionalDiags::MeantByteLiteral { span, code: escape_literal(code) }) suggestions.push(TypeErrorAdditionalDiags::MeantByteLiteral {
span,
code: escape_literal(code),
})
} }
} }
// If a character was expected and the found expression is a string literal // If a character was expected and the found expression is a string literal
@ -2006,7 +2045,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
&& let Some(code) = code.strip_prefix('"').and_then(|s| s.strip_suffix('"')) && let Some(code) = code.strip_prefix('"').and_then(|s| s.strip_suffix('"'))
&& code.chars().count() == 1 && code.chars().count() == 1
{ {
suggestions.push(TypeErrorAdditionalDiags::MeantCharLiteral { span, code: escape_literal(code) }) suggestions.push(TypeErrorAdditionalDiags::MeantCharLiteral {
span,
code: escape_literal(code),
})
} }
} }
// If a string was expected and the found expression is a character literal, // If a string was expected and the found expression is a character literal,
@ -2016,7 +2058,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
if let Some(code) = if let Some(code) =
code.strip_prefix('\'').and_then(|s| s.strip_suffix('\'')) code.strip_prefix('\'').and_then(|s| s.strip_suffix('\''))
{ {
suggestions.push(TypeErrorAdditionalDiags::MeantStrLiteral { span, code: escape_literal(code) }) suggestions.push(TypeErrorAdditionalDiags::MeantStrLiteral {
span,
code: escape_literal(code),
})
} }
} }
} }
@ -2025,17 +2070,24 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
(ty::Bool, ty::Tuple(list)) => if list.len() == 0 { (ty::Bool, ty::Tuple(list)) => if list.len() == 0 {
suggestions.extend(self.suggest_let_for_letchains(&trace.cause, span)); suggestions.extend(self.suggest_let_for_letchains(&trace.cause, span));
} }
(ty::Array(_, _), ty::Array(_, _)) => suggestions.extend(self.suggest_specify_actual_length(terr, trace, span)), (ty::Array(_, _), ty::Array(_, _)) => {
suggestions.extend(self.suggest_specify_actual_length(terr, trace, span))
}
_ => {} _ => {}
} }
} }
let code = trace.cause.code(); let code = trace.cause.code();
if let &MatchExpressionArm(box MatchExpressionArmCause { source, .. }) = code if let &(MatchExpressionArm(box MatchExpressionArmCause { source, .. })
&& let hir::MatchSource::TryDesugar = source | BlockTailExpression(.., source)
&& let Some((expected_ty, found_ty, _, _)) = self.values_str(trace.values) ) = code
{ && let hir::MatchSource::TryDesugar(_) = source
suggestions.push(TypeErrorAdditionalDiags::TryCannotConvert { found: found_ty.content(), expected: expected_ty.content() }); && let Some((expected_ty, found_ty, _, _)) = self.values_str(trace.values)
} {
suggestions.push(TypeErrorAdditionalDiags::TryCannotConvert {
found: found_ty.content(),
expected: expected_ty.content(),
});
}
suggestions suggestions
} }
@ -2905,8 +2957,11 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> {
CompareImplItemObligation { kind: ty::AssocKind::Const, .. } => { CompareImplItemObligation { kind: ty::AssocKind::Const, .. } => {
ObligationCauseFailureCode::ConstCompat { span, subdiags } ObligationCauseFailureCode::ConstCompat { span, subdiags }
} }
BlockTailExpression(.., hir::MatchSource::TryDesugar(_)) => {
ObligationCauseFailureCode::TryCompat { span, subdiags }
}
MatchExpressionArm(box MatchExpressionArmCause { source, .. }) => match source { MatchExpressionArm(box MatchExpressionArmCause { source, .. }) => match source {
hir::MatchSource::TryDesugar => { hir::MatchSource::TryDesugar(_) => {
ObligationCauseFailureCode::TryCompat { span, subdiags } ObligationCauseFailureCode::TryCompat { span, subdiags }
} }
_ => ObligationCauseFailureCode::MatchCompat { span, subdiags }, _ => ObligationCauseFailureCode::MatchCompat { span, subdiags },

View file

@ -146,7 +146,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = sub_origin { if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = sub_origin {
if let ObligationCauseCode::ReturnValue(hir_id) if let ObligationCauseCode::ReturnValue(hir_id)
| ObligationCauseCode::BlockTailExpression(hir_id) = cause.code() | ObligationCauseCode::BlockTailExpression(hir_id, ..) = cause.code()
{ {
let parent_id = tcx.hir().get_parent_item(*hir_id); let parent_id = tcx.hir().get_parent_item(*hir_id);
if let Some(fn_decl) = tcx.hir().fn_decl_by_hir_id(parent_id.into()) { if let Some(fn_decl) = tcx.hir().fn_decl_by_hir_id(parent_id.into()) {

View file

@ -346,6 +346,7 @@ pub enum ExprKind<'tcx> {
/// A `match` expression. /// A `match` expression.
Match { Match {
scrutinee: ExprId, scrutinee: ExprId,
scrutinee_hir_id: hir::HirId,
arms: Box<[ArmId]>, arms: Box<[ArmId]>,
}, },
/// A block. /// A block.

View file

@ -70,7 +70,7 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp
visitor.visit_expr(&visitor.thir()[expr]); visitor.visit_expr(&visitor.thir()[expr]);
} }
Loop { body } => visitor.visit_expr(&visitor.thir()[body]), Loop { body } => visitor.visit_expr(&visitor.thir()[body]),
Match { scrutinee, ref arms } => { Match { scrutinee, ref arms, .. } => {
visitor.visit_expr(&visitor.thir()[scrutinee]); visitor.visit_expr(&visitor.thir()[scrutinee]);
for &arm in &**arms { for &arm in &**arms {
visitor.visit_arm(&visitor.thir()[arm]); visitor.visit_arm(&visitor.thir()[arm]);

View file

@ -402,7 +402,7 @@ pub enum ObligationCauseCode<'tcx> {
OpaqueReturnType(Option<(Ty<'tcx>, Span)>), OpaqueReturnType(Option<(Ty<'tcx>, Span)>),
/// Block implicit return /// Block implicit return
BlockTailExpression(hir::HirId), BlockTailExpression(hir::HirId, hir::MatchSource),
/// #[feature(trivial_bounds)] is not enabled /// #[feature(trivial_bounds)] is not enabled
TrivialBound, TrivialBound,
@ -543,7 +543,6 @@ pub struct MatchExpressionArmCause<'tcx> {
pub scrut_span: Span, pub scrut_span: Span,
pub source: hir::MatchSource, pub source: hir::MatchSource,
pub prior_arms: Vec<Span>, pub prior_arms: Vec<Span>,
pub scrut_hir_id: hir::HirId,
pub opt_suggest_box_span: Option<Span>, pub opt_suggest_box_span: Option<Span>,
} }

View file

@ -65,7 +65,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
let target = self.parse_block(args[1])?; let target = self.parse_block(args[1])?;
self.parse_call(args[2], destination, target) self.parse_call(args[2], destination, target)
}, },
ExprKind::Match { scrutinee, arms } => { ExprKind::Match { scrutinee, arms, .. } => {
let discr = self.parse_operand(*scrutinee)?; let discr = self.parse_operand(*scrutinee)?;
self.parse_match(arms, expr.span).map(|t| TerminatorKind::SwitchInt { discr, targets: t }) self.parse_match(arms, expr.span).map(|t| TerminatorKind::SwitchInt { discr, targets: t })
}, },

View file

@ -47,7 +47,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
ExprKind::Block { block: ast_block } => { ExprKind::Block { block: ast_block } => {
this.ast_block(destination, block, ast_block, source_info) this.ast_block(destination, block, ast_block, source_info)
} }
ExprKind::Match { scrutinee, ref arms } => { ExprKind::Match { scrutinee, ref arms, .. } => {
this.match_expr(destination, expr_span, block, &this.thir[scrutinee], arms) this.match_expr(destination, expr_span, block, &this.thir[scrutinee], arms)
} }
ExprKind::If { cond, then, else_opt, if_then_scope } => { ExprKind::If { cond, then, else_opt, if_then_scope } => {

View file

@ -732,6 +732,7 @@ impl<'tcx> Cx<'tcx> {
}, },
hir::ExprKind::Match(ref discr, ref arms, _) => ExprKind::Match { hir::ExprKind::Match(ref discr, ref arms, _) => ExprKind::Match {
scrutinee: self.mirror_expr(discr), scrutinee: self.mirror_expr(discr),
scrutinee_hir_id: discr.hir_id,
arms: arms.iter().map(|a| self.convert_arm(a)).collect(), arms: arms.iter().map(|a| self.convert_arm(a)).collect(),
}, },
hir::ExprKind::Loop(ref body, ..) => { hir::ExprKind::Loop(ref body, ..) => {

View file

@ -135,10 +135,12 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for MatchVisitor<'a, '_, 'tcx> {
}); });
return; return;
} }
ExprKind::Match { scrutinee, box ref arms } => { ExprKind::Match { scrutinee, scrutinee_hir_id, box ref arms } => {
let source = match ex.span.desugaring_kind() { let source = match ex.span.desugaring_kind() {
Some(DesugaringKind::ForLoop) => hir::MatchSource::ForLoopDesugar, Some(DesugaringKind::ForLoop) => hir::MatchSource::ForLoopDesugar,
Some(DesugaringKind::QuestionMark) => hir::MatchSource::TryDesugar, Some(DesugaringKind::QuestionMark) => {
hir::MatchSource::TryDesugar(scrutinee_hir_id)
}
Some(DesugaringKind::Await) => hir::MatchSource::AwaitDesugar, Some(DesugaringKind::Await) => hir::MatchSource::AwaitDesugar,
_ => hir::MatchSource::Normal, _ => hir::MatchSource::Normal,
}; };
@ -277,7 +279,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
| hir::MatchSource::FormatArgs => report_arm_reachability(&cx, &report), | hir::MatchSource::FormatArgs => report_arm_reachability(&cx, &report),
// Unreachable patterns in try and await expressions occur when one of // Unreachable patterns in try and await expressions occur when one of
// the arms are an uninhabited type. Which is OK. // the arms are an uninhabited type. Which is OK.
hir::MatchSource::AwaitDesugar | hir::MatchSource::TryDesugar => {} hir::MatchSource::AwaitDesugar | hir::MatchSource::TryDesugar(_) => {}
} }
// Check if the match is exhaustive. // Check if the match is exhaustive.

View file

@ -325,6 +325,11 @@ impl<'tcx> ConstToPat<'tcx> {
// `PartialEq::eq` on it. // `PartialEq::eq` on it.
return Err(FallbackToConstRef); return Err(FallbackToConstRef);
} }
ty::FnDef(..) => {
self.saw_const_match_error.set(true);
tcx.sess.emit_err(InvalidPattern { span, non_sm_ty: ty });
PatKind::Wild
}
ty::Adt(adt_def, _) if !self.type_marked_structural(ty) => { ty::Adt(adt_def, _) if !self.type_marked_structural(ty) => {
debug!("adt_def {:?} has !type_marked_structural for cv.ty: {:?}", adt_def, ty,); debug!("adt_def {:?} has !type_marked_structural for cv.ty: {:?}", adt_def, ty,);
self.saw_const_match_error.set(true); self.saw_const_match_error.set(true);
@ -440,7 +445,7 @@ impl<'tcx> ConstToPat<'tcx> {
} }
} }
}, },
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::FnDef(..) => PatKind::Constant { ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) => PatKind::Constant {
value: mir::ConstantKind::Ty(ty::Const::new_value(tcx, cv, ty)), value: mir::ConstantKind::Ty(ty::Const::new_value(tcx, cv, ty)),
}, },
ty::FnPtr(..) | ty::RawPtr(..) => unreachable!(), ty::FnPtr(..) | ty::RawPtr(..) => unreachable!(),

View file

@ -321,7 +321,7 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
print_indented!(self, format!("pat: {:?}", pat), depth_lvl + 1); print_indented!(self, format!("pat: {:?}", pat), depth_lvl + 1);
print_indented!(self, "}", depth_lvl); print_indented!(self, "}", depth_lvl);
} }
Match { scrutinee, arms } => { Match { scrutinee, arms, .. } => {
print_indented!(self, "Match {", depth_lvl); print_indented!(self, "Match {", depth_lvl);
print_indented!(self, "scrutinee:", depth_lvl + 1); print_indented!(self, "scrutinee:", depth_lvl + 1);
self.print_expr(*scrutinee, depth_lvl + 2); self.print_expr(*scrutinee, depth_lvl + 2);

View file

@ -45,7 +45,7 @@ impl NonConstExpr {
Self::Loop(ForLoop) | Self::Match(ForLoopDesugar) => &[sym::const_for], Self::Loop(ForLoop) | Self::Match(ForLoopDesugar) => &[sym::const_for],
Self::Match(TryDesugar) => &[sym::const_try], Self::Match(TryDesugar(_)) => &[sym::const_try],
// All other expressions are allowed. // All other expressions are allowed.
Self::Loop(Loop | While) | Self::Match(Normal | FormatArgs) => &[], Self::Loop(Loop | While) | Self::Match(Normal | FormatArgs) => &[],

View file

@ -2700,7 +2700,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
| ObligationCauseCode::MatchImpl(..) | ObligationCauseCode::MatchImpl(..)
| ObligationCauseCode::ReturnType | ObligationCauseCode::ReturnType
| ObligationCauseCode::ReturnValue(_) | ObligationCauseCode::ReturnValue(_)
| ObligationCauseCode::BlockTailExpression(_) | ObligationCauseCode::BlockTailExpression(..)
| ObligationCauseCode::AwaitableExpr(_) | ObligationCauseCode::AwaitableExpr(_)
| ObligationCauseCode::ForLoopIterator | ObligationCauseCode::ForLoopIterator
| ObligationCauseCode::QuestionMark | ObligationCauseCode::QuestionMark

View file

@ -130,6 +130,7 @@ pub trait Error: Debug + Display {
/// ///
/// ```rust /// ```rust
/// #![feature(error_generic_member_access)] /// #![feature(error_generic_member_access)]
/// #![feature(error_in_core)]
/// use core::fmt; /// use core::fmt;
/// use core::error::{request_ref, Request}; /// use core::error::{request_ref, Request};
/// ///
@ -360,6 +361,7 @@ impl dyn Error {
/// ///
/// ```rust /// ```rust
/// # #![feature(error_generic_member_access)] /// # #![feature(error_generic_member_access)]
/// # #![feature(error_in_core)]
/// use std::error::Error; /// use std::error::Error;
/// use core::error::request_value; /// use core::error::request_value;
/// ///
@ -383,6 +385,7 @@ where
/// ///
/// ```rust /// ```rust
/// # #![feature(error_generic_member_access)] /// # #![feature(error_generic_member_access)]
/// # #![feature(error_in_core)]
/// use core::error::Error; /// use core::error::Error;
/// use core::error::request_ref; /// use core::error::request_ref;
/// ///
@ -454,6 +457,7 @@ where
/// ///
/// ``` /// ```
/// #![feature(error_generic_member_access)] /// #![feature(error_generic_member_access)]
/// #![feature(error_in_core)]
/// use core::fmt; /// use core::fmt;
/// use core::error::Request; /// use core::error::Request;
/// use core::error::request_ref; /// use core::error::request_ref;
@ -524,6 +528,7 @@ impl<'a> Request<'a> {
/// ///
/// ```rust /// ```rust
/// #![feature(error_generic_member_access)] /// #![feature(error_generic_member_access)]
/// #![feature(error_in_core)]
/// ///
/// use core::error::Request; /// use core::error::Request;
/// ///
@ -558,6 +563,7 @@ impl<'a> Request<'a> {
/// ///
/// ```rust /// ```rust
/// #![feature(error_generic_member_access)] /// #![feature(error_generic_member_access)]
/// #![feature(error_in_core)]
/// ///
/// use core::error::Request; /// use core::error::Request;
/// ///
@ -593,6 +599,7 @@ impl<'a> Request<'a> {
/// ///
/// ```rust /// ```rust
/// #![feature(error_generic_member_access)] /// #![feature(error_generic_member_access)]
/// #![feature(error_in_core)]
/// ///
/// use core::error::Request; /// use core::error::Request;
/// ///
@ -625,6 +632,7 @@ impl<'a> Request<'a> {
/// ///
/// ```rust /// ```rust
/// #![feature(error_generic_member_access)] /// #![feature(error_generic_member_access)]
/// #![feature(error_in_core)]
/// ///
/// use core::error::Request; /// use core::error::Request;
/// ///
@ -691,6 +699,7 @@ impl<'a> Request<'a> {
/// ///
/// ```rust /// ```rust
/// #![feature(error_generic_member_access)] /// #![feature(error_generic_member_access)]
/// #![feature(error_in_core)]
/// ///
/// use core::error::Request; /// use core::error::Request;
/// use core::error::request_value; /// use core::error::request_value;
@ -778,6 +787,7 @@ impl<'a> Request<'a> {
/// ///
/// ```rust /// ```rust
/// #![feature(error_generic_member_access)] /// #![feature(error_generic_member_access)]
/// #![feature(error_in_core)]
/// ///
/// use core::error::Request; /// use core::error::Request;
/// use core::error::request_ref; /// use core::error::request_ref;

View file

@ -1530,10 +1530,19 @@ impl From<fs::File> for Stdio {
// vs `_exit`. Naming of Unix system calls is not standardised across Unices, so terminology is a // vs `_exit`. Naming of Unix system calls is not standardised across Unices, so terminology is a
// matter of convention and tradition. For clarity we usually speak of `exit`, even when we might // matter of convention and tradition. For clarity we usually speak of `exit`, even when we might
// mean an underlying system call such as `_exit`. // mean an underlying system call such as `_exit`.
#[derive(PartialEq, Eq, Clone, Copy, Debug, Default)] #[derive(PartialEq, Eq, Clone, Copy, Debug)]
#[stable(feature = "process", since = "1.0.0")] #[stable(feature = "process", since = "1.0.0")]
pub struct ExitStatus(imp::ExitStatus); pub struct ExitStatus(imp::ExitStatus);
/// The default value is one which indicates successful completion.
#[stable(feature = "process-exitcode-default", since = "CURRENT_RUSTC_VERSION")]
impl Default for ExitStatus {
fn default() -> Self {
// Ideally this would be done by ExitCode::default().into() but that is complicated.
ExitStatus::from_inner(imp::ExitStatus::default())
}
}
/// Allows extension traits within `std`. /// Allows extension traits within `std`.
#[unstable(feature = "sealed", issue = "none")] #[unstable(feature = "sealed", issue = "none")]
impl crate::sealed::Sealed for ExitStatus {} impl crate::sealed::Sealed for ExitStatus {}

View file

@ -20,9 +20,9 @@ cfg_if::cfg_if! {
// https://github.com/WebAssembly/wasi-libc/blob/a6f871343313220b76009827ed0153586361c0d5/libc-top-half/musl/include/alltypes.h.in#L108 // https://github.com/WebAssembly/wasi-libc/blob/a6f871343313220b76009827ed0153586361c0d5/libc-top-half/musl/include/alltypes.h.in#L108
#[repr(C)] #[repr(C)]
union pthread_attr_union { union pthread_attr_union {
__i: [ffi::c_int; if mem::size_of::<ffi::c_int>() == 8 { 14 } else { 9 }], __i: [ffi::c_int; if mem::size_of::<ffi::c_long>() == 8 { 14 } else { 9 }],
__vi: [ffi::c_int; if mem::size_of::<ffi::c_int>() == 8 { 14 } else { 9 }], __vi: [ffi::c_int; if mem::size_of::<ffi::c_long>() == 8 { 14 } else { 9 }],
__s: [ffi::c_ulong; if mem::size_of::<ffi::c_int>() == 8 { 7 } else { 9 }], __s: [ffi::c_ulong; if mem::size_of::<ffi::c_long>() == 8 { 7 } else { 9 }],
} }
#[repr(C)] #[repr(C)]

View file

@ -584,7 +584,7 @@ See the [Symbol Mangling] chapter for details on symbol mangling and the manglin
This instructs `rustc` to generate code specifically for a particular processor. This instructs `rustc` to generate code specifically for a particular processor.
You can run `rustc --print target-cpus` to see the valid options to pass You can run `rustc --print target-cpus` to see the valid options to pass
and the default target CPU for the current buid target. and the default target CPU for the current build target.
Each target has a default base CPU. Special values include: Each target has a default base CPU. Special values include:
* `native` can be passed to use the processor of the host machine. * `native` can be passed to use the processor of the host machine.

View file

@ -10,7 +10,7 @@ It's very small that there is no RwLock, no network, no stdin, and no file syste
Some abbreviation: Some abbreviation:
| Abbreviation | The full text | Description | | Abbreviation | The full text | Description |
| ---- | ---- | ---- | | ---- | ---- | ---- |
| TEE | Trusted Execution Environment | ARM TrustZone devide the system into two worlds/modes -- the secure world/mode and the normal world/mode. TEE is in the secure world/mode. | | TEE | Trusted Execution Environment | ARM TrustZone divides the system into two worlds/modes -- the secure world/mode and the normal world/mode. TEE is in the secure world/mode. |
| REE | Rich Execution Environment | The normal world. for example, Linux for Android phone is in REE side. | | REE | Rich Execution Environment | The normal world. for example, Linux for Android phone is in REE side. |
| TA | Trusted Application | The app run in TEE side system. | | TA | Trusted Application | The app run in TEE side system. |
| CA | Client Application | The progress run in REE side system. | | CA | Client Application | The progress run in REE side system. |

View file

@ -71,7 +71,7 @@ CXX_loongarch64_unknown_linux_gnu=/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-
AR_loongarch64_unknown_linux_gnu=/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-gcc-ar \ AR_loongarch64_unknown_linux_gnu=/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-gcc-ar \
CARGO_TARGET_LOONGARCH64_UNKNOWN_LINUX_GNUN_LINKER=/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-gcc \ CARGO_TARGET_LOONGARCH64_UNKNOWN_LINUX_GNUN_LINKER=/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-gcc \
# SET TARGET SYSTEM LIBRARY PATH # SET TARGET SYSTEM LIBRARY PATH
CARGO_TARGET_LOONGARCH64_UNKNOWN_LINUX_GNUN_RUNNER="qemu-loongarch64 -L /TOOLCHAIN_PATH/TARGET_LIBRAY_PATH" \ CARGO_TARGET_LOONGARCH64_UNKNOWN_LINUX_GNUN_RUNNER="qemu-loongarch64 -L /TOOLCHAIN_PATH/TARGET_LIBRARY_PATH" \
cargo run --target loongarch64-unknown-linux-gnu --release cargo run --target loongarch64-unknown-linux-gnu --release
``` ```
Tested on x86 architecture, other architectures not tested. Tested on x86 architecture, other architectures not tested.

View file

@ -86,7 +86,7 @@ The Rust testsuite could presumably be run natively.
For the systems where the maintainer can build natively, the rust For the systems where the maintainer can build natively, the rust
compiler itself is re-built natively. This involves the rust compiler compiler itself is re-built natively. This involves the rust compiler
being re-built with the newly self-built rust compiler, so excercises being re-built with the newly self-built rust compiler, so exercises
the result quite extensively. the result quite extensively.
Additionally, for some systems we build `librsvg`, and for the more Additionally, for some systems we build `librsvg`, and for the more

View file

@ -20,7 +20,7 @@ will fail to load on machines that do not support this.
It should support the full standard library (`std` and `alloc` either with It should support the full standard library (`std` and `alloc` either with
default or user-defined allocators). This target is probably most useful when default or user-defined allocators). This target is probably most useful when
targetted via cross-compilation (including from `x86_64-apple-darwin`), but if targeted via cross-compilation (including from `x86_64-apple-darwin`), but if
built manually, the host tools work. built manually, the host tools work.
It is similar to `x86_64-apple-darwin` in nearly all respects, although the It is similar to `x86_64-apple-darwin` in nearly all respects, although the
@ -49,7 +49,7 @@ suite seems to work.
Cross-compilation to this target from Apple hosts should generally work without Cross-compilation to this target from Apple hosts should generally work without
much configuration, so long as XCode and the CommandLineTools are installed. much configuration, so long as XCode and the CommandLineTools are installed.
Targetting it from non-Apple hosts is difficult, but no moreso than targetting Targeting it from non-Apple hosts is difficult, but no more so than targeting
`x86_64-apple-darwin`. `x86_64-apple-darwin`.
When compiling C code for this target, either the "`x86_64h-apple-macosx*`" LLVM When compiling C code for this target, either the "`x86_64h-apple-macosx*`" LLVM

View file

@ -1,6 +1,6 @@
# `--print` Options # `--print` Options
The behavior of the `--print` flag can be modified by optionally be specifiying a filepath The behavior of the `--print` flag can be modified by optionally be specifying a filepath
for each requested information kind, in the format `--print KIND=PATH`, just like for for each requested information kind, in the format `--print KIND=PATH`, just like for
`--emit`. When a path is specified, information will be written there instead of to stdout. `--emit`. When a path is specified, information will be written there instead of to stdout.

View file

@ -802,7 +802,8 @@ fn in_postfix_position<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> boo
match parent.kind { match parent.kind {
ExprKind::Call(child, _) | ExprKind::MethodCall(_, child, _, _) | ExprKind::Index(child, _, _) ExprKind::Call(child, _) | ExprKind::MethodCall(_, child, _, _) | ExprKind::Index(child, _, _)
if child.hir_id == e.hir_id => true, if child.hir_id == e.hir_id => true,
ExprKind::Field(_, _) | ExprKind::Match(_, _, MatchSource::TryDesugar | MatchSource::AwaitDesugar) => true, ExprKind::Match(.., MatchSource::TryDesugar(_) | MatchSource::AwaitDesugar)
| ExprKind::Field(_, _) => true,
_ => false, _ => false,
} }
} else { } else {

View file

@ -1038,7 +1038,7 @@ impl<'tcx> LateLintPass<'tcx> for Matches {
wild_in_or_pats::check(cx, arms); wild_in_or_pats::check(cx, arms);
} }
if source == MatchSource::TryDesugar { if let MatchSource::TryDesugar(_) = source {
try_err::check(cx, expr, ex); try_err::check(cx, expr, ex);
} }

View file

@ -80,7 +80,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, scrutine
/// Finds function return type by examining return expressions in match arms. /// Finds function return type by examining return expressions in match arms.
fn find_return_type<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx ExprKind<'_>) -> Option<Ty<'tcx>> { fn find_return_type<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx ExprKind<'_>) -> Option<Ty<'tcx>> {
if let ExprKind::Match(_, arms, MatchSource::TryDesugar) = expr { if let ExprKind::Match(_, arms, MatchSource::TryDesugar(_)) = expr {
for arm in *arms { for arm in *arms {
if let ExprKind::Ret(Some(ret)) = arm.body.kind { if let ExprKind::Ret(Some(ret)) = arm.body.kind {
return Some(cx.typeck_results().expr_ty(ret)); return Some(cx.typeck_results().expr_ty(ret));

View file

@ -64,7 +64,7 @@ pub(super) fn check(
ExprKind::Path(QPath::LangItem(rustc_hir::LangItem::TryTraitBranch, _, _)) ExprKind::Path(QPath::LangItem(rustc_hir::LangItem::TryTraitBranch, _, _))
), ),
ExprKind::MethodCall(_, self_arg, ..) if expr.hir_id == self_arg.hir_id => true, ExprKind::MethodCall(_, self_arg, ..) if expr.hir_id == self_arg.hir_id => true,
ExprKind::Match(_, _, MatchSource::TryDesugar | MatchSource::AwaitDesugar) ExprKind::Match(_, _, MatchSource::TryDesugar(_) | MatchSource::AwaitDesugar)
| ExprKind::Field(..) | ExprKind::Field(..)
| ExprKind::Index(..) => true, | ExprKind::Index(..) => true,
_ => false, _ => false,

View file

@ -236,7 +236,7 @@ fn indirect_usage<'tcx>(
!matches!( !matches!(
node, node,
Node::Expr(Expr { Node::Expr(Expr {
kind: ExprKind::Match(.., MatchSource::TryDesugar), kind: ExprKind::Match(.., MatchSource::TryDesugar(_)),
.. ..
}) })
) )

View file

@ -122,7 +122,7 @@ fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
} else { } else {
return; return;
}; };
if let ExprKind::Match(inner_expr_with_q, _, MatchSource::TryDesugar) = &arg.kind; if let ExprKind::Match(inner_expr_with_q, _, MatchSource::TryDesugar(_)) = &arg.kind;
if let ExprKind::Call(called, [inner_expr]) = &inner_expr_with_q.kind; if let ExprKind::Call(called, [inner_expr]) = &inner_expr_with_q.kind;
if let ExprKind::Path(QPath::LangItem(LangItem::TryTraitBranch, ..)) = &called.kind; if let ExprKind::Path(QPath::LangItem(LangItem::TryTraitBranch, ..)) = &called.kind;
if expr.span.ctxt() == inner_expr.span.ctxt(); if expr.span.ctxt() == inner_expr.span.ctxt();

View file

@ -34,7 +34,7 @@ declare_lint_pass!(QuestionMarkUsed => [QUESTION_MARK_USED]);
impl<'tcx> LateLintPass<'tcx> for QuestionMarkUsed { impl<'tcx> LateLintPass<'tcx> for QuestionMarkUsed {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
if let ExprKind::Match(_, _, MatchSource::TryDesugar) = expr.kind { if let ExprKind::Match(_, _, MatchSource::TryDesugar(_)) = expr.kind {
if !span_is_local(expr.span) { if !span_is_local(expr.span) {
return; return;
} }

View file

@ -52,7 +52,7 @@ impl ReturnVisitor {
impl<'tcx> Visitor<'tcx> for ReturnVisitor { impl<'tcx> Visitor<'tcx> for ReturnVisitor {
fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) { fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
if let hir::ExprKind::Ret(_) | hir::ExprKind::Match(.., hir::MatchSource::TryDesugar) = ex.kind { if let hir::ExprKind::Ret(_) | hir::ExprKind::Match(.., hir::MatchSource::TryDesugar(_)) = ex.kind {
self.found_return = true; self.found_return = true;
} else { } else {
hir_visit::walk_expr(self, ex); hir_visit::walk_expr(self, ex);

View file

@ -164,7 +164,7 @@ impl<'tcx> LateLintPass<'tcx> for Return {
if !in_external_macro(cx.sess(), stmt.span) if !in_external_macro(cx.sess(), stmt.span)
&& let StmtKind::Semi(expr) = stmt.kind && let StmtKind::Semi(expr) = stmt.kind
&& let ExprKind::Ret(Some(ret)) = expr.kind && let ExprKind::Ret(Some(ret)) = expr.kind
&& let ExprKind::Match(.., MatchSource::TryDesugar) = ret.kind && let ExprKind::Match(.., MatchSource::TryDesugar(_)) = ret.kind
// Ensure this is not the final stmt, otherwise removing it would cause a compile error // Ensure this is not the final stmt, otherwise removing it would cause a compile error
&& let OwnerNode::Item(item) = cx.tcx.hir().owner(cx.tcx.hir().get_parent_item(expr.hir_id)) && let OwnerNode::Item(item) = cx.tcx.hir().owner(cx.tcx.hir().get_parent_item(expr.hir_id))
&& let ItemKind::Fn(_, _, body) = item.kind && let ItemKind::Fn(_, _, body) = item.kind

View file

@ -42,7 +42,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
if cx.typeck_results().expr_ty(arg).is_unit() && !utils::is_unit_literal(arg) { if cx.typeck_results().expr_ty(arg).is_unit() && !utils::is_unit_literal(arg) {
!matches!( !matches!(
&arg.kind, &arg.kind,
ExprKind::Match(.., MatchSource::TryDesugar) | ExprKind::Path(..) ExprKind::Match(.., MatchSource::TryDesugar(_)) | ExprKind::Path(..)
) )
} else { } else {
false false

View file

@ -113,7 +113,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
} }
match e.kind { match e.kind {
ExprKind::Match(_, arms, MatchSource::TryDesugar) => { ExprKind::Match(_, arms, MatchSource::TryDesugar(_)) => {
let (ExprKind::Ret(Some(e)) | ExprKind::Break(_, Some(e))) = arms[0].body.kind else { let (ExprKind::Ret(Some(e)) | ExprKind::Break(_, Some(e))) = arms[0].body.kind else {
return; return;
}; };

View file

@ -149,7 +149,7 @@ fn expr_search_pat(tcx: TyCtxt<'_>, e: &Expr<'_>) -> (Pat, Pat) {
(Pat::Str("for"), Pat::Str("}")) (Pat::Str("for"), Pat::Str("}"))
}, },
ExprKind::Match(_, _, MatchSource::Normal) => (Pat::Str("match"), Pat::Str("}")), ExprKind::Match(_, _, MatchSource::Normal) => (Pat::Str("match"), Pat::Str("}")),
ExprKind::Match(e, _, MatchSource::TryDesugar) => (expr_search_pat(tcx, e).0, Pat::Str("?")), ExprKind::Match(e, _, MatchSource::TryDesugar(_)) => (expr_search_pat(tcx, e).0, Pat::Str("?")),
ExprKind::Match(e, _, MatchSource::AwaitDesugar) | ExprKind::Yield(e, YieldSource::Await { .. }) => { ExprKind::Match(e, _, MatchSource::AwaitDesugar) | ExprKind::Yield(e, YieldSource::Await { .. }) => {
(expr_search_pat(tcx, e).0, Pat::Str("await")) (expr_search_pat(tcx, e).0, Pat::Str("await"))
}, },

View file

@ -1765,7 +1765,7 @@ pub fn is_try<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'tcx>) -> Option<&'tc
if let ExprKind::Match(_, arms, ref source) = expr.kind { if let ExprKind::Match(_, arms, ref source) = expr.kind {
// desugared from a `?` operator // desugared from a `?` operator
if *source == MatchSource::TryDesugar { if let MatchSource::TryDesugar(_) = *source {
return Some(expr); return Some(expr);
} }

View file

@ -161,7 +161,7 @@ pub fn for_each_expr_with_closures<'tcx, B, C: Continue>(
/// returns `true` if expr contains match expr desugared from try /// returns `true` if expr contains match expr desugared from try
fn contains_try(expr: &hir::Expr<'_>) -> bool { fn contains_try(expr: &hir::Expr<'_>) -> bool {
for_each_expr(expr, |e| { for_each_expr(expr, |e| {
if matches!(e.kind, hir::ExprKind::Match(_, _, hir::MatchSource::TryDesugar)) { if matches!(e.kind, hir::ExprKind::Match(_, _, hir::MatchSource::TryDesugar(_))) {
ControlFlow::Break(()) ControlFlow::Break(())
} else { } else {
ControlFlow::Continue(()) ControlFlow::Continue(())

View file

@ -98,7 +98,7 @@ fn if_same_then_else2() -> Result<&'static str, ()> {
}; };
if true { if true {
//~^ ERROR: this `if` has identical blocks // FIXME: should emit "this `if` has identical blocks"
Ok("foo")?; Ok("foo")?;
} else { } else {
Ok("foo")?; Ok("foo")?;

View file

@ -82,25 +82,6 @@ LL | | f32::NAN
LL | | }; LL | | };
| |_____^ | |_____^
error: this `if` has identical blocks
--> $DIR/if_same_then_else2.rs:100:13
|
LL | if true {
| _____________^
LL | |
LL | | Ok("foo")?;
LL | | } else {
| |_____^
|
note: same as this
--> $DIR/if_same_then_else2.rs:103:12
|
LL | } else {
| ____________^
LL | | Ok("foo")?;
LL | | }
| |_____^
error: this `if` has identical blocks error: this `if` has identical blocks
--> $DIR/if_same_then_else2.rs:124:20 --> $DIR/if_same_then_else2.rs:124:20
| |
@ -122,5 +103,5 @@ LL | | return Ok(&foo[0..]);
LL | | } LL | | }
| |_____^ | |_____^
error: aborting due to 6 previous errors error: aborting due to 5 previous errors

View file

@ -23,6 +23,6 @@ define-function: (
}, },
) )
call-function: ("sup-check", ("dark", "rgb(221, 221, 221)")) call-function: ("sup-check", ("ayu", "#c5c5c5"))
call-function: ("sup-check", ("ayu", "rgb(197, 197, 197)")) call-function: ("sup-check", ("dark", "#ddd"))
call-function: ("sup-check", ("light", "rgb(0, 0, 0)")) call-function: ("sup-check", ("light", "black"))

View file

@ -61,6 +61,8 @@ LL + Some(())
error[E0308]: `?` operator has incompatible types error[E0308]: `?` operator has incompatible types
--> $DIR/compatible-variants.rs:35:5 --> $DIR/compatible-variants.rs:35:5
| |
LL | fn d() -> Option<()> {
| ---------- expected `Option<()>` because of return type
LL | c()? LL | c()?
| ^^^^ expected `Option<()>`, found `()` | ^^^^ expected `Option<()>`, found `()`
| |

View file

@ -2,7 +2,9 @@ error[E0308]: mismatched types
--> $DIR/placeholder-pattern-fail.rs:9:47 --> $DIR/placeholder-pattern-fail.rs:9:47
| |
LL | let _: for<'a, 'b> fn(Inv<'a>, Inv<'b>) = sub; LL | let _: for<'a, 'b> fn(Inv<'a>, Inv<'b>) = sub;
| ^^^ one type is more general than the other | -------------------------------- ^^^ one type is more general than the other
| |
| expected due to this
| |
= note: expected fn pointer `for<'a, 'b> fn(Inv<'a>, Inv<'b>)` = note: expected fn pointer `for<'a, 'b> fn(Inv<'a>, Inv<'b>)`
found fn pointer `for<'a> fn(Inv<'a>, Inv<'a>)` found fn pointer `for<'a> fn(Inv<'a>, Inv<'a>)`

View file

@ -2,7 +2,9 @@ error[E0308]: mismatched types
--> $DIR/hrtb-exists-forall-fn.rs:17:34 --> $DIR/hrtb-exists-forall-fn.rs:17:34
| |
LL | let _: for<'b> fn(&'b u32) = foo(); LL | let _: for<'b> fn(&'b u32) = foo();
| ^^^^^ one type is more general than the other | ------------------- ^^^^^ one type is more general than the other
| |
| expected due to this
| |
= note: expected fn pointer `for<'b> fn(&'b u32)` = note: expected fn pointer `for<'b> fn(&'b u32)`
found fn pointer `fn(&u32)` found fn pointer `fn(&u32)`

View file

@ -0,0 +1,13 @@
#![feature(inline_const_pat)]
//~^ WARN the feature `inline_const_pat` is incomplete
fn uwu() {}
fn main() {
let x = [];
match x[123] {
const { uwu } => {}
//~^ ERROR `fn() {uwu}` cannot be used in patterns
_ => {}
}
}

View file

@ -0,0 +1,17 @@
warning: the feature `inline_const_pat` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/pat-match-fndef.rs:1:12
|
LL | #![feature(inline_const_pat)]
| ^^^^^^^^^^^^^^^^
|
= note: see issue #76001 <https://github.com/rust-lang/rust/issues/76001> for more information
= note: `#[warn(incomplete_features)]` on by default
error: `fn() {uwu}` cannot be used in patterns
--> $DIR/pat-match-fndef.rs:9:9
|
LL | const { uwu } => {}
| ^^^^^^^^^^^^^
error: aborting due to previous error; 1 warning emitted

View file

@ -1,6 +1,8 @@
error[E0308]: `?` operator has incompatible types error[E0308]: `?` operator has incompatible types
--> $DIR/issue-51632-try-desugar-incompatible-types.rs:8:5 --> $DIR/issue-51632-try-desugar-incompatible-types.rs:8:5
| |
LL | fn forbidden_narratives() -> Result<isize, ()> {
| ----------------- expected `Result<isize, ()>` because of return type
LL | missing_discourses()? LL | missing_discourses()?
| ^^^^^^^^^^^^^^^^^^^^^ expected `Result<isize, ()>`, found `isize` | ^^^^^^^^^^^^^^^^^^^^^ expected `Result<isize, ()>`, found `isize`
| |

View file

@ -0,0 +1,21 @@
#![allow(unused)]
fn test(shouldwe: Option<u32>, shouldwe2: Option<u32>) -> u32 {
//~^ NOTE expected `u32` because of return type
match shouldwe {
Some(val) => {
match shouldwe2 {
Some(val) => {
return val;
}
None => (), //~ ERROR mismatched types
//~^ NOTE expected `u32`, found `()`
}
}
None => return 12,
}
}
fn main() {
println!("returned {}", test(None, Some(5)));
}

View file

@ -0,0 +1,12 @@
error[E0308]: mismatched types
--> $DIR/non-first-arm-doesnt-match-expected-return-type.rs:11:25
|
LL | fn test(shouldwe: Option<u32>, shouldwe2: Option<u32>) -> u32 {
| --- expected `u32` because of return type
...
LL | None => (),
| ^^ expected `u32`, found `()`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.

View file

@ -2,7 +2,9 @@ error[E0308]: mismatched types
--> $DIR/higher-ranked-implied.rs:12:16 --> $DIR/higher-ranked-implied.rs:12:16
| |
LL | let y: B = x; LL | let y: B = x;
| ^ one type is more general than the other | - ^ one type is more general than the other
| |
| expected due to this
| |
= note: expected fn pointer `for<'a, 'b> fn(Inv<&'a &'b ()>, Inv<&'b &'a ()>, Inv<&'b ()>)` = note: expected fn pointer `for<'a, 'b> fn(Inv<&'a &'b ()>, Inv<&'b &'a ()>, Inv<&'b ()>)`
found fn pointer `for<'a, 'b> fn(Inv<&'a &'b ()>, Inv<&'b &'a ()>, Inv<&'a ()>)` found fn pointer `for<'a, 'b> fn(Inv<&'a &'b ()>, Inv<&'b &'a ()>, Inv<&'a ()>)`
@ -11,7 +13,9 @@ error[E0308]: mismatched types
--> $DIR/higher-ranked-implied.rs:13:16 --> $DIR/higher-ranked-implied.rs:13:16
| |
LL | let _: A = y; LL | let _: A = y;
| ^ one type is more general than the other | - ^ one type is more general than the other
| |
| expected due to this
| |
= note: expected fn pointer `for<'a, 'b> fn(Inv<&'a &'b ()>, Inv<&'b &'a ()>, Inv<&'a ()>)` = note: expected fn pointer `for<'a, 'b> fn(Inv<&'a &'b ()>, Inv<&'b &'a ()>, Inv<&'a ()>)`
found fn pointer `for<'a, 'b> fn(Inv<&'a &'b ()>, Inv<&'b &'a ()>, Inv<&'b ()>)` found fn pointer `for<'a, 'b> fn(Inv<&'a &'b ()>, Inv<&'b &'a ()>, Inv<&'b ()>)`

View file

@ -2,7 +2,9 @@ error[E0308]: mismatched types
--> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:43 --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:43
| |
LL | let _: fn(&mut &isize, &mut &isize) = a; LL | let _: fn(&mut &isize, &mut &isize) = a;
| ^ one type is more general than the other | ---------------------------- ^ one type is more general than the other
| |
| expected due to this
| |
= note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b isize, &'c mut &'d isize)` = note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b isize, &'c mut &'d isize)`
found fn item `for<'a, 'b> fn(&'a mut &isize, &'b mut &isize) {a::<'_, '_>}` found fn item `for<'a, 'b> fn(&'a mut &isize, &'b mut &isize) {a::<'_, '_>}`

View file

@ -2,7 +2,9 @@ error[E0308]: mismatched types
--> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:56 --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:56
| |
LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a;
| ^ one type is more general than the other | ----------------------------------------- ^ one type is more general than the other
| |
| expected due to this
| |
= note: expected fn pointer `for<'a, 'b, 'c, 'd, 'e, 'f> fn(&'a mut &'b isize, &'c mut &'d isize, &'e mut &'f isize)` = note: expected fn pointer `for<'a, 'b, 'c, 'd, 'e, 'f> fn(&'a mut &'b isize, &'c mut &'d isize, &'e mut &'f isize)`
found fn item `for<'a, 'b, 'c> fn(&'a mut &isize, &'b mut &isize, &'c mut &isize) {a::<'_, '_, '_>}` found fn item `for<'a, 'b, 'c> fn(&'a mut &isize, &'b mut &isize, &'c mut &isize) {a::<'_, '_, '_>}`

View file

@ -2,7 +2,9 @@ error[E0308]: mismatched types
--> $DIR/regions-lifetime-bounds-on-fns.rs:20:43 --> $DIR/regions-lifetime-bounds-on-fns.rs:20:43
| |
LL | let _: fn(&mut &isize, &mut &isize) = a; LL | let _: fn(&mut &isize, &mut &isize) = a;
| ^ one type is more general than the other | ---------------------------- ^ one type is more general than the other
| |
| expected due to this
| |
= note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b isize, &'c mut &'d isize)` = note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b isize, &'c mut &'d isize)`
found fn item `for<'a, 'b> fn(&'a mut &isize, &'b mut &isize) {a::<'_, '_>}` found fn item `for<'a, 'b> fn(&'a mut &isize, &'b mut &isize) {a::<'_, '_>}`

View file

@ -1,6 +1,9 @@
error[E0308]: `?` operator has incompatible types error[E0308]: `?` operator has incompatible types
--> $DIR/remove-question-symbol-with-paren.rs:5:6 --> $DIR/remove-question-symbol-with-paren.rs:5:6
| |
LL | fn foo() -> Option<()> {
| ---------- expected `Option<()>` because of return type
LL | let x = Some(());
LL | (x?) LL | (x?)
| ^^ expected `Option<()>`, found `()` | ^^ expected `Option<()>`, found `()`
| |