1
Fork 0

Auto merge of #99592 - Dylan-DPC:rollup-xlw4wax, r=Dylan-DPC

Rollup of 6 pull requests

Successful merges:

 - #98174 (Rename `<*{mut,const} T>::as_{const,mut}` to `cast_`)
 - #98868 (Fix unreachable coverage generation for inlined functions)
 - #99393 (feat: omit suffixes in const generics (e.g. `1_i32`))
 - #99423 (Group CSS font rule)
 - #99539 (Improve suggestions for returning binding)
 - #99579 (Add same warning to Result::expect as Result::unwrap)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2022-07-22 07:12:19 +00:00
commit e7a9c11416
71 changed files with 949 additions and 706 deletions

View file

@ -9,11 +9,8 @@ use super::FunctionCx;
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
pub fn codegen_coverage(&self, bx: &mut Bx, coverage: Coverage, scope: SourceScope) { pub fn codegen_coverage(&self, bx: &mut Bx, coverage: Coverage, scope: SourceScope) {
// Determine the instance that coverage data was originally generated for. // Determine the instance that coverage data was originally generated for.
let scope_data = &self.mir.source_scopes[scope]; let instance = if let Some(inlined) = scope.inlined_instance(&self.mir.source_scopes) {
let instance = if let Some((inlined_instance, _)) = scope_data.inlined { self.monomorphize(inlined)
self.monomorphize(inlined_instance)
} else if let Some(inlined_scope) = scope_data.inlined_parent_scope {
self.monomorphize(self.mir.source_scopes[inlined_scope].inlined.unwrap().0)
} else { } else {
self.instance self.instance
}; };

View file

@ -954,6 +954,16 @@ pub struct Block<'hir> {
pub targeted_by_break: bool, pub targeted_by_break: bool,
} }
impl<'hir> Block<'hir> {
pub fn innermost_block(&self) -> &Block<'hir> {
let mut block = self;
while let Some(Expr { kind: ExprKind::Block(inner_block, _), .. }) = block.expr {
block = inner_block;
}
block
}
}
#[derive(Debug, HashStable_Generic)] #[derive(Debug, HashStable_Generic)]
pub struct Pat<'hir> { pub struct Pat<'hir> {
#[stable_hasher(ignore)] #[stable_hasher(ignore)]

View file

@ -316,37 +316,6 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>(
err err
} }
/// Structurally compares two types, modulo any inference variables.
///
/// Returns `true` if two types are equal, or if one type is an inference variable compatible
/// with the other type. A TyVar inference type is compatible with any type, and an IntVar or
/// FloatVar inference type are compatible with themselves or their concrete types (Int and
/// Float types, respectively). When comparing two ADTs, these rules apply recursively.
pub fn same_type_modulo_infer<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
match (&a.kind(), &b.kind()) {
(&ty::Adt(did_a, substs_a), &ty::Adt(did_b, substs_b)) => {
if did_a != did_b {
return false;
}
substs_a.types().zip(substs_b.types()).all(|(a, b)| same_type_modulo_infer(a, b))
}
(&ty::Int(_), &ty::Infer(ty::InferTy::IntVar(_)))
| (&ty::Infer(ty::InferTy::IntVar(_)), &ty::Int(_) | &ty::Infer(ty::InferTy::IntVar(_)))
| (&ty::Float(_), &ty::Infer(ty::InferTy::FloatVar(_)))
| (
&ty::Infer(ty::InferTy::FloatVar(_)),
&ty::Float(_) | &ty::Infer(ty::InferTy::FloatVar(_)),
)
| (&ty::Infer(ty::InferTy::TyVar(_)), _)
| (_, &ty::Infer(ty::InferTy::TyVar(_))) => true,
(&ty::Ref(_, ty_a, mut_a), &ty::Ref(_, ty_b, mut_b)) => {
mut_a == mut_b && same_type_modulo_infer(*ty_a, *ty_b)
}
_ => a == b,
}
}
impl<'a, 'tcx> InferCtxt<'a, 'tcx> { impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
pub fn report_region_errors( pub fn report_region_errors(
&self, &self,
@ -645,13 +614,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
err.span_label(span, "expected due to this"); err.span_label(span, "expected due to this");
} }
ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause { ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
semi_span, arm_block_id,
arm_span,
arm_ty,
prior_arm_block_id,
prior_arm_span,
prior_arm_ty,
source, source,
ref prior_arms, ref prior_arms,
last_ty,
scrut_hir_id, scrut_hir_id,
opt_suggest_box_span, opt_suggest_box_span,
arm_span,
scrut_span, scrut_span,
.. ..
}) => match source { }) => match source {
@ -682,10 +654,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
} }
} }
_ => { _ => {
// `last_ty` can be `!`, `expected` will have better info when present. // `prior_arm_ty` can be `!`, `expected` will have better info when present.
let t = self.resolve_vars_if_possible(match exp_found { let t = self.resolve_vars_if_possible(match exp_found {
Some(ty::error::ExpectedFound { expected, .. }) => expected, Some(ty::error::ExpectedFound { expected, .. }) => expected,
_ => last_ty, _ => prior_arm_ty,
}); });
let source_map = self.tcx.sess.source_map(); let source_map = self.tcx.sess.source_map();
let mut any_multiline_arm = source_map.is_multiline(arm_span); let mut any_multiline_arm = source_map.is_multiline(arm_span);
@ -710,37 +682,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}; };
let msg = "`match` arms have incompatible types"; let msg = "`match` arms have incompatible types";
err.span_label(outer_error_span, msg); err.span_label(outer_error_span, msg);
if let Some((sp, boxed)) = semi_span { self.suggest_remove_semi_or_return_binding(
if let (StatementAsExpression::NeedsBoxing, [.., prior_arm]) = err,
(boxed, &prior_arms[..]) prior_arm_block_id,
{ prior_arm_ty,
err.multipart_suggestion( prior_arm_span,
"consider removing this semicolon and boxing the expressions", arm_block_id,
vec![ arm_ty,
(prior_arm.shrink_to_lo(), "Box::new(".to_string()), arm_span,
(prior_arm.shrink_to_hi(), ")".to_string()), );
(arm_span.shrink_to_lo(), "Box::new(".to_string()),
(arm_span.shrink_to_hi(), ")".to_string()),
(sp, String::new()),
],
Applicability::HasPlaceholders,
);
} else if matches!(boxed, StatementAsExpression::NeedsBoxing) {
err.span_suggestion_short(
sp,
"consider removing this semicolon and boxing the expressions",
"",
Applicability::MachineApplicable,
);
} else {
err.span_suggestion_short(
sp,
"consider removing this semicolon",
"",
Applicability::MachineApplicable,
);
}
}
if let Some(ret_sp) = opt_suggest_box_span { if let Some(ret_sp) = opt_suggest_box_span {
// Get return type span and point to it. // Get return type span and point to it.
self.suggest_boxing_for_return_impl_trait( self.suggest_boxing_for_return_impl_trait(
@ -752,43 +702,33 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
} }
}, },
ObligationCauseCode::IfExpression(box IfExpressionCause { ObligationCauseCode::IfExpression(box IfExpressionCause {
then, then_id,
else_sp, else_id,
outer, then_ty,
semicolon, else_ty,
outer_span,
opt_suggest_box_span, opt_suggest_box_span,
}) => { }) => {
err.span_label(then, "expected because of this"); let then_span = self.find_block_span_from_hir_id(then_id);
if let Some(sp) = outer { let else_span = self.find_block_span_from_hir_id(then_id);
err.span_label(then_span, "expected because of this");
if let Some(sp) = outer_span {
err.span_label(sp, "`if` and `else` have incompatible types"); err.span_label(sp, "`if` and `else` have incompatible types");
} }
if let Some((sp, boxed)) = semicolon { self.suggest_remove_semi_or_return_binding(
if matches!(boxed, StatementAsExpression::NeedsBoxing) { err,
err.multipart_suggestion( Some(then_id),
"consider removing this semicolon and boxing the expression", then_ty,
vec![ then_span,
(then.shrink_to_lo(), "Box::new(".to_string()), Some(else_id),
(then.shrink_to_hi(), ")".to_string()), else_ty,
(else_sp.shrink_to_lo(), "Box::new(".to_string()), else_span,
(else_sp.shrink_to_hi(), ")".to_string()), );
(sp, String::new()),
],
Applicability::MachineApplicable,
);
} else {
err.span_suggestion_short(
sp,
"consider removing this semicolon",
"",
Applicability::MachineApplicable,
);
}
}
if let Some(ret_sp) = opt_suggest_box_span { if let Some(ret_sp) = opt_suggest_box_span {
self.suggest_boxing_for_return_impl_trait( self.suggest_boxing_for_return_impl_trait(
err, err,
ret_sp, ret_sp,
[then, else_sp].into_iter(), [then_span, else_span].into_iter(),
); );
} }
} }
@ -808,6 +748,56 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
} }
} }
fn suggest_remove_semi_or_return_binding(
&self,
err: &mut Diagnostic,
first_id: Option<hir::HirId>,
first_ty: Ty<'tcx>,
first_span: Span,
second_id: Option<hir::HirId>,
second_ty: Ty<'tcx>,
second_span: Span,
) {
let remove_semicolon =
[(first_id, second_ty), (second_id, first_ty)].into_iter().find_map(|(id, ty)| {
let hir::Node::Block(blk) = self.tcx.hir().get(id?) else { return None };
self.could_remove_semicolon(blk, ty)
});
match remove_semicolon {
Some((sp, StatementAsExpression::NeedsBoxing)) => {
err.multipart_suggestion(
"consider removing this semicolon and boxing the expressions",
vec![
(first_span.shrink_to_lo(), "Box::new(".to_string()),
(first_span.shrink_to_hi(), ")".to_string()),
(second_span.shrink_to_lo(), "Box::new(".to_string()),
(second_span.shrink_to_hi(), ")".to_string()),
(sp, String::new()),
],
Applicability::MachineApplicable,
);
}
Some((sp, StatementAsExpression::CorrectType)) => {
err.span_suggestion_short(
sp,
"consider removing this semicolon",
"",
Applicability::MachineApplicable,
);
}
None => {
for (id, ty) in [(first_id, second_ty), (second_id, first_ty)] {
if let Some(id) = id
&& let hir::Node::Block(blk) = self.tcx.hir().get(id)
&& self.consider_returning_binding(blk, ty, err)
{
break;
}
}
}
}
}
fn suggest_boxing_for_return_impl_trait( fn suggest_boxing_for_return_impl_trait(
&self, &self,
err: &mut Diagnostic, err: &mut Diagnostic,
@ -1723,15 +1713,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}; };
debug!("exp_found {:?} terr {:?} cause.code {:?}", exp_found, terr, cause.code()); debug!("exp_found {:?} terr {:?} cause.code {:?}", exp_found, terr, cause.code());
if let Some(exp_found) = exp_found { if let Some(exp_found) = exp_found {
let should_suggest_fixes = if let ObligationCauseCode::Pattern { root_ty, .. } = let should_suggest_fixes =
cause.code() if let ObligationCauseCode::Pattern { root_ty, .. } = cause.code() {
{ // Skip if the root_ty of the pattern is not the same as the expected_ty.
// Skip if the root_ty of the pattern is not the same as the expected_ty. // If these types aren't equal then we've probably peeled off a layer of arrays.
// If these types aren't equal then we've probably peeled off a layer of arrays. self.same_type_modulo_infer(*root_ty, exp_found.expected)
same_type_modulo_infer(self.resolve_vars_if_possible(*root_ty), exp_found.expected) } else {
} else { true
true };
};
if should_suggest_fixes { if should_suggest_fixes {
self.suggest_tuple_pattern(cause, &exp_found, diag); self.suggest_tuple_pattern(cause, &exp_found, diag);
@ -1786,7 +1775,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
.filter_map(|variant| { .filter_map(|variant| {
let sole_field = &variant.fields[0]; let sole_field = &variant.fields[0];
let sole_field_ty = sole_field.ty(self.tcx, substs); let sole_field_ty = sole_field.ty(self.tcx, substs);
if same_type_modulo_infer(sole_field_ty, exp_found.found) { if self.same_type_modulo_infer(sole_field_ty, exp_found.found) {
let variant_path = let variant_path =
with_no_trimmed_paths!(self.tcx.def_path_str(variant.def_id)); with_no_trimmed_paths!(self.tcx.def_path_str(variant.def_id));
// FIXME #56861: DRYer prelude filtering // FIXME #56861: DRYer prelude filtering
@ -1902,12 +1891,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
self.get_impl_future_output_ty(exp_found.expected).map(Binder::skip_binder), self.get_impl_future_output_ty(exp_found.expected).map(Binder::skip_binder),
self.get_impl_future_output_ty(exp_found.found).map(Binder::skip_binder), self.get_impl_future_output_ty(exp_found.found).map(Binder::skip_binder),
) { ) {
(Some(exp), Some(found)) if same_type_modulo_infer(exp, found) => match cause.code() { (Some(exp), Some(found)) if self.same_type_modulo_infer(exp, found) => match cause
ObligationCauseCode::IfExpression(box IfExpressionCause { then, .. }) => { .code()
{
ObligationCauseCode::IfExpression(box IfExpressionCause { then_id, .. }) => {
let then_span = self.find_block_span_from_hir_id(*then_id);
diag.multipart_suggestion( diag.multipart_suggestion(
"consider `await`ing on both `Future`s", "consider `await`ing on both `Future`s",
vec![ vec![
(then.shrink_to_hi(), ".await".to_string()), (then_span.shrink_to_hi(), ".await".to_string()),
(exp_span.shrink_to_hi(), ".await".to_string()), (exp_span.shrink_to_hi(), ".await".to_string()),
], ],
Applicability::MaybeIncorrect, Applicability::MaybeIncorrect,
@ -1934,7 +1926,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
diag.help("consider `await`ing on both `Future`s"); diag.help("consider `await`ing on both `Future`s");
} }
}, },
(_, Some(ty)) if same_type_modulo_infer(exp_found.expected, ty) => { (_, Some(ty)) if self.same_type_modulo_infer(exp_found.expected, ty) => {
diag.span_suggestion_verbose( diag.span_suggestion_verbose(
exp_span.shrink_to_hi(), exp_span.shrink_to_hi(),
"consider `await`ing on the `Future`", "consider `await`ing on the `Future`",
@ -1942,11 +1934,20 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
Applicability::MaybeIncorrect, Applicability::MaybeIncorrect,
); );
} }
(Some(ty), _) if same_type_modulo_infer(ty, exp_found.found) => match cause.code() { (Some(ty), _) if self.same_type_modulo_infer(ty, exp_found.found) => match cause.code()
ObligationCauseCode::Pattern { span: Some(span), .. } {
| ObligationCauseCode::IfExpression(box IfExpressionCause { then: span, .. }) => { ObligationCauseCode::Pattern { span: Some(then_span), .. } => {
diag.span_suggestion_verbose( diag.span_suggestion_verbose(
span.shrink_to_hi(), then_span.shrink_to_hi(),
"consider `await`ing on the `Future`",
".await",
Applicability::MaybeIncorrect,
);
}
ObligationCauseCode::IfExpression(box IfExpressionCause { then_id, .. }) => {
let then_span = self.find_block_span_from_hir_id(*then_id);
diag.span_suggestion_verbose(
then_span.shrink_to_hi(),
"consider `await`ing on the `Future`", "consider `await`ing on the `Future`",
".await", ".await",
Applicability::MaybeIncorrect, Applicability::MaybeIncorrect,
@ -1992,7 +1993,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
.iter() .iter()
.filter(|field| field.vis.is_accessible_from(field.did, self.tcx)) .filter(|field| field.vis.is_accessible_from(field.did, self.tcx))
.map(|field| (field.name, field.ty(self.tcx, expected_substs))) .map(|field| (field.name, field.ty(self.tcx, expected_substs)))
.find(|(_, ty)| same_type_modulo_infer(*ty, exp_found.found)) .find(|(_, ty)| self.same_type_modulo_infer(*ty, exp_found.found))
{ {
if let ObligationCauseCode::Pattern { span: Some(span), .. } = *cause.code() { if let ObligationCauseCode::Pattern { span: Some(span), .. } = *cause.code() {
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
@ -2057,7 +2058,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
| (_, ty::Infer(_)) | (_, ty::Infer(_))
| (ty::Param(_), _) | (ty::Param(_), _)
| (ty::Infer(_), _) => {} | (ty::Infer(_), _) => {}
_ if same_type_modulo_infer(exp_ty, found_ty) => {} _ if self.same_type_modulo_infer(exp_ty, found_ty) => {}
_ => show_suggestion = false, _ => show_suggestion = false,
}; };
} }
@ -2179,7 +2180,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
) { ) {
let [expected_tup_elem] = expected_fields[..] else { return }; let [expected_tup_elem] = expected_fields[..] else { return };
if !same_type_modulo_infer(expected_tup_elem, found) { if !self.same_type_modulo_infer(expected_tup_elem, found) {
return; return;
} }
@ -2647,6 +2648,76 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
span.is_desugaring(DesugaringKind::QuestionMark) span.is_desugaring(DesugaringKind::QuestionMark)
&& self.tcx.is_diagnostic_item(sym::From, trait_def_id) && self.tcx.is_diagnostic_item(sym::From, trait_def_id)
} }
/// Structurally compares two types, modulo any inference variables.
///
/// Returns `true` if two types are equal, or if one type is an inference variable compatible
/// with the other type. A TyVar inference type is compatible with any type, and an IntVar or
/// FloatVar inference type are compatible with themselves or their concrete types (Int and
/// Float types, respectively). When comparing two ADTs, these rules apply recursively.
pub fn same_type_modulo_infer(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
let (a, b) = self.resolve_vars_if_possible((a, b));
match (a.kind(), b.kind()) {
(&ty::Adt(def_a, substs_a), &ty::Adt(def_b, substs_b)) => {
if def_a != def_b {
return false;
}
substs_a
.types()
.zip(substs_b.types())
.all(|(a, b)| self.same_type_modulo_infer(a, b))
}
(&ty::FnDef(did_a, substs_a), &ty::FnDef(did_b, substs_b)) => {
if did_a != did_b {
return false;
}
substs_a
.types()
.zip(substs_b.types())
.all(|(a, b)| self.same_type_modulo_infer(a, b))
}
(&ty::Int(_) | &ty::Uint(_), &ty::Infer(ty::InferTy::IntVar(_)))
| (
&ty::Infer(ty::InferTy::IntVar(_)),
&ty::Int(_) | &ty::Uint(_) | &ty::Infer(ty::InferTy::IntVar(_)),
)
| (&ty::Float(_), &ty::Infer(ty::InferTy::FloatVar(_)))
| (
&ty::Infer(ty::InferTy::FloatVar(_)),
&ty::Float(_) | &ty::Infer(ty::InferTy::FloatVar(_)),
)
| (&ty::Infer(ty::InferTy::TyVar(_)), _)
| (_, &ty::Infer(ty::InferTy::TyVar(_))) => true,
(&ty::Ref(_, ty_a, mut_a), &ty::Ref(_, ty_b, mut_b)) => {
mut_a == mut_b && self.same_type_modulo_infer(ty_a, ty_b)
}
(&ty::RawPtr(a), &ty::RawPtr(b)) => {
a.mutbl == b.mutbl && self.same_type_modulo_infer(a.ty, b.ty)
}
(&ty::Slice(a), &ty::Slice(b)) => self.same_type_modulo_infer(a, b),
(&ty::Array(a_ty, a_ct), &ty::Array(b_ty, b_ct)) => {
self.same_type_modulo_infer(a_ty, b_ty) && a_ct == b_ct
}
(&ty::Tuple(a), &ty::Tuple(b)) => {
if a.len() != b.len() {
return false;
}
std::iter::zip(a.iter(), b.iter()).all(|(a, b)| self.same_type_modulo_infer(a, b))
}
(&ty::FnPtr(a), &ty::FnPtr(b)) => {
let a = a.skip_binder().inputs_and_output;
let b = b.skip_binder().inputs_and_output;
if a.len() != b.len() {
return false;
}
std::iter::zip(a.iter(), b.iter()).all(|(a, b)| self.same_type_modulo_infer(a, b))
}
// FIXME(compiler-errors): This needs to be generalized more
_ => a == b,
}
}
} }
impl<'a, 'tcx> InferCtxt<'a, 'tcx> { impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
@ -2798,3 +2869,237 @@ impl TyCategory {
} }
} }
} }
impl<'tcx> InferCtxt<'_, 'tcx> {
/// Given a [`hir::Block`], get the span of its last expression or
/// statement, peeling off any inner blocks.
pub fn find_block_span(&self, block: &'tcx hir::Block<'tcx>) -> Span {
let block = block.innermost_block();
if let Some(expr) = &block.expr {
expr.span
} else if let Some(stmt) = block.stmts.last() {
// possibly incorrect trailing `;` in the else arm
stmt.span
} else {
// empty block; point at its entirety
block.span
}
}
/// Given a [`hir::HirId`] for a block, get the span of its last expression
/// or statement, peeling off any inner blocks.
pub fn find_block_span_from_hir_id(&self, hir_id: hir::HirId) -> Span {
match self.tcx.hir().get(hir_id) {
hir::Node::Block(blk) => self.find_block_span(blk),
// The parser was in a weird state if either of these happen, but
// it's better not to panic.
hir::Node::Expr(e) => e.span,
_ => rustc_span::DUMMY_SP,
}
}
/// Be helpful when the user wrote `{... expr; }` and taking the `;` off
/// is enough to fix the error.
pub fn could_remove_semicolon(
&self,
blk: &'tcx hir::Block<'tcx>,
expected_ty: Ty<'tcx>,
) -> Option<(Span, StatementAsExpression)> {
let blk = blk.innermost_block();
// Do not suggest if we have a tail expr.
if blk.expr.is_some() {
return None;
}
let last_stmt = blk.stmts.last()?;
let hir::StmtKind::Semi(ref last_expr) = last_stmt.kind else {
return None;
};
let last_expr_ty = self.in_progress_typeck_results?.borrow().expr_ty_opt(*last_expr)?;
let needs_box = match (last_expr_ty.kind(), expected_ty.kind()) {
_ if last_expr_ty.references_error() => return None,
_ if self.same_type_modulo_infer(last_expr_ty, expected_ty) => {
StatementAsExpression::CorrectType
}
(ty::Opaque(last_def_id, _), ty::Opaque(exp_def_id, _))
if last_def_id == exp_def_id =>
{
StatementAsExpression::CorrectType
}
(ty::Opaque(last_def_id, last_bounds), ty::Opaque(exp_def_id, exp_bounds)) => {
debug!(
"both opaque, likely future {:?} {:?} {:?} {:?}",
last_def_id, last_bounds, exp_def_id, exp_bounds
);
let last_local_id = last_def_id.as_local()?;
let exp_local_id = exp_def_id.as_local()?;
match (
&self.tcx.hir().expect_item(last_local_id).kind,
&self.tcx.hir().expect_item(exp_local_id).kind,
) {
(
hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: last_bounds, .. }),
hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: exp_bounds, .. }),
) if iter::zip(*last_bounds, *exp_bounds).all(|(left, right)| {
match (left, right) {
(
hir::GenericBound::Trait(tl, ml),
hir::GenericBound::Trait(tr, mr),
) if tl.trait_ref.trait_def_id() == tr.trait_ref.trait_def_id()
&& ml == mr =>
{
true
}
(
hir::GenericBound::LangItemTrait(langl, _, _, argsl),
hir::GenericBound::LangItemTrait(langr, _, _, argsr),
) if langl == langr => {
// FIXME: consider the bounds!
debug!("{:?} {:?}", argsl, argsr);
true
}
_ => false,
}
}) =>
{
StatementAsExpression::NeedsBoxing
}
_ => StatementAsExpression::CorrectType,
}
}
_ => return None,
};
let span = if last_stmt.span.from_expansion() {
let mac_call = rustc_span::source_map::original_sp(last_stmt.span, blk.span);
self.tcx.sess.source_map().mac_call_stmt_semi_span(mac_call)?
} else {
last_stmt.span.with_lo(last_stmt.span.hi() - BytePos(1))
};
Some((span, needs_box))
}
/// Suggest returning a local binding with a compatible type if the block
/// has no return expression.
pub fn consider_returning_binding(
&self,
blk: &'tcx hir::Block<'tcx>,
expected_ty: Ty<'tcx>,
err: &mut Diagnostic,
) -> bool {
let blk = blk.innermost_block();
// Do not suggest if we have a tail expr.
if blk.expr.is_some() {
return false;
}
let mut shadowed = FxHashSet::default();
let mut candidate_idents = vec![];
let mut find_compatible_candidates = |pat: &hir::Pat<'_>| {
if let hir::PatKind::Binding(_, hir_id, ident, _) = &pat.kind
&& let Some(pat_ty) = self
.in_progress_typeck_results
.and_then(|typeck_results| typeck_results.borrow().node_type_opt(*hir_id))
{
let pat_ty = self.resolve_vars_if_possible(pat_ty);
if self.same_type_modulo_infer(pat_ty, expected_ty)
&& !(pat_ty, expected_ty).references_error()
&& shadowed.insert(ident.name)
{
candidate_idents.push((*ident, pat_ty));
}
}
true
};
let hir = self.tcx.hir();
for stmt in blk.stmts.iter().rev() {
let hir::StmtKind::Local(local) = &stmt.kind else { continue; };
local.pat.walk(&mut find_compatible_candidates);
}
match hir.find(hir.get_parent_node(blk.hir_id)) {
Some(hir::Node::Expr(hir::Expr { hir_id, .. })) => {
match hir.find(hir.get_parent_node(*hir_id)) {
Some(hir::Node::Arm(hir::Arm { pat, .. })) => {
pat.walk(&mut find_compatible_candidates);
}
Some(
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body), .. })
| hir::Node::ImplItem(hir::ImplItem {
kind: hir::ImplItemKind::Fn(_, body),
..
})
| hir::Node::TraitItem(hir::TraitItem {
kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body)),
..
})
| hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Closure(hir::Closure { body, .. }),
..
}),
) => {
for param in hir.body(*body).params {
param.pat.walk(&mut find_compatible_candidates);
}
}
Some(hir::Node::Expr(hir::Expr {
kind:
hir::ExprKind::If(
hir::Expr { kind: hir::ExprKind::Let(let_), .. },
then_block,
_,
),
..
})) if then_block.hir_id == *hir_id => {
let_.pat.walk(&mut find_compatible_candidates);
}
_ => {}
}
}
_ => {}
}
match &candidate_idents[..] {
[(ident, _ty)] => {
let sm = self.tcx.sess.source_map();
if let Some(stmt) = blk.stmts.last() {
let stmt_span = sm.stmt_span(stmt.span, blk.span);
let sugg = if sm.is_multiline(blk.span)
&& let Some(spacing) = sm.indentation_before(stmt_span)
{
format!("\n{spacing}{ident}")
} else {
format!(" {ident}")
};
err.span_suggestion_verbose(
stmt_span.shrink_to_hi(),
format!("consider returning the local binding `{ident}`"),
sugg,
Applicability::MaybeIncorrect,
);
} else {
let sugg = if sm.is_multiline(blk.span)
&& let Some(spacing) = sm.indentation_before(blk.span.shrink_to_lo())
{
format!("\n{spacing} {ident}\n{spacing}")
} else {
format!(" {ident} ")
};
let left_span = sm.span_through_char(blk.span, '{').shrink_to_hi();
err.span_suggestion_verbose(
sm.span_extend_while(left_span, |c| c.is_whitespace()).unwrap_or(left_span),
format!("consider returning the local binding `{ident}`"),
sugg,
Applicability::MaybeIncorrect,
);
}
true
}
values if (1..3).contains(&values.len()) => {
let spans = values.iter().map(|(ident, _)| ident.span).collect::<Vec<_>>();
err.span_note(spans, "consider returning one of these bindings");
true
}
_ => false,
}
}
}

