don't ICE when normalizing closure input tys
`normalize_and_add_constraints` doesn't add entries in `universe_causes` when creating new universes, causing an ICE. Remove it! Add spans to track normalization constraints. Fix couple places where `universe_causes` is not updated correctly to track newly added universes.
This commit is contained in:
parent
ff40f2ec95
commit
fc3d7eb91d
6 changed files with 150 additions and 58 deletions
|
@ -52,11 +52,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
Some(error_info) => error_info.to_universe_info(old_universe),
|
Some(error_info) => error_info.to_universe_info(old_universe),
|
||||||
None => UniverseInfo::other(),
|
None => UniverseInfo::other(),
|
||||||
};
|
};
|
||||||
for u in old_universe..universe {
|
for u in (old_universe + 1)..=universe {
|
||||||
self.borrowck_context
|
self.borrowck_context.constraints.universe_causes.insert(u, universe_info.clone());
|
||||||
.constraints
|
|
||||||
.universe_causes
|
|
||||||
.insert(u + 1, universe_info.clone());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,15 +68,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
where
|
where
|
||||||
T: TypeFoldable<'tcx>,
|
T: TypeFoldable<'tcx>,
|
||||||
{
|
{
|
||||||
|
let old_universe = self.infcx.universe();
|
||||||
|
|
||||||
let (instantiated, _) =
|
let (instantiated, _) =
|
||||||
self.infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical);
|
self.infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical);
|
||||||
|
|
||||||
for u in 0..canonical.max_universe.as_u32() {
|
for u in (old_universe + 1)..=self.infcx.universe() {
|
||||||
let info = UniverseInfo::other();
|
self.borrowck_context.constraints.universe_causes.insert(u, UniverseInfo::other());
|
||||||
self.borrowck_context
|
|
||||||
.constraints
|
|
||||||
.universe_causes
|
|
||||||
.insert(ty::UniverseIndex::from_u32(u), info);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
instantiated
|
instantiated
|
||||||
|
|
|
@ -8,7 +8,6 @@ use rustc_infer::infer::InferCtxt;
|
||||||
use rustc_middle::mir::ConstraintCategory;
|
use rustc_middle::mir::ConstraintCategory;
|
||||||
use rustc_middle::traits::query::OutlivesBound;
|
use rustc_middle::traits::query::OutlivesBound;
|
||||||
use rustc_middle::ty::{self, RegionVid, Ty};
|
use rustc_middle::ty::{self, RegionVid, Ty};
|
||||||
use rustc_span::DUMMY_SP;
|
|
||||||
use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
|
use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use type_op::TypeOpOutput;
|
use type_op::TypeOpOutput;
|
||||||
|
@ -219,6 +218,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn create(mut self) -> CreateResult<'tcx> {
|
pub(crate) fn create(mut self) -> CreateResult<'tcx> {
|
||||||
|
let span = self.infcx.tcx.def_span(self.universal_regions.defining_ty.def_id());
|
||||||
let unnormalized_input_output_tys = self
|
let unnormalized_input_output_tys = self
|
||||||
.universal_regions
|
.universal_regions
|
||||||
.unnormalized_input_tys
|
.unnormalized_input_tys
|
||||||
|
@ -250,7 +250,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
||||||
self.infcx
|
self.infcx
|
||||||
.tcx
|
.tcx
|
||||||
.sess
|
.sess
|
||||||
.delay_span_bug(DUMMY_SP, &format!("failed to normalize {:?}", ty));
|
.delay_span_bug(span, &format!("failed to normalize {:?}", ty));
|
||||||
TypeOpOutput {
|
TypeOpOutput {
|
||||||
output: self.infcx.tcx.ty_error(),
|
output: self.infcx.tcx.ty_error(),
|
||||||
constraints: None,
|
constraints: None,
|
||||||
|
@ -301,8 +301,8 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
||||||
&self.region_bound_pairs,
|
&self.region_bound_pairs,
|
||||||
self.implicit_region_bound,
|
self.implicit_region_bound,
|
||||||
self.param_env,
|
self.param_env,
|
||||||
Locations::All(DUMMY_SP),
|
Locations::All(span),
|
||||||
DUMMY_SP,
|
span,
|
||||||
ConstraintCategory::Internal,
|
ConstraintCategory::Internal,
|
||||||
&mut self.constraints,
|
&mut self.constraints,
|
||||||
)
|
)
|
||||||
|
|
|
@ -7,16 +7,11 @@
|
||||||
//! `RETURN_PLACE` the MIR arguments) are always fully normalized (and
|
//! `RETURN_PLACE` the MIR arguments) are always fully normalized (and
|
||||||
//! contain revealed `impl Trait` values).
|
//! contain revealed `impl Trait` values).
|
||||||
|
|
||||||
use crate::type_check::constraint_conversion::ConstraintConversion;
|
|
||||||
use rustc_index::vec::Idx;
|
use rustc_index::vec::Idx;
|
||||||
use rustc_infer::infer::LateBoundRegionConversionTime;
|
use rustc_infer::infer::LateBoundRegionConversionTime;
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::ty::Ty;
|
use rustc_middle::ty::Ty;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use rustc_span::DUMMY_SP;
|
|
||||||
use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
|
|
||||||
use rustc_trait_selection::traits::query::Fallible;
|
|
||||||
use type_op::TypeOpOutput;
|
|
||||||
|
|
||||||
use crate::universal_regions::UniversalRegions;
|
use crate::universal_regions::UniversalRegions;
|
||||||
|
|
||||||
|
@ -185,7 +180,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(skip(self, span), level = "debug")]
|
#[instrument(skip(self), level = "debug")]
|
||||||
fn equate_normalized_input_or_output(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, span: Span) {
|
fn equate_normalized_input_or_output(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, span: Span) {
|
||||||
if let Err(_) =
|
if let Err(_) =
|
||||||
self.eq_types(a, b, Locations::All(span), ConstraintCategory::BoringNoLocation)
|
self.eq_types(a, b, Locations::All(span), ConstraintCategory::BoringNoLocation)
|
||||||
|
@ -194,13 +189,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
// `rustc_traits::normalize_after_erasing_regions`. Ideally, we'd
|
// `rustc_traits::normalize_after_erasing_regions`. Ideally, we'd
|
||||||
// like to normalize *before* inserting into `local_decls`, but
|
// like to normalize *before* inserting into `local_decls`, but
|
||||||
// doing so ends up causing some other trouble.
|
// doing so ends up causing some other trouble.
|
||||||
let b = match self.normalize_and_add_constraints(b) {
|
let b = self.normalize(b, Locations::All(span));
|
||||||
Ok(n) => n,
|
|
||||||
Err(_) => {
|
|
||||||
debug!("equate_inputs_and_outputs: NoSolution");
|
|
||||||
b
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Note: if we have to introduce new placeholders during normalization above, then we won't have
|
// Note: if we have to introduce new placeholders during normalization above, then we won't have
|
||||||
// added those universes to the universe info, which we would want in `relate_tys`.
|
// added those universes to the universe info, which we would want in `relate_tys`.
|
||||||
|
@ -218,28 +207,4 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn normalize_and_add_constraints(&mut self, t: Ty<'tcx>) -> Fallible<Ty<'tcx>> {
|
|
||||||
let TypeOpOutput { output: norm_ty, constraints, .. } =
|
|
||||||
self.param_env.and(type_op::normalize::Normalize::new(t)).fully_perform(self.infcx)?;
|
|
||||||
|
|
||||||
debug!("{:?} normalized to {:?}", t, norm_ty);
|
|
||||||
|
|
||||||
for data in constraints {
|
|
||||||
ConstraintConversion::new(
|
|
||||||
self.infcx,
|
|
||||||
&self.borrowck_context.universal_regions,
|
|
||||||
&self.region_bound_pairs,
|
|
||||||
self.implicit_region_bound,
|
|
||||||
self.param_env,
|
|
||||||
Locations::All(DUMMY_SP),
|
|
||||||
DUMMY_SP,
|
|
||||||
ConstraintCategory::Internal,
|
|
||||||
&mut self.borrowck_context.constraints,
|
|
||||||
)
|
|
||||||
.convert_all(&*data);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(norm_ty)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,8 +138,6 @@ pub(crate) fn type_check<'mir, 'tcx>(
|
||||||
use_polonius: bool,
|
use_polonius: bool,
|
||||||
) -> MirTypeckResults<'tcx> {
|
) -> MirTypeckResults<'tcx> {
|
||||||
let implicit_region_bound = infcx.tcx.mk_region(ty::ReVar(universal_regions.fr_fn_body));
|
let implicit_region_bound = infcx.tcx.mk_region(ty::ReVar(universal_regions.fr_fn_body));
|
||||||
let mut universe_causes = FxHashMap::default();
|
|
||||||
universe_causes.insert(ty::UniverseIndex::from_u32(0), UniverseInfo::other());
|
|
||||||
let mut constraints = MirTypeckRegionConstraints {
|
let mut constraints = MirTypeckRegionConstraints {
|
||||||
placeholder_indices: PlaceholderIndices::default(),
|
placeholder_indices: PlaceholderIndices::default(),
|
||||||
placeholder_index_to_region: IndexVec::default(),
|
placeholder_index_to_region: IndexVec::default(),
|
||||||
|
@ -148,7 +146,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
|
||||||
member_constraints: MemberConstraintSet::default(),
|
member_constraints: MemberConstraintSet::default(),
|
||||||
closure_bounds_mapping: Default::default(),
|
closure_bounds_mapping: Default::default(),
|
||||||
type_tests: Vec::default(),
|
type_tests: Vec::default(),
|
||||||
universe_causes,
|
universe_causes: FxHashMap::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let CreateResult {
|
let CreateResult {
|
||||||
|
@ -165,9 +163,8 @@ pub(crate) fn type_check<'mir, 'tcx>(
|
||||||
|
|
||||||
debug!(?normalized_inputs_and_output);
|
debug!(?normalized_inputs_and_output);
|
||||||
|
|
||||||
for u in ty::UniverseIndex::ROOT..infcx.universe() {
|
for u in ty::UniverseIndex::ROOT..=infcx.universe() {
|
||||||
let info = UniverseInfo::other();
|
constraints.universe_causes.insert(u, UniverseInfo::other());
|
||||||
constraints.universe_causes.insert(u, info);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut borrowck_context = BorrowCheckContext {
|
let mut borrowck_context = BorrowCheckContext {
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
// Regression test for #102800
|
||||||
|
//
|
||||||
|
// Here we are generating higher-ranked region constraints when normalizing and relating closure
|
||||||
|
// input types. Previously this was an ICE in the error path because we didn't register enough
|
||||||
|
// diagnostic information to render the higher-ranked subtyping error.
|
||||||
|
|
||||||
|
// check-fail
|
||||||
|
|
||||||
|
trait Trait {
|
||||||
|
type Ty;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Trait for &'static () {
|
||||||
|
type Ty = ();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
|
||||||
|
//~^ ERROR lifetime may not live long enough
|
||||||
|
//~| ERROR higher-ranked subtype error
|
||||||
|
//~| ERROR higher-ranked subtype error
|
||||||
|
//~| ERROR implementation of `Trait` is not general enough
|
||||||
|
//~| ERROR implementation of `Trait` is not general enough
|
||||||
|
//~| ERROR implementation of `Trait` is not general enough
|
||||||
|
//~| ERROR implementation of `Trait` is not general enough
|
||||||
|
//~| ERROR implementation of `Trait` is not general enough
|
||||||
|
//~| ERROR implementation of `Trait` is not general enough
|
||||||
|
//~| ERROR implementation of `Trait` is not general enough
|
||||||
|
//~| ERROR implementation of `Trait` is not general enough
|
||||||
|
//~| ERROR implementation of `Trait` is not general enough
|
||||||
|
}
|
|
@ -0,0 +1,104 @@
|
||||||
|
error: lifetime may not live long enough
|
||||||
|
--> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48
|
||||||
|
|
|
||||||
|
LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
|
||||||
|
| ^-^
|
||||||
|
| ||
|
||||||
|
| |has type `<&'1 () as Trait>::Ty`
|
||||||
|
| requires that `'1` must outlive `'static`
|
||||||
|
|
||||||
|
error: higher-ranked subtype error
|
||||||
|
--> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48
|
||||||
|
|
|
||||||
|
LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
|
||||||
|
| ^^^
|
||||||
|
|
||||||
|
error: higher-ranked subtype error
|
||||||
|
--> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48
|
||||||
|
|
|
||||||
|
LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
|
||||||
|
| ^^^
|
||||||
|
|
||||||
|
error: implementation of `Trait` is not general enough
|
||||||
|
--> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48
|
||||||
|
|
|
||||||
|
LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
|
||||||
|
| ^^^^^^ implementation of `Trait` is not general enough
|
||||||
|
|
|
||||||
|
= note: `&'0 ()` must implement `Trait`, for any lifetime `'0`...
|
||||||
|
= note: ...but `Trait` is actually implemented for the type `&'static ()`
|
||||||
|
|
||||||
|
error: implementation of `Trait` is not general enough
|
||||||
|
--> $DIR/closure-malformed-projection-input-issue-102800.rs:18:12
|
||||||
|
|
|
||||||
|
LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Trait` is not general enough
|
||||||
|
|
|
||||||
|
= note: `&'0 ()` must implement `Trait`, for any lifetime `'0`...
|
||||||
|
= note: ...but `Trait` is actually implemented for the type `&'static ()`
|
||||||
|
|
||||||
|
error: implementation of `Trait` is not general enough
|
||||||
|
--> $DIR/closure-malformed-projection-input-issue-102800.rs:18:12
|
||||||
|
|
|
||||||
|
LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Trait` is not general enough
|
||||||
|
|
|
||||||
|
= note: `&'0 ()` must implement `Trait`, for any lifetime `'0`...
|
||||||
|
= note: ...but `Trait` is actually implemented for the type `&'static ()`
|
||||||
|
|
||||||
|
error: implementation of `Trait` is not general enough
|
||||||
|
--> $DIR/closure-malformed-projection-input-issue-102800.rs:18:12
|
||||||
|
|
|
||||||
|
LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Trait` is not general enough
|
||||||
|
|
|
||||||
|
= note: `&'0 ()` must implement `Trait`, for any lifetime `'0`...
|
||||||
|
= note: ...but `Trait` is actually implemented for the type `&'static ()`
|
||||||
|
|
||||||
|
error: implementation of `Trait` is not general enough
|
||||||
|
--> $DIR/closure-malformed-projection-input-issue-102800.rs:18:12
|
||||||
|
|
|
||||||
|
LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Trait` is not general enough
|
||||||
|
|
|
||||||
|
= note: `&'0 ()` must implement `Trait`, for any lifetime `'0`...
|
||||||
|
= note: ...but `Trait` is actually implemented for the type `&'static ()`
|
||||||
|
|
||||||
|
error: implementation of `Trait` is not general enough
|
||||||
|
--> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48
|
||||||
|
|
|
||||||
|
LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
|
||||||
|
| ^^^^^^ implementation of `Trait` is not general enough
|
||||||
|
|
|
||||||
|
= note: `&'0 ()` must implement `Trait`, for any lifetime `'0`...
|
||||||
|
= note: ...but `Trait` is actually implemented for the type `&'static ()`
|
||||||
|
|
||||||
|
error: implementation of `Trait` is not general enough
|
||||||
|
--> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48
|
||||||
|
|
|
||||||
|
LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
|
||||||
|
| ^^^^^^ implementation of `Trait` is not general enough
|
||||||
|
|
|
||||||
|
= note: `&'0 ()` must implement `Trait`, for any lifetime `'0`...
|
||||||
|
= note: ...but `Trait` is actually implemented for the type `&'static ()`
|
||||||
|
|
||||||
|
error: implementation of `Trait` is not general enough
|
||||||
|
--> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48
|
||||||
|
|
|
||||||
|
LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
|
||||||
|
| ^^^^^^ implementation of `Trait` is not general enough
|
||||||
|
|
|
||||||
|
= note: `&'0 ()` must implement `Trait`, for any lifetime `'0`...
|
||||||
|
= note: ...but `Trait` is actually implemented for the type `&'static ()`
|
||||||
|
|
||||||
|
error: implementation of `Trait` is not general enough
|
||||||
|
--> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48
|
||||||
|
|
|
||||||
|
LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
|
||||||
|
| ^^^^^^ implementation of `Trait` is not general enough
|
||||||
|
|
|
||||||
|
= note: `&'0 ()` must implement `Trait`, for any lifetime `'0`...
|
||||||
|
= note: ...but `Trait` is actually implemented for the type `&'static ()`
|
||||||
|
|
||||||
|
error: aborting due to 12 previous errors
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue