Skip to content

Commit f77bfb7

Browse files
committed
Auto merge of rust-lang#108620 - Dylan-DPC:rollup-o5c4evy, r=Dylan-DPC
Rollup of 7 pull requests Successful merges: - rust-lang#108143 (rustdoc: search by macro when query ends with `!`) - rust-lang#108394 (Make `x doc --open` work on every book) - rust-lang#108427 (Recover from for-else and while-else) - rust-lang#108462 (Fix `VecDeque::append` capacity overflow for ZSTs) - rust-lang#108568 (Make associated_item_def_ids for traits use an unstable option to also return associated types for RPITITs) - rust-lang#108604 (Add regression test for rust-lang#107280) - rust-lang#108605 (Add regression test for rust-lang#105821) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 609496e + 02e4eef commit f77bfb7

40 files changed

+642
-72
lines changed

compiler/rustc_metadata/src/rmeta/encoder.rs

+12-3
Original file line numberDiff line numberDiff line change
@@ -1101,9 +1101,18 @@ fn should_encode_const(def_kind: DefKind) -> bool {
11011101
}
11021102
}
11031103

1104-
// Return `false` to avoid encoding impl trait in trait, while we don't use the query.
1105-
fn should_encode_fn_impl_trait_in_trait<'tcx>(_tcx: TyCtxt<'tcx>, _def_id: DefId) -> bool {
1106-
false
1104+
// We only encode impl trait in trait when using `lower-impl-trait-in-trait-to-assoc-ty` unstable
1105+
// option.
1106+
fn should_encode_fn_impl_trait_in_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
1107+
if tcx.sess.opts.unstable_opts.lower_impl_trait_in_trait_to_assoc_ty
1108+
&& let Some(assoc_item) = tcx.opt_associated_item(def_id)
1109+
&& assoc_item.container == ty::AssocItemContainer::TraitContainer
1110+
&& assoc_item.kind == ty::AssocKind::Fn
1111+
{
1112+
true
1113+
} else {
1114+
false
1115+
}
11071116
}
11081117

11091118
impl<'a, 'tcx> EncodeContext<'a, 'tcx> {

compiler/rustc_middle/src/hir/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ pub fn provide(providers: &mut Providers) {
177177
}
178178
};
179179
providers.opt_def_kind = |tcx, def_id| tcx.hir().opt_def_kind(def_id.expect_local());
180+
providers.opt_rpitit_info = |_, _| None;
180181
providers.all_local_trait_impls = |tcx, ()| &tcx.resolutions(()).trait_impls;
181182
providers.expn_that_defined = |tcx, id| {
182183
let id = id.expect_local();

compiler/rustc_middle/src/query/mod.rs

+19
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ rustc_queries! {
9090
/// Definitions that were generated with no HIR, would be feeded to return `None`.
9191
query opt_local_def_id_to_hir_id(key: LocalDefId) -> Option<hir::HirId>{
9292
desc { |tcx| "getting HIR ID of `{}`", tcx.def_path_str(key.to_def_id()) }
93+
feedable
9394
}
9495

9596
/// Gives access to the HIR node's parent for the HIR owner `key`.
@@ -166,6 +167,7 @@ rustc_queries! {
166167
}
167168
cache_on_disk_if { key.is_local() }
168169
separate_provide_extern
170+
feedable
169171
}
170172

171173
query collect_return_position_impl_trait_in_trait_tys(key: DefId)
@@ -222,6 +224,7 @@ rustc_queries! {
222224
arena_cache
223225
cache_on_disk_if { key.is_local() }
224226
separate_provide_extern
227+
feedable
225228
}
226229

227230
/// Maps from the `DefId` of an item (trait/struct/enum/fn) to the
@@ -264,6 +267,7 @@ rustc_queries! {
264267
desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) }
265268
cache_on_disk_if { key.is_local() }
266269
separate_provide_extern
270+
feedable
267271
}
268272

