Do not record unresolved const vars in generator interior
This commit is contained in:
parent
aff003becd
commit
6210812494
@ -98,8 +98,8 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
|
||||
expr, scope, ty, self.expr_count, yield_data.span
|
||||
);
|
||||
|
||||
if let Some((unresolved_type, unresolved_type_span)) =
|
||||
self.fcx.unresolved_type_vars(&ty)
|
||||
if let Some((unresolved_term, unresolved_type_span)) =
|
||||
self.fcx.first_unresolved_const_or_ty_var(&ty)
|
||||
{
|
||||
// If unresolved type isn't a ty_var then unresolved_type_span is None
|
||||
let span = self
|
||||
@ -108,13 +108,13 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
|
||||
|
||||
// If we encounter an int/float variable, then inference fallback didn't
|
||||
// finish due to some other error. Don't emit spurious additional errors.
|
||||
if let ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(_)) =
|
||||
unresolved_type.kind()
|
||||
if let Some(unresolved_ty) = unresolved_term.ty()
|
||||
&& let ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(_)) = unresolved_ty.kind()
|
||||
{
|
||||
self.fcx
|
||||
.tcx
|
||||
.sess
|
||||
.delay_span_bug(span, &format!("Encountered var {:?}", unresolved_type));
|
||||
.delay_span_bug(span, &format!("Encountered var {:?}", unresolved_term));
|
||||
} else {
|
||||
let note = format!(
|
||||
"the type is part of the {} because of this {}",
|
||||
@ -122,7 +122,7 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
|
||||
);
|
||||
|
||||
self.fcx
|
||||
.need_type_info_err_in_generator(self.kind, span, unresolved_type)
|
||||
.need_type_info_err_in_generator(self.kind, span, unresolved_term)
|
||||
.span_note(yield_data.span, &*note)
|
||||
.emit();
|
||||
}
|
||||
@ -162,7 +162,7 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
|
||||
expr.map(|e| e.span)
|
||||
);
|
||||
if let Some((unresolved_type, unresolved_type_span)) =
|
||||
self.fcx.unresolved_type_vars(&ty)
|
||||
self.fcx.first_unresolved_const_or_ty_var(&ty)
|
||||
{
|
||||
debug!(
|
||||
"remained unresolved_type = {:?}, unresolved_type_span: {:?}",
|
||||
|
@ -571,7 +571,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
&self,
|
||||
kind: hir::GeneratorKind,
|
||||
span: Span,
|
||||
ty: Ty<'tcx>,
|
||||
ty: ty::Term<'tcx>,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
let ty = self.resolve_vars_if_possible(ty);
|
||||
let data = self.extract_inference_diagnostics_data(ty.into(), None);
|
||||
|
@ -1421,16 +1421,15 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
value.fold_with(&mut r)
|
||||
}
|
||||
|
||||
/// Returns the first unresolved variable contained in `T`. In the
|
||||
/// process of visiting `T`, this will resolve (where possible)
|
||||
/// type variables in `T`, but it never constructs the final,
|
||||
/// resolved type, so it's more efficient than
|
||||
/// `resolve_vars_if_possible()`.
|
||||
pub fn unresolved_type_vars<T>(&self, value: &T) -> Option<(Ty<'tcx>, Option<Span>)>
|
||||
/// Returns the first unresolved type or const variable contained in `T`.
|
||||
pub fn first_unresolved_const_or_ty_var<T>(
|
||||
&self,
|
||||
value: &T,
|
||||
) -> Option<(ty::Term<'tcx>, Option<Span>)>
|
||||
where
|
||||
T: TypeVisitable<'tcx>,
|
||||
{
|
||||
value.visit_with(&mut resolve::UnresolvedTypeFinder::new(self)).break_value()
|
||||
value.visit_with(&mut resolve::UnresolvedTypeOrConstFinder::new(self)).break_value()
|
||||
}
|
||||
|
||||
pub fn probe_const_var(
|
||||
|
@ -1,5 +1,6 @@
|
||||
use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use super::{FixupError, FixupResult, InferCtxt, Span};
|
||||
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
|
||||
use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFolder, TypeSuperFoldable};
|
||||
use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitor};
|
||||
use rustc_middle::ty::{self, Const, InferConst, Ty, TyCtxt, TypeFoldable, TypeVisitable};
|
||||
@ -110,48 +111,77 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticRegionResolver<'a, 'tcx> {
|
||||
/// type variables that don't yet have a value. The first unresolved type is stored.
|
||||
/// It does not construct the fully resolved type (which might
|
||||
/// involve some hashing and so forth).
|
||||
pub struct UnresolvedTypeFinder<'a, 'tcx> {
|
||||
pub struct UnresolvedTypeOrConstFinder<'a, 'tcx> {
|
||||
infcx: &'a InferCtxt<'tcx>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> UnresolvedTypeFinder<'a, 'tcx> {
|
||||
impl<'a, 'tcx> UnresolvedTypeOrConstFinder<'a, 'tcx> {
|
||||
pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self {
|
||||
UnresolvedTypeFinder { infcx }
|
||||
UnresolvedTypeOrConstFinder { infcx }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> TypeVisitor<'tcx> for UnresolvedTypeFinder<'a, 'tcx> {
|
||||
type BreakTy = (Ty<'tcx>, Option<Span>);
|
||||
impl<'a, 'tcx> TypeVisitor<'tcx> for UnresolvedTypeOrConstFinder<'a, 'tcx> {
|
||||
type BreakTy = (ty::Term<'tcx>, Option<Span>);
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
let t = self.infcx.shallow_resolve(t);
|
||||
if t.has_infer_types() {
|
||||
if let ty::Infer(infer_ty) = *t.kind() {
|
||||
// Since we called `shallow_resolve` above, this must
|
||||
// be an (as yet...) unresolved inference variable.
|
||||
let ty_var_span = if let ty::TyVar(ty_vid) = infer_ty {
|
||||
let mut inner = self.infcx.inner.borrow_mut();
|
||||
let ty_vars = &inner.type_variables();
|
||||
if let TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::TypeParameterDefinition(_, _),
|
||||
span,
|
||||
} = *ty_vars.var_origin(ty_vid)
|
||||
{
|
||||
Some(span)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
if let ty::Infer(infer_ty) = *t.kind() {
|
||||
// Since we called `shallow_resolve` above, this must
|
||||
// be an (as yet...) unresolved inference variable.
|
||||
let ty_var_span = if let ty::TyVar(ty_vid) = infer_ty {
|
||||
let mut inner = self.infcx.inner.borrow_mut();
|
||||
let ty_vars = &inner.type_variables();
|
||||
if let TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::TypeParameterDefinition(_, _),
|
||||
span,
|
||||
} = *ty_vars.var_origin(ty_vid)
|
||||
{
|
||||
Some(span)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
ControlFlow::Break((t, ty_var_span))
|
||||
}
|
||||
} else {
|
||||
// Otherwise, visit its contents.
|
||||
t.super_visit_with(self)
|
||||
}
|
||||
} else {
|
||||
// All type variables in inference types must already be resolved,
|
||||
// - no need to visit the contents, continue visiting.
|
||||
None
|
||||
};
|
||||
ControlFlow::Break((t.into(), ty_var_span))
|
||||
} else if !t.has_non_region_infer() {
|
||||
// All const/type variables in inference types must already be resolved,
|
||||
// no need to visit the contents.
|
||||
ControlFlow::CONTINUE
|
||||
} else {
|
||||
// Otherwise, keep visiting.
|
||||
t.super_visit_with(self)
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
let ct = self.infcx.shallow_resolve(ct);
|
||||
if let ty::ConstKind::Infer(i) = ct.kind() {
|
||||
// Since we called `shallow_resolve` above, this must
|
||||
// be an (as yet...) unresolved inference variable.
|
||||
let ct_var_span = if let ty::InferConst::Var(vid) = i {
|
||||
let mut inner = self.infcx.inner.borrow_mut();
|
||||
let ct_vars = &mut inner.const_unification_table();
|
||||
if let ConstVariableOrigin {
|
||||
span,
|
||||
kind: ConstVariableOriginKind::ConstParameterDefinition(_, _),
|
||||
} = ct_vars.probe_value(vid).origin
|
||||
{
|
||||
Some(span)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
ControlFlow::Break((ct.into(), ct_var_span))
|
||||
} else if !ct.has_non_region_infer() {
|
||||
// All const/type variables in inference types must already be resolved,
|
||||
// no need to visit the contents.
|
||||
ControlFlow::CONTINUE
|
||||
} else {
|
||||
// Otherwise, keep visiting.
|
||||
ct.super_visit_with(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -140,6 +140,15 @@ impl<'tcx> From<ty::Const<'tcx>> for GenericArg<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> From<ty::Term<'tcx>> for GenericArg<'tcx> {
|
||||
fn from(value: ty::Term<'tcx>) -> Self {
|
||||
match value.unpack() {
|
||||
ty::TermKind::Ty(t) => t.into(),
|
||||
ty::TermKind::Const(c) => c.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> GenericArg<'tcx> {
|
||||
#[inline]
|
||||
pub fn unpack(self) -> GenericArgKind<'tcx> {
|
||||
|
14
src/test/ui/generator/unresolved-ct-var.rs
Normal file
14
src/test/ui/generator/unresolved-ct-var.rs
Normal file
@ -0,0 +1,14 @@
|
||||
// incremental
|
||||
// edition:2021
|
||||
|
||||
fn main() {
|
||||
let _ = async {
|
||||
let s = std::array::from_fn(|_| ()).await;
|
||||
//~^ ERROR `[(); _]` is not a future
|
||||
//~| ERROR type inside `async` block must be known in this context
|
||||
//~| ERROR type inside `async` block must be known in this context
|
||||
//~| ERROR type inside `async` block must be known in this context
|
||||
//~| ERROR type inside `async` block must be known in this context
|
||||
//~| ERROR type inside `async` block must be known in this context
|
||||
};
|
||||
}
|
78
src/test/ui/generator/unresolved-ct-var.stderr
Normal file
78
src/test/ui/generator/unresolved-ct-var.stderr
Normal file
@ -0,0 +1,78 @@
|
||||
error[E0277]: `[(); _]` is not a future
|
||||
--> $DIR/unresolved-ct-var.rs:6:44
|
||||
|
|
||||
LL | let s = std::array::from_fn(|_| ()).await;
|
||||
| ---------------------------^^^^^^
|
||||
| | |
|
||||
| | `[(); _]` is not a future
|
||||
| | help: remove the `.await`
|
||||
| this call returns `[(); _]`
|
||||
|
|
||||
= help: the trait `Future` is not implemented for `[(); _]`
|
||||
= note: [(); _] must be a future or must implement `IntoFuture` to be awaited
|
||||
= note: required for `[(); _]` to implement `IntoFuture`
|
||||
|
||||
error[E0698]: type inside `async` block must be known in this context
|
||||
--> $DIR/unresolved-ct-var.rs:6:17
|
||||
|
|
||||
LL | let s = std::array::from_fn(|_| ()).await;
|
||||
| ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn`
|
||||
|
|
||||
note: the type is part of the `async` block because of this `await`
|
||||
--> $DIR/unresolved-ct-var.rs:6:44
|
||||
|
|
||||
LL | let s = std::array::from_fn(|_| ()).await;
|
||||
| ^^^^^^
|
||||
|
||||
error[E0698]: type inside `async` block must be known in this context
|
||||
--> $DIR/unresolved-ct-var.rs:6:17
|
||||
|
|
||||
LL | let s = std::array::from_fn(|_| ()).await;
|
||||
| ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn`
|
||||
|
|
||||
note: the type is part of the `async` block because of this `await`
|
||||
--> $DIR/unresolved-ct-var.rs:6:44
|
||||
|
|
||||
LL | let s = std::array::from_fn(|_| ()).await;
|
||||
| ^^^^^^
|
||||
|
||||
error[E0698]: type inside `async` block must be known in this context
|
||||
--> $DIR/unresolved-ct-var.rs:6:17
|
||||
|
|
||||
LL | let s = std::array::from_fn(|_| ()).await;
|
||||
| ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn`
|
||||
|
|
||||
note: the type is part of the `async` block because of this `await`
|
||||
--> $DIR/unresolved-ct-var.rs:6:44
|
||||
|
|
||||
LL | let s = std::array::from_fn(|_| ()).await;
|
||||
| ^^^^^^
|
||||
|
||||
error[E0698]: type inside `async` block must be known in this context
|
||||
--> $DIR/unresolved-ct-var.rs:6:17
|
||||
|
|
||||
LL | let s = std::array::from_fn(|_| ()).await;
|
||||
| ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn`
|
||||
|
|
||||
note: the type is part of the `async` block because of this `await`
|
||||
--> $DIR/unresolved-ct-var.rs:6:44
|
||||
|
|
||||
LL | let s = std::array::from_fn(|_| ()).await;
|
||||
| ^^^^^^
|
||||
|
||||
error[E0698]: type inside `async` block must be known in this context
|
||||
--> $DIR/unresolved-ct-var.rs:6:17
|
||||
|
|
||||
LL | let s = std::array::from_fn(|_| ()).await;
|
||||
| ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn`
|
||||
|
|
||||
note: the type is part of the `async` block because of this `await`
|
||||
--> $DIR/unresolved-ct-var.rs:6:44
|
||||
|
|
||||
LL | let s = std::array::from_fn(|_| ()).await;
|
||||
| ^^^^^^
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0698.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
Loading…
x
Reference in New Issue
Block a user