Rollup merge of #111980 - compiler-errors:unmapped-substs, r=lcnr

Preserve substs in opaques recorded in typeck results

This means that we now prepopulate MIR with opaques with the right substs.

The first commit is a hack that I think we discussed, having to do with `DefiningAnchor::Bubble` basically being equivalent to `DefiningAnchor::Error` in the new solver, so having to use `DefiningAnchor::Bind` instead, lol.

r? `@lcnr`
This commit is contained in:
Dylan DPC 2023-06-01 11:09:43 +05:30 committed by GitHub
commit ccf99bd769
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 128 additions and 188 deletions

View File

@ -279,8 +279,18 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
// HACK This bubble is required for this tests to pass:
// nested-return-type2-tait2.rs
// nested-return-type2-tait3.rs
let infcx =
self.tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).build();
// FIXME(-Ztrait-solver=next): We probably should use `DefiningAnchor::Error`
// and prepopulate this `InferCtxt` with known opaque values, rather than
// using the `Bind` anchor here. For now it's fine.
let infcx = self
.tcx
.infer_ctxt()
.with_opaque_type_inference(if self.tcx.trait_solver_next() {
DefiningAnchor::Bind(def_id)
} else {
DefiningAnchor::Bubble
})
.build();
let ocx = ObligationCtxt::new(&infcx);
// Require the hidden type to be well-formed with only the generics of the opaque type.
// Defining use functions may have more bounds than the opaque type, which is ok, as long as the

View File

@ -188,9 +188,6 @@ pub(crate) fn type_check<'mir, 'tcx>(
// FIXME(-Ztrait-solver=next): A bit dubious that we're only registering
// predefined opaques in the typeck root.
// FIXME(-Ztrait-solver=next): This is also totally wrong for TAITs, since
// the HIR typeck map defining usages back to their definition params,
// they won't actually match up with the usages in this body...
if infcx.tcx.trait_solver_next() && !infcx.tcx.is_typeck_child(body.source.def_id()) {
checker.register_predefined_opaques_in_new_solver();
}
@ -1042,10 +1039,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
.typeck(self.body.source.def_id().expect_local())
.concrete_opaque_types
.iter()
.map(|(&def_id, &hidden_ty)| {
let substs = ty::InternalSubsts::identity_for_item(self.infcx.tcx, def_id);
(ty::OpaqueTypeKey { def_id, substs }, hidden_ty)
})
.map(|(k, v)| (*k, *v))
.collect();
let renumbered_opaques = self.infcx.tcx.fold_regions(opaques, |_, _| {

View File

@ -1,3 +1,4 @@
use rustc_errors::StashKey;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{self as hir, Expr, ImplItem, Item, Node, TraitItem};
@ -59,7 +60,20 @@ pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: Local
}
}
let Some(hidden) = locator.found else {
if let Some(hidden) = locator.found {
// Only check against typeck if we didn't already error
if !hidden.ty.references_error() {
for concrete_type in locator.typeck_types {
if concrete_type.ty != tcx.erase_regions(hidden.ty)
&& !(concrete_type, hidden).references_error()
{
hidden.report_mismatch(&concrete_type, def_id, tcx).emit();
}
}
}
hidden.ty
} else {
let reported = tcx.sess.emit_err(UnconstrainedOpaqueType {
span: tcx.def_span(def_id),
name: tcx.item_name(tcx.local_parent(def_id).to_def_id()),
@ -70,21 +84,8 @@ pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: Local
_ => "item",
},
});
return tcx.ty_error(reported);
};
// Only check against typeck if we didn't already error
if !hidden.ty.references_error() {
for concrete_type in locator.typeck_types {
if concrete_type.ty != tcx.erase_regions(hidden.ty)
&& !(concrete_type, hidden).references_error()
{
hidden.report_mismatch(&concrete_type, def_id, tcx).emit();
}
}
tcx.ty_error(reported)
}
hidden.ty
}
struct TaitConstraintLocator<'tcx> {
@ -130,13 +131,28 @@ impl TaitConstraintLocator<'_> {
self.found = Some(ty::OpaqueHiddenType { span: DUMMY_SP, ty: self.tcx.ty_error(guar) });
return;
}
let Some(&typeck_hidden_ty) = tables.concrete_opaque_types.get(&self.def_id) else {
let mut constrained = false;
for (&opaque_type_key, &hidden_type) in &tables.concrete_opaque_types {
if opaque_type_key.def_id != self.def_id {
continue;
}
constrained = true;
let concrete_type =
self.tcx.erase_regions(hidden_type.remap_generic_params_to_declaration_params(
opaque_type_key,
self.tcx,
true,
));
if self.typeck_types.iter().all(|prev| prev.ty != concrete_type.ty) {
self.typeck_types.push(concrete_type);
}
}
if !constrained {
debug!("no constraints in typeck results");
return;
};
if self.typeck_types.iter().all(|prev| prev.ty != typeck_hidden_ty.ty) {
self.typeck_types.push(typeck_hidden_ty);
}
// Use borrowck to get the type with unerased regions.
let concrete_opaque_types = &self.tcx.mir_borrowck(item_def_id).concrete_opaque_types;
@ -190,17 +206,45 @@ impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
}
}
pub(super) fn find_opaque_ty_constraints_for_rpit(
tcx: TyCtxt<'_>,
pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: LocalDefId,
owner_def_id: LocalDefId,
) -> 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);
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) {
Node::Item(it) => intravisit::walk_item(&mut locator, it),
@ -208,17 +252,18 @@ pub(super) fn find_opaque_ty_constraints_for_rpit(
Node::TraitItem(it) => intravisit::walk_trait_item(&mut locator, it),
other => bug!("{:?} is not a valid scope for an opaque type item", other),
}
}
concrete.map(|concrete| concrete.ty).unwrap_or_else(|| {
let table = tcx.typeck(owner_def_id);
if let Some(guar) = table.tainted_by_errors {
// Some error in the
// owner fn prevented us from populating
mir_opaque_ty.ty
} else {
if let Some(guar) = tables.tainted_by_errors {
// Some error in the owner fn prevented us from populating
// the `concrete_opaque_types` table.
tcx.ty_error(guar)
} else {
table.concrete_opaque_types.get(&def_id).map(|ty| ty.ty).unwrap_or_else(|| {
// Fall back to the RPIT we inferred during HIR typeck
if let Some(hir_opaque_ty) = hir_opaque_ty {
hir_opaque_ty.ty
} else {
// We failed to resolve the opaque type or it
// resolves to itself. We interpret this as the
// no values of the hidden type ever being constructed,
@ -226,9 +271,9 @@ pub(super) fn find_opaque_ty_constraints_for_rpit(
// For backwards compatibility reasons, we fall back to
// `()` until we the diverging default is changed.
tcx.mk_diverging_default()
})
}
}
})
}
}
struct RpitConstraintChecker<'tcx> {

