diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index 69c090b662e54..3ab39e83f3123 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -61,37 +61,108 @@ impl<'tcx> 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 + self.instantiate_var( + relation, + target_is_expected, + target_vid.into(), + instantiation_variance, + source_ty.into(), + ) + } + + /// Instantiates the const variable `target_vid` with the given constant. + /// + /// This also tests if the given const `ct` contains an inference variable which was previously + /// unioned with `target_vid`. If this is the case, inferring `target_vid` to `ct` + /// would result in an infinite type as we continuously replace an inference variable + /// in `ct` with `ct` itself. + /// + /// This is especially important as unevaluated consts use their parents generics. + /// They therefore often contain unused args, making these errors far more likely. + /// + /// A good example of this is the following: + /// + /// ```compile_fail,E0308 + /// #![feature(generic_const_exprs)] + /// + /// fn bind(value: [u8; N]) -> [u8; 3 + 4] { + /// todo!() + /// } + /// + /// fn main() { + /// let mut arr = Default::default(); + /// arr = bind(arr); + /// } + /// ``` + /// + /// Here `3 + 4` ends up as `ConstKind::Unevaluated` which uses the generics + /// of `fn bind` (meaning that its args contain `N`). + /// + /// `bind(arr)` now infers that the type of `arr` must be `[u8; N]`. + /// The assignment `arr = bind(arr)` now tries to equate `N` with `3 + 4`. + /// + /// As `3 + 4` contains `N` in its args, this must not succeed. + /// + /// See `tests/ui/const-generics/occurs-check/` for more examples where this is relevant. + #[instrument(level = "debug", skip(self, relation))] + pub(crate) fn instantiate_const_var>>( + &self, + relation: &mut R, + target_is_expected: bool, + target_vid: ty::ConstVid, + source_ct: ty::Const<'tcx>, + ) -> RelateResult<'tcx, ()> { + // FIXME(generic_const_exprs): Occurs check failures for unevaluated + // constants and generic expressions are not yet handled correctly. + 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>( + &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_ty` would be `&'?2 ?3`, where `'?2` and `?3` are fresh + // Then the `generalized_term` 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 + // We then relate `generalized_term <: source_term`, adding constraints like `'x: '?2` and // `?1 <: ?3`. - let Generalization { value_may_be_infer: generalized_ty } = self.generalize( + let Generalization { value_may_be_infer: generalized_term } = self.generalize( relation.span(), relation.structurally_relate_aliases(), target_vid, instantiation_variance, - source_ty, + source_term, )?; - // 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); - } + // Constrain `b_vid` to the generalized type `generalized_term`. + self.union_var_term(target_vid, generalized_term); - // Finally, relate `generalized_ty` to `source_ty`, as described in previous comment. + // 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_ty.is_ty_var() { + if generalized_term.is_infer() { // This happens for cases like `::Assoc == ?0`. // We can't instantiate `?0` here as that would result in a // cyclic type. We instead delay the unification in case @@ -100,42 +171,51 @@ impl<'tcx> InferCtxt<'tcx> { if self.next_trait_solver() { let (lhs, rhs, direction) = match instantiation_variance { ty::Invariant => { - (generalized_ty.into(), source_ty.into(), AliasRelationDirection::Equate) + (generalized_term, source_term, AliasRelationDirection::Equate) } ty::Covariant => { - (generalized_ty.into(), source_ty.into(), AliasRelationDirection::Subtype) + (generalized_term, source_term, AliasRelationDirection::Subtype) } ty::Contravariant => { - (source_ty.into(), generalized_ty.into(), AliasRelationDirection::Subtype) + (source_term, generalized_term, 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) => { + 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_ty`. + // `?normalized_source <: generalized_term`. relation.register_predicates([ty::ProjectionPredicate { - projection_term: data.into(), - term: generalized_ty.into(), + projection_term: source_alias, + term: generalized_term, }]); } // The old solver only accepts projection predicates for associated types. - ty::Alias(ty::Inherent | ty::Free | ty::Opaque, _) => { - return Err(TypeError::CyclicTy(source_ty)); + 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())); } - _ => 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, + // constrain the `generalized_term` while using the original relation, // we therefore only have to flip the arguments. // // ```ignore (not code) @@ -149,109 +229,76 @@ impl<'tcx> InferCtxt<'tcx> { // 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)?; + 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(()) } - /// Instantiates the const variable `target_vid` with the given constant. - /// - /// This also tests if the given const `ct` contains an inference variable which was previously - /// unioned with `target_vid`. If this is the case, inferring `target_vid` to `ct` - /// would result in an infinite type as we continuously replace an inference variable - /// in `ct` with `ct` itself. - /// - /// This is especially important as unevaluated consts use their parents generics. - /// They therefore often contain unused args, making these errors far more likely. - /// - /// A good example of this is the following: - /// - /// ```compile_fail,E0308 - /// #![feature(generic_const_exprs)] - /// - /// fn bind(value: [u8; N]) -> [u8; 3 + 4] { - /// todo!() - /// } - /// - /// fn main() { - /// let mut arr = Default::default(); - /// arr = bind(arr); - /// } - /// ``` - /// - /// Here `3 + 4` ends up as `ConstKind::Unevaluated` which uses the generics - /// of `fn bind` (meaning that its args contain `N`). - /// - /// `bind(arr)` now infers that the type of `arr` must be `[u8; N]`. - /// The assignment `arr = bind(arr)` now tries to equate `N` with `3 + 4`. - /// - /// As `3 + 4` contains `N` in its args, this must not succeed. - /// - /// See `tests/ui/const-generics/occurs-check/` for more examples where this is relevant. - #[instrument(level = "debug", skip(self, relation))] - pub(crate) fn instantiate_const_var>>( - &self, - relation: &mut R, - target_is_expected: bool, - target_vid: ty::ConstVid, - source_ct: ty::Const<'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( - relation.span(), - relation.structurally_relate_aliases(), - target_vid, - ty::Invariant, - source_ct, - )?; - - debug_assert!(!generalized_ct.is_ct_infer()); - - self.inner - .borrow_mut() - .const_unification_table() - .union_value(target_vid, ConstVariableValue::Known { value: generalized_ct }); - - // 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, - )?; - } else { - relation.relate_with_variance( - ty::Invariant, - ty::VarianceDiagInfo::default(), - source_ct, - generalized_ct, - )?; + /// 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:?}"), } - - Ok(()) } /// 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> + Relate>>( + fn generalize( &self, span: Span, structurally_relate_aliases: StructurallyRelateAliases, - target_vid: impl Into, + target_vid: TermVid, ambient_variance: ty::Variance, - source_term: T, - ) -> RelateResult<'tcx, Generalization> { + source_term: Term<'tcx>, + ) -> RelateResult<'tcx, Generalization>> { 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 @@ impl<'tcx> InferCtxt<'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 @@ impl<'tcx> Generalizer<'_, '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 @@ impl<'tcx> Generalizer<'_, '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, TypeError<'tcx>> { + alias: ty::AliasTerm<'tcx>, + ) -> Result, 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 @@ impl<'tcx> Generalizer<'_, 'tcx> { // // 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 @@ impl<'tcx> Generalizer<'_, 'tcx> { } 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 @@ impl<'tcx> TypeRelation> for Generalizer<'_, '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 @@ impl<'tcx> TypeRelation> for Generalizer<'_, 'tcx> { // 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) diff --git a/compiler/rustc_infer/src/infer/unify_key.rs b/compiler/rustc_infer/src/infer/unify_key.rs index 5e5d0e063a0d7..4016054d8974e 100644 --- a/compiler/rustc_infer/src/infer/unify_key.rs +++ b/compiler/rustc_infer/src/infer/unify_key.rs @@ -110,6 +110,13 @@ impl<'tcx> ConstVariableValue<'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)] diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index aade274bfc98c..d342e4ba5efae 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -323,6 +323,13 @@ impl<'tcx> Const<'tcx> { matches!(self.kind(), ty::ConstKind::Infer(_)) } + pub fn ct_vid(self) -> Option { + 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 diff --git a/tests/ui/coherence/occurs-check/associated-type.next.stderr b/tests/ui/coherence/occurs-check/associated-type.next.stderr index 52794b19945b6..381f5c60f9831 100644 --- a/tests/ui/coherence/occurs-check/associated-type.next.stderr +++ b/tests/ui/coherence/occurs-check/associated-type.next.stderr @@ -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 fn(&'a (), ())>` for type `for<'a> fn(&'a (), ())` --> $DIR/associated-type.rs:32:1 | diff --git a/tests/ui/coherence/occurs-check/associated-type.old.stderr b/tests/ui/coherence/occurs-check/associated-type.old.stderr index 9fa443eefb3dc..40811a67dd180 100644 --- a/tests/ui/coherence/occurs-check/associated-type.old.stderr +++ b/tests/ui/coherence/occurs-check/associated-type.old.stderr @@ -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 fn(&'a (), ())>` for type `for<'a> fn(&'a (), ())` --> $DIR/associated-type.rs:32:1 | diff --git a/tests/ui/const-generics/mgca/free-type-alias-recursive.rs b/tests/ui/const-generics/mgca/free-type-alias-recursive.rs new file mode 100644 index 0000000000000..8d75c1a941a77 --- /dev/null +++ b/tests/ui/const-generics/mgca/free-type-alias-recursive.rs @@ -0,0 +1,13 @@ +//! Regression test for +//@ 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; +} diff --git a/tests/ui/const-generics/mgca/free-type-alias-recursive.stderr b/tests/ui/const-generics/mgca/free-type-alias-recursive.stderr new file mode 100644 index 0000000000000..df1bb0e8101a6 --- /dev/null +++ b/tests/ui/const-generics/mgca/free-type-alias-recursive.stderr @@ -0,0 +1,15 @@ +error[E0271]: type mismatch resolving `A normalizes-to _` + --> $DIR/free-type-alias-recursive.rs:7:1 + | +LL | type const A: () = A; + | ^^^^^^^^^^^^^^^^ types differ + +error: the constant `A` is not of type `()` + --> $DIR/free-type-alias-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`. diff --git a/tests/ui/const-generics/ogca/coherence-ambiguous.rs b/tests/ui/const-generics/ogca/coherence-ambiguous.rs index 21efe4cfe9818..bb20c0457c03d 100644 --- a/tests/ui/const-generics/ogca/coherence-ambiguous.rs +++ b/tests/ui/const-generics/ogca/coherence-ambiguous.rs @@ -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() {} diff --git a/tests/ui/const-generics/ogca/coherence-ambiguous.stderr b/tests/ui/const-generics/ogca/coherence-ambiguous.stderr new file mode 100644 index 0000000000000..919a0c8d70e94 --- /dev/null +++ b/tests/ui/const-generics/ogca/coherence-ambiguous.stderr @@ -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`. diff --git a/tests/ui/higher-ranked/structually-relate-aliases.stderr b/tests/ui/higher-ranked/structually-relate-aliases.stderr index b27a2dcceb138..f8fcb73db4478 100644 --- a/tests/ui/higher-ranked/structually-relate-aliases.stderr +++ b/tests/ui/higher-ranked/structually-relate-aliases.stderr @@ -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 | diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.stderr b/tests/ui/traits/next-solver/issue-118950-root-region.stderr index 5516f1e36089a..a4c8d259406b0 100644 --- a/tests/ui/traits/next-solver/issue-118950-root-region.stderr +++ b/tests/ui/traits/next-solver/issue-118950-root-region.stderr @@ -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.