View file

@ -1662,6 +1662,22 @@ impl SourceScope {
ClearCrossCrate::Clear => None, ClearCrossCrate::Clear => None,
} }
} }
/// The instance this source scope was inlined from, if any.
#[inline]
pub fn inlined_instance<'tcx>(
self,
source_scopes: &IndexVec<SourceScope, SourceScopeData<'tcx>>,
) -> Option<ty::Instance<'tcx>> {
let scope_data = &source_scopes[self];
if let Some((inlined_instance, _)) = scope_data.inlined {
Some(inlined_instance)
} else if let Some(inlined_scope) = scope_data.inlined_parent_scope {
Some(source_scopes[inlined_scope].inlined.unwrap().0)
} else {
None
}
}
} }
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]

View file

@ -351,7 +351,7 @@ pub enum ObligationCauseCode<'tcx> {
ConstPatternStructural, ConstPatternStructural,
/// Computing common supertype in an if expression /// Computing common supertype in an if expression
IfExpression(Box<IfExpressionCause>), IfExpression(Box<IfExpressionCause<'tcx>>),
/// Computing common supertype of an if expression with no else counter-part /// Computing common supertype of an if expression with no else counter-part
IfExpressionWithNoElse, IfExpressionWithNoElse,
@ -488,22 +488,27 @@ impl<'tcx> ty::Lift<'tcx> for StatementAsExpression {
#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)] #[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]
pub struct MatchExpressionArmCause<'tcx> { pub struct MatchExpressionArmCause<'tcx> {
pub arm_block_id: Option<hir::HirId>,
pub arm_ty: Ty<'tcx>,
pub arm_span: Span, pub arm_span: Span,
pub prior_arm_block_id: Option<hir::HirId>,
pub prior_arm_ty: Ty<'tcx>,
pub prior_arm_span: Span,
pub scrut_span: Span, pub scrut_span: Span,
pub semi_span: Option<(Span, StatementAsExpression)>,
pub source: hir::MatchSource, pub source: hir::MatchSource,
pub prior_arms: Vec<Span>, pub prior_arms: Vec<Span>,
pub last_ty: Ty<'tcx>,
pub scrut_hir_id: hir::HirId, pub scrut_hir_id: hir::HirId,
pub opt_suggest_box_span: Option<Span>, pub opt_suggest_box_span: Option<Span>,
} }
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct IfExpressionCause { #[derive(Lift, TypeFoldable, TypeVisitable)]
pub then: Span, pub struct IfExpressionCause<'tcx> {
pub else_sp: Span, pub then_id: hir::HirId,
pub outer: Option<Span>, pub else_id: hir::HirId,
pub semicolon: Option<(Span, StatementAsExpression)>, pub then_ty: Ty<'tcx>,
pub else_ty: Ty<'tcx>,
pub outer_span: Option<Span>,
pub opt_suggest_box_span: Option<Span>, pub opt_suggest_box_span: Option<Span>,
} }

View file

