Skip to content

Commit ccb5595

Browse files
committed
Auto merge of rust-lang#98900 - lcnr:region-stuff, r=jackh726
const_generics: correctly deal with bound variables removes the hack in `resolve` which was needed because we evaluated constants without caring about their bound variables. Each commit should be fairly self-contained, even if they build on each other r? `@jackh726`
2 parents b42244c + e666032 commit ccb5595

File tree

12 files changed

+76
-83
lines changed

12 files changed

+76
-83
lines changed

compiler/rustc_const_eval/src/interpret/intrinsics.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,9 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
7979
ty::Projection(_)
8080
| ty::Opaque(_, _)
8181
| ty::Param(_)
82-
| ty::Bound(_, _)
8382
| ty::Placeholder(_)
8483
| ty::Infer(_) => throw_inval!(TooGeneric),
84+
ty::Bound(_, _) => bug!("bound ty during ctfe"),
8585
ty::Bool
8686
| ty::Char
8787
| ty::Int(_)

compiler/rustc_const_eval/src/interpret/operand.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -559,15 +559,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
559559
layout: Option<TyAndLayout<'tcx>>,
560560
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
561561
match c.kind() {
562-
ty::ConstKind::Param(_) | ty::ConstKind::Bound(..) => throw_inval!(TooGeneric),
562+
ty::ConstKind::Param(_) | ty::ConstKind::Placeholder(..) => throw_inval!(TooGeneric),
563563
ty::ConstKind::Error(DelaySpanBugEmitted { reported, .. }) => {
564564
throw_inval!(AlreadyReported(reported))
565565
}
566566
ty::ConstKind::Unevaluated(uv) => {
567567
let instance = self.resolve(uv.def, uv.substs)?;
568568
Ok(self.eval_to_allocation(GlobalId { instance, promoted: uv.promoted })?.into())
569569
}
570-
ty::ConstKind::Infer(..) | ty::ConstKind::Placeholder(..) => {
570+
ty::ConstKind::Bound(..) | ty::ConstKind::Infer(..) => {
571571
span_bug!(self.cur_span(), "const_to_op: Unexpected ConstKind {:?}", c)
572572
}
573573
ty::ConstKind::Value(valtree) => {

compiler/rustc_infer/src/infer/combine.rs

+8-12
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,7 @@ struct Generalizer<'cx, 'tcx> {
486486

487487
param_env: ty::ParamEnv<'tcx>,
488488

489-
cache: SsoHashMap<Ty<'tcx>, RelateResult<'tcx, Ty<'tcx>>>,
489+
cache: SsoHashMap<Ty<'tcx>, Ty<'tcx>>,
490490
}
491491

492492
/// Result from a generalization operation. This includes
@@ -593,8 +593,8 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
593593
fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
594594
assert_eq!(t, t2); // we are abusing TypeRelation here; both LHS and RHS ought to be ==
595595

596-
if let Some(result) = self.cache.get(&t) {
597-
return result.clone();
596+
if let Some(&result) = self.cache.get(&t) {
597+
return Ok(result);
598598
}
599599
debug!("generalize: t={:?}", t);
600600

@@ -664,10 +664,10 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
664664
Ok(t)
665665
}
666666
_ => relate::super_relate_tys(self, t, t),
667-
};
667+
}?;
668668

669-
self.cache.insert(t, result.clone());
670-
return result;
669+
self.cache.insert(t, result);
670+
Ok(result)
671671
}
672672

