Do not deduplicate list of associated types provided by dyn principal
This commit is contained in:
parent
71e06b9c59
commit
72bd174c43
18 changed files with 265 additions and 117 deletions
|
@ -1,4 +1,4 @@
|
||||||
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
|
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
||||||
use rustc_errors::codes::*;
|
use rustc_errors::codes::*;
|
||||||
use rustc_errors::struct_span_code_err;
|
use rustc_errors::struct_span_code_err;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
@ -58,9 +58,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let (trait_bounds, mut projection_bounds) =
|
let (elaborated_trait_bounds, elaborated_projection_bounds) =
|
||||||
traits::expand_trait_aliases(tcx, user_written_bounds.iter().copied());
|
traits::expand_trait_aliases(tcx, user_written_bounds.iter().copied());
|
||||||
let (regular_traits, mut auto_traits): (Vec<_>, Vec<_>) = trait_bounds
|
let (regular_traits, mut auto_traits): (Vec<_>, Vec<_>) = elaborated_trait_bounds
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.partition(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id()));
|
.partition(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id()));
|
||||||
|
|
||||||
|
@ -103,29 +103,81 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Map the projection bounds onto a key that makes it easy to remove redundant
|
||||||
|
// bounds that are constrained by supertraits of the principal def id.
|
||||||
|
//
|
||||||
|
// Also make sure we detect conflicting bounds from expanding a trait alias and
|
||||||
|
// also specifying it manually, like:
|
||||||
|
// ```
|
||||||
|
// type Alias = Trait<Assoc = i32>;
|
||||||
|
// let _: &dyn Alias<Assoc = u32> = /* ... */;
|
||||||
|
// ```
|
||||||
|
let mut projection_bounds = FxIndexMap::default();
|
||||||
|
for (proj, proj_span) in elaborated_projection_bounds {
|
||||||
|
let key = (
|
||||||
|
proj.skip_binder().projection_term.def_id,
|
||||||
|
tcx.anonymize_bound_vars(
|
||||||
|
proj.map_bound(|proj| proj.projection_term.trait_ref(tcx)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
if let Some((old_proj, old_proj_span)) =
|
||||||
|
projection_bounds.insert(key, (proj, proj_span))
|
||||||
|
&& tcx.anonymize_bound_vars(proj) != tcx.anonymize_bound_vars(old_proj)
|
||||||
|
{
|
||||||
|
let item = tcx.item_name(proj.item_def_id());
|
||||||
|
self.dcx()
|
||||||
|
.struct_span_err(
|
||||||
|
span,
|
||||||
|
format!(
|
||||||
|
"conflicting associated type bounds for `{item}` when \
|
||||||
|
expanding trait alias"
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.with_span_label(
|
||||||
|
old_proj_span,
|
||||||
|
format!("`{item}` is specified to be `{}` here", old_proj.term()),
|
||||||
|
)
|
||||||
|
.with_span_label(
|
||||||
|
proj_span,
|
||||||
|
format!("`{item}` is specified to be `{}` here", proj.term()),
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let principal_trait = regular_traits.into_iter().next();
|
let principal_trait = regular_traits.into_iter().next();
|
||||||
|
|
||||||
let mut needed_associated_types = FxIndexSet::default();
|
let mut needed_associated_types = vec![];
|
||||||
if let Some((principal_trait, spans)) = &principal_trait {
|
if let Some((principal_trait, ref spans)) = principal_trait {
|
||||||
let pred: ty::Predicate<'tcx> = (*principal_trait).upcast(tcx);
|
let principal_trait = principal_trait.map_bound(|trait_pred| {
|
||||||
for ClauseWithSupertraitSpan { pred, supertrait_span } in traits::elaborate(
|
assert_eq!(trait_pred.polarity, ty::PredicatePolarity::Positive);
|
||||||
|
trait_pred.trait_ref
|
||||||
|
});
|
||||||
|
|
||||||
|
for ClauseWithSupertraitSpan { clause, supertrait_span } in traits::elaborate(
|
||||||
tcx,
|
tcx,
|
||||||
[ClauseWithSupertraitSpan::new(pred, *spans.last().unwrap())],
|
[ClauseWithSupertraitSpan::new(
|
||||||
|
ty::TraitRef::identity(tcx, principal_trait.def_id()).upcast(tcx),
|
||||||
|
*spans.last().unwrap(),
|
||||||
|
)],
|
||||||
)
|
)
|
||||||
.filter_only_self()
|
.filter_only_self()
|
||||||
{
|
{
|
||||||
debug!("observing object predicate `{pred:?}`");
|
let clause = clause.instantiate_supertrait(tcx, principal_trait);
|
||||||
|
debug!("observing object predicate `{clause:?}`");
|
||||||
|
|
||||||
let bound_predicate = pred.kind();
|
let bound_predicate = clause.kind();
|
||||||
match bound_predicate.skip_binder() {
|
match bound_predicate.skip_binder() {
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
|
ty::ClauseKind::Trait(pred) => {
|
||||||
// FIXME(negative_bounds): Handle this correctly...
|
// FIXME(negative_bounds): Handle this correctly...
|
||||||
let trait_ref =
|
let trait_ref =
|
||||||
tcx.anonymize_bound_vars(bound_predicate.rebind(pred.trait_ref));
|
tcx.anonymize_bound_vars(bound_predicate.rebind(pred.trait_ref));
|
||||||
needed_associated_types.extend(
|
needed_associated_types.extend(
|
||||||
tcx.associated_items(trait_ref.def_id())
|
tcx.associated_items(pred.trait_ref.def_id)
|
||||||
.in_definition_order()
|
.in_definition_order()
|
||||||
|
// We only care about associated types.
|
||||||
.filter(|item| item.kind == ty::AssocKind::Type)
|
.filter(|item| item.kind == ty::AssocKind::Type)
|
||||||
|
// No RPITITs -- even with `async_fn_in_dyn_trait`, they are implicit.
|
||||||
.filter(|item| !item.is_impl_trait_in_trait())
|
.filter(|item| !item.is_impl_trait_in_trait())
|
||||||
// If the associated type has a `where Self: Sized` bound,
|
// If the associated type has a `where Self: Sized` bound,
|
||||||
// we do not need to constrain the associated type.
|
// we do not need to constrain the associated type.
|
||||||
|
@ -133,7 +185,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
.map(|item| (item.def_id, trait_ref)),
|
.map(|item| (item.def_id, trait_ref)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => {
|
ty::ClauseKind::Projection(pred) => {
|
||||||
let pred = bound_predicate.rebind(pred);
|
let pred = bound_predicate.rebind(pred);
|
||||||
// A `Self` within the original bound will be instantiated with a
|
// A `Self` within the original bound will be instantiated with a
|
||||||
// `trait_object_dummy_self`, so check for that.
|
// `trait_object_dummy_self`, so check for that.
|
||||||
|
@ -161,8 +213,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
// `dyn MyTrait<MyOutput = X, Output = X>`, which is uglier but works. See
|
// `dyn MyTrait<MyOutput = X, Output = X>`, which is uglier but works. See
|
||||||
// the discussion in #56288 for alternatives.
|
// the discussion in #56288 for alternatives.
|
||||||
if !references_self {
|
if !references_self {
|
||||||
// Include projections defined on supertraits.
|
let key = (
|
||||||
projection_bounds.push((pred, supertrait_span));
|
pred.skip_binder().projection_term.def_id,
|
||||||
|
tcx.anonymize_bound_vars(
|
||||||
|
pred.map_bound(|proj| proj.projection_term.trait_ref(tcx)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
if !projection_bounds.contains_key(&key) {
|
||||||
|
projection_bounds.insert(key, (pred, supertrait_span));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.check_elaborated_projection_mentions_input_lifetimes(
|
self.check_elaborated_projection_mentions_input_lifetimes(
|
||||||
|
@ -182,12 +241,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
// types that we expect to be provided by the user, so the following loop
|
// types that we expect to be provided by the user, so the following loop
|
||||||
// removes all the associated types that have a corresponding `Projection`
|
// removes all the associated types that have a corresponding `Projection`
|
||||||
// clause, either from expanding trait aliases or written by the user.
|
// clause, either from expanding trait aliases or written by the user.
|
||||||
for &(projection_bound, span) in &projection_bounds {
|
for &(projection_bound, span) in projection_bounds.values() {
|
||||||
let def_id = projection_bound.item_def_id();
|
let def_id = projection_bound.item_def_id();
|
||||||
let trait_ref = tcx.anonymize_bound_vars(
|
|
||||||
projection_bound.map_bound(|p| p.projection_term.trait_ref(tcx)),
|
|
||||||
);
|
|
||||||
needed_associated_types.swap_remove(&(def_id, trait_ref));
|
|
||||||
if tcx.generics_require_sized_self(def_id) {
|
if tcx.generics_require_sized_self(def_id) {
|
||||||
tcx.emit_node_span_lint(
|
tcx.emit_node_span_lint(
|
||||||
UNUSED_ASSOCIATED_TYPE_BOUNDS,
|
UNUSED_ASSOCIATED_TYPE_BOUNDS,
|
||||||
|
@ -198,9 +253,22 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut missing_assoc_types = FxIndexSet::default();
|
||||||
|
let projection_bounds: Vec<_> = needed_associated_types
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|key| {
|
||||||
|
if let Some(assoc) = projection_bounds.get(&key) {
|
||||||
|
Some(*assoc)
|
||||||
|
} else {
|
||||||
|
missing_assoc_types.insert(key);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
if let Err(guar) = self.check_for_required_assoc_tys(
|
if let Err(guar) = self.check_for_required_assoc_tys(
|
||||||
principal_trait.as_ref().map_or(smallvec![], |(_, spans)| spans.clone()),
|
principal_trait.as_ref().map_or(smallvec![], |(_, spans)| spans.clone()),
|
||||||
needed_associated_types,
|
missing_assoc_types,
|
||||||
potential_assoc_types,
|
potential_assoc_types,
|
||||||
hir_bounds,
|
hir_bounds,
|
||||||
) {
|
) {
|
||||||
|
@ -266,7 +334,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
let existential_projections = projection_bounds.iter().map(|(bound, _)| {
|
let existential_projections = projection_bounds.into_iter().map(|(bound, _)| {
|
||||||
bound.map_bound(|mut b| {
|
bound.map_bound(|mut b| {
|
||||||
assert_eq!(b.projection_term.self_ty(), dummy_self);
|
assert_eq!(b.projection_term.self_ty(), dummy_self);
|
||||||
|
|
||||||
|
@ -291,12 +359,16 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
let auto_trait_predicates = auto_traits.into_iter().map(|(trait_pred, _)| {
|
let mut auto_trait_predicates: Vec<_> = auto_traits
|
||||||
assert_eq!(trait_pred.polarity(), ty::PredicatePolarity::Positive);
|
.into_iter()
|
||||||
assert_eq!(trait_pred.self_ty().skip_binder(), dummy_self);
|
.map(|(trait_pred, _)| {
|
||||||
|
assert_eq!(trait_pred.polarity(), ty::PredicatePolarity::Positive);
|
||||||
|
assert_eq!(trait_pred.self_ty().skip_binder(), dummy_self);
|
||||||
|
|
||||||
ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(trait_pred.def_id()))
|
ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(trait_pred.def_id()))
|
||||||
});
|
})
|
||||||
|
.collect();
|
||||||
|
auto_trait_predicates.dedup();
|
||||||
|
|
||||||
// N.b. principal, projections, auto traits
|
// N.b. principal, projections, auto traits
|
||||||
// FIXME: This is actually wrong with multiple principals in regards to symbol mangling
|
// FIXME: This is actually wrong with multiple principals in regards to symbol mangling
|
||||||
|
@ -306,7 +378,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
.chain(auto_trait_predicates)
|
.chain(auto_trait_predicates)
|
||||||
.collect::<SmallVec<[_; 8]>>();
|
.collect::<SmallVec<[_; 8]>>();
|
||||||
v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder()));
|
v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder()));
|
||||||
v.dedup();
|
|
||||||
let existential_predicates = tcx.mk_poly_existential_predicates(&v);
|
let existential_predicates = tcx.mk_poly_existential_predicates(&v);
|
||||||
|
|
||||||
// Use explicitly-specified region bound, unless the bound is missing.
|
// Use explicitly-specified region bound, unless the bound is missing.
|
||||||
|
|
|
@ -79,20 +79,11 @@ impl<'tcx> Relate<TyCtxt<'tcx>> for &'tcx ty::List<ty::PolyExistentialPredicate<
|
||||||
b: Self,
|
b: Self,
|
||||||
) -> RelateResult<'tcx, Self> {
|
) -> RelateResult<'tcx, Self> {
|
||||||
let tcx = relation.cx();
|
let tcx = relation.cx();
|
||||||
|
if a.len() != b.len() {
|
||||||
// FIXME: this is wasteful, but want to do a perf run to see how slow it is.
|
|
||||||
// We need to perform this deduplication as we sometimes generate duplicate projections
|
|
||||||
// in `a`.
|
|
||||||
let mut a_v: Vec<_> = a.into_iter().collect();
|
|
||||||
let mut b_v: Vec<_> = b.into_iter().collect();
|
|
||||||
a_v.dedup();
|
|
||||||
b_v.dedup();
|
|
||||||
if a_v.len() != b_v.len() {
|
|
||||||
return Err(TypeError::ExistentialMismatch(ExpectedFound::new(a, b)));
|
return Err(TypeError::ExistentialMismatch(ExpectedFound::new(a, b)));
|
||||||
}
|
}
|
||||||
|
let v =
|
||||||
let v = iter::zip(a_v, b_v).map(|(ep_a, ep_b)| {
|
iter::zip(a, b).map(|(ep_a, ep_b)| match (ep_a.skip_binder(), ep_b.skip_binder()) {
|
||||||
match (ep_a.skip_binder(), ep_b.skip_binder()) {
|
|
||||||
(ty::ExistentialPredicate::Trait(a), ty::ExistentialPredicate::Trait(b)) => {
|
(ty::ExistentialPredicate::Trait(a), ty::ExistentialPredicate::Trait(b)) => {
|
||||||
Ok(ep_a.rebind(ty::ExistentialPredicate::Trait(
|
Ok(ep_a.rebind(ty::ExistentialPredicate::Trait(
|
||||||
relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(),
|
relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(),
|
||||||
|
@ -109,8 +100,7 @@ impl<'tcx> Relate<TyCtxt<'tcx>> for &'tcx ty::List<ty::PolyExistentialPredicate<
|
||||||
ty::ExistentialPredicate::AutoTrait(b),
|
ty::ExistentialPredicate::AutoTrait(b),
|
||||||
) if a == b => Ok(ep_a.rebind(ty::ExistentialPredicate::AutoTrait(a))),
|
) if a == b => Ok(ep_a.rebind(ty::ExistentialPredicate::AutoTrait(a))),
|
||||||
_ => Err(TypeError::ExistentialMismatch(ExpectedFound::new(a, b))),
|
_ => Err(TypeError::ExistentialMismatch(ExpectedFound::new(a, b))),
|
||||||
}
|
});
|
||||||
});
|
|
||||||
tcx.mk_poly_existential_predicates_from_iter(v)
|
tcx.mk_poly_existential_predicates_from_iter(v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,25 +44,22 @@ pub trait Elaboratable<I: Interner> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ClauseWithSupertraitSpan<I: Interner> {
|
pub struct ClauseWithSupertraitSpan<I: Interner> {
|
||||||
pub pred: I::Predicate,
|
pub clause: I::Clause,
|
||||||
// Span of the supertrait predicatae that lead to this clause.
|
// Span of the supertrait predicatae that lead to this clause.
|
||||||
pub supertrait_span: I::Span,
|
pub supertrait_span: I::Span,
|
||||||
}
|
}
|
||||||
impl<I: Interner> ClauseWithSupertraitSpan<I> {
|
impl<I: Interner> ClauseWithSupertraitSpan<I> {
|
||||||
pub fn new(pred: I::Predicate, span: I::Span) -> Self {
|
pub fn new(clause: I::Clause, span: I::Span) -> Self {
|
||||||
ClauseWithSupertraitSpan { pred, supertrait_span: span }
|
ClauseWithSupertraitSpan { clause, supertrait_span: span }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<I: Interner> Elaboratable<I> for ClauseWithSupertraitSpan<I> {
|
impl<I: Interner> Elaboratable<I> for ClauseWithSupertraitSpan<I> {
|
||||||
fn predicate(&self) -> <I as Interner>::Predicate {
|
fn predicate(&self) -> <I as Interner>::Predicate {
|
||||||
self.pred
|
self.clause.as_predicate()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn child(&self, clause: <I as Interner>::Clause) -> Self {
|
fn child(&self, clause: <I as Interner>::Clause) -> Self {
|
||||||
ClauseWithSupertraitSpan {
|
ClauseWithSupertraitSpan { clause, supertrait_span: self.supertrait_span }
|
||||||
pred: clause.as_predicate(),
|
|
||||||
supertrait_span: self.supertrait_span,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn child_with_derived_cause(
|
fn child_with_derived_cause(
|
||||||
|
@ -72,7 +69,7 @@ impl<I: Interner> Elaboratable<I> for ClauseWithSupertraitSpan<I> {
|
||||||
_parent_trait_pred: crate::Binder<I, crate::TraitPredicate<I>>,
|
_parent_trait_pred: crate::Binder<I, crate::TraitPredicate<I>>,
|
||||||
_index: usize,
|
_index: usize,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
ClauseWithSupertraitSpan { pred: clause.as_predicate(), supertrait_span }
|
ClauseWithSupertraitSpan { clause, supertrait_span }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
//@ known-bug: rust-lang/rust#125957
|
|
||||||
#![feature(generic_const_exprs)]
|
|
||||||
#![allow(incomplete_features)]
|
|
||||||
#![feature(associated_const_equality)]
|
|
||||||
|
|
||||||
pub struct Equal<const T: usize, const R: usize>();
|
|
||||||
|
|
||||||
pub enum ParseMode {
|
|
||||||
Raw,
|
|
||||||
}
|
|
||||||
pub trait Parse {
|
|
||||||
const PARSE_MODE: ParseMode;
|
|
||||||
}
|
|
||||||
pub trait RenderRaw: Parse<PARSE_MODE = { ParseMode::Raw }> {}
|
|
||||||
|
|
||||||
trait GenericVec<T> {
|
|
||||||
fn unwrap() -> dyn RenderRaw;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {}
|
|
|
@ -1,28 +0,0 @@
|
||||||
//@ known-bug: #132330
|
|
||||||
//@compile-flags: -Znext-solver=globally
|
|
||||||
|
|
||||||
trait Service {
|
|
||||||
type S;
|
|
||||||
}
|
|
||||||
|
|
||||||
trait Framing {
|
|
||||||
type F;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Framing for () {
|
|
||||||
type F = ();
|
|
||||||
}
|
|
||||||
|
|
||||||
trait HttpService<F: Framing>: Service<S = F::F> {}
|
|
||||||
|
|
||||||
type BoxService = Box<dyn HttpService<(), S = ()>>;
|
|
||||||
|
|
||||||
fn build_server<F: FnOnce() -> BoxService>(_: F) {}
|
|
||||||
|
|
||||||
fn make_server<F: Framing>() -> Box<dyn HttpService<F, S = F::F>> {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
build_server(|| make_server())
|
|
||||||
}
|
|
|
@ -4,5 +4,5 @@ trait I32Iterator = Iterator<Item = i32>;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let _: &dyn I32Iterator<Item = u32> = &vec![42].into_iter();
|
let _: &dyn I32Iterator<Item = u32> = &vec![42].into_iter();
|
||||||
//~^ ERROR expected `IntoIter<u32>` to be an iterator that yields `i32`, but it yields `u32`
|
//~^ ERROR conflicting associated type bounds
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
error[E0271]: expected `IntoIter<u32>` to be an iterator that yields `i32`, but it yields `u32`
|
error: conflicting associated type bounds for `Item` when expanding trait alias
|
||||||
--> $DIR/associated-types-overridden-binding-2.rs:6:43
|
--> $DIR/associated-types-overridden-binding-2.rs:6:13
|
||||||
|
|
|
|
||||||
|
LL | trait I32Iterator = Iterator<Item = i32>;
|
||||||
|
| ---------- `Item` is specified to be `i32` here
|
||||||
|
...
|
||||||
LL | let _: &dyn I32Iterator<Item = u32> = &vec![42].into_iter();
|
LL | let _: &dyn I32Iterator<Item = u32> = &vec![42].into_iter();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `u32`
|
| ^^^^^^^^^^^^^^^^----------^
|
||||||
|
|
| |
|
||||||
= note: required for the cast from `&std::vec::IntoIter<u32>` to `&dyn Iterator<Item = u32, Item = i32>`
|
| `Item` is specified to be `u32` here
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0271`.
|
|
||||||
|
|
|
@ -8,4 +8,5 @@ trait U32Iterator = I32Iterator<Item = u32>; //~ ERROR type annotations needed
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let _: &dyn I32Iterator<Item = u32>;
|
let _: &dyn I32Iterator<Item = u32>;
|
||||||
|
//~^ ERROR conflicting associated type bounds
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,17 @@ note: required by a bound in `I32Iterator`
|
||||||
LL | trait I32Iterator = Iterator<Item = i32>;
|
LL | trait I32Iterator = Iterator<Item = i32>;
|
||||||
| ^^^^^^^^^^ required by this bound in `I32Iterator`
|
| ^^^^^^^^^^ required by this bound in `I32Iterator`
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: conflicting associated type bounds for `Item` when expanding trait alias
|
||||||
|
--> $DIR/associated-types-overridden-binding.rs:10:13
|
||||||
|
|
|
||||||
|
LL | trait I32Iterator = Iterator<Item = i32>;
|
||||||
|
| ---------- `Item` is specified to be `i32` here
|
||||||
|
...
|
||||||
|
LL | let _: &dyn I32Iterator<Item = u32>;
|
||||||
|
| ^^^^^^^^^^^^^^^^----------^
|
||||||
|
| |
|
||||||
|
| `Item` is specified to be `u32` here
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0284`.
|
For more information about this error, try `rustc --explain E0284`.
|
||||||
|
|
18
tests/ui/closures/deduce-from-object-supertrait.rs
Normal file
18
tests/ui/closures/deduce-from-object-supertrait.rs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
//@ check-pass
|
||||||
|
|
||||||
|
// This test checks that we look at consider the super traits of trait objects
|
||||||
|
// when deducing closure signatures.
|
||||||
|
|
||||||
|
trait Foo: Fn(Bar) {}
|
||||||
|
impl<T> Foo for T where T: Fn(Bar) {}
|
||||||
|
|
||||||
|
struct Bar;
|
||||||
|
impl Bar {
|
||||||
|
fn bar(&self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let x: &dyn Foo = &|x| {
|
||||||
|
x.bar();
|
||||||
|
};
|
||||||
|
}
|
21
tests/ui/dyn-compatibility/multiple-supers-should-work.rs
Normal file
21
tests/ui/dyn-compatibility/multiple-supers-should-work.rs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
//@ check-pass
|
||||||
|
|
||||||
|
// We previously incorrectly deduplicated the list of projection bounds
|
||||||
|
// of trait objects, causing us to incorrectly reject this code, cc #136458.
|
||||||
|
|
||||||
|
trait Sup<T> {
|
||||||
|
type Assoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Sup<T> for () {
|
||||||
|
type Assoc = T;
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Trait<A, B>: Sup<A, Assoc = A> + Sup<B, Assoc = B> {}
|
||||||
|
|
||||||
|
impl<T, U> Trait<T, U> for () {}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let x: &dyn Trait<(), _> = &();
|
||||||
|
let y: &dyn Trait<_, ()> = x;
|
||||||
|
}
|
|
@ -1,9 +1,12 @@
|
||||||
//@ known-bug: rust-lang/rust#126944
|
//@ check-pass
|
||||||
|
|
||||||
|
// Regression test for #126944.
|
||||||
|
|
||||||
// Step 1: Create two names for a single type: `Thing` and `AlsoThing`
|
// Step 1: Create two names for a single type: `Thing` and `AlsoThing`
|
||||||
|
|
||||||
struct Thing;
|
struct Thing;
|
||||||
struct Dummy;
|
struct Dummy;
|
||||||
pub trait DummyTrait {
|
trait DummyTrait {
|
||||||
type DummyType;
|
type DummyType;
|
||||||
}
|
}
|
||||||
impl DummyTrait for Dummy {
|
impl DummyTrait for Dummy {
|
||||||
|
@ -13,7 +16,7 @@ type AlsoThing = <Dummy as DummyTrait>::DummyType;
|
||||||
|
|
||||||
// Step 2: Create names for a single trait object type: `TraitObject` and `AlsoTraitObject`
|
// Step 2: Create names for a single trait object type: `TraitObject` and `AlsoTraitObject`
|
||||||
|
|
||||||
pub trait SomeTrait {
|
trait SomeTrait {
|
||||||
type Item;
|
type Item;
|
||||||
}
|
}
|
||||||
type TraitObject = dyn SomeTrait<Item = AlsoThing>;
|
type TraitObject = dyn SomeTrait<Item = AlsoThing>;
|
||||||
|
@ -21,12 +24,12 @@ type AlsoTraitObject = dyn SomeTrait<Item = Thing>;
|
||||||
|
|
||||||
// Step 3: Force the compiler to check whether the two names are the same type
|
// Step 3: Force the compiler to check whether the two names are the same type
|
||||||
|
|
||||||
pub trait Supertrait {
|
trait Supertrait {
|
||||||
type Foo;
|
type Foo;
|
||||||
}
|
}
|
||||||
pub trait Subtrait: Supertrait<Foo = TraitObject> {}
|
trait Subtrait: Supertrait<Foo = TraitObject> {}
|
||||||
|
|
||||||
pub trait HasOutput<A: ?Sized> {
|
trait HasOutput<A: ?Sized> {
|
||||||
type Output;
|
type Output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,3 +39,5 @@ where
|
||||||
{
|
{
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,32 @@
|
||||||
|
// Regression test for #133361.
|
||||||
|
|
||||||
|
trait Sup<T> {
|
||||||
|
type Assoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Sup<T> for () {
|
||||||
|
type Assoc = T;
|
||||||
|
}
|
||||||
|
impl<T, U> Dyn<T, U> for () {}
|
||||||
|
|
||||||
|
trait Dyn<A, B>: Sup<A, Assoc = A> + Sup<B, Assoc = B> {}
|
||||||
|
|
||||||
|
trait Trait {
|
||||||
|
type Assoc;
|
||||||
|
}
|
||||||
|
impl Trait for dyn Dyn<(), ()> {
|
||||||
|
type Assoc = &'static str;
|
||||||
|
}
|
||||||
|
impl<A, B> Trait for dyn Dyn<A, B> {
|
||||||
|
//~^ ERROR conflicting implementations of trait `Trait` for type `(dyn Dyn<(), ()> + 'static)`
|
||||||
|
type Assoc = usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call<A, B>(x: usize) -> <dyn Dyn<A, B> as Trait>::Assoc {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let x: &'static str = call::<(), ()>(0xDEADBEEF);
|
||||||
|
println!("{x}");
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
error[E0119]: conflicting implementations of trait `Trait` for type `(dyn Dyn<(), ()> + 'static)`
|
||||||
|
--> $DIR/incomplete-multiple-super-projection.rs:20:1
|
||||||
|
|
|
||||||
|
LL | impl Trait for dyn Dyn<(), ()> {
|
||||||
|
| ------------------------------ first implementation here
|
||||||
|
...
|
||||||
|
LL | impl<A, B> Trait for dyn Dyn<A, B> {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Dyn<(), ()> + 'static)`
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0119`.
|
|
@ -1,4 +1,4 @@
|
||||||
//@ known-bug: #79590
|
//@ check-pass
|
||||||
|
|
||||||
trait Database: Restriction<Inner = u32> {}
|
trait Database: Restriction<Inner = u32> {}
|
||||||
|
|
24
tests/ui/traits/object/outlives-super-proj.rs
Normal file
24
tests/ui/traits/object/outlives-super-proj.rs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
//@ check-pass
|
||||||
|
|
||||||
|
// Make sure that we still deduce outlives bounds from supertrait projections
|
||||||
|
// and require them for well-formedness.
|
||||||
|
|
||||||
|
trait Trait {
|
||||||
|
type Assoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Bar {
|
||||||
|
type Assoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Foo<'a, T: 'a>: Bar<Assoc = &'a T> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn outlives<'a, T: 'a>() {}
|
||||||
|
|
||||||
|
fn implied_outlives<'a, T: Trait>(x: &dyn Foo<'a, T::Assoc>) {
|
||||||
|
outlives::<'a, T::Assoc>();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -154,12 +154,12 @@ error[E0308]: mismatched types
|
||||||
--> $DIR/pretty.rs:41:56
|
--> $DIR/pretty.rs:41:56
|
||||||
|
|
|
|
||||||
LL | fn dyn_has_gat(x: &dyn HasGat<u8, Assoc<bool> = ()>) { x }
|
LL | fn dyn_has_gat(x: &dyn HasGat<u8, Assoc<bool> = ()>) { x }
|
||||||
| - ^ expected `()`, found `&dyn HasGat<u8, Assoc<bool> = ()>`
|
| - ^ expected `()`, found `&dyn HasGat<u8>`
|
||||||
| |
|
| |
|
||||||
| help: try adding a return type: `-> &dyn HasGat<u8, Assoc<bool> = ()>`
|
| help: try adding a return type: `-> &dyn HasGat<u8>`
|
||||||
|
|
|
|
||||||
= note: expected unit type `()`
|
= note: expected unit type `()`
|
||||||
found reference `&dyn HasGat<u8, Assoc<bool> = ()>`
|
found reference `&dyn HasGat<u8>`
|
||||||
|
|
||||||
error: aborting due to 14 previous errors; 1 warning emitted
|
error: aborting due to 14 previous errors; 1 warning emitted
|
||||||
|
|
||||||
|
|
12
tests/ui/traits/object/redundant.rs
Normal file
12
tests/ui/traits/object/redundant.rs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
//@ check-pass
|
||||||
|
|
||||||
|
trait Foo: Bar<Out = ()> {}
|
||||||
|
trait Bar {
|
||||||
|
type Out;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn w(x: &dyn Foo<Out = ()>) {
|
||||||
|
let x: &dyn Foo = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
Add table
Add a link
Reference in a new issue