@ -130,7 +130,6 @@ impl<N: fmt::Debug> fmt::Debug for traits::ImplSourceConstDestructData<N> {
// Lift implementations // Lift implementations
TrivialTypeTraversalAndLiftImpls! { TrivialTypeTraversalAndLiftImpls! {
super::IfExpressionCause,
super::ImplSourceDiscriminantKindData, super::ImplSourceDiscriminantKindData,
super::ImplSourcePointeeData, super::ImplSourcePointeeData,
} }

View file

@ -1729,7 +1729,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
} }
fn print_const(self, ct: ty::Const<'tcx>) -> Result<Self::Const, Self::Error> { fn print_const(self, ct: ty::Const<'tcx>) -> Result<Self::Const, Self::Error> {
self.pretty_print_const(ct, true) self.pretty_print_const(ct, false)
} }
fn path_crate(mut self, cnum: CrateNum) -> Result<Self::Path, Self::Error> { fn path_crate(mut self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {

View file

@ -28,6 +28,7 @@
//! return. //! return.
use crate::MirPass; use crate::MirPass;
use rustc_data_structures::fx::FxHashSet;
use rustc_index::vec::{Idx, IndexVec}; use rustc_index::vec::{Idx, IndexVec};
use rustc_middle::mir::coverage::*; use rustc_middle::mir::coverage::*;
use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
@ -267,7 +268,8 @@ pub fn remove_dead_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
return; return;
} }
let basic_blocks = body.basic_blocks_mut(); let basic_blocks = body.basic_blocks.as_mut();
let source_scopes = &body.source_scopes;
let mut replacements: Vec<_> = (0..num_blocks).map(BasicBlock::new).collect(); let mut replacements: Vec<_> = (0..num_blocks).map(BasicBlock::new).collect();
let mut used_blocks = 0; let mut used_blocks = 0;
for alive_index in reachable.iter() { for alive_index in reachable.iter() {
@ -282,7 +284,7 @@ pub fn remove_dead_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
} }
if tcx.sess.instrument_coverage() { if tcx.sess.instrument_coverage() {
save_unreachable_coverage(basic_blocks, used_blocks); save_unreachable_coverage(basic_blocks, source_scopes, used_blocks);
} }
basic_blocks.raw.truncate(used_blocks); basic_blocks.raw.truncate(used_blocks);
@ -311,56 +313,62 @@ pub fn remove_dead_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
/// `Unreachable` coverage statements. These are non-executable statements whose /// `Unreachable` coverage statements. These are non-executable statements whose
/// code regions are still recorded in the coverage map, representing regions /// code regions are still recorded in the coverage map, representing regions
/// with `0` executions. /// with `0` executions.
///
/// If there are no live `Counter` `Coverage` statements remaining, we remove
/// dead `Coverage` statements along with the dead blocks. Since at least one
/// counter per function is required by LLVM (and necessary, to add the
/// `function_hash` to the counter's call to the LLVM intrinsic
/// `instrprof.increment()`).
///
/// The `generator::StateTransform` MIR pass and MIR inlining can create
/// atypical conditions, where all live `Counter`s are dropped from the MIR.
///
/// With MIR inlining we can have coverage counters belonging to different
/// instances in a single body, so the strategy described above is applied to
/// coverage counters from each instance individually.
fn save_unreachable_coverage( fn save_unreachable_coverage(
basic_blocks: &mut IndexVec<BasicBlock, BasicBlockData<'_>>, basic_blocks: &mut IndexVec<BasicBlock, BasicBlockData<'_>>,
source_scopes: &IndexVec<SourceScope, SourceScopeData<'_>>,
first_dead_block: usize, first_dead_block: usize,
) { ) {
let has_live_counters = basic_blocks.raw[0..first_dead_block].iter().any(|live_block| { // Identify instances that still have some live coverage counters left.
live_block.statements.iter().any(|statement| { let mut live = FxHashSet::default();
if let StatementKind::Coverage(coverage) = &statement.kind { for basic_block in &basic_blocks.raw[0..first_dead_block] {
matches!(coverage.kind, CoverageKind::Counter { .. }) for statement in &basic_block.statements {
} else { let StatementKind::Coverage(coverage) = &statement.kind else { continue };
false let CoverageKind::Counter { .. } = coverage.kind else { continue };
} let instance = statement.source_info.scope.inlined_instance(source_scopes);
}) live.insert(instance);
}); }
if !has_live_counters { }
// If there are no live `Counter` `Coverage` statements anymore, don't
// move dead coverage to the `START_BLOCK`. Just allow the dead if live.is_empty() {
// `Coverage` statements to be dropped with the dead blocks.
//
// The `generator::StateTransform` MIR pass can create atypical
// conditions, where all live `Counter`s are dropped from the MIR.
//
// At least one Counter per function is required by LLVM (and necessary,
// to add the `function_hash` to the counter's call to the LLVM
// intrinsic `instrprof.increment()`).
return; return;
} }
// Retain coverage info for dead blocks, so coverage reports will still // Retain coverage for instances that still have some live counters left.
// report `0` executions for the uncovered code regions. let mut retained_coverage = Vec::new();
let mut dropped_coverage = Vec::new(); for dead_block in &basic_blocks.raw[first_dead_block..] {
for dead_block in basic_blocks.raw[first_dead_block..].iter() { for statement in &dead_block.statements {
for statement in dead_block.statements.iter() { let StatementKind::Coverage(coverage) = &statement.kind else { continue };
if let StatementKind::Coverage(coverage) = &statement.kind { let Some(code_region) = &coverage.code_region else { continue };
if let Some(code_region) = &coverage.code_region { let instance = statement.source_info.scope.inlined_instance(source_scopes);
dropped_coverage.push((statement.source_info, code_region.clone())); if live.contains(&instance) {
} retained_coverage.push((statement.source_info, code_region.clone()));
} }
} }
} }
let start_block = &mut basic_blocks[START_BLOCK]; let start_block = &mut basic_blocks[START_BLOCK];
for (source_info, code_region) in dropped_coverage { start_block.statements.extend(retained_coverage.into_iter().map(
start_block.statements.push(Statement { |(source_info, code_region)| Statement {
source_info, source_info,
kind: StatementKind::Coverage(Box::new(Coverage { kind: StatementKind::Coverage(Box::new(Coverage {
kind: CoverageKind::Unreachable, kind: CoverageKind::Unreachable,
code_region: Some(code_region), code_region: Some(code_region),
})), })),
}) },
} ));
} }
pub struct SimplifyLocals; pub struct SimplifyLocals;

View file

@ -98,6 +98,7 @@ mod merging;
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::sync; use rustc_data_structures::sync;
use rustc_hir::def_id::DefIdSet; use rustc_hir::def_id::DefIdSet;
use rustc_middle::mir;
use rustc_middle::mir::mono::MonoItem; use rustc_middle::mir::mono::MonoItem;
use rustc_middle::mir::mono::{CodegenUnit, Linkage}; use rustc_middle::mir::mono::{CodegenUnit, Linkage};
use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::print::with_no_trimmed_paths;
@ -479,9 +480,14 @@ fn codegened_and_inlined_items<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> &'tcx DefIdSe
if !visited.insert(did) { if !visited.insert(did) {
continue; continue;
} }
for scope in &tcx.instance_mir(instance.def).source_scopes { let body = tcx.instance_mir(instance.def);
if let Some((ref inlined, _)) = scope.inlined { for block in body.basic_blocks() {
result.insert(inlined.def_id()); for statement in &block.statements {
let mir::StatementKind::Coverage(_) = statement.kind else { continue };
let scope = statement.source_info.scope;
if let Some(inlined) = scope.inlined_instance(&body.source_scopes) {
result.insert(inlined.def_id());
}
} }
} }
} }

View file

@ -22,7 +22,6 @@ use rustc_hir::intravisit::Visitor;
use rustc_hir::GenericParam; use rustc_hir::GenericParam;
use rustc_hir::Item; use rustc_hir::Item;
use rustc_hir::Node; use rustc_hir::Node;
use rustc_infer::infer::error_reporting::same_type_modulo_infer;
use rustc_infer::traits::TraitEngine; use rustc_infer::traits::TraitEngine;
use rustc_middle::traits::select::OverflowError; use rustc_middle::traits::select::OverflowError;
use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::abstract_const::NotConstEvaluatable;
@ -640,7 +639,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
if expected.len() == 1 { "" } else { "s" }, if expected.len() == 1 { "" } else { "s" },
) )
); );
} else if !same_type_modulo_infer(given_ty, expected_ty) { } else if !self.same_type_modulo_infer(given_ty, expected_ty) {
// Print type mismatch // Print type mismatch
let (expected_args, given_args) = let (expected_args, given_args) =
self.cmp(given_ty, expected_ty); self.cmp(given_ty, expected_ty);

View file

@ -9,7 +9,6 @@ use rustc_span::Span;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
use rustc_trait_selection::traits::{ use rustc_trait_selection::traits::{
IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode, IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
StatementAsExpression,
}; };
impl<'a, 'tcx> FnCtxt<'a, 'tcx> { impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@ -75,8 +74,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}; };
let mut other_arms = vec![]; // Used only for diagnostics. let mut other_arms = vec![]; // Used only for diagnostics.
let mut prior_arm_ty = None; let mut prior_arm = None;
for (i, arm) in arms.iter().enumerate() { for arm in arms {
if let Some(g) = &arm.guard { if let Some(g) = &arm.guard {
self.diverges.set(Diverges::Maybe); self.diverges.set(Diverges::Maybe);
match g { match g {
@ -96,21 +95,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let opt_suggest_box_span = self.opt_suggest_box_span(arm_ty, orig_expected); let opt_suggest_box_span = self.opt_suggest_box_span(arm_ty, orig_expected);
let (arm_span, semi_span) = let (arm_block_id, arm_span) = if let hir::ExprKind::Block(blk, _) = arm.body.kind {
self.get_appropriate_arm_semicolon_removal_span(&arms, i, prior_arm_ty, arm_ty); (Some(blk.hir_id), self.find_block_span(blk))
let (span, code) = match i { } else {
(None, arm.body.span)
};
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.
0 => (arm_span, ObligationCauseCode::BlockTailExpression(arm.body.hir_id)), None => (arm_span, ObligationCauseCode::BlockTailExpression(arm.body.hir_id)),
_ => ( 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 {
arm_block_id,
arm_span, arm_span,
arm_ty,
prior_arm_block_id,
prior_arm_ty,
prior_arm_span,
scrut_span: scrut.span, scrut_span: scrut.span,
semi_span,
source: match_src, source: match_src,
prior_arms: other_arms.clone(), prior_arms: other_arms.clone(),
last_ty: prior_arm_ty.unwrap(),
scrut_hir_id: scrut.hir_id, scrut_hir_id: scrut.hir_id,
opt_suggest_box_span, opt_suggest_box_span,
})), })),
@ -139,7 +145,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let ret_ty = ret_coercion.borrow().expected_ty(); let ret_ty = ret_coercion.borrow().expected_ty();
let ret_ty = self.inh.infcx.shallow_resolve(ret_ty); let ret_ty = self.inh.infcx.shallow_resolve(ret_ty);
self.can_coerce(arm_ty, ret_ty) self.can_coerce(arm_ty, ret_ty)
&& prior_arm_ty.map_or(true, |t| self.can_coerce(t, ret_ty)) && prior_arm.map_or(true, |(_, t, _)| self.can_coerce(t, ret_ty))
// The match arms need to unify for the case of `impl Trait`. // The match arms need to unify for the case of `impl Trait`.
&& !matches!(ret_ty.kind(), ty::Opaque(..)) && !matches!(ret_ty.kind(), ty::Opaque(..))
} }
@ -181,7 +187,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if other_arms.len() > 5 { if other_arms.len() > 5 {
other_arms.remove(0); other_arms.remove(0);
} }
prior_arm_ty = Some(arm_ty);
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,
@ -207,28 +214,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
match_ty match_ty
} }
fn get_appropriate_arm_semicolon_removal_span(
&self,
arms: &'tcx [hir::Arm<'tcx>],
i: usize,
prior_arm_ty: Option<Ty<'tcx>>,
arm_ty: Ty<'tcx>,
) -> (Span, Option<(Span, StatementAsExpression)>) {
let arm = &arms[i];
let (arm_span, mut semi_span) = if let hir::ExprKind::Block(blk, _) = &arm.body.kind {
self.find_block_span(blk, prior_arm_ty)
} else {
(arm.body.span, None)
};
if semi_span.is_none() && i > 0 {
if let hir::ExprKind::Block(blk, _) = &arms[i - 1].body.kind {
let (_, semi_span_prev) = self.find_block_span(blk, Some(arm_ty));
semi_span = semi_span_prev;
}
}
(arm_span, semi_span)
}
/// When the previously checked expression (the scrutinee) diverges, /// When the previously checked expression (the scrutinee) diverges,
/// warn the user about the match arms being unreachable. /// warn the user about the match arms being unreachable.
fn warn_arms_when_scrutinee_diverges(&self, arms: &'tcx [hir::Arm<'tcx>]) { fn warn_arms_when_scrutinee_diverges(&self, arms: &'tcx [hir::Arm<'tcx>]) {
@ -313,7 +298,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
else_ty: Ty<'tcx>, else_ty: Ty<'tcx>,
opt_suggest_box_span: Option<Span>, opt_suggest_box_span: Option<Span>,
) -> ObligationCause<'tcx> { ) -> ObligationCause<'tcx> {
let mut outer_sp = if self.tcx.sess.source_map().is_multiline(span) { let mut outer_span = if self.tcx.sess.source_map().is_multiline(span) {
// The `if`/`else` isn't in one line in the output, include some context to make it // The `if`/`else` isn't in one line in the output, include some context to make it
// clear it is an if/else expression: // clear it is an if/else expression:
// ``` // ```
@ -339,69 +324,67 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
None None
}; };
let mut remove_semicolon = None; let (error_sp, else_id) = if let ExprKind::Block(block, _) = &else_expr.kind {
let error_sp = if let ExprKind::Block(block, _) = &else_expr.kind { let block = block.innermost_block();
let (error_sp, semi_sp) = self.find_block_span(block, Some(then_ty));
remove_semicolon = semi_sp; // Avoid overlapping spans that aren't as readable:
if block.expr.is_none() && block.stmts.is_empty() { // ```
// Avoid overlapping spans that aren't as readable: // 2 | let x = if true {
// ``` // | _____________-
// 2 | let x = if true { // 3 | | 3
// | _____________- // | | - expected because of this
// 3 | | 3 // 4 | | } else {
// | | - expected because of this // | |____________^
// 4 | | } else { // 5 | ||
// | |____________^ // 6 | || };
// 5 | || // | || ^
// 6 | || }; // | ||_____|
// | || ^ // | |______if and else have incompatible types
// | ||_____| // | expected integer, found `()`
// | |______if and else have incompatible types // ```
// | expected integer, found `()` // by not pointing at the entire expression:
// ``` // ```
// by not pointing at the entire expression: // 2 | let x = if true {
// ``` // | ------- `if` and `else` have incompatible types
// 2 | let x = if true { // 3 | 3
// | ------- `if` and `else` have incompatible types // | - expected because of this
// 3 | 3 // 4 | } else {
// | - expected because of this // | ____________^
// 4 | } else { // 5 | |
// | ____________^ // 6 | | };
// 5 | | // | |_____^ expected integer, found `()`
// 6 | | }; // ```
// | |_____^ expected integer, found `()` if block.expr.is_none() && block.stmts.is_empty()
// ``` && let Some(outer_span) = &mut outer_span
if outer_sp.is_some() { {
outer_sp = Some(self.tcx.sess.source_map().guess_head_span(span)); *outer_span = self.tcx.sess.source_map().guess_head_span(*outer_span);
}
} }
error_sp
(self.find_block_span(block), block.hir_id)
} else { } else {
// shouldn't happen unless the parser has done something weird (else_expr.span, else_expr.hir_id)
else_expr.span
}; };
// Compute `Span` of `then` part of `if`-expression. let then_id = if let ExprKind::Block(block, _) = &then_expr.kind {
let then_sp = if let ExprKind::Block(block, _) = &then_expr.kind { let block = block.innermost_block();
let (then_sp, semi_sp) = self.find_block_span(block, Some(else_ty)); // Exclude overlapping spans
remove_semicolon = remove_semicolon.or(semi_sp);
if block.expr.is_none() && block.stmts.is_empty() { if block.expr.is_none() && block.stmts.is_empty() {
outer_sp = None; // same as in `error_sp`; cleanup output outer_span = None;
} }
then_sp block.hir_id
} else { } else {
// shouldn't happen unless the parser has done something weird then_expr.hir_id
then_expr.span
}; };
// Finally construct the cause: // Finally construct the cause:
self.cause( self.cause(
error_sp, error_sp,
ObligationCauseCode::IfExpression(Box::new(IfExpressionCause { ObligationCauseCode::IfExpression(Box::new(IfExpressionCause {
then: then_sp, else_id,
else_sp: error_sp, then_id,
outer: outer_sp, then_ty,
semicolon: remove_semicolon, else_ty,
outer_span,
opt_suggest_box_span, opt_suggest_box_span,
})), })),
) )
@ -482,22 +465,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} }
} }
fn find_block_span(
&self,
block: &'tcx hir::Block<'tcx>,
expected_ty: Option<Ty<'tcx>>,
) -> (Span, Option<(Span, StatementAsExpression)>) {
if let Some(expr) = &block.expr {
(expr.span, None)
} else if let Some(stmt) = block.stmts.last() {
// possibly incorrect trailing `;` in the else arm
(stmt.span, expected_ty.and_then(|ty| self.could_remove_semicolon(block, ty)))
} else {
// empty block; point at its entirety
(block.span, None)
}
}
// When we have a `match` as a tail expression in a `fn` with a returned `impl Trait` // When we have a `match` as a tail expression in a `fn` with a returned `impl Trait`
// we check if the different arms would work with boxed trait objects instead and // we check if the different arms would work with boxed trait objects instead and
// provide a structured suggestion in that case. // provide a structured suggestion in that case.

