Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 8 pull requests #137406

Merged
merged 21 commits into from
Feb 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
6fe8b8d
Remove lifetime_capture_rules_2024 feature
compiler-errors Feb 9, 2025
4e4cb10
Add #[track_caller] to Duration Div impl
petertodd Feb 18, 2025
e565eee
Tweak E0277 when predicate comes indirectly from `?`
estebank Feb 18, 2025
8ef535e
Point out the type of more expressions on bad `?`
estebank Feb 20, 2025
ef3c339
compiletest: introduce and use `--src-root` and `--src-test-suite-root`
jieyouxu Feb 3, 2025
6d0c27e
bootstrap: pass `--src-root` and `--src-test-suite-root` instead of `…
jieyouxu Feb 3, 2025
0713bbc
Ignore fake borrows for packed field check
compiler-errors Feb 19, 2025
241a602
Make sure we don't overrun the stack in canonicalizer
compiler-errors Feb 5, 2025
31febc6
Point at type that doesn't implement needed trait
estebank Feb 20, 2025
a825e37
layout_of: put back not-so-unreachable case
Feb 21, 2025
7fea935
don't leave assoc const unnormalized due to unconstrained params
Feb 21, 2025
72bd174
Do not deduplicate list of associated types provided by dyn principal
compiler-errors Feb 3, 2025
a2a0cfe
Assert that we always construct dyn types with the right number of pr…
compiler-errors Feb 5, 2025
326072a
Rollup merge of #136458 - compiler-errors:fix-3, r=lcnr
matthiaskrgr Feb 22, 2025
57da7d3
Rollup merge of #136474 - jieyouxu:src-base, r=clubby789
matthiaskrgr Feb 22, 2025
7f1089e
Rollup merge of #136592 - compiler-errors:ensure-stack-in-canonical, …
matthiaskrgr Feb 22, 2025
085adfd
Rollup merge of #136787 - compiler-errors:lt2024feat, r=oli-obk
matthiaskrgr Feb 22, 2025
5400270
Rollup merge of #137207 - petertodd:2025-add-track-caller-to-duration…
matthiaskrgr Feb 22, 2025
890c4d2
Rollup merge of #137245 - estebank:from-residual-note-2, r=oli-obk
matthiaskrgr Feb 22, 2025
fa62fbe
Rollup merge of #137257 - compiler-errors:fake-borrow-of-packed-field…
matthiaskrgr Feb 22, 2025
6352044
Rollup merge of #137399 - lukas-code:oopsie-woopsie, r=compiler-errors
matthiaskrgr Feb 22, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/removed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ declare_features! (
Some("removed as it caused some confusion and discussion was inactive for years")),
/// Lazily evaluate constants. This allows constants to depend on type parameters.
(removed, lazy_normalization_consts, "1.46.0", Some(72219), Some("superseded by `generic_const_exprs`")),
/// Changes `impl Trait` to capture all lifetimes in scope.
(removed, lifetime_capture_rules_2024, "1.76.0", None, Some("unnecessary -- use edition 2024 instead")),
/// Allows using the `#[link_args]` attribute.
(removed, link_args, "1.53.0", Some(29596),
Some("removed in favor of using `-C link-arg=ARG` on command line, \
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,8 +214,6 @@ declare_features! (
(internal, intrinsics, "1.0.0", None),
/// Allows using `#[lang = ".."]` attribute for linking items to special compiler logic.
(internal, lang_items, "1.0.0", None),
/// Changes `impl Trait` to capture all lifetimes in scope.
(unstable, lifetime_capture_rules_2024, "1.76.0", None),
/// Allows `#[link(..., cfg(..))]`; perma-unstable per #37406
(internal, link_cfg, "1.14.0", None),
/// Allows using `?Trait` trait bounds in more contexts.
Expand Down
33 changes: 12 additions & 21 deletions compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,21 +305,15 @@ fn generic_param_def_as_bound_arg(param: &ty::GenericParamDef) -> ty::BoundVaria
}

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

let capture_all_in_scope_lifetimes =
opaque_captures_all_in_scope_lifetimes(self.tcx, opaque);
let capture_all_in_scope_lifetimes = opaque_captures_all_in_scope_lifetimes(opaque);
if capture_all_in_scope_lifetimes {
let lifetime_ident = |def_id: LocalDefId| {
let name = self.tcx.item_name(def_id.to_def_id());
Expand Down Expand Up @@ -2276,7 +2269,7 @@ fn is_late_bound_map(
}

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

Expand Down Expand Up @@ -2455,23 +2448,21 @@ fn is_late_bound_map(
}
}

struct AllCollector<'tcx> {
tcx: TyCtxt<'tcx>,
struct AllCollector {
has_fully_capturing_opaque: bool,
regions: FxHashSet<LocalDefId>,
}

impl<'v> Visitor<'v> for AllCollector<'v> {
fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
impl<'tcx> Visitor<'tcx> for AllCollector {
fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
if let hir::LifetimeName::Param(def_id) = lifetime_ref.res {
self.regions.insert(def_id);
}
}

fn visit_opaque_ty(&mut self, opaque: &'v hir::OpaqueTy<'v>) {
fn visit_opaque_ty(&mut self, opaque: &'tcx hir::OpaqueTy<'tcx>) {
if !self.has_fully_capturing_opaque {
self.has_fully_capturing_opaque =
opaque_captures_all_in_scope_lifetimes(self.tcx, opaque);
self.has_fully_capturing_opaque = opaque_captures_all_in_scope_lifetimes(opaque);
}
intravisit::walk_opaque_ty(self, opaque);
}
Expand Down
127 changes: 99 additions & 28 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
use rustc_errors::codes::*;
use rustc_errors::struct_span_code_err;
use rustc_hir as hir;
Expand Down Expand Up @@ -58,9 +58,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}
}

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

Expand Down Expand Up @@ -103,37 +103,89 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}
}

