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 a3dffdb

Browse files
committedJan 30, 2025·
Auto merge of rust-lang#136303 - lcnr:elaborate-skip-bad-projections, r=<try>
elaborate: avoid projections with unconstrained bound regions Should only do this for where-bounds and item bounds. Gonna rewrite later I think. This means we'll no longer need to support unconstrained regions in implied bounds, see lcnr/random-rust-snippets#15. This fixes ```rust trait Super { type SAssoc; } trait Trait<'a>: Super<SAssoc = <Self as Trait<'a>>::TAssoc> { type TAssoc; } fn test<'a, T: 'a>() {} fn unconstrained_lt<'arg, T: for<'a> Trait<'a>>(x: &'arg <T as Super>::SAssoc) { test::<'arg, <T as Super>::SAssoc>(); } ``` but breaks ```rust trait Super { type SAssoc; } trait Trait<'a>: Super<SAssoc = <Self as Trait<'a>>::TAssoc> { type TAssoc; } fn test<'a, T: 'a>() {} fn unconstrained_lt<'arg, T: for<'a> Trait<'a, TAssoc = usize>>(x: <T as Super>::SAssoc) -> usize { x } ``` r? `@compiler-errors`
2 parents 5a45ab9 + d6f2c89 commit a3dffdb

File tree

28 files changed

+326
-275
lines changed

28 files changed

+326
-275
lines changed
 

‎compiler/rustc_ast/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ pub mod token;
4444
pub mod tokenstream;
4545
pub mod visit;
4646

47+
pub use rustc_ast_ir::Limit;
48+
4749
pub use self::ast::*;
4850
pub use self::ast_traits::{AstDeref, AstNodeWrapper, HasAttrs, HasNodeId, HasTokens};
4951

‎compiler/rustc_ast_ir/src/lib.rs

+51
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
#![warn(unreachable_pub)]
66
// tidy-alphabetical-end
77

8+
use std::fmt;
9+
use std::ops::{Div, Mul};
10+
811
#[cfg(feature = "nightly")]
912
use rustc_macros::{Decodable, Encodable, HashStable_NoContext};
1013

@@ -86,3 +89,51 @@ pub enum Pinnedness {
8689
Not,
8790
Pinned,
8891
}
92+
93+
/// New-type wrapper around `usize` for representing limits. Ensures that comparisons against
94+
/// limits are consistent throughout the compiler.
95+
#[derive(Clone, Copy, Debug)]
96+
#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))]
97+
pub struct Limit(pub usize);
98+
99+
impl Limit {
100+
/// Create a new limit from a `usize`.
101+
pub fn new(value: usize) -> Self {
102+
Limit(value)
103+
}
104+
105+
/// Check that `value` is within the limit. Ensures that the same comparisons are used
106+
/// throughout the compiler, as mismatches can cause ICEs, see #72540.
107+
#[inline]
108+
pub fn value_within_limit(&self, value: usize) -> bool {
109+
value <= self.0
110+
}
111+
}
112+
113+
impl From<usize> for Limit {
114+
fn from(value: usize) -> Self {
115+
Self::new(value)
116+
}
117+
}
118+
119+
impl fmt::Display for Limit {
120+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
121+
self.0.fmt(f)
122+
}
123+
}
124+
125+
impl Div<usize> for Limit {
126+
type Output = Limit;
127+
128+
fn div(self, rhs: usize) -> Self::Output {
129+
Limit::new(self.0 / rhs)
130+
}
131+
}
132+
133+
impl Mul<usize> for Limit {
134+
type Output = Limit;
135+
136+
fn mul(self, rhs: usize) -> Self::Output {
137+
Limit::new(self.0 * rhs)
138+
}
139+
}

‎compiler/rustc_errors/src/diagnostic_impls.rs

+7
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use std::path::{Path, PathBuf};
66
use std::process::ExitStatus;
77

88
use rustc_abi::TargetDataLayoutErrors;
9+
use rustc_ast::Limit;
910
use rustc_ast::util::parser::ExprPrecedence;
1011
use rustc_ast_pretty::pprust;
1112
use rustc_macros::Subdiagnostic;
@@ -190,6 +191,12 @@ impl IntoDiagArg for PathBuf {
190191
}
191192
}
192193

194+
impl IntoDiagArg for Limit {
195+
fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
196+
self.to_string().into_diag_arg()
197+
}
198+
}
199+
193200
impl IntoDiagArg for PanicStrategy {
194201
fn into_diag_arg(self) -> DiagArgValue {
195202
DiagArgValue::Str(Cow::Owned(self.desc().to_string()))

‎compiler/rustc_hir_analysis/src/collect.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
4242
use rustc_trait_selection::error_reporting::traits::suggestions::NextTypeParamName;
4343
use rustc_trait_selection::infer::InferCtxtExt;
4444
use rustc_trait_selection::traits::ObligationCtxt;
45+
use rustc_type_ir::visit::collect_referenced_late_bound_regions;
4546
use tracing::{debug, instrument};
4647

4748
use crate::check::intrinsic::intrinsic_operation_unsafety;
@@ -635,11 +636,10 @@ fn get_new_lifetime_name<'tcx>(
635636
poly_trait_ref: ty::PolyTraitRef<'tcx>,
636637
generics: &hir::Generics<'tcx>,
637638
) -> String {
638-
let existing_lifetimes = tcx
639-
.collect_referenced_late_bound_regions(poly_trait_ref)
639+
let existing_lifetimes = collect_referenced_late_bound_regions(tcx, poly_trait_ref)
640640
.into_iter()
641641
.filter_map(|lt| {
642-
if let ty::BoundRegionKind::Named(_, name) = lt {
642+
if let ty::BoundRegionKind::Named(_, name) = lt.kind {
643643
Some(name.as_str().to_string())
644644
} else {
645645
None

‎compiler/rustc_hir_analysis/src/constrained_generic_params.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use rustc_middle::bug;
33
use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitor};
44
use rustc_middle::ty::{self, Ty, TyCtxt};
55
use rustc_span::Span;
6-
use rustc_type_ir::fold::TypeFoldable;
6+
use rustc_type_ir::fold::{TypeFoldable, expand_weak_alias_tys};
77
use tracing::debug;
88

99
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
@@ -51,7 +51,7 @@ pub(crate) fn parameters_for<'tcx>(
5151
include_nonconstraining: bool,
5252
) -> Vec<Parameter> {
5353
let mut collector = ParameterCollector { parameters: vec![], include_nonconstraining };
54-
let value = if !include_nonconstraining { tcx.expand_weak_alias_tys(value) } else { value };
54+
let value = if !include_nonconstraining { expand_weak_alias_tys(tcx, value) } else { value };
5555
value.visit_with(&mut collector);
5656
collector.parameters
5757
}

‎compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ use rustc_middle::bug;
1111
use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TyCtxt};
1212
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw, sym};
1313
use rustc_trait_selection::traits;
14-
use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
14+
use rustc_type_ir::visit::{
15+
TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
16+
collect_constrained_late_bound_regions, collect_referenced_late_bound_regions,
17+
};
1518
use smallvec::SmallVec;
1619
use tracing::{debug, instrument};
1720

@@ -358,9 +361,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
358361
// for<'a> <T as Iterator>::Item = &'a str // <-- 'a is bad
359362
// for<'a> <T as FnMut<(&'a u32,)>>::Output = &'a str // <-- 'a is ok
360363
let late_bound_in_projection_ty =
361-
tcx.collect_constrained_late_bound_regions(projection_term);
364+
collect_constrained_late_bound_regions(tcx, projection_term);
362365
let late_bound_in_term =
363-
tcx.collect_referenced_late_bound_regions(trait_ref.rebind(term));
366+
collect_referenced_late_bound_regions(tcx, trait_ref.rebind(term));
364367
debug!(?late_bound_in_projection_ty);
365368
debug!(?late_bound_in_term);
366369

‎compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ use rustc_span::{ErrorGuaranteed, Span};
1313
use rustc_trait_selection::error_reporting::traits::report_dyn_incompatibility;
1414
use rustc_trait_selection::traits::{self, hir_ty_lowering_dyn_compatibility_violations};
1515
use rustc_type_ir::elaborate::ClauseWithSupertraitSpan;
16+
use rustc_type_ir::visit::{
17+
collect_constrained_late_bound_regions, collect_referenced_late_bound_regions,
18+
};
1619
use smallvec::{SmallVec, smallvec};
1720
use tracing::{debug, instrument};
1821

@@ -362,10 +365,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
362365
//
363366
// for<'a> <T as Iterator>::Item = &'a str // <-- 'a is bad
364367
// for<'a> <T as FnMut<(&'a u32,)>>::Output = &'a str // <-- 'a is ok
365-
let late_bound_in_projection_term =
366-
tcx.collect_constrained_late_bound_regions(pred.map_bound(|pred| pred.projection_term));
368+
let late_bound_in_projection_term = collect_constrained_late_bound_regions(
369+
tcx,
370+
pred.map_bound(|pred| pred.projection_term),
371+
);
367372
let late_bound_in_term =
368-
tcx.collect_referenced_late_bound_regions(pred.map_bound(|pred| pred.term));
373+
collect_referenced_late_bound_regions(tcx, pred.map_bound(|pred| pred.term));
369374
debug!(?late_bound_in_projection_term);
370375
debug!(?late_bound_in_term);
371376

‎compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

+9-6
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw};
4949
use rustc_trait_selection::infer::InferCtxtExt;
5050
use rustc_trait_selection::traits::wf::object_region_bounds;
5151
use rustc_trait_selection::traits::{self, ObligationCtxt};
52+
use rustc_type_ir::visit::{
53+
collect_constrained_late_bound_regions, collect_referenced_late_bound_regions,
54+
};
5255
use tracing::{debug, instrument};
5356

5457
use crate::bounds::Bounds;
@@ -2606,9 +2609,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
26062609
// for<'a> fn(&'a String) -> &'a str <-- 'a is ok
26072610
let inputs = bare_fn_ty.inputs();
26082611
let late_bound_in_args =
2609-
tcx.collect_constrained_late_bound_regions(inputs.map_bound(|i| i.to_owned()));
2612+
collect_constrained_late_bound_regions(tcx, inputs.map_bound(|i| i.to_owned()));
26102613
let output = bare_fn_ty.output();
2611-
let late_bound_in_ret = tcx.collect_referenced_late_bound_regions(output);
2614+
let late_bound_in_ret = collect_referenced_late_bound_regions(tcx, output);
26122615

26132616
self.validate_late_bound_regions(late_bound_in_args, late_bound_in_ret, |br_name| {
26142617
struct_span_code_err!(
@@ -2665,12 +2668,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
26652668
#[instrument(level = "trace", skip(self, generate_err))]
26662669
fn validate_late_bound_regions<'cx>(
26672670
&'cx self,
2668-
constrained_regions: FxIndexSet<ty::BoundRegionKind>,
2669-
referenced_regions: FxIndexSet<ty::BoundRegionKind>,
2671+
constrained_regions: FxIndexSet<ty::BoundRegion>,
2672+
referenced_regions: FxIndexSet<ty::BoundRegion>,
26702673
generate_err: impl Fn(&str) -> Diag<'cx>,
26712674
) {
26722675
for br in referenced_regions.difference(&constrained_regions) {
2673-
let br_name = match *br {
2676+
let br_name = match br.kind {
26742677
ty::BoundRegionKind::Named(_, kw::UnderscoreLifetime)
26752678
| ty::BoundRegionKind::Anon
26762679
| ty::BoundRegionKind::ClosureEnv => "an anonymous lifetime".to_string(),
@@ -2680,7 +2683,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
26802683
let mut err = generate_err(&br_name);
26812684

26822685
if let ty::BoundRegionKind::Named(_, kw::UnderscoreLifetime)
2683-
| ty::BoundRegionKind::Anon = *br
2686+
| ty::BoundRegionKind::Anon = br.kind
26842687
{
26852688
// The only way for an anonymous lifetime to wind up
26862689
// in the return type but **also** be unconstrained is

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -305,8 +305,8 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
305305
self.parent(def_id)
306306
}
307307

308-
fn recursion_limit(self) -> usize {
309-
self.recursion_limit().0
308+
fn recursion_limit(self) -> Limit {
309+
self.recursion_limit()
310310
}
311311

312312
type Features = &'tcx rustc_feature::Features;

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

-61
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use rustc_abi::{ExternAbi, Float, Integer, IntegerType, Size};
66
use rustc_apfloat::Float as _;
77
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
88
use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher};
9-
use rustc_data_structures::stack::ensure_sufficient_stack;
109
use rustc_errors::ErrorGuaranteed;
1110
use rustc_hir as hir;
1211
use rustc_hir::def::{CtorOf, DefKind, Res};
@@ -895,30 +894,6 @@ impl<'tcx> TyCtxt<'tcx> {
895894
|| self.extern_crate(key).is_some_and(|e| e.is_direct())
896895
}
897896

898-
/// Expand any [weak alias types][weak] contained within the given `value`.
899-
///
900-
/// This should be used over other normalization routines in situations where
901-
/// it's important not to normalize other alias types and where the predicates
902-
/// on the corresponding type alias shouldn't be taken into consideration.
903-
///
904-
/// Whenever possible **prefer not to use this function**! Instead, use standard
905-
/// normalization routines or if feasible don't normalize at all.
906-
///
907-
/// This function comes in handy if you want to mimic the behavior of eager
908-
/// type alias expansion in a localized manner.
909-
///
910-
/// <div class="warning">
911-
/// This delays a bug on overflow! Therefore you need to be certain that the
912-
/// contained types get fully normalized at a later stage. Note that even on
913-
/// overflow all well-behaved weak alias types get expanded correctly, so the
914-
/// result is still useful.
915-
/// </div>
916-
///
917-
/// [weak]: ty::Weak
918-
pub fn expand_weak_alias_tys<T: TypeFoldable<TyCtxt<'tcx>>>(self, value: T) -> T {
919-
value.fold_with(&mut WeakAliasTypeExpander { tcx: self, depth: 0 })
920-
}
921-
922897
/// Peel off all [weak alias types] in this type until there are none left.
923898
///
924899
/// This only expands weak alias types in “head” / outermost positions. It can
@@ -1088,42 +1063,6 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for OpaqueTypeExpander<'tcx> {
10881063
}
10891064
}
10901065

1091-
struct WeakAliasTypeExpander<'tcx> {
1092-
tcx: TyCtxt<'tcx>,
1093-
depth: usize,
1094-
}
1095-
1096-
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for WeakAliasTypeExpander<'tcx> {
1097-
fn cx(&self) -> TyCtxt<'tcx> {
1098-
self.tcx
1099-
}
1100-
1101-
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
1102-
if !ty.has_type_flags(ty::TypeFlags::HAS_TY_WEAK) {
1103-
return ty;
1104-
}
1105-
let ty::Alias(ty::Weak, alias) = ty.kind() else {
1106-
return ty.super_fold_with(self);
1107-
};
1108-
if !self.tcx.recursion_limit().value_within_limit(self.depth) {
1109-
let guar = self.tcx.dcx().delayed_bug("overflow expanding weak alias type");
1110-
return Ty::new_error(self.tcx, guar);
1111-
}
1112-
1113-
self.depth += 1;
1114-
ensure_sufficient_stack(|| {
1115-
self.tcx.type_of(alias.def_id).instantiate(self.tcx, alias.args).fold_with(self)
1116-
})
1117-
}
1118-
1119-
fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
1120-
if !ct.has_type_flags(ty::TypeFlags::HAS_TY_WEAK) {
1121-
return ct;
1122-
}
1123-
ct.super_fold_with(self)
1124-
}
1125-
}
1126-
11271066
/// Indicates the form of `AsyncDestruct::Destructor`. Used to simplify async
11281067
/// drop glue for types not using async drop.
11291068
#[derive(Clone, Copy, PartialEq, Eq, Debug)]

0 commit comments

Comments
 (0)
Please sign in to comment.