1
Fork 0

support revealing defined opaque post borrowck

This commit is contained in:
lcnr 2024-11-26 16:01:08 +01:00
parent 18e2253e79
commit 34a8c2dbba
21 changed files with 226 additions and 58 deletions

View file

@ -322,8 +322,12 @@ fn check_opaque_meets_bounds<'tcx>(
}; };
let param_env = tcx.param_env(defining_use_anchor); let param_env = tcx.param_env(defining_use_anchor);
// FIXME(#132279): This should eventually use the already defined hidden types. // FIXME(#132279): Once `PostBorrowckAnalysis` is supported in the old solver, this branch should be removed.
let infcx = tcx.infer_ctxt().build(TypingMode::analysis_in_body(tcx, defining_use_anchor)); let infcx = tcx.infer_ctxt().build(if tcx.next_trait_solver_globally() {
TypingMode::post_borrowck_analysis(tcx, defining_use_anchor)
} else {
TypingMode::analysis_in_body(tcx, defining_use_anchor)
});
let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
let args = match origin { let args = match origin {
@ -417,7 +421,11 @@ fn check_opaque_meets_bounds<'tcx>(
let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env)?; ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env)?;
if let hir::OpaqueTyOrigin::FnReturn { .. } | hir::OpaqueTyOrigin::AsyncFn { .. } = origin { if infcx.next_trait_solver() {
Ok(())
} else if let hir::OpaqueTyOrigin::FnReturn { .. } | hir::OpaqueTyOrigin::AsyncFn { .. } =
origin
{
// HACK: this should also fall through to the hidden type check below, but the original // HACK: this should also fall through to the hidden type check below, but the original
// implementation had a bug where equivalent lifetimes are not identical. This caused us // implementation had a bug where equivalent lifetimes are not identical. This caused us
// to reject existing stable code that is otherwise completely fine. The real fix is to // to reject existing stable code that is otherwise completely fine. The real fix is to

View file

@ -1574,7 +1574,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
// Thus we need to prevent them from trying to match the `&_` autoref // Thus we need to prevent them from trying to match the `&_` autoref
// candidates that get created for `&self` trait methods. // candidates that get created for `&self` trait methods.
ty::Alias(ty::Opaque, alias_ty) ty::Alias(ty::Opaque, alias_ty)
if self.infcx.can_define_opaque_ty(alias_ty.def_id) if !self.next_trait_solver()
&& self.infcx.can_define_opaque_ty(alias_ty.def_id)
&& !xform_self_ty.is_ty_var() => && !xform_self_ty.is_ty_var() =>
{ {
return ProbeResult::NoMatch; return ProbeResult::NoMatch;

View file

@ -7,7 +7,7 @@ use rustc_middle::ty::relate::combine::PredicateEmittingRelation;
use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::{DUMMY_SP, ErrorGuaranteed}; use rustc_span::{DUMMY_SP, ErrorGuaranteed};
use super::{BoundRegionConversionTime, InferCtxt, SubregionOrigin}; use super::{BoundRegionConversionTime, InferCtxt, RegionVariableOrigin, SubregionOrigin};
impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
type Interner = TyCtxt<'tcx>; type Interner = TyCtxt<'tcx>;
@ -87,6 +87,10 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
self.inner.borrow_mut().unwrap_region_constraints().opportunistic_resolve_var(self.tcx, vid) self.inner.borrow_mut().unwrap_region_constraints().opportunistic_resolve_var(self.tcx, vid)
} }
fn next_region_infer(&self) -> ty::Region<'tcx> {
self.next_region_var(RegionVariableOrigin::MiscVariable(DUMMY_SP))
}
fn next_ty_infer(&self) -> Ty<'tcx> { fn next_ty_infer(&self) -> Ty<'tcx> {
self.next_ty_var(DUMMY_SP) self.next_ty_var(DUMMY_SP)
} }

View file