// Map the projection bounds onto a key that makes it easy to remove redundant
// bounds that are constrained by supertraits of the principal def id.
//
// Also make sure we detect conflicting bounds from expanding a trait alias and
// also specifying it manually, like:
// ```
// type Alias = Trait<Assoc = i32>;
// let _: &dyn Alias<Assoc = u32> = /* ... */;
// ```
let mut projection_bounds = FxIndexMap::default();
for (proj, proj_span) in elaborated_projection_bounds {
let key = (
proj.skip_binder().projection_term.def_id,
tcx.anonymize_bound_vars(
proj.map_bound(|proj| proj.projection_term.trait_ref(tcx)),
),
);
if let Some((old_proj, old_proj_span)) =
projection_bounds.insert(key, (proj, proj_span))
&& tcx.anonymize_bound_vars(proj) != tcx.anonymize_bound_vars(old_proj)
{
let item = tcx.item_name(proj.item_def_id());
self.dcx()
.struct_span_err(
span,
format!(
"conflicting associated type bounds for `{item}` when \
expanding trait alias"
),
)
.with_span_label(
old_proj_span,
format!("`{item}` is specified to be `{}` here", old_proj.term()),
)
.with_span_label(
proj_span,
format!("`{item}` is specified to be `{}` here", proj.term()),
)
.emit();
}
}

let principal_trait = regular_traits.into_iter().next();