673673
fn regions(
@@ -743,9 +743,7 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
743743
}
744744
}
745745
}
746-
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted })
747-
if self.tcx().lazy_normalization() =>
748-
{
746+
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
749747
assert_eq!(promoted, None);
750748
let substs = self.relate_with_variance(
751749
ty::Variance::Invariant,
@@ -967,9 +965,7 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
967965
}
968966
}
969967
}
970-
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted })
971-
if self.tcx().lazy_normalization() =>
972-
{
968+
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
973969
assert_eq!(promoted, None);
974970
let substs = self.relate_with_variance(
975971
ty::Variance::Invariant,

compiler/rustc_middle/src/ty/consts/kind.rs

+1
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ impl<'tcx> ConstKind<'tcx> {
180180
param_env: ParamEnv<'tcx>,
181181
eval_mode: EvalMode,
182182
) -> Option<Result<EvalResult<'tcx>, ErrorGuaranteed>> {
183+
assert!(!self.has_escaping_bound_vars(), "escaping vars in {self:?}");
183184
if let ConstKind::Unevaluated(unevaluated) = self {
184185
use crate::mir::interpret::ErrorHandled;
185186

compiler/rustc_middle/src/ty/relate.rs

-4
Original file line numberDiff line numberDiff line change
@@ -594,10 +594,6 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
594594
);
595595
}
596596

597-
let eagerly_eval = |x: ty::Const<'tcx>| x.eval(tcx, relation.param_env());
598-
let a = eagerly_eval(a);
599-
let b = eagerly_eval(b);
600-
601597
// Currently, the values that can be unified are primitive types,
602598
// and those that derive both `PartialEq` and `Eq`, corresponding
603599
// to structural-match types.

compiler/rustc_trait_selection/src/traits/project.rs

+44-4
Original file line numberDiff line numberDiff line change
@@ -635,13 +635,18 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
635635

636636
#[instrument(skip(self), level = "debug")]
637637
fn fold_const(&mut self, constant: ty::Const<'tcx>) -> ty::Const<'tcx> {
638-
if self.selcx.tcx().lazy_normalization() || !self.eager_inference_replacement {
638+
let tcx = self.selcx.tcx();
639+
if tcx.lazy_normalization() {
639640
constant
640641
} else {
641642
let constant = constant.super_fold_with(self);
642-
debug!(?constant);
643-
debug!("self.param_env: {:?}", self.param_env);
644-
constant.eval(self.selcx.tcx(), self.param_env)
643+
debug!(?constant, ?self.param_env);
644+
with_replaced_escaping_bound_vars(
645+
self.selcx.infcx(),
646+
&mut self.universes,
647+
constant,
648+
|constant| constant.eval(tcx, self.param_env),
649+
)
645650
}
646651
}
647652

@@ -671,6 +676,41 @@ pub struct BoundVarReplacer<'me, 'tcx> {
671676
universe_indices: &'me mut Vec<Option<ty::UniverseIndex>>,
672677
}
673678

679+
/// Executes `f` on `value` after replacing all escaping bound variables with placeholders
680+
/// and then replaces these placeholders with the original bound variables in the result.
681+
///
682+
/// In most places, bound variables should be replaced right when entering a binder, making
683+
/// this function unnecessary. However, normalization currently does not do that, so we have
684+
/// to do this lazily.
685+
///
686+
/// You should not add any additional uses of this function, at least not without first
687+
/// discussing it with t-types.
688+
///
689+
/// FIXME(@lcnr): We may even consider experimenting with eagerly replacing bound vars during
690+
/// normalization as well, at which point this function will be unnecessary and can be removed.
691+
pub fn with_replaced_escaping_bound_vars<'a, 'tcx, T: TypeFoldable<'tcx>, R: TypeFoldable<'tcx>>(
692+
infcx: &'a InferCtxt<'a, 'tcx>,
693+
universe_indices: &'a mut Vec<Option<ty::UniverseIndex>>,
694+
value: T,
695+
f: impl FnOnce(T) -> R,
696+
) -> R {
697+
if value.has_escaping_bound_vars() {
698+
let (value, mapped_regions, mapped_types, mapped_consts) =
699+
BoundVarReplacer::replace_bound_vars(infcx, universe_indices, value);
700+
let result = f(value);
701+
PlaceholderReplacer::replace_placeholders(
702+
infcx,
703+
mapped_regions,
704+
mapped_types,
705+
mapped_consts,
706+
universe_indices,
707+
result,
708+
)
709+
} else {
710+
f(value)
711+
}
712+
}
713+
674714
impl<'me, 'tcx> BoundVarReplacer<'me, 'tcx> {
675715
/// Returns `Some` if we *were* able to replace bound vars. If there are any bound vars that
676716
/// use a binding level above `universe_indices.len()`, we fail.

compiler/rustc_trait_selection/src/traits/query/normalize.rs

+10-9
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::infer::at::At;
66
use crate::infer::canonical::OriginalQueryValues;
77
use crate::infer::{InferCtxt, InferOk};
88
use crate::traits::error_reporting::InferCtxtExt;
9-
use crate::traits::project::needs_normalization;
9+
use crate::traits::project::{needs_normalization, BoundVarReplacer, PlaceholderReplacer};
1010
use crate::traits::{Obligation, ObligationCause, PredicateObligation, Reveal};
1111
use rustc_data_structures::sso::SsoHashMap;
1212
use rustc_data_structures::stack::ensure_sufficient_stack;
@@ -283,11 +283,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
283283
let tcx = self.infcx.tcx;
284284
let infcx = self.infcx;
285285
let (data, mapped_regions, mapped_types, mapped_consts) =
286-
crate::traits::project::BoundVarReplacer::replace_bound_vars(
287-
infcx,
288-
&mut self.universes,
289-
data,
290-
);
286+
BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, data);
291287
let data = data.try_fold_with(self)?;
292288

293289
let mut orig_values = OriginalQueryValues::default();
@@ -313,8 +309,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
313309
debug!("QueryNormalizer: result = {:#?}", result);
314310
debug!("QueryNormalizer: obligations = {:#?}", obligations);
315311
self.obligations.extend(obligations);
316-
317-
let res = crate::traits::project::PlaceholderReplacer::replace_placeholders(
312+
let res = PlaceholderReplacer::replace_placeholders(
318313
infcx,
319314
mapped_regions,
320315
mapped_types,
@@ -343,7 +338,13 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
343338
constant: ty::Const<'tcx>,
344339
) -> Result<ty::Const<'tcx>, Self::Error> {
345340
let constant = constant.try_super_fold_with(self)?;
346-
Ok(constant.eval(self.infcx.tcx, self.param_env))
341+
debug!(?constant, ?self.param_env);
342+
Ok(crate::traits::project::with_replaced_escaping_bound_vars(
343+
self.infcx,
344+
&mut self.universes,
345+
constant,
346+
|constant| constant.eval(self.infcx.tcx, self.param_env),
347+
))
347348
}
348349

349350
fn try_fold_mir_const(

compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -495,13 +495,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
495495

496496
pub fn to_const(&self, ast_c: &hir::AnonConst) -> ty::Const<'tcx> {
497497
let const_def_id = self.tcx.hir().local_def_id(ast_c.hir_id);
498+
let span = self.tcx.hir().span(ast_c.hir_id);
498499
let c = ty::Const::from_anon_const(self.tcx, const_def_id);
499-
self.register_wf_obligation(
500-
c.into(),
501-
self.tcx.hir().span(ast_c.hir_id),
502-
ObligationCauseCode::WellFormed(None),
503-
);
504-
c
500+
self.register_wf_obligation(c.into(), span, ObligationCauseCode::WellFormed(None));
501+
self.normalize_associated_types_in(span, c)
505502
}
506503

507504
pub fn const_arg_to_const(

src/test/ui/closures/issue-52437.rs

-1
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,4 @@ fn main() {
22
[(); &(&'static: loop { |x| {}; }) as *const _ as usize]
33
//~^ ERROR: invalid label name `'static`
44
//~| ERROR: type annotations needed
5-
//~| ERROR mismatched types
65
}

src/test/ui/closures/issue-52437.stderr

+2-11
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,6 @@ help: consider giving this closure parameter an explicit type
1515
LL | [(); &(&'static: loop { |x: _| {}; }) as *const _ as usize]
1616
| +++
1717

18-
error[E0308]: mismatched types
19-
--> $DIR/issue-52437.rs:2:5
20-
|
21-
LL | fn main() {
22-
| - expected `()` because of default return type
23-
LL | [(); &(&'static: loop { |x| {}; }) as *const _ as usize]
24-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found array `[(); _]`
25-
26-
error: aborting due to 3 previous errors
18+
error: aborting due to 2 previous errors
2719

28-
Some errors have detailed explanations: E0282, E0308.
29-
For more information about an error, try `rustc --explain E0282`.
20+
For more information about this error, try `rustc --explain E0282`.

src/test/ui/issues/issue-66706.rs

-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ fn a() {
22
[0; [|_: _ &_| ()].len()]
33
//~^ ERROR expected `,`, found `&`
44
//~| ERROR type annotations needed
5-
//~| ERROR mismatched types
65
}
76

87
fn b() {
@@ -13,13 +12,11 @@ fn b() {
1312
fn c() {
1413
[0; [|&_: _ &_| {}; 0 ].len()]
1514
//~^ ERROR expected `,`, found `&`
16-
//~| ERROR mismatched types
1715
}
1816

1917
fn d() {
2018
[0; match [|f @ &ref _| () ] {} ]
2119
//~^ ERROR expected identifier, found reserved identifier `_`
22-
//~| ERROR mismatched types
2320
}
2421

2522
fn main() {}

src/test/ui/issues/issue-66706.stderr

+5-30
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,21 @@ LL | [0; [|_: _ &_| ()].len()]
77
| help: missing `,`
88

99
error: expected identifier, found reserved identifier `_`
10-
--> $DIR/issue-66706.rs:9:20
10+
--> $DIR/issue-66706.rs:8:20
1111
|
1212
LL | [0; [|f @ &ref _| {} ; 0 ].len() ];
1313
| ^ expected identifier, found reserved identifier
1414

1515
error: expected `,`, found `&`
16-
--> $DIR/issue-66706.rs:14:17
16+
--> $DIR/issue-66706.rs:13:17
1717
|
1818
LL | [0; [|&_: _ &_| {}; 0 ].len()]
1919
| -^ expected `,`
2020
| |
2121
| help: missing `,`
2222

2323
error: expected identifier, found reserved identifier `_`
24-
--> $DIR/issue-66706.rs:20:26
24+
--> $DIR/issue-66706.rs:18:26
2525
|
2626
LL | [0; match [|f @ &ref _| () ] {} ]
2727
| ^ expected identifier, found reserved identifier
@@ -32,31 +32,6 @@ error[E0282]: type annotations needed
3232
LL | [0; [|_: _ &_| ()].len()]
3333
| ^ cannot infer type
3434

35-
error[E0308]: mismatched types
36-
--> $DIR/issue-66706.rs:2:5
37-
|
38-
LL | fn a() {
39-
| - help: try adding a return type: `-> [i32; _]`
40-
LL | [0; [|_: _ &_| ()].len()]
41-
| ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found array `[{integer}; _]`
42-
43-
error[E0308]: mismatched types
44-
--> $DIR/issue-66706.rs:14:5
45-
|
46-
LL | fn c() {
47-
| - help: try adding a return type: `-> [i32; _]`
48-
LL | [0; [|&_: _ &_| {}; 0 ].len()]
49-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found array `[{integer}; _]`
50-
51-
error[E0308]: mismatched types
52-
--> $DIR/issue-66706.rs:20:5
53-
|
54-
LL | fn d() {
55-
| - help: try adding a return type: `-> [i32; _]`
56-
LL | [0; match [|f @ &ref _| () ] {} ]
57-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found array `[{integer}; _]`
58-
59-
error: aborting due to 8 previous errors
35+
error: aborting due to 5 previous errors
6036

61-
Some errors have detailed explanations: E0282, E0308.
62-
For more information about an error, try `rustc --explain E0282`.
37+
For more information about this error, try `rustc --explain E0282`.

0 commit comments

Comments
 (0)