Auto merge of #113575 - aliemjay:opaque-hrtb-ice, r=lcnr
don't ICE on higher ranked hidden types This shouldn't allow more code to compile, only replaces the ICE with a nicer error message. Fixes https://github.com/rust-lang/rust/issues/97098. Fixes https://github.com/rust-lang/rust/issues/97099. Fixes #108399 Fixes #104196 Fixes #113481 Fixes #103186 Fixes #100818 r? `@lcnr` (because you showed interest in #100503 :)
This commit is contained in:
commit
03181e0547
@ -784,13 +784,20 @@ fn compute_value_for_scc(&mut self, scc_a: ConstraintSccIndex) {
|
|||||||
/// is considered a *lower bound*. If possible, we will modify
|
/// is considered a *lower bound*. If possible, we will modify
|
||||||
/// the constraint to set it equal to one of the option regions.
|
/// the constraint to set it equal to one of the option regions.
|
||||||
/// If we make any changes, returns true, else false.
|
/// If we make any changes, returns true, else false.
|
||||||
|
///
|
||||||
|
/// This function only adds the member constraints to the region graph,
|
||||||
|
/// it does not check them. They are later checked in
|
||||||
|
/// `check_member_constraints` after the region graph has been computed.
|
||||||
#[instrument(skip(self, member_constraint_index), level = "debug")]
|
#[instrument(skip(self, member_constraint_index), level = "debug")]
|
||||||
fn apply_member_constraint(
|
fn apply_member_constraint(
|
||||||
&mut self,
|
&mut self,
|
||||||
scc: ConstraintSccIndex,
|
scc: ConstraintSccIndex,
|
||||||
member_constraint_index: NllMemberConstraintIndex,
|
member_constraint_index: NllMemberConstraintIndex,
|
||||||
choice_regions: &[ty::RegionVid],
|
choice_regions: &[ty::RegionVid],
|
||||||
) -> bool {
|
) {
|
||||||
|
// Lazily compute the reverse graph, we'll need it later.
|
||||||
|
self.compute_reverse_scc_graph();
|
||||||
|
|
||||||
// Create a mutable vector of the options. We'll try to winnow
|
// Create a mutable vector of the options. We'll try to winnow
|
||||||
// them down.
|
// them down.
|
||||||
let mut choice_regions: Vec<ty::RegionVid> = choice_regions.to_vec();
|
let mut choice_regions: Vec<ty::RegionVid> = choice_regions.to_vec();
|
||||||
@ -805,10 +812,11 @@ fn apply_member_constraint(
|
|||||||
*c_r = self.scc_representatives[scc];
|
*c_r = self.scc_representatives[scc];
|
||||||
}
|
}
|
||||||
|
|
||||||
// The 'member region' in a member constraint is part of the
|
// If the member region lives in a higher universe, we currently choose
|
||||||
// hidden type, which must be in the root universe. Therefore,
|
// the most conservative option by leaving it unchanged.
|
||||||
// it cannot have any placeholders in its value.
|
if self.scc_universes[scc] != ty::UniverseIndex::ROOT {
|
||||||
assert!(self.scc_universes[scc] == ty::UniverseIndex::ROOT);
|
return;
|
||||||
|
}
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
self.scc_values.placeholders_contained_in(scc).next().is_none(),
|
self.scc_values.placeholders_contained_in(scc).next().is_none(),
|
||||||
"scc {:?} in a member constraint has placeholder value: {:?}",
|
"scc {:?} in a member constraint has placeholder value: {:?}",
|
||||||
@ -832,7 +840,6 @@ fn apply_member_constraint(
|
|||||||
// free region that must outlive the member region `R0` (`UB:
|
// free region that must outlive the member region `R0` (`UB:
|
||||||
// R0`). Therefore, we need only keep an option `O` if `UB: O`
|
// R0`). Therefore, we need only keep an option `O` if `UB: O`
|
||||||
// for all UB.
|
// for all UB.
|
||||||
self.compute_reverse_scc_graph();
|
|
||||||
let universal_region_relations = &self.universal_region_relations;
|
let universal_region_relations = &self.universal_region_relations;
|
||||||
for ub in self.rev_scc_graph.as_ref().unwrap().upper_bounds(scc) {
|
for ub in self.rev_scc_graph.as_ref().unwrap().upper_bounds(scc) {
|
||||||
debug!(?ub);
|
debug!(?ub);
|
||||||
@ -867,7 +874,7 @@ fn apply_member_constraint(
|
|||||||
}
|
}
|
||||||
}) else {
|
}) else {
|
||||||
debug!("no unique minimum choice");
|
debug!("no unique minimum choice");
|
||||||
return false;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let min_choice_scc = self.constraint_sccs.scc(min_choice);
|
let min_choice_scc = self.constraint_sccs.scc(min_choice);
|
||||||
@ -878,10 +885,6 @@ fn apply_member_constraint(
|
|||||||
min_choice,
|
min_choice,
|
||||||
member_constraint_index,
|
member_constraint_index,
|
||||||
});
|
});
|
||||||
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,6 +185,21 @@ pub(crate) fn name_regions<T>(&self, tcx: TyCtxt<'tcx>, ty: T) -> T
|
|||||||
{
|
{
|
||||||
tcx.fold_regions(ty, |region, _| match *region {
|
tcx.fold_regions(ty, |region, _| match *region {
|
||||||
ty::ReVar(vid) => {
|
ty::ReVar(vid) => {
|
||||||
|
let scc = self.constraint_sccs.scc(vid);
|
||||||
|
|
||||||
|
// Special handling of higher-ranked regions.
|
||||||
|
if self.scc_universes[scc] != ty::UniverseIndex::ROOT {
|
||||||
|
match self.scc_values.placeholders_contained_in(scc).enumerate().last() {
|
||||||
|
// If the region contains a single placeholder then they're equal.
|
||||||
|
Some((0, placeholder)) => {
|
||||||
|
return ty::Region::new_placeholder(tcx, placeholder);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback: this will produce a cryptic error message.
|
||||||
|
_ => return region,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Find something that we can name
|
// Find something that we can name
|
||||||
let upper_bound = self.approx_universal_upper_bound(vid);
|
let upper_bound = self.approx_universal_upper_bound(vid);
|
||||||
let upper_bound = &self.definitions[upper_bound];
|
let upper_bound = &self.definitions[upper_bound];
|
||||||
|
@ -351,6 +351,15 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ty::RePlaceholder(_) => {
|
||||||
|
explain_free_region(
|
||||||
|
tcx,
|
||||||
|
&mut err,
|
||||||
|
&format!("hidden type `{}` captures ", hidden_ty),
|
||||||
|
hidden_region,
|
||||||
|
"",
|
||||||
|
);
|
||||||
|
}
|
||||||
ty::ReError(_) => {
|
ty::ReError(_) => {
|
||||||
err.delay_as_bug();
|
err.delay_as_bug();
|
||||||
}
|
}
|
||||||
|
9
tests/ui/impl-trait/nested-rpit-hrtb-2.rs
Normal file
9
tests/ui/impl-trait/nested-rpit-hrtb-2.rs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
// The nested impl Trait references a higher-ranked region
|
||||||
|
|
||||||
|
trait Trait<'a> { type Assoc; }
|
||||||
|
impl<'a> Trait<'a> for () { type Assoc = &'a str; }
|
||||||
|
|
||||||
|
fn test() -> impl for<'a> Trait<'a, Assoc = impl Sized> {}
|
||||||
|
//~^ ERROR captures lifetime that does not appear in bounds
|
||||||
|
|
||||||
|
fn main() {}
|
12
tests/ui/impl-trait/nested-rpit-hrtb-2.stderr
Normal file
12
tests/ui/impl-trait/nested-rpit-hrtb-2.stderr
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds
|
||||||
|
--> $DIR/nested-rpit-hrtb-2.rs:6:57
|
||||||
|
|
|
||||||
|
LL | fn test() -> impl for<'a> Trait<'a, Assoc = impl Sized> {}
|
||||||
|
| -- ---------- ^^
|
||||||
|
| | |
|
||||||
|
| | opaque type defined here
|
||||||
|
| hidden type `&'a str` captures the lifetime `'a` as defined here
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0700`.
|
15
tests/ui/type-alias-impl-trait/nested-tait-hrtb.rs
Normal file
15
tests/ui/type-alias-impl-trait/nested-tait-hrtb.rs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
|
trait Trait<'a> { type Assoc; }
|
||||||
|
impl<'a> Trait<'a> for () { type Assoc = &'a str; }
|
||||||
|
|
||||||
|
type WithoutLt = impl Sized;
|
||||||
|
fn without_lt() -> impl for<'a> Trait<'a, Assoc = WithoutLt> {}
|
||||||
|
//~^ ERROR captures lifetime that does not appear in bounds
|
||||||
|
|
||||||
|
type WithLt<'a> = impl Sized + 'a;
|
||||||
|
//~^ ERROR concrete type differs from previous defining opaque type use
|
||||||
|
fn with_lt() -> impl for<'a> Trait<'a, Assoc = WithLt<'a>> {}
|
||||||
|
//~^ ERROR expected generic lifetime parameter, found `'a`
|
||||||
|
|
||||||
|
fn main() {}
|
35
tests/ui/type-alias-impl-trait/nested-tait-hrtb.stderr
Normal file
35
tests/ui/type-alias-impl-trait/nested-tait-hrtb.stderr
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
error[E0700]: hidden type for `WithoutLt` captures lifetime that does not appear in bounds
|
||||||
|
--> $DIR/nested-tait-hrtb.rs:7:62
|
||||||
|
|
|
||||||
|
LL | type WithoutLt = impl Sized;
|
||||||
|
| ---------- opaque type defined here
|
||||||
|
LL | fn without_lt() -> impl for<'a> Trait<'a, Assoc = WithoutLt> {}
|
||||||
|
| -- ^^
|
||||||
|
| |
|
||||||
|
| hidden type `&'a str` captures the lifetime `'a` as defined here
|
||||||
|
|
||||||
|
error[E0792]: expected generic lifetime parameter, found `'a`
|
||||||
|
--> $DIR/nested-tait-hrtb.rs:12:60
|
||||||
|
|
|
||||||
|
LL | type WithLt<'a> = impl Sized + 'a;
|
||||||
|
| -- this generic parameter must be used with a generic lifetime parameter
|
||||||
|
LL |
|
||||||
|
LL | fn with_lt() -> impl for<'a> Trait<'a, Assoc = WithLt<'a>> {}
|
||||||
|
| ^^
|
||||||
|
|
||||||
|
error: concrete type differs from previous defining opaque type use
|
||||||
|
--> $DIR/nested-tait-hrtb.rs:10:19
|
||||||
|
|
|
||||||
|
LL | type WithLt<'a> = impl Sized + 'a;
|
||||||
|
| ^^^^^^^^^^^^^^^ expected `&'a str`, got `{type error}`
|
||||||
|
|
|
||||||
|
note: previous use here
|
||||||
|
--> $DIR/nested-tait-hrtb.rs:12:17
|
||||||
|
|
|
||||||
|
LL | fn with_lt() -> impl for<'a> Trait<'a, Assoc = WithLt<'a>> {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0700, E0792.
|
||||||
|
For more information about an error, try `rustc --explain E0700`.
|
Loading…
Reference in New Issue
Block a user