let mut needed_associated_types = FxIndexSet::default();
if let Some((principal_trait, spans)) = &principal_trait {
let pred: ty::Predicate<'tcx> = (*principal_trait).upcast(tcx);
for ClauseWithSupertraitSpan { pred, supertrait_span } in traits::elaborate(
let mut needed_associated_types = vec![];
if let Some((principal_trait, ref spans)) = principal_trait {
let principal_trait = principal_trait.map_bound(|trait_pred| {
assert_eq!(trait_pred.polarity, ty::PredicatePolarity::Positive);
trait_pred.trait_ref
});

for ClauseWithSupertraitSpan { clause, supertrait_span } in traits::elaborate(
tcx,
[ClauseWithSupertraitSpan::new(pred, *spans.last().unwrap())],
[ClauseWithSupertraitSpan::new(
ty::TraitRef::identity(tcx, principal_trait.def_id()).upcast(tcx),
*spans.last().unwrap(),
)],
)
.filter_only_self()
{
debug!("observing object predicate `{pred:?}`");
let clause = clause.instantiate_supertrait(tcx, principal_trait);
debug!("observing object predicate `{clause:?}`");

let bound_predicate = pred.kind();
let bound_predicate = clause.kind();
match bound_predicate.skip_binder() {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
ty::ClauseKind::Trait(pred) => {
// FIXME(negative_bounds): Handle this correctly...
let trait_ref =
tcx.anonymize_bound_vars(bound_predicate.rebind(pred.trait_ref));
needed_associated_types.extend(
tcx.associated_items(trait_ref.def_id())
tcx.associated_items(pred.trait_ref.def_id)
.in_definition_order()
// We only care about associated types.
.filter(|item| item.kind == ty::AssocKind::Type)
// No RPITITs -- even with `async_fn_in_dyn_trait`, they are implicit.
.filter(|item| !item.is_impl_trait_in_trait())
// If the associated type has a `where Self: Sized` bound,
// we do not need to constrain the associated type.
.filter(|item| !tcx.generics_require_sized_self(item.def_id))
.map(|item| (item.def_id, trait_ref)),
);
}
ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => {
ty::ClauseKind::Projection(pred) => {
let pred = bound_predicate.rebind(pred);
// A `Self` within the original bound will be instantiated with a
// `trait_object_dummy_self`, so check for that.
Expand Down Expand Up @@ -161,8 +213,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
// `dyn MyTrait<MyOutput = X, Output = X>`, which is uglier but works. See
// the discussion in #56288 for alternatives.
if !references_self {
// Include projections defined on supertraits.
projection_bounds.push((pred, supertrait_span));
let key = (
pred.skip_binder().projection_term.def_id,
tcx.anonymize_bound_vars(
pred.map_bound(|proj| proj.projection_term.trait_ref(tcx)),
),
);
if !projection_bounds.contains_key(&key) {
projection_bounds.insert(key, (pred, supertrait_span));
}
}

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

let mut missing_assoc_types = FxIndexSet::default();
let projection_bounds: Vec<_> = needed_associated_types
.into_iter()
.filter_map(|key| {
if let Some(assoc) = projection_bounds.get(&key) {
Some(*assoc)
} else {
missing_assoc_types.insert(key);
None
}
})
.collect();

if let Err(guar) = self.check_for_required_assoc_tys(
principal_trait.as_ref().map_or(smallvec![], |(_, spans)| spans.clone()),
needed_associated_types,
missing_assoc_types,
potential_assoc_types,
hir_bounds,
) {
Expand Down Expand Up @@ -266,7 +334,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
})
});

let existential_projections = projection_bounds.iter().map(|(bound, _)| {
let existential_projections = projection_bounds.into_iter().map(|(bound, _)| {
bound.map_bound(|mut b| {
assert_eq!(b.projection_term.self_ty(), dummy_self);

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

let auto_trait_predicates = auto_traits.into_iter().map(|(trait_pred, _)| {
assert_eq!(trait_pred.polarity(), ty::PredicatePolarity::Positive);
assert_eq!(trait_pred.self_ty().skip_binder(), dummy_self);
let mut auto_trait_predicates: Vec<_> = auto_traits
.into_iter()
.map(|(trait_pred, _)| {
assert_eq!(trait_pred.polarity(), ty::PredicatePolarity::Positive);
assert_eq!(trait_pred.self_ty().skip_binder(), dummy_self);

ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(trait_pred.def_id()))
});
ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(trait_pred.def_id()))
})
.collect();
auto_trait_predicates.dedup();

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

// Use explicitly-specified region bound, unless the bound is missing.
Expand Down
6 changes: 2 additions & 4 deletions compiler/rustc_lint/src/impl_trait_overcaptures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,7 @@ declare_lint! {
///
/// ### Example
///
/// ```rust,compile_fail
/// # #![feature(lifetime_capture_rules_2024)]
/// ```rust,edition2024,compile_fail
/// # #![deny(impl_trait_redundant_captures)]
/// fn test<'a>(x: &'a i32) -> impl Sized + use<'a> { x }
/// ```
Expand Down Expand Up @@ -268,8 +267,7 @@ where
&& parent == self.parent_def_id
{
let opaque_span = self.tcx.def_span(opaque_def_id);
let new_capture_rules = opaque_span.at_least_rust_2024()
|| self.tcx.features().lifetime_capture_rules_2024();
let new_capture_rules = opaque_span.at_least_rust_2024();
if !new_capture_rules
&& !opaque.bounds.iter().any(|bound| matches!(bound, hir::GenericBound::Use(..)))
{
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_middle/src/mir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1364,13 +1364,13 @@ impl PlaceContext {
matches!(self, PlaceContext::MutatingUse(MutatingUseContext::Drop))
}

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

Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_middle/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use std::borrow::Cow;
use std::hash::{Hash, Hasher};
use std::sync::Arc;

use rustc_errors::{Applicability, Diag, EmissionGuarantee};
use rustc_errors::{Applicability, Diag, EmissionGuarantee, ErrorGuaranteed};
use rustc_hir as hir;
use rustc_hir::HirId;
use rustc_hir::def_id::DefId;
Expand Down Expand Up @@ -996,4 +996,7 @@ pub enum CodegenObligationError {
/// but was included during typeck due to the trivial_bounds feature.
Unimplemented,
FulfillmentError,
/// The selected impl has unconstrained generic parameters. This will emit an error
/// during impl WF checking.
UnconstrainedParam(ErrorGuaranteed),
}
Loading
Loading