Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit b8dc6aa

Browse files
committedDec 11, 2021
Auto merge of #91792 - matthiaskrgr:rollup-2epg7jq, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #91617 (Improve the readability of `List<T>`.) - #91640 (Simplify collection of in-band lifetimes) - #91682 (rustdoc: Show type layout for type aliases) - #91711 (Improve `std::iter::zip` example) - #91717 (Add deprecation warning for --passes) - #91718 (give more help in the unaligned_references lint) - #91782 (Correct since attribute for `is_symlink` feature) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents b9a37ad + bb23d82 commit b8dc6aa

File tree

32 files changed

+405
-271
lines changed

32 files changed

+405
-271
lines changed
 

‎compiler/rustc_ast_lowering/src/item.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -247,12 +247,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
247247
AnonymousLifetimeMode::PassThrough,
248248
|this, idty| {
249249
let ret_id = asyncness.opt_return_id();
250-
this.lower_fn_decl(
251-
&decl,
252-
Some((fn_def_id.to_def_id(), idty)),
253-
true,
254-
ret_id,
255-
)
250+
this.lower_fn_decl(&decl, Some((fn_def_id, idty)), true, ret_id)
256251
},
257252
);
258253
let sig = hir::FnSig {
@@ -1264,7 +1259,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
12641259
|this, idty| {
12651260
this.lower_fn_decl(
12661261
&sig.decl,
1267-
Some((fn_def_id.to_def_id(), idty)),
1262+
Some((fn_def_id, idty)),
12681263
impl_trait_return_allow,
12691264
is_async,
12701265
)

‎compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 87 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ enum ImplTraitContext<'b, 'a> {
228228
ReturnPositionOpaqueTy {
229229
/// `DefId` for the parent function, used to look up necessary
230230
/// information later.
231-
fn_def_id: DefId,
231+
fn_def_id: LocalDefId,
232232
/// Origin: Either OpaqueTyOrigin::FnReturn or OpaqueTyOrigin::AsyncFn,
233233
origin: hir::OpaqueTyOrigin,
234234
},
@@ -646,31 +646,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
646646
/// parameter while `f` is running (and restored afterwards).
647647
fn collect_in_band_defs<T>(
648648
&mut self,
649-
parent_def_id: LocalDefId,
650-
anonymous_lifetime_mode: AnonymousLifetimeMode,
651-
f: impl FnOnce(&mut Self) -> (Vec<hir::GenericParam<'hir>>, T),
652-
) -> (Vec<hir::GenericParam<'hir>>, T) {
653-
assert!(!self.is_collecting_in_band_lifetimes);
654-
assert!(self.lifetimes_to_define.is_empty());
655-
let old_anonymous_lifetime_mode = self.anonymous_lifetime_mode;
656-
657-
self.anonymous_lifetime_mode = anonymous_lifetime_mode;
658-
self.is_collecting_in_band_lifetimes = true;
659-
660-
let (in_band_ty_params, res) = f(self);
661-
662-
self.is_collecting_in_band_lifetimes = false;
663-
self.anonymous_lifetime_mode = old_anonymous_lifetime_mode;
664-
665-
let lifetimes_to_define = self.lifetimes_to_define.split_off(0);
649+
f: impl FnOnce(&mut Self) -> T,
650+
) -> (Vec<(Span, ParamName)>, T) {
651+
let was_collecting = std::mem::replace(&mut self.is_collecting_in_band_lifetimes, true);
652+
let len = self.lifetimes_to_define.len();
666653

667-
let params = lifetimes_to_define
668-
.into_iter()
669-
.map(|(span, hir_name)| self.lifetime_to_generic_param(span, hir_name, parent_def_id))
670-
.chain(in_band_ty_params.into_iter())
671-
.collect();
654+
let res = f(self);
672655

673-
(params, res)
656+
let lifetimes_to_define = self.lifetimes_to_define.split_off(len);
657+
self.is_collecting_in_band_lifetimes = was_collecting;
658+
(lifetimes_to_define, res)
674659
}
675660

676661
/// Converts a lifetime into a new generic parameter.
@@ -785,27 +770,39 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
785770
anonymous_lifetime_mode: AnonymousLifetimeMode,
786771
f: impl FnOnce(&mut Self, &mut Vec<hir::GenericParam<'hir>>) -> T,
787772
) -> (hir::Generics<'hir>, T) {
788-
let (in_band_defs, (mut lowered_generics, res)) =
789-
self.with_in_scope_lifetime_defs(&generics.params, |this| {
790-
this.collect_in_band_defs(parent_def_id, anonymous_lifetime_mode, |this| {
791-
let mut params = Vec::new();
792-
// Note: it is necessary to lower generics *before* calling `f`.
793-
// When lowering `async fn`, there's a final step when lowering
794-
// the return type that assumes that all in-scope lifetimes have
795-
// already been added to either `in_scope_lifetimes` or
796-
// `lifetimes_to_define`. If we swapped the order of these two,
797-
// in-band-lifetimes introduced by generics or where-clauses
798-
// wouldn't have been added yet.
799-
let generics = this.lower_generics_mut(
800-
generics,
801-
ImplTraitContext::Universal(&mut params, this.current_hir_id_owner),
802-
);
803-
let res = f(this, &mut params);
804-
(params, (generics, res))
773+
let (lifetimes_to_define, (mut lowered_generics, impl_trait_defs, res)) = self
774+
.collect_in_band_defs(|this| {
775+
this.with_anonymous_lifetime_mode(anonymous_lifetime_mode, |this| {
776+
this.with_in_scope_lifetime_defs(&generics.params, |this| {
777+
let mut impl_trait_defs = Vec::new();
778+
// Note: it is necessary to lower generics *before* calling `f`.
779+
// When lowering `async fn`, there's a final step when lowering
780+
// the return type that assumes that all in-scope lifetimes have
781+
// already been added to either `in_scope_lifetimes` or
782+
// `lifetimes_to_define`. If we swapped the order of these two,
783+
// in-band-lifetimes introduced by generics or where-clauses
784+
// wouldn't have been added yet.
785+
let generics = this.lower_generics_mut(
786+
generics,
787+
ImplTraitContext::Universal(
788+
&mut impl_trait_defs,
789+
this.current_hir_id_owner,
790+
),
791+
);
792+
let res = f(this, &mut impl_trait_defs);
793+
(generics, impl_trait_defs, res)
794+
})
805795
})
806796
});
807797

808-
lowered_generics.params.extend(in_band_defs);
798+
lowered_generics.params.extend(
799+
lifetimes_to_define
800+
.into_iter()
801+
.map(|(span, hir_name)| {
802+
self.lifetime_to_generic_param(span, hir_name, parent_def_id)
803+
})
804+
.chain(impl_trait_defs),
805+
);
809806

810807
let lowered_generics = lowered_generics.into_generics(self.arena);
811808
(lowered_generics, res)
@@ -1380,7 +1377,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
13801377
fn lower_opaque_impl_trait(
13811378
&mut self,
13821379
span: Span,
1383-
fn_def_id: Option<DefId>,
1380+
fn_def_id: Option<LocalDefId>,
13841381
origin: hir::OpaqueTyOrigin,
13851382
opaque_ty_node_id: NodeId,
13861383
capturable_lifetimes: Option<&FxHashSet<hir::LifetimeName>>,
@@ -1452,7 +1449,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
14521449
span: lctx.lower_span(span),
14531450
},
14541451
bounds: hir_bounds,
1455-
impl_trait_fn: fn_def_id,
14561452
origin,
14571453
};
14581454

@@ -1522,7 +1518,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
15221518
fn lower_fn_decl(
15231519
&mut self,
15241520
decl: &FnDecl,
1525-
mut in_band_ty_params: Option<(DefId, &mut Vec<hir::GenericParam<'hir>>)>,
1521+
mut in_band_ty_params: Option<(LocalDefId, &mut Vec<hir::GenericParam<'hir>>)>,
15261522
impl_trait_return_allow: bool,
15271523
make_ret_async: Option<NodeId>,
15281524
) -> &'hir hir::FnDecl<'hir> {
@@ -1580,7 +1576,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
15801576
Some((def_id, _)) if impl_trait_return_allow => {
15811577
ImplTraitContext::ReturnPositionOpaqueTy {
15821578
fn_def_id: def_id,
1583-
origin: hir::OpaqueTyOrigin::FnReturn,
1579+
origin: hir::OpaqueTyOrigin::FnReturn(def_id),
15841580
}
15851581
}
15861582
_ => ImplTraitContext::disallowed(),
@@ -1635,7 +1631,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
16351631
fn lower_async_fn_ret_ty(
16361632
&mut self,
16371633
output: &FnRetTy,
1638-
fn_def_id: DefId,
1634+
fn_def_id: LocalDefId,
16391635
opaque_ty_node_id: NodeId,
16401636
) -> hir::FnRetTy<'hir> {
16411637
debug!(
@@ -1689,18 +1685,29 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
16891685
// this is because the elided lifetimes from the return type
16901686
// should be figured out using the ordinary elision rules, and
16911687
// this desugaring achieves that.
1688+
1689+
debug!("lower_async_fn_ret_ty: in_scope_lifetimes={:#?}", self.in_scope_lifetimes);
1690+
debug!("lower_async_fn_ret_ty: lifetimes_to_define={:#?}", self.lifetimes_to_define);
1691+
1692+
// Calculate all the lifetimes that should be captured
1693+
// by the opaque type. This should include all in-scope
1694+
// lifetime parameters, including those defined in-band.
16921695
//
1693-
// The variable `input_lifetimes_count` tracks the number of
1694-
// lifetime parameters to the opaque type *not counting* those
1695-
// lifetimes elided in the return type. This includes those
1696-
// that are explicitly declared (`in_scope_lifetimes`) and
1697-
// those elided lifetimes we found in the arguments (current
1698-
// content of `lifetimes_to_define`). Next, we will process
1699-
// the return type, which will cause `lifetimes_to_define` to
1700-
// grow.
1701-
let input_lifetimes_count = self.in_scope_lifetimes.len() + self.lifetimes_to_define.len();
1702-
1703-
let mut lifetime_params = Vec::new();
1696+
// `lifetime_params` is a vector of tuple (span, parameter name, lifetime name).
1697+
1698+
// Input lifetime like `'a` or `'1`:
1699+
let mut lifetime_params: Vec<_> = self
1700+
.in_scope_lifetimes
1701+
.iter()
1702+
.cloned()
1703+
.map(|name| (name.ident().span, name, hir::LifetimeName::Param(name)))
1704+
.chain(
1705+
self.lifetimes_to_define
1706+
.iter()
1707+
.map(|&(span, name)| (span, name, hir::LifetimeName::Param(name))),
1708+
)
1709+
.collect();
1710+
17041711
self.with_hir_id_owner(opaque_ty_node_id, |this| {
17051712
// We have to be careful to get elision right here. The
17061713
// idea is that we create a lifetime parameter for each
@@ -1710,34 +1717,26 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
17101717
//
17111718
// Then, we will create `fn foo(..) -> Foo<'_, '_>`, and
17121719
// hence the elision takes place at the fn site.
1713-
let future_bound = this
1714-
.with_anonymous_lifetime_mode(AnonymousLifetimeMode::CreateParameter, |this| {
1715-
this.lower_async_fn_output_type_to_future_bound(output, fn_def_id, span)
1720+
let (lifetimes_to_define, future_bound) =
1721+
this.with_anonymous_lifetime_mode(AnonymousLifetimeMode::CreateParameter, |this| {
1722+
this.collect_in_band_defs(|this| {
1723+
this.lower_async_fn_output_type_to_future_bound(output, fn_def_id, span)
1724+
})
17161725
});
1717-
17181726
debug!("lower_async_fn_ret_ty: future_bound={:#?}", future_bound);
1727+
debug!("lower_async_fn_ret_ty: lifetimes_to_define={:#?}", lifetimes_to_define);
17191728

1720-
// Calculate all the lifetimes that should be captured
1721-
// by the opaque type. This should include all in-scope
1722-
// lifetime parameters, including those defined in-band.
1723-
//
1724-
// Note: this must be done after lowering the output type,
1725-
// as the output type may introduce new in-band lifetimes.
1726-
lifetime_params = this
1727-
.in_scope_lifetimes
1728-
.iter()
1729-
.cloned()
1730-
.map(|name| (name.ident().span, name))
1731-
.chain(this.lifetimes_to_define.iter().cloned())
1732-
.collect();
1733-
1734-
debug!("lower_async_fn_ret_ty: in_scope_lifetimes={:#?}", this.in_scope_lifetimes);
1735-
debug!("lower_async_fn_ret_ty: lifetimes_to_define={:#?}", this.lifetimes_to_define);
1729+
lifetime_params.extend(
1730+
// Output lifetime like `'_`:
1731+
lifetimes_to_define
1732+
.into_iter()
1733+
.map(|(span, name)| (span, name, hir::LifetimeName::Implicit(false))),
1734+
);
17361735
debug!("lower_async_fn_ret_ty: lifetime_params={:#?}", lifetime_params);
17371736

17381737
let generic_params =
1739-
this.arena.alloc_from_iter(lifetime_params.iter().map(|(span, hir_name)| {
1740-
this.lifetime_to_generic_param(*span, *hir_name, opaque_ty_def_id)
1738+
this.arena.alloc_from_iter(lifetime_params.iter().map(|&(span, hir_name, _)| {
1739+
this.lifetime_to_generic_param(span, hir_name, opaque_ty_def_id)
17411740
}));
17421741

17431742
let opaque_ty_item = hir::OpaqueTy {
@@ -1747,8 +1746,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
17471746
span: this.lower_span(span),
17481747
},
17491748
bounds: arena_vec![this; future_bound],
1750-
impl_trait_fn: Some(fn_def_id),
1751-
origin: hir::OpaqueTyOrigin::AsyncFn,
1749+
origin: hir::OpaqueTyOrigin::AsyncFn(fn_def_id),
17521750
};
17531751

17541752
trace!("exist ty from async fn def id: {:#?}", opaque_ty_def_id);
@@ -1771,25 +1769,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
17711769
//
17721770
// For the "output" lifetime parameters, we just want to
17731771
// generate `'_`.
1774-
let mut generic_args = Vec::with_capacity(lifetime_params.len());
1775-
generic_args.extend(lifetime_params[..input_lifetimes_count].iter().map(
1776-
|&(span, hir_name)| {
1777-
// Input lifetime like `'a` or `'1`:
1772+
let generic_args =
1773+
self.arena.alloc_from_iter(lifetime_params.into_iter().map(|(span, _, name)| {
17781774
GenericArg::Lifetime(hir::Lifetime {
17791775
hir_id: self.next_id(),
17801776
span: self.lower_span(span),
1781-
name: hir::LifetimeName::Param(hir_name),
1777+
name,
17821778
})
1783-
},
1784-
));
1785-
generic_args.extend(lifetime_params[input_lifetimes_count..].iter().map(|&(span, _)|
1786-
// Output lifetime like `'_`.
1787-
GenericArg::Lifetime(hir::Lifetime {
1788-
hir_id: self.next_id(),
1789-
span: self.lower_span(span),
1790-
name: hir::LifetimeName::Implicit(false),
1791-
})));
1792-
let generic_args = self.arena.alloc_from_iter(generic_args);
1779+
}));
17931780

17941781
// Create the `Foo<...>` reference itself. Note that the `type
17951782
// Foo = impl Trait` is, internally, created as a child of the
@@ -1805,7 +1792,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
18051792
fn lower_async_fn_output_type_to_future_bound(
18061793
&mut self,
18071794
output: &FnRetTy,
1808-
fn_def_id: DefId,
1795+
fn_def_id: LocalDefId,
18091796
span: Span,
18101797
) -> hir::GenericBound<'hir> {
18111798
// Compute the `T` in `Future<Output = T>` from the return type.
@@ -1816,7 +1803,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
18161803
// generates.
18171804
let context = ImplTraitContext::ReturnPositionOpaqueTy {
18181805
fn_def_id,
1819-
origin: hir::OpaqueTyOrigin::FnReturn,
1806+
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
18201807
};
18211808
self.lower_ty(ty, context)
18221809
}
@@ -2453,17 +2440,12 @@ impl<'hir> GenericArgsCtor<'hir> {
24532440
}
24542441
}
24552442

2443+
#[tracing::instrument(level = "debug")]
24562444
fn lifetimes_from_impl_trait_bounds(
24572445
opaque_ty_id: NodeId,
24582446
bounds: hir::GenericBounds<'_>,
24592447
lifetimes_to_include: Option<&FxHashSet<hir::LifetimeName>>,
24602448
) -> Vec<(hir::LifetimeName, Span)> {
2461-
debug!(
2462-
"lifetimes_from_impl_trait_bounds(opaque_ty_id={:?}, \
2463-
bounds={:#?})",
2464-
opaque_ty_id, bounds,
2465-
);
2466-
24672449
// This visitor walks over `impl Trait` bounds and creates defs for all lifetimes that
24682450
// appear in the bounds, excluding lifetimes that are created within the bounds.
24692451
// E.g., `'a`, `'b`, but not `'c` in `impl for<'c> SomeTrait<'a, 'b, 'c>`.

‎compiler/rustc_borrowck/src/region_infer/opaque_types.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ fn check_opaque_type_parameter_valid(
173173
// fn foo<l0..'ln>() -> foo::<'static..'static>::Foo<'l0..'lm>.
174174
//
175175
// which would error here on all of the `'static` args.
176-
OpaqueTyOrigin::FnReturn | OpaqueTyOrigin::AsyncFn => return true,
176+
OpaqueTyOrigin::FnReturn(..) | OpaqueTyOrigin::AsyncFn(..) => return true,
177177
// Check these
178178
OpaqueTyOrigin::TyAlias => {}
179179
}

‎compiler/rustc_hir/src/hir.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2248,17 +2248,16 @@ pub struct BareFnTy<'hir> {
22482248
pub struct OpaqueTy<'hir> {
22492249
pub generics: Generics<'hir>,
22502250
pub bounds: GenericBounds<'hir>,
2251-
pub impl_trait_fn: Option<DefId>,
22522251
pub origin: OpaqueTyOrigin,
22532252
}
22542253

22552254
/// From whence the opaque type came.
22562255
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)]
22572256
pub enum OpaqueTyOrigin {
22582257
/// `-> impl Trait`
2259-
FnReturn,
2258+
FnReturn(LocalDefId),
22602259
/// `async fn`
2261-
AsyncFn,
2260+
AsyncFn(LocalDefId),
22622261
/// type aliases: `type Foo = impl Trait;`
22632262
TyAlias,
22642263
}
@@ -2809,7 +2808,9 @@ impl ItemKind<'_> {
28092808
Some(match *self {
28102809
ItemKind::Fn(_, ref generics, _)
28112810
| ItemKind::TyAlias(_, ref generics)
2812-
| ItemKind::OpaqueTy(OpaqueTy { ref generics, impl_trait_fn: None, .. })
2811+
| ItemKind::OpaqueTy(OpaqueTy {
2812+
ref generics, origin: OpaqueTyOrigin::TyAlias, ..
2813+
})
28132814
| ItemKind::Enum(_, ref generics)
28142815
| ItemKind::Struct(_, ref generics)
28152816
| ItemKind::Union(_, ref generics)

‎compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
107107
kind:
108108
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
109109
bounds,
110-
origin: hir::OpaqueTyOrigin::AsyncFn,
110+
origin: hir::OpaqueTyOrigin::AsyncFn(..),
111111
..
112112
}),
113113
..

‎compiler/rustc_infer/src/infer/opaque_types.rs

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
276276
debug!(?concrete_ty);
277277

278278
let first_own_region = match opaque_defn.origin {
279-
hir::OpaqueTyOrigin::FnReturn | hir::OpaqueTyOrigin::AsyncFn => {
279+
hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {
280280
// We lower
281281
//
282282
// fn foo<'l0..'ln>() -> impl Trait<'l0..'lm>
@@ -461,35 +461,29 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
461461
if let Some(def_id) = def_id.as_local() {
462462
let opaque_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
463463
let parent_def_id = self.infcx.defining_use_anchor;
464-
let (in_definition_scope, origin) = match tcx.hir().expect_item(def_id).kind
465-
{
464+
let item_kind = &tcx.hir().expect_item(def_id).kind;
465+
let hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) = item_kind else {
466+
span_bug!(
467+
self.value_span,
468+
"weird opaque type: {:#?}, {:#?}",
469+
ty.kind(),
470+
item_kind
471+
)
472+
};
473+
let in_definition_scope = match *origin {
474+
// Async `impl Trait`
475+
hir::OpaqueTyOrigin::AsyncFn(parent) => parent == parent_def_id,
466476
// Anonymous `impl Trait`
467-
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
468-
impl_trait_fn: Some(parent),
469-
origin,
470-
..
471-
}) => (parent == parent_def_id.to_def_id(), origin),
477+
hir::OpaqueTyOrigin::FnReturn(parent) => parent == parent_def_id,
472478
// Named `type Foo = impl Bar;`
473-
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
474-
impl_trait_fn: None,
475-
origin,
476-
..
477-
}) => {
478-
(may_define_opaque_type(tcx, parent_def_id, opaque_hir_id), origin)
479-
}
480-
ref itemkind => {
481-
span_bug!(
482-
self.value_span,
483-
"weird opaque type: {:#?}, {:#?}",
484-
ty.kind(),
485-
itemkind
486-
)
479+
hir::OpaqueTyOrigin::TyAlias => {
480+
may_define_opaque_type(tcx, parent_def_id, opaque_hir_id)
487481
}
488482
};
489483
if in_definition_scope {
490484
let opaque_type_key =
491485
OpaqueTypeKey { def_id: def_id.to_def_id(), substs };
492-
return self.fold_opaque_ty(ty, opaque_type_key, origin);
486+
return self.fold_opaque_ty(ty, opaque_type_key, *origin);
493487
}
494488

495489
debug!(

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

Lines changed: 89 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
use crate::arena::Arena;
2-
32
use rustc_serialize::{Encodable, Encoder};
4-
53
use std::alloc::Layout;
64
use std::cmp::Ordering;
75
use std::fmt;
@@ -12,49 +10,69 @@ use std::ops::Deref;
1210
use std::ptr;
1311
use std::slice;
1412

15-
extern "C" {
16-
/// A dummy type used to force `List` to be unsized while not requiring references to it be wide
17-
/// pointers.
18-
type OpaqueListContents;
19-
}
20-
21-
/// A wrapper for slices with the additional invariant
22-
/// that the slice is interned and no other slice with
23-
/// the same contents can exist in the same context.
24-
/// This means we can use pointer for both
25-
/// equality comparisons and hashing.
26-
///
27-
/// Unlike slices, the types contained in `List` are expected to be `Copy`
28-
/// and iterating over a `List` returns `T` instead of a reference.
29-
///
30-
/// Note: `Slice` was already taken by the `Ty`.
13+
/// `List<T>` is a bit like `&[T]`, but with some critical differences.
14+
/// - IMPORTANT: Every `List<T>` is *required* to have unique contents. The
15+
/// type's correctness relies on this, *but it does not enforce it*.
16+
/// Therefore, any code that creates a `List<T>` must ensure uniqueness
17+
/// itself. In practice this is achieved by interning.
18+
/// - The length is stored within the `List<T>`, so `&List<Ty>` is a thin
19+
/// pointer.
20+
/// - Because of this, you cannot get a `List<T>` that is a sub-list of another
21+
/// `List<T>`. You can get a sub-slice `&[T]`, however.
22+
/// - `List<T>` can be used with `CopyTaggedPtr`, which is useful within
23+
/// structs whose size must be minimized.
24+
/// - Because of the uniqueness assumption, we can use the address of a
25+
/// `List<T>` for faster equality comparisons and hashing.
26+
/// - `T` must be `Copy`. This lets `List<T>` be stored in a dropless arena and
27+
/// iterators return a `T` rather than a `&T`.
28+
/// - `T` must not be zero-sized.
3129
#[repr(C)]
3230
pub struct List<T> {
3331
len: usize,
32+
33+
/// Although this claims to be a zero-length array, in practice `len`
34+
/// elements are actually present.
3435
data: [T; 0],
36+
3537
opaque: OpaqueListContents,
3638
}
3739

38-
unsafe impl<'a, T: 'a> rustc_data_structures::tagged_ptr::Pointer for &'a List<T> {
39-
const BITS: usize = std::mem::align_of::<usize>().trailing_zeros() as usize;
40-
#[inline]
41-
fn into_usize(self) -> usize {
42-
self as *const List<T> as usize
43-
}
44-
#[inline]
45-
unsafe fn from_usize(ptr: usize) -> Self {
46-
&*(ptr as *const List<T>)
47-
}
48-
unsafe fn with_ref<R, F: FnOnce(&Self) -> R>(ptr: usize, f: F) -> R {
49-
// Self: Copy so this is fine
50-
let ptr = Self::from_usize(ptr);
51-
f(&ptr)
52-
}
40+
extern "C" {
41+
/// A dummy type used to force `List` to be unsized while not requiring
42+
/// references to it be wide pointers.
43+
type OpaqueListContents;
5344
}
5445

55-
unsafe impl<T: Sync> Sync for List<T> {}
46+
impl<T> List<T> {
47+
/// Returns a reference to the (unique, static) empty list.
48+
#[inline(always)]
49+
pub fn empty<'a>() -> &'a List<T> {
50+
#[repr(align(64))]
51+
struct MaxAlign;
52+
53+
assert!(mem::align_of::<T>() <= mem::align_of::<MaxAlign>());
54+
55+
#[repr(C)]
56+
struct InOrder<T, U>(T, U);
57+
58+
// The empty slice is static and contains a single `0` usize (for the
59+
// length) that is 64-byte aligned, thus featuring the necessary
60+
// trailing padding for elements with up to 64-byte alignment.
61+
static EMPTY_SLICE: InOrder<usize, MaxAlign> = InOrder(0, MaxAlign);
62+
unsafe { &*(&EMPTY_SLICE as *const _ as *const List<T>) }
63+
}
64+
}
5665

5766
impl<T: Copy> List<T> {
67+
/// Allocates a list from `arena` and copies the contents of `slice` into it.
68+
///
69+
/// WARNING: the contents *must be unique*, such that no list with these
70+
/// contents has been previously created. If not, operations such as `eq`
71+
/// and `hash` might give incorrect results.
72+
///
73+
/// Panics if `T` is `Drop`, or `T` is zero-sized, or the slice is empty
74+
/// (because the empty list exists statically, and is available via
75+
/// `empty()`).
5876
#[inline]
5977
pub(super) fn from_arena<'tcx>(arena: &'tcx Arena<'tcx>, slice: &[T]) -> &'tcx List<T> {
6078
assert!(!mem::needs_drop::<T>());
@@ -73,7 +91,7 @@ impl<T: Copy> List<T> {
7391
.cast::<T>()
7492
.copy_from_nonoverlapping(slice.as_ptr(), slice.len());
7593

76-
&mut *mem
94+
&*mem
7795
}
7896
}
7997

@@ -107,11 +125,24 @@ impl<S: Encoder, T: Encodable<S>> Encodable<S> for &List<T> {
107125
}
108126
}
109127

128+
impl<T: PartialEq> PartialEq for List<T> {
129+
#[inline]
130+
fn eq(&self, other: &List<T>) -> bool {
131+
// Pointer equality implies list equality (due to the unique contents
132+
// assumption).
133+
ptr::eq(self, other)
134+
}
135+
}
136+
137+
impl<T: Eq> Eq for List<T> {}
138+
110139
impl<T> Ord for List<T>
111140
where
112141
T: Ord,
113142
{
114143
fn cmp(&self, other: &List<T>) -> Ordering {
144+
// Pointer equality implies list equality (due to the unique contents
145+
// assumption), but the contents must be compared otherwise.
115146
if self == other { Ordering::Equal } else { <[T] as Ord>::cmp(&**self, &**other) }
116147
}
117148
}
@@ -121,6 +152,8 @@ where
121152
T: PartialOrd,
122153
{
123154
fn partial_cmp(&self, other: &List<T>) -> Option<Ordering> {
155+
// Pointer equality implies list equality (due to the unique contents
156+
// assumption), but the contents must be compared otherwise.
124157
if self == other {
125158
Some(Ordering::Equal)
126159
} else {
@@ -129,17 +162,11 @@ where
129162
}
130163
}
131164

132-
impl<T: PartialEq> PartialEq for List<T> {
133-
#[inline]
134-
fn eq(&self, other: &List<T>) -> bool {
135-
ptr::eq(self, other)
136-
}
137-
}
138-
impl<T: Eq> Eq for List<T> {}
139-
140165
impl<T> Hash for List<T> {
141166
#[inline]
142167
fn hash<H: Hasher>(&self, s: &mut H) {
168+
// Pointer hashing is sufficient (due to the unique contents
169+
// assumption).
143170
(self as *const List<T>).hash(s)
144171
}
145172
}
@@ -168,13 +195,24 @@ impl<'a, T: Copy> IntoIterator for &'a List<T> {
168195
}
169196
}
170197

171-
impl<T> List<T> {
172-
#[inline(always)]
173-
pub fn empty<'a>() -> &'a List<T> {
174-
#[repr(align(64), C)]
175-
struct EmptySlice([u8; 64]);
176-
static EMPTY_SLICE: EmptySlice = EmptySlice([0; 64]);
177-
assert!(mem::align_of::<T>() <= 64);
178-
unsafe { &*(&EMPTY_SLICE as *const _ as *const List<T>) }
198+
unsafe impl<T: Sync> Sync for List<T> {}
199+
200+
unsafe impl<'a, T: 'a> rustc_data_structures::tagged_ptr::Pointer for &'a List<T> {
201+
const BITS: usize = std::mem::align_of::<usize>().trailing_zeros() as usize;
202+
203+
#[inline]
204+
fn into_usize(self) -> usize {
205+
self as *const List<T> as usize
206+
}
207+
208+
#[inline]
209+
unsafe fn from_usize(ptr: usize) -> &'a List<T> {
210+
&*(ptr as *const List<T>)
211+
}
212+
213+
unsafe fn with_ref<R, F: FnOnce(&Self) -> R>(ptr: usize, f: F) -> R {
214+
// `Self` is `&'a List<T>` which impls `Copy`, so this is fine.
215+
let ptr = Self::from_usize(ptr);
216+
f(&ptr)
179217
}
180218
}

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

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2055,13 +2055,17 @@ impl<'tcx> TyCtxt<'tcx> {
20552055
}
20562056
}
20572057

2058-
/// Yields the parent function's `DefId` if `def_id` is an `impl Trait` definition.
2059-
pub fn is_impl_trait_defn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
2060-
if let Some(def_id) = def_id.as_local() {
2061-
if let Node::Item(item) = tcx.hir().get(tcx.hir().local_def_id_to_hir_id(def_id)) {
2062-
if let hir::ItemKind::OpaqueTy(ref opaque_ty) = item.kind {
2063-
return opaque_ty.impl_trait_fn;
2064-
}
2058+
/// Yields the parent function's `LocalDefId` if `def_id` is an `impl Trait` definition.
2059+
pub fn is_impl_trait_defn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<LocalDefId> {
2060+
let def_id = def_id.as_local()?;
2061+
if let Node::Item(item) = tcx.hir().get(tcx.hir().local_def_id_to_hir_id(def_id)) {
2062+
if let hir::ItemKind::OpaqueTy(ref opaque_ty) = item.kind {
2063+
return match opaque_ty.origin {
2064+
hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent) => {
2065+
Some(parent)
2066+
}
2067+
hir::OpaqueTyOrigin::TyAlias => None,
2068+
};
20652069
}
20662070
}
20672071
None

‎compiler/rustc_mir_transform/src/check_packed_ref.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,11 @@ impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> {
105105
a misaligned reference is undefined behavior (even if that \
106106
reference is never dereferenced)",
107107
)
108+
.help(
109+
"copy the field contents to a local variable, or replace the \
110+
reference with a raw pointer and use `read_unaligned`/`write_unaligned` \
111+
(loads and stores via `*p` must be properly aligned even when using raw pointers)"
112+
)
108113
.emit()
109114
},
110115
);

‎compiler/rustc_resolve/src/late/lifetimes.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -968,7 +968,10 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
968968
let (generics, bounds) = match opaque_ty.kind {
969969
// Named opaque `impl Trait` types are reached via `TyKind::Path`.
970970
// This arm is for `impl Trait` in the types of statics, constants and locals.
971-
hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn: None, .. }) => {
971+
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
972+
origin: hir::OpaqueTyOrigin::TyAlias,
973+
..
974+
}) => {
972975
intravisit::walk_ty(self, ty);
973976

974977
// Elided lifetimes are not allowed in non-return
@@ -985,7 +988,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
985988
}
986989
// RPIT (return position impl trait)
987990
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
988-
impl_trait_fn: Some(_),
991+
origin: hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..),
989992
ref generics,
990993
bounds,
991994
..
@@ -1695,7 +1698,11 @@ fn compute_object_lifetime_defaults(
16951698
hir::ItemKind::Struct(_, ref generics)
16961699
| hir::ItemKind::Union(_, ref generics)
16971700
| hir::ItemKind::Enum(_, ref generics)
1698-
| hir::ItemKind::OpaqueTy(hir::OpaqueTy { ref generics, impl_trait_fn: None, .. })
1701+
| hir::ItemKind::OpaqueTy(hir::OpaqueTy {
1702+
ref generics,
1703+
origin: hir::OpaqueTyOrigin::TyAlias,
1704+
..
1705+
})
16991706
| hir::ItemKind::TyAlias(_, ref generics)
17001707
| hir::ItemKind::Trait(_, _, ref generics, ..) => {
17011708
let result = object_lifetime_defaults_for_item(tcx, generics);
@@ -2067,7 +2074,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
20672074
..
20682075
}) = self.tcx.hir().get(parent_hir_id)
20692076
{
2070-
if opaque.origin != hir::OpaqueTyOrigin::AsyncFn {
2077+
if !matches!(opaque.origin, hir::OpaqueTyOrigin::AsyncFn(..)) {
20712078
continue 'lifetimes;
20722079
}
20732080
// We want to do this only if the liftime identifier is already defined

‎compiler/rustc_ty_utils/src/ty.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ fn trait_of_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
248248
fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
249249
// The param_env of an impl Trait type is its defining function's param_env
250250
if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) {
251-
return param_env(tcx, parent);
251+
return param_env(tcx, parent.to_def_id());
252252
}
253253
// Compute the bounds on Self and the type parameters.
254254

@@ -313,7 +313,7 @@ fn well_formed_types_in_env<'tcx>(
313313

314314
// The environment of an impl Trait type is its defining function's environment.
315315
if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) {
316-
return well_formed_types_in_env(tcx, parent);
316+
return well_formed_types_in_env(tcx, parent.to_def_id());
317317
}
318318

319319
// Compute the bounds on `Self` and the type parameters.

‎compiler/rustc_typeck/src/astconv/mod.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2336,9 +2336,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
23362336
let def_id = item_id.def_id.to_def_id();
23372337

23382338
match opaque_ty.kind {
2339-
hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn, .. }) => {
2340-
self.impl_trait_ty_to_ty(def_id, lifetimes, impl_trait_fn.is_some())
2341-
}
2339+
hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => self
2340+
.impl_trait_ty_to_ty(
2341+
def_id,
2342+
lifetimes,
2343+
matches!(
2344+
origin,
2345+
hir::OpaqueTyOrigin::FnReturn(..)
2346+
| hir::OpaqueTyOrigin::AsyncFn(..)
2347+
),
2348+
),
23422349
ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i),
23432350
}
23442351
}

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
541541
}
542542

543543
if let ItemKind::OpaqueTy(hir::OpaqueTy {
544-
origin: hir::OpaqueTyOrigin::AsyncFn | hir::OpaqueTyOrigin::FnReturn,
544+
origin: hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::FnReturn(..),
545545
..
546546
}) = item.kind
547547
{
@@ -567,7 +567,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
567567
visitor.visit_item(&item);
568568
let is_async = match item.kind {
569569
ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => {
570-
matches!(origin, hir::OpaqueTyOrigin::AsyncFn)
570+
matches!(origin, hir::OpaqueTyOrigin::AsyncFn(..))
571571
}
572572
_ => unreachable!(),
573573
};
@@ -604,7 +604,7 @@ pub(super) fn check_opaque_for_cycles<'tcx>(
604604
) -> Result<(), ErrorReported> {
605605
if tcx.try_expand_impl_trait_type(def_id.to_def_id(), substs).is_err() {
606606
match origin {
607-
hir::OpaqueTyOrigin::AsyncFn => async_opaque_type_cycle_error(tcx, span),
607+
hir::OpaqueTyOrigin::AsyncFn(..) => async_opaque_type_cycle_error(tcx, span),
608608
_ => opaque_type_cycle_error(tcx, def_id, span),
609609
}
610610
Err(ErrorReported)
@@ -635,7 +635,7 @@ fn check_opaque_meets_bounds<'tcx>(
635635
) {
636636
match origin {
637637
// Checked when type checking the function containing them.
638-
hir::OpaqueTyOrigin::FnReturn | hir::OpaqueTyOrigin::AsyncFn => return,
638+
hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => return,
639639
// Can have different predicates to their defining use
640640
hir::OpaqueTyOrigin::TyAlias => {}
641641
}

‎compiler/rustc_typeck/src/collect.rs

Lines changed: 45 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -594,7 +594,11 @@ fn type_param_predicates(
594594
ItemKind::Fn(.., ref generics, _)
595595
| ItemKind::Impl(hir::Impl { ref generics, .. })
596596
| ItemKind::TyAlias(_, ref generics)
597-
| ItemKind::OpaqueTy(OpaqueTy { ref generics, impl_trait_fn: None, .. })
597+
| ItemKind::OpaqueTy(OpaqueTy {
598+
ref generics,
599+
origin: hir::OpaqueTyOrigin::TyAlias,
600+
..
601+
})
598602
| ItemKind::Enum(_, ref generics)
599603
| ItemKind::Struct(_, ref generics)
600604
| ItemKind::Union(_, ref generics) => generics,
@@ -793,7 +797,10 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
793797
}
794798

795799
// Desugared from `impl Trait`, so visited by the function's return type.
796-
hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn: Some(_), .. }) => {}
800+
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
801+
origin: hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..),
802+
..
803+
}) => {}
797804

798805
// Don't call `type_of` on opaque types, since that depends on type
799806
// checking function bodies. `check_item_type` ensures that it's called
@@ -1488,15 +1495,18 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
14881495
Some(tcx.typeck_root_def_id(def_id))
14891496
}
14901497
Node::Item(item) => match item.kind {
1491-
ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn, .. }) => {
1492-
impl_trait_fn.or_else(|| {
1493-
let parent_id = tcx.hir().get_parent_item(hir_id);
1494-
assert!(parent_id != hir_id && parent_id != CRATE_HIR_ID);
1495-
debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id);
1496-
// Opaque types are always nested within another item, and
1497-
// inherit the generics of the item.
1498-
Some(tcx.hir().local_def_id(parent_id).to_def_id())
1499-
})
1498+
ItemKind::OpaqueTy(hir::OpaqueTy {
1499+
origin:
1500+
hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id),
1501+
..
1502+
}) => Some(fn_def_id.to_def_id()),
1503+
ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => {
1504+
let parent_id = tcx.hir().get_parent_item(hir_id);
1505+
assert!(parent_id != hir_id && parent_id != CRATE_HIR_ID);
1506+
debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id);
1507+
// Opaque types are always nested within another item, and
1508+
// inherit the generics of the item.
1509+
Some(tcx.hir().local_def_id(parent_id).to_def_id())
15001510
}
15011511
_ => None,
15021512
},
@@ -2051,31 +2061,32 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
20512061
generics
20522062
}
20532063
ItemKind::OpaqueTy(OpaqueTy {
2054-
bounds: _,
2055-
impl_trait_fn,
2064+
origin: hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::FnReturn(..),
2065+
..
2066+
}) => {
2067+
// return-position impl trait
2068+
//
2069+
// We don't inherit predicates from the parent here:
2070+
// If we have, say `fn f<'a, T: 'a>() -> impl Sized {}`
2071+
// then the return type is `f::<'static, T>::{{opaque}}`.
2072+
//
2073+
// If we inherited the predicates of `f` then we would
2074+
// require that `T: 'static` to show that the return
2075+
// type is well-formed.
2076+
//
2077+
// The only way to have something with this opaque type
2078+
// is from the return type of the containing function,
2079+
// which will ensure that the function's predicates
2080+
// hold.
2081+
return ty::GenericPredicates { parent: None, predicates: &[] };
2082+
}
2083+
ItemKind::OpaqueTy(OpaqueTy {
20562084
ref generics,
2057-
origin: _,
2085+
origin: hir::OpaqueTyOrigin::TyAlias,
2086+
..
20582087
}) => {
2059-
if impl_trait_fn.is_some() {
2060-
// return-position impl trait
2061-
//
2062-
// We don't inherit predicates from the parent here:
2063-
// If we have, say `fn f<'a, T: 'a>() -> impl Sized {}`
2064-
// then the return type is `f::<'static, T>::{{opaque}}`.
2065-
//
2066-
// If we inherited the predicates of `f` then we would
2067-
// require that `T: 'static` to show that the return
2068-
// type is well-formed.
2069-
//
2070-
// The only way to have something with this opaque type
2071-
// is from the return type of the containing function,
2072-
// which will ensure that the function's predicates
2073-
// hold.
2074-
return ty::GenericPredicates { parent: None, predicates: &[] };
2075-
} else {
2076-
// type-alias impl trait
2077-
generics
2078-
}
2088+
// type-alias impl trait
2089+
generics
20792090
}
20802091

20812092
_ => NO_GENERICS,

‎compiler/rustc_typeck/src/collect/type_of.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -394,13 +394,13 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
394394
let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
395395
tcx.mk_adt(def, substs)
396396
}
397-
ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: None, .. }) => {
397+
ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => {
398398
find_opaque_ty_constraints(tcx, def_id)
399399
}
400400
// Opaque types desugared from `impl Trait`.
401-
ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: Some(owner), .. }) => {
401+
ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(owner) | hir::OpaqueTyOrigin::AsyncFn(owner), .. }) => {
402402
let concrete_ty = tcx
403-
.mir_borrowck(owner.expect_local())
403+
.mir_borrowck(owner)
404404
.concrete_opaque_types
405405
.get_value_matching(|(key, _)| key.def_id == def_id.to_def_id())
406406
.copied()
@@ -413,7 +413,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
413413
),
414414
);
415415
if let Some(ErrorReported) =
416-
tcx.typeck(owner.expect_local()).tainted_by_errors
416+
tcx.typeck(owner).tainted_by_errors
417417
{
418418
// Some error in the
419419
// owner fn prevented us from populating

‎library/core/src/iter/adapters/zip.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,23 @@ impl<A: Iterator, B: Iterator> Zip<A, B> {
4545
///
4646
/// let xs = [1, 2, 3];
4747
/// let ys = [4, 5, 6];
48-
/// for (x, y) in zip(&xs, &ys) {
49-
/// println!("x:{}, y:{}", x, y);
50-
/// }
48+
///
49+
/// let mut iter = zip(xs, ys);
50+
///
51+
/// assert_eq!(iter.next().unwrap(), (1, 4));
52+
/// assert_eq!(iter.next().unwrap(), (2, 5));
53+
/// assert_eq!(iter.next().unwrap(), (3, 6));
54+
/// assert!(iter.next().is_none());
5155
///
5256
/// // Nested zips are also possible:
5357
/// let zs = [7, 8, 9];
54-
/// for ((x, y), z) in zip(zip(&xs, &ys), &zs) {
55-
/// println!("x:{}, y:{}, z:{}", x, y, z);
56-
/// }
58+
///
59+
/// let mut iter = zip(zip(xs, ys), zs);
60+
///
61+
/// assert_eq!(iter.next().unwrap(), ((1, 4), 7));
62+
/// assert_eq!(iter.next().unwrap(), ((2, 5), 8));
63+
/// assert_eq!(iter.next().unwrap(), ((3, 6), 9));
64+
/// assert!(iter.next().is_none());
5765
/// ```
5866
#[unstable(feature = "iter_zip", issue = "83574")]
5967
pub fn zip<A, B>(a: A, b: B) -> Zip<A::IntoIter, B::IntoIter>

‎library/std/src/fs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1058,7 +1058,7 @@ impl Metadata {
10581058
/// }
10591059
/// ```
10601060
#[must_use]
1061-
#[stable(feature = "is_symlink", since = "1.57.0")]
1061+
#[stable(feature = "is_symlink", since = "1.58.0")]
10621062
pub fn is_symlink(&self) -> bool {
10631063
self.file_type().is_symlink()
10641064
}

‎library/std/src/path.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2817,7 +2817,7 @@ impl Path {
28172817
/// check errors, call [`fs::symlink_metadata`] and handle its [`Result`]. Then call
28182818
/// [`fs::Metadata::is_symlink`] if it was [`Ok`].
28192819
#[must_use]
2820-
#[stable(feature = "is_symlink", since = "1.57.0")]
2820+
#[stable(feature = "is_symlink", since = "1.58.0")]
28212821
pub fn is_symlink(&self) -> bool {
28222822
fs::symlink_metadata(self).map(|m| m.is_symlink()).unwrap_or(false)
28232823
}

‎src/librustdoc/config.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,19 @@ impl Options {
327327
return Err(0);
328328
}
329329

330+
let color = config::parse_color(matches);
331+
let config::JsonConfig { json_rendered, json_unused_externs, .. } =
332+
config::parse_json(matches);
333+
let error_format = config::parse_error_format(matches, color, json_rendered);
334+
335+
let codegen_options = CodegenOptions::build(matches, error_format);
336+
let debugging_opts = DebuggingOptions::build(matches, error_format);
337+
338+
let diag = new_handler(error_format, None, &debugging_opts);
339+
340+
// check for deprecated options
341+
check_deprecated_options(matches, &diag);
342+
330343
if matches.opt_strs("passes") == ["list"] {
331344
println!("Available passes for running rustdoc:");
332345
for pass in passes::PASSES {
@@ -359,19 +372,6 @@ impl Options {
359372
return Err(0);
360373
}
361374

362-
let color = config::parse_color(matches);
363-
let config::JsonConfig { json_rendered, json_unused_externs, .. } =
364-
config::parse_json(matches);
365-
let error_format = config::parse_error_format(matches, color, json_rendered);
366-
367-
let codegen_options = CodegenOptions::build(matches, error_format);
368-
let debugging_opts = DebuggingOptions::build(matches, error_format);
369-
370-
let diag = new_handler(error_format, None, &debugging_opts);
371-
372-
// check for deprecated options
373-
check_deprecated_options(matches, &diag);
374-
375375
let mut emit = Vec::new();
376376
for list in matches.opt_strs("emit") {
377377
for kind in list.split(',') {

‎src/librustdoc/html/render/print_item.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -976,6 +976,7 @@ fn item_typedef(
976976
// associated items from the aliased type (see discussion in #32077), but
977977
// we need #14072 to make sense of the generics.
978978
render_assoc_items(w, cx, it, def_id, AssocItemRender::All);
979+
document_type_layout(w, cx, def_id);
979980
}
980981

981982
fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Union) {

‎src/test/rustdoc-ui/issue-91713.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// check-pass
2+
// compile-flags: --passes list
3+
// error-pattern: the `passes` flag is deprecated
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
warning: the `passes` flag is deprecated
2+
|
3+
= note: see issue #44136 <https://github.com/rust-lang/rust/issues/44136> for more information
4+
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
Available passes for running rustdoc:
2+
check_doc_test_visibility - run various visibility-related lints on doctests
3+
strip-hidden - strips all `#[doc(hidden)]` items from the output
4+
unindent-comments - removes excess indentation on comments in order for markdown to like it
5+
strip-private - strips all private items from a crate which cannot be seen externally, implies strip-priv-imports
6+
strip-priv-imports - strips all private import statements (`use`, `extern crate`) from a crate
7+
propagate-doc-cfg - propagates `#[doc(cfg(...))]` to child items
8+
collect-intra-doc-links - resolves intra-doc links
9+
check-code-block-syntax - validates syntax inside Rust code blocks
10+
collect-trait-impls - retrieves trait impls for items in the crate
11+
calculate-doc-coverage - counts the number of items with and without documentation
12+
check-invalid-html-tags - detects invalid HTML tags in doc comments
13+
check-bare-urls - detects URLs that are not hyperlinks
14+
15+
Default passes for rustdoc:
16+
collect-trait-impls
17+
unindent-comments
18+
check_doc_test_visibility
19+
strip-hidden (when not --document-hidden-items)
20+
strip-private (when not --document-private-items)
21+
strip-priv-imports (when --document-private-items)
22+
collect-intra-doc-links
23+
check-code-block-syntax
24+
check-invalid-html-tags
25+
propagate-doc-cfg
26+
check-bare-urls
27+
28+
Passes run with `--show-coverage`:
29+
strip-hidden (when not --document-hidden-items)
30+
strip-private (when not --document-private-items)
31+
calculate-doc-coverage

‎src/test/rustdoc/type-layout.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,18 @@ pub struct GenericLifetimes<'a>(&'a str);
5050
// @has - '(unsized)'
5151
pub struct Unsized([u8]);
5252

53+
// @has type_layout/type.TypeAlias.html 'Size: '
54+
// @has - ' bytes'
55+
pub type TypeAlias = X;
56+
57+
// @has type_layout/type.GenericTypeAlias.html 'Size: '
58+
// @has - '8 bytes'
59+
pub type GenericTypeAlias = (Generic<(u32, ())>, Generic<u32>);
60+
61+
// Regression test for the rustdoc equivalent of #85103.
62+
// @has type_layout/type.Edges.html 'Encountered an error during type layout; the type failed to be normalized.'
63+
pub type Edges<'a, E> = std::borrow::Cow<'a, [E]>;
64+
5365
// @!has type_layout/trait.MyTrait.html 'Size: '
5466
pub trait MyTrait {}
5567

‎src/test/ui/async-await/generics-and-bounds.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// edition:2018
33
// compile-flags: --crate-type lib
44

5+
#![feature(in_band_lifetimes)]
6+
57
use std::future::Future;
68

79
pub async fn simple_generic<T>() {}
@@ -71,6 +73,10 @@ pub fn call_with_ref_block<'a>(f: &'a (impl Foo + 'a)) -> impl Future<Output = (
7173
async move { f.foo() }
7274
}
7375

76+
pub fn call_with_ref_block_in_band(f: &'a (impl Foo + 'a)) -> impl Future<Output = ()> + 'a {
77+
async move { f.foo() }
78+
}
79+
7480
pub fn async_block_with_same_generic_params_unifies() {
7581
let mut a = call_generic_bound_block(FooType);
7682
a = call_generic_bound_block(FooType);
@@ -85,4 +91,9 @@ pub fn async_block_with_same_generic_params_unifies() {
8591
let f_two = FooType;
8692
let mut d = call_with_ref_block(&f_one);
8793
d = call_with_ref_block(&f_two);
94+
95+
let f_one = FooType;
96+
let f_two = FooType;
97+
let mut d = call_with_ref_block_in_band(&f_one);
98+
d = call_with_ref_block_in_band(&f_two);
8899
}

‎src/test/ui/binding/issue-53114-safety-checks.stderr

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ LL | let _ = &p.b;
88
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
99
= note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
1010
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
11+
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
1112

1213
warning: reference to packed field is unaligned
1314
--> $DIR/issue-53114-safety-checks.rs:29:17
@@ -18,6 +19,7 @@ LL | let (_,) = (&p.b,);
1819
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
1920
= note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
2021
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
22+
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
2123

2224
warning: reference to packed field is unaligned
2325
--> $DIR/issue-53114-safety-checks.rs:39:11
@@ -28,6 +30,7 @@ LL | match &p.b { _ => { } }
2830
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
2931
= note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
3032
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
33+
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
3134

3235
warning: reference to packed field is unaligned
3336
--> $DIR/issue-53114-safety-checks.rs:45:12
@@ -38,6 +41,7 @@ LL | match (&p.b,) { (_,) => { } }
3841
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
3942
= note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
4043
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
44+
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
4145

4246
error[E0133]: access to union field is unsafe and requires unsafe function or block
4347
--> $DIR/issue-53114-safety-checks.rs:26:13

‎src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ LL | println!("{}", foo.x);
88
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
99
= note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
1010
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
11+
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
1112
= note: this warning originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
1213

1314
warning: 1 warning emitted

‎src/test/ui/lint/unaligned_references.stderr

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ LL | #![deny(unaligned_references)]
1212
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
1313
= note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
1414
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
15+
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
1516

1617
error: reference to packed field is unaligned
1718
--> $DIR/unaligned_references.rs:24:17
@@ -22,6 +23,7 @@ LL | let _ = &good.data;
2223
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
2324
= note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
2425
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
26+
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
2527

2628
error: reference to packed field is unaligned
2729
--> $DIR/unaligned_references.rs:27:17
@@ -32,6 +34,7 @@ LL | let _ = &good.data as *const _;
3234
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
3335
= note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
3436
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
37+
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
3538

3639
error: reference to packed field is unaligned
3740
--> $DIR/unaligned_references.rs:29:27
@@ -42,6 +45,7 @@ LL | let _: *const _ = &good.data;
4245
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
4346
= note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
4447
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
48+
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
4549

4650
error: reference to packed field is unaligned
4751
--> $DIR/unaligned_references.rs:32:17
@@ -52,6 +56,7 @@ LL | let _ = good.data.clone();
5256
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
5357
= note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
5458
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
59+
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
5560

5661
error: reference to packed field is unaligned
5762
--> $DIR/unaligned_references.rs:35:17
@@ -62,6 +67,7 @@ LL | let _ = &good.data2[0];
6267
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
6368
= note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
6469
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
70+
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
6571

6672
error: reference to packed field is unaligned
6773
--> $DIR/unaligned_references.rs:45:17
@@ -72,6 +78,7 @@ LL | let _ = &packed2.x;
7278
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
7379
= note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
7480
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
81+
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
7582

7683
error: aborting due to 7 previous errors
7784

‎src/test/ui/lint/unaligned_references_external_macro.stderr

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ LL | | }
2424
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
2525
= note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
2626
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
27+
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
2728
= note: this error originates in the macro `unaligned_references_external_crate::mac` (in Nightly builds, run with -Z macro-backtrace for more info)
2829

2930
error: aborting due to previous error

‎src/test/ui/packed/issue-27060.stderr

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ LL | #[deny(unaligned_references)]
1212
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
1313
= note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
1414
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
15+
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
1516

1617
error: reference to packed field is unaligned
1718
--> $DIR/issue-27060.rs:18:13
@@ -22,6 +23,7 @@ LL | let _ = &good.data2[0];
2223
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
2324
= note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
2425
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
26+
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
2527

2628
error: reference to packed field is unaligned
2729
--> $DIR/issue-27060.rs:21:13
@@ -32,6 +34,7 @@ LL | let _ = &good.data;
3234
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
3335
= note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
3436
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
37+
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
3538

3639
error: reference to packed field is unaligned
3740
--> $DIR/issue-27060.rs:23:13
@@ -42,6 +45,7 @@ LL | let _ = &good.data2[0];
4245
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
4346
= note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
4447
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
48+
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
4549

4650
error: aborting due to 4 previous errors
4751

‎src/test/ui/packed/packed-struct-borrow-element-64bit.stderr

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ LL | let brw = &foo.baz;
88
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
99
= note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
1010
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
11+
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
1112

1213
warning: 1 warning emitted
1314

‎src/test/ui/packed/packed-struct-borrow-element.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ LL | let brw = &foo.baz;
88
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
99
= note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
1010
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
11+
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
1112

1213
warning: reference to packed field is unaligned
1314
--> $DIR/packed-struct-borrow-element.rs:30:15
@@ -18,6 +19,7 @@ LL | let brw = &foo.baz;
1819
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
1920
= note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
2021
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
22+
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
2123

2224
warning: 2 warnings emitted
2325

0 commit comments

Comments
 (0)
Please sign in to comment.