View file

@ -30,17 +30,15 @@ use rustc_middle::ty::{
}; };
use rustc_session::lint; use rustc_session::lint;
use rustc_span::hygiene::DesugaringKind; use rustc_span::hygiene::DesugaringKind;
use rustc_span::source_map::{original_sp, DUMMY_SP};
use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::{self, BytePos, Span}; use rustc_span::{Span, DUMMY_SP};
use rustc_trait_selection::infer::InferCtxtExt as _; use rustc_trait_selection::infer::InferCtxtExt as _;
use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
use rustc_trait_selection::traits::{ use rustc_trait_selection::traits::{
self, ObligationCause, ObligationCauseCode, StatementAsExpression, TraitEngine, TraitEngineExt, self, ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt,
}; };
use std::collections::hash_map::Entry; use std::collections::hash_map::Entry;
use std::iter;
use std::slice; use std::slice;
impl<'a, 'tcx> FnCtxt<'a, 'tcx> { impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@ -1059,84 +1057,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
)); ));
} }
pub(in super::super) fn could_remove_semicolon(
&self,
blk: &'tcx hir::Block<'tcx>,
expected_ty: Ty<'tcx>,
) -> Option<(Span, StatementAsExpression)> {
// Be helpful when the user wrote `{... expr;}` and
// taking the `;` off is enough to fix the error.
let last_stmt = blk.stmts.last()?;
let hir::StmtKind::Semi(ref last_expr) = last_stmt.kind else {
return None;
};
let last_expr_ty = self.node_ty(last_expr.hir_id);
let needs_box = match (last_expr_ty.kind(), expected_ty.kind()) {
(ty::Opaque(last_def_id, _), ty::Opaque(exp_def_id, _))
if last_def_id == exp_def_id =>
{
StatementAsExpression::CorrectType
}
(ty::Opaque(last_def_id, last_bounds), ty::Opaque(exp_def_id, exp_bounds)) => {
debug!(
"both opaque, likely future {:?} {:?} {:?} {:?}",
last_def_id, last_bounds, exp_def_id, exp_bounds
);
let last_local_id = last_def_id.as_local()?;
let exp_local_id = exp_def_id.as_local()?;
match (
&self.tcx.hir().expect_item(last_local_id).kind,
&self.tcx.hir().expect_item(exp_local_id).kind,
) {
(
hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: last_bounds, .. }),
hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: exp_bounds, .. }),
) if iter::zip(*last_bounds, *exp_bounds).all(|(left, right)| {
match (left, right) {
(
hir::GenericBound::Trait(tl, ml),
hir::GenericBound::Trait(tr, mr),
) if tl.trait_ref.trait_def_id() == tr.trait_ref.trait_def_id()
&& ml == mr =>
{
true
}
(
hir::GenericBound::LangItemTrait(langl, _, _, argsl),
hir::GenericBound::LangItemTrait(langr, _, _, argsr),
) if langl == langr => {
// FIXME: consider the bounds!
debug!("{:?} {:?}", argsl, argsr);
true
}
_ => false,
}
}) =>
{
StatementAsExpression::NeedsBoxing
}
_ => StatementAsExpression::CorrectType,
}
}
_ => StatementAsExpression::CorrectType,
};
if (matches!(last_expr_ty.kind(), ty::Error(_))
|| self.can_sub(self.param_env, last_expr_ty, expected_ty).is_err())
&& matches!(needs_box, StatementAsExpression::CorrectType)
{
return None;
}
let span = if last_stmt.span.from_expansion() {
let mac_call = original_sp(last_stmt.span, blk.span);
self.tcx.sess.source_map().mac_call_stmt_semi_span(mac_call)?
} else {
last_stmt.span.with_lo(last_stmt.span.hi() - BytePos(1))
};
Some((span, needs_box))
}
// Instantiates the given path, which must refer to an item with the given // Instantiates the given path, which must refer to an item with the given
// number of type parameters and type. // number of type parameters and type.
#[instrument(skip(self, span), level = "debug")] #[instrument(skip(self, span), level = "debug")]

View file

@ -3,7 +3,6 @@ use crate::astconv::AstConv;
use crate::errors::{AddReturnTypeSuggestion, ExpectedReturnTypeLabel}; use crate::errors::{AddReturnTypeSuggestion, ExpectedReturnTypeLabel};
use rustc_ast::util::parser::ExprPrecedence; use rustc_ast::util::parser::ExprPrecedence;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{Applicability, Diagnostic, MultiSpan}; use rustc_errors::{Applicability, Diagnostic, MultiSpan};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind}; use rustc_hir::def::{CtorOf, DefKind};
@ -14,7 +13,7 @@ use rustc_hir::{
use rustc_infer::infer::{self, TyCtxtInferExt}; use rustc_infer::infer::{self, TyCtxtInferExt};
use rustc_infer::traits::{self, StatementAsExpression}; use rustc_infer::traits::{self, StatementAsExpression};
use rustc_middle::lint::in_external_macro; use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::{self, Binder, IsSuggestable, Subst, ToPredicate, Ty, TypeVisitable}; use rustc_middle::ty::{self, Binder, IsSuggestable, Subst, ToPredicate, Ty};
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
use rustc_span::Span; use rustc_span::Span;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
@ -904,117 +903,4 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
false false
} }
} }
pub(crate) fn consider_returning_binding(
&self,
blk: &'tcx hir::Block<'tcx>,
expected_ty: Ty<'tcx>,
err: &mut Diagnostic,
) {
let mut shadowed = FxHashSet::default();
let mut candidate_idents = vec![];
let mut find_compatible_candidates = |pat: &hir::Pat<'_>| {
if let hir::PatKind::Binding(_, hir_id, ident, _) = &pat.kind
&& let Some(pat_ty) = self.typeck_results.borrow().node_type_opt(*hir_id)
{
let pat_ty = self.resolve_vars_if_possible(pat_ty);
if self.can_coerce(pat_ty, expected_ty)
&& !(pat_ty, expected_ty).references_error()
&& shadowed.insert(ident.name)
{
candidate_idents.push((*ident, pat_ty));
}
}
true
};
let hir = self.tcx.hir();
for stmt in blk.stmts.iter().rev() {
let StmtKind::Local(local) = &stmt.kind else { continue; };
local.pat.walk(&mut find_compatible_candidates);
}
match hir.find(hir.get_parent_node(blk.hir_id)) {
Some(hir::Node::Expr(hir::Expr { hir_id, .. })) => {
match hir.find(hir.get_parent_node(*hir_id)) {
Some(hir::Node::Arm(hir::Arm { pat, .. })) => {
pat.walk(&mut find_compatible_candidates);
}
Some(
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body), .. })
| hir::Node::ImplItem(hir::ImplItem {
kind: hir::ImplItemKind::Fn(_, body),
..
})
| hir::Node::TraitItem(hir::TraitItem {
kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body)),
..
})
| hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Closure(hir::Closure { body, .. }),
..
}),
) => {
for param in hir.body(*body).params {
param.pat.walk(&mut find_compatible_candidates);
}
}
Some(hir::Node::Expr(hir::Expr {
kind:
hir::ExprKind::If(
hir::Expr { kind: hir::ExprKind::Let(let_), .. },
then_block,
_,
),
..
})) if then_block.hir_id == *hir_id => {
let_.pat.walk(&mut find_compatible_candidates);
}
_ => {}
}
}
_ => {}
}
match &candidate_idents[..] {
[(ident, _ty)] => {
let sm = self.tcx.sess.source_map();
if let Some(stmt) = blk.stmts.last() {
let stmt_span = sm.stmt_span(stmt.span, blk.span);
let sugg = if sm.is_multiline(blk.span)
&& let Some(spacing) = sm.indentation_before(stmt_span)
{
format!("\n{spacing}{ident}")
} else {
format!(" {ident}")
};
err.span_suggestion_verbose(
stmt_span.shrink_to_hi(),
format!("consider returning the local binding `{ident}`"),
sugg,
Applicability::MachineApplicable,
);
} else {
let sugg = if sm.is_multiline(blk.span)
&& let Some(spacing) = sm.indentation_before(blk.span.shrink_to_lo())
{
format!("\n{spacing} {ident}\n{spacing}")
} else {
format!(" {ident} ")
};
let left_span = sm.span_through_char(blk.span, '{').shrink_to_hi();
err.span_suggestion_verbose(
sm.span_extend_while(left_span, |c| c.is_whitespace()).unwrap_or(left_span),
format!("consider returning the local binding `{ident}`"),
sugg,
Applicability::MachineApplicable,
);
}
}
values if (1..3).contains(&values.len()) => {
let spans = values.iter().map(|(ident, _)| ident.span).collect::<Vec<_>>();
err.span_note(spans, "consider returning one of these bindings");
}
_ => {}
}
}
} }

View file