@ -990,11 +990,17 @@ impl<'tcx> InferCtxt<'tcx> {
#[inline(always)] #[inline(always)]
pub fn can_define_opaque_ty(&self, id: impl Into<DefId>) -> bool { pub fn can_define_opaque_ty(&self, id: impl Into<DefId>) -> bool {
debug_assert!(!self.next_trait_solver());
match self.typing_mode() { match self.typing_mode() {
TypingMode::Analysis { defining_opaque_types } => { TypingMode::Analysis { defining_opaque_types } => {
id.into().as_local().is_some_and(|def_id| defining_opaque_types.contains(&def_id)) id.into().as_local().is_some_and(|def_id| defining_opaque_types.contains(&def_id))
} }
TypingMode::Coherence | TypingMode::PostAnalysis => false, // FIXME(#132279): This function is quite weird in post-analysis
// and post-borrowck analysis mode. We may need to modify its uses
// to support PostBorrowckAnalysis in the old solver as well.
TypingMode::Coherence
| TypingMode::PostBorrowckAnalysis { .. }
| TypingMode::PostAnalysis => false,
} }
} }
@ -1276,7 +1282,6 @@ impl<'tcx> InferCtxt<'tcx> {
/// using canonicalization or carrying this inference context around. /// using canonicalization or carrying this inference context around.
pub fn typing_env(&self, param_env: ty::ParamEnv<'tcx>) -> ty::TypingEnv<'tcx> { pub fn typing_env(&self, param_env: ty::ParamEnv<'tcx>) -> ty::TypingEnv<'tcx> {
let typing_mode = match self.typing_mode() { let typing_mode = match self.typing_mode() {
ty::TypingMode::Coherence => ty::TypingMode::Coherence,
// FIXME(#132279): This erases the `defining_opaque_types` as it isn't possible // FIXME(#132279): This erases the `defining_opaque_types` as it isn't possible
// to handle them without proper canonicalization. This means we may cause cycle // to handle them without proper canonicalization. This means we may cause cycle
// errors and fail to reveal opaques while inside of bodies. We should rename this // errors and fail to reveal opaques while inside of bodies. We should rename this
@ -1284,7 +1289,9 @@ impl<'tcx> InferCtxt<'tcx> {
ty::TypingMode::Analysis { defining_opaque_types: _ } => { ty::TypingMode::Analysis { defining_opaque_types: _ } => {
TypingMode::non_body_analysis() TypingMode::non_body_analysis()
} }
ty::TypingMode::PostAnalysis => ty::TypingMode::PostAnalysis, mode @ (ty::TypingMode::Coherence
| ty::TypingMode::PostBorrowckAnalysis { .. }
| ty::TypingMode::PostAnalysis) => mode,
}; };
ty::TypingEnv { typing_mode, param_env } ty::TypingEnv { typing_mode, param_env }
} }

View file

@ -98,6 +98,7 @@ impl<'tcx> InferCtxt<'tcx> {
span: Span, span: Span,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, TypeError<'tcx>> { ) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, TypeError<'tcx>> {
debug_assert!(!self.next_trait_solver());
let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() { let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() {
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) if def_id.is_local() => { ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) if def_id.is_local() => {
let def_id = def_id.expect_local(); let def_id = def_id.expect_local();
@ -546,7 +547,9 @@ impl<'tcx> InferCtxt<'tcx> {
); );
} }
} }
ty::TypingMode::PostAnalysis => bug!("insert hidden type post-analysis"), mode @ (ty::TypingMode::PostBorrowckAnalysis { .. } | ty::TypingMode::PostAnalysis) => {
bug!("insert hidden type in {mode:?}")
}
} }
Ok(()) Ok(())

View file

@ -339,7 +339,9 @@ where
match self.typing_mode() { match self.typing_mode() {
TypingMode::Coherence => {} TypingMode::Coherence => {}
TypingMode::Analysis { .. } | TypingMode::PostAnalysis => { TypingMode::Analysis { .. }
| TypingMode::PostBorrowckAnalysis { .. }
| TypingMode::PostAnalysis => {
self.discard_impls_shadowed_by_env(goal, &mut candidates); self.discard_impls_shadowed_by_env(goal, &mut candidates);
} }
} }

View file

@ -644,6 +644,12 @@ where
} }
} }
pub(super) fn next_region_var(&mut self) -> I::Region {
let region = self.delegate.next_region_infer();
self.inspect.add_var_value(region);
region
}
pub(super) fn next_ty_infer(&mut self) -> I::Ty { pub(super) fn next_ty_infer(&mut self) -> I::Ty {
let ty = self.delegate.next_ty_infer(); let ty = self.delegate.next_ty_infer();
self.inspect.add_var_value(ty); self.inspect.add_var_value(ty);

View file

@ -23,7 +23,7 @@ mod trait_goals;
use rustc_type_ir::inherent::*; use rustc_type_ir::inherent::*;
pub use rustc_type_ir::solve::*; pub use rustc_type_ir::solve::*;
use rustc_type_ir::{self as ty, Interner}; use rustc_type_ir::{self as ty, Interner, TypingMode};
use tracing::instrument; use tracing::instrument;
pub use self::eval_ctxt::{EvalCtxt, GenerateProofTree, SolverDelegateEvalExt}; pub use self::eval_ctxt::{EvalCtxt, GenerateProofTree, SolverDelegateEvalExt};
@ -321,6 +321,19 @@ where
Ok(ct) Ok(ct)
} }
} }
fn opaque_type_is_rigid(&self, def_id: I::DefId) -> bool {
match self.typing_mode() {
// Opaques are never rigid outside of analysis mode.
TypingMode::Coherence | TypingMode::PostAnalysis => false,
// During analysis, opaques are rigid unless they may be defined by
// the current body.
TypingMode::Analysis { defining_opaque_types: non_rigid_opaques }
| TypingMode::PostBorrowckAnalysis { defined_opaque_types: non_rigid_opaques } => {
!def_id.as_local().is_some_and(|def_id| non_rigid_opaques.contains(&def_id))
}
}
}
} }
fn response_no_constraints_raw<I: Interner>( fn response_no_constraints_raw<I: Interner>(

View file

@ -6,7 +6,7 @@ mod weak_types;
use rustc_type_ir::fast_reject::DeepRejectCtxt; use rustc_type_ir::fast_reject::DeepRejectCtxt;
use rustc_type_ir::inherent::*; use rustc_type_ir::inherent::*;
use rustc_type_ir::lang_items::TraitSolverLangItem; use rustc_type_ir::lang_items::TraitSolverLangItem;
use rustc_type_ir::{self as ty, Interner, NormalizesTo, TypingMode, Upcast as _}; use rustc_type_ir::{self as ty, Interner, NormalizesTo, Upcast as _};
use tracing::instrument; use tracing::instrument;
use crate::delegate::SolverDelegate; use crate::delegate::SolverDelegate;
@ -71,21 +71,10 @@ where
Ok(()) Ok(())
} }
ty::AliasTermKind::OpaqueTy => { ty::AliasTermKind::OpaqueTy => {
match self.typing_mode() { if self.opaque_type_is_rigid(rigid_alias.def_id) {
// Opaques are never rigid outside of analysis mode.
TypingMode::Coherence | TypingMode::PostAnalysis => Err(NoSolution),
// During analysis, opaques are only rigid if we may not define it.
TypingMode::Analysis { defining_opaque_types } => {
if rigid_alias
.def_id
.as_local()
.is_some_and(|def_id| defining_opaque_types.contains(&def_id))
{
Err(NoSolution)
} else {
Ok(()) Ok(())
} } else {
} Err(NoSolution)
} }
} }
// FIXME(generic_const_exprs): we would need to support generic consts here // FIXME(generic_const_exprs): we would need to support generic consts here

