Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit f581572

Browse files
committedDec 4, 2021
Auto merge of rust-lang#91505 - matthiaskrgr:rollup-orxgsxo, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - rust-lang#90538 (Document how recursion is handled for `ty::Ty`) - rust-lang#90851 (Add unchecked downcast methods) - rust-lang#91209 (Implement ``@snapshot`` check for htmldocck) - rust-lang#91385 (Suggest the `pat_param` specifier before `|` on 2021 edition ) - rust-lang#91478 (Remove incorrect newline from float cast suggestion) - rust-lang#91481 (Use let_else in some more places in rustc_lint) - rust-lang#91488 (Fix ICE when `yield`ing in function returning `impl Trait`) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 14c1e71 + df51bff commit f581572

File tree

23 files changed

+530
-146
lines changed

23 files changed

+530
-146
lines changed
 

‎compiler/rustc_borrowck/src/type_check/input_output.rs‎

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,29 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
117117
}
118118
}
119119

120-
assert!(body.yield_ty().is_some() == universal_regions.yield_ty.is_some());
121-
if let Some(mir_yield_ty) = body.yield_ty() {
122-
let ur_yield_ty = universal_regions.yield_ty.unwrap();
120+
debug!(
121+
"equate_inputs_and_outputs: body.yield_ty {:?}, universal_regions.yield_ty {:?}",
122+
body.yield_ty(),
123+
universal_regions.yield_ty
124+
);
125+
126+
// We will not have a universal_regions.yield_ty if we yield (by accident)
127+
// outside of a generator and return an `impl Trait`, so emit a delay_span_bug
128+
// because we don't want to panic in an assert here if we've already got errors.
129+
if body.yield_ty().is_some() != universal_regions.yield_ty.is_some() {
130+
self.tcx().sess.delay_span_bug(
131+
body.span,
132+
&format!(
133+
"Expected body to have yield_ty ({:?}) iff we have a UR yield_ty ({:?})",
134+
body.yield_ty(),
135+
universal_regions.yield_ty,
136+
),
137+
);
138+
}
139+
140+
if let (Some(mir_yield_ty), Some(ur_yield_ty)) =
141+
(body.yield_ty(), universal_regions.yield_ty)
142+
{
123143
let yield_span = body.local_decls[RETURN_PLACE].source_info.span;
124144
self.equate_normalized_input_or_output(ur_yield_ty, mir_yield_ty, yield_span);
125145
}

‎compiler/rustc_expand/src/mbe/macro_rules.rs‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,6 +1027,24 @@ fn check_matcher_core(
10271027
),
10281028
);
10291029
err.span_label(sp, format!("not allowed after `{}` fragments", kind));
1030+
1031+
if kind == NonterminalKind::PatWithOr
1032+
&& sess.edition == Edition::Edition2021
1033+
&& next_token.is_token(&BinOp(token::BinOpToken::Or))
1034+
{
1035+
let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl(
1036+
span,
1037+
name,
1038+
Some(NonterminalKind::PatParam { inferred: false }),
1039+
));
1040+
err.span_suggestion(
1041+
span,
1042+
&format!("try a `pat_param` fragment specifier instead"),
1043+
suggestion,
1044+
Applicability::MaybeIncorrect,
1045+
);
1046+
}
1047+
10301048
let msg = "allowed there are: ";
10311049
match possible {
10321050
&[] => {}

‎compiler/rustc_lint/src/array_into_iter.rs‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,8 @@ impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter {
7979
let receiver_ty = cx.typeck_results().expr_ty(receiver_arg);
8080
let adjustments = cx.typeck_results().expr_adjustments(receiver_arg);
8181

82-
let target = match adjustments.last() {
83-
Some(Adjustment { kind: Adjust::Borrow(_), target }) => target,
84-
_ => return,
82+
let Some(Adjustment { kind: Adjust::Borrow(_), target }) = adjustments.last() else {
83+
return
8584
};
8685

8786
let types =

‎compiler/rustc_lint/src/builtin.rs‎

Lines changed: 29 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -609,14 +609,12 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
609609
// If the trait is private, add the impl items to `private_traits` so they don't get
610610
// reported for missing docs.
611611
let real_trait = trait_ref.path.res.def_id();
612-
if let Some(def_id) = real_trait.as_local() {
613-
let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
614-
if let Some(Node::Item(item)) = cx.tcx.hir().find(hir_id) {
615-
if let hir::VisibilityKind::Inherited = item.vis.node {
616-
for impl_item_ref in items {
617-
self.private_traits.insert(impl_item_ref.id.hir_id());
618-
}
619-
}
612+
let Some(def_id) = real_trait.as_local() else { return };
613+
let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
614+
let Some(Node::Item(item)) = cx.tcx.hir().find(hir_id) else { return };
615+
if let hir::VisibilityKind::Inherited = item.vis.node {
616+
for impl_item_ref in items {
617+
self.private_traits.insert(impl_item_ref.id.hir_id());
620618
}
621619
}
622620
return;
@@ -829,9 +827,8 @@ impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations {
829827
_ => return,
830828
}
831829

832-
let debug = match cx.tcx.get_diagnostic_item(sym::Debug) {
833-
Some(debug) => debug,
834-
None => return,
830+
let Some(debug) = cx.tcx.get_diagnostic_item(sym::Debug) else {
831+
return
835832
};
836833

837834
if self.impling_types.is_none() {
@@ -1509,9 +1506,8 @@ impl TypeAliasBounds {
15091506

15101507
impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds {
15111508
fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
1512-
let (ty, type_alias_generics) = match item.kind {
1513-
hir::ItemKind::TyAlias(ref ty, ref generics) => (&*ty, generics),
1514-
_ => return,
1509+
let hir::ItemKind::TyAlias(ty, type_alias_generics) = &item.kind else {
1510+
return
15151511
};
15161512
if let hir::TyKind::OpaqueDef(..) = ty.kind {
15171513
// Bounds are respected for `type X = impl Trait`
@@ -2266,16 +2262,15 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
22662262
// and should check for them here.
22672263
match predicate.bounded_ty.kind {
22682264
hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) => {
2269-
if let Res::Def(DefKind::TyParam, def_id) = path.res {
2270-
let index = ty_generics.param_def_id_to_index[&def_id];
2271-
(
2272-
Self::lifetimes_outliving_type(inferred_outlives, index),
2273-
&predicate.bounds,
2274-
predicate.span,
2275-
)
2276-
} else {
2277-
continue;
2278-
}
2265+
let Res::Def(DefKind::TyParam, def_id) = path.res else {
2266+
continue
2267+
};
2268+
let index = ty_generics.param_def_id_to_index[&def_id];
2269+
(
2270+
Self::lifetimes_outliving_type(inferred_outlives, index),
2271+
&predicate.bounds,
2272+
predicate.span,
2273+
)
22792274
}
22802275
_ => {
22812276
continue;
@@ -3216,18 +3211,17 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels {
32163211
for (idx, _) in statement.match_indices(':') {
32173212
let possible_label = statement[start_idx..idx].trim();
32183213
let mut chars = possible_label.chars();
3219-
if let Some(c) = chars.next() {
3220-
// A label starts with an alphabetic character or . or _ and continues with alphanumeric characters, _, or $
3221-
if (c.is_alphabetic() || matches!(c, '.' | '_'))
3222-
&& chars.all(|c| c.is_alphanumeric() || matches!(c, '_' | '$'))
3223-
{
3224-
found_labels.push(possible_label);
3225-
} else {
3226-
// If we encounter a non-label, there cannot be any further labels, so stop checking
3227-
break;
3228-
}
3229-
} else {
3214+
let Some(c) = chars.next() else {
32303215
// Empty string means a leading ':' in this section, which is not a label
3216+
break
3217+
};
3218+
// A label starts with an alphabetic character or . or _ and continues with alphanumeric characters, _, or $
3219+
if (c.is_alphabetic() || matches!(c, '.' | '_'))
3220+
&& chars.all(|c| c.is_alphanumeric() || matches!(c, '_' | '$'))
3221+
{
3222+
found_labels.push(possible_label);
3223+
} else {
3224+
// If we encounter a non-label, there cannot be any further labels, so stop checking
32313225
break;
32323226
}
32333227

‎compiler/rustc_lint/src/levels.rs‎

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -227,14 +227,12 @@ impl<'s> LintLevelsBuilder<'s> {
227227
let sess = self.sess;
228228
let bad_attr = |span| struct_span_err!(sess, span, E0452, "malformed lint attribute input");
229229
for attr in attrs {
230-
let level = match Level::from_symbol(attr.name_or_empty()) {
231-
None => continue,
232-
Some(lvl) => lvl,
230+
let Some(level) = Level::from_symbol(attr.name_or_empty()) else {
231+
continue
233232
};
234233

235-
let mut metas = match attr.meta_item_list() {
236-
Some(x) => x,
237-
None => continue,
234+
let Some(mut metas) = attr.meta_item_list() else {
235+
continue
238236
};
239237

240238
if metas.is_empty() {
@@ -481,9 +479,8 @@ impl<'s> LintLevelsBuilder<'s> {
481479
continue;
482480
}
483481

484-
let (lint_attr_name, lint_attr_span) = match *src {
485-
LintLevelSource::Node(name, span, _) => (name, span),
486-
_ => continue,
482+
let LintLevelSource::Node(lint_attr_name, lint_attr_span, _) = *src else {
483+
continue
487484
};
488485

489486
let lint = builtin::UNUSED_ATTRIBUTES;

‎compiler/rustc_lint/src/noop_method_call.rs‎

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,8 @@ declare_lint_pass!(NoopMethodCall => [NOOP_METHOD_CALL]);
4040
impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
4141
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
4242
// We only care about method calls.
43-
let (call, elements) = match expr.kind {
44-
ExprKind::MethodCall(call, _, elements, _) => (call, elements),
45-
_ => return,
43+
let ExprKind::MethodCall(call, _, elements, _) = &expr.kind else {
44+
return
4645
};
4746
// We only care about method calls corresponding to the `Clone`, `Deref` and `Borrow`
4847
// traits and ignore any other method call.
@@ -70,9 +69,8 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
7069
}
7170
let param_env = cx.tcx.param_env(trait_id);
7271
// Resolve the trait method instance.
73-
let i = match ty::Instance::resolve(cx.tcx, param_env, did, substs) {
74-
Ok(Some(i)) => i,
75-
_ => return,
72+
let Ok(Some(i)) = ty::Instance::resolve(cx.tcx, param_env, did, substs) else {
73+
return
7674
};
7775
// (Re)check that it implements the noop diagnostic.
7876
let Some(name) = cx.tcx.get_diagnostic_name(i.def_id()) else { return };

‎compiler/rustc_lint/src/traits.rs‎

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,8 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
9191

9292
let predicates = cx.tcx.explicit_predicates_of(item.def_id);
9393
for &(predicate, span) in predicates.predicates {
94-
let trait_predicate = match predicate.kind().skip_binder() {
95-
Trait(trait_predicate) => trait_predicate,
96-
_ => continue,
94+
let Trait(trait_predicate) = predicate.kind().skip_binder() else {
95+
continue
9796
};
9897
if trait_predicate.constness == ty::BoundConstness::ConstIfConst {
9998
// `~const Drop` definitely have meanings so avoid linting here.
@@ -106,9 +105,8 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
106105
continue;
107106
}
108107
cx.struct_span_lint(DROP_BOUNDS, span, |lint| {
109-
let needs_drop = match cx.tcx.get_diagnostic_item(sym::needs_drop) {
110-
Some(needs_drop) => needs_drop,
111-
None => return,
108+
let Some(needs_drop) = cx.tcx.get_diagnostic_item(sym::needs_drop) else {
109+
return
112110
};
113111
let msg = format!(
114112
"bounds on `{}` are most likely incorrect, consider instead \
@@ -123,17 +121,15 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
123121
}
124122

125123
fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx>) {
126-
let bounds = match &ty.kind {
127-
hir::TyKind::TraitObject(bounds, _lifetime, _syntax) => bounds,
128-
_ => return,
124+
let hir::TyKind::TraitObject(bounds, _lifetime, _syntax) = &ty.kind else {
125+
return
129126
};
130127
for bound in &bounds[..] {
131128
let def_id = bound.trait_ref.trait_def_id();
132129
if cx.tcx.lang_items().drop_trait() == def_id {
133130
cx.struct_span_lint(DYN_DROP, bound.span, |lint| {
134-
let needs_drop = match cx.tcx.get_diagnostic_item(sym::needs_drop) {
135-
Some(needs_drop) => needs_drop,
136-
None => return,
131+
let Some(needs_drop) = cx.tcx.get_diagnostic_item(sym::needs_drop) else {
132+
return
137133
};
138134
let msg = format!(
139135
"types that do not implement `Drop` can still have drop glue, consider \

‎compiler/rustc_lint/src/types.rs‎

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1342,11 +1342,10 @@ impl<'tcx> LateLintPass<'tcx> for VariantSizeDifferences {
13421342
| ty::layout::LayoutError::NormalizationFailure(_, _),
13431343
) => return,
13441344
};
1345-
let (variants, tag) = match layout.variants {
1346-
Variants::Multiple {
1345+
let Variants::Multiple {
13471346
tag_encoding: TagEncoding::Direct, tag, ref variants, ..
1348-
} => (variants, tag),
1349-
_ => return,
1347+
} = &layout.variants else {
1348+
return
13501349
};
13511350

13521351
let tag_size = tag.value.size(&cx.tcx).bytes();

‎compiler/rustc_middle/src/ty/adt.rs‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,30 @@ bitflags! {
6464
/// Moreover, Rust only allows recursive data types through indirection.
6565
///
6666
/// [adt]: https://en.wikipedia.org/wiki/Algebraic_data_type
67+
///
68+
/// # Recursive types
69+
///
70+
/// It may seem impossible to represent recursive types using [`Ty`],
71+
/// since [`TyKind::Adt`] includes [`AdtDef`], which includes its fields,
72+
/// creating a cycle. However, `AdtDef` does not actually include the *types*
73+
/// of its fields; it includes just their [`DefId`]s.
74+
///
75+
/// [`TyKind::Adt`]: ty::TyKind::Adt
76+
///
77+
/// For example, the following type:
78+
///
79+
/// ```
80+
/// struct S { x: Box<S> }
81+
/// ```
82+
///
83+
/// is essentially represented with [`Ty`] as the following pseudocode:
84+
///
85+
/// ```
86+
/// struct S { x }
87+
/// ```
88+
///
89+
/// where `x` here represents the `DefId` of `S.x`. Then, the `DefId`
90+
/// can be used with [`TyCtxt::type_of()`] to get the type of the field.
6791
pub struct AdtDef {
6892
/// The `DefId` of the struct, enum or union item.
6993
pub did: DefId,

‎compiler/rustc_middle/src/ty/mod.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1711,7 +1711,7 @@ impl ReprOptions {
17111711

17121712
impl<'tcx> FieldDef {
17131713
/// Returns the type of this field. The resulting type is not normalized. The `subst` is
1714-
/// typically obtained via the second field of `TyKind::AdtDef`.
1714+
/// typically obtained via the second field of [`TyKind::Adt`].
17151715
pub fn ty(&self, tcx: TyCtxt<'tcx>, subst: SubstsRef<'tcx>) -> Ty<'tcx> {
17161716
tcx.type_of(self.did).subst(tcx, subst)
17171717
}

‎compiler/rustc_typeck/src/check/demand.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1223,7 +1223,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12231223
// Missing try_into implementation for `{integer}` to `{float}`
12241224
err.multipart_suggestion_verbose(
12251225
&format!(
1226-
"{}, producing the floating point representation of the integer,
1226+
"{}, producing the floating point representation of the integer, \
12271227
rounded if necessary",
12281228
cast_msg,
12291229
),

‎library/alloc/src/boxed.rs‎

Lines changed: 109 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1518,8 +1518,6 @@ impl<T, const N: usize> TryFrom<Box<[T]>> for Box<[T; N]> {
15181518
}
15191519

15201520
impl<A: Allocator> Box<dyn Any, A> {
1521-
#[inline]
1522-
#[stable(feature = "rust1", since = "1.0.0")]
15231521
/// Attempt to downcast the box to a concrete type.
15241522
///
15251523
/// # Examples
@@ -1537,21 +1535,48 @@ impl<A: Allocator> Box<dyn Any, A> {
15371535
/// print_if_string(Box::new(my_string));
15381536
/// print_if_string(Box::new(0i8));
15391537
/// ```
1538+
#[inline]
1539+
#[stable(feature = "rust1", since = "1.0.0")]
15401540
pub fn downcast<T: Any>(self) -> Result<Box<T, A>, Self> {
1541-
if self.is::<T>() {
1542-
unsafe {
1543-
let (raw, alloc): (*mut dyn Any, _) = Box::into_raw_with_allocator(self);
1544-
Ok(Box::from_raw_in(raw as *mut T, alloc))
1545-
}
1546-
} else {
1547-
Err(self)
1541+
if self.is::<T>() { unsafe { Ok(self.downcast_unchecked::<T>()) } } else { Err(self) }
1542+
}
1543+
1544+
/// Downcasts the box to a concrete type.
1545+
///
1546+
/// For a safe alternative see [`downcast`].
1547+
///
1548+
/// # Examples
1549+
///
1550+
/// ```
1551+
/// #![feature(downcast_unchecked)]
1552+
///
1553+
/// use std::any::Any;
1554+
///
1555+
/// let x: Box<dyn Any> = Box::new(1_usize);
1556+
///
1557+
/// unsafe {
1558+
/// assert_eq!(*x.downcast_unchecked::<usize>(), 1);
1559+
/// }
1560+
/// ```
1561+
///
1562+
/// # Safety
1563+
///
1564+
/// The contained value must be of type `T`. Calling this method
1565+
/// with the incorrect type is *undefined behavior*.
1566+
///
1567+
/// [`downcast`]: Self::downcast
1568+
#[inline]
1569+
#[unstable(feature = "downcast_unchecked", issue = "90850")]
1570+
pub unsafe fn downcast_unchecked<T: Any>(self) -> Box<T, A> {
1571+
debug_assert!(self.is::<T>());
1572+
unsafe {
1573+
let (raw, alloc): (*mut dyn Any, _) = Box::into_raw_with_allocator(self);
1574+
Box::from_raw_in(raw as *mut T, alloc)
15481575
}
15491576
}
15501577
}
15511578

15521579
impl<A: Allocator> Box<dyn Any + Send, A> {
1553-
#[inline]
1554-
#[stable(feature = "rust1", since = "1.0.0")]
15551580
/// Attempt to downcast the box to a concrete type.
15561581
///
15571582
/// # Examples
@@ -1569,21 +1594,48 @@ impl<A: Allocator> Box<dyn Any + Send, A> {
15691594
/// print_if_string(Box::new(my_string));
15701595
/// print_if_string(Box::new(0i8));
15711596
/// ```
1597+
#[inline]
1598+
#[stable(feature = "rust1", since = "1.0.0")]
15721599
pub fn downcast<T: Any>(self) -> Result<Box<T, A>, Self> {
1573-
if self.is::<T>() {
1574-
unsafe {
1575-
let (raw, alloc): (*mut (dyn Any + Send), _) = Box::into_raw_with_allocator(self);
1576-
Ok(Box::from_raw_in(raw as *mut T, alloc))
1577-
}
1578-
} else {
1579-
Err(self)
1600+
if self.is::<T>() { unsafe { Ok(self.downcast_unchecked::<T>()) } } else { Err(self) }
1601+
}
1602+
1603+
/// Downcasts the box to a concrete type.
1604+
///
1605+
/// For a safe alternative see [`downcast`].
1606+
///
1607+
/// # Examples
1608+
///
1609+
/// ```
1610+
/// #![feature(downcast_unchecked)]
1611+
///
1612+
/// use std::any::Any;
1613+
///
1614+
/// let x: Box<dyn Any + Send> = Box::new(1_usize);
1615+
///
1616+
/// unsafe {
1617+
/// assert_eq!(*x.downcast_unchecked::<usize>(), 1);
1618+
/// }
1619+
/// ```
1620+
///
1621+
/// # Safety
1622+
///
1623+
/// The contained value must be of type `T`. Calling this method
1624+
/// with the incorrect type is *undefined behavior*.
1625+
///
1626+
/// [`downcast`]: Self::downcast
1627+
#[inline]
1628+
#[unstable(feature = "downcast_unchecked", issue = "90850")]
1629+
pub unsafe fn downcast_unchecked<T: Any>(self) -> Box<T, A> {
1630+
debug_assert!(self.is::<T>());
1631+
unsafe {
1632+
let (raw, alloc): (*mut (dyn Any + Send), _) = Box::into_raw_with_allocator(self);
1633+
Box::from_raw_in(raw as *mut T, alloc)
15801634
}
15811635
}
15821636
}
15831637

15841638
impl<A: Allocator> Box<dyn Any + Send + Sync, A> {
1585-
#[inline]
1586-
#[stable(feature = "box_send_sync_any_downcast", since = "1.51.0")]
15871639
/// Attempt to downcast the box to a concrete type.
15881640
///
15891641
/// # Examples
@@ -1601,15 +1653,44 @@ impl<A: Allocator> Box<dyn Any + Send + Sync, A> {
16011653
/// print_if_string(Box::new(my_string));
16021654
/// print_if_string(Box::new(0i8));
16031655
/// ```
1656+
#[inline]
1657+
#[stable(feature = "box_send_sync_any_downcast", since = "1.51.0")]
16041658
pub fn downcast<T: Any>(self) -> Result<Box<T, A>, Self> {
1605-
if self.is::<T>() {
1606-
unsafe {
1607-
let (raw, alloc): (*mut (dyn Any + Send + Sync), _) =
1608-
Box::into_raw_with_allocator(self);
1609-
Ok(Box::from_raw_in(raw as *mut T, alloc))
1610-
}
1611-
} else {
1612-
Err(self)
1659+
if self.is::<T>() { unsafe { Ok(self.downcast_unchecked::<T>()) } } else { Err(self) }
1660+
}
1661+
1662+
/// Downcasts the box to a concrete type.
1663+
///
1664+
/// For a safe alternative see [`downcast`].
1665+
///
1666+
/// # Examples
1667+
///
1668+
/// ```
1669+
/// #![feature(downcast_unchecked)]
1670+
///
1671+
/// use std::any::Any;
1672+
///
1673+
/// let x: Box<dyn Any + Send + Sync> = Box::new(1_usize);
1674+
///
1675+
/// unsafe {
1676+
/// assert_eq!(*x.downcast_unchecked::<usize>(), 1);
1677+
/// }
1678+
/// ```
1679+
///
1680+
/// # Safety
1681+
///
1682+
/// The contained value must be of type `T`. Calling this method
1683+
/// with the incorrect type is *undefined behavior*.
1684+
///
1685+
/// [`downcast`]: Self::downcast
1686+
#[inline]
1687+
#[unstable(feature = "downcast_unchecked", issue = "90850")]
1688+
pub unsafe fn downcast_unchecked<T: Any>(self) -> Box<T, A> {
1689+
debug_assert!(self.is::<T>());
1690+
unsafe {
1691+
let (raw, alloc): (*mut (dyn Any + Send + Sync), _) =
1692+
Box::into_raw_with_allocator(self);
1693+
Box::from_raw_in(raw as *mut T, alloc)
16131694
}
16141695
}
16151696
}

‎library/core/src/any.rs‎

Lines changed: 166 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ impl fmt::Debug for dyn Any + Send + Sync {
164164
}
165165

166166
impl dyn Any {
167-
/// Returns `true` if the boxed type is the same as `T`.
167+
/// Returns `true` if the inner type is the same as `T`.
168168
///
169169
/// # Examples
170170
///
@@ -195,7 +195,7 @@ impl dyn Any {
195195
t == concrete
196196
}
197197

198-
/// Returns some reference to the boxed value if it is of type `T`, or
198+
/// Returns some reference to the inner value if it is of type `T`, or
199199
/// `None` if it isn't.
200200
///
201201
/// # Examples
@@ -221,13 +221,13 @@ impl dyn Any {
221221
// SAFETY: just checked whether we are pointing to the correct type, and we can rely on
222222
// that check for memory safety because we have implemented Any for all types; no other
223223
// impls can exist as they would conflict with our impl.
224-
unsafe { Some(&*(self as *const dyn Any as *const T)) }
224+
unsafe { Some(self.downcast_ref_unchecked()) }
225225
} else {
226226
None
227227
}
228228
}
229229

230-
/// Returns some mutable reference to the boxed value if it is of type `T`, or
230+
/// Returns some mutable reference to the inner value if it is of type `T`, or
231231
/// `None` if it isn't.
232232
///
233233
/// # Examples
@@ -257,15 +257,73 @@ impl dyn Any {
257257
// SAFETY: just checked whether we are pointing to the correct type, and we can rely on
258258
// that check for memory safety because we have implemented Any for all types; no other
259259
// impls can exist as they would conflict with our impl.
260-
unsafe { Some(&mut *(self as *mut dyn Any as *mut T)) }
260+
unsafe { Some(self.downcast_mut_unchecked()) }
261261
} else {
262262
None
263263
}
264264
}
265+
266+
/// Returns a reference to the inner value as type `dyn T`.
267+
///
268+
/// # Examples
269+
///
270+
/// ```
271+
/// #![feature(downcast_unchecked)]
272+
///
273+
/// use std::any::Any;
274+
///
275+
/// let x: Box<dyn Any> = Box::new(1_usize);
276+
///
277+
/// unsafe {
278+
/// assert_eq!(*x.downcast_ref_unchecked::<usize>(), 1);
279+
/// }
280+
/// ```
281+
///
282+
/// # Safety
283+
///
284+
/// The contained value must be of type `T`. Calling this method
285+
/// with the incorrect type is *undefined behavior*.
286+
#[unstable(feature = "downcast_unchecked", issue = "90850")]
287+
#[inline]
288+
pub unsafe fn downcast_ref_unchecked<T: Any>(&self) -> &T {
289+
debug_assert!(self.is::<T>());
290+
// SAFETY: caller guarantees that T is the correct type
291+
unsafe { &*(self as *const dyn Any as *const T) }
292+
}
293+
294+
/// Returns a mutable reference to the inner value as type `dyn T`.
295+
///
296+
/// # Examples
297+
///
298+
/// ```
299+
/// #![feature(downcast_unchecked)]
300+
///
301+
/// use std::any::Any;
302+
///
303+
/// let mut x: Box<dyn Any> = Box::new(1_usize);
304+
///
305+
/// unsafe {
306+
/// *x.downcast_mut_unchecked::<usize>() += 1;
307+
/// }
308+
///
309+
/// assert_eq!(*x.downcast_ref::<usize>().unwrap(), 2);
310+
/// ```
311+
///
312+
/// # Safety
313+
///
314+
/// The contained value must be of type `T`. Calling this method
315+
/// with the incorrect type is *undefined behavior*.
316+
#[unstable(feature = "downcast_unchecked", issue = "90850")]
317+
#[inline]
318+
pub unsafe fn downcast_mut_unchecked<T: Any>(&mut self) -> &mut T {
319+
debug_assert!(self.is::<T>());
320+
// SAFETY: caller guarantees that T is the correct type
321+
unsafe { &mut *(self as *mut dyn Any as *mut T) }
322+
}
265323
}
266324

267325
impl dyn Any + Send {
268-
/// Forwards to the method defined on the type `Any`.
326+
/// Forwards to the method defined on the type `dyn Any`.
269327
///
270328
/// # Examples
271329
///
@@ -289,7 +347,7 @@ impl dyn Any + Send {
289347
<dyn Any>::is::<T>(self)
290348
}
291349

292-
/// Forwards to the method defined on the type `Any`.
350+
/// Forwards to the method defined on the type `dyn Any`.
293351
///
294352
/// # Examples
295353
///
@@ -313,7 +371,7 @@ impl dyn Any + Send {
313371
<dyn Any>::downcast_ref::<T>(self)
314372
}
315373

316-
/// Forwards to the method defined on the type `Any`.
374+
/// Forwards to the method defined on the type `dyn Any`.
317375
///
318376
/// # Examples
319377
///
@@ -340,6 +398,60 @@ impl dyn Any + Send {
340398
pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
341399
<dyn Any>::downcast_mut::<T>(self)
342400
}
401+
402+
/// Forwards to the method defined on the type `dyn Any`.
403+
///
404+
/// # Examples
405+
///
406+
/// ```
407+
/// #![feature(downcast_unchecked)]
408+
///
409+
/// use std::any::Any;
410+
///
411+
/// let x: Box<dyn Any> = Box::new(1_usize);
412+
///
413+
/// unsafe {
414+
/// assert_eq!(*x.downcast_ref_unchecked::<usize>(), 1);
415+
/// }
416+
/// ```
417+
///
418+
/// # Safety
419+
///
420+
/// Same as the method on the type `dyn Any`.
421+
#[unstable(feature = "downcast_unchecked", issue = "90850")]
422+
#[inline]
423+
pub unsafe fn downcast_ref_unchecked<T: Any>(&self) -> &T {
424+
// SAFETY: guaranteed by caller
425+
unsafe { <dyn Any>::downcast_ref_unchecked::<T>(self) }
426+
}
427+
428+
/// Forwards to the method defined on the type `dyn Any`.
429+
///
430+
/// # Examples
431+
///
432+
/// ```
433+
/// #![feature(downcast_unchecked)]
434+
///
435+
/// use std::any::Any;
436+
///
437+
/// let mut x: Box<dyn Any> = Box::new(1_usize);
438+
///
439+
/// unsafe {
440+
/// *x.downcast_mut_unchecked::<usize>() += 1;
441+
/// }
442+
///
443+
/// assert_eq!(*x.downcast_ref::<usize>().unwrap(), 2);
444+
/// ```
445+
///
446+
/// # Safety
447+
///
448+
/// Same as the method on the type `dyn Any`.
449+
#[unstable(feature = "downcast_unchecked", issue = "90850")]
450+
#[inline]
451+
pub unsafe fn downcast_mut_unchecked<T: Any>(&mut self) -> &mut T {
452+
// SAFETY: guaranteed by caller
453+
unsafe { <dyn Any>::downcast_mut_unchecked::<T>(self) }
454+
}
343455
}
344456

345457
impl dyn Any + Send + Sync {
@@ -418,6 +530,52 @@ impl dyn Any + Send + Sync {
418530
pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
419531
<dyn Any>::downcast_mut::<T>(self)
420532
}
533+
534+
/// Forwards to the method defined on the type `Any`.
535+
///
536+
/// # Examples
537+
///
538+
/// ```
539+
/// #![feature(downcast_unchecked)]
540+
///
541+
/// use std::any::Any;
542+
///
543+
/// let x: Box<dyn Any> = Box::new(1_usize);
544+
///
545+
/// unsafe {
546+
/// assert_eq!(*x.downcast_ref_unchecked::<usize>(), 1);
547+
/// }
548+
/// ```
549+
#[unstable(feature = "downcast_unchecked", issue = "90850")]
550+
#[inline]
551+
pub unsafe fn downcast_ref_unchecked<T: Any>(&self) -> &T {
552+
// SAFETY: guaranteed by caller
553+
unsafe { <dyn Any>::downcast_ref_unchecked::<T>(self) }
554+
}
555+
556+
/// Forwards to the method defined on the type `Any`.
557+
///
558+
/// # Examples
559+
///
560+
/// ```
561+
/// #![feature(downcast_unchecked)]
562+
///
563+
/// use std::any::Any;
564+
///
565+
/// let mut x: Box<dyn Any> = Box::new(1_usize);
566+
///
567+
/// unsafe {
568+
/// *x.downcast_mut_unchecked::<usize>() += 1;
569+
/// }
570+
///
571+
/// assert_eq!(*x.downcast_ref::<usize>().unwrap(), 2);
572+
/// ```
573+
#[unstable(feature = "downcast_unchecked", issue = "90850")]
574+
#[inline]
575+
pub unsafe fn downcast_mut_unchecked<T: Any>(&mut self) -> &mut T {
576+
// SAFETY: guaranteed by caller
577+
unsafe { <dyn Any>::downcast_mut_unchecked::<T>(self) }
578+
}
421579
}
422580

423581
///////////////////////////////////////////////////////////////////////////////

‎src/etc/htmldocck.py‎

Lines changed: 76 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,20 @@
9090
highlights for example. If you want to simply check for the presence of
9191
a given node or attribute, use an empty string (`""`) as a `PATTERN`.
9292
93-
* `@count PATH XPATH COUNT' checks for the occurrence of the given XPath
93+
* `@count PATH XPATH COUNT` checks for the occurrence of the given XPath
9494
in the specified file. The number of occurrences must match the given
9595
count.
9696
97+
* `@snapshot NAME PATH XPATH` creates a snapshot test named NAME.
98+
A snapshot test captures a subtree of the DOM, at the location
99+
determined by the XPath, and compares it to a pre-recorded value
100+
in a file. The file's name is the test's name with the `.rs` extension
101+
replaced with `.NAME.html`, where NAME is the snapshot's name.
102+
103+
htmldocck supports the `--bless` option to accept the current subtree
104+
as expected, saving it to the file determined by the snapshot's name.
105+
compiletest's `--bless` flag is forwarded to htmldocck.
106+
97107
* `@has-dir PATH` checks for the existence of the given directory.
98108
99109
All conditions can be negated with `!`. `@!has foo/type.NoSuch.html`
@@ -137,6 +147,10 @@
137147

138148
channel = os.environ["DOC_RUST_LANG_ORG_CHANNEL"]
139149

150+
# Initialized in main
151+
rust_test_path = None
152+
bless = None
153+
140154
class CustomHTMLParser(HTMLParser):
141155
"""simplified HTML parser.
142156
@@ -387,6 +401,32 @@ def get_tree_count(tree, path):
387401
return len(tree.findall(path))
388402

389403

404+
def check_snapshot(snapshot_name, tree):
405+
assert rust_test_path.endswith('.rs')
406+
snapshot_path = '{}.{}.{}'.format(rust_test_path[:-3], snapshot_name, 'html')
407+
try:
408+
with open(snapshot_path, 'r') as snapshot_file:
409+
expected_str = snapshot_file.read()
410+
except FileNotFoundError:
411+
if bless:
412+
expected_str = None
413+
else:
414+
raise FailedCheck('No saved snapshot value')
415+
416+
actual_str = ET.tostring(tree).decode('utf-8')
417+
418+
if expected_str != actual_str:
419+
if bless:
420+
with open(snapshot_path, 'w') as snapshot_file:
421+
snapshot_file.write(actual_str)
422+
else:
423+
print('--- expected ---\n')
424+
print(expected_str)
425+
print('\n\n--- actual ---\n')
426+
print(actual_str)
427+
print()
428+
raise FailedCheck('Actual snapshot value is different than expected')
429+
390430
def stderr(*args):
391431
if sys.version_info.major < 3:
392432
file = codecs.getwriter('utf-8')(sys.stderr)
@@ -448,6 +488,28 @@ def check_command(c, cache):
448488
ret = expected == found
449489
else:
450490
raise InvalidCheck('Invalid number of @{} arguments'.format(c.cmd))
491+
492+
elif c.cmd == 'snapshot': # snapshot test
493+
if len(c.args) == 3: # @snapshot <snapshot-name> <html-path> <xpath>
494+
[snapshot_name, html_path, pattern] = c.args
495+
tree = cache.get_tree(html_path)
496+
xpath = normalize_xpath(pattern)
497+
subtrees = tree.findall(xpath)
498+
if len(subtrees) == 1:
499+
[subtree] = subtrees
500+
try:
501+
check_snapshot(snapshot_name, subtree)
502+
ret = True
503+
except FailedCheck as err:
504+
cerr = str(err)
505+
ret = False
506+
elif len(subtrees) == 0:
507+
raise FailedCheck('XPATH did not match')
508+
else:
509+
raise FailedCheck('Expected 1 match, but found {}'.format(len(subtrees)))
510+
else:
511+
raise InvalidCheck('Invalid number of @{} arguments'.format(c.cmd))
512+
451513
elif c.cmd == 'has-dir': # has-dir test
452514
if len(c.args) == 1: # @has-dir <path> = has-dir test
453515
try:
@@ -458,11 +520,13 @@ def check_command(c, cache):
458520
ret = False
459521
else:
460522
raise InvalidCheck('Invalid number of @{} arguments'.format(c.cmd))
523+
461524
elif c.cmd == 'valid-html':
462525
raise InvalidCheck('Unimplemented @valid-html')
463526

464527
elif c.cmd == 'valid-links':
465528
raise InvalidCheck('Unimplemented @valid-links')
529+
466530
else:
467531
raise InvalidCheck('Unrecognized @{}'.format(c.cmd))
468532

@@ -483,11 +547,19 @@ def check(target, commands):
483547

484548

485549
if __name__ == '__main__':
486-
if len(sys.argv) != 3:
487-
stderr('Usage: {} <doc dir> <template>'.format(sys.argv[0]))
550+
if len(sys.argv) not in [3, 4]:
551+
stderr('Usage: {} <doc dir> <template> [--bless]'.format(sys.argv[0]))
488552
raise SystemExit(1)
489553

490-
check(sys.argv[1], get_commands(sys.argv[2]))
554+
rust_test_path = sys.argv[2]
555+
if len(sys.argv) > 3 and sys.argv[3] == '--bless':
556+
bless = True
557+
else:
558+
# We only support `--bless` at the end of the arguments.
559+
# This assert is to prevent silent failures.
560+
assert '--bless' not in sys.argv
561+
bless = False
562+
check(sys.argv[1], get_commands(rust_test_path))
491563
if ERR_COUNT:
492564
stderr("\nEncountered {} errors".format(ERR_COUNT))
493565
raise SystemExit(1)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<div class="docblock"><p>Hello world!
2+
Goodbye!
3+
Hello again!</p>
4+
</div>
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<div class="docblock"><p>Hello world!</p>
2+
<p>Goodbye!
3+
Hello again!</p>
4+
</div>

‎src/test/rustdoc/mixing-doc-comments-and-attrs.rs‎

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,15 @@
11
#![crate_name = "foo"]
22

33
// @has 'foo/struct.S1.html'
4-
// @count - '//details[@class="rustdoc-toggle top-doc"]/div[@class="docblock"]/p' \
5-
// 1
6-
// @has - '//details[@class="rustdoc-toggle top-doc"]/div[@class="docblock"]/p[1]' \
7-
// 'Hello world! Goodbye! Hello again!'
4+
// @snapshot S1_top-doc - '//details[@class="rustdoc-toggle top-doc"]/div[@class="docblock"]'
85

96
#[doc = "Hello world!\n\n"]
107
/// Goodbye!
118
#[doc = " Hello again!\n"]
129
pub struct S1;
1310

1411
// @has 'foo/struct.S2.html'
15-
// @count - '//details[@class="rustdoc-toggle top-doc"]/div[@class="docblock"]/p' \
16-
// 2
17-
// @has - '//details[@class="rustdoc-toggle top-doc"]/div[@class="docblock"]/p[1]' \
18-
// 'Hello world!'
19-
// @has - '//details[@class="rustdoc-toggle top-doc"]/div[@class="docblock"]/p[2]' \
20-
// 'Goodbye! Hello again!'
12+
// @snapshot S2_top-doc - '//details[@class="rustdoc-toggle top-doc"]/div[@class="docblock"]'
2113

2214
/// Hello world!
2315
///
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#![feature(generators)]
2+
3+
fn foo() -> impl Sized {
4+
yield 1; //~ ERROR E0627
5+
}
6+
7+
fn main() {}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0627]: yield expression outside of generator literal
2+
--> $DIR/issue-91477.rs:4:5
3+
|
4+
LL | yield 1;
5+
| ^^^^^^^
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0627`.

‎src/test/ui/macros/macro-pat-pattern-followed-by-or-in-2021.stderr‎

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,29 @@ error: `$x:pat` is followed by `|`, which is not allowed for `pat` fragments
22
--> $DIR/macro-pat-pattern-followed-by-or-in-2021.rs:3:28
33
|
44
LL | macro_rules! foo { ($x:pat | $y:pat) => {} }
5-
| ^ not allowed after `pat` fragments
5+
| ------ ^ not allowed after `pat` fragments
6+
| |
7+
| help: try a `pat_param` fragment specifier instead: `$x:pat_param`
68
|
79
= note: allowed there are: `=>`, `,`, `=`, `if` or `in`
810

911
error: `$x:pat` is followed by `|`, which is not allowed for `pat` fragments
1012
--> $DIR/macro-pat-pattern-followed-by-or-in-2021.rs:4:32
1113
|
1214
LL | macro_rules! bar { ($($x:pat)+ | $($y:pat)+) => {} }
13-
| ^ not allowed after `pat` fragments
15+
| ------ ^ not allowed after `pat` fragments
16+
| |
17+
| help: try a `pat_param` fragment specifier instead: `$x:pat_param`
1418
|
1519
= note: allowed there are: `=>`, `,`, `=`, `if` or `in`
1620

1721
error: `$pat:pat` may be followed by `|`, which is not allowed for `pat` fragments
1822
--> $DIR/macro-pat-pattern-followed-by-or-in-2021.rs:7:36
1923
|
2024
LL | ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => {
21-
| ^ not allowed after `pat` fragments
25+
| -------- ^ not allowed after `pat` fragments
26+
| |
27+
| help: try a `pat_param` fragment specifier instead: `$pat:pat_param`
2228
|
2329
= note: allowed there are: `=>`, `,`, `=`, `if` or `in`
2430

‎src/test/ui/macros/macro-pat2021-pattern-followed-by-or.stderr‎

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,29 @@ error: `$x:pat` is followed by `|`, which is not allowed for `pat` fragments
22
--> $DIR/macro-pat2021-pattern-followed-by-or.rs:4:28
33
|
44
LL | macro_rules! foo { ($x:pat | $y:pat) => {} }
5-
| ^ not allowed after `pat` fragments
5+
| ------ ^ not allowed after `pat` fragments
6+
| |
7+
| help: try a `pat_param` fragment specifier instead: `$x:pat_param`
68
|
79
= note: allowed there are: `=>`, `,`, `=`, `if` or `in`
810

911
error: `$x:pat` is followed by `|`, which is not allowed for `pat` fragments
1012
--> $DIR/macro-pat2021-pattern-followed-by-or.rs:7:28
1113
|
1214
LL | macro_rules! ogg { ($x:pat | $y:pat_param) => {} }
13-
| ^ not allowed after `pat` fragments
15+
| ------ ^ not allowed after `pat` fragments
16+
| |
17+
| help: try a `pat_param` fragment specifier instead: `$x:pat_param`
1418
|
1519
= note: allowed there are: `=>`, `,`, `=`, `if` or `in`
1620

1721
error: `$pat:pat` may be followed by `|`, which is not allowed for `pat` fragments
1822
--> $DIR/macro-pat2021-pattern-followed-by-or.rs:9:35
1923
|
2024
LL | ( $expr:expr , $( $( $pat:pat)|+ => $expr_arm:pat),+ ) => {
21-
| ^ not allowed after `pat` fragments
25+
| -------- ^ not allowed after `pat` fragments
26+
| |
27+
| help: try a `pat_param` fragment specifier instead: `$pat:pat_param`
2228
|
2329
= note: allowed there are: `=>`, `,`, `=`, `if` or `in`
2430

‎src/test/ui/numeric/numeric-cast.stderr‎

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -994,8 +994,8 @@ error[E0308]: mismatched types
994994
LL | foo::<f64>(x_usize);
995995
| ^^^^^^^ expected `f64`, found `usize`
996996
|
997-
help: you can cast a `usize` to an `f64`, producing the floating point representation of the integer,
998-
| rounded if necessary
997+
help: you can cast a `usize` to an `f64`, producing the floating point representation of the integer, rounded if necessary
998+
|
999999
LL | foo::<f64>(x_usize as f64);
10001000
| ++++++
10011001

@@ -1005,8 +1005,8 @@ error[E0308]: mismatched types
10051005
LL | foo::<f64>(x_u64);
10061006
| ^^^^^ expected `f64`, found `u64`
10071007
|
1008-
help: you can cast a `u64` to an `f64`, producing the floating point representation of the integer,
1009-
| rounded if necessary
1008+
help: you can cast a `u64` to an `f64`, producing the floating point representation of the integer, rounded if necessary
1009+
|
10101010
LL | foo::<f64>(x_u64 as f64);
10111011
| ++++++
10121012

@@ -1115,8 +1115,8 @@ error[E0308]: mismatched types
11151115
LL | foo::<f32>(x_usize);
11161116
| ^^^^^^^ expected `f32`, found `usize`
11171117
|
1118-
help: you can cast a `usize` to an `f32`, producing the floating point representation of the integer,
1119-
| rounded if necessary
1118+
help: you can cast a `usize` to an `f32`, producing the floating point representation of the integer, rounded if necessary
1119+
|
11201120
LL | foo::<f32>(x_usize as f32);
11211121
| ++++++
11221122

@@ -1126,8 +1126,8 @@ error[E0308]: mismatched types
11261126
LL | foo::<f32>(x_u64);
11271127
| ^^^^^ expected `f32`, found `u64`
11281128
|
1129-
help: you can cast a `u64` to an `f32`, producing the floating point representation of the integer,
1130-
| rounded if necessary
1129+
help: you can cast a `u64` to an `f32`, producing the floating point representation of the integer, rounded if necessary
1130+
|
11311131
LL | foo::<f32>(x_u64 as f32);
11321132
| ++++++
11331133

@@ -1137,8 +1137,8 @@ error[E0308]: mismatched types
11371137
LL | foo::<f32>(x_u32);
11381138
| ^^^^^ expected `f32`, found `u32`
11391139
|
1140-
help: you can cast a `u32` to an `f32`, producing the floating point representation of the integer,
1141-
| rounded if necessary
1140+
help: you can cast a `u32` to an `f32`, producing the floating point representation of the integer, rounded if necessary
1141+
|
11421142
LL | foo::<f32>(x_u32 as f32);
11431143
| ++++++
11441144

‎src/tools/compiletest/src/runtest.rs‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2219,12 +2219,12 @@ impl<'test> TestCx<'test> {
22192219
self.check_rustdoc_test_option(proc_res);
22202220
} else {
22212221
let root = self.config.find_rust_src_root().unwrap();
2222-
let res = self.cmd2procres(
2223-
Command::new(&self.config.docck_python)
2224-
.arg(root.join("src/etc/htmldocck.py"))
2225-
.arg(&out_dir)
2226-
.arg(&self.testpaths.file),
2227-
);
2222+
let mut cmd = Command::new(&self.config.docck_python);
2223+
cmd.arg(root.join("src/etc/htmldocck.py")).arg(&out_dir).arg(&self.testpaths.file);
2224+
if self.config.bless {
2225+
cmd.arg("--bless");
2226+
}
2227+
let res = self.cmd2procres(&mut cmd);
22282228
if !res.status.success() {
22292229
self.fatal_proc_rec_with_ctx("htmldocck failed!", &res, |mut this| {
22302230
this.compare_to_default_rustdoc(&out_dir)

0 commit comments

Comments
 (0)
This repository has been archived.