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
|
||||
/// the constraint to set it equal to one of the option regions.
|
||||
/// 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")]
|
||||
fn apply_member_constraint(
|
||||
&mut self,
|
||||
scc: ConstraintSccIndex,
|
||||
member_constraint_index: NllMemberConstraintIndex,
|
||||
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
|
||||
// them down.
|
||||
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];
|
||||
}
|
||||
|
||||
// The 'member region' in a member constraint is part of the
|
||||
// hidden type, which must be in the root universe. Therefore,
|
||||
// it cannot have any placeholders in its value.
|
||||
assert!(self.scc_universes[scc] == ty::UniverseIndex::ROOT);
|
||||
// If the member region lives in a higher universe, we currently choose
|
||||
// the most conservative option by leaving it unchanged.
|
||||
if self.scc_universes[scc] != ty::UniverseIndex::ROOT {
|
||||
return;
|
||||
}
|
||||
debug_assert!(
|
||||
self.scc_values.placeholders_contained_in(scc).next().is_none(),
|
||||
"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:
|
||||
// R0`). Therefore, we need only keep an option `O` if `UB: O`
|
||||
// for all UB.
|
||||
self.compute_reverse_scc_graph();
|
||||
let universal_region_relations = &self.universal_region_relations;
|
||||
for ub in self.rev_scc_graph.as_ref().unwrap().upper_bounds(scc) {
|
||||
debug!(?ub);
|
||||
@ -867,7 +874,7 @@ fn apply_member_constraint(
|
||||
}
|
||||
}) else {
|
||||
debug!("no unique minimum choice");
|
||||
return false;
|
||||
return;
|
||||
};
|
||||
|
||||
let min_choice_scc = self.constraint_sccs.scc(min_choice);
|
||||
@ -878,10 +885,6 @@ fn apply_member_constraint(
|
||||
min_choice,
|
||||
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 {
|
||||
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
|
||||
let upper_bound = self.approx_universal_upper_bound(vid);
|
||||
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(_) => {
|
||||
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