View File

@ -583,19 +583,15 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
continue;
}
let hidden_type =
self.tcx().erase_regions(hidden_type.remap_generic_params_to_declaration_params(
opaque_type_key,
self.tcx(),
true,
));
// Here we only detect impl trait definition conflicts when they
// are equal modulo regions.
if let Some(last_opaque_ty) = self
.typeck_results
.concrete_opaque_types
.insert(opaque_type_key.def_id, hidden_type)
.insert(opaque_type_key, hidden_type)
&& last_opaque_ty.ty != hidden_type.ty
{
assert!(!self.tcx().trait_solver_next());
hidden_type
.report_mismatch(&last_opaque_ty, opaque_type_key.def_id, self.tcx())
.stash(

View File

@ -155,11 +155,7 @@ pub struct TypeckResults<'tcx> {
/// 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
/// (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<LocalDefId, ty::OpaqueHiddenType<'tcx>>,
pub concrete_opaque_types: FxIndexMap<ty::OpaqueTypeKey<'tcx>, ty::OpaqueHiddenType<'tcx>>,
/// Tracks the minimum captures required for a closure;
/// see `MinCaptureInformationMap` for more details.

View File

@ -13,16 +13,9 @@ error: internal compiler error: projection clauses should be implied from elsewh
LL | async fn foo(x: u32) -> u32 {
| ^^^query stack during panic:
#0 [typeck] type-checking `foo`
#1 [thir_body] building THIR for `foo`
#2 [check_match] match-checking `foo`
#3 [mir_built] building MIR for `foo`
#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
#1 [type_of] computing type of `foo::{opaque#0}`
#2 [check_mod_item_types] checking item types in top-level module
#3 [analysis] running analysis passes on this crate
end of query stack
error: aborting due to 2 previous errors

View File

@ -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 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
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`...
--> $DIR/param-env-infer.rs:11:1
|

View File

@ -4,41 +4,6 @@ error[E0391]: cycle detected when computing type of `cycle1::{opaque#0}`
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`...
--> $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 {
| ^^^^^^^^^^
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`...
--> $DIR/auto-trait-leak.rs:20:5
|

View File

@ -4,9 +4,9 @@ impl Trait for () {}
fn foo<T: Trait, U: Trait>() -> impl Trait {
//~^ WARN function cannot return without recursing [unconditional_recursion]
let a: T = foo::<T, U>();
//~^ ERROR concrete type differs from previous defining opaque type use
loop {}
let _: T = foo::<U, T>();
//~^ ERROR concrete type differs from previous defining opaque type use
}
fn main() {}

View File

@ -11,15 +11,15 @@ LL | let a: T = foo::<T, U>();
= note: `#[warn(unconditional_recursion)]` on by default
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
|
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

View File

@ -0,0 +1,19 @@
// compile-flags: -Ztrait-solver=next
// check-pass
// Makes sure we don't prepopulate the MIR typeck of `define`
// with `Foo<T, U> = T`, but instead, `Foo<B, A> = B`, so that
// the param-env predicates actually apply.
#![feature(type_alias_impl_trait)]
type Foo<T: Send, U> = impl NeedsSend<T>;
trait NeedsSend<T> {}
impl<T: Send> NeedsSend<T> for T {}
fn define<A, B: Send>(a: A, b: B) {
let y: Option<Foo<B, A>> = Some(b);
}
fn main() {}

View File

@ -1,3 +1,5 @@
// revisions: current next
//[next] compile-flags: -Ztrait-solver=next
// check-pass
#![feature(type_alias_impl_trait)]

View File

@ -8,7 +8,6 @@ type X<A, B> = impl Into<&'static A>;
fn f<A, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) {
//~^ ERROR the trait bound `&'static B: From<&A>` is not satisfied
//~| ERROR concrete type differs from previous defining opaque type use
(a, a)
}

View File

@ -10,15 +10,6 @@ help: consider introducing a `where` clause, but there might be an alternative b
LL | fn f<A, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) where &'static B: From<&A> {
| ++++++++++++++++++++++++++
error: concrete type differs from previous defining opaque type use
--> $DIR/multiple-def-uses-in-one-fn.rs:9:45
|
LL | fn f<A, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) {
| ^^^^^^^^^^^^^^^^^^
| |
| expected `&B`, got `&A`
| this expression supplies two conflicting concrete types for the same opaque type
error: aborting due to 2 previous errors
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.