269273
/// Elaborated version of the predicates from `explicit_item_bounds`.
@@ -588,6 +592,7 @@ rustc_queries! {
588592
desc { |tcx| "computing explicit predicates of `{}`", tcx.def_path_str(key) }
589593
cache_on_disk_if { key.is_local() }
590594
separate_provide_extern
595+
feedable
591596
}
592597

593598
/// Returns the inferred outlives predicates (e.g., for `struct
@@ -596,6 +601,7 @@ rustc_queries! {
596601
desc { |tcx| "computing inferred outlives predicates of `{}`", tcx.def_path_str(key) }
597602
cache_on_disk_if { key.is_local() }
598603
separate_provide_extern
604+
feedable
599605
}
600606

601607
/// Maps from the `DefId` of a trait to the list of
@@ -728,6 +734,7 @@ rustc_queries! {
728734
desc { |tcx| "computing associated item data for `{}`", tcx.def_path_str(key) }
729735
cache_on_disk_if { key.is_local() }
730736
separate_provide_extern
737+
feedable
731738
}
732739

733740
/// Collects the associated items defined on a trait or impl.
@@ -1142,6 +1149,15 @@ rustc_queries! {
11421149
desc { |tcx| "looking up definition kind of `{}`", tcx.def_path_str(def_id) }
11431150
cache_on_disk_if { def_id.is_local() }
11441151
separate_provide_extern
1152+
feedable
1153+
}
1154+
1155+
/// The `opt_rpitit_info` query returns the pair of the def id of the function where the RPIT
1156+
/// is defined and the opaque def id if any.
1157+
query opt_rpitit_info(def_id: DefId) -> Option<ty::ImplTraitInTraitData> {
1158+
desc { |tcx| "opt_rpitit_info `{}`", tcx.def_path_str(def_id) }
1159+
cache_on_disk_if { def_id.is_local() }
1160+
feedable
11451161
}
11461162

11471163
/// Gets the span for the definition.
@@ -1157,6 +1173,7 @@ rustc_queries! {
11571173
desc { |tcx| "looking up span for `{}`'s identifier", tcx.def_path_str(def_id) }
11581174
cache_on_disk_if { def_id.is_local() }
11591175
separate_provide_extern
1176+
feedable
11601177
}
11611178

11621179
query lookup_stability(def_id: DefId) -> Option<attr::Stability> {
@@ -1498,6 +1515,7 @@ rustc_queries! {
14981515
desc { |tcx| "looking up whether `{}` is a default impl", tcx.def_path_str(def_id) }
14991516
cache_on_disk_if { def_id.is_local() }
15001517
separate_provide_extern
1518+
feedable
15011519
}
15021520

15031521
query check_well_formed(key: hir::OwnerId) -> () {
@@ -1695,6 +1713,7 @@ rustc_queries! {
16951713
query visibility(def_id: DefId) -> ty::Visibility<DefId> {
16961714
desc { |tcx| "computing visibility of `{}`", tcx.def_path_str(def_id) }
16971715
separate_provide_extern
1716+
feedable
16981717
}
16991718

17001719
query inhabited_predicate_adt(key: DefId) -> ty::inhabitedness::InhabitedPredicate<'tcx> {

compiler/rustc_middle/src/ty/mod.rs

+6
Original file line numberDiff line numberDiff line change
@@ -2071,6 +2071,12 @@ pub enum ImplOverlapKind {
20712071
Issue33140,
20722072
}
20732073

2074+
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
2075+
pub enum ImplTraitInTraitData {
2076+
Trait { fn_def_id: DefId, opaque_def_id: DefId },
2077+
Impl { fn_def_id: DefId },
2078+
}
2079+
20742080
impl<'tcx> TyCtxt<'tcx> {
20752081
pub fn typeck_body(self, body: hir::BodyId) -> &'tcx TypeckResults<'tcx> {
20762082
self.typeck(self.hir().body_owner_def_id(body))

compiler/rustc_parse/locales/en-US.ftl

+4
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,10 @@ parse_missing_in_in_for_loop = missing `in` in `for` loop
151151
parse_missing_expression_in_for_loop = missing expression to iterate on in `for` loop
152152
.suggestion = try adding an expression to the `for` loop
153153
154+
parse_loop_else = `{$loop_kind}...else` loops are not supported
155+
.note = consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
156+
.loop_keyword = `else` is attached to this loop
157+
154158
parse_missing_comma_after_match_arm = expected `,` following `match` arm
155159
.suggestion = missing a comma here to end this `match` arm
156160

compiler/rustc_parse/src/errors.rs

+11
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,17 @@ pub(crate) struct MissingExpressionInForLoop {
451451
pub span: Span,
452452
}
453453

454+
#[derive(Diagnostic)]
455+
#[diag(parse_loop_else)]
456+
#[note]
457+
pub(crate) struct LoopElseNotSupported {
458+
#[primary_span]
459+
pub span: Span,
460+
pub loop_kind: &'static str,
461+
#[label(parse_loop_keyword)]
462+
pub loop_kw: Span,
463+
}
464+
454465
#[derive(Diagnostic)]
455466
#[diag(parse_missing_comma_after_match_arm)]
456467
pub(crate) struct MissingCommaAfterMatchArm {

compiler/rustc_parse/src/parser/expr.rs

+22
Original file line numberDiff line numberDiff line change
@@ -2503,9 +2503,27 @@ impl<'a> Parser<'a> {
25032503
let (attrs, loop_block) = self.parse_inner_attrs_and_block()?;
25042504

25052505
let kind = ExprKind::ForLoop(pat, expr, loop_block, opt_label);
2506+
2507+
self.recover_loop_else("for", lo)?;
2508+
25062509
Ok(self.mk_expr_with_attrs(lo.to(self.prev_token.span), kind, attrs))
25072510
}
25082511

2512+
/// Recovers from an `else` clause after a loop (`for...else`, `while...else`)
2513+
fn recover_loop_else(&mut self, loop_kind: &'static str, loop_kw: Span) -> PResult<'a, ()> {
2514+
if self.token.is_keyword(kw::Else) && self.may_recover() {
2515+
let else_span = self.token.span;
2516+
self.bump();
2517+
let else_clause = self.parse_expr_else()?;
2518+
self.sess.emit_err(errors::LoopElseNotSupported {
2519+
span: else_span.to(else_clause.span),
2520+
loop_kind,
2521+
loop_kw,
2522+
});
2523+
}
2524+
Ok(())
2525+
}
2526+
25092527
fn error_missing_in_for_loop(&mut self) {
25102528
let (span, sub): (_, fn(_) -> _) = if self.token.is_ident_named(sym::of) {
25112529
// Possibly using JS syntax (#75311).
@@ -2530,6 +2548,9 @@ impl<'a> Parser<'a> {
25302548
err.span_label(cond.span, "this `while` condition successfully parsed");
25312549
err
25322550
})?;
2551+
2552+
self.recover_loop_else("while", lo)?;
2553+
25332554
Ok(self.mk_expr_with_attrs(
25342555
lo.to(self.prev_token.span),
25352556
ExprKind::While(cond, body, opt_label),
@@ -2541,6 +2562,7 @@ impl<'a> Parser<'a> {
25412562
fn parse_expr_loop(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
25422563
let loop_span = self.prev_token.span;
25432564
let (attrs, body) = self.parse_inner_attrs_and_block()?;
2565+
self.recover_loop_else("loop", lo)?;
25442566
Ok(self.mk_expr_with_attrs(
25452567
lo.to(self.prev_token.span),
25462568
ExprKind::Loop(body, opt_label, loop_span),

compiler/rustc_session/src/options.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1503,6 +1503,9 @@ options! {
15031503
"what location details should be tracked when using caller_location, either \
15041504
`none`, or a comma separated list of location details, for which \
15051505
valid options are `file`, `line`, and `column` (default: `file,line,column`)"),
1506+
lower_impl_trait_in_trait_to_assoc_ty: bool = (false, parse_bool, [TRACKED],
1507+
"modify the lowering strategy for `impl Trait` in traits so that they are lowered to \
1508+
generic associated types"),
15061509
ls: bool = (false, parse_bool, [UNTRACKED],
15071510
"list the symbols defined by a library crate (default: no)"),
15081511
macro_backtrace: bool = (false, parse_bool, [UNTRACKED],

compiler/rustc_ty_utils/src/assoc.rs

+90-6
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ use rustc_hir::def::DefKind;
44
use rustc_hir::def_id::{DefId, LocalDefId};
55
use rustc_hir::definitions::DefPathData;
66
use rustc_hir::intravisit::{self, Visitor};
7-
use rustc_middle::ty::{self, DefIdTree, TyCtxt};
7+
use rustc_middle::ty::{self, DefIdTree, ImplTraitInTraitData, InternalSubsts, TyCtxt};
8+
use rustc_span::symbol::kw;
89

910
pub fn provide(providers: &mut ty::query::Providers) {
1011
*providers = ty::query::Providers {
@@ -21,9 +22,37 @@ pub fn provide(providers: &mut ty::query::Providers) {
2122
fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] {
2223
let item = tcx.hir().expect_item(def_id.expect_local());
2324
match item.kind {
24-
hir::ItemKind::Trait(.., ref trait_item_refs) => tcx.arena.alloc_from_iter(
25-
trait_item_refs.iter().map(|trait_item_ref| trait_item_ref.id.owner_id.to_def_id()),
26-
),
25+
hir::ItemKind::Trait(.., ref trait_item_refs) => {
26+
if tcx.sess.opts.unstable_opts.lower_impl_trait_in_trait_to_assoc_ty {
27+
// We collect RPITITs for each trait method's return type and create a
28+
// corresponding associated item using associated_items_for_impl_trait_in_trait
29+
// query.
30+
tcx.arena.alloc_from_iter(
31+
trait_item_refs
32+
.iter()
33+
.map(|trait_item_ref| trait_item_ref.id.owner_id.to_def_id())
34+
.chain(
35+
trait_item_refs
36+
.iter()
37+
.filter(|trait_item_ref| {
38+
matches!(trait_item_ref.kind, hir::AssocItemKind::Fn { .. })
39+
})
40+
.flat_map(|trait_item_ref| {
41+
let trait_fn_def_id =
42+
trait_item_ref.id.owner_id.def_id.to_def_id();
43+
tcx.associated_items_for_impl_trait_in_trait(trait_fn_def_id)
44+
})
45+
.map(|def_id| *def_id),
46+
),
47+
)
48+
} else {
49+
tcx.arena.alloc_from_iter(
50+
trait_item_refs
51+
.iter()
52+
.map(|trait_item_ref| trait_item_ref.id.owner_id.to_def_id()),
53+
)
54+
}
55+
}
2756
hir::ItemKind::Impl(ref impl_) => tcx.arena.alloc_from_iter(
2857
impl_.items.iter().map(|impl_item_ref| impl_item_ref.id.owner_id.to_def_id()),
2958
),
@@ -193,10 +222,65 @@ fn associated_item_for_impl_trait_in_trait(
193222
let span = tcx.def_span(opaque_ty_def_id);
194223
let trait_assoc_ty =
195224
tcx.at(span).create_def(trait_def_id.expect_local(), DefPathData::ImplTraitAssocTy);
196-
trait_assoc_ty.def_id()
225+
226+
let local_def_id = trait_assoc_ty.def_id();
227+
let def_id = local_def_id.to_def_id();
228+
229+
trait_assoc_ty.opt_def_kind(Some(DefKind::AssocTy));
230+
231+
// There's no HIR associated with this new synthesized `def_id`, so feed
232+
// `opt_local_def_id_to_hir_id` with `None`.
233+
trait_assoc_ty.opt_local_def_id_to_hir_id(None);
234+
235+
// Copy span of the opaque.
236+
trait_assoc_ty.def_ident_span(Some(span));
237+
238+
// Add the def_id of the function and opaque that generated this synthesized associated type.
239+
trait_assoc_ty.opt_rpitit_info(Some(ImplTraitInTraitData::Trait {
240+
fn_def_id,
241+
opaque_def_id: opaque_ty_def_id.to_def_id(),
242+
}));
243+
244+
trait_assoc_ty.associated_item(ty::AssocItem {
245+
name: kw::Empty,
246+
kind: ty::AssocKind::Type,
247+
def_id,
248+
trait_item_def_id: None,
249+
container: ty::TraitContainer,
250+
fn_has_self_parameter: false,
251+
});
252+
253+
// Copy visility of the containing function.
254+
trait_assoc_ty.visibility(tcx.visibility(fn_def_id));
255+
256+
// Copy impl_defaultness of the containing function.
257+
trait_assoc_ty.impl_defaultness(tcx.impl_defaultness(fn_def_id));
258+
259+
// Copy type_of of the opaque.
260+
trait_assoc_ty.type_of(ty::EarlyBinder(tcx.mk_opaque(
261+
opaque_ty_def_id.to_def_id(),
262+
InternalSubsts::identity_for_item(tcx, opaque_ty_def_id.to_def_id()),
263+
)));
264+
265+
// Copy generics_of of the opaque.
266+
trait_assoc_ty.generics_of(tcx.generics_of(opaque_ty_def_id).clone());
267+
268+
// There are no predicates for the synthesized associated type.
269+
trait_assoc_ty.explicit_predicates_of(ty::GenericPredicates {
270+
parent: Some(trait_def_id),
271+
predicates: &[],
272+
});
273+
274+
// There are no inferred outlives for the synthesized associated type.
275+
trait_assoc_ty.inferred_outlives_of(&[]);
276+
277+
// FIXME implement this.
278+
trait_assoc_ty.explicit_item_bounds(&[]);
279+
280+
local_def_id
197281
}
198282

199-
/// Given an `trait_assoc_def_id` that corresponds to a previously synthethized impl trait in trait
283+
/// Given an `trait_assoc_def_id` that corresponds to a previously synthesized impl trait in trait
200284
/// into an associated type and an `impl_def_id` corresponding to an impl block, create and return
201285
/// the corresponding associated item inside the impl block.
202286
fn impl_associated_item_for_impl_trait_in_trait(

library/alloc/src/collections/vec_deque/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1924,7 +1924,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
19241924
#[stable(feature = "append", since = "1.4.0")]
19251925
pub fn append(&mut self, other: &mut Self) {
19261926
if T::IS_ZST {
1927-
self.len += other.len;
1927+
self.len = self.len.checked_add(other.len).expect("capacity overflow");
19281928
other.len = 0;
19291929
other.head = 0;
19301930
return;

library/alloc/tests/vec_deque.rs

+14
Original file line numberDiff line numberDiff line change
@@ -1045,6 +1045,20 @@ fn test_append_double_drop() {
10451045
assert_eq!(count_b, 1);
10461046
}
10471047

1048+
#[test]
1049+
#[should_panic]
1050+
fn test_append_zst_capacity_overflow() {
1051+
let mut v = Vec::with_capacity(usize::MAX);
1052+
// note: using resize instead of set_len here would
1053+
// be *extremely* slow in unoptimized builds.
1054+
// SAFETY: `v` has capacity `usize::MAX`, and no initialization
1055+
// is needed for empty tuples.
1056+
unsafe { v.set_len(usize::MAX) };
1057+
let mut v = VecDeque::from(v);
1058+
let mut w = vec![()].into();
1059+
v.append(&mut w);
1060+
}
1061+
10481062
#[test]
10491063
fn test_retain() {
10501064
let mut buf = VecDeque::new();

0 commit comments

Comments
 (0)