Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

don't ICE when normalizing closure input tys #99818

Merged
merged 1 commit into from
Oct 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 6 additions & 11 deletions compiler/rustc_borrowck/src/type_check/canonical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
Some(error_info) => error_info.to_universe_info(old_universe),
None => UniverseInfo::other(),
};
for u in old_universe..universe {
self.borrowck_context
.constraints
.universe_causes
.insert(u + 1, universe_info.clone());
for u in (old_universe + 1)..=universe {
self.borrowck_context.constraints.universe_causes.insert(u, universe_info.clone());
}
}

Expand All @@ -71,15 +68,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
where
T: TypeFoldable<'tcx>,
{
let old_universe = self.infcx.universe();

let (instantiated, _) =
self.infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical);

for u in 0..canonical.max_universe.as_u32() {
let info = UniverseInfo::other();
self.borrowck_context
.constraints
.universe_causes
.insert(ty::UniverseIndex::from_u32(u), info);
for u in (old_universe + 1)..=self.infcx.universe() {
self.borrowck_context.constraints.universe_causes.insert(u, UniverseInfo::other());
}

instantiated
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use rustc_infer::infer::InferCtxt;
use rustc_middle::mir::ConstraintCategory;
use rustc_middle::traits::query::OutlivesBound;
use rustc_middle::ty::{self, RegionVid, Ty};
use rustc_span::DUMMY_SP;
use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
use std::rc::Rc;
use type_op::TypeOpOutput;
Expand Down Expand Up @@ -219,6 +218,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, '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
.universal_regions
.unnormalized_input_tys
Expand Down Expand Up @@ -250,7 +250,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
self.infcx
.tcx
.sess
.delay_span_bug(DUMMY_SP, &format!("failed to normalize {:?}", ty));
.delay_span_bug(span, &format!("failed to normalize {:?}", ty));
TypeOpOutput {
output: self.infcx.tcx.ty_error(),
constraints: None,
Expand Down Expand Up @@ -301,8 +301,8 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
&self.region_bound_pairs,
self.implicit_region_bound,
self.param_env,
Locations::All(DUMMY_SP),
DUMMY_SP,
Locations::All(span),
span,
ConstraintCategory::Internal,
&mut self.constraints,
)
Expand Down
39 changes: 2 additions & 37 deletions compiler/rustc_borrowck/src/type_check/input_output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,11 @@
//! `RETURN_PLACE` the MIR arguments) are always fully normalized (and
//! contain revealed `impl Trait` values).

use crate::type_check::constraint_conversion::ConstraintConversion;
use rustc_index::vec::Idx;
use rustc_infer::infer::LateBoundRegionConversionTime;
use rustc_middle::mir::*;
use rustc_middle::ty::Ty;
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;

Expand Down Expand Up @@ -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) {
if let Err(_) =
self.eq_types(a, b, Locations::All(span), ConstraintCategory::BoringNoLocation)
Expand All @@ -194,13 +189,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// `rustc_traits::normalize_after_erasing_regions`. Ideally, we'd
// like to normalize *before* inserting into `local_decls`, but
// doing so ends up causing some other trouble.
let b = match self.normalize_and_add_constraints(b) {
Ok(n) => n,
Err(_) => {
debug!("equate_inputs_and_outputs: NoSolution");
b
}
};
let b = self.normalize(b, Locations::All(span));

// 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`.
Expand All @@ -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)
}
}
9 changes: 3 additions & 6 deletions compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,6 @@ pub(crate) fn type_check<'mir, 'tcx>(
use_polonius: bool,
) -> MirTypeckResults<'tcx> {
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 {
placeholder_indices: PlaceholderIndices::default(),
placeholder_index_to_region: IndexVec::default(),
Expand All @@ -148,7 +146,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
member_constraints: MemberConstraintSet::default(),
closure_bounds_mapping: Default::default(),
type_tests: Vec::default(),
universe_causes,
universe_causes: FxHashMap::default(),
};

let CreateResult {
Expand All @@ -165,9 +163,8 @@ pub(crate) fn type_check<'mir, 'tcx>(

debug!(?normalized_inputs_and_output);

for u in ty::UniverseIndex::ROOT..infcx.universe() {
let info = UniverseInfo::other();
constraints.universe_causes.insert(u, info);
for u in ty::UniverseIndex::ROOT..=infcx.universe() {
constraints.universe_causes.insert(u, UniverseInfo::other());
}

let mut borrowck_context = BorrowCheckContext {
Expand Down
31 changes: 31 additions & 0 deletions src/test/ui/nll/closure-malformed-projection-input-issue-102800.rs
Original file line number Diff line number Diff line change
@@ -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
}
104 changes: 104 additions & 0 deletions src/test/ui/nll/closure-malformed-projection-input-issue-102800.stderr
Original file line number Diff line number Diff line change
@@ -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