Skip to content

Commit b87eda7

Browse files
committed
Auto merge of rust-lang#137406 - matthiaskrgr:rollup-9nknrsb, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - rust-lang#136458 (Do not deduplicate list of associated types provided by dyn principal) - rust-lang#136474 ([`compiletest`-related cleanups 3/7] Make the distinction between sources root vs test suite sources root in compiletest less confusing) - rust-lang#136592 (Make sure we don't overrun the stack in canonicalizer) - rust-lang#136787 (Remove `lifetime_capture_rules_2024` feature) - rust-lang#137207 (Add #[track_caller] to Duration Div impl) - rust-lang#137245 (Tweak E0277 when predicate comes indirectly from ?) - rust-lang#137257 (Ignore fake borrows for packed field check) - rust-lang#137399 (fix ICE in layout computation with unnormalizable const) r? `@ghost` `@rustbot` modify labels: rollup
2 parents dc37ff8 + 6352044 commit b87eda7

File tree

65 files changed

+785
-386
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+785
-386
lines changed

compiler/rustc_feature/src/removed.rs

+2
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ declare_features! (
135135
Some("removed as it caused some confusion and discussion was inactive for years")),
136136
/// Lazily evaluate constants. This allows constants to depend on type parameters.
137137
(removed, lazy_normalization_consts, "1.46.0", Some(72219), Some("superseded by `generic_const_exprs`")),
138+
/// Changes `impl Trait` to capture all lifetimes in scope.
139+
(removed, lifetime_capture_rules_2024, "1.76.0", None, Some("unnecessary -- use edition 2024 instead")),
138140
/// Allows using the `#[link_args]` attribute.
139141
(removed, link_args, "1.53.0", Some(29596),
140142
Some("removed in favor of using `-C link-arg=ARG` on command line, \

compiler/rustc_feature/src/unstable.rs

-2
Original file line numberDiff line numberDiff line change
@@ -214,8 +214,6 @@ declare_features! (
214214
(internal, intrinsics, "1.0.0", None),
215215
/// Allows using `#[lang = ".."]` attribute for linking items to special compiler logic.
216216
(internal, lang_items, "1.0.0", None),
217-
/// Changes `impl Trait` to capture all lifetimes in scope.
218-
(unstable, lifetime_capture_rules_2024, "1.76.0", None),
219217
/// Allows `#[link(..., cfg(..))]`; perma-unstable per #37406
220218
(internal, link_cfg, "1.14.0", None),
221219
/// Allows using `?Trait` trait bounds in more contexts.

compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs

+12-21
Original file line numberDiff line numberDiff line change
@@ -305,21 +305,15 @@ fn generic_param_def_as_bound_arg(param: &ty::GenericParamDef) -> ty::BoundVaria
305305
}
306306

307307
/// Whether this opaque always captures lifetimes in scope.
308-
/// Right now, this is all RPITIT and TAITs, and when `lifetime_capture_rules_2024`
309-
/// is enabled. We don't check the span of the edition, since this is done
310-
/// on a per-opaque basis to account for nested opaques.
311-
fn opaque_captures_all_in_scope_lifetimes<'tcx>(
312-
tcx: TyCtxt<'tcx>,
313-
opaque: &'tcx hir::OpaqueTy<'tcx>,
314-
) -> bool {
308+
/// Right now, this is all RPITIT and TAITs, and when the opaque
309+
/// is coming from a span corresponding to edition 2024.
310+
fn opaque_captures_all_in_scope_lifetimes<'tcx>(opaque: &'tcx hir::OpaqueTy<'tcx>) -> bool {
315311
match opaque.origin {
316312
// if the opaque has the `use<...>` syntax, the user is telling us that they only want
317313
// to account for those lifetimes, so do not try to be clever.
318314
_ if opaque.bounds.iter().any(|bound| matches!(bound, hir::GenericBound::Use(..))) => false,
319315
hir::OpaqueTyOrigin::AsyncFn { .. } | hir::OpaqueTyOrigin::TyAlias { .. } => true,
320-
_ if tcx.features().lifetime_capture_rules_2024() || opaque.span.at_least_rust_2024() => {
321-
true
322-
}
316+
_ if opaque.span.at_least_rust_2024() => true,
323317
hir::OpaqueTyOrigin::FnReturn { in_trait_or_impl, .. } => in_trait_or_impl.is_some(),
324318
}
325319
}
@@ -519,8 +513,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
519513
fn visit_opaque_ty(&mut self, opaque: &'tcx rustc_hir::OpaqueTy<'tcx>) {
520514
let captures = RefCell::new(FxIndexMap::default());
521515

522-
let capture_all_in_scope_lifetimes =
523-
opaque_captures_all_in_scope_lifetimes(self.tcx, opaque);
516+
let capture_all_in_scope_lifetimes = opaque_captures_all_in_scope_lifetimes(opaque);
524517
if capture_all_in_scope_lifetimes {
525518
let lifetime_ident = |def_id: LocalDefId| {
526519
let name = self.tcx.item_name(def_id.to_def_id());
@@ -2276,7 +2269,7 @@ fn is_late_bound_map(
22762269
}
22772270

22782271
let mut appears_in_output =
2279-
AllCollector { tcx, has_fully_capturing_opaque: false, regions: Default::default() };
2272+
AllCollector { has_fully_capturing_opaque: false, regions: Default::default() };
22802273
intravisit::walk_fn_ret_ty(&mut appears_in_output, &sig.decl.output);
22812274
if appears_in_output.has_fully_capturing_opaque {
22822275
appears_in_output.regions.extend(generics.params.iter().map(|param| param.def_id));
@@ -2289,7 +2282,7 @@ fn is_late_bound_map(
22892282
// Subtle point: because we disallow nested bindings, we can just
22902283
// ignore binders here and scrape up all names we see.
22912284
let mut appears_in_where_clause =
2292-
AllCollector { tcx, has_fully_capturing_opaque: true, regions: Default::default() };
2285+
AllCollector { has_fully_capturing_opaque: true, regions: Default::default() };
22932286
appears_in_where_clause.visit_generics(generics);
22942287
debug!(?appears_in_where_clause.regions);
22952288

@@ -2455,23 +2448,21 @@ fn is_late_bound_map(
24552448
}
24562449
}
24572450

2458-
struct AllCollector<'tcx> {
2459-
tcx: TyCtxt<'tcx>,
2451+
struct AllCollector {
24602452
has_fully_capturing_opaque: bool,
24612453
regions: FxHashSet<LocalDefId>,
24622454
}
24632455

2464-
impl<'v> Visitor<'v> for AllCollector<'v> {
2465-
fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
2456+
impl<'tcx> Visitor<'tcx> for AllCollector {
2457+
fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
24662458
if let hir::LifetimeName::Param(def_id) = lifetime_ref.res {
24672459
self.regions.insert(def_id);
24682460
}
24692461
}
24702462

2471-
fn visit_opaque_ty(&mut self, opaque: &'v hir::OpaqueTy<'v>) {
2463+
fn visit_opaque_ty(&mut self, opaque: &'tcx hir::OpaqueTy<'tcx>) {
24722464
if !self.has_fully_capturing_opaque {
2473-
self.has_fully_capturing_opaque =
2474-
opaque_captures_all_in_scope_lifetimes(self.tcx, opaque);
2465+
self.has_fully_capturing_opaque = opaque_captures_all_in_scope_lifetimes(opaque);
24752466
}
24762467
intravisit::walk_opaque_ty(self, opaque);
24772468
}

compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs

+99-28
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
1+
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
22
use rustc_errors::codes::*;
33
use rustc_errors::struct_span_code_err;
44
use rustc_hir as hir;
@@ -58,9 +58,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
5858
}
5959
}
6060

61-
let (trait_bounds, mut projection_bounds) =
61+
let (elaborated_trait_bounds, elaborated_projection_bounds) =
6262
traits::expand_trait_aliases(tcx, user_written_bounds.iter().copied());
63-
let (regular_traits, mut auto_traits): (Vec<_>, Vec<_>) = trait_bounds
63+
let (regular_traits, mut auto_traits): (Vec<_>, Vec<_>) = elaborated_trait_bounds
6464
.into_iter()
6565
.partition(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id()));
6666

@@ -103,37 +103,89 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
103103
}
104104
}
105105

106+
// Map the projection bounds onto a key that makes it easy to remove redundant
107+
// bounds that are constrained by supertraits of the principal def id.
108+
//
109+
// Also make sure we detect conflicting bounds from expanding a trait alias and
110+
// also specifying it manually, like:
111+
// ```
112+
// type Alias = Trait<Assoc = i32>;
113+
// let _: &dyn Alias<Assoc = u32> = /* ... */;
114+
// ```
115+
let mut projection_bounds = FxIndexMap::default();
116+
for (proj, proj_span) in elaborated_projection_bounds {
117+
let key = (
118+
proj.skip_binder().projection_term.def_id,
119+
tcx.anonymize_bound_vars(
120+
proj.map_bound(|proj| proj.projection_term.trait_ref(tcx)),
121+
),
122+
);
123+
if let Some((old_proj, old_proj_span)) =
124+
projection_bounds.insert(key, (proj, proj_span))
125+
&& tcx.anonymize_bound_vars(proj) != tcx.anonymize_bound_vars(old_proj)
126+
{
127+
let item = tcx.item_name(proj.item_def_id());
128+
self.dcx()
129+
.struct_span_err(
130+
span,
131+
format!(
132+
"conflicting associated type bounds for `{item}` when \
133+
expanding trait alias"
134+
),
135+
)
136+
.with_span_label(
137+
old_proj_span,
138+
format!("`{item}` is specified to be `{}` here", old_proj.term()),
139+
)
140+
.with_span_label(
141+
proj_span,
142+
format!("`{item}` is specified to be `{}` here", proj.term()),
143+
)
144+
.emit();
145+
}
146+
}
147+
106148
let principal_trait = regular_traits.into_iter().next();
107149

108-
let mut needed_associated_types = FxIndexSet::default();
109-
if let Some((principal_trait, spans)) = &principal_trait {
110-
let pred: ty::Predicate<'tcx> = (*principal_trait).upcast(tcx);
111-
for ClauseWithSupertraitSpan { pred, supertrait_span } in traits::elaborate(
150+
let mut needed_associated_types = vec![];
151+
if let Some((principal_trait, ref spans)) = principal_trait {
152+
let principal_trait = principal_trait.map_bound(|trait_pred| {
153+
assert_eq!(trait_pred.polarity, ty::PredicatePolarity::Positive);
154+
trait_pred.trait_ref
155+
});
156+
157+
for ClauseWithSupertraitSpan { clause, supertrait_span } in traits::elaborate(
112158
tcx,
113-
[ClauseWithSupertraitSpan::new(pred, *spans.last().unwrap())],
159+
[ClauseWithSupertraitSpan::new(
160+
ty::TraitRef::identity(tcx, principal_trait.def_id()).upcast(tcx),
161+
*spans.last().unwrap(),
162+
)],
114163
)
115164
.filter_only_self()
116165
{
117-
debug!("observing object predicate `{pred:?}`");
166+
let clause = clause.instantiate_supertrait(tcx, principal_trait);
167+
debug!("observing object predicate `{clause:?}`");
118168

119-
let bound_predicate = pred.kind();
169+
let bound_predicate = clause.kind();
120170
match bound_predicate.skip_binder() {
121-
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
171+
ty::ClauseKind::Trait(pred) => {
122172
// FIXME(negative_bounds): Handle this correctly...
123173
let trait_ref =
124174
tcx.anonymize_bound_vars(bound_predicate.rebind(pred.trait_ref));
125175
needed_associated_types.extend(
126-
tcx.associated_items(trait_ref.def_id())
176+
tcx.associated_items(pred.trait_ref.def_id)
127177
.in_definition_order()
178+
// We only care about associated types.
128179
.filter(|item| item.kind == ty::AssocKind::Type)
180+
// No RPITITs -- even with `async_fn_in_dyn_trait`, they are implicit.
129181
.filter(|item| !item.is_impl_trait_in_trait())
130182
// If the associated type has a `where Self: Sized` bound,
131183
// we do not need to constrain the associated type.
132184
.filter(|item| !tcx.generics_require_sized_self(item.def_id))
133185
.map(|item| (item.def_id, trait_ref)),
134186
);
135187
}
136-
ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => {
188+
ty::ClauseKind::Projection(pred) => {
137189
let pred = bound_predicate.rebind(pred);
138190
// A `Self` within the original bound will be instantiated with a
139191
// `trait_object_dummy_self`, so check for that.
@@ -161,8 +213,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
161213
// `dyn MyTrait<MyOutput = X, Output = X>`, which is uglier but works. See
162214
// the discussion in #56288 for alternatives.
163215
if !references_self {
164-
// Include projections defined on supertraits.
165-
projection_bounds.push((pred, supertrait_span));
216+
let key = (
217+
pred.skip_binder().projection_term.def_id,
218+
tcx.anonymize_bound_vars(
219+
pred.map_bound(|proj| proj.projection_term.trait_ref(tcx)),
220+
),
221+
);
222+
if !projection_bounds.contains_key(&key) {
223+
projection_bounds.insert(key, (pred, supertrait_span));
224+
}
166225
}
167226

168227
self.check_elaborated_projection_mentions_input_lifetimes(
@@ -182,12 +241,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
182241
// types that we expect to be provided by the user, so the following loop
183242
// removes all the associated types that have a corresponding `Projection`
184243
// clause, either from expanding trait aliases or written by the user.
185-
for &(projection_bound, span) in &projection_bounds {
244+
for &(projection_bound, span) in projection_bounds.values() {
186245
let def_id = projection_bound.item_def_id();
187-
let trait_ref = tcx.anonymize_bound_vars(
188-
projection_bound.map_bound(|p| p.projection_term.trait_ref(tcx)),
189-
);
190-
needed_associated_types.swap_remove(&(def_id, trait_ref));
191246
if tcx.generics_require_sized_self(def_id) {
192247
tcx.emit_node_span_lint(
193248
UNUSED_ASSOCIATED_TYPE_BOUNDS,
@@ -198,9 +253,22 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
198253
}
199254
}
200255

256+
let mut missing_assoc_types = FxIndexSet::default();
257+
let projection_bounds: Vec<_> = needed_associated_types
258+
.into_iter()
259+
.filter_map(|key| {
260+
if let Some(assoc) = projection_bounds.get(&key) {
261+
Some(*assoc)
262+
} else {
263+
missing_assoc_types.insert(key);
264+
None
265+
}
266+
})
267+
.collect();
268+
201269
if let Err(guar) = self.check_for_required_assoc_tys(
202270
principal_trait.as_ref().map_or(smallvec![], |(_, spans)| spans.clone()),
203-
needed_associated_types,
271+
missing_assoc_types,
204272
potential_assoc_types,
205273
hir_bounds,
206274
) {
@@ -266,7 +334,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
266334
})
267335
});
268336

269-
let existential_projections = projection_bounds.iter().map(|(bound, _)| {
337+
let existential_projections = projection_bounds.into_iter().map(|(bound, _)| {
270338
bound.map_bound(|mut b| {
271339
assert_eq!(b.projection_term.self_ty(), dummy_self);
272340

@@ -291,12 +359,16 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
291359
})
292360
});
293361

294-
let auto_trait_predicates = auto_traits.into_iter().map(|(trait_pred, _)| {
295-
assert_eq!(trait_pred.polarity(), ty::PredicatePolarity::Positive);
296-
assert_eq!(trait_pred.self_ty().skip_binder(), dummy_self);
362+
let mut auto_trait_predicates: Vec<_> = auto_traits
363+
.into_iter()
364+
.map(|(trait_pred, _)| {
365+
assert_eq!(trait_pred.polarity(), ty::PredicatePolarity::Positive);
366+
assert_eq!(trait_pred.self_ty().skip_binder(), dummy_self);
297367

298-
ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(trait_pred.def_id()))
299-
});
368+
ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(trait_pred.def_id()))
369+
})
370+
.collect();
371+
auto_trait_predicates.dedup();
300372

301373
// N.b. principal, projections, auto traits
302374
// FIXME: This is actually wrong with multiple principals in regards to symbol mangling
@@ -306,7 +378,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
306378
.chain(auto_trait_predicates)
307379
.collect::<SmallVec<[_; 8]>>();
308380
v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder()));
309-
v.dedup();
310381
let existential_predicates = tcx.mk_poly_existential_predicates(&v);
311382

312383
// Use explicitly-specified region bound, unless the bound is missing.

compiler/rustc_lint/src/impl_trait_overcaptures.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,7 @@ declare_lint! {
8686
///
8787
/// ### Example
8888
///
89-
/// ```rust,compile_fail
90-
/// # #![feature(lifetime_capture_rules_2024)]
89+
/// ```rust,edition2024,compile_fail
9190
/// # #![deny(impl_trait_redundant_captures)]
9291
/// fn test<'a>(x: &'a i32) -> impl Sized + use<'a> { x }
9392
/// ```
@@ -268,8 +267,7 @@ where
268267
&& parent == self.parent_def_id
269268
{
270269
let opaque_span = self.tcx.def_span(opaque_def_id);
271-
let new_capture_rules = opaque_span.at_least_rust_2024()
272-
|| self.tcx.features().lifetime_capture_rules_2024();
270+
let new_capture_rules = opaque_span.at_least_rust_2024();
273271
if !new_capture_rules
274272
&& !opaque.bounds.iter().any(|bound| matches!(bound, hir::GenericBound::Use(..)))
275273
{

compiler/rustc_middle/src/mir/visit.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1364,13 +1364,13 @@ impl PlaceContext {
13641364
matches!(self, PlaceContext::MutatingUse(MutatingUseContext::Drop))
13651365
}
13661366

1367-
/// Returns `true` if this place context represents a borrow.
1367+
/// Returns `true` if this place context represents a borrow, excluding fake borrows
1368+
/// (which are an artifact of borrowck and not actually borrows in runtime MIR).
13681369
pub fn is_borrow(self) -> bool {
13691370
matches!(
13701371
self,
1371-
PlaceContext::NonMutatingUse(
1372-
NonMutatingUseContext::SharedBorrow | NonMutatingUseContext::FakeBorrow
1373-
) | PlaceContext::MutatingUse(MutatingUseContext::Borrow)
1372+
PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow)
1373+
| PlaceContext::MutatingUse(MutatingUseContext::Borrow)
13741374
)
13751375
}
13761376

compiler/rustc_middle/src/traits/mod.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use std::borrow::Cow;
1212
use std::hash::{Hash, Hasher};
1313
use std::sync::Arc;
1414

15-
use rustc_errors::{Applicability, Diag, EmissionGuarantee};
15+
use rustc_errors::{Applicability, Diag, EmissionGuarantee, ErrorGuaranteed};
1616
use rustc_hir as hir;
1717
use rustc_hir::HirId;
1818
use rustc_hir::def_id::DefId;
@@ -996,4 +996,7 @@ pub enum CodegenObligationError {
996996
/// but was included during typeck due to the trivial_bounds feature.
997997
Unimplemented,
998998
FulfillmentError,
999+
/// The selected impl has unconstrained generic parameters. This will emit an error
1000+
/// during impl WF checking.
1001+
UnconstrainedParam(ErrorGuaranteed),
9991002
}

0 commit comments

Comments
 (0)