Skip to content

Commit e6c83d9

Browse files
Rollup merge of #104788 - compiler-errors:unresolved-ct-in-gen, r=fee1-dead
Do not record unresolved const vars in generator interior Don't record types in the generator interior when we see unresolved const variables. We already do this for associated types -- this is important to avoid unresolved inference variables in the generator results during writeback, since the writeback results get stable hashed in incremental mode. Fixes #104787
2 parents a2e485c + 6210812 commit e6c83d9

File tree

7 files changed

+173
-43
lines changed

7 files changed

+173
-43
lines changed

compiler/rustc_hir_typeck/src/generator_interior/mod.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,8 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
9898
expr, scope, ty, self.expr_count, yield_data.span
9999
);
100100

101-
if let Some((unresolved_type, unresolved_type_span)) =
102-
self.fcx.unresolved_type_vars(&ty)
101+
if let Some((unresolved_term, unresolved_type_span)) =
102+
self.fcx.first_unresolved_const_or_ty_var(&ty)
103103
{
104104
// If unresolved type isn't a ty_var then unresolved_type_span is None
105105
let span = self
@@ -108,21 +108,21 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
108108

109109
// If we encounter an int/float variable, then inference fallback didn't
110110
// finish due to some other error. Don't emit spurious additional errors.
111-
if let ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(_)) =
112-
unresolved_type.kind()
111+
if let Some(unresolved_ty) = unresolved_term.ty()
112+
&& let ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(_)) = unresolved_ty.kind()
113113
{
114114
self.fcx
115115
.tcx
116116
.sess
117-
.delay_span_bug(span, &format!("Encountered var {:?}", unresolved_type));
117+
.delay_span_bug(span, &format!("Encountered var {:?}", unresolved_term));
118118
} else {
119119
let note = format!(
120120
"the type is part of the {} because of this {}",
121121
self.kind, yield_data.source
122122
);
123123

124124
self.fcx
125-
.need_type_info_err_in_generator(self.kind, span, unresolved_type)
125+
.need_type_info_err_in_generator(self.kind, span, unresolved_term)
126126
.span_note(yield_data.span, &*note)
127127
.emit();
128128
}
@@ -162,7 +162,7 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
162162
expr.map(|e| e.span)
163163
);
164164
if let Some((unresolved_type, unresolved_type_span)) =
165-
self.fcx.unresolved_type_vars(&ty)
165+
self.fcx.first_unresolved_const_or_ty_var(&ty)
166166
{
167167
debug!(
168168
"remained unresolved_type = {:?}, unresolved_type_span: {:?}",

compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -568,7 +568,7 @@ impl<'tcx> InferCtxt<'tcx> {
568568
&self,
569569
kind: hir::GeneratorKind,
570570
span: Span,
571-
ty: Ty<'tcx>,
571+
ty: ty::Term<'tcx>,
572572
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
573573
let ty = self.resolve_vars_if_possible(ty);
574574
let data = self.extract_inference_diagnostics_data(ty.into(), None);

compiler/rustc_infer/src/infer/mod.rs

+6-7
Original file line numberDiff line numberDiff line change
@@ -1421,16 +1421,15 @@ impl<'tcx> InferCtxt<'tcx> {
14211421
value.fold_with(&mut r)
14221422
}
14231423

1424-
/// Returns the first unresolved variable contained in `T`. In the
1425-
/// process of visiting `T`, this will resolve (where possible)
1426-
/// type variables in `T`, but it never constructs the final,
1427-
/// resolved type, so it's more efficient than
1428-
/// `resolve_vars_if_possible()`.
1429-
pub fn unresolved_type_vars<T>(&self, value: &T) -> Option<(Ty<'tcx>, Option<Span>)>
1424+
/// Returns the first unresolved type or const variable contained in `T`.
1425+
pub fn first_unresolved_const_or_ty_var<T>(
1426+
&self,
1427+
value: &T,
1428+
) -> Option<(ty::Term<'tcx>, Option<Span>)>
14301429
where
14311430
T: TypeVisitable<'tcx>,
14321431
{
1433-
value.visit_with(&mut resolve::UnresolvedTypeFinder::new(self)).break_value()
1432+
value.visit_with(&mut resolve::UnresolvedTypeOrConstFinder::new(self)).break_value()
14341433
}
14351434

14361435
pub fn probe_const_var(

compiler/rustc_infer/src/infer/resolve.rs

+58-28
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
22
use super::{FixupError, FixupResult, InferCtxt, Span};
3+
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
34
use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFolder, TypeSuperFoldable};
45
use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitor};
56
use rustc_middle::ty::{self, Const, InferConst, Ty, TyCtxt, TypeFoldable, TypeVisitable};
@@ -110,48 +111,77 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticRegionResolver<'a, 'tcx> {
110111
/// type variables that don't yet have a value. The first unresolved type is stored.
111112
/// It does not construct the fully resolved type (which might
112113
/// involve some hashing and so forth).
113-
pub struct UnresolvedTypeFinder<'a, 'tcx> {
114+
pub struct UnresolvedTypeOrConstFinder<'a, 'tcx> {
114115
infcx: &'a InferCtxt<'tcx>,
115116
}
116117

117-
impl<'a, 'tcx> UnresolvedTypeFinder<'a, 'tcx> {
118+
impl<'a, 'tcx> UnresolvedTypeOrConstFinder<'a, 'tcx> {
118119
pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self {
119-
UnresolvedTypeFinder { infcx }
120+
UnresolvedTypeOrConstFinder { infcx }
120121
}
121122
}
122123

123-
impl<'a, 'tcx> TypeVisitor<'tcx> for UnresolvedTypeFinder<'a, 'tcx> {
124-
type BreakTy = (Ty<'tcx>, Option<Span>);
124+
impl<'a, 'tcx> TypeVisitor<'tcx> for UnresolvedTypeOrConstFinder<'a, 'tcx> {
125+
type BreakTy = (ty::Term<'tcx>, Option<Span>);
125126
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
126127
let t = self.infcx.shallow_resolve(t);
127-
if t.has_infer_types() {
128-
if let ty::Infer(infer_ty) = *t.kind() {
129-
// Since we called `shallow_resolve` above, this must
130-
// be an (as yet...) unresolved inference variable.
131-
let ty_var_span = if let ty::TyVar(ty_vid) = infer_ty {
132-
let mut inner = self.infcx.inner.borrow_mut();
133-
let ty_vars = &inner.type_variables();
134-
if let TypeVariableOrigin {
135-
kind: TypeVariableOriginKind::TypeParameterDefinition(_, _),
136-
span,
137-
} = *ty_vars.var_origin(ty_vid)
138-
{
139-
Some(span)
140-
} else {
141-
None
142-
}
128+
if let ty::Infer(infer_ty) = *t.kind() {
129+
// Since we called `shallow_resolve` above, this must
130+
// be an (as yet...) unresolved inference variable.
131+
let ty_var_span = if let ty::TyVar(ty_vid) = infer_ty {
132+
let mut inner = self.infcx.inner.borrow_mut();
133+
let ty_vars = &inner.type_variables();
134+
if let TypeVariableOrigin {
135+
kind: TypeVariableOriginKind::TypeParameterDefinition(_, _),
136+
span,
137+
} = *ty_vars.var_origin(ty_vid)
138+
{
139+
Some(span)
143140
} else {
144141
None
145-
};
146-
ControlFlow::Break((t, ty_var_span))
142+
}
147143
} else {
148-
// Otherwise, visit its contents.
149-
t.super_visit_with(self)
150-
}
144+
None
145+
};
146+
ControlFlow::Break((t.into(), ty_var_span))
147+
} else if !t.has_non_region_infer() {
148+
// All const/type variables in inference types must already be resolved,
149+
// no need to visit the contents.
150+
ControlFlow::CONTINUE
151151
} else {
152-
// All type variables in inference types must already be resolved,
153-
// - no need to visit the contents, continue visiting.
152+
// Otherwise, keep visiting.
153+
t.super_visit_with(self)
154+
}
155+
}
156+
157+
fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
158+
let ct = self.infcx.shallow_resolve(ct);
159+
if let ty::ConstKind::Infer(i) = ct.kind() {
160+
// Since we called `shallow_resolve` above, this must
161+
// be an (as yet...) unresolved inference variable.
162+
let ct_var_span = if let ty::InferConst::Var(vid) = i {
163+
let mut inner = self.infcx.inner.borrow_mut();
164+
let ct_vars = &mut inner.const_unification_table();
165+
if let ConstVariableOrigin {
166+
span,
167+
kind: ConstVariableOriginKind::ConstParameterDefinition(_, _),
168+
} = ct_vars.probe_value(vid).origin
169+
{
170+
Some(span)
171+
} else {
172+
None
173+
}
174+
} else {
175+
None
176+
};
177+
ControlFlow::Break((ct.into(), ct_var_span))
178+
} else if !ct.has_non_region_infer() {
179+
// All const/type variables in inference types must already be resolved,
180+
// no need to visit the contents.
154181
ControlFlow::CONTINUE
182+
} else {
183+
// Otherwise, keep visiting.
184+
ct.super_visit_with(self)
155185
}
156186
}
157187
}

compiler/rustc_middle/src/ty/subst.rs

+9
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,15 @@ impl<'tcx> From<ty::Const<'tcx>> for GenericArg<'tcx> {
140140
}
141141
}
142142

143+
impl<'tcx> From<ty::Term<'tcx>> for GenericArg<'tcx> {
144+
fn from(value: ty::Term<'tcx>) -> Self {
145+
match value.unpack() {
146+
ty::TermKind::Ty(t) => t.into(),
147+
ty::TermKind::Const(c) => c.into(),
148+
}
149+
}
150+
}
151+
143152
impl<'tcx> GenericArg<'tcx> {
144153
#[inline]
145154
pub fn unpack(self) -> GenericArgKind<'tcx> {
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// incremental
2+
// edition:2021
3+
4+
fn main() {
5+
let _ = async {
6+
let s = std::array::from_fn(|_| ()).await;
7+
//~^ ERROR `[(); _]` is not a future
8+
//~| ERROR type inside `async` block must be known in this context
9+
//~| ERROR type inside `async` block must be known in this context
10+
//~| ERROR type inside `async` block must be known in this context
11+
//~| ERROR type inside `async` block must be known in this context
12+
//~| ERROR type inside `async` block must be known in this context
13+
};
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
error[E0277]: `[(); _]` is not a future
2+
--> $DIR/unresolved-ct-var.rs:6:44
3+
|
4+
LL | let s = std::array::from_fn(|_| ()).await;
5+
| ---------------------------^^^^^^
6+
| | |
7+
| | `[(); _]` is not a future
8+
| | help: remove the `.await`
9+
| this call returns `[(); _]`
10+
|
11+
= help: the trait `Future` is not implemented for `[(); _]`
12+
= note: [(); _] must be a future or must implement `IntoFuture` to be awaited
13+
= note: required for `[(); _]` to implement `IntoFuture`
14+
15+
error[E0698]: type inside `async` block must be known in this context
16+
--> $DIR/unresolved-ct-var.rs:6:17
17+
|
18+
LL | let s = std::array::from_fn(|_| ()).await;
19+
| ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn`
20+
|
21+
note: the type is part of the `async` block because of this `await`
22+
--> $DIR/unresolved-ct-var.rs:6:44
23+
|
24+
LL | let s = std::array::from_fn(|_| ()).await;
25+
| ^^^^^^
26+
27+
error[E0698]: type inside `async` block must be known in this context
28+
--> $DIR/unresolved-ct-var.rs:6:17
29+
|
30+
LL | let s = std::array::from_fn(|_| ()).await;
31+
| ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn`
32+
|
33+
note: the type is part of the `async` block because of this `await`
34+
--> $DIR/unresolved-ct-var.rs:6:44
35+
|
36+
LL | let s = std::array::from_fn(|_| ()).await;
37+
| ^^^^^^
38+
39+
error[E0698]: type inside `async` block must be known in this context
40+
--> $DIR/unresolved-ct-var.rs:6:17
41+
|
42+
LL | let s = std::array::from_fn(|_| ()).await;
43+
| ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn`
44+
|
45+
note: the type is part of the `async` block because of this `await`
46+
--> $DIR/unresolved-ct-var.rs:6:44
47+
|
48+
LL | let s = std::array::from_fn(|_| ()).await;
49+
| ^^^^^^
50+
51+
error[E0698]: type inside `async` block must be known in this context
52+
--> $DIR/unresolved-ct-var.rs:6:17
53+
|
54+
LL | let s = std::array::from_fn(|_| ()).await;
55+
| ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn`
56+
|
57+
note: the type is part of the `async` block because of this `await`
58+
--> $DIR/unresolved-ct-var.rs:6:44
59+
|
60+
LL | let s = std::array::from_fn(|_| ()).await;
61+
| ^^^^^^
62+
63+
error[E0698]: type inside `async` block must be known in this context
64+
--> $DIR/unresolved-ct-var.rs:6:17
65+
|
66+
LL | let s = std::array::from_fn(|_| ()).await;
67+
| ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn`
68+
|
69+
note: the type is part of the `async` block because of this `await`
70+
--> $DIR/unresolved-ct-var.rs:6:44
71+
|
72+
LL | let s = std::array::from_fn(|_| ()).await;
73+
| ^^^^^^
74+
75+
error: aborting due to 6 previous errors
76+
77+
Some errors have detailed explanations: E0277, E0698.
78+
For more information about an error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)