Skip to content

Commit ced0974

Browse files
committed
Auto merge of #123537 - compiler-errors:shallow, r=lcnr
Simplify shallow resolver to just fold ty/consts Probably faster than using a whole folder?
2 parents 468f115 + ecef296 commit ced0974

File tree

13 files changed

+96
-125
lines changed

13 files changed

+96
-125
lines changed

compiler/rustc_borrowck/src/type_check/relate_tys.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ impl<'bccx, 'tcx> TypeRelation<'tcx> for NllTypeRelating<'_, 'bccx, 'tcx> {
434434
a: ty::Const<'tcx>,
435435
b: ty::Const<'tcx>,
436436
) -> RelateResult<'tcx, ty::Const<'tcx>> {
437-
let a = self.type_checker.infcx.shallow_resolve(a);
437+
let a = self.type_checker.infcx.shallow_resolve_const(a);
438438
assert!(!a.has_non_region_infer(), "unexpected inference var {:?}", a);
439439
assert!(!b.has_non_region_infer(), "unexpected inference var {:?}", b);
440440

compiler/rustc_infer/src/infer/canonical/canonicalizer.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -802,7 +802,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
802802
const_var: ty::Const<'tcx>,
803803
) -> ty::Const<'tcx> {
804804
debug_assert!(
805-
!self.infcx.is_some_and(|infcx| const_var != infcx.shallow_resolve(const_var))
805+
!self.infcx.is_some_and(|infcx| const_var != infcx.shallow_resolve_const(const_var))
806806
);
807807
let var = self.canonical_var(info, const_var.into());
808808
ty::Const::new_bound(self.tcx, self.binder_index, var, self.fold_ty(const_var.ty()))

compiler/rustc_infer/src/infer/mod.rs

+70-96
Original file line numberDiff line numberDiff line change
@@ -1241,19 +1241,76 @@ impl<'tcx> InferCtxt<'tcx> {
12411241
}
12421242
}
12431243

1244-
/// Resolve any type variables found in `value` -- but only one
1245-
/// level. So, if the variable `?X` is bound to some type
1246-
/// `Foo<?Y>`, then this would return `Foo<?Y>` (but `?Y` may
1247-
/// itself be bound to a type).
1248-
///
1249-
/// Useful when you only need to inspect the outermost level of
1250-
/// the type and don't care about nested types (or perhaps you
1251-
/// will be resolving them as well, e.g. in a loop).
1252-
pub fn shallow_resolve<T>(&self, value: T) -> T
1253-
where
1254-
T: TypeFoldable<TyCtxt<'tcx>>,
1255-
{
1256-
value.fold_with(&mut ShallowResolver { infcx: self })
1244+
pub fn shallow_resolve(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
1245+
if let ty::Infer(v) = ty.kind() { self.fold_infer_ty(*v).unwrap_or(ty) } else { ty }
1246+
}
1247+
1248+
// This is separate from `shallow_resolve` to keep that method small and inlinable.
1249+
#[inline(never)]
1250+
fn fold_infer_ty(&self, v: InferTy) -> Option<Ty<'tcx>> {
1251+
match v {
1252+
ty::TyVar(v) => {
1253+
// Not entirely obvious: if `typ` is a type variable,
1254+
// it can be resolved to an int/float variable, which
1255+
// can then be recursively resolved, hence the
1256+
// recursion. Note though that we prevent type
1257+
// variables from unifying to other type variables
1258+
// directly (though they may be embedded
1259+
// structurally), and we prevent cycles in any case,
1260+
// so this recursion should always be of very limited
1261+
// depth.
1262+
//
1263+
// Note: if these two lines are combined into one we get
1264+
// dynamic borrow errors on `self.inner`.
1265+
let known = self.inner.borrow_mut().type_variables().probe(v).known();
1266+
known.map(|t| self.shallow_resolve(t))
1267+
}
1268+
1269+
ty::IntVar(v) => self
1270+
.inner
1271+
.borrow_mut()
1272+
.int_unification_table()
1273+
.probe_value(v)
1274+
.map(|v| v.to_type(self.tcx)),
1275+
1276+
ty::FloatVar(v) => self
1277+
.inner
1278+
.borrow_mut()
1279+
.float_unification_table()
1280+
.probe_value(v)
1281+
.map(|v| v.to_type(self.tcx)),
1282+
1283+
ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => None,
1284+
}
1285+
}
1286+
1287+
pub fn shallow_resolve_const(&self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
1288+
match ct.kind() {
1289+
ty::ConstKind::Infer(infer_ct) => match infer_ct {
1290+
InferConst::Var(vid) => self
1291+
.inner
1292+
.borrow_mut()
1293+
.const_unification_table()
1294+
.probe_value(vid)
1295+
.known()
1296+
.unwrap_or(ct),
1297+
InferConst::EffectVar(vid) => self
1298+
.inner
1299+
.borrow_mut()
1300+
.effect_unification_table()
1301+
.probe_value(vid)
1302+
.known()
1303+
.unwrap_or(ct),
1304+
InferConst::Fresh(_) => ct,
1305+
},
1306+
ty::ConstKind::Param(_)
1307+
| ty::ConstKind::Bound(_, _)
1308+
| ty::ConstKind::Placeholder(_)
1309+
| ty::ConstKind::Unevaluated(_)
1310+
| ty::ConstKind::Value(_)
1311+
| ty::ConstKind::Error(_)
1312+
| ty::ConstKind::Expr(_) => ct,
1313+
}
12571314
}
12581315

