Skip to content

Commit 6be8a06

Browse files
committed
Auto merge of rust-lang#87698 - camsteffen:rollup-yvjfc26, r=camsteffen
Rollup of 6 pull requests Successful merges: - rust-lang#86176 (Implement a `explicit_generic_args_with_impl_trait` feature gate) - rust-lang#87654 (Add documentation for the order of Option and Result) - rust-lang#87659 (Fix invalid suggestions for non-ASCII characters in byte constants) - rust-lang#87673 (Tweak opaque type mismatch error) - rust-lang#87687 (Inline some macros) - rust-lang#87690 (Add missing "allocated object" doc link to `<*mut T>::add`) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 3227e35 + 7fc26e9 commit 6be8a06

32 files changed

+437
-170
lines changed

compiler/rustc_ast_lowering/src/expr.rs

+4-12
Original file line numberDiff line numberDiff line change
@@ -442,18 +442,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
442442
then: &Block,
443443
else_opt: Option<&Expr>,
444444
) -> hir::ExprKind<'hir> {
445-
macro_rules! make_if {
446-
($opt:expr) => {{
447-
let cond = self.lower_expr(cond);
448-
let then_expr = self.lower_block_expr(then);
449-
hir::ExprKind::If(cond, self.arena.alloc(then_expr), $opt)
450-
}};
451-
}
452-
if let Some(rslt) = else_opt {
453-
make_if!(Some(self.lower_expr(rslt)))
454-
} else {
455-
make_if!(None)
456-
}
445+
let cond = self.lower_expr(cond);
446+
let then = self.arena.alloc(self.lower_block_expr(then));
447+
let els = else_opt.map(|els| self.lower_expr(els));
448+
hir::ExprKind::If(cond, then, els)
457449
}
458450

459451
fn lower_expr_if_let(

compiler/rustc_feature/src/active.rs

+3
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,9 @@ declare_features! (
687687
/// Trait upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`.
688688
(incomplete, trait_upcasting, "1.56.0", Some(65991), None),
689689

690+
/// Allows explicit generic arguments specification with `impl Trait` present.
691+
(active, explicit_generic_args_with_impl_trait, "1.56.0", Some(83701), None),
692+
690693
// -------------------------------------------------------------------------
691694
// feature-group-end: actual feature gates
692695
// -------------------------------------------------------------------------

compiler/rustc_infer/src/infer/error_reporting/mod.rs

+43-25
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ use rustc_middle::ty::{
7171
subst::{GenericArgKind, Subst, SubstsRef},
7272
Region, Ty, TyCtxt, TypeFoldable,
7373
};
74-
use rustc_span::{sym, BytePos, DesugaringKind, Pos, Span};
74+
use rustc_span::{sym, BytePos, DesugaringKind, MultiSpan, Pos, Span};
7575
use rustc_target::spec::abi;
7676
use std::ops::ControlFlow;
7777
use std::{cmp, fmt, iter};
@@ -1485,31 +1485,49 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
14851485
let count = values.len();
14861486
let kind = key.descr();
14871487
let mut returned_async_output_error = false;
1488-
for sp in values {
1489-
err.span_label(
1490-
*sp,
1491-
format!(
1492-
"{}{}{} {}{}",
1493-
if sp.is_desugaring(DesugaringKind::Async)
1494-
&& !returned_async_output_error
1495-
{
1496-
"checked the `Output` of this `async fn`, "
1497-
} else if count == 1 {
1498-
"the "
1499-
} else {
1500-
""
1501-
},
1502-
if count > 1 { "one of the " } else { "" },
1503-
target,
1504-
kind,
1505-
pluralize!(count),
1506-
),
1507-
);
1508-
if sp.is_desugaring(DesugaringKind::Async)
1509-
&& returned_async_output_error == false
1510-
{
1511-
err.note("while checking the return type of the `async fn`");
1488+
for &sp in values {
1489+
if sp.is_desugaring(DesugaringKind::Async) && !returned_async_output_error {
1490+
if &[sp] != err.span.primary_spans() {
1491+
let mut span: MultiSpan = sp.into();
1492+
span.push_span_label(
1493+
sp,
1494+
format!(
1495+
"checked the `Output` of this `async fn`, {}{} {}{}",
1496+
if count > 1 { "one of the " } else { "" },
1497+
target,
1498+
kind,
1499+
pluralize!(count),
1500+
),
1501+
);
1502+
err.span_note(
1503+
span,
1504+
"while checking the return type of the `async fn`",
1505+
);
1506+
} else {
1507+
err.span_label(
1508+
sp,
1509+
format!(
1510+
"checked the `Output` of this `async fn`, {}{} {}{}",
1511+
if count > 1 { "one of the " } else { "" },
1512+
target,
1513+
kind,
1514+
pluralize!(count),
1515+
),
1516+
);
1517+
err.note("while checking the return type of the `async fn`");
1518+
}
15121519
returned_async_output_error = true;
1520+
} else {
1521+
err.span_label(
1522+
sp,
1523+
format!(
1524+
"{}{} {}{}",
1525+
if count == 1 { "the " } else { "one of the " },
1526+
target,
1527+
kind,
1528+
pluralize!(count),
1529+
),
1530+
);
15131531
}
15141532
}
15151533
}

compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -769,7 +769,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
769769

770770
// (#83606): Do not emit a suggestion if the parent has an `impl Trait`
771771
// as an argument otherwise it will cause the E0282 error.
772-
if !has_impl_trait {
772+
if !has_impl_trait || self.tcx.features().explicit_generic_args_with_impl_trait {
773773
err.span_suggestion_verbose(
774774
span,
775775
"consider specifying the const argument",

compiler/rustc_parse/src/lexer/unescape_error_reporting.rs

+29-8
Original file line numberDiff line numberDiff line change
@@ -153,16 +153,37 @@ pub(crate) fn emit_unescape_error(
153153
EscapeError::NonAsciiCharInByte => {
154154
assert!(mode.is_bytes());
155155
let (c, span) = last_char();
156-
handler
157-
.struct_span_err(span, "non-ASCII character in byte constant")
158-
.span_label(span, "byte constant must be ASCII")
159-
.span_suggestion(
156+
let mut err = handler.struct_span_err(span, "non-ASCII character in byte constant");
157+
err.span_label(span, "byte constant must be ASCII");
158+
if (c as u32) <= 0xFF {
159+
err.span_suggestion(
160160
span,
161-
"use a \\xHH escape for a non-ASCII byte",
161+
&format!(
162+
"if you meant to use the unicode code point for '{}', use a \\xHH escape",
163+
c
164+
),
162165
format!("\\x{:X}", c as u32),
163-
Applicability::MachineApplicable,
164-
)
165-
.emit();
166+
Applicability::MaybeIncorrect,
167+
);
168+
} else if matches!(mode, Mode::Byte) {
169+
err.span_label(span, "this multibyte character does not fit into a single byte");
170+
} else if matches!(mode, Mode::ByteStr) {
171+
let mut utf8 = String::new();
172+
utf8.push(c);
173+
err.span_suggestion(
174+
span,
175+
&format!(
176+
"if you meant to use the UTF-8 encoding of '{}', use \\xHH escapes",
177+
c
178+
),
179+
utf8.as_bytes()
180+
.iter()
181+
.map(|b: &u8| format!("\\x{:X}", *b))
182+
.fold("".to_string(), |a, c| a + &c),
183+
Applicability::MaybeIncorrect,
184+
);
185+
}
186+
err.emit();
166187
}
167188
EscapeError::NonAsciiCharInByteString => {
168189
assert!(mode.is_bytes());

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,7 @@ symbols! {
554554
expected,
555555
expf32,
556556
expf64,
557+
explicit_generic_args_with_impl_trait,
557558
export_name,
558559
expr,
559560
extended_key_value_attributes,

compiler/rustc_typeck/src/astconv/generics.rs

+32-3
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,32 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
459459

460460
let default_counts = gen_params.own_defaults();
461461
let param_counts = gen_params.own_counts();
462-
let named_type_param_count = param_counts.types - has_self as usize;
462+
463+
// Subtracting from param count to ensure type params synthesized from `impl Trait`
464+
// cannot be explictly specified even with `explicit_generic_args_with_impl_trait`
465+
// feature enabled.
466+
let synth_type_param_count = if tcx.features().explicit_generic_args_with_impl_trait {
467+
gen_params
468+
.params
469+
.iter()
470+
.filter(|param| {
471+
matches!(
472+
param.kind,
473+
ty::GenericParamDefKind::Type {
474+
synthetic: Some(
475+
hir::SyntheticTyParamKind::ImplTrait
476+
| hir::SyntheticTyParamKind::FromAttr
477+
),
478+
..
479+
}
480+
)
481+
})
482+
.count()
483+
} else {
484+
0
485+
};
486+
let named_type_param_count =
487+
param_counts.types - has_self as usize - synth_type_param_count;
463488
let infer_lifetimes =
464489
gen_pos != GenericArgPosition::Type && !gen_args.has_lifetime_params();
465490

@@ -588,6 +613,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
588613
param_counts.consts + named_type_param_count
589614
- default_counts.types
590615
- default_counts.consts
616+
- synth_type_param_count
591617
};
592618
debug!("expected_min: {:?}", expected_min);
593619
debug!("arg_counts.lifetimes: {:?}", gen_args.num_lifetime_params());
@@ -617,7 +643,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
617643
seg: &hir::PathSegment<'_>,
618644
generics: &ty::Generics,
619645
) -> bool {
620-
let explicit = !seg.infer_args;
646+
if seg.infer_args || tcx.features().explicit_generic_args_with_impl_trait {
647+
return false;
648+
}
649+
621650
let impl_trait = generics.params.iter().any(|param| {
622651
matches!(
623652
param.kind,
@@ -630,7 +659,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
630659
)
631660
});
632661

633-
if explicit && impl_trait {
662+
if impl_trait {
634663
let spans = seg
635664
.args()
636665
.args

compiler/rustc_typeck/src/check/_match.rs

+49-51
Original file line numberDiff line numberDiff line change
@@ -13,41 +13,6 @@ use rustc_trait_selection::traits::{
1313
StatementAsExpression,
1414
};
1515

16-
macro_rules! create_maybe_get_coercion_reason {
17-
($fn_name:ident, $node:expr) => {
18-
pub(crate) fn $fn_name(&self, hir_id: hir::HirId, sp: Span) -> Option<(Span, String)> {
19-
let node = $node(self.tcx.hir(), hir_id);
20-
if let hir::Node::Block(block) = node {
21-
// check that the body's parent is an fn
22-
let parent = self.tcx.hir().get(
23-
self.tcx.hir().get_parent_node(self.tcx.hir().get_parent_node(block.hir_id)),
24-
);
25-
if let (
26-
Some(expr),
27-
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(..), .. }),
28-
) = (&block.expr, parent)
29-
{
30-
// check that the `if` expr without `else` is the fn body's expr
31-
if expr.span == sp {
32-
return self.get_fn_decl(hir_id).and_then(|(fn_decl, _)| {
33-
let span = fn_decl.output.span();
34-
let snippet = self.tcx.sess.source_map().span_to_snippet(span).ok()?;
35-
Some((
36-
span,
37-
format!("expected `{}` because of this return type", snippet),
38-
))
39-
});
40-
}
41-
}
42-
}
43-
if let hir::Node::Local(hir::Local { ty: Some(_), pat, .. }) = node {
44-
return Some((pat.span, "expected because of this assignment".to_string()));
45-
}
46-
None
47-
}
48-
};
49-
}
50-
5116
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
5217
pub fn check_match(
5318
&self,
@@ -154,7 +119,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
154119
expr.span,
155120
&arms[0].body,
156121
&mut coercion,
157-
|hir_id, span| self.maybe_get_coercion_reason(hir_id, span),
122+
|hir_id, span| self.coercion_reason_match(hir_id, span),
158123
) {
159124
tcx.ty_error()
160125
} else {
@@ -373,23 +338,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
373338
error
374339
}
375340

376-
create_maybe_get_coercion_reason!(
377-
maybe_get_coercion_reason,
378-
|hir: rustc_middle::hir::map::Map<'a>, id| {
379-
let arm_id = hir.get_parent_node(id);
380-
let match_id = hir.get_parent_node(arm_id);
381-
let containing_id = hir.get_parent_node(match_id);
382-
hir.get(containing_id)
383-
}
384-
);
341+
pub(crate) fn coercion_reason_if(
342+
&self,
343+
hir_id: hir::HirId,
344+
span: Span,
345+
) -> Option<(Span, String)> {
346+
self.coercion_reason_inner(hir_id, span, 1)
347+
}
385348

386-
create_maybe_get_coercion_reason!(
387-
maybe_get_coercion_reason_if,
388-
|hir: rustc_middle::hir::map::Map<'a>, id| {
389-
let rslt = hir.get_parent_node(hir.get_parent_node(id));
390-
hir.get(rslt)
349+
pub(crate) fn coercion_reason_match(
350+
&self,
351+
hir_id: hir::HirId,
352+
span: Span,
353+
) -> Option<(Span, String)> {
354+
self.coercion_reason_inner(hir_id, span, 2)
355+
}
356+
357+
fn coercion_reason_inner(
358+
&self,
359+
hir_id: hir::HirId,
360+
span: Span,
361+
parent_index: usize,
362+
) -> Option<(Span, String)> {
363+
let hir = self.tcx.hir();
364+
let mut parent_iter = hir.parent_iter(hir_id);
365+
let (_, node) = parent_iter.nth(parent_index)?;
366+
match node {
367+
hir::Node::Block(block) => {
368+
let expr = block.expr?;
369+
// check that the body's parent is an fn
370+
let (_, parent) = parent_iter.nth(1)?;
371+
if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(..), .. }) = parent {
372+
// check that the `if` expr without `else` is the fn body's expr
373+
if expr.span == span {
374+
let (fn_decl, _) = self.get_fn_decl(hir_id)?;
375+
let span = fn_decl.output.span();
376+
let snippet = self.tcx.sess.source_map().span_to_snippet(span).ok()?;
377+
return Some((
378+
span,
379+
format!("expected `{}` because of this return type", snippet),
380+
));
381+
}
382+
}
383+
None
384+
}
385+
hir::Node::Local(hir::Local { ty: Some(_), pat, .. }) => {
386+
Some((pat.span, "expected because of this assignment".to_string()))
387+
}
388+
_ => None,
391389
}
392-
);
390+
}
393391

394392
pub(crate) fn if_cause(
395393
&self,

compiler/rustc_typeck/src/check/expr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -838,7 +838,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
838838
self.diverges.set(cond_diverges | then_diverges & else_diverges);
839839
} else {
840840
self.if_fallback_coercion(sp, then_expr, &mut coerce, |hir_id, span| {
841-
self.maybe_get_coercion_reason_if(hir_id, span)
841+
self.coercion_reason_if(hir_id, span)
842842
});
843843

844844
// If the condition is false we can't diverge.

library/core/src/option.rs

+13
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,19 @@
285285
//! assert_eq!(res, ["error!", "error!", "foo", "error!", "bar"]);
286286
//! ```
287287
//!
288+
//! ## Comparison operators
289+
//!
290+
//! If `T` implements [`PartialOrd`] then [`Option<T>`] will derive its
291+
//! [`PartialOrd`] implementation. With this order, [`None`] compares as
292+
//! less than any [`Some`], and two [`Some`] compare the same way as their
293+
//! contained values would in `T`. If `T` also implements
294+
//! [`Ord`], then so does [`Option<T>`].
295+
//!
296+
//! ```
297+
//! assert!(None < Some(0));
298+
//! assert!(Some(0) < Some(1));
299+
//! ```
300+
//!
288301
//! ## Iterating over `Option`
289302
//!
290303
//! An [`Option`] can be iterated over. This can be helpful if you need an

0 commit comments

Comments
 (0)