@ -97,7 +97,7 @@ impl<T: ?Sized> *const T {
/// refactored. /// refactored.
#[unstable(feature = "ptr_const_cast", issue = "92675")] #[unstable(feature = "ptr_const_cast", issue = "92675")]
#[rustc_const_unstable(feature = "ptr_const_cast", issue = "92675")] #[rustc_const_unstable(feature = "ptr_const_cast", issue = "92675")]
pub const fn as_mut(self) -> *mut T { pub const fn cast_mut(self) -> *mut T {
self as _ self as _
} }

View file

@ -96,11 +96,13 @@ impl<T: ?Sized> *mut T {
/// refactored. /// refactored.
/// ///
/// While not strictly required (`*mut T` coerces to `*const T`), this is provided for symmetry /// While not strictly required (`*mut T` coerces to `*const T`), this is provided for symmetry
/// with `as_mut()` on `*const T` and may have documentation value if used instead of implicit /// with [`cast_mut`] on `*const T` and may have documentation value if used instead of implicit
/// coercion. /// coercion.
///
/// [`cast_mut`]: #method.cast_mut
#[unstable(feature = "ptr_const_cast", issue = "92675")] #[unstable(feature = "ptr_const_cast", issue = "92675")]
#[rustc_const_unstable(feature = "ptr_const_cast", issue = "92675")] #[rustc_const_unstable(feature = "ptr_const_cast", issue = "92675")]
pub const fn as_const(self) -> *const T { pub const fn cast_const(self) -> *const T {
self as _ self as _
} }
@ -289,7 +291,7 @@ impl<T: ?Sized> *mut T {
/// For the mutable counterpart see [`as_mut`]. /// For the mutable counterpart see [`as_mut`].
/// ///
/// [`as_uninit_ref`]: #method.as_uninit_ref-1 /// [`as_uninit_ref`]: #method.as_uninit_ref-1
/// [`as_mut`]: #method.as_mut-1 /// [`as_mut`]: #method.as_mut
/// ///
/// # Safety /// # Safety
/// ///

View file

@ -1009,6 +1009,15 @@ impl<T, E> Result<T, E> {
/// Returns the contained [`Ok`] value, consuming the `self` value. /// Returns the contained [`Ok`] value, consuming the `self` value.
/// ///
/// Because this function may panic, its use is generally discouraged.
/// Instead, prefer to use pattern matching and handle the [`Err`]
/// case explicitly, or call [`unwrap_or`], [`unwrap_or_else`], or
/// [`unwrap_or_default`].
///
/// [`unwrap_or`]: Result::unwrap_or
/// [`unwrap_or_else`]: Result::unwrap_or_else
/// [`unwrap_or_default`]: Result::unwrap_or_default
///
/// # Panics /// # Panics
/// ///
/// Panics if the value is an [`Err`], with a panic message including the /// Panics if the value is an [`Err`], with a panic message including the

View file

@ -216,6 +216,15 @@ details.rustdoc-toggle > summary::before,
div.impl-items > div:not(.docblock):not(.item-info), div.impl-items > div:not(.docblock):not(.item-info),
.content ul.crate a.crate, .content ul.crate a.crate,
a.srclink, a.srclink,
#main-content > .since,
#help-button > button,
details.rustdoc-toggle.top-doc > summary,
details.rustdoc-toggle.top-doc > summary::before,
details.rustdoc-toggle.non-exhaustive > summary,
details.rustdoc-toggle.non-exhaustive > summary::before,
.scraped-example-title,
.more-examples-toggle summary, .more-examples-toggle .hide-more,
.example-links a,
/* This selector is for the items listed in the "all items" page. */ /* This selector is for the items listed in the "all items" page. */
#main-content > ul.docblock > li > a { #main-content > ul.docblock > li > a {
font-family: "Fira Sans", Arial, NanumBarunGothic, sans-serif; font-family: "Fira Sans", Arial, NanumBarunGothic, sans-serif;
@ -702,7 +711,6 @@ pre, .rustdoc.source .example-wrap {
} }
#main-content > .since { #main-content > .since {
top: inherit; top: inherit;
font-family: "Fira Sans", Arial, sans-serif;
} }
.content table:not(.table-display) { .content table:not(.table-display) {
@ -1518,7 +1526,6 @@ input:checked + .slider {
} }
#help-button > button { #help-button > button {
font-family: "Fira Sans", Arial, sans-serif;
text-align: center; text-align: center;
/* Rare exception to specifying font sizes in rem. Since this is acting /* Rare exception to specifying font sizes in rem. Since this is acting
as an icon, it's okay to specify their sizes in pixels. */ as an icon, it's okay to specify their sizes in pixels. */
@ -1690,7 +1697,6 @@ details.rustdoc-toggle.top-doc > summary,
details.rustdoc-toggle.top-doc > summary::before, details.rustdoc-toggle.top-doc > summary::before,
details.rustdoc-toggle.non-exhaustive > summary, details.rustdoc-toggle.non-exhaustive > summary,
details.rustdoc-toggle.non-exhaustive > summary::before { details.rustdoc-toggle.non-exhaustive > summary::before {
font-family: 'Fira Sans';
font-size: 1rem; font-size: 1rem;
} }
@ -2176,10 +2182,6 @@ in storage.js plus the media query with (min-width: 701px)
border-radius: 50px; border-radius: 50px;
} }
.scraped-example-title {
font-family: 'Fira Sans';
}
.scraped-example .code-wrapper { .scraped-example .code-wrapper {
position: relative; position: relative;
display: flex; display: flex;
@ -2283,10 +2285,6 @@ in storage.js plus the media query with (min-width: 701px)
cursor: pointer; cursor: pointer;
} }
.more-examples-toggle summary, .more-examples-toggle .hide-more {
font-family: 'Fira Sans';
}
.more-scraped-examples { .more-scraped-examples {
margin-left: 5px; margin-left: 5px;
display: flex; display: flex;
@ -2321,7 +2319,6 @@ in storage.js plus the media query with (min-width: 701px)
.example-links a { .example-links a {
margin-top: 20px; margin-top: 20px;
font-family: 'Fira Sans';
} }
.example-links ul { .example-links ul {

View file

@ -0,0 +1,21 @@
1| |// Regression test for issue #98833.
2| |// compile-flags: -Zinline-mir
3| |
4| 1|fn main() {
5| 1| println!("{}", live::<false>());
6| 1|}
7| |
8| |#[inline]
9| 1|fn live<const B: bool>() -> u32 {
10| 1| if B {
11| 0| dead()
12| | } else {
13| 1| 0
14| | }
15| 1|}
16| |
17| |#[inline]
18| 0|fn dead() -> u32 {
19| 0| 42
20| 0|}

View file

@ -0,0 +1,20 @@
// Regression test for issue #98833.
// compile-flags: -Zinline-mir
fn main() {
println!("{}", live::<false>());
}
#[inline]
fn live<const B: bool>() -> u32 {
if B {
dead()
} else {
0
}
}
#[inline]
fn dead() -> u32 {
42
}

View file

@ -7,7 +7,7 @@ pub struct Simd<T, const WIDTH: usize> {
inner: T, inner: T,
} }
// @has foo/struct.Simd.html '//div[@id="trait-implementations-list"]//h3[@class="code-header in-band"]' 'impl Add<Simd<u8, 16_usize>> for Simd<u8, 16>' // @has foo/struct.Simd.html '//div[@id="trait-implementations-list"]//h3[@class="code-header in-band"]' 'impl Add<Simd<u8, 16>> for Simd<u8, 16>'
impl Add for Simd<u8, 16> { impl Add for Simd<u8, 16> {
type Output = Self; type Output = Self;

View file

@ -1,5 +1,5 @@
#![crate_name = "foo"] #![crate_name = "foo"]
// @has foo/struct.Foo.html '//pre[@class="rust struct"]' \ // @has foo/struct.Foo.html '//pre[@class="rust struct"]' \
// 'pub struct Foo<const M: usize = 10_usize, const N: usize = M, T = i32>(_);' // 'pub struct Foo<const M: usize = 10, const N: usize = M, T = i32>(_);'
pub struct Foo<const M: usize = 10, const N: usize = M, T = i32>(T); pub struct Foo<const M: usize = 10, const N: usize = M, T = i32>(T);

View file

@ -19,8 +19,8 @@ pub use extern_crate::WTrait;
// @has foo/trait.Trait.html '//pre[@class="rust trait"]' \ // @has foo/trait.Trait.html '//pre[@class="rust trait"]' \
// 'pub trait Trait<const N: usize>' // 'pub trait Trait<const N: usize>'
// @has - '//*[@id="impl-Trait%3C1_usize%3E-for-u8"]//h3[@class="code-header in-band"]' 'impl Trait<1_usize> for u8' // @has - '//*[@id="impl-Trait%3C1%3E-for-u8"]//h3[@class="code-header in-band"]' 'impl Trait<1> for u8'
// @has - '//*[@id="impl-Trait%3C2_usize%3E-for-u8"]//h3[@class="code-header in-band"]' 'impl Trait<2_usize> for u8' // @has - '//*[@id="impl-Trait%3C2%3E-for-u8"]//h3[@class="code-header in-band"]' 'impl Trait<2> for u8'
// @has - '//*[@id="impl-Trait%3C{1%20+%202}%3E-for-u8"]//h3[@class="code-header in-band"]' 'impl Trait<{1 + 2}> for u8' // @has - '//*[@id="impl-Trait%3C{1%20+%202}%3E-for-u8"]//h3[@class="code-header in-band"]' 'impl Trait<{1 + 2}> for u8'
// @has - '//*[@id="impl-Trait%3CN%3E-for-%5Bu8%3B%20N%5D"]//h3[@class="code-header in-band"]' \ // @has - '//*[@id="impl-Trait%3CN%3E-for-%5Bu8%3B%20N%5D"]//h3[@class="code-header in-band"]' \
// 'impl<const N: usize> Trait<N> for [u8; N]' // 'impl<const N: usize> Trait<N> for [u8; N]'

View file

@ -44,11 +44,11 @@ struct WithParameters<T, const N: usize, M = u32> {
} }
impl<T> WithParameters<T, 1> { impl<T> WithParameters<T, 1> {
fn with_ref(&self) {} //~ ERROR passing `WithParameters<T, 1_usize>` by reference fn with_ref(&self) {} //~ ERROR passing `WithParameters<T, 1>` by reference
} }
impl<T> WithParameters<T, 1, u8> { impl<T> WithParameters<T, 1, u8> {
fn with_ref(&self) {} //~ ERROR passing `WithParameters<T, 1_usize, u8>` by reference fn with_ref(&self) {} //~ ERROR passing `WithParameters<T, 1, u8>` by reference
} }
fn main() {} fn main() {}

View file

@ -22,17 +22,17 @@ error: passing `Foo` by reference
LL | fn with_ref(&self) {} LL | fn with_ref(&self) {}
| ^^^^^ help: try passing by value: `Foo` | ^^^^^ help: try passing by value: `Foo`
error: passing `WithParameters<T, 1_usize>` by reference error: passing `WithParameters<T, 1>` by reference
--> $DIR/rustc_pass_by_value_self.rs:47:17 --> $DIR/rustc_pass_by_value_self.rs:47:17
| |
LL | fn with_ref(&self) {} LL | fn with_ref(&self) {}
| ^^^^^ help: try passing by value: `WithParameters<T, 1_usize>` | ^^^^^ help: try passing by value: `WithParameters<T, 1>`
error: passing `WithParameters<T, 1_usize, u8>` by reference error: passing `WithParameters<T, 1, u8>` by reference
--> $DIR/rustc_pass_by_value_self.rs:51:17 --> $DIR/rustc_pass_by_value_self.rs:51:17
| |
LL | fn with_ref(&self) {} LL | fn with_ref(&self) {}
| ^^^^^ help: try passing by value: `WithParameters<T, 1_usize, u8>` | ^^^^^ help: try passing by value: `WithParameters<T, 1, u8>`
error: aborting due to 5 previous errors error: aborting due to 5 previous errors

View file

@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/match_arr_unknown_len.rs:3:9 --> $DIR/match_arr_unknown_len.rs:3:9
| |
LL | [1, 2] => true, LL | [1, 2] => true,
| ^^^^^^ expected `2_usize`, found `N` | ^^^^^^ expected `2`, found `N`
| |
= note: expected array `[u32; 2]` = note: expected array `[u32; 2]`
found array `[u32; N]` found array `[u32; N]`

View file

@ -18,14 +18,6 @@ LL | | break 0u8;
LL | | }; LL | | };
| |_________- enclosing `async` block | |_________- enclosing `async` block
error[E0271]: type mismatch resolving `<impl Future<Output = u8> as Future>::Output == ()`
--> $DIR/async-block-control-flow-static-semantics.rs:26:39
|
LL | let _: &dyn Future<Output = ()> = &block;
| ^^^^^^ expected `()`, found `u8`
|
= note: required for the cast from `impl Future<Output = u8>` to the object type `dyn Future<Output = ()>`
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/async-block-control-flow-static-semantics.rs:21:58 --> $DIR/async-block-control-flow-static-semantics.rs:21:58
| |
@ -40,7 +32,7 @@ LL | | }
| |_^ expected `u8`, found `()` | |_^ expected `u8`, found `()`
error[E0271]: type mismatch resolving `<impl Future<Output = u8> as Future>::Output == ()` error[E0271]: type mismatch resolving `<impl Future<Output = u8> as Future>::Output == ()`
--> $DIR/async-block-control-flow-static-semantics.rs:17:39 --> $DIR/async-block-control-flow-static-semantics.rs:26:39
| |
LL | let _: &dyn Future<Output = ()> = &block; LL | let _: &dyn Future<Output = ()> = &block;
| ^^^^^^ expected `()`, found `u8` | ^^^^^^ expected `()`, found `u8`
@ -55,6 +47,14 @@ LL | fn return_targets_async_block_not_fn() -> u8 {
| | | |
| implicitly returns `()` as its body has no tail or `return` expression | implicitly returns `()` as its body has no tail or `return` expression
error[E0271]: type mismatch resolving `<impl Future<Output = u8> as Future>::Output == ()`
--> $DIR/async-block-control-flow-static-semantics.rs:17:39
|
LL | let _: &dyn Future<Output = ()> = &block;
| ^^^^^^ expected `()`, found `u8`
|
= note: required for the cast from `impl Future<Output = u8>` to the object type `dyn Future<Output = ()>`
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/async-block-control-flow-static-semantics.rs:47:44 --> $DIR/async-block-control-flow-static-semantics.rs:47:44
| |

View file

@ -4,7 +4,7 @@ error[E0277]: the trait bound `u16: Bar<N>` is not satisfied
LL | type Assoc = u16; LL | type Assoc = u16;
| ^^^ the trait `Bar<N>` is not implemented for `u16` | ^^^ the trait `Bar<N>` is not implemented for `u16`
| |
= help: the trait `Bar<3_usize>` is implemented for `u16` = help: the trait `Bar<3>` is implemented for `u16`
note: required by a bound in `Foo::Assoc` note: required by a bound in `Foo::Assoc`
--> $DIR/associated-type-bound-fail.rs:4:17 --> $DIR/associated-type-bound-fail.rs:4:17
| |

View file

@ -2,10 +2,10 @@ error[E0308]: mismatched types
--> $DIR/generic-expr-default-concrete.rs:10:5 --> $DIR/generic-expr-default-concrete.rs:10:5
| |
LL | Foo::<10, 12> LL | Foo::<10, 12>
| ^^^^^^^^^^^^^ expected `11_usize`, found `12_usize` | ^^^^^^^^^^^^^ expected `11`, found `12`
| |
= note: expected type `11_usize` = note: expected type `11`
found type `12_usize` found type `12`
error: aborting due to previous error error: aborting due to previous error

View file

@ -1,22 +1,22 @@
pub struct Example<const N: usize=13>; pub struct Example<const N: usize = 13>;
pub struct Example2<T=u32, const N: usize=13>(T); pub struct Example2<T = u32, const N: usize = 13>(T);
pub struct Example3<const N: usize=13, T=u32>(T); pub struct Example3<const N: usize = 13, T = u32>(T);
pub struct Example4<const N: usize=13, const M: usize=4>; pub struct Example4<const N: usize = 13, const M: usize = 4>;
fn main() { fn main() {
let e: Example::<13> = (); let e: Example<13> = ();
//~^ Error: mismatched types //~^ Error: mismatched types
//~| expected struct `Example` //~| expected struct `Example`
let e: Example2::<u32, 13> = (); let e: Example2<u32, 13> = ();
//~^ Error: mismatched types //~^ Error: mismatched types
//~| expected struct `Example2` //~| expected struct `Example2`
let e: Example3::<13, u32> = (); let e: Example3<13, u32> = ();
//~^ Error: mismatched types //~^ Error: mismatched types
//~| expected struct `Example3` //~| expected struct `Example3`
let e: Example3::<7> = (); let e: Example3<7> = ();
//~^ Error: mismatched types //~^ Error: mismatched types
//~| expected struct `Example3<7_usize>` //~| expected struct `Example3<7>`
let e: Example4::<7> = (); let e: Example4<7> = ();
//~^ Error: mismatched types //~^ Error: mismatched types
//~| expected struct `Example4<7_usize>` //~| expected struct `Example4<7>`
} }

View file

@ -1,8 +1,8 @@
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/mismatch.rs:7:28 --> $DIR/mismatch.rs:7:26
| |
LL | let e: Example::<13> = (); LL | let e: Example<13> = ();
| ------------- ^^ expected struct `Example`, found `()` | ----------- ^^ expected struct `Example`, found `()`
| | | |
| expected due to this | expected due to this
| |
@ -10,10 +10,10 @@ LL | let e: Example::<13> = ();
found unit type `()` found unit type `()`
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/mismatch.rs:10:34 --> $DIR/mismatch.rs:10:32
| |
LL | let e: Example2::<u32, 13> = (); LL | let e: Example2<u32, 13> = ();
| ------------------- ^^ expected struct `Example2`, found `()` | ----------------- ^^ expected struct `Example2`, found `()`
| | | |
| expected due to this | expected due to this
| |
@ -21,10 +21,10 @@ LL | let e: Example2::<u32, 13> = ();
found unit type `()` found unit type `()`
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/mismatch.rs:13:34 --> $DIR/mismatch.rs:13:32
| |
LL | let e: Example3::<13, u32> = (); LL | let e: Example3<13, u32> = ();
| ------------------- ^^ expected struct `Example3`, found `()` | ----------------- ^^ expected struct `Example3`, found `()`
| | | |
| expected due to this | expected due to this
| |
@ -32,25 +32,25 @@ LL | let e: Example3::<13, u32> = ();
found unit type `()` found unit type `()`
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/mismatch.rs:16:28 --> $DIR/mismatch.rs:16:26
| |
LL | let e: Example3::<7> = (); LL | let e: Example3<7> = ();
| ------------- ^^ expected struct `Example3`, found `()` | ----------- ^^ expected struct `Example3`, found `()`
| | | |
| expected due to this | expected due to this
| |
= note: expected struct `Example3<7_usize>` = note: expected struct `Example3<7>`
found unit type `()` found unit type `()`
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/mismatch.rs:19:28 --> $DIR/mismatch.rs:19:26
| |
LL | let e: Example4::<7> = (); LL | let e: Example4<7> = ();
| ------------- ^^ expected struct `Example4`, found `()` | ----------- ^^ expected struct `Example4`, found `()`
| | | |
| expected due to this | expected due to this
| |
= note: expected struct `Example4<7_usize>` = note: expected struct `Example4<7>`
found unit type `()` found unit type `()`
error: aborting due to 5 previous errors error: aborting due to 5 previous errors

View file

@ -4,16 +4,15 @@ trait Trait {}
impl<const N: u32> Trait for Uwu<N> {} impl<const N: u32> Trait for Uwu<N> {}
fn rawr() -> impl Trait { fn rawr() -> impl Trait {
//~^ error: the trait bound `Uwu<10_u32, 12_u32>: Trait` is not satisfied //~^ error: the trait bound `Uwu<10, 12>: Trait` is not satisfied
Uwu::<10, 12> Uwu::<10, 12>
} }
trait Traitor<const N: u8 = 1, const M: u8 = N> { } trait Traitor<const N: u8 = 1, const M: u8 = N> {}
impl<const N: u8> Traitor<N, 2> for u32 {} impl<const N: u8> Traitor<N, 2> for u32 {}
impl Traitor<1, 2> for u64 {} impl Traitor<1, 2> for u64 {}
fn uwu<const N: u8>() -> impl Traitor<N> { fn uwu<const N: u8>() -> impl Traitor<N> {
//~^ error: the trait bound `u32: Traitor<N>` is not satisfied //~^ error: the trait bound `u32: Traitor<N>` is not satisfied
1_u32 1_u32

View file

@ -1,16 +1,16 @@
error[E0277]: the trait bound `Uwu<10_u32, 12_u32>: Trait` is not satisfied error[E0277]: the trait bound `Uwu<10, 12>: Trait` is not satisfied
--> $DIR/rp_impl_trait_fail.rs:6:14 --> $DIR/rp_impl_trait_fail.rs:6:14
| |
LL | fn rawr() -> impl Trait { LL | fn rawr() -> impl Trait {
| ^^^^^^^^^^ the trait `Trait` is not implemented for `Uwu<10_u32, 12_u32>` | ^^^^^^^^^^ the trait `Trait` is not implemented for `Uwu<10, 12>`
LL | LL |
LL | Uwu::<10, 12> LL | Uwu::<10, 12>
| ------------- return type was inferred to be `Uwu<10_u32, 12_u32>` here | ------------- return type was inferred to be `Uwu<10, 12>` here
| |
= help: the trait `Trait` is implemented for `Uwu<N>` = help: the trait `Trait` is implemented for `Uwu<N>`
error[E0277]: the trait bound `u32: Traitor<N>` is not satisfied error[E0277]: the trait bound `u32: Traitor<N>` is not satisfied
--> $DIR/rp_impl_trait_fail.rs:17:26 --> $DIR/rp_impl_trait_fail.rs:16:26
| |
LL | fn uwu<const N: u8>() -> impl Traitor<N> { LL | fn uwu<const N: u8>() -> impl Traitor<N> {
| ^^^^^^^^^^^^^^^ the trait `Traitor<N>` is not implemented for `u32` | ^^^^^^^^^^^^^^^ the trait `Traitor<N>` is not implemented for `u32`
@ -19,11 +19,11 @@ LL | 1_u32
| ----- return type was inferred to be `u32` here | ----- return type was inferred to be `u32` here
| |
= help: the following other types implement trait `Traitor<N, M>`: = help: the following other types implement trait `Traitor<N, M>`:
<u32 as Traitor<N, 2_u8>> <u32 as Traitor<N, 2>>
<u64 as Traitor<1_u8, 2_u8>> <u64 as Traitor<1, 2>>
error[E0277]: the trait bound `u64: Traitor` is not satisfied error[E0277]: the trait bound `u64: Traitor` is not satisfied
--> $DIR/rp_impl_trait_fail.rs:22:13 --> $DIR/rp_impl_trait_fail.rs:21:13
| |
LL | fn owo() -> impl Traitor { LL | fn owo() -> impl Traitor {
| ^^^^^^^^^^^^ the trait `Traitor` is not implemented for `u64` | ^^^^^^^^^^^^ the trait `Traitor` is not implemented for `u64`
@ -32,8 +32,8 @@ LL | 1_u64
| ----- return type was inferred to be `u64` here | ----- return type was inferred to be `u64` here
| |
= help: the following other types implement trait `Traitor<N, M>`: = help: the following other types implement trait `Traitor<N, M>`:
<u32 as Traitor<N, 2_u8>> <u32 as Traitor<N, 2>>
<u64 as Traitor<1_u8, 2_u8>> <u64 as Traitor<1, 2>>
error: aborting due to 3 previous errors error: aborting due to 3 previous errors

View file

@ -16,7 +16,7 @@ trait Traitor<const N: u8 = 1, const M: u8 = N> {
} }
} }
impl Traitor<2, 3> for bool { } impl Traitor<2, 3> for bool {}
fn bar<const N: u8>(arg: &dyn Traitor<N>) -> u8 { fn bar<const N: u8>(arg: &dyn Traitor<N>) -> u8 {
arg.owo() arg.owo()
@ -26,5 +26,5 @@ fn main() {
foo(&10_u32); foo(&10_u32);
//~^ error: the trait bound `u32: Trait` is not satisfied //~^ error: the trait bound `u32: Trait` is not satisfied
bar(&true); bar(&true);
//~^ error: the trait bound `bool: Traitor<{_: u8}>` is not satisfied //~^ error: the trait bound `bool: Traitor<_>` is not satisfied
} }

View file

@ -6,19 +6,19 @@ LL | foo(&10_u32);
| | | |
| required by a bound introduced by this call | required by a bound introduced by this call
| |
= help: the trait `Trait<2_u8>` is implemented for `u32` = help: the trait `Trait<2>` is implemented for `u32`
= note: required for the cast from `u32` to the object type `dyn Trait` = note: required for the cast from `u32` to the object type `dyn Trait`
error[E0277]: the trait bound `bool: Traitor<{_: u8}>` is not satisfied error[E0277]: the trait bound `bool: Traitor<_>` is not satisfied
--> $DIR/trait_objects_fail.rs:28:9 --> $DIR/trait_objects_fail.rs:28:9
| |
LL | bar(&true); LL | bar(&true);
| --- ^^^^^ the trait `Traitor<{_: u8}>` is not implemented for `bool` | --- ^^^^^ the trait `Traitor<_>` is not implemented for `bool`
| | | |
| required by a bound introduced by this call | required by a bound introduced by this call
| |
= help: the trait `Traitor<2_u8, 3_u8>` is implemented for `bool` = help: the trait `Traitor<2, 3>` is implemented for `bool`
= note: required for the cast from `bool` to the object type `dyn Traitor<{_: u8}>` = note: required for the cast from `bool` to the object type `dyn Traitor<_>`
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View file

@ -3,16 +3,20 @@ struct Ooopsies<const N: u8 = { u8::MAX + 1 }>;
trait Trait<const N: u8> {} trait Trait<const N: u8> {}
impl Trait<3> for () {} impl Trait<3> for () {}
struct WhereClause<const N: u8 = 2> where (): Trait<N>; struct WhereClause<const N: u8 = 2>
//~^ error: the trait bound `(): Trait<2_u8>` is not satisfied where
(): Trait<N>;
//~^ error: the trait bound `(): Trait<2>` is not satisfied
trait Traitor<T, const N: u8> {} trait Traitor<T, const N: u8> {}
struct WhereClauseTooGeneric<T = u32, const N: u8 = 2>(T) where (): Traitor<T, N>; struct WhereClauseTooGeneric<T = u32, const N: u8 = 2>(T)
where
(): Traitor<T, N>;
// no error on struct def // no error on struct def
struct DependentDefaultWfness<const N: u8 = 1, T = WhereClause<N>>(T); struct DependentDefaultWfness<const N: u8 = 1, T = WhereClause<N>>(T);
fn foo() -> DependentDefaultWfness { fn foo() -> DependentDefaultWfness {
//~^ error: the trait bound `(): Trait<1_u8>` is not satisfied //~^ error: the trait bound `(): Trait<1>` is not satisfied
loop {} loop {}
} }

View file

@ -4,26 +4,29 @@ error[E0080]: evaluation of constant value failed
LL | struct Ooopsies<const N: u8 = { u8::MAX + 1 }>; LL | struct Ooopsies<const N: u8 = { u8::MAX + 1 }>;
| ^^^^^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow | ^^^^^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow
error[E0277]: the trait bound `(): Trait<2_u8>` is not satisfied error[E0277]: the trait bound `(): Trait<2>` is not satisfied
--> $DIR/wfness.rs:6:47 --> $DIR/wfness.rs:8:9
| |
LL | struct WhereClause<const N: u8 = 2> where (): Trait<N>; LL | (): Trait<N>;
| ^^^^^^^^ the trait `Trait<2_u8>` is not implemented for `()` | ^^^^^^^^ the trait `Trait<2>` is not implemented for `()`
| |
= help: the trait `Trait<3_u8>` is implemented for `()` = help: the trait `Trait<3>` is implemented for `()`
error[E0277]: the trait bound `(): Trait<1_u8>` is not satisfied error[E0277]: the trait bound `(): Trait<1>` is not satisfied
--> $DIR/wfness.rs:14:13 --> $DIR/wfness.rs:18:13
| |
LL | fn foo() -> DependentDefaultWfness { LL | fn foo() -> DependentDefaultWfness {
| ^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<1_u8>` is not implemented for `()` | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<1>` is not implemented for `()`
| |
= help: the trait `Trait<3_u8>` is implemented for `()` = help: the trait `Trait<3>` is implemented for `()`
note: required by a bound in `WhereClause` note: required by a bound in `WhereClause`
--> $DIR/wfness.rs:6:47 --> $DIR/wfness.rs:8:9
| |
LL | struct WhereClause<const N: u8 = 2> where (): Trait<N>; LL | struct WhereClause<const N: u8 = 2>
| ^^^^^^^^ required by this bound in `WhereClause` | ----------- required by a bound in this
LL | where
LL | (): Trait<N>;
| ^^^^^^^^ required by this bound in `WhereClause`
error: aborting due to 3 previous errors error: aborting due to 3 previous errors

View file

@ -2,10 +2,10 @@ error[E0308]: mismatched types
--> $DIR/different_generic_args.rs:11:9 --> $DIR/different_generic_args.rs:11:9
| |
LL | u = ConstUsize::<4> {}; LL | u = ConstUsize::<4> {};
| ^^^^^^^^^^^^^^^^^^ expected `3_usize`, found `4_usize` | ^^^^^^^^^^^^^^^^^^ expected `3`, found `4`
| |
= note: expected struct `ConstUsize<3_usize>` = note: expected struct `ConstUsize<3>`
found struct `ConstUsize<4_usize>` found struct `ConstUsize<4>`
error: aborting due to previous error error: aborting due to previous error

View file

@ -2,10 +2,10 @@ error[E0308]: mismatched types
--> $DIR/different_generic_args.rs:11:9 --> $DIR/different_generic_args.rs:11:9
| |
LL | u = ConstUsize::<4> {}; LL | u = ConstUsize::<4> {};
| ^^^^^^^^^^^^^^^^^^ expected `3_usize`, found `4_usize` | ^^^^^^^^^^^^^^^^^^ expected `3`, found `4`
| |
= note: expected struct `ConstUsize<3_usize>` = note: expected struct `ConstUsize<3>`
found struct `ConstUsize<4_usize>` found struct `ConstUsize<4>`
error: aborting due to previous error error: aborting due to previous error

View file

@ -2,10 +2,10 @@ error[E0308]: mismatched types
--> $DIR/different_generic_args_array.rs:9:9 --> $DIR/different_generic_args_array.rs:9:9
| |
LL | x = Const::<{ [4] }> {}; LL | x = Const::<{ [4] }> {};
| ^^^^^^^^^^^^^^^^^^^ expected `[3_usize]`, found `[4_usize]` | ^^^^^^^^^^^^^^^^^^^ expected `[3]`, found `[4]`
| |
= note: expected struct `Const<[3_usize]>` = note: expected struct `Const<[3]>`
found struct `Const<[4_usize]>` found struct `Const<[4]>`
error: aborting due to previous error error: aborting due to previous error

View file

@ -5,14 +5,14 @@ LL | <() as Foo<N>>::test()
| ^^^^^^^^^^^^^^^^^^^^ the trait `Foo<N>` is not implemented for `()` | ^^^^^^^^^^^^^^^^^^^^ the trait `Foo<N>` is not implemented for `()`
| |
= help: the following other types implement trait `Foo<N>`: = help: the following other types implement trait `Foo<N>`:
<() as Foo<0_u8>> <() as Foo<0>>
<() as Foo<100_u8>> <() as Foo<100>>
<() as Foo<101_u8>> <() as Foo<101>>
<() as Foo<102_u8>> <() as Foo<102>>
<() as Foo<103_u8>> <() as Foo<103>>
<() as Foo<104_u8>> <() as Foo<104>>
<() as Foo<105_u8>> <() as Foo<105>>
<() as Foo<106_u8>> <() as Foo<106>>
and 248 others and 248 others
error: aborting due to previous error error: aborting due to previous error

View file

@ -14,7 +14,7 @@ LL | fn ty_fn() -> Bar<i32, _> {
| ---------^- | ---------^-
| | | | | |
| | not allowed in type signatures | | not allowed in type signatures
| help: replace with the correct return type: `Bar<i32, 3_usize>` | help: replace with the correct return type: `Bar<i32, 3>`
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
--> $DIR/in-signature.rs:17:25 --> $DIR/in-signature.rs:17:25
@ -24,7 +24,7 @@ LL | fn ty_fn_mixed() -> Bar<_, _> {
| | | | | | | |
| | | not allowed in type signatures | | | not allowed in type signatures
| | not allowed in type signatures | | not allowed in type signatures
| help: replace with the correct return type: `Bar<i32, 3_usize>` | help: replace with the correct return type: `Bar<i32, 3>`
error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
--> $DIR/in-signature.rs:22:15 --> $DIR/in-signature.rs:22:15
@ -45,7 +45,7 @@ LL | const TY_CT: Bar<i32, _> = Bar::<i32, 3>(0);
| ^^^^^^^^^^^ | ^^^^^^^^^^^
| | | |
| not allowed in type signatures | not allowed in type signatures
| help: replace with the correct type: `Bar<i32, 3_usize>` | help: replace with the correct type: `Bar<i32, 3>`
error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables
--> $DIR/in-signature.rs:28:19 --> $DIR/in-signature.rs:28:19
@ -54,7 +54,7 @@ LL | static TY_STATIC: Bar<i32, _> = Bar::<i32, 3>(0);
| ^^^^^^^^^^^ | ^^^^^^^^^^^
| | | |
| not allowed in type signatures | not allowed in type signatures
| help: replace with the correct type: `Bar<i32, 3_usize>` | help: replace with the correct type: `Bar<i32, 3>`
error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
--> $DIR/in-signature.rs:30:20 --> $DIR/in-signature.rs:30:20
@ -63,7 +63,7 @@ LL | const TY_CT_MIXED: Bar<_, _> = Bar::<i32, 3>(0);
| ^^^^^^^^^ | ^^^^^^^^^
| | | |
| not allowed in type signatures | not allowed in type signatures
| help: replace with the correct type: `Bar<i32, 3_usize>` | help: replace with the correct type: `Bar<i32, 3>`
error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables
--> $DIR/in-signature.rs:32:25 --> $DIR/in-signature.rs:32:25
@ -72,7 +72,7 @@ LL | static TY_STATIC_MIXED: Bar<_, _> = Bar::<i32, 3>(0);
| ^^^^^^^^^ | ^^^^^^^^^
| | | |
| not allowed in type signatures | not allowed in type signatures
| help: replace with the correct type: `Bar<i32, 3_usize>` | help: replace with the correct type: `Bar<i32, 3>`
error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
--> $DIR/in-signature.rs:35:21 --> $DIR/in-signature.rs:35:21

View file

@ -56,19 +56,19 @@ error[E0308]: mismatched types
--> $DIR/abstract-const-as-cast-3.rs:23:5 --> $DIR/abstract-const-as-cast-3.rs:23:5
| |
LL | assert_impl::<HasCastInTraitImpl<13, { 12 as u128 }>>(); LL | assert_impl::<HasCastInTraitImpl<13, { 12 as u128 }>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `12_u128`, found `13_u128` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `12`, found `13`
| |
= note: expected type `12_u128` = note: expected type `12`
found type `13_u128` found type `13`
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/abstract-const-as-cast-3.rs:25:5 --> $DIR/abstract-const-as-cast-3.rs:25:5
| |
LL | assert_impl::<HasCastInTraitImpl<14, 13>>(); LL | assert_impl::<HasCastInTraitImpl<14, 13>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `13_u128`, found `14_u128` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `13`, found `14`
| |
= note: expected type `13_u128` = note: expected type `13`
found type `14_u128` found type `14`
error: unconstrained generic constant error: unconstrained generic constant
--> $DIR/abstract-const-as-cast-3.rs:35:5 --> $DIR/abstract-const-as-cast-3.rs:35:5
@ -128,19 +128,19 @@ error[E0308]: mismatched types
--> $DIR/abstract-const-as-cast-3.rs:41:5 --> $DIR/abstract-const-as-cast-3.rs:41:5
| |
LL | assert_impl::<HasCastInTraitImpl<13, { 12 as u128 }>>(); LL | assert_impl::<HasCastInTraitImpl<13, { 12 as u128 }>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `12_u128`, found `13_u128` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `12`, found `13`
| |
= note: expected type `12_u128` = note: expected type `12`
found type `13_u128` found type `13`
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/abstract-const-as-cast-3.rs:43:5 --> $DIR/abstract-const-as-cast-3.rs:43:5
| |
LL | assert_impl::<HasCastInTraitImpl<14, 13>>(); LL | assert_impl::<HasCastInTraitImpl<14, 13>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `13_u128`, found `14_u128` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `13`, found `14`
| |
= note: expected type `13_u128` = note: expected type `13`
found type `14_u128` found type `14`
error: aborting due to 12 previous errors error: aborting due to 12 previous errors

View file

@ -2,7 +2,7 @@
#![allow(incomplete_features)] #![allow(incomplete_features)]
fn test<const N: usize>() -> [u8; N - 1] { fn test<const N: usize>() -> [u8; N - 1] {
//~^ ERROR evaluation of `test::<0_usize>::{constant#0}` failed //~^ ERROR evaluation of `test::<0>::{constant#0}` failed
todo!() todo!()
} }

View file

@ -1,4 +1,4 @@
error[E0080]: evaluation of `test::<0_usize>::{constant#0}` failed error[E0080]: evaluation of `test::<0>::{constant#0}` failed
--> $DIR/from-sig-fail.rs:4:35 --> $DIR/from-sig-fail.rs:4:35
| |
LL | fn test<const N: usize>() -> [u8; N - 1] { LL | fn test<const N: usize>() -> [u8; N - 1] {

View file

@ -4,14 +4,14 @@ error[E0423]: expected value, found type parameter `T`
LL | impl<T> Bar<T> for [u8; T] {} LL | impl<T> Bar<T> for [u8; T] {}
| ^ not a value | ^ not a value
error[E0599]: the function or associated item `foo` exists for struct `Foo<{_: usize}>`, but its trait bounds were not satisfied error[E0599]: the function or associated item `foo` exists for struct `Foo<_>`, but its trait bounds were not satisfied
--> $DIR/issue-69654.rs:17:10 --> $DIR/issue-69654.rs:17:10
| |
LL | struct Foo<const N: usize> {} LL | struct Foo<const N: usize> {}
| -------------------------- function or associated item `foo` not found for this struct | -------------------------- function or associated item `foo` not found for this struct
... ...
LL | Foo::foo(); LL | Foo::foo();
| ^^^ function or associated item cannot be called on `Foo<{_: usize}>` due to unsatisfied trait bounds | ^^^ function or associated item cannot be called on `Foo<_>` due to unsatisfied trait bounds
| |
= note: the following trait bounds were not satisfied: = note: the following trait bounds were not satisfied:
`[u8; _]: Bar<[(); _]>` `[u8; _]: Bar<[(); _]>`

View file

@ -34,21 +34,21 @@ LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True,
= help: const parameters may only be used as standalone arguments, i.e. `J` = help: const parameters may only be used as standalone arguments, i.e. `J`
= help: use `#![feature(generic_const_exprs)]` to allow generic const expressions = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
error[E0283]: type annotations needed: cannot satisfy `IsLessOrEqual<I, 8_u32>: True` error[E0283]: type annotations needed: cannot satisfy `IsLessOrEqual<I, 8>: True`
--> $DIR/issue-72787.rs:21:26 --> $DIR/issue-72787.rs:21:26
| |
LL | IsLessOrEqual<I, 8>: True, LL | IsLessOrEqual<I, 8>: True,
| ^^^^ | ^^^^
| |
= note: cannot satisfy `IsLessOrEqual<I, 8_u32>: True` = note: cannot satisfy `IsLessOrEqual<I, 8>: True`
error[E0283]: type annotations needed: cannot satisfy `IsLessOrEqual<I, 8_u32>: True` error[E0283]: type annotations needed: cannot satisfy `IsLessOrEqual<I, 8>: True`
--> $DIR/issue-72787.rs:21:26 --> $DIR/issue-72787.rs:21:26
| |
LL | IsLessOrEqual<I, 8>: True, LL | IsLessOrEqual<I, 8>: True,
| ^^^^ | ^^^^
| |
= note: cannot satisfy `IsLessOrEqual<I, 8_u32>: True` = note: cannot satisfy `IsLessOrEqual<I, 8>: True`
error: aborting due to 6 previous errors error: aborting due to 6 previous errors

View file

@ -2,10 +2,13 @@
#![allow(incomplete_features)] #![allow(incomplete_features)]
type Arr<const N: usize> = [u8; N - 1]; type Arr<const N: usize> = [u8; N - 1];
//~^ ERROR evaluation of `Arr::<0_usize>::{constant#0}` failed //~^ ERROR evaluation of `Arr::<0>::{constant#0}` failed
fn test<const N: usize>() -> Arr<N> where [u8; N - 1]: Sized { fn test<const N: usize>() -> Arr<N>
//~^ ERROR evaluation of `test::<0_usize>::{constant#0}` failed where
[u8; N - 1]: Sized,
//~^ ERROR evaluation of `test::<0>::{constant#0}` failed
{
todo!() todo!()
} }

View file

@ -1,10 +1,10 @@
error[E0080]: evaluation of `test::<0_usize>::{constant#0}` failed error[E0080]: evaluation of `test::<0>::{constant#0}` failed
--> $DIR/simple_fail.rs:7:48 --> $DIR/simple_fail.rs:9:10
| |
LL | fn test<const N: usize>() -> Arr<N> where [u8; N - 1]: Sized { LL | [u8; N - 1]: Sized,
| ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow | ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow
error[E0080]: evaluation of `Arr::<0_usize>::{constant#0}` failed error[E0080]: evaluation of `Arr::<0>::{constant#0}` failed
--> $DIR/simple_fail.rs:4:33 --> $DIR/simple_fail.rs:4:33
| |
LL | type Arr<const N: usize> = [u8; N - 1]; LL | type Arr<const N: usize> = [u8; N - 1];

View file

@ -6,8 +6,8 @@ LL | let _: [u8; 17] = foo();
| |
help: consider specifying the generic arguments help: consider specifying the generic arguments
| |
LL | let _: [u8; 17] = foo::<17_usize, M>(); LL | let _: [u8; 17] = foo::<17, M>();
| +++++++++++++++ | +++++++++
error: aborting due to previous error error: aborting due to previous error

View file

@ -8,12 +8,12 @@ LL | | value: 3,
LL | | nested: &Bar(5), LL | | nested: &Bar(5),
LL | | } LL | | }
LL | | }> = x; LL | | }> = x;
| | - ^ expected `Foo { value: 3_i32, nested: &Bar::<i32>(5_i32) }`, found `Foo { value: 3_i32, nested: &Bar::<i32>(4_i32) }` | | - ^ expected `Foo { value: 3, nested: &Bar::<i32>(5) }`, found `Foo { value: 3, nested: &Bar::<i32>(4) }`
| |______| | |______|
| expected due to this | expected due to this
| |
= note: expected struct `Test<Foo { value: 3_i32, nested: &Bar::<i32>(5_i32) }>` = note: expected struct `Test<Foo { value: 3, nested: &Bar::<i32>(5) }>`
found struct `Test<Foo { value: 3_i32, nested: &Bar::<i32>(4_i32) }>` found struct `Test<Foo { value: 3, nested: &Bar::<i32>(4) }>`
error: aborting due to previous error error: aborting due to previous error

View file

@ -1,4 +1,4 @@
error[E0015]: cannot call non-const fn `Foo::{constant#0}::Foo::<17_usize>::value` in constants error[E0015]: cannot call non-const fn `Foo::{constant#0}::Foo::<17>::value` in constants
--> $DIR/nested-type.rs:15:5 --> $DIR/nested-type.rs:15:5
| |
LL | Foo::<17>::value() LL | Foo::<17>::value()

View file

@ -1,10 +1,10 @@
error[E0277]: the trait bound `A<{_: usize}>: Bar<{_: usize}>` is not satisfied error[E0277]: the trait bound `A<_>: Bar<_>` is not satisfied
--> $DIR/unused-substs-1.rs:12:13 --> $DIR/unused-substs-1.rs:12:13
| |
LL | let _ = A; LL | let _ = A;
| ^ the trait `Bar<{_: usize}>` is not implemented for `A<{_: usize}>` | ^ the trait `Bar<_>` is not implemented for `A<_>`
| |
= help: the trait `Bar<N>` is implemented for `A<7_usize>` = help: the trait `Bar<N>` is implemented for `A<7>`
note: required by a bound in `A` note: required by a bound in `A`
--> $DIR/unused-substs-1.rs:9:11 --> $DIR/unused-substs-1.rs:9:11
| |

View file

@ -2,10 +2,10 @@ error[E0308]: mismatched types
--> $DIR/types-mismatch-const-args.rs:14:41 --> $DIR/types-mismatch-const-args.rs:14:41
| |
LL | let _: A<'a, u32, {2u32}, {3u32}> = A::<'a, u32, {2u32 + 2u32}, {3u32}> { data: PhantomData }; LL | let _: A<'a, u32, {2u32}, {3u32}> = A::<'a, u32, {2u32 + 2u32}, {3u32}> { data: PhantomData };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `2_u32`, found `4_u32` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `2`, found `4`
| |
= note: expected type `2_u32` = note: expected type `2`
found type `4_u32` found type `4`
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/types-mismatch-const-args.rs:16:41 --> $DIR/types-mismatch-const-args.rs:16:41
@ -26,8 +26,8 @@ LL | let _: A<'a, u16, {4u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data
| | | |
| expected due to this | expected due to this
| |
= note: expected struct `A<'a, u16, 4_u32, _>` = note: expected struct `A<'a, u16, 4, _>`
found struct `A<'b, u32, 2_u32, _>` found struct `A<'b, u32, 2, _>`
error: aborting due to 3 previous errors error: aborting due to 3 previous errors

View file

@ -2,12 +2,12 @@ error[E0308]: mismatched types
--> $DIR/types-mismatch-const-args.rs:14:41 --> $DIR/types-mismatch-const-args.rs:14:41
| |
LL | let _: A<'a, u32, {2u32}, {3u32}> = A::<'a, u32, {2u32 + 2u32}, {3u32}> { data: PhantomData }; LL | let _: A<'a, u32, {2u32}, {3u32}> = A::<'a, u32, {2u32 + 2u32}, {3u32}> { data: PhantomData };
| -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `2_u32`, found `4_u32` | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `2`, found `4`
| | | |
| expected due to this | expected due to this
| |
= note: expected struct `A<'_, _, 2_u32, _>` = note: expected struct `A<'_, _, 2, _>`
found struct `A<'_, _, 4_u32, _>` found struct `A<'_, _, 4, _>`
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/types-mismatch-const-args.rs:16:41 --> $DIR/types-mismatch-const-args.rs:16:41
@ -28,8 +28,8 @@ LL | let _: A<'a, u16, {4u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data
| | | |
| expected due to this | expected due to this
| |
= note: expected struct `A<'a, u16, 4_u32, _>` = note: expected struct `A<'a, u16, 4, _>`
found struct `A<'b, u32, 2_u32, _>` found struct `A<'b, u32, 2, _>`
error: aborting due to 3 previous errors error: aborting due to 3 previous errors

View file

@ -1,10 +1,10 @@
error[E0080]: evaluation of `post_monomorphization_error::ValidateConstImm::<2_i32, 0_i32, 1_i32>::VALID` failed error[E0080]: evaluation of `post_monomorphization_error::ValidateConstImm::<2, 0, 1>::VALID` failed
--> $DIR/auxiliary/post_monomorphization_error.rs:7:17 --> $DIR/auxiliary/post_monomorphization_error.rs:7:17
| |
LL | let _ = 1 / ((IMM >= MIN && IMM <= MAX) as usize); LL | let _ = 1 / ((IMM >= MIN && IMM <= MAX) as usize);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to divide `1_usize` by zero | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to divide `1_usize` by zero
note: the above error was encountered while instantiating `fn post_monomorphization_error::stdarch_intrinsic::<2_i32>` note: the above error was encountered while instantiating `fn post_monomorphization_error::stdarch_intrinsic::<2>`
--> $DIR/issue-85155.rs:19:5 --> $DIR/issue-85155.rs:19:5
| |
LL | post_monomorphization_error::stdarch_intrinsic::<2>(); LL | post_monomorphization_error::stdarch_intrinsic::<2>();

View file

@ -104,7 +104,7 @@ error[E0366]: `Drop` impls cannot be specialized
LL | impl Drop for X<3> { fn drop(&mut self) { } } // REJECT LL | impl Drop for X<3> { fn drop(&mut self) { } } // REJECT
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
= note: `3_usize` is not a generic parameter = note: `3` is not a generic parameter
note: use the same sequence of generic lifetime, type and const parameters as the struct definition note: use the same sequence of generic lifetime, type and const parameters as the struct definition
--> $DIR/reject-specialized-drops-8142.rs:17:1 --> $DIR/reject-specialized-drops-8142.rs:17:1
| |

View file

@ -12,13 +12,13 @@ note: the above error was encountered while instantiating `fn foo::<i32>`
LL | foo::<i32>(); LL | foo::<i32>();
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^
error[E0080]: evaluation of `bar::<0_usize>::{constant#0}` failed error[E0080]: evaluation of `bar::<0>::{constant#0}` failed
--> $DIR/const-expr-generic-err.rs:9:13 --> $DIR/const-expr-generic-err.rs:9:13
| |
LL | const { N - 1 } LL | const { N - 1 }
| ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow | ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow
note: the above error was encountered while instantiating `fn bar::<0_usize>` note: the above error was encountered while instantiating `fn bar::<0>`
--> $DIR/const-expr-generic-err.rs:14:5 --> $DIR/const-expr-generic-err.rs:14:5
| |
LL | bar::<0>(); LL | bar::<0>();

View file

@ -7,8 +7,6 @@ LL | let t8 = t8n(t7, t7p(f, g));
| required by a bound introduced by this call | required by a bound introduced by this call
| |
= help: the trait `Fn<(_,)>` is not implemented for `impl Fn(((_, _), _))` = help: the trait `Fn<(_,)>` is not implemented for `impl Fn(((_, _), _))`
= note: expected a closure with arguments `(((_, _), _),)`
found a closure with arguments `(_,)`
note: required by a bound in `t8n` note: required by a bound in `t8n`
--> $DIR/issue-59494.rs:5:45 --> $DIR/issue-59494.rs:5:45
| |

View file

@ -116,7 +116,7 @@ warning: taking a reference to a function item does not give a function pointer
--> $DIR/function-item-references.rs:118:22 --> $DIR/function-item-references.rs:118:22
| |
LL | println!("{:p}", &take_generic_array::<u32, 4>); LL | println!("{:p}", &take_generic_array::<u32, 4>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: cast `take_generic_array` to obtain a function pointer: `take_generic_array::<u32, 4_usize> as fn(_)` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: cast `take_generic_array` to obtain a function pointer: `take_generic_array::<u32, 4> as fn(_)`
warning: taking a reference to a function item does not give a function pointer warning: taking a reference to a function item does not give a function pointer
--> $DIR/function-item-references.rs:120:22 --> $DIR/function-item-references.rs:120:22
@ -128,7 +128,7 @@ warning: taking a reference to a function item does not give a function pointer
--> $DIR/function-item-references.rs:122:22 --> $DIR/function-item-references.rs:122:22
| |
LL | println!("{:p}", &multiple_generic_arrays::<u32, f32, 4, 8>); LL | println!("{:p}", &multiple_generic_arrays::<u32, f32, 4, 8>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: cast `multiple_generic_arrays` to obtain a function pointer: `multiple_generic_arrays::<u32, f32, 4_usize, 8_usize> as fn(_, _)` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: cast `multiple_generic_arrays` to obtain a function pointer: `multiple_generic_arrays::<u32, f32, 4, 8> as fn(_, _)`
warning: taking a reference to a function item does not give a function pointer warning: taking a reference to a function item does not give a function pointer
--> $DIR/function-item-references.rs:124:22 --> $DIR/function-item-references.rs:124:22

View file

@ -61,13 +61,13 @@ impl Other {
fn other(&self) {} fn other(&self) {}
} }
struct Struct<T>{ struct Struct<T> {
_phatom: PhantomData<T> _phatom: PhantomData<T>,
} }
impl<T> Default for Struct<T> { impl<T> Default for Struct<T> {
fn default() -> Self { fn default() -> Self {
Self{ _phatom: PhantomData } Self { _phatom: PhantomData }
} }
} }
@ -76,9 +76,9 @@ impl<T: Clone + Copy + PartialEq + Eq + PartialOrd + Ord> Struct<T> {
} }
fn main() { fn main() {
let point_f64 = Point{ x: 1_f64, y: 1_f64}; let point_f64 = Point { x: 1_f64, y: 1_f64 };
let d = point_f64.distance(); let d = point_f64.distance();
let point_i32 = Point{ x: 1_i32, y: 1_i32}; let point_i32 = Point { x: 1_i32, y: 1_i32 };
let d = point_i32.distance(); let d = point_i32.distance();
//~^ ERROR no method named `distance` found for struct `Point<i32> //~^ ERROR no method named `distance` found for struct `Point<i32>
let d = point_i32.other(); let d = point_i32.other();
@ -92,9 +92,9 @@ fn main() {
wrapper.other(); wrapper.other();
//~^ ERROR no method named `other` found for struct `Wrapper //~^ ERROR no method named `other` found for struct `Wrapper
let boolean = true; let boolean = true;
let wrapper = Wrapper2::<'_, _, 3> {x: &boolean}; let wrapper = Wrapper2::<'_, _, 3> { x: &boolean };
wrapper.method(); wrapper.method();
//~^ ERROR no method named `method` found for struct `Wrapper2<'_, bool, 3_usize> //~^ ERROR no method named `method` found for struct `Wrapper2<'_, bool, 3>
wrapper.other(); wrapper.other();
//~^ ERROR no method named `other` found for struct `Wrapper2 //~^ ERROR no method named `other` found for struct `Wrapper2
let a = vec![1, 2, 3]; let a = vec![1, 2, 3];

View file

@ -50,14 +50,14 @@ LL | struct Wrapper<T>(T);
LL | wrapper.other(); LL | wrapper.other();
| ^^^^^ method not found in `Wrapper<bool>` | ^^^^^ method not found in `Wrapper<bool>`
error[E0599]: no method named `method` found for struct `Wrapper2<'_, bool, 3_usize>` in the current scope error[E0599]: no method named `method` found for struct `Wrapper2<'_, bool, 3>` in the current scope
--> $DIR/method-not-found-generic-arg-elision.rs:96:13 --> $DIR/method-not-found-generic-arg-elision.rs:96:13
| |
LL | struct Wrapper2<'a, T, const C: usize> { LL | struct Wrapper2<'a, T, const C: usize> {
| -------------------------------------- method `method` not found for this struct | -------------------------------------- method `method` not found for this struct
... ...
LL | wrapper.method(); LL | wrapper.method();
| ^^^^^^ method not found in `Wrapper2<'_, bool, 3_usize>` | ^^^^^^ method not found in `Wrapper2<'_, bool, 3>`
| |
= note: the method was found for = note: the method was found for
- `Wrapper2<'a, i8, C>` - `Wrapper2<'a, i8, C>`
@ -71,7 +71,7 @@ LL | struct Wrapper2<'a, T, const C: usize> {
| -------------------------------------- method `other` not found for this struct | -------------------------------------- method `other` not found for this struct
... ...
LL | wrapper.other(); LL | wrapper.other();
| ^^^^^ method not found in `Wrapper2<'_, bool, 3_usize>` | ^^^^^ method not found in `Wrapper2<'_, bool, 3>`
error[E0599]: no method named `not_found` found for struct `Vec<{integer}>` in the current scope error[E0599]: no method named `not_found` found for struct `Vec<{integer}>` in the current scope
--> $DIR/method-not-found-generic-arg-elision.rs:101:7 --> $DIR/method-not-found-generic-arg-elision.rs:101:7
@ -82,7 +82,7 @@ LL | a.not_found();
error[E0599]: the method `method` exists for struct `Struct<f64>`, but its trait bounds were not satisfied error[E0599]: the method `method` exists for struct `Struct<f64>`, but its trait bounds were not satisfied
--> $DIR/method-not-found-generic-arg-elision.rs:104:7 --> $DIR/method-not-found-generic-arg-elision.rs:104:7
| |
LL | struct Struct<T>{ LL | struct Struct<T> {
| ---------------- method `method` not found for this struct | ---------------- method `method` not found for this struct
... ...
LL | s.method(); LL | s.method();

View file

@ -1,10 +1,10 @@
error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 2, found `Simd<u32, 4_usize>` with length 4 error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 2, found `Simd<u32, 4>` with length 4
--> $DIR/generic-shuffle.rs:24:31 --> $DIR/generic-shuffle.rs:24:31
| |
LL | let _: Simd<u32, 4> = simd_shuffle(v, v, I); LL | let _: Simd<u32, 4> = simd_shuffle(v, v, I);
| ^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `u32` (element of input `Simd<u32, 4_usize>`), found `Simd<f32, 2_usize>` with element type `f32` error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `u32` (element of input `Simd<u32, 4>`), found `Simd<f32, 2>` with element type `f32`
--> $DIR/generic-shuffle.rs:27:31 --> $DIR/generic-shuffle.rs:27:31
| |
LL | let _: Simd<f32, 2> = simd_shuffle(v, v, I); LL | let _: Simd<f32, 2> = simd_shuffle(v, v, I);

View file

@ -2,37 +2,37 @@ error[E0599]: no method named `ceil` found for struct `Simd` in the current scop
--> $DIR/libm_no_std_cant_float.rs:14:17 --> $DIR/libm_no_std_cant_float.rs:14:17
| |
LL | let _xc = x.ceil(); LL | let _xc = x.ceil();
| ^^^^ method not found in `Simd<f32, 4_usize>` | ^^^^ method not found in `Simd<f32, 4>`
error[E0599]: no method named `floor` found for struct `Simd` in the current scope error[E0599]: no method named `floor` found for struct `Simd` in the current scope
--> $DIR/libm_no_std_cant_float.rs:15:17 --> $DIR/libm_no_std_cant_float.rs:15:17
| |
LL | let _xf = x.floor(); LL | let _xf = x.floor();
| ^^^^^ method not found in `Simd<f32, 4_usize>` | ^^^^^ method not found in `Simd<f32, 4>`
error[E0599]: no method named `round` found for struct `Simd` in the current scope error[E0599]: no method named `round` found for struct `Simd` in the current scope
--> $DIR/libm_no_std_cant_float.rs:16:17 --> $DIR/libm_no_std_cant_float.rs:16:17
| |
LL | let _xr = x.round(); LL | let _xr = x.round();
| ^^^^^ method not found in `Simd<f32, 4_usize>` | ^^^^^ method not found in `Simd<f32, 4>`
error[E0599]: no method named `trunc` found for struct `Simd` in the current scope error[E0599]: no method named `trunc` found for struct `Simd` in the current scope
--> $DIR/libm_no_std_cant_float.rs:17:17 --> $DIR/libm_no_std_cant_float.rs:17:17
| |
LL | let _xt = x.trunc(); LL | let _xt = x.trunc();
| ^^^^^ method not found in `Simd<f32, 4_usize>` | ^^^^^ method not found in `Simd<f32, 4>`
error[E0599]: no method named `mul_add` found for struct `Simd` in the current scope error[E0599]: no method named `mul_add` found for struct `Simd` in the current scope
--> $DIR/libm_no_std_cant_float.rs:18:19 --> $DIR/libm_no_std_cant_float.rs:18:19
| |
LL | let _xfma = x.mul_add(x, x); LL | let _xfma = x.mul_add(x, x);
| ^^^^^^^ method not found in `Simd<f32, 4_usize>` | ^^^^^^^ method not found in `Simd<f32, 4>`
error[E0599]: no method named `sqrt` found for struct `Simd` in the current scope error[E0599]: no method named `sqrt` found for struct `Simd` in the current scope
--> $DIR/libm_no_std_cant_float.rs:19:20 --> $DIR/libm_no_std_cant_float.rs:19:20
| |
LL | let _xsqrt = x.sqrt(); LL | let _xsqrt = x.sqrt();
| ^^^^ method not found in `Simd<f32, 4_usize>` | ^^^^ method not found in `Simd<f32, 4>`
error: aborting due to 6 previous errors error: aborting due to 6 previous errors

View file

@ -2,7 +2,7 @@
#![feature(repr_simd, platform_intrinsics)] #![feature(repr_simd, platform_intrinsics)]
// error-pattern:monomorphising SIMD type `Simd<0_usize>` of zero length // error-pattern:monomorphising SIMD type `Simd<0>` of zero length
#[repr(simd)] #[repr(simd)]
struct Simd<const N: usize>([f32; N]); struct Simd<const N: usize>([f32; N]);

View file

@ -1,4 +1,4 @@
error: monomorphising SIMD type `Simd<0_usize>` of zero length error: monomorphising SIMD type `Simd<0>` of zero length
error: aborting due to previous error error: aborting due to previous error

View file

@ -2,7 +2,7 @@
#![feature(repr_simd, platform_intrinsics)] #![feature(repr_simd, platform_intrinsics)]
// error-pattern:monomorphising SIMD type `Simd<65536_usize>` of length greater than 32768 // error-pattern:monomorphising SIMD type `Simd<65536>` of length greater than 32768
#[repr(simd)] #[repr(simd)]
struct Simd<const N: usize>([f32; N]); struct Simd<const N: usize>([f32; N]);

View file

@ -1,4 +1,4 @@
error: monomorphising SIMD type `Simd<65536_usize>` of length greater than 32768 error: monomorphising SIMD type `Simd<65536>` of length greater than 32768
error: aborting due to previous error error: aborting due to previous error

View file

@ -1,23 +0,0 @@
// run-rustfix
#![allow(unused)]
fn a(i: i32) -> i32 { i }
//~^ ERROR mismatched types
fn b(opt_str: Option<String>) {
let s: String = if let Some(s) = opt_str {
s
//~^ ERROR mismatched types
} else {
String::new()
};
}
fn c() -> Option<i32> {
//~^ ERROR mismatched types
let x = Some(1);
x
}
fn main() {}

View file

@ -1,5 +1,3 @@
// run-rustfix
#![allow(unused)] #![allow(unused)]
fn a(i: i32) -> i32 {} fn a(i: i32) -> i32 {}
@ -18,4 +16,36 @@ fn c() -> Option<i32> {
let x = Some(1); let x = Some(1);
} }
fn d(opt_str: Option<String>) {
let s: String = if let Some(s) = opt_str {
//~^ ERROR mismatched types
} else {
String::new()
};
}
fn d2(opt_str: Option<String>) {
let s = if let Some(s) = opt_str {
} else {
String::new()
//~^ ERROR `if` and `else` have incompatible types
};
}
fn e(opt_str: Option<String>) {
let s: String = match opt_str {
Some(s) => {}
//~^ ERROR mismatched types
None => String::new(),
};
}
fn e2(opt_str: Option<String>) {
let s = match opt_str {
Some(s) => {}
None => String::new(),
//~^ ERROR `match` arms have incompatible types
};
}
fn main() {} fn main() {}

View file

@ -1,5 +1,5 @@
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/return-bindings.rs:5:17 --> $DIR/return-bindings.rs:3:17
| |
LL | fn a(i: i32) -> i32 {} LL | fn a(i: i32) -> i32 {}
| - ^^^ expected `i32`, found `()` | - ^^^ expected `i32`, found `()`
@ -12,7 +12,7 @@ LL | fn a(i: i32) -> i32 { i }
| + | +
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/return-bindings.rs:9:46 --> $DIR/return-bindings.rs:7:46
| |
LL | let s: String = if let Some(s) = opt_str { LL | let s: String = if let Some(s) = opt_str {
| ______________________________________________^ | ______________________________________________^
@ -28,7 +28,7 @@ LL ~
| |
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/return-bindings.rs:16:11 --> $DIR/return-bindings.rs:14:11
| |
LL | fn c() -> Option<i32> { LL | fn c() -> Option<i32> {
| - ^^^^^^^^^^^ expected enum `Option`, found `()` | - ^^^^^^^^^^^ expected enum `Option`, found `()`
@ -43,6 +43,68 @@ LL ~ let x = Some(1);
LL + x LL + x
| |
error: aborting due to 3 previous errors error[E0308]: mismatched types
--> $DIR/return-bindings.rs:20:46
|
LL | let s: String = if let Some(s) = opt_str {
| ______________________________________________^
LL | |
LL | | } else {
| |_____^ expected struct `String`, found `()`
|
help: consider returning the local binding `s`
|
LL ~ let s: String = if let Some(s) = opt_str {
LL + s
LL ~
|
error[E0308]: `if` and `else` have incompatible types
--> $DIR/return-bindings.rs:30:9
|
LL | let s = if let Some(s) = opt_str {
| ______________________________________-
LL | | } else {
| |_____- expected because of this
LL | String::new()
| ^^^^^^^^^^^^^ expected `()`, found struct `String`
|
help: consider returning the local binding `s`
|
LL ~ let s = if let Some(s) = opt_str {
LL + s
LL ~ } else {
|
error[E0308]: mismatched types
--> $DIR/return-bindings.rs:37:20
|
LL | Some(s) => {}
| ^^ expected struct `String`, found `()`
|
help: consider returning the local binding `s`
|
LL | Some(s) => { s }
| +
error[E0308]: `match` arms have incompatible types
--> $DIR/return-bindings.rs:46:17
|
LL | let s = match opt_str {
| _____________-
LL | | Some(s) => {}
| | -- this is found to be of type `()`
LL | | None => String::new(),
| | ^^^^^^^^^^^^^ expected `()`, found struct `String`
LL | |
LL | | };
| |_____- `match` arms have incompatible types
|
help: consider returning the local binding `s`
|
LL | Some(s) => { s }
| +
error: aborting due to 7 previous errors
For more information about this error, try `rustc --explain E0308`. For more information about this error, try `rustc --explain E0308`.

View file

@ -25,7 +25,7 @@ error: non-defining opaque type use in defining scope
LL | 7u32 LL | 7u32
| ^^^^ | ^^^^
| |
note: used non-generic constant `123_usize` for generic parameter note: used non-generic constant `123` for generic parameter
--> $DIR/generic_nondefining_use.rs:11:15 --> $DIR/generic_nondefining_use.rs:11:15
| |
LL | type OneConst<const X: usize> = impl Debug; LL | type OneConst<const X: usize> = impl Debug;