support revealing defined opaque post borrowck
This commit is contained in:
parent
18e2253e79
commit
34a8c2dbba
21 changed files with 226 additions and 58 deletions
|
@ -322,8 +322,12 @@ fn check_opaque_meets_bounds<'tcx>(
|
|||
};
|
||||
let param_env = tcx.param_env(defining_use_anchor);
|
||||
|
||||
// FIXME(#132279): This should eventually use the already defined hidden types.
|
||||
let infcx = tcx.infer_ctxt().build(TypingMode::analysis_in_body(tcx, defining_use_anchor));
|
||||
// FIXME(#132279): Once `PostBorrowckAnalysis` is supported in the old solver, this branch should be removed.
|
||||
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 args = match origin {
|
||||
|
@ -417,7 +421,11 @@ fn check_opaque_meets_bounds<'tcx>(
|
|||
let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
|
||||
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
|
||||
// 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
|
||||
|
|
|
@ -1574,7 +1574,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
// Thus we need to prevent them from trying to match the `&_` autoref
|
||||
// candidates that get created for `&self` trait methods.
|
||||
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() =>
|
||||
{
|
||||
return ProbeResult::NoMatch;
|
||||
|
|
|
@ -7,7 +7,7 @@ use rustc_middle::ty::relate::combine::PredicateEmittingRelation;
|
|||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
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> {
|
||||
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)
|
||||
}
|
||||
|
||||
fn next_region_infer(&self) -> ty::Region<'tcx> {
|
||||
self.next_region_var(RegionVariableOrigin::MiscVariable(DUMMY_SP))
|
||||
}
|
||||
|
||||
fn next_ty_infer(&self) -> Ty<'tcx> {
|
||||
self.next_ty_var(DUMMY_SP)
|
||||
}
|
||||
|
|
|
@ -990,11 +990,17 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
|
||||
#[inline(always)]
|
||||
pub fn can_define_opaque_ty(&self, id: impl Into<DefId>) -> bool {
|
||||
debug_assert!(!self.next_trait_solver());
|
||||
match self.typing_mode() {
|
||||
TypingMode::Analysis { defining_opaque_types } => {
|
||||
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.
|
||||
pub fn typing_env(&self, param_env: ty::ParamEnv<'tcx>) -> ty::TypingEnv<'tcx> {
|
||||
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
|
||||
// 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
|
||||
|
@ -1284,7 +1289,9 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
ty::TypingMode::Analysis { defining_opaque_types: _ } => {
|
||||
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 }
|
||||
}
|
||||
|
|
|
@ -98,6 +98,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
span: Span,
|
||||
param_env: ty::ParamEnv<'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() {
|
||||
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) if def_id.is_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(())
|
||||
|
|
|
@ -339,7 +339,9 @@ where
|
|||
|
||||
match self.typing_mode() {
|
||||
TypingMode::Coherence => {}
|
||||
TypingMode::Analysis { .. } | TypingMode::PostAnalysis => {
|
||||
TypingMode::Analysis { .. }
|
||||
| TypingMode::PostBorrowckAnalysis { .. }
|
||||
| TypingMode::PostAnalysis => {
|
||||
self.discard_impls_shadowed_by_env(goal, &mut candidates);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
let ty = self.delegate.next_ty_infer();
|
||||
self.inspect.add_var_value(ty);
|
||||
|
|
|
@ -23,7 +23,7 @@ mod trait_goals;
|
|||
|
||||
use rustc_type_ir::inherent::*;
|
||||
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;
|
||||
|
||||
pub use self::eval_ctxt::{EvalCtxt, GenerateProofTree, SolverDelegateEvalExt};
|
||||
|
@ -321,6 +321,19 @@ where
|
|||
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>(
|
||||
|
|
|
@ -6,7 +6,7 @@ mod weak_types;
|
|||
use rustc_type_ir::fast_reject::DeepRejectCtxt;
|
||||
use rustc_type_ir::inherent::*;
|
||||
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 crate::delegate::SolverDelegate;
|
||||
|
@ -71,21 +71,10 @@ where
|
|||
Ok(())
|
||||
}
|
||||
ty::AliasTermKind::OpaqueTy => {
|
||||
match self.typing_mode() {
|
||||
// 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 {
|
||||
if self.opaque_type_is_rigid(rigid_alias.def_id) {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Err(NoSolution)
|
||||
}
|
||||
}
|
||||
// FIXME(generic_const_exprs): we would need to support generic consts here
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
//! behaves differently depending on the current `TypingMode`.
|
||||
|
||||
use rustc_index::bit_set::GrowableBitSet;
|
||||
use rustc_type_ir::fold::fold_regions;
|
||||
use rustc_type_ir::inherent::*;
|
||||
use rustc_type_ir::{self as ty, Interner, TypingMode};
|
||||
|
||||
|
@ -95,6 +96,26 @@ where
|
|||
);
|
||||
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 => {
|
||||
// FIXME: Add an assertion that opaque type storage is empty.
|
||||
let actual = cx.type_of(opaque_ty.def_id).instantiate(cx, opaque_ty.args);
|
||||
|
|
|
@ -69,7 +69,9 @@ where
|
|||
// it's not a real impl.
|
||||
(ty::ImplPolarity::Reservation, _) => match ecx.typing_mode() {
|
||||
TypingMode::Coherence => Certainty::AMBIGUOUS,
|
||||
TypingMode::Analysis { .. } | TypingMode::PostAnalysis => return Err(NoSolution),
|
||||
TypingMode::Analysis { .. }
|
||||
| TypingMode::PostBorrowckAnalysis { .. }
|
||||
| TypingMode::PostAnalysis => return Err(NoSolution),
|
||||
},
|
||||
|
||||
// Impl matches polarity
|
||||
|
@ -174,20 +176,7 @@ where
|
|||
// ideally we want to avoid, since we can make progress on this goal
|
||||
// via an alias bound or a locally-inferred hidden type instead.
|
||||
if let ty::Alias(ty::Opaque, opaque_ty) = goal.predicate.self_ty().kind() {
|
||||
match ecx.typing_mode() {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
debug_assert!(ecx.opaque_type_is_rigid(opaque_ty.def_id));
|
||||
}
|
||||
|
||||
ecx.probe_and_evaluate_goal_for_constituent_tys(
|
||||
|
|
|
@ -205,7 +205,9 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
|
|||
// transmute checking and polymorphic MIR optimizations could
|
||||
// get a result which isn't correct for all monomorphizations.
|
||||
match self.typing_mode() {
|
||||
TypingMode::Coherence | TypingMode::Analysis { .. } => false,
|
||||
TypingMode::Coherence
|
||||
| TypingMode::Analysis { .. }
|
||||
| TypingMode::PostBorrowckAnalysis { .. } => false,
|
||||
TypingMode::PostAnalysis => {
|
||||
let poly_trait_ref = self.resolve_vars_if_possible(goal_trait_ref);
|
||||
!poly_trait_ref.still_further_specializable()
|
||||
|
|
|
@ -118,9 +118,10 @@ pub(super) fn needs_normalization<'tcx, T: TypeVisitable<TyCtxt<'tcx>>>(
|
|||
// Opaques are treated as rigid outside of `TypingMode::PostAnalysis`,
|
||||
// so we can ignore those.
|
||||
match infcx.typing_mode() {
|
||||
TypingMode::Coherence | TypingMode::Analysis { defining_opaque_types: _ } => {
|
||||
flags.remove(ty::TypeFlags::HAS_TY_OPAQUE)
|
||||
}
|
||||
// FIXME(#132279): We likely want to reveal opaques during post borrowck analysis
|
||||
TypingMode::Coherence
|
||||
| TypingMode::Analysis { .. }
|
||||
| TypingMode::PostBorrowckAnalysis { .. } => flags.remove(ty::TypeFlags::HAS_TY_OPAQUE),
|
||||
TypingMode::PostAnalysis => {}
|
||||
}
|
||||
|
||||
|
@ -213,9 +214,10 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
|
|||
ty::Opaque => {
|
||||
// Only normalize `impl Trait` outside of type inference, usually in codegen.
|
||||
match self.selcx.infcx.typing_mode() {
|
||||
TypingMode::Coherence | TypingMode::Analysis { defining_opaque_types: _ } => {
|
||||
ty.super_fold_with(self)
|
||||
}
|
||||
// FIXME(#132279): We likely want to reveal opaques during post borrowck analysis
|
||||
TypingMode::Coherence
|
||||
| TypingMode::Analysis { .. }
|
||||
| TypingMode::PostBorrowckAnalysis { .. } => ty.super_fold_with(self),
|
||||
TypingMode::PostAnalysis => {
|
||||
let recursion_limit = self.cx().recursion_limit();
|
||||
if !recursion_limit.value_within_limit(self.depth) {
|
||||
|
|
|
@ -975,7 +975,9 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
|
|||
// transmute checking and polymorphic MIR optimizations could
|
||||
// get a result which isn't correct for all monomorphizations.
|
||||
match selcx.infcx.typing_mode() {
|
||||
TypingMode::Coherence | TypingMode::Analysis { .. } => {
|
||||
TypingMode::Coherence
|
||||
| TypingMode::Analysis { .. }
|
||||
| TypingMode::PostBorrowckAnalysis { .. } => {
|
||||
debug!(
|
||||
assoc_ty = ?selcx.tcx().def_path_str(node_item.item.def_id),
|
||||
?obligation.predicate,
|
||||
|
|
|
@ -216,9 +216,9 @@ impl<'a, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'a, 'tcx> {
|
|||
ty::Opaque => {
|
||||
// Only normalize `impl Trait` outside of type inference, usually in codegen.
|
||||
match self.infcx.typing_mode() {
|
||||
TypingMode::Coherence | TypingMode::Analysis { defining_opaque_types: _ } => {
|
||||
ty.try_super_fold_with(self)?
|
||||
}
|
||||
TypingMode::Coherence
|
||||
| TypingMode::Analysis { .. }
|
||||
| TypingMode::PostBorrowckAnalysis { .. } => ty.try_super_fold_with(self)?,
|
||||
|
||||
TypingMode::PostAnalysis => {
|
||||
let args = data.args.try_fold_with(self)?;
|
||||
|
|
|
@ -1471,7 +1471,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
let obligation = &stack.obligation;
|
||||
match self.infcx.typing_mode() {
|
||||
TypingMode::Coherence => {}
|
||||
TypingMode::Analysis { .. } | TypingMode::PostAnalysis => return Ok(()),
|
||||
TypingMode::Analysis { .. }
|
||||
| TypingMode::PostBorrowckAnalysis { .. }
|
||||
| TypingMode::PostAnalysis => return Ok(()),
|
||||
}
|
||||
|
||||
debug!("is_knowable()");
|
||||
|
@ -1518,6 +1520,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
TypingMode::Analysis { defining_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 defining scope or we're outside of analysis.
|
||||
//
|
||||
|
|
|
@ -149,7 +149,8 @@ fn resolve_associated_item<'tcx>(
|
|||
// get a result which isn't correct for all monomorphizations.
|
||||
match typing_env.typing_mode {
|
||||
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(),
|
||||
}
|
||||
};
|
||||
|
|
|
@ -63,6 +63,12 @@ pub enum TypingMode<I: Interner> {
|
|||
/// }
|
||||
/// ```
|
||||
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
|
||||
/// 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
|
||||
|
@ -85,6 +91,12 @@ impl<I: Interner> 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) }
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -126,6 +138,7 @@ pub trait InferCtxtLike: Sized {
|
|||
vid: ty::RegionVid,
|
||||
) -> <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_const_infer(&self) -> <Self::Interner as Interner>::Const;
|
||||
fn fresh_args_for_item(
|
||||
|
|
|
@ -136,9 +136,9 @@ where
|
|||
relation.register_predicates([ty::Binder::dummy(ty::PredicateKind::Ambiguous)]);
|
||||
Ok(a)
|
||||
}
|
||||
TypingMode::Analysis { .. } | TypingMode::PostAnalysis => {
|
||||
structurally_relate_tys(relation, a, b)
|
||||
}
|
||||
TypingMode::Analysis { .. }
|
||||
| TypingMode::PostBorrowckAnalysis { .. }
|
||||
| TypingMode::PostAnalysis => structurally_relate_tys(relation, a, b),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
66
tests/ui/traits/next-solver/opaques/no-define-in-wf-check.rs
Normal file
66
tests/ui/traits/next-solver/opaques/no-define-in-wf-check.rs
Normal 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() {}
|
Loading…
Add table
Add a link
Reference in a new issue