Skip to content

Commit

Permalink
Rollup merge of rust-lang#99818 - aliemjay:fix-closure-normalize, r=e…
Browse files Browse the repository at this point in the history
…stebank

don't ICE when normalizing closure input tys

We were ICEing while rendering diagnostics because `universe_causes` is expected to track every universe created in the typeck's infcx.

`normalize_and_add_constraints` doesn't update `universe_causes`
when creating new universes, causing an ICE. Remove it!

Add spans to better track normalization constraints.

Fix couple places where `universe_causes` is not updated correctly to
track newly added universes.

Fixes rust-lang#99665
  • Loading branch information
Dylan-DPC authored Sep 2, 2022
2 parents a53e417 + 4eae7a1 commit aae7b23
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 58 deletions.
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 @@ -50,11 +50,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 @@ -69,15 +66,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 @@ -137,8 +137,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 @@ -147,7 +145,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 @@ -164,9 +162,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
52 changes: 52 additions & 0 deletions src/test/ui/nll/closure-malformed-projection-input-issue-99665.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Regression test for #99665
//
// Here we are generating region constraints
// when normalizing input types of the closure.

// check-fail

pub trait MyComponent {
type Properties;
}

struct Ty1<T>(T);
struct Ty2<T>(T);

impl<M> MyComponent for Ty1<M>
where
M: 'static,
{
type Properties = ();
}

impl<M> MyComponent for Ty2<M>
where
M: 'static,
{
type Properties = &'static M;
}

fn fail() {
// This should fail because `Ty1<&u8>` is inferred to be higher-ranked.
// So effectively we're trying to prove `for<'a> Ty1<&'a u8>: MyComponent`.
|_: <Ty1<&u8> as MyComponent>::Properties| {};
//~^ ERROR lifetime may not live long enough
//~| ERROR higher-ranked subtype error
//~| ERROR higher-ranked lifetime error
//~| ERROR higher-ranked lifetime error
//~| ERROR higher-ranked lifetime error

|_: <Ty2<&u8> as MyComponent>::Properties| {};
//~^ ERROR higher-ranked subtype error
//~| ERROR higher-ranked lifetime error
//~| ERROR higher-ranked lifetime error
//~| ERROR higher-ranked lifetime error
}

fn pass() {
// Here both are not higher-ranked, so they sould pass.
|| -> <Ty1<&u8> as MyComponent>::Properties { panic!() };
|| -> <Ty2<&u8> as MyComponent>::Properties { panic!() };
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
error: lifetime may not live long enough
--> $DIR/closure-malformed-projection-input-issue-99665.rs:32:5
|
LL | |_: <Ty1<&u8> as MyComponent>::Properties| {};
| ^-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ||
| |has type `<Ty1<&'1 u8> as MyComponent>::Properties`
| requires that `'1` must outlive `'static`

error: higher-ranked subtype error
--> $DIR/closure-malformed-projection-input-issue-99665.rs:32:5
|
LL | |_: <Ty1<&u8> as MyComponent>::Properties| {};
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: higher-ranked lifetime error
--> $DIR/closure-malformed-projection-input-issue-99665.rs:32:5
|
LL | |_: <Ty1<&u8> as MyComponent>::Properties| {};
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: could not normalize `&[closure@$DIR/closure-malformed-projection-input-issue-99665.rs:32:5: 32:47]`

error: higher-ranked subtype error
--> $DIR/closure-malformed-projection-input-issue-99665.rs:39:5
|
LL | |_: <Ty2<&u8> as MyComponent>::Properties| {};
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: higher-ranked lifetime error
--> $DIR/closure-malformed-projection-input-issue-99665.rs:39:5
|
LL | |_: <Ty2<&u8> as MyComponent>::Properties| {};
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: could not normalize `&[closure@$DIR/closure-malformed-projection-input-issue-99665.rs:39:5: 39:47]`

error: higher-ranked lifetime error
--> $DIR/closure-malformed-projection-input-issue-99665.rs:32:5
|
LL | |_: <Ty1<&u8> as MyComponent>::Properties| {};
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: could not normalize `[closure@$DIR/closure-malformed-projection-input-issue-99665.rs:32:5: 32:47]`

error: higher-ranked lifetime error
--> $DIR/closure-malformed-projection-input-issue-99665.rs:32:5
|
LL | |_: <Ty1<&u8> as MyComponent>::Properties| {};
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: could not normalize `[closure@$DIR/closure-malformed-projection-input-issue-99665.rs:32:5: 32:47]`

error: higher-ranked lifetime error
--> $DIR/closure-malformed-projection-input-issue-99665.rs:39:5
|
LL | |_: <Ty2<&u8> as MyComponent>::Properties| {};
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: could not normalize `[closure@$DIR/closure-malformed-projection-input-issue-99665.rs:39:5: 39:47]`

error: higher-ranked lifetime error
--> $DIR/closure-malformed-projection-input-issue-99665.rs:39:5
|
LL | |_: <Ty2<&u8> as MyComponent>::Properties| {};
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: could not normalize `[closure@$DIR/closure-malformed-projection-input-issue-99665.rs:39:5: 39:47]`

error: aborting due to 9 previous errors

0 comments on commit aae7b23

Please sign in to comment.