12591316
pub fn root_var(&self, var: ty::TyVid) -> ty::TyVid {
@@ -1764,89 +1821,6 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for InferenceLiteralEraser<'tcx> {
17641821
}
17651822
}
17661823

1767-
struct ShallowResolver<'a, 'tcx> {
1768-
infcx: &'a InferCtxt<'tcx>,
1769-
}
1770-
1771-
impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ShallowResolver<'a, 'tcx> {
1772-
fn interner(&self) -> TyCtxt<'tcx> {
1773-
self.infcx.tcx
1774-
}
1775-
1776-
/// If `ty` is a type variable of some kind, resolve it one level
1777-
/// (but do not resolve types found in the result). If `typ` is
1778-
/// not a type variable, just return it unmodified.
1779-
#[inline]
1780-
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
1781-
if let ty::Infer(v) = ty.kind() { self.fold_infer_ty(*v).unwrap_or(ty) } else { ty }
1782-
}
1783-
1784-
fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
1785-
match ct.kind() {
1786-
ty::ConstKind::Infer(InferConst::Var(vid)) => self
1787-
.infcx
1788-
.inner
1789-
.borrow_mut()
1790-
.const_unification_table()
1791-
.probe_value(vid)
1792-
.known()
1793-
.unwrap_or(ct),
1794-
ty::ConstKind::Infer(InferConst::EffectVar(vid)) => self
1795-
.infcx
1796-
.inner
1797-
.borrow_mut()
1798-
.effect_unification_table()
1799-
.probe_value(vid)
1800-
.known()
1801-
.unwrap_or(ct),
1802-
_ => ct,
1803-
}
1804-
}
1805-
}
1806-
1807-
impl<'a, 'tcx> ShallowResolver<'a, 'tcx> {
1808-
// This is separate from `fold_ty` to keep that method small and inlinable.
1809-
#[inline(never)]
1810-
fn fold_infer_ty(&mut self, v: InferTy) -> Option<Ty<'tcx>> {
1811-
match v {
1812-
ty::TyVar(v) => {
1813-
// Not entirely obvious: if `typ` is a type variable,
1814-
// it can be resolved to an int/float variable, which
1815-
// can then be recursively resolved, hence the
1816-
// recursion. Note though that we prevent type
1817-
// variables from unifying to other type variables
1818-
// directly (though they may be embedded
1819-
// structurally), and we prevent cycles in any case,
1820-
// so this recursion should always be of very limited
1821-
// depth.
1822-
//
1823-
// Note: if these two lines are combined into one we get
1824-
// dynamic borrow errors on `self.inner`.
1825-
let known = self.infcx.inner.borrow_mut().type_variables().probe(v).known();
1826-
known.map(|t| self.fold_ty(t))
1827-
}
1828-
1829-
ty::IntVar(v) => self
1830-
.infcx
1831-
.inner
1832-
.borrow_mut()
1833-
.int_unification_table()
1834-
.probe_value(v)
1835-
.map(|v| v.to_type(self.infcx.tcx)),
1836-
1837-
ty::FloatVar(v) => self
1838-
.infcx
1839-
.inner
1840-
.borrow_mut()
1841-
.float_unification_table()
1842-
.probe_value(v)
1843-
.map(|v| v.to_type(self.infcx.tcx)),
1844-
1845-
ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => None,
1846-
}
1847-
}
1848-
}
1849-
18501824
impl<'tcx> TypeTrace<'tcx> {
18511825
pub fn span(&self) -> Span {
18521826
self.cause.span

compiler/rustc_infer/src/infer/relate/combine.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,8 @@ impl<'tcx> InferCtxt<'tcx> {
155155
return Ok(a);
156156
}
157157

158-
let a = self.shallow_resolve(a);
159-
let b = self.shallow_resolve(b);
158+
let a = self.shallow_resolve_const(a);
159+
let b = self.shallow_resolve_const(b);
160160

161161
// We should never have to relate the `ty` field on `Const` as it is checked elsewhere that consts have the
162162
// correct type for the generic param they are an argument for. However there have been a number of cases

compiler/rustc_infer/src/infer/resolve.rs

+6-8
Original file line numberDiff line numberDiff line change
@@ -12,29 +12,27 @@ use rustc_middle::ty::{self, Const, InferConst, Ty, TyCtxt, TypeFoldable};
1212
/// useful for printing messages etc but also required at various
1313
/// points for correctness.
1414
pub struct OpportunisticVarResolver<'a, 'tcx> {
15-
// The shallow resolver is used to resolve inference variables at every
16-
// level of the type.
17-
shallow_resolver: crate::infer::ShallowResolver<'a, 'tcx>,
15+
infcx: &'a InferCtxt<'tcx>,
1816
}
1917

2018
impl<'a, 'tcx> OpportunisticVarResolver<'a, 'tcx> {
2119
#[inline]
2220
pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self {
23-
OpportunisticVarResolver { shallow_resolver: crate::infer::ShallowResolver { infcx } }
21+
OpportunisticVarResolver { infcx }
2422
}
2523
}
2624

2725
impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for OpportunisticVarResolver<'a, 'tcx> {
2826
fn interner(&self) -> TyCtxt<'tcx> {
29-
TypeFolder::interner(&self.shallow_resolver)
27+
self.infcx.tcx
3028
}
3129

3230
#[inline]
3331
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
3432
if !t.has_non_region_infer() {
3533
t // micro-optimize -- if there is nothing in this type that this fold affects...
3634
} else {
37-
let t = self.shallow_resolver.fold_ty(t);
35+
let t = self.infcx.shallow_resolve(t);
3836
t.super_fold_with(self)
3937
}
4038
}
@@ -43,7 +41,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for OpportunisticVarResolver<'a, 'tcx> {
4341
if !ct.has_non_region_infer() {
4442
ct // micro-optimize -- if there is nothing in this const that this fold affects...
4543
} else {
46-
let ct = self.shallow_resolver.fold_const(ct);
44+
let ct = self.infcx.shallow_resolve_const(ct);
4745
ct.super_fold_with(self)
4846
}
4947
}
@@ -160,7 +158,7 @@ impl<'a, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for FullTypeResolver<'a, 'tcx> {
160158
if !c.has_infer() {
161159
Ok(c) // micro-optimize -- if there is nothing in this const that this fold affects...
162160
} else {
163-
let c = self.infcx.shallow_resolve(c);
161+
let c = self.infcx.shallow_resolve_const(c);
164162
match c.kind() {
165163
ty::ConstKind::Infer(InferConst::Var(vid)) => {
166164
return Err(FixupError::UnresolvedConst(vid));

compiler/rustc_trait_selection/src/solve/normalize.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for NormalizationFolder<'_, 'tcx> {
198198
#[instrument(level = "debug", skip(self), ret)]
199199
fn try_fold_const(&mut self, ct: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, Self::Error> {
200200
let infcx = self.at.infcx;
201-
debug_assert_eq!(ct, infcx.shallow_resolve(ct));
201+
debug_assert_eq!(ct, infcx.shallow_resolve_const(ct));
202202
if !ct.has_aliases() {
203203
return Ok(ct);
204204
}

compiler/rustc_trait_selection/src/traits/coherence.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,7 @@ fn plug_infer_with_placeholders<'tcx>(
501501
}
502502

503503
fn visit_const(&mut self, ct: ty::Const<'tcx>) {
504-
let ct = self.infcx.shallow_resolve(ct);
504+
let ct = self.infcx.shallow_resolve_const(ct);
505505
if ct.is_ct_infer() {
506506
let Ok(InferOk { value: (), obligations }) =
507507
self.infcx.at(&ObligationCause::dummy(), ty::ParamEnv::empty()).eq(

compiler/rustc_trait_selection/src/traits/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ fn pred_known_to_hold_modulo_regions<'tcx>(
162162
let errors = ocx.select_all_or_error();
163163
match errors.as_slice() {
164164
// Only known to hold if we did no inference.
165-
[] => infcx.shallow_resolve(goal) == goal,
165+
[] => infcx.resolve_vars_if_possible(goal) == goal,
166166

167167
errors => {
168168
debug!(?errors);

compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1173,8 +1173,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
11731173
return;
11741174
}
11751175

1176-
let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
1177-
match self_ty.skip_binder().kind() {
1176+
let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
1177+
match self_ty.kind() {
11781178
ty::Alias(..)
11791179
| ty::Dynamic(..)
11801180
| ty::Error(_)
@@ -1325,7 +1325,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
13251325
obligation: &PolyTraitObligation<'tcx>,
13261326
candidates: &mut SelectionCandidateSet<'tcx>,
13271327
) {
1328-
let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
1328+
let self_ty = self.infcx.resolve_vars_if_possible(obligation.self_ty());
13291329

13301330
match self_ty.skip_binder().kind() {
13311331
ty::FnPtr(_) => candidates.vec.push(BuiltinCandidate { has_nested: false }),

compiler/rustc_trait_selection/src/traits/select/confirmation.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -157,10 +157,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
157157
) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
158158
let tcx = self.tcx();
159159

160-
let trait_predicate = self.infcx.shallow_resolve(obligation.predicate);
161160
let placeholder_trait_predicate =
162-
self.infcx.enter_forall_and_leak_universe(trait_predicate).trait_ref;
163-
let placeholder_self_ty = placeholder_trait_predicate.self_ty();
161+
self.infcx.enter_forall_and_leak_universe(obligation.predicate).trait_ref;
162+
let placeholder_self_ty = self.infcx.shallow_resolve(placeholder_trait_predicate.self_ty());
164163
let candidate_predicate = self
165164
.for_each_item_bound(
166165
placeholder_self_ty,
@@ -422,7 +421,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
422421
) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
423422
debug!(?obligation, "confirm_auto_impl_candidate");
424423

425-
let self_ty = self.infcx.shallow_resolve(obligation.predicate.self_ty());
424+
let self_ty = obligation.predicate.self_ty().map_bound(|ty| self.infcx.shallow_resolve(ty));
426425
let types = self.constituent_types_for_ty(self_ty)?;
427426
Ok(self.vtable_auto_impl(obligation, obligation.predicate.def_id(), types))
428427
}
@@ -1378,7 +1377,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
13781377
let drop_trait = self.tcx().require_lang_item(LangItem::Drop, None);
13791378

13801379
let tcx = self.tcx();
1381-
let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
1380+
let self_ty = obligation.self_ty().map_bound(|ty| self.infcx.shallow_resolve(ty));
13821381

13831382
let mut nested = vec![];
13841383
let cause = obligation.derived_cause(BuiltinDerivedObligation);

compiler/rustc_trait_selection/src/traits/select/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
571571
)?;
572572
// If the predicate has done any inference, then downgrade the
573573
// result to ambiguous.
574-
if this.infcx.shallow_resolve(goal) != goal {
574+
if this.infcx.resolve_vars_if_possible(goal) != goal {
575575
result = result.max(EvaluatedToAmbig);
576576
}
577577
Ok(result)
@@ -1774,9 +1774,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
17741774
// that means that we must have newly inferred something about the GAT.
17751775
// We should give up in that case.
17761776
if !generics.params.is_empty()
1777-
&& obligation.predicate.args[generics.parent_count..]
1778-
.iter()
1779-
.any(|&p| p.has_non_region_infer() && self.infcx.shallow_resolve(p) != p)
1777+
&& obligation.predicate.args[generics.parent_count..].iter().any(|&p| {
1778+
p.has_non_region_infer() && self.infcx.resolve_vars_if_possible(p) != p
1779+
})
17801780
{
17811781
ProjectionMatchesProjection::Ambiguous
17821782
} else {

compiler/rustc_trait_selection/src/traits/util.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for PlaceholderReplacer<'_, 'tcx> {
649649
}
650650

651651
fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
652-
let ct = self.infcx.shallow_resolve(ct);
652+
let ct = self.infcx.shallow_resolve_const(ct);
653653
if let ty::ConstKind::Placeholder(p) = ct.kind() {
654654
let replace_var = self.mapped_consts.get(&p);
655655
match replace_var {

compiler/rustc_trait_selection/src/traits/wf.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ pub fn obligations<'tcx>(
4444
GenericArgKind::Const(ct) => {
4545
match ct.kind() {
4646
ty::ConstKind::Infer(_) => {
47-
let resolved = infcx.shallow_resolve(ct);
47+
let resolved = infcx.shallow_resolve_const(ct);
4848
if resolved == ct {
4949
// No progress.
5050
return None;

0 commit comments

Comments
 (0)