Auto merge of #117088 - lcnr:generalize-alias, r=compiler-errors
generalize: handle occurs check failure in aliases mostly fixes #105787, except for the `for<'a> fn(<<?x as OtherTrait>::Assoc as Trait<'a>>::Assoc) eq ?x` case in https://github.com/rust-lang/trait-system-refactor-initiative/issues/8. r? `@compiler-errors`
This commit is contained in:
commit
25dca40751
@ -326,7 +326,9 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
) -> RelateResult<'tcx, ty::Const<'tcx>> {
|
||||
let span =
|
||||
self.inner.borrow_mut().const_unification_table().probe_value(target_vid).origin.span;
|
||||
let Generalization { value, needs_wf: _ } = generalize::generalize(
|
||||
// FIXME(generic_const_exprs): Occurs check failures for unevaluated
|
||||
// constants and generic expressions are not yet handled correctly.
|
||||
let Generalization { value_may_be_infer: value, needs_wf: _ } = generalize::generalize(
|
||||
self,
|
||||
&mut CombineDelegate { infcx: self, span, param_env },
|
||||
ct,
|
||||
@ -445,7 +447,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
|
||||
// `'?2` and `?3` are fresh region/type inference
|
||||
// variables. (Down below, we will relate `a_ty <: b_ty`,
|
||||
// adding constraints like `'x: '?2` and `?1 <: ?3`.)
|
||||
let Generalization { value: b_ty, needs_wf } = generalize::generalize(
|
||||
let Generalization { value_may_be_infer: b_ty, needs_wf } = generalize::generalize(
|
||||
self.infcx,
|
||||
&mut CombineDelegate {
|
||||
infcx: self.infcx,
|
||||
@ -457,7 +459,6 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
|
||||
ambient_variance,
|
||||
)?;
|
||||
|
||||
debug!(?b_ty);
|
||||
self.infcx.inner.borrow_mut().type_variables().instantiate(b_vid, b_ty);
|
||||
|
||||
if needs_wf {
|
||||
@ -477,19 +478,52 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
|
||||
// relations wind up attributed to the same spans. We need
|
||||
// to associate causes/spans with each of the relations in
|
||||
// the stack to get this right.
|
||||
match ambient_variance {
|
||||
ty::Variance::Invariant => self.equate(a_is_expected).relate(a_ty, b_ty),
|
||||
ty::Variance::Covariant => self.sub(a_is_expected).relate(a_ty, b_ty),
|
||||
ty::Variance::Contravariant => self.sub(a_is_expected).relate_with_variance(
|
||||
ty::Contravariant,
|
||||
ty::VarianceDiagInfo::default(),
|
||||
a_ty,
|
||||
b_ty,
|
||||
),
|
||||
ty::Variance::Bivariant => {
|
||||
unreachable!("no code should be generalizing bivariantly (currently)")
|
||||
if b_ty.is_ty_var() {
|
||||
// This happens for cases like `<?0 as Trait>::Assoc == ?0`.
|
||||
// We can't instantiate `?0` here as that would result in a
|
||||
// cyclic type. We instead delay the unification in case
|
||||
// the alias can be normalized to something which does not
|
||||
// mention `?0`.
|
||||
|
||||
// FIXME(-Ztrait-solver=next): replace this with `AliasRelate`
|
||||
let &ty::Alias(kind, data) = a_ty.kind() else {
|
||||
bug!("generalization should only result in infer vars for aliases");
|
||||
};
|
||||
if !self.infcx.next_trait_solver() {
|
||||
// The old solver only accepts projection predicates for associated types.
|
||||
match kind {
|
||||
ty::AliasKind::Projection => {}
|
||||
ty::AliasKind::Inherent | ty::AliasKind::Weak | ty::AliasKind::Opaque => {
|
||||
return Err(TypeError::CyclicTy(a_ty));
|
||||
}
|
||||
}
|
||||
}
|
||||
}?;
|
||||
|
||||
// FIXME: This does not handle subtyping correctly, we should switch to
|
||||
// alias-relate in the new solver and could instead create a new inference
|
||||
// variable for `a_ty`, emitting `Projection(a_ty, a_infer)` and
|
||||
// `a_infer <: b_ty`.
|
||||
self.obligations.push(Obligation::new(
|
||||
self.tcx(),
|
||||
self.trace.cause.clone(),
|
||||
self.param_env,
|
||||
ty::ProjectionPredicate { projection_ty: data, term: b_ty.into() },
|
||||
))
|
||||
} else {
|
||||
match ambient_variance {
|
||||
ty::Variance::Invariant => self.equate(a_is_expected).relate(a_ty, b_ty),
|
||||
ty::Variance::Covariant => self.sub(a_is_expected).relate(a_ty, b_ty),
|
||||
ty::Variance::Contravariant => self.sub(a_is_expected).relate_with_variance(
|
||||
ty::Contravariant,
|
||||
ty::VarianceDiagInfo::default(),
|
||||
a_ty,
|
||||
b_ty,
|
||||
),
|
||||
ty::Variance::Bivariant => {
|
||||
unreachable!("no code should be generalizing bivariantly (currently)")
|
||||
}
|
||||
}?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1,13 +1,16 @@
|
||||
use std::mem;
|
||||
|
||||
use rustc_data_structures::sso::SsoHashMap;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
|
||||
use rustc_middle::ty::error::TypeError;
|
||||
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
|
||||
use rustc_middle::ty::{self, InferConst, Term, Ty, TyCtxt, TypeVisitableExt};
|
||||
use rustc_middle::ty::visit::MaxUniverse;
|
||||
use rustc_middle::ty::{self, InferConst, Term, Ty, TyCtxt, TypeVisitable, TypeVisitableExt};
|
||||
use rustc_span::Span;
|
||||
|
||||
use crate::infer::nll_relate::TypeRelatingDelegate;
|
||||
use crate::infer::type_variable::TypeVariableValue;
|
||||
use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind, TypeVariableValue};
|
||||
use crate::infer::{InferCtxt, RegionVariableOrigin};
|
||||
|
||||
/// Attempts to generalize `term` for the type variable `for_vid`.
|
||||
@ -38,27 +41,30 @@ pub(super) fn generalize<'tcx, D: GeneralizerDelegate<'tcx>, T: Into<Term<'tcx>>
|
||||
root_vid,
|
||||
for_universe,
|
||||
root_term: term.into(),
|
||||
in_alias: false,
|
||||
needs_wf: false,
|
||||
cache: Default::default(),
|
||||
};
|
||||
|
||||
assert!(!term.has_escaping_bound_vars());
|
||||
let value = generalizer.relate(term, term)?;
|
||||
let value_may_be_infer = generalizer.relate(term, term)?;
|
||||
let needs_wf = generalizer.needs_wf;
|
||||
Ok(Generalization { value, needs_wf })
|
||||
Ok(Generalization { value_may_be_infer, needs_wf })
|
||||
}
|
||||
|
||||
/// Abstracts the handling of region vars between HIR and MIR/NLL typechecking
|
||||
/// in the generalizer code.
|
||||
pub trait GeneralizerDelegate<'tcx> {
|
||||
pub(super) trait GeneralizerDelegate<'tcx> {
|
||||
fn param_env(&self) -> ty::ParamEnv<'tcx>;
|
||||
|
||||
fn forbid_inference_vars() -> bool;
|
||||
|
||||
fn span(&self) -> Span;
|
||||
|
||||
fn generalize_region(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx>;
|
||||
}
|
||||
|
||||
pub struct CombineDelegate<'cx, 'tcx> {
|
||||
pub(super) struct CombineDelegate<'cx, 'tcx> {
|
||||
pub infcx: &'cx InferCtxt<'tcx>,
|
||||
pub param_env: ty::ParamEnv<'tcx>,
|
||||
pub span: Span,
|
||||
@ -73,6 +79,10 @@ impl<'tcx> GeneralizerDelegate<'tcx> for CombineDelegate<'_, 'tcx> {
|
||||
false
|
||||
}
|
||||
|
||||
fn span(&self) -> Span {
|
||||
self.span
|
||||
}
|
||||
|
||||
fn generalize_region(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> {
|
||||
// FIXME: This is non-ideal because we don't give a
|
||||
// very descriptive origin for this region variable.
|
||||
@ -93,6 +103,10 @@ where
|
||||
<Self as TypeRelatingDelegate<'tcx>>::forbid_inference_vars()
|
||||
}
|
||||
|
||||
fn span(&self) -> Span {
|
||||
<Self as TypeRelatingDelegate<'tcx>>::span(&self)
|
||||
}
|
||||
|
||||
fn generalize_region(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> {
|
||||
<Self as TypeRelatingDelegate<'tcx>>::generalize_existential(self, universe)
|
||||
}
|
||||
@ -139,6 +153,13 @@ struct Generalizer<'me, 'tcx, D> {
|
||||
|
||||
cache: SsoHashMap<Ty<'tcx>, Ty<'tcx>>,
|
||||
|
||||
/// This is set once we're generalizing the arguments of an alias.
|
||||
///
|
||||
/// This is necessary to correctly handle
|
||||
/// `<T as Bar<<?0 as Foo>::Assoc>::Assoc == ?0`. This equality can
|
||||
/// hold by either normalizing the outer or the inner associated type.
|
||||
in_alias: bool,
|
||||
|
||||
/// See the field `needs_wf` in `Generalization`.
|
||||
needs_wf: bool,
|
||||
}
|
||||
@ -193,7 +214,7 @@ where
|
||||
opt_variances,
|
||||
a_subst,
|
||||
b_subst,
|
||||
true,
|
||||
false,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -309,6 +330,44 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
ty::Alias(kind, data) => {
|
||||
// An occurs check failure inside of an alias does not mean
|
||||
// that the types definitely don't unify. We may be able
|
||||
// to normalize the alias after all.
|
||||
//
|
||||
// We handle this by lazily equating the alias and generalizing
|
||||
// it to an inference variable.
|
||||
let is_nested_alias = mem::replace(&mut self.in_alias, true);
|
||||
let result = match self.relate(data, data) {
|
||||
Ok(data) => Ok(Ty::new_alias(self.tcx(), kind, data)),
|
||||
Err(e) => {
|
||||
if is_nested_alias {
|
||||
return Err(e);
|
||||
} else {
|
||||
let mut visitor = MaxUniverse::new();
|
||||
t.visit_with(&mut visitor);
|
||||
let infer_replacement_is_complete =
|
||||
self.for_universe.can_name(visitor.max_universe())
|
||||
&& !t.has_escaping_bound_vars();
|
||||
if !infer_replacement_is_complete {
|
||||
warn!("may incompletely handle alias type: {t:?}");
|
||||
}
|
||||
|
||||
debug!("generalization failure in alias");
|
||||
Ok(self.infcx.next_ty_var_in_universe(
|
||||
TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::MiscVariable,
|
||||
span: self.delegate.span(),
|
||||
},
|
||||
self.for_universe,
|
||||
))
|
||||
}
|
||||
}
|
||||
};
|
||||
self.in_alias = is_nested_alias;
|
||||
result
|
||||
}
|
||||
|
||||
_ => relate::structurally_relate_tys(self, t, t),
|
||||
}?;
|
||||
|
||||
@ -456,8 +515,16 @@ where
|
||||
/// not only the generalized type, but also a bool flag
|
||||
/// indicating whether further WF checks are needed.
|
||||
#[derive(Debug)]
|
||||
pub struct Generalization<T> {
|
||||
pub value: T,
|
||||
pub(super) struct Generalization<T> {
|
||||
/// When generalizing `<?0 as Trait>::Assoc` or
|
||||
/// `<T as Bar<<?0 as Foo>::Assoc>>::Assoc`
|
||||
/// for `?0` generalization returns an inference
|
||||
/// variable.
|
||||
///
|
||||
/// This has to be handled wotj care as it can
|
||||
/// otherwise very easily result in infinite
|
||||
/// recursion.
|
||||
pub(super) value_may_be_infer: T,
|
||||
|
||||
/// If true, then the generalized type may not be well-formed,
|
||||
/// even if the source type is well-formed, so we should add an
|
||||
@ -484,5 +551,5 @@ pub struct Generalization<T> {
|
||||
/// will force the calling code to check that `WF(Foo<?C, ?D>)`
|
||||
/// holds, which in turn implies that `?C::Item == ?D`. So once
|
||||
/// `?C` is constrained, that should suffice to restrict `?D`.
|
||||
pub needs_wf: bool,
|
||||
pub(super) needs_wf: bool,
|
||||
}
|
||||
|
@ -214,13 +214,17 @@ where
|
||||
}
|
||||
|
||||
fn generalize(&mut self, ty: Ty<'tcx>, for_vid: ty::TyVid) -> RelateResult<'tcx, Ty<'tcx>> {
|
||||
let Generalization { value: ty, needs_wf: _ } = generalize::generalize(
|
||||
let Generalization { value_may_be_infer: ty, needs_wf: _ } = generalize::generalize(
|
||||
self.infcx,
|
||||
&mut self.delegate,
|
||||
ty,
|
||||
for_vid,
|
||||
self.ambient_variance,
|
||||
)?;
|
||||
|
||||
if ty.is_ty_var() {
|
||||
span_bug!(self.delegate.span(), "occurs check failure in MIR typeck");
|
||||
}
|
||||
Ok(ty)
|
||||
}
|
||||
|
||||
|
25
tests/ui/coherence/occurs-check/associated-type.next.stderr
Normal file
25
tests/ui/coherence/occurs-check/associated-type.next.stderr
Normal file
@ -0,0 +1,25 @@
|
||||
WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
|
||||
WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!2_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
|
||||
WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
|
||||
WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!2_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
|
||||
WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
|
||||
WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!2_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
|
||||
WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
|
||||
WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!2_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
|
||||
error[E0119]: conflicting implementations of trait `Overlap<for<'a> fn(&'a (), ())>` for type `for<'a> fn(&'a (), ())`
|
||||
--> $DIR/associated-type.rs:31:1
|
||||
|
|
||||
LL | impl<T> Overlap<T> for T {
|
||||
| ------------------------ first implementation here
|
||||
...
|
||||
LL | / impl<T> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T
|
||||
LL | |
|
||||
LL | | where
|
||||
LL | | for<'a> *const T: ToUnit<'a>,
|
||||
| |_________________________________^ conflicting implementation for `for<'a> fn(&'a (), ())`
|
||||
|
|
||||
= note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0119`.
|
25
tests/ui/coherence/occurs-check/associated-type.old.stderr
Normal file
25
tests/ui/coherence/occurs-check/associated-type.old.stderr
Normal file
@ -0,0 +1,25 @@
|
||||
WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
|
||||
WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!3_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
|
||||
WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
|
||||
WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!3_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
|
||||
WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
|
||||
WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!3_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
|
||||
WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
|
||||
WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!3_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
|
||||
error[E0119]: conflicting implementations of trait `Overlap<for<'a> fn(&'a (), _)>` for type `for<'a> fn(&'a (), _)`
|
||||
--> $DIR/associated-type.rs:31:1
|
||||
|
|
||||
LL | impl<T> Overlap<T> for T {
|
||||
| ------------------------ first implementation here
|
||||
...
|
||||
LL | / impl<T> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T
|
||||
LL | |
|
||||
LL | | where
|
||||
LL | | for<'a> *const T: ToUnit<'a>,
|
||||
| |_________________________________^ conflicting implementation for `for<'a> fn(&'a (), _)`
|
||||
|
|
||||
= note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0119`.
|
45
tests/ui/coherence/occurs-check/associated-type.rs
Normal file
45
tests/ui/coherence/occurs-check/associated-type.rs
Normal file
@ -0,0 +1,45 @@
|
||||
// revisions: old next
|
||||
//[next] compile-flags: -Ztrait-solver=next
|
||||
|
||||
// A regression test for #105787
|
||||
|
||||
// Using the higher ranked projection hack to prevent us from replacing the projection
|
||||
// with an inference variable.
|
||||
trait ToUnit<'a> {
|
||||
type Unit;
|
||||
}
|
||||
|
||||
struct LocalTy;
|
||||
impl<'a> ToUnit<'a> for *const LocalTy {
|
||||
type Unit = ();
|
||||
}
|
||||
|
||||
impl<'a, T: Copy + ?Sized> ToUnit<'a> for *const T {
|
||||
type Unit = ();
|
||||
}
|
||||
|
||||
trait Overlap<T> {
|
||||
type Assoc;
|
||||
}
|
||||
|
||||
type Assoc<'a, T> = <*const T as ToUnit<'a>>::Unit;
|
||||
|
||||
impl<T> Overlap<T> for T {
|
||||
type Assoc = usize;
|
||||
}
|
||||
|
||||
impl<T> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T
|
||||
//~^ ERROR conflicting implementations of trait
|
||||
where
|
||||
for<'a> *const T: ToUnit<'a>,
|
||||
{
|
||||
type Assoc = Box<usize>;
|
||||
}
|
||||
|
||||
fn foo<T: Overlap<U>, U>(x: T::Assoc) -> T::Assoc {
|
||||
x
|
||||
}
|
||||
|
||||
fn main() {
|
||||
foo::<for<'a> fn(&'a (), ()), for<'a> fn(&'a (), ())>(3usize);
|
||||
}
|
12
tests/ui/coherence/occurs-check/opaques.next.stderr
Normal file
12
tests/ui/coherence/occurs-check/opaques.next.stderr
Normal file
@ -0,0 +1,12 @@
|
||||
error[E0119]: conflicting implementations of trait `Trait<Alias<_>>` for type `Alias<_>`
|
||||
--> $DIR/opaques.rs:29:1
|
||||
|
|
||||
LL | impl<T> Trait<T> for T {
|
||||
| ---------------------- first implementation here
|
||||
...
|
||||
LL | impl<T> Trait<T> for defining_scope::Alias<T> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Alias<_>`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0119`.
|
37
tests/ui/coherence/occurs-check/opaques.rs
Normal file
37
tests/ui/coherence/occurs-check/opaques.rs
Normal file
@ -0,0 +1,37 @@
|
||||
//revisions: old next
|
||||
//[next] compile-flags: -Ztrait-solver=next
|
||||
|
||||
// A regression test for #105787
|
||||
|
||||
//[old] known-bug: #105787
|
||||
//[old] check-pass
|
||||
#![feature(type_alias_impl_trait)]
|
||||
mod defining_scope {
|
||||
use super::*;
|
||||
pub type Alias<T> = impl Sized;
|
||||
|
||||
pub fn cast<T>(x: Container<Alias<T>, T>) -> Container<T, T> {
|
||||
x
|
||||
}
|
||||
}
|
||||
|
||||
struct Container<T: Trait<U>, U> {
|
||||
x: <T as Trait<U>>::Assoc,
|
||||
}
|
||||
|
||||
trait Trait<T> {
|
||||
type Assoc;
|
||||
}
|
||||
|
||||
impl<T> Trait<T> for T {
|
||||
type Assoc = Box<u32>;
|
||||
}
|
||||
impl<T> Trait<T> for defining_scope::Alias<T> {
|
||||
//[next]~^ ERROR conflicting implementations of trait
|
||||
type Assoc = usize;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x: Box<u32> = defining_scope::cast::<()>(Container { x: 0 }).x;
|
||||
println!("{}", *x);
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
// check-pass
|
||||
// compile-flags: -Ztrait-solver=next
|
||||
|
||||
trait Test {
|
||||
@ -22,7 +23,9 @@ fn main() {
|
||||
let mut x: Inv<_> = Inv(None);
|
||||
// This ends up equating `Inv<?x>` with `Inv<<?x as Test>::Assoc>`
|
||||
// which fails the occurs check when generalizing `?x`.
|
||||
//
|
||||
// We end up emitting a delayed obligation, causing this to still
|
||||
// succeed.
|
||||
x = transform(x);
|
||||
//~^ ERROR mismatched types
|
||||
x = Inv::<i32>(None);
|
||||
}
|
||||
|
@ -1,9 +0,0 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/equating-projection-cyclically.rs:25:9
|
||||
|
|
||||
LL | x = transform(x);
|
||||
| ^^^^^^^^^^^^ cyclic type of infinite size
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
@ -0,0 +1,9 @@
|
||||
error[E0271]: type mismatch resolving `<<T as Id<_>>::Id as Unnormalizable>::Assoc == _`
|
||||
--> $DIR/occurs-check-nested-alias.rs:35:9
|
||||
|
|
||||
LL | x = y;
|
||||
| ^ types differ
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0271`.
|
@ -0,0 +1,37 @@
|
||||
// revisions: old next
|
||||
//[old] check-pass
|
||||
|
||||
// Need to emit an alias-relate instead of a `Projection` goal here.
|
||||
//[next] compile-flags: -Ztrait-solver=next
|
||||
//[next] known-bug: trait-system-refactor-initiative#8
|
||||
#![crate_type = "lib"]
|
||||
#![allow(unused)]
|
||||
trait Unnormalizable {
|
||||
type Assoc;
|
||||
}
|
||||
|
||||
trait Id<T> {
|
||||
type Id;
|
||||
}
|
||||
impl<T, U> Id<T> for U {
|
||||
type Id = U;
|
||||
}
|
||||
|
||||
struct Inv<T>(*mut T);
|
||||
|
||||
fn unconstrained<T>() -> T {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn create<T, U: Unnormalizable>(
|
||||
x: &U,
|
||||
) -> (Inv<T>, Inv<<<U as Id<T>>::Id as Unnormalizable>::Assoc>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn foo<T: Unnormalizable>() {
|
||||
let q = unconstrained();
|
||||
let (mut x, y) = create::<_, _>(&q);
|
||||
x = y;
|
||||
drop::<T>(q);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user