View file

@ -2,6 +2,7 @@
//! behaves differently depending on the current `TypingMode`. //! behaves differently depending on the current `TypingMode`.
use rustc_index::bit_set::GrowableBitSet; use rustc_index::bit_set::GrowableBitSet;
use rustc_type_ir::fold::fold_regions;
use rustc_type_ir::inherent::*; use rustc_type_ir::inherent::*;
use rustc_type_ir::{self as ty, Interner, TypingMode}; use rustc_type_ir::{self as ty, Interner, TypingMode};
@ -95,6 +96,26 @@ where
); );
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
} }
TypingMode::PostBorrowckAnalysis { defined_opaque_types } => {
let Some(def_id) = opaque_ty.def_id.as_local() else {
return Err(NoSolution);
};
if !defined_opaque_types.contains(&def_id) {
return Err(NoSolution);
}
let actual = cx.type_of(opaque_ty.def_id).instantiate(cx, opaque_ty.args);
// FIXME: Actually use a proper binder here instead of relying on `ReErased`.
//
// This is also probably unsound or sth :shrug:
let actual = fold_regions(cx, actual, |re, _dbi| match re.kind() {
ty::ReErased => self.next_region_var(),
_ => re,
});
self.eq(goal.param_env, expected, actual)?;
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}
TypingMode::PostAnalysis => { TypingMode::PostAnalysis => {
// FIXME: Add an assertion that opaque type storage is empty. // FIXME: Add an assertion that opaque type storage is empty.
let actual = cx.type_of(opaque_ty.def_id).instantiate(cx, opaque_ty.args); let actual = cx.type_of(opaque_ty.def_id).instantiate(cx, opaque_ty.args);

View file

@ -69,7 +69,9 @@ where
// it's not a real impl. // it's not a real impl.
(ty::ImplPolarity::Reservation, _) => match ecx.typing_mode() { (ty::ImplPolarity::Reservation, _) => match ecx.typing_mode() {
TypingMode::Coherence => Certainty::AMBIGUOUS, TypingMode::Coherence => Certainty::AMBIGUOUS,
TypingMode::Analysis { .. } | TypingMode::PostAnalysis => return Err(NoSolution), TypingMode::Analysis { .. }
| TypingMode::PostBorrowckAnalysis { .. }
| TypingMode::PostAnalysis => return Err(NoSolution),
}, },
// Impl matches polarity // Impl matches polarity
@ -174,20 +176,7 @@ where
// ideally we want to avoid, since we can make progress on this goal // ideally we want to avoid, since we can make progress on this goal
// via an alias bound or a locally-inferred hidden type instead. // via an alias bound or a locally-inferred hidden type instead.
if let ty::Alias(ty::Opaque, opaque_ty) = goal.predicate.self_ty().kind() { if let ty::Alias(ty::Opaque, opaque_ty) = goal.predicate.self_ty().kind() {
match ecx.typing_mode() { debug_assert!(ecx.opaque_type_is_rigid(opaque_ty.def_id));
TypingMode::Coherence | TypingMode::PostAnalysis => {
unreachable!("rigid opaque outside of analysis: {goal:?}");
}
TypingMode::Analysis { defining_opaque_types } => {
if opaque_ty
.def_id
.as_local()
.is_some_and(|def_id| defining_opaque_types.contains(&def_id))
{
return Err(NoSolution);
}
}
}
} }
ecx.probe_and_evaluate_goal_for_constituent_tys( ecx.probe_and_evaluate_goal_for_constituent_tys(

View file

@ -205,7 +205,9 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
// transmute checking and polymorphic MIR optimizations could // transmute checking and polymorphic MIR optimizations could
// get a result which isn't correct for all monomorphizations. // get a result which isn't correct for all monomorphizations.
match self.typing_mode() { match self.typing_mode() {
TypingMode::Coherence | TypingMode::Analysis { .. } => false, TypingMode::Coherence
| TypingMode::Analysis { .. }
| TypingMode::PostBorrowckAnalysis { .. } => false,
TypingMode::PostAnalysis => { TypingMode::PostAnalysis => {
let poly_trait_ref = self.resolve_vars_if_possible(goal_trait_ref); let poly_trait_ref = self.resolve_vars_if_possible(goal_trait_ref);
!poly_trait_ref.still_further_specializable() !poly_trait_ref.still_further_specializable()

View file

@ -118,9 +118,10 @@ pub(super) fn needs_normalization<'tcx, T: TypeVisitable<TyCtxt<'tcx>>>(
// Opaques are treated as rigid outside of `TypingMode::PostAnalysis`, // Opaques are treated as rigid outside of `TypingMode::PostAnalysis`,
// so we can ignore those. // so we can ignore those.
match infcx.typing_mode() { match infcx.typing_mode() {
TypingMode::Coherence | TypingMode::Analysis { defining_opaque_types: _ } => { // FIXME(#132279): We likely want to reveal opaques during post borrowck analysis
flags.remove(ty::TypeFlags::HAS_TY_OPAQUE) TypingMode::Coherence
} | TypingMode::Analysis { .. }
| TypingMode::PostBorrowckAnalysis { .. } => flags.remove(ty::TypeFlags::HAS_TY_OPAQUE),
TypingMode::PostAnalysis => {} TypingMode::PostAnalysis => {}
} }
@ -213,9 +214,10 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
ty::Opaque => { ty::Opaque => {
// Only normalize `impl Trait` outside of type inference, usually in codegen. // Only normalize `impl Trait` outside of type inference, usually in codegen.
match self.selcx.infcx.typing_mode() { match self.selcx.infcx.typing_mode() {
TypingMode::Coherence | TypingMode::Analysis { defining_opaque_types: _ } => { // FIXME(#132279): We likely want to reveal opaques during post borrowck analysis
ty.super_fold_with(self) TypingMode::Coherence
} | TypingMode::Analysis { .. }
| TypingMode::PostBorrowckAnalysis { .. } => ty.super_fold_with(self),
TypingMode::PostAnalysis => { TypingMode::PostAnalysis => {
let recursion_limit = self.cx().recursion_limit(); let recursion_limit = self.cx().recursion_limit();
if !recursion_limit.value_within_limit(self.depth) { if !recursion_limit.value_within_limit(self.depth) {

View file

@ -975,7 +975,9 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
// transmute checking and polymorphic MIR optimizations could // transmute checking and polymorphic MIR optimizations could
// get a result which isn't correct for all monomorphizations. // get a result which isn't correct for all monomorphizations.
match selcx.infcx.typing_mode() { match selcx.infcx.typing_mode() {
TypingMode::Coherence | TypingMode::Analysis { .. } => { TypingMode::Coherence
| TypingMode::Analysis { .. }
| TypingMode::PostBorrowckAnalysis { .. } => {
debug!( debug!(
assoc_ty = ?selcx.tcx().def_path_str(node_item.item.def_id), assoc_ty = ?selcx.tcx().def_path_str(node_item.item.def_id),
?obligation.predicate, ?obligation.predicate,

View file

@ -216,9 +216,9 @@ impl<'a, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'a, 'tcx> {
ty::Opaque => { ty::Opaque => {
// Only normalize `impl Trait` outside of type inference, usually in codegen. // Only normalize `impl Trait` outside of type inference, usually in codegen.
match self.infcx.typing_mode() { match self.infcx.typing_mode() {
TypingMode::Coherence | TypingMode::Analysis { defining_opaque_types: _ } => { TypingMode::Coherence
ty.try_super_fold_with(self)? | TypingMode::Analysis { .. }
} | TypingMode::PostBorrowckAnalysis { .. } => ty.try_super_fold_with(self)?,
TypingMode::PostAnalysis => { TypingMode::PostAnalysis => {
let args = data.args.try_fold_with(self)?; let args = data.args.try_fold_with(self)?;

View file

@ -1471,7 +1471,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let obligation = &stack.obligation; let obligation = &stack.obligation;
match self.infcx.typing_mode() { match self.infcx.typing_mode() {
TypingMode::Coherence => {} TypingMode::Coherence => {}
TypingMode::Analysis { .. } | TypingMode::PostAnalysis => return Ok(()), TypingMode::Analysis { .. }
| TypingMode::PostBorrowckAnalysis { .. }
| TypingMode::PostAnalysis => return Ok(()),
} }
debug!("is_knowable()"); debug!("is_knowable()");
@ -1518,6 +1520,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
TypingMode::Analysis { defining_opaque_types } => { TypingMode::Analysis { defining_opaque_types } => {
defining_opaque_types.is_empty() || !pred.has_opaque_types() defining_opaque_types.is_empty() || !pred.has_opaque_types()
} }
// The hidden types of `defined_opaque_types` is not local to the current
// inference context, so we can freely move this to the global cache.
TypingMode::PostBorrowckAnalysis { .. } => true,
// The global cache is only used if there are no opaque types in // The global cache is only used if there are no opaque types in
// the defining scope or we're outside of analysis. // the defining scope or we're outside of analysis.
// //

View file

@ -149,7 +149,8 @@ fn resolve_associated_item<'tcx>(
// get a result which isn't correct for all monomorphizations. // get a result which isn't correct for all monomorphizations.
match typing_env.typing_mode { match typing_env.typing_mode {
ty::TypingMode::Coherence ty::TypingMode::Coherence
| ty::TypingMode::Analysis { defining_opaque_types: _ } => false, | ty::TypingMode::Analysis { .. }
| ty::TypingMode::PostBorrowckAnalysis { .. } => false,
ty::TypingMode::PostAnalysis => !trait_ref.still_further_specializable(), ty::TypingMode::PostAnalysis => !trait_ref.still_further_specializable(),
} }
}; };

View file

@ -63,6 +63,12 @@ pub enum TypingMode<I: Interner> {
/// } /// }
/// ``` /// ```
Analysis { defining_opaque_types: I::DefiningOpaqueTypes }, Analysis { defining_opaque_types: I::DefiningOpaqueTypes },
/// Any analysis after borrowck for a given body should be able to use all the
/// hidden types defined by borrowck, without being able to define any new ones.
///
/// This is currently only used by the new solver, but should be implemented in
/// the old solver as well.
PostBorrowckAnalysis { defined_opaque_types: I::DefiningOpaqueTypes },
/// After analysis, mostly during codegen and MIR optimizations, we're able to /// After analysis, mostly during codegen and MIR optimizations, we're able to
/// reveal all opaque types. As the concrete type should *never* be observable /// reveal all opaque types. As the concrete type should *never* be observable
/// directly by the user, this should not be used by checks which may expose /// directly by the user, this should not be used by checks which may expose
@ -85,6 +91,12 @@ impl<I: Interner> TypingMode<I> {
pub fn analysis_in_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> { pub fn analysis_in_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
TypingMode::Analysis { defining_opaque_types: cx.opaque_types_defined_by(body_def_id) } TypingMode::Analysis { defining_opaque_types: cx.opaque_types_defined_by(body_def_id) }
} }
pub fn post_borrowck_analysis(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
TypingMode::PostBorrowckAnalysis {
defined_opaque_types: cx.opaque_types_defined_by(body_def_id),
}
}
} }
pub trait InferCtxtLike: Sized { pub trait InferCtxtLike: Sized {
@ -126,6 +138,7 @@ pub trait InferCtxtLike: Sized {
vid: ty::RegionVid, vid: ty::RegionVid,
) -> <Self::Interner as Interner>::Region; ) -> <Self::Interner as Interner>::Region;
fn next_region_infer(&self) -> <Self::Interner as Interner>::Region;
fn next_ty_infer(&self) -> <Self::Interner as Interner>::Ty; fn next_ty_infer(&self) -> <Self::Interner as Interner>::Ty;
fn next_const_infer(&self) -> <Self::Interner as Interner>::Const; fn next_const_infer(&self) -> <Self::Interner as Interner>::Const;
fn fresh_args_for_item( fn fresh_args_for_item(

View file

@ -136,9 +136,9 @@ where
relation.register_predicates([ty::Binder::dummy(ty::PredicateKind::Ambiguous)]); relation.register_predicates([ty::Binder::dummy(ty::PredicateKind::Ambiguous)]);
Ok(a) Ok(a)
} }
TypingMode::Analysis { .. } | TypingMode::PostAnalysis => { TypingMode::Analysis { .. }
structurally_relate_tys(relation, a, b) | TypingMode::PostBorrowckAnalysis { .. }
} | TypingMode::PostAnalysis => structurally_relate_tys(relation, a, b),
} }
} }

View file

@ -0,0 +1,34 @@
error: unconstrained opaque type
--> $DIR/no-define-in-wf-check.rs:19:18
|
LL | type Tait1 = impl Sized;
| ^^^^^^^^^^
|
= note: `Tait1` must be used in combination with a concrete type within the same module
error: unconstrained opaque type
--> $DIR/no-define-in-wf-check.rs:27:18
|
LL | type Tait1 = impl Sized;
| ^^^^^^^^^^
|
= note: `Tait1` must be used in combination with a concrete type within the same module
error: unconstrained opaque type
--> $DIR/no-define-in-wf-check.rs:36:18
|
LL | type Tait1 = impl Sized;
| ^^^^^^^^^^
|
= note: `Tait1` must be used in combination with a concrete type within the same module
error: unconstrained opaque type
--> $DIR/no-define-in-wf-check.rs:47:18
|
LL | type Tait1 = impl Sized;
| ^^^^^^^^^^
|
= note: `Tait1` must be used in combination with a concrete type within the same module
error: aborting due to 4 previous errors

View file

@ -0,0 +1,66 @@
//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
//@[next] check-pass
// Regression test for trait-system-refactor-initiative#106. We previously
// tried to define other opaques while checking that opaques are well-formed.
//
// This resulted in undesirable ambiguity
#![feature(type_alias_impl_trait)]
mod ex0 {
fn foo() -> (impl Sized, impl Sized) {
((), ())
}
}
mod ex1 {
type Tait1 = impl Sized;
//[current]~^ ERROR unconstrained opaque type
fn foo(x: Tait1) -> impl Sized {
let () = x;
}
}
mod ex2 {
type Tait1 = impl Sized;
//[current]~^ ERROR unconstrained opaque type
type Tait2 = impl Sized;
fn foo(x: Tait1) -> Tait2 {
let () = x;
}
}
mod ex3 {
type Tait1 = impl Sized;
//[current]~^ ERROR unconstrained opaque type
trait Something<T> {}
impl<T, U> Something<U> for T {}
type Tait2 = impl Something<Tait1>;
fn foo(x: Tait1) -> Tait2 {
let () = x;
}
}
mod ex4 {
type Tait1 = impl Sized;
//[current]~^ ERROR unconstrained opaque type
trait Trait<U> {
type Assoc;
}
impl<T, U> Trait<U> for T {
type Assoc = T;
}
// ambiguity when checking that `Tait2` is wf
//
// ambiguity proving `(): Trait<Tait1>`.
type Tait2 = impl Trait<(), Assoc = impl Trait<Tait1>>;
fn foo(x: Tait1) -> Tait2 {
let () = x;
}
}
fn main() {}