mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Properly generalize unevaluated consts
This commit is contained in:
@@ -61,103 +61,13 @@ pub fn instantiate_ty_var<R: PredicateEmittingRelation<InferCtxt<'tcx>>>(
|
||||
) -> RelateResult<'tcx, ()> {
|
||||
debug_assert!(self.inner.borrow_mut().type_variables().probe(target_vid).is_unknown());
|
||||
|
||||
// Generalize `source_ty` depending on the current variance. As an example, assume
|
||||
// `?target <: &'x ?1`, where `'x` is some free region and `?1` is an inference
|
||||
// variable.
|
||||
//
|
||||
// Then the `generalized_ty` would be `&'?2 ?3`, where `'?2` and `?3` are fresh
|
||||
// region/type inference variables.
|
||||
//
|
||||
// We then relate `generalized_ty <: source_ty`, adding constraints like `'x: '?2` and
|
||||
// `?1 <: ?3`.
|
||||
let Generalization { value_may_be_infer: generalized_ty } = self.generalize(
|
||||
relation.span(),
|
||||
relation.structurally_relate_aliases(),
|
||||
target_vid,
|
||||
self.instantiate_var(
|
||||
relation,
|
||||
target_is_expected,
|
||||
target_vid.into(),
|
||||
instantiation_variance,
|
||||
source_ty,
|
||||
)?;
|
||||
|
||||
// Constrain `b_vid` to the generalized type `generalized_ty`.
|
||||
if let &ty::Infer(ty::TyVar(generalized_vid)) = generalized_ty.kind() {
|
||||
self.inner.borrow_mut().type_variables().equate(target_vid, generalized_vid);
|
||||
} else {
|
||||
self.inner.borrow_mut().type_variables().instantiate(target_vid, generalized_ty);
|
||||
}
|
||||
|
||||
// Finally, relate `generalized_ty` to `source_ty`, as described in previous comment.
|
||||
//
|
||||
// FIXME(#16847): This code is non-ideal because all these subtype
|
||||
// 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.
|
||||
if generalized_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`.
|
||||
if self.next_trait_solver() {
|
||||
let (lhs, rhs, direction) = match instantiation_variance {
|
||||
ty::Invariant => {
|
||||
(generalized_ty.into(), source_ty.into(), AliasRelationDirection::Equate)
|
||||
}
|
||||
ty::Covariant => {
|
||||
(generalized_ty.into(), source_ty.into(), AliasRelationDirection::Subtype)
|
||||
}
|
||||
ty::Contravariant => {
|
||||
(source_ty.into(), generalized_ty.into(), AliasRelationDirection::Subtype)
|
||||
}
|
||||
ty::Bivariant => unreachable!("bivariant generalization"),
|
||||
};
|
||||
|
||||
relation.register_predicates([ty::PredicateKind::AliasRelate(lhs, rhs, direction)]);
|
||||
} else {
|
||||
match source_ty.kind() {
|
||||
&ty::Alias(ty::Projection, data) => {
|
||||
// FIXME: This does not handle subtyping correctly, we could
|
||||
// instead create a new inference variable `?normalized_source`, emitting
|
||||
// `Projection(normalized_source, ?ty_normalized)` and
|
||||
// `?normalized_source <: generalized_ty`.
|
||||
relation.register_predicates([ty::ProjectionPredicate {
|
||||
projection_term: data.into(),
|
||||
term: generalized_ty.into(),
|
||||
}]);
|
||||
}
|
||||
// The old solver only accepts projection predicates for associated types.
|
||||
ty::Alias(ty::Inherent | ty::Free | ty::Opaque, _) => {
|
||||
return Err(TypeError::CyclicTy(source_ty));
|
||||
}
|
||||
_ => bug!("generalized `{source_ty:?} to infer, not an alias"),
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// NOTE: The `instantiation_variance` is not the same variance as
|
||||
// used by the relation. When instantiating `b`, `target_is_expected`
|
||||
// is flipped and the `instantiation_variance` is also flipped. To
|
||||
// constrain the `generalized_ty` while using the original relation,
|
||||
// we therefore only have to flip the arguments.
|
||||
//
|
||||
// ```ignore (not code)
|
||||
// ?a rel B
|
||||
// instantiate_ty_var(?a, B) # expected and variance not flipped
|
||||
// B' rel B
|
||||
// ```
|
||||
// or
|
||||
// ```ignore (not code)
|
||||
// A rel ?b
|
||||
// instantiate_ty_var(?b, A) # expected and variance flipped
|
||||
// A rel A'
|
||||
// ```
|
||||
if target_is_expected {
|
||||
relation.relate(generalized_ty, source_ty)?;
|
||||
} else {
|
||||
debug!("flip relation");
|
||||
relation.relate(source_ty, generalized_ty)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
source_ty.into(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Instantiates the const variable `target_vid` with the given constant.
|
||||
@@ -204,54 +114,191 @@ pub(crate) fn instantiate_const_var<R: PredicateEmittingRelation<InferCtxt<'tcx>
|
||||
) -> RelateResult<'tcx, ()> {
|
||||
// FIXME(generic_const_exprs): Occurs check failures for unevaluated
|
||||
// constants and generic expressions are not yet handled correctly.
|
||||
let Generalization { value_may_be_infer: generalized_ct } = self.generalize(
|
||||
debug_assert!(
|
||||
self.inner.borrow_mut().const_unification_table().probe_value(target_vid).is_unknown()
|
||||
);
|
||||
|
||||
self.instantiate_var(
|
||||
relation,
|
||||
target_is_expected,
|
||||
target_vid.into(),
|
||||
ty::Invariant,
|
||||
source_ct.into(),
|
||||
)
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self, relation))]
|
||||
fn instantiate_var<R: PredicateEmittingRelation<Self>>(
|
||||
&self,
|
||||
relation: &mut R,
|
||||
target_is_expected: bool,
|
||||
target_vid: TermVid,
|
||||
instantiation_variance: ty::Variance,
|
||||
source_term: Term<'tcx>,
|
||||
) -> RelateResult<'tcx, ()> {
|
||||
// Generalize `source_term` depending on the current variance. As an example, assume
|
||||
// `?target <: &'x ?1`, where `'x` is some free region and `?1` is an inference
|
||||
// variable.
|
||||
//
|
||||
// Then the `generalized_term` would be `&'?2 ?3`, where `'?2` and `?3` are fresh
|
||||
// region/type inference variables.
|
||||
//
|
||||
// We then relate `generalized_term <: source_term`, adding constraints like `'x: '?2` and
|
||||
// `?1 <: ?3`.
|
||||
let Generalization { value_may_be_infer: generalized_term } = self.generalize(
|
||||
relation.span(),
|
||||
relation.structurally_relate_aliases(),
|
||||
target_vid,
|
||||
ty::Invariant,
|
||||
source_ct,
|
||||
instantiation_variance,
|
||||
source_term,
|
||||
)?;
|
||||
|
||||
debug_assert!(!generalized_ct.is_ct_infer());
|
||||
// Constrain `b_vid` to the generalized type `generalized_term`.
|
||||
self.union_var_term(target_vid, generalized_term);
|
||||
|
||||
self.inner
|
||||
.borrow_mut()
|
||||
.const_unification_table()
|
||||
.union_value(target_vid, ConstVariableValue::Known { value: generalized_ct });
|
||||
// Finally, relate `generalized_term` to `source_term`, as described in previous comment.
|
||||
//
|
||||
// FIXME(#16847): This code is non-ideal because all these subtype
|
||||
// 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.
|
||||
if generalized_term.is_infer() {
|
||||
// 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`.
|
||||
if self.next_trait_solver() {
|
||||
let (lhs, rhs, direction) = match instantiation_variance {
|
||||
ty::Invariant => {
|
||||
(generalized_term, source_term, AliasRelationDirection::Equate)
|
||||
}
|
||||
ty::Covariant => {
|
||||
(generalized_term, source_term, AliasRelationDirection::Subtype)
|
||||
}
|
||||
ty::Contravariant => {
|
||||
(source_term, generalized_term, AliasRelationDirection::Subtype)
|
||||
}
|
||||
ty::Bivariant => unreachable!("bivariant generalization"),
|
||||
};
|
||||
|
||||
// Make sure that the order is correct when relating the
|
||||
// generalized const and the source.
|
||||
if target_is_expected {
|
||||
relation.relate_with_variance(
|
||||
ty::Invariant,
|
||||
ty::VarianceDiagInfo::default(),
|
||||
generalized_ct,
|
||||
source_ct,
|
||||
)?;
|
||||
relation.register_predicates([ty::PredicateKind::AliasRelate(lhs, rhs, direction)]);
|
||||
} else {
|
||||
let Some(source_alias) = source_term.to_alias_term() else {
|
||||
bug!("generalized `{source_term:?} to infer, not an alias");
|
||||
};
|
||||
match source_alias.kind(self.tcx) {
|
||||
ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst => {
|
||||
// FIXME: This does not handle subtyping correctly, we could
|
||||
// instead create a new inference variable `?normalized_source`, emitting
|
||||
// `Projection(normalized_source, ?ty_normalized)` and
|
||||
// `?normalized_source <: generalized_term`.
|
||||
relation.register_predicates([ty::ProjectionPredicate {
|
||||
projection_term: source_alias,
|
||||
term: generalized_term,
|
||||
}]);
|
||||
}
|
||||
// The old solver only accepts projection predicates for associated types.
|
||||
ty::AliasTermKind::InherentTy
|
||||
| ty::AliasTermKind::FreeTy
|
||||
| ty::AliasTermKind::OpaqueTy => {
|
||||
return Err(TypeError::CyclicTy(source_term.expect_type()));
|
||||
}
|
||||
ty::AliasTermKind::InherentConst
|
||||
| ty::AliasTermKind::FreeConst
|
||||
| ty::AliasTermKind::UnevaluatedConst => {
|
||||
return Err(TypeError::CyclicConst(source_term.expect_const()));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
relation.relate_with_variance(
|
||||
ty::Invariant,
|
||||
ty::VarianceDiagInfo::default(),
|
||||
source_ct,
|
||||
generalized_ct,
|
||||
)?;
|
||||
// NOTE: The `instantiation_variance` is not the same variance as
|
||||
// used by the relation. When instantiating `b`, `target_is_expected`
|
||||
// is flipped and the `instantiation_variance` is also flipped. To
|
||||
// constrain the `generalized_term` while using the original relation,
|
||||
// we therefore only have to flip the arguments.
|
||||
//
|
||||
// ```ignore (not code)
|
||||
// ?a rel B
|
||||
// instantiate_ty_var(?a, B) # expected and variance not flipped
|
||||
// B' rel B
|
||||
// ```
|
||||
// or
|
||||
// ```ignore (not code)
|
||||
// A rel ?b
|
||||
// instantiate_ty_var(?b, A) # expected and variance flipped
|
||||
// A rel A'
|
||||
// ```
|
||||
match generalized_term.kind() {
|
||||
ty::TermKind::Ty(_) => {
|
||||
if target_is_expected {
|
||||
relation.relate(generalized_term, source_term)?;
|
||||
} else {
|
||||
debug!("flip relation");
|
||||
relation.relate(source_term, generalized_term)?;
|
||||
}
|
||||
}
|
||||
ty::TermKind::Const(_) => {
|
||||
// Override consts to always be invariant
|
||||
if target_is_expected {
|
||||
relation.relate_with_variance(
|
||||
ty::Invariant,
|
||||
ty::VarianceDiagInfo::default(),
|
||||
generalized_term,
|
||||
source_term,
|
||||
)?;
|
||||
} else {
|
||||
relation.relate_with_variance(
|
||||
ty::Invariant,
|
||||
ty::VarianceDiagInfo::default(),
|
||||
source_term,
|
||||
generalized_term,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// This is a thin wrapper around inserting into the var tables. You probably want
|
||||
/// [`Self::instantiate_var`] instead, which calls this method.
|
||||
fn union_var_term(&self, l: TermVid, r: ty::Term<'tcx>) {
|
||||
match (l, r.kind()) {
|
||||
(TermVid::Ty(l), ty::TermKind::Ty(r)) => {
|
||||
if let Some(r) = r.ty_vid() {
|
||||
self.inner.borrow_mut().type_variables().equate(l, r)
|
||||
} else {
|
||||
self.inner.borrow_mut().type_variables().instantiate(l, r)
|
||||
}
|
||||
}
|
||||
(TermVid::Const(l), ty::TermKind::Const(r)) => {
|
||||
if let Some(r) = r.ct_vid() {
|
||||
self.inner.borrow_mut().const_unification_table().union(l, r)
|
||||
} else {
|
||||
self.inner
|
||||
.borrow_mut()
|
||||
.const_unification_table()
|
||||
.union_value(l, ConstVariableValue::Known { value: r })
|
||||
}
|
||||
}
|
||||
_ => bug!("mismatched term kinds in generalize: {l:?}, {r:?}"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Attempts to generalize `source_term` for the type variable `target_vid`.
|
||||
/// This checks for cycles -- that is, whether `source_term` references `target_vid`.
|
||||
fn generalize<T: Into<Term<'tcx>> + Relate<TyCtxt<'tcx>>>(
|
||||
fn generalize(
|
||||
&self,
|
||||
span: Span,
|
||||
structurally_relate_aliases: StructurallyRelateAliases,
|
||||
target_vid: impl Into<TermVid>,
|
||||
target_vid: TermVid,
|
||||
ambient_variance: ty::Variance,
|
||||
source_term: T,
|
||||
) -> RelateResult<'tcx, Generalization<T>> {
|
||||
source_term: Term<'tcx>,
|
||||
) -> RelateResult<'tcx, Generalization<Term<'tcx>>> {
|
||||
assert!(!source_term.has_escaping_bound_vars());
|
||||
let (for_universe, root_vid) = match target_vid.into() {
|
||||
let (for_universe, root_vid) = match target_vid {
|
||||
TermVid::Ty(ty_vid) => {
|
||||
(self.probe_ty_var(ty_vid).unwrap_err(), TermVid::Ty(self.root_var(ty_vid)))
|
||||
}
|
||||
@@ -267,7 +314,7 @@ fn generalize<T: Into<Term<'tcx>> + Relate<TyCtxt<'tcx>>>(
|
||||
structurally_relate_aliases,
|
||||
root_vid,
|
||||
for_universe,
|
||||
root_term: source_term.into(),
|
||||
root_term: source_term,
|
||||
ambient_variance,
|
||||
in_alias: false,
|
||||
cache: Default::default(),
|
||||
@@ -377,8 +424,12 @@ fn cyclic_term_error(&self) -> TypeError<'tcx> {
|
||||
|
||||
/// Create a new type variable in the universe of the target when
|
||||
/// generalizing an alias.
|
||||
fn next_ty_var_for_alias(&self) -> Ty<'tcx> {
|
||||
self.infcx.next_ty_var_in_universe(self.span, self.for_universe)
|
||||
fn next_var_for_alias_of_kind(&self, alias: ty::AliasTerm<'tcx>) -> ty::Term<'tcx> {
|
||||
if alias.kind(self.cx()).is_type() {
|
||||
self.infcx.next_ty_var_in_universe(self.span, self.for_universe).into()
|
||||
} else {
|
||||
self.infcx.next_const_var_in_universe(self.span, self.for_universe).into()
|
||||
}
|
||||
}
|
||||
|
||||
/// An occurs check failure inside of an alias does not mean
|
||||
@@ -399,10 +450,10 @@ fn next_ty_var_for_alias(&self) -> Ty<'tcx> {
|
||||
/// continue generalizing the alias. This ends up pulling down the universe of the
|
||||
/// inference variable and is incomplete in case the alias would normalize to a type
|
||||
/// which does not mention that inference variable.
|
||||
fn generalize_alias_ty(
|
||||
fn generalize_alias_term(
|
||||
&mut self,
|
||||
alias: ty::AliasTy<'tcx>,
|
||||
) -> Result<Ty<'tcx>, TypeError<'tcx>> {
|
||||
alias: ty::AliasTerm<'tcx>,
|
||||
) -> Result<Term<'tcx>, TypeError<'tcx>> {
|
||||
// We do not eagerly replace aliases with inference variables if they have
|
||||
// escaping bound vars, see the method comment for details. However, when we
|
||||
// are inside of an alias with escaping bound vars replacing nested aliases
|
||||
@@ -410,12 +461,12 @@ fn generalize_alias_ty(
|
||||
//
|
||||
// cc trait-system-refactor-initiative#110
|
||||
if self.infcx.next_trait_solver() && !alias.has_escaping_bound_vars() && !self.in_alias {
|
||||
return Ok(self.next_ty_var_for_alias());
|
||||
return Ok(self.next_var_for_alias_of_kind(alias));
|
||||
}
|
||||
|
||||
let is_nested_alias = mem::replace(&mut self.in_alias, true);
|
||||
let result = match self.relate(alias, alias) {
|
||||
Ok(alias) => Ok(alias.to_ty(self.cx())),
|
||||
Ok(alias) => Ok(alias.to_term(self.cx())),
|
||||
Err(e) => {
|
||||
if is_nested_alias {
|
||||
return Err(e);
|
||||
@@ -430,7 +481,7 @@ fn generalize_alias_ty(
|
||||
}
|
||||
|
||||
debug!("generalization failure in alias");
|
||||
Ok(self.next_ty_var_for_alias())
|
||||
Ok(self.next_var_for_alias_of_kind(alias))
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -585,7 +636,9 @@ fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
|
||||
}
|
||||
|
||||
ty::Alias(_, data) => match self.structurally_relate_aliases {
|
||||
StructurallyRelateAliases::No => self.generalize_alias_ty(data),
|
||||
StructurallyRelateAliases::No => {
|
||||
self.generalize_alias_term(data.into()).map(|v| v.expect_type())
|
||||
}
|
||||
StructurallyRelateAliases::Yes => relate::structurally_relate_tys(self, t, t),
|
||||
},
|
||||
|
||||
@@ -695,17 +748,26 @@ fn consts(
|
||||
// FIXME: Unevaluated constants are also not rigid, so the current
|
||||
// approach of always relating them structurally is incomplete.
|
||||
//
|
||||
// FIXME: remove this branch once `structurally_relate_consts` is fully
|
||||
// structural.
|
||||
ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args }) => {
|
||||
let args = self.relate_with_variance(
|
||||
ty::Invariant,
|
||||
ty::VarianceDiagInfo::default(),
|
||||
args,
|
||||
args,
|
||||
)?;
|
||||
Ok(ty::Const::new_unevaluated(self.cx(), ty::UnevaluatedConst { def, args }))
|
||||
}
|
||||
// FIXME: replace the StructurallyRelateAliases::Yes branch with
|
||||
// `structurally_relate_consts` once it is fully structural.
|
||||
ty::ConstKind::Unevaluated(uv) => match self.structurally_relate_aliases {
|
||||
// Hack: Fall back to old behavior if GCE is enabled (it used to just be the Yes
|
||||
// path), as doing this new No path breaks some GCE things. I expect GCE to be
|
||||
// ripped out soon so this shouldn't matter soon.
|
||||
StructurallyRelateAliases::No if !self.cx().features().generic_const_exprs() => {
|
||||
self.generalize_alias_term(uv.into()).map(|v| v.expect_const())
|
||||
}
|
||||
_ => {
|
||||
let ty::UnevaluatedConst { def, args } = uv;
|
||||
let args = self.relate_with_variance(
|
||||
ty::Invariant,
|
||||
ty::VarianceDiagInfo::default(),
|
||||
args,
|
||||
args,
|
||||
)?;
|
||||
Ok(ty::Const::new_unevaluated(self.cx(), ty::UnevaluatedConst { def, args }))
|
||||
}
|
||||
},
|
||||
ty::ConstKind::Placeholder(placeholder) => {
|
||||
if self.for_universe.can_name(placeholder.universe) {
|
||||
Ok(c)
|
||||
|
||||
@@ -110,6 +110,13 @@ pub(crate) fn known(&self) -> Option<ty::Const<'tcx>> {
|
||||
ConstVariableValue::Known { value } => Some(value),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn is_unknown(&self) -> bool {
|
||||
match *self {
|
||||
ConstVariableValue::Unknown { .. } => true,
|
||||
ConstVariableValue::Known { .. } => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Copy, Clone, Debug)]
|
||||
|
||||
@@ -323,6 +323,13 @@ pub fn is_ct_infer(self) -> bool {
|
||||
matches!(self.kind(), ty::ConstKind::Infer(_))
|
||||
}
|
||||
|
||||
pub fn ct_vid(self) -> Option<ty::ConstVid> {
|
||||
match self.kind() {
|
||||
ConstKind::Infer(ty::InferConst::Var(vid)) => Some(vid),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterator that walks `self` and any types reachable from
|
||||
/// `self`, in depth-first order. Note that just walks the types
|
||||
/// that appear in `self`, it does not descend into the fields of
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1))], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. }
|
||||
WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1))], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. }
|
||||
WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTerm { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1))], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. }
|
||||
WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTerm { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1))], 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:32:1
|
||||
|
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1))], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. }
|
||||
WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1))], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. }
|
||||
WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTerm { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1))], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. }
|
||||
WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTerm { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1))], 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:32:1
|
||||
|
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
//! Regression test for <https://github.com/rust-lang/rust/issues/153831>
|
||||
//@ check-fail
|
||||
//@compile-flags: -Znext-solver=globally --emit=obj
|
||||
#![feature(min_generic_const_args)]
|
||||
#![expect(incomplete_features)]
|
||||
|
||||
type const A: () = A;
|
||||
//~^ ERROR type mismatch resolving `A normalizes-to _`
|
||||
//~| ERROR the constant `A` is not of type `()`
|
||||
|
||||
fn main() {
|
||||
A;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
error[E0271]: type mismatch resolving `A normalizes-to _`
|
||||
--> $DIR/free-const-recursive.rs:7:1
|
||||
|
|
||||
LL | type const A: () = A;
|
||||
| ^^^^^^^^^^^^^^^^ types differ
|
||||
|
||||
error: the constant `A` is not of type `()`
|
||||
--> $DIR/free-const-recursive.rs:7:1
|
||||
|
|
||||
LL | type const A: () = A;
|
||||
| ^^^^^^^^^^^^^^^^ expected `()`, found a different `()`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0271`.
|
||||
@@ -0,0 +1,19 @@
|
||||
//! See also <https://github.com/rust-lang/rust/issues/153831>
|
||||
//@ check-fail
|
||||
//@compile-flags: -Znext-solver=globally --emit=obj
|
||||
#![feature(min_generic_const_args)]
|
||||
#![expect(incomplete_features)]
|
||||
|
||||
trait Trait {
|
||||
type const A: ();
|
||||
}
|
||||
|
||||
impl Trait for () {
|
||||
type const A: () = <() as Trait>::A;
|
||||
//~^ ERROR type mismatch resolving `<() as Trait>::A normalizes-to _`
|
||||
//~| ERROR the constant `<() as Trait>::A` is not of type `()`
|
||||
}
|
||||
|
||||
fn main() {
|
||||
<() as Trait>::A;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
error[E0271]: type mismatch resolving `<() as Trait>::A normalizes-to _`
|
||||
--> $DIR/projection-const-recursive.rs:12:5
|
||||
|
|
||||
LL | type const A: () = <() as Trait>::A;
|
||||
| ^^^^^^^^^^^^^^^^ types differ
|
||||
|
||||
error: the constant `<() as Trait>::A` is not of type `()`
|
||||
--> $DIR/projection-const-recursive.rs:12:5
|
||||
|
|
||||
LL | type const A: () = <() as Trait>::A;
|
||||
| ^^^^^^^^^^^^^^^^ expected `()`, found a different `()`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0271`.
|
||||
@@ -1,5 +1,4 @@
|
||||
// FIXME(ogca): this should ERROR not pass!!
|
||||
//@ check-pass
|
||||
//@ check-fail
|
||||
|
||||
#![feature(generic_const_items, min_generic_const_args, opaque_generic_const_args)]
|
||||
#![expect(incomplete_features)]
|
||||
@@ -12,8 +11,8 @@ trait Trait {}
|
||||
|
||||
impl Trait for [(); FOO::<1>] {}
|
||||
impl Trait for [(); BAR::<1>] {}
|
||||
// FIXME(ogca): this should ERROR!
|
||||
//~^ ERROR conflicting implementations of trait `Trait` for type `[(); FOO::<1>]`
|
||||
impl Trait for [(); BAR::<2>] {}
|
||||
// FIXME(ogca): this should ERROR!
|
||||
//~^ ERROR conflicting implementations of trait `Trait` for type `[(); FOO::<1>]`
|
||||
|
||||
fn main() {}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
error[E0119]: conflicting implementations of trait `Trait` for type `[(); FOO::<1>]`
|
||||
--> $DIR/coherence-ambiguous.rs:13:1
|
||||
|
|
||||
LL | impl Trait for [(); FOO::<1>] {}
|
||||
| ----------------------------- first implementation here
|
||||
LL | impl Trait for [(); BAR::<1>] {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `[(); FOO::<1>]`
|
||||
|
||||
error[E0119]: conflicting implementations of trait `Trait` for type `[(); FOO::<1>]`
|
||||
--> $DIR/coherence-ambiguous.rs:15:1
|
||||
|
|
||||
LL | impl Trait for [(); FOO::<1>] {}
|
||||
| ----------------------------- first implementation here
|
||||
...
|
||||
LL | impl Trait for [(); BAR::<2>] {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `[(); FOO::<1>]`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0119`.
|
||||
@@ -1,4 +1,4 @@
|
||||
WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a))], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit), .. }
|
||||
WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTerm { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a))], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit), .. }
|
||||
error[E0277]: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied
|
||||
--> $DIR/structually-relate-aliases.rs:13:36
|
||||
|
|
||||
|
||||
@@ -16,7 +16,7 @@ help: this trait has no implementations, consider adding one
|
||||
LL | trait ToUnit<'a> {
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a)), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc), .. }
|
||||
WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTerm { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a)), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc), .. }
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0425.
|
||||
|
||||
Reference in New Issue
Block a user