Check that RPITs are compatible with the opaques inferred during HIR typeck too
This commit is contained in:
parent
3d09b990d7
commit
df1c1afdaf
7 changed files with 46 additions and 155 deletions
|
@ -1,3 +1,4 @@
|
||||||
|
use rustc_errors::StashKey;
|
||||||
use rustc_hir::def_id::LocalDefId;
|
use rustc_hir::def_id::LocalDefId;
|
||||||
use rustc_hir::intravisit::{self, Visitor};
|
use rustc_hir::intravisit::{self, Visitor};
|
||||||
use rustc_hir::{self as hir, Expr, ImplItem, Item, Node, TraitItem};
|
use rustc_hir::{self as hir, Expr, ImplItem, Item, Node, TraitItem};
|
||||||
|
@ -210,12 +211,40 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>(
|
||||||
def_id: LocalDefId,
|
def_id: LocalDefId,
|
||||||
owner_def_id: LocalDefId,
|
owner_def_id: LocalDefId,
|
||||||
) -> Ty<'_> {
|
) -> Ty<'_> {
|
||||||
let concrete = tcx.mir_borrowck(owner_def_id).concrete_opaque_types.get(&def_id).copied();
|
let tables = tcx.typeck(owner_def_id);
|
||||||
|
|
||||||
if let Some(concrete) = concrete {
|
// Check that all of the opaques we inferred during HIR are compatible.
|
||||||
|
// FIXME: We explicitly don't check that the types inferred during HIR
|
||||||
|
// typeck are compatible with the one that we infer during borrowck,
|
||||||
|
// because that one actually sometimes has consts evaluated eagerly so
|
||||||
|
// using strict type equality will fail.
|
||||||
|
let mut hir_opaque_ty: Option<ty::OpaqueHiddenType<'tcx>> = None;
|
||||||
|
if tables.tainted_by_errors.is_none() {
|
||||||
|
for (&opaque_type_key, &hidden_type) in &tables.concrete_opaque_types {
|
||||||
|
if opaque_type_key.def_id != def_id {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let concrete_type = tcx.erase_regions(
|
||||||
|
hidden_type.remap_generic_params_to_declaration_params(opaque_type_key, tcx, true),
|
||||||
|
);
|
||||||
|
if let Some(prev) = &mut hir_opaque_ty {
|
||||||
|
if concrete_type.ty != prev.ty && !(concrete_type, prev.ty).references_error() {
|
||||||
|
prev.report_mismatch(&concrete_type, def_id, tcx).stash(
|
||||||
|
tcx.def_span(opaque_type_key.def_id),
|
||||||
|
StashKey::OpaqueHiddenTypeMismatch,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
hir_opaque_ty = Some(concrete_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mir_opaque_ty = tcx.mir_borrowck(owner_def_id).concrete_opaque_types.get(&def_id).copied();
|
||||||
|
if let Some(mir_opaque_ty) = mir_opaque_ty {
|
||||||
let scope = tcx.hir().local_def_id_to_hir_id(owner_def_id);
|
let scope = tcx.hir().local_def_id_to_hir_id(owner_def_id);
|
||||||
debug!(?scope);
|
debug!(?scope);
|
||||||
let mut locator = RpitConstraintChecker { def_id, tcx, found: concrete };
|
let mut locator = RpitConstraintChecker { def_id, tcx, found: mir_opaque_ty };
|
||||||
|
|
||||||
match tcx.hir().get(scope) {
|
match tcx.hir().get(scope) {
|
||||||
Node::Item(it) => intravisit::walk_item(&mut locator, it),
|
Node::Item(it) => intravisit::walk_item(&mut locator, it),
|
||||||
|
@ -224,38 +253,16 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>(
|
||||||
other => bug!("{:?} is not a valid scope for an opaque type item", other),
|
other => bug!("{:?} is not a valid scope for an opaque type item", other),
|
||||||
}
|
}
|
||||||
|
|
||||||
concrete.ty
|
mir_opaque_ty.ty
|
||||||
} else {
|
} else {
|
||||||
let tables = tcx.typeck(owner_def_id);
|
|
||||||
if let Some(guar) = tables.tainted_by_errors {
|
if let Some(guar) = tables.tainted_by_errors {
|
||||||
// Some error in the
|
// Some error in the owner fn prevented us from populating
|
||||||
// owner fn prevented us from populating
|
|
||||||
// the `concrete_opaque_types` table.
|
// the `concrete_opaque_types` table.
|
||||||
tcx.ty_error(guar)
|
tcx.ty_error(guar)
|
||||||
} else {
|
} else {
|
||||||
// Fall back to the RPIT we inferred during HIR typeck
|
// Fall back to the RPIT we inferred during HIR typeck
|
||||||
let mut opaque_ty: Option<ty::OpaqueHiddenType<'tcx>> = None;
|
if let Some(hir_opaque_ty) = hir_opaque_ty {
|
||||||
for (&opaque_type_key, &hidden_type) in &tables.concrete_opaque_types {
|
hir_opaque_ty.ty
|
||||||
if opaque_type_key.def_id != def_id {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let concrete_type =
|
|
||||||
tcx.erase_regions(hidden_type.remap_generic_params_to_declaration_params(
|
|
||||||
opaque_type_key,
|
|
||||||
tcx,
|
|
||||||
true,
|
|
||||||
));
|
|
||||||
if let Some(prev) = &mut opaque_ty {
|
|
||||||
if concrete_type.ty != prev.ty && !(concrete_type, prev.ty).references_error() {
|
|
||||||
prev.report_mismatch(&concrete_type, def_id, tcx).emit();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
opaque_ty = Some(concrete_type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(opaque_ty) = opaque_ty {
|
|
||||||
opaque_ty.ty
|
|
||||||
} else {
|
} else {
|
||||||
// We failed to resolve the opaque type or it
|
// We failed to resolve the opaque type or it
|
||||||
// resolves to itself. We interpret this as the
|
// resolves to itself. We interpret this as the
|
||||||
|
|
|
@ -155,10 +155,6 @@ pub struct TypeckResults<'tcx> {
|
||||||
/// We also store the type here, so that the compiler can use it as a hint
|
/// We also store the type here, so that the compiler can use it as a hint
|
||||||
/// for figuring out hidden types, even if they are only set in dead code
|
/// for figuring out hidden types, even if they are only set in dead code
|
||||||
/// (which doesn't show up in MIR).
|
/// (which doesn't show up in MIR).
|
||||||
///
|
|
||||||
/// These types are mapped back to the opaque's identity substitutions
|
|
||||||
/// (with erased regions), which is why we don't associated substs with any
|
|
||||||
/// of these usages.
|
|
||||||
pub concrete_opaque_types: FxIndexMap<ty::OpaqueTypeKey<'tcx>, ty::OpaqueHiddenType<'tcx>>,
|
pub concrete_opaque_types: FxIndexMap<ty::OpaqueTypeKey<'tcx>, ty::OpaqueHiddenType<'tcx>>,
|
||||||
|
|
||||||
/// Tracks the minimum captures required for a closure;
|
/// Tracks the minimum captures required for a closure;
|
||||||
|
|
|
@ -13,16 +13,9 @@ error: internal compiler error: projection clauses should be implied from elsewh
|
||||||
LL | async fn foo(x: u32) -> u32 {
|
LL | async fn foo(x: u32) -> u32 {
|
||||||
| ^^^query stack during panic:
|
| ^^^query stack during panic:
|
||||||
#0 [typeck] type-checking `foo`
|
#0 [typeck] type-checking `foo`
|
||||||
#1 [thir_body] building THIR for `foo`
|
#1 [type_of] computing type of `foo::{opaque#0}`
|
||||||
#2 [check_match] match-checking `foo`
|
#2 [check_mod_item_types] checking item types in top-level module
|
||||||
#3 [mir_built] building MIR for `foo`
|
#3 [analysis] running analysis passes on this crate
|
||||||
#4 [unsafety_check_result] unsafety-checking `foo`
|
|
||||||
#5 [mir_const] preparing `foo` for borrow checking
|
|
||||||
#6 [mir_promoted] promoting constants in MIR for `foo`
|
|
||||||
#7 [mir_borrowck] borrow-checking `foo`
|
|
||||||
#8 [type_of] computing type of `foo::{opaque#0}`
|
|
||||||
#9 [check_mod_item_types] checking item types in top-level module
|
|
||||||
#10 [analysis] running analysis passes on this crate
|
|
||||||
end of query stack
|
end of query stack
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
|
@ -13,41 +13,6 @@ error[E0391]: cycle detected when computing type of `make_dyn_star::{opaque#0}`
|
||||||
LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
|
LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: ...which requires borrow-checking `make_dyn_star`...
|
|
||||||
--> $DIR/param-env-infer.rs:11:1
|
|
||||||
|
|
|
||||||
LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires promoting constants in MIR for `make_dyn_star`...
|
|
||||||
--> $DIR/param-env-infer.rs:11:1
|
|
||||||
|
|
|
||||||
LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires preparing `make_dyn_star` for borrow checking...
|
|
||||||
--> $DIR/param-env-infer.rs:11:1
|
|
||||||
|
|
|
||||||
LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires unsafety-checking `make_dyn_star`...
|
|
||||||
--> $DIR/param-env-infer.rs:11:1
|
|
||||||
|
|
|
||||||
LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires building MIR for `make_dyn_star`...
|
|
||||||
--> $DIR/param-env-infer.rs:11:1
|
|
||||||
|
|
|
||||||
LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires match-checking `make_dyn_star`...
|
|
||||||
--> $DIR/param-env-infer.rs:11:1
|
|
||||||
|
|
|
||||||
LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires building THIR for `make_dyn_star`...
|
|
||||||
--> $DIR/param-env-infer.rs:11:1
|
|
||||||
|
|
|
||||||
LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires type-checking `make_dyn_star`...
|
note: ...which requires type-checking `make_dyn_star`...
|
||||||
--> $DIR/param-env-infer.rs:11:1
|
--> $DIR/param-env-infer.rs:11:1
|
||||||
|
|
|
|
||||||
|
|
|
@ -4,41 +4,6 @@ error[E0391]: cycle detected when computing type of `cycle1::{opaque#0}`
|
||||||
LL | fn cycle1() -> impl Clone {
|
LL | fn cycle1() -> impl Clone {
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: ...which requires borrow-checking `cycle1`...
|
|
||||||
--> $DIR/auto-trait-leak.rs:12:1
|
|
||||||
|
|
|
||||||
LL | fn cycle1() -> impl Clone {
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires promoting constants in MIR for `cycle1`...
|
|
||||||
--> $DIR/auto-trait-leak.rs:12:1
|
|
||||||
|
|
|
||||||
LL | fn cycle1() -> impl Clone {
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires preparing `cycle1` for borrow checking...
|
|
||||||
--> $DIR/auto-trait-leak.rs:12:1
|
|
||||||
|
|
|
||||||
LL | fn cycle1() -> impl Clone {
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires unsafety-checking `cycle1`...
|
|
||||||
--> $DIR/auto-trait-leak.rs:12:1
|
|
||||||
|
|
|
||||||
LL | fn cycle1() -> impl Clone {
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires building MIR for `cycle1`...
|
|
||||||
--> $DIR/auto-trait-leak.rs:12:1
|
|
||||||
|
|
|
||||||
LL | fn cycle1() -> impl Clone {
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires match-checking `cycle1`...
|
|
||||||
--> $DIR/auto-trait-leak.rs:12:1
|
|
||||||
|
|
|
||||||
LL | fn cycle1() -> impl Clone {
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires building THIR for `cycle1`...
|
|
||||||
--> $DIR/auto-trait-leak.rs:12:1
|
|
||||||
|
|
|
||||||
LL | fn cycle1() -> impl Clone {
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires type-checking `cycle1`...
|
note: ...which requires type-checking `cycle1`...
|
||||||
--> $DIR/auto-trait-leak.rs:14:5
|
--> $DIR/auto-trait-leak.rs:14:5
|
||||||
|
|
|
|
||||||
|
@ -50,41 +15,6 @@ note: ...which requires computing type of `cycle2::{opaque#0}`...
|
||||||
|
|
|
|
||||||
LL | fn cycle2() -> impl Clone {
|
LL | fn cycle2() -> impl Clone {
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
note: ...which requires borrow-checking `cycle2`...
|
|
||||||
--> $DIR/auto-trait-leak.rs:19:1
|
|
||||||
|
|
|
||||||
LL | fn cycle2() -> impl Clone {
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires promoting constants in MIR for `cycle2`...
|
|
||||||
--> $DIR/auto-trait-leak.rs:19:1
|
|
||||||
|
|
|
||||||
LL | fn cycle2() -> impl Clone {
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires preparing `cycle2` for borrow checking...
|
|
||||||
--> $DIR/auto-trait-leak.rs:19:1
|
|
||||||
|
|
|
||||||
LL | fn cycle2() -> impl Clone {
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires unsafety-checking `cycle2`...
|
|
||||||
--> $DIR/auto-trait-leak.rs:19:1
|
|
||||||
|
|
|
||||||
LL | fn cycle2() -> impl Clone {
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires building MIR for `cycle2`...
|
|
||||||
--> $DIR/auto-trait-leak.rs:19:1
|
|
||||||
|
|
|
||||||
LL | fn cycle2() -> impl Clone {
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires match-checking `cycle2`...
|
|
||||||
--> $DIR/auto-trait-leak.rs:19:1
|
|
||||||
|
|
|
||||||
LL | fn cycle2() -> impl Clone {
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires building THIR for `cycle2`...
|
|
||||||
--> $DIR/auto-trait-leak.rs:19:1
|
|
||||||
|
|
|
||||||
LL | fn cycle2() -> impl Clone {
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires type-checking `cycle2`...
|
note: ...which requires type-checking `cycle2`...
|
||||||
--> $DIR/auto-trait-leak.rs:20:5
|
--> $DIR/auto-trait-leak.rs:20:5
|
||||||
|
|
|
|
||||||
|
|
|
@ -4,9 +4,9 @@ impl Trait for () {}
|
||||||
fn foo<T: Trait, U: Trait>() -> impl Trait {
|
fn foo<T: Trait, U: Trait>() -> impl Trait {
|
||||||
//~^ WARN function cannot return without recursing [unconditional_recursion]
|
//~^ WARN function cannot return without recursing [unconditional_recursion]
|
||||||
let a: T = foo::<T, U>();
|
let a: T = foo::<T, U>();
|
||||||
//~^ ERROR concrete type differs from previous defining opaque type use
|
|
||||||
loop {}
|
loop {}
|
||||||
let _: T = foo::<U, T>();
|
let _: T = foo::<U, T>();
|
||||||
|
//~^ ERROR concrete type differs from previous defining opaque type use
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -11,15 +11,15 @@ LL | let a: T = foo::<T, U>();
|
||||||
= note: `#[warn(unconditional_recursion)]` on by default
|
= note: `#[warn(unconditional_recursion)]` on by default
|
||||||
|
|
||||||
error: concrete type differs from previous defining opaque type use
|
error: concrete type differs from previous defining opaque type use
|
||||||
|
--> $DIR/multiple-defining-usages-in-body.rs:8:16
|
||||||
|
|
|
||||||
|
LL | let _: T = foo::<U, T>();
|
||||||
|
| ^^^^^^^^^^^^^ expected `T`, got `U`
|
||||||
|
|
|
||||||
|
note: previous use here
|
||||||
--> $DIR/multiple-defining-usages-in-body.rs:6:16
|
--> $DIR/multiple-defining-usages-in-body.rs:6:16
|
||||||
|
|
|
|
||||||
LL | let a: T = foo::<T, U>();
|
LL | let a: T = foo::<T, U>();
|
||||||
| ^^^^^^^^^^^^^ expected `U`, got `T`
|
|
||||||
|
|
|
||||||
note: previous use here
|
|
||||||
--> $DIR/multiple-defining-usages-in-body.rs:9:16
|
|
||||||
|
|
|
||||||
LL | let _: T = foo::<U, T>();
|
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to previous error; 1 warning emitted
|
error: aborting due to previous error; 1 warning emitted
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue